Compare commits

...

645 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
rakshasa a88cab6d2e Released v0.9.0. 2024-09-29 11:06:14 +00:00
rakshasa 9a93281ded Merge branch 'stickz-session-fix' 2024-09-07 08:29:22 +00:00
rakshasa 133ce36570 Fixed goto warning. 2024-09-07 08:29:00 +00:00
rakshasa a142301d02 Merge branch 'session-fix' of github.com:stickz/rtorrent-rak into stickz-session-fix 2024-09-07 08:17:07 +00:00
rakshasa f04e512887 Merge branch 'stickz-memory-leak' 2024-09-07 08:02:55 +00:00
rakshasa d32d59315d Merge branch 'memory-leak' of github.com:stickz/rtorrent-rak into stickz-memory-leak 2024-09-07 07:54:00 +00:00
rakshasa 86e85ae485 Merge branch 'stickz-lto-fix' 2024-09-07 06:29:21 +00:00
stickz 6e9902c23b Fix critical memory leak
This commit fixes a critical memory leak with the inserting RPC commands. We must initialize the cmd_flags with the delete key, otherwise they hang around in memory forever; potentially leaking significant amounts of resources.
2024-09-06 11:16:47 -04:00
stickz d4427931a2 Fix session file data corruption
From https://github.com/jesec/rtorrent/commit/f9a875b633eb083ec82f89ebeae8678ca424e8b2

This commit ensures session files land on the disk in the event of a system crash or power outage. It prevents data corruption of rTorrent session files, which causes torrent client breakage.

Optimizations from the initial implementation include
1) Skipping unnecessary file metadata updates during the sync process.
2) Skipping variable initialization since open will assign -1 on failure.
2024-09-06 11:05:35 -04:00
stickz ea3828a17e Fix Link Time Optimizations
This commit fixes compiling rTorrent with LTO (Link Time Optimizations). We just need to rename from variables in the directory_entry structure to avoid ODR and ZLIB conflicts.
2024-09-01 08:20:01 -04:00
rakshasa 4e246a401f Remove decision structure for popcount_wrapper
The decision structure is very costly. It's significantly faster to work with long long than to use it.
2024-08-31 12:14:50 +00:00
rakshasa eacf9798e2 commit 30addc1a5e
Author: kannibalox <kannibalox@gmail.com>
Date:   Mon Jun 10 13:09:29 2024 -0400

    Use regular iterators intead of bucket-local ones

    Trying to manually predict which bucket a hashed key will land in does not
    appear to be well-defined behavior.

    Fixes #1285
2024-08-20 17:56:03 +00:00
rakshasa 892e595015 Added PKG_CHECK_EXISTS exception. 2024-08-09 13:06:14 +00:00
Jari Sundell 1da0e3476d Removed stray spaces. 2023-03-16 22:10:38 +01:00
Jari Sundell c0a5a55444 Disable delay tracker scrape on start. 2023-03-16 22:10:38 +01:00
stickz 551712f842 Fix typo in "trackers.delay_scrape" 2023-03-16 22:10:38 +01:00
stickz c7c290a86b Add "trackers.delay_scrape" command 2023-03-16 22:10:38 +01:00
stickz 2e1a499942 Don't delay scraping for newly added torrents 2023-03-16 22:10:38 +01:00
stickz c86f0d0333 Don't force the trackers to scrape when rTorrent first starts
rTorrent will do this gradually, so we can start connecting to peers right away.

This patch shaves approximately 5 minutes off the start time with thousands of torrents.
2023-03-16 22:10:38 +01:00
Aleksa Sarai 92bec88d09 utils: lockfile: avoid stack overflow for lockfile buffer
There appears to have been some change on openSUSE (likely some new
hardening flags for builds, or some glibc hardening) such that incorrect
buffer handling results in a segfault even if the buffer is never
overflowed.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2023-03-10 22:22:36 +01:00
Jari Sundell d067bd802e Create FUNDING.yml 2022-09-08 05:08:17 +09:00
Jari Sundell 50924eeda0 Updated paypal link 2022-09-08 05:04:14 +09:00
Jari Sundell 1e40014482 Added rbedit to README. 2021-12-13 04:07:40 +09:00
Jari Sundell 8cafb55881 Updated ADA address. 2021-11-25 02:12:52 +09:00
Jari Sundell a6bc99bb82 Updated and cleaned up automake. (#1102) 2021-08-07 17:49:23 +09:00
Jari Sundell 52ceb39ca3 Updated release link. 2021-08-04 14:27:15 +09:00
Jari Sundell 926893ee62 Update README.md 2021-08-04 00:18:42 +09:00
Jari Sundell cf13789f8c Update README.md 2021-07-20 10:35:14 +09:00
rakshasa d15d93be88 Added ipv6 options. 2021-06-21 21:14:48 +09:00
rakshasa 582e4e4025 Added '--disable-execinfo' option to configure. 2021-06-16 23:29:01 +09:00
rakshasa 952777d75e Added commands to update choke queue. 2021-05-01 19:45:50 +09:00
rakshasa 19dbaa7442 Added missing ax_execinfo.m4 file. 2021-04-04 14:59:36 +09:00
rakshasa 3f72e27603 Replaced custom execinfo autoconf test. 2021-02-27 22:13:01 +09:00
rakshasa e267e8bc07 Fixed automake required files. 2021-02-25 00:05:27 +09:00
Jari Sundell 79765768ff Update README.md 2019-12-25 23:40:57 +09:00
Jari Sundell 8cc1d8f2c5 Optimize build by using a single makefile file. (#941) 2019-12-06 00:35:47 +09:00
Trog 3798de01a0 few missing sub-commands of network and throttle for the RPC interface (#937) 2019-12-01 14:55:23 +09:00
Jari Sundell 8ac98c6d3a New readme. 2019-10-03 13:25:35 +09:00
rakshasa 81500adc53 Remove obsolete check. 2019-09-11 01:51:47 +09:00
lps-rocks 14d7121185 Increase maximum SCGI request to 16MB (#905) 2019-08-29 00:44:09 +09:00
Jari Sundell 7659cd0ec0 Backport changes from feature-bind. 2019-08-23 23:25:24 +09:00
rakshasa f43f9e430d Merge branch 'chros73-ui_mod_status_mod' 2019-08-02 00:13:41 +09:00
chros f22475d1bf Modify throttle status bar mod to be able to display multiple values (See #6) 2019-07-27 11:22:56 +01:00
Jari Sundell b697a4608b Merge pull request #898 from Nicholi/log_append
Added log.append_file command
2019-07-26 20:08:09 +09:00
nicholi 765665fc28 When opening log files use new append parameter. Also added append_gz_file command. 2019-07-26 01:03:57 -07:00
nicholi 5f70986099 Added log.append_file. 2019-07-24 00:46:17 -07:00
rakshasa 6154d16987 Bumped to version 0.9.8. 2019-07-19 13:38:33 +02:00
rakshasa a5e8631cba Added log.close. 2019-07-17 19:41:23 +02:00
rakshasa 07dcd04357 Revert to only using ax_with_curses.m4, and upgrade it to version 16 which seems to be the last unborked version. 2019-07-13 14:36:05 +02:00
rakshasa 863de44c18 Added d.tracker_announce.force. 2019-07-11 17:46:35 +02:00
Jari Sundell 24135ed48e Merge pull request #763 from MindTooth/travis_path_fix
travis: Fix test in wrong path, and jobs parallelization
2019-07-09 21:24:12 +02:00
rakshasa 83709d28c9 Merge branch 'toff-master' 2019-07-08 21:40:02 +02:00
rakshasa 859d5a9578 Merge branch 'master' of https://github.com/toff/rtorrent into toff-master 2019-07-08 21:39:31 +02:00
rakshasa adc9b1dec5 Merge branch 'zetafunction-autoconf' 2019-07-08 20:30:09 +02:00
rakshasa 285972a20d Fixed configure.ac. (zetafunction) 2019-07-08 20:29:43 +02:00
Jari Sundell 3ec2f52db5 Merge pull request #857 from skangas/view-keys-man
Update change view keys to 0-9 in man page
2019-07-08 19:41:20 +02:00
rakshasa ac64fc3f63 Added _GNU_SOURCE to fallocate test. (neheb) 2019-07-08 19:37:17 +02:00
rakshasa b26dc42f3a Merge branch 'ffontaine-master' 2019-06-10 01:18:32 +09:00
rakshasa 6572088aec Merge branch 'master' of https://github.com/ffontaine/rtorrent into ffontaine-master 2019-06-09 23:51:22 +09:00
rakshasa 31a0ea1a2d Merge branch 'master' of github.com:rakshasa/rtorrent 2019-06-09 17:10:17 +09:00
rakshasa 2d72a0d2c0 Merge branch 'chros73-input_history_with_categories' 2019-06-09 17:09:59 +09:00
rakshasa a3a384b049 Fixed minor issues. 2019-06-09 17:09:35 +09:00
Jari Sundell f37dd0d5c2 Merge pull request #722 from g0tmi1k/config
Update rtorrent.rc
2019-06-09 16:27:53 +09:00
Jari Sundell 78c25011cd Merge pull request #824 from Irishsmurf/patch-1
Fix typo in README
2019-06-09 16:25:07 +09:00
rakshasa 35d98c91e0 Merge branch 'master' of github.com:rakshasa/rtorrent 2019-06-09 16:24:18 +09:00
rakshasa 27811db659 Merge branch 'ss23-749_ncurses_tinfo' 2019-06-09 16:24:00 +09:00
rakshasa 4e73ce6bfd Merge branch '749_ncurses_tinfo' of https://github.com/ss23/rtorrent into ss23-749_ncurses_tinfo 2019-06-09 15:43:54 +09:00
Jari Sundell 8c8e73bb72 Merge pull request #794 from waveletlet/master
Edit getsession() for 0.9 config format
2019-06-09 15:17:18 +09:00
Jari Sundell 0d5b344d2a Switch to C++11 MRT RNG for random bytes
Switching to a better RNG for generating strings will prevent the common peerID collisions the rTorrent client has been seeing for YEARS in #440 and #318.
2019-06-08 16:22:47 +09:00
Fabrice Fontaine 703cac9a42 Fix cross compilation, based on OpenWRT patch.
[Vincent: tweak the patch for version 0.13.6]
[Bernd: tweak the patch for version 0.13.7]

Signed-off-by: Gustavo Zacarias <gustavo@zacarias.com.ar>
Signed-off-by: Vicente Olivert Riera <Vincent.Riera@imgtec.com>
Signed-off-by: Bernd Kuhls <bernd.kuhls@t-online.de>
[Retrieved from:
https://git.buildroot.net/buildroot/tree/package/libtorrent/0001-Fix-cross-compilation-based-on-OpenWRT-patch.patch]
Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
2019-04-20 21:37:26 +02:00
Stefan Kangas e6c008b2b7 Update change view keys to 0-9 in man page 2019-04-08 10:03:15 +02:00
Daniel Cheng 81de60e0ae Update global CFLAGS/CXXFLAGS/LIBS at the end of configure.ac
Changes to CFLAGS/CXXFLAGS/LIBS affect following lines in configure.ac.
As originally written, this would cause random libraries, such as
libtorrent, to be linked into the autoconf test program. Occasionally,
this would cause the things like the pkgconfig checks to fail with
mysterious linker errors (e.g. rakshasa/rtorrent#156).

Instead, only populate these global flags with the additional flags for
dependencies at the very end, before the invocation of AC_OUTPUT.
2019-01-13 23:37:36 -08:00
David K c361d6010e Fix typo in README
s/nessesary/necessary
2019-01-03 21:10:09 +00:00
Birger J. Nordølum 724dc088ca travis: Fix test in wrong path, and jobs parallelization 2018-11-14 22:05:19 +01:00
rakshasa c62fa6a756 Merge branch 'pyroscope-cmd-d_multicall_filtered' 2018-10-20 22:00:21 +09:00
rakshasa 656d735de7 Merge branch 'cmd-d_multicall_filtered' of https://github.com/pyroscope/rtorrent into pyroscope-cmd-d_multicall_filtered 2018-10-20 21:47:36 +09:00
rakshasa 408013478c Merge branch 'pyroscope-cmd-compare' 2018-10-20 21:38:39 +09:00
rakshasa fa61b8c11c Merge branch 'cmd-compare' of https://github.com/pyroscope/rtorrent into pyroscope-cmd-compare 2018-10-20 21:38:28 +09:00
rakshasa 1339a3ace9 Merge branch 'chros73-event_system_commands' 2018-10-20 21:35:35 +09:00
rakshasa 4ba128163f Merge branch 'event_system_commands' of https://github.com/chros73/rtorrent into chros73-event_system_commands 2018-10-20 21:30:39 +09:00
rakshasa 908a99751f Merge branch 'chros73-list_type_method_fix' 2018-10-20 21:22:13 +09:00
waveletlet c115640934 Edit getsession() for 0.9 config format 2018-10-18 19:39:32 -03:00
waveletlet 9043c46815 Edit getsession() for 0.9 config format 2018-10-18 19:36:49 -03:00
chros 1f418366d4 Fix 'list' type method (See #25) 2018-10-01 23:27:58 +01:00
toff 30c78c7034 Merge branch 'master' into master 2018-09-29 11:31:06 +02:00
chros 74435f6c40 Add 'event.system.startup_done/shutdown' commands/events (Closes #24) 2018-09-26 15:12:20 +01:00
Jari Sundell a4b281afa4 Merge pull request #753 from ss23/cross_compiling-execinfo
Use AC_COMPILE instead of AC_RUN to check for execinfo.h
2018-06-27 18:36:21 +09:00
Stephen Shkardoon f84670dd63 Use AC_COMPILE instead of AC_RUN to check for execinfo.h
This way enables cross compiling, since we don't need to run anything during the configure script.
2018-06-25 20:14:43 +12:00
rakshasa f0207ce654 Added "try" command that catches input_errors and logs them on rpc_events. 2018-06-23 17:01:34 +09:00
Stephen Shkardoon 9cce5a0bd1 Fix compiling if ncurses was built using --with-terminfo
Resolves #749
Patch from https://bugs.gentoo.org/658390
2018-06-20 01:50:45 +12:00
g0tmi1k 95cff549c6 Removed stop_untied at @pyroscope's request 2018-06-19 10:56:45 +01:00
g0tmi1k 92898a9831 Use session.path for rpc.socket in rtorrent.rc 2018-06-19 10:56:36 +01:00
g0tmi1k fcfbf0e79f Fix typos in rtorrent.rc 2018-06-19 10:51:35 +01:00
g0tmi1k 680b47c197 Add example rtorrent.rc
Source: https://github.com/rakshasa/rtorrent/wiki/CONFIG-Template
2018-06-19 10:48:25 +01:00
Jari Sundell 7804ed3009 Merge pull request #748 from pyroscope/d_custom_if_z-empty-val
d.custom.if_z: return default also for existing but empty value
2018-06-19 18:11:00 +09:00
pyroscope d9b39f5ac6 d.custom.if_z: return default also for existing but empty value 2018-06-18 19:41:53 +02:00
Jari Sundell 08aa287cfc Merge pull request #614 from chros73/adjustable_global_throttle_steps
Make global throttle steps adjustable
2018-06-19 00:08:32 +09:00
Jari Sundell 851d1902a0 Merge pull request #738 from pyroscope/d_custom_if_z+keys+items
add d.custom.if_z + d.custom.keys + d.custom.items
2018-06-19 00:06:23 +09:00
Jari Sundell b600ff0c0e Merge pull request #742 from pyroscope/cmd-event-view-change
add 'event.view.hide/show' commands / events
2018-06-16 18:48:10 +09:00
Jari Sundell a639461c4a Merge pull request #743 from pyroscope/fix-log-xmlrpc-close
fix: properly close the XMLRPC log, resetting the handle after close
2018-06-16 18:46:11 +09:00
Jari Sundell c1057d5ac7 Merge pull request #745 from pyroscope/cmd-value
add 'value' command / conversion op
2018-06-16 18:33:39 +09:00
pyroscope 2ac65ad7e1 add 'value' command / conversion op 2018-06-16 06:54:39 +02:00
pyroscope a4939cb9fd add 'compare' command / operator 2018-06-15 22:36:55 +02:00
pyroscope 3d88ac2cc8 fix: properly close the XMLRPC log, resetting the handle after close 2018-06-15 19:38:12 +02:00
pyroscope f37fefcc54 add 'event.view.hide/show' commands / events 2018-06-15 18:36:01 +02:00
pyroscope 885836f68b add 'd.multicall.filtered' command 2018-06-15 00:40:00 +02:00
pyroscope ca4c3bee8d add d.custom.if_z + d.custom.keys + d.custom.items 2018-06-14 20:32:28 +02:00
Jari Sundell 6c278668e4 Merge pull request #587 from pyroscope/add-position-display-in-title
add '[ X of Y ]' to title bar
2018-06-11 23:15:21 +09:00
Jari Sundell 1665437588 Merge pull request #576 from chros73/simple_math_commands
Add support for basic arithmetic operators
2018-06-11 23:06:37 +09:00
rakshasa 327164f9d8 Bumped version to 0.6.7. 2018-06-07 13:18:34 +09:00
rakshasa 5d22fdd4b6 Merge branch 'chros73-ipv4_filter_enhancement' 2018-06-05 18:52:12 +09:00
rakshasa 7455f2eb86 Merge branch 'ipv4_filter_enhancement' of https://github.com/chros73/rtorrent into chros73-ipv4_filter_enhancement 2018-06-05 18:35:05 +09:00
rakshasa 53767cee92 Merge branch 'chros73-throttle_args_fix' 2018-06-05 17:02:33 +09:00
rakshasa aa9e729ca7 Merge branch 'throttle_args_fix' of https://github.com/chros73/rtorrent into chros73-throttle_args_fix 2018-06-05 17:00:04 +09:00
Jari Sundell e43853b782 Merge pull request #677 from ss23/patch-1
Include SCGI/XMLRPC example in rtorrent.rc
2018-06-05 16:58:25 +09:00
rakshasa 81932c0b12 Merge branch 'duraki-patch-1' 2018-06-05 16:56:59 +09:00
rakshasa 61264c4f17 Merge branch 'patch-1' of https://github.com/duraki/rtorrent into duraki-patch-1 2018-06-05 16:55:02 +09:00
rakshasa 244a84dcf5 Merge branch 'chros73-fix_cxxflags_check' 2018-06-05 16:53:03 +09:00
rakshasa c9a5736d5d Merge branch 'fix_cxxflags_check' of https://github.com/chros73/rtorrent into chros73-fix_cxxflags_check 2018-06-05 16:50:47 +09:00
rakshasa 9322acb33d Merge branch 'pyroscope-fix-double-slash-319' 2018-06-05 16:47:57 +09:00
rakshasa a5e722b48f Merge branch 'fix-double-slash-319' of https://github.com/pyroscope/rtorrent into pyroscope-fix-double-slash-319 2018-06-05 16:45:35 +09:00
rakshasa ba4828d226 Merge branch 'pyroscope-handle-sighup-578' 2018-06-05 16:42:40 +09:00
rakshasa dfced79186 Merge branch 'handle-sighup-578' of https://github.com/pyroscope/rtorrent into pyroscope-handle-sighup-578 2018-06-05 16:40:25 +09:00
rakshasa dd2a4cc151 Fixed ncurses.h include bug fix by theirix. 2018-06-05 16:37:48 +09:00
rakshasa fd372b5e48 Cleaned up download list bug fix.. 2018-06-05 16:22:01 +09:00
chros 6dc87e499a Fix bugs in 'math.*' commands (See #14) 2018-06-01 11:51:42 +01:00
chros 6c11a1dbb0 Fix error message in as_vector method (See #14) 2018-03-03 09:08:28 +00:00
chros 3ea47d7acb Fix for missing throttle arguments (See #23) 2018-01-24 18:20:14 +00:00
☃ Stephen Shkardoon ☃ b82f3614c3 Include SCGI/XMLRPC example in rtorrent.rc
Examples are for scgi_port, and scgi_local (with scheduling to change permissions on the file).
2018-01-14 02:09:42 +13:00
devil ❂ tux 2987ba8081 Fix: Missing ranlib in autoconf
On RHEL7 & possibly CentOS configuring using `autogen` does not append RANLIB nor is registered by default, this fixes definition of the library.
2017-12-15 10:45:31 +01:00
chros 33f8fe804b IPv4 filter enhancement (Closes #21) 2017-12-10 18:54:55 +00:00
chros 1a4f6dab1a Modfiy gcc v6.x fix for empty CXXFLAGS (See #20) 2017-08-02 12:51:03 +01:00
chros 943b576e1f Fix compilation issue with gcc v6.x and empty CXXFLAGS (See #20) 2017-07-30 20:37:21 +01:00
chros 29d57e858a Make global throttle steps adjustable (Closes #17) 2017-06-06 09:54:01 +01:00
Toff 7ec9b6685b Merge pyroscope and chros73 suggestion: Command name uniformisation.
ui.console.log.tempfilter => view.temp_filter.log
2017-05-06 11:17:25 +02:00
Toff d5de8a91d1 Merge chros73 suggestions (settings to exclude views and hide info logs)
- Certain views can be excluded from subfiltering via view.temp_filter.excluded config option
    - its default value: "default,started,stopped"
    - example usage in config: view.temp_filter.excluded.set="default,started,stopped,leeching"

- Log messages can be displayed when temp filtering occured
    - disabled by default
    - can be enabled with: ui.console.log.tempfilter.set=1
2017-04-17 14:56:11 +02:00
pyroscope 4d6f6fe335 add '[ X of Y ]' to title bar 2017-04-01 12:30:10 +02:00
pyroscope 2ec90c6892 no // at start of expanded paths (closes #319) 2017-03-17 21:44:08 +01:00
pyroscope 63dfe341a6 handle SIGHUP like SIGINT (closes #578) 2017-03-17 20:25:11 +01:00
chros 13676f06e5 Add median command (See #14) 2017-03-11 11:40:08 +00:00
chros 6cb176ada3 Add more info to throw message in math commands (See #14) 2017-03-07 13:12:18 +00:00
chros 8b6a1ad079 Add count and average commands (See #14) 2017-03-07 12:57:31 +00:00
chros 3002c95b2c Rename couple of arithmetic commands (See #14) 2017-03-06 19:41:49 +00:00
chros 9590949fa7 Add support for basic arithmetic operators (See #14) 2017-03-06 13:06:59 +00:00
Shivaram Lingamneni 321147cdb8 only redraw the download list if the deleted download was onscreen 2017-01-08 14:49:54 -08:00
Toff 6ee61ee6b5 Merge chros73 suggestions (filter indicator, "start/stopped" view case)
- Suffix filtered view name with "(filtered)"
- Add a check to not filter "start" and "stopped" view
2017-01-08 19:45:46 +01:00
Shivaram Lingamneni 2097c9ca3e unfocus_download should always redraw the download list 2016-12-30 09:19:34 -08:00
rakshasa 10ce6864b8 Added non-pkgconfig check for curl as macosx doesn't include the 'pc' file. 2016-11-05 06:58:44 +09:00
Toff e15270271d Add a temporary name filter for the main view.
By using 'F' in the main view you can enter a regex
that will be used to filter the view based on the torrent name.
To remove the filter set the input to empty.
This is adding a 'view.temp_filter' property and a 'match{}' function.
For example with Ctrl+X you could do:
command> view.temp_filter=main,"match={d.name=,.*linux.*iso}"
2016-10-31 12:19:41 +01:00
Jari Sundell 226e670dec Merge pull request #514 from rakshasa/feature-travis
Travis improvements.
2016-10-23 13:33:00 +09:00
rakshasa 74bd0be5d8 Travis improvements. 2016-10-23 12:23:29 +09:00
Jari Sundell e3a5ed9c75 Merge pull request #513 from rakshasa/fix-cppunit
Fix cppunit
2016-10-23 09:32:42 +09:00
rakshasa c7c5a00f66 Cleaned up check for dependencies. 2016-10-23 09:21:40 +09:00
rakshasa 71a52bfac2 Use pkg-config for cppunit test. 2016-10-23 08:53:11 +09:00
Jari Sundell 16e1961636 Merge pull request #512 from rakshasa/fix-dht
Fix dht
2016-10-23 03:10:49 +09:00
rakshasa 2aa130eda9 More work on dht manager. 2016-10-22 14:19:46 +09:00
rakshasa 008561ef47 More dht manager logging. 2016-10-22 12:33:31 +09:00
rakshasa e02c6b29fa More logging stuff. 2016-10-22 11:21:56 +09:00
rakshasa e2c769f459 Improved logging of dht manager. 2016-10-22 10:51:41 +09:00
Jari Sundell c3f6db0384 Merge pull request #507 from rakshasa/ipv6
Ipv6
2016-10-11 06:44:15 +09:00
rakshasa 40a5b63223 Merge branch 'master' into ipv6 2016-10-10 22:11:52 +09:00
rakshasa e6439a173e Merge branch 'master' of github.com:rakshasa/rtorrent 2016-09-23 08:30:55 +09:00
rakshasa 84913766d5 Removed unneeded parameter. 2016-09-23 08:25:40 +09:00
rakshasa 89b02f275e Added "system.shutdown", "system.shutdown.normal" and "system.shutdown.quick". 2016-09-23 08:22:24 +09:00
Jari Sundell ce00085107 Merge pull request #502 from Speeddymon/Speeddymon-doc_fix-2
Speeddymon doc fix 2
2016-09-09 19:41:52 +09:00
Speeddymon d7529d3b84 Correct Download list layout style to 0.9 format.
Blame @rakshasa for using old style.
2016-09-09 01:57:07 -05:00
Speeddymon 23cf6b260c Merge pull request #4 from rakshasa/master
Sync with upstream master
2016-09-09 01:55:25 -05:00
Jari Sundell 06f1c032b0 Merge pull request #496 from chros73/fix_type_of_var
Fix type of m_ssl_verify_host variable
2016-08-30 22:17:17 +09:00
chros bdb0d99c5c Fix type of m_ssl_verify_host variable (See #12) 2016-08-29 11:04:51 +01:00
rakshasa 7c5e42f4b9 Merge branch 'ipv6' of github.com:rakshasa/rtorrent into ipv6 2016-08-29 18:23:08 +09:00
rakshasa e1afe25413 Merge branch 'master' into ipv6 2016-08-29 18:19:45 +09:00
Jari Sundell 0cba9cbf9b Merge pull request #494 from chros73/init_scripts
Add init scripts into doc directory
2016-08-26 18:06:55 +09:00
chros 017cb1bd59 Fixing variables in rtorrentInitTmux.bash script (See #10) 2016-08-25 19:04:11 +01:00
chros dfdbf5e69c Add init scripts into doc directory (See #10) 2016-08-25 18:38:58 +01:00
Jari Sundell 15e64bdade Merge pull request #492 from chros73/fast_resume_fix
Fix fast resume script breaking single file torrents
2016-08-25 21:25:32 +09:00
chros 5838b8e68c Fix fast resume script breaking single file torrents (See #7) 2016-08-25 12:47:14 +01:00
Jari Sundell 13162f98cb Merge pull request #485 from pyroscope/fix-set_kb
scale integer values with given unit, not only converted strings (closes #484)
2016-08-18 08:36:24 +09:00
Jari Sundell b5e4dc0342 Merge pull request #479 from kannibalox/patch-1
Expose the number of current HTTP connections
2016-08-15 06:16:09 +09:00
pyroscope 41a059c999 scale integer values with given unit, not only converted strings (closes #484) 2016-08-13 14:45:00 +02:00
kannibalox 55c61e9099 Expose the number of current HTTP connections 2016-08-12 02:32:26 +00:00
Jari Sundell e1fa392ecb Merge pull request #477 from mvucBmM0/master
Fix Merzlya display (PR #474)
2016-08-10 02:17:32 +09:00
Speeddymon 9d7398d1da Merge pull request #3 from rakshasa/master
Merge mainline master with fork master
2016-08-05 22:57:34 -05:00
mvucBmM0 a194da08b0 Fix Merzlya display (PR #474) 2016-08-06 03:08:13 +01:00
rakshasa 51c5190eb1 Removed commands that were deprecated in version 0.7.0. 2016-08-06 05:24:43 +09:00
rakshasa 66619840d8 Increased max file size to 512GB. 2016-08-06 03:02:14 +09:00
Jari Sundell 63c2b7aef5 Merge pull request #474 from rakshasa/merzlya-display
Merzlya display
2016-08-04 00:08:21 +09:00
rakshasa 2c60226bd2 Cleaned up compact display. 2016-08-03 23:57:02 +09:00
rakshasa d111594d20 Added merzlya's torrent status display changes. 2016-08-03 23:01:28 +09:00
Jari Sundell a0f97e4b06 Merge pull request #459 from chros73/fix_filter_started
Fix scheduled sorting/filtering bug on started and stopped views in rtorrent
2016-08-03 22:04:59 +09:00
Jari Sundell a7079c594e Merge pull request #460 from netpok/master
Fix warning message of deprecated commands
2016-08-03 21:56:32 +09:00
Jari Sundell ed48d586d8 Merge pull request #465 from chros73/expose_meta_property
Expose meta property of downloads
2016-08-03 21:55:50 +09:00
Jari Sundell 8be4e5bbf7 Merge pull request #461 from Speeddymon/Speeddymon-patch-1
Update example rtorrent.rc to 0.9 format
2016-08-02 20:35:45 +09:00
chros 8140c3fe07 Expose meta property of downloads (See #5) 2016-07-21 18:55:21 +01:00
netpok 8385957b06 Fix warning message of deprecated commands 2016-07-15 11:52:33 +02:00
Jari Sundell 1363e50a7b Merge pull request #455 from Speeddymon/Speeddymon-patch-2
Fix travis config
2016-07-13 09:42:25 +09:00
Speeddymon f24154e772 Fix travis config 2016-07-09 14:02:31 -05:00
Speeddymon 3f698b3b39 Update example rtorrent.rc to 0.9 format 2016-07-09 13:59:08 -05:00
chros a8c67b4aab Fix scheduled sorting/filtering bug on started and stopped views in rtorrent (See #3) 2016-07-06 23:15:04 +01:00
Jari Sundell aac0ea48f7 Merge pull request #430 from yate/peer-units
use whatever unit necessary in peer list info
2016-06-29 21:08:42 +09:00
Jari Sundell 1db32f2f63 Merge pull request #444 from jmdevince/master
Show non-preloaded pieces stats
2016-06-29 21:06:22 +09:00
rakshasa efc9097d62 Renamed system.use_daemon to system.daemon. 2016-06-27 01:46:54 +09:00
Jari Sundell 5a56fbd5d1 Merge pull request #446 from zp/daemon
Allow rtorrent to run as a daemon, slightly modified version of #111
2016-06-27 01:40:42 +09:00
zp 7ea5729676 trim modified files 2016-06-19 07:04:23 -05:00
zp c01709fa27 Allow rtorrent to run as a daemon, slightly modified version of the PR provided by sallyswiss 2016-06-19 02:06:30 -05:00
jmdevince 0797d636fb Show non-preloaded pieces stats 2016-06-15 09:46:33 -04:00
yate b68d4c2db9 use whatever unit necessary in peer list info 2016-05-15 22:58:16 -04:00
Jari Sundell 9abcea84c7 Merge pull request #280 from mynamewastaken/patch-1
Partially update outdated documentation
2016-03-10 10:46:27 +09:00
Jari Sundell cc1f7fb2cb Merge pull request #407 from rakshasa/fix-stray-simple
Fix a stray 'simple' method.insert check.
2016-03-10 10:18:32 +09:00
rakshasa 944d304193 Fixed travis config file. 2016-03-10 09:41:16 +09:00
rakshasa 629e421d67 Updated travis file to properly select gcc-4.7. 2016-03-10 09:37:58 +09:00
rakshasa 3e7f9d8b4f Removed make check. 2016-03-10 09:24:08 +09:00
rakshasa a8cb524345 Merge branch 'master' into fix-stray-simple 2016-03-10 09:02:04 +09:00
rakshasa 0510e4db9d Don't run 'make check' in travis as it has linker issues. 2016-03-10 08:59:33 +09:00
rakshasa a975804797 Merge branch 'master' into fix-stray-simple 2016-03-10 08:50:59 +09:00
rakshasa adf4a32097 Fixed name. 2016-03-10 08:50:43 +09:00
rakshasa 3edeb364bc Fix a stray 'simple' method.insert check. 2016-03-10 08:47:14 +09:00
Jari Sundell 73a344711d Merge pull request #406 from rakshasa/test-travis
Adding travis file for testing.
2016-03-10 08:46:13 +09:00
rakshasa 4ba24af463 Adding travis file for testing. 2016-03-10 08:27:27 +09:00
Jari Sundell 44f0ac3447 Merge pull request #379 from krichter722/configure_fix
added checkout URL to action-if-not-found of PKG_CHECK_MODULES for li…
2016-03-10 08:12:46 +09:00
rakshasa a92da121d7 Cleaned up XDG_CONFIG_HOME patch. 2016-03-10 04:21:24 +09:00
rakshasa 4fb036f87d Revert "Merge pull request #317 from jlec/tinfo"
This reverts commit b19cf8b4ff, reversing
changes made to 83d7dc8964.
2016-03-10 04:03:56 +09:00
Jari Sundell 6a8d332b4c Merge pull request #306 from gulafaran/master
add support for the XDG base dir spec for rtorrent.rc
2016-03-10 03:34:27 +09:00
Jari Sundell 911596d65e Merge pull request #263 from lotheac/master
don't depend on dirent DT_DIR
2016-03-10 03:30:14 +09:00
Jari Sundell b19cf8b4ff Merge pull request #317 from jlec/tinfo
Try use pkg-config to detect ncurses libraries
2016-03-10 03:21:41 +09:00
Jari Sundell 83d7dc8964 Merge pull request #366 from RecursiveForest/master
change *dl_rate() to *down_rate()
2016-03-10 02:51:00 +09:00
Jari Sundell b89fa31f37 Merge pull request #405 from pyroscope/cmd-ui-current-view
added ui.current_view command
2016-03-09 07:07:31 +09:00
pyroscope 30d8379391 added ui.current_view command 2016-03-08 13:25:04 +01:00
Jari Sundell 605819ea6c Merge pull request #401 from pyroscope/system-env-command
Added system.env=NAME command
2016-03-08 19:24:35 +09:00
pyroscope 1f5e4d37d5 added system.env=NAME command 2016-03-05 03:12:35 +01:00
Karl-Philipp Richter 33601ddc0c added checkout URL to action-if-not-found of PKG_CHECK_MODULES for libtorrent, fixed #377 2016-01-25 08:33:52 +01:00
Samantha Baldwin e1cc736f11 change *dl_rate() to *down_rate() 2015-12-19 01:28:14 -05:00
Jari Sundell 9647749b01 Merge pull request #351 from Micdu70/master
Save downloaded stat of each torrent
2015-11-17 08:00:25 +09:00
Micdu70 06db5776ae Save downloaded stat of each torrent 2015-11-05 18:41:27 +01:00
rakshasa 62cb5a4605 Bumped master to 0.9.6. 2015-09-08 05:12:40 +09:00
rakshasa d4905d512a Merge branch 'master' of github.com:rakshasa/rtorrent 2015-08-08 22:29:31 +09:00
Justin Lecher 9ba4d1d92e Try use pkg-config to detect ncurses libraries
Modern ncurses version provide a pkg-config interface, so let's try to
use it first. This also helps when ncurses provides functions inside
libtinfo.so and thus needs to be linked against it as well.

Signed-off-by: Justin Lecher <jlec@gentoo.org>
2015-07-29 09:32:37 +02:00
Tom Englund 1c47bf6162 add support for the XDG base dir spec for rtorrent.rc 2015-06-23 14:14:27 +02:00
Jari Sundell 50d6437792 Merge pull request #291 from RSully/patch-1
Add load.raw_start_verbose
2015-05-06 02:23:36 +09:00
Ryan eb5443bbad Add load.raw_start_verbose
Fixes #289.
2015-05-04 19:21:25 -04:00
mynamewastaken 1a728fc683 Partially update outdated documentation 2015-03-10 20:33:47 -05:00
Lauri Tirkkonen 0d1dc8a331 don't depend on dirent DT_DIR 2015-01-03 16:20:57 +02:00
rakshasa b5f2cfe393 Renamed mincore instrumentation plotter. 2014-11-09 23:12:46 +09:00
rakshasa 7343e33a6a Added 'log.open_file_pid' and 'log.open_gz_file_pid' commands that appends the pid automatically. 2014-11-04 23:34:51 +09:00
rakshasa e3cc2c601d Use a generic function for logging and allow output groups to be appended.
log.open_file = "instrumentation_memory.log", "/foo/instrumentation_memory.log", "instrumentation_memory", ...
2014-11-04 22:46:35 +09:00
rakshasa 3cf9cffe68 Moved logging commands to a separate file. 2014-11-04 19:48:55 +09:00
Jari Sundell 0ba4d7d943 Merge pull request #243 from salorium/ipv6
d.timestamp.finished for create torrent
2014-11-04 19:37:33 +09:00
Jari Sundell cc10161c90 Merge pull request #232 from hkjn/master
Also mentions that ^o changes destination dir in -help output, like online docs do
2014-11-04 19:37:22 +09:00
salorium d1e807acc5 d.timestamp.finished for create torrent
English (translate):
Adding initialization d.timestamp.finished at the torrent download but is not set seeding. For example when we create a torrent, it is not downloaded.

French:
Ajout de l'initialisation d.timestamp.finished lors que le torrent n'est pas télécharger mais mis en seeding. Par exemple lors que l'on créer un torrent, celui ci n'est pas télécharger.
2014-10-07 08:20:57 +02:00
rakshasa 0df0a6650d Removed ifdef for ipv6. 2014-09-23 18:56:29 +09:00
rakshasa 6c39da6943 Updated authors and readme. 2014-09-15 16:03:10 +09:00
Henrik Jonsson 089fa765b8 Merge branch 'master' of https://github.com/hkjn/rtorrent 2014-09-05 14:49:02 +02:00
Henrik Jonsson 92197d6286 Merge branch 'master' of https://github.com/hkjn/rtorrent 2014-09-05 14:48:57 +02:00
Henrik Jonsson 9937ea27bc Merge branch 'master' of https://github.com/hkjn/rtorrent 2014-09-05 14:47:20 +02:00
Henrik Jonsson b5bff0cb9c Also mentions that ^o changes destination dir in -help output, like http://libtorrent.rakshasa.no/rtorrent/rtorrent.1.html does 2014-09-05 14:47:16 +02:00
Henrik Jonsson 3d166de175 Also mentions that ^o changes destination dir in -help output, like http://libtorrent.rakshasa.no/rtorrent/rtorrent.1.html does 2014-09-04 12:50:47 +02:00
rakshasa 7007973c76 Added ipv6 patch. 2014-08-14 20:56:20 +09:00
rakshasa 7537a3c2a9 Merge branch 'master' of github.com:rakshasa/rtorrent 2014-07-02 23:11:58 +09:00
rakshasa 81c652292a Added updated autoconf scripts. 2014-07-02 23:11:14 +09:00
Jari Sundell f4c312e2c0 Added command name to exception when it is missing '='. 2014-06-24 03:49:15 +09:00
rakshasa 975d001ea7 Merge branch 'pr/127' 2014-06-18 22:06:37 +09:00
Jari Sundell fe9a4e9714 Updated gitignore. 2014-06-18 03:43:32 +09:00
Jari Sundell 52689695ff Merge branch 'master' of git://github.com/rakshasa/rtorrent 2014-06-18 02:59:09 +09:00
Jari Sundell 2a19c613c1 Merge pull request #213 from rakshasa/c++11
C++11
2014-06-18 00:52:16 +09:00
rakshasa dc8e786d58 Merge branch 'master' into c++11
Conflicts:
	src/command_dynamic.cc
	src/command_events.cc
	src/command_groups.cc
	src/command_ip.cc
	src/command_network.cc
2014-06-18 00:44:36 +09:00
rakshasa b8e24b78cd Added missing option strings commands. 2014-06-13 18:24:03 +09:00
rakshasa 4244921383 Added script to generate option strings wiki page. 2014-06-13 18:23:37 +09:00
Jari Sundell afebadcbdf Added '.dirstamp' to gitignore. 2014-06-13 01:32:45 +09:00
rakshasa d74409c2d7 Merge branch 'master' into old_features 2014-06-12 23:03:54 +09:00
rakshasa 1fefc4720b Forgot to commit changes to how ssl_verify_host/peer parameters are converted. 2014-06-12 22:19:33 +09:00
rakshasa 09f6243c6a Cleaned up how ssl_verify_host/peer is set. 2014-06-12 22:08:40 +09:00
rakshasa 390328ec97 Merge branch 'master' into pr/190 2014-06-12 21:43:31 +09:00
rakshasa bfd1a8da8c Updated migration script to handle rutorrent. 2014-05-31 03:18:26 +09:00
rakshasa 4ac807870e Un-deprecate scgi_port/local. 2014-05-28 17:04:06 +09:00
rakshasa 5acfd592f0 Added sed script for converting gui's to the new 0.9 commands. 2014-05-20 17:55:12 +09:00
rakshasa e4e73aeee9 Set deprecated commands to be off by default. If needed use the '-D' option, however note that they will be removed permanently in the future. 2014-05-16 01:14:47 +09:00
rakshasa 8e69930cc4 Changed thread name to included 'rtorrent'. 2014-05-15 23:42:36 +09:00
rakshasa 3b39f37f49 C++11 compatibility fixes. 2014-05-13 23:36:37 +09:00
rakshasa 4f36c3e49f Merge remote-tracking branch 'origin/master' into xirvik 2014-05-09 18:05:56 +09:00
rakshasa e42ec54920 Bumped scgi listen queue to 100. 2014-05-09 18:05:30 +09:00
rakshasa 6a3234eaa7 Bumped to 0.9.4. 2014-05-09 17:54:04 +09:00
rakshasa ce5d67a9c0 Merge branch 'master' into xirvik 2014-05-03 00:28:14 +09:00
rakshasa d396c8e058 Changed rpc log types. 2014-04-25 19:55:47 +09:00
rakshasa 904a390fba Merge branch 'master' into xirvik 2014-04-25 17:25:04 +09:00
rakshasa 9548e08935 Removed debugging exceptions. 2014-04-25 17:24:42 +09:00
rakshasa 696c2b2b33 Merge branch 'master' into xirvik 2014-04-21 22:34:45 +09:00
rakshasa ce125b1c54 Updated instrumentation plot. 2014-04-21 22:33:47 +09:00
rakshasa 82a68420f4 Fixed non-POSIX conformant included headers. 2014-04-18 22:27:13 +09:00
rakshasa d9f6f5aef4 Cleaned up CurlStack. 2014-04-18 22:16:24 +09:00
Mike Valentine 24f84214c8 Added config parameter network.http.ssl_verify_host to support certificates.
Added config parameter network.http.ssl_verify_host to support certificates
with a mismatched or empty CN. Default is 2 (verify name match). Use 1 to simply
verify the presence of a name or 0 to allow for missing names.
2014-04-12 14:06:22 -04:00
rakshasa 38f39bdb23 Added unordered curve to plot. 2014-04-10 22:32:07 +09:00
rakshasa 906683714b Updated instrumentation transfers plot script. 2014-04-10 22:00:46 +09:00
rakshasa a536fc09a0 Updated autoconf scripts. 2014-04-01 11:49:19 +02:00
rakshasa dea7c80996 Updated instrumenation transfer plot script. 2014-04-01 01:03:44 +02:00
rakshasa 3e3a84b3a0 Added 'network.listen.backlog{,.set}' commands. 2014-03-23 14:46:10 +01:00
rakshasa 866289b38a Updated email address. 2014-01-28 23:29:05 +09:00
rakshasa c9e894982f Merge branch 'master' of github.com:rakshasa/rtorrent 2013-11-28 01:53:41 +09:00
rakshasa 6b7adfd6bd Added scripts for gnuplot. 2013-11-28 01:53:20 +09:00
Jari Sundell fcd1fdb2fe Merge pull request #164 from artagnon/doc
Janitorial documentation work
2013-11-26 09:59:22 -08:00
Ramkumar Ramachandra a5d92cc940 rtorrent.1.xml: nuke deprecated stop_on_ratio
Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
2013-11-26 23:24:36 +05:30
Ramkumar Ramachandra 9fcef7fbd6 rtorrent.1.xml: nuke a bunch of deprecated on_* functions
Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
2013-11-26 23:24:36 +05:30
Ramkumar Ramachandra effdc5642d rtorrent.1.xml: document (max|min)_(uploads|downloads)
Only max_uploads was documented previously.

Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
2013-11-26 23:24:36 +05:30
Ramkumar Ramachandra fe5439f6a0 rtorrent.1.xml: document set_* functions for throttle
Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
2013-11-26 23:24:36 +05:30
Ramkumar Ramachandra 58fba68aff rtorrent.1.xml: add more DHT variables
Use TODO placeholders for the moment.

Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
2013-11-26 23:24:36 +05:30
Ramkumar Ramachandra 89dfa3a268 rtorrent.1.xml: clearly demarcate DHT settings
DHT stuff is clearly demarcated in the code, so let the manual also
follow along.

Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
2013-11-26 23:24:36 +05:30
Ramkumar Ramachandra 0d620e77db rtorrent.1.xml: remove schedule and schedule_remove
They were deprecated a long time ago.

Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
2013-11-26 23:24:36 +05:30
rakshasa 55b826d6cb Added brackets around configure parameters. 2013-11-22 23:20:50 +09:00
rakshasa 385b342deb Fixed typo in IPv6 option. 2013-11-22 23:03:00 +09:00
rakshasa 2e9baa1635 Added logging of some ui events. 2013-11-06 23:23:20 +09:00
rakshasa 67236d7757 Fixed an issue with input window. 2013-11-06 23:22:54 +09:00
rakshasa 66edb39863 Added 'log.open_gz_file' option. 2013-08-30 00:09:08 +09:00
rakshasa 00a349f68c Added slot_call_list. 2013-08-27 23:18:31 +09:00
rakshasa 370bae4b98 Removed all dependencies on sigc++. 2013-08-27 00:43:23 +09:00
rakshasa 323f0df30c Merge branch 'master' into xirvik 2013-08-26 23:48:23 +09:00
rakshasa aa93404278 Added subdirs option to suppress warnings. 2013-08-26 23:47:31 +09:00
rakshasa 1e4739c862 Merge branch 'master' into xirvik 2013-08-26 23:17:56 +09:00
rakshasa aa2f784ae6 Converted sigc::signals to STL. 2013-08-26 23:15:33 +09:00
rakshasa 529eda5aab Converted sigc++ slots to std::tr1::function. 2013-08-24 00:14:25 +09:00
rakshasa 629ebcbd54 Removed deprecated signals for chunks passed/failed. 2013-08-22 03:48:54 +09:00
rakshasa d8d7861244 Removed old logging signals. 2013-08-22 03:33:48 +09:00
Jari Sundell bc4209e380 Merge pull request #128 from skydrome/automake-1.12
Fix warning on automake-1.12.4
2013-08-21 07:08:34 -07:00
rakshasa e36a0d43a4 Added missing <unistd.h> include. 2013-08-21 22:59:54 +09:00
rakshasa c3ad68156e Adding test output file gitignore. 2013-08-16 22:11:32 +09:00
rakshasa 6697806185 Use pid and ppid to XOR the seed value for random and rand48. 2013-08-16 16:29:59 +09:00
rakshasa 412a2f79b9 Removed obsolete logging facility. 2013-07-31 23:24:02 +09:00
rakshasa 0bf60679e4 Changed file permissions for log_stats.plot. 2013-07-31 06:17:13 +09:00
rakshasa 0329608f69 Merge remote-tracking branch 'origin/master' into xirvik 2013-06-13 23:08:15 +09:00
skydrome b113a02584 Fix warning on automake-1.12.4
warning: 'INCLUDES' is the old name for 'AM_CPPFLAGS' (or '*_CPPFLAGS')
2013-05-09 14:00:09 -04:00
Jorge Israel Peña 49d00285c8 added SA_RESTART to automatically restart system calls interrupted by signals (as was already done by signal()) as well as error checking on sigaction() 2013-04-07 21:21:27 -07:00
Jorge Israel Peña 2cd70f4342 replace signal() call with sigaction() for better portability
signal() is known to have portability problems. Some systems such as
old Unix systems and System V employ a behavior in which the signal
disposition is reset to SIG_DFL (default) upon invocation of a signal
handler by the delivery of a signal.

See issue #51 in which Solaris users experience signal-based issues.

Solaris is a system which employs the SIG_DFL reset behavior even in
version 11.1.

See http://docs.oracle.com/cd/E26502_01/html/E29034/signal-3c.html

> If signal() is used, disp is the address of a signal handler, and sig is not SIGILL,
> SIGTRAP, or SIGPWR, the system first sets the signal's disposition to SIG_DFL before
> executing the signal handler.

On Solaris the default signal disposition for SIGUSR1 is to exit the application.

See http://docs.oracle.com/cd/E26502_01/html/E29033/signal.h-3head.html

If I'm correct in assuming this is the problem Solaris users are encountering,
the solution to this (and likely any other portability issues that may arise)
is to use sigaction() which has explicitly defined behavior as per the POSIX standards.

As you can see, it's a pretty drop-in solution. In fact, on some systems such as Linux,
glibc defines signal() as a wrapper around sigaction() to use BSD semantics (i.e. not the
behavior detailed above), which is likely why few others have experienced these problems.

See http://man7.org/linux/man-pages/man2/signal.2.html
2013-04-07 19:41:32 -07:00
rakshasa 7689059dbc Cleaned up thread code. 2013-04-03 21:16:11 +09:00
rakshasa 3b2a47a6d0 Use thread_base::interrupt for all SIGUSR1 interrupt signals and don't set a handler if it's not supported. 2013-03-03 05:00:31 +09:00
rakshasa e28692492b Fixed obsolete macro statements. 2013-02-26 17:44:42 +09:00
rakshasa 2c97841e92 Removed unused member variables. 2013-02-26 17:40:41 +09:00
rakshasa bb27adcfd3 Merge branch 'master' into xirvik 2012-10-31 17:55:44 +09:00
rakshasa 5e6cb5da04 Merge branch 'master' of github.com:rakshasa/rtorrent 2012-10-24 14:35:59 +09:00
rakshasa cd029a67c5 Bumped version to 0.9.3. 2012-10-23 22:39:07 +09:00
Jari Sundell addc323ec8 Merge pull request #89 from ShanaTsunTsunLove/master
Typo in rtorrent.rc
2012-09-05 12:14:54 -07:00
Mateusz Kowalczyk 2217b14095 Typo in default rtorrent.rc comment 2012-08-28 12:35:10 +01:00
rakshasa 6a84facae0 Merge branch 'master' of github.com:rakshasa/rtorrent 2012-08-14 17:56:24 +09:00
rakshasa 66a116841a Removed old options. 2012-08-14 17:55:31 +09:00
rakshasa bacb6c0f72 Removed unused variables. 2012-07-23 23:54:21 +09:00
Jari Sundell 40fc8bbf80 Merge pull request #79 from nullren/master
Restore create_link and delete_link.
2012-07-10 23:21:25 -07:00
nullren 13f672ab4d using lt_log_print
replaced push_log_std with lt_log_print using LOG_TORRENT_WARN.
2012-06-27 00:19:09 -07:00
rakshasa 2967f9a224 Cleaned up old documents and scripts. 2012-06-27 15:43:32 +09:00
nullren eac7536f6a restored create_link
took away empty-body warnings from clang by restoring error messages
using push_log_std.
2012-06-23 20:21:47 -07:00
rakshasa 78f64a3e08 Use internal_error for priority queue exceptions. 2012-05-31 20:16:26 +09:00
rakshasa cf77a17399 Cleaned up command wrappers. 2012-05-22 17:19:19 +09:00
rakshasa 7a2ec0ff86 Merge branch 'master' into xirvik 2012-05-21 16:12:00 +09:00
rakshasa 48733c84ec Added 'catch' command to allow safely calling commands that might fail with input_error. Note that double-brackets are required as the method needs to be called by the 'catch' command, not the parser.
catch = ((foo.bar,"bad input"))
2012-05-21 16:08:49 +09:00
rakshasa b020aa0197 Pass command target when using rpc::call_object with dict_key. 2012-05-21 16:08:18 +09:00
rakshasa e95b66fc51 Merge branch 'master' into xirvik 2012-05-14 20:18:48 +09:00
rakshasa 678049bc09 Fixed brackets in autoconf scripts. 2012-05-14 20:18:29 +09:00
rakshasa 2f102f0fcd Merge branch 'master' into xirvik 2012-05-14 19:41:36 +09:00
rakshasa d0f6bb440a Fixed clang compilation issues. 2012-05-07 02:25:37 +09:00
rakshasa 8f5f383e3c For POSIX threads config script try none first to avoid adding flags when not needed. 2012-05-07 02:19:12 +09:00
rakshasa 2ca49e3485 Removed unused parse command function. 2012-05-07 01:53:39 +09:00
rakshasa 004862850d Allow command function lists for dynamically created functions. 2012-05-04 22:56:58 +09:00
rakshasa d2d09d97f8 Replace old command call functions with the new one taking torrent::Objects. 2012-05-04 22:33:26 +09:00
rakshasa fb75510c0f Allow functions and lists of functions to be passed to view.event_{added,removed}. 2012-05-04 21:31:12 +09:00
rakshasa 8d0f9b3300 Removed old hanshake log signal. 2012-05-04 05:17:11 +09:00
rakshasa 76ed90f514 Removed commented out settings for views. 2012-05-04 05:09:21 +09:00
rakshasa b79dea94b2 Wait for disowned http requests to finish to ensure stopped event gets sent to tracker on client shutdown. 2012-05-04 04:02:59 +09:00
rakshasa cf1c44ef5b Removed sigc++ dependency from ConnectionManager. 2012-05-04 04:02:59 +09:00
rakshasa 6d61cc09c3 Merge branch 'master' into xirvik 2012-05-01 00:56:52 +09:00
rakshasa f1ece0ae12 Wait for disowned http requests to finish to ensure stopped event gets sent to tracker on client shutdown. 2012-05-01 00:29:50 +09:00
Jari Sundell 9df9183a0c Merge pull request #45 from SineSwiper/master
New rtorrent_fast_resume script
2012-04-27 00:41:12 -07:00
rakshasa 75933db69b Merge branch 'master' into xirvik 2012-04-26 21:23:08 +09:00
rakshasa f373b20c1b Removed old handshake logging functions. 2012-04-26 21:22:35 +09:00
rakshasa efa3c670a5 Merge branch 'master' into xirvik 2012-04-25 22:23:38 +09:00
rakshasa 22acdd87c3 Print backtrace for internal_error. 2012-04-25 22:23:15 +09:00
rakshasa c46ee642fe Merge branch 'master' into xirvik 2012-04-25 21:47:12 +09:00
rakshasa cca1f21471 Added logging of segfault/bus signal and backtrace to LOG_CRITICAL. 2012-04-25 21:46:23 +09:00
rakshasa 27888e73bc Changed to latest version. 2012-04-23 16:14:06 +09:00
rakshasa 4dd7582240 Bumped version to 0.9.2. 2012-04-20 16:03:55 +09:00
rakshasa 03c0a4e18c Allow tilde for 'log.open_file' path. 2012-04-18 17:32:12 +09:00
rakshasa c2b768cd6d Minor updates to choke group documentation. 2012-04-18 16:55:30 +09:00
rakshasa 097e3d9056 Merge branch 'master' into xirvik 2012-04-16 17:07:32 +09:00
rakshasa 63cf700593 Updated documentation for choke groups. 2012-04-16 17:06:53 +09:00
rakshasa 0132ce6b81 Merge branch 'master' into xirvik 2012-04-16 00:43:20 +09:00
rakshasa 17201984a6 When 'throttle.max_*.global.*.set' commands are called they will automatically update the libtorrent settings, so it is no longer needed to set the throttle to force this update. 2012-04-16 00:40:47 +09:00
rakshasa a7b7b26d08 Merge branch 'master' into xirvik 2012-04-13 20:54:58 +09:00
rakshasa 0a9e03df57 Added logging of options for created torrents. 2012-04-13 20:53:57 +09:00
rakshasa 90830dc765 Use right function argument for inotify test. 2012-04-12 18:44:42 +09:00
rakshasa 0b39455a4b Merge branch 'master' into xirvik 2012-04-12 15:30:12 +09:00
rakshasa d2dd143d2e Added 'throttle.update' to force 'throttle.max_{up,down}loads.global' setting to take effect. 2012-04-12 15:29:07 +09:00
rakshasa b71b44dbd6 Merge branch 'master' of github.com:rakshasa/rtorrent 2012-04-11 19:27:17 +09:00
Jari Sundell 83294e2198 Merge pull request #53 from taylorchu/master
Sigc++ header cleanup.
2012-04-11 03:26:45 -07:00
rakshasa 46862e23a9 Added ENODEV to "error_number.h". 2012-04-11 19:24:24 +09:00
taylorchu 077288407f fix build after removing sigc++ for download.cc 2012-04-10 15:42:45 -07:00
rakshasa 05d16707d4 Merge branch 'master' into xirvik 2012-04-10 21:46:51 +09:00
rakshasa 3fe1a734ac Differentiate scrape and normal requests in the tracker list. 2012-04-10 15:38:41 +09:00
rakshasa 9c2745ecb3 Added missing return value to watched command. 2012-04-10 15:38:07 +09:00
rakshasa e79b38f907 Merge branch 'master' into xirvik 2012-04-09 15:39:14 +09:00
rakshasa fdc6ee56de Removed sigc++ signal from ConnectionList. 2012-04-07 15:06:25 +09:00
rakshasa 36f8e5d349 Use TR1 slots instead of sigc++ for DownloadInfo events. 2012-04-07 03:37:37 +09:00
rakshasa 5bed4f01ad Added tracker related commands. 2012-04-04 02:49:05 +09:00
rakshasa 020de10f38 Return hex instead of binary for 'd.chunks_seen'. 2012-04-04 02:09:08 +09:00
rakshasa 7343c0d67c Merge branch 'master' into xirvik 2012-04-02 16:05:26 +09:00
rakshasa b28f2ea807 Added 'd.chunks_seen', which is limited to 'Download::peers_accounted()' number of peers for optimization reasons. 2012-04-01 02:22:18 +09:00
rakshasa 9aa54d2344 Added 'directory.watch.added'. 2012-03-29 23:04:17 +09:00
rakshasa 6141a5656f Merge branch 'master' into xirvik 2012-03-29 22:06:11 +09:00
rakshasa dc817e24e4 Added inotify autoconf script. 2012-03-29 22:05:43 +09:00
rakshasa d1ff1fe77c Solaris compatibility fixes. 2012-03-26 23:18:10 +09:00
rakshasa 51fff1fdc5 Fixed version number. 2012-03-26 16:26:56 +09:00
SineSwiper 47d36c0690 Add new version of rtorrent_fast_resume.pl
Add torrent_data script to peek at torrent contents
2012-03-25 16:54:02 -04:00
rakshasa 07d326535d Merge branch 'master' into xirvik 2012-03-21 01:25:05 +09:00
rakshasa bb75f06c6d Replaced std::placeholders with tr1::placholders. 2012-03-21 01:24:35 +09:00
rakshasa 04acc8a0af Converted std::bind calls to tr1::bind. 2012-03-21 01:22:25 +09:00
rakshasa 0514a5c0d1 Merge branch 'master' into xirvik 2012-03-21 00:09:58 +09:00
rakshasa f1cd0f4780 Added 'system.api_version', which will be incremented every time the API changes. (sans brainfarts) 2012-03-21 00:05:37 +09:00
rakshasa ece90f975b Initiate worker thread after initializing libtorrent to ensure logging is properly done. 2012-03-20 23:52:32 +09:00
rakshasa 89611a222c Merge branch 'master' into xirvik 2012-03-19 19:05:01 +09:00
rakshasa 2c72c31e1c Since logs are now thread-safe, allow all threads to push log messages. #43 2012-03-19 15:33:50 +09:00
rakshasa cf3a1674a3 Merge branch 'master' into xirvik
Conflicts:
	configure.ac
2012-03-16 18:02:38 +09:00
rakshasa 64c66c81ae Bumped version to 0.9.1. 2012-03-16 18:01:19 +09:00
rakshasa bc993807d1 Merge branch 'master' into xirvik 2012-03-13 21:10:49 +09:00
rakshasa 3ac22e4bc7 Bumped default max file size to 128Gb. 2012-03-12 21:30:43 +09:00
rakshasa 3d1b0b5971 Cleaned up old log code. 2012-03-12 20:55:29 +09:00
rakshasa 7e0d5956b5 Use new logging buffer for complete log view. 2012-03-12 20:41:19 +09:00
rakshasa a186932c03 Use log_buffer for console logs. 2012-03-12 04:09:18 +09:00
Jari Sundell 79e9990669 Merge pull request #38 from sochotnicky/master
Without this change build will fail when using gold linker
2012-03-08 06:20:45 -08:00
Stanislav Ochotnicky 31ba6341cf Fix build with gold linker
This is needed for certain optimization levels with llvm
2012-03-08 11:00:57 +01:00
rakshasa 6b71d75c33 Test against both libtinfo and libtinfow. 2012-02-27 19:54:53 +09:00
rakshasa 4ff2483f07 Fixed libtinfow detection. 2012-02-27 17:40:08 +09:00
rakshasa d8f41a28fa Added check to see if libinfow is required by ncursesw. 2012-02-27 01:22:47 +09:00
rakshasa 482a9ba09f Used AX_PTHREAD and AX_WITH_CURSES macros. 2012-02-24 16:22:17 +09:00
rakshasa f7403d30e9 Merge branch 'master' into xirvik 2012-02-22 16:50:48 +09:00
rakshasa 639af87e53 Use new logging API. 2012-02-21 15:37:50 +09:00
rakshasa 6a45ca2dd6 Merge branch 'master' into xirvik 2012-02-18 02:22:48 +09:00
rakshasa 78abb7fed1 Reorder libraries for the unit test. 2012-02-18 02:21:17 +09:00
rakshasa 2da20f984e Merge branch 'master' into xirvik 2012-02-17 14:05:28 +09:00
rakshasa 1b4d8f9626 Removed old thread test code. 2012-02-16 15:08:30 +09:00
rakshasa a0ce6c09a6 Merge branch 'master' into xirvik 2012-02-15 13:15:13 +09:00
rakshasa 4bcf7f4f5e Added 'ipv4_filter.dump'. 2012-02-15 13:14:57 +09:00
rakshasa 45d2d0bd49 Added type names to events. 2012-02-14 19:37:21 +09:00
rakshasa 26581c74c1 Merge branch 'master' into xirvik 2012-02-14 13:38:47 +09:00
rakshasa 7fe2fb1584 Properly initialize the main poll object. 2012-02-14 13:38:27 +09:00
rakshasa d4cbe5294d Cleaned up formating. 2012-02-14 00:55:19 +09:00
rakshasa 0cbc11b536 Merge branch 'master' into xirvik 2012-02-13 19:08:14 +09:00
rakshasa d4a3ec0224 Add logging for IP addresses added. 2012-02-13 19:07:53 +09:00
rakshasa f50358b284 Merge branch 'master' into xirvik 2012-02-13 17:17:07 +09:00
rakshasa 4f601fda79 Use intermediate std::string to store the arguments to work around a possible bug. 2012-02-13 17:15:54 +09:00
rakshasa 8ed8ee9f81 Merge branch 'master' of github.com:rakshasa/rtorrent 2012-02-13 11:53:43 +09:00
Jari Sundell 2178422d90 Merge pull request #30 from extravagant/autoconf-2-68
Updated with AC_LANG_SOURCE directives
2012-02-12 18:45:59 -08:00
Extravagant f1852cd222 Updated with AC_LANG_SOURCE directives
Please see this informative thread on bug-autoconf:
http://www.mail-archive.com/bug-autoconf@gnu.org/msg03052.html
2012-02-12 22:23:40 +00:00
rakshasa 47125b9c38 Moved main thread object to libtorrent. 2012-02-12 21:58:16 +09:00
rakshasa 9ad22ab8ff Fixed log syntax. 2012-02-12 15:11:26 +09:00
rakshasa ba30dcd7cf Added names to threads. 2012-02-11 19:14:22 +09:00
rakshasa 4632053301 Added 'ip_tables.size_data'. 2012-02-11 18:52:46 +09:00
rakshasa 309711025b Cleaned up some code. 2012-02-11 16:17:13 +09:00
rakshasa 53edee3e06 Merge branch 'xirvik' of github.com:rakshasa/rtorrent-xirvik into xirvik 2012-02-08 15:16:02 +09:00
rakshasa cfc4984c3a Reverted version to stable. 2012-02-08 15:15:09 +09:00
Jari Sundell 6a399cd927 Merge remote branch 'upstream/master' into xirvik
Conflicts:
	.gitignore
2012-02-05 07:00:27 -05:00
rakshasa be95b82d29 Potential fix to the issue of torrents remaining closed after final hashing. 2012-01-30 00:29:06 +09:00
rakshasa 74ea256036 Updated gitignore files. 2012-01-29 22:31:51 +09:00
Jari Sundell 79517e61aa Merge branch 'master' into xirvik 2012-01-19 01:20:52 +09:00
Jari Sundell 222018e395 Removed obsolete 'system.hash.read_ahead', 'system.hash.interval' and 'system.hash.max_tries'. 2012-01-09 21:49:27 +09:00
Jari Sundell 18d51a60a1 Exit the autogen.sh script if one of the commands fail. 2012-01-05 13:30:47 +09:00
Jari Sundell e58f3975f1 Fixed compiler issues with clang. 2011-12-29 18:58:12 +09:00
Jari Sundell 002833f7b7 Fixed compile issues with C++03. 2011-12-27 17:26:36 +09:00
Jari Sundell 0626dcf783 C++11 fixes. 2011-12-27 16:45:19 +09:00
Jari Sundell f51b280cbf Merge branch 'master' into c++11 2011-12-27 15:50:01 +09:00
Jari Sundell 4c29d3b714 Removed extra semicolon. 2011-12-26 14:32:45 +09:00
Jari Sundell 28634f2c8c Added slot for poll creation. 2011-12-21 01:54:29 +09:00
Jari Sundell 007d83e904 Moved code from ThreadBase to torrent::thread_base. 2011-12-19 03:20:42 +09:00
Jari Sundell 5b7a2b5e95 Moved setting of PTHREAD related variables outside of the macro. 2011-12-19 03:19:54 +09:00
Jari Sundell 1c1993acef Cleaned up code. 2011-12-14 13:38:16 +09:00
Jari Sundell 1fc70a733d Merge branch 'master' into c++11
Conflicts:
	src/core/manager.cc
	src/thread_base.cc
2011-12-13 19:49:10 +09:00
Jari Sundell ee859a6137 Removed deprecated PollManager files. 2011-12-12 03:32:36 +09:00
Jari Sundell 4d1f5dce67 Fixed poll arguments. 2011-12-12 02:58:16 +09:00
Jari Sundell 6dfd2fe0cd Moved polling code to libtorrent. 2011-12-12 01:46:09 +09:00
Jari Sundell 89213982d5 Moving thread code to libtorrent. 2011-12-12 00:03:50 +09:00
Jari Sundell 2d8036e3a8 Use new API call. 2011-12-11 17:52:10 +09:00
Jari Sundell a2ad162fe3 Don't display scrape requests. 2011-12-11 15:41:05 +09:00
Jari Sundell 21944b941a Make sure we don't access freed memory if a download is erased during the erased event. 2011-12-11 12:21:24 +09:00
Jari Sundell 41d49b7c18 Merge branch 'master' into c++11
Conflicts:
	src/command_network.cc
2011-12-07 16:08:05 +09:00
Jari Sundell 3c4d21d34c Merge branch 'master' into xirvik 2011-12-07 02:31:56 +09:00
Jari Sundell 0d648119d2 Merge branch 'master' into xirvik 2011-11-26 01:47:03 +09:00
Jari Sundell 9a9dcb88f7 Merge branch 'master' into c++11 2011-11-26 01:44:52 +09:00
Jari Sundell 58727fe7fd Fixed compiler issues with gcc-4.6 c++0x. 2011-11-18 17:28:50 +09:00
Jari Sundell f0da99b5c3 Merge branch 'master' into xirvik 2011-11-08 01:10:14 +09:00
Jari Sundell c55f5611a9 Added 'd.tracker.send_scrape = <seconds_to_request>' command for sending scrape requests to all trackers that support it.
Newly inserted downloads send scrape requests after 30 seconds.
2011-11-08 00:45:11 +09:00
Jari Sundell 52530d5538 Added more scrape information to tracker info. 2011-11-07 21:34:06 +09:00
Jari Sundell 8d4aed7dae Use new function for inserting tracker. 2011-11-06 23:14:06 +09:00
Jari Sundell 7b38cc29aa Merge branch 'master' into xirvik 2011-11-06 03:38:37 +09:00
Jari Sundell 31495b06be Merge branch 'master' into xirvik 2011-10-27 13:44:32 +09:00
Jari Sundell 413becea38 Added some autoconf files to '.gitignore'. 2011-10-22 18:47:43 +09:00
263 changed files with 45849 additions and 9304 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
+7
View File
@@ -0,0 +1,7 @@
;;; Directory Local Variables
;;; For more information see (info "(emacs) Directory Variables")
((c++-mode
(flycheck-clang-language-standard . "c++11")
(flycheck-gcc-language-standard . "c++11")))
+13
View File
@@ -0,0 +1,13 @@
# These are supported funding model platforms
github: [rakshasa]
patreon: rtorrent
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: ['https://rakshasa.github.io/rtorrent/donate.html']
@@ -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
+68 -5
View File
@@ -1,9 +1,72 @@
# Compiled source #
###################
*.o
*.lo
*.a
*.la
*.so
*.in
*.sub
*.pc
*.orig
*.rej
# Autoconf files #
##################
.deps
.libs
Makefile
aclocal.m4
ar-lib
autom4te.cache
compile
config.h
config.guess
config.status
confdefs.h
conftest.dir
configure
depcomp
install-sh
libtool
ltmain.sh
missing
stamp-h1
src/rtorrent
scripts/libtool.m4
scripts/ltoptions.m4
scripts/ltsugar.m4
scripts/ltversion.m4
scripts/lt~obsolete.m4
scripts/lt*.m4
test/rtorrentTest
# Editor poo #
##############
.#*
\#*#
*~
# Packages #
############
# it's better to unpack these files and commit the raw source
# git has its own built in compression methods
*.gz
*.tar
*.zip
# Logs and databases #
######################
*.log
# OS generated files #
######################
.DS_Store?
.dirstamp
ehthumbs.db
Icon?
Thumbs.db
TAGS
# rTorrent specific files
###########################
src/rtorrent
test/rtorrent_Test*
test-driver
+85
View File
@@ -0,0 +1,85 @@
language: cpp
env:
global:
- MAKEFLAGS="-j 12"
matrix:
include:
- compiler: clang
env: COMPILER=clang++ SKIP_CHECK=true
- compiler: clang
env: COMPILER=clang++
addons:
apt:
packages:
- libcppunit-dev
- compiler: clang
env: COMPILER=clang++-3.6
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.6
packages:
- clang-3.6
- libcppunit-dev
- compiler: clang
env: COMPILER=clang++-3.7
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.7
packages:
- clang-3.7
- libcppunit-dev
- compiler: clang
env: COMPILER=clang++-3.8
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.8
packages:
- clang-3.8
- libcppunit-dev
- compiler: gcc
env: COMPILER=g++-4.7 SKIP_CHECK=true
addons:
apt:
sources: ubuntu-toolchain-r-test
packages:
- g++-4.7
- compiler: gcc
env: COMPILER=g++-4.7
addons:
apt:
sources: ubuntu-toolchain-r-test
packages:
- g++-4.7
- libcppunit-dev
- compiler: gcc
env: COMPILER=g++-4.8
addons:
apt:
sources: ubuntu-toolchain-r-test
packages:
- g++-4.8
- libcppunit-dev
# TODO: Use the same branch name if libtorrent has it.
before_install:
- git clone https://github.com/rakshasa/libtorrent.git
- |
pushd libtorrent \
&& (git checkout ${TRAVIS_BRANCH} || true) \
&& ./autogen.sh \
&& CXX="$COMPILER" ./configure --prefix=/usr \
&& make \
&& sudo make install \
&& popd
script:
- ./autogen.sh && CXX="$COMPILER" ./configure && make
- if [ ! $SKIP_CHECK ]; then make check; fi
+1 -1
View File
@@ -1 +1 @@
Jari Sundell <jaris@ifi.uio.no>
Jari Sundell <sundell.software@gmail.com>
+254 -115
View File
@@ -1,81 +1,109 @@
Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
Installation Instructions
*************************
Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software
Foundation, Inc.
This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it.
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 warranty of any kind.
Basic Installation
==================
These are generic installation instructions.
Briefly, the shell command './configure && make && make install'
should configure, build, and install this package. The following
more-detailed instructions are generic; see the 'README' file for
instructions specific to this package. Some packages provide this
'INSTALL' file but do not implement all of the features documented
below. The lack of an optional feature in a given package is not
necessarily a bug. More recommendations for GNU packages can be found
in *note Makefile Conventions: (standards)Makefile Conventions.
The `configure' shell script attempts to guess correct values for
The 'configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
those values to create a 'Makefile' in each directory of the package.
It may also create one or more '.h' files containing system-dependent
definitions. Finally, it creates a shell script 'config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
file 'config.log' containing compiler output (useful mainly for
debugging 'configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. (Caching is
disabled by default to prevent problems with accidental use of stale
cache files.)
It can also use an optional file (typically called 'config.cache' and
enabled with '--cache-file=config.cache' or simply '-C') that saves the
results of its tests to speed up reconfiguring. Caching is disabled by
default to prevent problems with accidental use of stale cache files.
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
to figure out how 'configure' could check whether to do them, and mail
diffs or instructions to the address given in the 'README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
some point 'config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You only need
`configure.ac' if you want to change it or regenerate `configure' using
a newer version of `autoconf'.
The file 'configure.ac' (or 'configure.in') is used to create
'configure' by a program called 'autoconf'. You need 'configure.ac' if
you want to change it or regenerate 'configure' using a newer version of
'autoconf'.
The simplest way to compile this package is:
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
1. 'cd' to the directory containing the package's source code and type
'./configure' to configure the package for your system.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
Running 'configure' might take a while. While running, it prints
some messages telling which features it is checking for.
2. Type `make' to compile the package.
2. Type 'make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
3. Optionally, type 'make check' to run any self-tests that come with
the package, generally using the just-built uninstalled binaries.
4. Type `make install' to install the programs and any data files and
documentation.
4. Type 'make install' to install the programs and any data files and
documentation. When installing into a prefix owned by root, it is
recommended that the package be configured and built as a regular
user, and only the 'make install' phase executed with root
privileges.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
5. Optionally, type 'make installcheck' to repeat any self-tests, but
this time using the binaries in their final installed location.
This target does not install anything. Running this target as a
regular user, particularly if the prior 'make install' required
root privileges, verifies that the installation completed
correctly.
6. You can remove the program binaries and object files from the
source code directory by typing 'make clean'. To also remove the
files that 'configure' created (so you can compile the package for
a different kind of computer), type 'make distclean'. There is
also a 'make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
7. Often, you can also type 'make uninstall' to remove the installed
files again. In practice, not all packages have tested that
uninstallation works correctly, even though it is required by the
GNU Coding Standards.
8. Some packages, particularly those that use Automake, provide 'make
distcheck', which can by used by developers to test that all other
targets like 'make install' and 'make uninstall' work correctly.
This target is generally not run by end users.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. Run `./configure --help'
the 'configure' script does not know about. Run './configure --help'
for details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
You can give 'configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here is
an example:
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
./configure CC=c99 CFLAGS=-g LIBS=-lposix
*Note Defining Variables::, for more details.
@@ -84,146 +112,257 @@ Compiling For Multiple Architectures
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
own directory. To do this, you can use GNU 'make'. 'cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
the 'configure' script. 'configure' automatically checks for the source
code in the directory that 'configure' is in and in '..'. This is known
as a "VPATH" build.
If you have to use a `make' that does not support the `VPATH'
variable, you have to compile the package for one architecture at a
time in the source code directory. After you have installed the
package for one architecture, use `make distclean' before reconfiguring
for another architecture.
With a non-GNU 'make', it is safer to compile the package for one
architecture at a time in the source code directory. After you have
installed the package for one architecture, use 'make distclean' before
reconfiguring for another architecture.
On MacOS X 10.5 and later systems, you can create libraries and
executables that work on multiple system types--known as "fat" or
"universal" binaries--by specifying multiple '-arch' options to the
compiler but only a single '-arch' option to the preprocessor. Like
this:
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CPP="gcc -E" CXXCPP="g++ -E"
This is not guaranteed to produce working output in all cases, you
may have to build one architecture at a time and combine the results
using the 'lipo' tool if you have problems.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
By default, 'make install' installs the package's commands under
'/usr/local/bin', include files under '/usr/local/include', etc. You
can specify an installation prefix other than '/usr/local' by giving
'configure' the option '--prefix=PREFIX', where PREFIX must be an
absolute file name.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
pass the option '--exec-prefix=PREFIX' to 'configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=PATH' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
options like '--bindir=DIR' to specify different values for particular
kinds of files. Run 'configure --help' for a list of the directories
you can set and what kinds of files go in them. In general, the default
for these options is expressed in terms of '${prefix}', so that
specifying just '--prefix' will affect all of the other directory
specifications that were not explicitly provided.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
The most portable way to affect installation locations is to pass the
correct locations to 'configure'; however, many packages provide one or
both of the following shortcuts of passing variable assignments to the
'make install' command line to change installation locations without
having to reconfigure or recompile.
The first method involves providing an override variable for each
affected directory. For example, 'make install
prefix=/alternate/directory' will choose an alternate location for all
directory configuration variables that were expressed in terms of
'${prefix}'. Any directories that were specified during 'configure',
but not in terms of '${prefix}', must each be overridden at install time
for the entire installation to be relocated. The approach of makefile
variable overrides for each directory variable is required by the GNU
Coding Standards, and ideally causes no recompilation. However, some
platforms have known limitations with the semantics of shared libraries
that end up requiring recompilation when using this method, particularly
noticeable in packages that use GNU Libtool.
The second method involves providing the 'DESTDIR' variable. For
example, 'make install DESTDIR=/alternate/directory' will prepend
'/alternate/directory' before all installation names. The approach of
'DESTDIR' overrides is not required by the GNU Coding Standards, and
does not work on platforms that have drive letters. On the other hand,
it does better at avoiding recompilation issues, and works well even
when some directory options were not specified in terms of '${prefix}'
at 'configure' time.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving 'configure' the
option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'.
Some packages pay attention to '--enable-FEATURE' options to
'configure', where FEATURE indicates an optional part of the package.
They may also pay attention to '--with-PACKAGE' options, where PACKAGE
is something like 'gnu-as' or 'x' (for the X Window System). The
'README' should mention any '--enable-' and '--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
For packages that use the X Window System, 'configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
you can use the 'configure' options '--x-includes=DIR' and
'--x-libraries=DIR' to specify their locations.
Some packages offer the ability to configure how verbose the
execution of 'make' will be. For these packages, running './configure
--enable-silent-rules' sets the default to minimal output, which can be
overridden with 'make V=1'; while running './configure
--disable-silent-rules' sets the default to verbose, which can be
overridden with 'make V=0'.
Particular systems
==================
On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC
is not installed, it is recommended to use the following options in
order to use an ANSI C compiler:
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
HP-UX 'make' updates targets which have the same time stamps as their
prerequisites, which makes it generally unusable when shipped generated
files such as 'configure' are involved. Use GNU 'make' instead.
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
parse its '<wchar.h>' header file. The option '-nodtk' can be used as a
workaround. If GNU CC is not installed, it is therefore recommended to
try
./configure CC="cc"
and if that doesn't work, try
./configure CC="cc -nodtk"
On Solaris, don't put '/usr/ucb' early in your 'PATH'. This
directory contains several dysfunctional programs; working variants of
these programs are available in '/usr/bin'. So, if you need '/usr/ucb'
in your 'PATH', put it _after_ '/usr/bin'.
On Haiku, software installed for all users goes in '/boot/common',
not '/usr/local'. It is recommended to use the following options:
./configure --prefix=/boot/common
Specifying the System Type
==========================
There may be some features `configure' cannot figure out
There may be some features 'configure' cannot figure out
automatically, but needs to determine by the type of machine the package
will run on. Usually, assuming the package is built to be run on the
_same_ architectures, `configure' can figure that out, but if it prints
_same_ architectures, 'configure' can figure that out, but if it prints
a message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
'--build=TYPE' option. TYPE can either be a short name for the system
type, such as 'sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS KERNEL-OS
OS
KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
See the file 'config.sub' for the possible values of each field. If
'config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the `--target=TYPE' option to select the type of system they will
use the option '--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
eventually be run) with '--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
If you want to set default values for 'configure' scripts to share,
you can create a site shell script called 'config.site' that gives
default values for variables like 'CC', 'cache_file', and 'prefix'.
'configure' looks for 'PREFIX/share/config.site' if it exists, then
'PREFIX/etc/config.site' if it exists. Or, you can set the
'CONFIG_SITE' environment variable to the location of the site script.
A warning: not all 'configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
environment passed to 'configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
them in the 'configure' command line, using 'VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
will cause the specified gcc to be used as the C compiler (unless it is
causes the specified 'gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
`configure' Invocation
Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an
Autoconf limitation. Until the limitation is lifted, you can use this
workaround:
CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
'configure' Invocation
======================
`configure' recognizes the following options to control how it
'configure' recognizes the following options to control how it
operates.
`--help'
`-h'
Print a summary of the options to `configure', and exit.
'--help'
'-h'
Print a summary of all of the options to 'configure', and exit.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
'--help=short'
'--help=recursive'
Print a summary of the options unique to this package's
'configure', and exit. The 'short' variant lists options used only
in the top level, while the 'recursive' variant lists options also
present in any nested packages.
'--version'
'-V'
Print the version of Autoconf used to generate the 'configure'
script, and exit.
`--cache-file=FILE'
'--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
traditionally 'config.cache'. FILE defaults to '/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
'--config-cache'
'-C'
Alias for '--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
'--quiet'
'--silent'
'-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
suppress all normal output, redirect it to '/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
'--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
'configure' can determine that directory automatically.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.
'--prefix=DIR'
Use DIR as the installation prefix. *note Installation Names:: for
more details, including other options available for fine-tuning the
installation locations.
'--no-create'
'-n'
Run the configure checks, but stop before creating any output
files.
'configure' also accepts some other, not widely useful, options. Run
'configure --help' for more details.
-3
View File
@@ -4,15 +4,12 @@ SUBDIRS = \
test
EXTRA_DIST= \
autogen.sh \
rak/address_info.h \
rak/algorithm.h \
rak/allocators.h \
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 \
+10 -5
View File
@@ -1,8 +1,8 @@
BUILDING
Run "./autogen.sh" to generate the configure scripts if
nessesary. The man page "doc/rtorrent.1" must be generated with
"docbook2man rtorrent.1.xml" if it is missing.
Run "aclocal -I scripts && autoconf -i && autoheader && automake --add-missing"
to generate the configure scripts if necessary. The man page "doc/rtorrent.1"
must be generated with "docbook2man rtorrent.1.xml" if it is missing.
Note that rtorrent follows the development of libtorrent closely, and
thus the versions must be in sync. This should not be nessesary in the
@@ -32,5 +32,10 @@ DEPENDENCIES
CONTACT
Send bug reports, suggestions and patches to <jaris@ifi.uio.no> or
to the mailinglist.
Jari Sundell
Skomakerveien 33
3185 Skoppum, NORWAY
Send bug reports, suggestions and patches to
<sundell.software@gmail.com> or to the mailinglist.
+40
View File
@@ -0,0 +1,40 @@
[![Donate](https://rakshasa.github.io/rtorrent/donate_paypal_green.svg)](https://paypal.me/jarisundelljp)
RTorrent BitTorrent Client
========
Introduction
------------
To learn how to use rTorrent visit the [Wiki](https://github.com/rakshasa/rtorrent/wiki).
Stable
------
* [https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.13.8.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.13.8.tar.gz)
* [https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.9.8.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.9.8.tar.gz)
Unstable
------
* [https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.14.0.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.14.0.tar.gz)
* [https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.10.0.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.10.0.tar.gz)
Related Projects
----------------
* [https://github.com/rakshasa/rbedit](https://github.com/rakshasa/rbedit): A dependency-free bencode editor.
Donate to rTorrent development
------------------------------
* [Paypal](https://paypal.me/jarisundellno)
* [Patreon](https://www.patreon.com/rtorrent)
* [SubscribeStar](https://www.subscribestar.com/rtorrent)
* Bitcoin: 1MpmXm5AHtdBoDaLZstJw8nupJJaeKu8V8
* Ethereum: 0x9AB1e3C3d8a875e870f161b3e9287Db0E6DAfF78
* Litecoin: LdyaVR67LBnTf6mAT4QJnjSG2Zk67qxmfQ
* Cardano: addr1qytaslmqmk6dspltw06sp0zf83dh09u79j49ceh5y26zdcccgq4ph7nmx6kgmzeldauj43254ey97f3x4xw49d86aguqwfhlte
Help keep rTorrent development going by donating to its creator.
-51
View File
@@ -1,51 +0,0 @@
#! /bin/sh
echo aclocal...
(aclocal --version) < /dev/null > /dev/null 2>&1 || {
echo aclocal not found
exit 1
}
aclocal -I ./scripts -I . ${ACLOCAL_FLAGS}
echo autoheader...
(autoheader --version) < /dev/null > /dev/null 2>&1 || {
echo autoheader not found
exit 1
}
autoheader
echo -n "libtoolize... "
if ( (glibtoolize --version) < /dev/null > /dev/null 2>&1 ); then
echo "using glibtoolize"
glibtoolize --automake --copy --force
elif ( (libtoolize --version) < /dev/null > /dev/null 2>&1 ) ; then
echo "using libtoolize"
libtoolize --automake --copy --force
else
echo "libtoolize nor glibtoolize not found"
exit 1
fi
echo automake...
(automake --version) < /dev/null > /dev/null 2>&1 || {
echo automake not found
exit 1
}
automake --add-missing --copy --gnu
echo autoconf...
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
echo autoconf not found
exit 1
}
autoconf
echo ready to configure
exit 0
+62 -41
View File
@@ -1,52 +1,72 @@
AC_INIT(rtorrent, 0.9.0, jaris@ifi.uio.no)
m4_pattern_allow([PKG_CHECK_EXISTS])
AM_INIT_AUTOMAKE
AM_CONFIG_HEADER(config.h)
AM_PATH_CPPUNIT(1.9.6)
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
LT_INIT
AC_PROG_CXX
AC_PROG_LIBTOOL
AC_DEFINE([API_VERSION], [11], [api version])
TORRENT_CHECK_CXXFLAGS()
TORRENT_ENABLE_DEBUG()
TORRENT_ENABLE_EXTRA_DEBUG()
TORRENT_ENABLE_WERROR()
# Filter out unwanted flags added by autoconf on some systems, e.g. MacOS.
TORRENT_REMOVE_UNWANTED(CXX, $CXX, -std=c++11 -std=gnu++11)
TORRENT_DISABLE_IPV6
AX_CXX_COMPILE_STDCXX([17], [noext], [mandatory])
AC_SYS_LARGEFILE
TORRENT_CHECK_EXECINFO()
TORRENT_OTFD()
RAK_CHECK_CFLAGS
RAK_CHECK_CXXFLAGS
RAK_ENABLE_DEBUG
RAK_ENABLE_EXTRA_DEBUG
RAK_ENABLE_WERROR
TORRENT_DISABLE_IPV6
TORRENT_ENABLE_ARCH
TORRENT_WITH_SYSROOT
TORRENT_WITHOUT_VARIABLE_FDSET()
TORRENT_WITHOUT_NCURSESW()
TORRENT_WITHOUT_STATVFS()
TORRENT_WITHOUT_STATFS()
TORRENT_WITHOUT_VARIABLE_FDSET
TORRENT_WITHOUT_STATVFS
TORRENT_WITHOUT_STATFS
ACX_PTHREAD(CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS";
LIBS="$PTHREAD_LIBS $LIBS"
)
AC_ARG_ENABLE(execinfo,
AS_HELP_STRING([--disable-execinfo],
[disable libexecinfo [[default=enable]]]),
[
if test "$enableval" = "yes"; then
AX_EXECINFO
fi
],[
AX_EXECINFO
])
PKG_CHECK_MODULES(sigc, sigc++-2.0,
CXXFLAGS="$CXXFLAGS $sigc_CFLAGS";
LIBS="$LIBS $sigc_LIBS")
AX_PTHREAD([], AC_MSG_ERROR([requires pthread]))
AX_WITH_CURSES
PKG_CHECK_MODULES(libcurl, libcurl >= 7.15.4,
CXXFLAGS="$CXXFLAGS $libcurl_CFLAGS";
LIBS="$LIBS $libcurl_LIBS")
if test "x$ax_cv_ncursesw" != xyes && test "x$ax_cv_ncurses" != xyes; then
AC_MSG_ERROR([requires either NcursesW or Ncurses library])
fi
PKG_CHECK_MODULES(libtorrent, libtorrent >= 0.13.0,
CXXFLAGS="$CXXFLAGS $libtorrent_CFLAGS";
LIBS="$LIBS $libtorrent_LIBS")
PKG_CHECK_MODULES([LIBCURL], [libcurl],, [LIBCURL_CHECK_CONFIG])
PKG_CHECK_MODULES([CPPUNIT], [cppunit],, [no_cppunit="yes"])
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)
@@ -55,19 +75,20 @@ TORRENT_CHECK_CACHELINE()
TORRENT_CHECK_POPCOUNT()
CC_ATTRIBUTE_UNUSED(
AC_DEFINE([__UNUSED], [__attribute__((unused))], [Wrapper around unused attribute]),
AC_DEFINE([__UNUSED], [], [Null-wrapper if unused attribute is unsupported])
AC_DEFINE([__UNUSED], [__attribute__((unused))], [Wrapper around unused attribute]),
AC_DEFINE([__UNUSED], [], [Null-wrapper if unused attribute is unsupported])
)
AC_OUTPUT([
Makefile
doc/Makefile
src/Makefile
src/core/Makefile
src/display/Makefile
src/input/Makefile
src/rpc/Makefile
src/ui/Makefile
src/utils/Makefile
test/Makefile
dnl Only update global build variables immediately before generating the output,
dnl to avoid affecting the global build environment for other autoconf checks.
LIBS="$PTHREAD_LIBS $CURSES_LIB $CURSES_LIBS $LIBCURL $LIBCURL_LIBS $DEPENDENCIES_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS $LIBCURL_CPPFLAGS $LIBCURL_CFLAGS $DEPENDENCIES_CFLAGS $CURSES_CFLAGS"
CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS $LIBCURL_CPPFLAGS $LIBCURL_CFLAGS $DEPENDENCIES_CFLAGS $CURSES_CFLAGS"
AC_CONFIG_FILES([
Makefile
doc/Makefile
src/Makefile
test/Makefile
])
AC_OUTPUT
-5
View File
@@ -1,7 +1,2 @@
#man_MANS = rtorrent.1
EXTRA_DIST= \
faq.xml \
rtorrent.1 \
rtorrent.1.xml \
rtorrent.rc
Regular → Executable
View File
Regular → Executable
View File
+28
View File
@@ -0,0 +1,28 @@
# Choke Groups
## Settings
choke_group.insert = "leech_fast"
Create a new group named "leech_fast", accessible by the string or
index / reverse index according to order of insertion. E.g. '-1'
refers to the last inserted choke group, while 0 refers to the first.
All commands that applies to a group requires the first argument to be
the index, reverse index or the group name.
choke_group.tracker.mode.set = -1,"aggressive"
Set the tracker mode for torrents in this group.
choke_group.up.heuristics.set = -1,"upload_leech_experimental"
choke_group.down.heuristics.set = -1,"download_leech"
Set the heuristics used when deciding on which peers to choke and
unchoke. Use "strings.choke_heuristics{,.upload,.download}" to get a
list of the available heuristics.
choke_group.up.max.set = -1,250
choke_group.down.max.set = -1,500
Set the max total number of unchoked peers for all torrents in this choke group.
+64
View File
@@ -0,0 +1,64 @@
# IP filtering
## Introduction
## Make a new ip table
ip_tables.insert_table = <table_name>
Create a new empty table with the name table\_name, with the default
value returned being $0$.
There is currently no use of the generic ip tables commands.
## Add a new address block
ip_tables.add_address = <table_name>, 10.0.0.0/8, <value>
Set <value\> for all addresses in the address block, overwriting prior
values.
## Add a new address block
ip_tables.load = <table_name>, ~/foo.txt, <value>
Set <value\> for all addresses in the file foo.txt separated by
newline, similar to add\_address.
## Get value for address
ip_tables.get = <table_name>, 10.10.10.10
Returns the value set for an address, or the address block it belongs
to. The default is $0$.
## Size of data structures
ip_tables.size_data = <table_name>
Returns the size in bytes of all data structures for this table,
excluding the root class object itself. Note that the in-memory table is
dynamically consolidated, as such memory use will always be based on
actual fragmentation.
The table is a b-tree with 1024 nodes per branch.
## IPv4 filtering table
ipv4_filter.add_address = 10.0.0.0/8, unwanted
ipv4_filter.add_address = 11.0.0.0/8, preferred
ipv4_filter.load = ~/filters.txt, unwanted
ipv4_filter.get = 10.10.10.10
ipv4_filter.size_data =
The main ip filter, currently supporting unwanted (do not allow
connections) and preferred (currently used only in private code).
## Constants
strings.ip_filter =
=>
{ "unwanted", PeerInfo::flag_unwanted },
{ "preferred", PeerInfo::flag_preferred },
Constants used by ipv4\_filter values.
+85
View File
@@ -0,0 +1,85 @@
\section{IP filtering}
\subsection{Introduction}
\subsection{Make a new ip table}
\begin{verbatim}
ip_tables.insert_table = <table_name>
\end{verbatim}
Create a new empty table with the name 'table\_name', with the default
value returned being $0$.
There is currently no use of the generic ip tables commands.
\subsection{Add a new address block}
\begin{verbatim}
ip_tables.add_address = <table_name>, 10.0.0.0/8, <value>
\end{verbatim}
Set <value> for all addresses in the address block, overwriting prior
values.
\subsection{Add a new address block}
\begin{verbatim}
ip_tables.load = <table_name>, ~/foo.txt, <value>
\end{verbatim}
Set <value> for all addresses in the file 'foo.txt' separated by
newline, similar to 'add\_address'.
\subsection{Get value for address}
\begin{verbatim}
ip_tables.get = <table_name>, 10.10.10.10
\end{verbatim}
Returns the value set for an address, or the address block it belongs
to. The default is $0$.
\subsection{Size of data structures}
\begin{verbatim}
ip_tables.size_data = <table_name>
\end{verbatim}
Returns the size in bytes of all data structures for this table,
excluding the root class object itself. Note that the in-memory table
is dynamically consolidated, as such memory use will always be based
on actual fragmentation.
The table is a b-tree with 1024 nodes per branch.
\subsection{IPv4 filtering table}
\begin{verbatim}
ipv4_filter.add_address = 10.0.0.0/8, unwanted
ipv4_filter.add_address = 11.0.0.0/8, preferred
ipv4_filter.load = ~/filters.txt, unwanted
ipv4_filter.get = 10.10.10.10
ipv4_filter.size_data =
\end{verbatim}
The main ip filter, currently supporting 'unwanted' (do not allow
connections) and 'preferred' (currently used only in private code).
\subsection{Constants}
\begin{verbatim}
strings.ip_filter =
=>
{ "unwanted", PeerInfo::flag_unwanted },
{ "preferred", PeerInfo::flag_preferred },
\end{verbatim}
Constants used by ipv4_filter values.
+50
View File
@@ -0,0 +1,50 @@
# Logging
## Opening log files
# log.open_file = "log name", "file path"
log.open_file = "rtorrent.log", (cat,/tmp/rtorrent.log.,(system.pid))
A newly opened log file is not connected to any logging events.
Some control over formatting will be provided at a later date.
## Adding outputs to events
# log.add_output = "logging event", "log name"
log.add_output = "info", "rtorrent.log"
log.add_output = "dht_debug", "tracker.log"
log.add_output = "tracker_debug", "tracker.log"
Each log handle can be added to multiple different logging events.
## Logging events
"critical"
"error"
"warn"
"notice"
"info"
"debug"
The above events receive logging events from all the sub-groups
displayed below, and each event also reciving events from the event
above in importance.
Thus some high-volume sub-group events such as “tracker\_debug” are not
part of “debug” and every “warn” event will receive events from “error”,
“critical”.
"connection_*"
"dht_*"
"peer_*"
"rpc_*"
"storage_*"
"thread_*"
"tracker_*"
"torrent_*"
All sub-groups have events from “critical” to “debug” defined.
+4 -5
View File
@@ -52,7 +52,7 @@ Decrease the download throttle by 1/5/50 KB.
\fB->\fR
View download.
.TP
\fB1 - 7\fR
\fB0 - 9\fR
Change view.
.TP
\fB^S\fR
@@ -99,6 +99,9 @@ Delete the file the torrent is tied to, and clear the association.
.TP
\fBI\fR
Toggle whether torrent ignores ratio settings.
.TP
\fBF\fR
Add a temporary name based regex filter to the current view.
.SS "DOWNLOAD VIEW KEYS"
.TP
\fB->\fR
@@ -496,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
+55 -74
View File
@@ -122,7 +122,7 @@ View download.
</varlistentry>
<varlistentry>
<term>1 - 7</term>
<term>0 - 9</term>
<listitem><para>
Change view.
</para></listitem>
@@ -225,6 +225,13 @@ Toggle whether torrent ignores ratio settings.
</para></listitem>
</varlistentry>
<varlistentry>
<term>F</term>
<listitem><para>
Add a temporary name based regex filter to the current view.
</para></listitem>
</varlistentry>
</variablelist>
</refsect2>
@@ -507,29 +514,6 @@ Enable/disable peer exchange for torrents that aren't marked private. Disabled b
</para></listitem>
</varlistentry>
<varlistentry>
<term>schedule = <replaceable>id</replaceable>,<replaceable>start</replaceable>,<replaceable>interval</replaceable>,<replaceable>command</replaceable></term>
<listitem><para>
Call <emphasis>command</emphasis> every <emphasis>interval</emphasis>
seconds, starting from <emphasis>start</emphasis>. An
<emphasis>interval</emphasis> of zero calls the task once, while a
<emphasis>start</emphasis> of zero calls it immediately. Currently
<emphasis>command</emphasis> is forwarded to the option handler.
<emphasis>start</emphasis> and <emphasis>interval</emphasis> may
optionally use a time format, <emphasis>dd:hh:mm:ss</emphasis>. F.ex to
start a task every day at <emphasis>18:00</emphasis>, use
<emphasis>18:00:00,24:00:00</emphasis>.
</para></listitem>
</varlistentry>
<varlistentry>
<term>schedule_remove = <replaceable>id</replaceable></term>
<listitem><para>
Delete <emphasis>id</emphasis> from the scheduler.
</para></listitem>
</varlistentry>
<varlistentry>
<term>start_tied =</term>
<listitem><para>
@@ -580,40 +564,6 @@ torrent::input_error exception on bad input.
</para></listitem>
</varlistentry>
<varlistentry>
<term>stop_on_ratio = <replaceable>min_ratio</replaceable></term>
<term>stop_on_ratio = <replaceable>min_ratio</replaceable>,<replaceable>min_upload</replaceable></term>
<term>stop_on_ratio = <replaceable>min_ratio</replaceable>,<replaceable>min_upload</replaceable>,<replaceable>max_ratio</replaceable></term>
<listitem><para>
Stop torrents when they reach the given upload ratio
<emphasis>min_ratio</emphasis> in percent. If the optional
<emphasis>min_upload</emphasis> is given, require a total
upload amount of this many bytes as well. If the optional
<emphasis>max_ratio</emphasis> is given, stop the torrent
when reaching this ratio regardless of the total upload
amount. Exclude certain torrent by pressing
<emphasis>Shift+I</emphasis> in the downlist list.
Use with the <emphasis>schedule</emphasis> option.
</para></listitem>
</varlistentry>
<varlistentry>
<term>on_insert = <replaceable>id</replaceable>,<replaceable>command</replaceable></term>
<term>on_erase = <replaceable>id</replaceable>,<replaceable>command</replaceable></term>
<term>on_open = <replaceable>id</replaceable>,<replaceable>command</replaceable></term>
<term>on_close = <replaceable>id</replaceable>,<replaceable>command</replaceable></term>
<term>on_start = <replaceable>id</replaceable>,<replaceable>command</replaceable></term>
<term>on_stop = <replaceable>id</replaceable>,<replaceable>command</replaceable></term>
<term>on_hash_queued = <replaceable>id</replaceable>,<replaceable>command</replaceable></term>
<term>on_hash_removed = <replaceable>id</replaceable>,<replaceable>command</replaceable></term>
<term>on_hash_done = <replaceable>id</replaceable>,<replaceable>command</replaceable></term>
<term>on_finished = <replaceable>id</replaceable>,<replaceable>command</replaceable></term>
<listitem><para>
Call a command on a download when its state changes. Only a subset of
commands are available.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
@@ -629,6 +579,8 @@ commands are available.
<varlistentry>
<term>upload_rate = <replaceable>KB</replaceable></term>
<term>download_rate = <replaceable>KB</replaceable></term>
<term>set_upload_rate = <replaceable>TODO</replaceable></term>
<term>set_download_rate = <replaceable>TODO</replaceable></term>
<listitem><para>
Set the maximum global uploand and download rates.
</para></listitem>
@@ -653,14 +605,19 @@ Set the minimum nad maximum number of peers to allow while seeding, or
<varlistentry>
<term>max_uploads = <replaceable>value</replaceable></term>
<term>max_downloads = <replaceable>value</replaceable></term>
<term>min_uploads = <replaceable>value</replaceable></term>
<term>min_downloads = <replaceable>value</replaceable></term>
<listitem><para>
Set the maximum number of simultaneous uploads per download.
Set the maximum/minimum number of simultaneous uploads/downloads per download/upload.
</para></listitem>
</varlistentry>
<varlistentry>
<term>max_uploads_div = <replaceable>value</replaceable></term>
<term>max_downloads_div = <replaceable>value</replaceable></term>
<term>set_max_uploads_div = <replaceable>value</replaceable></term>
<term>set_max_downloads_div = <replaceable>value</replaceable></term>
<listitem><para>
Change the divider used to calculate the max upload and download slots
to use when the throttle is changed. Disable by
@@ -671,6 +628,8 @@ setting <emphasis>0</emphasis>.
<varlistentry>
<term>max_uploads_global = <replaceable>value</replaceable></term>
<term>max_downloads_global = <replaceable>value</replaceable></term>
<term>set_max_uploads_global = <replaceable>value</replaceable></term>
<term>set_max_downloads_global = <replaceable>value</replaceable></term>
<listitem><para>
Max upload and download slots allowed. Disable by
setting <emphasis>0</emphasis>.
@@ -746,6 +705,27 @@ not allow connections to UDP trackers.
</para></listitem>
</varlistentry>
<varlistentry>
<term>http_capath = <replaceable>path</replaceable></term>
<term>http_cacert = <replaceable>filename</replaceable></term>
<listitem><para>
Set the certificates to use in http requests. See Curl's
CURLOPT_CAPATH and CURLOPT_CAINFO options for further information.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>DHT-RELATED SETTINGS</title>
<para>
Settings related to DHT
</para>
<variablelist>
<varlistentry>
<term>dht = <replaceable>disabled|off|auto|on</replaceable></term>
<listitem><para>
@@ -779,11 +759,23 @@ The port is optional, with port 6881 being used by default.
</varlistentry>
<varlistentry>
<term>http_capath = <replaceable>path</replaceable></term>
<term>http_cacert = <replaceable>filename</replaceable></term>
<term>dht_statistics = <replaceable>TODO</replaceable></term>
<listitem><para>
Set the certificates to use in http requests. See Curl's
CURLOPT_CAPATH and CURLOPT_CAINFO options for further information.
TODO
</para></listitem>
</varlistentry>
<varlistentry>
<term>set_dht_port = <replaceable>TODO</replaceable></term>
<listitem><para>
TODO
</para></listitem>
</varlistentry>
<varlistentry>
<term>set_dht_throttle = <replaceable>TODO</replaceable></term>
<listitem><para>
TODO
</para></listitem>
</varlistentry>
@@ -791,7 +783,6 @@ CURLOPT_CAPATH and CURLOPT_CAINFO options for further information.
</refsect1>
<refsect1>
<title>USER-INTERFACE SETTINGS</title>
<para>
@@ -987,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>
+30
View File
@@ -0,0 +1,30 @@
#/bin/bash
gnuplot << EOF
set terminal png size 1024 * 1, 768 enhanced
set xdata time
set timefmt "%s"
set format x "%H:%M"
set y2tics
set autoscale xfix
set key autotitle columnhead
set format y "%.0f"
set format y2 "%.0f"
set output "output_$1_incore_sync.png"
plot \
"instrumentation_mincore.log.$1" using 1:6 title 'success' with lines lw 4 axis x1y1,\
"instrumentation_mincore.log.$1" using 1:7 title 'failed' with lines lw 4 axis x1y1,\
"instrumentation_mincore.log.$1" using 1:8 title 'not synced' with lines lw 4 axis x1y2,\
"instrumentation_mincore.log.$1" using 1:9 title 'not deallocated' with lines lw 4 axis x1y2
set format y "%.0g"
set output "output_$1_incore_alloc.png"
plot \
"instrumentation_mincore.log.$1" using 1:12 title 'allocations' with lines lw 2 axis x1y1,\
"instrumentation_mincore.log.$1" using 1:13 title 'deallocations' with lines lw 4 axis x1y1,\
"instrumentation_mincore.log.$1" using 1:10 title 'alloc failed' with lines lw 2 axis x1y2
EOF
+49
View File
@@ -0,0 +1,49 @@
#/bin/bash
gnuplot << EOF
set terminal png size 1024,768 enhanced
set xdata time
set timefmt "%s"
set format x "%H:%M"
set y2tics
set autoscale xfix
set key autotitle columnhead
# set datafile missing '0'
set format y "%.0f"
set format y2 "%.0f"
set yrange [0:]
set y2range [0:]
set output "output_$1_transfer_requests.png"
plot \
"instrumentation_transfers.log.$1" using 1:2 title 'delegated' with lines lw 4 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:3 title 'downloading' with lines lw 4 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:4 title 'finished' with lines lw 4 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:5 title 'skipped' with lines lw 2 axis x1y2,\
"instrumentation_transfers.log.$1" using 1:6 title 'unknown' with lines lw 2 axis x1y2,\
"instrumentation_transfers.log.$1" using 1:7 title 'unordered' with lines lw 2 axis x1y2,\
"instrumentation_transfers.log.$1" using 1:19 title 'unaccounted' with lines lw 2 axis x1y2
set output "output_$1_transfer_queues.png"
plot \
"instrumentation_transfers.log.$1" using 1:8 title 'queue added' with lines lw 2 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:9 title 'queue moved' with lines lw 2 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:10 title 'queue removed' with lines lw 2 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:11 title 'queue total' with lines lw 4 axis x1y2,\
"instrumentation_transfers.log.$1" using 1:12 title 'unordered added' with lines lw 2 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:13 title 'unordered moved' with lines lw 2 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:14 title 'unordered removed' with lines lw 2 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:15 title 'unordered total' with lines lw 4 axis x1y2,\
"instrumentation_transfers.log.$1" using 1:16 title 'stalled added' with lines lw 2 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:17 title 'stalled moved' with lines lw 2 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:18 title 'stalled removed' with lines lw 2 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:19 title 'stalled total' with lines lw 4 axis x1y2,\
"instrumentation_transfers.log.$1" using 1:20 title 'choked added' with lines lw 2 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:21 title 'choked moved' with lines lw 2 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:22 title 'choked removed' with lines lw 2 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:23 title 'choked total' with lines lw 4 axis x1y2
EOF
+85 -59
View File
@@ -1,102 +1,128 @@
# This is an example resource file for rTorrent. Copy to
# ~/.rtorrent.rc and enable/modify the options as needed. Remember to
# uncomment the options you wish to enable.
#############################################################################
# This is an (old) example resource file for rTorrent.
# Copy to ~/.rtorrent.rc and enable/modify the options as needed.
# Remember to uncomment the options you wish to enable.
#
# See 'rtorrent.rc-example' for a newer, basic configuration.
#
# Sample: https://github.com/rakshasa/rtorrent/wiki/CONFIG-Template
# Complete: https://rtorrent-docs.readthedocs.io/en/latest/cmd-ref.html
# Useful: https://rtorrent-docs.readthedocs.io/en/latest/use-cases.html
# Manual: https://rtorrent-docs.readthedocs.io/en/latest/
# Convert: https://github.com/rakshasa/rtorrent/wiki/rTorrent-0.9-Comprehensive-Command-list-(WIP)
# Handbook: https://media.readthedocs.org/pdf/rtorrent-docs/latest/rtorrent-docs.pdf
# File: https://github.com/rakshasa/rtorrent/blob/master/doc/rtorrent.rc
#############################################################################
# Maximum and minimum number of peers to connect to per torrent.
#min_peers = 40
#max_peers = 100
#
#throttle.min_peers.normal.set = 40
#throttle.max_peers.normal.set = 100
# Same as above but for seeding completed torrents (-1 = same as downloading)
#min_peers_seed = 10
#max_peers_seed = 50
# Same as above but for seeding completed torrents.
# "-1" = same as downloading.
#
#throttle.min_peers.seed.set = 10
#throttle.max_peers.seed.set = 50
# Maximum number of simultanious uploads per torrent.
#max_uploads = 15
# Maximum number of simultaneous uploads per torrent.
#
#throttle.max_uploads.set = 15
# Global upload and download rate in KiB. "0" for unlimited.
#download_rate = 0
#upload_rate = 0
# Global upload and download rate in KiB.
# "0" for unlimited.
#
#throttle.global_down.max_rate.set_kb = 0
#throttle.global_up.max_rate.set_kb = 0
# Default directory to save the downloaded torrents.
#directory = ./
#
#directory.default.set = ./
# Default session directory. Make sure you don't run multiple instance
# of rtorrent using the same session directory. Perhaps using a
# of rTorrent using the same session directory. Perhaps using a
# relative path?
#session = ./session
#
#session.path.set = ./session
# Watch a directory for new torrents, and stop those that have been
# deleted.
#schedule = watch_directory,5,5,load_start=./watch/*.torrent
#schedule = untied_directory,5,5,stop_untied=
#
#schedule2 = watch_directory,5,5,load.start=./watch/*.torrent
# Close torrents when diskspace is low.
#schedule = low_diskspace,5,60,close_low_diskspace=100M
# Close torrents when disk-space is low.
#
#schedule2 = low_diskspace,5,60,close_low_diskspace=100M
# The ip address reported to the tracker.
#ip = 127.0.0.1
#ip = rakshasa.no
# The IP address reported to the tracker.
#
#network.local_address.set = 127.0.0.1
#network.local_address.set = rakshasa.no
# The ip address the listening socket and outgoing connections is
# The IP address the listening socket and outgoing connections is
# bound to.
#bind = 127.0.0.1
#bind = rakshasa.no
#
#network.bind_address.set = 127.0.0.1
#network.bind_address.set = rakshasa.no
# Port range to use for listening.
#port_range = 6890-6999
#
#network.port_range.set = 6890-6999
# Start opening ports at a random position within the port range.
#port_random = no
#
#network.port_random.set = no
# Check hash for finished torrents. Might be usefull until the bug is
# fixed that causes lack of diskspace not to be properly reported.
#check_hash = no
# Check hash for finished torrents. Might be useful until the bug is
# fixed that causes lack of disk-space not to be properly reported.
#
#pieces.hash.on_completion.set = no
# Set whetever the client should try to connect to UDP trackers.
#use_udp_trackers = yes
# Set whether the client should try to connect to UDP trackers.
#
#trackers.use_udp.set = yes
# Alternative calls to bind and ip that should handle dynamic ip's.
#schedule = ip_tick,0,1800,ip=rakshasa
#schedule = bind_tick,0,1800,bind=rakshasa
# Alternative calls to bind and IP that should handle dynamic IP's.
#
#schedule2 = ip_tick,0,1800,ip=rakshasa
#schedule2 = bind_tick,0,1800,bind=rakshasa
# Encryption options, set to none (default) or any combination of the following:
# allow_incoming, try_outgoing, require, require_RC4, enable_retry, prefer_plaintext
#
# The example value allows incoming encrypted connections, starts unencrypted
# outgoing connections but retries with encryption if they fail, preferring
# plaintext to RC4 encryption after the encrypted handshake
# plain-text to RC4 encryption after the encrypted handshake.
#
# encryption = allow_incoming,enable_retry,prefer_plaintext
# protocol.encryption.set = allow_incoming,enable_retry,prefer_plaintext
# Enable DHT support for trackerless torrents or when all trackers are down.
# May be set to "disable" (completely disable DHT), "off" (do not start DHT),
# "auto" (start and stop DHT as needed), or "on" (start DHT immediately).
# The default is "off". For DHT to work, a session directory must be defined.
#
# dht = auto
# UDP port to use for DHT.
#
# dht_port = 6881
# Enable peer exchange (for torrents not marked private)
#
# peer_exchange = yes
# dht.mode.set = auto
# UDP port to use for DHT.
#
# Do not modify the following parameters unless you know what you're doing.
#dht.port.set = 6881
# Enable peer exchange (for torrents not marked private).
#
#protocol.pex.set = yes
# Hash read-ahead controls how many MB to request the kernel to read
# ahead. If the value is too low the disk may not be fully utilized,
# while if too high the kernel might not be able to keep the read
# pages in memory thus end up trashing.
#hash_read_ahead = 10
# Set download list layout style ("full", "compact").
#
#ui.torrent_list.layout.set = "full"
# Interval between attempts to check the hash, in milliseconds.
#hash_interval = 100
# Run rTorrent as a daemon, controlled via XMLRPC.
#
#system.daemon.set = false
# 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.
#hash_max_tries = 10
# SCGI Connectivity (for alternative rtorrent interfaces, XMLRPC)
# Use a IP socket with scgi_port, or a Unix socket with scgi_local.
# schedule can be used to set permissions on the unix socket.
#
#network.scgi.open_port = "127.0.0.1:5000"
#network.scgi.open_local = (cat,(session.path),/rpc.sock)
#schedule2 = socket_chmod, 0, 0, "execute.nothrow=chmod,770,(cat,(session.path),/rpc.sock)"
+106
View File
@@ -0,0 +1,106 @@
#############################################################################
# A minimal rTorrent configuration that provides the basic features
# you want to have in addition to the built-in defaults.
#
# See https://github.com/rakshasa/rtorrent/wiki/CONFIG-Template
# for an up-to-date version.
#############################################################################
# Instance layout (base paths)
method.insert = cfg.basedir, private|const|string, (cat,"/home/USERNAME/rtorrent/")
method.insert = cfg.download, private|const|string, (cat,(cfg.basedir),"download/")
method.insert = cfg.logs, private|const|string, (cat,(cfg.basedir),"log/")
method.insert = cfg.logfile, private|const|string, (cat,(cfg.logs),"rtorrent-",(system.time),".log")
method.insert = cfg.session, private|const|string, (cat,(cfg.basedir),".session/")
method.insert = cfg.watch, private|const|string, (cat,(cfg.basedir),"watch/")
# Create instance directories
execute.throw = sh, -c, (cat,\
"mkdir -p \"",(cfg.download),"\" ",\
"\"",(cfg.logs),"\" ",\
"\"",(cfg.session),"\" ",\
"\"",(cfg.watch),"/load\" ",\
"\"",(cfg.watch),"/start\" ")
# Listening port for incoming peer traffic (fixed; you can also randomize it)
network.port_range.set = 50000-50000
network.port_random.set = no
# Tracker-less torrent and UDP tracker support
# (conservative settings for 'private' trackers, change for 'public')
dht.mode.set = disable
protocol.pex.set = no
trackers.use_udp.set = no
# Peer settings
throttle.max_uploads.set = 100
throttle.max_uploads.global.set = 250
throttle.min_peers.normal.set = 20
throttle.max_peers.normal.set = 60
throttle.min_peers.seed.set = 30
throttle.max_peers.seed.set = 80
trackers.numwant.set = 80
protocol.encryption.set = allow_incoming,try_outgoing,enable_retry
# Limits for file handle resources, this is optimized for
# an `ulimit` of 1024 (a common default). You MUST leave
# a ceiling of handles reserved for rTorrent's internal needs!
network.http.max_open.set = 50
network.max_open_files.set = 600
network.max_open_sockets.set = 300
# Memory resource usage (increase if you have a large number of items loaded,
# and/or the available resources to spend)
pieces.memory.max.set = 1800M
network.xmlrpc.size_limit.set = 4M
# Basic operational settings (no need to change these)
session.path.set = (cat, (cfg.session))
directory.default.set = (cat, (cfg.download))
log.execute = (cat, (cfg.logs), "execute.log")
##log.xmlrpc = (cat, (cfg.logs), "xmlrpc.log")
execute.nothrow = sh, -c, (cat, "echo >",\
(session.path), "rtorrent.pid", " ", (system.pid))
# Other operational settings (check & adapt)
encoding.add = utf8
system.umask.set = 0027
system.cwd.set = (directory.default)
network.http.dns_cache_timeout.set = 25
schedule2 = monitor_diskspace, 15, 60, ((close_low_diskspace, 1000M))
##pieces.hash.on_completion.set = no
##view.sort_current = seeding, greater=d.ratio=
##keys.layout.set = qwerty
##network.http.capath.set = "/etc/ssl/certs"
##network.http.ssl_verify_peer.set = 0
##network.http.ssl_verify_host.set = 0
# Some additional values and commands
method.insert = system.startup_time, value|const, (system.time)
method.insert = d.data_path, simple,\
"if=(d.is_multi_file),\
(cat, (d.directory), /),\
(cat, (d.directory), /, (d.name))"
method.insert = d.session_file, simple, "cat=(session.path), (d.hash), .torrent"
# Watch directories (add more as you like, but use unique schedule names)
schedule2 = watch_start, 10, 10, ((load.start_verbose, (cat, (cfg.watch), "start/*.torrent")))
schedule2 = watch_load, 11, 10, ((load.verbose, (cat, (cfg.watch), "load/*.torrent")))
# Run the rTorrent process as a daemon in the background
# (and control via XMLRPC sockets)
#system.daemon.set = true
#network.scgi.open_local = (cat,(session.path),rtorrent.sock)
#execute.nothrow = chmod,770,(cat,(session.path),rtorrent.sock)
# Logging:
# Levels = critical error warn notice info debug
# Groups = connection_* dht_* peer_* rpc_* storage_* thread_* tracker_* torrent_*
print = (cat, "Logging to ", (cfg.logfile))
log.open_file = "log", (cfg.logfile)
log.add_output = "info", "log"
##log.add_output = "tracker_debug", "log"
### END of rtorrent.rc ###
+131
View File
@@ -0,0 +1,131 @@
#!/usr/bin/perl
# Perl script to add rTorrent fast resume data to torrent files.
#
# Usage:
# rtorrent_fast_resume.pl [base-directory] < plain.torrent > with_fast_resume.torrent
# -OR-
# rtorrent_fast_resume.pl [base-directory] plain.torrent [with_fast_resume.torrent]
use strict;
use warnings;
use Convert::Bencode_XS qw(bencode bdecode);
use File::Spec; # core module
use POSIX; # core module
$/ = undef;
$| = 1;
# Process ARGV
my $d = $ARGV[0];
if ($d and not -d $d) {
if (-f $d and -s $d and not $ARGV[2]) { # missing directory, but has file
$ARGV[2] = $ARGV[1];
$ARGV[1] = $ARGV[0];
$d = '';
}
else { die "$d is not a directory\n"; }
}
$d ||= ".";
$d .= "/" unless $d =~ m#/$#;
my ($in, $out, $msg);
my ($in_file, $out_file) = ('', '');
if ($ARGV[1]) {
$in_file = $ARGV[1];
open($in, ($ARGV[2] ? '<' : '+<'), $in_file) || die "Cannot open $in_file for input!\n";
unless ($ARGV[2]) {
$out = $in;
$out_file = $in_file;
}
}
else { $in = *STDIN; }
if ($ARGV[2]) {
$out_file = $ARGV[2];
open($out, '>', $out_file) || die "Cannot open $out_file for output!\n";
$msg = *STDOUT;
}
elsif (!$ARGV[1]) { $out = *STDOUT; }
$msg //= *STDERR;
print {$msg} "Total input torrent size: ".sprintf('%.2f', (-s $in_file) / 1024)." KB\n" if $in_file;
print {$msg} "Decoding ".($in_file || 'torrent from standard input')."...";
my $t = bdecode(scalar <$in>);
die "No info key.\n" unless ref $t eq "HASH" and exists $t->{info};
my $psize = $t->{info}{"piece length"} or die "No piece length key.\n";
print {$msg} "done\n\n";
my @files;
my $tsize = 0;
if (exists $t->{info}{files}) {
print {$msg} "Multi file torrent: $t->{info}{name}\n";
for (@{$t->{info}{files}}) {
push @files, join "/", $t->{info}{name},@{$_->{path}};
$tsize += $_->{length};
}
}
else {
print {$msg} "Single file torrent: $t->{info}{name}\n";
@files = ($t->{info}{name});
$tsize = $t->{info}{length};
}
my $chunks = int(($tsize + $psize - 1) / $psize);
print {$msg} "Total size: ".sprintf('%.2f', $tsize / 1024**2)." MB; $chunks chunks; ", scalar @files, " files.\n\n";
die "Inconsistent piece information!\n" if $chunks*20 != length $t->{info}{pieces};
print {$msg} "Adding fast resume information...";
# flags => 1+16+
my $pmod = 0;
$t->{libtorrent_resume}{bitfield} = $chunks;
foreach my $f (0..$#files) {
die "$d$files[$f] not found.\n" unless -e "$d$files[$f]";
my $mtime = (stat "$d$files[$f]")[9];
# Compute number of chunks per file
my $fsize = (exists $t->{info}{files}) ? $t->{info}{files}[$f]{length} : 1;
my $fchunks = ($pmod ? 1 : 0);
if ($pmod >= $fsize) { ($fsize, $pmod ) = (0, $pmod-$fsize); }
else { ($pmod, $fsize) = (0, $fsize-$pmod); }
$fchunks += ceil($fsize / $psize);
$pmod ||= $psize - ($fsize % $psize);
$t->{libtorrent_resume}{files}[$f] = {
priority => 0, # Don't download; we already have the file, so don't clobber it!
mtime => $mtime,
completed => $fchunks,
};
};
$t->{libtorrent_resume}{'uncertain_pieces.timestamp'} = time;
# Some extra information to re-enforce the fact that this is a finished torrent
if (exists $t->{info}{files}) {
$d .= $t->{info}{name};
}
$t->{rtorrent} = {
state => 1, # started
state_changed => time,
state_counter => 1,
chunks_wanted => 0,
chunks_done => $chunks,
complete => 1,
hashing => 0, # Not hashing
directory => File::Spec->file_name_is_absolute($d) ? $d : File::Spec->rel2abs($d),
((tied_to_file => File::Spec->file_name_is_absolute($out_file) ? $out_file : File::Spec->rel2abs($out_file)) x!! $out_file),
'timestamp.finished' => 0,
'timestamp.started' => time,
};
print {$msg} "done\n";
print {$msg} "Encoding ".($out_file || 'torrent from standard output')."...";
seek($out, 0, 0); # just in case files are the same
print {$out} bencode($t);
close($in);
close($out);
print {$msg} "done\n";
exit;
+164
View File
@@ -0,0 +1,164 @@
#!/bin/bash
#############
###<Notes>###
#############
# This script depends on screen.
# For the stop function to work, you must set an
# explicit session directory using absolute paths (no, ~ is not absolute) in your rtorrent.rc.
# If you typically just start rtorrent with just "rtorrent" on the
# command line, all you need to change is the "user" option.
# Attach to the screen session as your user with
# "screen -dr rtorrent". Change "rtorrent" with srnname option.
# Licensed under the GPLv2 by lostnihilist: lostnihilist _at_ gmail _dot_ com
##############
###</Notes>###
##############
#######################
##Start Configuration##
#######################
# You can specify your configuration in a different file
# (so that it is saved with upgrades, saved in your home directory,
# or whatever reason you want to)
# by commenting out/deleting the configuration lines and placing them
# in a text file (say /home/user/.rtorrent.init.conf) exactly as you would
# have written them here (you can leave the comments if you desire
# and then uncommenting the following line correcting the path/filename
# for the one you used. note the space after the ".".
# . /etc/rtorrent.init.conf
#Do not put a space on either side of the equal signs e.g.
# user = user
# will not work
# system user to run as (can only use one)
user="user"
# system user to run as # not implemented, see d_start for beginning implementation
# group=$(id -ng "$user")
# the full path to the filename where you store your rtorrent configuration
# must keep parentheses around the entire statement, quotations around each config file
config=("$(su -c 'echo $HOME' $user)/.rtorrent.rc")
# Examples:
# config=("/home/user/.rtorrent.rc")
# config=("/home/user/.rtorrent.rc" "/mnt/some/drive/.rtorrent2.rc")
# config=("/home/user/.rtorrent.rc"
# "/mnt/some/drive/.rtorrent2.rc"
# "/mnt/another/drive/.rtorrent3.rc")
# set of options to run with each instance, separated by a new line
# must keep parentheses around the entire statement
#if no special options, specify with: ""
options=("")
# Examples:
# starts one instance, sourcing both .rtorrent.rc and .rtorrent2.rc
# options=("-o import=~/.rtorrent2.rc")
# starts two instances, ignoring .rtorrent.rc for both, and using
# .rtorrent2.rc for the first, and .rtorrent3.rc for the second
# we do not check for valid options
# options=("-n -o import=~/.rtorrent2.rc" "-n -o import=~/rtorrent3.rc")
# default directory for screen, needs to be an absolute path
base=$(su -c 'echo $HOME' $user)
# name of screen session
srnname="rtorrent"
# file to log to (makes for easier debugging if something goes wrong)
logfile="/var/log/rtorrentInit.log"
#######################
###END CONFIGURATION###
#######################
PATH=/usr/bin:/usr/local/bin:/usr/local/sbin:/sbin:/bin:/usr/sbin
DESC="rtorrent"
NAME=rtorrent
DAEMON=$NAME
SCRIPTNAME=/etc/init.d/$NAME
checkcnfg() {
exists=0
for i in `echo "$PATH" | tr ':' '\n'` ; do
if [ -f $i/$NAME ] ; then
exists=1
break
fi
done
if [ $exists -eq 0 ] ; then
echo "cannot find $NAME binary in PATH: $PATH" | tee -a "$logfile" >&2
exit 3
fi
for (( i=0 ; i < ${#config[@]} ; i++ )) ; do
if ! [ -r "${config[i]}" ] ; then
echo "cannot find readable config ${config[i]}. check that it is there and permissions are appropriate" | tee -a "$logfile" >&2
exit 3
fi
session=$(getsession "${config[i]}")
if ! [ -d "${session}" ] ; then
echo "cannot find readable session directory ${session} from config ${config[i]}. check permissions" | tee -a "$logfile" >&2
exit 3
fi
done
}
d_start() {
[ -d "${base}" ] && cd "${base}"
stty stop undef && stty start undef
su -c "screen -S "${srnname}" -X screen rtorrent ${options} 2>&1 1>/dev/null" ${user} | tee -a "$logfile" >&2
# this works for the screen command, but starting rtorrent below adopts screen session gid
# even if it is not the screen session we started (e.g. running under an undesirable gid
#su -c "screen -ls | grep -sq "\.${srnname}[[:space:]]" " ${user} || su -c "sg \"$group\" -c \"screen -fn -dm -S ${srnname} 2>&1 1>/dev/null\"" ${user} | tee -a "$logfile" >&2
for (( i=0 ; i < ${#options[@]} ; i++ )) ; do
sleep 3
su -c "screen -S "${srnname}" -X screen rtorrent ${options[i]} 2>&1 1>/dev/null" ${user} | tee -a "$logfile" >&2
done
}
d_stop() {
for (( i=0 ; i < ${#config[@]} ; i++ )) ; do
session=$(getsession "${config[i]}")
if ! [ -s ${session}/rtorrent.lock ] ; then
return
fi
pid=$(cat ${session}/rtorrent.lock | awk -F: '{print($2)}' | sed "s/[^0-9]//g")
# make sure the pid doesn't belong to another process
if ps -A | grep -sq ${pid}.*rtorrent ; then
kill -s INT ${pid}
fi
done
}
getsession() {
session=$(cat "$1" | grep "^[[:space:]]*session.path.set[[:space:]]*=" | sed "s/^[[:space:]]*session.path.set[[:space:]]*=[[:space:]]*//" )
#session=${session/#~/`getent passwd ${user}|cut -d: -f6`}
echo $session
}
checkcnfg
case "$1" in
start)
echo -n "Starting $DESC: $NAME"
d_start
echo "."
;;
stop)
echo -n "Stopping $DESC: $NAME"
d_stop
echo "."
;;
restart|force-reload)
echo -n "Restarting $DESC: $NAME"
d_stop
sleep 1
d_start
echo "."
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
exit 1
;;
esac
exit 0
+137
View File
@@ -0,0 +1,137 @@
#!/bin/sh
#############
###<Notes>###
#############
# This script depends on screen.
# For the stop function to work, you must set an
# explicit session directory using ABSOLUTE paths (no, ~ is not absolute) in your rtorrent.rc.
# If you typically just start rtorrent with just "rtorrent" on the
# command line, all you need to change is the "user" option.
# Attach to the screen session as your user with
# "screen -dr rtorrent". Change "rtorrent" with srnname option.
# Licensed under the GPLv2 by lostnihilist: lostnihilist _at_ gmail _dot_ com
##############
###</Notes>###
##############
#######################
##Start Configuration##
#######################
# You can specify your configuration in a different file
# (so that it is saved with upgrades, saved in your home directory,
# or whateve reason you want to)
# by commenting out/deleting the configuration lines and placing them
# in a text file (say /home/user/.rtorrent.init.conf) exactly as you would
# have written them here (you can leave the comments if you desire
# and then uncommenting the following line correcting the path/filename
# for the one you used. note the space after the ".".
# . /etc/rtorrent.init.conf
#Do not put a space on either side of the equal signs e.g.
# user = user
# will not work
# system user to run as
user="user"
# the system group to run as, not implemented, see d_start for beginning implementation
# group=`id -ng "$user"`
# the full path to the filename where you store your rtorrent configuration
config="`su -c 'echo $HOME' $user`/.rtorrent.rc"
# set of options to run with
options=""
# default directory for screen, needs to be an absolute path
base="`su -c 'echo $HOME' $user`"
# name of screen session
srnname="rtorrent"
# file to log to (makes for easier debugging if something goes wrong)
logfile="/var/log/rtorrentInit.log"
#######################
###END CONFIGURATION###
#######################
PATH=/usr/bin:/usr/local/bin:/usr/local/sbin:/sbin:/bin:/usr/sbin
DESC="rtorrent"
NAME=rtorrent
DAEMON=$NAME
SCRIPTNAME=/etc/init.d/$NAME
checkcnfg() {
exists=0
for i in `echo "$PATH" | tr ':' '\n'` ; do
if [ -f $i/$NAME ] ; then
exists=1
break
fi
done
if [ $exists -eq 0 ] ; then
echo "cannot find rtorrent binary in PATH $PATH" | tee -a "$logfile" >&2
exit 3
fi
if ! [ -r "${config}" ] ; then
echo "cannot find readable config ${config}. check that it is there and permissions are appropriate" | tee -a "$logfile" >&2
exit 3
fi
session=`getsession "$config"`
if ! [ -d "${session}" ] ; then
echo "cannot find readable session directory ${session} from config ${config}. check permissions" | tee -a "$logfile" >&2
exit 3
fi
}
d_start() {
[ -d "${base}" ] && cd "${base}"
stty stop undef && stty start undef
su -c "screen -ls | grep -sq "\.${srnname}[[:space:]]" " ${user} || su -c "screen -dm -S ${srnname} 2>&1 1>/dev/null" ${user} | tee -a "$logfile" >&2
# this works for the screen command, but starting rtorrent below adopts screen session gid
# even if it is not the screen session we started (e.g. running under an undesirable gid
#su -c "screen -ls | grep -sq "\.${srnname}[[:space:]]" " ${user} || su -c "sg \"$group\" -c \"screen -fn -dm -S ${srnname} 2>&1 1>/dev/null\"" ${user} | tee -a "$logfile" >&2
su -c "screen -S "${srnname}" -X screen rtorrent ${options} 2>&1 1>/dev/null" ${user} | tee -a "$logfile" >&2
}
d_stop() {
session=`getsession "$config"`
if ! [ -s ${session}/rtorrent.lock ] ; then
return
fi
pid=`cat ${session}/rtorrent.lock | awk -F: '{print($2)}' | sed "s/[^0-9]//g"`
if ps -A | grep -sq ${pid}.*rtorrent ; then # make sure the pid doesn't belong to another process
kill -s INT ${pid}
fi
}
getsession() {
session=`cat "$1" | grep "^[[:space:]]*session.path.set[[:space:]]*=" | sed "s/^[[:space:]]*session.path.set[[:space:]]*=[[:space:]]*//" `
echo $session
}
checkcnfg
case "$1" in
start)
echo -n "Starting $DESC: $NAME"
d_start
echo "."
;;
stop)
echo -n "Stopping $DESC: $NAME"
d_stop
echo "."
;;
restart|force-reload)
echo -n "Restarting $DESC: $NAME"
d_stop
sleep 1
d_start
echo "."
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
exit 1
;;
esac
exit 0
+166
View File
@@ -0,0 +1,166 @@
#!/bin/bash
### BEGIN INIT INFO
# Provides: rtorrent_autostart
# Required-Start: $local_fs $remote_fs $network $syslog $netdaemons
# Required-Stop: $local_fs $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: rtorrent script using tmux
# Description: rtorrent script using tmux
### END INIT INFO
#############
###<Notes>###
#############
# This script depends on tmux and is based on 'rtorrentInitScreen.sh' script
# with the following enhancements:
# - init script 'start' option can be called without breaking anything
# - init script 'status' option can be used in scripts to determine whether rtorrent is running or not
# - auto removes damaged/stuck 'rtorrent.lock' file if necessary
# - saves session (just in case) before stopping with 'rtxmlrp' if it exists
# - provides examples how to script tmux windows
#
# For the stop function to work, you must set an explicit session directory
# using ABSOLUTE paths (no, ~ is not absolute) in your rtorrent.rc and with
# "sessiondir" option.
# If you typically just start rtorrent with just "rtorrent" on the
# command line, all you need to change is the "user" and "sessiondir" option.
# Attach to the tmux session as your user with
# "tmux -2u new-session -A -s rtorrent". Change "rtorrent" with "tmuxname" option.
# Licensed under the GPLv2 by lostnihilist: lostnihilist _at_ gmail _dot_ com
##############
###</Notes>###
##############
#######################
##Start Configuration##
#######################
# You can specify your configuration in a different file.
# (so that it is saved with upgrades, saved in your home directory,
# or whatever reason you want to)
# by commenting out/deleting the configuration lines and placing them
# in a text file (say /home/user/.rtorrent.init.conf) exactly as you would
# have written them here (you can leave the comments if you desire
# and then uncommenting the following line correcting the path/filename.
# for the one you used. note the space after the ".".
# . /etc/rtorrent.init.conf
# system user to run as
user="username"
# default directory for tmux, needs to be an absolute path
base=$(su -c 'echo $HOME' $user)
# the full path to the filename where you store your rtorrent configuration
config="$base/.rtorrent.rc"
# the full path to the session directory of rtorrent
sessiondir="/mnt/Torrents/.rtorrent/.session"
# options to pass to rtorrent; e.g. don't read config from $HOME but load alternate
#options="-n -O import=$config"
options=""
# name of tmux session
tmuxname="rtorrent"
# name of window in tmux session
tmuxwindowname="rT"
#######################
###END CONFIGURATION###
#######################
PATH=/usr/bin:/usr/local/bin:/usr/local/sbin:/sbin:/bin:/usr/sbin
NAME=rtorrent
DAEMON=$NAME
SCRIPTNAME=/etc/init.d/$NAME
RTXMLRPCBIN="$base/bin/rtxmlrpc"
checkcnfg() {
if [ -z "$(which $DAEMON)" ] ; then
echo "Cannot find $DAEMON binary in PATH: $PATH"
exit 3
fi
if ! [ -r "$config" ] ; then
echo "Cannot find readable config $config. Check that it is there and permissions are appropriate"
exit 3
fi
if ! [ -d "$sessiondir" ] ; then
echo "Cannot find readable session directory $sessiondir from config $config. Check permissions"
exit 3
fi
}
status() {
if [ -e "${sessiondir}/rtorrent.lock" ] ; then
pid=`cat ${sessiondir}/rtorrent.lock | awk -F: '{print($2)}' | sed "s/[^0-9]//g"`
# make sure the pid isn't empty and doesn't belong to another process : this will match lines containing rtorrent, which grep '[r]torrent' does not!
# if there is no process as the 'pid' suggests then delete the stuck "rtorrent.lock" file (to be able to start rtorrent)
[[ -n "$pid" ]] && ps aux | grep -sq ${pid}.*[r]torrent && echo -e ${pid} || rm -f "${sessiondir}/rtorrent.lock"
fi
}
d_start() {
[ -d "$base" ] && cd "$base"
# if STDIN is a terminal (we are using interactive mode)
[ -t 0 ] && stty stop undef && stty start undef
# start the default 2 tmux window (bash and mc) if there isn't tmux session called "tmuxname" option (rtorrent)
if ! su -c "tmux ls | grep -sq ${tmuxname}: " $user ; then
# 1st window (0): split it into 3 panes, display 'date' in the last one
su -c "tmux -2u new-session -d -s ${tmuxname} -n 'shell1'" $user
su -c "tmux -2u split-window -v -t ${tmuxname}:0 'bash'" $user
su -c "tmux -2u split-window -h -t ${tmuxname}:0 'date; bash'" $user
# 2nd window (1): start 'mc' if it exists
su -c "tmux -2u new-window -t ${tmuxname}:1 -n 'mc1' 'command which mc && mc ~/; bash'" $user
fi
# start rtorrent always in the 3rd tmux window (2) if it's not running and leave shell behind to be able to see reason of a crash
if [ "$(status)" == "" ]; then
su -c "tmux -2u list-panes -t ${tmuxname}:2 &>/dev/null && tmux -2u respawn-pane -t ${tmuxname}:2 -k \"${DAEMON} ${options}; bash\" || tmux -2u new-window -t ${tmuxname}:2 -n ${tmuxwindowname} \"${DAEMON} ${options}; bash\"" $user
fi
}
d_stop() {
pid=$(status)
if [ "$pid" != "" ]; then
# save session before stopping explicitly (just in case) if rtxmlrpc util exists then wait for 5 seconds to be able to complete it
[ -L "$RTXMLRPCBIN" ] && "$RTXMLRPCBIN" session.save &>/dev/null && sleep 5
# INT (2, Interrupt from keyboard): normal shutdown
kill -s INT $pid
fi
}
checkcnfg
case "$1" in
start)
echo -n "Starting $tmuxwindowname: $NAME"
d_start
echo "."
;;
stop)
echo -n "Stopping $tmuxwindowname: $NAME"
d_stop
echo "."
;;
restart|force-reload)
echo -n "Restarting $tmuxwindowname: $NAME"
d_stop
sleep 1
d_start
echo "."
;;
status)
status
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload|status}" >&2
exit 1
;;
esac
exit 0
+23
View File
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
PORT_NUMBER=${1:-5001}
echo "Option Strings"
echo "=============="
echo
echo "Introduction"
echo "------------"
echo
echo "Client version: " `xmlrpc2scgi.py -p scgi://127.0.0.1:${PORT_NUMBER} system.client_version`
echo
echo "Generated by 'rtorrent/doc/scripts/print_option_string.sh' on `date -u`."
for i in strings.choke_heuristics strings.choke_heuristics.upload strings.choke_heuristics.download strings.connection_type strings.encryption strings.ip_filter strings.ip_tos strings.log_group strings.tracker_event strings.tracker_mode; do
echo
echo $i
echo `echo $i | tr 'a-z_.' '-'`
echo
echo '```'
xmlrpc2scgi.py -p scgi://127.0.0.1:${PORT_NUMBER} $i | tr , '\n' | tr '[' ' ' | tr ']' ' '
echo '```'
done
File diff suppressed because it is too large Load Diff
+23
View File
@@ -0,0 +1,23 @@
#!/usr/bin/perl
# Perl script to read torrent data
use strict;
use warnings;
use Convert::Bencode_XS qw(bdecode);
use Data::Dumper;
$/ = undef;
$| = 1;
my $in;
my $in_file = $ARGV[0];
if ($in_file) { open($in, '<', $in_file) || die "Cannot open $in_file for input!\n"; }
else { $in = *STDIN; }
print "Total input torrent size: ".sprintf('%.2f', (-s $in_file) / 1024)." KB\n" if $in_file;
print "Decoding ".($in_file || 'torrent from standard input')."...";
my $t = bdecode(scalar <$in>);
print "done\n\n";
print Data::Dumper->new([$t], ['*Torrent'])->Indent(1)->Useqq(1)->Quotekeys(0)->Sortkeys(1)->Dump;
+22 -5
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);
}
@@ -159,10 +159,7 @@ make_base(_InputIter __first, _InputIter __last, _Ftor __ftor) {
template<typename T>
inline int popcount_wrapper(T t) {
#if USE_BUILTIN_POPCOUNT
if (std::numeric_limits<T>::digits <= std::numeric_limits<unsigned int>::digits)
return __builtin_popcount(t);
else
return __builtin_popcountll(t);
return __builtin_popcountll(t);
#else
#error __builtin_popcount not found.
unsigned int count = 0;
@@ -176,6 +173,26 @@ inline int popcount_wrapper(T t) {
#endif
}
// Get the median of an unordered set of numbers of arbitrary
// type by modifing the underlying dataset
template <typename T = double, typename _InputIter>
T median(_InputIter __first, _InputIter __last) {
T __med;
unsigned int __size = __last - __first;
unsigned int __middle = __size / 2;
_InputIter __target1 = __first + __middle;
std::nth_element(__first, __target1, __last);
__med = *__target1;
if (__size % 2 == 0) {
_InputIter __target2 = std::max_element(__first, __target1);
__med = (__med + *__target2) / 2.0;
}
return __med;
}
}
#endif
+1
View File
@@ -51,6 +51,7 @@ public:
static const int e_deadlk = EDEADLK;
static const int e_noent = ENOENT;
static const int e_nodev = ENODEV;
static const int e_nomem = ENOMEM;
static const int e_notdir = ENOTDIR;
static const int e_isdir = EISDIR;
+1 -1
View File
@@ -38,7 +38,7 @@
#define RAK_FILE_STAT_H
#include <string>
#include <inttypes.h>
#include <cinttypes>
#include <sys/stat.h>
namespace rak {
+1 -1
View File
@@ -38,7 +38,7 @@
#define RAK_FS_STAT_H
#include <string>
#include <inttypes.h>
#include <cinttypes>
#include <rak/error_number.h>
-632
View File
@@ -1,632 +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);
}
}
#endif
-654
View File
@@ -1,654 +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>
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::auto_ptr<base_type>(base); }
base_type* release() { return m_base.release(); }
Result operator () () { return (*m_base)(); }
private:
std::auto_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::auto_ptr<base_type>(base); }
base_type* release() { return m_base.release(); }
Result operator () (Arg1 arg1) { return (*m_base)(arg1); }
private:
std::auto_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::auto_ptr<base_type>(base); }
base_type* release() { return m_base.release(); }
Result operator () (Arg1 arg1, Arg2 arg2) { return (*m_base)(arg1, arg2); }
private:
std::auto_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::auto_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::auto_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::auto_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::auto_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
+4 -3
View File
@@ -37,9 +37,10 @@
#ifndef RAK_PARTIAL_QUEUE_H
#define RAK_PARTIAL_QUEUE_H
#include <array>
#include <cstring>
#include <stdexcept>
#include <inttypes.h>
#include <cinttypes>
namespace rak {
@@ -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
+10 -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;
@@ -60,6 +24,7 @@ public:
using base_type::end;
using base_type::size;
using base_type::empty;
using base_type::clear;
priority_queue(Compare l = Compare(), Equal e = Equal())
: m_compare(l), m_equal(e) {}
@@ -73,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);
@@ -80,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>
@@ -94,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);
}
@@ -109,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
+48 -67
View File
@@ -1,80 +1,44 @@
// 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 <stdexcept>
#include <rak/allocators.h>
#include <rak/functional.h>
#include <rak/functional_fun.h>
#include <cassert>
#include <functional>
#include <rak/priority_queue.h>
#include <rak/timer.h>
#include "torrent/exceptions.h"
namespace rak {
class priority_item {
public:
typedef std::function<void (void)> slot_void;
priority_item() {}
~priority_item() {
if (is_queued())
throw std::logic_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.set(NULL);
m_slot = slot_void();
}
bool is_valid() const { return m_slot.is_valid(); }
bool is_queued() const { return m_time != timer(); }
bool is_valid() const { return (bool)m_slot; }
bool is_queued() const { return m_time != timer(); }
void call() { m_slot(); }
void set_slot(function0<void>::base_type* s) { m_slot.set(s); }
const timer& time() const { return m_time; }
void clear_time() { m_time = timer(); }
void set_time(const timer& t) { m_time = t; }
slot_void& slot() { return m_slot; }
bool compare(const timer& t) const { return m_time > t; }
const timer& time() const { return m_time; }
void clear_time() { m_time = timer(); }
void set_time(const timer& t) { m_time = t; }
bool compare(const timer& t) const { return m_time > t; }
private:
priority_item(const priority_item&);
void operator = (const priority_item&);
timer m_time;
function0<void> m_slot;
slot_void m_slot;
};
struct priority_compare {
@@ -84,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) {
@@ -94,23 +57,23 @@ priority_queue_perform(priority_queue_default* queue, timer t) {
queue->pop();
v->clear_time();
v->call();
v->slot()();
}
}
inline void
priority_queue_insert(priority_queue_default* queue, priority_item* item, timer t) {
if (t == timer())
throw std::logic_error("priority_queue_insert(...) received a bad timer.");
throw torrent::internal_error("priority_queue_insert(...) received a bad timer.");
if (!item->is_valid())
throw std::logic_error("priority_queue_insert(...) called on an invalid item.");
throw torrent::internal_error("priority_queue_insert(...) called on an invalid item.");
if (item->is_queued())
throw std::logic_error("priority_queue_insert(...) called on an already queued item.");
throw torrent::internal_error("priority_queue_insert(...) called on an already queued item.");
if (queue->find(item) != queue->end())
throw std::logic_error("priority_queue_insert(...) item found in queue.");
throw torrent::internal_error("priority_queue_insert(...) item found in queue.");
item->set_time(t);
queue->push(item);
@@ -124,16 +87,34 @@ priority_queue_erase(priority_queue_default* queue, priority_item* item) {
// Check is_valid() after is_queued() so that it is safe to call
// erase on untouched instances.
if (!item->is_valid())
throw std::logic_error("priority_queue_erase(...) called on an invalid item.");
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 std::logic_error("priority_queue_erase(...) could not find item in queue.");
if (queue->find(item) != queue->end())
throw std::logic_error("priority_queue_erase(...) item still in queue.");
if (!queue->erase(item))
throw torrent::internal_error("priority_queue_erase(...) could not find item in queue.");
}
inline void
priority_queue_update(priority_queue_default* queue, priority_item* item, timer t) {
if (t == timer())
throw torrent::internal_error("priority_queue_insert(...) received a bad timer.");
if (!item->is_valid())
throw torrent::internal_error("priority_queue_insert(...) called on an invalid item.");
if (queue->find(item) == queue->end()) {
if (item->is_queued())
throw torrent::internal_error("priority_queue_update(...) cannot insert an already queued item.");
item->set_time(t);
queue->push(item);
} else {
item->set_time(t);
queue->update();
}
}
}
+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) {}
+196 -48
View File
@@ -47,9 +47,12 @@
#ifndef RAK_SOCKET_ADDRESS_H
#define RAK_SOCKET_ADDRESS_H
#include <cinttypes>
#include <cstdint>
#include <cstring>
#include <string>
#include <stdexcept>
#include <string>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
@@ -77,11 +80,13 @@ public:
static const int pf_local = PF_UNIX;
#endif
bool is_any() const;
bool is_valid() const;
bool is_bindable() const;
bool is_address_any() const;
// Should we need to set AF_UNSPEC?
bool is_valid_inet_class() const { return family() == af_inet || family() == af_inet6; }
void clear() { std::memset(this, 0, sizeof(socket_address)); set_family(); }
sa_family_t family() const { return m_sockaddr.sa_family; }
@@ -93,6 +98,8 @@ public:
std::string address_str() const;
bool address_c_str(char* buf, socklen_t size) const;
std::string pretty_address_str() const;
// Attemts to set it as an inet, then an inet6 address. It will
// never set anything but net addresses, no local/unix.
bool set_address_str(const std::string& a) { return set_address_c_str(a.c_str()); }
@@ -109,18 +116,17 @@ public:
const sockaddr* c_sockaddr() const { return &m_sockaddr; }
const sockaddr_in* c_sockaddr_inet() const { return &m_sockaddrInet; }
#ifdef RAK_USE_INET6
socket_address_inet6* sa_inet6() { return reinterpret_cast<socket_address_inet6*>(this); }
const socket_address_inet6* sa_inet6() const { return reinterpret_cast<const socket_address_inet6*>(this); }
sockaddr_in6* c_sockaddr_inet6() { return &m_sockaddrInet6; }
const sockaddr_in6* c_sockaddr_inet6() const { return &m_sockaddrInet6; }
#endif
// Copy a socket address which has the length 'length. Zero out any
// extranous bytes and ensure it does not go beyond the size of this
// struct.
void copy(const socket_address& src, size_t length);
void copy_sockaddr(const sockaddr* src);
static socket_address* cast_from(sockaddr* sa) { return reinterpret_cast<socket_address*>(sa); }
static const socket_address* cast_from(const sockaddr* sa) { return reinterpret_cast<const socket_address*>(sa); }
@@ -139,13 +145,11 @@ private:
union {
sockaddr m_sockaddr;
sockaddr_in m_sockaddrInet;
#ifdef RAK_USE_INET6
sockaddr_in6 m_sockaddrInet6;
#endif
};
};
// Remeber to set the AF_INET.
// Remember to set the AF_INET.
class socket_address_inet {
public:
@@ -184,6 +188,8 @@ public:
const sockaddr* c_sockaddr() const { return reinterpret_cast<const sockaddr*>(&m_sockaddr); }
const sockaddr_in* c_sockaddr_inet() const { return &m_sockaddr; }
socket_address_inet6 to_mapped_address() const;
bool operator == (const socket_address_inet& rhs) const;
bool operator < (const socket_address_inet& rhs) const;
@@ -192,57 +198,70 @@ private:
struct sockaddr_in m_sockaddr;
};
// Unique key for the address, excluding port numbers etc.
class socket_address_key {
class socket_address_inet6 {
public:
// socket_address_host_key() {}
bool is_any() const { return is_port_any() && is_address_any(); }
bool is_valid() const { return !is_port_any() && !is_address_any(); }
bool is_port_any() const { return port() == 0; }
bool is_address_any() const { return std::memcmp(&m_sockaddr.sin6_addr, &in6addr_any, sizeof(in6_addr)) == 0; }
socket_address_key(const socket_address& sa) {
*this = sa;
}
void clear() { std::memset(this, 0, sizeof(socket_address_inet6)); set_family(); }
socket_address_key& operator = (const socket_address& sa) {
if (sa.family() == 0) {
std::memset(this, 0, sizeof(socket_address_key));
uint16_t port() const { return ntohs(m_sockaddr.sin6_port); }
uint16_t port_n() const { return m_sockaddr.sin6_port; }
void set_port(uint16_t p) { m_sockaddr.sin6_port = htons(p); }
void set_port_n(uint16_t p) { m_sockaddr.sin6_port = p; }
} else if (sa.family() == socket_address::af_inet) {
// Using hardware order as we use operator < to compare when
// using inet only.
m_addr.s_addr = sa.sa_inet()->address_h();
in6_addr address() const { return m_sockaddr.sin6_addr; }
const in6_addr* address_ptr() const { return &m_sockaddr.sin6_addr; }
std::string address_str() const;
bool address_c_str(char* buf, socklen_t size) const;
} else {
// When we implement INET6 handling, embed the ipv4 address in
// the ipv6 address.
throw std::logic_error("socket_address_key(...) received an unsupported protocol family.");
}
void set_address(in6_addr a) { m_sockaddr.sin6_addr = a; }
bool set_address_str(const std::string& a) { return set_address_c_str(a.c_str()); }
bool set_address_c_str(const char* a);
return *this;
}
void set_address_any() { set_port(0); set_address(in6addr_any); }
// socket_address_key& operator = (const socket_address_key& sa) {
// }
std::string pretty_address_str() const;
bool operator < (const socket_address_key& sa) const {
// Compare the memory area instead.
return m_addr.s_addr < sa.m_addr.s_addr;
}
sa_family_t family() const { return m_sockaddr.sin6_family; }
void set_family() { m_sockaddr.sin6_family = AF_INET6; }
sockaddr* c_sockaddr() { return reinterpret_cast<sockaddr*>(&m_sockaddr); }
sockaddr_in6* c_sockaddr_inet6() { return &m_sockaddr; }
const sockaddr* c_sockaddr() const { return reinterpret_cast<const sockaddr*>(&m_sockaddr); }
const sockaddr_in6* c_sockaddr_inet6() const { return &m_sockaddr; }
socket_address normalize_address() const;
bool operator == (const socket_address_inet6& rhs) const;
bool operator < (const socket_address_inet6& rhs) const;
private:
union {
in_addr m_addr;
// #ifdef RAK_USE_INET6
// in_addr6 m_addr6;
// #endif
};
struct sockaddr_in6 m_sockaddr;
};
inline bool
socket_address::is_any() const {
switch (family()) {
case af_inet:
return sa_inet()->is_any();
case af_inet6:
return sa_inet6()->is_any();
default:
return false;
}
}
inline bool
socket_address::is_valid() const {
switch (family()) {
case af_inet:
return sa_inet()->is_valid();
// case af_inet6:
// return sa_inet6().is_valid();
case af_inet6:
return sa_inet6()->is_valid();
default:
return false;
}
@@ -253,6 +272,8 @@ socket_address::is_bindable() const {
switch (family()) {
case af_inet:
return !sa_inet()->is_address_any();
case af_inet6:
return !sa_inet6()->is_address_any();
default:
return false;
}
@@ -263,6 +284,8 @@ socket_address::is_address_any() const {
switch (family()) {
case af_inet:
return sa_inet()->is_address_any();
case af_inet6:
return sa_inet6()->is_address_any();
default:
return true;
}
@@ -273,6 +296,8 @@ socket_address::port() const {
switch (family()) {
case af_inet:
return sa_inet()->port();
case af_inet6:
return sa_inet6()->port();
default:
return 0;
}
@@ -283,6 +308,8 @@ socket_address::set_port(uint16_t p) {
switch (family()) {
case af_inet:
return sa_inet()->set_port(p);
case af_inet6:
return sa_inet6()->set_port(p);
default:
break;
}
@@ -293,6 +320,8 @@ socket_address::address_str() const {
switch (family()) {
case af_inet:
return sa_inet()->address_str();
case af_inet6:
return sa_inet6()->address_str();
default:
return std::string();
}
@@ -303,17 +332,38 @@ socket_address::address_c_str(char* buf, socklen_t size) const {
switch (family()) {
case af_inet:
return sa_inet()->address_c_str(buf, size);
case af_inet6:
return sa_inet6()->address_c_str(buf, size);
default:
return false;
}
}
inline std::string
socket_address::pretty_address_str() const {
switch (family()) {
case af_inet:
return sa_inet()->address_str();
case af_inet6:
return sa_inet6()->pretty_address_str();
case af_unspec:
return std::string("unspec");
default:
return std::string("invalid");
}
}
inline bool
socket_address::set_address_c_str(const char* a) {
if (sa_inet()->set_address_c_str(a)) {
sa_inet()->set_family();
return true;
} else if (sa_inet6()->set_address_c_str(a)) {
sa_inet6()->set_family();
return true;
} else {
return false;
}
@@ -325,6 +375,8 @@ socket_address::length() const {
switch(family()) {
case af_inet:
return sizeof(sockaddr_in);
case af_inet6:
return sizeof(sockaddr_in6);
default:
return 0;
}
@@ -333,13 +385,16 @@ socket_address::length() const {
inline void
socket_address::copy(const socket_address& src, size_t length) {
length = std::min(length, sizeof(socket_address));
// Does this get properly optimized?
std::memset(this, 0, sizeof(socket_address));
std::memcpy(this, &src, length);
}
// Should we be able to compare af_unspec?
inline void
socket_address::copy_sockaddr(const sockaddr* src) {
std::memset(this, 0, sizeof(socket_address));
std::memcpy(this, src, socket_address::cast_from(src)->length());
}
inline bool
socket_address::operator == (const socket_address& rhs) const {
@@ -349,8 +404,8 @@ socket_address::operator == (const socket_address& rhs) const {
switch (family()) {
case af_inet:
return *sa_inet() == *rhs.sa_inet();
// case af_inet6:
// return *sa_inet6() == *rhs.sa_inet6();
case af_inet6:
return *sa_inet6() == *rhs.sa_inet6();
default:
throw std::logic_error("socket_address::operator == (rhs) invalid type comparison.");
}
@@ -364,8 +419,8 @@ socket_address::operator < (const socket_address& rhs) const {
switch (family()) {
case af_inet:
return *sa_inet() < *rhs.sa_inet();
// case af_inet6:
// return *sa_inet6() < *rhs.sa_inet6();
case af_inet6:
return *sa_inet6() < *rhs.sa_inet6();
default:
throw std::logic_error("socket_address::operator < (rhs) invalid type comparison.");
}
@@ -391,6 +446,21 @@ socket_address_inet::set_address_c_str(const char* a) {
return inet_pton(AF_INET, a, &m_sockaddr.sin_addr);
}
inline socket_address_inet6
socket_address_inet::to_mapped_address() const {
uint32_t addr32[4];
addr32[0] = 0;
addr32[1] = 0;
addr32[2] = htonl(0xffff);
addr32[3] = m_sockaddr.sin_addr.s_addr;
socket_address_inet6 sa;
sa.clear();
sa.set_address(*reinterpret_cast<in6_addr *>(addr32));
sa.set_port_n(m_sockaddr.sin_port);
return sa;
}
inline bool
socket_address_inet::operator == (const socket_address_inet& rhs) const {
return
@@ -406,6 +476,84 @@ socket_address_inet::operator < (const socket_address_inet& rhs) const {
m_sockaddr.sin_port < rhs.m_sockaddr.sin_port);
}
inline std::string
socket_address_inet6::address_str() const {
char buf[INET6_ADDRSTRLEN];
if (!address_c_str(buf, INET6_ADDRSTRLEN))
return std::string();
return std::string(buf);
}
inline bool
socket_address_inet6::address_c_str(char* buf, socklen_t size) const {
return inet_ntop(family(), &m_sockaddr.sin6_addr, buf, size);
}
inline bool
socket_address_inet6::set_address_c_str(const char* a) {
return inet_pton(AF_INET6, a, &m_sockaddr.sin6_addr);
}
inline std::string
socket_address_inet6::pretty_address_str() const {
char buf[INET6_ADDRSTRLEN + 2 + 6];
if (inet_ntop(family(), &m_sockaddr.sin6_addr, buf + 1, INET6_ADDRSTRLEN) == NULL)
return std::string();
buf[0] = '[';
char* last_char = (char*)std::memchr(buf + 1, 0, INET6_ADDRSTRLEN);
// TODO: Throw exception here.
if (last_char == NULL || last_char >= buf + 1 + INET6_ADDRSTRLEN)
throw std::logic_error("inet_ntop for inet6 returned bad buffer");
*(last_char++) = ']';
if (!is_port_any()) {
if (snprintf(last_char, 7, ":%" PRIu16, port()) == -1)
return std::string("error"); // TODO: Throw here.
} else {
*last_char = '\0';
}
return std::string(buf);
}
inline socket_address
socket_address_inet6::normalize_address() const {
const uint32_t *addr32 = reinterpret_cast<const uint32_t *>(m_sockaddr.sin6_addr.s6_addr);
if (addr32[0] == 0 && addr32[1] == 0 && addr32[2] == htonl(0xffff)) {
socket_address addr4;
addr4.sa_inet()->set_family();
addr4.sa_inet()->set_address_n(addr32[3]);
addr4.sa_inet()->set_port_n(m_sockaddr.sin6_port);
return addr4;
}
return *reinterpret_cast<const socket_address*>(this);
}
inline bool
socket_address_inet6::operator == (const socket_address_inet6& rhs) const {
return
memcmp(&m_sockaddr.sin6_addr, &rhs.m_sockaddr.sin6_addr, sizeof(in6_addr)) == 0 &&
m_sockaddr.sin6_port == rhs.m_sockaddr.sin6_port;
}
inline bool
socket_address_inet6::operator < (const socket_address_inet6& rhs) const {
int addr_comp = memcmp(&m_sockaddr.sin6_addr, &rhs.m_sockaddr.sin6_addr, sizeof(in6_addr));
return
addr_comp < 0 ||
(addr_comp == 0 ||
m_sockaddr.sin6_port < rhs.m_sockaddr.sin6_port);
}
}
#endif
+54 -3
View File
@@ -39,9 +39,13 @@
#include <algorithm>
#include <cctype>
#include <climits>
#include <cstdlib>
#include <functional>
#include <iterator>
#include <locale>
#include <random>
namespace rak {
@@ -312,11 +316,13 @@ transform_hex_str(const Sequence& seq) {
template <typename Sequence>
Sequence
generate_random(size_t length) {
std::random_device rd;
std::mt19937 mt(rd());
using bytes_randomizer = std::independent_bits_engine<std::mt19937, CHAR_BIT, uint8_t>;
bytes_randomizer bytes(mt);
Sequence s;
s.reserve(length);
std::generate_n(std::back_inserter(s), length, &::random);
std::generate_n(std::back_inserter(s), length, std::ref(bytes));
return s;
}
@@ -371,6 +377,51 @@ is_all_name(const Sequence& src) {
return is_all_name(src.begin(), src.end());
}
template <typename Iterator>
std::string
sanitize(Iterator first, Iterator last) {
std::string dest;
for (; first != last; ++first) {
if (std::isprint(*first) && *first != '\r' && *first != '\n' && *first != '\t')
dest += *first;
else
dest += " ";
}
return dest;
}
template <typename Sequence>
std::string
sanitize(const Sequence& src) {
return trim(sanitize(src.begin(), src.end()));
}
template <typename Iterator>
std::string striptags(Iterator first, Iterator last) {
bool copychar = true;
std::string dest;
for (; first != last; ++first) {
if (std::isprint(*first) && *first == '<') {
copychar = false;
} else if (std::isprint(*first) && *first == '>') {
copychar = true;
continue;
}
if (copychar)
dest += *first;
}
return dest;
}
template <typename Sequence>
std::string striptags(const Sequence& src) {
return striptags(src.begin(), src.end());
}
}
#endif
+4 -1
View File
@@ -38,7 +38,7 @@
#define RAK_TIMER_H
#include <limits>
#include <inttypes.h>
#include <cinttypes>
#include <sys/time.h>
namespace rak {
@@ -49,6 +49,9 @@ class timer {
timer(int64_t usec = 0) : m_time(usec) {}
timer(timeval tv) : m_time((int64_t)(uint32_t)tv.tv_sec * 1000000 + (int64_t)(uint32_t)tv.tv_usec % 1000000) {}
bool is_zero() const { return m_time == 0; }
bool is_not_zero() const { return m_time != 0; }
int32_t seconds() const { return m_time / 1000000; }
int32_t seconds_ceiling() const { return (m_time + 1000000 - 1) / 1000000; }
int64_t usec() const { return m_time; }
+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
-227
View File
@@ -1,227 +0,0 @@
dnl PGSGL: When updating, comment out port-specific part below;
dnl see the comment below with the word "PostgreSQL".
dnl
dnl Available from the GNU Autoconf Macro Archive at:
dnl http://www.gnu.org/software/ac-archive/htmldoc/acx_pthread.html
dnl
AC_DEFUN([ACX_PTHREAD], [
AC_REQUIRE([AC_CANONICAL_HOST])
AC_LANG_SAVE
AC_LANG_C
acx_pthread_ok=no
# We used to check for pthread.h first, but this fails if pthread.h
# requires special compiler flags (e.g. on True64 or Sequent).
# It gets checked for in the link test anyway.
# First of all, check if the user has set any of the PTHREAD_LIBS,
# etcetera environment variables, and if threads linking works using
# them:
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
AC_MSG_RESULT($acx_pthread_ok)
if test x"$acx_pthread_ok" = xno; then
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
fi
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
fi
# We must check for the threads library under a number of different
# names; the ordering is very important because some systems
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
# libraries is broken (non-POSIX).
# Create a list of thread flags to try. Items starting with a "-" are
# C compiler flags, and other items are library names, except for "none"
# which indicates that we try without any flags at all, and "pthread-config"
# which is a program returning the flags for the Pth emulation library.
acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config pthreadGC2"
# The ordering *is* (sometimes) important. Some notes on the
# individual items follow:
# pthreads: AIX (must check this before -lpthread)
# none: in case threads are in libc; should be tried before -Kthread and
# other compiler flags to prevent continual compiler warnings
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
# -pthreads: Solaris/gcc
# -mthreads: Mingw32/gcc, Lynx/gcc
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
# doesn't hurt to check since this sometimes defines pthreads too;
# also defines -D_REENTRANT)
# pthread: Linux, etcetera
# --thread-safe: KAI C++
# pthread-config: use pthread-config program (for GNU Pth library)
case "${host_cpu}-${host_os}" in
*solaris*)
# On Solaris (at least, for some versions), libc contains stubbed
# (non-functional) versions of the pthreads routines, so link-based
# tests will erroneously succeed. (We need to link with -pthread or
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
# a function called by this macro, so we could check for that, but
# who knows whether they'll stub that too in a future libc.) So,
# we'll just look for -pthreads and -lpthread first:
acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags"
;;
esac
if test x"$acx_pthread_ok" = xno; then
for flag in $acx_pthread_flags; do
tryPTHREAD_CFLAGS=""
tryPTHREAD_LIBS=""
case $flag in
none)
AC_MSG_CHECKING([whether pthreads work without any flags])
;;
-*)
AC_MSG_CHECKING([whether pthreads work with $flag])
tryPTHREAD_CFLAGS="$flag"
;;
pthread-config)
# skip this if we already have flags defined, for PostgreSQL
if test x"$PTHREAD_CFLAGS" != x -o x"$PTHREAD_LIBS" != x; then continue; fi
AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no)
if test x"$acx_pthread_config" = xno; then continue; fi
tryPTHREAD_CFLAGS="`pthread-config --cflags`"
tryPTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
;;
*)
AC_MSG_CHECKING([for the pthreads library -l$flag])
tryPTHREAD_LIBS="-l$flag"
;;
esac
save_LIBS="$LIBS"
save_CFLAGS="$CFLAGS"
LIBS="$tryPTHREAD_LIBS $PTHREAD_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS $tryPTHREAD_CFLAGS"
# Check for various functions. We must include pthread.h,
# since some functions may be macros. (On the Sequent, we
# need a special flag -Kthread to make this header compile.)
# We check for pthread_join because it is in -lpthread on IRIX
# while pthread_create is in libc. We check for pthread_attr_init
# due to DEC craziness with -lpthreads. We check for
# pthread_cleanup_push because it is one of the few pthread
# functions on Solaris that doesn't have a non-functional libc stub.
# We try pthread_create on general principles.
AC_TRY_LINK([#include <pthread.h>],
[pthread_t th; pthread_join(th, 0);
pthread_attr_init(0); pthread_cleanup_push(0, 0);
pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
[acx_pthread_ok=yes], [acx_pthread_ok=no])
if test "x$acx_pthread_ok" = xyes; then
# Don't use options that are ignored by the compiler.
# We find them by checking stderror.
cat >conftest.$ac_ext <<_ACEOF
int
main (int argc, char **argv)
{
(void) argc;
(void) argv;
return 0;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
if test "`(eval $ac_link 2>&1 1>&5)`" = ""; then
# we continue with more flags because Linux needs -lpthread
# for libpq builds on PostgreSQL. The test above only
# tests for building binaries, not shared libraries.
PTHREAD_LIBS=" $tryPTHREAD_LIBS $PTHREAD_LIBS"
PTHREAD_CFLAGS="$PTHREAD_CFLAGS $tryPTHREAD_CFLAGS"
else acx_pthread_ok=no
fi
fi
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
AC_MSG_RESULT($acx_pthread_ok)
done
fi
# Various other checks:
if test "x$acx_pthread_ok" = xyes; then
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# Detect AIX lossage: threads are created detached by default
# and the JOINABLE attribute has a nonstandard name (UNDETACHED).
AC_MSG_CHECKING([for joinable pthread attribute])
AC_TRY_LINK([#include <pthread.h>],
[int attr=PTHREAD_CREATE_JOINABLE;],
ok=PTHREAD_CREATE_JOINABLE, ok=unknown)
if test x"$ok" = xunknown; then
AC_TRY_LINK([#include <pthread.h>],
[int attr=PTHREAD_CREATE_UNDETACHED;],
ok=PTHREAD_CREATE_UNDETACHED, ok=unknown)
fi
if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then
AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok,
[Define to the necessary symbol if this constant
uses a non-standard name on your system.])
fi
AC_MSG_RESULT(${ok})
if test x"$ok" = xunknown; then
AC_MSG_WARN([we do not know how to create joinable pthreads])
fi
AC_MSG_CHECKING([if more special flags are required for pthreads])
flag=no
# We always add these in PostgreSQL
# case "${host_cpu}-${host_os}" in
# *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
# *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
# esac
AC_MSG_RESULT(${flag})
if test "x$flag" != xno; then
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
fi
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
# Supporting cc_r would require a special CC in all places that
# use libpq, and that is ugly, so we don't do it. Users can still
# define their compiler as cc_r to do thread builds of everything.
# More AIX lossage: must compile with cc_r
AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC})
else
PTHREAD_CC="$CC"
fi
AC_SUBST(PTHREAD_LIBS)
AC_SUBST(PTHREAD_CFLAGS)
AC_SUBST(PTHREAD_CC)
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
if test x"$acx_pthread_ok" = xyes; then
ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
:
else
acx_pthread_ok=no
$2
fi
AC_LANG_RESTORE
])dnl ACX_PTHREAD
+14 -14
View File
@@ -3,10 +3,10 @@
AC_DEFUN([CC_ATTRIBUTE_CONSTRUCTOR], [
AC_CACHE_CHECK([if compiler supports __attribute__((constructor))],
[cc_cv_attribute_constructor],
[AC_COMPILE_IFELSE([
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([
void ctor() __attribute__((constructor));
void ctor() { };
],
])],
[cc_cv_attribute_constructor=yes],
[cc_cv_attribute_constructor=no])
])
@@ -23,9 +23,9 @@ AC_DEFUN([CC_ATTRIBUTE_CONSTRUCTOR], [
AC_DEFUN([CC_ATTRIBUTE_FORMAT], [
AC_CACHE_CHECK([if compiler supports __attribute__((format(printf, n, n)))],
[cc_cv_attribute_format],
[AC_COMPILE_IFELSE([
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([
void __attribute__((format(printf, 1, 2))) printflike(const char *fmt, ...) { }
],
])],
[cc_cv_attribute_format=yes],
[cc_cv_attribute_format=no])
])
@@ -42,9 +42,9 @@ AC_DEFUN([CC_ATTRIBUTE_FORMAT], [
AC_DEFUN([CC_ATTRIBUTE_INTERNAL], [
AC_CACHE_CHECK([if compiler supports __attribute__((visibility("internal")))],
[cc_cv_attribute_internal],
[AC_COMPILE_IFELSE([
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([
void __attribute__((visibility("internal"))) internal_function() { }
],
])],
[cc_cv_attribute_internal=yes],
[cc_cv_attribute_internal=no])
])
@@ -66,9 +66,9 @@ AC_DEFUN([CC_ATTRIBUTE_VISIBILITY], [
AC_CACHE_CHECK([if compiler supports __attribute__((visibility("default")))],
[cc_cv_attribute_visibility],
[AC_COMPILE_IFELSE([
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([
void __attribute__((visibility("default"))) visibility_function() { }
],
])],
[cc_cv_attribute_visibility=yes],
[cc_cv_attribute_visibility=no])
])
@@ -90,10 +90,10 @@ AC_DEFUN([CC_ATTRIBUTE_VISIBILITY], [
AC_DEFUN([CC_ATTRIBUTE_NONNULL], [
AC_CACHE_CHECK([if compiler supports __attribute__((nonnull()))],
[cc_cv_attribute_nonnull],
[AC_COMPILE_IFELSE([
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([
void some_function(void *foo, void *bar) __attribute__((nonnull()));
void some_function(void *foo, void *bar) { }
],
])],
[cc_cv_attribute_nonnull=yes],
[cc_cv_attribute_nonnull=no])
])
@@ -110,9 +110,9 @@ AC_DEFUN([CC_ATTRIBUTE_NONNULL], [
AC_DEFUN([CC_ATTRIBUTE_UNUSED], [
AC_CACHE_CHECK([if compiler supports __attribute__((unused))],
[cc_cv_attribute_unused],
[AC_COMPILE_IFELSE([
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([
void some_function(void *foo, __attribute__((unused)) void *bar);
],
])],
[cc_cv_attribute_unused=yes],
[cc_cv_attribute_unused=no])
])
@@ -129,13 +129,13 @@ AC_DEFUN([CC_ATTRIBUTE_UNUSED], [
AC_DEFUN([CC_FUNC_EXPECT], [
AC_CACHE_CHECK([if compiler has __builtin_expect function],
[cc_cv_func_expect],
[AC_COMPILE_IFELSE([
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([
int some_function()
{
int a = 3;
return (int)__builtin_expect(a, 3);
}
],
])],
[cc_cv_func_expect=yes],
[cc_cv_func_expect=no])
])
+141
View File
@@ -0,0 +1,141 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_check_zlib.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_CHECK_ZLIB([action-if-found], [action-if-not-found])
#
# DESCRIPTION
#
# This macro searches for an installed zlib library. If nothing was
# specified when calling configure, it searches first in /usr/local and
# then in /usr, /opt/local and /sw. If the --with-zlib=DIR is specified,
# it will try to find it in DIR/include/zlib.h and DIR/lib/libz.a. If
# --without-zlib is specified, the library is not searched at all.
#
# If either the header file (zlib.h) or the library (libz) is not found,
# shell commands 'action-if-not-found' is run. If 'action-if-not-found' is
# not specified, the configuration exits on error, asking for a valid zlib
# installation directory or --without-zlib.
#
# If both header file and library are found, shell commands
# 'action-if-found' is run. If 'action-if-found' is not specified, the
# default action appends '-I${ZLIB_HOME}/include' to CPFLAGS, appends
# '-L$ZLIB_HOME}/lib' to LDFLAGS, prepends '-lz' to LIBS, and calls
# AC_DEFINE(HAVE_LIBZ). You should use autoheader to include a definition
# for this symbol in a config.h file. Sample usage in a C/C++ source is as
# follows:
#
# #ifdef HAVE_LIBZ
# #include <zlib.h>
# #endif /* HAVE_LIBZ */
#
# LICENSE
#
# Copyright (c) 2008 Loic Dachary <loic@senga.org>
# Copyright (c) 2010 Bastien Chevreux <bach@chevreux.org>
#
# 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, 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 16
AU_ALIAS([CHECK_ZLIB], [AX_CHECK_ZLIB])
AC_DEFUN([AX_CHECK_ZLIB],
#
# Handle user hints
#
[AC_MSG_CHECKING(if zlib is wanted)
zlib_places="/usr/local /usr /opt/local /sw"
AC_ARG_WITH([zlib],
[ --with-zlib=DIR root directory path of zlib installation @<:@defaults to
/usr/local or /usr if not found in /usr/local@:>@
--without-zlib to disable zlib usage completely],
[if test "$withval" != no ; then
AC_MSG_RESULT(yes)
if test -d "$withval"
then
zlib_places="$withval $zlib_places"
else
AC_MSG_WARN([Sorry, $withval does not exist, checking usual places])
fi
else
zlib_places=
AC_MSG_RESULT(no)
fi],
[AC_MSG_RESULT(yes)])
#
# Locate zlib, if wanted
#
if test -n "${zlib_places}"
then
# check the user supplied or any other more or less 'standard' place:
# Most UNIX systems : /usr/local and /usr
# MacPorts / Fink on OSX : /opt/local respectively /sw
for ZLIB_HOME in ${zlib_places} ; do
if test -f "${ZLIB_HOME}/include/zlib.h"; then break; fi
ZLIB_HOME=""
done
ZLIB_OLD_LDFLAGS=$LDFLAGS
ZLIB_OLD_CPPFLAGS=$CPPFLAGS
if test -n "${ZLIB_HOME}"; then
LDFLAGS="$LDFLAGS -L${ZLIB_HOME}/lib"
CPPFLAGS="$CPPFLAGS -I${ZLIB_HOME}/include"
fi
AC_LANG_PUSH([C])
AC_CHECK_LIB([z], [inflateEnd], [zlib_cv_libz=yes], [zlib_cv_libz=no])
AC_CHECK_HEADER([zlib.h], [zlib_cv_zlib_h=yes], [zlib_cv_zlib_h=no])
AC_LANG_POP([C])
if test "$zlib_cv_libz" = "yes" && test "$zlib_cv_zlib_h" = "yes"
then
#
# If both library and header were found, action-if-found
#
m4_ifblank([$1],[
CPPFLAGS="$CPPFLAGS -I${ZLIB_HOME}/include"
LDFLAGS="$LDFLAGS -L${ZLIB_HOME}/lib"
LIBS="-lz $LIBS"
AC_DEFINE([HAVE_LIBZ], [1],
[Define to 1 if you have `z' library (-lz)])
],[
# Restore variables
LDFLAGS="$ZLIB_OLD_LDFLAGS"
CPPFLAGS="$ZLIB_OLD_CPPFLAGS"
$1
])
else
#
# If either header or library was not found, action-if-not-found
#
m4_default([$2],[
AC_MSG_ERROR([either specify a valid zlib installation with --with-zlib=DIR or disable zlib usage with --without-zlib])
])
fi
fi
])
+962
View File
@@ -0,0 +1,962 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
#
# DESCRIPTION
#
# Check for baseline language coverage in the compiler for the specified
# version of the C++ standard. If necessary, add switches to CXX and
# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard)
# or '14' (for the C++14 standard).
#
# The second argument, if specified, indicates whether you insist on an
# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
# -std=c++11). If neither is specified, you get whatever works, with
# preference for no added switch, and then for an extended mode.
#
# The third argument, if specified 'mandatory' or if left unspecified,
# indicates that baseline support for the specified C++ standard is
# required and that the macro should error out if no mode with that
# support is found. If specified 'optional', then configuration proceeds
# regardless, after defining HAVE_CXX${VERSION} if and only if a
# supporting mode is found.
#
# LICENSE
#
# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
# Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
# Copyright (c) 2015 Paul Norman <penorman@mac.com>
# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
# Copyright (c) 2016, 2018 Krzesimir Nowak <qdlacz@gmail.com>
# Copyright (c) 2019 Enji Cooper <yaneurabeya@gmail.com>
# Copyright (c) 2020 Jason Merrill <jason@redhat.com>
#
# 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 12
dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
dnl (serial version number 13).
AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
[$1], [14], [ax_cxx_compile_alternatives="14 1y"],
[$1], [17], [ax_cxx_compile_alternatives="17 1z"],
[m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
m4_if([$2], [], [],
[$2], [ext], [],
[$2], [noext], [],
[m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
[$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
[$3], [optional], [ax_cxx_compile_cxx$1_required=false],
[m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
AC_LANG_PUSH([C++])dnl
ac_success=no
m4_if([$2], [], [dnl
AC_CACHE_CHECK(whether $CXX supports C++$1 features by default,
ax_cv_cxx_compile_cxx$1,
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
[ax_cv_cxx_compile_cxx$1=yes],
[ax_cv_cxx_compile_cxx$1=no])])
if test x$ax_cv_cxx_compile_cxx$1 = xyes; then
ac_success=yes
fi])
m4_if([$2], [noext], [], [dnl
if test x$ac_success = xno; then
for alternative in ${ax_cxx_compile_alternatives}; do
switch="-std=gnu++${alternative}"
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
$cachevar,
[ac_save_CXX="$CXX"
CXX="$CXX $switch"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
[eval $cachevar=yes],
[eval $cachevar=no])
CXX="$ac_save_CXX"])
if eval test x\$$cachevar = xyes; then
CXX="$CXX $switch"
if test -n "$CXXCPP" ; then
CXXCPP="$CXXCPP $switch"
fi
ac_success=yes
break
fi
done
fi])
m4_if([$2], [ext], [], [dnl
if test x$ac_success = xno; then
dnl HP's aCC needs +std=c++11 according to:
dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
dnl Cray's crayCC needs "-h std=c++11"
for alternative in ${ax_cxx_compile_alternatives}; do
for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
$cachevar,
[ac_save_CXX="$CXX"
CXX="$CXX $switch"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
[eval $cachevar=yes],
[eval $cachevar=no])
CXX="$ac_save_CXX"])
if eval test x\$$cachevar = xyes; then
CXX="$CXX $switch"
if test -n "$CXXCPP" ; then
CXXCPP="$CXXCPP $switch"
fi
ac_success=yes
break
fi
done
if test x$ac_success = xyes; then
break
fi
done
fi])
AC_LANG_POP([C++])
if test x$ax_cxx_compile_cxx$1_required = xtrue; then
if test x$ac_success = xno; then
AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
fi
fi
if test x$ac_success = xno; then
HAVE_CXX$1=0
AC_MSG_NOTICE([No compiler with C++$1 support was found])
else
HAVE_CXX$1=1
AC_DEFINE(HAVE_CXX$1,1,
[define if the compiler supports basic C++$1 syntax])
fi
AC_SUBST(HAVE_CXX$1)
])
dnl Test body for checking C++11 support
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
)
dnl Test body for checking C++14 support
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
)
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
_AX_CXX_COMPILE_STDCXX_testbody_new_in_17
)
dnl Tests for new features in C++11
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
// If the compiler admits that it is not ready for C++11, why torture it?
// Hopefully, this will speed up the test.
#ifndef __cplusplus
#error "This is not a C++ compiler"
#elif __cplusplus < 201103L
#error "This is not a C++11 compiler"
#else
namespace cxx11
{
namespace test_static_assert
{
template <typename T>
struct check
{
static_assert(sizeof(int) <= sizeof(T), "not big enough");
};
}
namespace test_final_override
{
struct Base
{
virtual ~Base() {}
virtual void f() {}
};
struct Derived : public Base
{
virtual ~Derived() override {}
virtual void f() override {}
};
}
namespace test_double_right_angle_brackets
{
template < typename T >
struct check {};
typedef check<void> single_type;
typedef check<check<void>> double_type;
typedef check<check<check<void>>> triple_type;
typedef check<check<check<check<void>>>> quadruple_type;
}
namespace test_decltype
{
int
f()
{
int a = 1;
decltype(a) b = 2;
return a + b;
}
}
namespace test_type_deduction
{
template < typename T1, typename T2 >
struct is_same
{
static const bool value = false;
};
template < typename T >
struct is_same<T, T>
{
static const bool value = true;
};
template < typename T1, typename T2 >
auto
add(T1 a1, T2 a2) -> decltype(a1 + a2)
{
return a1 + a2;
}
int
test(const int c, volatile int v)
{
static_assert(is_same<int, decltype(0)>::value == true, "");
static_assert(is_same<int, decltype(c)>::value == false, "");
static_assert(is_same<int, decltype(v)>::value == false, "");
auto ac = c;
auto av = v;
auto sumi = ac + av + 'x';
auto sumf = ac + av + 1.0;
static_assert(is_same<int, decltype(ac)>::value == true, "");
static_assert(is_same<int, decltype(av)>::value == true, "");
static_assert(is_same<int, decltype(sumi)>::value == true, "");
static_assert(is_same<int, decltype(sumf)>::value == false, "");
static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
return (sumf > 0.0) ? sumi : add(c, v);
}
}
namespace test_noexcept
{
int f() { return 0; }
int g() noexcept { return 0; }
static_assert(noexcept(f()) == false, "");
static_assert(noexcept(g()) == true, "");
}
namespace test_constexpr
{
template < typename CharT >
unsigned long constexpr
strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
{
return *s ? strlen_c_r(s + 1, acc + 1) : acc;
}
template < typename CharT >
unsigned long constexpr
strlen_c(const CharT *const s) noexcept
{
return strlen_c_r(s, 0UL);
}
static_assert(strlen_c("") == 0UL, "");
static_assert(strlen_c("1") == 1UL, "");
static_assert(strlen_c("example") == 7UL, "");
static_assert(strlen_c("another\0example") == 7UL, "");
}
namespace test_rvalue_references
{
template < int N >
struct answer
{
static constexpr int value = N;
};
answer<1> f(int&) { return answer<1>(); }
answer<2> f(const int&) { return answer<2>(); }
answer<3> f(int&&) { return answer<3>(); }
void
test()
{
int i = 0;
const int c = 0;
static_assert(decltype(f(i))::value == 1, "");
static_assert(decltype(f(c))::value == 2, "");
static_assert(decltype(f(0))::value == 3, "");
}
}
namespace test_uniform_initialization
{
struct test
{
static const int zero {};
static const int one {1};
};
static_assert(test::zero == 0, "");
static_assert(test::one == 1, "");
}
namespace test_lambdas
{
void
test1()
{
auto lambda1 = [](){};
auto lambda2 = lambda1;
lambda1();
lambda2();
}
int
test2()
{
auto a = [](int i, int j){ return i + j; }(1, 2);
auto b = []() -> int { return '0'; }();
auto c = [=](){ return a + b; }();
auto d = [&](){ return c; }();
auto e = [a, &b](int x) mutable {
const auto identity = [](int y){ return y; };
for (auto i = 0; i < a; ++i)
a += b--;
return x + identity(a + b);
}(0);
return a + b + c + d + e;
}
int
test3()
{
const auto nullary = [](){ return 0; };
const auto unary = [](int x){ return x; };
using nullary_t = decltype(nullary);
using unary_t = decltype(unary);
const auto higher1st = [](nullary_t f){ return f(); };
const auto higher2nd = [unary](nullary_t f1){
return [unary, f1](unary_t f2){ return f2(unary(f1())); };
};
return higher1st(nullary) + higher2nd(nullary)(unary);
}
}
namespace test_variadic_templates
{
template <int...>
struct sum;
template <int N0, int... N1toN>
struct sum<N0, N1toN...>
{
static constexpr auto value = N0 + sum<N1toN...>::value;
};
template <>
struct sum<>
{
static constexpr auto value = 0;
};
static_assert(sum<>::value == 0, "");
static_assert(sum<1>::value == 1, "");
static_assert(sum<23>::value == 23, "");
static_assert(sum<1, 2>::value == 3, "");
static_assert(sum<5, 5, 11>::value == 21, "");
static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
}
// http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
// Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
// because of this.
namespace test_template_alias_sfinae
{
struct foo {};
template<typename T>
using member = typename T::member_type;
template<typename T>
void func(...) {}
template<typename T>
void func(member<T>*) {}
void test();
void test() { func<foo>(0); }
}
} // namespace cxx11
#endif // __cplusplus >= 201103L
]])
dnl Tests for new features in C++14
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
// If the compiler admits that it is not ready for C++14, why torture it?
// Hopefully, this will speed up the test.
#ifndef __cplusplus
#error "This is not a C++ compiler"
#elif __cplusplus < 201402L
#error "This is not a C++14 compiler"
#else
namespace cxx14
{
namespace test_polymorphic_lambdas
{
int
test()
{
const auto lambda = [](auto&&... args){
const auto istiny = [](auto x){
return (sizeof(x) == 1UL) ? 1 : 0;
};
const int aretiny[] = { istiny(args)... };
return aretiny[0];
};
return lambda(1, 1L, 1.0f, '1');
}
}
namespace test_binary_literals
{
constexpr auto ivii = 0b0000000000101010;
static_assert(ivii == 42, "wrong value");
}
namespace test_generalized_constexpr
{
template < typename CharT >
constexpr unsigned long
strlen_c(const CharT *const s) noexcept
{
auto length = 0UL;
for (auto p = s; *p; ++p)
++length;
return length;
}
static_assert(strlen_c("") == 0UL, "");
static_assert(strlen_c("x") == 1UL, "");
static_assert(strlen_c("test") == 4UL, "");
static_assert(strlen_c("another\0test") == 7UL, "");
}
namespace test_lambda_init_capture
{
int
test()
{
auto x = 0;
const auto lambda1 = [a = x](int b){ return a + b; };
const auto lambda2 = [a = lambda1(x)](){ return a; };
return lambda2();
}
}
namespace test_digit_separators
{
constexpr auto ten_million = 100'000'000;
static_assert(ten_million == 100000000, "");
}
namespace test_return_type_deduction
{
auto f(int& x) { return x; }
decltype(auto) g(int& x) { return x; }
template < typename T1, typename T2 >
struct is_same
{
static constexpr auto value = false;
};
template < typename T >
struct is_same<T, T>
{
static constexpr auto value = true;
};
int
test()
{
auto x = 0;
static_assert(is_same<int, decltype(f(x))>::value, "");
static_assert(is_same<int&, decltype(g(x))>::value, "");
return x;
}
}
} // namespace cxx14
#endif // __cplusplus >= 201402L
]])
dnl Tests for new features in C++17
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[
// If the compiler admits that it is not ready for C++17, why torture it?
// Hopefully, this will speed up the test.
#ifndef __cplusplus
#error "This is not a C++ compiler"
#elif __cplusplus < 201703L
#error "This is not a C++17 compiler"
#else
#include <initializer_list>
#include <utility>
#include <type_traits>
namespace cxx17
{
namespace test_constexpr_lambdas
{
constexpr int foo = [](){return 42;}();
}
namespace test::nested_namespace::definitions
{
}
namespace test_fold_expression
{
template<typename... Args>
int multiply(Args... args)
{
return (args * ... * 1);
}
template<typename... Args>
bool all(Args... args)
{
return (args && ...);
}
}
namespace test_extended_static_assert
{
static_assert (true);
}
namespace test_auto_brace_init_list
{
auto foo = {5};
auto bar {5};
static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);
static_assert(std::is_same<int, decltype(bar)>::value);
}
namespace test_typename_in_template_template_parameter
{
template<template<typename> typename X> struct D;
}
namespace test_fallthrough_nodiscard_maybe_unused_attributes
{
int f1()
{
return 42;
}
[[nodiscard]] int f2()
{
[[maybe_unused]] auto unused = f1();
switch (f1())
{
case 17:
f1();
[[fallthrough]];
case 42:
f1();
}
return f1();
}
}
namespace test_extended_aggregate_initialization
{
struct base1
{
int b1, b2 = 42;
};
struct base2
{
base2() {
b3 = 42;
}
int b3;
};
struct derived : base1, base2
{
int d;
};
derived d1 {{1, 2}, {}, 4}; // full initialization
derived d2 {{}, {}, 4}; // value-initialized bases
}
namespace test_general_range_based_for_loop
{
struct iter
{
int i;
int& operator* ()
{
return i;
}
const int& operator* () const
{
return i;
}
iter& operator++()
{
++i;
return *this;
}
};
struct sentinel
{
int i;
};
bool operator== (const iter& i, const sentinel& s)
{
return i.i == s.i;
}
bool operator!= (const iter& i, const sentinel& s)
{
return !(i == s);
}
struct range
{
iter begin() const
{
return {0};
}
sentinel end() const
{
return {5};
}
};
void f()
{
range r {};
for (auto i : r)
{
[[maybe_unused]] auto v = i;
}
}
}
namespace test_lambda_capture_asterisk_this_by_value
{
struct t
{
int i;
int foo()
{
return [*this]()
{
return i;
}();
}
};
}
namespace test_enum_class_construction
{
enum class byte : unsigned char
{};
byte foo {42};
}
namespace test_constexpr_if
{
template <bool cond>
int f ()
{
if constexpr(cond)
{
return 13;
}
else
{
return 42;
}
}
}
namespace test_selection_statement_with_initializer
{
int f()
{
return 13;
}
int f2()
{
if (auto i = f(); i > 0)
{
return 3;
}
switch (auto i = f(); i + 4)
{
case 17:
return 2;
default:
return 1;
}
}
}
namespace test_template_argument_deduction_for_class_templates
{
template <typename T1, typename T2>
struct pair
{
pair (T1 p1, T2 p2)
: m1 {p1},
m2 {p2}
{}
T1 m1;
T2 m2;
};
void f()
{
[[maybe_unused]] auto p = pair{13, 42u};
}
}
namespace test_non_type_auto_template_parameters
{
template <auto n>
struct B
{};
B<5> b1;
B<'a'> b2;
}
namespace test_structured_bindings
{
int arr[2] = { 1, 2 };
std::pair<int, int> pr = { 1, 2 };
auto f1() -> int(&)[2]
{
return arr;
}
auto f2() -> std::pair<int, int>&
{
return pr;
}
struct S
{
int x1 : 2;
volatile double y1;
};
S f3()
{
return {};
}
auto [ x1, y1 ] = f1();
auto& [ xr1, yr1 ] = f1();
auto [ x2, y2 ] = f2();
auto& [ xr2, yr2 ] = f2();
const auto [ x3, y3 ] = f3();
}
namespace test_exception_spec_type_system
{
struct Good {};
struct Bad {};
void g1() noexcept;
void g2();
template<typename T>
Bad
f(T*, T*);
template<typename T1, typename T2>
Good
f(T1*, T2*);
static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);
}
namespace test_inline_variables
{
template<class T> void f(T)
{}
template<class T> inline T g(T)
{
return T{};
}
template<> inline void f<>(int)
{}
template<> int g<>(int)
{
return 5;
}
}
} // namespace cxx17
#endif // __cplusplus < 201703L
]])
+67
View File
@@ -0,0 +1,67 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_execinfo.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_EXECINFO([ACTION-IF-EXECINFO-H-IS-FOUND], [ACTION-IF-EXECINFO-H-IS-NOT-FOUND], [ADDITIONAL-TYPES-LIST])
#
# DESCRIPTION
#
# Checks for execinfo.h header and if the len parameter/return type can be
# found from a list, also define backtrace_size_t to that type.
#
# By default the list of types to try contains int and size_t, but should
# some yet undiscovered system use e.g. unsigned, the 3rd argument can be
# used for extensions. I'd like to hear of further suggestions.
#
# Executes ACTION-IF-EXECINFO-H-IS-FOUND when present and the execinfo.h
# header is found or ACTION-IF-EXECINFO-H-IS-NOT-FOUND in case the header
# seems unavailable.
#
# Also adds -lexecinfo to LIBS on BSD if needed.
#
# LICENSE
#
# Copyright (c) 2014 Thomas Jahns <jahns@dkrz.de>
#
# 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_EXECINFO],
[AC_CHECK_HEADERS([execinfo.h])
AS_IF([test x"$ac_cv_header_execinfo_h" = xyes],
[AC_CACHE_CHECK([size parameter type for backtrace()],
[ax_cv_proto_backtrace_type],
[AC_LANG_PUSH([C])
for ax_cv_proto_backtrace_type in size_t int m4_ifnblank([$3],[$3 ])none; do
AS_IF([test "${ax_cv_proto_backtrace_type}" = none],
[ax_cv_proto_backtrace_type= ; break])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
#include <execinfo.h>
extern
${ax_cv_proto_backtrace_type} backtrace(void **addrlist, ${ax_cv_proto_backtrace_type} len);
char **backtrace_symbols(void *const *buffer, ${ax_cv_proto_backtrace_type} size);
])],
[break])
done
AC_LANG_POP([C])])])
AS_IF([test x${ax_cv_proto_backtrace_type} != x],
[AC_DEFINE_UNQUOTED([backtrace_size_t], [$ax_cv_proto_backtrace_type],
[Defined to return type of backtrace().])])
AC_SEARCH_LIBS([backtrace],[execinfo])
AS_IF([test x"${ax_cv_proto_backtrace_type}" != x -a x"$ac_cv_header_execinfo_h" = xyes -a x"$ac_cv_search_backtrace" != xno],
[AC_DEFINE([HAVE_BACKTRACE],[1],
[Defined if backtrace() could be fully identified.])
]m4_ifnblank([$1],[$1
]),m4_ifnblank([$2],[$2
]))])
dnl
dnl Local Variables:
dnl mode: autoconf
dnl End:
dnl
+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])
])
+522
View File
@@ -0,0 +1,522 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_pthread.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
#
# DESCRIPTION
#
# This macro figures out how to build C programs using POSIX threads. It
# sets the PTHREAD_LIBS output variable to the threads library and linker
# flags, and the PTHREAD_CFLAGS output variable to any special C compiler
# flags that are needed. (The user can also force certain compiler
# flags/libs to be tested by setting these environment variables.)
#
# Also sets PTHREAD_CC and PTHREAD_CXX to any special C compiler that is
# needed for multi-threaded programs (defaults to the value of CC
# respectively CXX otherwise). (This is necessary on e.g. AIX to use the
# special cc_r/CC_r compiler alias.)
#
# NOTE: You are assumed to not only compile your program with these flags,
# but also to link with them as well. For example, you might link with
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
# $PTHREAD_CXX $CXXFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
#
# If you are only building threaded programs, you may wish to use these
# variables in your default LIBS, CFLAGS, and CC:
#
# LIBS="$PTHREAD_LIBS $LIBS"
# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS"
# CC="$PTHREAD_CC"
# CXX="$PTHREAD_CXX"
#
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
#
# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
# PTHREAD_CFLAGS.
#
# ACTION-IF-FOUND is a list of shell commands to run if a threads library
# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
# is not found. If ACTION-IF-FOUND is not specified, the default action
# will define HAVE_PTHREAD.
#
# Please let the authors know if this macro fails on any platform, or if
# you have any other suggestions or comments. This macro was based on work
# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
# Alejandro Forero Cuervo to the autoconf macro repository. We are also
# grateful for the helpful feedback of numerous users.
#
# Updated for Autoconf 2.68 by Daniel Richard G.
#
# LICENSE
#
# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
# Copyright (c) 2019 Marc Stevens <marc.stevens@cwi.nl>
#
# 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 31
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
AC_DEFUN([AX_PTHREAD], [
AC_REQUIRE([AC_CANONICAL_HOST])
AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([AC_PROG_SED])
AC_LANG_PUSH([C])
ax_pthread_ok=no
# We used to check for pthread.h first, but this fails if pthread.h
# requires special compiler flags (e.g. on Tru64 or Sequent).
# It gets checked for in the link test anyway.
# First of all, check if the user has set any of the PTHREAD_LIBS,
# etcetera environment variables, and if threads linking works using
# them:
if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
ax_pthread_save_CC="$CC"
ax_pthread_save_CFLAGS="$CFLAGS"
ax_pthread_save_LIBS="$LIBS"
AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
AS_IF([test "x$PTHREAD_CXX" != "x"], [CXX="$PTHREAD_CXX"])
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])
AC_MSG_RESULT([$ax_pthread_ok])
if test "x$ax_pthread_ok" = "xno"; then
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
fi
CC="$ax_pthread_save_CC"
CFLAGS="$ax_pthread_save_CFLAGS"
LIBS="$ax_pthread_save_LIBS"
fi
# We must check for the threads library under a number of different
# names; the ordering is very important because some systems
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
# libraries is broken (non-POSIX).
# Create a list of thread flags to try. Items with a "," contain both
# C compiler flags (before ",") and linker flags (after ","). Other items
# starting with a "-" are C compiler flags, and remaining items are
# library names, except for "none" which indicates that we try without
# any flags at all, and "pthread-config" which is a program returning
# the flags for the Pth emulation library.
ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
# The ordering *is* (sometimes) important. Some notes on the
# individual items follow:
# pthreads: AIX (must check this before -lpthread)
# none: in case threads are in libc; should be tried before -Kthread and
# other compiler flags to prevent continual compiler warnings
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
# (Note: HP C rejects this with "bad form for `-t' option")
# -pthreads: Solaris/gcc (Note: HP C also rejects)
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
# doesn't hurt to check since this sometimes defines pthreads and
# -D_REENTRANT too), HP C (must be checked before -lpthread, which
# is present but should not be used directly; and before -mthreads,
# because the compiler interprets this as "-mt" + "-hreads")
# -mthreads: Mingw32/gcc, Lynx/gcc
# pthread: Linux, etcetera
# --thread-safe: KAI C++
# pthread-config: use pthread-config program (for GNU Pth library)
case $host_os in
freebsd*)
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
ax_pthread_flags="-kthread lthread $ax_pthread_flags"
;;
hpux*)
# From the cc(1) man page: "[-mt] Sets various -D flags to enable
# multi-threading and also sets -lpthread."
ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
;;
openedition*)
# IBM z/OS requires a feature-test macro to be defined in order to
# enable POSIX threads at all, so give the user a hint if this is
# not set. (We don't define these ourselves, as they can affect
# other portions of the system API in unpredictable ways.)
AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING],
[
# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
AX_PTHREAD_ZOS_MISSING
# endif
],
[AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])])
;;
solaris*)
# On Solaris (at least, for some versions), libc contains stubbed
# (non-functional) versions of the pthreads routines, so link-based
# tests will erroneously succeed. (N.B.: The stubs are missing
# pthread_cleanup_push, or rather a function called by this macro,
# so we could check for that, but who knows whether they'll stub
# that too in a future libc.) So we'll check first for the
# standard Solaris way of linking pthreads (-mt -lpthread).
ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags"
;;
esac
# Are we compiling with Clang?
AC_CACHE_CHECK([whether $CC is Clang],
[ax_cv_PTHREAD_CLANG],
[ax_cv_PTHREAD_CLANG=no
# Note that Autoconf sets GCC=yes for Clang as well as GCC
if test "x$GCC" = "xyes"; then
AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
[/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
# if defined(__clang__) && defined(__llvm__)
AX_PTHREAD_CC_IS_CLANG
# endif
],
[ax_cv_PTHREAD_CLANG=yes])
fi
])
ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
# Note that for GCC and Clang -pthread generally implies -lpthread,
# except when -nostdlib is passed.
# This is problematic using libtool to build C++ shared libraries with pthread:
# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460
# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333
# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555
# To solve this, first try -pthread together with -lpthread for GCC
AS_IF([test "x$GCC" = "xyes"],
[ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags"])
# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first
AS_IF([test "x$ax_pthread_clang" = "xyes"],
[ax_pthread_flags="-pthread,-lpthread -pthread"])
# The presence of a feature test macro requesting re-entrant function
# definitions is, on some systems, a strong hint that pthreads support is
# correctly enabled
case $host_os in
darwin* | hpux* | linux* | osf* | solaris*)
ax_pthread_check_macro="_REENTRANT"
;;
aix*)
ax_pthread_check_macro="_THREAD_SAFE"
;;
*)
ax_pthread_check_macro="--"
;;
esac
AS_IF([test "x$ax_pthread_check_macro" = "x--"],
[ax_pthread_check_cond=0],
[ax_pthread_check_cond="!defined($ax_pthread_check_macro)"])
if test "x$ax_pthread_ok" = "xno"; then
for ax_pthread_try_flag in $ax_pthread_flags; do
case $ax_pthread_try_flag in
none)
AC_MSG_CHECKING([whether pthreads work without any flags])
;;
*,*)
PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"`
PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"`
AC_MSG_CHECKING([whether pthreads work with "$PTHREAD_CFLAGS" and "$PTHREAD_LIBS"])
;;
-*)
AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
PTHREAD_CFLAGS="$ax_pthread_try_flag"
;;
pthread-config)
AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
PTHREAD_CFLAGS="`pthread-config --cflags`"
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
;;
*)
AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
PTHREAD_LIBS="-l$ax_pthread_try_flag"
;;
esac
ax_pthread_save_CFLAGS="$CFLAGS"
ax_pthread_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
# Check for various functions. We must include pthread.h,
# since some functions may be macros. (On the Sequent, we
# need a special flag -Kthread to make this header compile.)
# We check for pthread_join because it is in -lpthread on IRIX
# while pthread_create is in libc. We check for pthread_attr_init
# due to DEC craziness with -lpthreads. We check for
# pthread_cleanup_push because it is one of the few pthread
# functions on Solaris that doesn't have a non-functional libc stub.
# We try pthread_create on general principles.
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
# if $ax_pthread_check_cond
# error "$ax_pthread_check_macro must be defined"
# endif
static void *some_global = NULL;
static void routine(void *a)
{
/* To avoid any unused-parameter or
unused-but-set-parameter warning. */
some_global = a;
}
static void *start_routine(void *a) { return a; }],
[pthread_t th; pthread_attr_t attr;
pthread_create(&th, 0, start_routine, 0);
pthread_join(th, 0);
pthread_attr_init(&attr);
pthread_cleanup_push(routine, 0);
pthread_cleanup_pop(0) /* ; */])],
[ax_pthread_ok=yes],
[])
CFLAGS="$ax_pthread_save_CFLAGS"
LIBS="$ax_pthread_save_LIBS"
AC_MSG_RESULT([$ax_pthread_ok])
AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
done
fi
# Clang needs special handling, because older versions handle the -pthread
# option in a rather... idiosyncratic way
if test "x$ax_pthread_clang" = "xyes"; then
# Clang takes -pthread; it has never supported any other flag
# (Note 1: This will need to be revisited if a system that Clang
# supports has POSIX threads in a separate library. This tends not
# to be the way of modern systems, but it's conceivable.)
# (Note 2: On some systems, notably Darwin, -pthread is not needed
# to get POSIX threads support; the API is always present and
# active. We could reasonably leave PTHREAD_CFLAGS empty. But
# -pthread does define _REENTRANT, and while the Darwin headers
# ignore this macro, third-party headers might not.)
# However, older versions of Clang make a point of warning the user
# that, in an invocation where only linking and no compilation is
# taking place, the -pthread option has no effect ("argument unused
# during compilation"). They expect -pthread to be passed in only
# when source code is being compiled.
#
# Problem is, this is at odds with the way Automake and most other
# C build frameworks function, which is that the same flags used in
# compilation (CFLAGS) are also used in linking. Many systems
# supported by AX_PTHREAD require exactly this for POSIX threads
# support, and in fact it is often not straightforward to specify a
# flag that is used only in the compilation phase and not in
# linking. Such a scenario is extremely rare in practice.
#
# Even though use of the -pthread flag in linking would only print
# a warning, this can be a nuisance for well-run software projects
# that build with -Werror. So if the active version of Clang has
# this misfeature, we search for an option to squash it.
AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread],
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
# Create an alternate version of $ac_link that compiles and
# links in two steps (.c -> .o, .o -> exe) instead of one
# (.c -> exe), because the warning occurs only in the second
# step
ax_pthread_save_ac_link="$ac_link"
ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
ax_pthread_link_step=`AS_ECHO(["$ac_link"]) | sed "$ax_pthread_sed"`
ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
ax_pthread_save_CFLAGS="$CFLAGS"
for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
AS_IF([test "x$ax_pthread_try" = "xunknown"], [break])
CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
ac_link="$ax_pthread_save_ac_link"
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
[ac_link="$ax_pthread_2step_ac_link"
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
[break])
])
done
ac_link="$ax_pthread_save_ac_link"
CFLAGS="$ax_pthread_save_CFLAGS"
AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no])
ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
])
case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
no | unknown) ;;
*) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
esac
fi # $ax_pthread_clang = yes
# Various other checks:
if test "x$ax_pthread_ok" = "xyes"; then
ax_pthread_save_CFLAGS="$CFLAGS"
ax_pthread_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
AC_CACHE_CHECK([for joinable pthread attribute],
[ax_cv_PTHREAD_JOINABLE_ATTR],
[ax_cv_PTHREAD_JOINABLE_ATTR=unknown
for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
[int attr = $ax_pthread_attr; return attr /* ; */])],
[ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],
[])
done
])
AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
test "x$ax_pthread_joinable_attr_defined" != "xyes"],
[AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE],
[$ax_cv_PTHREAD_JOINABLE_ATTR],
[Define to necessary symbol if this constant
uses a non-standard name on your system.])
ax_pthread_joinable_attr_defined=yes
])
AC_CACHE_CHECK([whether more special flags are required for pthreads],
[ax_cv_PTHREAD_SPECIAL_FLAGS],
[ax_cv_PTHREAD_SPECIAL_FLAGS=no
case $host_os in
solaris*)
ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
;;
esac
])
AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
test "x$ax_pthread_special_flags_added" != "xyes"],
[PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
ax_pthread_special_flags_added=yes])
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
[ax_cv_PTHREAD_PRIO_INHERIT],
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
[[int i = PTHREAD_PRIO_INHERIT;
return i;]])],
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
[ax_cv_PTHREAD_PRIO_INHERIT=no])
])
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
test "x$ax_pthread_prio_inherit_defined" != "xyes"],
[AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])
ax_pthread_prio_inherit_defined=yes
])
CFLAGS="$ax_pthread_save_CFLAGS"
LIBS="$ax_pthread_save_LIBS"
# More AIX lossage: compile with *_r variant
if test "x$GCC" != "xyes"; then
case $host_os in
aix*)
AS_CASE(["x/$CC"],
[x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
[#handle absolute path differently from PATH based program lookup
AS_CASE(["x$CC"],
[x/*],
[
AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])
AS_IF([test "x${CXX}" != "x"], [AS_IF([AS_EXECUTABLE_P([${CXX}_r])],[PTHREAD_CXX="${CXX}_r"])])
],
[
AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])
AS_IF([test "x${CXX}" != "x"], [AC_CHECK_PROGS([PTHREAD_CXX],[${CXX}_r],[$CXX])])
]
)
])
;;
esac
fi
fi
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX"
AC_SUBST([PTHREAD_LIBS])
AC_SUBST([PTHREAD_CFLAGS])
AC_SUBST([PTHREAD_CC])
AC_SUBST([PTHREAD_CXX])
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
if test "x$ax_pthread_ok" = "xyes"; then
ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
:
else
ax_pthread_ok=no
$2
fi
AC_LANG_POP
])dnl AX_PTHREAD
+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
+582
View File
@@ -0,0 +1,582 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_with_curses.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_WITH_CURSES
#
# DESCRIPTION
#
# This macro checks whether a SysV or X/Open-compatible Curses library is
# present, along with the associated header file. The NcursesW
# (wide-character) library is searched for first, followed by Ncurses,
# then the system-default plain Curses. The first library found is the
# one returned. Finding libraries will first be attempted by using
# pkg-config, and should the pkg-config files not be available, will
# fallback to combinations of known flags itself.
#
# The following options are understood: --with-ncursesw, --with-ncurses,
# --without-ncursesw, --without-ncurses. The "--with" options force the
# macro to use that particular library, terminating with an error if not
# found. The "--without" options simply skip the check for that library.
# The effect on the search pattern is:
#
# (no options) - NcursesW, Ncurses, Curses
# --with-ncurses --with-ncursesw - NcursesW only [*]
# --without-ncurses --with-ncursesw - NcursesW only [*]
# --with-ncursesw - NcursesW only [*]
# --with-ncurses --without-ncursesw - Ncurses only [*]
# --with-ncurses - NcursesW, Ncurses [**]
# --without-ncurses --without-ncursesw - Curses only
# --without-ncursesw - Ncurses, Curses
# --without-ncurses - NcursesW, Curses
#
# [*] If the library is not found, abort the configure script.
#
# [**] If the second library (Ncurses) is not found, abort configure.
#
# The following preprocessor symbols may be defined by this macro if the
# appropriate conditions are met:
#
# HAVE_CURSES - if any SysV or X/Open Curses library found
# HAVE_CURSES_ENHANCED - if library supports X/Open Enhanced functions
# HAVE_CURSES_COLOR - if library supports color (enhanced functions)
# HAVE_CURSES_OBSOLETE - if library supports certain obsolete features
# HAVE_NCURSESW - if NcursesW (wide char) library is to be used
# HAVE_NCURSES - if the Ncurses library is to be used
#
# HAVE_CURSES_H - if <curses.h> is present and should be used
# HAVE_NCURSESW_H - if <ncursesw.h> should be used
# HAVE_NCURSES_H - if <ncurses.h> should be used
# HAVE_NCURSESW_CURSES_H - if <ncursesw/curses.h> should be used
# HAVE_NCURSES_CURSES_H - if <ncurses/curses.h> should be used
#
# (These preprocessor symbols are discussed later in this document.)
#
# The following output variables are defined by this macro; they are
# precious and may be overridden on the ./configure command line:
#
# CURSES_LIBS - library to add to xxx_LDADD
# CURSES_CFLAGS - include paths to add to xxx_CPPFLAGS
#
# In previous versions of this macro, the flags CURSES_LIB and
# CURSES_CPPFLAGS were defined. These have been renamed, in keeping with
# AX_WITH_CURSES's close bigger brother, PKG_CHECK_MODULES, which should
# eventually supersede the use of AX_WITH_CURSES. Neither the library
# listed in CURSES_LIBS, nor the flags in CURSES_CFLAGS are added to LIBS,
# respectively CPPFLAGS, by default. You need to add both to the
# appropriate xxx_LDADD/xxx_CPPFLAGS line in your Makefile.am. For
# example:
#
# prog_LDADD = @CURSES_LIBS@
# prog_CPPFLAGS = @CURSES_CFLAGS@
#
# If CURSES_LIBS is set on the configure command line (such as by running
# "./configure CURSES_LIBS=-lmycurses"), then the only header searched for
# is <curses.h>. If the user needs to specify an alternative path for a
# library (such as for a non-standard NcurseW), the user should use the
# LDFLAGS variable.
#
# The following shell variables may be defined by this macro:
#
# ax_cv_curses - set to "yes" if any Curses library found
# ax_cv_curses_enhanced - set to "yes" if Enhanced functions present
# ax_cv_curses_color - set to "yes" if color functions present
# ax_cv_curses_obsolete - set to "yes" if obsolete features present
#
# ax_cv_ncursesw - set to "yes" if NcursesW library found
# ax_cv_ncurses - set to "yes" if Ncurses library found
# ax_cv_plaincurses - set to "yes" if plain Curses library found
# ax_cv_curses_which - set to "ncursesw", "ncurses", "plaincurses" or "no"
#
# These variables can be used in your configure.ac to determine the level
# of support you need from the Curses library. For example, if you must
# have either Ncurses or NcursesW, you could include:
#
# AX_WITH_CURSES
# if test "x$ax_cv_ncursesw" != xyes && test "x$ax_cv_ncurses" != xyes; then
# AC_MSG_ERROR([requires either NcursesW or Ncurses library])
# fi
#
# If any Curses library will do (but one must be present and must support
# color), you could use:
#
# AX_WITH_CURSES
# if test "x$ax_cv_curses" != xyes || test "x$ax_cv_curses_color" != xyes; then
# AC_MSG_ERROR([requires an X/Open-compatible Curses library with color])
# fi
#
# Certain preprocessor symbols and shell variables defined by this macro
# can be used to determine various features of the Curses library. In
# particular, HAVE_CURSES and ax_cv_curses are defined if the Curses
# library found conforms to the traditional SysV and/or X/Open Base Curses
# definition. Any working Curses library conforms to this level.
#
# HAVE_CURSES_ENHANCED and ax_cv_curses_enhanced are defined if the
# library supports the X/Open Enhanced Curses definition. In particular,
# the wide-character types attr_t, cchar_t and wint_t, the functions
# wattr_set() and wget_wch() and the macros WA_NORMAL and _XOPEN_CURSES
# are checked. The Ncurses library does NOT conform to this definition,
# although NcursesW does.
#
# HAVE_CURSES_COLOR and ax_cv_curses_color are defined if the library
# supports color functions and macros such as COLOR_PAIR, A_COLOR,
# COLOR_WHITE, COLOR_RED and init_pair(). These are NOT part of the
# X/Open Base Curses definition, but are part of the Enhanced set of
# functions. The Ncurses library DOES support these functions, as does
# NcursesW.
#
# HAVE_CURSES_OBSOLETE and ax_cv_curses_obsolete are defined if the
# library supports certain features present in SysV and BSD Curses but not
# defined in the X/Open definition. In particular, the functions
# getattrs(), getcurx() and getmaxx() are checked.
#
# To use the HAVE_xxx_H preprocessor symbols, insert the following into
# your system.h (or equivalent) header file:
#
# #if defined HAVE_NCURSESW_CURSES_H
# # include <ncursesw/curses.h>
# #elif defined HAVE_NCURSESW_H
# # include <ncursesw.h>
# #elif defined HAVE_NCURSES_CURSES_H
# # include <ncurses/curses.h>
# #elif defined HAVE_NCURSES_H
# # include <ncurses.h>
# #elif defined HAVE_CURSES_H
# # include <curses.h>
# #else
# # error "SysV or X/Open-compatible Curses header file required"
# #endif
#
# For previous users of this macro: you should not need to change anything
# in your configure.ac or Makefile.am, as the previous (serial 10)
# semantics are still valid. However, you should update your system.h (or
# equivalent) header file to the fragment shown above. You are encouraged
# also to make use of the extended functionality provided by this version
# of AX_WITH_CURSES, as well as in the additional macros
# AX_WITH_CURSES_PANEL, AX_WITH_CURSES_MENU and AX_WITH_CURSES_FORM.
#
# LICENSE
#
# Copyright (c) 2009 Mark Pulford <mark@kyne.com.au>
# Copyright (c) 2009 Damian Pietras <daper@daper.net>
# Copyright (c) 2012 Reuben Thomas <rrt@sc3d.org>
# Copyright (c) 2011 John Zaitseff <J.Zaitseff@zap.org.au>
#
# 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 18
# internal function to factorize common code that is used by both ncurses
# and ncursesw
AC_DEFUN([_FIND_CURSES_FLAGS], [
AC_MSG_CHECKING([for $1 via pkg-config])
AX_REQUIRE_DEFINED([PKG_CHECK_EXISTS])
_PKG_CONFIG([_ax_cv_$1_libs], [libs], [$1])
_PKG_CONFIG([_ax_cv_$1_cppflags], [cflags], [$1])
AS_IF([test "x$pkg_failed" = "xyes" || test "x$pkg_failed" = "xuntried"],[
AC_MSG_RESULT([no])
# No suitable .pc file found, have to find flags via fallback
AC_CACHE_CHECK([for $1 via fallback], [ax_cv_$1], [
AS_ECHO()
pkg_cv__ax_cv_$1_libs="-l$1"
pkg_cv__ax_cv_$1_cppflags="-D_GNU_SOURCE $CURSES_CFLAGS"
LIBS="$ax_saved_LIBS $pkg_cv__ax_cv_$1_libs"
CPPFLAGS="$ax_saved_CPPFLAGS $pkg_cv__ax_cv_$1_cppflags"
AC_MSG_CHECKING([for initscr() with $pkg_cv__ax_cv_$1_libs])
AC_LINK_IFELSE([AC_LANG_CALL([], [initscr])],
[
AC_MSG_RESULT([yes])
AC_MSG_CHECKING([for nodelay() with $pkg_cv__ax_cv_$1_libs])
AC_LINK_IFELSE([AC_LANG_CALL([], [nodelay])],[
ax_cv_$1=yes
],[
AC_MSG_RESULT([no])
m4_if(
[$1],[ncursesw],[pkg_cv__ax_cv_$1_libs="$pkg_cv__ax_cv_$1_libs -ltinfow"],
[$1],[ncurses],[pkg_cv__ax_cv_$1_libs="$pkg_cv__ax_cv_$1_libs -ltinfo"]
)
LIBS="$ax_saved_LIBS $pkg_cv__ax_cv_$1_libs"
AC_MSG_CHECKING([for nodelay() with $pkg_cv__ax_cv_$1_libs])
AC_LINK_IFELSE([AC_LANG_CALL([], [nodelay])],[
ax_cv_$1=yes
],[
ax_cv_$1=no
])
])
],[
ax_cv_$1=no
])
])
],[
AC_MSG_RESULT([yes])
# Found .pc file, using its information
LIBS="$ax_saved_LIBS $pkg_cv__ax_cv_$1_libs"
CPPFLAGS="$ax_saved_CPPFLAGS $pkg_cv__ax_cv_$1_cppflags"
ax_cv_$1=yes
])
])
AU_ALIAS([MP_WITH_CURSES], [AX_WITH_CURSES])
AC_DEFUN([AX_WITH_CURSES], [
AC_ARG_VAR([CURSES_LIBS], [linker library for Curses, e.g. -lcurses])
AC_ARG_VAR([CURSES_CFLAGS], [preprocessor flags for Curses, e.g. -I/usr/include/ncursesw])
AC_ARG_WITH([ncurses], [AS_HELP_STRING([--with-ncurses],
[force the use of Ncurses or NcursesW])],
[], [with_ncurses=check])
AC_ARG_WITH([ncursesw], [AS_HELP_STRING([--without-ncursesw],
[do not use NcursesW (wide character support)])],
[], [with_ncursesw=check])
ax_saved_LIBS=$LIBS
ax_saved_CPPFLAGS=$CPPFLAGS
AS_IF([test "x$with_ncurses" = xyes || test "x$with_ncursesw" = xyes],
[ax_with_plaincurses=no], [ax_with_plaincurses=check])
ax_cv_curses_which=no
# Test for NcursesW
AS_IF([test "x$CURSES_LIBS" = x && test "x$with_ncursesw" != xno], [
_FIND_CURSES_FLAGS([ncursesw])
AS_IF([test "x$ax_cv_ncursesw" = xno && test "x$with_ncursesw" = xyes], [
AC_MSG_ERROR([--with-ncursesw specified but could not find NcursesW library])
])
AS_IF([test "x$ax_cv_ncursesw" = xyes], [
ax_cv_curses=yes
ax_cv_curses_which=ncursesw
CURSES_LIBS="$pkg_cv__ax_cv_ncursesw_libs"
CURSES_CFLAGS="$pkg_cv__ax_cv_ncursesw_cppflags"
AC_DEFINE([HAVE_NCURSESW], [1], [Define to 1 if the NcursesW library is present])
AC_DEFINE([HAVE_CURSES], [1], [Define to 1 if a SysV or X/Open compatible Curses library is present])
AC_CACHE_CHECK([for working ncursesw/curses.h], [ax_cv_header_ncursesw_curses_h], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
@%:@define _XOPEN_SOURCE_EXTENDED 1
@%:@include <ncursesw/curses.h>
]], [[
chtype a = A_BOLD;
int b = KEY_LEFT;
chtype c = COLOR_PAIR(1) & A_COLOR;
attr_t d = WA_NORMAL;
cchar_t e;
wint_t f;
int g = getattrs(stdscr);
int h = getcurx(stdscr) + getmaxx(stdscr);
initscr();
init_pair(1, COLOR_WHITE, COLOR_RED);
wattr_set(stdscr, d, 0, NULL);
wget_wch(stdscr, &f);
]])],
[ax_cv_header_ncursesw_curses_h=yes],
[ax_cv_header_ncursesw_curses_h=no])
])
AS_IF([test "x$ax_cv_header_ncursesw_curses_h" = xyes], [
ax_cv_curses_enhanced=yes
ax_cv_curses_color=yes
ax_cv_curses_obsolete=yes
AC_DEFINE([HAVE_CURSES_ENHANCED], [1], [Define to 1 if library supports X/Open Enhanced functions])
AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)])
AC_DEFINE([HAVE_CURSES_OBSOLETE], [1], [Define to 1 if library supports certain obsolete features])
AC_DEFINE([HAVE_NCURSESW_CURSES_H], [1], [Define to 1 if <ncursesw/curses.h> is present])
])
AC_CACHE_CHECK([for working ncursesw.h], [ax_cv_header_ncursesw_h], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
@%:@define _XOPEN_SOURCE_EXTENDED 1
@%:@include <ncursesw.h>
]], [[
chtype a = A_BOLD;
int b = KEY_LEFT;
chtype c = COLOR_PAIR(1) & A_COLOR;
attr_t d = WA_NORMAL;
cchar_t e;
wint_t f;
int g = getattrs(stdscr);
int h = getcurx(stdscr) + getmaxx(stdscr);
initscr();
init_pair(1, COLOR_WHITE, COLOR_RED);
wattr_set(stdscr, d, 0, NULL);
wget_wch(stdscr, &f);
]])],
[ax_cv_header_ncursesw_h=yes],
[ax_cv_header_ncursesw_h=no])
])
AS_IF([test "x$ax_cv_header_ncursesw_h" = xyes], [
ax_cv_curses_enhanced=yes
ax_cv_curses_color=yes
ax_cv_curses_obsolete=yes
AC_DEFINE([HAVE_CURSES_ENHANCED], [1], [Define to 1 if library supports X/Open Enhanced functions])
AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)])
AC_DEFINE([HAVE_CURSES_OBSOLETE], [1], [Define to 1 if library supports certain obsolete features])
AC_DEFINE([HAVE_NCURSESW_H], [1], [Define to 1 if <ncursesw.h> is present])
])
AC_CACHE_CHECK([for working ncurses.h], [ax_cv_header_ncurses_h_with_ncursesw], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
@%:@define _XOPEN_SOURCE_EXTENDED 1
@%:@include <ncurses.h>
]], [[
chtype a = A_BOLD;
int b = KEY_LEFT;
chtype c = COLOR_PAIR(1) & A_COLOR;
attr_t d = WA_NORMAL;
cchar_t e;
wint_t f;
int g = getattrs(stdscr);
int h = getcurx(stdscr) + getmaxx(stdscr);
initscr();
init_pair(1, COLOR_WHITE, COLOR_RED);
wattr_set(stdscr, d, 0, NULL);
wget_wch(stdscr, &f);
]])],
[ax_cv_header_ncurses_h_with_ncursesw=yes],
[ax_cv_header_ncurses_h_with_ncursesw=no])
])
AS_IF([test "x$ax_cv_header_ncurses_h_with_ncursesw" = xyes], [
ax_cv_curses_enhanced=yes
ax_cv_curses_color=yes
ax_cv_curses_obsolete=yes
AC_DEFINE([HAVE_CURSES_ENHANCED], [1], [Define to 1 if library supports X/Open Enhanced functions])
AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)])
AC_DEFINE([HAVE_CURSES_OBSOLETE], [1], [Define to 1 if library supports certain obsolete features])
AC_DEFINE([HAVE_NCURSES_H], [1], [Define to 1 if <ncurses.h> is present])
])
AS_IF([test "x$ax_cv_header_ncursesw_curses_h" = xno && test "x$ax_cv_header_ncursesw_h" = xno && test "x$ax_cv_header_ncurses_h_with_ncursesw" = xno], [
AC_MSG_WARN([could not find a working ncursesw/curses.h, ncursesw.h or ncurses.h])
])
])
])
unset pkg_cv__ax_cv_ncursesw_libs
unset pkg_cv__ax_cv_ncursesw_cppflags
# Test for Ncurses
AS_IF([test "x$CURSES_LIBS" = x && test "x$with_ncurses" != xno && test "x$ax_cv_curses_which" = xno], [
_FIND_CURSES_FLAGS([ncurses])
AS_IF([test "x$ax_cv_ncurses" = xno && test "x$with_ncurses" = xyes], [
AC_MSG_ERROR([--with-ncurses specified but could not find Ncurses library])
])
AS_IF([test "x$ax_cv_ncurses" = xyes], [
ax_cv_curses=yes
ax_cv_curses_which=ncurses
CURSES_LIBS="$pkg_cv__ax_cv_ncurses_libs"
CURSES_CFLAGS="$pkg_cv__ax_cv_ncurses_cppflags"
AC_DEFINE([HAVE_NCURSES], [1], [Define to 1 if the Ncurses library is present])
AC_DEFINE([HAVE_CURSES], [1], [Define to 1 if a SysV or X/Open compatible Curses library is present])
AC_CACHE_CHECK([for working ncurses/curses.h], [ax_cv_header_ncurses_curses_h], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
@%:@include <ncurses/curses.h>
]], [[
chtype a = A_BOLD;
int b = KEY_LEFT;
chtype c = COLOR_PAIR(1) & A_COLOR;
int g = getattrs(stdscr);
int h = getcurx(stdscr) + getmaxx(stdscr);
initscr();
init_pair(1, COLOR_WHITE, COLOR_RED);
]])],
[ax_cv_header_ncurses_curses_h=yes],
[ax_cv_header_ncurses_curses_h=no])
])
AS_IF([test "x$ax_cv_header_ncurses_curses_h" = xyes], [
ax_cv_curses_color=yes
ax_cv_curses_obsolete=yes
AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)])
AC_DEFINE([HAVE_CURSES_OBSOLETE], [1], [Define to 1 if library supports certain obsolete features])
AC_DEFINE([HAVE_NCURSES_CURSES_H], [1], [Define to 1 if <ncurses/curses.h> is present])
])
AC_CACHE_CHECK([for working ncurses.h], [ax_cv_header_ncurses_h], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
@%:@include <ncurses.h>
]], [[
chtype a = A_BOLD;
int b = KEY_LEFT;
chtype c = COLOR_PAIR(1) & A_COLOR;
int g = getattrs(stdscr);
int h = getcurx(stdscr) + getmaxx(stdscr);
initscr();
init_pair(1, COLOR_WHITE, COLOR_RED);
]])],
[ax_cv_header_ncurses_h=yes],
[ax_cv_header_ncurses_h=no])
])
AS_IF([test "x$ax_cv_header_ncurses_h" = xyes], [
ax_cv_curses_color=yes
ax_cv_curses_obsolete=yes
AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)])
AC_DEFINE([HAVE_CURSES_OBSOLETE], [1], [Define to 1 if library supports certain obsolete features])
AC_DEFINE([HAVE_NCURSES_H], [1], [Define to 1 if <ncurses.h> is present])
])
AS_IF([test "x$ax_cv_header_ncurses_curses_h" = xno && test "x$ax_cv_header_ncurses_h" = xno], [
AC_MSG_WARN([could not find a working ncurses/curses.h or ncurses.h])
])
])
])
unset pkg_cv__ax_cv_ncurses_libs
unset pkg_cv__ax_cv_ncurses_cppflags
# Test for plain Curses (or if CURSES_LIBS was set by user)
AS_IF([test "x$with_plaincurses" != xno && test "x$ax_cv_curses_which" = xno], [
AS_IF([test "x$CURSES_LIBS" != x], [
LIBS="$ax_saved_LIBS $CURSES_LIBS"
], [
LIBS="$ax_saved_LIBS -lcurses"
])
AC_CACHE_CHECK([for Curses library], [ax_cv_plaincurses], [
AC_LINK_IFELSE([AC_LANG_CALL([], [initscr])],
[ax_cv_plaincurses=yes], [ax_cv_plaincurses=no])
])
AS_IF([test "x$ax_cv_plaincurses" = xyes], [
ax_cv_curses=yes
ax_cv_curses_which=plaincurses
AS_IF([test "x$CURSES_LIBS" = x], [
CURSES_LIBS="-lcurses"
])
AC_DEFINE([HAVE_CURSES], [1], [Define to 1 if a SysV or X/Open compatible Curses library is present])
# Check for base conformance (and header file)
AC_CACHE_CHECK([for working curses.h], [ax_cv_header_curses_h], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
@%:@include <curses.h>
]], [[
chtype a = A_BOLD;
int b = KEY_LEFT;
initscr();
]])],
[ax_cv_header_curses_h=yes],
[ax_cv_header_curses_h=no])
])
AS_IF([test "x$ax_cv_header_curses_h" = xyes], [
AC_DEFINE([HAVE_CURSES_H], [1], [Define to 1 if <curses.h> is present])
# Check for X/Open Enhanced conformance
AC_CACHE_CHECK([for X/Open Enhanced Curses conformance], [ax_cv_plaincurses_enhanced], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
@%:@define _XOPEN_SOURCE_EXTENDED 1
@%:@include <curses.h>
@%:@ifndef _XOPEN_CURSES
@%:@error "this Curses library is not enhanced"
"this Curses library is not enhanced"
@%:@endif
]], [[
chtype a = A_BOLD;
int b = KEY_LEFT;
chtype c = COLOR_PAIR(1) & A_COLOR;
attr_t d = WA_NORMAL;
cchar_t e;
wint_t f;
initscr();
init_pair(1, COLOR_WHITE, COLOR_RED);
wattr_set(stdscr, d, 0, NULL);
wget_wch(stdscr, &f);
]])],
[ax_cv_plaincurses_enhanced=yes],
[ax_cv_plaincurses_enhanced=no])
])
AS_IF([test "x$ax_cv_plaincurses_enhanced" = xyes], [
ax_cv_curses_enhanced=yes
ax_cv_curses_color=yes
AC_DEFINE([HAVE_CURSES_ENHANCED], [1], [Define to 1 if library supports X/Open Enhanced functions])
AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)])
])
# Check for color functions
AC_CACHE_CHECK([for Curses color functions], [ax_cv_plaincurses_color], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
@%:@define _XOPEN_SOURCE_EXTENDED 1
@%:@include <curses.h>
]], [[
chtype a = A_BOLD;
int b = KEY_LEFT;
chtype c = COLOR_PAIR(1) & A_COLOR;
initscr();
init_pair(1, COLOR_WHITE, COLOR_RED);
]])],
[ax_cv_plaincurses_color=yes],
[ax_cv_plaincurses_color=no])
])
AS_IF([test "x$ax_cv_plaincurses_color" = xyes], [
ax_cv_curses_color=yes
AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)])
])
# Check for obsolete functions
AC_CACHE_CHECK([for obsolete Curses functions], [ax_cv_plaincurses_obsolete], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
@%:@include <curses.h>
]], [[
chtype a = A_BOLD;
int b = KEY_LEFT;
int g = getattrs(stdscr);
int h = getcurx(stdscr) + getmaxx(stdscr);
initscr();
]])],
[ax_cv_plaincurses_obsolete=yes],
[ax_cv_plaincurses_obsolete=no])
])
AS_IF([test "x$ax_cv_plaincurses_obsolete" = xyes], [
ax_cv_curses_obsolete=yes
AC_DEFINE([HAVE_CURSES_OBSOLETE], [1], [Define to 1 if library supports certain obsolete features])
])
])
AS_IF([test "x$ax_cv_header_curses_h" = xno], [
AC_MSG_WARN([could not find a working curses.h])
])
])
])
AS_IF([test "x$ax_cv_curses" != xyes], [ax_cv_curses=no])
AS_IF([test "x$ax_cv_curses_enhanced" != xyes], [ax_cv_curses_enhanced=no])
AS_IF([test "x$ax_cv_curses_color" != xyes], [ax_cv_curses_color=no])
AS_IF([test "x$ax_cv_curses_obsolete" != xyes], [ax_cv_curses_obsolete=no])
LIBS=$ax_saved_LIBS
CPPFLAGS=$ax_saved_CPPFLAGS
unset ax_saved_LIBS
unset ax_saved_CPPFLAGS
])dnl
+175 -122
View File
@@ -1,15 +1,15 @@
AC_DEFUN([TORRENT_CHECK_XFS], [
AC_MSG_CHECKING(for XFS support)
AC_COMPILE_IFELSE(
[[#include <xfs/libxfs.h>
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <xfs/libxfs.h>
#include <sys/ioctl.h>
int main() {
struct xfs_flock64 l;
ioctl(0, XFS_IOC_RESVSP64, &l);
return 0;
}
]],
])],
[
AC_DEFINE(USE_XFS, 1, Use XFS filesystem stuff.)
AC_MSG_RESULT(yes)
@@ -21,9 +21,9 @@ AC_DEFUN([TORRENT_CHECK_XFS], [
AC_DEFUN([TORRENT_WITHOUT_XFS], [
AC_ARG_WITH(xfs,
[ --without-xfs Do not check for XFS filesystem support],
AS_HELP_STRING([--without-xfs],[do not check for XFS filesystem support]),
[
if test "$withval" = "yes"; then
if test "$withval" = "yes"; then
TORRENT_CHECK_XFS
fi
], [
@@ -34,7 +34,7 @@ AC_DEFUN([TORRENT_WITHOUT_XFS], [
AC_DEFUN([TORRENT_WITH_XFS], [
AC_ARG_WITH(xfs,
[ --with-xfs Check for XFS filesystem support],
AS_HELP_STRING([--with-xfs],[check for XFS filesystem support]),
[
if test "$withval" = "yes"; then
TORRENT_CHECK_XFS
@@ -46,13 +46,13 @@ AC_DEFUN([TORRENT_WITH_XFS], [
AC_DEFUN([TORRENT_CHECK_EPOLL], [
AC_MSG_CHECKING(for epoll support)
AC_COMPILE_IFELSE(
[[#include <sys/epoll.h>
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <sys/epoll.h>
int main() {
int fd = epoll_create(100);
return 0;
}
]],
])],
[
AC_DEFINE(USE_EPOLL, 1, Use epoll.)
AC_MSG_RESULT(yes)
@@ -63,7 +63,7 @@ AC_DEFUN([TORRENT_CHECK_EPOLL], [
AC_DEFUN([TORRENT_WITHOUT_EPOLL], [
AC_ARG_WITH(epoll,
[ --without-epoll Do not check for epoll support.],
AS_HELP_STRING([--without-epoll],[do not check for epoll support]),
[
if test "$withval" = "yes"; then
TORRENT_CHECK_EPOLL
@@ -77,17 +77,18 @@ AC_DEFUN([TORRENT_WITHOUT_EPOLL], [
AC_DEFUN([TORRENT_CHECK_KQUEUE], [
AC_MSG_CHECKING(for kqueue support)
AC_LINK_IFELSE(
[[#include <sys/time.h> /* Because OpenBSD's sys/event.h fails to compile otherwise. Yeah... */
AC_LINK_IFELSE([AC_LANG_SOURCE([
#include <sys/time.h> /* Because OpenBSD's sys/event.h fails to compile otherwise. Yeah... */
#include <sys/event.h>
int main() {
int fd = kqueue();
return 0;
}
]],
])],
[
AC_DEFINE(USE_KQUEUE, 1, Use kqueue.)
AC_MSG_RESULT(yes)
TORRENT_CHECK_KQUEUE_SOCKET_ONLY
], [
AC_MSG_RESULT(no)
])
@@ -96,33 +97,33 @@ AC_DEFUN([TORRENT_CHECK_KQUEUE], [
AC_DEFUN([TORRENT_CHECK_KQUEUE_SOCKET_ONLY], [
AC_MSG_CHECKING(whether kqueue supports pipes and ptys)
AC_RUN_IFELSE(
[[#include <fcntl.h>
AC_LINK_IFELSE([AC_LANG_SOURCE([
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/event.h>
#include <sys/time.h>
int main() {
struct kevent ev[2], ev_out[2];
struct kevent ev@<:@2@:>@, ev_out@<:@2@:>@;
struct timespec ts = { 0, 0 };
int pfd[2], pty[2], kfd, n;
char buffer[9001];
int pfd@<:@2@:>@, pty@<:@2@:>@, kfd, n;
char buffer@<:@9001@:>@;
if (pipe(pfd) == -1) return 1;
if (fcntl(pfd[1], F_SETFL, O_NONBLOCK) == -1) return 2;
while ((n = write(pfd[1], buffer, sizeof(buffer))) == sizeof(buffer));
if ((pty[0]=posix_openpt(O_RDWR | O_NOCTTY)) == -1) return 3;
if ((pty[1]=grantpt(pty[0])) == -1) return 4;
EV_SET(ev+0, pfd[1], EVFILT_WRITE, EV_ADD | EV_ENABLE, 0, 0, NULL);
EV_SET(ev+1, pty[1], EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, NULL);
if (fcntl(pfd@<:@1@:>@, F_SETFL, O_NONBLOCK) == -1) return 2;
while ((n = write(pfd@<:@1@:>@, buffer, sizeof(buffer))) == sizeof(buffer));
if ((pty@<:@0@:>@=posix_openpt(O_RDWR | O_NOCTTY)) == -1) return 3;
if ((pty@<:@1@:>@=grantpt(pty@<:@0@:>@)) == -1) return 4;
EV_SET(ev+0, pfd@<:@1@:>@, EVFILT_WRITE, EV_ADD | EV_ENABLE, 0, 0, NULL);
EV_SET(ev+1, pty@<:@1@:>@, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, NULL);
if ((kfd = kqueue()) == -1) return 5;
if ((n = kevent(kfd, ev, 2, NULL, 0, NULL)) == -1) return 6;
if (ev_out[0].flags & EV_ERROR) return 7;
if (ev_out[1].flags & EV_ERROR) return 8;
read(pfd[0], buffer, sizeof(buffer));
if (ev_out@<:@0@:>@.flags & EV_ERROR) return 7;
if (ev_out@<:@1@:>@.flags & EV_ERROR) return 8;
read(pfd@<:@0@:>@, buffer, sizeof(buffer));
if ((n = kevent(kfd, NULL, 0, ev_out, 2, &ts)) < 1) return 9;
return 0;
}
]],
])],
[
AC_MSG_RESULT(yes)
], [
@@ -133,20 +134,31 @@ AC_DEFUN([TORRENT_CHECK_KQUEUE_SOCKET_ONLY], [
AC_DEFUN([TORRENT_WITH_KQUEUE], [
AC_ARG_WITH(kqueue,
[ --with-kqueue enable kqueue. [[default=no]]],
AS_HELP_STRING([--with-kqueue],[enable kqueue [[default=no]]]),
[
if test "$withval" = "yes"; then
TORRENT_CHECK_KQUEUE
TORRENT_CHECK_KQUEUE_SOCKET_ONLY
fi
])
])
AC_DEFUN([TORRENT_WITHOUT_KQUEUE], [
AC_ARG_WITH(kqueue,
AS_HELP_STRING([--without-kqueue],[do not check for kqueue support]),
[
if test "$withval" = "yes"; then
TORRENT_CHECK_KQUEUE
fi
], [
TORRENT_CHECK_KQUEUE
])
])
AC_DEFUN([TORRENT_WITHOUT_VARIABLE_FDSET], [
AC_ARG_WITH(variable-fdset,
[ --without-variable-fdset do not use non-portable variable sized fd_set's.],
AS_HELP_STRING([--without-variable-fdset],[do not use non-portable variable sized fd_set's]),
[
if test "$withval" = "yes"; then
AC_DEFINE(USE_VARIABLE_FDSET, 1, defined when we allow the use of fd_set's of any size)
@@ -160,14 +172,13 @@ AC_DEFUN([TORRENT_WITHOUT_VARIABLE_FDSET], [
AC_DEFUN([TORRENT_CHECK_FALLOCATE], [
AC_MSG_CHECKING(for fallocate)
AC_TRY_LINK([#include <fcntl.h>
#include <linux/falloc.h>
],[ fallocate(0, FALLOC_FL_KEEP_SIZE, 0, 0); return 0;
],
[
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#define _GNU_SOURCE
#include <fcntl.h>
]], [[ fallocate(0, FALLOC_FL_KEEP_SIZE, 0, 0); return 0;
]])],[
AC_DEFINE(HAVE_FALLOCATE, 1, Linux's fallocate supported.)
AC_MSG_RESULT(yes)
], [
],[
AC_MSG_RESULT(no)
])
])
@@ -176,13 +187,12 @@ AC_DEFUN([TORRENT_CHECK_FALLOCATE], [
AC_DEFUN([TORRENT_CHECK_POSIX_FALLOCATE], [
AC_MSG_CHECKING(for posix_fallocate)
AC_TRY_LINK([#include <fcntl.h>
],[ posix_fallocate(0, 0, 0);
],
[
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <fcntl.h>
]], [[ posix_fallocate(0, 0, 0);
]])],[
AC_DEFINE(USE_POSIX_FALLOCATE, 1, posix_fallocate supported.)
AC_MSG_RESULT(yes)
], [
],[
AC_MSG_RESULT(no)
])
])
@@ -190,7 +200,7 @@ AC_DEFUN([TORRENT_CHECK_POSIX_FALLOCATE], [
AC_DEFUN([TORRENT_WITH_POSIX_FALLOCATE], [
AC_ARG_WITH(posix-fallocate,
[ --with-posix-fallocate Check for and use posix_fallocate to allocate files.],
AS_HELP_STRING([--with-posix-fallocate],[check for and use posix_fallocate to allocate files]),
[
if test "$withval" = "yes"; then
TORRENT_CHECK_POSIX_FALLOCATE
@@ -198,33 +208,12 @@ AC_DEFUN([TORRENT_WITH_POSIX_FALLOCATE], [
])
])
AC_DEFUN([TORRENT_WITHOUT_NCURSESW], [
AC_ARG_WITH(ncursesw,
[ --without-ncursesw Don't try to use wide char ncurses.],
[
if test "$withval" = "no"; then
AC_SEARCH_LIBS(add_wch, ncursesw,
AC_DEFINE(HAVE_NCURSESW, 1, defined if ncurses wide character support is available),
AC_SEARCH_LIBS(wbkgdset, ncurses curses,,echo "*** The ncurses library is required!";exit 1)
)
else
AC_SEARCH_LIBS(wbkgdset, ncurses curses,,echo "*** The ncurses library is required!";exit 1)
fi
],[
AC_SEARCH_LIBS(add_wch, ncursesw,
AC_DEFINE(HAVE_NCURSESW, 1, defined if ncurses wide character support is available),
AC_SEARCH_LIBS(wbkgdset, ncurses curses,,echo "*** The ncurses library is required!";exit 1)
)
])
])
AC_DEFUN([TORRENT_CHECK_STATVFS], [
AC_CHECK_HEADERS(sys/vfs.h sys/statvfs.h sys/statfs.h)
AC_MSG_CHECKING(for statvfs)
AC_TRY_LINK(
[
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#if HAVE_SYS_VFS_H
#include <sys/vfs.h>
#endif
@@ -234,12 +223,11 @@ AC_DEFUN([TORRENT_CHECK_STATVFS], [
#if HAVE_SYS_STATFS_H
#include <sys/statfs.h>
#endif
],[
]], [[
struct statvfs s; fsblkcnt_t c;
statvfs("", &s);
fstatvfs(0, &s);
],
[
]])],[
AC_DEFINE(FS_STAT_FD, [fstatvfs(fd, &m_stat) == 0], Function to determine filesystem stats from fd)
AC_DEFINE(FS_STAT_FN, [statvfs(fn, &m_stat) == 0], Function to determine filesystem stats from filename)
AC_DEFINE(FS_STAT_STRUCT, [struct statvfs], Type of second argument to statfs function)
@@ -248,8 +236,7 @@ AC_DEFUN([TORRENT_CHECK_STATVFS], [
AC_DEFINE(FS_STAT_BLOCK_SIZE, [(m_stat.f_frsize)], Determine the block size)
AC_MSG_RESULT(ok)
have_stat_vfs=yes
],
[
],[
AC_MSG_RESULT(no)
have_stat_vfs=no
])
@@ -260,8 +247,7 @@ AC_DEFUN([TORRENT_CHECK_STATFS], [
AC_MSG_CHECKING(for statfs)
AC_TRY_LINK(
[
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#if HAVE_SYS_STATFS_H
#include <sys/statfs.h>
#endif
@@ -271,12 +257,11 @@ AC_DEFUN([TORRENT_CHECK_STATFS], [
#if HAVE_SYS_MOUNT_H
#include <sys/mount.h>
#endif
],[
]], [[
struct statfs s;
statfs("", &s);
fstatfs(0, &s);
],
[
]])],[
AC_DEFINE(FS_STAT_FD, [fstatfs(fd, &m_stat) == 0], Function to determine filesystem stats from fd)
AC_DEFINE(FS_STAT_FN, [statfs(fn, &m_stat) == 0], Function to determine filesystem stats from filename)
AC_DEFINE(FS_STAT_STRUCT, [struct statfs], Type of second argument to statfs function)
@@ -285,8 +270,7 @@ AC_DEFUN([TORRENT_CHECK_STATFS], [
AC_DEFINE(FS_STAT_BLOCK_SIZE, [(m_stat.f_bsize)], Determine the block size)
AC_MSG_RESULT(ok)
have_stat_vfs=yes
],
[
],[
AC_MSG_RESULT(no)
have_stat_vfs=no
])
@@ -304,7 +288,7 @@ AC_DEFUN([TORRENT_DISABLED_STATFS], [
AC_DEFUN([TORRENT_WITHOUT_STATVFS], [
AC_ARG_WITH(statvfs,
[ --without-statvfs Don't try to use statvfs to find free diskspace.],
AS_HELP_STRING([--without-statvfs],[don't try to use statvfs to find free diskspace]),
[
if test "$withval" = "yes"; then
TORRENT_CHECK_STATVFS
@@ -319,7 +303,7 @@ AC_DEFUN([TORRENT_WITHOUT_STATVFS], [
AC_DEFUN([TORRENT_WITHOUT_STATFS], [
AC_ARG_WITH(statfs,
[ --without-statfs Don't try to use statfs to find free diskspace.],
AS_HELP_STRING([--without-statfs],[don't try to use statfs to find free diskspace]),
[
if test "$have_stat_vfs" = "no"; then
if test "$withval" = "yes"; then
@@ -341,7 +325,7 @@ AC_DEFUN([TORRENT_WITHOUT_STATFS], [
AC_DEFUN([TORRENT_WITH_ADDRESS_SPACE], [
AC_ARG_WITH(address-space,
AC_HELP_STRING([--with-address-space=MB], [Change the default address space size, default 1024 MB.]),
AS_HELP_STRING([--with-address-space=MB],[change the default address space size [[default=1024mb]]]),
[
if test ! -z $withval -a "$withval" != "yes" -a "$withval" != "no"; then
AC_DEFINE_UNQUOTED(DEFAULT_ADDRESS_SPACE_SIZE, [$withval])
@@ -360,30 +344,9 @@ AC_DEFUN([TORRENT_WITH_ADDRESS_SPACE], [
])
])
AC_DEFUN([TORRENT_CHECK_TR1], [
AC_LANG_PUSH(C++)
AC_MSG_CHECKING(for TR1 support)
AC_COMPILE_IFELSE(
[[#include <tr1/unordered_map>
class Foo;
typedef std::tr1::unordered_map<Foo*, int> Bar;
]],
[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_TR1, 1, Define to 1 if your C++ library supports the extensions from Technical Report 1)
],
[
AC_MSG_RESULT(no)
]
)
AC_LANG_POP(C++)
])
AC_DEFUN([TORRENT_WITH_FASTCGI], [
AC_ARG_WITH(fastcgi,
[ --with-fastcgi=PATH Enable FastCGI RPC support. (DO NOT USE)],
AS_HELP_STRING([--with-fastcgi=PATH],[enable FastCGI RPC support (DO NOT USE)]),
[
AC_MSG_CHECKING([for FastCGI (DO NOT USE)])
@@ -394,13 +357,10 @@ AC_DEFUN([TORRENT_WITH_FASTCGI], [
CXXFLAGS="$CXXFLAGS"
LIBS="$LIBS -lfcgi"
AC_TRY_LINK(
[ #include <fcgiapp.h>
],[ FCGX_Init(); ],
[
AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include <fcgiapp.h>
]], [[ FCGX_Init(); ]])],[
AC_MSG_RESULT(ok)
],
[
],[
AC_MSG_RESULT(not found)
AC_MSG_ERROR(Could not compile FastCGI test.)
])
@@ -411,13 +371,10 @@ AC_DEFUN([TORRENT_WITH_FASTCGI], [
CXXFLAGS="$CXXFLAGS -I$withval/include"
LIBS="$LIBS -lfcgi -L$withval/lib"
AC_TRY_LINK(
[ #include <fcgiapp.h>
],[ FCGX_Init(); ],
[
AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include <fcgiapp.h>
]], [[ FCGX_Init(); ]])],[
AC_MSG_RESULT(ok)
],
[
],[
AC_MSG_RESULT(not found)
AC_MSG_ERROR(Could not compile FastCGI test.)
])
@@ -432,7 +389,7 @@ AC_DEFUN([TORRENT_WITH_XMLRPC_C], [
AC_MSG_CHECKING(for XMLRPC-C)
AC_ARG_WITH(xmlrpc-c,
[ --with-xmlrpc-c=PATH Enable XMLRPC-C support.],
AS_HELP_STRING([--with-xmlrpc-c=PATH],[enable XMLRPC-C support]),
[
if test "$withval" = "no"; then
AC_MSG_RESULT(no)
@@ -443,17 +400,15 @@ 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`"
AC_TRY_LINK(
[ #include <xmlrpc-c/server.h>
],[ xmlrpc_registry_new(NULL); ],
[
AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include <xmlrpc-c/server.h>
]], [[ xmlrpc_registry_new(NULL); ]])],[
AC_MSG_RESULT(ok)
], [
],[
AC_MSG_RESULT(failed)
AC_MSG_ERROR(Could not compile XMLRPC-C test.)
])
@@ -470,3 +425,101 @@ AC_DEFUN([TORRENT_WITH_XMLRPC_C], [
AC_MSG_RESULT(ignored)
])
])
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++)
AC_CHECK_HEADERS([sys/inotify.h mcheck.h])
AC_MSG_CHECKING([whether sys/inotify.h actually works])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <sys/inotify.h>
int main(int,const char**) { return (-1 == inotify_init()); }])
],[
AC_DEFINE(HAVE_INOTIFY, 1, [sys/inotify.h exists and works correctly])
AC_MSG_RESULT(yes)],
[AC_MSG_RESULT(failed)]
)
AC_LANG_POP(C++)
])
AC_DEFUN([TORRENT_CHECK_PTHREAD_SETNAME_NP], [
AC_CHECK_HEADERS(pthread.h)
AC_MSG_CHECKING(for pthread_setname_np type)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <pthread.h>
#include <sys/types.h>
]], [[
pthread_t t;
pthread_setname_np(t, "foo");
]])],[
AC_DEFINE(HAS_PTHREAD_SETNAME_NP_GENERIC, 1, The function to set pthread name has a pthread_t argumet.)
AC_MSG_RESULT(generic)
],[
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <pthread.h>
#include <sys/types.h>
]],[[
pthread_t t;
pthread_setname_np("foo");
]])],[
AC_DEFINE(HAS_PTHREAD_SETNAME_NP_DARWIN, 1, The function to set pthread name has no pthread argument.)
AC_MSG_RESULT(darwin)
],[
AC_MSG_RESULT(no)
])
])
])
AC_DEFUN([TORRENT_DISABLE_PTHREAD_SETNAME_NP], [
AC_MSG_CHECKING([for pthread_setname_no])
AC_ARG_ENABLE(pthread-setname-np,
AS_HELP_STRING([--disable-pthread-setname-np],[disable pthread_setname_np]),
[
if test "$enableval" = "no"; then
AC_MSG_RESULT(disabled)
else
AC_MSG_RESULT(checking)
TORRENT_CHECK_PTHREAD_SETNAME_NP
fi
], [
TORRENT_CHECK_PTHREAD_SETNAME_NP
]
)
])
+77 -128
View File
@@ -1,56 +1,7 @@
AC_DEFUN([TORRENT_CHECK_CXXFLAGS], [
AC_MSG_CHECKING([for user-defined CXXFLAGS])
if test -n "$CXXFLAGS"; then
AC_MSG_RESULT([user-defined "$CXXFLAGS"])
else
CXXFLAGS="-O2 -Wall"
AC_MSG_RESULT([default "$CXXFLAGS"])
fi
])
AC_DEFUN([TORRENT_ENABLE_DEBUG], [
AC_ARG_ENABLE(debug,
[ --enable-debug enable debug information [[default=yes]]],
[
if test "$enableval" = "yes"; then
CXXFLAGS="$CXXFLAGS -g -DDEBUG"
else
CXXFLAGS="$CXXFLAGS -DNDEBUG"
fi
],[
CXXFLAGS="$CXXFLAGS -g -DDEBUG"
])
])
AC_DEFUN([TORRENT_ENABLE_WERROR], [
AC_ARG_ENABLE(werror,
[ --enable-werror enable the -Werror and -Wall flag [[default=no]]],
[
if test "$enableval" = "yes"; then
CXXFLAGS="$CXXFLAGS -Werror -Wall"
fi
])
])
AC_DEFUN([TORRENT_ENABLE_EXTRA_DEBUG], [
AC_ARG_ENABLE(extra-debug,
[ --enable-extra-debug enable extra debugging checks. [[default=no]]],
[
if test "$enableval" = "yes"; then
AC_DEFINE(USE_EXTRA_DEBUG, 1, Enable extra debugging checks.)
fi
])
])
AC_DEFUN([TORRENT_WITH_SYSROOT], [
AC_ARG_WITH(sysroot,
[ --with-sysroot=PATH compile and link with a specific sysroot.],
AS_HELP_STRING([--with-sysroot=PATH],
[compile and link with a specific sysroot]),
[
AC_MSG_CHECKING(for sysroot)
@@ -62,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
@@ -70,9 +21,23 @@ 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,
[ --enable-arch=ARCH comma seprated list of architectures to compile for.],
AS_HELP_STRING([--enable-arch=ARCH],
[comma seprated list of architectures to compile for]),
[
AC_MSG_CHECKING(for target architectures)
@@ -95,48 +60,28 @@ AC_DEFUN([TORRENT_ENABLE_ARCH], [
])
AC_DEFUN([TORRENT_OTFD], [
AC_LANG_PUSH(C++)
AC_MSG_CHECKING(for proper overloaded template function disambiguation)
AC_COMPILE_IFELSE(
[[template <typename T> void f(T&) {}
template <typename T> void f(T*) {}
int main() { int *i = 0; f(*i); f(i); }
]],
[
AC_MSG_RESULT(yes)
], [
AC_MSG_RESULT(no)
AC_MSG_ERROR([your compiler does not properly handle overloaded template function disambiguation])
])
AC_LANG_POP(C++)
])
AC_DEFUN([TORRENT_MINCORE_SIGNEDNESS], [
AC_LANG_PUSH(C++)
AC_MSG_CHECKING(signedness of mincore parameter)
AC_COMPILE_IFELSE(
[[#include <sys/types.h>
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
void f() { mincore((char*)0, 0, (unsigned char*)0); }
]],
])],
[
AC_DEFINE(USE_MINCORE, 1, Use mincore)
AC_DEFINE(USE_MINCORE_UNSIGNED, 1, use unsigned char* in mincore)
AC_MSG_RESULT(unsigned)
],
[
AC_COMPILE_IFELSE(
[[#include <sys/types.h>
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
void f() { mincore((char*)0, 0, (char*)0); }
]],
])],
[
AC_DEFINE(USE_MINCORE, 1, Use mincore)
AC_DEFINE(USE_MINCORE_UNSIGNED, 0, use char* in mincore)
@@ -152,7 +97,8 @@ AC_DEFUN([TORRENT_MINCORE_SIGNEDNESS], [
AC_DEFUN([TORRENT_MINCORE], [
AC_ARG_ENABLE(mincore,
[ --disable-mincore disable mincore check [[default=enable]]],
AS_HELP_STRING([--disable-mincore],
[disable mincore check [[default=enable]]]),
[
if test "$enableval" = "yes"; then
TORRENT_MINCORE_SIGNEDNESS()
@@ -168,11 +114,11 @@ AC_DEFUN([TORRENT_MINCORE], [
AC_DEFUN([TORRENT_CHECK_MADVISE], [
AC_MSG_CHECKING(for madvise)
AC_COMPILE_IFELSE(
[[#include <sys/types.h>
#include <sys/mman.h>
void f() { static char test[1024]; madvise((void *)test, sizeof(test), MADV_NORMAL); }
]],
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <sys/types.h>
#include <sys/mman.h>
void f() { static char test@<:@1024@:>@; madvise((void *)test, sizeof(test), MADV_NORMAL); }
])],
[
AC_MSG_RESULT(yes)
AC_DEFINE(USE_MADVISE, 1, Use madvise)
@@ -184,10 +130,9 @@ AC_DEFUN([TORRENT_CHECK_MADVISE], [
AC_DEFUN([TORRENT_CHECK_POPCOUNT], [
AC_MSG_CHECKING(for __builtin_popcount)
AC_COMPILE_IFELSE(
[[
void f() { __builtin_popcount(0); }
]],
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
int f() { return __builtin_popcount(0); }
])],
[
AC_MSG_RESULT(yes)
AC_DEFINE(USE_BUILTIN_POPCOUNT, 1, Use __builtin_popcount.)
@@ -199,12 +144,12 @@ AC_DEFUN([TORRENT_CHECK_POPCOUNT], [
AC_DEFUN([TORRENT_CHECK_CACHELINE], [
AC_MSG_CHECKING(for cacheline)
AC_COMPILE_IFELSE(
[[#include <stdlib.h>
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <stdlib.h>
#include <linux/cache.h>
void* vptr __cacheline_aligned;
void f() { posix_memalign(&vptr, SMP_CACHE_BYTES, 42); }
]],
])],
[
AC_MSG_RESULT(found builtin)
dnl AC_DEFINE(LT_SMP_CACHE_BYTES, SMP_CACHE_BYTES, Largest L1 cache size we know of, should work on all archs.)
@@ -221,34 +166,19 @@ dnl Need to fix this so that it uses the stuff defined by the system.
])
])
AC_DEFUN([TORRENT_CHECK_EXECINFO], [
AC_MSG_CHECKING(for execinfo.h)
AC_RUN_IFELSE(
[[#include <execinfo.h>
int main() { backtrace((void**)0, 0); backtrace_symbols((char**)0, 0); return 0;}
]],
[
AC_MSG_RESULT(yes)
AC_DEFINE(USE_EXECINFO, 1, Use execinfo.h)
], [
AC_MSG_RESULT(no)
])
])
AC_DEFUN([TORRENT_CHECK_ALIGNED], [
AC_MSG_CHECKING(the byte alignment)
AC_RUN_IFELSE(
[[#include <inttypes.h>
AC_RUN_IFELSE([AC_LANG_SOURCE([
#include <inttypes.h>
int main() {
char buf[8] = { 0, 0, 0, 0, 1, 0, 0, 0 };
char buf@<:@8@:>@ = { 0, 0, 0, 0, 1, 0, 0, 0 };
int i;
for (i = 1; i < 4; ++i)
if (*(uint32_t*)(buf + i) == 0) return -1;
return 0;
}
]],
])],
[
AC_MSG_RESULT(none needed)
], [
@@ -260,7 +190,8 @@ AC_DEFUN([TORRENT_CHECK_ALIGNED], [
AC_DEFUN([TORRENT_ENABLE_ALIGNED], [
AC_ARG_ENABLE(aligned,
[ --enable-aligned enable alignment safe code [[default=check]]],
AS_HELP_STRING([--enable-aligned],
[enable alignment safe code [[default=check]]]),
[
if test "$enableval" = "yes"; then
AC_DEFINE(USE_ALIGNED, 1, Require byte alignment)
@@ -271,27 +202,45 @@ AC_DEFUN([TORRENT_ENABLE_ALIGNED], [
])
AC_DEFUN([TORRENT_DISABLE_INSTRUMENTATION], [
AC_MSG_CHECKING([if instrumentation should be included])
AC_ARG_ENABLE(instrumentation,
AS_HELP_STRING([--disable-instrumentation],
[disable instrumentation [[default=enabled]]]),
[
if test "$enableval" = "yes"; then
AC_DEFINE(LT_INSTRUMENTATION, 1, enable instrumentation)
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
],[
AC_DEFINE(LT_INSTRUMENTATION, 1, enable instrumentation)
AC_MSG_RESULT(yes)
])
])
AC_DEFUN([TORRENT_ENABLE_INTERRUPT_SOCKET], [
AC_ARG_ENABLE(interrupt-socket,
AS_HELP_STRING([--enable-interrupt-socket],
[enable interrupt socket [[default=no]]]),
[
if test "$enableval" = "yes"; then
AC_DEFINE(USE_INTERRUPT_SOCKET, 1, Use interrupt socket instead of pthread_kill)
fi
]
)
])
AC_DEFUN([TORRENT_DISABLE_IPV6], [
AC_ARG_ENABLE(ipv6,
[ --enable-ipv6 disable ipv6 [[default=no]]],
AS_HELP_STRING([--enable-ipv6],
[enable ipv6 [[default=no]]]),
[
if test "$enableval" = "yes"; then
AC_DEFINE(RAK_USE_INET6, 1, enable ipv6 stuff)
fi
])
])
AC_DEFUN([TORRENT_ENABLE_TR1], [
AC_ARG_ENABLE(std_tr1,
[ --disable-std_tr1 disable check for support for TR1 [[default=enable]]],
[
if test "$enableval" = "yes"; then
TORRENT_CHECK_TR1()
else
AC_MSG_CHECKING(for TR1 support)
AC_MSG_RESULT(disabled)
fi
],[
TORRENT_CHECK_TR1()
])
])
+63
View File
@@ -0,0 +1,63 @@
AC_DEFUN([RAK_CHECK_CFLAGS], [
AC_MSG_CHECKING([for user-defined CFLAGS])
if test "$CFLAGS" = ""; then
unset CFLAGS
AC_MSG_RESULT([undefined])
else
AC_MSG_RESULT([user-defined "$CFLAGS"])
fi
])
AC_DEFUN([RAK_CHECK_CXXFLAGS], [
AC_MSG_CHECKING([for user-defined CXXFLAGS])
if test "$CXXFLAGS" = ""; then
unset CXXFLAGS
AC_MSG_RESULT([undefined])
else
AC_MSG_RESULT([user-defined "$CXXFLAGS"])
fi
])
AC_DEFUN([RAK_ENABLE_DEBUG], [
AC_ARG_ENABLE(debug,
AS_HELP_STRING([--enable-debug],[enable debug information [[default=yes]]]),
[
if test "$enableval" = "yes"; then
CXXFLAGS="$CXXFLAGS -g -DDEBUG"
else
CXXFLAGS="$CXXFLAGS -DNDEBUG"
fi
],[
CXXFLAGS="$CXXFLAGS -g -DDEBUG"
])
])
AC_DEFUN([RAK_ENABLE_WERROR], [
AC_ARG_ENABLE(werror,
AS_HELP_STRING([--enable-werror],[enable the -Werror and -Wall flags [[default -Wall only]]]),
[
if test "$enableval" = "yes"; then
CXXFLAGS="$CXXFLAGS -Werror -Wall"
fi
],[
CXXFLAGS="$CXXFLAGS -Wall"
])
])
AC_DEFUN([RAK_ENABLE_EXTRA_DEBUG], [
AC_ARG_ENABLE(extra-debug,
AS_HELP_STRING([--enable-extra-debug],[enable extra debugging checks [[default=no]]]),
[
if test "$enableval" = "yes"; then
AC_DEFINE(USE_EXTRA_DEBUG, 1, Enable extra debugging checks.)
fi
])
])
+38
View File
@@ -0,0 +1,38 @@
AC_DEFUN([TORRENT_CHECK_OPENSSL],
[
PKG_CHECK_MODULES(OPENSSL, libcrypto,
CXXFLAGS="$CXXFLAGS $OPENSSL_CFLAGS";
LIBS="$LIBS $OPENSSL_LIBS")
AC_DEFINE(USE_OPENSSL, 1, Using OpenSSL.)
AC_DEFINE(USE_OPENSSL_SHA, 1, Using OpenSSL's SHA1 implementation.)
]
)
AC_DEFUN([TORRENT_ARG_OPENSSL],
[
AC_ARG_ENABLE(openssl,
[ --disable-openssl Don't use OpenSSL's SHA1 implementation.],
[
if test "$enableval" = "yes"; then
TORRENT_CHECK_OPENSSL
else
AC_DEFINE(USE_NSS_SHA, 1, Using Mozilla's SHA1 implementation.)
fi
],[
TORRENT_CHECK_OPENSSL
])
]
)
AC_DEFUN([TORRENT_ARG_CYRUS_RC4],
[
AC_ARG_ENABLE(cyrus-rc4,
[ --enable-cyrus-rc4=PFX Use Cyrus RC4 implementation.],
[
CXXFLAGS="$CXXFLAGS -I${enableval}/include";
LIBS="$LIBS -lrc4 -L${enableval}/lib"
AC_DEFINE(USE_CYRUS_RC4, 1, Using Cyrus RC4 implementation.)
])
]
)
+177 -24
View File
@@ -1,14 +1,181 @@
SUBDIRS = \
core \
display \
input \
rpc \
ui \
utils
noinst_LIBRARIES = libsub_root.a
bin_PROGRAMS = rtorrent
rtorrent_LDADD = libsub_root.a @PTHREAD_LIBS@
rtorrent_SOURCES = main.cc
libsub_root_a_SOURCES = \
core/curl_get.cc \
core/curl_get.h \
core/curl_socket.cc \
core/curl_socket.h \
core/curl_stack.cc \
core/curl_stack.h \
core/dht_manager.cc \
core/dht_manager.h \
core/download.cc \
core/download.h \
core/download_factory.cc \
core/download_factory.h \
core/download_list.cc \
core/download_list.h \
core/download_slot_map.h \
core/download_store.cc \
core/download_store.h \
core/http_queue.cc \
core/http_queue.h \
core/manager.cc \
core/manager.h \
core/poll_manager.cc \
core/poll_manager.h \
core/range_map.h \
core/view.cc \
core/view.h \
core/view_manager.cc \
core/view_manager.h \
\
display/attributes.h \
display/canvas.cc \
display/canvas.h \
display/color_map.h \
display/frame.cc \
display/frame.h \
display/manager.cc \
display/manager.h \
display/utils.cc \
display/utils.h \
display/text_element.h \
display/text_element_list.cc \
display/text_element_list.h \
display/text_element_string.cc \
display/text_element_string.h \
display/text_element_value.cc \
display/text_element_value.h \
display/window.cc \
display/window.h \
display/window_download_chunks_seen.cc \
display/window_download_chunks_seen.h \
display/window_download_list.cc \
display/window_download_list.h \
display/window_download_statusbar.cc \
display/window_download_statusbar.h \
display/window_download_transfer_list.cc \
display/window_download_transfer_list.h \
display/window_file_list.cc \
display/window_file_list.h \
display/window_http_queue.cc \
display/window_http_queue.h \
display/window_input.cc \
display/window_input.h \
display/window_log.cc \
display/window_log.h \
display/window_log_complete.cc \
display/window_log_complete.h \
display/window_peer_list.cc \
display/window_peer_list.h \
display/window_statusbar.cc \
display/window_statusbar.h \
display/window_string_list.cc \
display/window_string_list.h \
display/window_text.cc \
display/window_text.h \
display/window_title.cc \
display/window_title.h \
display/window_tracker_list.cc \
display/window_tracker_list.h \
\
input/bindings.cc \
input/bindings.h \
input/input_event.cc \
input/input_event.h \
input/manager.cc \
input/manager.h \
input/path_input.cc \
input/path_input.h \
input/text_input.cc \
input/text_input.h \
\
rpc/command.h \
rpc/command.cc \
rpc/command_impl.h \
rpc/command_map.cc \
rpc/command_map.h \
rpc/command_scheduler.cc \
rpc/command_scheduler.h \
rpc/command_scheduler_item.cc \
rpc/command_scheduler_item.h \
rpc/exec_file.cc \
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 \
rpc/parse.h \
rpc/parse_commands.cc \
rpc/parse_commands.h \
rpc/parse_options.cc \
rpc/parse_options.h \
rpc/scgi.cc \
rpc/scgi.h \
rpc/scgi_task.cc \
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 \
ui/download_list.cc \
ui/download_list.h \
ui/element_base.h \
ui/element_base.cc \
ui/element_chunks_seen.cc \
ui/element_chunks_seen.h \
ui/element_download_list.cc \
ui/element_download_list.h \
ui/element_file_list.cc \
ui/element_file_list.h \
ui/element_log_complete.cc \
ui/element_log_complete.h \
ui/element_menu.cc \
ui/element_menu.h \
ui/element_peer_list.cc \
ui/element_peer_list.h \
ui/element_string_list.cc \
ui/element_string_list.h \
ui/element_text.cc \
ui/element_text.h \
ui/element_tracker_list.cc \
ui/element_tracker_list.h \
ui/element_transfer_list.cc \
ui/element_transfer_list.h \
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 \
utils/socket_fd.cc \
utils/socket_fd.h \
\
command_download.cc \
command_dynamic.cc \
command_events.cc \
@@ -18,6 +185,7 @@ libsub_root_a_SOURCES = \
command_helpers.h \
command_groups.cc \
command_local.cc \
command_logging.cc \
command_network.cc \
command_peer.cc \
command_throttle.cc \
@@ -34,23 +202,8 @@ libsub_root_a_SOURCES = \
signal_handler.h \
thread_base.cc \
thread_base.h \
thread_main.cc \
thread_main.h \
thread_worker.cc \
thread_worker.h
bin_PROGRAMS = rtorrent
rtorrent_LDADD = \
libsub_root.a \
ui/libsub_ui.a \
core/libsub_core.a \
display/libsub_display.a \
input/libsub_input.a \
rpc/libsub_rpc.a \
utils/libsub_utils.a
rtorrent_SOURCES = \
main.cc
INCLUDES = -I$(srcdir) -I$(top_srcdir)
AM_CPPFLAGS = -I$(srcdir) -I$(top_srcdir)
+105 -92
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.");
@@ -138,10 +105,10 @@ apply_d_change_link(core::Download* download, const torrent::Object::list_type&
switch (changeType) {
case 0:
if (symlink(target.c_str(), link.c_str()) == -1)
// control->core()->push_log("create_link failed: " + std::string(rak::error_number::current().c_str()));
// control->core()->push_log("create_link failed: " + std::string(rak::error_number::current().c_str()) + " to " + target);
; // Disabled.
if (symlink(target.c_str(), link.c_str()) == -1){
lt_log_print(torrent::LOG_TORRENT_WARN, "create_link failed: %s",
rak::error_number::current().c_str());
}
break;
case 1:
@@ -150,9 +117,10 @@ apply_d_change_link(core::Download* download, const torrent::Object::list_type&
rak::error_number::clear_global();
if (!fileStat.update_link(link) || !fileStat.is_link() ||
unlink(link.c_str()) == -1)
; // control->core()->push_log("delete_link failed: " + std::string(rak::error_number::current().c_str()));
unlink(link.c_str()) == -1){
lt_log_print(torrent::LOG_TORRENT_WARN, "delete_link failed: %s",
rak::error_number::current().c_str());
}
break;
}
default:
@@ -273,6 +241,41 @@ retrieve_d_custom_throw(core::Download* download, const std::string& key) {
}
}
torrent::Object
retrieve_d_custom_if_z(core::Download* download, const torrent::Object::list_type& args) {
torrent::Object::list_const_iterator itr = args.begin();
if (itr == args.end())
throw torrent::bencode_error("d.custom.if_z: Missing key argument.");
const std::string& key = (itr++)->as_string();
if (key.empty())
throw torrent::bencode_error("d.custom.if_z: Empty key argument.");
if (itr == args.end())
throw torrent::bencode_error("d.custom.if_z: Missing default argument.");
try {
const std::string& val = download->bencode()->get_key("rtorrent").get_key("custom").get_key_string(key);
return val.empty() ? itr->as_string() : val;
} catch (torrent::bencode_error& e) {
return itr->as_string();
}
}
torrent::Object
retrieve_d_custom_map(core::Download* download, bool keys_only, const torrent::Object::list_type& args) {
if (args.begin() != args.end())
throw torrent::bencode_error("d.custom.keys/items takes no arguments.");
torrent::Object result = keys_only ? torrent::Object::create_list() : torrent::Object::create_map();
torrent::Object::map_type& entries = download->bencode()->get_key("rtorrent").get_key("custom").as_map();
for (torrent::Object::map_type::const_iterator itr = entries.begin(), last = entries.end(); itr != last; itr++) {
if (keys_only) result.as_list().push_back(itr->first);
else result.as_map()[itr->first] = itr->second;
}
return result;
}
torrent::Object
retrieve_d_bitfield(core::Download* download) {
const torrent::Bitfield* bitField = download->download()->file_list()->bitfield();
@@ -283,30 +286,6 @@ retrieve_d_bitfield(core::Download* download) {
return torrent::Object(rak::transform_hex(bitField->begin(), bitField->end()));
}
// Just a helper function atm.
torrent::Object
cmd_d_initialize_logs(core::Download* download) {
download->info()->signal_network_log().connect(sigc::mem_fun(control->core(), &core::Manager::push_log_complete));
download->info()->signal_storage_error().connect(sigc::mem_fun(control->core(), &core::Manager::push_log_complete));
return torrent::Object();
}
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_CONNECTION_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;
@@ -316,7 +295,10 @@ apply_d_add_peer(core::Download* download, const std::string& arg) {
if (download->download()->info()->is_private())
throw torrent::input_error("Download is private.");
ret = std::sscanf(arg.c_str(), "%1023[^:]:%i%c", host, &port, &dummy);
ret = std::sscanf(arg.c_str(), "[%64[^]]]:%i%c", host, &port, &dummy);
if (ret < 1)
ret = std::sscanf(arg.c_str(), "%1023[^:]:%i%c", host, &port, &dummy);
if (ret == 1)
port = 6881;
@@ -326,7 +308,31 @@ 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_inet, 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
d_chunks_seen(core::Download* download) {
const uint8_t* seen = download->download()->chunks_seen();
if (seen == NULL)
return std::string();
uint32_t size = download->download()->file_list()->size_chunks();
std::string result;
result.resize(size * 2);
rak::transform_hex((const char*)seen, (const char*)seen + size, result.begin());
return result;
}
torrent::Object
@@ -362,9 +368,9 @@ f_multicall(core::Download* download, const torrent::Object::list_type& args) {
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
for (torrent::Object::list_const_iterator cItr = ++args.begin(), cLast = args.end(); cItr != args.end(); cItr++) {
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);
}
}
@@ -387,11 +393,11 @@ t_multicall(core::Download* download, const torrent::Object::list_type& args) {
for (int itr = 0, last = download->tracker_list()->size(); itr != last; itr++) {
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
for (torrent::Object::list_const_iterator cItr = ++args.begin(), cLast = args.end(); cItr != args.end(); cItr++) {
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);
}
}
@@ -415,7 +421,7 @@ p_multicall(core::Download* download, const torrent::Object::list_type& args) {
itr != last; itr++) {
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
for (torrent::Object::list_const_iterator cItr = ++args.begin(), cLast = args.end(); cItr != args.end(); cItr++) {
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);
@@ -547,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();
@@ -559,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
@@ -568,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();
}
@@ -583,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)
@@ -675,6 +678,7 @@ initialize_command_download() {
CMD2_DL ("d.is_pex_active", CMD2_ON_INFO(is_pex_active));
CMD2_DL ("d.is_partially_done", CMD2_ON_DATA(is_partially_done));
CMD2_DL ("d.is_not_partially_done", CMD2_ON_DATA(is_not_partially_done));
CMD2_DL ("d.is_meta", CMD2_ON_INFO(is_meta_download));
CMD2_DL_V ("d.resume", std::bind(&core::DownloadList::resume_default, control->core()->download_list(), std::placeholders::_1));
CMD2_DL_V ("d.pause", std::bind(&core::DownloadList::pause_default, control->core()->download_list(), std::placeholders::_1));
@@ -698,6 +702,9 @@ initialize_command_download() {
CMD2_DL_STRING("d.custom", std::bind(&retrieve_d_custom, std::placeholders::_1, std::placeholders::_2));
CMD2_DL_STRING("d.custom_throw", std::bind(&retrieve_d_custom_throw, std::placeholders::_1, std::placeholders::_2));
CMD2_DL_LIST ("d.custom.set", std::bind(&apply_d_custom, std::placeholders::_1, std::placeholders::_2));
CMD2_DL_LIST ("d.custom.if_z", std::bind(&retrieve_d_custom_if_z, std::placeholders::_1, std::placeholders::_2));
CMD2_DL_LIST ("d.custom.keys", std::bind(&retrieve_d_custom_map, std::placeholders::_1, true, std::placeholders::_2));
CMD2_DL_LIST ("d.custom.items", std::bind(&retrieve_d_custom_map, std::placeholders::_1, false, std::placeholders::_2));
CMD2_DL_VAR_STRING_PUBLIC("d.custom1", "rtorrent", "custom1");
CMD2_DL_VAR_STRING_PUBLIC("d.custom2", "rtorrent", "custom2");
@@ -814,21 +821,29 @@ initialize_command_download() {
CMD2_DL ("d.size_pex", CMD2_ON_DL(size_pex));
CMD2_DL ("d.max_size_pex", CMD2_ON_DL(max_size_pex));
CMD2_DL ("d.chunks_seen", std::bind(&d_chunks_seen, std::placeholders::_1));
CMD2_DL ("d.completed_bytes", CMD2_ON_FL(completed_bytes));
CMD2_DL ("d.completed_chunks", CMD2_ON_FL(completed_chunks));
CMD2_DL ("d.left_bytes", CMD2_ON_FL(left_bytes));
CMD2_DL ("d.wanted_chunks", CMD2_ON_DATA(wanted_chunks));
CMD2_DL_V ("d.tracker_announce", std::bind(&torrent::Download::manual_request, CMD2_BIND_DL, false));
// 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 ("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));
// TODO: Deprecate 'd.tracker_focus'.
CMD2_DL ("d.tracker_focus", std::bind(&core::Download::tracker_list_size, std::placeholders::_1));
CMD2_DL ("d.tracker_size", std::bind(&core::Download::tracker_list_size, std::placeholders::_1));
CMD2_DL_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));
@@ -849,12 +864,10 @@ initialize_command_download() {
// std::bind(&core::Download::main, std::placeholders::_1)),
// 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", 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 ("d.initialize_logs", std::bind(&cmd_d_initialize_logs, std::placeholders::_1));
CMD2_DL_LIST ("f.multicall", std::bind(&f_multicall, std::placeholders::_1, std::placeholders::_2));
CMD2_DL_LIST ("p.multicall", std::bind(&p_multicall, std::placeholders::_1, std::placeholders::_2));
CMD2_DL_LIST ("t.multicall", std::bind(&t_multicall, std::placeholders::_1, std::placeholders::_2));
+172 -135
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
@@ -37,11 +37,36 @@
#include "config.h"
#include <algorithm>
#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},
{"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) {
for (auto f : object_storage_flags)
if (f.first == flag)
return f.second;
throw torrent::input_error("unknown flag");
}
std::string
system_method_generate_command(torrent::Object::list_const_iterator first, torrent::Object::list_const_iterator last) {
@@ -83,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;
@@ -96,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);
@@ -108,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_local(torrent::raw_string::from_string(rawKey)) != control->object_storage()->end(0) ||
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;
@@ -137,6 +174,8 @@ system_method_insert_object(const torrent::Object::list_type& args, int flags) {
case rpc::object_storage::flag_function_type:
system_method_generate_command2(&value, itrArgs, args.end());
break;
case rpc::object_storage::flag_list_type:
break;
case rpc::object_storage::flag_multi_type:
break;
default:
@@ -148,67 +187,96 @@ system_method_insert_object(const torrent::Object::list_type& args, int flags) {
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;
rpc::object_storage::iterator obj_itr = control->object_storage()->insert_str(rawKey, value, flags);
if ((flags & rpc::object_storage::mask_type) == rpc::object_storage::flag_list_type) {
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(raw_key, valueList, flags);
} else {
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<0>(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<0>(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>(
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;
}
}
@@ -236,94 +304,32 @@ 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));
const std::string& options = itrArgs->as_string();
torrent::Object::list_type new_args;
new_args.push_back(raw_key);
if (options.find("private") != std::string::npos)
flags &= ~rpc::CommandMap::flag_public_xmlrpc;
if (options.find("const") != std::string::npos)
flags &= ~rpc::CommandMap::flag_modifiable;
if (options.find("multi") != std::string::npos) {
torrent::Object::list_type new_args;
new_args.push_back(rawKey);
if ((new_flags & rpc::object_storage::flag_function_type) ||
(new_flags & rpc::object_storage::flag_multi_type)) {
new_args.push_back(system_method_generate_command(++itrArgs, args.end()));
int new_flags = rpc::object_storage::flag_multi_type;
if (options.find("static") != std::string::npos)
new_flags |= rpc::object_storage::flag_static;
if (options.find("private") != std::string::npos)
new_flags |= rpc::object_storage::flag_private;
if (options.find("const") != std::string::npos)
new_flags |= rpc::object_storage::flag_constant;
if (options.find("rlookup") != std::string::npos)
new_flags |= rpc::object_storage::flag_rlookup;
return system_method_insert_object(new_args, new_flags);
} else if (options.find("simple") != std::string::npos) {
torrent::Object::list_type new_args;
new_args.push_back(rawKey);
new_args.push_back(system_method_generate_command(++itrArgs, args.end()));
int new_flags = rpc::object_storage::flag_function_type;
if (options.find("static") != std::string::npos)
new_flags |= rpc::object_storage::flag_static;
if (options.find("private") != std::string::npos)
new_flags |= rpc::object_storage::flag_private;
if (options.find("const") != std::string::npos)
new_flags |= rpc::object_storage::flag_constant;
return system_method_insert_object(new_args, new_flags);
} else if (options.find("value") != std::string::npos ||
options.find("bool") != std::string::npos ||
options.find("string") != std::string::npos ||
options.find("list") != std::string::npos ||
options.find("simple") != std::string::npos) {
torrent::Object::list_type new_args;
new_args.push_back(rawKey);
} else if ((new_flags & rpc::object_storage::flag_value_type) ||
(new_flags & rpc::object_storage::flag_bool_type) ||
(new_flags & rpc::object_storage::flag_string_type) ||
(new_flags & rpc::object_storage::flag_list_type)) {
if (++itrArgs != args.end())
new_args.insert(new_args.end(), itrArgs, args.end());
int new_flags;
if (options.find("value") != std::string::npos)
new_flags = rpc::object_storage::flag_value_type;
else if (options.find("bool") != std::string::npos)
new_flags = rpc::object_storage::flag_bool_type;
else if (options.find("string") != std::string::npos)
new_flags = rpc::object_storage::flag_string_type;
else if (options.find("list") != std::string::npos)
new_flags = rpc::object_storage::flag_list_type;
else if (options.find("simple") != std::string::npos)
new_flags = rpc::object_storage::flag_function_type;
else
throw torrent::input_error("No support for 'list' variable type.");
if (options.find("static") != std::string::npos)
new_flags |= rpc::object_storage::flag_static;
if (options.find("private") != std::string::npos)
new_flags |= rpc::object_storage::flag_private;
if (options.find("const") != std::string::npos)
new_flags |= rpc::object_storage::flag_constant;
return system_method_insert_object(new_args, new_flags);
} else {
// THROW.
throw torrent::input_error("No object type specified.");
}
return torrent::Object();
return system_method_insert_object(new_args, new_flags);
}
// method.erase <> {name}
@@ -354,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<0>(new_key, ""), create_new_key<0>(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();
}
@@ -365,11 +370,11 @@ system_method_set_function(const torrent::Object::list_type& args) {
if (args.empty())
throw torrent::input_error("Invalid argument count.");
rpc::object_storage::local_iterator itr =
control->object_storage()->find_local(torrent::raw_string::from_string(args.front().as_string()));
rpc::object_storage::iterator itr =
control->object_storage()->find_raw_string(torrent::raw_string::from_string(args.front().as_string()));
if (itr == control->object_storage()->end(0) || itr->second.flags & rpc::object_storage::flag_constant)
throw torrent::input_error("Command is not modifiable.");
if (itr == control->object_storage()->end() || itr->second.flags & rpc::object_storage::flag_constant)
throw torrent::input_error("Command is not modifiable.");
return control->object_storage()->set_str_function(args.front().as_string(),
system_method_generate_command(++args.begin(), args.end()));
@@ -381,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);
}
@@ -393,15 +398,15 @@ 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();
}
if (itrArgs->is_dict_key())
if (itrArgs->is_dict_key() || itrArgs->is_list())
control->object_storage()->set_str_multi_key_obj(key.c_str(), cmd_key, *itrArgs);
else
control->object_storage()->set_str_multi_key(key, cmd_key, system_method_generate_command(itrArgs, args.end()));
@@ -412,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);
@@ -422,16 +427,34 @@ system_method_list_keys(const torrent::Object::string_type& args) {
return rawResult;
}
torrent::Object
cmd_catch(rpc::target_type target, const torrent::Object& args) {
try {
return rpc::call_object(args, target);
} catch (torrent::input_error& e) {
lt_log_print(torrent::LOG_WARN, "Caught exception: '%s'.", e.what());
return torrent::Object();
}
}
#define CMD2_METHOD_INSERT(key, flags) \
CMD2_ANY_LIST(key, std::bind(&system_method_insert_object, std::placeholders::_2, flags));
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);
CMD2_ANY_LIST ("method.insert", std::bind(&system_method_insert, std::placeholders::_2));
CMD2_ANY_LIST ("method.insert.value", std::bind(&system_method_insert_object, std::placeholders::_2, rpc::object_storage::flag_value_type));
CMD2_ANY_LIST ("method.insert.bool", std::bind(&system_method_insert_object, std::placeholders::_2, rpc::object_storage::flag_bool_type));
CMD2_ANY_LIST ("method.insert.string", std::bind(&system_method_insert_object, std::placeholders::_2, rpc::object_storage::flag_string_type));
CMD2_ANY_LIST ("method.insert.list", std::bind(&system_method_insert_object, std::placeholders::_2, rpc::object_storage::flag_list_type));
CMD2_METHOD_INSERT("method.insert.simple", rpc::object_storage::flag_function_type);
CMD2_METHOD_INSERT("method.insert.c_simple", rpc::object_storage::flag_constant | rpc::object_storage::flag_function_type);
@@ -455,4 +478,18 @@ initialize_command_dynamic() {
CMD2_ANY_STRING ("method.rlookup", std::bind(&rpc::object_storage::rlookup_obj_list, control->object_storage(), std::placeholders::_2));
CMD2_ANY_STRING_V("method.rlookup.clear", std::bind(&rpc::object_storage::rlookup_clear, control->object_storage(), std::placeholders::_2));
CMD2_ANY ("catch", std::bind(&cmd_catch, std::placeholders::_1, std::placeholders::_2));
CMD2_ANY ("strings.choke_heuristics", std::bind(&torrent::option_list_strings, torrent::OPTION_CHOKE_HEURISTICS));
CMD2_ANY ("strings.choke_heuristics.upload", std::bind(&torrent::option_list_strings, torrent::OPTION_CHOKE_HEURISTICS_UPLOAD));
CMD2_ANY ("strings.choke_heuristics.download", std::bind(&torrent::option_list_strings, torrent::OPTION_CHOKE_HEURISTICS_DOWNLOAD));
CMD2_ANY ("strings.connection_type", std::bind(&torrent::option_list_strings, torrent::OPTION_CONNECTION_TYPE));
CMD2_ANY ("strings.encryption", std::bind(&torrent::option_list_strings, torrent::OPTION_ENCRYPTION));
CMD2_ANY ("strings.ip_filter", std::bind(&torrent::option_list_strings, torrent::OPTION_IP_FILTER));
CMD2_ANY ("strings.ip_tos", std::bind(&torrent::option_list_strings, torrent::OPTION_IP_TOS));
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
}
+78 -60
View File
@@ -1,50 +1,15 @@
// 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 <cstdio>
#include <rak/error_number.h>
#include <rak/file_stat.h>
#include <rak/path.h>
#include <rak/string_manip.h>
#include <sigc++/adaptors/bind.h>
#include <torrent/rate.h>
#include <torrent/hash_string.h>
#include <torrent/utils/log.h>
#include <torrent/utils/directory_events.h>
#include "core/download.h"
#include "core/download_list.h"
@@ -65,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]
@@ -102,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.");
@@ -215,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();
}
@@ -297,7 +261,7 @@ d_multicall(const torrent::Object::list_type& args) {
for (core::Download** vItr = dlist; vItr != dlist + dlist_size; vItr++) {
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
for (torrent::Object::list_const_iterator cItr = ++args.begin(), cLast = args.end(); cItr != args.end(); cItr++) {
for (torrent::Object::list_const_iterator cItr = ++args.begin(); cItr != args.end(); cItr++) {
const std::string& cmd = cItr->as_string();
row.push_back(rpc::parse_command(rpc::make_target(*vItr), cmd.c_str(), cmd.c_str() + cmd.size()).first);
}
@@ -307,16 +271,65 @@ d_multicall(const torrent::Object::list_type& args) {
}
torrent::Object
test_thread_locking() {
worker_thread->queue_item(&ThreadWorker::start_log_counter);
d_multicall_filtered(const torrent::Object::list_type& args) {
if (args.size() < 2)
throw torrent::input_error("d.multicall.filtered requires at least 2 arguments.");
torrent::Object::list_const_iterator arg = args.begin();
// Find the given view
core::ViewManager* viewManager = control->view_manager();
core::ViewManager::iterator viewItr = viewManager->find(arg->as_string().empty() ? "default" : arg->as_string());
if (viewItr == viewManager->end())
throw torrent::input_error("Could not find view '" + arg->as_string() + "'.");
// Make a filtered copy of the current item list
core::View::base_type dlist;
(*viewItr)->filter_by(*++arg, dlist);
// Generate result by iterating over all items
torrent::Object resultRaw = torrent::Object::create_list();
torrent::Object::list_type& result = resultRaw.as_list();
++arg; // skip to first command
for (core::View::iterator item = dlist.begin(); item != dlist.end(); ++item) {
// Add empty row to result
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
// Call the provided commands and assemble their results
for (torrent::Object::list_const_iterator command = arg; command != args.end(); command++) {
const std::string& cmdstr = command->as_string();
row.push_back(rpc::parse_command(rpc::make_target(*item), cmdstr.c_str(), cmdstr.c_str() + cmdstr.size()).first);
}
}
return resultRaw;
}
static void
call_watch_command(const std::string& command, const std::string& path) {
rpc::commands.call_catch(command.c_str(), rpc::make_target(), path);
}
torrent::Object
directory_watch_added(const torrent::Object::list_type& args) {
if (args.size() != 2)
throw torrent::input_error("Too few arguments.");
const std::string& path = args.front().as_string();
const std::string& command = args.back().as_string();
if (!control->directory_events()->open())
throw torrent::input_error("Could not open inotify:" + std::string(rak::error_number::current().c_str()));
control->directory_events()->notify_on(path.c_str(),
torrent::directory_events::flag_on_added | torrent::directory_events::flag_on_updated,
std::bind(&call_watch_command, command, std::placeholders::_1));
return torrent::Object();
}
void
initialize_command_events() {
CMD2_ANY("test.thread_locking", std::bind(&test_thread_locking));
CMD2_ANY_STRING ("on_ratio", std::bind(&apply_on_ratio, std::placeholders::_2));
CMD2_ANY ("start_tied", std::bind(&apply_start_tied));
@@ -339,9 +352,14 @@ initialize_command_events() {
CMD2_ANY_LIST ("load.raw_verbose", std::bind(&apply_load, std::placeholders::_2, core::Manager::create_raw_data));
CMD2_ANY_LIST ("load.raw_start", std::bind(&apply_load, std::placeholders::_2,
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));
CMD2_ANY_LIST ("d.multicall.filtered", std::bind(&d_multicall_filtered, std::placeholders::_2));
CMD2_ANY_LIST ("directory.watch.added", std::bind(&directory_watch_added, std::placeholders::_2));
}
+52 -52
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 <torrent/download/resource_manager.h>
#include <torrent/download/choke_group.h>
#include <torrent/download/choke_queue.h>
#include <torrent/utils/log.h>
#include <torrent/utils/option_strings.h>
#include "ui/root.h"
@@ -52,6 +17,9 @@
// For cg_d_group.
#include "core/download.h"
#define LT_LOG_SUBSYSTEM(log_fmt, ...) \
lt_log_print_subsystem(torrent::LOG_TORRENT_INFO, "choke_queue", log_fmt, __VA_ARGS__);
// A hack to allow testing of the new choke_group API without the
// working parts present.
#define USE_CHOKE_GROUP 0
@@ -101,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++)
@@ -122,6 +90,22 @@ apply_cg_insert(const std::string& arg) {
return torrent::Object();
}
torrent::Object
apply_cg_all_update_balance(bool is_up) {
LT_LOG_SUBSYSTEM("apply update balance: resource_manager is_up:%i", (int)is_up);
for (torrent::ResourceManager::group_iterator
itr = torrent::resource_manager()->group_begin(),
last = torrent::resource_manager()->group_end(); itr != last; itr++) {
if (is_up)
itr->up_queue()->balance();
else
itr->down_queue()->balance();
}
return torrent::Object();
}
//
// The hacked version:
//
@@ -137,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.");
@@ -170,18 +153,26 @@ 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);
}
int
cg_get_can_unchoke(torrent::choke_queue* cq) {
return cq->max_unchoked_signed() - (int)cq->size_unchoked();
}
torrent::Object
apply_cg_insert(const std::string& arg) {
int64_t dummy;
@@ -190,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());
@@ -205,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.");
@@ -214,6 +203,20 @@ apply_cg_index_of(const std::string& arg) {
return std::distance(cg_list_hack.begin(), itr);
}
torrent::Object
apply_cg_all_update_balance(bool is_up) {
LT_LOG_SUBSYSTEM("apply update balance: hack is_up:%i", (int)is_up);
for (auto itr : cg_list_hack) {
if (is_up)
itr->up_queue()->balance();
else
itr->down_queue()->balance();
}
return torrent::Object();
}
//
// End of choke group hack.
//
@@ -335,12 +338,6 @@ options.
void
initialize_command_groups() {
// Move somewhere else?
CMD2_ANY ("strings.choke_heuristics", std::bind(&torrent::option_list_strings, torrent::OPTION_CHOKE_HEURISTICS));
CMD2_ANY ("strings.choke_heuristics.upload", std::bind(&torrent::option_list_strings, torrent::OPTION_CHOKE_HEURISTICS_UPLOAD));
CMD2_ANY ("strings.choke_heuristics.download", std::bind(&torrent::option_list_strings, torrent::OPTION_CHOKE_HEURISTICS_DOWNLOAD));
CMD2_ANY ("strings.tracker_mode", std::bind(&torrent::option_list_strings, torrent::OPTION_TRACKER_MODE));
CMD2_ANY ("choke_group.list", std::bind(&apply_cg_list));
CMD2_ANY_STRING ("choke_group.insert", std::bind(&apply_cg_insert, std::placeholders::_2));
@@ -362,6 +359,9 @@ initialize_command_groups() {
std::bind(&torrent::choke_group::tracker_mode, CG_GROUP_AT())));
CMD2_ANY_LIST ("choke_group.tracker.mode.set", std::bind(&apply_cg_tracker_mode_set, std::placeholders::_2));
CMD2_ANY ("choke_group.all.up.update_balance", std::bind(&apply_cg_all_update_balance, true));
CMD2_ANY ("choke_group.all.down.update_balance", std::bind(&apply_cg_all_update_balance, false));
CMD2_ANY ("choke_group.up.rate", std::bind(&torrent::choke_group::up_rate, CG_GROUP_AT()));
CMD2_ANY ("choke_group.down.rate", std::bind(&torrent::choke_group::down_rate, CG_GROUP_AT()));
+2
View File
@@ -49,6 +49,7 @@ void initialize_command_file();
void initialize_command_ip();
void initialize_command_peer();
void initialize_command_local();
void initialize_command_logging();
void initialize_command_network();
void initialize_command_groups();
void initialize_command_throttle();
@@ -63,6 +64,7 @@ initialize_commands() {
initialize_command_network();
initialize_command_groups();
initialize_command_local();
initialize_command_logging();
initialize_command_ui();
initialize_command_download();
initialize_command_file();
+26 -71
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,68 +56,68 @@ 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); \
CMD2_ANY(key, std::bind(&rpc::object_storage::get, control->object_storage(), \
CMD2_ANY(key, std::bind(&rpc::object_storage::get, control->object_storage(), \
torrent::raw_string::from_c_str(key))); \
CMD2_ANY_VALUE(key ".set", std::bind(&rpc::object_storage::set_bool, control->object_storage(), \
torrent::raw_string::from_c_str(key), std::placeholders::_2));
#define CMD2_VAR_VALUE(key, value) \
control->object_storage()->insert_c_str(key, int64_t(value), rpc::object_storage::flag_value_type); \
CMD2_ANY(key, std::bind(&rpc::object_storage::get, control->object_storage(), \
CMD2_ANY(key, std::bind(&rpc::object_storage::get, control->object_storage(), \
torrent::raw_string::from_c_str(key))); \
CMD2_ANY_VALUE(key ".set", std::bind(&rpc::object_storage::set_value, control->object_storage(), \
torrent::raw_string::from_c_str(key), std::placeholders::_2));
#define CMD2_VAR_STRING(key, value) \
control->object_storage()->insert_c_str(key, value, rpc::object_storage::flag_string_type); \
CMD2_ANY(key, std::bind(&rpc::object_storage::get, control->object_storage(), \
CMD2_ANY(key, std::bind(&rpc::object_storage::get, control->object_storage(), \
torrent::raw_string::from_c_str(key))); \
CMD2_ANY_STRING(key ".set", std::bind(&rpc::object_storage::set_string, control->object_storage(), \
torrent::raw_string::from_c_str(key), std::placeholders::_2));
torrent::raw_string::from_c_str(key), std::placeholders::_2));
#define CMD2_VAR_C_STRING(key, value) \
control->object_storage()->insert_c_str(key, value, rpc::object_storage::flag_string_type); \
CMD2_ANY(key, std::bind(&rpc::object_storage::get, control->object_storage(), \
CMD2_ANY(key, std::bind(&rpc::object_storage::get, control->object_storage(), \
torrent::raw_string::from_c_str(key)));
#define CMD2_VAR_LIST(key) \
control->object_storage()->insert_c_str(key, torrent::Object::create_list(), rpc::object_storage::flag_list_type); \
CMD2_ANY(key, std::bind(&rpc::object_storage::get, control->object_storage(), \
CMD2_ANY(key, std::bind(&rpc::object_storage::get, control->object_storage(), \
torrent::raw_string::from_c_str(key))); \
CMD2_ANY_LIST(key ".set", std::bind(&rpc::object_storage::set_list, control->object_storage(), \
torrent::raw_string::from_c_str(key), std::placeholders::_2)); \
torrent::raw_string::from_c_str(key), std::placeholders::_2)); \
CMD2_ANY_VOID(key ".push_back", std::bind(&rpc::object_storage::list_push_back, control->object_storage(), \
torrent::raw_string::from_c_str(key), std::placeholders::_2));
torrent::raw_string::from_c_str(key), std::placeholders::_2));
#define CMD2_FUNC_SINGLE(key, cmds) \
CMD2_ANY(key, std::bind(&rpc::command_function_call, torrent::raw_string::from_c_str(cmds), \
#define CMD2_FUNC_SINGLE(key, cmds) \
CMD2_ANY(key, std::bind(&rpc::command_function_call_object, torrent::Object(torrent::raw_string::from_c_str(cmds)), \
std::placeholders::_1, std::placeholders::_2));
#define CMD2_REDIRECT(from_key, to_key) \
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<0>(from_key, ""), create_new_key<0>(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<0>(from_key, ""), create_new_key<0>(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:
@@ -175,7 +139,11 @@ struct object_convert_type<Functor, void> {
template <typename Arg1>
torrent::Object operator () (Arg1& arg1) { m_slot(arg1); return torrent::Object(); }
template <typename Arg1, typename Arg2>
torrent::Object operator () (const Arg1& arg1) { m_slot(arg1); return torrent::Object(); }
template <typename Arg1, typename Arg2>
torrent::Object operator () (Arg1& arg1, Arg2& arg2) { m_slot(arg1, arg2); return torrent::Object(); }
template <typename Arg1, typename Arg2>
torrent::Object operator () (const Arg1& arg1, const Arg2& arg2) { m_slot(arg1, arg2); return torrent::Object(); }
Functor m_slot;
};
@@ -184,17 +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;
}
#endif
+240 -76
View File
@@ -45,39 +45,14 @@
#include "globals.h"
#include "command_helpers.h"
void
ipv4_filter_parse(const char* address, int value) {
uint32_t ip_values[4] = { 0, 0, 0, 0 };
unsigned int block = rpc::ipv4_table::mask_bits;
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
char ip_dot;
int values_read;
if ((values_read = sscanf(address, "%u%1[.]%u%1[.]%u%1[.]%u/%u",
ip_values + 0, &ip_dot,
ip_values + 1, &ip_dot,
ip_values + 2, &ip_dot,
ip_values + 3,
&block)) < 2 ||
// Make sure the dot is included.
(values_read < 7 && values_read % 2) ||
ip_values[0] >= 256 ||
ip_values[1] >= 256 ||
ip_values[2] >= 256 ||
ip_values[3] >= 256 ||
block > rpc::ipv4_table::mask_bits)
throw torrent::input_error("Invalid address format.");
// E.g. '10.10.' will be '10.10.0.0/16'.
if (values_read < 7)
block = 8 * (values_read / 2);
torrent::PeerList::ipv4_filter()->insert((ip_values[0] << 24) + (ip_values[1] << 16) + (ip_values[2] << 8) + ip_values[3],
rpc::ipv4_table::mask_bits - block, value);
}
bool ipv4_range_parse(const char* address, uint32_t* address_start, uint32_t* address_end);
torrent::Object
apply_ip_tables_insert_table(const std::string& args) {
@@ -88,6 +63,17 @@ apply_ip_tables_insert_table(const std::string& args) {
return torrent::Object();
}
torrent::Object
apply_ip_tables_size_data(const std::string& args) {
rpc::ip_table_list::const_iterator itr = ip_tables.find(args);
if (itr != ip_tables.end())
throw torrent::input_error("IP table does not exist.");
uint32_t size = itr->table.sizeof_data();
return size;
}
torrent::Object
apply_ip_tables_get(const torrent::Object::list_type& args) {
if (args.size() != 2)
@@ -97,20 +83,21 @@ apply_ip_tables_get(const torrent::Object::list_type& args) {
const std::string& name = (args_itr++)->as_string();
const std::string& address = (args_itr++)->as_string();
// Move to a helper function, add support for addresses.
uint32_t ip_values[4];
if (sscanf(address.c_str(), "%u.%u.%u.%u",
ip_values + 0, ip_values + 1, ip_values + 2, ip_values + 3) != 4)
throw torrent::input_error("Invalid address format.");
uint32_t address_start;
uint32_t address_end;
rpc::ip_table_list::iterator table_itr = ip_tables.find(name);
if (table_itr == ip_tables.end())
throw torrent::input_error("Could not find ip table.");
return table_itr->table.at((ip_values[0] << 24) + (ip_values[1] << 16) + (ip_values[2] << 8) + ip_values[3]);
if (!ipv4_range_parse(address.c_str(), &address_start, &address_end))
throw torrent::input_error("Invalid address format.");
if(!table_itr->table.defined(address_start, address_end))
throw torrent::input_error("No value defined for specified IP(s).");
return table_itr->table.at(address_start, address_end);
}
torrent::Object
@@ -123,15 +110,6 @@ apply_ip_tables_add_address(const torrent::Object::list_type& args) {
const std::string& name = (args_itr++)->as_string();
const std::string& address = (args_itr++)->as_string();
const std::string& value_str = (args_itr++)->as_string();
// Move to a helper function, add support for addresses.
uint32_t ip_values[4];
unsigned int block = rpc::ipv4_table::mask_bits;
if (sscanf(address.c_str(), "%u.%u.%u.%u/%u",
ip_values + 0, ip_values + 1, ip_values + 2, ip_values + 3, &block) < 4 ||
block > rpc::ipv4_table::mask_bits)
throw torrent::input_error("Invalid address format.");
int value;
@@ -145,8 +123,13 @@ apply_ip_tables_add_address(const torrent::Object::list_type& args) {
if (table_itr == ip_tables.end())
throw torrent::input_error("Could not find ip table.");
table_itr->table.insert((ip_values[0] << 24) + (ip_values[1] << 16) + (ip_values[2] << 8) + ip_values[3],
rpc::ipv4_table::mask_bits - block, value);
uint32_t address_start;
uint32_t address_end;
if (ipv4_range_parse(address.c_str(), &address_start, &address_end))
table_itr->table.insert(address_start, address_end, value);
else
throw torrent::input_error("Invalid address format.");
return torrent::Object();
}
@@ -155,6 +138,158 @@ apply_ip_tables_add_address(const torrent::Object::list_type& args) {
// IPv4 filter functions:
//
///////////////////////////////////////////////////////////
// IPV4_RANGE_PARSE parses string into an ip range
//
// should be compatible with lines in p2p files
// everything in address before colon is ignored
//
// ip range can be single ip in which case start=end
// ip range can be cidr notation a.b.c.d/e
// ip range can be explicit range like in p2p line a.b.c.d-w.x.y.z
//
// returns false if line does not contain valid ip or ip range
// address_start and address_end will contain start and end ip
//
// addresses parsed are returned in host byte order
// to get network byte order call htonl(address)
///////////////////////////////////////////////////////////
bool
ipv4_range_parse(const char* address, uint32_t* address_start, uint32_t* address_end) {
// same length as buffer used to do reads so no worries about overflow
char address_copy[4096];
bool valid = false;
char address_start_str[20];
int address_start_index=0;
struct sockaddr_in sa_start;
*address_start=0;
*address_end=0;
// get rid of everything after '#' comments
// copy everything up to '#' to address_copy and work from there
while(address[address_start_index] != '#' && address[address_start_index] != '\r' &&
address[address_start_index] != '\n' && address[address_start_index] != '\0' &&
address_start_index < 4096 ) {
address_copy[address_start_index] = address[address_start_index];
address_start_index++;
}
address_copy[address_start_index] = '\0';
address_start_index=0;
// skip everything up to and including last ':' character and whitespace
const char* addr = strrchr(address_copy, ':');
addr = (addr == NULL) ? address_copy : addr + 1;
while(addr[0] == ' ' || addr[0] == '\t')
addr++;
while(((addr[0] >= '0' && addr[0] <= '9') || addr[0] == '.') && address_start_index < 19) {
address_start_str[address_start_index] = addr[0];
address_start_index++;
addr++;
}
address_start_str[address_start_index] = '\0';
if(strchr(addr, '-') != NULL) {
// explicit range
char address_end_str[20];
int address_end_index=0;
struct sockaddr_in sa_end;
while(addr[0] == '-' || addr[0] == ' ' || addr[0] == '\t')
addr++;
while(((addr[0] >= '0' && addr[0] <= '9') || addr[0] == '.') && address_end_index < 19) {
address_end_str[address_end_index] = addr[0];
address_end_index++;
addr++;
}
address_end_str[address_end_index] = '\0';
if(inet_pton(AF_INET, address_start_str, &(sa_start.sin_addr)) != 0 && inet_pton(AF_INET, address_end_str, &(sa_end.sin_addr)) != 0) {
*address_start = ntohl(sa_start.sin_addr.s_addr);
*address_end = ntohl(sa_end.sin_addr.s_addr);
if(*address_start <= *address_end)
valid=true;
}
} else if(strchr(addr, '/') != NULL) {
// cidr range
char mask_bits_str[20];
int mask_bits_index=0;
uint32_t mask_bits;
while(addr[0] == '/' || addr[0] == ' ' || addr[0] == '\t')
addr++;
while( (addr[0] >= '0' && addr[0] <= '9') && mask_bits_index < 19) {
mask_bits_str[mask_bits_index] = addr[0];
mask_bits_index++;
addr++;
}
mask_bits_str[mask_bits_index] = '\0';
if(inet_pton(AF_INET, address_start_str, &(sa_start.sin_addr)) != 0 && sscanf(mask_bits_str, "%u", &mask_bits) != 0) {
if(mask_bits <=32) {
uint32_t ip=ntohl(sa_start.sin_addr.s_addr);
uint32_t mask=0;
uint32_t end_mask=0;
mask = (~mask) << (32-mask_bits);
*address_start = ip & mask;
end_mask = (~end_mask) >> mask_bits;
*address_end = (ip & mask) | end_mask;
valid=true;
}
}
} else {
// single ip
if(inet_pton(AF_INET, address_start_str, &(sa_start.sin_addr)) != 0) {
*address_start = ntohl(sa_start.sin_addr.s_addr);
*address_end = *address_start;
valid=true;
}
}
return valid;
}
///////////////////////////////////////////////////////////
// IPV4_FILTER_PARSE
//
// should now be compatible with lines in p2p files
//
// addresses in table MUST be in host byte order
// ntohl is called after parsing ip address(es)
///////////////////////////////////////////////////////////
void
ipv4_filter_parse(const char* address, int value) {
uint32_t address_start;
uint32_t address_end;
if (ipv4_range_parse(address, &address_start, &address_end) ) {
torrent::PeerList::ipv4_filter()->insert(address_start, address_end, value);
char start_str[INET_ADDRSTRLEN];
char end_str[INET_ADDRSTRLEN];
uint32_t net_start = htonl(address_start);
uint32_t net_end = htonl(address_end);
inet_ntop(AF_INET, &net_start, start_str, INET_ADDRSTRLEN);
inet_ntop(AF_INET, &net_end, end_str, INET_ADDRSTRLEN);
lt_log_print(torrent::LOG_CONNECTION_FILTER, "Adding ip filter for %s-%s.", start_str, end_str);
}
}
torrent::Object
apply_ipv4_filter_size_data() {
return torrent::PeerList::ipv4_filter()->sizeof_data();
@@ -162,14 +297,16 @@ apply_ipv4_filter_size_data() {
torrent::Object
apply_ipv4_filter_get(const std::string& args) {
// Move to a helper function, add support for addresses.
uint32_t ip_values[4];
uint32_t address_start;
uint32_t address_end;
if (sscanf(args.c_str(), "%u.%u.%u.%u",
ip_values + 0, ip_values + 1, ip_values + 2, ip_values + 3) != 4)
if (!ipv4_range_parse(args.c_str(), &address_start, &address_end))
throw torrent::input_error("Invalid address format.");
return torrent::PeerList::ipv4_filter()->at((ip_values[0] << 24) + (ip_values[1] << 16) + (ip_values[2] << 8) + ip_values[3]);
if(!torrent::PeerList::ipv4_filter()->defined(address_start, address_end))
throw torrent::input_error("No value defined for specified IP(s).");
return torrent::PeerList::ipv4_filter()->at(address_start, address_end);
}
torrent::Object
@@ -187,30 +324,23 @@ apply_ipv4_filter_load(const torrent::Object::list_type& args) {
if (args.size() != 2)
throw torrent::input_error("Incorrect number of arguments.");
torrent::Object::list_const_iterator args_itr = args.begin();
std::string filename = args.front().as_string();
std::string value_name = args.back().as_string();
int value = torrent::option_find_string(torrent::OPTION_IP_FILTER, value_name.c_str());
std::fstream file(rak::path_expand(args.front().as_string()).c_str(), std::ios::in);
std::fstream file(rak::path_expand(filename).c_str(), std::ios::in);
if (!file.is_open())
throw torrent::input_error("Could not open ip filter file: " + args.front().as_string());
throw torrent::input_error("Could not open ip filter file: " + filename);
int value = torrent::option_find_string(torrent::OPTION_IP_FILTER, args.back().as_string().c_str());
char buffer[4096];
unsigned int lineNumber = 0;
char buffer[4096];
try {
while (file.good() && !file.getline(buffer, 4096).fail()) {
if (file.gcount() == 0)
throw torrent::internal_error("parse_command_file(...) file.gcount() == 0.");
int lineLength = file.gcount() - 1;
// In case we are at the end of the file and the last character is
// not a line feed, we'll just increase the read character count so
// that the last would also be included in option line.
if (file.eof() && file.get() != '\n')
lineLength++;
lineNumber++;
if (buffer[0] == '\0' || buffer[0] == '#')
@@ -220,28 +350,62 @@ apply_ipv4_filter_load(const torrent::Object::list_type& args) {
}
} catch (torrent::input_error& e) {
snprintf(buffer, 2048, "Error in ip filter file: %s:%u: %s", args.front().as_string().c_str(), lineNumber, e.what());
snprintf(buffer, 2048, "Error in ip filter file: %s:%u: %s", filename.c_str(), lineNumber, e.what());
throw torrent::input_error(buffer);
}
lt_log_print(torrent::LOG_CONNECTION_INFO, "Loaded %u %s address blocks (%u kb in-memory) from '%s'.",
lt_log_print(torrent::LOG_CONNECTION_FILTER, "loaded %u %s address blocks (%u kb in-memory) from '%s'",
lineNumber,
args.back().as_string().c_str(),
value_name.c_str(),
torrent::PeerList::ipv4_filter()->sizeof_data() / 1024,
args.front().as_string().c_str());
filename.c_str());
return torrent::Object();
}
torrent::Object
apply_ipv4_filter_dump() {
torrent::Object raw_result = torrent::Object::create_list();
torrent::Object::list_type& result = raw_result.as_list();
torrent::ipv4_table::range_map_type range_map = torrent::PeerList::ipv4_filter()->range_map;
torrent::ipv4_table::range_map_type::iterator iter = range_map.begin();
while(iter != range_map.end()) {
char buffer[64];
uint32_t address_start = iter->first;
uint32_t address_end = (iter->second).first;
int value = (iter->second).second;
char start_str[INET_ADDRSTRLEN];
char end_str[INET_ADDRSTRLEN];
uint32_t net_start = htonl(address_start);
uint32_t net_end = htonl(address_end);
inet_ntop(AF_INET, &net_start, start_str, INET_ADDRSTRLEN);
inet_ntop(AF_INET, &net_end, end_str, INET_ADDRSTRLEN);
snprintf(buffer, 64, "%s-%s %s", start_str, end_str, torrent::option_as_string(torrent::OPTION_IP_FILTER, value));
result.push_back((std::string)buffer);
iter++;
}
return raw_result;
}
void
initialize_command_ip() {
CMD2_ANY_STRING ("ip_tables.insert_table", std::bind(&apply_ip_tables_insert_table, std::placeholders::_2));
CMD2_ANY_LIST ("ip_tables.get", std::bind(&apply_ip_tables_get, std::placeholders::_2));
CMD2_ANY_LIST ("ip_tables.add_address", std::bind(&apply_ip_tables_add_address, std::placeholders::_2));
CMD2_ANY_STRING ("ip_tables.insert_table", std::bind(&apply_ip_tables_insert_table, std::placeholders::_2));
CMD2_ANY_STRING ("ip_tables.size_data", std::bind(&apply_ip_tables_size_data, std::placeholders::_2));
CMD2_ANY_LIST ("ip_tables.get", std::bind(&apply_ip_tables_get, std::placeholders::_2));
CMD2_ANY_LIST ("ip_tables.add_address", std::bind(&apply_ip_tables_add_address, std::placeholders::_2));
CMD2_ANY ("ipv4_filter.size_data", std::bind(&apply_ipv4_filter_size_data));
CMD2_ANY_STRING ("ipv4_filter.get", std::bind(&apply_ipv4_filter_get, std::placeholders::_2));
CMD2_ANY_LIST ("ipv4_filter.add_address", std::bind(&apply_ipv4_filter_add_address, std::placeholders::_2));
CMD2_ANY_LIST ("ipv4_filter.load", std::bind(&apply_ipv4_filter_load, std::placeholders::_2));
CMD2_ANY_LIST ("ipv4_filter.dump", std::bind(&apply_ipv4_filter_dump));
}
+38 -150
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>
@@ -48,8 +12,6 @@
#include <torrent/chunk_manager.h>
#include <torrent/data/file_manager.h>
#include <torrent/data/chunk_utils.h>
#include <torrent/utils/log.h>
#include <torrent/utils/log_files.h>
#include <torrent/utils/option_strings.h>
#include "core/download.h"
@@ -62,6 +24,7 @@
#include "utils/file_status_cache.h"
#include "globals.h"
#include "rpc/lua.h"
#include "control.h"
#include "command_helpers.h"
@@ -81,60 +44,12 @@ apply_pieces_stats_total_size() {
}
torrent::Object
apply_log(const torrent::Object::string_type& arg, int logType) {
if (rpc::execFile.log_fd() != -1) {
switch (logType) {
case 0: ::close(rpc::execFile.log_fd()); rpc::execFile.set_log_fd(-1); break;
case 1:
// if (control->scgi()) {
// ::close(control->scgi()->log_fd());
// control->scgi()->set_log_fd(-1);
// }
break;
default: break;
}
}
system_env(const torrent::Object::string_type& arg) {
if (arg.empty())
throw torrent::input_error("system.env: Missing variable name.");
if (!arg.empty()) {
int logFd = open(rak::path_expand(arg).c_str(), O_WRONLY | O_APPEND | O_CREAT, 0644);
if (logFd < 0)
throw torrent::input_error("Could not open execute log file.");
switch (logType) {
case 0: rpc::execFile.set_log_fd(logFd); break;
// case 1: if (control->scgi()) control->scgi()->set_log_fd(logFd); break;
default: break;
}
control->core()->push_log("Opened log file.");
} else {
control->core()->push_log("Closed log file.");
}
return torrent::Object();
}
torrent::Object
apply_log_libtorrent(const torrent::Object::list_type& args) {
if (args.empty() || args.size() > 2)
throw torrent::input_error("Invalid argument count.");
torrent::log_file* log_file = torrent::find_log_file(args.front().as_string().c_str());
if (log_file == NULL)
throw torrent::input_error("Invalid log name.");
if (args.size() == 1) {
log_file->close();
return torrent::Object();
}
if (!log_file->open_file(args.back().as_string().c_str()))
throw torrent::input_error("Could not open log file.");
return torrent::Object();
char* val = getenv(arg.c_str());
return std::string(val ? val : "");
}
torrent::Object
@@ -185,7 +100,7 @@ check_name(const std::string& str) {
throw torrent::input_error("Non-alphanumeric characters found.");
return str;
}
}
torrent::Object
group_insert(const torrent::Object::list_type& args) {
@@ -208,7 +123,7 @@ group_insert(const torrent::Object::list_type& args) {
if (rpc::call_command_value("method.use_intermediate") == 1) {
// Deprecated in 0.7.0:
CMD2_REDIRECT_GENERIC_STR("group." + name + ".view", "group2." + name + ".view");
CMD2_REDIRECT_GENERIC_STR("group." + name + ".view.set", "group2." + name + ".view.set");
CMD2_REDIRECT_GENERIC_STR("group." + name + ".ratio.min", "group2." + name + ".ratio.min");
@@ -220,7 +135,7 @@ group_insert(const torrent::Object::list_type& args) {
} if (rpc::call_command_value("method.use_intermediate") == 2) {
// Deprecated in 0.7.0:
CMD2_REDIRECT_GENERIC_STR_NO_EXPORT("group." + name + ".view", "group2." + name + ".view");
CMD2_REDIRECT_GENERIC_STR_NO_EXPORT("group." + name + ".view.set", "group2." + name + ".view.set");
CMD2_REDIRECT_GENERIC_STR_NO_EXPORT("group." + name + ".ratio.min", "group2." + name + ".ratio.min");
@@ -234,27 +149,6 @@ group_insert(const torrent::Object::list_type& args) {
return name;
}
torrent::Object
log_vmmap_dump(const std::string& str) {
core::DownloadList* d_list = control->core()->download_list();
std::vector<torrent::vm_mapping> all_mappings;
for (core::DownloadList::iterator itr = d_list->begin(), last = d_list->end(); itr != last; itr++) {
std::vector<torrent::vm_mapping> tmp_mappings = torrent::chunk_list_mapping((*itr)->download());
all_mappings.insert(all_mappings.end(), tmp_mappings.begin(), tmp_mappings.end());
}
FILE* log_file = fopen(str.c_str(), "w");
for (std::vector<torrent::vm_mapping>::iterator itr = all_mappings.begin(), last = all_mappings.end(); itr != last; itr++) {
fprintf(log_file, "%8p-%8p [%5llxk]\n", itr->ptr, (char*)itr->ptr + itr->length, (long long unsigned int)(itr->length / 1024));
}
fclose(log_file);
return torrent::Object();
}
static const int file_print_use_space = 0x1;
static const int file_print_delim_space = 0x2;
@@ -263,10 +157,10 @@ file_print_list(torrent::Object::list_const_iterator first, torrent::Object::lis
while (first != last) {
switch (first->type()) {
case torrent::Object::TYPE_STRING:
fprintf(output, " %s" + !(flags & file_print_use_space), first->as_string().c_str());
fprintf(output, (const char*)" %s" + !(flags & file_print_use_space), first->as_string().c_str());
break;
case torrent::Object::TYPE_VALUE:
fprintf(output, " %lli" + !(flags & file_print_use_space), first->as_value());
fprintf(output, (const char*)" %" PRIi64 + !(flags & file_print_use_space), first->as_value());
break;
case torrent::Object::TYPE_LIST:
file_print_list(first->as_list().begin(), first->as_list().end(), output, 0);
@@ -286,9 +180,9 @@ torrent::Object
cmd_file_append(const torrent::Object::list_type& args) {
if (args.empty())
throw torrent::input_error("Invalid number of arguments.");
FILE* output = fopen(args.front().as_string().c_str(), "a");
if (output == NULL)
throw torrent::input_error("Could not append to file '" + args.front().as_string() + "': " + rak::error_number::current().c_str());
@@ -299,60 +193,55 @@ cmd_file_append(const torrent::Object::list_type& args) {
return torrent::Object();
}
torrent::Object
apply_log_open_file(const torrent::Object::list_type& args) {
if (args.size() != 2)
throw torrent::input_error("Invalid number of arguments.");
torrent::log_open_file_output(args.front().as_string().c_str(), args.back().as_string().c_str());
return torrent::Object();
}
torrent::Object
apply_log_add_output(const torrent::Object::list_type& args) {
if (args.size() != 2)
throw torrent::input_error("Invalid number of arguments.");
torrent::log_add_group_output(torrent::option_find_string(torrent::OPTION_LOG_GROUP, args.front().as_string().c_str()),
args.back().as_string().c_str());
return torrent::Object();
}
void
initialize_command_local() {
torrent::ChunkManager* chunkManager = torrent::chunk_manager();
torrent::FileManager* fileManager = torrent::file_manager();
core::DownloadList* dList = control->core()->download_list();
core::DownloadStore* dStore = control->core()->download_store();
torrent::ChunkManager* chunkManager = torrent::chunk_manager();
torrent::FileManager* fileManager = torrent::file_manager();
CMD2_ANY ("system.hostname", std::bind(&system_hostname));
CMD2_ANY ("system.pid", std::bind(&getpid));
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)64 << 30);
CMD2_VAR_VALUE ("system.file.max_size", (int64_t)512 << 30);
CMD2_VAR_VALUE ("system.file.split_size", -1);
CMD2_VAR_STRING ("system.file.split_suffix", ".part");
CMD2_ANY ("system.file_status_cache.size", std::bind(&utils::FileStatusCache::size,
(utils::FileStatusCache::base_type*)control->core()->file_status_cache()));
(utils::FileStatusCache::base_type*)control->core()->file_status_cache()));
CMD2_ANY_V ("system.file_status_cache.prune", std::bind(&utils::FileStatusCache::prune, control->core()->file_status_cache()));
CMD2_VAR_BOOL ("file.prioritize_toc", 0);
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));
CMD2_ANY_STRING ("system.env", std::bind(&system_env, std::placeholders::_2));
CMD2_ANY ("system.time", std::bind(&rak::timer::seconds, &cachedTime));
CMD2_ANY ("system.time_seconds", std::bind(&rak::timer::current_seconds));
CMD2_ANY ("system.time_usec", std::bind(&rak::timer::current_usec));
CMD2_ANY_VALUE_V ("system.umask.set", std::bind(&umask, std::placeholders::_2));
CMD2_VAR_BOOL ("system.daemon", false);
CMD2_ANY_V ("system.shutdown.normal", std::bind(&Control::receive_normal_shutdown, control));
CMD2_ANY_V ("system.shutdown.quick", std::bind(&Control::receive_quick_shutdown, control));
CMD2_REDIRECT_GENERIC_NO_EXPORT("system.shutdown", "system.shutdown.normal");
CMD2_ANY ("system.cwd", std::bind(&system_get_cwd));
CMD2_ANY_STRING ("system.cwd.set", std::bind(&system_set_cwd, std::placeholders::_2));
@@ -396,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));
@@ -411,14 +307,6 @@ initialize_command_local() {
CMD2_EXECUTE ("execute.capture", rpc::ExecFile::flag_throw | rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_capture);
CMD2_EXECUTE ("execute.capture_nothrow", rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_capture);
CMD2_ANY_LIST ("log.open_file", std::bind(&apply_log_open_file, std::placeholders::_2));
CMD2_ANY_LIST ("log.add_output", std::bind(&apply_log_add_output, std::placeholders::_2));
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_LIST ("log.libtorrent", std::bind(&apply_log_libtorrent, std::placeholders::_2));
CMD2_ANY_LIST ("file.append", std::bind(&cmd_file_append, std::placeholders::_2));
// TODO: Convert to new command types:
+147
View File
@@ -0,0 +1,147 @@
#include "config.h"
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <torrent/data/chunk_utils.h>
#include <torrent/object.h>
#include <torrent/utils/log.h>
#include <torrent/utils/option_strings.h>
#include "core/download.h"
#include "core/download_list.h"
#include "core/manager.h"
#include "rak/path.h"
#include "rpc/parse_commands.h"
#include "globals.h"
#include "control.h"
#include "command_helpers.h"
static const int log_flag_use_gz = 0x1;
static const int log_flag_append_pid = 0x2;
static const int log_flag_append_file = 0x4;
void
log_add_group_output_str(const char* group_name, const char* output_id) {
int log_group = torrent::option_find_string(torrent::OPTION_LOG_GROUP, group_name);
torrent::log_add_group_output(log_group, output_id);
}
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();
std::string file_name = rak::path_expand((itr++)->as_string());
if ((output_flags & log_flag_append_pid)) {
char buffer[32];
snprintf(buffer, 32, ".%li", (long)getpid());
file_name += buffer;
}
bool append = (output_flags & log_flag_append_file);
if ((output_flags & log_flag_use_gz))
torrent::log_open_gz_file_output(output_id.c_str(), file_name.c_str(), append);
else
torrent::log_open_file_output(output_id.c_str(), file_name.c_str(), append);
while (itr != args.end())
log_add_group_output_str((itr++)->as_string().c_str(), output_id.c_str());
return torrent::Object();
}
torrent::Object
apply_log_add_output(const torrent::Object::list_type& args) {
if (args.size() != 2)
throw torrent::input_error("Invalid number of arguments.");
log_add_group_output_str(args.front().as_string().c_str(),
args.back().as_string().c_str());
return torrent::Object();
}
// TODO: Deprecated.
torrent::Object
apply_log(const torrent::Object::string_type& arg, int logType) {
if (rpc::execFile.log_fd() != -1) {
switch (logType) {
case 0: ::close(rpc::execFile.log_fd()); rpc::execFile.set_log_fd(-1); break;
case 1:
// if (control->scgi()) {
// ::close(control->scgi()->log_fd());
// control->scgi()->set_log_fd(-1);
// }
break;
default: break;
}
}
if (!arg.empty()) {
int logFd = open(rak::path_expand(arg).c_str(), O_WRONLY | O_APPEND | O_CREAT, 0644);
if (logFd < 0)
throw torrent::input_error("Could not open execute log file.");
switch (logType) {
case 0: rpc::execFile.set_log_fd(logFd); break;
// case 1: if (control->scgi()) control->scgi()->set_log_fd(logFd); break;
default: break;
}
control->core()->push_log("Opened log file.");
} else {
control->core()->push_log("Closed log file.");
}
return torrent::Object();
}
torrent::Object
log_vmmap_dump(const std::string& str) {
core::DownloadList* d_list = control->core()->download_list();
std::vector<torrent::vm_mapping> all_mappings;
for (core::DownloadList::iterator itr = d_list->begin(), last = d_list->end(); itr != last; itr++) {
std::vector<torrent::vm_mapping> tmp_mappings = torrent::chunk_list_mapping((*itr)->download());
all_mappings.insert(all_mappings.end(), tmp_mappings.begin(), tmp_mappings.end());
}
FILE* log_file = fopen(str.c_str(), "w");
for (std::vector<torrent::vm_mapping>::iterator itr = all_mappings.begin(), last = all_mappings.end(); itr != last; itr++) {
fprintf(log_file, "%8p-%8p [%5llxk]\n", itr->ptr, (char*)itr->ptr + itr->length, (long long unsigned int)(itr->length / 1024));
}
fclose(log_file);
return torrent::Object();
}
void
initialize_command_logging() {
CMD2_ANY_LIST ("log.open_file", std::bind(&apply_log_open, 0, std::placeholders::_2));
CMD2_ANY_LIST ("log.open_gz_file", std::bind(&apply_log_open, log_flag_use_gz, std::placeholders::_2));
CMD2_ANY_LIST ("log.open_file_pid", std::bind(&apply_log_open, log_flag_append_pid, std::placeholders::_2));
CMD2_ANY_LIST ("log.open_gz_file_pid", std::bind(&apply_log_open, log_flag_append_pid | log_flag_use_gz, std::placeholders::_2));
CMD2_ANY_LIST ("log.append_file", std::bind(&apply_log_open, log_flag_append_file, std::placeholders::_2));
CMD2_ANY_LIST ("log.append_gz_file", std::bind(&apply_log_open, log_flag_append_file, std::placeholders::_2));
CMD2_ANY_STRING_V("log.close", std::bind(&torrent::log_close_output_str, std::placeholders::_2));
CMD2_ANY_LIST ("log.add_output", std::bind(&apply_log_add_output, std::placeholders::_2));
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.rpc", std::bind(&ThreadWorker::set_rpc_log, worker_thread, std::placeholders::_2));
CMD2_REDIRECT ("log.xmlrpc", "log.rpc"); // For backwards compatibility
}
+80 -122
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>
@@ -92,55 +56,46 @@ apply_tos(const torrent::Object::string_type& arg) {
return torrent::Object();
}
torrent::Object apply_hash_read_ahead(int arg) { torrent::set_hash_read_ahead(arg << 20); return torrent::Object(); }
torrent::Object apply_hash_interval(int arg) { torrent::set_hash_interval(arg * 1000); return torrent::Object(); }
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.set_slot_find_download(rak::mem_fn(control->core()->download_list(), &core::DownloadList::find_hex_ptr));
rpc::xmlrpc.set_slot_find_file(rak::ptr_fn(&xmlrpc_find_file));
rpc::xmlrpc.set_slot_find_tracker(rak::ptr_fn(&xmlrpc_find_tracker));
rpc::xmlrpc.set_slot_find_peer(rak::ptr_fn(&xmlrpc_find_peer));
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_INFO, "XMLRPC initialized with %u functions.", count);
lt_log_print(torrent::LOG_RPC_EVENTS, "RPC initialized with %u functions.", count);
}
torrent::Object
@@ -148,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;
@@ -169,15 +123,16 @@ apply_scgi(const std::string& arg, int type) {
sa.sa_inet()->clear();
saPtr = &sa;
lt_log_print(torrent::LOG_RPC_WARN, "The SCGI socket has not been bound to any address and likely poses a security risk.");
lt_log_print(torrent::LOG_RPC_EVENTS, "SCGI socket is open to any address and is a security risk");
} else if (std::sscanf(arg.c_str(), "%1023[^:]:%i%c", address, &port, &dummy) == 2) {
if ((err = rak::address_info::get_address_info(address, PF_INET, SOCK_STREAM, &ai)) != 0)
} else if (std::sscanf(arg.c_str(), "%1023[^:]:%i%c", address, &port, &dummy) == 2 ||
std::sscanf(arg.c_str(), "[%64[^]]]:%i%c", address, &port, &dummy) == 2) { // [xx::xx]:port format
if ((err = rak::address_info::get_address_info(address,PF_UNSPEC, SOCK_STREAM, &ai)) != 0)
throw torrent::input_error("Could not bind address: " + std::string(rak::address_info::strerror(err)) + ".");
saPtr = ai->address();
lt_log_print(torrent::LOG_RPC_WARN, "The SCGI socket is bound to a specific network device yet may still pose a security risk, consider using 'scgi_local'.");
lt_log_print(torrent::LOG_RPC_EVENTS, "SCGI socket is bound to an address and might be a security risk");
} else {
throw torrent::input_error("Could not parse address.");
@@ -226,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();
}
@@ -236,14 +191,6 @@ initialize_command_network() {
torrent::FileManager* fileManager = torrent::file_manager();
core::CurlStack* httpStack = control->core()->http_stack();
CMD2_ANY ("strings.connection_type", std::bind(&torrent::option_list_strings, torrent::OPTION_CONNECTION_TYPE));
CMD2_ANY ("strings.encryption", std::bind(&torrent::option_list_strings, torrent::OPTION_ENCRYPTION));
CMD2_ANY ("strings.ip_filter", std::bind(&torrent::option_list_strings, torrent::OPTION_IP_FILTER));
CMD2_ANY ("strings.ip_tos", std::bind(&torrent::option_list_strings, torrent::OPTION_IP_TOS));
CMD2_VAR_BOOL ("log.handshake", false);
// CMD2_ANY_STRING ("encoding_list", std::bind(&apply_encoding_list, std::placeholders::_2));
CMD2_ANY_STRING ("encoding.add", std::bind(&apply_encoding_list, std::placeholders::_2));
// Isn't port_open used?
@@ -251,7 +198,9 @@ initialize_command_network() {
CMD2_VAR_BOOL ("network.port_random", true);
CMD2_VAR_STRING ("network.port_range", "6881-6999");
CMD2_ANY ("network.listen.port", std::bind(&torrent::ConnectionManager::listen_port, cm));
CMD2_ANY ("network.listen.port", std::bind(&torrent::ConnectionManager::listen_port, cm));
CMD2_ANY ("network.listen.backlog", std::bind(&torrent::ConnectionManager::listen_backlog, cm));
CMD2_ANY_VALUE_V ("network.listen.backlog.set", std::bind(&torrent::ConnectionManager::set_listen_backlog, cm, std::placeholders::_2));
CMD2_VAR_BOOL ("protocol.pex", true);
CMD2_ANY_LIST ("protocol.encryption.set", std::bind(&apply_encryption, std::placeholders::_2));
@@ -264,18 +213,21 @@ initialize_command_network() {
CMD2_VAR_STRING ("protocol.choke_heuristics.down.leech", "download_leech");
CMD2_VAR_STRING ("protocol.choke_heuristics.down.seed", "download_leech");
CMD2_ANY ("network.http.capath", std::bind(&core::CurlStack::http_capath, httpStack));
CMD2_ANY_STRING_V("network.http.capath.set", std::bind(&core::CurlStack::set_http_capath, httpStack, std::placeholders::_2));
CMD2_ANY ("network.http.cacert", std::bind(&core::CurlStack::http_cacert, httpStack));
CMD2_ANY_STRING_V("network.http.cacert.set", std::bind(&core::CurlStack::set_http_cacert, httpStack, std::placeholders::_2));
CMD2_ANY ("network.http.proxy_address", std::bind(&core::CurlStack::http_proxy, httpStack));
CMD2_ANY_STRING_V("network.http.proxy_address.set", std::bind(&core::CurlStack::set_http_proxy, httpStack, std::placeholders::_2));
CMD2_ANY ("network.http.max_open", std::bind(&core::CurlStack::max_active, httpStack));
CMD2_ANY_VALUE_V ("network.http.max_open.set", std::bind(&core::CurlStack::set_max_active, httpStack, std::placeholders::_2));
CMD2_ANY ("network.http.ssl_verify_peer", std::bind(&core::CurlStack::ssl_verify_peer, httpStack));
CMD2_ANY_VALUE_V ("network.http.ssl_verify_peer.set", std::bind(&core::CurlStack::set_ssl_verify_peer, httpStack, std::placeholders::_2));
CMD2_ANY ("network.http.capath", std::bind(&core::CurlStack::http_capath, httpStack));
CMD2_ANY_STRING_V("network.http.capath.set", std::bind(&core::CurlStack::set_http_capath, httpStack, std::placeholders::_2));
CMD2_ANY ("network.http.dns_cache_timeout", std::bind(&core::CurlStack::dns_timeout, httpStack));
CMD2_ANY_VALUE_V ("network.http.dns_cache_timeout.set", std::bind(&core::CurlStack::set_dns_timeout, httpStack, std::placeholders::_2));
CMD2_ANY ("network.http.current_open", std::bind(&core::CurlStack::active, httpStack));
CMD2_ANY ("network.http.max_open", std::bind(&core::CurlStack::max_active, httpStack));
CMD2_ANY_VALUE_V ("network.http.max_open.set", std::bind(&core::CurlStack::set_max_active, httpStack, std::placeholders::_2));
CMD2_ANY ("network.http.proxy_address", std::bind(&core::CurlStack::http_proxy, httpStack));
CMD2_ANY_STRING_V("network.http.proxy_address.set", std::bind(&core::CurlStack::set_http_proxy, httpStack, std::placeholders::_2));
CMD2_ANY ("network.http.ssl_verify_host", std::bind(&core::CurlStack::ssl_verify_host, httpStack));
CMD2_ANY_VALUE_V ("network.http.ssl_verify_host.set", std::bind(&core::CurlStack::set_ssl_verify_host, httpStack, std::placeholders::_2));
CMD2_ANY ("network.http.ssl_verify_peer", std::bind(&core::CurlStack::ssl_verify_peer, httpStack));
CMD2_ANY_VALUE_V ("network.http.ssl_verify_peer.set", std::bind(&core::CurlStack::set_ssl_verify_peer, httpStack, std::placeholders::_2));
CMD2_ANY ("network.send_buffer.size", std::bind(&torrent::ConnectionManager::send_buffer_size, cm));
CMD2_ANY_VALUE_V ("network.send_buffer.size.set", std::bind(&torrent::ConnectionManager::set_send_buffer_size, cm, std::placeholders::_2));
@@ -283,31 +235,37 @@ initialize_command_network() {
CMD2_ANY_VALUE_V ("network.receive_buffer.size.set", std::bind(&torrent::ConnectionManager::set_receive_buffer_size, cm, std::placeholders::_2));
CMD2_ANY_STRING ("network.tos.set", std::bind(&apply_tos, std::placeholders::_2));
CMD2_ANY ("network.bind_address", std::bind(&core::Manager::bind_address, control->core()));
CMD2_ANY_STRING_V("network.bind_address.set", std::bind(&core::Manager::set_bind_address, control->core(), std::placeholders::_2));
CMD2_ANY ("network.local_address", std::bind(&core::Manager::local_address, control->core()));
CMD2_ANY_STRING_V("network.local_address.set", std::bind(&core::Manager::set_local_address, control->core(), std::placeholders::_2));
CMD2_ANY ("network.proxy_address", std::bind(&core::Manager::proxy_address, control->core()));
CMD2_ANY_STRING_V("network.proxy_address.set", std::bind(&core::Manager::set_proxy_address, control->core(), std::placeholders::_2));
CMD2_ANY ("network.bind_address", std::bind(&core::Manager::bind_address, control->core()));
CMD2_ANY_STRING_V("network.bind_address.set", std::bind(&core::Manager::set_bind_address, control->core(), std::placeholders::_2));
CMD2_ANY ("network.local_address", std::bind(&core::Manager::local_address, control->core()));
CMD2_ANY_STRING_V("network.local_address.set", std::bind(&core::Manager::set_local_address, control->core(), std::placeholders::_2));
CMD2_ANY ("network.proxy_address", std::bind(&core::Manager::proxy_address, control->core()));
CMD2_ANY_STRING_V("network.proxy_address.set", std::bind(&core::Manager::set_proxy_address, control->core(), std::placeholders::_2));
CMD2_ANY ("network.max_open_files", std::bind(&torrent::FileManager::max_open_files, fileManager));
CMD2_ANY_VALUE_V ("network.max_open_files.set", std::bind(&torrent::FileManager::set_max_open_files, fileManager, std::placeholders::_2));
CMD2_ANY ("network.open_sockets", std::bind(&torrent::ConnectionManager::size, cm));
CMD2_ANY ("network.max_open_sockets", std::bind(&torrent::ConnectionManager::max_size, cm));
CMD2_ANY_VALUE_V ("network.max_open_sockets.set", std::bind(&torrent::ConnectionManager::set_max_size, cm, std::placeholders::_2));
CMD2_ANY ("network.open_files", std::bind(&torrent::FileManager::open_files, fileManager));
CMD2_ANY ("network.max_open_files", std::bind(&torrent::FileManager::max_open_files, fileManager));
CMD2_ANY_VALUE_V ("network.max_open_files.set", std::bind(&torrent::FileManager::set_max_open_files, fileManager, std::placeholders::_2));
CMD2_ANY ("network.total_handshakes", std::bind(&torrent::total_handshakes));
CMD2_ANY ("network.open_sockets", std::bind(&torrent::ConnectionManager::size, cm));
CMD2_ANY ("network.max_open_sockets", std::bind(&torrent::ConnectionManager::max_size, cm));
CMD2_ANY_VALUE_V ("network.max_open_sockets.set", std::bind(&torrent::ConnectionManager::set_max_size, cm, std::placeholders::_2));
CMD2_ANY_STRING ("network.scgi.open_port", std::bind(&apply_scgi, std::placeholders::_2, 1));
CMD2_ANY_STRING ("network.scgi.open_local", std::bind(&apply_scgi, std::placeholders::_2, 2));
CMD2_VAR_BOOL ("network.scgi.dont_route", false);
CMD2_ANY_STRING ("network.scgi.open_port", std::bind(&apply_scgi, std::placeholders::_2, 1));
CMD2_ANY_STRING ("network.scgi.open_local", std::bind(&apply_scgi, std::placeholders::_2, 2));
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_ANY ("system.hash.read_ahead", std::bind(&torrent::hash_read_ahead));
CMD2_ANY_VALUE_V ("system.hash.read_ahead.set", std::bind(&apply_hash_read_ahead, std::placeholders::_2));
CMD2_ANY ("system.hash.interval", std::bind(&torrent::hash_interval));
CMD2_ANY_VALUE_V ("system.hash.interval.set", std::bind(&apply_hash_interval, std::placeholders::_2));
CMD2_ANY ("system.hash.max_tries", std::bind(&torrent::hash_max_tries));
CMD2_ANY_VALUE_V ("system.hash.max_tries.set", std::bind(&torrent::set_hash_max_tries, std::placeholders::_2));
CMD2_VAR_BOOL ("network.rpc.use_xmlrpc", true);
CMD2_VAR_BOOL ("network.rpc.use_jsonrpc", true);
CMD2_ANY ("network.block.ipv4", std::bind(&torrent::ConnectionManager::is_block_ipv4, cm));
CMD2_ANY_VALUE_V ("network.block.ipv4.set", std::bind(&torrent::ConnectionManager::set_block_ipv4, cm, std::placeholders::_2));
CMD2_ANY ("network.block.ipv6", std::bind(&torrent::ConnectionManager::is_block_ipv6, cm));
CMD2_ANY_VALUE_V ("network.block.ipv6.set", std::bind(&torrent::ConnectionManager::set_block_ipv6, cm, std::placeholders::_2));
CMD2_ANY ("network.prefer.ipv6", std::bind(&torrent::ConnectionManager::is_prefer_ipv6, cm));
CMD2_ANY_VALUE_V ("network.prefer.ipv6.set", std::bind(&torrent::ConnectionManager::set_prefer_ipv6, cm, std::placeholders::_2));
}
+6 -1
View File
@@ -69,7 +69,12 @@ retrieve_p_id_html(torrent::Peer* peer) {
torrent::Object
retrieve_p_address(torrent::Peer* peer) {
return rak::socket_address::cast_from(peer->peer_info()->socket_address())->address_str();
const rak::socket_address *addr = rak::socket_address::cast_from(peer->peer_info()->socket_address());
if (addr->family() == rak::socket_address::af_inet6)
return "[" + addr->address_str() + "]";
else
return addr->address_str();
}
torrent::Object
+34 -10
View File
@@ -89,19 +89,22 @@ parse_address_range(const torrent::Object::list_type& args, torrent::Object::lis
// convert to [begin, end) making sure the end doesn't overflow
// (this precludes 255.255.255.255 from ever matching, but that's not a real IP anyway)
return std::make_pair<uint32_t, uint32_t>(begin, std::max(end, end + 1));
return std::make_pair((uint32_t)begin, (uint32_t)std::max(end, end + 1));
}
torrent::Object
apply_throttle(const torrent::Object::list_type& args, bool up) {
torrent::Object::list_const_iterator argItr = args.begin();
if (argItr == args.end())
throw torrent::input_error("Missing throttle name.");
const std::string& name = argItr->as_string();
if (name.empty() || name == "NULL")
throw torrent::input_error("Invalid throttle name.");
throw torrent::input_error("Invalid throttle name '" + name + "'.");
if ((++argItr)->as_string().empty())
return torrent::Object();
if (++argItr == args.end() || argItr->as_string().empty())
throw torrent::input_error("Missing throttle rate for '" + name + "'.");
int64_t rate;
rpc::parse_whole_value_nothrow(argItr->as_string().c_str(), &rate);
@@ -162,10 +165,21 @@ apply_address_throttle(const torrent::Object::list_type& args) {
return torrent::Object();
}
torrent::Object
throttle_update(const char* variable, int64_t value) {
rpc::commands.call_command(variable, value);
control->ui()->adjust_up_throttle(0);
control->ui()->adjust_down_throttle(0);
return torrent::Object();
}
void
initialize_command_throttle() {
CMD2_ANY ("throttle.unchoked_uploads", std::bind(&torrent::ResourceManager::currently_upload_unchoked, torrent::resource_manager()));
CMD2_ANY ("throttle.unchoked_downloads", std::bind(&torrent::ResourceManager::currently_download_unchoked, torrent::resource_manager()));
CMD2_ANY ("throttle.unchoked_uploads", std::bind(&torrent::ResourceManager::currently_upload_unchoked, torrent::resource_manager()));
CMD2_ANY ("throttle.max_unchoked_uploads", std::bind(&torrent::ResourceManager::max_upload_unchoked, torrent::resource_manager()));
CMD2_ANY ("throttle.unchoked_downloads", std::bind(&torrent::ResourceManager::currently_download_unchoked, torrent::resource_manager()));
CMD2_ANY ("throttle.max_unchoked_downloads", std::bind(&torrent::ResourceManager::max_download_unchoked, torrent::resource_manager()));
CMD2_VAR_VALUE ("throttle.min_peers.normal", 100);
CMD2_VAR_VALUE ("throttle.max_peers.normal", 200);
@@ -177,10 +191,20 @@ initialize_command_throttle() {
CMD2_VAR_VALUE ("throttle.min_downloads", 0);
CMD2_VAR_VALUE ("throttle.max_downloads", 50);
CMD2_VAR_VALUE ("throttle.max_uploads.div", 1);
CMD2_VAR_VALUE ("throttle.max_uploads.global", 0);
CMD2_VAR_VALUE ("throttle.max_downloads.div", 1);
CMD2_VAR_VALUE ("throttle.max_downloads.global", 0);
CMD2_VAR_VALUE ("throttle.max_uploads.div._val", 1);
CMD2_VAR_VALUE ("throttle.max_uploads.global._val", 0);
CMD2_VAR_VALUE ("throttle.max_downloads.div._val", 1);
CMD2_VAR_VALUE ("throttle.max_downloads.global._val", 0);
CMD2_REDIRECT_GENERIC("throttle.max_uploads.div", "throttle.max_uploads.div._val");
CMD2_REDIRECT_GENERIC("throttle.max_uploads.global", "throttle.max_uploads.global._val");
CMD2_REDIRECT_GENERIC("throttle.max_downloads.div", "throttle.max_downloads.div._val");
CMD2_REDIRECT_GENERIC("throttle.max_downloads.global", "throttle.max_downloads.global._val");
CMD2_ANY_VALUE ("throttle.max_uploads.div.set", std::bind(&throttle_update, "throttle.max_uploads.div._val.set", std::placeholders::_2));
CMD2_ANY_VALUE ("throttle.max_uploads.global.set", std::bind(&throttle_update, "throttle.max_uploads.global._val.set", std::placeholders::_2));
CMD2_ANY_VALUE ("throttle.max_downloads.div.set", std::bind(&throttle_update, "throttle.max_downloads.div._val.set", std::placeholders::_2));
CMD2_ANY_VALUE ("throttle.max_downloads.global.set", std::bind(&throttle_update, "throttle.max_downloads.global._val.set", std::placeholders::_2));
// TODO: Move the logic into some libtorrent function.
CMD2_ANY ("throttle.global_up.rate", std::bind(&torrent::Rate::rate, torrent::up_rate()));
+54 -81
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,60 +44,81 @@ 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_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));
// 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_V ("t.enable", std::bind(&torrent::Tracker::enable, std::placeholders::_1));
CMD2_TRACKER_V ("t.disable", std::bind(&torrent::Tracker::disable, std::placeholders::_1));
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.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.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.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.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.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_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_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)));
CMD2_VAR_BOOL ("trackers.delay_scrape", false);
CMD2_VAR_VALUE ("trackers.numwant", -1);
CMD2_VAR_BOOL ("trackers.use_udp", true);
+359 -82
View File
@@ -1,60 +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 <sys/types.h>
#include <ctime>
#include <rak/functional.h>
#include <rak/functional_fun.h>
#include <sigc++/adaptors/bind.h>
#include <regex>
#include <rak/algorithm.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"
#include "control.h"
#include "command_helpers.h"
typedef void (core::ViewManager::*view_cfilter_slot)(const std::string&, const torrent::Object&);
typedef void (core::ViewManager::*view_event_slot)(const std::string&, const std::string&);
typedef void (core::ViewManager::*view_event_slot)(const std::string&, const torrent::Object&);
torrent::Object
apply_view_filter_on(const torrent::Object::list_type& args) {
@@ -62,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.");
@@ -76,33 +42,12 @@ apply_view_filter_on(const torrent::Object::list_type& args) {
return torrent::Object();
}
torrent::Object
apply_view_cfilter(view_cfilter_slot viewFilterSlot, const torrent::Object::list_type& args) {
if (args.size() != 2)
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.");
(control->view_manager()->*viewFilterSlot)(name, args.back());
return torrent::Object();
}
torrent::Object
apply_view_event(view_event_slot viewFilterSlot, const torrent::Object::list_type& args) {
if (args.size() != 2)
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.");
(control->view_manager()->*viewFilterSlot)(name, args.back().as_string());
throw torrent::input_error("Wrong argument count.");
(control->view_manager()->*viewFilterSlot)(args.front().as_string(), args.back());
return torrent::Object();
}
@@ -154,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);
@@ -163,13 +108,48 @@ 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);
return result;
}
torrent::Object
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)
throw torrent::input_error("'value' takes at most two arguments!");
torrent::Object::value_type val = 0;
if (args.front().is_value()) {
val = args.front().as_value();
} else {
int base = args.size() > 1 ? args.back().is_value() ?
args.back().as_value() : strtol(args.back().as_string().c_str(), NULL, 10) : 10;
char* endptr = 0;
val = strtoll(args.front().as_string().c_str(), &endptr, base);
while (*endptr == ' ' || *endptr == '\n') ++endptr;
if (*endptr)
throw torrent::input_error("Junk at end of number: " + args.front().as_string());
}
return val;
}
torrent::Object
apply_try(rpc::target_type target, const torrent::Object& args) {
try {
return rpc::call_object(args, target);
} catch (torrent::input_error& e) {
lt_log_print(torrent::LOG_RPC_EVENTS, "try command caught input_error: %s", e.what());
}
return torrent::Object();
}
// Move these boolean operators to a new file.
inline bool
@@ -204,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;
}
@@ -219,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;
@@ -242,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;
}
@@ -282,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());
@@ -305,6 +285,103 @@ torrent::Object apply_equal(rpc::target_type target, const torrent::Object::list
return result.is_value() ? result.as_value() == 0 : (int64_t)false;
}
torrent::Object
apply_compare(rpc::target_type target, const torrent::Object::list_type& args) {
if (!rpc::is_target_pair(target))
throw torrent::input_error("Can only compare a target pair.");
if (args.size() < 2)
throw torrent::input_error("Need at least order and one field.");
torrent::Object::list_const_iterator itr = args.begin();
std::string order = (itr++)->as_string();
const char* current = order.c_str();
torrent::Object result1;
torrent::Object result2;
for (torrent::Object::list_const_iterator last = args.end(); itr != last; itr++) {
std::string field = itr->as_string();
result1 = rpc::parse_command_single(rpc::get_target_left(target), field);
result2 = rpc::parse_command_single(rpc::get_target_right(target), field);
if (result1.type() != result2.type())
throw torrent::input_error(std::string("Type mismatch in compare of ") + field);
bool descending = *current == 'd' || *current == 'D' || *current == '-';
if (*current) {
if (!descending && !(*current == 'a' || *current == 'A' || *current == '+'))
throw torrent::input_error(std::string("Bad order '") + *current + "' in " + order);
++current;
}
switch (result1.type()) {
case torrent::Object::TYPE_VALUE:
if (result1.as_value() != result2.as_value())
return (int64_t) (descending ^ (result1.as_value() < result2.as_value()));
break;
case torrent::Object::TYPE_STRING:
if (result1.as_string() != result2.as_string())
return (int64_t) (descending ^ (result1.as_string() < result2.as_string()));
break;
default:
break; // treat unknown types as equal
}
}
// if all else is equal, ensure stable sort order based on memory location
return (int64_t) (target.second < target.third);
}
// Regexp based 'match' function.
// arg1: the text to match.
// arg2: the regexp pattern.
// eg: match{d.name=,.*linux.*iso}
torrent::Object apply_match(rpc::target_type target, const torrent::Object::list_type& args) {
if (args.size() != 2)
throw torrent::input_error("Wrong argument count for 'match': 2 arguments needed.");
// This really should be converted to using args flagged as
// commands, so that we can compare commands and statics values.
torrent::Object result1;
torrent::Object result2;
rpc::target_type target1 = rpc::is_target_pair(target) ? rpc::get_target_left(target) : target;
rpc::target_type target2 = rpc::is_target_pair(target) ? rpc::get_target_right(target) : target;
if (args.front().is_dict_key())
result1 = rpc::commands.call_command(args.front().as_dict_key().c_str(), args.front().as_dict_obj(), target1);
else
result1 = rpc::parse_command_single(target1, args.front().as_string());
if (args.back().is_dict_key())
result2 = rpc::commands.call_command(args.back().as_dict_key().c_str(), args.back().as_dict_obj(), target2);
else
result2 = args.back().as_string();
if (result1.type() != result2.type())
throw torrent::input_error("Type mismatch for 'match' arguments.");
std::string text = result1.as_string();
std::string pattern = result2.as_string();
std::transform(text.begin(), text.end(), text.begin(), ::tolower);
std::transform(pattern.begin(), pattern.end(), pattern.begin(), ::tolower);
bool isAMatch = false;
try {
std::regex re(pattern);
isAMatch = std::regex_match(text, re);
} catch (const std::regex_error& exc) {
control->core()->push_log_std("regex_error: " + std::string(exc.what()));
}
return isAMatch ? (int64_t)true : (int64_t)false;
}
torrent::Object
apply_to_time(const torrent::Object& rawArgs, int flags) {
std::tm *u;
@@ -314,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();
@@ -357,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));
@@ -373,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)
@@ -471,8 +548,8 @@ 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->get_event_added().empty() || !view->get_event_removed().empty())
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.");
view->set_filter("d.views.has=" + args);
@@ -489,6 +566,11 @@ cmd_ui_set_view(const torrent::Object::string_type& args) {
return torrent::Object();
}
torrent::Object
cmd_ui_current_view() {
return control->ui()->download_list()->current_view()->name();
}
torrent::Object
cmd_ui_unfocus_download(core::Download* download) {
control->ui()->download_list()->unfocus_download(download);
@@ -537,6 +619,155 @@ apply_elapsed_greater(const torrent::Object::list_type& args) {
return (int64_t)(start_time != 0 && rak::timer::current_seconds() - start_time > rpc::convert_to_value(args.back()));
}
inline std::vector<int64_t>
as_vector(const torrent::Object::list_type& args) {
if (args.size() == 0)
throw torrent::input_error("Wrong argument count in as_vector.");
std::vector<int64_t> result;
for (torrent::Object::list_const_iterator itr = args.begin(), last = args.end(); itr != last; itr++) {
if (itr->is_value()) {
result.push_back(itr->as_value());
} else if (itr->is_string()) {
result.push_back(rpc::convert_to_value(itr->as_string()));
} else if (itr->is_list()) {
std::vector<int64_t> subResult = as_vector(itr->as_list());
result.insert(result.end(), subResult.begin(), subResult.end());
} else {
throw torrent::input_error("Wrong type supplied to as_vector.");
}
}
return result;
}
int64_t
apply_math_basic(const char* name, const std::function<int64_t(int64_t,int64_t)> op, const torrent::Object::list_type& args) {
int64_t val = 0, rhs = 0;
bool divides = !strcmp(name, "math.div") || !strcmp(name, "math.mod");
if (args.size() == 0)
throw torrent::input_error(std::string(name) + ": No arguments provided!");
for (torrent::Object::list_const_iterator itr = args.begin(), last = args.end(); itr != last; itr++) {
if (itr->is_value()) {
rhs = itr->as_value();
} else if (itr->is_string()) {
rhs = rpc::convert_to_value(itr->as_string());
} else if (itr->is_list()) {
rhs = apply_math_basic(name, op, itr->as_list());
} else {
throw torrent::input_error(std::string(name) + ": Wrong argument type");
}
if (divides && !rhs && itr != args.begin())
throw torrent::input_error(std::string(name) + ": Division by zero!");
val = itr == args.begin() ? rhs : op(val, rhs);
}
return val;
}
int64_t
apply_arith_basic(const std::function<int64_t(int64_t,int64_t)> op, const torrent::Object::list_type& args) {
if (args.size() == 0)
throw torrent::input_error("Wrong argument count in apply_arith_basic.");
int64_t val = 0;
for (torrent::Object::list_const_iterator itr = args.begin(), last = args.end(); itr != last; itr++) {
if (itr->is_value()) {
val = itr == args.begin() ? itr->as_value() : (op(val, itr->as_value()) ? val : itr->as_value());
} else if (itr->is_string()) {
int64_t cval = rpc::convert_to_value(itr->as_string());
val = itr == args.begin() ? cval : (op(val, cval) ? val : cval);
} else if (itr->is_list()) {
int64_t fval = apply_arith_basic(op, itr->as_list());
val = itr == args.begin() ? fval : (op(val, fval) ? val : fval);
} else {
throw torrent::input_error("Wrong type supplied to apply_arith_basic.");
}
}
return val;
}
int64_t
apply_arith_count(const torrent::Object::list_type& args) {
if (args.size() == 0)
throw torrent::input_error("Wrong argument count in apply_arith_count.");
int64_t val = 0;
for (torrent::Object::list_const_iterator itr = args.begin(), last = args.end(); itr != last; itr++) {
switch (itr->type()) {
case torrent::Object::TYPE_VALUE:
case torrent::Object::TYPE_STRING:
val++;
break;
case torrent::Object::TYPE_LIST:
val += apply_arith_count(itr->as_list());
break;
default:
throw torrent::input_error("Wrong type supplied to apply_arith_count.");
}
}
return val;
}
int64_t
apply_arith_other(const char* op, const torrent::Object::list_type& args) {
if (args.size() == 0)
throw torrent::input_error("Wrong argument count in apply_arith_other.");
if (strcmp(op, "average") == 0) {
return (int64_t)(apply_math_basic(op, std::plus<int64_t>(), args) / apply_arith_count(args));
} else if (strcmp(op, "median") == 0) {
std::vector<int64_t> result = as_vector(args);
return (int64_t)rak::median(result.begin(), result.end());
} else {
throw torrent::input_error("Wrong operation supplied to apply_arith_other.");
}
}
torrent::Object
cmd_status_throttle_names(bool up, const torrent::Object::list_type& args) {
if (args.size() == 0)
return torrent::Object();
std::vector<std::string> throttle_name_list;
for (torrent::Object::list_const_iterator itr = args.begin(), last = args.end(); itr != last; itr++) {
if (itr->is_string())
throttle_name_list.push_back(itr->as_string());
}
if (up)
control->ui()->set_status_throttle_up_names(throttle_name_list);
else
control->ui()->set_status_throttle_down_names(throttle_name_list);
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");
@@ -546,12 +777,15 @@ initialize_command_ui() {
CMD2_ANY_L ("view.list", std::bind(&apply_view_list));
CMD2_ANY_LIST("view.set", std::bind(&apply_view_set, std::placeholders::_2));
CMD2_ANY_LIST("view.filter", std::bind(&apply_view_cfilter, &core::ViewManager::set_filter, std::placeholders::_2));
CMD2_ANY_LIST("view.filter_on", std::bind(&apply_view_filter_on, std::placeholders::_2));
CMD2_ANY_LIST ("view.filter", std::bind(&apply_view_event, &core::ViewManager::set_filter, std::placeholders::_2));
CMD2_ANY_LIST ("view.filter_on", std::bind(&apply_view_filter_on, std::placeholders::_2));
CMD2_ANY_LIST ("view.filter.temp", std::bind(&apply_view_event, &core::ViewManager::set_filter_temp, std::placeholders::_2));
CMD2_VAR_STRING("view.filter.temp.excluded", "default,started,stopped");
CMD2_VAR_BOOL ("view.filter.temp.log", 0);
CMD2_ANY_LIST("view.sort", std::bind(&apply_view_sort, std::placeholders::_2));
CMD2_ANY_LIST("view.sort_new", std::bind(&apply_view_cfilter, &core::ViewManager::set_sort_new, std::placeholders::_2));
CMD2_ANY_LIST("view.sort_current", std::bind(&apply_view_cfilter, &core::ViewManager::set_sort_current, std::placeholders::_2));
CMD2_ANY_LIST("view.sort_new", std::bind(&apply_view_event, &core::ViewManager::set_sort_new, std::placeholders::_2));
CMD2_ANY_LIST("view.sort_current", std::bind(&apply_view_event, &core::ViewManager::set_sort_current, std::placeholders::_2));
CMD2_ANY_LIST("view.event_added", std::bind(&apply_view_event, &core::ViewManager::set_event_added, std::placeholders::_2));
CMD2_ANY_LIST("view.event_removed", std::bind(&apply_view_event, &core::ViewManager::set_event_removed, std::placeholders::_2));
@@ -570,11 +804,30 @@ initialize_command_ui() {
// Commands that affect the default rtorrent UI.
CMD2_DL ("ui.unfocus_download", std::bind(&cmd_ui_unfocus_download, std::placeholders::_1));
CMD2_ANY ("ui.current_view", std::bind(&cmd_ui_current_view));
CMD2_ANY_STRING("ui.current_view.set", std::bind(&cmd_ui_set_view, std::placeholders::_2));
CMD2_ANY ("ui.input.history.size", std::bind(&ui::Root::get_input_history_size, control->ui()));
CMD2_ANY_VALUE_V("ui.input.history.size.set", std::bind(&ui::Root::set_input_history_size, control->ui(), std::placeholders::_2));
CMD2_ANY_V ("ui.input.history.clear", std::bind(&ui::Root::clear_input_history, control->ui()));
CMD2_VAR_VALUE ("ui.throttle.global.step.small", 5);
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));
// TODO: Add 'option_string' for rtorrent-specific options.
CMD2_VAR_STRING("ui.torrent_list.layout", "full");
// Move.
CMD2_ANY("print", &apply_print);
CMD2_ANY("cat", &apply_cat);
CMD2_ANY_LIST("value", &apply_value);
CMD2_ANY("try", &apply_try);
CMD2_ANY("if", std::bind(&apply_if, std::placeholders::_1, std::placeholders::_2, 0));
CMD2_ANY("not", &apply_not);
CMD2_ANY("false", &apply_false);
@@ -588,6 +841,8 @@ initialize_command_ui() {
CMD2_ANY_LIST("less", &apply_less);
CMD2_ANY_LIST("greater", &apply_greater);
CMD2_ANY_LIST("equal", &apply_equal);
CMD2_ANY_LIST("compare", &apply_compare);
CMD2_ANY_LIST("match", &apply_match);
CMD2_ANY_VALUE("convert.gm_time", std::bind(&apply_to_time, std::placeholders::_2, 0));
CMD2_ANY_VALUE("convert.gm_date", std::bind(&apply_to_time, std::placeholders::_2, 0x2));
@@ -599,6 +854,28 @@ initialize_command_ui() {
CMD2_ANY_VALUE("convert.xb", std::bind(&apply_to_xb, std::placeholders::_2));
CMD2_ANY_VALUE("convert.throttle", std::bind(&apply_to_throttle, std::placeholders::_2));
CMD2_ANY_LIST("math.add", std::bind(&apply_math_basic, "math.add", std::plus<int64_t>(), std::placeholders::_2));
CMD2_ANY_LIST("math.sub", std::bind(&apply_math_basic, "math.sub", std::minus<int64_t>(), std::placeholders::_2));
CMD2_ANY_LIST("math.mul", std::bind(&apply_math_basic, "math.mul", std::multiplies<int64_t>(), std::placeholders::_2));
CMD2_ANY_LIST("math.div", std::bind(&apply_math_basic, "math.div", std::divides<int64_t>(), std::placeholders::_2));
CMD2_ANY_LIST("math.mod", std::bind(&apply_math_basic, "math.mod", std::modulus<int64_t>(), std::placeholders::_2));
CMD2_ANY_LIST("math.min", std::bind(&apply_arith_basic, std::less<int64_t>(), std::placeholders::_2));
CMD2_ANY_LIST("math.max", std::bind(&apply_arith_basic, std::greater<int64_t>(), std::placeholders::_2));
CMD2_ANY_LIST("math.cnt", std::bind(&apply_arith_count, std::placeholders::_2));
CMD2_ANY_LIST("math.avg", std::bind(&apply_arith_other, "average", std::placeholders::_2));
CMD2_ANY_LIST("math.med", std::bind(&apply_arith_other, "median", std::placeholders::_2));
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]);
});
}
}
+38 -47
View File
@@ -1,56 +1,27 @@
// 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/stat.h>
#include <torrent/connection_manager.h>
#include <torrent/utils/directory_events.h>
#include "core/manager.h"
#include "core/download_store.h"
#include "core/view_manager.h"
#include "core/dht_manager.h"
#include "core/http_queue.h"
#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"
@@ -66,6 +37,8 @@ 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),
m_shutdownReceived(false),
@@ -75,11 +48,11 @@ Control::Control() :
m_viewManager = new core::ViewManager();
m_dhtManager = new core::DhtManager();
m_inputStdin->slot_pressed(sigc::mem_fun(m_input, &input::Manager::pressed));
m_inputStdin->slot_pressed(std::bind(&input::Manager::pressed, m_input, std::placeholders::_1));
m_taskShutdown.set_slot(rak::mem_fn(this, &Control::handle_shutdown));
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() {
@@ -93,16 +66,18 @@ Control::~Control() {
delete m_core;
delete m_dhtManager;
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);
@@ -114,23 +89,27 @@ Control::initialize() {
m_ui->init(this);
m_inputStdin->insert(main_thread->poll());
if(!display::Canvas::daemon()) {
m_inputStdin->insert(torrent::main_thread()->poll());
}
}
void
Control::cleanup() {
// delete m_scgi; m_scgi = NULL;
rpc::xmlrpc.cleanup();
rpc::rpc.cleanup();
priority_queue_erase(&taskScheduler, &m_taskShutdown);
m_inputStdin->remove(main_thread->poll());
if(!display::Canvas::daemon()) {
m_inputStdin->remove(torrent::main_thread()->poll());
}
m_core->download_store()->disable();
m_ui->cleanup();
m_core->cleanup();
display::Canvas::erase_std();
display::Canvas::refresh_std();
display::Canvas::do_update();
@@ -146,17 +125,29 @@ Control::cleanup_exception() {
bool
Control::is_shutdown_completed() {
return m_shutdownQuick && !worker_thread->is_active() && torrent::is_inactive();
if (!m_shutdownQuick || worker_thread->is_active())
return false;
// Tracker requests can be disowned, so wait for these to
// finish. The edge case of torrent http downloads may delay
// shutdown.
if (!core()->http_stack()->empty() || !core()->http_queue()->empty())
return false;
return torrent::is_inactive();
}
void
Control::handle_shutdown() {
rpc::commands.call_catch("event.system.shutdown", rpc::make_target(), "shutdown", "System shutdown event action failed: ");
if (!m_shutdownQuick) {
// Temporary hack:
if (worker_thread->is_active())
worker_thread->queue_item(&ThreadBase::stop_thread);
torrent::connection_manager()->listen_close();
m_directory_events->close();
m_core->shutdown(false);
if (!m_taskShutdown.is_queued())
+18 -8
View File
@@ -37,7 +37,8 @@
#ifndef RTORRENT_CONTROL_H
#define RTORRENT_CONTROL_H
#include <inttypes.h>
#include <atomic>
#include <cinttypes>
#include <sys/types.h>
#include <rak/timer.h>
#include <rak/priority_queue_default.h>
@@ -66,6 +67,11 @@ namespace rpc {
class CommandScheduler;
class XmlRpc;
class object_storage;
class LuaEngine;
}
namespace torrent {
class directory_events;
}
class Control {
@@ -83,14 +89,13 @@ 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; }
core::DhtManager* dht_manager() { return m_dhtManager; }
ui::Root* ui() { return m_ui; }
display::Manager* display() { return m_display; }
input::Manager* input() { return m_input; }
@@ -98,6 +103,9 @@ 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; }
uint64_t tick() const { return m_tick; }
void inc_tick() { m_tick++; }
@@ -118,8 +126,10 @@ private:
input::Manager* m_input;
input::InputEvent* m_inputStdin;
rpc::CommandScheduler* m_commandScheduler;
rpc::object_storage* m_objectStorage;
rpc::CommandScheduler* m_commandScheduler;
rpc::object_storage* m_objectStorage;
rpc::LuaEngine* m_lua_engine;
torrent::directory_events* m_directory_events;
uint64_t m_tick;
@@ -128,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
-41
View File
@@ -1,41 +0,0 @@
noinst_LIBRARIES = libsub_core.a
libsub_core_a_SOURCES = \
curl_get.cc \
curl_get.h \
curl_socket.cc \
curl_socket.h \
curl_stack.cc \
curl_stack.h \
dht_manager.cc \
dht_manager.h \
download.cc \
download.h \
download_factory.cc \
download_factory.h \
download_list.cc \
download_list.h \
download_slot_map.h \
download_store.cc \
download_store.h \
http_queue.cc \
http_queue.h \
log.cc \
log.h \
manager.cc \
manager.h \
poll_manager.cc \
poll_manager.h \
poll_manager_epoll.cc \
poll_manager_epoll.h \
poll_manager_kqueue.cc \
poll_manager_kqueue.h \
poll_manager_select.cc \
poll_manager_select.h \
range_map.h \
view.cc \
view.h \
view_manager.cc \
view_manager.h
INCLUDES = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir)
+21 -4
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)
@@ -82,18 +85,21 @@ 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.set_slot(rak::mem_fn(this, &CurlGet::receive_timeout));
priority_queue_erase(&taskScheduler, &m_taskTimeout);
priority_queue_insert(&taskScheduler, &m_taskTimeout, cachedTime + rak::timer::from_seconds(m_timeout + 5));
m_taskTimeout.slot() = std::bind(&CurlGet::receive_timeout, this);
priority_queue_update(&taskScheduler, &m_taskTimeout, cachedTime + rak::timer::from_seconds(m_timeout + 5));
}
curl_easy_setopt(m_handle, CURLOPT_FORBID_REUSE, (long)1);
curl_easy_setopt(m_handle, CURLOPT_NOSIGNAL, (long)1);
curl_easy_setopt(m_handle, CURLOPT_FOLLOWLOCATION, (long)1);
curl_easy_setopt(m_handle, CURLOPT_MAXREDIRS, (long)5);
curl_easy_setopt(m_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_easy_setopt(m_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER);
curl_easy_setopt(m_handle, CURLOPT_ENCODING, "");
m_ipv6 = false;
m_stack->add_get(this);
}
@@ -110,6 +116,17 @@ CurlGet::close() {
m_handle = NULL;
}
void
CurlGet::retry_ipv6() {
CURL* nhandle = curl_easy_duphandle(m_handle);
curl_easy_setopt(nhandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
curl_easy_cleanup(m_handle);
m_handle = nhandle;
m_ipv6 = true;
}
void
CurlGet::receive_timeout() {
return m_stack->transfer_done(m_handle, "Timed out");
+4 -1
View File
@@ -40,7 +40,6 @@
#include <iosfwd>
#include <string>
#include <curl/curl.h>
#include <sigc++/signal.h>
#include <torrent/http.h>
#include "rak/priority_queue_default.h"
@@ -59,6 +58,9 @@ public:
void start();
void close();
bool is_using_ipv6() { return m_ipv6; }
void retry_ipv6();
bool is_busy() const { return m_handle; }
bool is_active() const { return m_active; }
@@ -76,6 +78,7 @@ private:
void receive_timeout();
bool m_active;
bool m_ipv6;
rak::priority_item m_taskTimeout;
+16 -47
View File
@@ -1,46 +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.h>
#include "control.h"
@@ -50,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.
@@ -69,29 +39,28 @@ CurlSocket::receive_socket(void* easy_handle, curl_socket_t fd, int what, void*
if (socket == NULL) {
socket = stack->new_socket(fd);
main_thread->poll()->open(socket);
torrent::main_thread()->poll()->open(socket);
// No interface for libcurl to signal when it's interested in error events.
// Assume that hence it must always be interested in them.
main_thread->poll()->insert_error(socket);
}
torrent::main_thread()->poll()->insert_error(socket);
}
if (what == CURL_POLL_NONE || what == CURL_POLL_OUT)
main_thread->poll()->remove_read(socket);
torrent::main_thread()->poll()->remove_read(socket);
else
main_thread->poll()->insert_read(socket);
torrent::main_thread()->poll()->insert_read(socket);
if (what == CURL_POLL_NONE || what == CURL_POLL_IN)
main_thread->poll()->remove_write(socket);
torrent::main_thread()->poll()->remove_write(socket);
else
main_thread->poll()->insert_write(socket);
torrent::main_thread()->poll()->insert_write(socket);
return 0;
}
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
@@ -99,7 +68,7 @@ CurlSocket::close() {
if (m_fileDesc == -1)
throw torrent::internal_error("CurlSocket::close() m_fileDesc == -1.");
main_thread->poll()->closed(this);
torrent::main_thread()->poll()->closed(this);
m_fileDesc = -1;
}
+3 -1
View File
@@ -50,6 +50,8 @@ public:
CurlSocket(int fd, CurlStack* stack) : m_stack(stack) { m_fileDesc = fd; }
~CurlSocket();
const char* type_name() const { return "curl"; }
void close();
static int receive_socket(void* easy_handle, curl_socket_t fd, int what, void* userp, void* socketp);
@@ -62,7 +64,7 @@ private:
virtual void event_write();
virtual void event_error();
CurlStack* m_stack;
CurlStack* m_stack;
};
}
+81 -83
View File
@@ -1,63 +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 <sigc++/adaptors/bind.h>
#include <torrent/exceptions.h>
#include "rak/functional.h"
#include "curl_get.h"
#include "curl_socket.h"
#include "curl_stack.h"
namespace std { using namespace tr1; }
namespace core {
CurlStack::CurlStack() :
m_handle((void*)curl_multi_init()),
m_active(0),
m_maxActive(32),
m_ssl_verify_peer(true),
m_dns_timeout(60) {
m_taskTimeout.set_slot(rak::mem_fn(this, &CurlStack::receive_timeout));
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);
@@ -68,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*
@@ -82,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;
@@ -94,40 +62,70 @@ CurlStack::receive_action(CurlSocket* socket, int events) {
do {
int count;
#if (LIBCURL_VERSION_NUM >= 0x071003)
code = curl_multi_socket_action((CURLM*)m_handle, socket != NULL ? socket->file_descriptor() : CURL_SOCKET_TIMEOUT, events, &count);
code = curl_multi_socket_action((CURLM*)m_handle,
socket != NULL ? socket->file_descriptor() : CURL_SOCKET_TIMEOUT,
events,
&count);
#else
code = curl_multi_socket((CURLM*)m_handle, socket != NULL ? socket->file_descriptor() : CURL_SOCKET_TIMEOUT, &count);
code = curl_multi_socket((CURLM*)m_handle,
socket != NULL ? socket->file_descriptor() : CURL_SOCKET_TIMEOUT,
&count);
#endif
if (code > 0)
throw torrent::internal_error("Error calling curl_multi_socket_action.");
// Socket might be removed when cleaning handles below, future calls should not use it.
// Socket might be removed when cleaning handles below, future
// calls should not use it.
socket = NULL;
events = 0;
if ((unsigned int)count != size()) {
// Done with some handles.
int t;
CURLMsg* msg;
while ((msg = curl_multi_info_read((CURLM*)m_handle, &t)) != NULL) {
if (msg->msg != CURLMSG_DONE)
throw torrent::internal_error("CurlStack::receive_action() msg->msg != CURLMSG_DONE.");
transfer_done(msg->easy_handle, msg->data.result == CURLE_OK ? NULL : curl_easy_strerror(msg->data.result));
}
while (process_done_handle())
; // Do nothing.
if (empty())
priority_queue_erase(&taskScheduler, &m_taskTimeout);
priority_queue_erase(&taskScheduler, &m_task_timeout);
}
} while (code == CURLM_CALL_MULTI_PERFORM);
}
bool
CurlStack::process_done_handle() {
int remaining_msgs = 0;
CURLMsg* msg = curl_multi_info_read((CURLM*)m_handle, &remaining_msgs);
if (msg == NULL)
return false;
if (msg->msg != CURLMSG_DONE)
throw torrent::internal_error("CurlStack::receive_action() msg->msg != CURLMSG_DONE.");
if (msg->data.result == CURLE_COULDNT_RESOLVE_HOST) {
iterator itr = std::find_if(begin(), end(), [&msg](CurlGet* get) { return get->handle() == msg->easy_handle; });
if (itr == end())
throw torrent::internal_error("Could not find CurlGet when calling CurlStack::receive_action.");
if (!(*itr)->is_using_ipv6()) {
(*itr)->retry_ipv6();
if (curl_multi_add_handle((CURLM*)m_handle, (*itr)->handle()) > 0)
throw torrent::internal_error("Error calling curl_multi_add_handle.");
}
} else {
transfer_done(msg->easy_handle,
msg->data.result == CURLE_OK ? NULL : curl_easy_strerror(msg->data.result));
}
return remaining_msgs != 0;
}
void
CurlStack::transfer_done(void* handle, const char* msg) {
iterator itr = std::find_if(begin(), end(), 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.");
@@ -143,42 +141,43 @@ 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_VERIFYPEER, (long)m_ssl_verify_peer);
curl_easy_setopt(get->handle(), CURLOPT_SSL_VERIFYHOST, (long)(m_ssl_verify_host ? 2 : 0));
curl_easy_setopt(get->handle(), CURLOPT_SSL_VERIFYPEER, (long)(m_ssl_verify_peer ? 1 : 0));
curl_easy_setopt(get->handle(), CURLOPT_DNS_CACHE_TIMEOUT, m_dns_timeout);
base_type::push_back(get);
if (m_active >= m_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.");
@@ -205,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)
@@ -233,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;
}
+32 -59
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
#ifndef RTORRENT_CORE_CURL_STACK_H
#define RTORRENT_CORE_CURL_STACK_H
#include <deque>
#include <string>
#include <sigc++/functors/slot.h>
#include "rak/priority_queue_default.h"
@@ -82,26 +45,31 @@ 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; }
void set_ssl_verify_host(bool s) { m_ssl_verify_host = s; }
void set_ssl_verify_peer(bool s) { m_ssl_verify_peer = s; }
long dns_timeout() const { return m_dns_timeout; }
@@ -126,21 +94,26 @@ class CurlStack : std::deque<CurlGet*> {
void receive_timeout();
bool process_done_handle();
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_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};
};
}
+69 -93
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"
@@ -54,6 +18,9 @@
#include "download_store.h"
#include "manager.h"
#define LT_LOG_THIS(log_fmt, ...) \
lt_log_print_subsystem(torrent::LOG_DHT_MANAGER, "dht_manager", log_fmt, __VA_ARGS__);
namespace core {
const char* DhtManager::dht_settings[dht_settings_num] = { "disable", "off", "auto", "on" };
@@ -65,69 +32,77 @@ DhtManager::~DhtManager() {
void
DhtManager::load_dht_cache() {
if (m_start == dht_disable || !control->core()->download_store()->is_enabled())
if (m_start == dht_disable || !control->core()->download_store()->is_enabled()) {
LT_LOG_THIS("ignoring cache file", 0);
return;
}
std::string cache_filename = control->core()->download_store()->path() + "rtorrent.dht_cache";
std::fstream cache_stream(cache_filename.c_str(), std::ios::in | std::ios::binary);
torrent::Object cache = torrent::Object::create_map();
std::fstream cache_file((control->core()->download_store()->path() + "rtorrent.dht_cache").c_str(), std::ios::in | std::ios::binary);
if (cache_file.is_open()) {
cache_file >> cache;
if (cache_stream.is_open()) {
cache_stream >> cache;
// If the cache file is corrupted we will just discard it with an
// error message.
if (cache_file.fail()) {
lt_log_print(torrent::LOG_DHT_WARN, "DHT cache file corrupted, discarding.");
if (cache_stream.fail()) {
LT_LOG_THIS("cache file corrupted, discarding (path:%s)", cache_filename.c_str());
cache = torrent::Object::create_map();
} else {
LT_LOG_THIS("cache file read (path:%s)", cache_filename.c_str());
}
} else {
LT_LOG_THIS("could not open cache file (path:%s)", cache_filename.c_str());
}
try {
torrent::dht_manager()->initialize(cache);
torrent::dht_controller()->initialize(cache);
if (m_start == dht_on)
start_dht();
} catch (torrent::local_error& e) {
lt_log_print(torrent::LOG_DHT_WARN, "DHT failed: %s", e.what());
}
if (m_start == dht_on)
start_dht();
}
void
DhtManager::start_dht() {
priority_queue_erase(&taskScheduler, &m_stopTimeout);
if (!torrent::dht_manager()->is_valid() || torrent::dht_manager()->is_active())
if (!torrent::dht_controller()->is_valid()) {
LT_LOG_THIS("server start skipped, manager is uninitialized", 0);
return;
}
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;
lt_log_print(torrent::LOG_DHT_INFO, "Starting DHT server on port %d.", port);
try {
torrent::dht_manager()->start(port);
torrent::dht_manager()->reset_statistics();
m_updateTimeout.set_slot(rak::mem_fn(this, &DhtManager::update));
priority_queue_insert(&taskScheduler, &m_updateTimeout, (cachedTime + rak::timer::from_seconds(60)).round_seconds());
m_dhtPrevCycle = 0;
m_dhtPrevQueriesSent = 0;
m_dhtPrevRepliesReceived = 0;
m_dhtPrevQueriesReceived = 0;
m_dhtPrevBytesUp = 0;
m_dhtPrevBytesDown = 0;
} catch (torrent::local_error& e) {
lt_log_print(torrent::LOG_DHT_ERROR, "DHT start failed: %s", e.what());
if (!torrent::dht_controller()->start(port)) {
m_start = dht_off;
return;
}
torrent::dht_controller()->reset_statistics();
m_updateTimeout.slot() = std::bind(&DhtManager::update, this);
priority_queue_insert(&taskScheduler, &m_updateTimeout, (cachedTime + rak::timer::from_seconds(60)).round_seconds());
m_dhtPrevCycle = 0;
m_dhtPrevQueriesSent = 0;
m_dhtPrevRepliesReceived = 0;
m_dhtPrevQueriesReceived = 0;
m_dhtPrevBytesUp = 0;
m_dhtPrevBytesDown = 0;
}
void
@@ -135,16 +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);
lt_log_print(torrent::LOG_DHT_INFO, "Stopping DHT server.");
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";
@@ -155,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;
@@ -186,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()) {
@@ -195,9 +171,9 @@ 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.set_slot(rak::mem_fn(this, &DhtManager::stop_dht));
m_stopTimeout.slot() = std::bind(&DhtManager::stop_dht, this);
priority_queue_insert(&taskScheduler, &m_stopTimeout, (cachedTime + rak::timer::from_seconds(15 * 60)).round_seconds());
}
}
@@ -211,23 +187,23 @@ 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())
lt_log_print(torrent::LOG_DHT_WARN, "DHT port appears to be unreachable, no queries received.");
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) {
// No replies to over 20 queries plus two per node we have. Probably firewalled.
if (!m_warned)
lt_log_print(torrent::LOG_DHT_WARN, "DHT port appears to be firewalled, no replies received.");
LT_LOG_THIS("listening port appears to be firewalled, no replies received", 0);
m_warned = true;
return false;
@@ -236,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) {
@@ -248,7 +224,7 @@ DhtManager::log_statistics(bool force) {
if (m_dhtPrevCycle == 1) {
char buffer[128];
snprintf(buffer, sizeof(buffer), "DHT bootstrap complete, have %d nodes in %d buckets.", stats.num_nodes, stats.num_buckets);
control->core()->get_log_complete().push_front(buffer);
control->core()->push_log_complete(buffer);
m_dhtPrevCycle = stats.cycle;
return false;
};
@@ -257,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,
@@ -271,7 +247,7 @@ DhtManager::log_statistics(bool force) {
stats.max_peers,
stats.num_trackers);
control->core()->get_log_complete().push_front(buffer);
control->core()->push_log_complete(buffer);
m_dhtPrevCycle = stats.cycle;
m_dhtPrevQueriesSent = stats.queries_sent;
@@ -289,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);
@@ -315,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
+7 -64
View File
@@ -1,52 +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 <sigc++/adaptors/bind.h>
#include <sigc++/adaptors/hide.h>
#include <sigc++/signal.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"
@@ -61,36 +22,28 @@ Download::Download(download_type d) :
m_download(d),
m_hashFailed(false),
m_chunksFailed(0),
m_resumeFlags(~uint32_t()),
m_group(0) {
m_connTrackerSucceeded = m_download.info()->signal_tracker_success().connect(sigc::bind(sigc::mem_fun(*this, &Download::receive_tracker_msg), ""));
m_connTrackerFailed = m_download.info()->signal_tracker_failed().connect(sigc::mem_fun(*this, &Download::receive_tracker_msg));
m_connStorageError = m_download.info()->signal_storage_error().connect(sigc::mem_fun(*this, &Download::receive_storage_error));
m_download.info()->signal_chunk_failed().connect(sigc::mem_fun(*this, &Download::receive_chunk_failed));
m_download.info()->signal_tracker_success().push_back(std::bind(&Download::receive_tracker_msg, this, ""));
m_download.info()->signal_tracker_failed().push_back(std::bind(&Download::receive_tracker_msg, this, std::placeholders::_1));
}
Download::~Download() {
if (!m_download.is_valid())
return;
m_connTrackerSucceeded.disconnect();
m_connTrackerFailed.disconnect();
m_connStorageError.disconnect();
m_download = download_type();
}
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();
}
}
@@ -125,11 +78,6 @@ Download::receive_tracker_msg(std::string msg) {
m_message = "Tracker: [" + msg + "]";
}
void
Download::receive_storage_error(std::string msg) {
m_message = "Storage error: [" + msg + "]";
}
float
Download::distributed_copies() const {
const uint8_t* avail = m_download.chunks_seen();
@@ -154,11 +102,6 @@ Download::distributed_copies() const {
return minAvail + 1 - bitfield->is_all_set() - (float)num / m_download.file_list()->size_chunks();
}
void
Download::receive_chunk_failed(__UNUSED uint32_t idx) {
m_chunksFailed++;
}
void
Download::set_throttle_name(const std::string& throttleName) {
if (m_download.info()->is_active())
+7 -62
View File
@@ -1,43 +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 <sigc++/connection.h>
#include <torrent/common.h>
#include <torrent/download.h>
#include <torrent/download_info.h>
#include <torrent/hash_string.h>
@@ -47,11 +11,6 @@
#include "globals.h"
namespace torrent {
class PeerList;
class TrackerList;
}
namespace core {
class Download {
@@ -60,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;
@@ -72,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(); }
@@ -103,19 +61,16 @@ 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; }
uint32_t chunks_failed() const { return m_chunksFailed; }
void enable_udp_trackers(bool state);
uint32_t priority();
@@ -141,24 +96,14 @@ private:
void operator () (const Download&);
void receive_tracker_msg(std::string msg);
void receive_storage_error(std::string msg);
void receive_chunk_failed(uint32_t idx);
// Store the FileList instance so we can use slots etc on it.
download_type m_download;
bool m_hashFailed;
std::string m_message;
uint32_t m_chunksFailed;
uint32_t m_resumeFlags;
sigc::connection m_connTrackerSucceeded;
sigc::connection m_connTrackerFailed;
sigc::connection m_connStorageError;
unsigned int m_group;
};
+98 -91
View File
@@ -1,46 +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 <cstdlib>
#include <fstream>
#include <functional>
#include <sstream>
#include <stdexcept>
#include <rak/path.h>
#include <torrent/utils/log.h>
#include <torrent/utils/resume.h>
#include <torrent/object.h>
#include <torrent/object_stream.h>
@@ -70,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
@@ -103,16 +69,17 @@ DownloadFactory::DownloadFactory(Manager* m) :
m_session(false),
m_start(false),
m_printLog(true),
m_isFile(false) {
m_isFile(false),
m_initLoad(false) {
m_taskLoad.set_slot(rak::mem_fn(this, &DownloadFactory::receive_load));
m_taskCommit.set_slot(rak::mem_fn(this, &DownloadFactory::receive_commit));
m_taskLoad.slot() = std::bind(&DownloadFactory::receive_load, this);
m_taskCommit.slot() = std::bind(&DownloadFactory::receive_commit, this);
// m_variables["connection_leech"] = rpc::call_command_void("protocol.connection.leech");
// m_variables["connection_seed"] = rpc::call_command_void("protocol.connection.seed");
// m_variables["connection_leech"] = rpc::call_command("protocol.connection.leech");
// m_variables["connection_seed"] = rpc::call_command("protocol.connection.seed");
m_variables["connection_leech"] = std::string();
m_variables["connection_seed"] = std::string();
m_variables["directory"] = rpc::call_command_void("directory.default");
m_variables["directory"] = rpc::call_command("directory.default");
m_variables["tied_to_file"] = torrent::Object((int64_t)false);
}
@@ -205,16 +172,26 @@ 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;
if (download == NULL) {
// core::Manager should already have added the error message to
// the log.
m_slotFinished();
m_slot_finished();
return;
}
@@ -224,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)
@@ -232,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
@@ -245,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());
@@ -253,26 +235,30 @@ DownloadFactory::receive_success() {
if (!rtorrent->has_key_string("custom4")) rtorrent->insert_key("custom4", std::string());
if (!rtorrent->has_key_string("custom5")) rtorrent->insert_key("custom5", std::string());
rpc::call_command("d.uploads_min.set", rpc::call_command_void("throttle.min_uploads"), rpc::make_target(download));
rpc::call_command("d.uploads_max.set", rpc::call_command_void("throttle.max_uploads"), rpc::make_target(download));
rpc::call_command("d.downloads_min.set", rpc::call_command_void("throttle.min_downloads"), rpc::make_target(download));
rpc::call_command("d.downloads_max.set", rpc::call_command_void("throttle.max_downloads"), rpc::make_target(download));
rpc::call_command("d.peers_min.set", rpc::call_command_void("throttle.min_peers.normal"), rpc::make_target(download));
rpc::call_command("d.peers_max.set", rpc::call_command_void("throttle.max_peers.normal"), rpc::make_target(download));
rpc::call_command("d.tracker_numwant.set", rpc::call_command_void("trackers.numwant"), rpc::make_target(download));
rpc::call_command("d.max_file_size.set", rpc::call_command_void("system.file.max_size"), rpc::make_target(download));
rpc::call_command("d.uploads_min.set", rpc::call_command("throttle.min_uploads"), rpc::make_target(download));
rpc::call_command("d.uploads_max.set", rpc::call_command("throttle.max_uploads"), rpc::make_target(download));
rpc::call_command("d.downloads_min.set", rpc::call_command("throttle.min_downloads"), rpc::make_target(download));
rpc::call_command("d.downloads_max.set", rpc::call_command("throttle.max_downloads"), rpc::make_target(download));
rpc::call_command("d.peers_min.set", rpc::call_command("throttle.min_peers.normal"), rpc::make_target(download));
rpc::call_command("d.peers_max.set", rpc::call_command("throttle.max_peers.normal"), rpc::make_target(download));
rpc::call_command("d.tracker_numwant.set", rpc::call_command("trackers.numwant"), rpc::make_target(download));
rpc::call_command("d.max_file_size.set", rpc::call_command("system.file.max_size"), rpc::make_target(download));
if (rpc::call_command_value("d.complete", rpc::make_target(download)) != 0) {
if (rpc::call_command_value("throttle.min_peers.seed") >= 0)
rpc::call_command("d.peers_min.set", rpc::call_command_void("throttle.min_peers.seed"), rpc::make_target(download));
rpc::call_command("d.peers_min.set", rpc::call_command("throttle.min_peers.seed"), rpc::make_target(download));
if (rpc::call_command_value("throttle.max_peers.seed") >= 0)
rpc::call_command("d.peers_max.set", rpc::call_command_void("throttle.max_peers.seed"), rpc::make_target(download));
rpc::call_command("d.peers_max.set", rpc::call_command("throttle.max_peers.seed"), rpc::make_target(download));
}
if (!rpc::call_command_value("trackers.use_udp"))
download->enable_udp_trackers(false);
// Skip forcing trackers to scrape when rtorrent starts
if (m_initLoad && rpc::call_command_value("trackers.delay_scrape"))
download->set_resume_flags(torrent::Download::start_skip_tracker);
// Check first if we already have these values set in the session
// torrent, so that it is safe to change the values.
//
@@ -302,7 +288,7 @@ DownloadFactory::receive_success() {
// ATM doesn't really ever get here.
delete download;
m_slotFinished();
m_slot_finished();
return;
}
@@ -310,8 +296,12 @@ DownloadFactory::receive_success() {
torrent::HashString infohash = download->info()->hash();
try {
std::for_each(m_commands.begin(), m_commands.end(),
rak::bind2nd(std::ptr_fun(&rpc::parse_command_multiple_std), rpc::make_target(download)));
if (torrent::log_groups[torrent::LOG_TORRENT_DEBUG].valid())
log_created(download, rtorrent);
std::for_each(m_commands.begin(), m_commands.end(), [&download](const std::string& cmd) {
rpc::parse_command_multiple_std(cmd, rpc::make_target(download));
});
if (m_manager->download_list()->find(infohash) == m_manager->download_list()->end())
throw torrent::input_error("The newly created download was removed.");
@@ -325,11 +315,9 @@ DownloadFactory::receive_success() {
} catch (torrent::input_error& e) {
std::string msg = "Command on torrent creation failed: " + std::string(e.what());
if (m_printLog) {
m_manager->get_log_important().push_front(msg);
m_manager->get_log_complete().push_front(msg);
}
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);
@@ -338,18 +326,42 @@ DownloadFactory::receive_success() {
}
}
m_slotFinished();
m_slot_finished();
}
void
DownloadFactory::log_created(Download* download, torrent::Object* rtorrent) {
std::stringstream dump;
dump << "info_hash = " << torrent::hash_string_to_hex_str(download->info()->hash()) << std::endl;
dump << "session = " << (m_session ? "true" : "false") << std::endl;
if (download->download()->info()->is_meta_download())
dump << "magnet = true" << std::endl;
if (!rtorrent->has_key_string("directory"))
dump << "directory = \"" << (m_variables["directory"].is_string() ? m_variables["directory"].as_string() : std::string()) << '"' << std::endl;
else
dump << "directory_base = \"" << (rtorrent->get_key("directory").is_string() ? rtorrent->get_key("directory").as_string() : std::string()) << '"' << std::endl;
dump << "---COMMANDS---" << std::endl;
for (command_list_type::const_iterator itr = m_commands.begin(); itr != m_commands.end(); itr++) {
dump << *itr << std::endl;
}
std::string dump_str = dump.str();
lt_log_print_dump(torrent::LOG_TORRENT_DEBUG, dump_str.c_str(), dump_str.size(), "Creating new download:");
}
void
DownloadFactory::receive_failed(const std::string& msg) {
// Add message to log.
if (m_printLog) {
m_manager->get_log_important().push_front(msg + ": \"" + m_uri + "\"");
m_manager->get_log_complete().push_front(msg + ": \"" + m_uri + "\"");
}
if (m_printLog)
m_manager->push_log_std(msg + ": \"" + m_uri + "\"");
m_slotFinished();
m_slot_finished();
}
void
@@ -380,17 +392,12 @@ 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"));
if (rtorrent->has_key_value("total_downloaded"))
download->info()->mutable_down_rate()->set_total(rtorrent->get_key_value("total_downloaded"));
if (rtorrent->has_key_value("chunks_done") && rtorrent->has_key_value("chunks_wanted"))
download->download()->set_chunks_done(rtorrent->get_key_value("chunks_done"), rtorrent->get_key_value("chunks_wanted"));
+11 -4
View File
@@ -41,8 +41,9 @@
#ifndef RTORRENT_CORE_DOWNLOAD_FACTORY_H
#define RTORRENT_CORE_DOWNLOAD_FACTORY_H
#include <functional>
#include <iosfwd>
#include <sigc++/functors/slot.h>
#include <rak/priority_queue_default.h>
#include <torrent/object.h>
@@ -54,7 +55,7 @@ class Manager;
class DownloadFactory {
public:
typedef sigc::slot<void> Slot;
typedef std::function<void ()> slot_void;
typedef std::vector<std::string> command_list_type;
// Do not destroy this object while it is in a HttpQueue.
@@ -77,10 +78,13 @@ public:
bool get_start() const { return m_start; }
void set_start(bool v) { m_start = v; }
bool get_init_load() const { return m_initLoad; }
void set_init_load(bool v) { m_initLoad = v; }
bool print_log() const { return m_printLog; }
void set_print_log(bool v) { m_printLog = v; }
void slot_finished(Slot s) { m_slotFinished = s; }
void slot_finished(slot_void s) { m_slot_finished = s; }
private:
void receive_load();
@@ -89,6 +93,8 @@ private:
void receive_success();
void receive_failed(const std::string& msg);
void log_created(Download* download, torrent::Object* rtorrent);
void initialize_rtorrent(Download* download, torrent::Object* rtorrent);
Manager* m_manager;
@@ -103,11 +109,12 @@ private:
bool m_start;
bool m_printLog;
bool m_isFile;
bool m_initLoad;
command_list_type m_commands;
torrent::Object::map_type m_variables;
Slot m_slotFinished;
slot_void m_slot_finished;
rak::priority_item m_taskLoad;
rak::priority_item m_taskCommit;
};
+71 -80
View File
@@ -1,46 +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 <sigc++/adaptors/bind.h>
#include <rak/functional.h>
#include <rak/string_manip.h>
#include <torrent/data/file.h>
#include <torrent/utils/resume.h>
@@ -64,6 +26,7 @@
#include "download.h"
#include "download_list.h"
#include "download_store.h"
#include "ui/root.h"
#define DL_TRIGGER_EVENT(download, event_name) \
rpc::commands.call_catch(event_name, rpc::make_target(download), torrent::Object(), "Event '" event_name "' failed: ");
@@ -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,25 +43,26 @@ 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.");
control->dht_manager()->save_dht_cache();
control->ui()->save_input_history();
}
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
@@ -108,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*
@@ -119,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;
@@ -140,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()) {
@@ -158,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;
@@ -178,14 +142,16 @@ DownloadList::iterator
DownloadList::insert(Download* download) {
iterator itr = base_type::insert(end(), download);
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Inserting download.");
try {
(*itr)->data()->slot_initial_hash() = std::bind(&DownloadList::hash_done, this, download);
(*itr)->data()->slot_download_done() = std::bind(&DownloadList::received_finished, this, 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");
@@ -208,6 +174,8 @@ DownloadList::erase(iterator itr) {
if (itr == end())
throw torrent::internal_error("DownloadList::erase(...) could not find download.");
lt_log_print_info(torrent::LOG_TORRENT_INFO, (*itr)->info(), "download_list", "Erasing download.");
// Makes sure close doesn't restart hashing of this download.
(*itr)->set_hash_failed(true);
@@ -216,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;
@@ -242,6 +210,8 @@ void
DownloadList::open_throw(Download* download) {
check_contains(download);
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Opening download.");
if (download->download()->info()->is_open())
return;
@@ -257,7 +227,6 @@ DownloadList::open_throw(Download* download) {
void
DownloadList::close(Download* download) {
try {
close_throw(download);
} catch (torrent::local_error& e) {
@@ -267,6 +236,8 @@ DownloadList::close(Download* download) {
void
DownloadList::close_directly(Download* download) {
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Closing download directly.");
if (download->download()->info()->is_active()) {
download->download()->stop(torrent::Download::stop_skip_tracker);
@@ -280,6 +251,7 @@ DownloadList::close_directly(Download* download) {
void
DownloadList::close_quick(Download* download) {
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Closing download quickly.");
close(download);
// Make sure we cancel any tracker requests. This should rather be
@@ -293,6 +265,8 @@ void
DownloadList::close_throw(Download* download) {
check_contains(download);
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Closing download with throw.");
// When pause gets called it will clear the initial hash check state
// and set hash failed. This should ensure hashing doesn't restart
// until resume gets called.
@@ -324,6 +298,8 @@ void
DownloadList::resume(Download* download, int flags) {
check_contains(download);
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Resuming download: flags:%0x.", flags);
try {
if (download->download()->info()->is_active())
@@ -361,26 +337,26 @@ DownloadList::resume(Download* download, int flags) {
rpc::call_command("d.state_counter.set", rpc::call_command_value("d.state_counter", rpc::make_target(download)) + 1, rpc::make_target(download));
if (download->is_done()) {
torrent::Object conn_current = rpc::call_command_void("d.connection_seed", rpc::make_target(download));
torrent::Object choke_up = rpc::call_command_void("d.up.choke_heuristics.seed", rpc::make_target(download));
torrent::Object choke_down = rpc::call_command_void("d.down.choke_heuristics.seed", rpc::make_target(download));
torrent::Object conn_current = rpc::call_command("d.connection_seed", torrent::Object(), rpc::make_target(download));
torrent::Object choke_up = rpc::call_command("d.up.choke_heuristics.seed", torrent::Object(), rpc::make_target(download));
torrent::Object choke_down = rpc::call_command("d.down.choke_heuristics.seed", torrent::Object(), rpc::make_target(download));
if (conn_current.is_string_empty()) conn_current = rpc::call_command_void("protocol.connection.seed", rpc::make_target(download));
if (choke_up.is_string_empty()) choke_up = rpc::call_command_void("protocol.choke_heuristics.up.seed", rpc::make_target(download));
if (choke_down.is_string_empty()) choke_down = rpc::call_command_void("protocol.choke_heuristics.down.seed", rpc::make_target(download));
if (conn_current.is_string_empty()) conn_current = rpc::call_command("protocol.connection.seed", torrent::Object(), rpc::make_target(download));
if (choke_up.is_string_empty()) choke_up = rpc::call_command("protocol.choke_heuristics.up.seed", torrent::Object(), rpc::make_target(download));
if (choke_down.is_string_empty()) choke_down = rpc::call_command("protocol.choke_heuristics.down.seed", torrent::Object(), rpc::make_target(download));
rpc::call_command("d.connection_current.set", conn_current, rpc::make_target(download));
rpc::call_command("d.up.choke_heuristics.set", choke_up, rpc::make_target(download));
rpc::call_command("d.down.choke_heuristics.set", choke_down, rpc::make_target(download));
} else {
torrent::Object conn_current = rpc::call_command_void("d.connection_leech", rpc::make_target(download));
torrent::Object choke_up = rpc::call_command_void("d.up.choke_heuristics.leech", rpc::make_target(download));
torrent::Object choke_down = rpc::call_command_void("d.down.choke_heuristics.leech", rpc::make_target(download));
torrent::Object conn_current = rpc::call_command("d.connection_leech", torrent::Object(), rpc::make_target(download));
torrent::Object choke_up = rpc::call_command("d.up.choke_heuristics.leech", torrent::Object(), rpc::make_target(download));
torrent::Object choke_down = rpc::call_command("d.down.choke_heuristics.leech", torrent::Object(), rpc::make_target(download));
if (conn_current.is_string_empty()) conn_current = rpc::call_command_void("protocol.connection.leech", rpc::make_target(download));
if (choke_up.is_string_empty()) choke_up = rpc::call_command_void("protocol.choke_heuristics.up.leech", rpc::make_target(download));
if (choke_down.is_string_empty()) choke_down = rpc::call_command_void("protocol.choke_heuristics.down.leech", rpc::make_target(download));
if (conn_current.is_string_empty()) conn_current = rpc::call_command("protocol.connection.leech", torrent::Object(), rpc::make_target(download));
if (choke_up.is_string_empty()) choke_up = rpc::call_command("protocol.choke_heuristics.up.leech", torrent::Object(), rpc::make_target(download));
if (choke_down.is_string_empty()) choke_down = rpc::call_command("protocol.choke_heuristics.down.leech", torrent::Object(), rpc::make_target(download));
rpc::call_command("d.connection_current.set", conn_current, rpc::make_target(download));
rpc::call_command("d.up.choke_heuristics.set", choke_up, rpc::make_target(download));
@@ -417,6 +393,8 @@ void
DownloadList::pause(Download* download, int flags) {
check_contains(download);
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Pausing download: flags:%0x.", flags);
try {
download->set_resume_flags(~uint32_t());
@@ -448,8 +426,8 @@ DownloadList::pause(Download* download, int flags) {
// If initial seeding is complete, don't try it again when restarting.
if (download->is_done() &&
rpc::call_command_void("d.connection_current", rpc::make_target(download)).as_string() == "initial_seed")
rpc::call_command("d.connection_seed.set", rpc::call_command_void("d.connection_current", rpc::make_target(download)), rpc::make_target(download));
rpc::call_command("d.connection_current", torrent::Object(), rpc::make_target(download)).as_string() == "initial_seed")
rpc::call_command("d.connection_seed.set", rpc::call_command("d.connection_current", torrent::Object(), rpc::make_target(download)), rpc::make_target(download));
// Save the state after all the slots, etc have been called so we
// include the modifications they may make.
@@ -464,8 +442,9 @@ void
DownloadList::check_hash(Download* download) {
check_contains(download);
try {
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Checking hash.");
try {
if (rpc::call_command_value("d.hashing", rpc::make_target(download)) != Download::variable_hashing_stopped)
return;
@@ -480,6 +459,8 @@ void
DownloadList::hash_done(Download* download) {
check_contains(download);
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Hash done.");
if (download->is_hash_checking() || download->is_active())
throw torrent::internal_error("DownloadList::hash_done(...) download in invalid state.");
@@ -532,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");
}
@@ -554,6 +535,8 @@ void
DownloadList::hash_queue(Download* download, int type) {
check_contains(download);
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Hash queue.");
if (rpc::call_command_value("d.hashing", rpc::make_target(download)) != Download::variable_hashing_stopped)
throw torrent::internal_error("DownloadList::hash_queue(...) hashing already queued.");
@@ -583,6 +566,8 @@ void
DownloadList::received_finished(Download* download) {
check_contains(download);
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Received finished.");
if (rpc::call_command_value("pieces.hash.on_completion"))
// Set some 'checking_finished_thingie' variable to make hash_done
// trigger correctly, also so it can bork on missing data.
@@ -596,19 +581,21 @@ void
DownloadList::confirm_finished(Download* download) {
check_contains(download);
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Confirming finished.");
if (download->download()->info()->is_meta_download())
return process_meta_download(download);
rpc::call_command("d.complete.set", (int64_t)1, rpc::make_target(download));
// Clean up these settings:
torrent::Object conn_current = rpc::call_command_void("d.connection_seed", rpc::make_target(download));
torrent::Object choke_up = rpc::call_command_void("d.up.choke_heuristics.seed", rpc::make_target(download));
torrent::Object choke_down = rpc::call_command_void("d.down.choke_heuristics.seed", rpc::make_target(download));
torrent::Object conn_current = rpc::call_command("d.connection_seed", torrent::Object(), rpc::make_target(download));
torrent::Object choke_up = rpc::call_command("d.up.choke_heuristics.seed", torrent::Object(), rpc::make_target(download));
torrent::Object choke_down = rpc::call_command("d.down.choke_heuristics.seed", torrent::Object(), rpc::make_target(download));
if (conn_current.is_string_empty()) conn_current = rpc::call_command_void("protocol.connection.seed", rpc::make_target(download));
if (choke_up.is_string_empty()) choke_up = rpc::call_command_void("protocol.choke_heuristics.up.seed", rpc::make_target(download));
if (choke_down.is_string_empty()) choke_down = rpc::call_command_void("protocol.choke_heuristics.down.seed", rpc::make_target(download));
if (conn_current.is_string_empty()) conn_current = rpc::call_command("protocol.connection.seed", torrent::Object(), rpc::make_target(download));
if (choke_up.is_string_empty()) choke_up = rpc::call_command("protocol.choke_heuristics.up.seed", torrent::Object(), rpc::make_target(download));
if (choke_down.is_string_empty()) choke_down = rpc::call_command("protocol.choke_heuristics.down.seed", torrent::Object(), rpc::make_target(download));
rpc::call_command("d.connection_current.set", conn_current, rpc::make_target(download));
rpc::call_command("d.up.choke_heuristics.set", choke_up, rpc::make_target(download));
@@ -618,11 +605,11 @@ DownloadList::confirm_finished(Download* download) {
if (rpc::call_command_value("d.peers_min", rpc::make_target(download)) == rpc::call_command_value("throttle.min_peers.normal") &&
rpc::call_command_value("throttle.min_peers.seed") >= 0)
rpc::call_command("d.peers_min.set", rpc::call_command_void("throttle.min_peers.seed"), rpc::make_target(download));
rpc::call_command("d.peers_min.set", rpc::call_command("throttle.min_peers.seed"), rpc::make_target(download));
if (rpc::call_command_value("d.peers_max", rpc::make_target(download)) == rpc::call_command_value("throttle.max_peers.normal") &&
rpc::call_command_value("throttle.max_peers.seed") >= 0)
rpc::call_command("d.peers_max.set", rpc::call_command_void("throttle.max_peers.seed"), rpc::make_target(download));
rpc::call_command("d.peers_max.set", rpc::call_command("throttle.max_peers.seed"), rpc::make_target(download));
// Do this before the slots are called in case one of them closes
// the download.
@@ -642,6 +629,9 @@ DownloadList::confirm_finished(Download* download) {
DL_TRIGGER_EVENT(download, "event.download.finished");
if (find(infohash) == end())
return;
// if (download->resume_flags() != ~uint32_t())
// throw torrent::internal_error("DownloadList::confirm_finished(...) download->resume_flags() != ~uint32_t().");
@@ -655,8 +645,7 @@ DownloadList::confirm_finished(Download* download) {
// being hashed.
download->set_resume_flags(~uint32_t());
if (find(infohash) != end() &&
!download->is_active() && rpc::call_command_value("d.state", rpc::make_target(download)) == 1)
if (!download->is_active() && rpc::call_command_value("d.state", rpc::make_target(download)) == 1)
resume(download,
torrent::Download::start_no_create |
torrent::Download::start_skip_tracker |
@@ -665,6 +654,8 @@ DownloadList::confirm_finished(Download* download) {
void
DownloadList::process_meta_download(Download* download) {
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Processing meta download.");
rpc::call_command("d.stop", torrent::Object(), rpc::make_target(download));
rpc::call_command("d.close", torrent::Object(), rpc::make_target(download));
+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);
+6 -6
View File
@@ -37,21 +37,21 @@
#ifndef RTORRENT_CORE_DOWNLOAD_SLOT_MAP_H
#define RTORRENT_CORE_DOWNLOAD_SLOT_MAP_H
#include <functional>
#include <map>
#include <string>
#include <sigc++/functors/slot.h>
#include "download.h"
namespace core {
class DownloadSlotMap : public std::map<std::string, sigc::slot1<void, Download*> > {
class DownloadSlotMap : public std::map<std::string, std::function<void (Download*)> > {
public:
typedef sigc::slot1<void, Download*> SlotDownload;
typedef std::map<std::string, SlotDownload> Base;
typedef std::function<void (Download*)> slot_download;
typedef std::map<std::string, slot_download> Base;
void insert(const std::string& key, SlotDownload s) { Base::operator[](key) = s; }
void erase(const std::string& key) { Base::erase(key); }
void insert(const std::string& key, slot_download s) { Base::operator[](key) = s; }
void erase(const std::string& key) { Base::erase(key); }
void for_each(Download* d);
};
+22 -39
View File
@@ -1,45 +1,10 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// DownloadStore handles the saving and listing of session torrents.
#include "config.h"
#include <fstream>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <rak/error_number.h>
#include <rak/path.h>
@@ -55,6 +20,7 @@
#include "download.h"
#include "download_store.h"
#include "rpc/parse_commands.h"
namespace core {
@@ -100,6 +66,7 @@ DownloadStore::set_path(const std::string& path) {
bool
DownloadStore::write_bencode(const std::string& filename, const torrent::Object& obj, uint32_t skip_mask) {
int fd;
torrent::Object tmp;
std::fstream output(filename.c_str(), std::ios::out | std::ios::trunc);
@@ -121,6 +88,21 @@ DownloadStore::write_bencode(const std::string& filename, const torrent::Object&
goto download_store_save_error;
output.close();
// Ensure that the new file is actually written to the disk
fd = ::open(filename.c_str(), O_WRONLY);
if (fd < 0)
goto download_store_save_error;
if (rpc::call_command_value("system.files.session.fdatasync")) {
#ifdef __APPLE__
fsync(fd);
#else
fdatasync(fd);
#endif
::close(fd);
}
return true;
download_store_save_error:
@@ -140,6 +122,7 @@ DownloadStore::save(Download* d, int flags) {
rtorrent_base->insert_key("chunks_done", d->download()->file_list()->completed_chunks());
rtorrent_base->insert_key("chunks_wanted", d->download()->data()->wanted_chunks());
rtorrent_base->insert_key("total_uploaded", d->info()->up_rate()->total());
rtorrent_base->insert_key("total_downloaded", d->info()->down_rate()->total());
// Don't save for completed torrents when we've cleared the uncertain_pieces.
torrent::resume_save_progress(*d->download(), *resume_base);
@@ -161,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());
@@ -182,7 +165,7 @@ DownloadStore::remove(Download* d) {
// This also needs to check that it isn't a directory.
bool
not_correct_format(const utils::directory_entry& entry) {
return !DownloadStore::is_correct_format(entry.d_name);
return !DownloadStore::is_correct_format(entry.s_name);
}
utils::Directory
@@ -195,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
+15 -17
View File
@@ -38,45 +38,43 @@
#include <memory>
#include <sstream>
#include <sigc++/adaptors/bind.h>
#include <sigc++/adaptors/hide.h>
#include <torrent/http.h>
#include "rak/functional.h"
#include "http_queue.h"
#include "curl_get.h"
namespace std { using namespace tr1; }
namespace core {
HttpQueue::iterator
HttpQueue::insert(const std::string& url, std::iostream* s) {
std::auto_ptr<CurlGet> h(m_slotFactory());
std::unique_ptr<CurlGet> h(m_slot_factory());
h->set_url(url);
h->set_stream(s);
h->set_timeout(5 * 60);
iterator itr = Base::insert(end(), h.get());
iterator signal_itr = base_type::insert(end(), h.get());
h->signal_done().push_back(std::bind(&HttpQueue::erase, this, itr));
h->signal_failed().push_back(std::bind(&HttpQueue::erase, this, itr));
h->signal_done().push_back(std::bind(&HttpQueue::erase, this, signal_itr));
h->signal_failed().push_back(std::bind(&HttpQueue::erase, this, signal_itr));
(*itr)->start();
(*signal_itr)->start();
h.release();
m_signalInsert.emit(*itr);
return itr;
for (signal_curl_get::iterator itr = m_signal_insert.begin(), last = m_signal_insert.end(); itr != last; itr++)
(*itr)(*signal_itr);
return signal_itr;
}
void
HttpQueue::erase(iterator itr) {
m_signalErase.emit(*itr);
HttpQueue::erase(iterator signal_itr) {
for (signal_curl_get::iterator itr = m_signal_erase.begin(), last = m_signal_erase.end(); itr != last; itr++)
(*itr)(*signal_itr);
delete *itr;
Base::erase(itr);
delete *signal_itr;
base_type::erase(signal_itr);
}
void
@@ -84,7 +82,7 @@ HttpQueue::clear() {
while (!empty())
erase(begin());
Base::clear();
base_type::clear();
}
}
+22 -21
View File
@@ -37,9 +37,9 @@
#ifndef RTORRENT_CORE_HTTP_QUEUE_H
#define RTORRENT_CORE_HTTP_QUEUE_H
#include <list>
#include <functional>
#include <iosfwd>
#include <sigc++/signal.h>
#include <list>
namespace core {
@@ -47,22 +47,23 @@ class CurlGet;
class HttpQueue : private std::list<CurlGet*> {
public:
typedef std::list<CurlGet*> Base;
typedef sigc::signal1<void, CurlGet*> SignalHttp;
typedef sigc::slot0<CurlGet*> SlotFactory;
typedef std::list<CurlGet*> base_type;
typedef std::function<CurlGet* ()> slot_factory;
typedef std::function<void (CurlGet*)> slot_curl_get;
typedef std::list<slot_curl_get> signal_curl_get;
using Base::iterator;
using Base::const_iterator;
using Base::reverse_iterator;
using Base::const_reverse_iterator;
using base_type::iterator;
using base_type::const_iterator;
using base_type::reverse_iterator;
using base_type::const_reverse_iterator;
using Base::begin;
using Base::end;
using Base::rbegin;
using Base::rend;
using base_type::begin;
using base_type::end;
using base_type::rbegin;
using base_type::rend;
using Base::empty;
using Base::size;
using base_type::empty;
using base_type::size;
HttpQueue() {}
~HttpQueue() { clear(); }
@@ -77,15 +78,15 @@ public:
void clear();
void slot_factory(SlotFactory s) { m_slotFactory = s; }
void set_slot_factory(slot_factory s) { m_slot_factory = s; }
SignalHttp& signal_insert() { return m_signalInsert; }
SignalHttp& signal_erase() { return m_signalErase; }
signal_curl_get& signal_insert() { return m_signal_insert; }
signal_curl_get& signal_erase() { return m_signal_erase; }
private:
SlotFactory m_slotFactory;
SignalHttp m_signalInsert;
SignalHttp m_signalErase;
slot_factory m_slot_factory;
signal_curl_get m_signal_insert;
signal_curl_get m_signal_erase;
};
}

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