Compare commits

...

119 Commits

Author SHA1 Message Date
rakshasa d3ecc83b32 Release 0.15.7. 2025-09-05 07:28:59 +00:00
Bryant Eadon 457d5170b8 cleanup of personal information
Given the change to the README I thought it might be a good idea to also update the copyright notices which had an address too.
2025-09-05 07:28:47 +00:00
Jari Sundell 1c598d51ef Fix formatting and capitalization in README.md 2025-09-05 07:28:34 +00:00
Jari Sundell 644ea6c23f Revise README structure and donation information
Updated sections in README for clarity and formatting.
2025-09-05 07:28:25 +00:00
Bryant Eadon de3615a72c README combined
Combined README files to reduce clutter.  However, the build instructions are incomplete ... I've started by modifying these so a build will complete using the instructions once I get a closer look at libtorrent ... additions welcome.
2025-09-05 07:28:18 +00:00
Bryant Eadon e9e4064bb3 Delete uused file
minor cleanup.
2025-09-05 07:28:10 +00:00
Bryant Eadon 04fc51e76b Update README.md
proposing a new message for the release download.  to draw attention to the github repo, instead of the archive.
2025-09-05 07:28:02 +00:00
rakshasa 24693fc19e Release 0.15.6. 2025-08-23 08:08:36 +00:00
rakshasa 9661a2aaa9 Added test for xmlrpc string reflection. 2025-08-11 10:18:20 +02:00
rakshasa aaf42c247e Strict checking of d.views push_back arguments. 2025-08-11 10:16:23 +02:00
rakshasa cba48f4a10 Invert color of focus ui element. 2025-08-11 10:14:46 +02:00
rakshasa 4463bf418e Release 0.15.5. 2025-06-22 16:44:05 +00:00
Phil Rosenthal 8bd7c79755 Fix file descriptor leak in session file saving
When system.files.session.fdatasync is set to "no", file descriptors
  were not being closed after writing session files, causing a severe
  resource leak. Each save operation would leak one file descriptor.

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

  The fix moves the close() call outside the fdatasync conditional block,
  ensuring file descriptors are always properly closed regardless of the
  fdatasync setting.
2025-06-18 19:04:45 +02:00
rakshasa f2b83d50e8 Use libtorrent stable-0.15 branch in workflow. 2025-06-08 13:01:36 +02:00
rakshasa ab40059891 Use libtorrent stable-0.15 branch in workflow. 2025-06-08 13:01:36 +02:00
rakshasa b9d880dea3 Properly handle -1 value passed to curl set_timeout. 2025-06-08 13:01:36 +02:00
rakshasa b4c59d2c7a Fixed corrupted stack in curl stack due to wrong argument type. 2025-06-07 13:17:34 +02:00
rakshasa 231606afc1 Fix ExecFile waitpid error handling. 2025-06-01 18:41:22 +02:00
rakshasa a9196b43d4 Added missing header to Makefile.am. 2025-06-01 15:40:22 +02:00
rakshasa 8203949259 Removed deprecated headers from Makefile.am. 2025-06-01 15:27:42 +02:00
rakshasa 537c692f47 Tagged release 0.15.4. 2025-06-01 14:44:29 +02:00
Rosen Penev 95b1a19ef1 use _T sizes for curl
The non _T are deprecated.

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

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

Could also add const to it.

Do the same with color_names.

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

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

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

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-04-15 10:07:29 +02:00
rakshasa 316b0b51d5 Use new thread event loop method. 2025-04-14 11:15:07 +02:00
rakshasa a8622e5c80 Cleaned up thread-related code. 2025-04-12 23:03:08 +02:00
Abzie d1dd5ac080 Add RPC options to rtorrent.rc-example documentation 2025-04-11 16:16:44 +02:00
Abzie 9f2b81534a Add RPC options to rtorrent.rc documentation 2025-04-11 16:16:44 +02:00
Jari Sundell 2ab7460cbc Fix SCGI threading and added missing header. 2025-04-01 01:26:07 +09:00
rakshasa 2a998df4f1 Fixed LUA compilaition issue. 2025-03-31 06:19:02 +02:00
rakshasa d5b28c30a9 Added default switch cases to RpcManager. 2025-03-30 15:38:07 +02:00
rakshasa a5a1e2fde5 Updated common.m4. 2025-03-30 15:38:07 +02:00
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
260 changed files with 31790 additions and 7860 deletions
@@ -0,0 +1,96 @@
# 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: Sleep for 30 seconds
run: sleep 30s
shell: bash
- 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 }}
@@ -14,6 +14,8 @@ jobs:
- name: Fetch libtorrent
run: |
git clone https://github.com/rakshasa/libtorrent
cd libtorrent
git checkout stable-0.15
- name: Build libtorrent
run: |
cd libtorrent
@@ -54,7 +56,7 @@ jobs:
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
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
@@ -64,69 +66,17 @@ jobs:
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
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
# - 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
+58
View File
@@ -0,0 +1,58 @@
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
cd libtorrent
git checkout stable-0.15
- name: Build libtorrent
run: |
cd libtorrent
libtoolize
aclocal -I scripts
autoconf -i
autoheader
automake --add-missing
./configure
make
sudo make install
cd ..
rm -rf libtorrent
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- name: Fetch base branch
run: |
git remote add upstream "https://github.com/${{ github.event.pull_request.base.repo.full_name }}"
git fetch --no-tags --no-recurse-submodules upstream "${{ github.event.pull_request.base.ref }}"
- name: Install Dependencies
run: |
sudo apt-get install -y \
libcppunit-dev \
libcurl4-openssl-dev
- name: Configure Project
run: |
libtoolize
aclocal -I scripts
autoconf -i
autoheader
automake --add-missing
./configure
- name: Build Project
run: |
make
- name: Run Unit Tests
run: |
make check
+2 -2
View File
@@ -18,6 +18,7 @@
.libs
Makefile
aclocal.m4
ar-lib
autom4te.cache
compile
config.h
@@ -67,6 +68,5 @@ TAGS
# rTorrent specific files
###########################
src/rtorrent
test/rtorrentTest
test/rtorrent_Test*
test-driver
test/rtorrentTest.trs
+1 -5
View File
@@ -4,21 +4,17 @@ SUBDIRS = \
test
EXTRA_DIST= \
rtorrent.lua \
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/path.h \
rak/partial_queue.h \
rak/priority_queue.h \
rak/priority_queue_default.h \
rak/regex.h \
rak/socket_address.h \
rak/string_manip.h \
rak/timer.h \
rak/unordered_vector.h \
scripts/checks.m4 \
scripts/common.m4 \
View File
-41
View File
@@ -1,41 +0,0 @@
BUILDING
Run "aclocal -I scripts && autoconf -i && autoheader && automake --add-missing"
to generate the configure scripts if necessary. The man page "doc/rtorrent.1"
must be generated with "docbook2man rtorrent.1.xml" if it is missing.
Note that rtorrent follows the development of libtorrent closely, and
thus the versions must be in sync. This should not be nessesary in the
future, when the library API stabilizes.
USAGE
See the man page or website for instructions.
LICENSE
GNU GPL, see COPYING. "libtorrent/src/utils/sha_fast.{cc,h}" is
originally from the Mozilla NSS and is under a triple license; MPL,
LGPL and GPL. An exception to non-NSS code has been added for linking
to OpenSSL as requested by Debian, though the author considers that
library to be part of the Operative System and thus linking is allowed
according to the GPL.
Use whatever fits your purpose, the code required to compile with
Mozilla's NSS implementation of SHA1 has been retained and can be
compiled if the user wishes to avoid using OpenSSL.
DEPENDENCIES
libcurl >= 7.12.0
ncurses
CONTACT
Jari Sundell
Skomakerveien 33
3185 Skoppum, NORWAY
Send bug reports, suggestions and patches to
<sundell.software@gmail.com> or to the mailinglist.
+69 -21
View File
@@ -1,40 +1,88 @@
[![Donate](https://rakshasa.github.io/rtorrent/donate_paypal_green.svg)](https://paypal.me/jarisundelljp)
RTorrent BitTorrent Client
========
Introduction
------------
A ncurses-based command line torrent client for high performance.
To learn how to use rTorrent visit the [Wiki](https://github.com/rakshasa/rtorrent/wiki).
Stable
------
* [https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.13.8.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.13.8.tar.gz)
* [https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.9.8.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.9.8.tar.gz)
Unstable
------
* [https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.14.0.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.14.0.tar.gz)
* [https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.10.0.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.10.0.tar.gz)
Download the [latest stable release](https://github.com/rakshasa/rtorrent/releases/latest)
Related Projects
----------------
* [https://github.com/rakshasa/rbedit](https://github.com/rakshasa/rbedit): A dependency-free bencode editor.
* [https://github.com/rakshasa/rbedit](https://github.com/rakshasa/rbedit): A dependency-free bencode editor.
Donate to rTorrent development
------------------------------
* [Paypal](https://paypal.me/jarisundellno)
* [Patreon](https://www.patreon.com/rtorrent)
* [SubscribeStar](https://www.subscribestar.com/rtorrent)
* Bitcoin: 1MpmXm5AHtdBoDaLZstJw8nupJJaeKu8V8
* Ethereum: 0x9AB1e3C3d8a875e870f161b3e9287Db0E6DAfF78
* Litecoin: LdyaVR67LBnTf6mAT4QJnjSG2Zk67qxmfQ
* Cardano: addr1qytaslmqmk6dspltw06sp0zf83dh09u79j49ceh5y26zdcccgq4ph7nmx6kgmzeldauj43254ey97f3x4xw49d86aguqwfhlte
* [Paypal](https://paypal.me/jarisundellno)
* [Patreon](https://www.patreon.com/rtorrent)
* [SubscribeStar](https://www.subscribestar.com/rtorrent)
* Bitcoin: 1MpmXm5AHtdBoDaLZstJw8nupJJaeKu8V8
* Ethereum: 0x9AB1e3C3d8a875e870f161b3e9287Db0E6DAfF78
* Litecoin: LdyaVR67LBnTf6mAT4QJnjSG2Zk67qxmfQ
* Cardano: addr1qytaslmqmk6dspltw06sp0zf83dh09u79j49ceh5y26zdcccgq4ph7nmx6kgmzeldauj43254ey97f3x4xw49d86aguqwfhlte
Help keep rTorrent development going by donating to its creator.
BUILDING
--------
Jump into the github cloned directory
```
cd rtorrent
```
## Install build dependencies
Install [libtorrent](https://libtorrent.org/) with the same version rTorrent.
Generate configure scripts:
```
autoreconf -ivf
```
Optionally, generate man pages:
```
docbook2man rtorrent.1.xml
```
Man pages output to "doc/rtorrent.1".
RTorrent follows the development of [libtorrent](https://libtorrent.org/) closely, and thus the versions must be in sync.
## USAGE
Refer to User Guide: https://github.com/rakshasa/rtorrent/wiki/User-Guide
## LICENSE
GNU GPL, see COPYING. "libtorrent/src/utils/sha_fast.{cc,h}" is
originally from the Mozilla NSS and is under a triple license; MPL,
LGPL and GPL. An exception to non-NSS code has been added for linking to OpenSSL as requested by Debian, though the author considers that library to be part of the Operative System and thus linking is allowed according to the GPL.
Use whatever fits your purpose, the code required to compile with
Mozilla's NSS implementation of SHA1 has been retained and can be
compiled if the user wishes to avoid using OpenSSL.
## DEPENDENCIES
* libcurl >= 7.12.0
* libtorrent = (same version)
* ncurses
## BUILD DEPENDENCIES
* libtoolize
* aclocal
* autoconf
* autoheader
* automake
+16 -15
View File
@@ -1,20 +1,23 @@
m4_pattern_allow([PKG_CHECK_EXISTS])
AC_INIT([rtorrent],[0.15.0],[sundell.software@gmail.com])
AC_INIT([rtorrent],[0.15.7],[sundell.software@gmail.com])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIRS([scripts])
AM_INIT_AUTOMAKE([foreign subdir-objects])
AM_PROG_AR
AC_DEFINE([API_VERSION], [10], [api version])
AC_PROG_RANLIB
AC_PROG_CXX
AC_SYS_LARGEFILE
LT_INIT
AX_CXX_COMPILE_STDCXX([14], [noext], [mandatory])
AC_PROG_CXX
AC_DEFINE([API_VERSION], [15], [api version])
# Filter out unwanted flags added by autoconf on some systems, e.g. MacOS.
TORRENT_REMOVE_UNWANTED(CXX, $CXX, -std=c++11 -std=gnu++11)
AX_CXX_COMPILE_STDCXX([17], [noext], [mandatory])
AC_SYS_LARGEFILE
RAK_CHECK_CFLAGS
RAK_CHECK_CXXFLAGS
@@ -51,12 +54,13 @@ fi
PKG_CHECK_MODULES([LIBCURL], [libcurl],, [LIBCURL_CHECK_CONFIG])
PKG_CHECK_MODULES([CPPUNIT], [cppunit],, [no_cppunit="yes"])
PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.15.0])
PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.15.7])
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
@@ -67,13 +71,6 @@ AC_DEFINE(HAVE_CONFIG_H, 1, true if config.h was included)
AC_DEFINE(USER_AGENT, [std::string(PACKAGE "/" VERSION "/") + torrent::version()], Http user agent)
AC_CHECK_FUNCS(posix_memalign)
TORRENT_CHECK_CACHELINE()
TORRENT_CHECK_POPCOUNT()
CC_ATTRIBUTE_UNUSED(
AC_DEFINE([__UNUSED], [__attribute__((unused))], [Wrapper around unused attribute]),
AC_DEFINE([__UNUSED], [], [Null-wrapper if unused attribute is unsupported])
)
dnl Only update global build variables immediately before generating the output,
dnl to avoid affecting the global build environment for other autoconf checks.
@@ -81,10 +78,14 @@ LIBS="$PTHREAD_LIBS $CURSES_LIB $CURSES_LIBS $LIBCURL $LIBCURL_LIBS $DEPENDENCIE
CFLAGS="$CFLAGS $PTHREAD_CFLAGS $LIBCURL_CPPFLAGS $LIBCURL_CFLAGS $DEPENDENCIES_CFLAGS $CURSES_CFLAGS"
CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS $LIBCURL_CPPFLAGS $LIBCURL_CFLAGS $DEPENDENCIES_CFLAGS $CURSES_CFLAGS"
TORRENT_CHECK_CACHELINE()
TORRENT_CHECK_POPCOUNT()
AC_CONFIG_FILES([
Makefile
doc/Makefile
src/Makefile
test/Makefile
])
AC_OUTPUT
+1 -5
View File
@@ -499,10 +499,6 @@ Number of attempts to check the hash while using the mincore status,
before forcing. Overworked systems might need lower values to get a
decent hash checking rate.
.TP
\fBsafe_sync = \fIyes|no\fB\fR
Always use MS_SYNC rather than MS_ASYNC when syncing chunks. This may
be nessesary in case of filesystem bugs like NFS in linux ~2.6.13.
.TP
\fBmax_open_files = \fIvalue\fB\fR
Number of files to simultaneously keep open. LibTorrent dynamically
opens and closes files as necessary when mapping files to
@@ -560,4 +556,4 @@ log messages, but may be useful to debug connection problems.
.SH "AUTHORS"
.PP
Jari "Rakshasa" Sundell <jaris@ifi.uio.no>
Jari "Rakshasa" Sundell
+1 -11
View File
@@ -978,16 +978,6 @@ decent hash checking rate.
</para></listitem>
</varlistentry>
<varlistentry>
<term>safe_sync = <replaceable>yes|no</replaceable></term>
<listitem><para>
Always use MS_SYNC rather than MS_ASYNC when syncing chunks. This may
be nessesary in case of filesystem bugs like NFS in linux ~2.6.13.
</para></listitem>
</varlistentry>
<varlistentry>
<term>max_open_files = <replaceable>value</replaceable></term>
<listitem><para>
@@ -1122,7 +1112,7 @@ log messages, but may be useful to debug connection problems.
<para>
<simplelist type="vert">
<member>Jari "Rakshasa" Sundell <email>jaris@ifi.uio.no</email></member>
<member>Jari "Rakshasa" Sundell <email>sundell.software@gmail.com</email></member>
</simplelist>
</para>
+4
View File
@@ -73,6 +73,10 @@
#
#network.port_random.set = no
# Set RPC type
#network.rpc.use_xmlrpc.set = true
#network.rpc.use_jsonrpc.set = true
# Check hash for finished torrents. Might be useful until the bug is
# fixed that causes lack of disk-space not to be properly reported.
#
+2
View File
@@ -76,6 +76,8 @@ schedule2 = monitor_diskspace, 15, 60, ((close_low_diskspace, 1000M))
##network.http.capath.set = "/etc/ssl/certs"
##network.http.ssl_verify_peer.set = 0
##network.http.ssl_verify_host.set = 0
#network.rpc.use_xmlrpc.set = true
#network.rpc.use_jsonrpc.set = true
# Some additional values and commands
method.insert = system.startup_time, value|const, (system.time)
+1 -4
View File
@@ -29,10 +29,7 @@
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Contact: Jari Sundell
// Wrapper for addrinfo with focus on zero-copy conversion to and from
// the c-type and wrapper.
+3 -5
View File
@@ -29,10 +29,8 @@
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Contact: Jari Sundell <sundell.software@gmail.com>
#ifndef RAK_ALGORITHM_H
#define RAK_ALGORITHM_H
@@ -115,7 +113,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);
}
-110
View File
@@ -1,110 +0,0 @@
// rak - Rakshasa's toolbox
// Copyright (C) 2005-2007, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Some allocators for cacheline aligned chunks of memory, etc.
#ifndef RAK_ALLOCATORS_H
#define RAK_ALLOCATORS_H
#include <cstddef>
#include <limits>
#include <stdlib.h>
#include <sys/types.h>
namespace rak {
template <class T = void*>
class cacheline_allocator {
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef const void* const_void_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
cacheline_allocator() throw() { }
cacheline_allocator(const cacheline_allocator&) throw() { }
template <class U>
cacheline_allocator(const cacheline_allocator<U>&) throw() { }
~cacheline_allocator() throw() { }
template <class U>
struct rebind { typedef cacheline_allocator<U> other; };
// return address of values
pointer address (reference value) const { return &value; }
const_pointer address (const_reference value) const { return &value; }
size_type max_size () const throw() { return std::numeric_limits<size_t>::max() / sizeof(T); }
pointer allocate(size_type num, const_void_pointer hint = 0) { return alloc_size(num*sizeof(T)); }
static pointer alloc_size(size_type size) {
pointer ptr = NULL;
int __UNUSED result = posix_memalign((void**)&ptr, LT_SMP_CACHE_BYTES, size);
return ptr;
}
void construct (pointer p, const T& value) { new((void*)p)T(value); }
void destroy (pointer p) { p->~T(); }
void deallocate (pointer p, size_type num) { free((void*)p); }
};
template <class T1, class T2>
bool operator== (const cacheline_allocator<T1>&, const cacheline_allocator<T2>&) throw() {
return true;
}
template <class T1, class T2>
bool operator!= (const cacheline_allocator<T1>&, const cacheline_allocator<T2>&) throw() {
return false;
}
}
//
// Operator new with custom allocators:
//
template <typename T>
void* operator new(size_t s, rak::cacheline_allocator<T> a) { return a.alloc_size(s); }
#endif // namespace rak
+1 -4
View File
@@ -29,10 +29,7 @@
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Contact: Jari Sundell <sundell.software@gmail.com>
#ifndef RAK_ERROR_NUMBER_H
#define RAK_ERROR_NUMBER_H
+2 -4
View File
@@ -29,10 +29,8 @@
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Contact: Jari Sundell <sundell.software@gmail.com>
#ifndef RAK_FILE_STAT_H
#define RAK_FILE_STAT_H
-683
View File
@@ -1,683 +0,0 @@
// rak - Rakshasa's toolbox
// Copyright (C) 2005-2007, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RAK_FUNCTIONAL_H
#define RAK_FUNCTIONAL_H
#include <cstddef>
#include <functional>
namespace rak {
template <typename Type>
struct reference_fix {
typedef Type type;
};
template <typename Type>
struct reference_fix<Type&> {
typedef Type type;
};
template <typename Type>
struct value_t {
value_t(Type v) : m_v(v) {}
Type operator () () const { return m_v; }
Type m_v;
};
template <typename Type>
inline value_t<Type>
value(Type v) {
return value_t<Type>(v);
}
template <typename Type, typename Ftor>
struct accumulate_t {
accumulate_t(Type t, Ftor f) : result(t), m_f(f) {}
template <typename Arg>
void operator () (const Arg& a) { result += m_f(a); }
Type result;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline accumulate_t<Type, Ftor>
accumulate(Type t, Ftor f) {
return accumulate_t<Type, Ftor>(t, f);
}
// Operators:
template <typename Type, typename Ftor>
struct equal_t {
typedef bool result_type;
equal_t(Type t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (Arg& a) {
return m_t == m_f(a);
}
Type m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline equal_t<Type, Ftor>
equal(Type t, Ftor f) {
return equal_t<Type, Ftor>(t, f);
}
template <typename Type, typename Ftor>
struct equal_ptr_t {
typedef bool result_type;
equal_ptr_t(Type* t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (const Arg& a) {
return *m_t == *m_f(a);
}
Type* m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline equal_ptr_t<Type, Ftor>
equal_ptr(Type* t, Ftor f) {
return equal_ptr_t<Type, Ftor>(t, f);
}
template <typename Type, typename Ftor>
struct not_equal_t {
typedef bool result_type;
not_equal_t(Type t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (Arg& a) {
return m_t != m_f(a);
}
Type m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline not_equal_t<Type, Ftor>
not_equal(Type t, Ftor f) {
return not_equal_t<Type, Ftor>(t, f);
}
template <typename Type, typename Ftor>
struct less_t {
typedef bool result_type;
less_t(Type t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (Arg& a) {
return m_t < m_f(a);
}
Type m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline less_t<Type, Ftor>
less(Type t, Ftor f) {
return less_t<Type, Ftor>(t, f);
}
template <typename FtorA, typename FtorB>
struct less2_t : public std::binary_function<typename FtorA::argument_type, typename FtorB::argument_type, bool> {
less2_t(FtorA f_a, FtorB f_b) : m_f_a(f_a), m_f_b(f_b) {}
bool operator () (typename FtorA::argument_type a, typename FtorB::argument_type b) {
return m_f_a(a) < m_f_b(b);
}
FtorA m_f_a;
FtorB m_f_b;
};
template <typename FtorA, typename FtorB>
inline less2_t<FtorA, FtorB>
less2(FtorA f_a, FtorB f_b) {
return less2_t<FtorA,FtorB>(f_a,f_b);
}
template <typename Type, typename Ftor>
struct _greater {
typedef bool result_type;
_greater(Type t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (Arg& a) {
return m_t > m_f(a);
}
Type m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline _greater<Type, Ftor>
greater(Type t, Ftor f) {
return _greater<Type, Ftor>(t, f);
}
template <typename FtorA, typename FtorB>
struct greater2_t : public std::binary_function<typename FtorA::argument_type, typename FtorB::argument_type, bool> {
greater2_t(FtorA f_a, FtorB f_b) : m_f_a(f_a), m_f_b(f_b) {}
bool operator () (typename FtorA::argument_type a, typename FtorB::argument_type b) {
return m_f_a(a) > m_f_b(b);
}
FtorA m_f_a;
FtorB m_f_b;
};
template <typename FtorA, typename FtorB>
inline greater2_t<FtorA, FtorB>
greater2(FtorA f_a, FtorB f_b) {
return greater2_t<FtorA,FtorB>(f_a,f_b);
}
template <typename Type, typename Ftor>
struct less_equal_t {
typedef bool result_type;
less_equal_t(Type t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (Arg& a) {
return m_t <= m_f(a);
}
Type m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline less_equal_t<Type, Ftor>
less_equal(Type t, Ftor f) {
return less_equal_t<Type, Ftor>(t, f);
}
template <typename Type, typename Ftor>
struct greater_equal_t {
typedef bool result_type;
greater_equal_t(Type t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (Arg& a) {
return m_t >= m_f(a);
}
Type m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline greater_equal_t<Type, Ftor>
greater_equal(Type t, Ftor f) {
return greater_equal_t<Type, Ftor>(t, f);
}
template<typename Tp>
struct invert : public std::unary_function<Tp, Tp> {
Tp
operator () (const Tp& x) const { return ~x; }
};
template <typename Src, typename Dest>
struct on_t : public std::unary_function<typename Src::argument_type, typename Dest::result_type> {
typedef typename Dest::result_type result_type;
on_t(Src s, Dest d) : m_dest(d), m_src(s) {}
result_type operator () (typename reference_fix<typename Src::argument_type>::type arg) {
return m_dest(m_src(arg));
}
Dest m_dest;
Src m_src;
};
template <typename Src, typename Dest>
inline on_t<Src, Dest>
on(Src s, Dest d) {
return on_t<Src, Dest>(s, d);
}
template <typename Src, typename Dest>
struct on2_t : public std::binary_function<typename Src::argument_type, typename Dest::second_argument_type, typename Dest::result_type> {
typedef typename Dest::result_type result_type;
on2_t(Src s, Dest d) : m_dest(d), m_src(s) {}
result_type operator () (typename reference_fix<typename Src::argument_type>::type first, typename reference_fix<typename Dest::second_argument_type>::type second) {
return m_dest(m_src(first), second);
}
Dest m_dest;
Src m_src;
};
template <typename Src, typename Dest>
inline on2_t<Src, Dest>
on2(Src s, Dest d) {
return on2_t<Src, Dest>(s, d);
}
// Creates a functor for accessing a member.
template <typename Class, typename Member>
struct mem_ptr_t : public std::unary_function<Class*, Member&> {
mem_ptr_t(Member Class::*m) : m_member(m) {}
Member& operator () (Class* c) {
return c->*m_member;
}
const Member& operator () (const Class* c) {
return c->*m_member;
}
Member Class::*m_member;
};
template <typename Class, typename Member>
inline mem_ptr_t<Class, Member>
mem_ptr(Member Class::*m) {
return mem_ptr_t<Class, Member>(m);
}
template <typename Class, typename Member>
struct mem_ref_t : public std::unary_function<Class&, Member&> {
mem_ref_t(Member Class::*m) : m_member(m) {}
Member& operator () (Class& c) {
return c.*m_member;
}
Member Class::*m_member;
};
template <typename Class, typename Member>
struct const_mem_ref_t : public std::unary_function<const Class&, const Member&> {
const_mem_ref_t(const Member Class::*m) : m_member(m) {}
const Member& operator () (const Class& c) {
return c.*m_member;
}
const Member Class::*m_member;
};
template <typename Class, typename Member>
inline mem_ref_t<Class, Member>
mem_ref(Member Class::*m) {
return mem_ref_t<Class, Member>(m);
}
template <typename Class, typename Member>
inline const_mem_ref_t<Class, Member>
const_mem_ref(const Member Class::*m) {
return const_mem_ref_t<Class, Member>(m);
}
template <typename Cond, typename Then>
struct if_then_t {
if_then_t(Cond c, Then t) : m_cond(c), m_then(t) {}
template <typename Arg>
void operator () (Arg& a) {
if (m_cond(a))
m_then(a);
}
Cond m_cond;
Then m_then;
};
template <typename Cond, typename Then>
inline if_then_t<Cond, Then>
if_then(Cond c, Then t) {
return if_then_t<Cond, Then>(c, t);
}
template <typename T>
struct call_delete : public std::unary_function<T*, void> {
void operator () (T* t) {
delete t;
}
};
template <typename T>
inline void
call_delete_func(T* t) {
delete t;
}
template <typename Operation>
class bind1st_t : public std::unary_function<typename Operation::second_argument_type, typename Operation::result_type> {
public:
typedef typename reference_fix<typename Operation::first_argument_type>::type value_type;
typedef typename reference_fix<typename Operation::second_argument_type>::type argument_type;
bind1st_t(const Operation& op, const value_type v) :
m_op(op), m_value(v) {}
typename Operation::result_type
operator () (const argument_type arg) {
return m_op(m_value, arg);
}
protected:
Operation m_op;
value_type m_value;
};
template <typename Operation, typename Type>
inline bind1st_t<Operation>
bind1st(const Operation& op, const Type& val) {
return bind1st_t<Operation>(op, val);
}
template <typename Operation>
class bind2nd_t : public std::unary_function<typename Operation::first_argument_type, typename Operation::result_type> {
public:
typedef typename reference_fix<typename Operation::first_argument_type>::type argument_type;
typedef typename reference_fix<typename Operation::second_argument_type>::type value_type;
bind2nd_t(const Operation& op, const value_type v) :
m_op(op), m_value(v) {}
typename Operation::result_type
operator () (argument_type arg) {
return m_op(arg, m_value);
}
protected:
Operation m_op;
value_type m_value;
};
template <typename Operation, typename Type>
inline bind2nd_t<Operation>
bind2nd(const Operation& op, const Type& val) {
return bind2nd_t<Operation>(op, val);
}
// Lightweight callback function including pointer to object. Should
// be replaced by TR1 stuff later. Requires an object to bind, instead
// of using a seperate functor for that.
template <typename Ret>
class ptr_fun0 {
public:
typedef Ret result_type;
typedef Ret (*Function)();
ptr_fun0() {}
ptr_fun0(Function f) : m_function(f) {}
bool is_valid() const { return m_function; }
Ret operator () () { return m_function(); }
private:
Function m_function;
};
template <typename Object, typename Ret>
class mem_fun0 {
public:
typedef Ret result_type;
typedef Ret (Object::*Function)();
mem_fun0() : m_object(NULL) {}
mem_fun0(Object* o, Function f) : m_object(o), m_function(f) {}
bool is_valid() const { return m_object; }
Ret operator () () { return (m_object->*m_function)(); }
private:
Object* m_object;
Function m_function;
};
template <typename Object, typename Ret>
class const_mem_fun0 {
public:
typedef Ret result_type;
typedef Ret (Object::*Function)() const;
const_mem_fun0() : m_object(NULL) {}
const_mem_fun0(const Object* o, Function f) : m_object(o), m_function(f) {}
bool is_valid() const { return m_object; }
Ret operator () () const { return (m_object->*m_function)(); }
private:
const Object* m_object;
Function m_function;
};
template <typename Object, typename Ret, typename Arg1>
class mem_fun1 {
public:
typedef Ret result_type;
typedef Ret (Object::*Function)(Arg1);
mem_fun1() : m_object(NULL) {}
mem_fun1(Object* o, Function f) : m_object(o), m_function(f) {}
bool is_valid() const { return m_object; }
Ret operator () (Arg1 a1) { return (m_object->*m_function)(a1); }
private:
Object* m_object;
Function m_function;
};
template <typename Object, typename Ret, typename Arg1>
class const_mem_fun1 {
public:
typedef Ret result_type;
typedef Ret (Object::*Function)(Arg1) const;
const_mem_fun1() : m_object(NULL) {}
const_mem_fun1(const Object* o, Function f) : m_object(o), m_function(f) {}
bool is_valid() const { return m_object; }
Ret operator () (Arg1 a1) const { return (m_object->*m_function)(a1); }
private:
const Object* m_object;
Function m_function;
};
template <typename Object, typename Ret, typename Arg1, typename Arg2>
class mem_fun2 : public std::binary_function<Arg1, Arg2, Ret> {
public:
typedef Ret result_type;
typedef Ret (Object::*Function)(Arg1, Arg2);
typedef Object object_type;
mem_fun2() : m_object(NULL) {}
mem_fun2(Object* o, Function f) : m_object(o), m_function(f) {}
bool is_valid() const { return m_object; }
object_type* object() { return m_object; }
const object_type* object() const { return m_object; }
Ret operator () (Arg1 a1, Arg2 a2) { return (m_object->*m_function)(a1, a2); }
private:
Object* m_object;
Function m_function;
};
template <typename Object, typename Ret, typename Arg1, typename Arg2, typename Arg3>
class mem_fun3 {
public:
typedef Ret result_type;
typedef Ret (Object::*Function)(Arg1, Arg2, Arg3);
mem_fun3() : m_object(NULL) {}
mem_fun3(Object* o, Function f) : m_object(o), m_function(f) {}
bool is_valid() const { return m_object; }
Ret operator () (Arg1 a1, Arg2 a2, Arg3 a3) { return (m_object->*m_function)(a1, a2, a3); }
private:
Object* m_object;
Function m_function;
};
template <typename Ret>
inline ptr_fun0<Ret>
ptr_fun(Ret (*f)()) { return ptr_fun0<Ret>(f); }
template <typename Object, typename Ret>
inline mem_fun0<Object, Ret>
make_mem_fun(Object* o, Ret (Object::*f)()) {
return mem_fun0<Object, Ret>(o, f);
}
template <typename Object, typename Ret>
inline const_mem_fun0<Object, Ret>
make_mem_fun(const Object* o, Ret (Object::*f)() const) {
return const_mem_fun0<Object, Ret>(o, f);
}
template <typename Object, typename Ret, typename Arg1>
inline mem_fun1<Object, Ret, Arg1>
make_mem_fun(Object* o, Ret (Object::*f)(Arg1)) {
return mem_fun1<Object, Ret, Arg1>(o, f);
}
template <typename Object, typename Ret, typename Arg1>
inline const_mem_fun1<Object, Ret, Arg1>
make_mem_fun(const Object* o, Ret (Object::*f)(Arg1) const) {
return const_mem_fun1<Object, Ret, Arg1>(o, f);
}
template <typename Object, typename Ret, typename Arg1, typename Arg2>
inline mem_fun2<Object, Ret, Arg1, Arg2>
make_mem_fun(Object* o, Ret (Object::*f)(Arg1, Arg2)) {
return mem_fun2<Object, Ret, Arg1, Arg2>(o, f);
}
template <typename Object, typename Ret, typename Arg1, typename Arg2, typename Arg3>
inline mem_fun3<Object, Ret, Arg1, Arg2, Arg3>
make_mem_fun(Object* o, Ret (Object::*f)(Arg1, Arg2, Arg3)) {
return mem_fun3<Object, Ret, Arg1, Arg2, Arg3>(o, f);
}
template <typename Container>
inline void
slot_list_call(const Container& slot_list) {
if (slot_list.empty())
return;
typename Container::const_iterator first = slot_list.begin();
typename Container::const_iterator next = slot_list.begin();
while (++next != slot_list.end()) {
(*first)();
first = next;
}
(*first)();
}
template <typename Container, typename Arg1>
inline void
slot_list_call(const Container& slot_list, Arg1 arg1) {
if (slot_list.empty())
return;
typename Container::const_iterator first = slot_list.begin();
typename Container::const_iterator next = slot_list.begin();
while (++next != slot_list.end()) {
(*first)(arg1);
first = next;
}
(*first)(arg1);
}
template <typename Container, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
inline void
slot_list_call(const Container& slot_list, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) {
if (slot_list.empty())
return;
typename Container::const_iterator first = slot_list.begin();
typename Container::const_iterator next = slot_list.begin();
while (++next != slot_list.end()) {
(*first)(arg1, arg2, arg3, arg4);
first = next;
}
(*first)(arg1, arg2, arg3, arg4);
}
}
#endif
+2 -4
View File
@@ -29,10 +29,8 @@
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Contact: Jari Sundell <sundell.software@gmail.com>
#ifndef RAK_PARTIAL_QUEUE_H
#define RAK_PARTIAL_QUEUE_H
+2 -4
View File
@@ -29,10 +29,8 @@
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Contact: Jari Sundell <sundell.software@gmail.com>
// Various functions for manipulating file paths. Also consider making
// a directory iterator.
-79
View File
@@ -1,79 +0,0 @@
// priority_queue is a priority queue implemented using a binary
// heap. It can contain multiple instances of a value.
#ifndef RAK_PRIORITY_QUEUE_H
#define RAK_PRIORITY_QUEUE_H
#include <algorithm>
#include <functional>
#include <vector>
namespace rak {
template <typename Value, typename Compare, typename Equal, typename Alloc = std::allocator<Value> >
class priority_queue : public std::vector<Value, Alloc> {
public:
typedef std::vector<Value, Alloc> base_type;
typedef typename base_type::reference reference;
typedef typename base_type::const_reference const_reference;
typedef typename base_type::iterator iterator;
typedef typename base_type::const_iterator const_iterator;
typedef typename base_type::value_type value_type;
using base_type::begin;
using base_type::end;
using base_type::size;
using base_type::empty;
using base_type::clear;
priority_queue(Compare l = Compare(), Equal e = Equal())
: m_compare(l), m_equal(e) {}
const_reference top() const {
return base_type::front();
}
void pop() {
std::pop_heap(begin(), end(), m_compare);
base_type::pop_back();
}
void update() {
std::make_heap(begin(), end(), m_compare);
}
void push(const value_type& value) {
base_type::push_back(value);
std::push_heap(begin(), end(), m_compare);
}
template <typename Key>
iterator find(const Key& key) {
return std::find_if(begin(), end(), [&](auto& value) { return m_equal(value, key); });
}
template <typename Key>
bool erase(const Key& key) {
iterator itr = find(key);
if (itr == end())
return false;
erase(itr);
return true;
}
// Removes 'itr' from the queue.
void erase(iterator itr) {
base_type::erase(itr);
std::make_heap(begin(), end(), m_compare);
}
private:
Compare m_compare;
Equal m_equal;
};
}
#endif
-160
View File
@@ -1,160 +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_PRIORITY_QUEUE_DEFAULT_H
#define RAK_PRIORITY_QUEUE_DEFAULT_H
#include <functional>
#include <rak/allocators.h>
#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 torrent::internal_error("priority_item::~priority_item() called on a queued item.");
m_time = timer();
m_slot = slot_void();
}
bool is_valid() const { return (bool)m_slot; }
bool is_queued() const { return m_time != timer(); }
slot_void& slot() { return m_slot; }
const timer& time() const { return m_time; }
void clear_time() { m_time = timer(); }
void set_time(const timer& t) { m_time = t; }
bool compare(const timer& t) const { return m_time > t; }
private:
priority_item(const priority_item&);
void operator = (const priority_item&);
timer m_time;
slot_void m_slot;
};
struct priority_compare {
bool operator () (const priority_item* const p1, const priority_item* const p2) const {
return p1->time() > p2->time();
}
};
typedef std::equal_to<priority_item*> priority_equal;
typedef priority_queue<priority_item*, priority_compare, priority_equal,
cacheline_allocator<priority_item*> > priority_queue_default;
inline void
priority_queue_perform(priority_queue_default* queue, timer t) {
while (!queue->empty() && queue->top()->time() <= t) {
priority_item* v = queue->top();
queue->pop();
v->clear_time();
v->slot()();
}
}
inline void
priority_queue_insert(priority_queue_default* queue, priority_item* item, timer t) {
if (t == timer())
throw torrent::internal_error("priority_queue_insert(...) received a bad timer.");
if (!item->is_valid())
throw torrent::internal_error("priority_queue_insert(...) called on an invalid item.");
if (item->is_queued())
throw torrent::internal_error("priority_queue_insert(...) called on an already queued item.");
if (queue->find(item) != queue->end())
throw torrent::internal_error("priority_queue_insert(...) item found in queue.");
item->set_time(t);
queue->push(item);
}
inline void
priority_queue_erase(priority_queue_default* queue, priority_item* item) {
if (!item->is_queued())
return;
// Check is_valid() after is_queued() so that it is safe to call
// erase on untouched instances.
if (!item->is_valid())
throw torrent::internal_error("priority_queue_erase(...) called on an invalid item.");
// Unqueue it before erasing.
item->clear_time();
if (!queue->erase(item))
throw torrent::internal_error("priority_queue_erase(...) could not find item in queue.");
}
inline void
priority_queue_update(priority_queue_default* queue, priority_item* item, timer t) {
if (t == timer())
throw torrent::internal_error("priority_queue_update(...) received a bad timer.");
if (!item->is_valid())
throw torrent::internal_error("priority_queue_update(...) called on an invalid item.");
if (queue->find(item) == queue->end()) {
if (item->is_queued())
throw torrent::internal_error("priority_queue_update(...) cannot insert an already queued item.");
item->set_time(t);
queue->push(item);
} else {
item->set_time(t);
queue->update();
}
}
}
#endif
+3 -5
View File
@@ -29,10 +29,8 @@
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Contact: Jari Sundell <sundell.software@gmail.com>
// This is a hacked up whole string pattern matching. Replace with
// TR1's regex when that becomes widely available. It is intended for
@@ -50,7 +48,7 @@
namespace rak {
class regex : public std::unary_function<std::string, bool> {
class regex : public std::function<bool (std::string)> {
public:
regex() {}
regex(const std::string& p) : m_pattern(p) {}
+2 -4
View File
@@ -29,10 +29,8 @@
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Contact: Jari Sundell <sundell.software@gmail.com>
// Wrappers for the various sockaddr types with focus on zero-copy
// casting between the original type and the wrapper class.
+5 -7
View File
@@ -29,10 +29,8 @@
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Contact: Jari Sundell <sundell.software@gmail.com>
#ifndef RAK_STRING_MANIP_H
#define RAK_STRING_MANIP_H
@@ -143,8 +141,8 @@ public:
return *this;
}
bool operator == (__UNUSED const split_iterator_t& itr) const { return m_pos == m_seq->end(); }
bool operator != (__UNUSED const split_iterator_t& itr) const { return m_pos != m_seq->end(); }
bool operator == (const split_iterator_t&) const { return m_pos == m_seq->end(); }
bool operator != (const split_iterator_t&) const { return m_pos != m_seq->end(); }
private:
const Sequence* m_seq;
@@ -161,7 +159,7 @@ split_iterator(const Sequence& seq, typename Sequence::value_type delim) {
template <typename Sequence>
inline split_iterator_t<Sequence>
split_iterator(__UNUSED const Sequence& seq) {
split_iterator(const Sequence&) {
return split_iterator_t<Sequence>();
}
-110
View File
@@ -1,110 +0,0 @@
// libTorrent - BitTorrent library
// Copyright (C) 2005-2007, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RAK_TIMER_H
#define RAK_TIMER_H
#include <limits>
#include <cinttypes>
#include <sys/time.h>
namespace rak {
// Don't convert negative Timer to timeval and then back to Timer, that will bork.
class timer {
public:
timer(int64_t usec = 0) : m_time(usec) {}
timer(timeval tv) : m_time((int64_t)(uint32_t)tv.tv_sec * 1000000 + (int64_t)(uint32_t)tv.tv_usec % 1000000) {}
bool is_zero() const { return m_time == 0; }
bool is_not_zero() const { return m_time != 0; }
int32_t seconds() const { return m_time / 1000000; }
int32_t seconds_ceiling() const { return (m_time + 1000000 - 1) / 1000000; }
int64_t usec() const { return m_time; }
timer round_seconds() const { return (m_time / 1000000) * 1000000; }
timer round_seconds_ceiling() const { return ((m_time + 1000000 - 1) / 1000000) * 1000000; }
timeval tval() const {
timeval val;
val.tv_sec = m_time / 1000000;
val.tv_usec = m_time % 1000000;
return val;
}
static timer current();
static int64_t current_seconds() { return current().seconds(); }
static int64_t current_usec() { return current().usec(); }
static timer from_minutes(uint32_t minutes) { return rak::timer((uint64_t)minutes * 60 * 1000000); }
static timer from_seconds(uint32_t seconds) { return rak::timer((uint64_t)seconds * 1000000); }
static timer from_milliseconds(uint32_t msec) { return rak::timer((uint64_t)msec * 1000); }
static timer max() { return std::numeric_limits<int64_t>::max(); }
bool operator < (const timer& t) const { return m_time < t.m_time; }
bool operator > (const timer& t) const { return m_time > t.m_time; }
bool operator <= (const timer& t) const { return m_time <= t.m_time; }
bool operator >= (const timer& t) const { return m_time >= t.m_time; }
bool operator == (const timer& t) const { return m_time == t.m_time; }
bool operator != (const timer& t) const { return m_time != t.m_time; }
timer operator - (const timer& t) const { return timer(m_time - t.m_time); }
timer operator + (const timer& t) const { return timer(m_time + t.m_time); }
timer operator * (int64_t t) const { return timer(m_time * t); }
timer operator / (int64_t t) const { return timer(m_time / t); }
timer operator -= (int64_t t) { m_time -= t; return *this; }
timer operator -= (const timer& t) { m_time -= t.m_time; return *this; }
timer operator += (int64_t t) { m_time += t; return *this; }
timer operator += (const timer& t) { m_time += t.m_time; return *this; }
private:
int64_t m_time;
};
inline timer
timer::current() {
timeval t;
gettimeofday(&t, 0);
return timer(t);
}
}
#endif
+2 -4
View File
@@ -29,10 +29,8 @@
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Contact: Jari Sundell <sundell.software@gmail.com>
#ifndef RAK_UNORDERED_VECTOR_H
#define RAK_UNORDERED_VECTOR_H
+42
View File
@@ -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
-19
View File
@@ -107,25 +107,6 @@ AC_DEFUN([CC_ATTRIBUTE_NONNULL], [
fi
])
AC_DEFUN([CC_ATTRIBUTE_UNUSED], [
AC_CACHE_CHECK([if compiler supports __attribute__((unused))],
[cc_cv_attribute_unused],
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([
void some_function(void *foo, __attribute__((unused)) void *bar);
])],
[cc_cv_attribute_unused=yes],
[cc_cv_attribute_unused=no])
])
if test "x$cc_cv_attribute_unused" = "xyes"; then
AC_DEFINE([SUPPORT_ATTRIBUTE_UNUSED], 1, [Define this if the compiler supports the unused attribute])
$1
else
true
$2
fi
])
AC_DEFUN([CC_FUNC_EXPECT], [
AC_CACHE_CHECK([if compiler has __builtin_expect function],
[cc_cv_func_expect],
+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])
])
+20 -39
View File
@@ -88,49 +88,11 @@ AC_DEFUN([TORRENT_CHECK_KQUEUE], [
[
AC_DEFINE(USE_KQUEUE, 1, Use kqueue.)
AC_MSG_RESULT(yes)
TORRENT_CHECK_KQUEUE_SOCKET_ONLY
], [
AC_MSG_RESULT(no)
])
])
AC_DEFUN([TORRENT_CHECK_KQUEUE_SOCKET_ONLY], [
AC_MSG_CHECKING(whether kqueue supports pipes and ptys)
AC_LINK_IFELSE([AC_LANG_SOURCE([
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/event.h>
#include <sys/time.h>
int main() {
struct kevent ev@<:@2@:>@, ev_out@<:@2@:>@;
struct timespec ts = { 0, 0 };
int pfd@<:@2@:>@, pty@<:@2@:>@, kfd, n;
char buffer@<:@9001@:>@;
if (pipe(pfd) == -1) return 1;
if (fcntl(pfd@<:@1@:>@, F_SETFL, O_NONBLOCK) == -1) return 2;
while ((n = write(pfd@<:@1@:>@, buffer, sizeof(buffer))) == sizeof(buffer));
if ((pty@<:@0@:>@=posix_openpt(O_RDWR | O_NOCTTY)) == -1) return 3;
if ((pty@<:@1@:>@=grantpt(pty@<:@0@:>@)) == -1) return 4;
EV_SET(ev+0, pfd@<:@1@:>@, EVFILT_WRITE, EV_ADD | EV_ENABLE, 0, 0, NULL);
EV_SET(ev+1, pty@<:@1@:>@, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, NULL);
if ((kfd = kqueue()) == -1) return 5;
if ((n = kevent(kfd, ev, 2, NULL, 0, NULL)) == -1) return 6;
if (ev_out@<:@0@:>@.flags & EV_ERROR) return 7;
if (ev_out@<:@1@:>@.flags & EV_ERROR) return 8;
read(pfd@<:@0@:>@, buffer, sizeof(buffer));
if ((n = kevent(kfd, NULL, 0, ev_out, 2, &ts)) < 1) return 9;
return 0;
}
])],
[
AC_MSG_RESULT(yes)
], [
AC_DEFINE(KQUEUE_SOCKET_ONLY, 1, kqueue only supports sockets.)
AC_MSG_RESULT(no)
])
])
AC_DEFUN([TORRENT_WITH_KQUEUE], [
AC_ARG_WITH(kqueue,
@@ -400,7 +362,7 @@ AC_DEFUN([TORRENT_WITH_XMLRPC_C], [
else
xmlrpc_cc_prg="$withval"
fi
if eval $xmlrpc_cc_prg --version 2>/dev/null >/dev/null; then
CXXFLAGS="$CXXFLAGS `$xmlrpc_cc_prg --cflags server-util`"
LIBS="$LIBS `$xmlrpc_cc_prg server-util --libs`"
@@ -439,6 +401,25 @@ AC_DEFUN([TORRENT_WITH_TINYXML2], [
])
])
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++)
+30 -7
View File
@@ -13,7 +13,7 @@ AC_DEFUN([TORRENT_WITH_SYSROOT], [
AC_MSG_ERROR(The sysroot option must point to a directory, like f.ex "/Developer/SDKs/MacOSX10.4u.sdk".)
else
AC_MSG_RESULT($withval)
CXXFLAGS="$CXXFLAGS -isysroot $withval"
LDFLAGS="$LDFLAGS -Wl,-syslibroot,$withval"
fi
@@ -21,6 +21,19 @@ AC_DEFUN([TORRENT_WITH_SYSROOT], [
])
AC_DEFUN([TORRENT_REMOVE_UNWANTED],
[
values_to_check=`for i in $2; do echo $i; done`
unwanted_values=`for i in $3; do echo $i; done`
if test -z "${unwanted_values}"; then
$1="$2"
else
result=`echo "${values_to_check}" | $GREP -Fvx -- "${unwanted_values}" | $GREP -v '^$'`
$1=$(echo "$result" | tr -d '\n')
fi
])
AC_DEFUN([TORRENT_ENABLE_ARCH], [
AC_ARG_ENABLE(arch,
AS_HELP_STRING([--enable-arch=ARCH],
@@ -104,7 +117,7 @@ AC_DEFUN([TORRENT_CHECK_MADVISE], [
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <sys/types.h>
#include <sys/mman.h>
void f() { static char test@<:@1024@:>@; madvise((void *)test, sizeof(test), MADV_NORMAL); }
void f() { static char test@<:@1024@:>@; madvise((void *)test, sizeof(test), MADV_NORMAL); }
])],
[
AC_MSG_RESULT(yes)
@@ -114,6 +127,21 @@ AC_DEFUN([TORRENT_CHECK_MADVISE], [
])
])
AC_DEFUN([TORRENT_CHECK_POSIX_FADVISE], [
AC_MSG_CHECKING(for posix_fadvise)
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <fcntl.h>
void f() { posix_fadvise(0, 0, 0, POSIX_FADV_RANDOM); }
])],
[
AC_MSG_RESULT(yes)
AC_DEFINE(USE_POSIX_FADVISE, 1, Use posix_fadvise)
], [
AC_MSG_RESULT(no)
])
])
AC_DEFUN([TORRENT_CHECK_POPCOUNT], [
AC_MSG_CHECKING(for __builtin_popcount)
@@ -139,17 +167,12 @@ AC_DEFUN([TORRENT_CHECK_CACHELINE], [
])],
[
AC_MSG_RESULT(found builtin)
dnl AC_DEFINE(LT_SMP_CACHE_BYTES, SMP_CACHE_BYTES, Largest L1 cache size we know of, should work on all archs.)
dnl AC_DEFINE(lt_cacheline_aligned, __cacheline_aligned, LibTorrent defined cacheline aligned.)
dnl Need to fix this so that it uses the stuff defined by the system.
AC_DEFINE(LT_SMP_CACHE_BYTES, 128, Largest L1 cache size we know of should work on all archs.)
AC_DEFINE(lt_cacheline_aligned, __attribute__((__aligned__(LT_SMP_CACHE_BYTES))), LibTorrent defined cacheline aligned.)
], [
AC_MSG_RESULT(using default 128 bytes)
AC_DEFINE(LT_SMP_CACHE_BYTES, 128, Largest L1 cache size we know of should work on all archs.)
AC_DEFINE(lt_cacheline_aligned, __attribute__((__aligned__(LT_SMP_CACHE_BYTES))), LibTorrent defined cacheline aligned.)
])
])
+11 -4
View File
@@ -26,8 +26,6 @@ libsub_root_a_SOURCES = \
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 \
@@ -37,6 +35,7 @@ libsub_root_a_SOURCES = \
display/attributes.h \
display/canvas.cc \
display/canvas.h \
display/color_map.h \
display/frame.cc \
display/frame.h \
display/manager.cc \
@@ -107,6 +106,12 @@ libsub_root_a_SOURCES = \
rpc/exec_file.h \
rpc/fixed_key.h \
rpc/ip_table_list.h \
rpc/lua.h \
rpc/lua.cc \
rpc/jsonrpc.cc \
rpc/jsonrpc.h \
rpc/rpc_manager.cc \
rpc/rpc_manager.h \
rpc/object_storage.cc \
rpc/object_storage.h \
rpc/parse.cc \
@@ -125,6 +130,7 @@ libsub_root_a_SOURCES = \
rpc/xmlrpc_tinyxml2.cc \
rpc/tinyxml2/tinyxml2.h \
rpc/tinyxml2/tinyxml2.cc \
rpc/nlohmann/json.h \
\
ui/download.cc \
ui/download.h \
@@ -155,10 +161,13 @@ libsub_root_a_SOURCES = \
ui/root.cc \
ui/root.h \
\
utils/base64.cc \
utils/base64.h \
utils/directory.cc \
utils/directory.h \
utils/file_status_cache.cc \
utils/file_status_cache.h \
utils/functional.h \
utils/list_focus.h \
utils/lockfile.cc \
utils/lockfile.h \
@@ -189,8 +198,6 @@ libsub_root_a_SOURCES = \
option_parser.h \
signal_handler.cc \
signal_handler.h \
thread_base.cc \
thread_base.h \
thread_worker.cc \
thread_worker.h
+51 -83
View File
@@ -1,44 +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
#include "config.h"
#include <functional>
#include <unistd.h>
#include <cassert>
#include <cstdio>
#include <functional>
#include <netdb.h>
#include <unistd.h>
#include <rak/file_stat.h>
#include <rak/error_number.h>
#include <rak/path.h>
@@ -47,14 +13,14 @@
#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 +70,7 @@ apply_d_change_link(core::Download* download, const torrent::Object::list_type&
const std::string& type = (itr++)->as_string();
const std::string& prefix = (itr++)->as_string();
const std::string& postfix = (itr++)->as_string();
if (type.empty())
throw torrent::input_error("Invalid arguments.");
@@ -319,21 +285,6 @@ retrieve_d_bitfield(core::Download* download) {
return torrent::Object(rak::transform_hex(bitField->begin(), bitField->end()));
}
struct call_add_d_peer_t {
call_add_d_peer_t(core::Download* d, int port) : m_download(d), m_port(port) { }
void operator() (const sockaddr* sa, int err) {
if (sa == NULL) {
lt_log_print(torrent::LOG_TORRENT_WARN, "could not resolve hostname for added peer");
} else {
m_download->download()->add_peer(sa, m_port);
}
}
core::Download* m_download;
int m_port;
};
void
apply_d_add_peer(core::Download* download, const std::string& arg) {
int port, ret;
@@ -356,7 +307,17 @@ apply_d_add_peer(core::Download* download, const std::string& arg) {
if (port < 1 || port > 65535)
throw torrent::input_error("Invalid port number.");
torrent::connection_manager()->resolver()(host, (int)rak::socket_address::pf_unspec, SOCK_STREAM, call_add_d_peer_t(download, port));
assert(std::this_thread::get_id() == torrent::main_thread::thread()->thread_id());
// Currently discarding SOCK_STREAM.
torrent::this_thread::resolver()->resolve_preferred(NULL, host, AF_UNSPEC, AF_INET, [download, port](torrent::c_sa_shared_ptr sa, int err) {
if (sa == nullptr) {
lt_log_print(torrent::LOG_TORRENT_WARN, "could not resolve hostname for added peer: %s", gai_strerror(err));
return;
}
download->download()->add_peer(sa.get(), port);
});
}
torrent::Object
@@ -410,7 +371,7 @@ f_multicall(core::Download* download, const torrent::Object::list_type& args) {
for (torrent::Object::list_const_iterator cItr = ++args.begin(); cItr != args.end(); cItr++) {
const std::string& cmd = cItr->as_string();
row.push_back(rpc::parse_command(rpc::make_target(*itr), cmd.c_str(), cmd.c_str() + cmd.size()).first);
row.push_back(rpc::parse_command(rpc::make_target(itr->get()), cmd.c_str(), cmd.c_str() + cmd.size()).first);
}
}
@@ -427,21 +388,24 @@ t_multicall(core::Download* download, const torrent::Object::list_type& args) {
// Add some pre-parsing of the commands, so we don't spend time
// parsing and searching command map for every single call.
torrent::Object resultRaw = torrent::Object::create_list();
torrent::Object::list_type& result = resultRaw.as_list();
torrent::Object result_raw = torrent::Object::create_list();
torrent::Object::list_type& result = result_raw.as_list();
for (int itr = 0, last = download->tracker_list()->size(); itr != last; itr++) {
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
for (uint32_t idx = 0, last = download->tracker_list_size(); idx < last; idx++) {
auto& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
auto tracker = download->tracker_controller().at(idx);
if (!tracker.is_valid())
continue;
for (torrent::Object::list_const_iterator cItr = ++args.begin(); cItr != args.end(); cItr++) {
const std::string& cmd = cItr->as_string();
torrent::Tracker* t = download->tracker_list()->at(itr);
row.push_back(rpc::parse_command(rpc::make_target(t), cmd.c_str(), cmd.c_str() + cmd.size()).first);
row.push_back(rpc::parse_command(rpc::make_target(&tracker), cmd.c_str(), cmd.c_str() + cmd.size()).first);
}
}
return resultRaw;
return result_raw;
}
torrent::Object
@@ -522,7 +486,8 @@ download_tracker_insert(core::Download* download, const torrent::Object::list_ty
if (group < 0 || group > 32)
throw torrent::input_error("Tracker group number invalid.");
download->download()->tracker_list()->insert_url(group, args.back().as_string(), true);
download->tracker_controller().add_extra_tracker(group, args.back().as_string());
return torrent::Object();
}
@@ -582,19 +547,20 @@ download_set_variable_string(core::Download* download, const torrent::Object::st
//
torrent::Object
d_list_push_back(core::Download* download, const torrent::Object& rawArgs, const char* first_key, const char* second_key) {
download_get_variable(download, first_key, second_key).as_list().push_back(rawArgs);
d_list_push_back_string(core::Download* download, const torrent::Object& rawArgs, const char* first_key, const char* second_key) {
auto& arg = rawArgs.as_string();
download_get_variable(download, first_key, second_key).as_list().push_back(arg);
return torrent::Object();
}
torrent::Object
d_list_push_back_unique(core::Download* download, const torrent::Object& rawArgs, const char* first_key, const char* second_key) {
const torrent::Object& args = (rawArgs.is_list() && !rawArgs.as_list().empty()) ? rawArgs.as_list().front() : rawArgs;
d_list_push_back_unique_string(core::Download* download, const torrent::Object& rawArgs, const char* first_key, const char* second_key) {
auto& arg = rawArgs.as_string();
torrent::Object::list_type& list = download_get_variable(download, first_key, second_key).as_list();
if (std::find_if(list.begin(), list.end(), [args](const torrent::Object& obj) { return torrent::object_equal(obj, args); }) == list.end())
list.push_back(rawArgs);
if (std::none_of(list.begin(), list.end(), [arg](const torrent::Object& obj) { return torrent::object_equal(obj, arg); }))
list.push_back(arg);
return torrent::Object();
}
@@ -604,7 +570,7 @@ d_list_has(core::Download* download, const torrent::Object& rawArgs, const char*
const torrent::Object& args = (rawArgs.is_list() && !rawArgs.as_list().empty()) ? rawArgs.as_list().front() : rawArgs;
torrent::Object::list_type& list = download_get_variable(download, first_key, second_key).as_list();
return (int64_t)(std::find_if(list.begin(), list.end(), [args](const torrent::Object& obj) { return torrent::object_equal(obj, args); }) != list.end());
return (int64_t)(std::any_of(list.begin(), list.end(), [args](const auto& obj) { return torrent::object_equal(obj, args); }));
}
torrent::Object
@@ -626,7 +592,6 @@ d_list_remove(core::Download* download, const torrent::Object& rawArgs, const ch
#define CMD2_BIND_CL std::bind(&core::Download::connection_list, std::placeholders::_1)
#define CMD2_BIND_FL std::bind(&core::Download::file_list, std::placeholders::_1)
#define CMD2_BIND_PL std::bind(&core::Download::c_peer_list, std::placeholders::_1)
#define CMD2_BIND_TL std::bind(&core::Download::tracker_list, std::placeholders::_1)
#define CMD2_BIND_TC std::bind(&core::Download::tracker_controller, std::placeholders::_1)
#define CMD2_BIND_INFO std::bind(&core::Download::info, std::placeholders::_1)
@@ -812,8 +777,8 @@ initialize_command_download() {
CMD2_DL ("d.views", std::bind(&download_get_variable, std::placeholders::_1, "rtorrent", "views"));
CMD2_DL ("d.views.has", std::bind(&d_list_has, std::placeholders::_1, std::placeholders::_2, "rtorrent", "views"));
CMD2_DL ("d.views.remove", std::bind(&d_list_remove, std::placeholders::_1, std::placeholders::_2, "rtorrent", "views"));
CMD2_DL ("d.views.push_back", std::bind(&d_list_push_back, std::placeholders::_1, std::placeholders::_2, "rtorrent", "views"));
CMD2_DL ("d.views.push_back_unique", std::bind(&d_list_push_back_unique, std::placeholders::_1, std::placeholders::_2, "rtorrent", "views"));
CMD2_DL ("d.views.push_back", std::bind(&d_list_push_back_string, std::placeholders::_1, std::placeholders::_2, "rtorrent", "views"));
CMD2_DL ("d.views.push_back_unique", std::bind(&d_list_push_back_unique_string, std::placeholders::_1, std::placeholders::_2, "rtorrent", "views"));
// This command really needs to be improved, so we have proper
// logging support.
@@ -871,17 +836,20 @@ initialize_command_download() {
CMD2_DL ("d.wanted_chunks", CMD2_ON_DATA(wanted_chunks));
// Do not exposre d.tracker_announce.force to regular users.
CMD2_DL_V ("d.tracker_announce", std::bind(&torrent::Download::manual_request, CMD2_BIND_DL, false));
CMD2_DL_V ("d.tracker_announce.force", std::bind(&torrent::Download::manual_request, CMD2_BIND_DL, true));
CMD2_DL_V ("d.tracker_announce", std::bind(&torrent::Download::manual_request, CMD2_BIND_DL, false));
CMD2_DL_V ("d.tracker_announce.force", std::bind(&torrent::Download::manual_request, CMD2_BIND_DL, true));
CMD2_DL ("d.tracker_numwant", std::bind(&torrent::TrackerList::numwant, CMD2_BIND_TL));
CMD2_DL_VALUE_V ("d.tracker_numwant.set", std::bind(&torrent::TrackerList::set_numwant, CMD2_BIND_TL, std::placeholders::_2));
CMD2_DL ("d.tracker_numwant", std::bind(&torrent::tracker::TrackerControllerWrapper::numwant, CMD2_BIND_TC));
CMD2_DL_VALUE_V ("d.tracker_numwant.set", std::bind(&torrent::tracker::TrackerControllerWrapper::set_numwant, CMD2_BIND_TC, std::placeholders::_2));
// TODO: Deprecate 'd.tracker_focus'.
CMD2_DL ("d.tracker_focus", std::bind(&core::Download::tracker_list_size, std::placeholders::_1));
CMD2_DL ("d.tracker_size", std::bind(&core::Download::tracker_list_size, std::placeholders::_1));
CMD2_DL_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::tracker::TrackerControllerWrapper::has_active_trackers, CMD2_BIND_TC));
CMD2_DL ("d.tracker.has_active_not_scrape", std::bind(&torrent::tracker::TrackerControllerWrapper::has_active_trackers_not_scrape, CMD2_BIND_TC));
CMD2_DL ("d.tracker.has_usable", std::bind(&torrent::tracker::TrackerControllerWrapper::has_usable_trackers, CMD2_BIND_TC));
CMD2_DL_LIST ("d.tracker.insert", std::bind(&download_tracker_insert, std::placeholders::_1, std::placeholders::_2));
CMD2_DL_VALUE_V ("d.tracker.send_scrape", [](auto download, uint64_t arg) { download->tracker_controller().scrape_request(arg); });
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));
+7 -42
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <algorithm>
@@ -187,7 +151,7 @@ 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;
if ((flags & rpc::object_storage::mask_type) == rpc::object_storage::flag_list_type) {
torrent::Object valueList = torrent::Object::create_list();
@@ -360,7 +324,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(new_key, dest_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_modifiable);
rpc::commands.create_redirect(new_key, dest_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_modifiable);
return torrent::Object();
}
@@ -443,12 +407,13 @@ cmd_catch(rpc::target_type target, const torrent::Object& args) {
void
initialize_command_dynamic() {
// clang-format off
#ifdef HAVE_XMLRPC_TINYXML2
#ifdef HAVE_XMLRPC_TINYXML2
CMD2_ANY ("system.listMethods", std::bind(&system_listMethods)); // only used by tinyxml2
#endif
#endif
CMD2_VAR_BOOL ("method.use_deprecated", true);
CMD2_VAR_VALUE ("method.use_intermediate", 1);
// Keep these for future use when we deprecate more commands.
CMD2_VAR_BOOL ("method.use_deprecated", false);
CMD2_VAR_VALUE ("method.use_intermediate", 0);
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));
+71 -121
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>
@@ -47,6 +11,9 @@
#include <torrent/utils/log.h>
#include <torrent/utils/directory_events.h>
#include "globals.h"
#include "control.h"
#include "command_helpers.h"
#include "core/download.h"
#include "core/download_list.h"
#include "core/manager.h"
@@ -55,74 +22,55 @@
#include "rpc/parse.h"
#include "rpc/parse_commands.h"
#include "globals.h"
#include "control.h"
#include "command_helpers.h"
#include "thread_worker.h"
torrent::Object
apply_on_ratio(const torrent::Object& rawArgs) {
const std::string& groupName = rawArgs.as_string();
auto& group_name = rawArgs.as_string();
auto view_itr = control->view_manager()->find(rpc::commands.call("group2." + group_name + ".view", rpc::make_target()).as_string());
char buffer[32 + groupName.size()];
sprintf(buffer, "group2.%s.view", groupName.c_str());
core::ViewManager::iterator viewItr = control->view_manager()->find(rpc::commands.call(buffer, rpc::make_target()).as_string());
if (viewItr == control->view_manager()->end())
if (view_itr == control->view_manager()->end())
throw torrent::input_error("Could not find view.");
char* bufferStart = buffer + sprintf(buffer, "group2.%s.ratio.", groupName.c_str());
// first argument: minimum ratio to reach
// second argument: minimum upload amount to reach [optional]
// third argument: maximum ratio to reach [optional]
std::strcpy(bufferStart, "min");
int64_t minRatio = rpc::commands.call(buffer, rpc::make_target()).as_value();
std::strcpy(bufferStart, "max");
int64_t maxRatio = rpc::commands.call(buffer, rpc::make_target()).as_value();
std::strcpy(bufferStart, "upload");
int64_t minUpload = rpc::commands.call(buffer, rpc::make_target()).as_value();
int64_t min_ratio = rpc::commands.call("group2." + group_name + ".ratio.min", rpc::make_target()).as_value();
int64_t max_ratio = rpc::commands.call("group2." + group_name + ".ratio.max", rpc::make_target()).as_value();
int64_t min_upload = rpc::commands.call("group2." + group_name + ".ratio.upload", rpc::make_target()).as_value();
std::vector<core::Download*> downloads;
for (core::View::iterator itr = (*viewItr)->begin_visible(), last = (*viewItr)->end_visible(); itr != last; itr++) {
for (auto itr = (*view_itr)->begin_visible(), last = (*view_itr)->end_visible(); itr != last; itr++) {
if (!(*itr)->is_seeding() || rpc::call_command_value("d.ignore_commands", rpc::make_target(*itr)) != 0)
continue;
// rpc::parse_command_single(rpc::make_target(*itr), "print={Checked ratio of download.}");
int64_t total_done = (*itr)->download()->bytes_done();
int64_t total_upload = (*itr)->info()->up_rate()->total();
int64_t totalDone = (*itr)->download()->bytes_done();
int64_t totalUpload = (*itr)->info()->up_rate()->total();
if (!(totalUpload >= minUpload && totalUpload * 100 >= totalDone * minRatio) &&
!(maxRatio > 0 && totalUpload * 100 > totalDone * maxRatio))
if (!(total_upload >= min_upload && total_upload * 100 >= total_done * min_ratio) &&
!(max_ratio > 0 && total_upload * 100 > total_done * max_ratio))
continue;
downloads.push_back(*itr);
}
sprintf(buffer, "group.%s.ratio.command", groupName.c_str());
auto ratio_command = "group." + group_name + ".ratio.command";
for (std::vector<core::Download*>::iterator itr = downloads.begin(), last = downloads.end(); itr != last; itr++) {
// rpc::commands.call("print", rpc::make_target(*itr), "Calling ratio command.");
rpc::commands.call_catch(buffer, rpc::make_target(*itr), torrent::Object(), "Ratio reached, but command failed: ");
}
for (std::vector<core::Download*>::iterator itr = downloads.begin(), last = downloads.end(); itr != last; itr++)
rpc::commands.call_catch(ratio_command, rpc::make_target(*itr), torrent::Object(), "Ratio reached, but command failed: ");
return torrent::Object();
}
torrent::Object
apply_start_tied() {
for (core::DownloadList::iterator itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ++itr) {
for (auto itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ++itr) {
if (rpc::call_command_value("d.state", rpc::make_target(*itr)) == 1)
continue;
rak::file_stat fs;
const std::string& tiedToFile = rpc::call_command_string("d.tied_to_file", rpc::make_target(*itr));
const std::string& tied_to_file = rpc::call_command_string("d.tied_to_file", rpc::make_target(*itr));
if (!tiedToFile.empty() && fs.update(rak::path_expand(tiedToFile)))
if (!tied_to_file.empty() && fs.update(rak::path_expand(tied_to_file)))
rpc::parse_command_single(rpc::make_target(*itr), "d.try_start=");
}
@@ -131,14 +79,14 @@ apply_start_tied() {
torrent::Object
apply_stop_untied() {
for (core::DownloadList::iterator itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ++itr) {
for (auto itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ++itr) {
if (rpc::call_command_value("d.state", rpc::make_target(*itr)) == 0)
continue;
rak::file_stat fs;
const std::string& tiedToFile = rpc::call_command_string("d.tied_to_file", rpc::make_target(*itr));
const std::string& tied_to_file = rpc::call_command_string("d.tied_to_file", rpc::make_target(*itr));
if (!tiedToFile.empty() && !fs.update(rak::path_expand(tiedToFile)))
if (!tied_to_file.empty() && !fs.update(rak::path_expand(tied_to_file)))
rpc::parse_command_single(rpc::make_target(*itr), "d.try_stop=");
}
@@ -147,11 +95,11 @@ apply_stop_untied() {
torrent::Object
apply_close_untied() {
for (core::DownloadList::iterator itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ++itr) {
for (auto itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ++itr) {
rak::file_stat fs;
const std::string& tiedToFile = rpc::call_command_string("d.tied_to_file", rpc::make_target(*itr));
const std::string& tied_to_file = rpc::call_command_string("d.tied_to_file", rpc::make_target(*itr));
if (rpc::call_command_value("d.ignore_commands", rpc::make_target(*itr)) == 0 && !tiedToFile.empty() && !fs.update(rak::path_expand(tiedToFile)))
if (rpc::call_command_value("d.ignore_commands", rpc::make_target(*itr)) == 0 && !tied_to_file.empty() && !fs.update(rak::path_expand(tied_to_file)))
rpc::parse_command_single(rpc::make_target(*itr), "d.try_close=");
}
@@ -160,11 +108,11 @@ apply_close_untied() {
torrent::Object
apply_remove_untied() {
for (core::DownloadList::iterator itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ) {
for (auto itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ) {
rak::file_stat fs;
const std::string& tiedToFile = rpc::call_command_string("d.tied_to_file", rpc::make_target(*itr));
const std::string& tied_to_file = rpc::call_command_string("d.tied_to_file", rpc::make_target(*itr));
if (!tiedToFile.empty() && !fs.update(rak::path_expand(tiedToFile))) {
if (!tied_to_file.empty() && !fs.update(rak::path_expand(tied_to_file))) {
// Need to clear tied_to_file so it doesn't try to delete it.
rpc::call_command("d.tied_to_file.set", std::string(), rpc::make_target(*itr));
@@ -185,9 +133,9 @@ apply_schedule(const torrent::Object::list_type& args) {
torrent::Object::list_const_iterator itr = args.begin();
const std::string& arg1 = (itr++)->as_string();
const std::string& arg2 = (itr++)->as_string();
const std::string& arg3 = (itr++)->as_string();
auto& arg1 = (itr++)->as_string();
auto& arg2 = (itr++)->as_string();
auto& arg3 = (itr++)->as_string();
control->command_scheduler()->parse(arg1, arg2, arg3, *itr);
@@ -201,7 +149,7 @@ apply_load(const torrent::Object::list_type& args, int flags) {
if (argsItr == args.end())
throw torrent::input_error("Too few arguments.");
const std::string& filename = argsItr->as_string();
auto& filename = argsItr->as_string();
core::Manager::command_list_type commands;
while (++argsItr != args.end())
@@ -216,28 +164,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();
}
@@ -247,20 +194,20 @@ apply_download_list(const torrent::Object::list_type& args) {
torrent::Object::list_const_iterator argsItr = args.begin();
core::ViewManager* viewManager = control->view_manager();
core::ViewManager::iterator viewItr;
core::ViewManager::iterator view_itr;
if (argsItr != args.end() && !argsItr->as_string().empty())
viewItr = viewManager->find((argsItr++)->as_string());
view_itr = viewManager->find((argsItr++)->as_string());
else
viewItr = viewManager->find("default");
view_itr = viewManager->find("default");
if (viewItr == viewManager->end())
if (view_itr == viewManager->end())
throw torrent::input_error("Could not find view.");
torrent::Object result = torrent::Object::create_list();
torrent::Object::list_type& resultList = result.as_list();
for (core::View::const_iterator itr = (*viewItr)->begin_visible(), last = (*viewItr)->end_visible(); itr != last; itr++) {
for (core::View::const_iterator itr = (*view_itr)->begin_visible(), last = (*view_itr)->end_visible(); itr != last; itr++) {
const torrent::HashString* hashString = &(*itr)->info()->hash();
resultList.push_back(rak::transform_hex(hashString->begin(), hashString->end()));
@@ -275,32 +222,31 @@ d_multicall(const torrent::Object::list_type& args) {
throw torrent::input_error("Too few arguments.");
core::ViewManager* viewManager = control->view_manager();
core::ViewManager::iterator viewItr;
core::ViewManager::iterator view_itr;
if (!args.front().as_string().empty())
viewItr = viewManager->find(args.front().as_string());
view_itr = viewManager->find(args.front().as_string());
else
viewItr = viewManager->find("default");
view_itr = viewManager->find("default");
if (viewItr == viewManager->end())
if (view_itr == viewManager->end())
throw torrent::input_error("Could not find view.");
// Add some pre-parsing of the commands, so we don't spend time
// parsing and searching command map for every single call.
unsigned int dlist_size = (*viewItr)->size_visible();
core::Download* dlist[dlist_size];
std::vector<core::Download*> dlist((*view_itr)->size_visible());
std::copy((*viewItr)->begin_visible(), (*viewItr)->end_visible(), dlist);
std::copy((*view_itr)->begin_visible(), (*view_itr)->end_visible(), dlist.data());
torrent::Object resultRaw = torrent::Object::create_list();
torrent::Object::list_type& result = resultRaw.as_list();
for (core::Download** vItr = dlist; vItr != dlist + dlist_size; vItr++) {
for (auto download : dlist) {
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
for (torrent::Object::list_const_iterator cItr = ++args.begin(); cItr != args.end(); cItr++) {
const std::string& cmd = cItr->as_string();
row.push_back(rpc::parse_command(rpc::make_target(*vItr), cmd.c_str(), cmd.c_str() + cmd.size()).first);
auto& cmd = cItr->as_string();
row.push_back(rpc::parse_command(rpc::make_target(download), cmd.c_str(), cmd.c_str() + cmd.size()).first);
}
}
@@ -315,14 +261,14 @@ d_multicall_filtered(const torrent::Object::list_type& args) {
// Find the given view
core::ViewManager* viewManager = control->view_manager();
core::ViewManager::iterator viewItr = viewManager->find(arg->as_string().empty() ? "default" : arg->as_string());
core::ViewManager::iterator view_itr = viewManager->find(arg->as_string().empty() ? "default" : arg->as_string());
if (viewItr == viewManager->end())
if (view_itr == viewManager->end())
throw torrent::input_error("Could not find view '" + arg->as_string() + "'.");
// Make a filtered copy of the current item list
core::View::base_type dlist;
(*viewItr)->filter_by(*++arg, dlist);
(*view_itr)->filter_by(*++arg, dlist);
// Generate result by iterating over all items
torrent::Object resultRaw = torrent::Object::create_list();
@@ -335,7 +281,7 @@ d_multicall_filtered(const torrent::Object::list_type& args) {
// 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();
auto& cmdstr = command->as_string();
row.push_back(rpc::parse_command(rpc::make_target(*item), cmdstr.c_str(), cmdstr.c_str() + cmdstr.size()).first);
}
}
@@ -353,8 +299,8 @@ directory_watch_added(const torrent::Object::list_type& args) {
if (args.size() != 2)
throw torrent::input_error("Too few arguments.");
const std::string& path = args.front().as_string();
const std::string& command = args.back().as_string();
auto& path = args.front().as_string();
auto& command = args.back().as_string();
if (!control->directory_events()->open())
throw torrent::input_error("Could not open inotify:" + std::string(rak::error_number::current().c_str()));
@@ -374,7 +320,10 @@ initialize_command_events() {
CMD2_ANY ("close_untied", std::bind(&apply_close_untied));
CMD2_ANY ("remove_untied", std::bind(&apply_remove_untied));
// TODO: Deprecate schedule2 in the future.
CMD2_ANY_LIST ("schedule", std::bind(&apply_schedule, std::placeholders::_2));
CMD2_ANY_LIST ("schedule2", std::bind(&apply_schedule, std::placeholders::_2));
CMD2_ANY_STRING_V("schedule.remove", std::bind(&rpc::CommandScheduler::erase_str, control->command_scheduler(), std::placeholders::_2));
CMD2_ANY_STRING_V("schedule_remove2", std::bind(&rpc::CommandScheduler::erase_str, control->command_scheduler(), std::placeholders::_2));
CMD2_ANY_STRING_V("import", std::bind(&apply_import, std::placeholders::_2));
@@ -391,7 +340,8 @@ initialize_command_events() {
core::Manager::create_quiet | core::Manager::create_start | core::Manager::create_raw_data));
CMD2_ANY_LIST ("load.raw_start_verbose", std::bind(&apply_load, std::placeholders::_2, core::Manager::create_start | core::Manager::create_raw_data));
CMD2_ANY_VALUE ("close_low_diskspace", std::bind(&apply_close_low_diskspace, std::placeholders::_2));
CMD2_ANY_VALUE ("close_low_diskspace", std::bind(&apply_close_low_diskspace, std::placeholders::_2, 99));
CMD2_ANY_VALUE ("close_low_diskspace.normal", std::bind(&apply_close_low_diskspace, std::placeholders::_2, 3));
CMD2_ANY_LIST ("download_list", std::bind(&apply_download_list, std::placeholders::_2));
CMD2_ANY_LIST ("d.multicall2", std::bind(&d_multicall, std::placeholders::_2));
+3 -5
View File
@@ -29,10 +29,8 @@
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Contact: Jari Sundell <sundell.software@gmail.com>
#include "config.h"
@@ -53,7 +51,7 @@ apply_f_set_priority(torrent::File* file, uint32_t value) {
if (value > torrent::PRIORITY_HIGH)
throw torrent::input_error("Invalid value.");
file->set_priority((torrent::priority_t)value);
file->set_priority(static_cast<torrent::priority_enum>(value));
}
// TODO: Redundant.
+2 -4
View File
@@ -29,10 +29,8 @@
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Contact: Jari Sundell <sundell.software@gmail.com>
#include "config.h"
+9 -45
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_UTILS_COMMAND_HELPERS_H
#define RTORRENT_UTILS_COMMAND_HELPERS_H
@@ -49,7 +13,7 @@ void initialize_commands();
#define CMD2_A_FUNCTION(key, function, slot, parm, doc) \
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::function>::type>(key, slot, &rpc::function, \
rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_xmlrpc, NULL, NULL);
rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_rpc, NULL, NULL);
#define CMD2_A_FUNCTION_PRIVATE(key, function, slot, parm, doc) \
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::function>::type>(key, slot, &rpc::function, \
@@ -92,9 +56,9 @@ void initialize_commands();
#define CMD2_PEER_V(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::Peer*>, object_convert_void(slot), "i:", "")
#define CMD2_PEER_VALUE_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_value<torrent::Peer*>, object_convert_void(slot), "i:i", "")
#define CMD2_TRACKER(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::Tracker*>, slot, "i:", "")
#define CMD2_TRACKER_V(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::Tracker*>, object_convert_void(slot), "i:", "")
#define CMD2_TRACKER_VALUE_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_value<torrent::Tracker*>, object_convert_void(slot), "i:i", "")
#define CMD2_TRACKER(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::tracker::Tracker*>, slot, "i:", "")
#define CMD2_TRACKER_V(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::tracker::Tracker*>, object_convert_void(slot), "i:", "")
#define CMD2_TRACKER_VALUE_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_value<torrent::tracker::Tracker*>, object_convert_void(slot), "i:i", "")
#define CMD2_VAR_BOOL(key, value) \
control->object_storage()->insert_c_str(key, int64_t(value), rpc::object_storage::flag_bool_type); \
@@ -137,19 +101,19 @@ void initialize_commands();
std::placeholders::_1, std::placeholders::_2));
#define CMD2_REDIRECT(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_dont_delete);
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_dont_delete);
#define CMD2_REDIRECT_GENERIC(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_dont_delete);
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_dont_delete);
#define CMD2_REDIRECT_GENERIC_NO_EXPORT(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_dont_delete);
#define CMD2_REDIRECT_FILE(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_file_target | rpc::CommandMap::flag_dont_delete);
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_file_target | rpc::CommandMap::flag_dont_delete);
#define CMD2_REDIRECT_TRACKER(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_tracker_target | rpc::CommandMap::flag_dont_delete);
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_tracker_target | rpc::CommandMap::flag_dont_delete);
#define CMD2_REDIRECT_GENERIC_STR(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, \
rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_no_target);
rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_no_target);
#define CMD2_REDIRECT_GENERIC_STR_NO_EXPORT(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, \
+2 -4
View File
@@ -29,10 +29,8 @@
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Contact: Jari Sundell <sundell.software@gmail.com>
#include "config.h"
+27 -41
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <fcntl.h>
@@ -60,6 +24,7 @@
#include "utils/file_status_cache.h"
#include "globals.h"
#include "rpc/lua.h"
#include "control.h"
#include "command_helpers.h"
@@ -241,6 +206,7 @@ initialize_command_local() {
CMD2_VAR_C_STRING("system.api_version", (int64_t)API_VERSION);
CMD2_VAR_C_STRING("system.client_version", PACKAGE_VERSION);
CMD2_VAR_C_STRING("system.library_version", torrent::version());
CMD2_VAR_VALUE ("system.file.allocate", 0);
CMD2_VAR_VALUE ("system.file.max_size", (int64_t)512 << 30);
CMD2_VAR_VALUE ("system.file.split_size", -1);
@@ -254,15 +220,27 @@ initialize_command_local() {
CMD2_VAR_LIST ("file.prioritize_toc.first");
CMD2_VAR_LIST ("file.prioritize_toc.last");
CMD2_ANY ("system.files.advise_random", std::bind(&FM_t::advise_random, fileManager));
CMD2_ANY_VALUE_V ("system.files.advise_random.set", std::bind(&FM_t::set_advise_random, fileManager, std::placeholders::_2));
CMD2_ANY ("system.files.advise_random.hashing", std::bind(&FM_t::advise_random_hashing, fileManager));
CMD2_ANY_VALUE_V ("system.files.advise_random.hashing.set", std::bind(&FM_t::set_advise_random_hashing, fileManager, std::placeholders::_2));
CMD2_VAR_BOOL ("system.files.session.fdatasync", true);
CMD2_ANY ("system.files.opened_counter", std::bind(&FM_t::files_opened_counter, fileManager));
CMD2_ANY ("system.files.closed_counter", std::bind(&FM_t::files_closed_counter, fileManager));
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 ("system.time", []([[maybe_unused]] auto t, [[maybe_unused]] auto o) -> torrent::Object {
return torrent::this_thread::cached_seconds().count();
});
CMD2_ANY ("system.time_seconds", []([[maybe_unused]] auto t, [[maybe_unused]] auto o) -> torrent::Object {
return torrent::utils::cast_seconds(torrent::utils::time_since_epoch()).count();
});
CMD2_ANY ("system.time_usec", []([[maybe_unused]] auto t, [[maybe_unused]] auto o) -> torrent::Object {
return torrent::utils::time_since_epoch().count();
});
CMD2_ANY_VALUE_V ("system.umask.set", std::bind(&umask, std::placeholders::_2));
@@ -301,7 +279,7 @@ initialize_command_local() {
CMD2_ANY ("pieces.stats.total_size", std::bind(&apply_pieces_stats_total_size));
CMD2_ANY ("pieces.hash.queue_size", std::bind(&torrent::hash_queue_size));
CMD2_ANY ("pieces.hash.queue_size", std::bind(&torrent::main_thread::hash_queue_size));
CMD2_VAR_BOOL ("pieces.hash.on_completion", true);
CMD2_VAR_STRING ("directory.default", "./");
@@ -315,9 +293,17 @@ initialize_command_local() {
CMD2_ANY_V ("session.save", std::bind(&core::DownloadList::session_save, dList));
#define CMD2_EXECUTE(key, flags) \
#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));
CMD2_EXECUTE ("execute", rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_throw);
CMD2_EXECUTE ("execute2", rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_throw);
CMD2_EXECUTE ("execute.throw", rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_throw);
CMD2_EXECUTE ("execute.throw.bg", rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_throw | rpc::ExecFile::flag_background);
+2 -1
View File
@@ -142,5 +142,6 @@ initialize_command_logging() {
CMD2_ANY_STRING ("log.execute", std::bind(&apply_log, std::placeholders::_2, 0));
CMD2_ANY_STRING ("log.vmmap.dump", std::bind(&log_vmmap_dump, std::placeholders::_2));
CMD2_ANY_STRING_V("log.xmlrpc", std::bind(&ThreadWorker::set_xmlrpc_log, worker_thread, std::placeholders::_2));
CMD2_ANY_STRING_V("log.rpc", std::bind(&ThreadWorker::set_rpc_log, worker_thread, std::placeholders::_2));
CMD2_REDIRECT ("log.xmlrpc", "log.rpc"); // For backwards compatibility
}
+41 -80
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,7 @@
#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>
@@ -51,6 +14,7 @@
#include <torrent/utils/log.h>
#include <torrent/utils/option_strings.h>
#include "core/curl_stack.h"
#include "core/download.h"
#include "core/manager.h"
#include "rpc/scgi.h"
@@ -94,51 +58,46 @@ apply_tos(const torrent::Object::string_type& arg) {
torrent::Object apply_encoding_list(const std::string& arg) { torrent::encoding_list()->push_back(arg); return torrent::Object(); }
torrent::File*
xmlrpc_find_file(core::Download* download, uint32_t index) {
if (index >= download->file_list()->size_files())
return NULL;
return (*download->file_list())[index];
}
// Ergh... time to update the Tracker API to allow proper ptrs.
torrent::Tracker*
xmlrpc_find_tracker(core::Download* download, uint32_t index) {
if (index >= download->tracker_list()->size())
return NULL;
return download->tracker_list()->at(index);
}
torrent::Peer*
xmlrpc_find_peer(core::Download* download, const torrent::HashString& hash) {
torrent::ConnectionList::iterator itr = download->connection_list()->find(hash.c_str());
if (itr == download->connection_list()->end())
return NULL;
return *itr;
}
void
initialize_xmlrpc() {
rpc::xmlrpc.initialize();
rpc::xmlrpc.slot_find_download() = std::bind(&core::DownloadList::find_hex_ptr, control->core()->download_list(), std::placeholders::_1);
rpc::xmlrpc.slot_find_file() = std::bind(&xmlrpc_find_file, std::placeholders::_1, std::placeholders::_2);
rpc::xmlrpc.slot_find_tracker() = std::bind(&xmlrpc_find_tracker, std::placeholders::_1, std::placeholders::_2);
rpc::xmlrpc.slot_find_peer() = std::bind(&xmlrpc_find_peer, std::placeholders::_1, std::placeholders::_2);
initialize_rpc() {
rpc::rpc.initialize();
rpc::rpc.slot_find_download() = [](const char* hash) {
return control->core()->download_list()->find_hex_ptr(hash);
};
rpc::rpc.slot_find_file() = [](core::Download* d, uint32_t index) -> torrent::File* {
if (index >= d->file_list()->size_files())
throw torrent::input_error("invalid parameters: index not found");
return (*d->file_list())[index].get();
};
rpc::rpc.slot_find_tracker() = [](core::Download* d, uint32_t index) -> torrent::tracker::Tracker {
if (index >= d->tracker_controller().size())
throw torrent::input_error("invalid parameters: index not found");
// TODO: This should be rewritten to check if the tracker is valid and use a different
// function.
return d->tracker_controller().at(index);
};
rpc::rpc.slot_find_peer() = [](core::Download* d, const torrent::HashString& hash) -> torrent::Peer* {
auto itr = d->connection_list()->find(hash.c_str());
if (itr == d->connection_list()->end())
throw torrent::input_error("invalid parameters: hash not found");
return *itr;
};
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.c_str(), itr->second.m_parm, itr->second.m_doc);
rpc::rpc.insert_command(itr->first.c_str(), itr->second.m_parm, itr->second.m_doc);
}
lt_log_print(torrent::LOG_RPC_EVENTS, "XMLRPC initialized with %u functions.", count);
lt_log_print(torrent::LOG_RPC_EVENTS, "RPC initialized with %u functions.", count);
}
torrent::Object
@@ -146,8 +105,7 @@ apply_scgi(const std::string& arg, int type) {
if (worker_thread->scgi() != NULL)
throw torrent::input_error("SCGI already enabled.");
if (!rpc::xmlrpc.is_valid())
initialize_xmlrpc();
initialize_rpc();
rpc::SCgi* scgi = new rpc::SCgi;
@@ -225,7 +183,7 @@ apply_xmlrpc_dialect(const std::string& arg) {
else
value = -1;
rpc::xmlrpc.set_dialect(value);
rpc::rpc.set_dialect(value);
return torrent::Object();
}
@@ -298,9 +256,12 @@ initialize_command_network() {
CMD2_ANY_STRING ("network.scgi.open_local", std::bind(&apply_scgi, std::placeholders::_2, 2));
CMD2_VAR_BOOL ("network.scgi.dont_route", false);
CMD2_ANY_STRING ("network.xmlrpc.dialect.set", std::bind(&apply_xmlrpc_dialect, std::placeholders::_2));
CMD2_ANY ("network.xmlrpc.size_limit", std::bind(&rpc::XmlRpc::size_limit, rpc::xmlrpc));
CMD2_ANY_VALUE_V ("network.xmlrpc.size_limit.set", std::bind(&rpc::XmlRpc::set_size_limit, rpc::xmlrpc, std::placeholders::_2));
CMD2_ANY_STRING ("network.xmlrpc.dialect.set", [](const auto&, const auto& arg) { return apply_xmlrpc_dialect(arg); })
CMD2_ANY ("network.xmlrpc.size_limit", [](const auto&, const auto&){ return rpc::rpc.size_limit(); });
CMD2_ANY_VALUE_V ("network.xmlrpc.size_limit.set", [](const auto&, const auto& arg){ return rpc::rpc.set_size_limit(arg); });
CMD2_VAR_BOOL ("network.rpc.use_xmlrpc", true);
CMD2_VAR_BOOL ("network.rpc.use_jsonrpc", true);
CMD2_ANY ("network.block.ipv4", std::bind(&torrent::ConnectionManager::is_block_ipv4, cm));
CMD2_ANY_VALUE_V ("network.block.ipv4.set", std::bind(&torrent::ConnectionManager::set_block_ipv4, cm, std::placeholders::_2));
+2 -4
View File
@@ -29,10 +29,8 @@
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Contact: Jari Sundell <sundell.software@gmail.com>
#include "config.h"
+3 -41
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <sys/types.h>
@@ -52,7 +16,7 @@ torrent::Object
cmd_scheduler_simple_added(core::Download* download) {
unsigned int numActive = (*control->view_manager()->find("active"))->size_visible();
int64_t maxActive = rpc::call_command("scheduler.max_active", torrent::Object()).as_value();
if (numActive < (uint64_t)maxActive)
control->core()->download_list()->resume(download);
@@ -83,7 +47,7 @@ cmd_scheduler_simple_removed(core::Download* download) {
}
torrent::Object
cmd_scheduler_simple_update(core::Download* download) {
cmd_scheduler_simple_update([[maybe_unused]] core::Download* download) {
core::View* viewActive = *control->view_manager()->find("active");
core::View* viewStarted = *control->view_manager()->find("started");
@@ -91,7 +55,6 @@ cmd_scheduler_simple_update(core::Download* download) {
uint64_t maxActive = rpc::call_command("scheduler.max_active", torrent::Object()).as_value();
if (viewActive->size_visible() < maxActive) {
for (core::View::iterator itr = viewStarted->begin_visible(), last = viewStarted->end_visible(); itr != last; itr++) {
if ((*itr)->is_active())
continue;
@@ -102,8 +65,7 @@ cmd_scheduler_simple_update(core::Download* download) {
break;
}
} else if (viewActive->size_visible() > maxActive) {
} else {
while (viewActive->size_visible() > maxActive)
control->core()->download_list()->pause(*viewActive->begin_visible());
}
+2 -4
View File
@@ -29,10 +29,8 @@
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Contact: Jari Sundell <sundell.software@gmail.com>
#include "config.h"
+69 -93
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 <cassert>
#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 +19,16 @@
#include "core/dht_manager.h"
void
tracker_set_enabled(torrent::Tracker* tracker, bool state) {
tracker_set_enabled(torrent::tracker::Tracker* tracker, bool state) {
if (state)
tracker->enable();
else
tracker->disable();
}
struct call_add_node_t {
call_add_node_t(int port) : m_port(port) { }
void operator() (const sockaddr* sa, int err) {
if (sa == NULL) {
lt_log_print(torrent::LOG_DHT_WARN, "Could not resolve host.");
} else {
torrent::dht_manager()->add_node(sa, m_port);
}
}
int m_port;
};
torrent::Object
apply_dht_add_node(const std::string& arg) {
if (!torrent::dht_manager()->is_valid())
if (!torrent::dht_controller()->is_valid())
throw torrent::input_error("DHT not enabled.");
int port, ret;
@@ -92,68 +45,91 @@ 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));
assert(std::this_thread::get_id() == torrent::main_thread::thread()->thread_id());
// Currently discarding SOCK_STREAM.
torrent::this_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));
if (arg == 0) {
for (auto itr : *control->core()->download_list())
itr->tracker_controller().for_each([](auto& tracker) { tracker.disable(); });
if (arg && !rpc::call_command_value("trackers.use_udp"))
(*itr)->enable_udp_trackers(false);
}
} else if (rpc::call_command_value("trackers.use_udp") == 0) {
for (auto itr : *control->core()->download_list()) {
itr->tracker_controller().for_each([](auto& tracker) {
if (tracker.type() == torrent::TRACKER_UDP)
tracker.disable();
else
tracker.enable();
});
}
} else {
for (auto itr : *control->core()->download_list())
itr->tracker_controller().for_each([](auto& tracker) { tracker.enable(); });
}
return torrent::Object();
}
void
initialize_command_tracker() {
CMD2_TRACKER ("t.is_open", std::bind(&torrent::Tracker::is_busy, std::placeholders::_1));
CMD2_TRACKER ("t.is_enabled", std::bind(&torrent::Tracker::is_enabled, std::placeholders::_1));
CMD2_TRACKER ("t.is_usable", std::bind(&torrent::Tracker::is_usable, std::placeholders::_1));
CMD2_TRACKER ("t.is_busy", std::bind(&torrent::Tracker::is_busy, std::placeholders::_1));
CMD2_TRACKER ("t.is_extra_tracker", std::bind(&torrent::Tracker::is_extra_tracker, std::placeholders::_1));
CMD2_TRACKER ("t.can_scrape", std::bind(&torrent::Tracker::can_scrape, std::placeholders::_1));
CMD2_TRACKER ("t.is_busy", std::bind(&torrent::tracker::Tracker::is_busy, std::placeholders::_1));
CMD2_TRACKER ("t.is_enabled", std::bind(&torrent::tracker::Tracker::is_enabled, std::placeholders::_1));
CMD2_TRACKER ("t.is_extra_tracker", std::bind(&torrent::tracker::Tracker::is_extra_tracker, std::placeholders::_1));
CMD2_TRACKER ("t.is_open", std::bind(&torrent::tracker::Tracker::is_busy, std::placeholders::_1));
CMD2_TRACKER ("t.is_scrapable", std::bind(&torrent::tracker::Tracker::is_scrapable, std::placeholders::_1));
CMD2_TRACKER ("t.is_usable", std::bind(&torrent::tracker::Tracker::is_usable, std::placeholders::_1));
CMD2_TRACKER_V ("t.enable", std::bind(&torrent::Tracker::enable, std::placeholders::_1));
CMD2_TRACKER_V ("t.disable", std::bind(&torrent::Tracker::disable, std::placeholders::_1));
// TODO: Deprecate.
CMD2_TRACKER ("t.can_scrape", std::bind(&torrent::tracker::Tracker::is_scrapable, std::placeholders::_1));
CMD2_TRACKER_V ("t.enable", std::bind(&torrent::tracker::Tracker::enable, std::placeholders::_1));
CMD2_TRACKER_V ("t.disable", std::bind(&torrent::tracker::Tracker::disable, std::placeholders::_1));
CMD2_TRACKER_VALUE_V("t.is_enabled.set", std::bind(&tracker_set_enabled, std::placeholders::_1, std::placeholders::_2));
CMD2_TRACKER ("t.url", std::bind(&torrent::Tracker::url, std::placeholders::_1));
CMD2_TRACKER ("t.group", std::bind(&torrent::Tracker::group, std::placeholders::_1));
CMD2_TRACKER ("t.type", std::bind(&torrent::Tracker::type, std::placeholders::_1));
CMD2_TRACKER ("t.id", std::bind(&torrent::Tracker::tracker_id, std::placeholders::_1));
CMD2_TRACKER ("t.url", std::bind(&torrent::tracker::Tracker::url, std::placeholders::_1));
CMD2_TRACKER ("t.group", std::bind(&torrent::tracker::Tracker::group, std::placeholders::_1));
CMD2_TRACKER ("t.type", std::bind(&torrent::tracker::Tracker::type, std::placeholders::_1));
CMD2_TRACKER ("t.id", std::bind(&torrent::tracker::Tracker::tracker_id, std::placeholders::_1));
CMD2_TRACKER ("t.latest_event", std::bind(&torrent::Tracker::latest_event, std::placeholders::_1));
CMD2_TRACKER ("t.latest_new_peers", std::bind(&torrent::Tracker::latest_new_peers, std::placeholders::_1));
CMD2_TRACKER ("t.latest_sum_peers", std::bind(&torrent::Tracker::latest_sum_peers, std::placeholders::_1));
CMD2_TRACKER ("t.latest_event", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().latest_event(); });
CMD2_TRACKER ("t.latest_new_peers", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().latest_new_peers(); });
CMD2_TRACKER ("t.latest_sum_peers", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().latest_sum_peers(); });
// Time since last connection, connection attempt.
CMD2_TRACKER ("t.normal_interval", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().normal_interval(); });
CMD2_TRACKER ("t.min_interval", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().min_interval(); });
CMD2_TRACKER ("t.normal_interval", std::bind(&torrent::Tracker::normal_interval, std::placeholders::_1));
CMD2_TRACKER ("t.min_interval", std::bind(&torrent::Tracker::min_interval, std::placeholders::_1));
CMD2_TRACKER ("t.activity_time_next", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().activity_time_next(); });
CMD2_TRACKER ("t.activity_time_last", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().activity_time_last(); });
CMD2_TRACKER ("t.activity_time_next", std::bind(&torrent::Tracker::activity_time_next, std::placeholders::_1));
CMD2_TRACKER ("t.activity_time_last", std::bind(&torrent::Tracker::activity_time_last, std::placeholders::_1));
CMD2_TRACKER ("t.success_time_next", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().success_time_next(); });
CMD2_TRACKER ("t.success_time_last", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().success_time_last(); });
CMD2_TRACKER ("t.success_counter", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().success_counter(); });
CMD2_TRACKER ("t.success_time_next", std::bind(&torrent::Tracker::success_time_next, std::placeholders::_1));
CMD2_TRACKER ("t.success_time_last", std::bind(&torrent::Tracker::success_time_last, std::placeholders::_1));
CMD2_TRACKER ("t.success_counter", std::bind(&torrent::Tracker::success_counter, std::placeholders::_1));
CMD2_TRACKER ("t.failed_time_next", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().failed_time_next(); });
CMD2_TRACKER ("t.failed_time_last", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().failed_time_last(); });
CMD2_TRACKER ("t.failed_counter", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().failed_counter(); });
CMD2_TRACKER ("t.failed_time_next", std::bind(&torrent::Tracker::failed_time_next, std::placeholders::_1));
CMD2_TRACKER ("t.failed_time_last", std::bind(&torrent::Tracker::failed_time_last, std::placeholders::_1));
CMD2_TRACKER ("t.failed_counter", std::bind(&torrent::Tracker::failed_counter, std::placeholders::_1));
CMD2_TRACKER ("t.scrape_time_last", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().scrape_time_last(); });
CMD2_TRACKER ("t.scrape_counter", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().scrape_counter(); });
CMD2_TRACKER ("t.scrape_time_last", std::bind(&torrent::Tracker::scrape_time_last, std::placeholders::_1));
CMD2_TRACKER ("t.scrape_counter", std::bind(&torrent::Tracker::scrape_counter, std::placeholders::_1));
CMD2_TRACKER ("t.scrape_complete", std::bind(&torrent::Tracker::scrape_complete, std::placeholders::_1));
CMD2_TRACKER ("t.scrape_incomplete", std::bind(&torrent::Tracker::scrape_incomplete, std::placeholders::_1));
CMD2_TRACKER ("t.scrape_downloaded", std::bind(&torrent::Tracker::scrape_downloaded, std::placeholders::_1));
CMD2_TRACKER ("t.scrape_complete", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().scrape_complete(); });
CMD2_TRACKER ("t.scrape_incomplete", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().scrape_incomplete(); });
CMD2_TRACKER ("t.scrape_downloaded", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().scrape_downloaded(); });
CMD2_ANY_VALUE ("trackers.enable", std::bind(&apply_enable_trackers, int64_t(1)));
CMD2_ANY_VALUE ("trackers.disable", std::bind(&apply_enable_trackers, int64_t(0)));
+48 -56
View File
@@ -1,54 +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 <sys/types.h>
#include <ctime>
#include <regex>
#include <rak/algorithm.h>
#include <rak/functional.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"
@@ -63,7 +27,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.");
@@ -130,11 +94,12 @@ apply_view_set(const torrent::Object::list_type& args) {
// if (args.front().as_string() == "main")
// control->ui()->download_list()->set_view(*itr);
// else
throw torrent::input_error("No such target.");
throw torrent::input_error("No such target.");
}
torrent::Object
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);
@@ -143,7 +108,7 @@ apply_print(rpc::target_type target, const torrent::Object& rawArgs) {
}
torrent::Object
apply_cat(rpc::target_type target, const torrent::Object& rawArgs) {
apply_cat([[maybe_unused]] rpc::target_type target, const torrent::Object& rawArgs) {
std::string result;
rpc::print_object_std(&result, &rawArgs, 0);
@@ -151,7 +116,7 @@ apply_cat(rpc::target_type target, const torrent::Object& rawArgs) {
}
torrent::Object
apply_value(rpc::target_type target, const torrent::Object::list_type& args) {
apply_value([[maybe_unused]] rpc::target_type target, const torrent::Object::list_type& args) {
if (args.size() < 1)
throw torrent::input_error("'value' takes at least a number argument!");
if (args.size() > 2)
@@ -219,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;
}
@@ -234,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;
@@ -257,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;
}
@@ -297,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());
@@ -426,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();
@@ -442,7 +407,9 @@ apply_to_time(const torrent::Object& rawArgs, int flags) {
torrent::Object
apply_to_elapsed_time(const torrent::Object& rawArgs) {
uint64_t arg = cachedTime.seconds() - rawArgs.as_value();
auto cached_seconds = torrent::this_thread::cached_seconds().count();
uint64_t arg = cached_seconds - rawArgs.as_value();
char buffer[48];
snprintf(buffer, 48, "%2d:%02d:%02d", (int)(arg / 3600), (int)((arg / 60) % 60), (int)(arg % 60));
@@ -469,7 +436,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));
@@ -485,7 +452,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)
@@ -583,7 +550,7 @@ cmd_view_size_not_visible(const torrent::Object::string_type& args) {
torrent::Object
cmd_view_persistent(const torrent::Object::string_type& args) {
core::View* view = *control->view_manager()->find_throw(args);
if (!view->get_filter().is_empty() || !view->event_added().is_empty() || !view->event_removed().is_empty())
throw torrent::input_error("Cannot set modified views as persitent.");
@@ -640,8 +607,9 @@ apply_elapsed_less(const torrent::Object::list_type& args) {
throw torrent::input_error("Wrong argument count.");
int64_t start_time = rpc::convert_to_value(args.front());
auto cached_seconds = torrent::this_thread::cached_seconds().count();
return (int64_t)(start_time != 0 && rak::timer::current_seconds() - start_time < rpc::convert_to_value(args.back()));
return (int64_t)(start_time != 0 && cached_seconds - start_time < rpc::convert_to_value(args.back()));
}
torrent::Object
@@ -650,8 +618,9 @@ apply_elapsed_greater(const torrent::Object::list_type& args) {
throw torrent::input_error("Wrong argument count.");
int64_t start_time = rpc::convert_to_value(args.front());
auto cached_seconds = torrent::this_thread::cached_seconds().count();
return (int64_t)(start_time != 0 && rak::timer::current_seconds() - start_time > rpc::convert_to_value(args.back()));
return (int64_t)(start_time != 0 && cached_seconds - start_time > rpc::convert_to_value(args.back()));
}
inline std::vector<int64_t>
@@ -796,6 +765,14 @@ cmd_status_throttle_names(bool up, const torrent::Object::list_type& args) {
return torrent::Object();
}
torrent::Object
apply_set_color(int color_id, const torrent::Object::string_type& color_str) {
control->object_storage()->set_str_string(display::color_vars[color_id], color_str);
display::Canvas::build_colors();
return torrent::Object();
}
void
initialize_command_ui() {
CMD2_VAR_STRING("keys.layout", "qwerty");
@@ -843,6 +820,8 @@ initialize_command_ui() {
CMD2_VAR_VALUE ("ui.throttle.global.step.medium", 50);
CMD2_VAR_VALUE ("ui.throttle.global.step.large", 500);
CMD2_VAR_VALUE ("ui.focus.page_size", 0);
CMD2_ANY_LIST ("ui.status.throttle.up.set", std::bind(&cmd_status_throttle_names, true, std::placeholders::_2));
CMD2_ANY_LIST ("ui.status.throttle.down.set", std::bind(&cmd_status_throttle_names, false, std::placeholders::_2));
@@ -893,4 +872,17 @@ initialize_command_ui() {
CMD2_ANY_LIST ("elapsed.less", std::bind(&apply_elapsed_less, std::placeholders::_2));
CMD2_ANY_LIST ("elapsed.greater", std::bind(&apply_elapsed_greater, std::placeholders::_2));
// Build set/get methods for all color definitions
for (int color_id = 1; color_id < display::RCOLOR_MAX; color_id++) {
control->object_storage()->insert_str(display::color_vars[color_id], "", rpc::object_storage::flag_string_type);
CMD2_ANY_STRING(std::string(display::color_vars[color_id]) + ".set", [color_id](const auto&, const auto& arg) {
return apply_set_color(color_id, arg);
});
CMD2_ANY(display::color_vars[color_id], [color_id](const auto&, const auto&) {
return control->object_storage()->get_str(display::color_vars[color_id]);
});
}
}
+31 -70
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <unistd.h>
@@ -41,38 +5,38 @@
#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/curl_stack.h"
#include "core/dht_manager.h"
#include "core/download_store.h"
#include "core/http_queue.h"
#include "core/manager.h"
#include "core/view_manager.h"
#include "display/canvas.h"
#include "display/window.h"
#include "display/window_http_queue.h"
#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"
#include "ui/root.h"
#include "control.h"
Control::Control() :
m_ui(new ui::Root()),
m_display(new display::Manager()),
m_input(new input::Manager()),
m_inputStdin(new input::InputEvent(STDIN_FILENO)),
m_commandScheduler(new rpc::CommandScheduler()),
m_objectStorage(new rpc::object_storage()),
m_directory_events(new torrent::directory_events()),
m_tick(0),
m_shutdownReceived(false),
m_shutdownQuick(false) {
m_ui(new ui::Root()),
m_display(new display::Manager()),
m_input(new input::Manager()),
m_inputStdin(new input::InputEvent(STDIN_FILENO)),
m_commandScheduler(new rpc::CommandScheduler()),
m_objectStorage(new rpc::object_storage()),
m_lua_engine(new rpc::LuaEngine()),
m_directory_events(new torrent::directory_events()) {
m_core = new core::Manager();
m_viewManager = new core::ViewManager();
@@ -80,7 +44,7 @@ Control::Control() :
m_inputStdin->slot_pressed(std::bind(&input::Manager::pressed, m_input, std::placeholders::_1));
m_taskShutdown.slot() = std::bind(&Control::handle_shutdown, this);
m_task_shutdown.slot() = std::bind(&Control::handle_shutdown, this);
m_commandScheduler->set_slot_error_message([this](const std::string& msg) { m_core->push_log_std(msg); });
}
@@ -99,14 +63,15 @@ Control::~Control() {
delete m_directory_events;
delete m_commandScheduler;
delete m_objectStorage;
delete m_lua_engine;
}
void
Control::initialize() {
display::Canvas::initialize();
display::Window::slot_schedule(rak::make_mem_fun(m_display, &display::Manager::schedule));
display::Window::slot_unschedule(rak::make_mem_fun(m_display, &display::Manager::unschedule));
display::Window::slot_adjust(rak::make_mem_fun(m_display, &display::Manager::adjust_layout));
display::Window::slot_schedule([this](display::Window* w, std::chrono::microseconds t) { m_display->schedule(w, t); });
display::Window::slot_unschedule([this](display::Window* w) { m_display->unschedule(w); });
display::Window::slot_adjust([this]() { m_display->adjust_layout(); });
m_core->http_stack()->set_user_agent(USER_AGENT);
@@ -119,19 +84,18 @@ Control::initialize() {
m_ui->init(this);
if(!display::Canvas::daemon()) {
m_inputStdin->insert(torrent::main_thread()->poll());
m_inputStdin->insert(torrent::this_thread::poll());
}
}
void
Control::cleanup() {
// delete m_scgi; m_scgi = NULL;
rpc::xmlrpc.cleanup();
rpc::rpc.cleanup();
priority_queue_erase(&taskScheduler, &m_taskShutdown);
torrent::this_thread::scheduler()->erase(&m_task_shutdown);
if(!display::Canvas::daemon()) {
m_inputStdin->remove(torrent::main_thread()->poll());
m_inputStdin->remove(torrent::this_thread::poll());
}
m_core->download_store()->disable();
@@ -147,8 +111,6 @@ Control::cleanup() {
void
Control::cleanup_exception() {
// delete m_scgi; m_scgi = NULL;
display::Canvas::cleanup();
}
@@ -171,21 +133,20 @@ Control::handle_shutdown() {
rpc::commands.call_catch("event.system.shutdown", rpc::make_target(), "shutdown", "System shutdown event action failed: ");
if (!m_shutdownQuick) {
// Temporary hack:
if (worker_thread->is_active())
worker_thread->queue_item(&ThreadBase::stop_thread);
worker_thread->stop_thread_wait();
torrent::connection_manager()->listen_close();
m_directory_events->close();
m_core->shutdown(false);
if (!m_taskShutdown.is_queued())
priority_queue_insert(&taskScheduler, &m_taskShutdown, cachedTime + rak::timer::from_seconds(5));
if (!m_task_shutdown.is_scheduled())
torrent::this_thread::scheduler()->wait_for_ceil_seconds(&m_task_shutdown, 5s);
} else {
// Temporary hack:
if (worker_thread->is_active())
worker_thread->queue_item(&ThreadBase::stop_thread);
worker_thread->stop_thread_wait();
m_core->shutdown(true);
}
+10 -44
View File
@@ -1,48 +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
#ifndef RTORRENT_CONTROL_H
#define RTORRENT_CONTROL_H
#include <atomic>
#include <cinttypes>
#include <sys/types.h>
#include <rak/timer.h>
#include <rak/priority_queue_default.h>
#include <torrent/torrent.h>
#include <torrent/utils/scheduler.h>
namespace ui {
class Root;
@@ -61,12 +24,13 @@ namespace display {
namespace input {
class InputEvent;
class Manager;
}
}
namespace rpc {
class CommandScheduler;
class XmlRpc;
class object_storage;
class LuaEngine;
}
namespace torrent {
@@ -77,7 +41,7 @@ class Control {
public:
Control();
~Control();
bool is_shutdown_completed();
bool is_shutdown_received() { return m_shutdownReceived; }
bool is_shutdown_started() { return m_shutdownQuick; }
@@ -102,6 +66,7 @@ public:
rpc::CommandScheduler* command_scheduler() { return m_commandScheduler; }
rpc::object_storage* object_storage() { return m_objectStorage; }
rpc::LuaEngine* lua_engine() { return m_lua_engine; }
torrent::directory_events* directory_events() { return m_directory_events; }
@@ -126,17 +91,18 @@ private:
rpc::CommandScheduler* m_commandScheduler;
rpc::object_storage* m_objectStorage;
rpc::LuaEngine* m_lua_engine;
torrent::directory_events* m_directory_events;
uint64_t m_tick;
uint64_t m_tick{};
mode_t m_umask;
std::string m_workingDirectory;
rak::priority_item m_taskShutdown;
torrent::utils::SchedulerEntry m_task_shutdown;
std::atomic<bool> m_shutdownReceived;
std::atomic<bool> m_shutdownQuick;
std::atomic<bool> m_shutdownReceived{};
std::atomic<bool> m_shutdownQuick{};
};
#endif
+18 -47
View File
@@ -1,49 +1,14 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include "core/curl_get.h"
#include <iostream>
#include <curl/curl.h>
#include <curl/easy.h>
#include <torrent/exceptions.h>
#include "globals.h"
#include "curl_get.h"
#include "curl_stack.h"
#include "core/curl_stack.h"
namespace core {
@@ -55,6 +20,12 @@ curl_get_receive_write(void* data, size_t size, size_t nmemb, void* handle) {
return 0;
}
CurlGet::CurlGet(CurlStack* s) :
m_stack(s) {
m_task_timeout.slot() = [this]() { receive_timeout(); };
}
CurlGet::~CurlGet() {
close();
}
@@ -85,8 +56,7 @@ CurlGet::start() {
// Normally libcurl should handle the timeout. But sometimes that doesn't
// work right so we do a fallback timeout that just aborts the transfer.
m_taskTimeout.slot() = std::bind(&CurlGet::receive_timeout, this);
priority_queue_update(&taskScheduler, &m_taskTimeout, cachedTime + rak::timer::from_seconds(m_timeout + 5));
torrent::this_thread::scheduler()->update_wait_for_ceil_seconds(&m_task_timeout, 5s + 1s*m_timeout);
}
curl_easy_setopt(m_handle, CURLOPT_FORBID_REUSE, (long)1);
@@ -105,7 +75,8 @@ CurlGet::start() {
void
CurlGet::close() {
priority_queue_erase(&taskScheduler, &m_taskTimeout);
torrent::this_thread::scheduler()->erase(&m_task_timeout);
if (!is_busy())
return;
@@ -132,18 +103,18 @@ CurlGet::receive_timeout() {
return m_stack->transfer_done(m_handle, "Timed out");
}
double
curl_off_t
CurlGet::size_done() {
double d = 0.0;
curl_easy_getinfo(m_handle, CURLINFO_SIZE_DOWNLOAD, &d);
curl_off_t d = 0;
curl_easy_getinfo(m_handle, CURLINFO_SIZE_DOWNLOAD_T, &d);
return d;
}
double
curl_off_t
CurlGet::size_total() {
double d = 0.0;
curl_easy_getinfo(m_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d);
curl_off_t d = 0;
curl_easy_getinfo(m_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &d);
return d;
}
+12 -49
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_CORE_CURL_GET_H
#define RTORRENT_CORE_CURL_GET_H
@@ -41,8 +5,7 @@
#include <string>
#include <curl/curl.h>
#include <torrent/http.h>
#include "rak/priority_queue_default.h"
#include <torrent/utils/scheduler.h>
namespace core {
@@ -50,9 +13,7 @@ class CurlStack;
class CurlGet : public torrent::Http {
public:
friend class CurlStack;
CurlGet(CurlStack* s) : m_active(false), m_handle(NULL), m_stack(s) {}
CurlGet(CurlStack* s);
virtual ~CurlGet();
void start();
@@ -66,23 +27,25 @@ public:
void set_active(bool a) { m_active = a; }
double size_done();
double size_total();
curl_off_t size_done();
curl_off_t size_total();
CURL* handle() { return m_handle; }
private:
CurlGet(const CurlGet&);
void operator = (const CurlGet&);
friend class CurlStack;
CurlGet(const CurlGet&) = delete;
void operator = (const CurlGet&) = delete;
void receive_timeout();
bool m_active;
bool m_active{};
bool m_ipv6;
rak::priority_item m_taskTimeout;
CURL* m_handle;
torrent::utils::SchedulerEntry m_task_timeout;
CURL* m_handle{};
CurlStack* m_stack;
};
+14 -16
View File
@@ -1,21 +1,20 @@
#include "config.h"
#include <curl/curl.h>
#include <curl/multi.h>
#include "curl_socket.h"
#include <cassert>
#include <curl/multi.h>
#include <torrent/poll.h>
#include <torrent/exceptions.h>
#include <torrent/utils/thread_base.h>
#include <torrent/utils/thread.h>
#include "control.h"
#include "curl_socket.h"
#include "curl_stack.h"
#include "core/curl_stack.h"
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;
@@ -37,29 +36,28 @@ CurlSocket::receive_socket(void* easy_handle, curl_socket_t fd, int what, void*
if (socket == NULL) {
socket = stack->new_socket(fd);
torrent::main_thread()->poll()->open(socket);
torrent::this_thread::poll()->open(socket);
// No interface for libcurl to signal when it's interested in error events.
// Assume that hence it must always be interested in them.
torrent::main_thread()->poll()->insert_error(socket);
torrent::this_thread::poll()->insert_error(socket);
}
if (what == CURL_POLL_NONE || what == CURL_POLL_OUT)
torrent::main_thread()->poll()->remove_read(socket);
torrent::this_thread::poll()->remove_read(socket);
else
torrent::main_thread()->poll()->insert_read(socket);
torrent::this_thread::poll()->insert_read(socket);
if (what == CURL_POLL_NONE || what == CURL_POLL_IN)
torrent::main_thread()->poll()->remove_write(socket);
torrent::this_thread::poll()->remove_write(socket);
else
torrent::main_thread()->poll()->insert_write(socket);
torrent::this_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
@@ -67,7 +65,7 @@ CurlSocket::close() {
if (m_fileDesc == -1)
throw torrent::internal_error("CurlSocket::close() m_fileDesc == -1.");
torrent::main_thread()->poll()->closed(this);
torrent::this_thread::poll()->closed(this);
m_fileDesc = -1;
}
+1 -36
View File
@@ -1,42 +1,7 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2008, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_CORE_CURL_SOCKET_H
#define RTORRENT_CORE_CURL_SOCKET_H
#include <curl/curl.h>
#include <torrent/event.h>
#include "globals.h"
+17 -11
View File
@@ -4,7 +4,6 @@
#include <curl/multi.h>
#include <torrent/exceptions.h>
#include "rak/functional.h"
#include "curl_get.h"
#include "curl_socket.h"
#include "curl_stack.h"
@@ -38,7 +37,8 @@ CurlStack::shutdown() {
front()->close();
curl_multi_cleanup((CURLM*)m_handle);
priority_queue_erase(&taskScheduler, &m_task_timeout);
torrent::this_thread::scheduler()->erase(&m_task_timeout);
}
CurlGet*
@@ -86,7 +86,7 @@ CurlStack::receive_action(CurlSocket* socket, int events) {
; // Do nothing.
if (empty())
priority_queue_erase(&taskScheduler, &m_task_timeout);
torrent::this_thread::scheduler()->erase(&m_task_timeout);
}
} while (code == CURLM_CALL_MULTI_PERFORM);
@@ -141,12 +141,15 @@ void
CurlStack::receive_timeout() {
receive_action(NULL, 0);
// Sometimes libcurl forgets to reset the timeout. Try to poll the value in that case, or use 10 seconds.
if (!empty() && !m_task_timeout.is_queued()) {
long timeout;
curl_multi_timeout((CURLM*)m_handle, &timeout);
priority_queue_insert(&taskScheduler, &m_task_timeout,
cachedTime + rak::timer::from_milliseconds(std::max<unsigned long>(timeout, 10000)));
if (!empty() && !m_task_timeout.is_scheduled()) {
// Sometimes libcurl forgets to reset the timeout. Try to poll the value in that case, or use 10
// seconds max.
long timeout_ms;
curl_multi_timeout((CURLM*)m_handle, &timeout_ms);
auto timeout = std::max<std::chrono::microseconds>(std::chrono::milliseconds(timeout_ms), 10s);
torrent::this_thread::scheduler()->wait_for_ceil_seconds(&m_task_timeout, timeout);
}
}
@@ -230,10 +233,13 @@ CurlStack::global_cleanup() {
// TODO: Is this function supposed to set a per-handle timeout, or is
// it the shortest timeout amongst all handles?
int
CurlStack::set_timeout(void* handle, long timeout_ms, void* userp) {
CurlStack::set_timeout(void*, long timeout_ms, void* userp) {
CurlStack* stack = (CurlStack*)userp;
priority_queue_update(&taskScheduler, &stack->m_task_timeout, cachedTime + rak::timer::from_milliseconds(timeout_ms));
if (timeout_ms == -1)
torrent::this_thread::scheduler()->erase(&stack->m_task_timeout);
else
torrent::this_thread::scheduler()->update_wait_for_ceil_seconds(&stack->m_task_timeout, std::chrono::milliseconds(timeout_ms));
return 0;
}
+8 -9
View File
@@ -3,8 +3,7 @@
#include <deque>
#include <string>
#include "rak/priority_queue_default.h"
#include <torrent/utils/scheduler.h>
namespace core {
@@ -20,7 +19,7 @@ class CurlSocket;
// removal of elements.
class CurlStack : std::deque<CurlGet*> {
public:
public:
friend class CurlGet;
typedef std::deque<CurlGet*> base_type;
@@ -80,17 +79,17 @@ class CurlStack : std::deque<CurlGet*> {
void receive_action(CurlSocket* socket, int type);
static int set_timeout(void* handle, long timeout_ms, void* userp);
static int set_timeout(void*, long timeout_ms, void* userp);
void transfer_done(void* handle, const char* msg);
protected:
protected:
void add_get(CurlGet* get);
void remove_get(CurlGet* get);
private:
CurlStack(const CurlStack&);
void operator = (const CurlStack&);
private:
CurlStack(const CurlStack&) = delete;
void operator = (const CurlStack&) = delete;
void receive_timeout();
@@ -103,7 +102,7 @@ class CurlStack : std::deque<CurlGet*> {
unsigned int m_active{0};
unsigned int m_max_active{32};
rak::priority_item m_task_timeout;
torrent::utils::SchedulerEntry m_task_timeout;
std::string m_user_agent;
std::string m_http_proxy;
+36 -71
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"
@@ -62,8 +26,8 @@ namespace core {
const char* DhtManager::dht_settings[dht_settings_num] = { "disable", "off", "auto", "on" };
DhtManager::~DhtManager() {
priority_queue_erase(&taskScheduler, &m_updateTimeout);
priority_queue_erase(&taskScheduler, &m_stopTimeout);
torrent::this_thread::scheduler()->erase(&m_update_timeout);
torrent::this_thread::scheduler()->erase(&m_stop_timeout);
}
void
@@ -94,7 +58,7 @@ DhtManager::load_dht_cache() {
LT_LOG_THIS("could not open cache file (path:%s)", cache_filename.c_str());
}
torrent::dht_manager()->initialize(cache);
torrent::dht_controller()->initialize(cache);
if (m_start == dht_on)
start_dht();
@@ -102,36 +66,37 @@ DhtManager::load_dht_cache() {
void
DhtManager::start_dht() {
priority_queue_erase(&taskScheduler, &m_stopTimeout);
torrent::this_thread::scheduler()->erase(&m_stop_timeout);
if (!torrent::dht_manager()->is_valid()) {
if (!torrent::dht_controller()->is_valid()) {
LT_LOG_THIS("server start skipped, manager is uninitialized", 0);
return;
}
if (torrent::dht_manager()->is_active()) {
if (torrent::dht_controller()->is_active()) {
LT_LOG_THIS("server start skipped, already active", 0);
return;
}
torrent::ThrottlePair throttles = control->core()->get_throttle(m_throttleName);
torrent::dht_manager()->set_upload_throttle(throttles.first);
torrent::dht_manager()->set_download_throttle(throttles.second);
torrent::dht_controller()->set_upload_throttle(throttles.first);
torrent::dht_controller()->set_download_throttle(throttles.second);
int port = rpc::call_command_value("dht.port");
if (port <= 0)
return;
if (!torrent::dht_manager()->start(port)) {
if (!torrent::dht_controller()->start(port)) {
m_start = dht_off;
return;
}
torrent::dht_manager()->reset_statistics();
torrent::dht_controller()->reset_statistics();
m_updateTimeout.slot() = std::bind(&DhtManager::update, this);
priority_queue_insert(&taskScheduler, &m_updateTimeout, (cachedTime + rak::timer::from_seconds(60)).round_seconds());
m_update_timeout.slot() = std::bind(&DhtManager::update, this);
torrent::this_thread::scheduler()->wait_for_ceil_seconds(&m_update_timeout, 60s);
m_dhtPrevCycle = 0;
m_dhtPrevQueriesSent = 0;
@@ -143,20 +108,20 @@ DhtManager::start_dht() {
void
DhtManager::stop_dht() {
priority_queue_erase(&taskScheduler, &m_updateTimeout);
priority_queue_erase(&taskScheduler, &m_stopTimeout);
torrent::this_thread::scheduler()->erase(&m_update_timeout);
torrent::this_thread::scheduler()->erase(&m_stop_timeout);
if (torrent::dht_manager()->is_active()) {
if (torrent::dht_controller()->is_active()) {
LT_LOG_THIS("stopping server", 0);
log_statistics(true);
torrent::dht_manager()->stop();
torrent::dht_controller()->stop();
}
}
void
DhtManager::save_dht_cache() {
if (!control->core()->download_store()->is_enabled() || !torrent::dht_manager()->is_valid())
if (!control->core()->download_store()->is_enabled() || !torrent::dht_controller()->is_valid())
return;
std::string filename = control->core()->download_store()->path() + "rtorrent.dht_cache";
@@ -167,7 +132,7 @@ DhtManager::save_dht_cache() {
return;
torrent::Object cache = torrent::Object::create_map();
cache_file << *torrent::dht_manager()->store_cache(&cache);
cache_file << *torrent::dht_controller()->store_cache(&cache);
if (!cache_file.good())
return;
@@ -198,42 +163,42 @@ 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()) {
if (m_start == dht_auto && !m_stop_timeout.is_scheduled()) {
DownloadList::const_iterator itr, end;
for (itr = control->core()->download_list()->begin(), end = control->core()->download_list()->end(); itr != end; ++itr)
if ((*itr)->download()->info()->is_active() && !(*itr)->download()->info()->is_private())
break;
if (itr == end) {
m_stopTimeout.slot() = std::bind(&DhtManager::stop_dht, this);
priority_queue_insert(&taskScheduler, &m_stopTimeout, (cachedTime + rak::timer::from_seconds(15 * 60)).round_seconds());
m_stop_timeout.slot() = std::bind(&DhtManager::stop_dht, this);
torrent::this_thread::scheduler()->wait_for_ceil_seconds(&m_stop_timeout, 15min);
}
}
// While bootstrapping (log_statistics returns true), check every minute if it completed, otherwise update every 15 minutes.
if (log_statistics(false))
priority_queue_insert(&taskScheduler, &m_updateTimeout, (cachedTime + rak::timer::from_seconds(60)).round_seconds());
torrent::this_thread::scheduler()->wait_for_ceil_seconds(&m_update_timeout, 1min);
else
priority_queue_insert(&taskScheduler, &m_updateTimeout, (cachedTime + rak::timer::from_seconds(15 * 60)).round_seconds());
torrent::this_thread::scheduler()->wait_for_ceil_seconds(&m_update_timeout, 15min);
}
bool
DhtManager::log_statistics(bool force) {
torrent::DhtManager::statistics_type stats = torrent::dht_manager()->get_statistics();
auto stats = torrent::dht_controller()->get_statistics();
// Check for firewall problems.
if (stats.cycle > 2 && stats.queries_sent - m_dhtPrevQueriesSent > 100 && stats.queries_received == m_dhtPrevQueriesReceived) {
// We should have had clients ping us at least but have received
// nothing, that means the UDP port is probably unreachable.
if (torrent::dht_manager()->can_receive_queries())
if (torrent::dht_controller()->is_receiving_requests())
LT_LOG_THIS("listening port appears to be unreachable, no queries received", 0);
torrent::dht_manager()->set_can_receive(false);
torrent::dht_controller()->set_receive_requests(false);
}
if (stats.queries_sent - m_dhtPrevQueriesSent > stats.num_nodes * 2 + 20 && stats.replies_received == m_dhtPrevRepliesReceived) {
@@ -248,7 +213,7 @@ DhtManager::log_statistics(bool force) {
m_warned = false;
if (stats.queries_received > m_dhtPrevQueriesReceived)
torrent::dht_manager()->set_can_receive(true);
torrent::dht_controller()->set_receive_requests(true);
// Nothing to log while bootstrapping, but check again every minute.
if (stats.cycle <= 1) {
@@ -269,7 +234,7 @@ DhtManager::log_statistics(bool force) {
// afterwards (i.e. every 2 hours), or when forced.
if ((force && stats.cycle != m_dhtPrevCycle) || stats.cycle == 3 || stats.cycle > m_dhtPrevCycle + 7) {
char buffer[256];
snprintf(buffer, sizeof(buffer),
snprintf(buffer, sizeof(buffer),
"DHT statistics: %d queries in, %d queries out, %d replies received, %lld bytes read, %lld bytes sent, "
"%d known nodes in %d buckets, %d peers (highest: %d) tracked in %d torrents.",
stats.queries_received - m_dhtPrevQueriesReceived,
@@ -301,11 +266,11 @@ DhtManager::dht_statistics() {
torrent::Object dhtStats = torrent::Object::create_map();
dhtStats.insert_key("dht", dht_settings[m_start]);
dhtStats.insert_key("active", torrent::dht_manager()->is_active());
dhtStats.insert_key("active", torrent::dht_controller()->is_active());
dhtStats.insert_key("throttle", m_throttleName);
if (torrent::dht_manager()->is_active()) {
torrent::DhtManager::statistics_type stats = torrent::dht_manager()->get_statistics();
if (torrent::dht_controller()->is_active()) {
auto stats = torrent::dht_controller()->get_statistics();
dhtStats.insert_key("cycle", stats.cycle);
dhtStats.insert_key("queries_received", stats.queries_received);
@@ -327,7 +292,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;
+6 -43
View File
@@ -1,51 +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
#ifndef RTORRENT_CORE_DHT_MANAGER_H
#define RTORRENT_CORE_DHT_MANAGER_H
#include <rak/priority_queue_default.h>
#include <torrent/object.h>
#include <torrent/utils/scheduler.h>
namespace core {
class DhtManager {
public:
DhtManager() : m_warned(false), m_start(dht_off) { }
~DhtManager();
void load_dht_cache();
@@ -80,11 +42,12 @@ private:
uint64_t m_dhtPrevBytesUp;
uint64_t m_dhtPrevBytesDown;
rak::priority_item m_updateTimeout;
rak::priority_item m_stopTimeout;
bool m_warned;
torrent::utils::SchedulerEntry m_update_timeout;
torrent::utils::SchedulerEntry m_stop_timeout;
int m_start;
bool m_warned{};
int m_start{dht_off};
std::string m_throttleName;
};
+13 -51
View File
@@ -1,50 +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 <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"
@@ -56,11 +18,7 @@
namespace core {
Download::Download(download_type d) :
m_download(d),
m_hashFailed(false),
m_resumeFlags(~uint32_t()),
m_group(0) {
m_download(d) {
m_download.info()->signal_tracker_success().push_back(std::bind(&Download::receive_tracker_msg, this, ""));
m_download.info()->signal_tracker_failed().push_back(std::bind(&Download::receive_tracker_msg, this, std::placeholders::_1));
@@ -75,13 +33,17 @@ Download::~Download() {
void
Download::enable_udp_trackers(bool state) {
for (torrent::TrackerList::iterator itr = m_download.tracker_list()->begin(), last = m_download.tracker_list()->end(); itr != last; ++itr)
if ((*itr)->type() == torrent::Tracker::TRACKER_UDP) {
if (state)
(*itr)->enable();
else
(*itr)->disable();
}
for (int idx = 0, end = m_download.tracker_controller().size(); idx < end; ++idx) {
auto tracker = m_download.tracker_controller().at(idx);
if (tracker.type() != torrent::TRACKER_UDP)
continue;
if (state)
tracker.enable();
else
tracker.disable();
}
}
uint32_t
+12 -55
View File
@@ -1,56 +1,16 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_CORE_DOWNLOAD_H
#define RTORRENT_CORE_DOWNLOAD_H
#include <torrent/common.h>
#include <torrent/download.h>
#include <torrent/download_info.h>
#include <torrent/hash_string.h>
#include <torrent/tracker_list.h>
#include <torrent/data/file_list.h>
#include <torrent/peer/connection_list.h>
#include <torrent/tracker/wrappers.h>
#include "globals.h"
namespace torrent {
class PeerList;
class TrackerList;
}
namespace core {
class Download {
@@ -59,7 +19,6 @@ public:
typedef torrent::FileList file_list_type;
typedef torrent::PeerList peer_list_type;
typedef torrent::TrackerList tracker_list_type;
typedef torrent::TrackerController tracker_controller_type;
typedef torrent::ConnectionList connection_list_type;
typedef download_type::ConnectionType connection_type;
@@ -71,10 +30,10 @@ public:
Download(download_type d);
~Download();
const torrent::DownloadInfo* info() const { return m_download.info(); }
const torrent::download_data* data() const { return m_download.data(); }
auto info() const { return m_download.info(); }
auto data() const { return m_download.data(); }
torrent::DownloadMain* main() { return m_download.main(); }
auto main() { return m_download.main(); }
bool is_open() const { return m_download.info()->is_open(); }
bool is_active() const { return m_download.info()->is_active(); }
@@ -102,13 +61,11 @@ public:
torrent::Object* bencode() { return m_download.bencode(); }
tracker_list_type* tracker_list() { return m_download.tracker_list(); }
uint32_t tracker_list_size() const { return m_download.tracker_list()->size(); }
auto tracker_controller() { return m_download.tracker_controller(); }
uint32_t tracker_list_size() const { return m_download.c_tracker_controller().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; }
@@ -143,10 +100,10 @@ private:
// Store the FileList instance so we can use slots etc on it.
download_type m_download;
bool m_hashFailed;
bool m_hashFailed{};
std::string m_message;
uint32_t m_resumeFlags;
unsigned int m_group;
uint32_t m_resumeFlags{~uint32_t{}};
unsigned int m_group{};
};
inline bool
+38 -40
View File
@@ -37,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;
return std::unique_ptr<torrent::Object>();
torrent::Object obj;
stream >> obj;
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
@@ -61,20 +60,10 @@ is_magnet_uri(const std::string& uri) {
}
DownloadFactory::DownloadFactory(Manager* m) :
m_manager(m),
m_stream(NULL),
m_object(NULL),
m_commited(false),
m_loaded(false),
m_manager(m) {
m_session(false),
m_start(false),
m_printLog(true),
m_isFile(false),
m_initLoad(false) {
m_taskLoad.slot() = std::bind(&DownloadFactory::receive_load, this);
m_taskCommit.slot() = std::bind(&DownloadFactory::receive_commit, this);
m_task_load.slot() = std::bind(&DownloadFactory::receive_load, this);
m_task_commit.slot() = std::bind(&DownloadFactory::receive_commit, this);
// m_variables["connection_leech"] = rpc::call_command("protocol.connection.leech");
// m_variables["connection_seed"] = rpc::call_command("protocol.connection.seed");
@@ -85,8 +74,8 @@ DownloadFactory::DownloadFactory(Manager* m) :
}
DownloadFactory::~DownloadFactory() {
priority_queue_erase(&taskScheduler, &m_taskLoad);
priority_queue_erase(&taskScheduler, &m_taskCommit);
torrent::this_thread::scheduler()->erase(&m_task_load);
torrent::this_thread::scheduler()->erase(&m_task_commit);
delete m_stream;
delete m_object;
@@ -96,7 +85,7 @@ DownloadFactory::~DownloadFactory() {
void
DownloadFactory::load(const std::string& uri) {
m_uri = uri;
priority_queue_insert(&taskScheduler, &m_taskLoad, cachedTime);
torrent::this_thread::scheduler()->wait_for(&m_task_load, 0ms);
}
// This function must be called before DownloadFactory::commit().
@@ -111,7 +100,7 @@ DownloadFactory::load_raw_data(const std::string& input) {
void
DownloadFactory::commit() {
priority_queue_insert(&taskScheduler, &m_taskCommit, cachedTime);
torrent::this_thread::scheduler()->wait_for(&m_task_commit, 0ms);
}
void
@@ -173,9 +162,19 @@ DownloadFactory::receive_commit() {
void
DownloadFactory::receive_success() {
auto rtorrent_object = download_factory_load_stream((rak::path_expand(m_uri) + ".rtorrent").c_str());
auto libtorrent_resume_object = download_factory_load_stream((rak::path_expand(m_uri) + ".libtorrent_resume").c_str());
uint32_t tracker_key;
if (rtorrent_object && rtorrent_object->has_key_value("key"))
tracker_key = rtorrent_object->get_key_value("key");
else
tracker_key = random() % (std::numeric_limits<uint32_t>::max() - 1) + 1;
Download* download = m_stream != NULL ?
m_manager->download_list()->create(m_stream, m_printLog) :
m_manager->download_list()->create(m_object, m_printLog);
m_manager->download_list()->create(m_stream, tracker_key, m_printLog) :
m_manager->download_list()->create(m_object, tracker_key, m_printLog);
m_object = NULL;
@@ -200,8 +199,11 @@ 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
@@ -213,6 +215,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_controller().key());
initialize_rtorrent(download, rtorrent);
if (!rtorrent->has_key_string("custom1")) rtorrent->insert_key("custom1", std::string());
@@ -352,15 +356,17 @@ DownloadFactory::receive_failed(const std::string& msg) {
void
DownloadFactory::initialize_rtorrent(Download* download, torrent::Object* rtorrent) {
auto cached_seconds = torrent::this_thread::cached_seconds().count();
if (!rtorrent->has_key_value("state") || rtorrent->get_key_value("state") > 1) {
rtorrent->insert_key("state", (int64_t)m_start);
rtorrent->insert_key("state_changed", cachedTime.seconds());
rtorrent->insert_key("state_changed", cached_seconds);
rtorrent->insert_key("state_counter", int64_t());
} else if (!rtorrent->has_key_value("state_changed") ||
rtorrent->get_key_value("state_changed") > cachedTime.seconds() || rtorrent->get_key_value("state_changed") == 0 ||
rtorrent->get_key_value("state_changed") > cached_seconds || rtorrent->get_key_value("state_changed") == 0 ||
!rtorrent->has_key_value("state_counter") || (uint64_t)rtorrent->get_key_value("state_counter") > (1 << 20)) {
rtorrent->insert_key("state_changed", cachedTime.seconds());
rtorrent->insert_key("state_changed", cached_seconds);
rtorrent->insert_key("state_counter", int64_t());
}
@@ -378,14 +384,6 @@ DownloadFactory::initialize_rtorrent(Download* download, torrent::Object* rtorre
else
rpc::call_command("d.priority.set", (int64_t)2, rpc::make_target(download));
if (rtorrent->has_key_value("key")) {
download->tracker_list()->set_key(rtorrent->get_key_value("key"));
} else {
download->tracker_list()->set_key(random() % (std::numeric_limits<uint32_t>::max() - 1) + 1);
rtorrent->insert_key("key", download->tracker_list()->key());
}
if (rtorrent->has_key_value("total_uploaded"))
download->info()->mutable_up_rate()->set_total(rtorrent->get_key_value("total_uploaded"));
+14 -49
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// The DownloadFactory class assures that loading torrents can be done
// anywhere in the code by queueing the task. The user may change
// settings while, or even after, the torrent is loading.
@@ -44,13 +8,14 @@
#include <functional>
#include <iosfwd>
#include <rak/priority_queue_default.h>
#include <torrent/object.h>
#include <torrent/utils/scheduler.h>
#include "http_queue.h"
namespace core {
class Download;
class Manager;
class DownloadFactory {
@@ -98,25 +63,25 @@ private:
void initialize_rtorrent(Download* download, torrent::Object* rtorrent);
Manager* m_manager;
std::iostream* m_stream;
torrent::Object* m_object;
std::iostream* m_stream{};
torrent::Object* m_object{};
bool m_commited;
bool m_loaded;
bool m_commited{};
bool m_loaded{};
std::string m_uri;
bool m_session;
bool m_start;
bool m_printLog;
bool m_isFile;
bool m_initLoad;
bool m_session{};
bool m_start{};
bool m_printLog{true};
bool m_isFile{};
bool m_initLoad{};
command_list_type m_commands;
torrent::Object::map_type m_variables;
slot_void m_slot_finished;
rak::priority_item m_taskLoad;
rak::priority_item m_taskCommit;
slot_void m_slot_finished;
torrent::utils::SchedulerEntry m_task_load;
torrent::utils::SchedulerEntry m_task_commit;
};
bool is_network_uri(const std::string& uri);
+45 -61
View File
@@ -1,45 +1,8 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <algorithm>
#include <fstream>
#include <iostream>
#include <rak/functional.h>
#include <rak/string_manip.h>
#include <torrent/data/file.h>
#include <torrent/utils/resume.h>
@@ -71,7 +34,7 @@
namespace core {
inline void
DownloadList::check_contains(Download* d) {
DownloadList::check_contains([[maybe_unused]] Download* d) {
#ifdef USE_EXTRA_DEBUG
if (std::find(begin(), end(), d) == end())
throw torrent::internal_error("DownloadList::check_contains(...) failed.");
@@ -80,15 +43,32 @@ 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>());
int error_count = 0;
base_type::clear();
while (!empty()) {
auto download = back();
try {
close(download);
base_type::pop_back();
torrent::download_remove(*download->download());
delete download;
} catch (torrent::internal_error& e) {
lt_log_print(torrent::LOG_ERROR, "DownloadList::clear() failed to close or remove download: %s", e.what());
error_count++;
continue;
}
}
if (error_count > 0)
throw torrent::internal_error("DownloadList::clear() failed to close or remove " + std::to_string(error_count) + " downloads.");
}
void
DownloadList::session_save() {
unsigned int c = std::count_if(begin(), end(), std::bind1st(std::mem_fun(&DownloadStore::save_resume), control->core()->download_store()));
unsigned int c = std::count_if(begin(), end(), [&](Download* d) { return control->core()->download_store()->save_resume(d); });
if (c != size())
lt_log_print(torrent::LOG_ERROR, "Failed to save session torrents.");
@@ -99,7 +79,7 @@ DownloadList::session_save() {
DownloadList::iterator
DownloadList::find(const torrent::HashString& hash) {
return std::find_if(begin(), end(), rak::equal(hash, rak::on(std::mem_fun(&Download::info), std::mem_fun(&torrent::DownloadInfo::hash))));
return std::find_if(begin(), end(), [hash](Download* d) { return hash == d->info()->hash(); });
}
DownloadList::iterator
@@ -109,7 +89,7 @@ DownloadList::find_hex(const char* hash) {
for (torrent::HashString::iterator itr = key.begin(), last = key.end(); itr != last; itr++, hash += 2)
*itr = (rak::hexchar_to_value(*hash) << 4) + rak::hexchar_to_value(*(hash + 1));
return std::find_if(begin(), end(), rak::equal(key, rak::on(std::mem_fun(&Download::info), std::mem_fun(&torrent::DownloadInfo::hash))));
return std::find_if(begin(), end(), [key](Download* d) { return key == d->info()->hash(); });
}
Download*
@@ -120,18 +100,18 @@ 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;
if (printLog)
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not create download: %s", e.what());
delete obj;
return NULL;
}
@@ -141,13 +121,13 @@ DownloadList::create(torrent::Object* obj, bool printLog) {
}
Download*
DownloadList::create(std::istream* str, bool printLog) {
DownloadList::create(std::istream* str, uint32_t tracker_key, bool printLog) {
torrent::Object* object = new torrent::Object;
torrent::Download download;
try {
*str >> *object;
// Don't throw input_error from here as gcc-3.3.5 produces bad
// code.
if (str->fail()) {
@@ -159,7 +139,7 @@ DownloadList::create(std::istream* str, bool printLog) {
return NULL;
}
download = torrent::download_add(object);
download = torrent::download_add(object, tracker_key);
} catch (torrent::local_error& e) {
delete object;
@@ -187,8 +167,8 @@ DownloadList::insert(Download* download) {
// This needs to be separated into two different calls to ensure
// the download remains in the view.
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), std::bind2nd(std::mem_fun(&View::insert), download));
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), std::bind2nd(std::mem_fun(&View::filter_download), download));
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), [&download](View* v) { v->insert(download); });
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), [&download](View* v) { v->filter_download(download); });
DL_TRIGGER_EVENT(*itr, "event.download.inserted");
@@ -221,7 +201,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;
@@ -251,7 +231,7 @@ DownloadList::open_throw(Download* download) {
if (download->download()->info()->is_open())
return;
int openFlags = download->resume_flags();
if (rpc::call_command_value("system.file.allocate"))
@@ -290,7 +270,7 @@ void
DownloadList::close_quick(Download* download) {
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Closing download quickly.");
close(download);
// Make sure we cancel any tracker requests. This should rather be
// handled by some parameter to the close function, or some other
// way of giving the client more control of when STOPPED requests
@@ -370,7 +350,9 @@ DownloadList::resume(Download* download, int flags) {
// This will never actually do anything due to the above hash check.
// open_throw(download);
rpc::call_command("d.state_changed.set", cachedTime.seconds(), rpc::make_target(download));
auto cached_seconds = torrent::this_thread::cached_seconds().count();
rpc::call_command("d.state_changed.set", cached_seconds, rpc::make_target(download));
rpc::call_command("d.state_counter.set", rpc::call_command_value("d.state_counter", rpc::make_target(download)) + 1, rpc::make_target(download));
if (download->is_done()) {
@@ -452,13 +434,15 @@ DownloadList::pause(Download* download, int flags) {
download->download()->stop(flags);
torrent::resume_save_progress(*download->download(), download->download()->bencode()->get_key("libtorrent_resume"));
// TODO: This is actually for pause, not stop... And doesn't get
// called when the download isn't active, but was in the 'started'
// view.
DL_TRIGGER_EVENT(download, "event.download.paused");
rpc::call_command("d.state_changed.set", cachedTime.seconds(), rpc::make_target(download));
auto cached_seconds = torrent::this_thread::cached_seconds().count();
rpc::call_command("d.state_changed.set", cached_seconds, rpc::make_target(download));
rpc::call_command("d.state_counter.set", rpc::call_command_value("d.state_counter", rpc::make_target(download)), rpc::make_target(download));
// If initial seeding is complete, don't try it again when restarting.
@@ -550,8 +534,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");
}
+4 -39
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_CORE_DOWNLOAD_LIST_H
#define RTORRENT_CORE_DOWNLOAD_LIST_H
@@ -43,6 +7,7 @@
namespace torrent {
class HashString;
class Object;
}
namespace core {
@@ -74,7 +39,7 @@ public:
using base_type::empty;
using base_type::size;
DownloadList() { }
DownloadList() = default;
void clear();
@@ -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);
+8 -4
View File
@@ -20,6 +20,7 @@
#include "download.h"
#include "download_store.h"
#include "rpc/parse_commands.h"
namespace core {
@@ -93,11 +94,14 @@ DownloadStore::write_bencode(const std::string& filename, const torrent::Object&
if (fd < 0)
goto download_store_save_error;
if (rpc::call_command_value("system.files.session.fdatasync")) {
#ifdef __APPLE__
fsync(fd);
fsync(fd);
#else
fdatasync(fd);
fdatasync(fd);
#endif
}
::close(fd);
return true;
@@ -141,7 +145,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());
@@ -175,7 +179,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;
}
+2 -39
View File
@@ -1,46 +1,9 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <memory>
#include <sstream>
#include <torrent/http.h>
#include "rak/functional.h"
#include "http_queue.h"
#include "curl_get.h"
@@ -48,8 +11,8 @@ namespace core {
HttpQueue::iterator
HttpQueue::insert(const std::string& url, std::iostream* s) {
std::auto_ptr<CurlGet> h(m_slot_factory());
std::unique_ptr<CurlGet> h(m_slot_factory());
h->set_url(url);
h->set_stream(s);
h->set_timeout(5 * 60);
+3 -39
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_CORE_HTTP_QUEUE_H
#define RTORRENT_CORE_HTTP_QUEUE_H
@@ -47,10 +11,10 @@ class CurlGet;
class HttpQueue : private std::list<CurlGet*> {
public:
typedef std::list<CurlGet*> base_type;
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;
typedef std::list<slot_curl_get> signal_curl_get;
using base_type::iterator;
using base_type::const_iterator;
@@ -65,7 +29,7 @@ public:
using base_type::empty;
using base_type::size;
HttpQueue() {}
HttpQueue() = default;
~HttpQueue() { clear(); }
// Note that any slots connected to the CurlGet signals must be
+59 -45
View File
@@ -17,23 +17,23 @@
#include <torrent/error.h>
#include <torrent/exceptions.h>
#include <torrent/object_stream.h>
#include <torrent/tracker_list.h>
#include <torrent/throttle.h>
#include <torrent/utils/log.h>
#include "rpc/parse_commands.h"
#include "utils/directory.h"
#include "utils/base64.h"
#include "utils/file_status_cache.h"
#include "globals.h"
#include "curl_get.h"
#include "curl_stack.h"
#include "control.h"
#include "download.h"
#include "download_factory.h"
#include "download_store.h"
#include "http_queue.h"
#include "manager.h"
#include "poll_manager.h"
#include "view.h"
namespace core {
@@ -50,15 +50,14 @@ Manager::push_log(const char* msg) {
}
Manager::Manager() :
m_hashingView(NULL),
m_log_important(torrent::log_open_log_buffer("important")),
m_log_complete(torrent::log_open_log_buffer("complete"))
{
m_downloadStore = new DownloadStore();
m_downloadList = new DownloadList();
m_fileStatusCache = new FileStatusCache();
m_httpQueue = new HttpQueue();
m_httpStack = new CurlStack();
m_log_important(torrent::log_open_log_buffer("important")),
m_log_complete(torrent::log_open_log_buffer("complete")) {
m_download_store = std::make_unique<DownloadStore>();
m_download_list = std::make_unique<DownloadList>();
m_file_status_cache = std::make_unique<FileStatusCache>();
m_http_queue = std::make_unique<HttpQueue>();
m_http_stack = std::make_unique<CurlStack>();
torrent::Throttle* unthrottled = torrent::Throttle::create_throttle();
unthrottled->set_max_rate(0);
@@ -67,19 +66,12 @@ Manager::Manager() :
Manager::~Manager() {
torrent::Throttle::destroy_throttle(m_throttles["NULL"].first);
delete m_downloadList;
// TODO: Clean up logs objects.
delete m_downloadStore;
delete m_httpQueue;
delete m_fileStatusCache;
}
void
Manager::set_hashing_view(View* v) {
if (v == NULL || m_hashingView != NULL)
throw torrent::internal_error("Manager::set_hashing_view(...) received NULL or is already set.");
if (v == nullptr || m_hashingView != nullptr)
throw torrent::internal_error("Manager::set_hashing_view(...) received nullptr or is already set.");
m_hashingView = v;
m_hashingView->signal_changed().push_back(std::bind(&Manager::receive_hashing_changed, this));
@@ -88,12 +80,12 @@ Manager::set_hashing_view(View* v) {
torrent::ThrottlePair
Manager::get_throttle(const std::string& name) {
ThrottleMap::const_iterator itr = m_throttles.find(name);
torrent::ThrottlePair throttles = (itr == m_throttles.end() ? torrent::ThrottlePair(NULL, NULL) : itr->second);
torrent::ThrottlePair throttles = (itr == m_throttles.end() ? torrent::ThrottlePair(nullptr, nullptr) : itr->second);
if (throttles.first == NULL)
if (throttles.first == nullptr)
throttles.first = torrent::up_throttle_global();
if (throttles.second == NULL)
if (throttles.second == nullptr)
throttles.second = torrent::down_throttle_global();
return throttles;
@@ -107,7 +99,7 @@ Manager::set_address_throttle(uint32_t begin, uint32_t end, torrent::ThrottlePai
torrent::ThrottlePair
Manager::get_address_throttle(const sockaddr* addr) {
return m_addressThrottles.get(rak::socket_address::cast_from(addr)->sa_inet()->address_h(), torrent::ThrottlePair(NULL, NULL));
return m_addressThrottles.get(rak::socket_address::cast_from(addr)->sa_inet()->address_h(), torrent::ThrottlePair(nullptr, nullptr));
}
int64_t
@@ -120,7 +112,7 @@ Manager::retrieve_throttle_value(const torrent::Object::string_type& name, bool
torrent::Throttle* throttle = up ? itr->second.first : itr->second.second;
// check whether the actual up/down throttle exist (one of the pair can be missing)
if (throttle == NULL)
if (throttle == nullptr)
return (int64_t)-1;
int64_t throttle_max = (int64_t)throttle->max_rate();
@@ -142,36 +134,36 @@ Manager::retrieve_throttle_value(const torrent::Object::string_type& name, bool
// Most of this should be possible to move out.
void
Manager::initialize_second() {
torrent::Http::slot_factory() = std::bind(&CurlStack::new_object, m_httpStack);
m_httpQueue->set_slot_factory(std::bind(&CurlStack::new_object, m_httpStack));
torrent::Http::slot_factory() = std::bind(&CurlStack::new_object, m_http_stack.get());
m_http_queue->set_slot_factory(std::bind(&CurlStack::new_object, m_http_stack.get()));
CurlStack::global_init();
}
void
Manager::cleanup() {
m_httpStack->shutdown();
m_http_stack->shutdown();
// Need to disconnect log signals? Not really since we won't receive
// any more.
m_downloadList->clear();
m_download_list->clear();
// When we implement asynchronous DNS lookups, we need to cancel them
// here before the torrent::* objects are deleted.
torrent::cleanup();
delete m_httpStack;
m_http_stack.reset();
CurlStack::global_cleanup();
}
void
Manager::shutdown(bool force) {
if (!force)
std::for_each(m_downloadList->begin(), m_downloadList->end(), [this](Download* d) { m_downloadList->pause_default(d); });
std::for_each(m_download_list->begin(), m_download_list->end(), [this](Download* d) { m_download_list->pause_default(d); });
else
std::for_each(m_downloadList->begin(), m_downloadList->end(), [this](Download* d) { m_downloadList->close_quick(d); });
std::for_each(m_download_list->begin(), m_download_list->end(), [this](Download* d) { m_download_list->close_quick(d); });
}
void
@@ -225,7 +217,7 @@ Manager::set_bind_address(const std::string& addr) {
if ((err = rak::address_info::get_address_info(addr.c_str(), PF_INET, SOCK_STREAM, &ai)) != 0 &&
(err = rak::address_info::get_address_info(addr.c_str(), PF_INET6, SOCK_STREAM, &ai)) != 0)
throw torrent::input_error("Could not set bind address: " + std::string(rak::address_info::strerror(err)) + ".");
try {
if (torrent::connection_manager()->listen_port() != 0) {
@@ -237,7 +229,7 @@ Manager::set_bind_address(const std::string& addr) {
torrent::connection_manager()->set_bind_address(ai->address()->c_sockaddr());
}
m_httpStack->set_bind_address(!ai->address()->is_address_any() ? ai->address()->address_str() : std::string());
m_http_stack->set_bind_address(!ai->address()->is_address_any() ? ai->address()->address_str() : std::string());
rak::address_info::free_address_info(ai);
@@ -260,7 +252,7 @@ Manager::set_local_address(const std::string& addr) {
if ((err = rak::address_info::get_address_info(addr.c_str(), PF_INET, SOCK_STREAM, &ai)) != 0 &&
(err = rak::address_info::get_address_info(addr.c_str(), PF_INET6, SOCK_STREAM, &ai)) != 0)
throw torrent::input_error("Could not set local address: " + std::string(rak::address_info::strerror(err)) + ".");
try {
torrent::connection_manager()->set_local_address(ai->address()->c_sockaddr());
@@ -282,9 +274,9 @@ Manager::set_proxy_address(const std::string& addr) {
int port;
rak::address_info* ai;
char buf[addr.length() + 1];
std::string buf(addr.length() + 1, '\0');
int err = std::sscanf(addr.c_str(), "%[^:]:%i", buf, &port);
int err = std::sscanf(addr.c_str(), "%[^:]:%i", buf.data(), &port);
if (err <= 0)
throw torrent::input_error("Could not parse proxy address.");
@@ -292,7 +284,7 @@ Manager::set_proxy_address(const std::string& addr) {
if (err == 1)
port = 80;
if ((err = rak::address_info::get_address_info(buf, PF_INET, SOCK_STREAM, &ai)) != 0)
if ((err = rak::address_info::get_address_info(buf.data(), PF_INET, SOCK_STREAM, &ai)) != 0)
throw torrent::input_error("Could not set proxy address: " + std::string(rak::address_info::strerror(err)) + ".");
try {
@@ -313,6 +305,21 @@ Manager::receive_http_failed(std::string msg) {
push_log_std("Http download error: \"" + msg + "\"");
}
bool
is_data_uri(const std::string& uri) {
return std::strncmp(uri.c_str(), "data:", 5) == 0;
}
std::string
decode_data_uri(const std::string& uri) {
const auto start = uri.find("base64,", 5) + 7;
if (start == std::string::npos)
throw torrent::input_error("Invalid data uri: not base64 encoded.");
if (start >= uri.size())
throw torrent::input_error("Empty base64.");
return utils::decode_base64(uri.substr(start));
}
void
Manager::try_create_download(const std::string& uri, int flags, const command_list_type& commands) {
// If the path was attempted loaded before, skip it.
@@ -320,6 +327,7 @@ Manager::try_create_download(const std::string& uri, int flags, const command_li
!(flags & create_raw_data) &&
!is_network_uri(uri) &&
!is_magnet_uri(uri) &&
!is_data_uri(uri) &&
!file_status_cache()->insert(uri, 0))
return;
@@ -333,10 +341,16 @@ Manager::try_create_download(const std::string& uri, int flags, const command_li
f->set_print_log(!(flags & create_quiet));
f->slot_finished([f]() { delete f; });
if (flags & create_raw_data)
if (is_data_uri(uri)) {
// Allow the use of data URIs, primarily for JSON-RPC which
// doesn't have a defined mechanism for binary data
f->load_raw_data(decode_data_uri(uri));
f->variables()["tied_to_file"] = (int64_t)false;
} else if (flags & create_raw_data) {
f->load_raw_data(uri);
else
} else {
f->load(uri);
}
f->commit();
}
@@ -419,7 +433,7 @@ path_expand(std::vector<std::string>* paths, const std::string& pattern) {
currentCache.swap(nextCache);
}
std::transform(currentCache.begin(), currentCache.end(), std::back_inserter(*paths), std::mem_fun_ref(&utils::Directory::path));
std::transform(currentCache.begin(), currentCache.end(), std::back_inserter(*paths), std::mem_fn(&utils::Directory::path));
}
bool
@@ -453,14 +467,14 @@ Manager::try_create_download_expand(const std::string& uri, int flags, command_l
void
Manager::receive_hashing_changed() {
bool foundHashing = std::find_if(m_hashingView->begin_visible(), m_hashingView->end_visible(),
std::mem_fun(&Download::is_hash_checking)) != m_hashingView->end_visible();
std::mem_fn(&Download::is_hash_checking)) != m_hashingView->end_visible();
// Try quick hashing all those with hashing == initial, set them to
// something else when failed.
for (View::iterator itr = m_hashingView->begin_visible(), last = m_hashingView->end_visible(); itr != last; ++itr) {
if ((*itr)->is_hash_checked())
throw torrent::internal_error("core::Manager::receive_hashing_changed() (*itr)->is_hash_checked().");
if ((*itr)->is_hash_checking() || (*itr)->is_hash_failed())
continue;
@@ -472,7 +486,7 @@ Manager::receive_hashing_changed() {
continue;
try {
m_downloadList->open_throw(*itr);
m_download_list->open_throw(*itr);
// Since the bitfield is allocated on loading of resume load or
// hash start, and unallocated on close, we know that if it it
+12 -16
View File
@@ -4,13 +4,11 @@
#include <iosfwd>
#include <memory>
#include <vector>
#include <torrent/utils/log_buffer.h>
#include <torrent/connection_manager.h>
#include <torrent/object.h>
#include "download_list.h"
#include "poll_manager.h"
#include "range_map.h"
namespace torrent {
@@ -23,6 +21,7 @@ class FileStatusCache;
namespace core {
class CurlStack;
class DownloadStore;
class HttpQueue;
@@ -35,18 +34,15 @@ public:
typedef DownloadList::iterator DListItr;
typedef utils::FileStatusCache FileStatusCache;
// typedef std::function<void (DownloadList::iterator)> slot_ready;
// typedef std::function<void ()> slot_void;
Manager();
~Manager();
DownloadList* download_list() { return m_downloadList; }
DownloadStore* download_store() { return m_downloadStore; }
FileStatusCache* file_status_cache() { return m_fileStatusCache; }
DownloadList* download_list() { return m_download_list.get(); }
DownloadStore* download_store() { return m_download_store.get(); }
FileStatusCache* file_status_cache() { return m_file_status_cache.get(); }
HttpQueue* http_queue() { return m_httpQueue; }
CurlStack* http_stack() { return m_httpStack; }
HttpQueue* http_queue() { return m_http_queue.get(); }
CurlStack* http_stack() { return m_http_stack.get(); }
View* hashing_view() { return m_hashingView; }
void set_hashing_view(View* v);
@@ -109,13 +105,13 @@ private:
void receive_http_failed(std::string msg);
void receive_hashing_changed();
DownloadList* m_downloadList;
DownloadStore* m_downloadStore;
FileStatusCache* m_fileStatusCache;
HttpQueue* m_httpQueue;
CurlStack* m_httpStack;
std::unique_ptr<DownloadList> m_download_list;
std::unique_ptr<DownloadStore> m_download_store;
std::unique_ptr<FileStatusCache> m_file_status_cache;
std::unique_ptr<HttpQueue> m_http_queue;
std::unique_ptr<CurlStack> m_http_stack;
View* m_hashingView;
View* m_hashingView{};
ThrottleMap m_throttles;
AddressThrottleMap m_addressThrottles;
-91
View File
@@ -1,91 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <stdexcept>
#include <unistd.h>
#include <torrent/exceptions.h>
#include <torrent/poll_epoll.h>
#include <torrent/poll_kqueue.h>
#include <torrent/poll_select.h>
#include "globals.h"
#include "control.h"
#include "manager.h"
#include "poll_manager.h"
namespace core {
torrent::Poll*
create_poll() {
const char* poll_name = getenv("RTORRENT_POLL");
int maxOpen = sysconf(_SC_OPEN_MAX);
torrent::Poll* poll = NULL;
if (poll_name != NULL) {
if (!strcmp(poll_name, "epoll"))
poll = torrent::PollEPoll::create(maxOpen);
else if (!strcmp(poll_name, "kqueue"))
poll = torrent::PollKQueue::create(maxOpen);
else if (!strcmp(poll_name, "select"))
poll = torrent::PollSelect::create(maxOpen);
if (poll == NULL)
control->core()->push_log_std(std::string("Cannot enable '") + poll_name + "' based polling.");
}
if (poll != NULL)
control->core()->push_log_std(std::string("Using '") + poll_name + "' based polling.");
else if ((poll = torrent::PollEPoll::create(maxOpen)) != NULL)
control->core()->push_log_std("Using 'epoll' based polling.");
else if ((poll = torrent::PollKQueue::create(maxOpen)) != NULL)
control->core()->push_log_std("Using 'kqueue' based polling.");
else if ((poll = torrent::PollSelect::create(maxOpen)) != NULL)
control->core()->push_log_std("Using 'select' based polling.");
else
throw torrent::internal_error("Could not create any Poll object.");
return poll;
}
}
-52
View File
@@ -1,52 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_CORE_POLL_MANAGER_H
#define RTORRENT_CORE_POLL_MANAGER_H
#include "curl_stack.h"
namespace torrent {
class Poll;
}
namespace core {
torrent::Poll* create_poll();
}
#endif
+7 -7
View File
@@ -29,10 +29,8 @@
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Contact: Jari Sundell <sundell.software@gmail.com>
#ifndef RTORRENT_CORE_RANGE_MAP_H
#define RTORRENT_CORE_RANGE_MAP_H
@@ -49,13 +47,15 @@ namespace core {
template<typename Key, typename T, typename Compare = std::less<Key>,
typename Alloc = std::allocator<std::pair<const Key, T> > >
class RangeMap : private std::map<Key, std::pair<Key, T>, Compare,
typename Alloc::template rebind<std::pair<const Key, std::pair<Key, T> > >::other> {
typename std::allocator_traits<Alloc>::template rebind_alloc<std::pair<const Key, std::pair<Key, T>>>> {
typedef std::map<Key, std::pair<Key, T>, Compare,
typename Alloc::template rebind<std::pair<const Key, std::pair<Key, T> > >::other> base_type;
typename std::allocator_traits<Alloc>::template rebind_alloc<std::pair<const Key, std::pair<Key, T>>>> base_type;
//std::allocator_traits<Alloc>::template rebind_alloc<std::pair<const Key, std::pair<Key, T>>>
public:
RangeMap() {}
RangeMap() = default;
RangeMap(const Compare& c) : base_type(c) {}
typedef typename base_type::iterator iterator;
+36 -49
View File
@@ -1,44 +1,7 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <algorithm>
#include <functional>
#include <rak/functional.h>
#include <torrent/download.h>
#include <torrent/exceptions.h>
@@ -53,7 +16,7 @@
namespace core {
// Also add focus thingie here?
struct view_downloads_compare : std::binary_function<Download*, Download*, bool> {
struct view_downloads_compare : std::function<bool (Download*, Download*)> {
view_downloads_compare(const torrent::Object& cmd) :
m_command(cmd) {}
@@ -87,7 +50,7 @@ struct view_downloads_compare : std::binary_function<Download*, Download*, bool>
const torrent::Object& m_command;
};
struct view_downloads_filter : std::unary_function<Download*, bool> {
struct view_downloads_filter : std::function<bool (Download*)> {
view_downloads_filter(const torrent::Object& cmd, const torrent::Object& cmd2) :
m_command(cmd), m_command2(cmd2) {}
@@ -150,7 +113,7 @@ struct view_downloads_filter : std::unary_function<Download*, bool> {
void
View::emit_changed() {
priority_queue_update(&taskScheduler, &m_delayChanged, cachedTime);
torrent::this_thread::scheduler()->update_wait_for(&m_delay_changed, 0ms);
}
void
@@ -164,7 +127,7 @@ View::~View() {
return;
clear_filter_on();
priority_queue_erase(&taskScheduler, &m_delayChanged);
torrent::this_thread::scheduler()->erase(&m_delay_changed);
}
void
@@ -180,13 +143,12 @@ View::initialize(const std::string& name) {
m_name = name;
// Urgh, wrong. No filtering being done.
std::for_each(dlist->begin(), dlist->end(), rak::bind1st(std::mem_fun(&View::push_back), this));
std::for_each(dlist->begin(), dlist->end(), [&](Download* d) { push_back(d); });
m_size = base_type::size();
m_focus = 0;
set_last_changed(rak::timer());
m_delayChanged.slot() = std::bind(&View::emit_changed_now, this);
m_delay_changed.slot() = [this]() { emit_changed_now(); };
}
void
@@ -236,20 +198,45 @@ View::set_not_visible(Download* download) {
}
void
View::next_focus() {
View::next_focus(unsigned int i) {
if (empty())
return;
m_focus = (m_focus + 1) % (size() + 1);
// If at the boundary, roll over
if (m_focus == size() - 1) {
m_focus = size();
emit_changed();
return;
}
// Move forward, stop at the boundary
if (m_focus == size()) // Needs special handling to ensure it's not off by one
m_focus = i - 1;
else
m_focus += i;
if (m_focus > size() - 1)
m_focus = size() - 1;
emit_changed();
}
void
View::prev_focus() {
View::prev_focus(unsigned int i) {
if (empty())
return;
m_focus = (m_focus - 1 + size() + 1) % (size() + 1);
// If at the boundary, roll over
if (m_focus == size()) {
m_focus = size() - 1;
emit_changed();
return;
}
// Move backward, stop at the boundary
m_focus -= i;
if (m_focus < 0 || m_focus > size())
m_focus = size();
emit_changed();
}
@@ -360,7 +347,7 @@ View::clear_filter_on() {
inline void
View::insert_visible(Download* d) {
iterator itr = std::find_if(begin_visible(), end_visible(), std::bind1st(view_downloads_compare(m_sortNew), d));
iterator itr = std::find_if(begin_visible(), end_visible(), [&d, this](Download* d2) { return view_downloads_compare(m_sortNew)(d, d2); });
m_size++;
m_focus += (m_focus >= position(itr));
+13 -46
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Provides a filtered and sorted list of downloads that can be
// updated auto-magically.
//
@@ -50,11 +14,11 @@
#define RTORRENT_CORE_VIEW_DOWNLOADS_H
#include <functional>
#include <list>
#include <string>
#include <vector>
#include <rak/timer.h>
#include <torrent/object.h>
#include <torrent/utils/scheduler.h>
#include "globals.h"
@@ -75,7 +39,7 @@ public:
using base_type::size_type;
View() {}
View() = default;
~View();
void initialize(const std::string& name);
@@ -114,8 +78,11 @@ public:
void set_visible(Download* download);
void set_not_visible(Download* download);
void next_focus();
void prev_focus();
void next_focus(unsigned int i);
void prev_focus(unsigned int i);
void next_focus() { next_focus(1); }
void prev_focus() { prev_focus(1); }
void sort();
@@ -146,8 +113,8 @@ public:
//
// Currently initialized to rak::timer(), though perhaps we should
// use cachedTimer.
rak::timer last_changed() const { return m_lastChanged; }
void set_last_changed(const rak::timer& t = ::cachedTime) { m_lastChanged = t; }
auto last_changed() const { return m_last_changed; }
void set_last_changed(std::chrono::microseconds t = torrent::this_thread::cached_time()) { m_last_changed = t; }
// Don't connect any slots until after initialize else it get's
// triggered when adding the Download's in DownloadList.
@@ -184,10 +151,10 @@ private:
torrent::Object m_event_added;
torrent::Object m_event_removed;
rak::timer m_lastChanged;
std::chrono::microseconds m_last_changed{};
signal_void m_signal_changed;
rak::priority_item m_delayChanged;
signal_void m_signal_changed;
torrent::utils::SchedulerEntry m_delay_changed;
};
} // namespace core
+4 -41
View File
@@ -1,43 +1,6 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <algorithm>
#include <rak/functional.h>
#include <torrent/exceptions.h>
#include <torrent/object.h>
@@ -55,7 +18,7 @@ namespace core {
void
ViewManager::clear() {
std::for_each(begin(), end(), rak::call_delete<View>());
std::for_each(begin(), end(), [](View* v) { delete v; });
base_type::clear();
}
@@ -76,12 +39,12 @@ ViewManager::insert(const std::string& name) {
ViewManager::iterator
ViewManager::find(const std::string& name) {
return std::find_if(begin(), end(), rak::equal(name, std::mem_fun(&View::name)));
return std::find_if(begin(), end(), [name](View* v){ return name == v->name(); });
}
ViewManager::iterator
ViewManager::find_throw(const std::string& name) {
iterator itr = std::find_if(begin(), end(), rak::equal(name, std::mem_fun(&View::name)));
iterator itr = std::find_if(begin(), end(), [name](View* v){ return name == v->name(); });
if (itr == end())
throw torrent::input_error("Could not find view: " + name);
@@ -93,7 +56,7 @@ void
ViewManager::sort(const std::string& name, uint32_t timeout) {
iterator viewItr = find_throw(name);
if ((*viewItr)->last_changed() + rak::timer::from_seconds(timeout) > cachedTime)
if ((*viewItr)->last_changed() + std::chrono::seconds(timeout) > torrent::this_thread::cached_time())
return;
// Should we rename sort, or add a seperate function?
+3 -39
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_CORE_VIEW_MANAGER_H
#define RTORRENT_CORE_VIEW_MANAGER_H
@@ -48,12 +12,12 @@ class ViewManager : public rak::unordered_vector<View*> {
public:
typedef rak::unordered_vector<View*> base_type;
typedef std::list<std::string> filter_args;
using base_type::iterator;
using base_type::const_iterator;
using base_type::reverse_iterator;
using base_type::const_reverse_iterator;
using base_type::size_type;
using base_type::begin;
@@ -64,7 +28,7 @@ public:
using base_type::empty;
using base_type::size;
ViewManager() {}
ViewManager() = default;
~ViewManager() { clear(); }
// Ffff... Just throwing together an interface, need to think some
+1 -1
View File
@@ -35,7 +35,7 @@ public:
static const int color_invalid = ~int();
static const int color_default = 0;
Attributes() {}
Attributes() = default;
Attributes(const char* pos, int attr, int col) :
m_position(pos), m_attributes(attr), m_colors(col) {}
Attributes(const char* pos, const Attributes& old) :
+120 -43
View File
@@ -1,45 +1,9 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <unistd.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <torrent/exceptions.h>
#include <unistd.h>
#include "rpc/parse_commands.h"
@@ -48,14 +12,16 @@
namespace display {
bool Canvas::m_isInitialized = false;
bool Canvas::m_isDaemon = false;
bool Canvas::m_isDaemon = false;
// Maps ncurses color IDs to a ncurses attribute int
std::unordered_map<int, int> Canvas::m_attr_map = {};
Canvas::Canvas(int x, int y, int width, int height) {
if (!m_isDaemon) {
m_window = newwin(height, width, y, x);
m_window = newwin(height, width, y, x);
if (m_window == NULL)
throw torrent::internal_error("Could not allocate ncurses canvas.");
if (m_window == NULL)
throw torrent::internal_error("Could not allocate ncurses canvas.");
}
}
@@ -73,7 +39,7 @@ Canvas::print_attributes(unsigned int x, unsigned int y, const char* first, cons
move(x, y);
attr_t org_attr;
short org_pair;
short org_pair;
wattr_get(m_window, &org_attr, &org_pair, NULL);
attributes_list::const_iterator attrItr = attributes->begin();
@@ -111,6 +77,9 @@ Canvas::initialize() {
if (!m_isDaemon) {
initscr();
start_color();
use_default_colors();
Canvas::build_colors();
raw();
noecho();
nodelay(stdscr, TRUE);
@@ -119,6 +88,114 @@ Canvas::initialize() {
}
}
// Function wrapper for what possibly is a macro
int
get_colors() {
return COLORS;
}
// Turns the string color definitions from the "ui.color.*" RPC
// commands into valid ncurses color pairs
void
Canvas::build_colors() {
// This may get called early in the start process by the config
// file, so we need to delay building until initscr() has a chance
// to run
if (!m_isInitialized || m_isDaemon)
return;
// basic color names, index maps to ncurses COLOR_*
static constexpr std::array color_names{
"black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"};
// Those hold the background colors of "odd" and "even"
int bg_odd = -1;
int bg_even = -1;
for (int k = 1; k < RCOLOR_MAX; k++) {
init_pair(k, -1, -1);
std::string color_def = rpc::call_command_string(color_vars[k]);
if (color_def.empty())
continue; // Use terminal default if definition is empty
short color[2] = {-1, -1}; // fg, bg
short color_idx = 0; // 0 = fg; 1 = bg
short bright = 0;
unsigned long attr = A_NORMAL;
// Process string as space-separated words
size_t start = 0, end = 0;
while (true) {
end = color_def.find(' ', start);
std::string word = color_def.substr(start, end - start);
if (word == "bold")
attr |= A_BOLD;
else if (word == "standout")
attr |= A_STANDOUT;
else if (word == "underline")
attr |= A_UNDERLINE;
else if (word == "reverse")
attr |= A_REVERSE;
else if (word == "blink")
attr |= A_BLINK;
else if (word == "dim")
attr |= A_DIM;
else if (word == "on") {
color_idx = 1;
bright = 0;
} // Switch to background color
else if (word == "gray" || word == "grey")
color[color_idx] = bright ? 7 : 8; // Bright gray is white
else if (word == "bright")
bright = 8;
else if (word.find_first_not_of("0123456789") == std::string::npos) {
// Handle numeric index
short c = -1;
sscanf(word.c_str(), "%hd", &c);
color[color_idx] = c;
} else
for (short c = 0; c < 8; c++) { // Check for basic color names
if (word == color_names[c]) {
color[color_idx] = bright + c;
break;
}
}
if (end == std::string::npos)
break;
start = end + 1;
}
// Check that fg & bg color index is valid
if ((color[0] != -1 && color[0] >= get_colors()) || (color[1] != -1 && color[1] >= get_colors())) {
char buf[33];
snprintf(buf, 33, "%d", get_colors());
Canvas::cleanup();
throw torrent::input_error(color_def + ": your terminal only supports " + buf + " colors.");
}
m_attr_map[k] = attr; // overwrite or insert the value
init_pair(k, color[0], color[1]);
if (k == RCOLOR_EVEN)
bg_even = color[1];
if (k == RCOLOR_ODD)
bg_odd = color[1];
}
// Now make copies of the basic colors with the "odd" and "even" definitions mixed in
for (int k = 1; k < RCOLOR_MAX; k++) {
short fg, bg;
pair_content(k, &fg, &bg);
// Replace the background color, and mix in the attributes
m_attr_map[k + 1 * RCOLOR_MAX] = m_attr_map[k] | m_attr_map[RCOLOR_EVEN];
m_attr_map[k + 2 * RCOLOR_MAX] = m_attr_map[k] | m_attr_map[RCOLOR_ODD];
init_pair(k + 1 * RCOLOR_MAX, fg, bg == -1 ? bg_even : bg);
init_pair(k + 2 * RCOLOR_MAX, fg, bg == -1 ? bg_odd : bg);
}
}
void
Canvas::cleanup() {
if (!m_isInitialized)
@@ -143,4 +220,4 @@ Canvas::term_size() {
return std::pair<int, int>(80, 24);
}
}
} // namespace display
+230 -84
View File
@@ -1,125 +1,206 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_DISPLAY_CANVAS_H
#define RTORRENT_DISPLAY_CANVAS_H
#include <string>
#include <unordered_map>
#include <vector>
#include "attributes.h"
#include "color_map.h"
namespace display {
class Canvas {
public:
typedef std::vector<Attributes> attributes_list;
typedef std::vector<Attributes> attributes_list;
typedef std::unordered_map<int, int> attributes_map;
Canvas(int x = 0, int y = 0, int width = 0, int height = 0);
~Canvas() { if (!m_isDaemon) { delwin(m_window); } }
~Canvas();
void refresh() { if (!m_isDaemon) { wnoutrefresh(m_window); } }
static void refresh_std() { if (!m_isDaemon) { wnoutrefresh(stdscr); } }
void redraw() { if (!m_isDaemon) { redrawwin(m_window); } }
static void redraw_std() { if (!m_isDaemon) { redrawwin(stdscr); } }
void refresh();
void redraw();
void resize(int w, int h);
void resize(int x, int y, int w, int h);
void resize(int w, int h) { if (!m_isDaemon) { wresize(m_window, h, w); } }
void resize(int x, int y, int w, int h);
static void refresh_std();
static void redraw_std();
static void resize_term(int x, int y);
static void resize_term(std::pair<int, int> dim);
static void resize_term(int x, int y) { if (!m_isDaemon) { resizeterm(y, x); } }
static void resize_term(std::pair<int, int> dim) { if (!m_isDaemon) { resizeterm(dim.second, dim.first); } }
unsigned int get_x();
unsigned int get_y();
unsigned int width();
unsigned int height();
unsigned int get_x() { int x, __UNUSED y; if (!m_isDaemon) { getyx(m_window, y, x); } else { x=1; } return x; }
unsigned int get_y() { int x, y; if (!m_isDaemon) { getyx(m_window, y, x); } else { y=1; } return y; }
unsigned int width() { int x, __UNUSED y; if (!m_isDaemon) { getmaxyx(m_window, y, x); } else { x=80; } return x; }
unsigned int height() { int x, y; if (!m_isDaemon) { getmaxyx(m_window, y, x); } else { y=24; } return y; }
void move(unsigned int x, unsigned int y) { if (!m_isDaemon) { wmove(m_window, y, x); } }
chtype get_background() { chtype bg=0; if (!m_isDaemon) { bg=getbkgd(m_window); } return bg; }
void set_background(chtype c) { if (!m_isDaemon) { return wbkgdset(m_window, c); } }
void erase() { if (!m_isDaemon) { werase(m_window); } }
static void erase_std() { if (!m_isDaemon) { werase(stdscr); } }
void print_border(chtype ls, chtype rs,
chtype ts, chtype bs,
chtype tl, chtype tr,
chtype bl, chtype br) { if (!m_isDaemon) { wborder(m_window, ls, rs, ts, bs, tl, tr, bl, br); } }
void move(unsigned int x, unsigned int y);
void erase();
static void erase_std();
// The format string is non-const, but that will not be a problem
// since the string shall always be a C string choosen at
// compiletime. Might cause extra copying of the string?
void print(const char* str, ...);
void print(unsigned int x, unsigned int y, const char* str, ...);
void print(const char* str, ...);
void print(unsigned int x, unsigned int y, const char* str, ...);
void print_attributes(unsigned int x, unsigned int y, const char* first, const char* last, const attributes_list* attributes);
void print_char(const chtype ch);
void print_char(unsigned int x, unsigned int y, const chtype ch);
void print_attributes(unsigned int x, unsigned int y, const char* first, const char* last, const attributes_list* attributes);
void print_char(const chtype ch) { if (!m_isDaemon) { waddch(m_window, ch); } }
void print_char(unsigned int x, unsigned int y, const chtype ch) { if (!m_isDaemon) { mvwaddch(m_window, y, x, ch); } }
void set_attr(unsigned int x, unsigned int y, unsigned int n, int attr, int color) { if (!m_isDaemon) { mvwchgat(m_window, y, x, n, attr, color, NULL); } }
void set_default_attributes(int attr) { if (!m_isDaemon) { (void)wattrset(m_window, attr); } }
void set_attr(unsigned int x, unsigned int y, unsigned int n, int attr, int color);
void set_attr(unsigned int x, unsigned int y, unsigned int n, ColorKind k);
void set_default_attributes(int attr);
// Initialize stdscr.
static void initialize();
static void cleanup();
static void initialize();
static void build_colors();
static void cleanup();
static int get_screen_width() { int x, __UNUSED y; if (!m_isDaemon) { getmaxyx(stdscr, y, x); } else { x=80; } return x; }
static int get_screen_height() { int x, y; if (!m_isDaemon) { getmaxyx(stdscr, y, x); } else { y=24;} return y; }
static int get_screen_width();
static int get_screen_height();
static std::pair<int, int> term_size();
static void do_update() { if (!m_isDaemon) { doupdate(); } }
static void do_update();
static bool daemon() { return m_isDaemon; }
static bool daemon() { return m_isDaemon; }
static const attributes_map& attr_map() { return m_attr_map; }
private:
Canvas(const Canvas&);
void operator = (const Canvas&);
void operator=(const Canvas&);
static bool m_isInitialized;
static bool m_isDaemon;
static bool m_isInitialized;
static bool m_isDaemon;
WINDOW* m_window;
// Maps ncurses color IDs to a ncurses attribute int
static std::unordered_map<int, int> m_attr_map;
WINDOW* m_window;
};
inline Canvas::~Canvas() {
if (!m_isDaemon) {
delwin(m_window);
}
}
inline void
Canvas::refresh() {
if (!m_isDaemon) {
wnoutrefresh(m_window);
}
}
inline void
Canvas::refresh_std() {
if (!m_isDaemon) {
wnoutrefresh(stdscr);
}
}
inline void
Canvas::redraw() {
if (!m_isDaemon) {
redrawwin(m_window);
}
}
inline void
Canvas::redraw_std() {
if (!m_isDaemon) {
redrawwin(stdscr);
}
}
inline void
Canvas::resize(int w, int h) {
if (!m_isDaemon) {
wresize(m_window, h, w);
}
}
inline void
Canvas::resize_term(int x, int y) {
if (!m_isDaemon) {
resizeterm(y, x);
}
}
inline void
Canvas::resize_term(std::pair<int, int> dim) {
if (!m_isDaemon) {
resizeterm(dim.second, dim.first);
}
}
inline unsigned int
Canvas::get_x() {
int x;
[[maybe_unused]] int y;
if (!m_isDaemon) {
getyx(m_window, y, x);
} else {
x = 1;
}
return x;
}
inline unsigned int
Canvas::get_y() {
int x, y;
if (!m_isDaemon) {
getyx(m_window, y, x);
} else {
y = 1;
}
return y;
}
inline unsigned int
Canvas::width() {
int x;
[[maybe_unused]] int y;
if (!m_isDaemon) {
getmaxyx(m_window, y, x);
} else {
x = 80;
}
return x;
}
inline unsigned int
Canvas::height() {
int x, y;
if (!m_isDaemon) {
getmaxyx(m_window, y, x);
} else {
y = 24;
}
return y;
}
inline void
Canvas::move(unsigned int x, unsigned int y) {
if (!m_isDaemon) {
wmove(m_window, y, x);
}
}
inline void
Canvas::erase() {
if (!m_isDaemon) {
werase(m_window);
}
}
inline void
Canvas::erase_std() {
if (!m_isDaemon) {
werase(stdscr);
}
}
inline void
Canvas::print(const char* str, ...) {
va_list arglist;
@@ -143,6 +224,71 @@ Canvas::print(unsigned int x, unsigned int y, const char* str, ...) {
}
}
inline void
Canvas::print_char(const chtype ch) {
if (!m_isDaemon) {
waddch(m_window, ch);
}
}
inline void
Canvas::print_char(unsigned int x, unsigned int y, const chtype ch) {
if (!m_isDaemon) {
mvwaddch(m_window, y, x, ch);
}
}
inline void
Canvas::set_attr(unsigned int x, unsigned int y, unsigned int n, int attr, int color) {
if (!m_isDaemon) {
mvwchgat(m_window, y, x, n, attr, color, NULL);
}
}
inline void
Canvas::set_attr(unsigned int x, unsigned int y, unsigned int n, ColorKind k) {
if (!m_isDaemon) {
mvwchgat(m_window, y, x, n, m_attr_map[k], k, NULL);
}
}
inline void
Canvas::set_default_attributes(int attr) {
if (!m_isDaemon) {
(void)wattrset(m_window, attr);
}
}
inline int
Canvas::get_screen_width() {
int x;
[[maybe_unused]] int y;
if (!m_isDaemon) {
getmaxyx(stdscr, y, x);
} else {
x = 80;
}
return x;
}
inline int
Canvas::get_screen_height() {
int x, y;
if (!m_isDaemon) {
getmaxyx(stdscr, y, x);
} else {
y = 24;
}
return y;
}
inline void
Canvas::do_update() {
if (!m_isDaemon) {
doupdate();
}
}
} // namespace display
#endif
+49
View File
@@ -0,0 +1,49 @@
#ifndef RTORRENT_DISPLAY_COLOR_MAP_H
#define RTORRENT_DISPLAY_COLOR_MAP_H
#include <array>
#include <map>
#include <curses.h>
namespace display {
enum ColorKind {
RCOLOR_NCURSES_DEFAULT, // Color 0 is reserved by ncurses and cannot be changed
RCOLOR_TITLE,
RCOLOR_FOOTER,
RCOLOR_FOCUS,
RCOLOR_LABEL,
RCOLOR_INFO,
RCOLOR_ALARM,
RCOLOR_COMPLETE,
RCOLOR_SEEDING,
RCOLOR_STOPPED,
RCOLOR_QUEUED,
RCOLOR_INCOMPLETE,
RCOLOR_LEECHING,
RCOLOR_ODD,
RCOLOR_EVEN,
RCOLOR_MAX,
};
static const std::array<const char*, RCOLOR_MAX> color_vars{
nullptr,
"ui.color.title",
"ui.color.footer",
"ui.color.focus",
"ui.color.label",
"ui.color.info",
"ui.color.alarm",
"ui.color.complete",
"ui.color.seeding",
"ui.color.stopped",
"ui.color.queued",
"ui.color.incomplete",
"ui.color.leeching",
"ui.color.odd",
"ui.color.even",
};
} // namespace display
#endif
+2 -13
View File
@@ -29,10 +29,8 @@
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Contact: Jari Sundell <sundell.software@gmail.com>
#include "config.h"
@@ -47,15 +45,6 @@
namespace display {
Frame::Frame() :
m_type(TYPE_NONE),
m_positionX(0),
m_positionY(0),
m_width(0),
m_height(0) {
}
bool
Frame::is_width_dynamic() const {
switch (m_type) {
+8 -12
View File
@@ -29,10 +29,8 @@
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Contact: Jari Sundell <sundell.software@gmail.com>
#ifndef RTORRENT_DISPLAY_FRAME_H
#define RTORRENT_DISPLAY_FRAME_H
@@ -56,7 +54,7 @@ public:
};
struct bounds_type {
bounds_type() {}
bounds_type() = default;
bounds_type(extent_type minW, extent_type minH, extent_type maxW, extent_type maxH) :
minWidth(minW), minHeight(minH), maxWidth(maxW), maxHeight(maxH) {}
@@ -74,8 +72,6 @@ public:
static const size_type max_size = 5;
Frame();
bool is_width_dynamic() const;
bool is_height_dynamic() const;
@@ -116,12 +112,12 @@ private:
inline void balance_row(uint32_t x, uint32_t y, uint32_t width, uint32_t height);
inline void balance_column(uint32_t x, uint32_t y, uint32_t width, uint32_t height);
Type m_type;
Type m_type{TYPE_NONE};
uint32_t m_positionX;
uint32_t m_positionY;
uint32_t m_width;
uint32_t m_height;
uint32_t m_positionX{};
uint32_t m_positionY{};
uint32_t m_width{};
uint32_t m_height{};
union {
Window* m_window;
+29 -61
View File
@@ -1,44 +1,7 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <stdexcept>
#include <algorithm>
#include <rak/functional.h>
#include "canvas.h"
#include "globals.h"
@@ -47,74 +10,79 @@
namespace display {
Manager::Manager() :
m_forceRedraw(false) {
Manager::Manager() {
m_scheduler.external_set_thread_id(std::this_thread::get_id());
m_taskUpdate.slot() = std::bind(&Manager::receive_update, this);
m_task_update.slot() = std::bind(&Manager::receive_update, this);
}
Manager::~Manager() {
priority_queue_erase(&taskScheduler, &m_taskUpdate);
torrent::this_thread::scheduler()->erase(&m_task_update);
}
void
Manager::force_redraw() {
m_forceRedraw = true;
m_force_redraw = true;
}
void
Manager::schedule(Window* w, rak::timer t) {
rak::priority_queue_update(&m_scheduler, w->task_update(), t);
schedule_update(50000);
Manager::schedule(Window* w, std::chrono::microseconds t) {
m_scheduler.external_set_cached_time(torrent::this_thread::cached_time());
m_scheduler.update_wait_until(w->task_update(), t);
schedule_update(50ms);
}
void
Manager::unschedule(Window* w) {
rak::priority_queue_erase(&m_scheduler, w->task_update());
schedule_update(50000);
m_scheduler.external_set_cached_time(torrent::this_thread::cached_time());
m_scheduler.erase(w->task_update());
schedule_update(50ms);
}
void
Manager::adjust_layout() {
Canvas::redraw_std();
m_rootFrame.balance(0, 0, Canvas::get_screen_width(), Canvas::get_screen_height());
m_root_frame.balance(0, 0, Canvas::get_screen_width(), Canvas::get_screen_height());
schedule_update(0);
schedule_update(0ms);
}
void
Manager::receive_update() {
if (m_forceRedraw) {
m_forceRedraw = false;
if (m_force_redraw) {
m_force_redraw = false;
display::Canvas::resize_term(display::Canvas::term_size());
Canvas::redraw_std();
adjust_layout();
m_rootFrame.redraw();
m_root_frame.redraw();
}
Canvas::refresh_std();
rak::priority_queue_perform(&m_scheduler, cachedTime);
m_rootFrame.refresh();
m_scheduler.external_perform(torrent::this_thread::cached_time());
m_root_frame.refresh();
Canvas::do_update();
m_timeLastUpdate = cachedTime;
schedule_update(50000);
m_time_last_update = torrent::this_thread::cached_time();
schedule_update(50ms);
}
void
Manager::schedule_update(uint32_t minInterval) {
Manager::schedule_update(std::chrono::microseconds min_interval) {
if (m_scheduler.empty()) {
rak::priority_queue_erase(&taskScheduler, &m_taskUpdate);
torrent::this_thread::scheduler()->erase(&m_task_update);
return;
}
if (!m_taskUpdate.is_queued() || m_taskUpdate.time() > m_scheduler.top()->time()) {
rak::priority_queue_update(&taskScheduler, &m_taskUpdate, std::max(m_scheduler.top()->time(), m_timeLastUpdate + minInterval));
}
if (m_task_update.is_scheduled() && m_task_update.time() <= m_scheduler.front()->time())
return;
torrent::this_thread::scheduler()->update_wait_until(&m_task_update, std::max(m_scheduler.front()->time(), m_time_last_update + min_interval));
}
}
+9 -48
View File
@@ -1,44 +1,7 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_DISPLAY_MANAGER_H
#define RTORRENT_DISPLAY_MANAGER_H
#include <list>
#include <rak/priority_queue_default.h>
#include <torrent/utils/scheduler.h>
#include "frame.h"
@@ -53,26 +16,24 @@ public:
void force_redraw();
void schedule(Window* w, rak::timer t);
void schedule(Window* w, std::chrono::microseconds t);
void unschedule(Window* w);
void adjust_layout();
void receive_update();
// New interface.
Frame* root_frame() { return &m_rootFrame; }
Frame* root_frame() { return &m_root_frame; }
private:
void schedule_update(uint32_t minInterval);
void schedule_update(std::chrono::microseconds min_interval);
bool m_forceRedraw;
rak::timer m_timeLastUpdate;
bool m_force_redraw{false};
Frame m_root_frame;
rak::priority_queue_default m_scheduler;
rak::priority_item m_taskUpdate;
// New interface.
Frame m_rootFrame;
std::chrono::microseconds m_time_last_update{};
torrent::utils::ExternalScheduler m_scheduler;
torrent::utils::SchedulerEntry m_task_update;
};
}
+4 -6
View File
@@ -29,10 +29,8 @@
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Contact: Jari Sundell <sundell.software@gmail.com>
#ifndef RTORRENT_DISPLAY_TEXT_ELEMENT_H
#define RTORRENT_DISPLAY_TEXT_ELEMENT_H
@@ -51,8 +49,8 @@ public:
static const extent_type extent_full = ~extent_type();
TextElement() {}
virtual ~TextElement() {}
TextElement() = default;
virtual ~TextElement() = default;
// The last element must point to a valid memory location into which
// the caller must write a '\0' to terminate the c string. The
+3 -6
View File
@@ -29,15 +29,12 @@
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Contact: Jari Sundell <sundell.software@gmail.com>
#include "config.h"
#include <algorithm>
#include <rak/functional.h>
#include <torrent/exceptions.h>
#include "text_element_list.h"
@@ -46,7 +43,7 @@ namespace display {
void
TextElementList::clear() {
std::for_each(begin(), end(), rak::call_delete<TextElement>());
std::for_each(begin(), end(), [](TextElement* t) { delete t; });
base_type::clear();
}
+4 -7
View File
@@ -29,10 +29,8 @@
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Contact: Jari Sundell <sundell.software@gmail.com>
#ifndef RTORRENT_DISPLAY_TEXT_ELEMENT_LIST_H
#define RTORRENT_DISPLAY_TEXT_ELEMENT_LIST_H
@@ -61,7 +59,6 @@ public:
using base_type::push_back;
TextElementList() : m_column(0), m_columnWidth(0) {}
virtual ~TextElementList() { clear(); }
void clear();
@@ -74,8 +71,8 @@ public:
virtual extent_type max_length();
private:
unsigned int m_column;
extent_type* m_columnWidth;
unsigned int m_column{};
extent_type* m_columnWidth{};
};
}
+2 -4
View File
@@ -29,10 +29,8 @@
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Contact: Jari Sundell <sundell.software@gmail.com>
#include "config.h"
+2 -4
View File
@@ -29,10 +29,8 @@
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Contact: Jari Sundell <sundell.software@gmail.com>
#ifndef RTORRENT_DISPLAY_TEXT_ELEMENT_STRING_H
#define RTORRENT_DISPLAY_TEXT_ELEMENT_STRING_H
+8 -43
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
#include "config.h"
#include "display/text_element_value.h"
#include <ctime>
#include "globals.h"
#include "text_element_value.h"
namespace display {
@@ -47,7 +12,7 @@ namespace display {
void
TextElement::push_attribute(Canvas::attributes_list* attributes, Attributes value) {
Attributes base = attributes->back();
if (value.colors() == Attributes::color_invalid)
value.set_colors(base.colors());
@@ -69,12 +34,12 @@ TextElementValueBase::print(char* first, char* last, Canvas::attributes_list* at
// Transform the value if needed.
if (m_flags & flag_elapsed)
val = cachedTime.seconds() - val;
val = torrent::this_thread::cached_seconds().count() - val;
else if (m_flags & flag_remaining)
val = val - cachedTime.seconds();
val = val - torrent::this_thread::cached_seconds().count();
if (m_flags & flag_usec)
val = rak::timer(val).seconds();
val = torrent::utils::cast_seconds(std::chrono::microseconds(val)).count();
// Print the value.
if (first == last) {
@@ -108,7 +73,7 @@ TextElementValueBase::print(char* first, char* last, Canvas::attributes_list* at
} else if (m_flags & flag_date) {
time_t t = val;
std::tm *u = std::gmtime(&t);
if (u == NULL)
return first;
@@ -117,7 +82,7 @@ TextElementValueBase::print(char* first, char* last, Canvas::attributes_list* at
} else if (m_flags & flag_time) {
time_t t = val;
std::tm *u = std::gmtime(&t);
if (u == NULL)
return first;
+2 -38
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_DISPLAY_TEXT_ELEMENT_VALUE_H
#define RTORRENT_DISPLAY_TEXT_ELEMENT_VALUE_H
@@ -86,7 +50,7 @@ public:
virtual extent_type max_length() { return 12; }
private:
virtual int64_t value(void* object) { return m_value; }
virtual int64_t value([[maybe_unused]] void* object) { return m_value; }
int64_t m_value;
};
@@ -104,7 +68,7 @@ public:
virtual extent_type max_length() { return 12; }
private:
virtual int64_t value(void* object) { return m_slot(); }
virtual int64_t value([[maybe_unused]] void* object) { return m_slot(); }
slot_type m_slot;
};
+23 -55
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <cstring>
@@ -41,19 +5,18 @@
#include <sstream>
#include <iomanip>
#include <rak/socket_address.h>
#include <rak/timer.h>
#include <torrent/exceptions.h>
#include <torrent/connection_manager.h>
#include <torrent/rate.h>
#include <torrent/throttle.h>
#include <torrent/torrent.h>
#include <torrent/tracker.h>
#include <torrent/tracker_list.h>
#include <torrent/tracker/tracker.h>
#include <torrent/data/file_list.h>
#include <torrent/data/file_manager.h>
#include <torrent/download/resource_manager.h>
#include <torrent/peer/client_info.h>
#include "core/curl_stack.h"
#include "core/download.h"
#include "core/manager.h"
#include "rpc/parse_commands.h"
@@ -88,7 +51,7 @@ print_hhmmss(char* first, char* last, time_t t) {
char*
print_hhmmss_local(char* first, char* last, time_t t) {
std::tm *u = std::localtime(&t);
if (u == NULL)
//return "inv_time";
throw torrent::internal_error("print_hhmmss_local(...) failed.");
@@ -107,7 +70,7 @@ print_ddhhmm(char* first, char* last, time_t t) {
char*
print_ddmmyyyy(char* first, char* last, time_t t) {
std::tm *u = std::gmtime(&t);
if (u == NULL)
//return "inv_time";
throw torrent::internal_error("print_ddmmyyyy(...) failed.");
@@ -196,15 +159,18 @@ print_download_status(char* first, char* last, core::Download* d) {
first = print_buffer(first, last, "Checking hash [%2i%%]",
(d->download()->chunks_hashed() * 100) / d->download()->file_list()->size_chunks());
} else if (d->tracker_list()->has_active_not_scrape()) {
torrent::TrackerList::iterator itr =
std::find_if(d->tracker_list()->begin(), d->tracker_list()->end(),
std::mem_fun(&torrent::Tracker::is_busy_not_scrape));
char status[128];
} else if (d->tracker_controller().has_active_trackers_not_scrape()) {
auto tracker = d->tracker_controller().find_if([](const auto& t) {
return t.is_busy_not_scrape();
});
(*itr)->get_status(status, sizeof(status));
first = print_buffer(first, last, "Tracker[%i:%i]: Connecting to %s %s",
(*itr)->group(), std::distance(d->tracker_list()->begin(), itr), (*itr)->url().c_str(), status);
if (tracker.is_valid()) {
auto status = tracker.status();
first = print_buffer(first, last, "Tracker[%i]: Connecting to %s %s", tracker.group(), tracker.url().c_str(), status.c_str());
} else {
first = print_buffer(first, last, "Tracker: Connecting ...");
}
} else if (!d->message().empty()) {
first = print_buffer(first, last, "%s", d->message().c_str());
@@ -222,7 +188,7 @@ print_download_status(char* first, char* last, core::Download* d) {
char*
print_download_column_compact(char* first, char* last) {
first = print_buffer(first, last, " %-64.64s", "Name");
first = print_buffer(first, last, "| Status | Downloaded | Size | Done | Up Rate | Down Rate | Uploaded | ETA | Ratio| Misc ");
first = print_buffer(first, last, "| Status | Downloaded | Size | Done | Up Rate | Down Rate | Uploaded | ETA | Ratio | Misc ");
if (first > last)
throw torrent::internal_error("print_download_column_compact(...) wrote past end of the buffer.");
@@ -238,7 +204,7 @@ print_download_info_compact(char* first, char* last, core::Download* d) {
if (!d->download()->info()->is_open())
first = print_buffer(first, last, " CLOSED ");
else if (!d->download()->info()->is_active())
first = print_buffer(first, last, " OPEN ");
first = print_buffer(first, last, " OPEN ");
else
first = print_buffer(first, last, " ");
@@ -258,12 +224,14 @@ print_download_info_compact(char* first, char* last, core::Download* d) {
first = print_buffer(first, last, "| %7.1f MB ", (double)d->info()->up_rate()->total() / (1 << 20));
first = print_buffer(first, last, "| ");
if (d->download()->info()->is_active() && !d->is_done())
if (d->download()->info()->is_active() && !d->is_done()) {
first = print_download_time_left(first, last, d);
else
first = print_buffer(first, last, " ");
first = print_buffer(first, last, " ");
} else {
first = print_buffer(first, last, " ");
}
first = print_buffer(first, last, "| %4.2f ", (double)rpc::call_command_value("d.ratio", rpc::make_target(d)) / 1000.0);
first = print_buffer(first, last, "| %5.2f ", (double)rpc::call_command_value("d.ratio", rpc::make_target(d)) / 1000.0);
first = print_buffer(first, last, "| %c%c",
rpc::call_command_string("d.tied_to_file", rpc::make_target(d)).empty() ? ' ' : 'T',
rpc::call_command_value("d.ignore_commands", rpc::make_target(d)) == 0 ? ' ' : 'I',
+23 -49
View File
@@ -1,70 +1,34 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <stdexcept>
#include "window.h"
#include <stdexcept>
namespace display {
Window::SlotTimer Window::m_slotSchedule;
Window::SlotWindow Window::m_slotUnschedule;
Window::Slot Window::m_slotAdjust;
Window::SlotTimer Window::m_slot_schedule;
Window::SlotWindow Window::m_slot_unschedule;
Window::Slot Window::m_slot_adjust;
// When constructing the window we set flag_offscreen so that redraw
// doesn't get triggered until after a successful Frame::balance call.
Window::Window(Canvas* canvas, int flags, extent_type minWidth, extent_type minHeight, extent_type maxWidth, extent_type maxHeight) :
Window::Window(Canvas* canvas, int flags, extent_type min_width, extent_type min_height, extent_type max_width, extent_type max_height) :
m_canvas(canvas),
m_flags(flags | flag_offscreen),
m_minWidth(minWidth),
m_minHeight(minHeight),
m_min_width(min_width),
m_min_height(min_height),
m_maxWidth(maxWidth),
m_maxHeight(maxHeight) {
m_max_width(max_width),
m_max_height(max_height) {
m_taskUpdate.slot() = std::bind(&Window::redraw, this);
m_task_update.slot() = [this] { redraw(); };
}
Window::~Window() {
if (is_active())
m_slotUnschedule(this);
m_slot_unschedule(this);
delete m_canvas;
}
@@ -82,7 +46,7 @@ Window::set_active(bool state) {
} else {
m_flags &= ~flag_active;
m_slotUnschedule(this);
m_slot_unschedule(this);
}
}
@@ -97,4 +61,14 @@ Window::resize(int x, int y, int w, int h) {
m_canvas->resize(x, y, w, h);
}
void
Window::schedule_update(unsigned int wait_seconds) {
if (wait_seconds == 0) {
m_slot_schedule(this, torrent::utils::ceil_seconds(torrent::this_thread::cached_time() + 100ms));
return;
}
m_slot_schedule(this, torrent::utils::ceil_seconds(torrent::this_thread::cached_time() + 1s*wait_seconds));
}
}
+28 -62
View File
@@ -1,44 +1,9 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_WINDOW_BASE_H
#define RTORRENT_WINDOW_BASE_H
#include <rak/timer.h>
#include <rak/functional.h>
#include <functional>
#include <torrent/utils/scheduler.h>
#include <torrent/utils/thread.h>
#include "canvas.h"
#include "globals.h"
@@ -46,15 +11,14 @@
namespace display {
class Canvas;
class Manager;
class Window {
public:
typedef uint32_t extent_type;
typedef rak::mem_fun0<Manager, void> Slot;
typedef rak::mem_fun1<Manager, void, Window*> SlotWindow;
typedef rak::mem_fun2<Manager, void, Window*, rak::timer> SlotTimer;
typedef std::function<void()> Slot;
typedef std::function<void(Window*)> SlotWindow;
typedef std::function<void(Window*, std::chrono::microseconds)> SlotTimer;
static const int flag_active = (1 << 0);
static const int flag_offscreen = (1 << 1);
@@ -86,19 +50,19 @@ public:
bool is_bottom() const { return m_flags & flag_bottom; }
void set_bottom(bool state) { if (state) m_flags |= flag_bottom; else m_flags &= ~flag_bottom; }
bool is_width_dynamic() const { return m_maxWidth > m_minWidth; }
bool is_height_dynamic() const { return m_maxHeight > m_minHeight; }
bool is_width_dynamic() const { return m_max_width > m_min_width; }
bool is_height_dynamic() const { return m_max_height > m_min_height; }
// Do not call mark_dirty() from withing redraw() as it may cause
// infinite looping in the display scheduler.
bool is_dirty() { return m_taskUpdate.is_queued(); }
void mark_dirty() { if (!is_active()) return; m_slotSchedule(this, cachedTime); }
bool is_dirty() { return m_task_update.is_scheduled(); }
void mark_dirty() { if (!is_active()) return; m_slot_schedule(this, torrent::this_thread::cached_time()); }
extent_type min_width() const { return m_minWidth; }
extent_type min_height() const { return m_minHeight; }
extent_type min_width() const { return m_min_width; }
extent_type min_height() const { return m_min_height; }
extent_type max_width() const { return std::max(m_maxWidth, m_minWidth); }
extent_type max_height() const { return std::max(m_maxHeight, m_minHeight); }
extent_type max_width() const { return std::max(m_max_width, m_min_width); }
extent_type max_height() const { return std::max(m_max_height, m_min_height); }
extent_type width() const { return m_canvas->width(); }
extent_type height() const { return m_canvas->height(); }
@@ -108,32 +72,34 @@ public:
virtual void redraw() = 0;
rak::priority_item* task_update() { return &m_taskUpdate; }
auto task_update() { return &m_task_update; }
// Slot for adjust and refresh.
static void slot_schedule(SlotTimer s) { m_slotSchedule = s; }
static void slot_unschedule(SlotWindow s) { m_slotUnschedule = s; }
static void slot_adjust(Slot s) { m_slotAdjust = s; }
static void slot_schedule(SlotTimer s) { m_slot_schedule = s; }
static void slot_unschedule(SlotWindow s) { m_slot_unschedule = s; }
static void slot_adjust(Slot s) { m_slot_adjust = s; }
protected:
Window(const Window&);
void operator = (const Window&);
static SlotTimer m_slotSchedule;
static SlotWindow m_slotUnschedule;
static Slot m_slotAdjust;
void schedule_update(unsigned int wait_seconds = 0);
static SlotTimer m_slot_schedule;
static SlotWindow m_slot_unschedule;
static Slot m_slot_adjust;
Canvas* m_canvas;
int m_flags;
extent_type m_minWidth;
extent_type m_minHeight;
extent_type m_min_width;
extent_type m_min_height;
extent_type m_maxWidth;
extent_type m_maxHeight;
extent_type m_max_width;
extent_type m_max_height;
rak::priority_item m_taskUpdate;
torrent::utils::SchedulerEntry m_task_update;
};
}
+4 -41
View File
@@ -1,44 +1,7 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <cmath>
#include <stdexcept>
#include <rak/functional.h>
#include <rak/string_manip.h>
#include <torrent/bitfield.h>
#include <torrent/data/block.h>
@@ -60,7 +23,7 @@ WindowDownloadChunksSeen::WindowDownloadChunksSeen(core::Download* d, unsigned i
void
WindowDownloadChunksSeen::redraw() {
// TODO: Make this depend on tracker signal.
m_slotSchedule(this, (cachedTime + rak::timer::from_seconds(10)).round_seconds());
schedule_update(10);
m_canvas->erase();
if (m_canvas->height() < 3 || m_canvas->width() < 18)
@@ -78,7 +41,7 @@ WindowDownloadChunksSeen::redraw() {
return;
}
if (!m_download->is_done()) {
if (!m_download->is_done()) {
m_canvas->print(36, 0, "X downloaded missing queued downloading");
m_canvas->print_char(50, 0, 'X' | A_BOLD);
m_canvas->print_char(61, 0, 'X' | A_BOLD | A_UNDERLINE);
@@ -95,7 +58,7 @@ WindowDownloadChunksSeen::redraw() {
std::vector<torrent::BlockList*> transferChunks(transfers->size(), 0);
std::copy(transfers->begin(), transfers->end(), transferChunks.begin());
std::sort(transferChunks.begin(), transferChunks.end(), rak::less2(std::mem_fun(&torrent::BlockList::index), std::mem_fun(&torrent::BlockList::index)));
std::sort(transferChunks.begin(), transferChunks.end());
std::vector<torrent::BlockList*>::const_iterator itrTransfer = transferChunks.begin();
@@ -111,7 +74,7 @@ WindowDownloadChunksSeen::redraw() {
if (bitfield->get(chunk - seen)) {
attr = A_NORMAL;
} else if (itrTransfer != transferChunks.end() && (uint32_t)(chunk - seen) == (*itrTransfer)->index()) {
if (std::find_if((*itrTransfer)->begin(), (*itrTransfer)->end(), std::mem_fun_ref(&torrent::Block::is_transfering)) != (*itrTransfer)->end())
if (std::any_of((*itrTransfer)->begin(), (*itrTransfer)->end(), std::mem_fn(&torrent::Block::is_transfering)))
attr = A_REVERSE;
else
attr = A_BOLD | A_UNDERLINE;
-36
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_DISPLAY_WINDOW_DOWNLOAD_CHUNKS_SEEN_H
#define RTORRENT_DISPLAY_WINDOW_DOWNLOAD_CHUNKS_SEEN_H
+74 -66
View File
@@ -1,41 +1,6 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include "display/color_map.h"
#include <rak/algorithm.h>
#include "core/download.h"
@@ -50,14 +15,13 @@
namespace display {
WindowDownloadList::WindowDownloadList() :
Window(new Canvas, 0, 120, 1, extent_full, extent_full),
m_view(NULL) {
Window(new Canvas, 0, 120, 1, extent_full, extent_full) {
}
WindowDownloadList::~WindowDownloadList() {
if (m_view != NULL)
m_view->signal_changed().erase(m_changed_itr);
m_view = NULL;
}
@@ -72,9 +36,48 @@ WindowDownloadList::set_view(core::View* l) {
m_changed_itr = m_view->signal_changed().insert(m_view->signal_changed().begin(), std::bind(&Window::mark_dirty, this));
}
// Return a pair of ints, representing a) the ncurses attributes and b) the ncurses color pair ID to use
std::pair<int, int>
WindowDownloadList::get_attr_color(core::View::iterator selected) {
core::Download* item = *selected;
unsigned long focus_attr = selected == m_view->focus() ? m_canvas->attr_map().at(RCOLOR_FOCUS) : 0;
int offset = (((selected - m_view->begin_visible()) & 1) + 1) * RCOLOR_MAX; // Determine the even/odd offset for the color pair
bool active = item->is_open() && item->is_active();
int title_color;
if (item->is_done())
title_color = (active ? item->info()->up_rate()->rate() ? RCOLOR_SEEDING : RCOLOR_COMPLETE : RCOLOR_STOPPED) + offset;
else
title_color = (active ? item->info()->down_rate()->rate() ? RCOLOR_LEECHING : RCOLOR_INCOMPLETE : RCOLOR_QUEUED) + offset;
return std::make_pair(m_canvas->attr_map().at(title_color) | focus_attr, title_color);
}
int
WindowDownloadList::page_size(const std::string layout_name) {
// Calculate the page size for torrents. This is a public method
// because it's also used to determine the default size for page
// up/down actions.
int layout_height;
if (layout_name == "full") {
layout_height = 3;
} else if (layout_name == "compact") {
layout_height = 1;
} else {
return 0;
}
return m_canvas->height() / layout_height;
}
int
WindowDownloadList::page_size() {
return page_size(rpc::call_command_string("ui.torrent_list.layout"));
}
void
WindowDownloadList::redraw() {
m_slotSchedule(this, (cachedTime + rak::timer::from_seconds(1)).round_seconds());
if (m_canvas->daemon())
return;
schedule_update();
m_canvas->erase();
@@ -95,24 +98,16 @@ WindowDownloadList::redraw() {
m_canvas->print(m_canvas->width() - 16, 0, "[%5d of %-5d]", item_idx + 1, m_view->size());
}
int layout_height;
const std::string layout_name = rpc::call_command_string("ui.torrent_list.layout");
m_canvas->set_attr(0, 0, -1, RCOLOR_TITLE);
if (layout_name == "full") {
layout_height = 3;
} else if (layout_name == "compact") {
layout_height = 1;
} else {
m_canvas->print(0, 0, "INVALID ui.torrent_list.layout '%s'", layout_name.c_str());
return;
}
const std::string layout_name = rpc::call_command_string("ui.torrent_list.layout");
typedef std::pair<core::View::iterator, core::View::iterator> Range;
Range range = rak::advance_bidirectional(m_view->begin_visible(),
m_view->focus() != m_view->end_visible() ? m_view->focus() : m_view->begin_visible(),
m_view->end_visible(),
m_canvas->height() / layout_height);
page_size(layout_name));
// Make sure we properly fill out the last lines so it looks like
// there are more torrents, yet don't hide it if we got the last one
@@ -120,39 +115,52 @@ WindowDownloadList::redraw() {
if (range.second != m_view->end_visible())
++range.second;
int pos = 1;
char buffer[m_canvas->width() + 1];
char* last = buffer + m_canvas->width() - 2 + 1;
int pos = 1;
std::string buffer(m_canvas->width() + 1, ' ');
char* last = buffer.data() + m_canvas->width() - 2 + 1;
// Add a proper 'column info' method.
if (layout_name == "compact") {
print_download_column_compact(buffer, last);
print_download_column_compact(buffer.data(), last);
m_canvas->set_default_attributes(A_BOLD);
m_canvas->print(0, pos++, " %s", buffer);
m_canvas->print(0, pos++, " %s", buffer.data());
}
if (layout_name == "full") {
while (range.first != range.second) {
print_download_title(buffer, last, *range.first);
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
print_download_info_full(buffer, last, *range.first);
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
print_download_status(buffer, last, *range.first);
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
bool is_focused = range.first == m_view->focus();
char focus_char = is_focused ? '*' : ' ';
ColorKind focus_color = is_focused ? RCOLOR_FOCUS : RCOLOR_LABEL;
auto attr_color = get_attr_color(range.first);
print_download_title(buffer.data(), last, *range.first);
m_canvas->print(0, pos, "%c %s", focus_char, buffer.data());
m_canvas->set_attr(2, pos++, -1, attr_color.first, attr_color.second);
print_download_info_full(buffer.data(), last, *range.first);
m_canvas->print(0, pos, "%c %s", focus_char, buffer.data());
m_canvas->set_attr(2, pos++, -1, focus_color);
print_download_status(buffer.data(), last, *range.first);
m_canvas->print(0, pos, "%c %s", focus_char, buffer.data());
m_canvas->set_attr(2, pos++, -1, focus_color);
range.first++;
}
} else {
while (range.first != range.second) {
print_download_info_compact(buffer, last, *range.first);
m_canvas->set_default_attributes(range.first == m_view->focus() ? A_REVERSE : A_NORMAL);
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
char focus_char = range.first == m_view->focus() ? '*' : ' ';
auto attr_color = get_attr_color(range.first);
print_download_info_compact(buffer.data(), last, *range.first);
m_canvas->print(0, pos, "%c %s", focus_char, buffer.data());
m_canvas->set_attr(2, pos++, -1, attr_color.first, attr_color.second);
range.first++;
}
}
}
}
} // namespace display
+7 -38
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_DISPLAY_WINDOW_DOWNLOAD_LIST_H
#define RTORRENT_DISPLAY_WINDOW_DOWNLOAD_LIST_H
@@ -47,6 +11,7 @@ namespace display {
class WindowDownloadList : public Window {
public:
typedef core::View::signal_void::iterator signal_void_itr;
typedef std::pair<core::View::iterator, core::View::iterator> ViewRange;
WindowDownloadList();
~WindowDownloadList();
@@ -55,9 +20,13 @@ public:
void set_view(core::View* l);
private:
core::View* m_view;
int page_size(const std::string layout_name);
int page_size();
private:
core::View* m_view{};
std::pair<int, int> get_attr_color(core::View::iterator selected);
signal_void_itr m_changed_itr;
};
+16 -51
View File
@@ -1,53 +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 "window_download_statusbar.h"
#include <torrent/rate.h>
#include <torrent/data/transfer_list.h>
#include <torrent/tracker_controller.h>
#include <torrent/tracker_list.h>
#include <torrent/peer/connection_list.h>
#include <torrent/peer/peer_list.h>
#include "canvas.h"
#include "globals.h"
#include "utils.h"
#include "window_download_statusbar.h"
#include "core/download.h"
namespace display {
@@ -59,17 +21,20 @@ WindowDownloadStatusbar::WindowDownloadStatusbar(core::Download* d) :
void
WindowDownloadStatusbar::redraw() {
m_slotSchedule(this, (cachedTime + rak::timer::from_seconds(1)).round_seconds());
if (m_canvas->daemon())
return;
schedule_update();
m_canvas->erase();
char buffer[m_canvas->width()];
char* last = buffer + m_canvas->width() - 2;
std::string buffer(m_canvas->width(), ' ');
char* last = buffer.data() + m_canvas->width() - 2;
print_download_info_full(buffer, last, m_download);
m_canvas->print(0, 0, "%s", buffer);
print_download_info_full(buffer.data(), last, m_download);
m_canvas->print(0, 0, "%s", buffer.data());
snprintf(buffer, last - buffer, "Peers: %i(%i) Min/Max: %i/%i Slots: U:%i/%i D:%i/%i U/I/C/A: %i/%i/%i/%i Unchoked: %u/%u Failed: %i",
snprintf(buffer.data(), last - buffer.data(), "Peers: %i(%i) Min/Max: %i/%i Slots: U:%i/%i D:%i/%i U/I/C/A: %i/%i/%i/%i Unchoked: %u/%u Failed: %i",
(int)m_download->download()->connection_list()->size(),
(int)m_download->download()->peer_list()->available_list_size(),
(int)m_download->download()->connection_list()->min_size(),
@@ -86,13 +51,13 @@ WindowDownloadStatusbar::redraw() {
(int)m_download->info()->download_unchoked(),
(int)m_download->download()->transfer_list()->failed_count());
m_canvas->print(0, 1, "%s", buffer);
m_canvas->print(0, 1, "%s", buffer.data());
print_download_status(buffer, last, m_download);
print_download_status(buffer.data(), last, m_download);
m_canvas->print(0, 2, "[%c:%i] %s",
m_download->tracker_list()->has_active() ? 'C' : ' ',
(int)(m_download->download()->tracker_controller()->seconds_to_next_timeout()),
buffer);
m_download->tracker_controller().has_active_trackers() ? 'C' : ' ',
(int)(m_download->download()->tracker_controller().seconds_to_next_timeout()),
buffer.data());
}
}

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