mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-08-05 17:52:29 +00:00
Compare commits
331 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 24693fc19e | |||
| 9661a2aaa9 | |||
| aaf42c247e | |||
| cba48f4a10 | |||
| 4463bf418e | |||
| 8bd7c79755 | |||
| f2b83d50e8 | |||
| ab40059891 | |||
| b9d880dea3 | |||
| b4c59d2c7a | |||
| 231606afc1 | |||
| a9196b43d4 | |||
| 8203949259 | |||
| 537c692f47 | |||
| 95b1a19ef1 | |||
| a4ab0112dc | |||
| 897a6face2 | |||
| 3ab38583b8 | |||
| 1003013f10 | |||
| 7bbd9a02a0 | |||
| f0809ec29d | |||
| e8c1f3ed2c | |||
| 3618b9dc4f | |||
| df8cb53ed2 | |||
| 2d565d1c80 | |||
| de6c48ca3f | |||
| 5fb61b2857 | |||
| 46e94259e8 | |||
| 9ff373fe58 | |||
| 6d888c008d | |||
| 9fe4d188e9 | |||
| 9d5b769d78 | |||
| 55615abe9e | |||
| 303edab9ec | |||
| 877c00d54e | |||
| 4c63cee7a2 | |||
| 58a74cee48 | |||
| 85e74b5542 | |||
| 6f8c1246dc | |||
| 97415c656b | |||
| 3d9c083032 | |||
| dd221ac66a | |||
| 25f729fab5 | |||
| 316b0b51d5 | |||
| a8622e5c80 | |||
| d1dd5ac080 | |||
| 9f2b81534a | |||
| 2ab7460cbc | |||
| 2a998df4f1 | |||
| d5b28c30a9 | |||
| a5a1e2fde5 | |||
| 34bc18940a | |||
| cde78f2353 | |||
| cc59125116 | |||
| 8ac31afd06 | |||
| 8d991b4ce5 | |||
| 3a227c190f | |||
| 9a2ce2b231 | |||
| f33fc331ce | |||
| 47af28aecd | |||
| c6ebdf876a | |||
| 5797ed9e7a | |||
| 9465c94b31 | |||
| 0adfc17335 | |||
| 37a5b7bccb | |||
| 80ef2e076d | |||
| 4ac7313ff1 | |||
| 6139217033 | |||
| 89b35af7a6 | |||
| 851ac469c3 | |||
| 1811248691 | |||
| bacf60af89 | |||
| 1f01b7e94d | |||
| d514e525ca | |||
| b2b723f248 | |||
| e3ab913f9a | |||
| 787e23a25d | |||
| 9f48226663 | |||
| 78915746ee | |||
| e7fc891f11 | |||
| 2e0a417367 | |||
| b5a6ee33a1 | |||
| 3378355b64 | |||
| 6f5d06907b | |||
| 712e7e5db0 | |||
| 2b73c92a3e | |||
| c5563d65c5 | |||
| d412caea66 | |||
| 9c92bfc7e2 | |||
| 4a074adc7b | |||
| 3bf494dbc6 | |||
| b193fedc65 | |||
| 6c5a6a3bb3 | |||
| 7534b02815 | |||
| 6d8c214d09 | |||
| 525b038dbb | |||
| 06741a7578 | |||
| 4cc79590be | |||
| 452397b8af | |||
| c9a8a1e35c | |||
| 8f77d87994 | |||
| 842edaa201 | |||
| 4876301cf4 | |||
| c2c6a4be26 | |||
| 350d03ca04 | |||
| 31602917b7 | |||
| a9898c6ef6 | |||
| 2bf81aa8f5 | |||
| a9c0b65b9d | |||
| 73fed24459 | |||
| f906e9a966 | |||
| 090b3889ce | |||
| 68fdb86c72 | |||
| 6b8a285e75 | |||
| 8f0331625a | |||
| 3c65afcf8c | |||
| cd9948a4a8 | |||
| 0d1b9e9d55 | |||
| 6561c00ae3 | |||
| b8cb828d96 | |||
| e3be3b2c12 | |||
| 0f93fa109c | |||
| 7e1193acab | |||
| 5792ed1ae2 | |||
| 8cfc71b936 | |||
| f2b065a798 | |||
| f33c2560a3 | |||
| db1e78fa9d | |||
| 48c40ee0c6 | |||
| 3aeb213dc4 | |||
| 5a200f5d8f | |||
| 713067ba94 | |||
| fea2cbfac6 | |||
| 6bf1731a1c | |||
| f2caa2651d | |||
| 511895a8b6 | |||
| 4e64fbc78b | |||
| 93b3a34f28 | |||
| ea1ca00f31 | |||
| 58b1fc4914 | |||
| 577818bde4 | |||
| 0ea7615d0a | |||
| 73c1233dc0 | |||
| 11ddc35d02 | |||
| 036916fd9f | |||
| b3fabd2a2b | |||
| 4b7c3ffafe | |||
| 730d43b6c7 | |||
| af2f30c183 | |||
| 36fd837d27 | |||
| 8dd8d691c5 | |||
| e367b162ab | |||
| 49cdfee65a | |||
| 5680db3598 | |||
| 4768eb8356 | |||
| fa2c7d961b | |||
| d6dcbc4a69 | |||
| cadfcb50d2 | |||
| 71a39cd8a0 | |||
| 0658486966 | |||
| 687fbbb83d | |||
| e355eb561f | |||
| 902de0b258 | |||
| 01e5df4167 | |||
| 8d85ce5857 | |||
| f9c9fa2e3b | |||
| 337897784d | |||
| 782b1e4ea8 | |||
| 3cfc213053 | |||
| b789d83b70 | |||
| 67babb65d6 | |||
| e0d5c95821 | |||
| 7f4c5df5ee | |||
| dd45684584 | |||
| fb8632e990 | |||
| b043b7b39e | |||
| 168093d256 | |||
| 0c2f0b7715 | |||
| 4a9d9952e1 | |||
| fd1d5dbdb2 | |||
| dd0c62c7f7 | |||
| 3a8e462bd3 | |||
| b360a734f1 | |||
| c18df7a366 | |||
| a269f808e1 | |||
| 4444df2e97 | |||
| 5a194ab037 | |||
| 1b43f8b591 | |||
| d6427203a4 | |||
| 87c6422052 | |||
| 6ab265ecd4 | |||
| 203c66a287 | |||
| c9fe2facfa | |||
| 5abcf52e55 | |||
| f2f84dd97a | |||
| 34de2b4ac9 | |||
| ef937863fd | |||
| 00fa4127e1 | |||
| 1b0cb722e6 | |||
| af23ca8032 | |||
| c85f9d6318 | |||
| ee120730cc | |||
| b284be6a66 | |||
| 6e976616a0 | |||
| 38b39bdafc | |||
| 48718bdac8 | |||
| 5ce84929e4 | |||
| c1d076f182 | |||
| f929594763 | |||
| a88cab6d2e | |||
| 9a93281ded | |||
| 133ce36570 | |||
| a142301d02 | |||
| f04e512887 | |||
| d32d59315d | |||
| 86e85ae485 | |||
| 6e9902c23b | |||
| d4427931a2 | |||
| ea3828a17e | |||
| 4e246a401f | |||
| eacf9798e2 | |||
| 892e595015 | |||
| 1da0e3476d | |||
| c0a5a55444 | |||
| 551712f842 | |||
| c7c290a86b | |||
| 2e1a499942 | |||
| c86f0d0333 | |||
| 92bec88d09 | |||
| d067bd802e | |||
| 50924eeda0 | |||
| 1e40014482 | |||
| 8cafb55881 | |||
| a6bc99bb82 | |||
| 52ceb39ca3 | |||
| 926893ee62 | |||
| cf13789f8c | |||
| d15d93be88 | |||
| 582e4e4025 | |||
| 952777d75e | |||
| 19dbaa7442 | |||
| 3f72e27603 | |||
| e267e8bc07 | |||
| 79765768ff | |||
| 8cc1d8f2c5 | |||
| 3798de01a0 | |||
| 8ac98c6d3a | |||
| 81500adc53 | |||
| 14d7121185 | |||
| 7659cd0ec0 | |||
| f43f9e430d | |||
| f22475d1bf | |||
| b697a4608b | |||
| 765665fc28 | |||
| 5f70986099 | |||
| 6154d16987 | |||
| a5e8631cba | |||
| 07dcd04357 | |||
| 863de44c18 | |||
| 24135ed48e | |||
| 83709d28c9 | |||
| 859d5a9578 | |||
| adc9b1dec5 | |||
| 285972a20d | |||
| 3ec2f52db5 | |||
| ac64fc3f63 | |||
| b26dc42f3a | |||
| 6572088aec | |||
| 31a0ea1a2d | |||
| 2d72a0d2c0 | |||
| a3a384b049 | |||
| f37dd0d5c2 | |||
| 78c25011cd | |||
| 35d98c91e0 | |||
| 27811db659 | |||
| 4e73ce6bfd | |||
| 8c8e73bb72 | |||
| 0d5b344d2a | |||
| 703cac9a42 | |||
| e6c008b2b7 | |||
| 81de60e0ae | |||
| c361d6010e | |||
| 724dc088ca | |||
| c62fa6a756 | |||
| 656d735de7 | |||
| 408013478c | |||
| fa61b8c11c | |||
| 1339a3ace9 | |||
| 4ba128163f | |||
| 908a99751f | |||
| c115640934 | |||
| 9043c46815 | |||
| 1f418366d4 | |||
| 30c78c7034 | |||
| 74435f6c40 | |||
| a4b281afa4 | |||
| f84670dd63 | |||
| f0207ce654 | |||
| 9cce5a0bd1 | |||
| 95cff549c6 | |||
| 92898a9831 | |||
| fcfbf0e79f | |||
| 680b47c197 | |||
| 7804ed3009 | |||
| d9b39f5ac6 | |||
| 08aa287cfc | |||
| 851d1902a0 | |||
| b600ff0c0e | |||
| a639461c4a | |||
| c1057d5ac7 | |||
| 2ac65ad7e1 | |||
| a4939cb9fd | |||
| 3d88ac2cc8 | |||
| f37fefcc54 | |||
| 885836f68b | |||
| ca4c3bee8d | |||
| 6c278668e4 | |||
| 1665437588 | |||
| 6dc87e499a | |||
| 6c11a1dbb0 | |||
| 29d57e858a | |||
| 7ec9b6685b | |||
| d5de8a91d1 | |||
| 4d6f6fe335 | |||
| 13676f06e5 | |||
| 6cb176ada3 | |||
| 8b6a1ad079 | |||
| 3002c95b2c | |||
| 9590949fa7 | |||
| 6ee61ee6b5 | |||
| e15270271d |
@@ -0,0 +1,33 @@
|
||||
---
|
||||
BasedOnStyle: LLVM
|
||||
Standard: c++14
|
||||
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AlwaysBreakAfterReturnType: TopLevelDefinitions
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BreakConstructorInitializers: AfterColon
|
||||
BreakStringLiterals: false
|
||||
ColumnLimit: 0
|
||||
ContinuationIndentWidth: 2
|
||||
IndentCaseLabels: false
|
||||
IndentWidth: 2
|
||||
PenaltyReturnTypeOnItsOwnLine: 130
|
||||
PointerAlignment: Left
|
||||
|
||||
AlignEscapedNewlines: Right
|
||||
AlignConsecutiveDeclarations:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: true
|
||||
AcrossComments: false
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: true
|
||||
AlignConsecutiveAssignments:
|
||||
Enabled: true
|
||||
|
||||
IncludeCategories:
|
||||
- Regex: "^(config|globals)\\.h"
|
||||
Priority: -1
|
||||
- Regex: "^torrent/.*"
|
||||
Priority: 1
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
---
|
||||
Checks: '-*,readability-identifier-naming'
|
||||
FormatStyle: 'file'
|
||||
CheckOptions:
|
||||
- key: readability-identifier-naming.LocalVariableCase
|
||||
value: lower_case
|
||||
- key: readability-identifier-naming.ParameterCase
|
||||
value: lower_case
|
||||
- key: readability-identifier-naming.FunctionCase
|
||||
value: lower_case
|
||||
- key: readability-identifier-naming.PrivateMemberPrefix
|
||||
value: m_
|
||||
- key: readability-identifier-naming.PrivateMemberCase
|
||||
value: lower_case
|
||||
- key: readability-identifier-naming.ClassConstantCase
|
||||
value: lower_case
|
||||
@@ -0,0 +1,7 @@
|
||||
;;; Directory Local Variables
|
||||
;;; For more information see (info "(emacs) Directory Variables")
|
||||
|
||||
((c++-mode
|
||||
(flycheck-clang-language-standard . "c++11")
|
||||
(flycheck-gcc-language-standard . "c++11")))
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [rakshasa]
|
||||
patreon: rtorrent
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||
custom: ['https://rakshasa.github.io/rtorrent/donate.html']
|
||||
@@ -0,0 +1,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 }}
|
||||
@@ -0,0 +1,82 @@
|
||||
name: Static analysis
|
||||
|
||||
on: pull_request
|
||||
|
||||
jobs:
|
||||
|
||||
clang-tidy:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Update Packages
|
||||
run: |
|
||||
sudo apt-get update
|
||||
- name: Fetch libtorrent
|
||||
run: |
|
||||
git clone https://github.com/rakshasa/libtorrent
|
||||
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 bear clang-tidy libcurl4-openssl-dev
|
||||
- name: Configure Project
|
||||
run: |
|
||||
libtoolize
|
||||
aclocal -I scripts
|
||||
autoconf -i
|
||||
autoheader
|
||||
automake --add-missing
|
||||
./configure
|
||||
- name: Prepare compile_commands.json
|
||||
run: |
|
||||
bear -- make
|
||||
- name: Create results directory
|
||||
run: |
|
||||
mkdir clang-tidy-result
|
||||
- name: Analyze
|
||||
run: |
|
||||
git diff -U0 "$(git merge-base HEAD "upstream/${{ github.event.pull_request.base.ref }}")" | clang-tidy-diff -p1 -path build -export-fixes clang-tidy-result/fixes.yml "-extra-arg=-include/${PWD}/config.h"
|
||||
- name: Save PR metadata
|
||||
run: |
|
||||
echo "${{ github.event.number }}" > clang-tidy-result/pr-id.txt
|
||||
echo "${{ github.event.pull_request.head.repo.full_name }}" > clang-tidy-result/pr-head-repo.txt
|
||||
echo "${{ github.event.pull_request.head.sha }}" > clang-tidy-result/pr-head-sha.txt
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: clang-tidy-result
|
||||
path: clang-tidy-result/
|
||||
# - name: Run clang-tidy-pr-comments action
|
||||
# uses: platisd/clang-tidy-pr-comments@v1
|
||||
# with:
|
||||
# # The GitHub token (or a personal access token)
|
||||
# github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# # The path to the clang-tidy fixes generated previously
|
||||
# clang_tidy_fixes: clang-tidy-result/fixes.yml
|
||||
# # Optionally set to true if you want the Action to request
|
||||
# # changes in case warnings are found
|
||||
# request_changes: true
|
||||
# # Optionally set the number of comments per review
|
||||
# # to avoid GitHub API timeouts for heavily loaded
|
||||
# # pull requests
|
||||
# suggestions_per_comment: 10
|
||||
@@ -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
@@ -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
|
||||
|
||||
+14
-3
@@ -1,5 +1,9 @@
|
||||
language: cpp
|
||||
|
||||
env:
|
||||
global:
|
||||
- MAKEFLAGS="-j 12"
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- compiler: clang
|
||||
@@ -67,8 +71,15 @@ matrix:
|
||||
# TODO: Use the same branch name if libtorrent has it.
|
||||
before_install:
|
||||
- git clone https://github.com/rakshasa/libtorrent.git
|
||||
- cd libtorrent && ./autogen.sh && CXX="$COMPILER" ./configure && make -j12 && sudo make install
|
||||
- |
|
||||
pushd libtorrent \
|
||||
&& (git checkout ${TRAVIS_BRANCH} || true) \
|
||||
&& ./autogen.sh \
|
||||
&& CXX="$COMPILER" ./configure --prefix=/usr \
|
||||
&& make \
|
||||
&& sudo make install \
|
||||
&& popd
|
||||
|
||||
script:
|
||||
- ./autogen.sh && CXX="$COMPILER" ./configure && make -j12
|
||||
- if [ ! $SKIP_CHECK ]; then make -j12 check; fi
|
||||
- ./autogen.sh && CXX="$COMPILER" ./configure && make
|
||||
- if [ ! $SKIP_CHECK ]; then make check; fi
|
||||
|
||||
@@ -1,81 +1,109 @@
|
||||
Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
|
||||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This file is free documentation; the Free Software Foundation gives
|
||||
unlimited permission to copy, distribute and modify it.
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved. This file is offered as-is,
|
||||
without warranty of any kind.
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
These are generic installation instructions.
|
||||
Briefly, the shell command './configure && make && make install'
|
||||
should configure, build, and install this package. The following
|
||||
more-detailed instructions are generic; see the 'README' file for
|
||||
instructions specific to this package. Some packages provide this
|
||||
'INSTALL' file but do not implement all of the features documented
|
||||
below. The lack of an optional feature in a given package is not
|
||||
necessarily a bug. More recommendations for GNU packages can be found
|
||||
in *note Makefile Conventions: (standards)Makefile Conventions.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
The 'configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
those values to create a 'Makefile' in each directory of the package.
|
||||
It may also create one or more '.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script 'config.status' that
|
||||
you can run in the future to recreate the current configuration, and a
|
||||
file `config.log' containing compiler output (useful mainly for
|
||||
debugging `configure').
|
||||
file 'config.log' containing compiler output (useful mainly for
|
||||
debugging 'configure').
|
||||
|
||||
It can also use an optional file (typically called `config.cache'
|
||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||
the results of its tests to speed up reconfiguring. (Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.)
|
||||
It can also use an optional file (typically called 'config.cache' and
|
||||
enabled with '--cache-file=config.cache' or simply '-C') that saves the
|
||||
results of its tests to speed up reconfiguring. Caching is disabled by
|
||||
default to prevent problems with accidental use of stale cache files.
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
to figure out how 'configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the 'README' so they can
|
||||
be considered for the next release. If you are using the cache, and at
|
||||
some point `config.cache' contains results you don't want to keep, you
|
||||
some point 'config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file `configure.ac' (or `configure.in') is used to create
|
||||
`configure' by a program called `autoconf'. You only need
|
||||
`configure.ac' if you want to change it or regenerate `configure' using
|
||||
a newer version of `autoconf'.
|
||||
The file 'configure.ac' (or 'configure.in') is used to create
|
||||
'configure' by a program called 'autoconf'. You need 'configure.ac' if
|
||||
you want to change it or regenerate 'configure' using a newer version of
|
||||
'autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system. If you're
|
||||
using `csh' on an old version of System V, you might need to type
|
||||
`sh ./configure' instead to prevent `csh' from trying to execute
|
||||
`configure' itself.
|
||||
1. 'cd' to the directory containing the package's source code and type
|
||||
'./configure' to configure the package for your system.
|
||||
|
||||
Running `configure' takes awhile. While running, it prints some
|
||||
messages telling which features it is checking for.
|
||||
Running 'configure' might take a while. While running, it prints
|
||||
some messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
2. Type 'make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
the package.
|
||||
3. Optionally, type 'make check' to run any self-tests that come with
|
||||
the package, generally using the just-built uninstalled binaries.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation.
|
||||
4. Type 'make install' to install the programs and any data files and
|
||||
documentation. When installing into a prefix owned by root, it is
|
||||
recommended that the package be configured and built as a regular
|
||||
user, and only the 'make install' phase executed with root
|
||||
privileges.
|
||||
|
||||
5. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
also a `make maintainer-clean' target, but that is intended mainly
|
||||
5. Optionally, type 'make installcheck' to repeat any self-tests, but
|
||||
this time using the binaries in their final installed location.
|
||||
This target does not install anything. Running this target as a
|
||||
regular user, particularly if the prior 'make install' required
|
||||
root privileges, verifies that the installation completed
|
||||
correctly.
|
||||
|
||||
6. You can remove the program binaries and object files from the
|
||||
source code directory by typing 'make clean'. To also remove the
|
||||
files that 'configure' created (so you can compile the package for
|
||||
a different kind of computer), type 'make distclean'. There is
|
||||
also a 'make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
7. Often, you can also type 'make uninstall' to remove the installed
|
||||
files again. In practice, not all packages have tested that
|
||||
uninstallation works correctly, even though it is required by the
|
||||
GNU Coding Standards.
|
||||
|
||||
8. Some packages, particularly those that use Automake, provide 'make
|
||||
distcheck', which can by used by developers to test that all other
|
||||
targets like 'make install' and 'make uninstall' work correctly.
|
||||
This target is generally not run by end users.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that
|
||||
the `configure' script does not know about. Run `./configure --help'
|
||||
the 'configure' script does not know about. Run './configure --help'
|
||||
for details on some of the pertinent environment variables.
|
||||
|
||||
You can give `configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here
|
||||
is an example:
|
||||
You can give 'configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here is
|
||||
an example:
|
||||
|
||||
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
|
||||
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
||||
|
||||
*Note Defining Variables::, for more details.
|
||||
|
||||
@@ -84,146 +112,257 @@ Compiling For Multiple Architectures
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you must use a version of `make' that
|
||||
supports the `VPATH' variable, such as GNU `make'. `cd' to the
|
||||
own directory. To do this, you can use GNU 'make'. 'cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'.
|
||||
the 'configure' script. 'configure' automatically checks for the source
|
||||
code in the directory that 'configure' is in and in '..'. This is known
|
||||
as a "VPATH" build.
|
||||
|
||||
If you have to use a `make' that does not support the `VPATH'
|
||||
variable, you have to compile the package for one architecture at a
|
||||
time in the source code directory. After you have installed the
|
||||
package for one architecture, use `make distclean' before reconfiguring
|
||||
for another architecture.
|
||||
With a non-GNU 'make', it is safer to compile the package for one
|
||||
architecture at a time in the source code directory. After you have
|
||||
installed the package for one architecture, use 'make distclean' before
|
||||
reconfiguring for another architecture.
|
||||
|
||||
On MacOS X 10.5 and later systems, you can create libraries and
|
||||
executables that work on multiple system types--known as "fat" or
|
||||
"universal" binaries--by specifying multiple '-arch' options to the
|
||||
compiler but only a single '-arch' option to the preprocessor. Like
|
||||
this:
|
||||
|
||||
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||
CPP="gcc -E" CXXCPP="g++ -E"
|
||||
|
||||
This is not guaranteed to produce working output in all cases, you
|
||||
may have to build one architecture at a time and combine the results
|
||||
using the 'lipo' tool if you have problems.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' will install the package's files in
|
||||
`/usr/local/bin', `/usr/local/man', etc. You can specify an
|
||||
installation prefix other than `/usr/local' by giving `configure' the
|
||||
option `--prefix=PATH'.
|
||||
By default, 'make install' installs the package's commands under
|
||||
'/usr/local/bin', include files under '/usr/local/include', etc. You
|
||||
can specify an installation prefix other than '/usr/local' by giving
|
||||
'configure' the option '--prefix=PREFIX', where PREFIX must be an
|
||||
absolute file name.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
give `configure' the option `--exec-prefix=PATH', the package will use
|
||||
PATH as the prefix for installing programs and libraries.
|
||||
Documentation and other data files will still use the regular prefix.
|
||||
pass the option '--exec-prefix=PREFIX' to 'configure', the package uses
|
||||
PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=PATH' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them.
|
||||
options like '--bindir=DIR' to specify different values for particular
|
||||
kinds of files. Run 'configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them. In general, the default
|
||||
for these options is expressed in terms of '${prefix}', so that
|
||||
specifying just '--prefix' will affect all of the other directory
|
||||
specifications that were not explicitly provided.
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
The most portable way to affect installation locations is to pass the
|
||||
correct locations to 'configure'; however, many packages provide one or
|
||||
both of the following shortcuts of passing variable assignments to the
|
||||
'make install' command line to change installation locations without
|
||||
having to reconfigure or recompile.
|
||||
|
||||
The first method involves providing an override variable for each
|
||||
affected directory. For example, 'make install
|
||||
prefix=/alternate/directory' will choose an alternate location for all
|
||||
directory configuration variables that were expressed in terms of
|
||||
'${prefix}'. Any directories that were specified during 'configure',
|
||||
but not in terms of '${prefix}', must each be overridden at install time
|
||||
for the entire installation to be relocated. The approach of makefile
|
||||
variable overrides for each directory variable is required by the GNU
|
||||
Coding Standards, and ideally causes no recompilation. However, some
|
||||
platforms have known limitations with the semantics of shared libraries
|
||||
that end up requiring recompilation when using this method, particularly
|
||||
noticeable in packages that use GNU Libtool.
|
||||
|
||||
The second method involves providing the 'DESTDIR' variable. For
|
||||
example, 'make install DESTDIR=/alternate/directory' will prepend
|
||||
'/alternate/directory' before all installation names. The approach of
|
||||
'DESTDIR' overrides is not required by the GNU Coding Standards, and
|
||||
does not work on platforms that have drive letters. On the other hand,
|
||||
it does better at avoiding recompilation issues, and works well even
|
||||
when some directory options were not specified in terms of '${prefix}'
|
||||
at 'configure' time.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving 'configure' the
|
||||
option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'.
|
||||
|
||||
Some packages pay attention to '--enable-FEATURE' options to
|
||||
'configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to '--with-PACKAGE' options, where PACKAGE
|
||||
is something like 'gnu-as' or 'x' (for the X Window System). The
|
||||
'README' should mention any '--enable-' and '--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
For packages that use the X Window System, 'configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
you can use the 'configure' options '--x-includes=DIR' and
|
||||
'--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Some packages offer the ability to configure how verbose the
|
||||
execution of 'make' will be. For these packages, running './configure
|
||||
--enable-silent-rules' sets the default to minimal output, which can be
|
||||
overridden with 'make V=1'; while running './configure
|
||||
--disable-silent-rules' sets the default to verbose, which can be
|
||||
overridden with 'make V=0'.
|
||||
|
||||
Particular systems
|
||||
==================
|
||||
|
||||
On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC
|
||||
is not installed, it is recommended to use the following options in
|
||||
order to use an ANSI C compiler:
|
||||
|
||||
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
|
||||
|
||||
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
|
||||
|
||||
HP-UX 'make' updates targets which have the same time stamps as their
|
||||
prerequisites, which makes it generally unusable when shipped generated
|
||||
files such as 'configure' are involved. Use GNU 'make' instead.
|
||||
|
||||
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
|
||||
parse its '<wchar.h>' header file. The option '-nodtk' can be used as a
|
||||
workaround. If GNU CC is not installed, it is therefore recommended to
|
||||
try
|
||||
|
||||
./configure CC="cc"
|
||||
|
||||
and if that doesn't work, try
|
||||
|
||||
./configure CC="cc -nodtk"
|
||||
|
||||
On Solaris, don't put '/usr/ucb' early in your 'PATH'. This
|
||||
directory contains several dysfunctional programs; working variants of
|
||||
these programs are available in '/usr/bin'. So, if you need '/usr/ucb'
|
||||
in your 'PATH', put it _after_ '/usr/bin'.
|
||||
|
||||
On Haiku, software installed for all users goes in '/boot/common',
|
||||
not '/usr/local'. It is recommended to use the following options:
|
||||
|
||||
./configure --prefix=/boot/common
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' cannot figure out
|
||||
There may be some features 'configure' cannot figure out
|
||||
automatically, but needs to determine by the type of machine the package
|
||||
will run on. Usually, assuming the package is built to be run on the
|
||||
_same_ architectures, `configure' can figure that out, but if it prints
|
||||
_same_ architectures, 'configure' can figure that out, but if it prints
|
||||
a message saying it cannot guess the machine type, give it the
|
||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name which has the form:
|
||||
'--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as 'sun4', or a canonical name which has the form:
|
||||
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS KERNEL-OS
|
||||
OS
|
||||
KERNEL-OS
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
See the file 'config.sub' for the possible values of each field. If
|
||||
'config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the `--target=TYPE' option to select the type of system they will
|
||||
use the option '--target=TYPE' to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
platform different from the build platform, you should specify the
|
||||
"host" platform (i.e., that on which the generated programs will
|
||||
eventually be run) with `--host=TYPE'.
|
||||
eventually be run) with '--host=TYPE'.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share,
|
||||
you can create a site shell script called `config.site' that gives
|
||||
default values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
If you want to set default values for 'configure' scripts to share,
|
||||
you can create a site shell script called 'config.site' that gives
|
||||
default values for variables like 'CC', 'cache_file', and 'prefix'.
|
||||
'configure' looks for 'PREFIX/share/config.site' if it exists, then
|
||||
'PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
'CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all 'configure' scripts look for a site script.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to `configure'. However, some packages may run
|
||||
environment passed to 'configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the `configure' command line, using `VAR=value'. For example:
|
||||
them in the 'configure' command line, using 'VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
will cause the specified gcc to be used as the C compiler (unless it is
|
||||
causes the specified 'gcc' to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
`configure' Invocation
|
||||
Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an
|
||||
Autoconf limitation. Until the limitation is lifted, you can use this
|
||||
workaround:
|
||||
|
||||
CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
'configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it
|
||||
'configure' recognizes the following options to control how it
|
||||
operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of the options to `configure', and exit.
|
||||
'--help'
|
||||
'-h'
|
||||
Print a summary of all of the options to 'configure', and exit.
|
||||
|
||||
`--version'
|
||||
`-V'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
'--help=short'
|
||||
'--help=recursive'
|
||||
Print a summary of the options unique to this package's
|
||||
'configure', and exit. The 'short' variant lists options used only
|
||||
in the top level, while the 'recursive' variant lists options also
|
||||
present in any nested packages.
|
||||
|
||||
'--version'
|
||||
'-V'
|
||||
Print the version of Autoconf used to generate the 'configure'
|
||||
script, and exit.
|
||||
|
||||
`--cache-file=FILE'
|
||||
'--cache-file=FILE'
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||
traditionally 'config.cache'. FILE defaults to '/dev/null' to
|
||||
disable caching.
|
||||
|
||||
`--config-cache'
|
||||
`-C'
|
||||
Alias for `--cache-file=config.cache'.
|
||||
'--config-cache'
|
||||
'-C'
|
||||
Alias for '--cache-file=config.cache'.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
'--quiet'
|
||||
'--silent'
|
||||
'-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to `/dev/null' (any error
|
||||
suppress all normal output, redirect it to '/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
`--srcdir=DIR'
|
||||
'--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
'configure' can determine that directory automatically.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
||||
'--prefix=DIR'
|
||||
Use DIR as the installation prefix. *note Installation Names:: for
|
||||
more details, including other options available for fine-tuning the
|
||||
installation locations.
|
||||
|
||||
'--no-create'
|
||||
'-n'
|
||||
Run the configure checks, but stop before creating any output
|
||||
files.
|
||||
|
||||
'configure' also accepts some other, not widely useful, options. Run
|
||||
'configure --help' for more details.
|
||||
|
||||
+1
-7
@@ -4,23 +4,17 @@ SUBDIRS = \
|
||||
test
|
||||
|
||||
EXTRA_DIST= \
|
||||
autogen.sh \
|
||||
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/functional_fun.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 \
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
BUILDING
|
||||
|
||||
Run "./autogen.sh" to generate the configure scripts if
|
||||
nessesary. The man page "doc/rtorrent.1" must be generated with
|
||||
"docbook2man rtorrent.1.xml" if it is missing.
|
||||
Run "aclocal -I scripts && autoconf -i && autoheader && automake --add-missing"
|
||||
to generate the configure scripts if necessary. The man page "doc/rtorrent.1"
|
||||
must be generated with "docbook2man rtorrent.1.xml" if it is missing.
|
||||
|
||||
Note that rtorrent follows the development of libtorrent closely, and
|
||||
thus the versions must be in sync. This should not be nessesary in the
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
[](https://paypal.me/jarisundelljp)
|
||||
|
||||
RTorrent BitTorrent Client
|
||||
========
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
To learn how to use rTorrent visit the [Wiki](https://github.com/rakshasa/rtorrent/wiki).
|
||||
|
||||
Stable
|
||||
------
|
||||
|
||||
* [https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.13.8.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.13.8.tar.gz)
|
||||
* [https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.9.8.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.9.8.tar.gz)
|
||||
|
||||
Unstable
|
||||
------
|
||||
|
||||
* [https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.14.0.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.14.0.tar.gz)
|
||||
* [https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.10.0.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.10.0.tar.gz)
|
||||
|
||||
Related Projects
|
||||
----------------
|
||||
|
||||
* [https://github.com/rakshasa/rbedit](https://github.com/rakshasa/rbedit): A dependency-free bencode editor.
|
||||
|
||||
Donate to rTorrent development
|
||||
------------------------------
|
||||
|
||||
* [Paypal](https://paypal.me/jarisundellno)
|
||||
* [Patreon](https://www.patreon.com/rtorrent)
|
||||
* [SubscribeStar](https://www.subscribestar.com/rtorrent)
|
||||
* Bitcoin: 1MpmXm5AHtdBoDaLZstJw8nupJJaeKu8V8
|
||||
* Ethereum: 0x9AB1e3C3d8a875e870f161b3e9287Db0E6DAfF78
|
||||
* Litecoin: LdyaVR67LBnTf6mAT4QJnjSG2Zk67qxmfQ
|
||||
* Cardano: addr1qytaslmqmk6dspltw06sp0zf83dh09u79j49ceh5y26zdcccgq4ph7nmx6kgmzeldauj43254ey97f3x4xw49d86aguqwfhlte
|
||||
|
||||
|
||||
Help keep rTorrent development going by donating to its creator.
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
#! /bin/sh
|
||||
|
||||
echo aclocal...
|
||||
(aclocal --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo aclocal not found
|
||||
exit 1
|
||||
}
|
||||
|
||||
aclocal -I ./scripts -I . ${ACLOCAL_FLAGS} || exit 1
|
||||
|
||||
echo autoheader...
|
||||
(autoheader --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo autoheader not found
|
||||
exit 1
|
||||
}
|
||||
|
||||
autoheader || exit 1
|
||||
|
||||
echo -n "libtoolize... "
|
||||
if ( (glibtoolize --version) < /dev/null > /dev/null 2>&1 ); then
|
||||
echo "using glibtoolize"
|
||||
glibtoolize --automake --copy --force || exit 1
|
||||
|
||||
elif ( (libtoolize --version) < /dev/null > /dev/null 2>&1 ) ; then
|
||||
echo "using libtoolize"
|
||||
libtoolize --automake --copy --force || exit 1
|
||||
|
||||
else
|
||||
echo "libtoolize nor glibtoolize not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo automake...
|
||||
(automake --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo automake not found
|
||||
exit 1
|
||||
}
|
||||
|
||||
automake --add-missing --copy --gnu || exit 1
|
||||
|
||||
echo autoconf...
|
||||
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo autoconf not found
|
||||
exit 1
|
||||
}
|
||||
|
||||
autoconf || exit 1
|
||||
|
||||
echo ready to configure
|
||||
|
||||
exit 0
|
||||
+51
-36
@@ -1,13 +1,23 @@
|
||||
AC_INIT(rtorrent, 0.9.7, sundell.software@gmail.com)
|
||||
m4_pattern_allow([PKG_CHECK_EXISTS])
|
||||
|
||||
AC_DEFINE(API_VERSION, 9, api version)
|
||||
AC_INIT([rtorrent],[0.15.6],[sundell.software@gmail.com])
|
||||
|
||||
AM_INIT_AUTOMAKE
|
||||
AC_CONFIG_HEADERS(config.h)
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_MACRO_DIRS([scripts])
|
||||
AM_INIT_AUTOMAKE([foreign subdir-objects])
|
||||
AM_PROG_AR
|
||||
|
||||
LT_INIT
|
||||
|
||||
AC_PROG_RANLIB
|
||||
AC_PROG_CXX
|
||||
AC_PROG_LIBTOOL
|
||||
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
|
||||
@@ -15,15 +25,8 @@ RAK_ENABLE_DEBUG
|
||||
RAK_ENABLE_EXTRA_DEBUG
|
||||
RAK_ENABLE_WERROR
|
||||
|
||||
RAK_CHECK_CXX11
|
||||
RAK_CHECK_TR1_LIB
|
||||
|
||||
TORRENT_DISABLE_IPV6
|
||||
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
TORRENT_CHECK_EXECINFO
|
||||
|
||||
TORRENT_ENABLE_ARCH
|
||||
TORRENT_WITH_SYSROOT
|
||||
|
||||
@@ -31,46 +34,58 @@ TORRENT_WITHOUT_VARIABLE_FDSET
|
||||
TORRENT_WITHOUT_STATVFS
|
||||
TORRENT_WITHOUT_STATFS
|
||||
|
||||
AC_ARG_ENABLE(execinfo,
|
||||
AS_HELP_STRING([--disable-execinfo],
|
||||
[disable libexecinfo [[default=enable]]]),
|
||||
[
|
||||
if test "$enableval" = "yes"; then
|
||||
AX_EXECINFO
|
||||
fi
|
||||
],[
|
||||
AX_EXECINFO
|
||||
])
|
||||
|
||||
AX_PTHREAD([], AC_MSG_ERROR([requires pthread]))
|
||||
AX_WITH_CURSES
|
||||
|
||||
if test "x$ax_cv_ncursesw" != xyes && test "x$ax_cv_ncurses" != xyes; then
|
||||
AC_MSG_ERROR([requires either NcursesW or Ncurses library])
|
||||
AC_MSG_ERROR([requires either NcursesW or Ncurses library])
|
||||
fi
|
||||
|
||||
PKG_CHECK_MODULES([LIBCURL], [libcurl], , [LIBCURL_CHECK_CONFIG])
|
||||
PKG_CHECK_MODULES([LIBCURL], [libcurl],, [LIBCURL_CHECK_CONFIG])
|
||||
PKG_CHECK_MODULES([CPPUNIT], [cppunit],, [no_cppunit="yes"])
|
||||
PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.13.7])
|
||||
|
||||
LIBS="$PTHREAD_LIBS $CURSES_LIB $CPPUNIT_LIBS $LIBCURL $LIBCURL_LIBS $DEPENDENCIES_LIBS $LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS $CPPUNIT_CFLAGS $LIBCURL_CPPFLAGS $LIBCURL_CFLAGS $DEPENDENCIES_CFLAGS $CURSES_CFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS $CPPUNIT_CFLAGS $LIBCURL_CPPFLAGS $LIBCURL_CFLAGS $DEPENDENCIES_CFLAGS $CURSES_CFLAGS"
|
||||
PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.15.6])
|
||||
|
||||
AC_LANG_PUSH(C++)
|
||||
TORRENT_WITH_XMLRPC_C
|
||||
AC_LANG_POP(C++)
|
||||
|
||||
TORRENT_WITH_LUA
|
||||
TORRENT_WITH_TINYXML2
|
||||
|
||||
if test ${with_xmlrpc_c+y} && test ${with_xmlrpc_tinyxml2+y}; then
|
||||
AC_MSG_ERROR([--with-xmlrpc-c and --with-xmlrpc-tinyxml2 cannot be used together. Please choose only one])
|
||||
fi
|
||||
|
||||
AC_DEFINE(HAVE_CONFIG_H, 1, true if config.h was included)
|
||||
AC_DEFINE(USER_AGENT, [std::string(PACKAGE "/" VERSION "/") + torrent::version()], Http user agent)
|
||||
|
||||
AC_CHECK_FUNCS(posix_memalign)
|
||||
|
||||
dnl Only update global build variables immediately before generating the output,
|
||||
dnl to avoid affecting the global build environment for other autoconf checks.
|
||||
LIBS="$PTHREAD_LIBS $CURSES_LIB $CURSES_LIBS $LIBCURL $LIBCURL_LIBS $DEPENDENCIES_LIBS $LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS $LIBCURL_CPPFLAGS $LIBCURL_CFLAGS $DEPENDENCIES_CFLAGS $CURSES_CFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS $LIBCURL_CPPFLAGS $LIBCURL_CFLAGS $DEPENDENCIES_CFLAGS $CURSES_CFLAGS"
|
||||
|
||||
TORRENT_CHECK_CACHELINE()
|
||||
TORRENT_CHECK_POPCOUNT()
|
||||
|
||||
CC_ATTRIBUTE_UNUSED(
|
||||
AC_DEFINE([__UNUSED], [__attribute__((unused))], [Wrapper around unused attribute]),
|
||||
AC_DEFINE([__UNUSED], [], [Null-wrapper if unused attribute is unsupported])
|
||||
)
|
||||
|
||||
AC_OUTPUT([
|
||||
Makefile
|
||||
doc/Makefile
|
||||
src/Makefile
|
||||
src/core/Makefile
|
||||
src/display/Makefile
|
||||
src/input/Makefile
|
||||
src/rpc/Makefile
|
||||
src/ui/Makefile
|
||||
src/utils/Makefile
|
||||
test/Makefile
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
doc/Makefile
|
||||
src/Makefile
|
||||
test/Makefile
|
||||
])
|
||||
|
||||
AC_OUTPUT
|
||||
|
||||
+4
-5
@@ -52,7 +52,7 @@ Decrease the download throttle by 1/5/50 KB.
|
||||
\fB->\fR
|
||||
View download.
|
||||
.TP
|
||||
\fB1 - 7\fR
|
||||
\fB0 - 9\fR
|
||||
Change view.
|
||||
.TP
|
||||
\fB^S\fR
|
||||
@@ -99,6 +99,9 @@ Delete the file the torrent is tied to, and clear the association.
|
||||
.TP
|
||||
\fBI\fR
|
||||
Toggle whether torrent ignores ratio settings.
|
||||
.TP
|
||||
\fBF\fR
|
||||
Add a temporary name based regex filter to the current view.
|
||||
.SS "DOWNLOAD VIEW KEYS"
|
||||
.TP
|
||||
\fB->\fR
|
||||
@@ -496,10 +499,6 @@ Number of attempts to check the hash while using the mincore status,
|
||||
before forcing. Overworked systems might need lower values to get a
|
||||
decent hash checking rate.
|
||||
.TP
|
||||
\fBsafe_sync = \fIyes|no\fB\fR
|
||||
Always use MS_SYNC rather than MS_ASYNC when syncing chunks. This may
|
||||
be nessesary in case of filesystem bugs like NFS in linux ~2.6.13.
|
||||
.TP
|
||||
\fBmax_open_files = \fIvalue\fB\fR
|
||||
Number of files to simultaneously keep open. LibTorrent dynamically
|
||||
opens and closes files as necessary when mapping files to
|
||||
|
||||
+8
-11
@@ -122,7 +122,7 @@ View download.
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>1 - 7</term>
|
||||
<term>0 - 9</term>
|
||||
<listitem><para>
|
||||
Change view.
|
||||
</para></listitem>
|
||||
@@ -225,6 +225,13 @@ Toggle whether torrent ignores ratio settings.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>F</term>
|
||||
<listitem><para>
|
||||
Add a temporary name based regex filter to the current view.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</refsect2>
|
||||
@@ -971,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>
|
||||
|
||||
+43
-23
@@ -1,22 +1,36 @@
|
||||
# This is an example resource file for rTorrent. Copy to
|
||||
# ~/.rtorrent.rc and enable/modify the options as needed. Remember to
|
||||
# uncomment the options you wish to enable.
|
||||
#############################################################################
|
||||
# This is an (old) example resource file for rTorrent.
|
||||
# Copy to ~/.rtorrent.rc and enable/modify the options as needed.
|
||||
# Remember to uncomment the options you wish to enable.
|
||||
#
|
||||
# See 'rtorrent.rc-example' for a newer, basic configuration.
|
||||
#
|
||||
# Sample: https://github.com/rakshasa/rtorrent/wiki/CONFIG-Template
|
||||
# Complete: https://rtorrent-docs.readthedocs.io/en/latest/cmd-ref.html
|
||||
# Useful: https://rtorrent-docs.readthedocs.io/en/latest/use-cases.html
|
||||
# Manual: https://rtorrent-docs.readthedocs.io/en/latest/
|
||||
# Convert: https://github.com/rakshasa/rtorrent/wiki/rTorrent-0.9-Comprehensive-Command-list-(WIP)
|
||||
# Handbook: https://media.readthedocs.org/pdf/rtorrent-docs/latest/rtorrent-docs.pdf
|
||||
# File: https://github.com/rakshasa/rtorrent/blob/master/doc/rtorrent.rc
|
||||
#############################################################################
|
||||
|
||||
# Maximum and minimum number of peers to connect to per torrent.
|
||||
#
|
||||
#throttle.min_peers.normal.set = 40
|
||||
#throttle.max_peers.normal.set = 100
|
||||
|
||||
# Same as above but for seeding completed torrents (-1 = same as downloading)
|
||||
# Same as above but for seeding completed torrents.
|
||||
# "-1" = same as downloading.
|
||||
#
|
||||
#throttle.min_peers.seed.set = 10
|
||||
#throttle.max_peers.seed.set = 50
|
||||
|
||||
# Maximum number of simultanious uploads per torrent.
|
||||
# Maximum number of simultaneous uploads per torrent.
|
||||
#
|
||||
#throttle.max_uploads.set = 15
|
||||
|
||||
# Global upload and download rate in KiB. "0" for unlimited.
|
||||
# Global upload and download rate in KiB.
|
||||
# "0" for unlimited.
|
||||
#
|
||||
#throttle.global_down.max_rate.set_kb = 0
|
||||
#throttle.global_up.max_rate.set_kb = 0
|
||||
@@ -26,7 +40,7 @@
|
||||
#directory.default.set = ./
|
||||
|
||||
# Default session directory. Make sure you don't run multiple instance
|
||||
# of rtorrent using the same session directory. Perhaps using a
|
||||
# of rTorrent using the same session directory. Perhaps using a
|
||||
# relative path?
|
||||
#
|
||||
#session.path.set = ./session
|
||||
@@ -35,18 +49,17 @@
|
||||
# deleted.
|
||||
#
|
||||
#schedule2 = watch_directory,5,5,load.start=./watch/*.torrent
|
||||
#schedule2 = untied_directory,5,5,stop_untied=
|
||||
|
||||
# Close torrents when diskspace is low.
|
||||
# Close torrents when disk-space is low.
|
||||
#
|
||||
#schedule2 = low_diskspace,5,60,close_low_diskspace=100M
|
||||
|
||||
# The ip address reported to the tracker.
|
||||
# The IP address reported to the tracker.
|
||||
#
|
||||
#network.local_address.set = 127.0.0.1
|
||||
#network.local_address.set = rakshasa.no
|
||||
|
||||
# The ip address the listening socket and outgoing connections is
|
||||
# The IP address the listening socket and outgoing connections is
|
||||
# bound to.
|
||||
#
|
||||
#network.bind_address.set = 127.0.0.1
|
||||
@@ -60,8 +73,12 @@
|
||||
#
|
||||
#network.port_random.set = no
|
||||
|
||||
# Check hash for finished torrents. Might be usefull until the bug is
|
||||
# fixed that causes lack of diskspace not to be properly reported.
|
||||
# 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.
|
||||
#
|
||||
#pieces.hash.on_completion.set = no
|
||||
|
||||
@@ -69,7 +86,7 @@
|
||||
#
|
||||
#trackers.use_udp.set = yes
|
||||
|
||||
# Alternative calls to bind and ip that should handle dynamic ip's.
|
||||
# Alternative calls to bind and IP that should handle dynamic IP's.
|
||||
#
|
||||
#schedule2 = ip_tick,0,1800,ip=rakshasa
|
||||
#schedule2 = bind_tick,0,1800,bind=rakshasa
|
||||
@@ -79,7 +96,7 @@
|
||||
#
|
||||
# The example value allows incoming encrypted connections, starts unencrypted
|
||||
# outgoing connections but retries with encryption if they fail, preferring
|
||||
# plaintext to RC4 encryption after the encrypted handshake
|
||||
# plain-text to RC4 encryption after the encrypted handshake.
|
||||
#
|
||||
# protocol.encryption.set = allow_incoming,enable_retry,prefer_plaintext
|
||||
|
||||
@@ -87,26 +104,29 @@
|
||||
# May be set to "disable" (completely disable DHT), "off" (do not start DHT),
|
||||
# "auto" (start and stop DHT as needed), or "on" (start DHT immediately).
|
||||
# The default is "off". For DHT to work, a session directory must be defined.
|
||||
#
|
||||
#
|
||||
# dht.mode.set = auto
|
||||
|
||||
# UDP port to use for DHT.
|
||||
# UDP port to use for DHT.
|
||||
#
|
||||
#dht.port.set = 6881
|
||||
|
||||
# Enable peer exchange (for torrents not marked private)
|
||||
# Enable peer exchange (for torrents not marked private).
|
||||
#
|
||||
#protocol.pex.set = yes
|
||||
|
||||
# Set downlad list layout style. ("full", "compact")
|
||||
# Set download list layout style ("full", "compact").
|
||||
#
|
||||
#ui.torrent_list.layout.set = "full"
|
||||
|
||||
# SCGI Connectivity (for alternative rtorrent interfaces, XMLRPC)
|
||||
# Run rTorrent as a daemon, controlled via XMLRPC.
|
||||
#
|
||||
#system.daemon.set = false
|
||||
|
||||
# SCGI Connectivity (for alternative rtorrent interfaces, XMLRPC)
|
||||
# Use a IP socket with scgi_port, or a Unix socket with scgi_local.
|
||||
# schedule can be used to set permissions on the unix socket.
|
||||
#
|
||||
#scgi_port = 127.0.0.1:5000
|
||||
#scgi_local = /home/user/rtorrent/rpc.socket
|
||||
#schedule = scgi_permission,0,0,"execute.nothrow=chmod,\"g+w,o=\",/home/user/rtorrent/rpc.socket"
|
||||
#network.scgi.open_port = "127.0.0.1:5000"
|
||||
#network.scgi.open_local = (cat,(session.path),/rpc.sock)
|
||||
#schedule2 = socket_chmod, 0, 0, "execute.nothrow=chmod,770,(cat,(session.path),/rpc.sock)"
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
#############################################################################
|
||||
# A minimal rTorrent configuration that provides the basic features
|
||||
# you want to have in addition to the built-in defaults.
|
||||
#
|
||||
# See https://github.com/rakshasa/rtorrent/wiki/CONFIG-Template
|
||||
# for an up-to-date version.
|
||||
#############################################################################
|
||||
|
||||
# Instance layout (base paths)
|
||||
method.insert = cfg.basedir, private|const|string, (cat,"/home/USERNAME/rtorrent/")
|
||||
method.insert = cfg.download, private|const|string, (cat,(cfg.basedir),"download/")
|
||||
method.insert = cfg.logs, private|const|string, (cat,(cfg.basedir),"log/")
|
||||
method.insert = cfg.logfile, private|const|string, (cat,(cfg.logs),"rtorrent-",(system.time),".log")
|
||||
method.insert = cfg.session, private|const|string, (cat,(cfg.basedir),".session/")
|
||||
method.insert = cfg.watch, private|const|string, (cat,(cfg.basedir),"watch/")
|
||||
|
||||
# Create instance directories
|
||||
execute.throw = sh, -c, (cat,\
|
||||
"mkdir -p \"",(cfg.download),"\" ",\
|
||||
"\"",(cfg.logs),"\" ",\
|
||||
"\"",(cfg.session),"\" ",\
|
||||
"\"",(cfg.watch),"/load\" ",\
|
||||
"\"",(cfg.watch),"/start\" ")
|
||||
|
||||
# Listening port for incoming peer traffic (fixed; you can also randomize it)
|
||||
network.port_range.set = 50000-50000
|
||||
network.port_random.set = no
|
||||
|
||||
# Tracker-less torrent and UDP tracker support
|
||||
# (conservative settings for 'private' trackers, change for 'public')
|
||||
dht.mode.set = disable
|
||||
protocol.pex.set = no
|
||||
trackers.use_udp.set = no
|
||||
|
||||
# Peer settings
|
||||
throttle.max_uploads.set = 100
|
||||
throttle.max_uploads.global.set = 250
|
||||
|
||||
throttle.min_peers.normal.set = 20
|
||||
throttle.max_peers.normal.set = 60
|
||||
throttle.min_peers.seed.set = 30
|
||||
throttle.max_peers.seed.set = 80
|
||||
trackers.numwant.set = 80
|
||||
|
||||
protocol.encryption.set = allow_incoming,try_outgoing,enable_retry
|
||||
|
||||
# Limits for file handle resources, this is optimized for
|
||||
# an `ulimit` of 1024 (a common default). You MUST leave
|
||||
# a ceiling of handles reserved for rTorrent's internal needs!
|
||||
network.http.max_open.set = 50
|
||||
network.max_open_files.set = 600
|
||||
network.max_open_sockets.set = 300
|
||||
|
||||
# Memory resource usage (increase if you have a large number of items loaded,
|
||||
# and/or the available resources to spend)
|
||||
pieces.memory.max.set = 1800M
|
||||
network.xmlrpc.size_limit.set = 4M
|
||||
|
||||
# Basic operational settings (no need to change these)
|
||||
session.path.set = (cat, (cfg.session))
|
||||
directory.default.set = (cat, (cfg.download))
|
||||
log.execute = (cat, (cfg.logs), "execute.log")
|
||||
##log.xmlrpc = (cat, (cfg.logs), "xmlrpc.log")
|
||||
execute.nothrow = sh, -c, (cat, "echo >",\
|
||||
(session.path), "rtorrent.pid", " ", (system.pid))
|
||||
|
||||
# Other operational settings (check & adapt)
|
||||
encoding.add = utf8
|
||||
system.umask.set = 0027
|
||||
system.cwd.set = (directory.default)
|
||||
network.http.dns_cache_timeout.set = 25
|
||||
schedule2 = monitor_diskspace, 15, 60, ((close_low_diskspace, 1000M))
|
||||
##pieces.hash.on_completion.set = no
|
||||
##view.sort_current = seeding, greater=d.ratio=
|
||||
##keys.layout.set = qwerty
|
||||
##network.http.capath.set = "/etc/ssl/certs"
|
||||
##network.http.ssl_verify_peer.set = 0
|
||||
##network.http.ssl_verify_host.set = 0
|
||||
#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)
|
||||
method.insert = d.data_path, simple,\
|
||||
"if=(d.is_multi_file),\
|
||||
(cat, (d.directory), /),\
|
||||
(cat, (d.directory), /, (d.name))"
|
||||
method.insert = d.session_file, simple, "cat=(session.path), (d.hash), .torrent"
|
||||
|
||||
# Watch directories (add more as you like, but use unique schedule names)
|
||||
schedule2 = watch_start, 10, 10, ((load.start_verbose, (cat, (cfg.watch), "start/*.torrent")))
|
||||
schedule2 = watch_load, 11, 10, ((load.verbose, (cat, (cfg.watch), "load/*.torrent")))
|
||||
|
||||
# Run the rTorrent process as a daemon in the background
|
||||
# (and control via XMLRPC sockets)
|
||||
#system.daemon.set = true
|
||||
#network.scgi.open_local = (cat,(session.path),rtorrent.sock)
|
||||
#execute.nothrow = chmod,770,(cat,(session.path),rtorrent.sock)
|
||||
|
||||
# Logging:
|
||||
# Levels = critical error warn notice info debug
|
||||
# Groups = connection_* dht_* peer_* rpc_* storage_* thread_* tracker_* torrent_*
|
||||
print = (cat, "Logging to ", (cfg.logfile))
|
||||
log.open_file = "log", (cfg.logfile)
|
||||
log.add_output = "info", "log"
|
||||
##log.add_output = "tracker_debug", "log"
|
||||
|
||||
### END of rtorrent.rc ###
|
||||
@@ -130,7 +130,7 @@ d_stop() {
|
||||
}
|
||||
|
||||
getsession() {
|
||||
session=$(cat "$1" | grep "^[[:space:]]*session[[:space:]]*=" | sed "s/^[[:space:]]*session[[:space:]]*=[[:space:]]*//" )
|
||||
session=$(cat "$1" | grep "^[[:space:]]*session.path.set[[:space:]]*=" | sed "s/^[[:space:]]*session.path.set[[:space:]]*=[[:space:]]*//" )
|
||||
#session=${session/#~/`getent passwd ${user}|cut -d: -f6`}
|
||||
echo $session
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ d_stop() {
|
||||
}
|
||||
|
||||
getsession() {
|
||||
session=`cat "$1" | grep "^[[:space:]]*session[[:space:]]*=" | sed "s/^[[:space:]]*session[[:space:]]*=[[:space:]]*//" `
|
||||
session=`cat "$1" | grep "^[[:space:]]*session.path.set[[:space:]]*=" | sed "s/^[[:space:]]*session.path.set[[:space:]]*=[[:space:]]*//" `
|
||||
echo $session
|
||||
}
|
||||
|
||||
|
||||
+22
-5
@@ -115,7 +115,7 @@ advance_backward(_InputIter __first, _InputIter __last, _Distance __distance) {
|
||||
}
|
||||
|
||||
template <typename _Value>
|
||||
struct compare_base : public std::binary_function<_Value, _Value, bool> {
|
||||
struct compare_base : public std::function<bool(_Value, _Value)> {
|
||||
bool operator () (const _Value& complete, const _Value& base) const {
|
||||
return !complete.compare(0, base.size(), base);
|
||||
}
|
||||
@@ -159,10 +159,7 @@ make_base(_InputIter __first, _InputIter __last, _Ftor __ftor) {
|
||||
template<typename T>
|
||||
inline int popcount_wrapper(T t) {
|
||||
#if USE_BUILTIN_POPCOUNT
|
||||
if (std::numeric_limits<T>::digits <= std::numeric_limits<unsigned int>::digits)
|
||||
return __builtin_popcount(t);
|
||||
else
|
||||
return __builtin_popcountll(t);
|
||||
return __builtin_popcountll(t);
|
||||
#else
|
||||
#error __builtin_popcount not found.
|
||||
unsigned int count = 0;
|
||||
@@ -176,6 +173,26 @@ inline int popcount_wrapper(T t) {
|
||||
#endif
|
||||
}
|
||||
|
||||
// Get the median of an unordered set of numbers of arbitrary
|
||||
// type by modifing the underlying dataset
|
||||
template <typename T = double, typename _InputIter>
|
||||
T median(_InputIter __first, _InputIter __last) {
|
||||
T __med;
|
||||
|
||||
unsigned int __size = __last - __first;
|
||||
unsigned int __middle = __size / 2;
|
||||
_InputIter __target1 = __first + __middle;
|
||||
std::nth_element(__first, __target1, __last);
|
||||
__med = *__target1;
|
||||
|
||||
if (__size % 2 == 0) {
|
||||
_InputIter __target2 = std::max_element(__first, __target1);
|
||||
__med = (__med + *__target2) / 2.0;
|
||||
}
|
||||
|
||||
return __med;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,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
-1
@@ -38,7 +38,7 @@
|
||||
#define RAK_FILE_STAT_H
|
||||
|
||||
#include <string>
|
||||
#include <inttypes.h>
|
||||
#include <cinttypes>
|
||||
#include <sys/stat.h>
|
||||
|
||||
namespace rak {
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@
|
||||
#define RAK_FS_STAT_H
|
||||
|
||||
#include <string>
|
||||
#include <inttypes.h>
|
||||
#include <cinttypes>
|
||||
|
||||
#include <rak/error_number.h>
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -1,656 +0,0 @@
|
||||
// rak - Rakshasa's toolbox
|
||||
// Copyright (C) 2005-2007, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
// This file contains functors that wrap function pointers and member
|
||||
// function pointers.
|
||||
//
|
||||
// 'fn' functors are polymorphic and derives from 'rak::function' and
|
||||
// thus is less strict about types, this adds the cost of calling a
|
||||
// virtual function.
|
||||
//
|
||||
// 'fun' functors are non-polymorphic and thus cheaper, but requires
|
||||
// the target object's type in the functor's template arguments.
|
||||
//
|
||||
// This should be replaced with TR1 stuff when it becomes widely
|
||||
// available. At the moment it behaves like std::auto_ptr, so be
|
||||
// careful when copying.
|
||||
|
||||
#ifndef RAK_FUNCTIONAL_FUN_H
|
||||
#define RAK_FUNCTIONAL_FUN_H
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include lt_tr1_functional
|
||||
#include lt_tr1_memory
|
||||
|
||||
namespace rak {
|
||||
|
||||
template <typename Result>
|
||||
class function_base0 {
|
||||
public:
|
||||
virtual ~function_base0() {}
|
||||
|
||||
virtual Result operator () () = 0;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1>
|
||||
class function_base1 : public std::unary_function<Arg1, Result> {
|
||||
public:
|
||||
virtual ~function_base1() {}
|
||||
|
||||
virtual Result operator () (Arg1 arg1) = 0;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1, typename Arg2>
|
||||
class function_base2 : public std::binary_function<Arg1, Arg2, Result> {
|
||||
public:
|
||||
virtual ~function_base2() {}
|
||||
|
||||
virtual Result operator () (Arg1 arg1, Arg2 arg2) = 0;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1, typename Arg2, typename Arg3>
|
||||
class function_base3 {
|
||||
public:
|
||||
virtual ~function_base3() {}
|
||||
|
||||
virtual Result operator () (Arg1 arg1, Arg2 arg2, Arg3 arg3) = 0;
|
||||
};
|
||||
|
||||
template <typename Result>
|
||||
class function0 {
|
||||
public:
|
||||
typedef Result result_type;
|
||||
typedef function_base0<Result> base_type;
|
||||
|
||||
bool is_valid() const { return m_base.get() != NULL; }
|
||||
|
||||
void set(base_type* base) { m_base = std::shared_ptr<base_type>(base); }
|
||||
base_type* release() { return m_base.release(); }
|
||||
|
||||
Result operator () () { return (*m_base)(); }
|
||||
|
||||
private:
|
||||
std::shared_ptr<base_type> m_base;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1>
|
||||
class function1 {
|
||||
public:
|
||||
typedef Result result_type;
|
||||
typedef function_base1<Result, Arg1> base_type;
|
||||
|
||||
bool is_valid() const { return m_base.get() != NULL; }
|
||||
|
||||
void set(base_type* base) { m_base = std::shared_ptr<base_type>(base); }
|
||||
base_type* release() { return m_base.release(); }
|
||||
|
||||
Result operator () (Arg1 arg1) { return (*m_base)(arg1); }
|
||||
|
||||
private:
|
||||
std::shared_ptr<base_type> m_base;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1, typename Arg2>
|
||||
class function2 {
|
||||
public:
|
||||
typedef Result result_type;
|
||||
typedef function_base2<Result, Arg1, Arg2> base_type;
|
||||
|
||||
bool is_valid() const { return m_base.get() != NULL; }
|
||||
|
||||
void set(base_type* base) { m_base = std::shared_ptr<base_type>(base); }
|
||||
base_type* release() { return m_base.release(); }
|
||||
|
||||
Result operator () (Arg1 arg1, Arg2 arg2) { return (*m_base)(arg1, arg2); }
|
||||
|
||||
private:
|
||||
std::shared_ptr<base_type> m_base;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg2>
|
||||
class function2<Result, void, Arg2> {
|
||||
public:
|
||||
typedef Result result_type;
|
||||
typedef function_base1<Result, Arg2> base_type;
|
||||
|
||||
bool is_valid() const { return m_base.get() != NULL; }
|
||||
|
||||
void set(base_type* base) { m_base = std::shared_ptr<base_type>(base); }
|
||||
base_type* release() { return m_base.release(); }
|
||||
|
||||
Result operator () (Arg2 arg2) { return (*m_base)(arg2); }
|
||||
|
||||
template <typename Discard>
|
||||
Result operator () (Discard discard, Arg2 arg2) { return (*m_base)(arg2); }
|
||||
|
||||
private:
|
||||
std::shared_ptr<base_type> m_base;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1, typename Arg2, typename Arg3>
|
||||
class function3 {
|
||||
public:
|
||||
typedef Result result_type;
|
||||
typedef function_base3<Result, Arg1, Arg2, Arg3> base_type;
|
||||
|
||||
bool is_valid() const { return m_base.get() != NULL; }
|
||||
|
||||
void set(base_type* base) { m_base = std::shared_ptr<base_type>(base); }
|
||||
base_type* release() { return m_base.release(); }
|
||||
|
||||
Result operator () (Arg1 arg1, Arg2 arg2, Arg3 arg3) { return (*m_base)(arg1, arg2, arg3); }
|
||||
|
||||
private:
|
||||
std::shared_ptr<base_type> m_base;
|
||||
};
|
||||
|
||||
template <typename Result>
|
||||
class ptr_fn0_t : public function_base0<Result> {
|
||||
public:
|
||||
typedef Result (*Func)();
|
||||
|
||||
ptr_fn0_t(Func func) : m_func(func) {}
|
||||
virtual ~ptr_fn0_t() {}
|
||||
|
||||
virtual Result operator () () { return m_func(); }
|
||||
|
||||
private:
|
||||
Func m_func;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1>
|
||||
class ptr_fn1_t : public function_base1<Result, Arg1> {
|
||||
public:
|
||||
typedef Result (*Func)(Arg1);
|
||||
|
||||
ptr_fn1_t(Func func) : m_func(func) {}
|
||||
virtual ~ptr_fn1_t() {}
|
||||
|
||||
virtual Result operator () (Arg1 arg1) { return m_func(arg1); }
|
||||
|
||||
private:
|
||||
Func m_func;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1, typename Arg2>
|
||||
class ptr_fn2_t : public function_base2<Result, Arg1, Arg2> {
|
||||
public:
|
||||
typedef Result (*Func)(Arg1, Arg2);
|
||||
|
||||
ptr_fn2_t(Func func) : m_func(func) {}
|
||||
virtual ~ptr_fn2_t() {}
|
||||
|
||||
virtual Result operator () (Arg1 arg1, Arg2 arg2) { return m_func(arg1, arg2); }
|
||||
|
||||
private:
|
||||
Func m_func;
|
||||
};
|
||||
|
||||
template <typename Object, typename Result>
|
||||
class mem_fn0_t : public function_base0<Result> {
|
||||
public:
|
||||
typedef Result (Object::*Func)();
|
||||
|
||||
mem_fn0_t(Object* object, Func func) : m_object(object), m_func(func) {}
|
||||
virtual ~mem_fn0_t() {}
|
||||
|
||||
virtual Result operator () () { return (m_object->*m_func)(); }
|
||||
|
||||
private:
|
||||
Object* m_object;
|
||||
Func m_func;
|
||||
};
|
||||
|
||||
template <typename Object, typename Result, typename Arg1>
|
||||
class mem_fn1_t : public function_base1<Result, Arg1> {
|
||||
public:
|
||||
typedef Result (Object::*Func)(Arg1);
|
||||
|
||||
mem_fn1_t(Object* object, Func func) : m_object(object), m_func(func) {}
|
||||
virtual ~mem_fn1_t() {}
|
||||
|
||||
virtual Result operator () (Arg1 arg1) { return (m_object->*m_func)(arg1); }
|
||||
|
||||
private:
|
||||
Object* m_object;
|
||||
Func m_func;
|
||||
};
|
||||
|
||||
template <typename Object, typename Result, typename Arg1, typename Arg2, typename Arg3>
|
||||
class mem_fn3_t : public function_base3<Result, Arg1, Arg2, Arg3> {
|
||||
public:
|
||||
typedef Result (Object::*Func)(Arg1, Arg2, Arg3);
|
||||
|
||||
mem_fn3_t(Object* object, Func func) : m_object(object), m_func(func) {}
|
||||
virtual ~mem_fn3_t() {}
|
||||
|
||||
virtual Result operator () (Arg1 arg1, Arg2 arg2, Arg3 arg3) { return (m_object->*m_func)(arg1, arg2, arg3); }
|
||||
|
||||
private:
|
||||
Object* m_object;
|
||||
Func m_func;
|
||||
};
|
||||
|
||||
template <typename Object, typename Result, typename Arg1, typename Arg2>
|
||||
class mem_fn2_t : public function_base2<Result, Arg1, Arg2> {
|
||||
public:
|
||||
typedef Result (Object::*Func)(Arg1, Arg2);
|
||||
|
||||
mem_fn2_t(Object* object, Func func) : m_object(object), m_func(func) {}
|
||||
virtual ~mem_fn2_t() {}
|
||||
|
||||
virtual Result operator () (Arg1 arg1, Arg2 arg2) { return (m_object->*m_func)(arg1, arg2); }
|
||||
|
||||
private:
|
||||
Object* m_object;
|
||||
Func m_func;
|
||||
};
|
||||
|
||||
template <typename Object, typename Result>
|
||||
class const_mem_fn0_t : public function_base0<Result> {
|
||||
public:
|
||||
typedef Result (Object::*Func)() const;
|
||||
|
||||
const_mem_fn0_t(const Object* object, Func func) : m_object(object), m_func(func) {}
|
||||
virtual ~const_mem_fn0_t() {}
|
||||
|
||||
virtual Result operator () () { return (m_object->*m_func)(); }
|
||||
|
||||
private:
|
||||
const Object* m_object;
|
||||
Func m_func;
|
||||
};
|
||||
|
||||
template <typename Object, typename Result, typename Arg1>
|
||||
class const_mem_fn1_t : public function_base1<Result, Arg1> {
|
||||
public:
|
||||
typedef Result (Object::*Func)(Arg1) const;
|
||||
|
||||
const_mem_fn1_t(const Object* object, Func func) : m_object(object), m_func(func) {}
|
||||
virtual ~const_mem_fn1_t() {}
|
||||
|
||||
virtual Result operator () (Arg1 arg1) { return (m_object->*m_func)(arg1); }
|
||||
|
||||
private:
|
||||
const Object* m_object;
|
||||
Func m_func;
|
||||
};
|
||||
|
||||
// Unary functor with a bound argument.
|
||||
template <typename Object, typename Result, typename Arg1>
|
||||
class mem_fn0_b1_t : public function_base0<Result> {
|
||||
public:
|
||||
typedef Result (Object::*Func)(Arg1);
|
||||
|
||||
mem_fn0_b1_t(Object* object, Func func, const Arg1 arg1) : m_object(object), m_func(func), m_arg1(arg1) {}
|
||||
virtual ~mem_fn0_b1_t() {}
|
||||
|
||||
virtual Result operator () () { return (m_object->*m_func)(m_arg1); }
|
||||
|
||||
private:
|
||||
Object* m_object;
|
||||
Func m_func;
|
||||
const Arg1 m_arg1;
|
||||
};
|
||||
|
||||
template <typename Object, typename Result, typename Arg1, typename Arg2>
|
||||
class mem_fn1_b1_t : public function_base1<Result, Arg2> {
|
||||
public:
|
||||
typedef Result (Object::*Func)(Arg1, Arg2);
|
||||
|
||||
mem_fn1_b1_t(Object* object, Func func, const Arg1 arg1) : m_object(object), m_func(func), m_arg1(arg1) {}
|
||||
virtual ~mem_fn1_b1_t() {}
|
||||
|
||||
virtual Result operator () (const Arg2 arg2) { return (m_object->*m_func)(m_arg1, arg2); }
|
||||
|
||||
private:
|
||||
Object* m_object;
|
||||
Func m_func;
|
||||
const Arg1 m_arg1;
|
||||
};
|
||||
|
||||
template <typename Object, typename Result, typename Arg1, typename Arg2>
|
||||
class mem_fn1_b2_t : public function_base1<Result, Arg1> {
|
||||
public:
|
||||
typedef Result (Object::*Func)(Arg1, Arg2);
|
||||
|
||||
mem_fn1_b2_t(Object* object, Func func, const Arg2 arg2) : m_object(object), m_func(func), m_arg2(arg2) {}
|
||||
virtual ~mem_fn1_b2_t() {}
|
||||
|
||||
virtual Result operator () (const Arg1 arg1) { return (m_object->*m_func)(arg1, m_arg2); }
|
||||
|
||||
private:
|
||||
Object* m_object;
|
||||
Func m_func;
|
||||
const Arg2 m_arg2;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1>
|
||||
class ptr_fn0_b1_t : public function_base0<Result> {
|
||||
public:
|
||||
typedef Result (*Func)(Arg1);
|
||||
|
||||
ptr_fn0_b1_t(Func func, const Arg1 arg1) : m_func(func), m_arg1(arg1) {}
|
||||
virtual ~ptr_fn0_b1_t() {}
|
||||
|
||||
virtual Result operator () () { return m_func(m_arg1); }
|
||||
|
||||
private:
|
||||
Func m_func;
|
||||
Arg1 m_arg1;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1, typename Arg2>
|
||||
class ptr_fn1_b1_t : public function_base1<Result, Arg2> {
|
||||
public:
|
||||
typedef Result (*Func)(Arg1, Arg2);
|
||||
|
||||
ptr_fn1_b1_t(Func func, const Arg1 arg1) : m_func(func), m_arg1(arg1) {}
|
||||
virtual ~ptr_fn1_b1_t() {}
|
||||
|
||||
virtual Result operator () (Arg2 arg2) { return m_func(m_arg1, arg2); }
|
||||
|
||||
private:
|
||||
Func m_func;
|
||||
Arg1 m_arg1;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1, typename Arg2, typename Arg3>
|
||||
class ptr_fn2_b1_t : public function_base2<Result, Arg2, Arg3> {
|
||||
public:
|
||||
typedef Result (*Func)(Arg1, Arg2, Arg3);
|
||||
|
||||
ptr_fn2_b1_t(Func func, const Arg1 arg1) : m_func(func), m_arg1(arg1) {}
|
||||
virtual ~ptr_fn2_b1_t() {}
|
||||
|
||||
virtual Result operator () (Arg2 arg2, Arg3 arg3) { return m_func(m_arg1, arg2, arg3); }
|
||||
|
||||
private:
|
||||
Func m_func;
|
||||
Arg1 m_arg1;
|
||||
};
|
||||
|
||||
template <typename Ftor>
|
||||
class ftor_fn1_t : public function_base1<typename Ftor::result_type, typename Ftor::argument_type> {
|
||||
public:
|
||||
typedef typename Ftor::result_type result_type;
|
||||
typedef typename Ftor::argument_type argument_type;
|
||||
|
||||
ftor_fn1_t(Ftor ftor) : m_ftor(ftor) {}
|
||||
virtual ~ftor_fn1_t() {}
|
||||
|
||||
virtual result_type operator () (argument_type arg1) { return m_ftor(arg1); }
|
||||
|
||||
private:
|
||||
Ftor m_ftor;
|
||||
};
|
||||
|
||||
template <typename Ftor>
|
||||
class ftor_fn2_t : public function_base2<typename Ftor::result_type, typename Ftor::first_argument_type, typename Ftor::second_argument_type> {
|
||||
public:
|
||||
typedef typename Ftor::result_type result_type;
|
||||
typedef typename Ftor::first_argument_type first_argument_type;
|
||||
typedef typename Ftor::second_argument_type second_argument_type;
|
||||
|
||||
ftor_fn2_t(Ftor ftor) : m_ftor(ftor) {}
|
||||
virtual ~ftor_fn2_t() {}
|
||||
|
||||
virtual result_type operator () (first_argument_type arg1, second_argument_type arg2) { return m_ftor(arg1, arg2); }
|
||||
|
||||
private:
|
||||
Ftor m_ftor;
|
||||
};
|
||||
|
||||
template <typename Result>
|
||||
class value_fn0_t : public function_base0<Result> {
|
||||
public:
|
||||
value_fn0_t(const Result& val) : m_value(val) {}
|
||||
|
||||
virtual Result operator () () { return m_value; }
|
||||
|
||||
private:
|
||||
Result m_value;
|
||||
};
|
||||
|
||||
template <typename Result, typename SrcResult>
|
||||
class convert_fn0_t : public function_base0<Result> {
|
||||
public:
|
||||
typedef function0<SrcResult> src_type;
|
||||
|
||||
convert_fn0_t(typename src_type::base_type* object) { m_object.set(object); }
|
||||
virtual ~convert_fn0_t() {}
|
||||
|
||||
virtual Result operator () () {
|
||||
return m_object();
|
||||
}
|
||||
|
||||
private:
|
||||
src_type m_object;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1, typename SrcResult, typename SrcArg1>
|
||||
class convert_fn1_t : public function_base1<Result, Arg1> {
|
||||
public:
|
||||
typedef function1<SrcResult, SrcArg1> src_type;
|
||||
|
||||
convert_fn1_t(typename src_type::base_type* object) { m_object.set(object); }
|
||||
virtual ~convert_fn1_t() {}
|
||||
|
||||
virtual Result operator () (Arg1 arg1) {
|
||||
return m_object(arg1);
|
||||
}
|
||||
|
||||
private:
|
||||
src_type m_object;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1, typename Arg2, typename SrcResult, typename SrcArg1, typename SrcArg2>
|
||||
class convert_fn2_t : public function_base2<Result, Arg1, Arg2> {
|
||||
public:
|
||||
typedef function2<SrcResult, SrcArg1, SrcArg2> src_type;
|
||||
|
||||
convert_fn2_t(typename src_type::base_type* object) { m_object.set(object); }
|
||||
virtual ~convert_fn2_t() {}
|
||||
|
||||
virtual Result operator () (Arg1 arg1, Arg2 arg2) {
|
||||
return m_object(arg1, arg2);
|
||||
}
|
||||
|
||||
private:
|
||||
src_type m_object;
|
||||
};
|
||||
|
||||
template <typename Result>
|
||||
inline function_base0<Result>*
|
||||
ptr_fn(Result (*func)()) {
|
||||
return new ptr_fn0_t<Result>(func);
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Result>
|
||||
inline function_base1<Result, Arg1>*
|
||||
ptr_fn(Result (*func)(Arg1)) {
|
||||
return new ptr_fn1_t<Result, Arg1>(func);
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Arg2, typename Result>
|
||||
inline function_base2<Result, Arg1, Arg2>*
|
||||
ptr_fn(Result (*func)(Arg1, Arg2)) {
|
||||
return new ptr_fn2_t<Result, Arg1, Arg2>(func);
|
||||
}
|
||||
|
||||
template <typename Result, typename Object>
|
||||
inline function_base0<Result>*
|
||||
mem_fn(Object* object, Result (Object::*func)()) {
|
||||
return new mem_fn0_t<Object, Result>(object, func);
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Result, typename Object>
|
||||
inline function_base1<Result, Arg1>*
|
||||
mem_fn(Object* object, Result (Object::*func)(Arg1)) {
|
||||
return new mem_fn1_t<Object, Result, Arg1>(object, func);
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Arg2, typename Result, typename Object>
|
||||
inline function_base2<Result, Arg1, Arg2>*
|
||||
mem_fn(Object* object, Result (Object::*func)(Arg1, Arg2)) {
|
||||
return new mem_fn2_t<Object, Result, Arg1, Arg2>(object, func);
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Arg2, typename Arg3, typename Result, typename Object>
|
||||
inline function_base3<Result, Arg1, Arg2, Arg3>*
|
||||
mem_fn(Object* object, Result (Object::*func)(Arg1, Arg2, Arg3)) {
|
||||
return new mem_fn3_t<Object, Result, Arg1, Arg2, Arg3>(object, func);
|
||||
}
|
||||
|
||||
template <typename Result, typename Object>
|
||||
inline function_base0<Result>*
|
||||
mem_fn(const Object* object, Result (Object::*func)() const) {
|
||||
return new const_mem_fn0_t<Object, Result>(object, func);
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Result, typename Object>
|
||||
inline function_base1<Result, Arg1>*
|
||||
mem_fn(const Object* object, Result (Object::*func)(Arg1) const) {
|
||||
return new const_mem_fn1_t<Object, Result, Arg1>(object, func);
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Result, typename Object>
|
||||
inline function_base0<Result>*
|
||||
bind_mem_fn(Object* object, Result (Object::*func)(Arg1), const Arg1 arg1) {
|
||||
return new mem_fn0_b1_t<Object, Result, Arg1>(object, func, arg1);
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Arg2, typename Result, typename Object>
|
||||
inline function_base1<Result, Arg2>*
|
||||
bind_mem_fn(Object* object, Result (Object::*func)(Arg1, Arg2), const Arg1 arg1) {
|
||||
return new mem_fn1_b1_t<Object, Result, Arg1, Arg2>(object, func, arg1);
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Arg2, typename Result, typename Object>
|
||||
inline function_base1<Result, Arg1>*
|
||||
bind2_mem_fn(Object* object, Result (Object::*func)(Arg1, Arg2), const Arg2 arg2) {
|
||||
return new mem_fn1_b2_t<Object, Result, Arg1, Arg2>(object, func, arg2);
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Result>
|
||||
inline function_base0<Result>*
|
||||
bind_ptr_fn(Result (*func)(Arg1), const Arg1 arg1) {
|
||||
return new ptr_fn0_b1_t<Result, Arg1>(func, arg1);
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Arg2, typename Result>
|
||||
inline function_base1<Result, Arg2>*
|
||||
bind_ptr_fn(Result (*func)(Arg1, Arg2), const Arg1 arg1) {
|
||||
return new ptr_fn1_b1_t<Result, Arg1, Arg2>(func, arg1);
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Arg2, typename Arg3, typename Result>
|
||||
inline function_base2<Result, Arg2, Arg3>*
|
||||
bind_ptr_fn(Result (*func)(Arg1, Arg2, Arg3), const Arg1 arg1) {
|
||||
return new ptr_fn2_b1_t<Result, Arg1, Arg2, Arg3>(func, arg1);
|
||||
}
|
||||
|
||||
template <typename Ftor>
|
||||
inline function_base1<typename Ftor::result_type, typename Ftor::argument_type>*
|
||||
ftor_fn1(Ftor ftor) {
|
||||
return new ftor_fn1_t<Ftor>(ftor);
|
||||
}
|
||||
|
||||
template <typename Ftor>
|
||||
inline function_base2<typename Ftor::result_type, typename Ftor::first_argument_type, typename Ftor::second_argument_type>*
|
||||
ftor_fn2(Ftor ftor) {
|
||||
return new ftor_fn2_t<Ftor>(ftor);
|
||||
}
|
||||
|
||||
template <typename Result>
|
||||
inline function_base0<Result>*
|
||||
value_fn(const Result& val) {
|
||||
return new value_fn0_t<Result>(val);
|
||||
}
|
||||
|
||||
template <typename A, typename B>
|
||||
struct equal_types_t {
|
||||
typedef A first_type;
|
||||
typedef B second_type;
|
||||
|
||||
const static int result = 0;
|
||||
};
|
||||
|
||||
template <typename A>
|
||||
struct equal_types_t<A, A> {
|
||||
typedef A first_type;
|
||||
typedef A second_type;
|
||||
|
||||
const static int result = 1;
|
||||
};
|
||||
|
||||
template <typename Result, typename SrcResult>
|
||||
inline function_base0<Result>*
|
||||
convert_fn(function_base0<SrcResult>* src) {
|
||||
if (equal_types_t<function_base0<Result>, function_base0<SrcResult> >::result)
|
||||
// The pointer cast never gets done if the types are different,
|
||||
// but needs to be here to pleasant the compiler.
|
||||
return reinterpret_cast<typename equal_types_t<function_base0<Result>, function_base0<SrcResult> >::first_type*>(src);
|
||||
else
|
||||
return new convert_fn0_t<Result, SrcResult>(src);
|
||||
}
|
||||
|
||||
template <typename Result, typename Arg1, typename SrcResult, typename SrcArg1>
|
||||
inline function_base1<Result, Arg1>*
|
||||
convert_fn(function_base1<SrcResult, SrcArg1>* src) {
|
||||
if (equal_types_t<function_base1<Result, Arg1>, function_base1<SrcResult, SrcArg1> >::result)
|
||||
// The pointer cast never gets done if the types are different,
|
||||
// but needs to be here to pleasant the compiler.
|
||||
return reinterpret_cast<typename equal_types_t<function_base1<Result, Arg1>, function_base1<SrcResult, SrcArg1> >::first_type*>(src);
|
||||
else
|
||||
return new convert_fn1_t<Result, Arg1, SrcResult, SrcArg1>(src);
|
||||
}
|
||||
|
||||
template <typename Result, typename Arg1, typename Arg2, typename SrcResult, typename SrcArg1, typename SrcArg2>
|
||||
inline function_base2<Result, Arg1, Arg2>*
|
||||
convert_fn(function_base2<SrcResult, SrcArg1, SrcArg2>* src) {
|
||||
if (equal_types_t<function_base2<Result, Arg1, Arg2>, function_base2<SrcResult, SrcArg1, SrcArg2> >::result)
|
||||
// The pointer cast never gets done if the types are different,
|
||||
// but needs to be here to pleasant the compiler.
|
||||
return reinterpret_cast<typename equal_types_t<function_base2<Result, Arg1, Arg2>, function_base2<SrcResult, SrcArg1, SrcArg2> >::first_type*>(src);
|
||||
else
|
||||
return new convert_fn2_t<Result, Arg1, Arg2, SrcResult, SrcArg1, SrcArg2>(src);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+4
-3
@@ -37,9 +37,10 @@
|
||||
#ifndef RAK_PARTIAL_QUEUE_H
|
||||
#define RAK_PARTIAL_QUEUE_H
|
||||
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <inttypes.h>
|
||||
#include <cinttypes>
|
||||
|
||||
namespace rak {
|
||||
|
||||
@@ -107,7 +108,7 @@ private:
|
||||
size_type m_index;
|
||||
size_type m_ceiling;
|
||||
|
||||
size_pair_type m_layers[num_layers];
|
||||
std::array<size_pair_type, num_layers> m_layers;
|
||||
};
|
||||
|
||||
inline void
|
||||
@@ -137,7 +138,7 @@ partial_queue::clear() {
|
||||
m_index = 0;
|
||||
m_ceiling = ceiling(num_layers - 1);
|
||||
|
||||
std::memset(m_layers, 0, num_layers * sizeof(size_pair_type));
|
||||
m_layers = {};
|
||||
}
|
||||
|
||||
inline bool
|
||||
|
||||
@@ -1,145 +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
|
||||
|
||||
// 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 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(), std::bind2nd(m_equal, 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. This assumes 'itr' has been
|
||||
// modified such that it has a higher priority than any other
|
||||
// element in the queue.
|
||||
void erase(iterator itr) {
|
||||
// std::push_heap(begin(), ++itr, m_compare);
|
||||
// pop();
|
||||
base_type::erase(itr);
|
||||
std::make_heap(begin(), end(), m_compare);
|
||||
}
|
||||
|
||||
private:
|
||||
Compare m_compare;
|
||||
Equal m_equal;
|
||||
};
|
||||
|
||||
// Iterate while the top node has higher priority, as 'Compare'
|
||||
// returns false.
|
||||
template <typename Queue, typename Compare>
|
||||
class queue_pop_iterator
|
||||
: public std::iterator<std::forward_iterator_tag, void, void, void, void> {
|
||||
public:
|
||||
typedef Queue container_type;
|
||||
|
||||
queue_pop_iterator() : m_queue(NULL) {}
|
||||
queue_pop_iterator(Queue* q, Compare c) : m_queue(q), m_compare(c) {}
|
||||
|
||||
queue_pop_iterator& operator ++ () { m_queue->pop(); return *this; }
|
||||
queue_pop_iterator& operator ++ (int) { m_queue->pop(); return *this; }
|
||||
|
||||
typename container_type::const_reference operator * () { return m_queue->top(); }
|
||||
|
||||
bool operator != (const queue_pop_iterator& itr) { return !m_queue->empty() && !m_compare(m_queue->top()); }
|
||||
bool operator == (const queue_pop_iterator& itr) { return m_queue->empty() || m_compare(m_queue->top()); }
|
||||
|
||||
private:
|
||||
Queue* m_queue;
|
||||
Compare m_compare;
|
||||
};
|
||||
|
||||
template <typename Queue, typename Compare>
|
||||
inline queue_pop_iterator<Queue, Compare>
|
||||
queue_popper(Queue& queue, Compare comp) {
|
||||
return queue_pop_iterator<Queue, Compare>(&queue, comp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,142 +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 lt_tr1_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.");
|
||||
|
||||
// Clear time before erasing to force it to the top.
|
||||
item->clear_time();
|
||||
|
||||
if (!queue->erase(item))
|
||||
throw torrent::internal_error("priority_queue_erase(...) could not find item in queue.");
|
||||
|
||||
if (queue->find(item) != queue->end())
|
||||
throw torrent::internal_error("priority_queue_erase(...) item still in queue.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+1
-1
@@ -50,7 +50,7 @@
|
||||
|
||||
namespace rak {
|
||||
|
||||
class regex : public std::unary_function<std::string, bool> {
|
||||
class regex : public std::function<bool (std::string)> {
|
||||
public:
|
||||
regex() {}
|
||||
regex(const std::string& p) : m_pattern(p) {}
|
||||
|
||||
+74
-5
@@ -47,9 +47,12 @@
|
||||
#ifndef RAK_SOCKET_ADDRESS_H
|
||||
#define RAK_SOCKET_ADDRESS_H
|
||||
|
||||
#include <cinttypes>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/types.h>
|
||||
@@ -77,11 +80,13 @@ public:
|
||||
static const int pf_local = PF_UNIX;
|
||||
#endif
|
||||
|
||||
bool is_any() const;
|
||||
bool is_valid() const;
|
||||
bool is_bindable() const;
|
||||
bool is_address_any() const;
|
||||
|
||||
// Should we need to set AF_UNSPEC?
|
||||
bool is_valid_inet_class() const { return family() == af_inet || family() == af_inet6; }
|
||||
|
||||
void clear() { std::memset(this, 0, sizeof(socket_address)); set_family(); }
|
||||
|
||||
sa_family_t family() const { return m_sockaddr.sa_family; }
|
||||
@@ -93,6 +98,8 @@ public:
|
||||
std::string address_str() const;
|
||||
bool address_c_str(char* buf, socklen_t size) const;
|
||||
|
||||
std::string pretty_address_str() const;
|
||||
|
||||
// Attemts to set it as an inet, then an inet6 address. It will
|
||||
// never set anything but net addresses, no local/unix.
|
||||
bool set_address_str(const std::string& a) { return set_address_c_str(a.c_str()); }
|
||||
@@ -119,6 +126,7 @@ public:
|
||||
// extranous bytes and ensure it does not go beyond the size of this
|
||||
// struct.
|
||||
void copy(const socket_address& src, size_t length);
|
||||
void copy_sockaddr(const sockaddr* src);
|
||||
|
||||
static socket_address* cast_from(sockaddr* sa) { return reinterpret_cast<socket_address*>(sa); }
|
||||
static const socket_address* cast_from(const sockaddr* sa) { return reinterpret_cast<const socket_address*>(sa); }
|
||||
@@ -215,6 +223,8 @@ public:
|
||||
|
||||
void set_address_any() { set_port(0); set_address(in6addr_any); }
|
||||
|
||||
std::string pretty_address_str() const;
|
||||
|
||||
sa_family_t family() const { return m_sockaddr.sin6_family; }
|
||||
void set_family() { m_sockaddr.sin6_family = AF_INET6; }
|
||||
|
||||
@@ -233,6 +243,18 @@ private:
|
||||
struct sockaddr_in6 m_sockaddr;
|
||||
};
|
||||
|
||||
inline bool
|
||||
socket_address::is_any() const {
|
||||
switch (family()) {
|
||||
case af_inet:
|
||||
return sa_inet()->is_any();
|
||||
case af_inet6:
|
||||
return sa_inet6()->is_any();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool
|
||||
socket_address::is_valid() const {
|
||||
switch (family()) {
|
||||
@@ -317,6 +339,21 @@ socket_address::address_c_str(char* buf, socklen_t size) const {
|
||||
}
|
||||
}
|
||||
|
||||
inline std::string
|
||||
socket_address::pretty_address_str() const {
|
||||
switch (family()) {
|
||||
case af_inet:
|
||||
return sa_inet()->address_str();
|
||||
case af_inet6:
|
||||
return sa_inet6()->pretty_address_str();
|
||||
case af_unspec:
|
||||
return std::string("unspec");
|
||||
default:
|
||||
return std::string("invalid");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline bool
|
||||
socket_address::set_address_c_str(const char* a) {
|
||||
if (sa_inet()->set_address_c_str(a)) {
|
||||
@@ -348,13 +385,16 @@ socket_address::length() const {
|
||||
inline void
|
||||
socket_address::copy(const socket_address& src, size_t length) {
|
||||
length = std::min(length, sizeof(socket_address));
|
||||
|
||||
// Does this get properly optimized?
|
||||
|
||||
std::memset(this, 0, sizeof(socket_address));
|
||||
std::memcpy(this, &src, length);
|
||||
}
|
||||
|
||||
// Should we be able to compare af_unspec?
|
||||
inline void
|
||||
socket_address::copy_sockaddr(const sockaddr* src) {
|
||||
std::memset(this, 0, sizeof(socket_address));
|
||||
std::memcpy(this, src, socket_address::cast_from(src)->length());
|
||||
}
|
||||
|
||||
inline bool
|
||||
socket_address::operator == (const socket_address& rhs) const {
|
||||
@@ -456,6 +496,35 @@ socket_address_inet6::set_address_c_str(const char* a) {
|
||||
return inet_pton(AF_INET6, a, &m_sockaddr.sin6_addr);
|
||||
}
|
||||
|
||||
inline std::string
|
||||
socket_address_inet6::pretty_address_str() const {
|
||||
char buf[INET6_ADDRSTRLEN + 2 + 6];
|
||||
|
||||
if (inet_ntop(family(), &m_sockaddr.sin6_addr, buf + 1, INET6_ADDRSTRLEN) == NULL)
|
||||
return std::string();
|
||||
|
||||
buf[0] = '[';
|
||||
|
||||
char* last_char = (char*)std::memchr(buf + 1, 0, INET6_ADDRSTRLEN);
|
||||
|
||||
// TODO: Throw exception here.
|
||||
|
||||
if (last_char == NULL || last_char >= buf + 1 + INET6_ADDRSTRLEN)
|
||||
throw std::logic_error("inet_ntop for inet6 returned bad buffer");
|
||||
|
||||
*(last_char++) = ']';
|
||||
|
||||
if (!is_port_any()) {
|
||||
if (snprintf(last_char, 7, ":%" PRIu16, port()) == -1)
|
||||
return std::string("error"); // TODO: Throw here.
|
||||
|
||||
} else {
|
||||
*last_char = '\0';
|
||||
}
|
||||
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
inline socket_address
|
||||
socket_address_inet6::normalize_address() const {
|
||||
const uint32_t *addr32 = reinterpret_cast<const uint32_t *>(m_sockaddr.sin6_addr.s6_addr);
|
||||
|
||||
+57
-6
@@ -39,9 +39,13 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <climits>
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <locale>
|
||||
#include <random>
|
||||
|
||||
|
||||
namespace rak {
|
||||
|
||||
@@ -139,8 +143,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;
|
||||
@@ -157,7 +161,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>();
|
||||
}
|
||||
|
||||
@@ -312,11 +316,13 @@ transform_hex_str(const Sequence& seq) {
|
||||
template <typename Sequence>
|
||||
Sequence
|
||||
generate_random(size_t length) {
|
||||
std::random_device rd;
|
||||
std::mt19937 mt(rd());
|
||||
using bytes_randomizer = std::independent_bits_engine<std::mt19937, CHAR_BIT, uint8_t>;
|
||||
bytes_randomizer bytes(mt);
|
||||
Sequence s;
|
||||
s.reserve(length);
|
||||
|
||||
std::generate_n(std::back_inserter(s), length, &::random);
|
||||
|
||||
std::generate_n(std::back_inserter(s), length, std::ref(bytes));
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -371,6 +377,51 @@ is_all_name(const Sequence& src) {
|
||||
return is_all_name(src.begin(), src.end());
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
std::string
|
||||
sanitize(Iterator first, Iterator last) {
|
||||
std::string dest;
|
||||
for (; first != last; ++first) {
|
||||
if (std::isprint(*first) && *first != '\r' && *first != '\n' && *first != '\t')
|
||||
dest += *first;
|
||||
else
|
||||
dest += " ";
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
template <typename Sequence>
|
||||
std::string
|
||||
sanitize(const Sequence& src) {
|
||||
return trim(sanitize(src.begin(), src.end()));
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
std::string striptags(Iterator first, Iterator last) {
|
||||
bool copychar = true;
|
||||
std::string dest;
|
||||
|
||||
for (; first != last; ++first) {
|
||||
if (std::isprint(*first) && *first == '<') {
|
||||
copychar = false;
|
||||
} else if (std::isprint(*first) && *first == '>') {
|
||||
copychar = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (copychar)
|
||||
dest += *first;
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
template <typename Sequence>
|
||||
std::string striptags(const Sequence& src) {
|
||||
return striptags(src.begin(), src.end());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
-110
@@ -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 <inttypes.h>
|
||||
#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
|
||||
@@ -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
|
||||
@@ -107,25 +107,6 @@ AC_DEFUN([CC_ATTRIBUTE_NONNULL], [
|
||||
fi
|
||||
])
|
||||
|
||||
AC_DEFUN([CC_ATTRIBUTE_UNUSED], [
|
||||
AC_CACHE_CHECK([if compiler supports __attribute__((unused))],
|
||||
[cc_cv_attribute_unused],
|
||||
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([
|
||||
void some_function(void *foo, __attribute__((unused)) void *bar);
|
||||
])],
|
||||
[cc_cv_attribute_unused=yes],
|
||||
[cc_cv_attribute_unused=no])
|
||||
])
|
||||
|
||||
if test "x$cc_cv_attribute_unused" = "xyes"; then
|
||||
AC_DEFINE([SUPPORT_ATTRIBUTE_UNUSED], 1, [Define this if the compiler supports the unused attribute])
|
||||
$1
|
||||
else
|
||||
true
|
||||
$2
|
||||
fi
|
||||
])
|
||||
|
||||
AC_DEFUN([CC_FUNC_EXPECT], [
|
||||
AC_CACHE_CHECK([if compiler has __builtin_expect function],
|
||||
[cc_cv_func_expect],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# ===========================================================================
|
||||
# http://www.gnu.org/software/autoconf-archive/ax_check_zlib.html
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_check_zlib.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
@@ -47,7 +47,7 @@
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# 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
|
||||
@@ -62,7 +62,7 @@
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
#serial 14
|
||||
#serial 16
|
||||
|
||||
AU_ALIAS([CHECK_ZLIB], [AX_CHECK_ZLIB])
|
||||
AC_DEFUN([AX_CHECK_ZLIB],
|
||||
@@ -108,11 +108,10 @@ then
|
||||
LDFLAGS="$LDFLAGS -L${ZLIB_HOME}/lib"
|
||||
CPPFLAGS="$CPPFLAGS -I${ZLIB_HOME}/include"
|
||||
fi
|
||||
AC_LANG_SAVE
|
||||
AC_LANG_C
|
||||
AC_LANG_PUSH([C])
|
||||
AC_CHECK_LIB([z], [inflateEnd], [zlib_cv_libz=yes], [zlib_cv_libz=no])
|
||||
AC_CHECK_HEADER([zlib.h], [zlib_cv_zlib_h=yes], [zlib_cv_zlib_h=no])
|
||||
AC_LANG_RESTORE
|
||||
AC_LANG_POP([C])
|
||||
if test "$zlib_cv_libz" = "yes" && test "$zlib_cv_zlib_h" = "yes"
|
||||
then
|
||||
#
|
||||
|
||||
@@ -0,0 +1,962 @@
|
||||
# ===========================================================================
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Check for baseline language coverage in the compiler for the specified
|
||||
# version of the C++ standard. If necessary, add switches to CXX and
|
||||
# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard)
|
||||
# or '14' (for the C++14 standard).
|
||||
#
|
||||
# The second argument, if specified, indicates whether you insist on an
|
||||
# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
|
||||
# -std=c++11). If neither is specified, you get whatever works, with
|
||||
# preference for no added switch, and then for an extended mode.
|
||||
#
|
||||
# The third argument, if specified 'mandatory' or if left unspecified,
|
||||
# indicates that baseline support for the specified C++ standard is
|
||||
# required and that the macro should error out if no mode with that
|
||||
# support is found. If specified 'optional', then configuration proceeds
|
||||
# regardless, after defining HAVE_CXX${VERSION} if and only if a
|
||||
# supporting mode is found.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
|
||||
# Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
|
||||
# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
|
||||
# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
|
||||
# Copyright (c) 2015 Paul Norman <penorman@mac.com>
|
||||
# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
|
||||
# Copyright (c) 2016, 2018 Krzesimir Nowak <qdlacz@gmail.com>
|
||||
# Copyright (c) 2019 Enji Cooper <yaneurabeya@gmail.com>
|
||||
# Copyright (c) 2020 Jason Merrill <jason@redhat.com>
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification, are
|
||||
# permitted in any medium without royalty provided the copyright notice
|
||||
# and this notice are preserved. This file is offered as-is, without any
|
||||
# warranty.
|
||||
|
||||
#serial 12
|
||||
|
||||
dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
|
||||
dnl (serial version number 13).
|
||||
|
||||
AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
|
||||
m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
|
||||
[$1], [14], [ax_cxx_compile_alternatives="14 1y"],
|
||||
[$1], [17], [ax_cxx_compile_alternatives="17 1z"],
|
||||
[m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
|
||||
m4_if([$2], [], [],
|
||||
[$2], [ext], [],
|
||||
[$2], [noext], [],
|
||||
[m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
|
||||
m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
|
||||
[$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
|
||||
[$3], [optional], [ax_cxx_compile_cxx$1_required=false],
|
||||
[m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
|
||||
AC_LANG_PUSH([C++])dnl
|
||||
ac_success=no
|
||||
|
||||
m4_if([$2], [], [dnl
|
||||
AC_CACHE_CHECK(whether $CXX supports C++$1 features by default,
|
||||
ax_cv_cxx_compile_cxx$1,
|
||||
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
|
||||
[ax_cv_cxx_compile_cxx$1=yes],
|
||||
[ax_cv_cxx_compile_cxx$1=no])])
|
||||
if test x$ax_cv_cxx_compile_cxx$1 = xyes; then
|
||||
ac_success=yes
|
||||
fi])
|
||||
|
||||
m4_if([$2], [noext], [], [dnl
|
||||
if test x$ac_success = xno; then
|
||||
for alternative in ${ax_cxx_compile_alternatives}; do
|
||||
switch="-std=gnu++${alternative}"
|
||||
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
|
||||
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
|
||||
$cachevar,
|
||||
[ac_save_CXX="$CXX"
|
||||
CXX="$CXX $switch"
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
|
||||
[eval $cachevar=yes],
|
||||
[eval $cachevar=no])
|
||||
CXX="$ac_save_CXX"])
|
||||
if eval test x\$$cachevar = xyes; then
|
||||
CXX="$CXX $switch"
|
||||
if test -n "$CXXCPP" ; then
|
||||
CXXCPP="$CXXCPP $switch"
|
||||
fi
|
||||
ac_success=yes
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi])
|
||||
|
||||
m4_if([$2], [ext], [], [dnl
|
||||
if test x$ac_success = xno; then
|
||||
dnl HP's aCC needs +std=c++11 according to:
|
||||
dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
|
||||
dnl Cray's crayCC needs "-h std=c++11"
|
||||
for alternative in ${ax_cxx_compile_alternatives}; do
|
||||
for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do
|
||||
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
|
||||
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
|
||||
$cachevar,
|
||||
[ac_save_CXX="$CXX"
|
||||
CXX="$CXX $switch"
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
|
||||
[eval $cachevar=yes],
|
||||
[eval $cachevar=no])
|
||||
CXX="$ac_save_CXX"])
|
||||
if eval test x\$$cachevar = xyes; then
|
||||
CXX="$CXX $switch"
|
||||
if test -n "$CXXCPP" ; then
|
||||
CXXCPP="$CXXCPP $switch"
|
||||
fi
|
||||
ac_success=yes
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test x$ac_success = xyes; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi])
|
||||
AC_LANG_POP([C++])
|
||||
if test x$ax_cxx_compile_cxx$1_required = xtrue; then
|
||||
if test x$ac_success = xno; then
|
||||
AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
|
||||
fi
|
||||
fi
|
||||
if test x$ac_success = xno; then
|
||||
HAVE_CXX$1=0
|
||||
AC_MSG_NOTICE([No compiler with C++$1 support was found])
|
||||
else
|
||||
HAVE_CXX$1=1
|
||||
AC_DEFINE(HAVE_CXX$1,1,
|
||||
[define if the compiler supports basic C++$1 syntax])
|
||||
fi
|
||||
AC_SUBST(HAVE_CXX$1)
|
||||
])
|
||||
|
||||
|
||||
dnl Test body for checking C++11 support
|
||||
|
||||
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
|
||||
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||
)
|
||||
|
||||
|
||||
dnl Test body for checking C++14 support
|
||||
|
||||
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
|
||||
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
|
||||
)
|
||||
|
||||
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
|
||||
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
|
||||
_AX_CXX_COMPILE_STDCXX_testbody_new_in_17
|
||||
)
|
||||
|
||||
dnl Tests for new features in C++11
|
||||
|
||||
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
|
||||
|
||||
// If the compiler admits that it is not ready for C++11, why torture it?
|
||||
// Hopefully, this will speed up the test.
|
||||
|
||||
#ifndef __cplusplus
|
||||
|
||||
#error "This is not a C++ compiler"
|
||||
|
||||
#elif __cplusplus < 201103L
|
||||
|
||||
#error "This is not a C++11 compiler"
|
||||
|
||||
#else
|
||||
|
||||
namespace cxx11
|
||||
{
|
||||
|
||||
namespace test_static_assert
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
struct check
|
||||
{
|
||||
static_assert(sizeof(int) <= sizeof(T), "not big enough");
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace test_final_override
|
||||
{
|
||||
|
||||
struct Base
|
||||
{
|
||||
virtual ~Base() {}
|
||||
virtual void f() {}
|
||||
};
|
||||
|
||||
struct Derived : public Base
|
||||
{
|
||||
virtual ~Derived() override {}
|
||||
virtual void f() override {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace test_double_right_angle_brackets
|
||||
{
|
||||
|
||||
template < typename T >
|
||||
struct check {};
|
||||
|
||||
typedef check<void> single_type;
|
||||
typedef check<check<void>> double_type;
|
||||
typedef check<check<check<void>>> triple_type;
|
||||
typedef check<check<check<check<void>>>> quadruple_type;
|
||||
|
||||
}
|
||||
|
||||
namespace test_decltype
|
||||
{
|
||||
|
||||
int
|
||||
f()
|
||||
{
|
||||
int a = 1;
|
||||
decltype(a) b = 2;
|
||||
return a + b;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_type_deduction
|
||||
{
|
||||
|
||||
template < typename T1, typename T2 >
|
||||
struct is_same
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
struct is_same<T, T>
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template < typename T1, typename T2 >
|
||||
auto
|
||||
add(T1 a1, T2 a2) -> decltype(a1 + a2)
|
||||
{
|
||||
return a1 + a2;
|
||||
}
|
||||
|
||||
int
|
||||
test(const int c, volatile int v)
|
||||
{
|
||||
static_assert(is_same<int, decltype(0)>::value == true, "");
|
||||
static_assert(is_same<int, decltype(c)>::value == false, "");
|
||||
static_assert(is_same<int, decltype(v)>::value == false, "");
|
||||
auto ac = c;
|
||||
auto av = v;
|
||||
auto sumi = ac + av + 'x';
|
||||
auto sumf = ac + av + 1.0;
|
||||
static_assert(is_same<int, decltype(ac)>::value == true, "");
|
||||
static_assert(is_same<int, decltype(av)>::value == true, "");
|
||||
static_assert(is_same<int, decltype(sumi)>::value == true, "");
|
||||
static_assert(is_same<int, decltype(sumf)>::value == false, "");
|
||||
static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
|
||||
return (sumf > 0.0) ? sumi : add(c, v);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_noexcept
|
||||
{
|
||||
|
||||
int f() { return 0; }
|
||||
int g() noexcept { return 0; }
|
||||
|
||||
static_assert(noexcept(f()) == false, "");
|
||||
static_assert(noexcept(g()) == true, "");
|
||||
|
||||
}
|
||||
|
||||
namespace test_constexpr
|
||||
{
|
||||
|
||||
template < typename CharT >
|
||||
unsigned long constexpr
|
||||
strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
|
||||
{
|
||||
return *s ? strlen_c_r(s + 1, acc + 1) : acc;
|
||||
}
|
||||
|
||||
template < typename CharT >
|
||||
unsigned long constexpr
|
||||
strlen_c(const CharT *const s) noexcept
|
||||
{
|
||||
return strlen_c_r(s, 0UL);
|
||||
}
|
||||
|
||||
static_assert(strlen_c("") == 0UL, "");
|
||||
static_assert(strlen_c("1") == 1UL, "");
|
||||
static_assert(strlen_c("example") == 7UL, "");
|
||||
static_assert(strlen_c("another\0example") == 7UL, "");
|
||||
|
||||
}
|
||||
|
||||
namespace test_rvalue_references
|
||||
{
|
||||
|
||||
template < int N >
|
||||
struct answer
|
||||
{
|
||||
static constexpr int value = N;
|
||||
};
|
||||
|
||||
answer<1> f(int&) { return answer<1>(); }
|
||||
answer<2> f(const int&) { return answer<2>(); }
|
||||
answer<3> f(int&&) { return answer<3>(); }
|
||||
|
||||
void
|
||||
test()
|
||||
{
|
||||
int i = 0;
|
||||
const int c = 0;
|
||||
static_assert(decltype(f(i))::value == 1, "");
|
||||
static_assert(decltype(f(c))::value == 2, "");
|
||||
static_assert(decltype(f(0))::value == 3, "");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_uniform_initialization
|
||||
{
|
||||
|
||||
struct test
|
||||
{
|
||||
static const int zero {};
|
||||
static const int one {1};
|
||||
};
|
||||
|
||||
static_assert(test::zero == 0, "");
|
||||
static_assert(test::one == 1, "");
|
||||
|
||||
}
|
||||
|
||||
namespace test_lambdas
|
||||
{
|
||||
|
||||
void
|
||||
test1()
|
||||
{
|
||||
auto lambda1 = [](){};
|
||||
auto lambda2 = lambda1;
|
||||
lambda1();
|
||||
lambda2();
|
||||
}
|
||||
|
||||
int
|
||||
test2()
|
||||
{
|
||||
auto a = [](int i, int j){ return i + j; }(1, 2);
|
||||
auto b = []() -> int { return '0'; }();
|
||||
auto c = [=](){ return a + b; }();
|
||||
auto d = [&](){ return c; }();
|
||||
auto e = [a, &b](int x) mutable {
|
||||
const auto identity = [](int y){ return y; };
|
||||
for (auto i = 0; i < a; ++i)
|
||||
a += b--;
|
||||
return x + identity(a + b);
|
||||
}(0);
|
||||
return a + b + c + d + e;
|
||||
}
|
||||
|
||||
int
|
||||
test3()
|
||||
{
|
||||
const auto nullary = [](){ return 0; };
|
||||
const auto unary = [](int x){ return x; };
|
||||
using nullary_t = decltype(nullary);
|
||||
using unary_t = decltype(unary);
|
||||
const auto higher1st = [](nullary_t f){ return f(); };
|
||||
const auto higher2nd = [unary](nullary_t f1){
|
||||
return [unary, f1](unary_t f2){ return f2(unary(f1())); };
|
||||
};
|
||||
return higher1st(nullary) + higher2nd(nullary)(unary);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_variadic_templates
|
||||
{
|
||||
|
||||
template <int...>
|
||||
struct sum;
|
||||
|
||||
template <int N0, int... N1toN>
|
||||
struct sum<N0, N1toN...>
|
||||
{
|
||||
static constexpr auto value = N0 + sum<N1toN...>::value;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct sum<>
|
||||
{
|
||||
static constexpr auto value = 0;
|
||||
};
|
||||
|
||||
static_assert(sum<>::value == 0, "");
|
||||
static_assert(sum<1>::value == 1, "");
|
||||
static_assert(sum<23>::value == 23, "");
|
||||
static_assert(sum<1, 2>::value == 3, "");
|
||||
static_assert(sum<5, 5, 11>::value == 21, "");
|
||||
static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
|
||||
|
||||
}
|
||||
|
||||
// http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
|
||||
// Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
|
||||
// because of this.
|
||||
namespace test_template_alias_sfinae
|
||||
{
|
||||
|
||||
struct foo {};
|
||||
|
||||
template<typename T>
|
||||
using member = typename T::member_type;
|
||||
|
||||
template<typename T>
|
||||
void func(...) {}
|
||||
|
||||
template<typename T>
|
||||
void func(member<T>*) {}
|
||||
|
||||
void test();
|
||||
|
||||
void test() { func<foo>(0); }
|
||||
|
||||
}
|
||||
|
||||
} // namespace cxx11
|
||||
|
||||
#endif // __cplusplus >= 201103L
|
||||
|
||||
]])
|
||||
|
||||
|
||||
dnl Tests for new features in C++14
|
||||
|
||||
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
|
||||
|
||||
// If the compiler admits that it is not ready for C++14, why torture it?
|
||||
// Hopefully, this will speed up the test.
|
||||
|
||||
#ifndef __cplusplus
|
||||
|
||||
#error "This is not a C++ compiler"
|
||||
|
||||
#elif __cplusplus < 201402L
|
||||
|
||||
#error "This is not a C++14 compiler"
|
||||
|
||||
#else
|
||||
|
||||
namespace cxx14
|
||||
{
|
||||
|
||||
namespace test_polymorphic_lambdas
|
||||
{
|
||||
|
||||
int
|
||||
test()
|
||||
{
|
||||
const auto lambda = [](auto&&... args){
|
||||
const auto istiny = [](auto x){
|
||||
return (sizeof(x) == 1UL) ? 1 : 0;
|
||||
};
|
||||
const int aretiny[] = { istiny(args)... };
|
||||
return aretiny[0];
|
||||
};
|
||||
return lambda(1, 1L, 1.0f, '1');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_binary_literals
|
||||
{
|
||||
|
||||
constexpr auto ivii = 0b0000000000101010;
|
||||
static_assert(ivii == 42, "wrong value");
|
||||
|
||||
}
|
||||
|
||||
namespace test_generalized_constexpr
|
||||
{
|
||||
|
||||
template < typename CharT >
|
||||
constexpr unsigned long
|
||||
strlen_c(const CharT *const s) noexcept
|
||||
{
|
||||
auto length = 0UL;
|
||||
for (auto p = s; *p; ++p)
|
||||
++length;
|
||||
return length;
|
||||
}
|
||||
|
||||
static_assert(strlen_c("") == 0UL, "");
|
||||
static_assert(strlen_c("x") == 1UL, "");
|
||||
static_assert(strlen_c("test") == 4UL, "");
|
||||
static_assert(strlen_c("another\0test") == 7UL, "");
|
||||
|
||||
}
|
||||
|
||||
namespace test_lambda_init_capture
|
||||
{
|
||||
|
||||
int
|
||||
test()
|
||||
{
|
||||
auto x = 0;
|
||||
const auto lambda1 = [a = x](int b){ return a + b; };
|
||||
const auto lambda2 = [a = lambda1(x)](){ return a; };
|
||||
return lambda2();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_digit_separators
|
||||
{
|
||||
|
||||
constexpr auto ten_million = 100'000'000;
|
||||
static_assert(ten_million == 100000000, "");
|
||||
|
||||
}
|
||||
|
||||
namespace test_return_type_deduction
|
||||
{
|
||||
|
||||
auto f(int& x) { return x; }
|
||||
decltype(auto) g(int& x) { return x; }
|
||||
|
||||
template < typename T1, typename T2 >
|
||||
struct is_same
|
||||
{
|
||||
static constexpr auto value = false;
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
struct is_same<T, T>
|
||||
{
|
||||
static constexpr auto value = true;
|
||||
};
|
||||
|
||||
int
|
||||
test()
|
||||
{
|
||||
auto x = 0;
|
||||
static_assert(is_same<int, decltype(f(x))>::value, "");
|
||||
static_assert(is_same<int&, decltype(g(x))>::value, "");
|
||||
return x;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace cxx14
|
||||
|
||||
#endif // __cplusplus >= 201402L
|
||||
|
||||
]])
|
||||
|
||||
|
||||
dnl Tests for new features in C++17
|
||||
|
||||
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[
|
||||
|
||||
// If the compiler admits that it is not ready for C++17, why torture it?
|
||||
// Hopefully, this will speed up the test.
|
||||
|
||||
#ifndef __cplusplus
|
||||
|
||||
#error "This is not a C++ compiler"
|
||||
|
||||
#elif __cplusplus < 201703L
|
||||
|
||||
#error "This is not a C++17 compiler"
|
||||
|
||||
#else
|
||||
|
||||
#include <initializer_list>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
|
||||
namespace cxx17
|
||||
{
|
||||
|
||||
namespace test_constexpr_lambdas
|
||||
{
|
||||
|
||||
constexpr int foo = [](){return 42;}();
|
||||
|
||||
}
|
||||
|
||||
namespace test::nested_namespace::definitions
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
namespace test_fold_expression
|
||||
{
|
||||
|
||||
template<typename... Args>
|
||||
int multiply(Args... args)
|
||||
{
|
||||
return (args * ... * 1);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
bool all(Args... args)
|
||||
{
|
||||
return (args && ...);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_extended_static_assert
|
||||
{
|
||||
|
||||
static_assert (true);
|
||||
|
||||
}
|
||||
|
||||
namespace test_auto_brace_init_list
|
||||
{
|
||||
|
||||
auto foo = {5};
|
||||
auto bar {5};
|
||||
|
||||
static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);
|
||||
static_assert(std::is_same<int, decltype(bar)>::value);
|
||||
}
|
||||
|
||||
namespace test_typename_in_template_template_parameter
|
||||
{
|
||||
|
||||
template<template<typename> typename X> struct D;
|
||||
|
||||
}
|
||||
|
||||
namespace test_fallthrough_nodiscard_maybe_unused_attributes
|
||||
{
|
||||
|
||||
int f1()
|
||||
{
|
||||
return 42;
|
||||
}
|
||||
|
||||
[[nodiscard]] int f2()
|
||||
{
|
||||
[[maybe_unused]] auto unused = f1();
|
||||
|
||||
switch (f1())
|
||||
{
|
||||
case 17:
|
||||
f1();
|
||||
[[fallthrough]];
|
||||
case 42:
|
||||
f1();
|
||||
}
|
||||
return f1();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_extended_aggregate_initialization
|
||||
{
|
||||
|
||||
struct base1
|
||||
{
|
||||
int b1, b2 = 42;
|
||||
};
|
||||
|
||||
struct base2
|
||||
{
|
||||
base2() {
|
||||
b3 = 42;
|
||||
}
|
||||
int b3;
|
||||
};
|
||||
|
||||
struct derived : base1, base2
|
||||
{
|
||||
int d;
|
||||
};
|
||||
|
||||
derived d1 {{1, 2}, {}, 4}; // full initialization
|
||||
derived d2 {{}, {}, 4}; // value-initialized bases
|
||||
|
||||
}
|
||||
|
||||
namespace test_general_range_based_for_loop
|
||||
{
|
||||
|
||||
struct iter
|
||||
{
|
||||
int i;
|
||||
|
||||
int& operator* ()
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
const int& operator* () const
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
iter& operator++()
|
||||
{
|
||||
++i;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct sentinel
|
||||
{
|
||||
int i;
|
||||
};
|
||||
|
||||
bool operator== (const iter& i, const sentinel& s)
|
||||
{
|
||||
return i.i == s.i;
|
||||
}
|
||||
|
||||
bool operator!= (const iter& i, const sentinel& s)
|
||||
{
|
||||
return !(i == s);
|
||||
}
|
||||
|
||||
struct range
|
||||
{
|
||||
iter begin() const
|
||||
{
|
||||
return {0};
|
||||
}
|
||||
|
||||
sentinel end() const
|
||||
{
|
||||
return {5};
|
||||
}
|
||||
};
|
||||
|
||||
void f()
|
||||
{
|
||||
range r {};
|
||||
|
||||
for (auto i : r)
|
||||
{
|
||||
[[maybe_unused]] auto v = i;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_lambda_capture_asterisk_this_by_value
|
||||
{
|
||||
|
||||
struct t
|
||||
{
|
||||
int i;
|
||||
int foo()
|
||||
{
|
||||
return [*this]()
|
||||
{
|
||||
return i;
|
||||
}();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace test_enum_class_construction
|
||||
{
|
||||
|
||||
enum class byte : unsigned char
|
||||
{};
|
||||
|
||||
byte foo {42};
|
||||
|
||||
}
|
||||
|
||||
namespace test_constexpr_if
|
||||
{
|
||||
|
||||
template <bool cond>
|
||||
int f ()
|
||||
{
|
||||
if constexpr(cond)
|
||||
{
|
||||
return 13;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 42;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_selection_statement_with_initializer
|
||||
{
|
||||
|
||||
int f()
|
||||
{
|
||||
return 13;
|
||||
}
|
||||
|
||||
int f2()
|
||||
{
|
||||
if (auto i = f(); i > 0)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
switch (auto i = f(); i + 4)
|
||||
{
|
||||
case 17:
|
||||
return 2;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_template_argument_deduction_for_class_templates
|
||||
{
|
||||
|
||||
template <typename T1, typename T2>
|
||||
struct pair
|
||||
{
|
||||
pair (T1 p1, T2 p2)
|
||||
: m1 {p1},
|
||||
m2 {p2}
|
||||
{}
|
||||
|
||||
T1 m1;
|
||||
T2 m2;
|
||||
};
|
||||
|
||||
void f()
|
||||
{
|
||||
[[maybe_unused]] auto p = pair{13, 42u};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_non_type_auto_template_parameters
|
||||
{
|
||||
|
||||
template <auto n>
|
||||
struct B
|
||||
{};
|
||||
|
||||
B<5> b1;
|
||||
B<'a'> b2;
|
||||
|
||||
}
|
||||
|
||||
namespace test_structured_bindings
|
||||
{
|
||||
|
||||
int arr[2] = { 1, 2 };
|
||||
std::pair<int, int> pr = { 1, 2 };
|
||||
|
||||
auto f1() -> int(&)[2]
|
||||
{
|
||||
return arr;
|
||||
}
|
||||
|
||||
auto f2() -> std::pair<int, int>&
|
||||
{
|
||||
return pr;
|
||||
}
|
||||
|
||||
struct S
|
||||
{
|
||||
int x1 : 2;
|
||||
volatile double y1;
|
||||
};
|
||||
|
||||
S f3()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
auto [ x1, y1 ] = f1();
|
||||
auto& [ xr1, yr1 ] = f1();
|
||||
auto [ x2, y2 ] = f2();
|
||||
auto& [ xr2, yr2 ] = f2();
|
||||
const auto [ x3, y3 ] = f3();
|
||||
|
||||
}
|
||||
|
||||
namespace test_exception_spec_type_system
|
||||
{
|
||||
|
||||
struct Good {};
|
||||
struct Bad {};
|
||||
|
||||
void g1() noexcept;
|
||||
void g2();
|
||||
|
||||
template<typename T>
|
||||
Bad
|
||||
f(T*, T*);
|
||||
|
||||
template<typename T1, typename T2>
|
||||
Good
|
||||
f(T1*, T2*);
|
||||
|
||||
static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);
|
||||
|
||||
}
|
||||
|
||||
namespace test_inline_variables
|
||||
{
|
||||
|
||||
template<class T> void f(T)
|
||||
{}
|
||||
|
||||
template<class T> inline T g(T)
|
||||
{
|
||||
return T{};
|
||||
}
|
||||
|
||||
template<> inline void f<>(int)
|
||||
{}
|
||||
|
||||
template<> int g<>(int)
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace cxx17
|
||||
|
||||
#endif // __cplusplus < 201703L
|
||||
|
||||
]])
|
||||
@@ -1,106 +0,0 @@
|
||||
# ============================================================================
|
||||
# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_0x.html
|
||||
# ============================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_CXX_COMPILE_STDCXX_0X
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Check for baseline language coverage in the compiler for the C++0x
|
||||
# standard.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification, are
|
||||
# permitted in any medium without royalty provided the copyright notice
|
||||
# and this notice are preserved. This file is offered as-is, without any
|
||||
# warranty.
|
||||
|
||||
#serial 7 (+1)
|
||||
|
||||
AU_ALIAS([AC_CXX_COMPILE_STDCXX_0X], [AX_CXX_COMPILE_STDCXX_0X])
|
||||
AC_DEFUN([AX_CXX_COMPILE_STDCXX_0X], [
|
||||
AC_CACHE_CHECK(if g++ supports C++0x features without additional flags,
|
||||
ax_cv_cxx_compile_cxx0x_native,
|
||||
[AC_LANG_SAVE
|
||||
AC_LANG_CPLUSPLUS
|
||||
AC_TRY_COMPILE([
|
||||
template <typename T>
|
||||
struct check
|
||||
{
|
||||
static_assert(sizeof(int) <= sizeof(T), "not big enough");
|
||||
};
|
||||
|
||||
typedef check<check<bool>> right_angle_brackets;
|
||||
|
||||
int a;
|
||||
decltype(a) b;
|
||||
|
||||
typedef check<int> check_type;
|
||||
check_type c;
|
||||
check_type&& cr = static_cast<check_type&&>(c);],,
|
||||
ax_cv_cxx_compile_cxx0x_native=yes, ax_cv_cxx_compile_cxx0x_native=no)
|
||||
AC_LANG_RESTORE
|
||||
])
|
||||
|
||||
AC_CACHE_CHECK(if g++ supports C++0x features with -std=c++0x,
|
||||
ax_cv_cxx_compile_cxx0x_cxx,
|
||||
[AC_LANG_SAVE
|
||||
AC_LANG_CPLUSPLUS
|
||||
ac_save_CXXFLAGS="$CXXFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS -std=c++0x"
|
||||
AC_TRY_COMPILE([
|
||||
template <typename T>
|
||||
struct check
|
||||
{
|
||||
static_assert(sizeof(int) <= sizeof(T), "not big enough");
|
||||
};
|
||||
|
||||
typedef check<check<bool>> right_angle_brackets;
|
||||
|
||||
int a;
|
||||
decltype(a) b;
|
||||
|
||||
typedef check<int> check_type;
|
||||
check_type c;
|
||||
check_type&& cr = static_cast<check_type&&>(c);],,
|
||||
ax_cv_cxx_compile_cxx0x_cxx=yes, ax_cv_cxx_compile_cxx0x_cxx=no)
|
||||
CXXFLAGS="$ac_save_CXXFLAGS"
|
||||
AC_LANG_RESTORE
|
||||
])
|
||||
|
||||
AC_CACHE_CHECK(if g++ supports C++0x features with -std=gnu++0x,
|
||||
ax_cv_cxx_compile_cxx0x_gxx,
|
||||
[AC_LANG_SAVE
|
||||
AC_LANG_CPLUSPLUS
|
||||
ac_save_CXXFLAGS="$CXXFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS -std=gnu++0x"
|
||||
AC_TRY_COMPILE([
|
||||
template <typename T>
|
||||
struct check
|
||||
{
|
||||
static_assert(sizeof(int) <= sizeof(T), "not big enough");
|
||||
};
|
||||
|
||||
typedef check<check<bool>> right_angle_brackets;
|
||||
|
||||
int a;
|
||||
decltype(a) b;
|
||||
|
||||
typedef check<int> check_type;
|
||||
check_type c;
|
||||
check_type&& cr = static_cast<check_type&&>(c);],,
|
||||
ax_cv_cxx_compile_cxx0x_gxx=yes, ax_cv_cxx_compile_cxx0x_gxx=no)
|
||||
CXXFLAGS="$ac_save_CXXFLAGS"
|
||||
AC_LANG_RESTORE
|
||||
])
|
||||
|
||||
if test "$ax_cv_cxx_compile_cxx0x_cxx" = yes; then
|
||||
AC_DEFINE(HAVE_STDCXX_0X,, [Define if compiler supports C++0x features.])
|
||||
CXXFLAGS="$CXXFLAGS -std=c++0x"
|
||||
fi
|
||||
])
|
||||
@@ -1,147 +0,0 @@
|
||||
# ============================================================================
|
||||
# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html
|
||||
# ============================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Check for baseline language coverage in the compiler for the C++11
|
||||
# standard; if necessary, add switches to CXXFLAGS to enable support.
|
||||
#
|
||||
# The first argument, if specified, indicates whether you insist on an
|
||||
# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
|
||||
# -std=c++11). If neither is specified, you get whatever works, with
|
||||
# preference for an extended mode.
|
||||
#
|
||||
# The second argument, if specified 'mandatory' or if left unspecified,
|
||||
# indicates that baseline C++11 support is required and that the macro
|
||||
# should error out if no mode with that support is found. If specified
|
||||
# 'optional', then configuration proceeds regardless, after defining
|
||||
# HAVE_CXX11 if and only if a supporting mode is found.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
|
||||
# Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
|
||||
# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
|
||||
# Copyright (c) 2014 Alexey Sokolov <sokolov@google.com>
|
||||
# Copyright (c) 2014 Jari Sundell <sundell.software@gmail.com>
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification, are
|
||||
# permitted in any medium without royalty provided the copyright notice
|
||||
# and this notice are preserved. This file is offered as-is, without any
|
||||
# warranty.
|
||||
|
||||
#serial 5
|
||||
|
||||
m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [[
|
||||
template <typename T>
|
||||
struct check
|
||||
{
|
||||
static_assert(sizeof(int) <= sizeof(T), "not big enough");
|
||||
};
|
||||
|
||||
struct Base {
|
||||
virtual void f() {}
|
||||
};
|
||||
struct Child : public Base {
|
||||
virtual void f() override {}
|
||||
};
|
||||
|
||||
typedef check<check<bool>> right_angle_brackets;
|
||||
|
||||
int a;
|
||||
decltype(a) b;
|
||||
|
||||
typedef check<int> check_type;
|
||||
check_type c;
|
||||
check_type&& cr = static_cast<check_type&&>(c);
|
||||
|
||||
auto d = a;
|
||||
auto l = [](){};
|
||||
|
||||
void unused() {
|
||||
l();
|
||||
}
|
||||
]])
|
||||
|
||||
AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl
|
||||
m4_if([$1], [], [],
|
||||
[$1], [ext], [],
|
||||
[$1], [noext], [],
|
||||
[m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl
|
||||
m4_if([$2], [], [ax_cxx_compile_cxx11_required=true],
|
||||
[$2], [mandatory], [ax_cxx_compile_cxx11_required=true],
|
||||
[$2], [optional], [ax_cxx_compile_cxx11_required=false],
|
||||
[m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_11])])
|
||||
AC_LANG_PUSH([C++])dnl
|
||||
ac_success=no
|
||||
AC_CACHE_CHECK(whether $CXX supports C++11 features by default,
|
||||
ax_cv_cxx_compile_cxx11,
|
||||
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
|
||||
[ax_cv_cxx_compile_cxx11=yes],
|
||||
[ax_cv_cxx_compile_cxx11=no])])
|
||||
if test x$ax_cv_cxx_compile_cxx11 = xyes; then
|
||||
ac_success=yes
|
||||
fi
|
||||
|
||||
m4_if([$1], [noext], [], [dnl
|
||||
if test x$ac_success = xno; then
|
||||
for switch in -std=gnu++11 -std=gnu++0x; do
|
||||
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch])
|
||||
AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch,
|
||||
$cachevar,
|
||||
[ac_save_CXXFLAGS="$CXXFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS $switch"
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
|
||||
[eval $cachevar=yes],
|
||||
[eval $cachevar=no])
|
||||
CXXFLAGS="$ac_save_CXXFLAGS"])
|
||||
if eval test x\$$cachevar = xyes; then
|
||||
CXXFLAGS="$CXXFLAGS $switch"
|
||||
ac_success=yes
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi])
|
||||
|
||||
m4_if([$1], [ext], [], [dnl
|
||||
if test x$ac_success = xno; then
|
||||
for switch in -std=c++11 -std=c++0x; do
|
||||
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch])
|
||||
AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch,
|
||||
$cachevar,
|
||||
[ac_save_CXXFLAGS="$CXXFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS $switch"
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
|
||||
[eval $cachevar=yes],
|
||||
[eval $cachevar=no])
|
||||
CXXFLAGS="$ac_save_CXXFLAGS"])
|
||||
if eval test x\$$cachevar = xyes; then
|
||||
CXXFLAGS="$CXXFLAGS $switch"
|
||||
ac_success=yes
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi])
|
||||
AC_LANG_POP([C++])
|
||||
if test x$ax_cxx_compile_cxx11_required = xtrue; then
|
||||
if test x$ac_success = xno; then
|
||||
AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.])
|
||||
fi
|
||||
else
|
||||
if test x$ac_success = xno; then
|
||||
HAVE_CXX11=0
|
||||
AC_MSG_NOTICE([No compiler with C++11 support was found])
|
||||
else
|
||||
HAVE_CXX11=1
|
||||
AC_DEFINE(HAVE_CXX11,1,
|
||||
[define if the compiler supports basic C++11 syntax])
|
||||
fi
|
||||
|
||||
AC_SUBST(HAVE_CXX11)
|
||||
fi
|
||||
])
|
||||
@@ -0,0 +1,67 @@
|
||||
# ===========================================================================
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_execinfo.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_EXECINFO([ACTION-IF-EXECINFO-H-IS-FOUND], [ACTION-IF-EXECINFO-H-IS-NOT-FOUND], [ADDITIONAL-TYPES-LIST])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Checks for execinfo.h header and if the len parameter/return type can be
|
||||
# found from a list, also define backtrace_size_t to that type.
|
||||
#
|
||||
# By default the list of types to try contains int and size_t, but should
|
||||
# some yet undiscovered system use e.g. unsigned, the 3rd argument can be
|
||||
# used for extensions. I'd like to hear of further suggestions.
|
||||
#
|
||||
# Executes ACTION-IF-EXECINFO-H-IS-FOUND when present and the execinfo.h
|
||||
# header is found or ACTION-IF-EXECINFO-H-IS-NOT-FOUND in case the header
|
||||
# seems unavailable.
|
||||
#
|
||||
# Also adds -lexecinfo to LIBS on BSD if needed.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2014 Thomas Jahns <jahns@dkrz.de>
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification, are
|
||||
# permitted in any medium without royalty provided the copyright notice
|
||||
# and this notice are preserved. This file is offered as-is, without any
|
||||
# warranty.
|
||||
|
||||
#serial 2
|
||||
|
||||
AC_DEFUN([AX_EXECINFO],
|
||||
[AC_CHECK_HEADERS([execinfo.h])
|
||||
AS_IF([test x"$ac_cv_header_execinfo_h" = xyes],
|
||||
[AC_CACHE_CHECK([size parameter type for backtrace()],
|
||||
[ax_cv_proto_backtrace_type],
|
||||
[AC_LANG_PUSH([C])
|
||||
for ax_cv_proto_backtrace_type in size_t int m4_ifnblank([$3],[$3 ])none; do
|
||||
AS_IF([test "${ax_cv_proto_backtrace_type}" = none],
|
||||
[ax_cv_proto_backtrace_type= ; break])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
|
||||
#include <execinfo.h>
|
||||
extern
|
||||
${ax_cv_proto_backtrace_type} backtrace(void **addrlist, ${ax_cv_proto_backtrace_type} len);
|
||||
char **backtrace_symbols(void *const *buffer, ${ax_cv_proto_backtrace_type} size);
|
||||
])],
|
||||
[break])
|
||||
done
|
||||
AC_LANG_POP([C])])])
|
||||
AS_IF([test x${ax_cv_proto_backtrace_type} != x],
|
||||
[AC_DEFINE_UNQUOTED([backtrace_size_t], [$ax_cv_proto_backtrace_type],
|
||||
[Defined to return type of backtrace().])])
|
||||
AC_SEARCH_LIBS([backtrace],[execinfo])
|
||||
AS_IF([test x"${ax_cv_proto_backtrace_type}" != x -a x"$ac_cv_header_execinfo_h" = xyes -a x"$ac_cv_search_backtrace" != xno],
|
||||
[AC_DEFINE([HAVE_BACKTRACE],[1],
|
||||
[Defined if backtrace() could be fully identified.])
|
||||
]m4_ifnblank([$1],[$1
|
||||
]),m4_ifnblank([$2],[$2
|
||||
]))])
|
||||
dnl
|
||||
dnl Local Variables:
|
||||
dnl mode: autoconf
|
||||
dnl End:
|
||||
dnl
|
||||
@@ -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])
|
||||
])
|
||||
+335
-122
@@ -1,5 +1,5 @@
|
||||
# ===========================================================================
|
||||
# http://www.gnu.org/software/autoconf-archive/ax_pthread.html
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_pthread.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
@@ -14,24 +14,28 @@
|
||||
# flags that are needed. (The user can also force certain compiler
|
||||
# flags/libs to be tested by setting these environment variables.)
|
||||
#
|
||||
# Also sets PTHREAD_CC to any special C compiler that is needed for
|
||||
# multi-threaded programs (defaults to the value of CC otherwise). (This
|
||||
# is necessary on AIX to use the special cc_r compiler alias.)
|
||||
# Also sets PTHREAD_CC and PTHREAD_CXX to any special C compiler that is
|
||||
# needed for multi-threaded programs (defaults to the value of CC
|
||||
# respectively CXX otherwise). (This is necessary on e.g. AIX to use the
|
||||
# special cc_r/CC_r compiler alias.)
|
||||
#
|
||||
# NOTE: You are assumed to not only compile your program with these flags,
|
||||
# but also link it with them as well. e.g. you should link with
|
||||
# but also to link with them as well. For example, you might link with
|
||||
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
|
||||
# $PTHREAD_CXX $CXXFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
|
||||
#
|
||||
# If you are only building threads programs, you may wish to use these
|
||||
# If you are only building threaded programs, you may wish to use these
|
||||
# variables in your default LIBS, CFLAGS, and CC:
|
||||
#
|
||||
# LIBS="$PTHREAD_LIBS $LIBS"
|
||||
# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
# CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS"
|
||||
# CC="$PTHREAD_CC"
|
||||
# CXX="$PTHREAD_CXX"
|
||||
#
|
||||
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
|
||||
# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
|
||||
# (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
|
||||
# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
|
||||
# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
|
||||
#
|
||||
# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
|
||||
# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
|
||||
@@ -55,6 +59,7 @@
|
||||
#
|
||||
# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
|
||||
# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
|
||||
# Copyright (c) 2019 Marc Stevens <marc.stevens@cwi.nl>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
@@ -67,7 +72,7 @@
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# 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
|
||||
@@ -82,35 +87,41 @@
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
#serial 17
|
||||
#serial 31
|
||||
|
||||
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
|
||||
AC_DEFUN([AX_PTHREAD], [
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||
AC_REQUIRE([AC_PROG_CC])
|
||||
AC_REQUIRE([AC_PROG_SED])
|
||||
AC_LANG_PUSH([C])
|
||||
ax_pthread_ok=no
|
||||
|
||||
# We used to check for pthread.h first, but this fails if pthread.h
|
||||
# requires special compiler flags (e.g. on True64 or Sequent).
|
||||
# requires special compiler flags (e.g. on Tru64 or Sequent).
|
||||
# It gets checked for in the link test anyway.
|
||||
|
||||
# First of all, check if the user has set any of the PTHREAD_LIBS,
|
||||
# etcetera environment variables, and if threads linking works using
|
||||
# them:
|
||||
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
|
||||
save_CFLAGS="$CFLAGS"
|
||||
if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
|
||||
ax_pthread_save_CC="$CC"
|
||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||
ax_pthread_save_LIBS="$LIBS"
|
||||
AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
|
||||
AS_IF([test "x$PTHREAD_CXX" != "x"], [CXX="$PTHREAD_CXX"])
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
save_LIBS="$LIBS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
|
||||
AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes)
|
||||
AC_MSG_RESULT($ax_pthread_ok)
|
||||
if test x"$ax_pthread_ok" = xno; then
|
||||
AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
|
||||
AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])
|
||||
AC_MSG_RESULT([$ax_pthread_ok])
|
||||
if test "x$ax_pthread_ok" = "xno"; then
|
||||
PTHREAD_LIBS=""
|
||||
PTHREAD_CFLAGS=""
|
||||
fi
|
||||
LIBS="$save_LIBS"
|
||||
CFLAGS="$save_CFLAGS"
|
||||
CC="$ax_pthread_save_CC"
|
||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||
LIBS="$ax_pthread_save_LIBS"
|
||||
fi
|
||||
|
||||
# We must check for the threads library under a number of different
|
||||
@@ -118,12 +129,14 @@ fi
|
||||
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
|
||||
# libraries is broken (non-POSIX).
|
||||
|
||||
# Create a list of thread flags to try. Items starting with a "-" are
|
||||
# C compiler flags, and other items are library names, except for "none"
|
||||
# which indicates that we try without any flags at all, and "pthread-config"
|
||||
# which is a program returning the flags for the Pth emulation library.
|
||||
# Create a list of thread flags to try. Items with a "," contain both
|
||||
# C compiler flags (before ",") and linker flags (after ","). Other items
|
||||
# starting with a "-" are C compiler flags, and remaining items are
|
||||
# library names, except for "none" which indicates that we try without
|
||||
# any flags at all, and "pthread-config" which is a program returning
|
||||
# the flags for the Pth emulation library.
|
||||
|
||||
ax_pthread_flags="none pthreads -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
|
||||
ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
|
||||
|
||||
# The ordering *is* (sometimes) important. Some notes on the
|
||||
# individual items follow:
|
||||
@@ -132,68 +145,163 @@ ax_pthread_flags="none pthreads -Kthread -kthread lthread -pthread -pthreads -mt
|
||||
# none: in case threads are in libc; should be tried before -Kthread and
|
||||
# other compiler flags to prevent continual compiler warnings
|
||||
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
|
||||
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
|
||||
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
|
||||
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
|
||||
# -pthreads: Solaris/gcc
|
||||
# -mthreads: Mingw32/gcc, Lynx/gcc
|
||||
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
|
||||
# (Note: HP C rejects this with "bad form for `-t' option")
|
||||
# -pthreads: Solaris/gcc (Note: HP C also rejects)
|
||||
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
|
||||
# doesn't hurt to check since this sometimes defines pthreads too;
|
||||
# also defines -D_REENTRANT)
|
||||
# ... -mt is also the pthreads flag for HP/aCC
|
||||
# doesn't hurt to check since this sometimes defines pthreads and
|
||||
# -D_REENTRANT too), HP C (must be checked before -lpthread, which
|
||||
# is present but should not be used directly; and before -mthreads,
|
||||
# because the compiler interprets this as "-mt" + "-hreads")
|
||||
# -mthreads: Mingw32/gcc, Lynx/gcc
|
||||
# pthread: Linux, etcetera
|
||||
# --thread-safe: KAI C++
|
||||
# pthread-config: use pthread-config program (for GNU Pth library)
|
||||
|
||||
case "${host_cpu}-${host_os}" in
|
||||
*solaris*)
|
||||
case $host_os in
|
||||
|
||||
freebsd*)
|
||||
|
||||
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
|
||||
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
|
||||
|
||||
ax_pthread_flags="-kthread lthread $ax_pthread_flags"
|
||||
;;
|
||||
|
||||
hpux*)
|
||||
|
||||
# From the cc(1) man page: "[-mt] Sets various -D flags to enable
|
||||
# multi-threading and also sets -lpthread."
|
||||
|
||||
ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
|
||||
;;
|
||||
|
||||
openedition*)
|
||||
|
||||
# IBM z/OS requires a feature-test macro to be defined in order to
|
||||
# enable POSIX threads at all, so give the user a hint if this is
|
||||
# not set. (We don't define these ourselves, as they can affect
|
||||
# other portions of the system API in unpredictable ways.)
|
||||
|
||||
AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING],
|
||||
[
|
||||
# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
|
||||
AX_PTHREAD_ZOS_MISSING
|
||||
# endif
|
||||
],
|
||||
[AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])])
|
||||
;;
|
||||
|
||||
solaris*)
|
||||
|
||||
# On Solaris (at least, for some versions), libc contains stubbed
|
||||
# (non-functional) versions of the pthreads routines, so link-based
|
||||
# tests will erroneously succeed. (We need to link with -pthreads/-mt/
|
||||
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
|
||||
# a function called by this macro, so we could check for that, but
|
||||
# who knows whether they'll stub that too in a future libc.) So,
|
||||
# we'll just look for -pthreads and -lpthread first:
|
||||
# tests will erroneously succeed. (N.B.: The stubs are missing
|
||||
# pthread_cleanup_push, or rather a function called by this macro,
|
||||
# so we could check for that, but who knows whether they'll stub
|
||||
# that too in a future libc.) So we'll check first for the
|
||||
# standard Solaris way of linking pthreads (-mt -lpthread).
|
||||
|
||||
ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
|
||||
;;
|
||||
|
||||
*-darwin*)
|
||||
ax_pthread_flags="none -pthread $ax_pthread_flags"
|
||||
ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags"
|
||||
;;
|
||||
esac
|
||||
|
||||
if test x"$ax_pthread_ok" = xno; then
|
||||
for flag in $ax_pthread_flags; do
|
||||
# Are we compiling with Clang?
|
||||
|
||||
case $flag in
|
||||
AC_CACHE_CHECK([whether $CC is Clang],
|
||||
[ax_cv_PTHREAD_CLANG],
|
||||
[ax_cv_PTHREAD_CLANG=no
|
||||
# Note that Autoconf sets GCC=yes for Clang as well as GCC
|
||||
if test "x$GCC" = "xyes"; then
|
||||
AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
|
||||
[/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
|
||||
# if defined(__clang__) && defined(__llvm__)
|
||||
AX_PTHREAD_CC_IS_CLANG
|
||||
# endif
|
||||
],
|
||||
[ax_cv_PTHREAD_CLANG=yes])
|
||||
fi
|
||||
])
|
||||
ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
|
||||
|
||||
|
||||
# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
|
||||
|
||||
# Note that for GCC and Clang -pthread generally implies -lpthread,
|
||||
# except when -nostdlib is passed.
|
||||
# This is problematic using libtool to build C++ shared libraries with pthread:
|
||||
# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460
|
||||
# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333
|
||||
# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555
|
||||
# To solve this, first try -pthread together with -lpthread for GCC
|
||||
|
||||
AS_IF([test "x$GCC" = "xyes"],
|
||||
[ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags"])
|
||||
|
||||
# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first
|
||||
|
||||
AS_IF([test "x$ax_pthread_clang" = "xyes"],
|
||||
[ax_pthread_flags="-pthread,-lpthread -pthread"])
|
||||
|
||||
|
||||
# The presence of a feature test macro requesting re-entrant function
|
||||
# definitions is, on some systems, a strong hint that pthreads support is
|
||||
# correctly enabled
|
||||
|
||||
case $host_os in
|
||||
darwin* | hpux* | linux* | osf* | solaris*)
|
||||
ax_pthread_check_macro="_REENTRANT"
|
||||
;;
|
||||
|
||||
aix*)
|
||||
ax_pthread_check_macro="_THREAD_SAFE"
|
||||
;;
|
||||
|
||||
*)
|
||||
ax_pthread_check_macro="--"
|
||||
;;
|
||||
esac
|
||||
AS_IF([test "x$ax_pthread_check_macro" = "x--"],
|
||||
[ax_pthread_check_cond=0],
|
||||
[ax_pthread_check_cond="!defined($ax_pthread_check_macro)"])
|
||||
|
||||
|
||||
if test "x$ax_pthread_ok" = "xno"; then
|
||||
for ax_pthread_try_flag in $ax_pthread_flags; do
|
||||
|
||||
case $ax_pthread_try_flag in
|
||||
none)
|
||||
AC_MSG_CHECKING([whether pthreads work without any flags])
|
||||
;;
|
||||
|
||||
*,*)
|
||||
PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"`
|
||||
PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"`
|
||||
AC_MSG_CHECKING([whether pthreads work with "$PTHREAD_CFLAGS" and "$PTHREAD_LIBS"])
|
||||
;;
|
||||
|
||||
-*)
|
||||
AC_MSG_CHECKING([whether pthreads work with $flag])
|
||||
PTHREAD_CFLAGS="$flag"
|
||||
AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
|
||||
PTHREAD_CFLAGS="$ax_pthread_try_flag"
|
||||
;;
|
||||
|
||||
pthread-config)
|
||||
AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no)
|
||||
if test x"$ax_pthread_config" = xno; then continue; fi
|
||||
AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
|
||||
AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
|
||||
PTHREAD_CFLAGS="`pthread-config --cflags`"
|
||||
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
|
||||
;;
|
||||
|
||||
*)
|
||||
AC_MSG_CHECKING([for the pthreads library -l$flag])
|
||||
PTHREAD_LIBS="-l$flag"
|
||||
AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
|
||||
PTHREAD_LIBS="-l$ax_pthread_try_flag"
|
||||
;;
|
||||
esac
|
||||
|
||||
save_LIBS="$LIBS"
|
||||
save_CFLAGS="$CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||
ax_pthread_save_LIBS="$LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
|
||||
# Check for various functions. We must include pthread.h,
|
||||
# since some functions may be macros. (On the Sequent, we
|
||||
@@ -204,8 +312,18 @@ for flag in $ax_pthread_flags; do
|
||||
# pthread_cleanup_push because it is one of the few pthread
|
||||
# functions on Solaris that doesn't have a non-functional libc stub.
|
||||
# We try pthread_create on general principles.
|
||||
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
|
||||
static void routine(void *a) { a = 0; }
|
||||
# if $ax_pthread_check_cond
|
||||
# error "$ax_pthread_check_macro must be defined"
|
||||
# endif
|
||||
static void *some_global = NULL;
|
||||
static void routine(void *a)
|
||||
{
|
||||
/* To avoid any unused-parameter or
|
||||
unused-but-set-parameter warning. */
|
||||
some_global = a;
|
||||
}
|
||||
static void *start_routine(void *a) { return a; }],
|
||||
[pthread_t th; pthread_attr_t attr;
|
||||
pthread_create(&th, 0, start_routine, 0);
|
||||
@@ -213,93 +331,188 @@ for flag in $ax_pthread_flags; do
|
||||
pthread_attr_init(&attr);
|
||||
pthread_cleanup_push(routine, 0);
|
||||
pthread_cleanup_pop(0) /* ; */])],
|
||||
[ax_pthread_ok=yes],
|
||||
[])
|
||||
[ax_pthread_ok=yes],
|
||||
[])
|
||||
|
||||
LIBS="$save_LIBS"
|
||||
CFLAGS="$save_CFLAGS"
|
||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||
LIBS="$ax_pthread_save_LIBS"
|
||||
|
||||
AC_MSG_RESULT($ax_pthread_ok)
|
||||
if test "x$ax_pthread_ok" = xyes; then
|
||||
break;
|
||||
fi
|
||||
AC_MSG_RESULT([$ax_pthread_ok])
|
||||
AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
|
||||
|
||||
PTHREAD_LIBS=""
|
||||
PTHREAD_CFLAGS=""
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Clang needs special handling, because older versions handle the -pthread
|
||||
# option in a rather... idiosyncratic way
|
||||
|
||||
if test "x$ax_pthread_clang" = "xyes"; then
|
||||
|
||||
# Clang takes -pthread; it has never supported any other flag
|
||||
|
||||
# (Note 1: This will need to be revisited if a system that Clang
|
||||
# supports has POSIX threads in a separate library. This tends not
|
||||
# to be the way of modern systems, but it's conceivable.)
|
||||
|
||||
# (Note 2: On some systems, notably Darwin, -pthread is not needed
|
||||
# to get POSIX threads support; the API is always present and
|
||||
# active. We could reasonably leave PTHREAD_CFLAGS empty. But
|
||||
# -pthread does define _REENTRANT, and while the Darwin headers
|
||||
# ignore this macro, third-party headers might not.)
|
||||
|
||||
# However, older versions of Clang make a point of warning the user
|
||||
# that, in an invocation where only linking and no compilation is
|
||||
# taking place, the -pthread option has no effect ("argument unused
|
||||
# during compilation"). They expect -pthread to be passed in only
|
||||
# when source code is being compiled.
|
||||
#
|
||||
# Problem is, this is at odds with the way Automake and most other
|
||||
# C build frameworks function, which is that the same flags used in
|
||||
# compilation (CFLAGS) are also used in linking. Many systems
|
||||
# supported by AX_PTHREAD require exactly this for POSIX threads
|
||||
# support, and in fact it is often not straightforward to specify a
|
||||
# flag that is used only in the compilation phase and not in
|
||||
# linking. Such a scenario is extremely rare in practice.
|
||||
#
|
||||
# Even though use of the -pthread flag in linking would only print
|
||||
# a warning, this can be a nuisance for well-run software projects
|
||||
# that build with -Werror. So if the active version of Clang has
|
||||
# this misfeature, we search for an option to squash it.
|
||||
|
||||
AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread],
|
||||
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],
|
||||
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
|
||||
# Create an alternate version of $ac_link that compiles and
|
||||
# links in two steps (.c -> .o, .o -> exe) instead of one
|
||||
# (.c -> exe), because the warning occurs only in the second
|
||||
# step
|
||||
ax_pthread_save_ac_link="$ac_link"
|
||||
ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
|
||||
ax_pthread_link_step=`AS_ECHO(["$ac_link"]) | sed "$ax_pthread_sed"`
|
||||
ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
|
||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||
for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
|
||||
AS_IF([test "x$ax_pthread_try" = "xunknown"], [break])
|
||||
CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
|
||||
ac_link="$ax_pthread_save_ac_link"
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
|
||||
[ac_link="$ax_pthread_2step_ac_link"
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
|
||||
[break])
|
||||
])
|
||||
done
|
||||
ac_link="$ax_pthread_save_ac_link"
|
||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||
AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no])
|
||||
ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
|
||||
])
|
||||
|
||||
case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
|
||||
no | unknown) ;;
|
||||
*) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
|
||||
esac
|
||||
|
||||
fi # $ax_pthread_clang = yes
|
||||
|
||||
|
||||
|
||||
# Various other checks:
|
||||
if test "x$ax_pthread_ok" = xyes; then
|
||||
save_LIBS="$LIBS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
save_CFLAGS="$CFLAGS"
|
||||
if test "x$ax_pthread_ok" = "xyes"; then
|
||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||
ax_pthread_save_LIBS="$LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
|
||||
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
|
||||
AC_MSG_CHECKING([for joinable pthread attribute])
|
||||
attr_name=unknown
|
||||
for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
|
||||
[int attr = $attr; return attr /* ; */])],
|
||||
[attr_name=$attr; break],
|
||||
[])
|
||||
done
|
||||
AC_MSG_RESULT($attr_name)
|
||||
if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
|
||||
AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
|
||||
[Define to necessary symbol if this constant
|
||||
uses a non-standard name on your system.])
|
||||
fi
|
||||
AC_CACHE_CHECK([for joinable pthread attribute],
|
||||
[ax_cv_PTHREAD_JOINABLE_ATTR],
|
||||
[ax_cv_PTHREAD_JOINABLE_ATTR=unknown
|
||||
for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
|
||||
[int attr = $ax_pthread_attr; return attr /* ; */])],
|
||||
[ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],
|
||||
[])
|
||||
done
|
||||
])
|
||||
AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
|
||||
test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
|
||||
test "x$ax_pthread_joinable_attr_defined" != "xyes"],
|
||||
[AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE],
|
||||
[$ax_cv_PTHREAD_JOINABLE_ATTR],
|
||||
[Define to necessary symbol if this constant
|
||||
uses a non-standard name on your system.])
|
||||
ax_pthread_joinable_attr_defined=yes
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING([if more special flags are required for pthreads])
|
||||
flag=no
|
||||
case "${host_cpu}-${host_os}" in
|
||||
*-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
|
||||
*-osf* | *-hpux*) flag="-D_REENTRANT";;
|
||||
*solaris*)
|
||||
if test "$GCC" = "yes"; then
|
||||
flag="-D_REENTRANT"
|
||||
else
|
||||
flag="-mt -D_REENTRANT"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
AC_MSG_RESULT(${flag})
|
||||
if test "x$flag" != xno; then
|
||||
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
|
||||
fi
|
||||
AC_CACHE_CHECK([whether more special flags are required for pthreads],
|
||||
[ax_cv_PTHREAD_SPECIAL_FLAGS],
|
||||
[ax_cv_PTHREAD_SPECIAL_FLAGS=no
|
||||
case $host_os in
|
||||
solaris*)
|
||||
ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
|
||||
;;
|
||||
esac
|
||||
])
|
||||
AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
|
||||
test "x$ax_pthread_special_flags_added" != "xyes"],
|
||||
[PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
|
||||
ax_pthread_special_flags_added=yes])
|
||||
|
||||
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
|
||||
ax_cv_PTHREAD_PRIO_INHERIT, [
|
||||
AC_LINK_IFELSE([
|
||||
AC_LANG_PROGRAM([[#include <pthread.h>]], [[int i = PTHREAD_PRIO_INHERIT;]])],
|
||||
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
|
||||
[ax_cv_PTHREAD_PRIO_INHERIT=no])
|
||||
[ax_cv_PTHREAD_PRIO_INHERIT],
|
||||
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
|
||||
[[int i = PTHREAD_PRIO_INHERIT;
|
||||
return i;]])],
|
||||
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
|
||||
[ax_cv_PTHREAD_PRIO_INHERIT=no])
|
||||
])
|
||||
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
|
||||
AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], 1, [Have PTHREAD_PRIO_INHERIT.]))
|
||||
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
|
||||
test "x$ax_pthread_prio_inherit_defined" != "xyes"],
|
||||
[AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])
|
||||
ax_pthread_prio_inherit_defined=yes
|
||||
])
|
||||
|
||||
LIBS="$save_LIBS"
|
||||
CFLAGS="$save_CFLAGS"
|
||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||
LIBS="$ax_pthread_save_LIBS"
|
||||
|
||||
# More AIX lossage: must compile with xlc_r or cc_r
|
||||
if test x"$GCC" != xyes; then
|
||||
AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC})
|
||||
else
|
||||
PTHREAD_CC=$CC
|
||||
# More AIX lossage: compile with *_r variant
|
||||
if test "x$GCC" != "xyes"; then
|
||||
case $host_os in
|
||||
aix*)
|
||||
AS_CASE(["x/$CC"],
|
||||
[x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
|
||||
[#handle absolute path differently from PATH based program lookup
|
||||
AS_CASE(["x$CC"],
|
||||
[x/*],
|
||||
[
|
||||
AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])
|
||||
AS_IF([test "x${CXX}" != "x"], [AS_IF([AS_EXECUTABLE_P([${CXX}_r])],[PTHREAD_CXX="${CXX}_r"])])
|
||||
],
|
||||
[
|
||||
AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])
|
||||
AS_IF([test "x${CXX}" != "x"], [AC_CHECK_PROGS([PTHREAD_CXX],[${CXX}_r],[$CXX])])
|
||||
]
|
||||
)
|
||||
])
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
else
|
||||
PTHREAD_CC="$CC"
|
||||
fi
|
||||
|
||||
AC_SUBST(PTHREAD_LIBS)
|
||||
AC_SUBST(PTHREAD_CFLAGS)
|
||||
AC_SUBST(PTHREAD_CC)
|
||||
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
|
||||
test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX"
|
||||
|
||||
AC_SUBST([PTHREAD_LIBS])
|
||||
AC_SUBST([PTHREAD_CFLAGS])
|
||||
AC_SUBST([PTHREAD_CC])
|
||||
AC_SUBST([PTHREAD_CXX])
|
||||
|
||||
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
|
||||
if test x"$ax_pthread_ok" = xyes; then
|
||||
ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
|
||||
if test "x$ax_pthread_ok" = "xyes"; then
|
||||
ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
|
||||
:
|
||||
else
|
||||
ax_pthread_ok=no
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# ===========================================================================
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_require_defined.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_REQUIRE_DEFINED(MACRO)
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# AX_REQUIRE_DEFINED is a simple helper for making sure other macros have
|
||||
# been defined and thus are available for use. This avoids random issues
|
||||
# where a macro isn't expanded. Instead the configure script emits a
|
||||
# non-fatal:
|
||||
#
|
||||
# ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found
|
||||
#
|
||||
# It's like AC_REQUIRE except it doesn't expand the required macro.
|
||||
#
|
||||
# Here's an example:
|
||||
#
|
||||
# AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2014 Mike Frysinger <vapier@gentoo.org>
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification, are
|
||||
# permitted in any medium without royalty provided the copyright notice
|
||||
# and this notice are preserved. This file is offered as-is, without any
|
||||
# warranty.
|
||||
|
||||
#serial 2
|
||||
|
||||
AC_DEFUN([AX_REQUIRE_DEFINED], [dnl
|
||||
m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])])
|
||||
])dnl AX_REQUIRE_DEFINED
|
||||
+105
-69
@@ -1,5 +1,5 @@
|
||||
# ===========================================================================
|
||||
# http://www.gnu.org/software/autoconf-archive/ax_with_curses.html
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_with_curses.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
@@ -12,7 +12,9 @@
|
||||
# present, along with the associated header file. The NcursesW
|
||||
# (wide-character) library is searched for first, followed by Ncurses,
|
||||
# then the system-default plain Curses. The first library found is the
|
||||
# one returned.
|
||||
# one returned. Finding libraries will first be attempted by using
|
||||
# pkg-config, and should the pkg-config files not be available, will
|
||||
# fallback to combinations of known flags itself.
|
||||
#
|
||||
# The following options are understood: --with-ncursesw, --with-ncurses,
|
||||
# --without-ncursesw, --without-ncurses. The "--with" options force the
|
||||
@@ -52,23 +54,29 @@
|
||||
#
|
||||
# (These preprocessor symbols are discussed later in this document.)
|
||||
#
|
||||
# The following output variable is defined by this macro; it is precious
|
||||
# and may be overridden on the ./configure command line:
|
||||
# The following output variables are defined by this macro; they are
|
||||
# precious and may be overridden on the ./configure command line:
|
||||
#
|
||||
# CURSES_LIB - library to add to xxx_LDADD
|
||||
# CURSES_LIBS - library to add to xxx_LDADD
|
||||
# CURSES_CFLAGS - include paths to add to xxx_CPPFLAGS
|
||||
#
|
||||
# The library listed in CURSES_LIB is NOT added to LIBS by default. You
|
||||
# need to add CURSES_LIB to the appropriate xxx_LDADD line in your
|
||||
# Makefile.am. For example:
|
||||
# In previous versions of this macro, the flags CURSES_LIB and
|
||||
# CURSES_CPPFLAGS were defined. These have been renamed, in keeping with
|
||||
# AX_WITH_CURSES's close bigger brother, PKG_CHECK_MODULES, which should
|
||||
# eventually supersede the use of AX_WITH_CURSES. Neither the library
|
||||
# listed in CURSES_LIBS, nor the flags in CURSES_CFLAGS are added to LIBS,
|
||||
# respectively CPPFLAGS, by default. You need to add both to the
|
||||
# appropriate xxx_LDADD/xxx_CPPFLAGS line in your Makefile.am. For
|
||||
# example:
|
||||
#
|
||||
# prog_LDADD = @CURSES_LIB@
|
||||
# prog_LDADD = @CURSES_LIBS@
|
||||
# prog_CPPFLAGS = @CURSES_CFLAGS@
|
||||
#
|
||||
# If CURSES_LIB is set on the configure command line (such as by running
|
||||
# "./configure CURSES_LIB=-lmycurses"), then the only header searched for
|
||||
# is <curses.h>. The user may use the CPPFLAGS precious variable to
|
||||
# override the standard #include search path. If the user needs to
|
||||
# specify an alternative path for a library (such as for a non-standard
|
||||
# NcurseW), the user should use the LDFLAGS variable.
|
||||
# If CURSES_LIBS is set on the configure command line (such as by running
|
||||
# "./configure CURSES_LIBS=-lmycurses"), then the only header searched for
|
||||
# is <curses.h>. If the user needs to specify an alternative path for a
|
||||
# library (such as for a non-standard NcurseW), the user should use the
|
||||
# LDFLAGS variable.
|
||||
#
|
||||
# The following shell variables may be defined by this macro:
|
||||
#
|
||||
@@ -88,7 +96,7 @@
|
||||
#
|
||||
# AX_WITH_CURSES
|
||||
# if test "x$ax_cv_ncursesw" != xyes && test "x$ax_cv_ncurses" != xyes; then
|
||||
# AX_MSG_ERROR([requires either NcursesW or Ncurses library])
|
||||
# AC_MSG_ERROR([requires either NcursesW or Ncurses library])
|
||||
# fi
|
||||
#
|
||||
# If any Curses library will do (but one must be present and must support
|
||||
@@ -167,7 +175,7 @@
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# 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
|
||||
@@ -182,11 +190,66 @@
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
#serial 13
|
||||
#serial 18
|
||||
|
||||
# internal function to factorize common code that is used by both ncurses
|
||||
# and ncursesw
|
||||
AC_DEFUN([_FIND_CURSES_FLAGS], [
|
||||
AC_MSG_CHECKING([for $1 via pkg-config])
|
||||
|
||||
AX_REQUIRE_DEFINED([PKG_CHECK_EXISTS])
|
||||
_PKG_CONFIG([_ax_cv_$1_libs], [libs], [$1])
|
||||
_PKG_CONFIG([_ax_cv_$1_cppflags], [cflags], [$1])
|
||||
|
||||
AS_IF([test "x$pkg_failed" = "xyes" || test "x$pkg_failed" = "xuntried"],[
|
||||
AC_MSG_RESULT([no])
|
||||
# No suitable .pc file found, have to find flags via fallback
|
||||
AC_CACHE_CHECK([for $1 via fallback], [ax_cv_$1], [
|
||||
AS_ECHO()
|
||||
pkg_cv__ax_cv_$1_libs="-l$1"
|
||||
pkg_cv__ax_cv_$1_cppflags="-D_GNU_SOURCE $CURSES_CFLAGS"
|
||||
LIBS="$ax_saved_LIBS $pkg_cv__ax_cv_$1_libs"
|
||||
CPPFLAGS="$ax_saved_CPPFLAGS $pkg_cv__ax_cv_$1_cppflags"
|
||||
|
||||
AC_MSG_CHECKING([for initscr() with $pkg_cv__ax_cv_$1_libs])
|
||||
AC_LINK_IFELSE([AC_LANG_CALL([], [initscr])],
|
||||
[
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_MSG_CHECKING([for nodelay() with $pkg_cv__ax_cv_$1_libs])
|
||||
AC_LINK_IFELSE([AC_LANG_CALL([], [nodelay])],[
|
||||
ax_cv_$1=yes
|
||||
],[
|
||||
AC_MSG_RESULT([no])
|
||||
m4_if(
|
||||
[$1],[ncursesw],[pkg_cv__ax_cv_$1_libs="$pkg_cv__ax_cv_$1_libs -ltinfow"],
|
||||
[$1],[ncurses],[pkg_cv__ax_cv_$1_libs="$pkg_cv__ax_cv_$1_libs -ltinfo"]
|
||||
)
|
||||
LIBS="$ax_saved_LIBS $pkg_cv__ax_cv_$1_libs"
|
||||
|
||||
AC_MSG_CHECKING([for nodelay() with $pkg_cv__ax_cv_$1_libs])
|
||||
AC_LINK_IFELSE([AC_LANG_CALL([], [nodelay])],[
|
||||
ax_cv_$1=yes
|
||||
],[
|
||||
ax_cv_$1=no
|
||||
])
|
||||
])
|
||||
],[
|
||||
ax_cv_$1=no
|
||||
])
|
||||
])
|
||||
],[
|
||||
AC_MSG_RESULT([yes])
|
||||
# Found .pc file, using its information
|
||||
LIBS="$ax_saved_LIBS $pkg_cv__ax_cv_$1_libs"
|
||||
CPPFLAGS="$ax_saved_CPPFLAGS $pkg_cv__ax_cv_$1_cppflags"
|
||||
ax_cv_$1=yes
|
||||
])
|
||||
])
|
||||
|
||||
AU_ALIAS([MP_WITH_CURSES], [AX_WITH_CURSES])
|
||||
AC_DEFUN([AX_WITH_CURSES], [
|
||||
AC_ARG_VAR([CURSES_LIB], [linker library for Curses, e.g. -lcurses])
|
||||
AC_ARG_VAR([CURSES_LIBS], [linker library for Curses, e.g. -lcurses])
|
||||
AC_ARG_VAR([CURSES_CFLAGS], [preprocessor flags for Curses, e.g. -I/usr/include/ncursesw])
|
||||
AC_ARG_WITH([ncurses], [AS_HELP_STRING([--with-ncurses],
|
||||
[force the use of Ncurses or NcursesW])],
|
||||
[], [with_ncurses=check])
|
||||
@@ -195,20 +258,17 @@ AC_DEFUN([AX_WITH_CURSES], [
|
||||
[], [with_ncursesw=check])
|
||||
|
||||
ax_saved_LIBS=$LIBS
|
||||
ax_saved_CPPFLAGS=$CPPFLAGS
|
||||
|
||||
AS_IF([test "x$with_ncurses" = xyes || test "x$with_ncursesw" = xyes],
|
||||
[ax_with_plaincurses=no], [ax_with_plaincurses=check])
|
||||
|
||||
ax_cv_curses_which=no
|
||||
|
||||
# Test for NcursesW
|
||||
AS_IF([test "x$CURSES_LIBS" = x && test "x$with_ncursesw" != xno], [
|
||||
_FIND_CURSES_FLAGS([ncursesw])
|
||||
|
||||
AS_IF([test "x$CURSES_LIB" = x && test "x$with_ncursesw" != xno], [
|
||||
LIBS="$ax_saved_LIBS -lncursesw"
|
||||
|
||||
AC_CACHE_CHECK([for NcursesW wide-character library], [ax_cv_ncursesw], [
|
||||
AC_LINK_IFELSE([AC_LANG_CALL([], [initscr])],
|
||||
[ax_cv_ncursesw=yes], [ax_cv_ncursesw=no])
|
||||
])
|
||||
AS_IF([test "x$ax_cv_ncursesw" = xno && test "x$with_ncursesw" = xyes], [
|
||||
AC_MSG_ERROR([--with-ncursesw specified but could not find NcursesW library])
|
||||
])
|
||||
@@ -216,7 +276,8 @@ AC_DEFUN([AX_WITH_CURSES], [
|
||||
AS_IF([test "x$ax_cv_ncursesw" = xyes], [
|
||||
ax_cv_curses=yes
|
||||
ax_cv_curses_which=ncursesw
|
||||
CURSES_LIB="-lncursesw"
|
||||
CURSES_LIBS="$pkg_cv__ax_cv_ncursesw_libs"
|
||||
CURSES_CFLAGS="$pkg_cv__ax_cv_ncursesw_cppflags"
|
||||
AC_DEFINE([HAVE_NCURSESW], [1], [Define to 1 if the NcursesW library is present])
|
||||
AC_DEFINE([HAVE_CURSES], [1], [Define to 1 if a SysV or X/Open compatible Curses library is present])
|
||||
|
||||
@@ -316,46 +377,15 @@ AC_DEFUN([AX_WITH_CURSES], [
|
||||
AS_IF([test "x$ax_cv_header_ncursesw_curses_h" = xno && test "x$ax_cv_header_ncursesw_h" = xno && test "x$ax_cv_header_ncurses_h_with_ncursesw" = xno], [
|
||||
AC_MSG_WARN([could not find a working ncursesw/curses.h, ncursesw.h or ncurses.h])
|
||||
])
|
||||
|
||||
dnl Test if we need to explicitly link against -ltinfow.
|
||||
AC_CACHE_CHECK([if curses tinfo library is linked properly], [ax_cv_ncurses_compiled], [
|
||||
LIBS="$ax_saved_LIBS $CURSES_LIB"
|
||||
AC_LINK_IFELSE([AC_LANG_CALL([], [keypad])], [ax_cv_ncurses_compiled=yes], [ax_cv_ncurses_compiled=no])
|
||||
|
||||
LIBS="$ax_saved_LIBS $CURSES_LIB -ltinfo"
|
||||
AC_LINK_IFELSE([AC_LANG_CALL([], [keypad])], [ax_cv_tinfo_compiled=yes], [ax_cv_tinfo_compiled=no])
|
||||
|
||||
LIBS="$ax_saved_LIBS $CURSES_LIB -ltinfow"
|
||||
AC_LINK_IFELSE([AC_LANG_CALL([], [keypad])], [ax_cv_tinfow_compiled=yes], [ax_cv_tinfow_compiled=no])
|
||||
|
||||
LIBS=$ax_saved_LIBS
|
||||
])
|
||||
|
||||
AS_IF([test "x$ax_cv_ncurses_compiled" = xno], [
|
||||
AS_IF(
|
||||
[test "x$ax_cv_tinfo_compiled" = xyes], [
|
||||
AC_MSG_RESULT([adding libtinfo])
|
||||
CURSES_LIB="$CURSES_LIB -ltinfo"
|
||||
],
|
||||
[test "x$ax_cv_tinfow_compiled" = xyes], [
|
||||
AC_MSG_RESULT([adding libtinfow])
|
||||
CURSES_LIB="$CURSES_LIB -ltinfow"
|
||||
], [
|
||||
AC_MSG_ERROR([no])
|
||||
])
|
||||
])
|
||||
])
|
||||
])
|
||||
unset pkg_cv__ax_cv_ncursesw_libs
|
||||
unset pkg_cv__ax_cv_ncursesw_cppflags
|
||||
|
||||
# Test for Ncurses
|
||||
AS_IF([test "x$CURSES_LIBS" = x && test "x$with_ncurses" != xno && test "x$ax_cv_curses_which" = xno], [
|
||||
_FIND_CURSES_FLAGS([ncurses])
|
||||
|
||||
AS_IF([test "x$CURSES_LIB" = x && test "x$with_ncurses" != xno && test "x$ax_cv_curses_which" = xno], [
|
||||
LIBS="$ax_saved_LIBS -lncurses"
|
||||
|
||||
AC_CACHE_CHECK([for Ncurses library], [ax_cv_ncurses], [
|
||||
AC_LINK_IFELSE([AC_LANG_CALL([], [initscr])],
|
||||
[ax_cv_ncurses=yes], [ax_cv_ncurses=no])
|
||||
])
|
||||
AS_IF([test "x$ax_cv_ncurses" = xno && test "x$with_ncurses" = xyes], [
|
||||
AC_MSG_ERROR([--with-ncurses specified but could not find Ncurses library])
|
||||
])
|
||||
@@ -363,7 +393,8 @@ AC_DEFUN([AX_WITH_CURSES], [
|
||||
AS_IF([test "x$ax_cv_ncurses" = xyes], [
|
||||
ax_cv_curses=yes
|
||||
ax_cv_curses_which=ncurses
|
||||
CURSES_LIB="-lncurses"
|
||||
CURSES_LIBS="$pkg_cv__ax_cv_ncurses_libs"
|
||||
CURSES_CFLAGS="$pkg_cv__ax_cv_ncurses_cppflags"
|
||||
AC_DEFINE([HAVE_NCURSES], [1], [Define to 1 if the Ncurses library is present])
|
||||
AC_DEFINE([HAVE_CURSES], [1], [Define to 1 if a SysV or X/Open compatible Curses library is present])
|
||||
|
||||
@@ -418,12 +449,13 @@ AC_DEFUN([AX_WITH_CURSES], [
|
||||
])
|
||||
])
|
||||
])
|
||||
unset pkg_cv__ax_cv_ncurses_libs
|
||||
unset pkg_cv__ax_cv_ncurses_cppflags
|
||||
|
||||
# Test for plain Curses (or if CURSES_LIB was set by user)
|
||||
|
||||
# Test for plain Curses (or if CURSES_LIBS was set by user)
|
||||
AS_IF([test "x$with_plaincurses" != xno && test "x$ax_cv_curses_which" = xno], [
|
||||
AS_IF([test "x$CURSES_LIB" != x], [
|
||||
LIBS="$ax_saved_LIBS $CURSES_LIB"
|
||||
AS_IF([test "x$CURSES_LIBS" != x], [
|
||||
LIBS="$ax_saved_LIBS $CURSES_LIBS"
|
||||
], [
|
||||
LIBS="$ax_saved_LIBS -lcurses"
|
||||
])
|
||||
@@ -436,8 +468,8 @@ AC_DEFUN([AX_WITH_CURSES], [
|
||||
AS_IF([test "x$ax_cv_plaincurses" = xyes], [
|
||||
ax_cv_curses=yes
|
||||
ax_cv_curses_which=plaincurses
|
||||
AS_IF([test "x$CURSES_LIB" = x], [
|
||||
CURSES_LIB="-lcurses"
|
||||
AS_IF([test "x$CURSES_LIBS" = x], [
|
||||
CURSES_LIBS="-lcurses"
|
||||
])
|
||||
AC_DEFINE([HAVE_CURSES], [1], [Define to 1 if a SysV or X/Open compatible Curses library is present])
|
||||
|
||||
@@ -543,4 +575,8 @@ AC_DEFUN([AX_WITH_CURSES], [
|
||||
AS_IF([test "x$ax_cv_curses_obsolete" != xyes], [ax_cv_curses_obsolete=no])
|
||||
|
||||
LIBS=$ax_saved_LIBS
|
||||
CPPFLAGS=$ax_saved_CPPFLAGS
|
||||
|
||||
unset ax_saved_LIBS
|
||||
unset ax_saved_CPPFLAGS
|
||||
])dnl
|
||||
|
||||
+94
-101
@@ -21,7 +21,7 @@ AC_DEFUN([TORRENT_CHECK_XFS], [
|
||||
|
||||
AC_DEFUN([TORRENT_WITHOUT_XFS], [
|
||||
AC_ARG_WITH(xfs,
|
||||
AC_HELP_STRING([--without-xfs], [do not check for XFS filesystem support]),
|
||||
AS_HELP_STRING([--without-xfs],[do not check for XFS filesystem support]),
|
||||
[
|
||||
if test "$withval" = "yes"; then
|
||||
TORRENT_CHECK_XFS
|
||||
@@ -34,7 +34,7 @@ AC_DEFUN([TORRENT_WITHOUT_XFS], [
|
||||
|
||||
AC_DEFUN([TORRENT_WITH_XFS], [
|
||||
AC_ARG_WITH(xfs,
|
||||
AC_HELP_STRING([--with-xfs], [check for XFS filesystem support]),
|
||||
AS_HELP_STRING([--with-xfs],[check for XFS filesystem support]),
|
||||
[
|
||||
if test "$withval" = "yes"; then
|
||||
TORRENT_CHECK_XFS
|
||||
@@ -63,7 +63,7 @@ AC_DEFUN([TORRENT_CHECK_EPOLL], [
|
||||
|
||||
AC_DEFUN([TORRENT_WITHOUT_EPOLL], [
|
||||
AC_ARG_WITH(epoll,
|
||||
AC_HELP_STRING([--without-epoll], [do not check for epoll support]),
|
||||
AS_HELP_STRING([--without-epoll],[do not check for epoll support]),
|
||||
[
|
||||
if test "$withval" = "yes"; then
|
||||
TORRENT_CHECK_EPOLL
|
||||
@@ -93,51 +93,13 @@ AC_DEFUN([TORRENT_CHECK_KQUEUE], [
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([TORRENT_CHECK_KQUEUE_SOCKET_ONLY], [
|
||||
AC_MSG_CHECKING(whether kqueue supports pipes and ptys)
|
||||
|
||||
AC_RUN_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,
|
||||
AC_HELP_STRING([--with-kqueue], [enable kqueue [[default=no]]]),
|
||||
AS_HELP_STRING([--with-kqueue],[enable kqueue [[default=no]]]),
|
||||
[
|
||||
if test "$withval" = "yes"; then
|
||||
TORRENT_CHECK_KQUEUE
|
||||
TORRENT_CHECK_KQUEUE_SOCKET_ONLY
|
||||
fi
|
||||
])
|
||||
])
|
||||
@@ -145,22 +107,20 @@ AC_DEFUN([TORRENT_WITH_KQUEUE], [
|
||||
|
||||
AC_DEFUN([TORRENT_WITHOUT_KQUEUE], [
|
||||
AC_ARG_WITH(kqueue,
|
||||
AC_HELP_STRING([--without-kqueue], [do not check for kqueue support]),
|
||||
AS_HELP_STRING([--without-kqueue],[do not check for kqueue support]),
|
||||
[
|
||||
if test "$withval" = "yes"; then
|
||||
TORRENT_CHECK_KQUEUE
|
||||
TORRENT_CHECK_KQUEUE_SOCKET_ONLY
|
||||
fi
|
||||
], [
|
||||
TORRENT_CHECK_KQUEUE
|
||||
TORRENT_CHECK_KQUEUE_SOCKET_ONLY
|
||||
])
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN([TORRENT_WITHOUT_VARIABLE_FDSET], [
|
||||
AC_ARG_WITH(variable-fdset,
|
||||
AC_HELP_STRING([--without-variable-fdset], [do not use non-portable variable sized fd_set's]),
|
||||
AS_HELP_STRING([--without-variable-fdset],[do not use non-portable variable sized fd_set's]),
|
||||
[
|
||||
if test "$withval" = "yes"; then
|
||||
AC_DEFINE(USE_VARIABLE_FDSET, 1, defined when we allow the use of fd_set's of any size)
|
||||
@@ -174,14 +134,13 @@ AC_DEFUN([TORRENT_WITHOUT_VARIABLE_FDSET], [
|
||||
AC_DEFUN([TORRENT_CHECK_FALLOCATE], [
|
||||
AC_MSG_CHECKING(for fallocate)
|
||||
|
||||
AC_TRY_LINK([#include <fcntl.h>
|
||||
#include <linux/falloc.h>
|
||||
],[ fallocate(0, FALLOC_FL_KEEP_SIZE, 0, 0); return 0;
|
||||
],
|
||||
[
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#define _GNU_SOURCE
|
||||
#include <fcntl.h>
|
||||
]], [[ fallocate(0, FALLOC_FL_KEEP_SIZE, 0, 0); return 0;
|
||||
]])],[
|
||||
AC_DEFINE(HAVE_FALLOCATE, 1, Linux's fallocate supported.)
|
||||
AC_MSG_RESULT(yes)
|
||||
], [
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
])
|
||||
@@ -190,13 +149,12 @@ AC_DEFUN([TORRENT_CHECK_FALLOCATE], [
|
||||
AC_DEFUN([TORRENT_CHECK_POSIX_FALLOCATE], [
|
||||
AC_MSG_CHECKING(for posix_fallocate)
|
||||
|
||||
AC_TRY_LINK([#include <fcntl.h>
|
||||
],[ posix_fallocate(0, 0, 0);
|
||||
],
|
||||
[
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <fcntl.h>
|
||||
]], [[ posix_fallocate(0, 0, 0);
|
||||
]])],[
|
||||
AC_DEFINE(USE_POSIX_FALLOCATE, 1, posix_fallocate supported.)
|
||||
AC_MSG_RESULT(yes)
|
||||
], [
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
])
|
||||
@@ -204,7 +162,7 @@ AC_DEFUN([TORRENT_CHECK_POSIX_FALLOCATE], [
|
||||
|
||||
AC_DEFUN([TORRENT_WITH_POSIX_FALLOCATE], [
|
||||
AC_ARG_WITH(posix-fallocate,
|
||||
AC_HELP_STRING([--with-posix-fallocate], [check for and use posix_fallocate to allocate files]),
|
||||
AS_HELP_STRING([--with-posix-fallocate],[check for and use posix_fallocate to allocate files]),
|
||||
[
|
||||
if test "$withval" = "yes"; then
|
||||
TORRENT_CHECK_POSIX_FALLOCATE
|
||||
@@ -217,8 +175,7 @@ AC_DEFUN([TORRENT_CHECK_STATVFS], [
|
||||
|
||||
AC_MSG_CHECKING(for statvfs)
|
||||
|
||||
AC_TRY_LINK(
|
||||
[
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#if HAVE_SYS_VFS_H
|
||||
#include <sys/vfs.h>
|
||||
#endif
|
||||
@@ -228,12 +185,11 @@ AC_DEFUN([TORRENT_CHECK_STATVFS], [
|
||||
#if HAVE_SYS_STATFS_H
|
||||
#include <sys/statfs.h>
|
||||
#endif
|
||||
],[
|
||||
]], [[
|
||||
struct statvfs s; fsblkcnt_t c;
|
||||
statvfs("", &s);
|
||||
fstatvfs(0, &s);
|
||||
],
|
||||
[
|
||||
]])],[
|
||||
AC_DEFINE(FS_STAT_FD, [fstatvfs(fd, &m_stat) == 0], Function to determine filesystem stats from fd)
|
||||
AC_DEFINE(FS_STAT_FN, [statvfs(fn, &m_stat) == 0], Function to determine filesystem stats from filename)
|
||||
AC_DEFINE(FS_STAT_STRUCT, [struct statvfs], Type of second argument to statfs function)
|
||||
@@ -242,8 +198,7 @@ AC_DEFUN([TORRENT_CHECK_STATVFS], [
|
||||
AC_DEFINE(FS_STAT_BLOCK_SIZE, [(m_stat.f_frsize)], Determine the block size)
|
||||
AC_MSG_RESULT(ok)
|
||||
have_stat_vfs=yes
|
||||
],
|
||||
[
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
have_stat_vfs=no
|
||||
])
|
||||
@@ -254,8 +209,7 @@ AC_DEFUN([TORRENT_CHECK_STATFS], [
|
||||
|
||||
AC_MSG_CHECKING(for statfs)
|
||||
|
||||
AC_TRY_LINK(
|
||||
[
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#if HAVE_SYS_STATFS_H
|
||||
#include <sys/statfs.h>
|
||||
#endif
|
||||
@@ -265,12 +219,11 @@ AC_DEFUN([TORRENT_CHECK_STATFS], [
|
||||
#if HAVE_SYS_MOUNT_H
|
||||
#include <sys/mount.h>
|
||||
#endif
|
||||
],[
|
||||
]], [[
|
||||
struct statfs s;
|
||||
statfs("", &s);
|
||||
fstatfs(0, &s);
|
||||
],
|
||||
[
|
||||
]])],[
|
||||
AC_DEFINE(FS_STAT_FD, [fstatfs(fd, &m_stat) == 0], Function to determine filesystem stats from fd)
|
||||
AC_DEFINE(FS_STAT_FN, [statfs(fn, &m_stat) == 0], Function to determine filesystem stats from filename)
|
||||
AC_DEFINE(FS_STAT_STRUCT, [struct statfs], Type of second argument to statfs function)
|
||||
@@ -279,8 +232,7 @@ AC_DEFUN([TORRENT_CHECK_STATFS], [
|
||||
AC_DEFINE(FS_STAT_BLOCK_SIZE, [(m_stat.f_bsize)], Determine the block size)
|
||||
AC_MSG_RESULT(ok)
|
||||
have_stat_vfs=yes
|
||||
],
|
||||
[
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
have_stat_vfs=no
|
||||
])
|
||||
@@ -298,7 +250,7 @@ AC_DEFUN([TORRENT_DISABLED_STATFS], [
|
||||
|
||||
AC_DEFUN([TORRENT_WITHOUT_STATVFS], [
|
||||
AC_ARG_WITH(statvfs,
|
||||
AC_HELP_STRING([--without-statvfs], [don't try to use statvfs to find free diskspace]),
|
||||
AS_HELP_STRING([--without-statvfs],[don't try to use statvfs to find free diskspace]),
|
||||
[
|
||||
if test "$withval" = "yes"; then
|
||||
TORRENT_CHECK_STATVFS
|
||||
@@ -313,7 +265,7 @@ AC_DEFUN([TORRENT_WITHOUT_STATVFS], [
|
||||
|
||||
AC_DEFUN([TORRENT_WITHOUT_STATFS], [
|
||||
AC_ARG_WITH(statfs,
|
||||
AC_HELP_STRING([--without-statfs], [don't try to use statfs to find free diskspace]),
|
||||
AS_HELP_STRING([--without-statfs],[don't try to use statfs to find free diskspace]),
|
||||
[
|
||||
if test "$have_stat_vfs" = "no"; then
|
||||
if test "$withval" = "yes"; then
|
||||
@@ -335,7 +287,7 @@ AC_DEFUN([TORRENT_WITHOUT_STATFS], [
|
||||
|
||||
AC_DEFUN([TORRENT_WITH_ADDRESS_SPACE], [
|
||||
AC_ARG_WITH(address-space,
|
||||
AC_HELP_STRING([--with-address-space=MB], [change the default address space size [[default=1024mb]]]),
|
||||
AS_HELP_STRING([--with-address-space=MB],[change the default address space size [[default=1024mb]]]),
|
||||
[
|
||||
if test ! -z $withval -a "$withval" != "yes" -a "$withval" != "no"; then
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_ADDRESS_SPACE_SIZE, [$withval])
|
||||
@@ -356,7 +308,7 @@ AC_DEFUN([TORRENT_WITH_ADDRESS_SPACE], [
|
||||
|
||||
AC_DEFUN([TORRENT_WITH_FASTCGI], [
|
||||
AC_ARG_WITH(fastcgi,
|
||||
AC_HELP_STRING([--with-fastcgi=PATH], [enable FastCGI RPC support (DO NOT USE)]),
|
||||
AS_HELP_STRING([--with-fastcgi=PATH],[enable FastCGI RPC support (DO NOT USE)]),
|
||||
[
|
||||
AC_MSG_CHECKING([for FastCGI (DO NOT USE)])
|
||||
|
||||
@@ -367,13 +319,10 @@ AC_DEFUN([TORRENT_WITH_FASTCGI], [
|
||||
CXXFLAGS="$CXXFLAGS"
|
||||
LIBS="$LIBS -lfcgi"
|
||||
|
||||
AC_TRY_LINK(
|
||||
[ #include <fcgiapp.h>
|
||||
],[ FCGX_Init(); ],
|
||||
[
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include <fcgiapp.h>
|
||||
]], [[ FCGX_Init(); ]])],[
|
||||
AC_MSG_RESULT(ok)
|
||||
],
|
||||
[
|
||||
],[
|
||||
AC_MSG_RESULT(not found)
|
||||
AC_MSG_ERROR(Could not compile FastCGI test.)
|
||||
])
|
||||
@@ -384,13 +333,10 @@ AC_DEFUN([TORRENT_WITH_FASTCGI], [
|
||||
CXXFLAGS="$CXXFLAGS -I$withval/include"
|
||||
LIBS="$LIBS -lfcgi -L$withval/lib"
|
||||
|
||||
AC_TRY_LINK(
|
||||
[ #include <fcgiapp.h>
|
||||
],[ FCGX_Init(); ],
|
||||
[
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include <fcgiapp.h>
|
||||
]], [[ FCGX_Init(); ]])],[
|
||||
AC_MSG_RESULT(ok)
|
||||
],
|
||||
[
|
||||
],[
|
||||
AC_MSG_RESULT(not found)
|
||||
AC_MSG_ERROR(Could not compile FastCGI test.)
|
||||
])
|
||||
@@ -405,7 +351,7 @@ AC_DEFUN([TORRENT_WITH_XMLRPC_C], [
|
||||
AC_MSG_CHECKING(for XMLRPC-C)
|
||||
|
||||
AC_ARG_WITH(xmlrpc-c,
|
||||
AC_HELP_STRING([--with-xmlrpc-c=PATH], [enable XMLRPC-C support]),
|
||||
AS_HELP_STRING([--with-xmlrpc-c=PATH],[enable XMLRPC-C support]),
|
||||
[
|
||||
if test "$withval" = "no"; then
|
||||
AC_MSG_RESULT(no)
|
||||
@@ -416,17 +362,15 @@ AC_DEFUN([TORRENT_WITH_XMLRPC_C], [
|
||||
else
|
||||
xmlrpc_cc_prg="$withval"
|
||||
fi
|
||||
|
||||
|
||||
if eval $xmlrpc_cc_prg --version 2>/dev/null >/dev/null; then
|
||||
CXXFLAGS="$CXXFLAGS `$xmlrpc_cc_prg --cflags server-util`"
|
||||
LIBS="$LIBS `$xmlrpc_cc_prg server-util --libs`"
|
||||
|
||||
AC_TRY_LINK(
|
||||
[ #include <xmlrpc-c/server.h>
|
||||
],[ xmlrpc_registry_new(NULL); ],
|
||||
[
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include <xmlrpc-c/server.h>
|
||||
]], [[ xmlrpc_registry_new(NULL); ]])],[
|
||||
AC_MSG_RESULT(ok)
|
||||
], [
|
||||
],[
|
||||
AC_MSG_RESULT(failed)
|
||||
AC_MSG_ERROR(Could not compile XMLRPC-C test.)
|
||||
])
|
||||
@@ -444,6 +388,37 @@ AC_DEFUN([TORRENT_WITH_XMLRPC_C], [
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([TORRENT_WITH_TINYXML2], [
|
||||
AC_MSG_CHECKING(for tinyxml2)
|
||||
|
||||
AC_ARG_WITH(xmlrpc-tinyxml2,
|
||||
AS_HELP_STRING([--with-xmlrpc-tinyxml2],[enable XMLRPC support via tinyxml2]),
|
||||
[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_XMLRPC_TINYXML2, 1, Support for XMLRPC via tinyxml2.)
|
||||
],[
|
||||
AC_MSG_RESULT(ignored)
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([TORRENT_WITH_LUA], [
|
||||
AC_ARG_WITH(lua,
|
||||
AS_HELP_STRING([--with-lua],[enable LUA support]),
|
||||
[
|
||||
if test "$withval" = "no"; then
|
||||
AC_MSG_RESULT(no)
|
||||
else
|
||||
AX_PROG_LUA
|
||||
AX_LUA_LIBS
|
||||
AX_LUA_HEADERS
|
||||
AC_DEFINE(HAVE_LUA, 1, Use LUA.)
|
||||
LIBS="$LIBS $LUA_LIB"
|
||||
CXXFLAGS="$CXXFLAGS $LUA_INCLUDE"
|
||||
fi
|
||||
],[
|
||||
AC_MSG_RESULT(ignored)
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([TORRENT_WITH_INOTIFY], [
|
||||
AC_LANG_PUSH(C++)
|
||||
@@ -468,23 +443,23 @@ AC_DEFUN([TORRENT_CHECK_PTHREAD_SETNAME_NP], [
|
||||
|
||||
AC_MSG_CHECKING(for pthread_setname_np type)
|
||||
|
||||
AC_TRY_LINK([
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
],[
|
||||
]], [[
|
||||
pthread_t t;
|
||||
pthread_setname_np(t, "foo");
|
||||
],[
|
||||
]])],[
|
||||
AC_DEFINE(HAS_PTHREAD_SETNAME_NP_GENERIC, 1, The function to set pthread name has a pthread_t argumet.)
|
||||
AC_MSG_RESULT(generic)
|
||||
],[
|
||||
AC_TRY_LINK([
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
],[
|
||||
]],[[
|
||||
pthread_t t;
|
||||
pthread_setname_np("foo");
|
||||
],[
|
||||
]])],[
|
||||
AC_DEFINE(HAS_PTHREAD_SETNAME_NP_DARWIN, 1, The function to set pthread name has no pthread argument.)
|
||||
AC_MSG_RESULT(darwin)
|
||||
],[
|
||||
@@ -492,3 +467,21 @@ AC_DEFUN([TORRENT_CHECK_PTHREAD_SETNAME_NP], [
|
||||
])
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([TORRENT_DISABLE_PTHREAD_SETNAME_NP], [
|
||||
AC_MSG_CHECKING([for pthread_setname_no])
|
||||
|
||||
AC_ARG_ENABLE(pthread-setname-np,
|
||||
AS_HELP_STRING([--disable-pthread-setname-np],[disable pthread_setname_np]),
|
||||
[
|
||||
if test "$enableval" = "no"; then
|
||||
AC_MSG_RESULT(disabled)
|
||||
else
|
||||
AC_MSG_RESULT(checking)
|
||||
TORRENT_CHECK_PTHREAD_SETNAME_NP
|
||||
fi
|
||||
], [
|
||||
TORRENT_CHECK_PTHREAD_SETNAME_NP
|
||||
]
|
||||
)
|
||||
])
|
||||
|
||||
+44
-30
@@ -1,6 +1,7 @@
|
||||
AC_DEFUN([TORRENT_WITH_SYSROOT], [
|
||||
AC_ARG_WITH(sysroot,
|
||||
AC_HELP_STRING([--with-sysroot=PATH], [compile and link with a specific sysroot]),
|
||||
AS_HELP_STRING([--with-sysroot=PATH],
|
||||
[compile and link with a specific sysroot]),
|
||||
[
|
||||
AC_MSG_CHECKING(for sysroot)
|
||||
|
||||
@@ -12,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
|
||||
@@ -20,9 +21,23 @@ AC_DEFUN([TORRENT_WITH_SYSROOT], [
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN([TORRENT_REMOVE_UNWANTED],
|
||||
[
|
||||
values_to_check=`for i in $2; do echo $i; done`
|
||||
unwanted_values=`for i in $3; do echo $i; done`
|
||||
if test -z "${unwanted_values}"; then
|
||||
$1="$2"
|
||||
else
|
||||
result=`echo "${values_to_check}" | $GREP -Fvx -- "${unwanted_values}" | $GREP -v '^$'`
|
||||
$1=$(echo "$result" | tr -d '\n')
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN([TORRENT_ENABLE_ARCH], [
|
||||
AC_ARG_ENABLE(arch,
|
||||
AC_HELP_STRING([--enable-arch=ARCH], [comma seprated list of architectures to compile for]),
|
||||
AS_HELP_STRING([--enable-arch=ARCH],
|
||||
[comma seprated list of architectures to compile for]),
|
||||
[
|
||||
AC_MSG_CHECKING(for target architectures)
|
||||
|
||||
@@ -82,7 +97,8 @@ AC_DEFUN([TORRENT_MINCORE_SIGNEDNESS], [
|
||||
|
||||
AC_DEFUN([TORRENT_MINCORE], [
|
||||
AC_ARG_ENABLE(mincore,
|
||||
AC_HELP_STRING([--disable-mincore], [disable mincore check [[default=enable]]]),
|
||||
AS_HELP_STRING([--disable-mincore],
|
||||
[disable mincore check [[default=enable]]]),
|
||||
[
|
||||
if test "$enableval" = "yes"; then
|
||||
TORRENT_MINCORE_SIGNEDNESS()
|
||||
@@ -101,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)
|
||||
@@ -111,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)
|
||||
|
||||
@@ -136,32 +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.)
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([TORRENT_CHECK_EXECINFO], [
|
||||
AC_MSG_CHECKING(for execinfo.h)
|
||||
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([
|
||||
#include <execinfo.h>
|
||||
int main() { backtrace((void**)0, 0); backtrace_symbols((char**)0, 0); return 0;}
|
||||
])],
|
||||
[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(USE_EXECINFO, 1, Use execinfo.h)
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
])
|
||||
|
||||
@@ -189,7 +200,8 @@ AC_DEFUN([TORRENT_CHECK_ALIGNED], [
|
||||
|
||||
AC_DEFUN([TORRENT_ENABLE_ALIGNED], [
|
||||
AC_ARG_ENABLE(aligned,
|
||||
AC_HELP_STRING([--enable-aligned], [enable alignment safe code [[default=check]]]),
|
||||
AS_HELP_STRING([--enable-aligned],
|
||||
[enable alignment safe code [[default=check]]]),
|
||||
[
|
||||
if test "$enableval" = "yes"; then
|
||||
AC_DEFINE(USE_ALIGNED, 1, Require byte alignment)
|
||||
@@ -204,7 +216,8 @@ AC_DEFUN([TORRENT_DISABLE_INSTRUMENTATION], [
|
||||
AC_MSG_CHECKING([if instrumentation should be included])
|
||||
|
||||
AC_ARG_ENABLE(instrumentation,
|
||||
AC_HELP_STRING([--disable-instrumentation], [disable instrumentation [[default=enabled]]]),
|
||||
AS_HELP_STRING([--disable-instrumentation],
|
||||
[disable instrumentation [[default=enabled]]]),
|
||||
[
|
||||
if test "$enableval" = "yes"; then
|
||||
AC_DEFINE(LT_INSTRUMENTATION, 1, enable instrumentation)
|
||||
@@ -221,7 +234,8 @@ AC_DEFUN([TORRENT_DISABLE_INSTRUMENTATION], [
|
||||
|
||||
AC_DEFUN([TORRENT_ENABLE_INTERRUPT_SOCKET], [
|
||||
AC_ARG_ENABLE(interrupt-socket,
|
||||
AC_HELP_STRING([--enable-interrupt-socket], [enable interrupt socket [[default=no]]]),
|
||||
AS_HELP_STRING([--enable-interrupt-socket],
|
||||
[enable interrupt socket [[default=no]]]),
|
||||
[
|
||||
if test "$enableval" = "yes"; then
|
||||
AC_DEFINE(USE_INTERRUPT_SOCKET, 1, Use interrupt socket instead of pthread_kill)
|
||||
@@ -230,10 +244,10 @@ AC_DEFUN([TORRENT_ENABLE_INTERRUPT_SOCKET], [
|
||||
)
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN([TORRENT_DISABLE_IPV6], [
|
||||
AC_ARG_ENABLE(ipv6,
|
||||
AC_HELP_STRING([--enable-ipv6], [enable ipv6 [[default=no]]]),
|
||||
AS_HELP_STRING([--enable-ipv6],
|
||||
[enable ipv6 [[default=no]]]),
|
||||
[
|
||||
if test "$enableval" = "yes"; then
|
||||
AC_DEFINE(RAK_USE_INET6, 1, enable ipv6 stuff)
|
||||
|
||||
@@ -1,272 +0,0 @@
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# Project ___| | | | _ \| |
|
||||
# / __| | | | |_) | |
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) 2006, David Shaw <dshaw@jabberwocky.com>
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
# are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
#
|
||||
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
# copies of the Software, and permit persons to whom the Software is
|
||||
# furnished to do so, under the terms of the COPYING file.
|
||||
#
|
||||
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
# KIND, either express or implied.
|
||||
#
|
||||
###########################################################################
|
||||
# LIBCURL_CHECK_CONFIG ([DEFAULT-ACTION], [MINIMUM-VERSION],
|
||||
# [ACTION-IF-YES], [ACTION-IF-NO])
|
||||
# ----------------------------------------------------------
|
||||
# David Shaw <dshaw@jabberwocky.com> May-09-2006
|
||||
#
|
||||
# Checks for libcurl. DEFAULT-ACTION is the string yes or no to
|
||||
# specify whether to default to --with-libcurl or --without-libcurl.
|
||||
# If not supplied, DEFAULT-ACTION is yes. MINIMUM-VERSION is the
|
||||
# minimum version of libcurl to accept. Pass the version as a regular
|
||||
# version number like 7.10.1. If not supplied, any version is
|
||||
# accepted. ACTION-IF-YES is a list of shell commands to run if
|
||||
# libcurl was successfully found and passed the various tests.
|
||||
# ACTION-IF-NO is a list of shell commands that are run otherwise.
|
||||
# Note that using --without-libcurl does run ACTION-IF-NO.
|
||||
#
|
||||
# This macro #defines HAVE_LIBCURL if a working libcurl setup is
|
||||
# found, and sets @LIBCURL@ and @LIBCURL_CPPFLAGS@ to the necessary
|
||||
# values. Other useful defines are LIBCURL_FEATURE_xxx where xxx are
|
||||
# the various features supported by libcurl, and LIBCURL_PROTOCOL_yyy
|
||||
# where yyy are the various protocols supported by libcurl. Both xxx
|
||||
# and yyy are capitalized. See the list of AH_TEMPLATEs at the top of
|
||||
# the macro for the complete list of possible defines. Shell
|
||||
# variables $libcurl_feature_xxx and $libcurl_protocol_yyy are also
|
||||
# defined to 'yes' for those features and protocols that were found.
|
||||
# Note that xxx and yyy keep the same capitalization as in the
|
||||
# curl-config list (e.g. it's "HTTP" and not "http").
|
||||
#
|
||||
# Users may override the detected values by doing something like:
|
||||
# LIBCURL="-lcurl" LIBCURL_CPPFLAGS="-I/usr/myinclude" ./configure
|
||||
#
|
||||
# For the sake of sanity, this macro assumes that any libcurl that is
|
||||
# found is after version 7.7.2, the first version that included the
|
||||
# curl-config script. Note that it is very important for people
|
||||
# packaging binary versions of libcurl to include this script!
|
||||
# Without curl-config, we can only guess what protocols are available,
|
||||
# or use curl_version_info to figure it out at runtime.
|
||||
|
||||
AC_DEFUN([LIBCURL_CHECK_CONFIG],
|
||||
[
|
||||
AH_TEMPLATE([LIBCURL_FEATURE_SSL],[Defined if libcurl supports SSL])
|
||||
AH_TEMPLATE([LIBCURL_FEATURE_KRB4],[Defined if libcurl supports KRB4])
|
||||
AH_TEMPLATE([LIBCURL_FEATURE_IPV6],[Defined if libcurl supports IPv6])
|
||||
AH_TEMPLATE([LIBCURL_FEATURE_LIBZ],[Defined if libcurl supports libz])
|
||||
AH_TEMPLATE([LIBCURL_FEATURE_ASYNCHDNS],[Defined if libcurl supports AsynchDNS])
|
||||
AH_TEMPLATE([LIBCURL_FEATURE_IDN],[Defined if libcurl supports IDN])
|
||||
AH_TEMPLATE([LIBCURL_FEATURE_SSPI],[Defined if libcurl supports SSPI])
|
||||
AH_TEMPLATE([LIBCURL_FEATURE_NTLM],[Defined if libcurl supports NTLM])
|
||||
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_HTTP],[Defined if libcurl supports HTTP])
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_HTTPS],[Defined if libcurl supports HTTPS])
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_FTP],[Defined if libcurl supports FTP])
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_FTPS],[Defined if libcurl supports FTPS])
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_FILE],[Defined if libcurl supports FILE])
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_TELNET],[Defined if libcurl supports TELNET])
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_LDAP],[Defined if libcurl supports LDAP])
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_DICT],[Defined if libcurl supports DICT])
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_TFTP],[Defined if libcurl supports TFTP])
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_RTSP],[Defined if libcurl supports RTSP])
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_POP3],[Defined if libcurl supports POP3])
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_IMAP],[Defined if libcurl supports IMAP])
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_SMTP],[Defined if libcurl supports SMTP])
|
||||
|
||||
AC_ARG_WITH(libcurl,
|
||||
AS_HELP_STRING([--with-libcurl=PREFIX],[look for the curl library in PREFIX/lib and headers in PREFIX/include]),
|
||||
[_libcurl_with=$withval],[_libcurl_with=ifelse([$1],,[yes],[$1])])
|
||||
|
||||
if test "$_libcurl_with" != "no" ; then
|
||||
|
||||
AC_PROG_AWK
|
||||
|
||||
_libcurl_version_parse="eval $AWK '{split(\$NF,A,\".\"); X=256*256*A[[1]]+256*A[[2]]+A[[3]]; print X;}'"
|
||||
|
||||
_libcurl_try_link=yes
|
||||
|
||||
if test -d "$_libcurl_with" ; then
|
||||
LIBCURL_CPPFLAGS="-I$withval/include"
|
||||
_libcurl_ldflags="-L$withval/lib"
|
||||
AC_PATH_PROG([_libcurl_config],[curl-config],[],
|
||||
["$withval/bin"])
|
||||
else
|
||||
AC_PATH_PROG([_libcurl_config],[curl-config],[],[$PATH])
|
||||
fi
|
||||
|
||||
if test x$_libcurl_config != "x" ; then
|
||||
AC_CACHE_CHECK([for the version of libcurl],
|
||||
[libcurl_cv_lib_curl_version],
|
||||
[libcurl_cv_lib_curl_version=`$_libcurl_config --version | $AWK '{print $[]2}'`])
|
||||
|
||||
_libcurl_version=`echo $libcurl_cv_lib_curl_version | $_libcurl_version_parse`
|
||||
_libcurl_wanted=`echo ifelse([$2],,[0],[$2]) | $_libcurl_version_parse`
|
||||
|
||||
if test $_libcurl_wanted -gt 0 ; then
|
||||
AC_CACHE_CHECK([for libcurl >= version $2],
|
||||
[libcurl_cv_lib_version_ok],
|
||||
[
|
||||
if test $_libcurl_version -ge $_libcurl_wanted ; then
|
||||
libcurl_cv_lib_version_ok=yes
|
||||
else
|
||||
libcurl_cv_lib_version_ok=no
|
||||
fi
|
||||
])
|
||||
fi
|
||||
|
||||
if test $_libcurl_wanted -eq 0 || test x$libcurl_cv_lib_version_ok = xyes ; then
|
||||
if test x"$LIBCURL_CPPFLAGS" = "x" ; then
|
||||
LIBCURL_CPPFLAGS=`$_libcurl_config --cflags`
|
||||
fi
|
||||
if test x"$LIBCURL" = "x" ; then
|
||||
LIBCURL=`$_libcurl_config --libs`
|
||||
|
||||
# This is so silly, but Apple actually has a bug in their
|
||||
# curl-config script. Fixed in Tiger, but there are still
|
||||
# lots of Panther installs around.
|
||||
case "${host}" in
|
||||
powerpc-apple-darwin7*)
|
||||
LIBCURL=`echo $LIBCURL | sed -e 's|-arch i386||g'`
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# All curl-config scripts support --feature
|
||||
_libcurl_features=`$_libcurl_config --feature`
|
||||
|
||||
# Is it modern enough to have --protocols? (7.12.4)
|
||||
if test $_libcurl_version -ge 461828 ; then
|
||||
_libcurl_protocols=`$_libcurl_config --protocols`
|
||||
fi
|
||||
else
|
||||
_libcurl_try_link=no
|
||||
fi
|
||||
|
||||
unset _libcurl_wanted
|
||||
fi
|
||||
|
||||
if test $_libcurl_try_link = yes ; then
|
||||
|
||||
# we didn't find curl-config, so let's see if the user-supplied
|
||||
# link line (or failing that, "-lcurl") is enough.
|
||||
LIBCURL=${LIBCURL-"$_libcurl_ldflags -lcurl"}
|
||||
|
||||
AC_CACHE_CHECK([whether libcurl is usable],
|
||||
[libcurl_cv_lib_curl_usable],
|
||||
[
|
||||
_libcurl_save_cppflags=$CPPFLAGS
|
||||
CPPFLAGS="$LIBCURL_CPPFLAGS $CPPFLAGS"
|
||||
_libcurl_save_libs=$LIBS
|
||||
LIBS="$LIBCURL $LIBS"
|
||||
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <curl/curl.h>]],[[
|
||||
/* Try and use a few common options to force a failure if we are
|
||||
missing symbols or can't link. */
|
||||
int x;
|
||||
curl_easy_setopt(NULL,CURLOPT_URL,NULL);
|
||||
x=CURL_ERROR_SIZE;
|
||||
x=CURLOPT_WRITEFUNCTION;
|
||||
x=CURLOPT_WRITEDATA;
|
||||
x=CURLOPT_ERRORBUFFER;
|
||||
x=CURLOPT_STDERR;
|
||||
x=CURLOPT_VERBOSE;
|
||||
if (x) {;}
|
||||
]])],libcurl_cv_lib_curl_usable=yes,libcurl_cv_lib_curl_usable=no)
|
||||
|
||||
CPPFLAGS=$_libcurl_save_cppflags
|
||||
LIBS=$_libcurl_save_libs
|
||||
unset _libcurl_save_cppflags
|
||||
unset _libcurl_save_libs
|
||||
])
|
||||
|
||||
if test $libcurl_cv_lib_curl_usable = yes ; then
|
||||
|
||||
# Does curl_free() exist in this version of libcurl?
|
||||
# If not, fake it with free()
|
||||
|
||||
_libcurl_save_cppflags=$CPPFLAGS
|
||||
CPPFLAGS="$CPPFLAGS $LIBCURL_CPPFLAGS"
|
||||
_libcurl_save_libs=$LIBS
|
||||
LIBS="$LIBS $LIBCURL"
|
||||
|
||||
AC_CHECK_FUNC(curl_free,,
|
||||
AC_DEFINE(curl_free,free,
|
||||
[Define curl_free() as free() if our version of curl lacks curl_free.]))
|
||||
|
||||
CPPFLAGS=$_libcurl_save_cppflags
|
||||
LIBS=$_libcurl_save_libs
|
||||
unset _libcurl_save_cppflags
|
||||
unset _libcurl_save_libs
|
||||
|
||||
AC_DEFINE(HAVE_LIBCURL,1,
|
||||
[Define to 1 if you have a functional curl library.])
|
||||
AC_SUBST(LIBCURL_CPPFLAGS)
|
||||
AC_SUBST(LIBCURL)
|
||||
|
||||
for _libcurl_feature in $_libcurl_features ; do
|
||||
AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_feature_$_libcurl_feature),[1])
|
||||
eval AS_TR_SH(libcurl_feature_$_libcurl_feature)=yes
|
||||
done
|
||||
|
||||
if test "x$_libcurl_protocols" = "x" ; then
|
||||
|
||||
# We don't have --protocols, so just assume that all
|
||||
# protocols are available
|
||||
_libcurl_protocols="HTTP FTP FILE TELNET LDAP DICT TFTP"
|
||||
|
||||
if test x$libcurl_feature_SSL = xyes ; then
|
||||
_libcurl_protocols="$_libcurl_protocols HTTPS"
|
||||
|
||||
# FTPS wasn't standards-compliant until version
|
||||
# 7.11.0 (0x070b00 == 461568)
|
||||
if test $_libcurl_version -ge 461568; then
|
||||
_libcurl_protocols="$_libcurl_protocols FTPS"
|
||||
fi
|
||||
fi
|
||||
|
||||
# RTSP, IMAP, POP3 and SMTP were added in
|
||||
# 7.20.0 (0x071400 == 463872)
|
||||
if test $_libcurl_version -ge 463872; then
|
||||
_libcurl_protocols="$_libcurl_protocols RTSP IMAP POP3 SMTP"
|
||||
fi
|
||||
fi
|
||||
|
||||
for _libcurl_protocol in $_libcurl_protocols ; do
|
||||
AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_protocol_$_libcurl_protocol),[1])
|
||||
eval AS_TR_SH(libcurl_protocol_$_libcurl_protocol)=yes
|
||||
done
|
||||
else
|
||||
unset LIBCURL
|
||||
unset LIBCURL_CPPFLAGS
|
||||
fi
|
||||
fi
|
||||
|
||||
unset _libcurl_try_link
|
||||
unset _libcurl_version_parse
|
||||
unset _libcurl_config
|
||||
unset _libcurl_feature
|
||||
unset _libcurl_features
|
||||
unset _libcurl_protocol
|
||||
unset _libcurl_protocols
|
||||
unset _libcurl_version
|
||||
unset _libcurl_ldflags
|
||||
fi
|
||||
|
||||
if test x$_libcurl_with = xno || test x$libcurl_cv_lib_curl_usable != xyes ; then
|
||||
# This is the IF-NO path
|
||||
ifelse([$4],,:,[$4])
|
||||
else
|
||||
# This is the IF-YES path
|
||||
ifelse([$3],,:,[$3])
|
||||
fi
|
||||
|
||||
unset _libcurl_with
|
||||
])dnl
|
||||
@@ -26,7 +26,7 @@ AC_DEFUN([RAK_CHECK_CXXFLAGS], [
|
||||
|
||||
AC_DEFUN([RAK_ENABLE_DEBUG], [
|
||||
AC_ARG_ENABLE(debug,
|
||||
AC_HELP_STRING([--enable-debug], [enable debug information [[default=yes]]]),
|
||||
AS_HELP_STRING([--enable-debug],[enable debug information [[default=yes]]]),
|
||||
[
|
||||
if test "$enableval" = "yes"; then
|
||||
CXXFLAGS="$CXXFLAGS -g -DDEBUG"
|
||||
@@ -41,7 +41,7 @@ AC_DEFUN([RAK_ENABLE_DEBUG], [
|
||||
|
||||
AC_DEFUN([RAK_ENABLE_WERROR], [
|
||||
AC_ARG_ENABLE(werror,
|
||||
AC_HELP_STRING([--enable-werror], [enable the -Werror and -Wall flags [[default -Wall only]]]),
|
||||
AS_HELP_STRING([--enable-werror],[enable the -Werror and -Wall flags [[default -Wall only]]]),
|
||||
[
|
||||
if test "$enableval" = "yes"; then
|
||||
CXXFLAGS="$CXXFLAGS -Werror -Wall"
|
||||
@@ -54,7 +54,7 @@ AC_DEFUN([RAK_ENABLE_WERROR], [
|
||||
|
||||
AC_DEFUN([RAK_ENABLE_EXTRA_DEBUG], [
|
||||
AC_ARG_ENABLE(extra-debug,
|
||||
AC_HELP_STRING([--enable-extra-debug], [enable extra debugging checks [[default=no]]]),
|
||||
AS_HELP_STRING([--enable-extra-debug],[enable extra debugging checks [[default=no]]]),
|
||||
[
|
||||
if test "$enableval" = "yes"; then
|
||||
AC_DEFINE(USE_EXTRA_DEBUG, 1, Enable extra debugging checks.)
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
AC_DEFUN([RAK_CHECK_CXX11], [
|
||||
AC_ARG_ENABLE([c++0x],
|
||||
AC_HELP_STRING([--enable-c++0x], [compile with C++0x (unsupported)]),
|
||||
[
|
||||
if test "$enableval" = "yes"; then
|
||||
AX_CXX_COMPILE_STDCXX_0X
|
||||
else
|
||||
AX_CXX_COMPILE_STDCXX_11(noext)
|
||||
fi
|
||||
],[
|
||||
AX_CXX_COMPILE_STDCXX_11(noext)
|
||||
]
|
||||
)
|
||||
])
|
||||
|
||||
AC_DEFUN([RAK_CHECK_TR1_LIB], [
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_MSG_CHECKING(should use TR1 headers)
|
||||
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
|
||||
#include <unordered_map>
|
||||
class Foo; typedef std::unordered_map<Foo*, int> Bar;
|
||||
Bar b1;
|
||||
])
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
AC_DEFINE(USE_TR1_LIB, 0, Define to 1 if you need to use TR1 containers.)
|
||||
|
||||
AC_DEFINE([lt_tr1_array], [<array>], [TR1 array])
|
||||
AC_DEFINE([lt_tr1_functional], [<functional>], [TR1 functional])
|
||||
AC_DEFINE([lt_tr1_memory], [<memory>], [TR1 memory])
|
||||
AC_DEFINE([lt_tr1_unordered_map], [<unordered_map>], [TR1 unordered_map])
|
||||
|
||||
], [
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
|
||||
#include <tr1/unordered_map>
|
||||
class Foo; typedef std::tr1::unordered_map<Foo*, int> Bar;
|
||||
Bar b1;
|
||||
])
|
||||
], [
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE(USE_TR1_LIB, 1, Define to 1 if you need to use TR1 containers.)
|
||||
|
||||
AC_DEFINE([lt_tr1_array], [<tr1/array>], [TR1 array])
|
||||
AC_DEFINE([lt_tr1_functional], [<tr1/functional>], [TR1 functional])
|
||||
AC_DEFINE([lt_tr1_memory], [<tr1/memory>], [TR1 memory])
|
||||
AC_DEFINE([lt_tr1_unordered_map], [<tr1/unordered_map>], [TR1 unordered_map])
|
||||
|
||||
], [
|
||||
AC_MSG_ERROR([No support for C++11 standard library nor TR1 extensions found.])
|
||||
])
|
||||
])
|
||||
|
||||
AH_VERBATIM(lt_tr1_zzz, [
|
||||
#if USE_TR1_LIB == 1
|
||||
namespace std { namespace tr1 {} using namespace tr1; }
|
||||
#endif
|
||||
])
|
||||
|
||||
AC_LANG_POP(C++)
|
||||
])
|
||||
@@ -0,0 +1,38 @@
|
||||
AC_DEFUN([TORRENT_CHECK_OPENSSL],
|
||||
[
|
||||
PKG_CHECK_MODULES(OPENSSL, libcrypto,
|
||||
CXXFLAGS="$CXXFLAGS $OPENSSL_CFLAGS";
|
||||
LIBS="$LIBS $OPENSSL_LIBS")
|
||||
|
||||
AC_DEFINE(USE_OPENSSL, 1, Using OpenSSL.)
|
||||
AC_DEFINE(USE_OPENSSL_SHA, 1, Using OpenSSL's SHA1 implementation.)
|
||||
]
|
||||
)
|
||||
|
||||
AC_DEFUN([TORRENT_ARG_OPENSSL],
|
||||
[
|
||||
AC_ARG_ENABLE(openssl,
|
||||
[ --disable-openssl Don't use OpenSSL's SHA1 implementation.],
|
||||
[
|
||||
if test "$enableval" = "yes"; then
|
||||
TORRENT_CHECK_OPENSSL
|
||||
else
|
||||
AC_DEFINE(USE_NSS_SHA, 1, Using Mozilla's SHA1 implementation.)
|
||||
fi
|
||||
],[
|
||||
TORRENT_CHECK_OPENSSL
|
||||
])
|
||||
]
|
||||
)
|
||||
|
||||
AC_DEFUN([TORRENT_ARG_CYRUS_RC4],
|
||||
[
|
||||
AC_ARG_ENABLE(cyrus-rc4,
|
||||
[ --enable-cyrus-rc4=PFX Use Cyrus RC4 implementation.],
|
||||
[
|
||||
CXXFLAGS="$CXXFLAGS -I${enableval}/include";
|
||||
LIBS="$LIBS -lrc4 -L${enableval}/lib"
|
||||
AC_DEFINE(USE_CYRUS_RC4, 1, Using Cyrus RC4 implementation.)
|
||||
])
|
||||
]
|
||||
)
|
||||
+173
-24
@@ -1,14 +1,179 @@
|
||||
SUBDIRS = \
|
||||
core \
|
||||
display \
|
||||
input \
|
||||
rpc \
|
||||
ui \
|
||||
utils
|
||||
|
||||
noinst_LIBRARIES = libsub_root.a
|
||||
bin_PROGRAMS = rtorrent
|
||||
|
||||
rtorrent_LDADD = libsub_root.a @PTHREAD_LIBS@
|
||||
rtorrent_SOURCES = main.cc
|
||||
|
||||
libsub_root_a_SOURCES = \
|
||||
core/curl_get.cc \
|
||||
core/curl_get.h \
|
||||
core/curl_socket.cc \
|
||||
core/curl_socket.h \
|
||||
core/curl_stack.cc \
|
||||
core/curl_stack.h \
|
||||
core/dht_manager.cc \
|
||||
core/dht_manager.h \
|
||||
core/download.cc \
|
||||
core/download.h \
|
||||
core/download_factory.cc \
|
||||
core/download_factory.h \
|
||||
core/download_list.cc \
|
||||
core/download_list.h \
|
||||
core/download_slot_map.h \
|
||||
core/download_store.cc \
|
||||
core/download_store.h \
|
||||
core/http_queue.cc \
|
||||
core/http_queue.h \
|
||||
core/manager.cc \
|
||||
core/manager.h \
|
||||
core/range_map.h \
|
||||
core/view.cc \
|
||||
core/view.h \
|
||||
core/view_manager.cc \
|
||||
core/view_manager.h \
|
||||
\
|
||||
display/attributes.h \
|
||||
display/canvas.cc \
|
||||
display/canvas.h \
|
||||
display/color_map.h \
|
||||
display/frame.cc \
|
||||
display/frame.h \
|
||||
display/manager.cc \
|
||||
display/manager.h \
|
||||
display/utils.cc \
|
||||
display/utils.h \
|
||||
display/text_element.h \
|
||||
display/text_element_list.cc \
|
||||
display/text_element_list.h \
|
||||
display/text_element_string.cc \
|
||||
display/text_element_string.h \
|
||||
display/text_element_value.cc \
|
||||
display/text_element_value.h \
|
||||
display/window.cc \
|
||||
display/window.h \
|
||||
display/window_download_chunks_seen.cc \
|
||||
display/window_download_chunks_seen.h \
|
||||
display/window_download_list.cc \
|
||||
display/window_download_list.h \
|
||||
display/window_download_statusbar.cc \
|
||||
display/window_download_statusbar.h \
|
||||
display/window_download_transfer_list.cc \
|
||||
display/window_download_transfer_list.h \
|
||||
display/window_file_list.cc \
|
||||
display/window_file_list.h \
|
||||
display/window_http_queue.cc \
|
||||
display/window_http_queue.h \
|
||||
display/window_input.cc \
|
||||
display/window_input.h \
|
||||
display/window_log.cc \
|
||||
display/window_log.h \
|
||||
display/window_log_complete.cc \
|
||||
display/window_log_complete.h \
|
||||
display/window_peer_list.cc \
|
||||
display/window_peer_list.h \
|
||||
display/window_statusbar.cc \
|
||||
display/window_statusbar.h \
|
||||
display/window_string_list.cc \
|
||||
display/window_string_list.h \
|
||||
display/window_text.cc \
|
||||
display/window_text.h \
|
||||
display/window_title.cc \
|
||||
display/window_title.h \
|
||||
display/window_tracker_list.cc \
|
||||
display/window_tracker_list.h \
|
||||
\
|
||||
input/bindings.cc \
|
||||
input/bindings.h \
|
||||
input/input_event.cc \
|
||||
input/input_event.h \
|
||||
input/manager.cc \
|
||||
input/manager.h \
|
||||
input/path_input.cc \
|
||||
input/path_input.h \
|
||||
input/text_input.cc \
|
||||
input/text_input.h \
|
||||
\
|
||||
rpc/command.h \
|
||||
rpc/command.cc \
|
||||
rpc/command_impl.h \
|
||||
rpc/command_map.cc \
|
||||
rpc/command_map.h \
|
||||
rpc/command_scheduler.cc \
|
||||
rpc/command_scheduler.h \
|
||||
rpc/command_scheduler_item.cc \
|
||||
rpc/command_scheduler_item.h \
|
||||
rpc/exec_file.cc \
|
||||
rpc/exec_file.h \
|
||||
rpc/fixed_key.h \
|
||||
rpc/ip_table_list.h \
|
||||
rpc/lua.h \
|
||||
rpc/lua.cc \
|
||||
rpc/jsonrpc.cc \
|
||||
rpc/jsonrpc.h \
|
||||
rpc/rpc_manager.cc \
|
||||
rpc/rpc_manager.h \
|
||||
rpc/object_storage.cc \
|
||||
rpc/object_storage.h \
|
||||
rpc/parse.cc \
|
||||
rpc/parse.h \
|
||||
rpc/parse_commands.cc \
|
||||
rpc/parse_commands.h \
|
||||
rpc/parse_options.cc \
|
||||
rpc/parse_options.h \
|
||||
rpc/scgi.cc \
|
||||
rpc/scgi.h \
|
||||
rpc/scgi_task.cc \
|
||||
rpc/scgi_task.h \
|
||||
rpc/xmlrpc.h \
|
||||
rpc/xmlrpc.cc \
|
||||
rpc/xmlrpc_c.cc \
|
||||
rpc/xmlrpc_tinyxml2.cc \
|
||||
rpc/tinyxml2/tinyxml2.h \
|
||||
rpc/tinyxml2/tinyxml2.cc \
|
||||
rpc/nlohmann/json.h \
|
||||
\
|
||||
ui/download.cc \
|
||||
ui/download.h \
|
||||
ui/download_list.cc \
|
||||
ui/download_list.h \
|
||||
ui/element_base.h \
|
||||
ui/element_base.cc \
|
||||
ui/element_chunks_seen.cc \
|
||||
ui/element_chunks_seen.h \
|
||||
ui/element_download_list.cc \
|
||||
ui/element_download_list.h \
|
||||
ui/element_file_list.cc \
|
||||
ui/element_file_list.h \
|
||||
ui/element_log_complete.cc \
|
||||
ui/element_log_complete.h \
|
||||
ui/element_menu.cc \
|
||||
ui/element_menu.h \
|
||||
ui/element_peer_list.cc \
|
||||
ui/element_peer_list.h \
|
||||
ui/element_string_list.cc \
|
||||
ui/element_string_list.h \
|
||||
ui/element_text.cc \
|
||||
ui/element_text.h \
|
||||
ui/element_tracker_list.cc \
|
||||
ui/element_tracker_list.h \
|
||||
ui/element_transfer_list.cc \
|
||||
ui/element_transfer_list.h \
|
||||
ui/root.cc \
|
||||
ui/root.h \
|
||||
\
|
||||
utils/base64.cc \
|
||||
utils/base64.h \
|
||||
utils/directory.cc \
|
||||
utils/directory.h \
|
||||
utils/file_status_cache.cc \
|
||||
utils/file_status_cache.h \
|
||||
utils/functional.h \
|
||||
utils/list_focus.h \
|
||||
utils/lockfile.cc \
|
||||
utils/lockfile.h \
|
||||
utils/socket_fd.cc \
|
||||
utils/socket_fd.h \
|
||||
\
|
||||
command_download.cc \
|
||||
command_dynamic.cc \
|
||||
command_events.cc \
|
||||
@@ -33,24 +198,8 @@ libsub_root_a_SOURCES = \
|
||||
option_parser.h \
|
||||
signal_handler.cc \
|
||||
signal_handler.h \
|
||||
thread_base.cc \
|
||||
thread_base.h \
|
||||
thread_worker.cc \
|
||||
thread_worker.h
|
||||
|
||||
bin_PROGRAMS = rtorrent
|
||||
|
||||
rtorrent_LDADD = \
|
||||
libsub_root.a \
|
||||
ui/libsub_ui.a \
|
||||
core/libsub_core.a \
|
||||
display/libsub_display.a \
|
||||
input/libsub_input.a \
|
||||
rpc/libsub_rpc.a \
|
||||
utils/libsub_utils.a \
|
||||
@PTHREAD_LIBS@
|
||||
|
||||
rtorrent_SOURCES = \
|
||||
main.cc
|
||||
|
||||
AM_CPPFLAGS = -I$(srcdir) -I$(top_srcdir)
|
||||
|
||||
+94
-87
@@ -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.");
|
||||
|
||||
@@ -140,7 +106,7 @@ apply_d_change_link(core::Download* download, const torrent::Object::list_type&
|
||||
case 0:
|
||||
if (symlink(target.c_str(), link.c_str()) == -1){
|
||||
lt_log_print(torrent::LOG_TORRENT_WARN, "create_link failed: %s",
|
||||
rak::error_number::current().c_str());
|
||||
rak::error_number::current().c_str());
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -274,6 +240,41 @@ retrieve_d_custom_throw(core::Download* download, const std::string& key) {
|
||||
}
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
retrieve_d_custom_if_z(core::Download* download, const torrent::Object::list_type& args) {
|
||||
torrent::Object::list_const_iterator itr = args.begin();
|
||||
if (itr == args.end())
|
||||
throw torrent::bencode_error("d.custom.if_z: Missing key argument.");
|
||||
const std::string& key = (itr++)->as_string();
|
||||
if (key.empty())
|
||||
throw torrent::bencode_error("d.custom.if_z: Empty key argument.");
|
||||
if (itr == args.end())
|
||||
throw torrent::bencode_error("d.custom.if_z: Missing default argument.");
|
||||
|
||||
try {
|
||||
const std::string& val = download->bencode()->get_key("rtorrent").get_key("custom").get_key_string(key);
|
||||
return val.empty() ? itr->as_string() : val;
|
||||
} catch (torrent::bencode_error& e) {
|
||||
return itr->as_string();
|
||||
}
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
retrieve_d_custom_map(core::Download* download, bool keys_only, const torrent::Object::list_type& args) {
|
||||
if (args.begin() != args.end())
|
||||
throw torrent::bencode_error("d.custom.keys/items takes no arguments.");
|
||||
|
||||
torrent::Object result = keys_only ? torrent::Object::create_list() : torrent::Object::create_map();
|
||||
torrent::Object::map_type& entries = download->bencode()->get_key("rtorrent").get_key("custom").as_map();
|
||||
|
||||
for (torrent::Object::map_type::const_iterator itr = entries.begin(), last = entries.end(); itr != last; itr++) {
|
||||
if (keys_only) result.as_list().push_back(itr->first);
|
||||
else result.as_map()[itr->first] = itr->second;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
retrieve_d_bitfield(core::Download* download) {
|
||||
const torrent::Bitfield* bitField = download->download()->file_list()->bitfield();
|
||||
@@ -284,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_CONNECTION_WARN, "Could not resolve hostname for added peer.");
|
||||
} else {
|
||||
m_download->download()->add_peer(sa, m_port);
|
||||
}
|
||||
}
|
||||
|
||||
core::Download* m_download;
|
||||
int m_port;
|
||||
};
|
||||
|
||||
void
|
||||
apply_d_add_peer(core::Download* download, const std::string& arg) {
|
||||
int port, ret;
|
||||
@@ -321,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
|
||||
@@ -375,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -392,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
|
||||
@@ -487,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();
|
||||
}
|
||||
|
||||
@@ -547,20 +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(),
|
||||
rak::bind1st(std::ptr_fun(&torrent::object_equal), 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();
|
||||
}
|
||||
@@ -570,8 +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(),
|
||||
rak::bind1st(std::ptr_fun(&torrent::object_equal), 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
|
||||
@@ -579,7 +578,7 @@ d_list_remove(core::Download* download, const torrent::Object& rawArgs, const ch
|
||||
const torrent::Object& args = (rawArgs.is_list() && !rawArgs.as_list().empty()) ? rawArgs.as_list().front() : rawArgs;
|
||||
torrent::Object::list_type& list = download_get_variable(download, first_key, second_key).as_list();
|
||||
|
||||
list.erase(std::remove_if(list.begin(), list.end(), rak::bind1st(std::ptr_fun(&torrent::object_equal), args)), list.end());
|
||||
list.erase(std::remove_if(list.begin(), list.end(), [args](const torrent::Object& obj) { return torrent::object_equal(obj, args); }), list.end());
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
@@ -593,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)
|
||||
@@ -710,6 +708,9 @@ initialize_command_download() {
|
||||
CMD2_DL_STRING("d.custom", std::bind(&retrieve_d_custom, std::placeholders::_1, std::placeholders::_2));
|
||||
CMD2_DL_STRING("d.custom_throw", std::bind(&retrieve_d_custom_throw, std::placeholders::_1, std::placeholders::_2));
|
||||
CMD2_DL_LIST ("d.custom.set", std::bind(&apply_d_custom, std::placeholders::_1, std::placeholders::_2));
|
||||
CMD2_DL_LIST ("d.custom.if_z", std::bind(&retrieve_d_custom_if_z, std::placeholders::_1, std::placeholders::_2));
|
||||
CMD2_DL_LIST ("d.custom.keys", std::bind(&retrieve_d_custom_map, std::placeholders::_1, true, std::placeholders::_2));
|
||||
CMD2_DL_LIST ("d.custom.items", std::bind(&retrieve_d_custom_map, std::placeholders::_1, false, std::placeholders::_2));
|
||||
|
||||
CMD2_DL_VAR_STRING_PUBLIC("d.custom1", "rtorrent", "custom1");
|
||||
CMD2_DL_VAR_STRING_PUBLIC("d.custom2", "rtorrent", "custom2");
|
||||
@@ -776,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.
|
||||
@@ -834,15 +835,21 @@ initialize_command_download() {
|
||||
|
||||
CMD2_DL ("d.wanted_chunks", CMD2_ON_DATA(wanted_chunks));
|
||||
|
||||
CMD2_DL_V ("d.tracker_announce", std::bind(&torrent::Download::manual_request, CMD2_BIND_DL, false));
|
||||
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));
|
||||
// Do not exposre d.tracker_announce.force to regular users.
|
||||
CMD2_DL_V ("d.tracker_announce", std::bind(&torrent::Download::manual_request, CMD2_BIND_DL, false));
|
||||
CMD2_DL_V ("d.tracker_announce.force", std::bind(&torrent::Download::manual_request, CMD2_BIND_DL, true));
|
||||
|
||||
CMD2_DL ("d.tracker_numwant", std::bind(&torrent::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));
|
||||
@@ -864,7 +871,7 @@ initialize_command_download() {
|
||||
// CG_GROUP_INDEX()));
|
||||
|
||||
CMD2_DL ("d.group", std::bind(&cg_d_group, std::placeholders::_1));
|
||||
CMD2_DL ("d.group.name", std::bind(&cg_d_group, std::placeholders::_1));
|
||||
CMD2_DL ("d.group.name", std::bind(&cg_d_group_name, std::placeholders::_1));
|
||||
CMD2_DL_V ("d.group.set", std::bind(&cg_d_group_set, std::placeholders::_1, std::placeholders::_2));
|
||||
|
||||
CMD2_DL_LIST ("f.multicall", std::bind(&f_multicall, std::placeholders::_1, std::placeholders::_2));
|
||||
|
||||
+146
-172
@@ -1,49 +1,36 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <torrent/utils/log.h>
|
||||
#include <torrent/utils/option_strings.h>
|
||||
|
||||
#include "globals.h"
|
||||
#include "control.h"
|
||||
#include "command_helpers.h"
|
||||
#include "control.h"
|
||||
#include "globals.h"
|
||||
#include "rpc/parse.h"
|
||||
#include "rpc/parse_options.h"
|
||||
|
||||
static std::vector<std::pair<const char*, int>> object_storage_flags = {
|
||||
{"multi", rpc::object_storage::flag_multi_type},
|
||||
{"simple", rpc::object_storage::flag_function_type},
|
||||
{"value", rpc::object_storage::flag_value_type},
|
||||
{"bool", rpc::object_storage::flag_bool_type},
|
||||
{"string", rpc::object_storage::flag_string_type},
|
||||
{"list", rpc::object_storage::flag_list_type},
|
||||
|
||||
{"static", rpc::object_storage::flag_static},
|
||||
{"private", rpc::object_storage::flag_private},
|
||||
{"const", rpc::object_storage::flag_constant},
|
||||
{"rlookup", rpc::object_storage::flag_rlookup}};
|
||||
|
||||
static int
|
||||
object_storage_parse_flag(const std::string& flag) {
|
||||
for (auto f : object_storage_flags)
|
||||
if (f.first == flag)
|
||||
return f.second;
|
||||
|
||||
throw torrent::input_error("unknown flag");
|
||||
}
|
||||
|
||||
std::string
|
||||
system_method_generate_command(torrent::Object::list_const_iterator first, torrent::Object::list_const_iterator last) {
|
||||
@@ -85,7 +72,7 @@ system_method_generate_command2(torrent::Object* object, torrent::Object::list_c
|
||||
if (first + 1 == last) {
|
||||
if (!first->is_dict_key())
|
||||
throw torrent::input_error("New command of wrong type.");
|
||||
|
||||
|
||||
*object = *first;
|
||||
|
||||
uint32_t flags = object->flags() & torrent::Object::mask_function;
|
||||
@@ -98,9 +85,9 @@ system_method_generate_command2(torrent::Object* object, torrent::Object::list_c
|
||||
while (first != last) {
|
||||
if (!first->is_dict_key())
|
||||
throw torrent::input_error("New command of wrong type.");
|
||||
|
||||
|
||||
object->as_list().push_back(*first++);
|
||||
|
||||
|
||||
uint32_t flags = object->as_list().back().flags() & torrent::Object::mask_function;
|
||||
object->as_list().back().unset_flags(torrent::Object::mask_function);
|
||||
object->as_list().back().set_flags((flags >> 1) & torrent::Object::mask_function);
|
||||
@@ -110,20 +97,32 @@ system_method_generate_command2(torrent::Object* object, torrent::Object::list_c
|
||||
|
||||
// torrent::Object
|
||||
// system_method_insert_function(const torrent::Object::list_type& args, int flags) {
|
||||
|
||||
|
||||
// }
|
||||
|
||||
// This is only used by tinyxml2, xmlrpc-c intercepts the call internally
|
||||
torrent::Object
|
||||
system_listMethods() {
|
||||
torrent::Object resultRaw = torrent::Object::create_list();
|
||||
torrent::Object::list_type& result = resultRaw.as_list();
|
||||
result.push_back("system.multicall"); // Handled directly by the XMLRPC code
|
||||
for (auto itr : rpc::commands) {
|
||||
result.push_back(itr.first);
|
||||
}
|
||||
return resultRaw;
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
system_method_insert_object(const torrent::Object::list_type& args, int flags) {
|
||||
if (args.empty())
|
||||
throw torrent::input_error("Invalid argument count.");
|
||||
|
||||
torrent::Object::list_const_iterator itrArgs = args.begin();
|
||||
const std::string& rawKey = (itrArgs++)->as_string();
|
||||
const std::string& raw_key = (itrArgs++)->as_string();
|
||||
|
||||
if (rawKey.empty() ||
|
||||
control->object_storage()->find_local(torrent::raw_string::from_string(rawKey)) != control->object_storage()->end(0) ||
|
||||
rpc::commands.has(rawKey) || rpc::commands.has(rawKey + ".set"))
|
||||
if (raw_key.empty() ||
|
||||
control->object_storage()->find_raw_string(torrent::raw_string::from_string(raw_key)) != control->object_storage()->end() ||
|
||||
rpc::commands.has(raw_key) || rpc::commands.has(raw_key + ".set"))
|
||||
throw torrent::input_error("Invalid key.");
|
||||
|
||||
torrent::Object value;
|
||||
@@ -139,6 +138,8 @@ system_method_insert_object(const torrent::Object::list_type& args, int flags) {
|
||||
case rpc::object_storage::flag_function_type:
|
||||
system_method_generate_command2(&value, itrArgs, args.end());
|
||||
break;
|
||||
case rpc::object_storage::flag_list_type:
|
||||
break;
|
||||
case rpc::object_storage::flag_multi_type:
|
||||
break;
|
||||
default:
|
||||
@@ -150,67 +151,96 @@ system_method_insert_object(const torrent::Object::list_type& args, int flags) {
|
||||
if (!(flags & rpc::object_storage::flag_static))
|
||||
cmd_flags |= rpc::CommandMap::flag_modifiable;
|
||||
if (!(flags & rpc::object_storage::flag_private))
|
||||
cmd_flags |= rpc::CommandMap::flag_public_xmlrpc;
|
||||
cmd_flags |= rpc::CommandMap::flag_public_rpc;
|
||||
|
||||
control->object_storage()->insert_str(rawKey, value, flags);
|
||||
if ((flags & rpc::object_storage::mask_type) == rpc::object_storage::flag_list_type) {
|
||||
torrent::Object valueList = torrent::Object::create_list();
|
||||
torrent::Object::list_type& valueListType = valueList.as_list();
|
||||
|
||||
if ((itrArgs)->is_list())
|
||||
valueListType = (itrArgs)->as_list();
|
||||
|
||||
control->object_storage()->insert_str(raw_key, valueList, flags);
|
||||
} else {
|
||||
control->object_storage()->insert_str(raw_key, value, flags);
|
||||
}
|
||||
|
||||
if ((flags & rpc::object_storage::mask_type) == rpc::object_storage::flag_function_type ||
|
||||
(flags & rpc::object_storage::mask_type) == rpc::object_storage::flag_multi_type) {
|
||||
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call<rpc::target_type> >::type>
|
||||
(create_new_key(rawKey),
|
||||
std::bind(&rpc::object_storage::call_function_str, control->object_storage(),
|
||||
rawKey, std::placeholders::_1, std::placeholders::_2),
|
||||
&rpc::command_base_call<rpc::target_type>,
|
||||
cmd_flags, NULL, NULL);
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call<rpc::target_type>>::type>(
|
||||
raw_key,
|
||||
std::bind(&rpc::object_storage::call_function_str, control->object_storage(), raw_key, std::placeholders::_1, std::placeholders::_2),
|
||||
&rpc::command_base_call<rpc::target_type>,
|
||||
cmd_flags,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
} else {
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call<rpc::target_type> >::type>
|
||||
(create_new_key(rawKey),
|
||||
std::bind(&rpc::object_storage::get_str, control->object_storage(), rawKey),
|
||||
&rpc::command_base_call<rpc::target_type>,
|
||||
cmd_flags, NULL, NULL);
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call<rpc::target_type>>::type>(
|
||||
raw_key,
|
||||
std::bind(&rpc::object_storage::get_str, control->object_storage(), raw_key),
|
||||
&rpc::command_base_call<rpc::target_type>,
|
||||
cmd_flags,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
// Not the right argument.
|
||||
// if (flags & rpc::object_storage::flag_rlookup) {
|
||||
// rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_string<rpc::target_type> >::type>
|
||||
// (create_new_key<9>(rawKey, ".rlookup"),
|
||||
// std::bind(&rpc::object_storage::rlookup_obj_list, control->object_storage(), rawKey),
|
||||
// (create_new_key<9>(raw_key, ".rlookup"),
|
||||
// std::bind(&rpc::object_storage::rlookup_obj_list, control->object_storage(), raw_key),
|
||||
// &rpc::command_base_call_string<rpc::target_type>,
|
||||
// cmd_flags, NULL, NULL);
|
||||
// }
|
||||
|
||||
// TODO: Next... Make test class for this.
|
||||
|
||||
// // Ehm... no proper handling if these throw.
|
||||
// // Ehm... no proper handling if these throw.
|
||||
|
||||
if (!(flags & rpc::object_storage::flag_constant)) {
|
||||
switch (flags & rpc::object_storage::mask_type) {
|
||||
case rpc::object_storage::flag_bool_type:
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_value<rpc::target_type> >::type>
|
||||
(create_new_key<5>(rawKey, ".set"),
|
||||
std::bind(&rpc::object_storage::set_str_bool, control->object_storage(), rawKey, std::placeholders::_2),
|
||||
&rpc::command_base_call_value<rpc::target_type>,
|
||||
cmd_flags, NULL, NULL);
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_value<rpc::target_type>>::type>(
|
||||
raw_key + ".set",
|
||||
std::bind(&rpc::object_storage::set_str_bool, control->object_storage(), raw_key, std::placeholders::_2),
|
||||
&rpc::command_base_call_value<rpc::target_type>,
|
||||
cmd_flags,
|
||||
NULL,
|
||||
NULL);
|
||||
break;
|
||||
case rpc::object_storage::flag_value_type:
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_value<rpc::target_type> >::type>
|
||||
(create_new_key<5>(rawKey, ".set"),
|
||||
std::bind(&rpc::object_storage::set_str_value, control->object_storage(), rawKey, std::placeholders::_2),
|
||||
&rpc::command_base_call_value<rpc::target_type>,
|
||||
cmd_flags, NULL, NULL);
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_value<rpc::target_type>>::type>(
|
||||
raw_key + ".set",
|
||||
std::bind(&rpc::object_storage::set_str_value, control->object_storage(), raw_key, std::placeholders::_2),
|
||||
&rpc::command_base_call_value<rpc::target_type>,
|
||||
cmd_flags,
|
||||
NULL,
|
||||
NULL);
|
||||
break;
|
||||
case rpc::object_storage::flag_string_type:
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_string<rpc::target_type> >::type>
|
||||
(create_new_key<5>(rawKey, ".set"),
|
||||
std::bind(&rpc::object_storage::set_str_string, control->object_storage(), rawKey, std::placeholders::_2),
|
||||
&rpc::command_base_call_string<rpc::target_type>,
|
||||
cmd_flags, NULL, NULL);
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_string<rpc::target_type>>::type>(
|
||||
raw_key + ".set",
|
||||
std::bind(&rpc::object_storage::set_str_string, control->object_storage(), raw_key, std::placeholders::_2),
|
||||
&rpc::command_base_call_string<rpc::target_type>,
|
||||
cmd_flags,
|
||||
NULL,
|
||||
NULL);
|
||||
break;
|
||||
case rpc::object_storage::flag_list_type:
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_list<rpc::target_type>>::type>(
|
||||
raw_key + ".set",
|
||||
std::bind(&rpc::object_storage::set_str_list, control->object_storage(), raw_key, std::placeholders::_2),
|
||||
&rpc::command_base_call_list<rpc::target_type>,
|
||||
cmd_flags,
|
||||
NULL,
|
||||
NULL);
|
||||
break;
|
||||
case rpc::object_storage::flag_function_type:
|
||||
case rpc::object_storage::flag_multi_type:
|
||||
default: break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,97 +268,32 @@ system_method_insert(const torrent::Object::list_type& args) {
|
||||
throw torrent::input_error("Invalid argument count.");
|
||||
|
||||
torrent::Object::list_const_iterator itrArgs = args.begin();
|
||||
const std::string& rawKey = (itrArgs++)->as_string();
|
||||
const std::string& raw_key = (itrArgs++)->as_string();
|
||||
|
||||
if (rawKey.empty() || rpc::commands.has(rawKey))
|
||||
if (raw_key.empty() || rpc::commands.has(raw_key))
|
||||
throw torrent::input_error("Invalid key.");
|
||||
|
||||
int flags = rpc::CommandMap::flag_delete_key | rpc::CommandMap::flag_modifiable | rpc::CommandMap::flag_public_xmlrpc;
|
||||
int new_flags = rpc::parse_option_flags(itrArgs->as_string(), std::bind(&object_storage_parse_flag, std::placeholders::_1));
|
||||
|
||||
const std::string& options = itrArgs->as_string();
|
||||
torrent::Object::list_type new_args;
|
||||
new_args.push_back(raw_key);
|
||||
|
||||
// TODO: Replace find with a method that does '|' separated search
|
||||
// for all valid options, and then cross-checks that unmixable ones
|
||||
// aren't in there. Use a bitfield.
|
||||
|
||||
if (options.find("private") != std::string::npos)
|
||||
flags &= ~rpc::CommandMap::flag_public_xmlrpc;
|
||||
if (options.find("const") != std::string::npos)
|
||||
flags &= ~rpc::CommandMap::flag_modifiable;
|
||||
|
||||
if (options.find("multi") != std::string::npos) {
|
||||
torrent::Object::list_type new_args;
|
||||
new_args.push_back(rawKey);
|
||||
if ((new_flags & rpc::object_storage::flag_function_type) ||
|
||||
(new_flags & rpc::object_storage::flag_multi_type)) {
|
||||
new_args.push_back(system_method_generate_command(++itrArgs, args.end()));
|
||||
|
||||
int new_flags = rpc::object_storage::flag_multi_type;
|
||||
|
||||
if (options.find("static") != std::string::npos)
|
||||
new_flags |= rpc::object_storage::flag_static;
|
||||
if (options.find("private") != std::string::npos)
|
||||
new_flags |= rpc::object_storage::flag_private;
|
||||
if (options.find("const") != std::string::npos)
|
||||
new_flags |= rpc::object_storage::flag_constant;
|
||||
if (options.find("rlookup") != std::string::npos)
|
||||
new_flags |= rpc::object_storage::flag_rlookup;
|
||||
|
||||
return system_method_insert_object(new_args, new_flags);
|
||||
|
||||
} else if (options.find("simple") != std::string::npos) {
|
||||
torrent::Object::list_type new_args;
|
||||
new_args.push_back(rawKey);
|
||||
new_args.push_back(system_method_generate_command(++itrArgs, args.end()));
|
||||
|
||||
int new_flags = rpc::object_storage::flag_function_type;
|
||||
|
||||
if (options.find("static") != std::string::npos)
|
||||
new_flags |= rpc::object_storage::flag_static;
|
||||
if (options.find("private") != std::string::npos)
|
||||
new_flags |= rpc::object_storage::flag_private;
|
||||
if (options.find("const") != std::string::npos)
|
||||
new_flags |= rpc::object_storage::flag_constant;
|
||||
|
||||
return system_method_insert_object(new_args, new_flags);
|
||||
|
||||
} else if (options.find("value") != std::string::npos ||
|
||||
options.find("bool") != std::string::npos ||
|
||||
options.find("string") != std::string::npos ||
|
||||
options.find("list") != std::string::npos) {
|
||||
torrent::Object::list_type new_args;
|
||||
new_args.push_back(rawKey);
|
||||
|
||||
} else if ((new_flags & rpc::object_storage::flag_value_type) ||
|
||||
(new_flags & rpc::object_storage::flag_bool_type) ||
|
||||
(new_flags & rpc::object_storage::flag_string_type) ||
|
||||
(new_flags & rpc::object_storage::flag_list_type)) {
|
||||
if (++itrArgs != args.end())
|
||||
new_args.insert(new_args.end(), itrArgs, args.end());
|
||||
|
||||
int new_flags;
|
||||
|
||||
if (options.find("value") != std::string::npos)
|
||||
new_flags = rpc::object_storage::flag_value_type;
|
||||
else if (options.find("bool") != std::string::npos)
|
||||
new_flags = rpc::object_storage::flag_bool_type;
|
||||
else if (options.find("string") != std::string::npos)
|
||||
new_flags = rpc::object_storage::flag_string_type;
|
||||
else if (options.find("list") != std::string::npos)
|
||||
new_flags = rpc::object_storage::flag_list_type;
|
||||
else if (options.find("simple") != std::string::npos)
|
||||
new_flags = rpc::object_storage::flag_function_type;
|
||||
else
|
||||
throw torrent::input_error("No support for 'list' variable type.");
|
||||
|
||||
if (options.find("static") != std::string::npos)
|
||||
new_flags |= rpc::object_storage::flag_static;
|
||||
if (options.find("private") != std::string::npos)
|
||||
new_flags |= rpc::object_storage::flag_private;
|
||||
if (options.find("const") != std::string::npos)
|
||||
new_flags |= rpc::object_storage::flag_constant;
|
||||
|
||||
return system_method_insert_object(new_args, new_flags);
|
||||
|
||||
} else {
|
||||
// THROW.
|
||||
throw torrent::input_error("No object type specified.");
|
||||
}
|
||||
|
||||
return torrent::Object();
|
||||
return system_method_insert_object(new_args, new_flags);
|
||||
}
|
||||
|
||||
// method.erase <> {name}
|
||||
@@ -359,8 +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(create_new_key(new_key), create_new_key(dest_key),
|
||||
rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_delete_key | rpc::CommandMap::flag_modifiable);
|
||||
rpc::commands.create_redirect(new_key, dest_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_modifiable);
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
@@ -370,11 +334,11 @@ system_method_set_function(const torrent::Object::list_type& args) {
|
||||
if (args.empty())
|
||||
throw torrent::input_error("Invalid argument count.");
|
||||
|
||||
rpc::object_storage::local_iterator itr =
|
||||
control->object_storage()->find_local(torrent::raw_string::from_string(args.front().as_string()));
|
||||
rpc::object_storage::iterator itr =
|
||||
control->object_storage()->find_raw_string(torrent::raw_string::from_string(args.front().as_string()));
|
||||
|
||||
if (itr == control->object_storage()->end(0) || itr->second.flags & rpc::object_storage::flag_constant)
|
||||
throw torrent::input_error("Command is not modifiable.");
|
||||
if (itr == control->object_storage()->end() || itr->second.flags & rpc::object_storage::flag_constant)
|
||||
throw torrent::input_error("Command is not modifiable.");
|
||||
|
||||
return control->object_storage()->set_str_function(args.front().as_string(),
|
||||
system_method_generate_command(++args.begin(), args.end()));
|
||||
@@ -386,9 +350,9 @@ system_method_has_key(const torrent::Object::list_type& args) {
|
||||
throw torrent::input_error("Invalid argument count.");
|
||||
|
||||
torrent::Object::list_const_iterator itrArgs = args.begin();
|
||||
const std::string& key = (itrArgs++)->as_string();
|
||||
const std::string& cmd_key = (itrArgs++)->as_string();
|
||||
|
||||
const std::string& key = (itrArgs++)->as_string();
|
||||
const std::string& cmd_key = (itrArgs++)->as_string();
|
||||
|
||||
return control->object_storage()->has_str_multi_key(key, cmd_key);
|
||||
}
|
||||
|
||||
@@ -398,9 +362,9 @@ system_method_set_key(const torrent::Object::list_type& args) {
|
||||
throw torrent::input_error("Invalid argument count.");
|
||||
|
||||
torrent::Object::list_const_iterator itrArgs = args.begin();
|
||||
const std::string& key = (itrArgs++)->as_string();
|
||||
const std::string& cmd_key = (itrArgs++)->as_string();
|
||||
|
||||
const std::string& key = (itrArgs++)->as_string();
|
||||
const std::string& cmd_key = (itrArgs++)->as_string();
|
||||
|
||||
if (itrArgs == args.end()) {
|
||||
control->object_storage()->erase_str_multi_key(key, cmd_key);
|
||||
return torrent::Object();
|
||||
@@ -417,9 +381,9 @@ system_method_set_key(const torrent::Object::list_type& args) {
|
||||
torrent::Object
|
||||
system_method_list_keys(const torrent::Object::string_type& args) {
|
||||
const torrent::Object::map_type& multi_cmd = control->object_storage()->get_str(args).as_map();
|
||||
|
||||
torrent::Object rawResult = torrent::Object::create_list();
|
||||
torrent::Object::list_type& result = rawResult.as_list();
|
||||
|
||||
torrent::Object rawResult = torrent::Object::create_list();
|
||||
torrent::Object::list_type& result = rawResult.as_list();
|
||||
|
||||
for (torrent::Object::map_const_iterator itr = multi_cmd.begin(), last = multi_cmd.end(); itr != last; itr++)
|
||||
result.push_back(itr->first);
|
||||
@@ -442,11 +406,20 @@ cmd_catch(rpc::target_type target, const torrent::Object& args) {
|
||||
|
||||
void
|
||||
initialize_command_dynamic() {
|
||||
// clang-format off
|
||||
#ifdef HAVE_XMLRPC_TINYXML2
|
||||
CMD2_ANY ("system.listMethods", std::bind(&system_listMethods)); // only used by tinyxml2
|
||||
#endif
|
||||
|
||||
// Keep these for future use when we deprecate more commands.
|
||||
CMD2_VAR_BOOL ("method.use_deprecated", false);
|
||||
CMD2_VAR_VALUE ("method.use_intermediate", 1);
|
||||
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));
|
||||
CMD2_ANY_LIST ("method.insert.bool", std::bind(&system_method_insert_object, std::placeholders::_2, rpc::object_storage::flag_bool_type));
|
||||
CMD2_ANY_LIST ("method.insert.string", std::bind(&system_method_insert_object, std::placeholders::_2, rpc::object_storage::flag_string_type));
|
||||
CMD2_ANY_LIST ("method.insert.list", std::bind(&system_method_insert_object, std::placeholders::_2, rpc::object_storage::flag_list_type));
|
||||
|
||||
CMD2_METHOD_INSERT("method.insert.simple", rpc::object_storage::flag_function_type);
|
||||
CMD2_METHOD_INSERT("method.insert.c_simple", rpc::object_storage::flag_constant | rpc::object_storage::flag_function_type);
|
||||
@@ -483,4 +456,5 @@ initialize_command_dynamic() {
|
||||
CMD2_ANY ("strings.log_group", std::bind(&torrent::option_list_strings, torrent::OPTION_LOG_GROUP));
|
||||
CMD2_ANY ("strings.tracker_event", std::bind(&torrent::option_list_strings, torrent::OPTION_TRACKER_EVENT));
|
||||
CMD2_ANY ("strings.tracker_mode", std::bind(&torrent::option_list_strings, torrent::OPTION_TRACKER_MODE));
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
+104
-117
@@ -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,67 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
return resultRaw;
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
d_multicall_filtered(const torrent::Object::list_type& args) {
|
||||
if (args.size() < 2)
|
||||
throw torrent::input_error("d.multicall.filtered requires at least 2 arguments.");
|
||||
torrent::Object::list_const_iterator arg = args.begin();
|
||||
|
||||
// Find the given view
|
||||
core::ViewManager* viewManager = control->view_manager();
|
||||
core::ViewManager::iterator view_itr = viewManager->find(arg->as_string().empty() ? "default" : arg->as_string());
|
||||
|
||||
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;
|
||||
(*view_itr)->filter_by(*++arg, dlist);
|
||||
|
||||
// Generate result by iterating over all items
|
||||
torrent::Object resultRaw = torrent::Object::create_list();
|
||||
torrent::Object::list_type& result = resultRaw.as_list();
|
||||
++arg; // skip to first command
|
||||
|
||||
for (core::View::iterator item = dlist.begin(); item != dlist.end(); ++item) {
|
||||
// Add empty row to result
|
||||
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
|
||||
|
||||
// Call the provided commands and assemble their results
|
||||
for (torrent::Object::list_const_iterator command = arg; command != args.end(); command++) {
|
||||
auto& cmdstr = command->as_string();
|
||||
row.push_back(rpc::parse_command(rpc::make_target(*item), cmdstr.c_str(), cmdstr.c_str() + cmdstr.size()).first);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,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()));
|
||||
@@ -338,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));
|
||||
@@ -355,10 +340,12 @@ 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));
|
||||
CMD2_ANY_LIST ("d.multicall.filtered", std::bind(&d_multicall_filtered, std::placeholders::_2));
|
||||
|
||||
CMD2_ANY_LIST ("directory.watch.added", std::bind(&directory_watch_added, std::placeholders::_2));
|
||||
}
|
||||
|
||||
+1
-1
@@ -53,7 +53,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.
|
||||
|
||||
+53
-47
@@ -1,44 +1,9 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <torrent/download/resource_manager.h>
|
||||
#include <torrent/download/choke_group.h>
|
||||
#include <torrent/download/choke_queue.h>
|
||||
#include <torrent/utils/log.h>
|
||||
#include <torrent/utils/option_strings.h>
|
||||
|
||||
#include "ui/root.h"
|
||||
@@ -52,6 +17,9 @@
|
||||
// For cg_d_group.
|
||||
#include "core/download.h"
|
||||
|
||||
#define LT_LOG_SUBSYSTEM(log_fmt, ...) \
|
||||
lt_log_print_subsystem(torrent::LOG_TORRENT_INFO, "choke_queue", log_fmt, __VA_ARGS__);
|
||||
|
||||
// A hack to allow testing of the new choke_group API without the
|
||||
// working parts present.
|
||||
#define USE_CHOKE_GROUP 0
|
||||
@@ -101,7 +69,7 @@ cg_d_group_set(core::Download* download, const torrent::Object& arg) {
|
||||
torrent::Object
|
||||
apply_cg_list() {
|
||||
torrent::Object::list_type result;
|
||||
|
||||
|
||||
for (torrent::ResourceManager::group_iterator
|
||||
itr = torrent::resource_manager()->group_begin(),
|
||||
last = torrent::resource_manager()->group_end(); itr != last; itr++)
|
||||
@@ -122,6 +90,22 @@ apply_cg_insert(const std::string& arg) {
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_cg_all_update_balance(bool is_up) {
|
||||
LT_LOG_SUBSYSTEM("apply update balance: resource_manager is_up:%i", (int)is_up);
|
||||
|
||||
for (torrent::ResourceManager::group_iterator
|
||||
itr = torrent::resource_manager()->group_begin(),
|
||||
last = torrent::resource_manager()->group_end(); itr != last; itr++) {
|
||||
if (is_up)
|
||||
itr->up_queue()->balance();
|
||||
else
|
||||
itr->down_queue()->balance();
|
||||
}
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
//
|
||||
// The hacked version:
|
||||
//
|
||||
@@ -137,8 +121,7 @@ cg_get_index(const torrent::Object& raw_args) {
|
||||
|
||||
if (arg.is_string()) {
|
||||
if (!rpc::parse_whole_value_nothrow(arg.as_string().c_str(), &index)) {
|
||||
std::vector<torrent::choke_group*>::iterator itr = std::find_if(cg_list_hack.begin(), cg_list_hack.end(),
|
||||
rak::equal(arg.as_string(), std::mem_fun(&torrent::choke_group::name)));
|
||||
auto itr = std::find_if(cg_list_hack.begin(), cg_list_hack.end(), [&arg](torrent::choke_group* cg) { return arg.as_string() == cg->name(); });
|
||||
|
||||
if (itr == cg_list_hack.end())
|
||||
throw torrent::input_error("Choke group not found.");
|
||||
@@ -170,18 +153,26 @@ cg_get_group(const torrent::Object& raw_args) {
|
||||
}
|
||||
|
||||
int64_t cg_d_group(core::Download* download) { return download->group(); }
|
||||
const std::string& cg_d_group_name(core::Download* download) {
|
||||
return cg_list_hack.at(download->group())->name();
|
||||
}
|
||||
void cg_d_group_set(core::Download* download, const torrent::Object& arg) { download->set_group(cg_get_index(arg)); }
|
||||
|
||||
torrent::Object
|
||||
apply_cg_list() {
|
||||
torrent::Object::list_type result;
|
||||
|
||||
for (std::vector<torrent::choke_group*>::iterator itr = cg_list_hack.begin(), last = cg_list_hack.end(); itr != last; itr++)
|
||||
result.push_back((*itr)->name());
|
||||
|
||||
for (auto itr : cg_list_hack)
|
||||
result.push_back(itr->name());
|
||||
|
||||
return torrent::Object::from_list(result);
|
||||
}
|
||||
|
||||
int
|
||||
cg_get_can_unchoke(torrent::choke_queue* cq) {
|
||||
return cq->max_unchoked_signed() - (int)cq->size_unchoked();
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_cg_insert(const std::string& arg) {
|
||||
int64_t dummy;
|
||||
@@ -190,8 +181,7 @@ apply_cg_insert(const std::string& arg) {
|
||||
throw torrent::input_error("Cannot use a value string as choke group name.");
|
||||
|
||||
if (arg.empty() ||
|
||||
std::find_if(cg_list_hack.begin(), cg_list_hack.end(),
|
||||
rak::equal(arg, std::mem_fun(&torrent::choke_group::name))) != cg_list_hack.end())
|
||||
std::find_if(cg_list_hack.begin(), cg_list_hack.end(), [&arg](torrent::choke_group* cg) { return arg == cg->name(); }) != cg_list_hack.end())
|
||||
throw torrent::input_error("Duplicate name for choke group.");
|
||||
|
||||
cg_list_hack.push_back(new torrent::choke_group());
|
||||
@@ -205,8 +195,7 @@ apply_cg_insert(const std::string& arg) {
|
||||
|
||||
torrent::Object
|
||||
apply_cg_index_of(const std::string& arg) {
|
||||
std::vector<torrent::choke_group*>::iterator itr =
|
||||
std::find_if(cg_list_hack.begin(), cg_list_hack.end(), rak::equal(arg, std::mem_fun(&torrent::choke_group::name)));
|
||||
auto itr = std::find_if(cg_list_hack.begin(), cg_list_hack.end(), [&arg](torrent::choke_group* cg) { return arg == cg->name(); });
|
||||
|
||||
if (itr == cg_list_hack.end())
|
||||
throw torrent::input_error("Choke group not found.");
|
||||
@@ -214,6 +203,20 @@ apply_cg_index_of(const std::string& arg) {
|
||||
return std::distance(cg_list_hack.begin(), itr);
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_cg_all_update_balance(bool is_up) {
|
||||
LT_LOG_SUBSYSTEM("apply update balance: hack is_up:%i", (int)is_up);
|
||||
|
||||
for (auto itr : cg_list_hack) {
|
||||
if (is_up)
|
||||
itr->up_queue()->balance();
|
||||
else
|
||||
itr->down_queue()->balance();
|
||||
}
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
//
|
||||
// End of choke group hack.
|
||||
//
|
||||
@@ -337,7 +340,7 @@ void
|
||||
initialize_command_groups() {
|
||||
CMD2_ANY ("choke_group.list", std::bind(&apply_cg_list));
|
||||
CMD2_ANY_STRING ("choke_group.insert", std::bind(&apply_cg_insert, std::placeholders::_2));
|
||||
|
||||
|
||||
#if USE_CHOKE_GROUP
|
||||
CMD2_ANY ("choke_group.size", std::bind(&torrent::ResourceManager::group_size, torrent::resource_manager()));
|
||||
CMD2_ANY_STRING ("choke_group.index_of", std::bind(&torrent::ResourceManager::group_index_of, torrent::resource_manager(), std::placeholders::_2));
|
||||
@@ -356,6 +359,9 @@ initialize_command_groups() {
|
||||
std::bind(&torrent::choke_group::tracker_mode, CG_GROUP_AT())));
|
||||
CMD2_ANY_LIST ("choke_group.tracker.mode.set", std::bind(&apply_cg_tracker_mode_set, std::placeholders::_2));
|
||||
|
||||
CMD2_ANY ("choke_group.all.up.update_balance", std::bind(&apply_cg_all_update_balance, true));
|
||||
CMD2_ANY ("choke_group.all.down.update_balance", std::bind(&apply_cg_all_update_balance, false));
|
||||
|
||||
CMD2_ANY ("choke_group.up.rate", std::bind(&torrent::choke_group::up_rate, CG_GROUP_AT()));
|
||||
CMD2_ANY ("choke_group.down.rate", std::bind(&torrent::choke_group::down_rate, CG_GROUP_AT()));
|
||||
|
||||
|
||||
+12
-68
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RTORRENT_UTILS_COMMAND_HELPERS_H
|
||||
#define RTORRENT_UTILS_COMMAND_HELPERS_H
|
||||
|
||||
@@ -49,7 +13,7 @@ void initialize_commands();
|
||||
|
||||
#define CMD2_A_FUNCTION(key, function, slot, parm, doc) \
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::function>::type>(key, slot, &rpc::function, \
|
||||
rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_xmlrpc, NULL, NULL);
|
||||
rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_rpc, NULL, NULL);
|
||||
|
||||
#define CMD2_A_FUNCTION_PRIVATE(key, function, slot, parm, doc) \
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::function>::type>(key, slot, &rpc::function, \
|
||||
@@ -92,9 +56,9 @@ void initialize_commands();
|
||||
#define CMD2_PEER_V(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::Peer*>, object_convert_void(slot), "i:", "")
|
||||
#define CMD2_PEER_VALUE_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_value<torrent::Peer*>, object_convert_void(slot), "i:i", "")
|
||||
|
||||
#define CMD2_TRACKER(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::Tracker*>, slot, "i:", "")
|
||||
#define CMD2_TRACKER_V(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::Tracker*>, object_convert_void(slot), "i:", "")
|
||||
#define CMD2_TRACKER_VALUE_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_value<torrent::Tracker*>, object_convert_void(slot), "i:i", "")
|
||||
#define CMD2_TRACKER(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::tracker::Tracker*>, slot, "i:", "")
|
||||
#define CMD2_TRACKER_V(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::tracker::Tracker*>, object_convert_void(slot), "i:", "")
|
||||
#define CMD2_TRACKER_VALUE_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_value<torrent::tracker::Tracker*>, object_convert_void(slot), "i:i", "")
|
||||
|
||||
#define CMD2_VAR_BOOL(key, value) \
|
||||
control->object_storage()->insert_c_str(key, int64_t(value), rpc::object_storage::flag_bool_type); \
|
||||
@@ -137,23 +101,23 @@ void initialize_commands();
|
||||
std::placeholders::_1, std::placeholders::_2));
|
||||
|
||||
#define CMD2_REDIRECT(from_key, to_key) \
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_dont_delete);
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_dont_delete);
|
||||
#define CMD2_REDIRECT_GENERIC(from_key, to_key) \
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_dont_delete);
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_dont_delete);
|
||||
#define CMD2_REDIRECT_GENERIC_NO_EXPORT(from_key, to_key) \
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_dont_delete);
|
||||
#define CMD2_REDIRECT_FILE(from_key, to_key) \
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_file_target | rpc::CommandMap::flag_dont_delete);
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_file_target | rpc::CommandMap::flag_dont_delete);
|
||||
#define CMD2_REDIRECT_TRACKER(from_key, to_key) \
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_tracker_target | rpc::CommandMap::flag_dont_delete);
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_tracker_target | rpc::CommandMap::flag_dont_delete);
|
||||
|
||||
#define CMD2_REDIRECT_GENERIC_STR(from_key, to_key) \
|
||||
rpc::commands.create_redirect(create_new_key(from_key), create_new_key(to_key), \
|
||||
rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_delete_key);
|
||||
rpc::commands.create_redirect(from_key, to_key, \
|
||||
rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_no_target);
|
||||
|
||||
#define CMD2_REDIRECT_GENERIC_STR_NO_EXPORT(from_key, to_key) \
|
||||
rpc::commands.create_redirect(create_new_key(from_key), create_new_key(to_key), \
|
||||
rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_delete_key);
|
||||
rpc::commands.create_redirect(from_key, to_key, \
|
||||
rpc::CommandMap::flag_no_target);
|
||||
|
||||
//
|
||||
// Conversion of return types:
|
||||
@@ -188,24 +152,4 @@ template <typename T>
|
||||
object_convert_type<T, void>
|
||||
object_convert_void(T f) { return f; }
|
||||
|
||||
//
|
||||
// Key creation:
|
||||
//
|
||||
|
||||
template <int postfix_size>
|
||||
inline const char*
|
||||
create_new_key(const std::string& key, const char postfix[postfix_size]) {
|
||||
char *buffer = new char[key.size() + std::max(postfix_size, 1)];
|
||||
std::memcpy(buffer, key.c_str(), key.size() + 1);
|
||||
std::memcpy(buffer + key.size(), postfix, postfix_size);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
inline const char*
|
||||
create_new_key(const std::string& key) {
|
||||
char *buffer = new char[key.size() + 1];
|
||||
std::memcpy(buffer, key.c_str(), key.size() + 1);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+2
-2
@@ -286,7 +286,7 @@ ipv4_filter_parse(const char* address, int value) {
|
||||
inet_ntop(AF_INET, &net_start, start_str, INET_ADDRSTRLEN);
|
||||
inet_ntop(AF_INET, &net_end, end_str, INET_ADDRSTRLEN);
|
||||
|
||||
lt_log_print(torrent::LOG_CONNECTION_DEBUG, "Adding ip filter for %s-%s.", start_str, end_str);
|
||||
lt_log_print(torrent::LOG_CONNECTION_FILTER, "Adding ip filter for %s-%s.", start_str, end_str);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,7 +355,7 @@ apply_ipv4_filter_load(const torrent::Object::list_type& args) {
|
||||
throw torrent::input_error(buffer);
|
||||
}
|
||||
|
||||
lt_log_print(torrent::LOG_CONNECTION_INFO, "Loaded %u %s address blocks (%u kb in-memory) from '%s'.",
|
||||
lt_log_print(torrent::LOG_CONNECTION_FILTER, "loaded %u %s address blocks (%u kb in-memory) from '%s'",
|
||||
lineNumber,
|
||||
value_name.c_str(),
|
||||
torrent::PeerList::ipv4_filter()->sizeof_data() / 1024,
|
||||
|
||||
+28
-42
@@ -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"
|
||||
|
||||
@@ -195,7 +160,7 @@ file_print_list(torrent::Object::list_const_iterator first, torrent::Object::lis
|
||||
fprintf(output, (const char*)" %s" + !(flags & file_print_use_space), first->as_string().c_str());
|
||||
break;
|
||||
case torrent::Object::TYPE_VALUE:
|
||||
fprintf(output, (const char*)" %lli" + !(flags & file_print_use_space), first->as_value());
|
||||
fprintf(output, (const char*)" %" PRIi64 + !(flags & file_print_use_space), first->as_value());
|
||||
break;
|
||||
case torrent::Object::TYPE_LIST:
|
||||
file_print_list(first->as_list().begin(), first->as_list().end(), output, 0);
|
||||
@@ -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);
|
||||
|
||||
+13
-41
@@ -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>
|
||||
@@ -56,6 +20,7 @@
|
||||
|
||||
static const int log_flag_use_gz = 0x1;
|
||||
static const int log_flag_append_pid = 0x2;
|
||||
static const int log_flag_append_file = 0x4;
|
||||
|
||||
void
|
||||
log_add_group_output_str(const char* group_name, const char* output_id) {
|
||||
@@ -67,7 +32,7 @@ torrent::Object
|
||||
apply_log_open(int output_flags, const torrent::Object::list_type& args) {
|
||||
if (args.size() < 2)
|
||||
throw torrent::input_error("Invalid number of arguments.");
|
||||
|
||||
|
||||
torrent::Object::list_const_iterator itr = args.begin();
|
||||
|
||||
std::string output_id = (itr++)->as_string();
|
||||
@@ -80,10 +45,12 @@ apply_log_open(int output_flags, const torrent::Object::list_type& args) {
|
||||
file_name += buffer;
|
||||
}
|
||||
|
||||
bool append = (output_flags & log_flag_append_file);
|
||||
|
||||
if ((output_flags & log_flag_use_gz))
|
||||
torrent::log_open_gz_file_output(output_id.c_str(), file_name.c_str());
|
||||
torrent::log_open_gz_file_output(output_id.c_str(), file_name.c_str(), append);
|
||||
else
|
||||
torrent::log_open_file_output(output_id.c_str(), file_name.c_str());
|
||||
torrent::log_open_file_output(output_id.c_str(), file_name.c_str(), append);
|
||||
|
||||
while (itr != args.end())
|
||||
log_add_group_output_str((itr++)->as_string().c_str(), output_id.c_str());
|
||||
@@ -166,10 +133,15 @@ initialize_command_logging() {
|
||||
CMD2_ANY_LIST ("log.open_gz_file", std::bind(&apply_log_open, log_flag_use_gz, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("log.open_file_pid", std::bind(&apply_log_open, log_flag_append_pid, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("log.open_gz_file_pid", std::bind(&apply_log_open, log_flag_append_pid | log_flag_use_gz, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("log.append_file", std::bind(&apply_log_open, log_flag_append_file, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("log.append_gz_file", std::bind(&apply_log_open, log_flag_append_file, std::placeholders::_2));
|
||||
|
||||
CMD2_ANY_LIST ("log.add_output", std::bind(&apply_log_add_output, std::placeholders::_2));
|
||||
CMD2_ANY_STRING_V("log.close", std::bind(&torrent::log_close_output_str, std::placeholders::_2));
|
||||
|
||||
CMD2_ANY_LIST ("log.add_output", std::bind(&apply_log_add_output, std::placeholders::_2));
|
||||
|
||||
CMD2_ANY_STRING ("log.execute", std::bind(&apply_log, std::placeholders::_2, 0));
|
||||
CMD2_ANY_STRING ("log.vmmap.dump", std::bind(&log_vmmap_dump, std::placeholders::_2));
|
||||
CMD2_ANY_STRING_V("log.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
|
||||
}
|
||||
|
||||
+68
-99
@@ -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, 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;
|
||||
|
||||
@@ -167,8 +125,7 @@ apply_scgi(const std::string& arg, int type) {
|
||||
sa.sa_inet()->clear();
|
||||
saPtr = &sa;
|
||||
|
||||
lt_log_print(torrent::LOG_RPC_EVENTS,
|
||||
"The SCGI socket has not been bound to any address and likely poses a security risk.");
|
||||
lt_log_print(torrent::LOG_RPC_EVENTS, "SCGI socket is open to any address and is a security risk");
|
||||
|
||||
} else if (std::sscanf(arg.c_str(), "%1023[^:]:%i%c", address, &port, &dummy) == 2 ||
|
||||
std::sscanf(arg.c_str(), "[%64[^]]]:%i%c", address, &port, &dummy) == 2) { // [xx::xx]:port format
|
||||
@@ -177,8 +134,7 @@ apply_scgi(const std::string& arg, int type) {
|
||||
|
||||
saPtr = ai->address();
|
||||
|
||||
lt_log_print(torrent::LOG_RPC_EVENTS,
|
||||
"The SCGI socket is bound to a specific network device yet may still pose a security risk, consider using 'scgi_local'.");
|
||||
lt_log_print(torrent::LOG_RPC_EVENTS, "SCGI socket is bound to an address and might be a security risk");
|
||||
|
||||
} else {
|
||||
throw torrent::input_error("Could not parse address.");
|
||||
@@ -227,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();
|
||||
}
|
||||
|
||||
@@ -265,7 +221,7 @@ initialize_command_network() {
|
||||
CMD2_ANY_STRING_V("network.http.capath.set", std::bind(&core::CurlStack::set_http_capath, httpStack, std::placeholders::_2));
|
||||
CMD2_ANY ("network.http.dns_cache_timeout", std::bind(&core::CurlStack::dns_timeout, httpStack));
|
||||
CMD2_ANY_VALUE_V ("network.http.dns_cache_timeout.set", std::bind(&core::CurlStack::set_dns_timeout, httpStack, std::placeholders::_2));
|
||||
CMD2_ANY ("network.http.current_open", std::bind(&core::CurlStack::active, httpStack));
|
||||
CMD2_ANY ("network.http.current_open", std::bind(&core::CurlStack::active, httpStack));
|
||||
CMD2_ANY ("network.http.max_open", std::bind(&core::CurlStack::max_active, httpStack));
|
||||
CMD2_ANY_VALUE_V ("network.http.max_open.set", std::bind(&core::CurlStack::set_max_active, httpStack, std::placeholders::_2));
|
||||
CMD2_ANY ("network.http.proxy_address", std::bind(&core::CurlStack::http_proxy, httpStack));
|
||||
@@ -281,24 +237,37 @@ initialize_command_network() {
|
||||
CMD2_ANY_VALUE_V ("network.receive_buffer.size.set", std::bind(&torrent::ConnectionManager::set_receive_buffer_size, cm, std::placeholders::_2));
|
||||
CMD2_ANY_STRING ("network.tos.set", std::bind(&apply_tos, std::placeholders::_2));
|
||||
|
||||
CMD2_ANY ("network.bind_address", std::bind(&core::Manager::bind_address, control->core()));
|
||||
CMD2_ANY_STRING_V("network.bind_address.set", std::bind(&core::Manager::set_bind_address, control->core(), std::placeholders::_2));
|
||||
CMD2_ANY ("network.local_address", std::bind(&core::Manager::local_address, control->core()));
|
||||
CMD2_ANY_STRING_V("network.local_address.set", std::bind(&core::Manager::set_local_address, control->core(), std::placeholders::_2));
|
||||
CMD2_ANY ("network.proxy_address", std::bind(&core::Manager::proxy_address, control->core()));
|
||||
CMD2_ANY_STRING_V("network.proxy_address.set", std::bind(&core::Manager::set_proxy_address, control->core(), std::placeholders::_2));
|
||||
CMD2_ANY ("network.bind_address", std::bind(&core::Manager::bind_address, control->core()));
|
||||
CMD2_ANY_STRING_V("network.bind_address.set", std::bind(&core::Manager::set_bind_address, control->core(), std::placeholders::_2));
|
||||
CMD2_ANY ("network.local_address", std::bind(&core::Manager::local_address, control->core()));
|
||||
CMD2_ANY_STRING_V("network.local_address.set", std::bind(&core::Manager::set_local_address, control->core(), std::placeholders::_2));
|
||||
CMD2_ANY ("network.proxy_address", std::bind(&core::Manager::proxy_address, control->core()));
|
||||
CMD2_ANY_STRING_V("network.proxy_address.set", std::bind(&core::Manager::set_proxy_address, control->core(), std::placeholders::_2));
|
||||
|
||||
CMD2_ANY ("network.max_open_files", std::bind(&torrent::FileManager::max_open_files, fileManager));
|
||||
CMD2_ANY_VALUE_V ("network.max_open_files.set", std::bind(&torrent::FileManager::set_max_open_files, fileManager, std::placeholders::_2));
|
||||
CMD2_ANY ("network.open_sockets", std::bind(&torrent::ConnectionManager::size, cm));
|
||||
CMD2_ANY ("network.max_open_sockets", std::bind(&torrent::ConnectionManager::max_size, cm));
|
||||
CMD2_ANY_VALUE_V ("network.max_open_sockets.set", std::bind(&torrent::ConnectionManager::set_max_size, cm, std::placeholders::_2));
|
||||
CMD2_ANY ("network.open_files", std::bind(&torrent::FileManager::open_files, fileManager));
|
||||
CMD2_ANY ("network.max_open_files", std::bind(&torrent::FileManager::max_open_files, fileManager));
|
||||
CMD2_ANY_VALUE_V ("network.max_open_files.set", std::bind(&torrent::FileManager::set_max_open_files, fileManager, std::placeholders::_2));
|
||||
CMD2_ANY ("network.total_handshakes", std::bind(&torrent::total_handshakes));
|
||||
CMD2_ANY ("network.open_sockets", std::bind(&torrent::ConnectionManager::size, cm));
|
||||
CMD2_ANY ("network.max_open_sockets", std::bind(&torrent::ConnectionManager::max_size, cm));
|
||||
CMD2_ANY_VALUE_V ("network.max_open_sockets.set", std::bind(&torrent::ConnectionManager::set_max_size, cm, std::placeholders::_2));
|
||||
|
||||
CMD2_ANY_STRING ("network.scgi.open_port", std::bind(&apply_scgi, std::placeholders::_2, 1));
|
||||
CMD2_ANY_STRING ("network.scgi.open_local", std::bind(&apply_scgi, std::placeholders::_2, 2));
|
||||
CMD2_VAR_BOOL ("network.scgi.dont_route", false);
|
||||
CMD2_ANY_STRING ("network.scgi.open_port", std::bind(&apply_scgi, std::placeholders::_2, 1));
|
||||
CMD2_ANY_STRING ("network.scgi.open_local", std::bind(&apply_scgi, std::placeholders::_2, 2));
|
||||
CMD2_VAR_BOOL ("network.scgi.dont_route", false);
|
||||
|
||||
CMD2_ANY_STRING ("network.xmlrpc.dialect.set", std::bind(&apply_xmlrpc_dialect, std::placeholders::_2));
|
||||
CMD2_ANY ("network.xmlrpc.size_limit", std::bind(&rpc::XmlRpc::size_limit));
|
||||
CMD2_ANY_VALUE_V ("network.xmlrpc.size_limit.set", std::bind(&rpc::XmlRpc::set_size_limit, std::placeholders::_2));
|
||||
CMD2_ANY_STRING ("network.xmlrpc.dialect.set", [](const auto&, const auto& arg) { return apply_xmlrpc_dialect(arg); })
|
||||
CMD2_ANY ("network.xmlrpc.size_limit", [](const auto&, const auto&){ return rpc::rpc.size_limit(); });
|
||||
CMD2_ANY_VALUE_V ("network.xmlrpc.size_limit.set", [](const auto&, const auto& arg){ return rpc::rpc.set_size_limit(arg); });
|
||||
|
||||
CMD2_VAR_BOOL ("network.rpc.use_xmlrpc", true);
|
||||
CMD2_VAR_BOOL ("network.rpc.use_jsonrpc", true);
|
||||
|
||||
CMD2_ANY ("network.block.ipv4", std::bind(&torrent::ConnectionManager::is_block_ipv4, cm));
|
||||
CMD2_ANY_VALUE_V ("network.block.ipv4.set", std::bind(&torrent::ConnectionManager::set_block_ipv4, cm, std::placeholders::_2));
|
||||
CMD2_ANY ("network.block.ipv6", std::bind(&torrent::ConnectionManager::is_block_ipv6, cm));
|
||||
CMD2_ANY_VALUE_V ("network.block.ipv6.set", std::bind(&torrent::ConnectionManager::set_block_ipv6, cm, std::placeholders::_2));
|
||||
|
||||
CMD2_ANY ("network.prefer.ipv6", std::bind(&torrent::ConnectionManager::is_prefer_ipv6, cm));
|
||||
CMD2_ANY_VALUE_V ("network.prefer.ipv6.set", std::bind(&torrent::ConnectionManager::set_prefer_ipv6, cm, std::placeholders::_2));
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -176,8 +176,10 @@ throttle_update(const char* variable, int64_t value) {
|
||||
|
||||
void
|
||||
initialize_command_throttle() {
|
||||
CMD2_ANY ("throttle.unchoked_uploads", std::bind(&torrent::ResourceManager::currently_upload_unchoked, torrent::resource_manager()));
|
||||
CMD2_ANY ("throttle.unchoked_downloads", std::bind(&torrent::ResourceManager::currently_download_unchoked, torrent::resource_manager()));
|
||||
CMD2_ANY ("throttle.unchoked_uploads", std::bind(&torrent::ResourceManager::currently_upload_unchoked, torrent::resource_manager()));
|
||||
CMD2_ANY ("throttle.max_unchoked_uploads", std::bind(&torrent::ResourceManager::max_upload_unchoked, torrent::resource_manager()));
|
||||
CMD2_ANY ("throttle.unchoked_downloads", std::bind(&torrent::ResourceManager::currently_download_unchoked, torrent::resource_manager()));
|
||||
CMD2_ANY ("throttle.max_unchoked_downloads", std::bind(&torrent::ResourceManager::max_download_unchoked, torrent::resource_manager()));
|
||||
|
||||
CMD2_VAR_VALUE ("throttle.min_peers.normal", 100);
|
||||
CMD2_VAR_VALUE ("throttle.max_peers.normal", 200);
|
||||
|
||||
+70
-93
@@ -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,71 +45,95 @@ 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)));
|
||||
CMD2_VAR_BOOL ("trackers.delay_scrape", false);
|
||||
CMD2_VAR_VALUE ("trackers.numwant", -1);
|
||||
CMD2_VAR_BOOL ("trackers.use_udp", true);
|
||||
|
||||
|
||||
+355
-57
@@ -1,51 +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 <rak/functional.h>
|
||||
#include <rak/functional_fun.h>
|
||||
#include <regex>
|
||||
#include <rak/algorithm.h>
|
||||
#include <torrent/utils/log.h>
|
||||
|
||||
#include "core/manager.h"
|
||||
#include "core/view_manager.h"
|
||||
#include "display/canvas.h"
|
||||
#include "ui/root.h"
|
||||
#include "ui/download_list.h"
|
||||
#include "display/color_map.h"
|
||||
#include "rpc/parse.h"
|
||||
|
||||
#include "globals.h"
|
||||
@@ -60,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.");
|
||||
|
||||
@@ -127,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);
|
||||
|
||||
@@ -140,13 +108,48 @@ apply_print(rpc::target_type target, const torrent::Object& rawArgs) {
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_cat(rpc::target_type target, const torrent::Object& rawArgs) {
|
||||
apply_cat([[maybe_unused]] rpc::target_type target, const torrent::Object& rawArgs) {
|
||||
std::string result;
|
||||
|
||||
rpc::print_object_std(&result, &rawArgs, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_value([[maybe_unused]] rpc::target_type target, const torrent::Object::list_type& args) {
|
||||
if (args.size() < 1)
|
||||
throw torrent::input_error("'value' takes at least a number argument!");
|
||||
if (args.size() > 2)
|
||||
throw torrent::input_error("'value' takes at most two arguments!");
|
||||
|
||||
torrent::Object::value_type val = 0;
|
||||
if (args.front().is_value()) {
|
||||
val = args.front().as_value();
|
||||
} else {
|
||||
int base = args.size() > 1 ? args.back().is_value() ?
|
||||
args.back().as_value() : strtol(args.back().as_string().c_str(), NULL, 10) : 10;
|
||||
char* endptr = 0;
|
||||
|
||||
val = strtoll(args.front().as_string().c_str(), &endptr, base);
|
||||
while (*endptr == ' ' || *endptr == '\n') ++endptr;
|
||||
if (*endptr)
|
||||
throw torrent::input_error("Junk at end of number: " + args.front().as_string());
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_try(rpc::target_type target, const torrent::Object& args) {
|
||||
try {
|
||||
return rpc::call_object(args, target);
|
||||
} catch (torrent::input_error& e) {
|
||||
lt_log_print(torrent::LOG_RPC_EVENTS, "try command caught input_error: %s", e.what());
|
||||
}
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
// Move these boolean operators to a new file.
|
||||
|
||||
inline bool
|
||||
@@ -181,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;
|
||||
}
|
||||
|
||||
@@ -196,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;
|
||||
@@ -219,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;
|
||||
}
|
||||
@@ -259,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());
|
||||
@@ -282,6 +285,103 @@ torrent::Object apply_equal(rpc::target_type target, const torrent::Object::list
|
||||
return result.is_value() ? result.as_value() == 0 : (int64_t)false;
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_compare(rpc::target_type target, const torrent::Object::list_type& args) {
|
||||
if (!rpc::is_target_pair(target))
|
||||
throw torrent::input_error("Can only compare a target pair.");
|
||||
|
||||
if (args.size() < 2)
|
||||
throw torrent::input_error("Need at least order and one field.");
|
||||
|
||||
torrent::Object::list_const_iterator itr = args.begin();
|
||||
std::string order = (itr++)->as_string();
|
||||
const char* current = order.c_str();
|
||||
|
||||
torrent::Object result1;
|
||||
torrent::Object result2;
|
||||
|
||||
for (torrent::Object::list_const_iterator last = args.end(); itr != last; itr++) {
|
||||
std::string field = itr->as_string();
|
||||
result1 = rpc::parse_command_single(rpc::get_target_left(target), field);
|
||||
result2 = rpc::parse_command_single(rpc::get_target_right(target), field);
|
||||
|
||||
if (result1.type() != result2.type())
|
||||
throw torrent::input_error(std::string("Type mismatch in compare of ") + field);
|
||||
|
||||
bool descending = *current == 'd' || *current == 'D' || *current == '-';
|
||||
if (*current) {
|
||||
if (!descending && !(*current == 'a' || *current == 'A' || *current == '+'))
|
||||
throw torrent::input_error(std::string("Bad order '") + *current + "' in " + order);
|
||||
++current;
|
||||
}
|
||||
|
||||
switch (result1.type()) {
|
||||
case torrent::Object::TYPE_VALUE:
|
||||
if (result1.as_value() != result2.as_value())
|
||||
return (int64_t) (descending ^ (result1.as_value() < result2.as_value()));
|
||||
break;
|
||||
|
||||
case torrent::Object::TYPE_STRING:
|
||||
if (result1.as_string() != result2.as_string())
|
||||
return (int64_t) (descending ^ (result1.as_string() < result2.as_string()));
|
||||
break;
|
||||
|
||||
default:
|
||||
break; // treat unknown types as equal
|
||||
}
|
||||
}
|
||||
|
||||
// if all else is equal, ensure stable sort order based on memory location
|
||||
return (int64_t) (target.second < target.third);
|
||||
}
|
||||
|
||||
// Regexp based 'match' function.
|
||||
// arg1: the text to match.
|
||||
// arg2: the regexp pattern.
|
||||
// eg: match{d.name=,.*linux.*iso}
|
||||
torrent::Object apply_match(rpc::target_type target, const torrent::Object::list_type& args) {
|
||||
if (args.size() != 2)
|
||||
throw torrent::input_error("Wrong argument count for 'match': 2 arguments needed.");
|
||||
|
||||
// This really should be converted to using args flagged as
|
||||
// commands, so that we can compare commands and statics values.
|
||||
|
||||
torrent::Object result1;
|
||||
torrent::Object result2;
|
||||
|
||||
rpc::target_type target1 = rpc::is_target_pair(target) ? rpc::get_target_left(target) : target;
|
||||
rpc::target_type target2 = rpc::is_target_pair(target) ? rpc::get_target_right(target) : target;
|
||||
|
||||
if (args.front().is_dict_key())
|
||||
result1 = rpc::commands.call_command(args.front().as_dict_key().c_str(), args.front().as_dict_obj(), target1);
|
||||
else
|
||||
result1 = rpc::parse_command_single(target1, args.front().as_string());
|
||||
|
||||
if (args.back().is_dict_key())
|
||||
result2 = rpc::commands.call_command(args.back().as_dict_key().c_str(), args.back().as_dict_obj(), target2);
|
||||
else
|
||||
result2 = args.back().as_string();
|
||||
|
||||
if (result1.type() != result2.type())
|
||||
throw torrent::input_error("Type mismatch for 'match' arguments.");
|
||||
|
||||
std::string text = result1.as_string();
|
||||
std::string pattern = result2.as_string();
|
||||
|
||||
std::transform(text.begin(), text.end(), text.begin(), ::tolower);
|
||||
std::transform(pattern.begin(), pattern.end(), pattern.begin(), ::tolower);
|
||||
|
||||
bool isAMatch = false;
|
||||
try {
|
||||
std::regex re(pattern);
|
||||
isAMatch = std::regex_match(text, re);
|
||||
} catch (const std::regex_error& exc) {
|
||||
control->core()->push_log_std("regex_error: " + std::string(exc.what()));
|
||||
}
|
||||
|
||||
return isAMatch ? (int64_t)true : (int64_t)false;
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_to_time(const torrent::Object& rawArgs, int flags) {
|
||||
std::tm *u;
|
||||
@@ -291,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();
|
||||
|
||||
@@ -307,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));
|
||||
@@ -334,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));
|
||||
@@ -350,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)
|
||||
@@ -448,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.");
|
||||
|
||||
@@ -505,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
|
||||
@@ -515,8 +618,159 @@ 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>
|
||||
as_vector(const torrent::Object::list_type& args) {
|
||||
if (args.size() == 0)
|
||||
throw torrent::input_error("Wrong argument count in as_vector.");
|
||||
|
||||
std::vector<int64_t> result;
|
||||
|
||||
for (torrent::Object::list_const_iterator itr = args.begin(), last = args.end(); itr != last; itr++) {
|
||||
|
||||
if (itr->is_value()) {
|
||||
result.push_back(itr->as_value());
|
||||
} else if (itr->is_string()) {
|
||||
result.push_back(rpc::convert_to_value(itr->as_string()));
|
||||
} else if (itr->is_list()) {
|
||||
std::vector<int64_t> subResult = as_vector(itr->as_list());
|
||||
result.insert(result.end(), subResult.begin(), subResult.end());
|
||||
} else {
|
||||
throw torrent::input_error("Wrong type supplied to as_vector.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int64_t
|
||||
apply_math_basic(const char* name, const std::function<int64_t(int64_t,int64_t)> op, const torrent::Object::list_type& args) {
|
||||
int64_t val = 0, rhs = 0;
|
||||
bool divides = !strcmp(name, "math.div") || !strcmp(name, "math.mod");
|
||||
|
||||
if (args.size() == 0)
|
||||
throw torrent::input_error(std::string(name) + ": No arguments provided!");
|
||||
|
||||
for (torrent::Object::list_const_iterator itr = args.begin(), last = args.end(); itr != last; itr++) {
|
||||
|
||||
if (itr->is_value()) {
|
||||
rhs = itr->as_value();
|
||||
} else if (itr->is_string()) {
|
||||
rhs = rpc::convert_to_value(itr->as_string());
|
||||
} else if (itr->is_list()) {
|
||||
rhs = apply_math_basic(name, op, itr->as_list());
|
||||
} else {
|
||||
throw torrent::input_error(std::string(name) + ": Wrong argument type");
|
||||
}
|
||||
|
||||
if (divides && !rhs && itr != args.begin())
|
||||
throw torrent::input_error(std::string(name) + ": Division by zero!");
|
||||
|
||||
val = itr == args.begin() ? rhs : op(val, rhs);
|
||||
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
int64_t
|
||||
apply_arith_basic(const std::function<int64_t(int64_t,int64_t)> op, const torrent::Object::list_type& args) {
|
||||
if (args.size() == 0)
|
||||
throw torrent::input_error("Wrong argument count in apply_arith_basic.");
|
||||
|
||||
int64_t val = 0;
|
||||
|
||||
for (torrent::Object::list_const_iterator itr = args.begin(), last = args.end(); itr != last; itr++) {
|
||||
|
||||
if (itr->is_value()) {
|
||||
val = itr == args.begin() ? itr->as_value() : (op(val, itr->as_value()) ? val : itr->as_value());
|
||||
} else if (itr->is_string()) {
|
||||
int64_t cval = rpc::convert_to_value(itr->as_string());
|
||||
val = itr == args.begin() ? cval : (op(val, cval) ? val : cval);
|
||||
} else if (itr->is_list()) {
|
||||
int64_t fval = apply_arith_basic(op, itr->as_list());
|
||||
val = itr == args.begin() ? fval : (op(val, fval) ? val : fval);
|
||||
} else {
|
||||
throw torrent::input_error("Wrong type supplied to apply_arith_basic.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
int64_t
|
||||
apply_arith_count(const torrent::Object::list_type& args) {
|
||||
if (args.size() == 0)
|
||||
throw torrent::input_error("Wrong argument count in apply_arith_count.");
|
||||
|
||||
int64_t val = 0;
|
||||
|
||||
for (torrent::Object::list_const_iterator itr = args.begin(), last = args.end(); itr != last; itr++) {
|
||||
|
||||
switch (itr->type()) {
|
||||
case torrent::Object::TYPE_VALUE:
|
||||
case torrent::Object::TYPE_STRING:
|
||||
val++;
|
||||
break;
|
||||
case torrent::Object::TYPE_LIST:
|
||||
val += apply_arith_count(itr->as_list());
|
||||
break;
|
||||
default:
|
||||
throw torrent::input_error("Wrong type supplied to apply_arith_count.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
int64_t
|
||||
apply_arith_other(const char* op, const torrent::Object::list_type& args) {
|
||||
if (args.size() == 0)
|
||||
throw torrent::input_error("Wrong argument count in apply_arith_other.");
|
||||
|
||||
if (strcmp(op, "average") == 0) {
|
||||
return (int64_t)(apply_math_basic(op, std::plus<int64_t>(), args) / apply_arith_count(args));
|
||||
} else if (strcmp(op, "median") == 0) {
|
||||
std::vector<int64_t> result = as_vector(args);
|
||||
return (int64_t)rak::median(result.begin(), result.end());
|
||||
} else {
|
||||
throw torrent::input_error("Wrong operation supplied to apply_arith_other.");
|
||||
}
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
cmd_status_throttle_names(bool up, const torrent::Object::list_type& args) {
|
||||
if (args.size() == 0)
|
||||
return torrent::Object();
|
||||
|
||||
std::vector<std::string> throttle_name_list;
|
||||
|
||||
for (torrent::Object::list_const_iterator itr = args.begin(), last = args.end(); itr != last; itr++) {
|
||||
if (itr->is_string())
|
||||
throttle_name_list.push_back(itr->as_string());
|
||||
}
|
||||
|
||||
if (up)
|
||||
control->ui()->set_status_throttle_up_names(throttle_name_list);
|
||||
else
|
||||
control->ui()->set_status_throttle_down_names(throttle_name_list);
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_set_color(int color_id, const torrent::Object::string_type& color_str) {
|
||||
control->object_storage()->set_str_string(display::color_vars[color_id], color_str);
|
||||
|
||||
display::Canvas::build_colors();
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -528,8 +782,11 @@ initialize_command_ui() {
|
||||
CMD2_ANY_L ("view.list", std::bind(&apply_view_list));
|
||||
CMD2_ANY_LIST("view.set", std::bind(&apply_view_set, std::placeholders::_2));
|
||||
|
||||
CMD2_ANY_LIST("view.filter", std::bind(&apply_view_event, &core::ViewManager::set_filter, std::placeholders::_2));
|
||||
CMD2_ANY_LIST("view.filter_on", std::bind(&apply_view_filter_on, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("view.filter", std::bind(&apply_view_event, &core::ViewManager::set_filter, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("view.filter_on", std::bind(&apply_view_filter_on, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("view.filter.temp", std::bind(&apply_view_event, &core::ViewManager::set_filter_temp, std::placeholders::_2));
|
||||
CMD2_VAR_STRING("view.filter.temp.excluded", "default,started,stopped");
|
||||
CMD2_VAR_BOOL ("view.filter.temp.log", 0);
|
||||
|
||||
CMD2_ANY_LIST("view.sort", std::bind(&apply_view_sort, std::placeholders::_2));
|
||||
CMD2_ANY_LIST("view.sort_new", std::bind(&apply_view_event, &core::ViewManager::set_sort_new, std::placeholders::_2));
|
||||
@@ -555,12 +812,27 @@ initialize_command_ui() {
|
||||
CMD2_ANY ("ui.current_view", std::bind(&cmd_ui_current_view));
|
||||
CMD2_ANY_STRING("ui.current_view.set", std::bind(&cmd_ui_set_view, std::placeholders::_2));
|
||||
|
||||
CMD2_ANY ("ui.input.history.size", std::bind(&ui::Root::get_input_history_size, control->ui()));
|
||||
CMD2_ANY_VALUE_V("ui.input.history.size.set", std::bind(&ui::Root::set_input_history_size, control->ui(), std::placeholders::_2));
|
||||
CMD2_ANY_V ("ui.input.history.clear", std::bind(&ui::Root::clear_input_history, control->ui()));
|
||||
|
||||
CMD2_VAR_VALUE ("ui.throttle.global.step.small", 5);
|
||||
CMD2_VAR_VALUE ("ui.throttle.global.step.medium", 50);
|
||||
CMD2_VAR_VALUE ("ui.throttle.global.step.large", 500);
|
||||
|
||||
CMD2_VAR_VALUE ("ui.focus.page_size", 0);
|
||||
|
||||
CMD2_ANY_LIST ("ui.status.throttle.up.set", std::bind(&cmd_status_throttle_names, true, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("ui.status.throttle.down.set", std::bind(&cmd_status_throttle_names, false, std::placeholders::_2));
|
||||
|
||||
// TODO: Add 'option_string' for rtorrent-specific options.
|
||||
CMD2_VAR_STRING("ui.torrent_list.layout", "full");
|
||||
|
||||
// Move.
|
||||
CMD2_ANY("print", &apply_print);
|
||||
CMD2_ANY("cat", &apply_cat);
|
||||
CMD2_ANY_LIST("value", &apply_value);
|
||||
CMD2_ANY("try", &apply_try);
|
||||
CMD2_ANY("if", std::bind(&apply_if, std::placeholders::_1, std::placeholders::_2, 0));
|
||||
CMD2_ANY("not", &apply_not);
|
||||
CMD2_ANY("false", &apply_false);
|
||||
@@ -574,6 +846,8 @@ initialize_command_ui() {
|
||||
CMD2_ANY_LIST("less", &apply_less);
|
||||
CMD2_ANY_LIST("greater", &apply_greater);
|
||||
CMD2_ANY_LIST("equal", &apply_equal);
|
||||
CMD2_ANY_LIST("compare", &apply_compare);
|
||||
CMD2_ANY_LIST("match", &apply_match);
|
||||
|
||||
CMD2_ANY_VALUE("convert.gm_time", std::bind(&apply_to_time, std::placeholders::_2, 0));
|
||||
CMD2_ANY_VALUE("convert.gm_date", std::bind(&apply_to_time, std::placeholders::_2, 0x2));
|
||||
@@ -585,6 +859,30 @@ initialize_command_ui() {
|
||||
CMD2_ANY_VALUE("convert.xb", std::bind(&apply_to_xb, std::placeholders::_2));
|
||||
CMD2_ANY_VALUE("convert.throttle", std::bind(&apply_to_throttle, std::placeholders::_2));
|
||||
|
||||
CMD2_ANY_LIST("math.add", std::bind(&apply_math_basic, "math.add", std::plus<int64_t>(), std::placeholders::_2));
|
||||
CMD2_ANY_LIST("math.sub", std::bind(&apply_math_basic, "math.sub", std::minus<int64_t>(), std::placeholders::_2));
|
||||
CMD2_ANY_LIST("math.mul", std::bind(&apply_math_basic, "math.mul", std::multiplies<int64_t>(), std::placeholders::_2));
|
||||
CMD2_ANY_LIST("math.div", std::bind(&apply_math_basic, "math.div", std::divides<int64_t>(), std::placeholders::_2));
|
||||
CMD2_ANY_LIST("math.mod", std::bind(&apply_math_basic, "math.mod", std::modulus<int64_t>(), std::placeholders::_2));
|
||||
CMD2_ANY_LIST("math.min", std::bind(&apply_arith_basic, std::less<int64_t>(), std::placeholders::_2));
|
||||
CMD2_ANY_LIST("math.max", std::bind(&apply_arith_basic, std::greater<int64_t>(), std::placeholders::_2));
|
||||
CMD2_ANY_LIST("math.cnt", std::bind(&apply_arith_count, std::placeholders::_2));
|
||||
CMD2_ANY_LIST("math.avg", std::bind(&apply_arith_other, "average", std::placeholders::_2));
|
||||
CMD2_ANY_LIST("math.med", std::bind(&apply_arith_other, "median", std::placeholders::_2));
|
||||
|
||||
CMD2_ANY_LIST ("elapsed.less", std::bind(&apply_elapsed_less, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("elapsed.greater", std::bind(&apply_elapsed_greater, std::placeholders::_2));
|
||||
|
||||
// Build set/get methods for all color definitions
|
||||
for (int color_id = 1; color_id < display::RCOLOR_MAX; color_id++) {
|
||||
control->object_storage()->insert_str(display::color_vars[color_id], "", rpc::object_storage::flag_string_type);
|
||||
|
||||
CMD2_ANY_STRING(std::string(display::color_vars[color_id]) + ".set", [color_id](const auto&, const auto& arg) {
|
||||
return apply_set_color(color_id, arg);
|
||||
});
|
||||
|
||||
CMD2_ANY(display::color_vars[color_id], [color_id](const auto&, const auto&) {
|
||||
return control->object_storage()->get_str(display::color_vars[color_id]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+34
-71
@@ -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,9 +44,9 @@ 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(rak::mem_fn(m_core, &core::Manager::push_log_std));
|
||||
m_commandScheduler->set_slot_error_message([this](const std::string& msg) { m_core->push_log_std(msg); });
|
||||
}
|
||||
|
||||
Control::~Control() {
|
||||
@@ -99,14 +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();
|
||||
}
|
||||
|
||||
@@ -168,22 +130,23 @@ Control::is_shutdown_completed() {
|
||||
|
||||
void
|
||||
Control::handle_shutdown() {
|
||||
rpc::commands.call_catch("event.system.shutdown", rpc::make_target(), "shutdown", "System shutdown event action failed: ");
|
||||
|
||||
if (!m_shutdownQuick) {
|
||||
// Temporary hack:
|
||||
if (worker_thread->is_active())
|
||||
worker_thread->queue_item(&ThreadBase::stop_thread);
|
||||
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);
|
||||
}
|
||||
|
||||
+14
-47
@@ -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
|
||||
|
||||
#ifndef RTORRENT_CONTROL_H
|
||||
#define RTORRENT_CONTROL_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <atomic>
|
||||
#include <cinttypes>
|
||||
#include <sys/types.h>
|
||||
#include <rak/timer.h>
|
||||
#include <rak/priority_queue_default.h>
|
||||
#include <torrent/torrent.h>
|
||||
#include <torrent/utils/scheduler.h>
|
||||
|
||||
namespace ui {
|
||||
class Root;
|
||||
@@ -60,12 +24,13 @@ namespace display {
|
||||
namespace input {
|
||||
class InputEvent;
|
||||
class Manager;
|
||||
}
|
||||
}
|
||||
|
||||
namespace rpc {
|
||||
class CommandScheduler;
|
||||
class XmlRpc;
|
||||
class object_storage;
|
||||
class LuaEngine;
|
||||
}
|
||||
|
||||
namespace torrent {
|
||||
@@ -76,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; }
|
||||
@@ -87,8 +52,8 @@ public:
|
||||
|
||||
void handle_shutdown();
|
||||
|
||||
void receive_normal_shutdown() { m_shutdownReceived = true; __sync_synchronize(); }
|
||||
void receive_quick_shutdown() { m_shutdownReceived = true; m_shutdownQuick = true; __sync_synchronize(); }
|
||||
void receive_normal_shutdown() { m_shutdownReceived = true; }
|
||||
void receive_quick_shutdown() { m_shutdownReceived = true; m_shutdownQuick = true; }
|
||||
|
||||
core::Manager* core() { return m_core; }
|
||||
core::ViewManager* view_manager() { return m_viewManager; }
|
||||
@@ -101,6 +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; }
|
||||
|
||||
@@ -125,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;
|
||||
|
||||
bool m_shutdownReceived lt_cacheline_aligned;
|
||||
bool m_shutdownQuick lt_cacheline_aligned;
|
||||
std::atomic<bool> m_shutdownReceived{};
|
||||
std::atomic<bool> m_shutdownQuick{};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
noinst_LIBRARIES = libsub_core.a
|
||||
|
||||
libsub_core_a_SOURCES = \
|
||||
curl_get.cc \
|
||||
curl_get.h \
|
||||
curl_socket.cc \
|
||||
curl_socket.h \
|
||||
curl_stack.cc \
|
||||
curl_stack.h \
|
||||
dht_manager.cc \
|
||||
dht_manager.h \
|
||||
download.cc \
|
||||
download.h \
|
||||
download_factory.cc \
|
||||
download_factory.h \
|
||||
download_list.cc \
|
||||
download_list.h \
|
||||
download_slot_map.h \
|
||||
download_store.cc \
|
||||
download_store.h \
|
||||
http_queue.cc \
|
||||
http_queue.h \
|
||||
manager.cc \
|
||||
manager.h \
|
||||
poll_manager.cc \
|
||||
poll_manager.h \
|
||||
range_map.h \
|
||||
view.cc \
|
||||
view.h \
|
||||
view_manager.cc \
|
||||
view_manager.h
|
||||
|
||||
AM_CPPFLAGS = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir)
|
||||
+21
-48
@@ -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();
|
||||
}
|
||||
@@ -67,6 +38,9 @@ CurlGet::start() {
|
||||
if (m_stream == NULL)
|
||||
throw torrent::internal_error("Tried to call CurlGet::start without a valid output stream.");
|
||||
|
||||
if (!m_stack->is_running())
|
||||
return;
|
||||
|
||||
m_handle = curl_easy_init();
|
||||
|
||||
if (m_handle == NULL)
|
||||
@@ -82,9 +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_erase(&taskScheduler, &m_taskTimeout);
|
||||
priority_queue_insert(&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);
|
||||
@@ -103,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;
|
||||
|
||||
@@ -130,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
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
+18
-53
@@ -1,60 +1,26 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2008, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <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;
|
||||
|
||||
if (!stack->is_running())
|
||||
return 0;
|
||||
|
||||
if (what == CURL_POLL_REMOVE) {
|
||||
// We also probably need the special code here as we're not
|
||||
// guaranteed that the fd will be closed, afaik.
|
||||
@@ -70,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
|
||||
@@ -100,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
@@ -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"
|
||||
|
||||
+51
-75
@@ -1,61 +1,18 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <curl/multi.h>
|
||||
#include <torrent/exceptions.h>
|
||||
|
||||
#include "rak/functional.h"
|
||||
#include "curl_get.h"
|
||||
#include "curl_socket.h"
|
||||
#include "curl_stack.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
CurlStack::CurlStack() :
|
||||
m_handle((void*)curl_multi_init()),
|
||||
m_active(0),
|
||||
m_maxActive(32),
|
||||
m_ssl_verify_host(true),
|
||||
m_ssl_verify_peer(true),
|
||||
m_dns_timeout(60) {
|
||||
|
||||
m_taskTimeout.slot() = std::bind(&CurlStack::receive_timeout, this);
|
||||
CurlStack::CurlStack() {
|
||||
m_handle = (void*)curl_multi_init();
|
||||
m_task_timeout.slot() = std::bind(&CurlStack::receive_timeout, this);
|
||||
|
||||
#if (LIBCURL_VERSION_NUM >= 0x071000)
|
||||
curl_multi_setopt((CURLM*)m_handle, CURLMOPT_TIMERDATA, this);
|
||||
@@ -66,11 +23,22 @@ CurlStack::CurlStack() :
|
||||
}
|
||||
|
||||
CurlStack::~CurlStack() {
|
||||
shutdown();
|
||||
}
|
||||
|
||||
void
|
||||
CurlStack::shutdown() {
|
||||
if (!m_running)
|
||||
return;
|
||||
|
||||
m_running = false;
|
||||
|
||||
while (!empty())
|
||||
front()->close();
|
||||
|
||||
curl_multi_cleanup((CURLM*)m_handle);
|
||||
priority_queue_erase(&taskScheduler, &m_taskTimeout);
|
||||
|
||||
torrent::this_thread::scheduler()->erase(&m_task_timeout);
|
||||
}
|
||||
|
||||
CurlGet*
|
||||
@@ -80,6 +48,9 @@ CurlStack::new_object() {
|
||||
|
||||
CurlSocket*
|
||||
CurlStack::new_socket(int fd) {
|
||||
if (!m_running)
|
||||
throw torrent::internal_error("CurlStack::new_socket() called when not running.");
|
||||
|
||||
CurlSocket* socket = new CurlSocket(fd, this);
|
||||
curl_multi_assign((CURLM*)m_handle, fd, socket);
|
||||
return socket;
|
||||
@@ -115,7 +86,7 @@ CurlStack::receive_action(CurlSocket* socket, int events) {
|
||||
; // Do nothing.
|
||||
|
||||
if (empty())
|
||||
priority_queue_erase(&taskScheduler, &m_taskTimeout);
|
||||
torrent::this_thread::scheduler()->erase(&m_task_timeout);
|
||||
}
|
||||
|
||||
} while (code == CURLM_CALL_MULTI_PERFORM);
|
||||
@@ -133,11 +104,11 @@ CurlStack::process_done_handle() {
|
||||
throw torrent::internal_error("CurlStack::receive_action() msg->msg != CURLMSG_DONE.");
|
||||
|
||||
if (msg->data.result == CURLE_COULDNT_RESOLVE_HOST) {
|
||||
iterator itr = std::find_if(begin(), end(), rak::equal(msg->easy_handle, std::mem_fun(&CurlGet::handle)));
|
||||
|
||||
iterator itr = std::find_if(begin(), end(), [&msg](CurlGet* get) { return get->handle() == msg->easy_handle; });
|
||||
|
||||
if (itr == end())
|
||||
throw torrent::internal_error("Could not find CurlGet when calling CurlStack::receive_action.");
|
||||
|
||||
|
||||
if (!(*itr)->is_using_ipv6()) {
|
||||
(*itr)->retry_ipv6();
|
||||
|
||||
@@ -155,7 +126,7 @@ CurlStack::process_done_handle() {
|
||||
|
||||
void
|
||||
CurlStack::transfer_done(void* handle, const char* msg) {
|
||||
iterator itr = std::find_if(begin(), end(), rak::equal(handle, std::mem_fun(&CurlGet::handle)));
|
||||
iterator itr = std::find_if(begin(), end(), [&handle](CurlGet* get) { return get->handle() == handle; });
|
||||
|
||||
if (itr == end())
|
||||
throw torrent::internal_error("Could not find CurlGet with the right easy_handle.");
|
||||
@@ -170,31 +141,34 @@ 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_taskTimeout.is_queued()) {
|
||||
long timeout;
|
||||
curl_multi_timeout((CURLM*)m_handle, &timeout);
|
||||
priority_queue_insert(&taskScheduler, &m_taskTimeout,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CurlStack::add_get(CurlGet* get) {
|
||||
if (!m_userAgent.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_USERAGENT, m_userAgent.c_str());
|
||||
if (!m_user_agent.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_USERAGENT, m_user_agent.c_str());
|
||||
|
||||
if (!m_httpProxy.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_PROXY, m_httpProxy.c_str());
|
||||
if (!m_http_proxy.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_PROXY, m_http_proxy.c_str());
|
||||
|
||||
if (!m_bindAddress.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_INTERFACE, m_bindAddress.c_str());
|
||||
if (!m_bind_address.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_INTERFACE, m_bind_address.c_str());
|
||||
|
||||
if (!m_httpCaPath.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_CAPATH, m_httpCaPath.c_str());
|
||||
if (!m_http_ca_path.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_CAPATH, m_http_ca_path.c_str());
|
||||
|
||||
if (!m_httpCaCert.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_CAINFO, m_httpCaCert.c_str());
|
||||
if (!m_http_ca_cert.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_CAINFO, m_http_ca_cert.c_str());
|
||||
|
||||
curl_easy_setopt(get->handle(), CURLOPT_SSL_VERIFYHOST, (long)(m_ssl_verify_host ? 2 : 0));
|
||||
curl_easy_setopt(get->handle(), CURLOPT_SSL_VERIFYPEER, (long)(m_ssl_verify_peer ? 1 : 0));
|
||||
@@ -202,12 +176,12 @@ CurlStack::add_get(CurlGet* get) {
|
||||
|
||||
base_type::push_back(get);
|
||||
|
||||
if (m_active >= m_maxActive)
|
||||
if (m_active >= m_max_active)
|
||||
return;
|
||||
|
||||
m_active++;
|
||||
get->set_active(true);
|
||||
|
||||
|
||||
if (curl_multi_add_handle((CURLM*)m_handle, get->handle()) > 0)
|
||||
throw torrent::internal_error("Error calling curl_multi_add_handle.");
|
||||
|
||||
@@ -234,8 +208,8 @@ CurlStack::remove_get(CurlGet* get) {
|
||||
if (curl_multi_remove_handle((CURLM*)m_handle, get->handle()) > 0)
|
||||
throw torrent::internal_error("Error calling curl_multi_remove_handle.");
|
||||
|
||||
if (m_active == m_maxActive &&
|
||||
(itr = std::find_if(begin(), end(), std::not1(std::mem_fun(&CurlGet::is_active)))) != end()) {
|
||||
if (m_active == m_max_active &&
|
||||
(itr = std::find_if(begin(), end(), [](CurlGet* get) { return !get->is_active(); })) != end()) {
|
||||
(*itr)->set_active(true);
|
||||
|
||||
if (curl_multi_add_handle((CURLM*)m_handle, (*itr)->handle()) > 0)
|
||||
@@ -259,11 +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_erase(&taskScheduler, &stack->m_taskTimeout);
|
||||
priority_queue_insert(&taskScheduler, &stack->m_taskTimeout, 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;
|
||||
}
|
||||
|
||||
+35
-67
@@ -1,46 +1,9 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RTORRENT_CORE_CURL_STACK_H
|
||||
#define RTORRENT_CORE_CURL_STACK_H
|
||||
|
||||
#include <deque>
|
||||
#include <string>
|
||||
|
||||
#include "rak/priority_queue_default.h"
|
||||
#include <torrent/utils/scheduler.h>
|
||||
|
||||
namespace core {
|
||||
|
||||
@@ -56,7 +19,7 @@ class CurlSocket;
|
||||
// removal of elements.
|
||||
|
||||
class CurlStack : std::deque<CurlGet*> {
|
||||
public:
|
||||
public:
|
||||
friend class CurlGet;
|
||||
|
||||
typedef std::deque<CurlGet*> base_type;
|
||||
@@ -81,24 +44,27 @@ class CurlStack : std::deque<CurlGet*> {
|
||||
CurlStack();
|
||||
~CurlStack();
|
||||
|
||||
void shutdown();
|
||||
bool is_running() const { return m_running; }
|
||||
|
||||
CurlGet* new_object();
|
||||
CurlSocket* new_socket(int fd);
|
||||
|
||||
unsigned int active() const { return m_active; }
|
||||
unsigned int max_active() const { return m_maxActive; }
|
||||
void set_max_active(unsigned int a) { m_maxActive = a; }
|
||||
unsigned int max_active() const { return m_max_active; }
|
||||
void set_max_active(unsigned int a) { m_max_active = a; }
|
||||
|
||||
const std::string& user_agent() const { return m_userAgent; }
|
||||
const std::string& http_proxy() const { return m_httpProxy; }
|
||||
const std::string& bind_address() const { return m_bindAddress; }
|
||||
const std::string& http_capath() const { return m_httpCaPath; }
|
||||
const std::string& http_cacert() const { return m_httpCaCert; }
|
||||
const std::string& user_agent() const { return m_user_agent; }
|
||||
const std::string& http_proxy() const { return m_http_proxy; }
|
||||
const std::string& bind_address() const { return m_bind_address; }
|
||||
const std::string& http_capath() const { return m_http_ca_path; }
|
||||
const std::string& http_cacert() const { return m_http_ca_cert; }
|
||||
|
||||
void set_user_agent(const std::string& s) { m_userAgent = s; }
|
||||
void set_http_proxy(const std::string& s) { m_httpProxy = s; }
|
||||
void set_bind_address(const std::string& s) { m_bindAddress = s; }
|
||||
void set_http_capath(const std::string& s) { m_httpCaPath = s; }
|
||||
void set_http_cacert(const std::string& s) { m_httpCaCert = s; }
|
||||
void set_user_agent(const std::string& s) { m_user_agent = s; }
|
||||
void set_http_proxy(const std::string& s) { m_http_proxy = s; }
|
||||
void set_bind_address(const std::string& s) { m_bind_address = s; }
|
||||
void set_http_capath(const std::string& s) { m_http_ca_path = s; }
|
||||
void set_http_cacert(const std::string& s) { m_http_ca_cert = s; }
|
||||
|
||||
bool ssl_verify_host() const { return m_ssl_verify_host; }
|
||||
bool ssl_verify_peer() const { return m_ssl_verify_peer; }
|
||||
@@ -113,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();
|
||||
|
||||
@@ -131,20 +97,22 @@ class CurlStack : std::deque<CurlGet*> {
|
||||
|
||||
void* m_handle;
|
||||
|
||||
unsigned int m_active;
|
||||
unsigned int m_maxActive;
|
||||
bool m_running{true};
|
||||
|
||||
rak::priority_item m_taskTimeout;
|
||||
unsigned int m_active{0};
|
||||
unsigned int m_max_active{32};
|
||||
|
||||
std::string m_userAgent;
|
||||
std::string m_httpProxy;
|
||||
std::string m_bindAddress;
|
||||
std::string m_httpCaPath;
|
||||
std::string m_httpCaCert;
|
||||
torrent::utils::SchedulerEntry m_task_timeout;
|
||||
|
||||
bool m_ssl_verify_host;
|
||||
bool m_ssl_verify_peer;
|
||||
long m_dns_timeout;
|
||||
std::string m_user_agent;
|
||||
std::string m_http_proxy;
|
||||
std::string m_bind_address;
|
||||
std::string m_http_ca_path;
|
||||
std::string m_http_ca_cert;
|
||||
|
||||
bool m_ssl_verify_host{true};
|
||||
bool m_ssl_verify_peer{true};
|
||||
long m_dns_timeout{60};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+36
-71
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -1,47 +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 <cstdlib>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <rak/path.h>
|
||||
#include lt_tr1_functional
|
||||
#include <torrent/utils/log.h>
|
||||
#include <torrent/utils/resume.h>
|
||||
#include <torrent/object.h>
|
||||
@@ -72,21 +37,20 @@ is_network_uri(const std::string& uri) {
|
||||
std::strncmp(uri.c_str(), "ftp://", 6) == 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
download_factory_add_stream(torrent::Object* root, const char* key, const char* filename) {
|
||||
static std::unique_ptr<torrent::Object>
|
||||
download_factory_load_stream(const char* filename) {
|
||||
std::fstream stream(filename, std::ios::in | std::ios::binary);
|
||||
|
||||
if (!stream.is_open())
|
||||
return false;
|
||||
|
||||
torrent::Object obj;
|
||||
stream >> obj;
|
||||
if (!stream.is_open())
|
||||
return std::unique_ptr<torrent::Object>();
|
||||
|
||||
auto obj = std::make_unique<torrent::Object>();
|
||||
stream >> *obj;
|
||||
|
||||
if (!stream.good())
|
||||
return false;
|
||||
return std::unique_ptr<torrent::Object>();
|
||||
|
||||
root->insert_key_move(key, obj);
|
||||
return true;
|
||||
return obj;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -96,19 +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_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");
|
||||
@@ -119,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;
|
||||
@@ -130,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().
|
||||
@@ -145,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
|
||||
@@ -207,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;
|
||||
|
||||
@@ -226,7 +191,7 @@ DownloadFactory::receive_success() {
|
||||
torrent::Object& meta = root->insert_key("rtorrent_meta_download", torrent::Object::create_map());
|
||||
meta.insert_key("start", m_start);
|
||||
meta.insert_key("print_log", m_printLog);
|
||||
|
||||
|
||||
torrent::Object::list_type& commands = meta.insert_key("commands", torrent::Object::create_list()).as_list();
|
||||
|
||||
for (command_list_type::iterator itr = m_commands.begin(); itr != m_commands.end(); ++itr)
|
||||
@@ -234,9 +199,12 @@ DownloadFactory::receive_success() {
|
||||
}
|
||||
|
||||
if (m_session) {
|
||||
download_factory_add_stream(root, "rtorrent", (rak::path_expand(m_uri) + ".rtorrent").c_str());
|
||||
download_factory_add_stream(root, "libtorrent_resume", (rak::path_expand(m_uri) + ".libtorrent_resume").c_str());
|
||||
|
||||
if (rtorrent_object)
|
||||
root->insert_key_move("rtorrent", *rtorrent_object);
|
||||
|
||||
if (libtorrent_resume_object)
|
||||
root->insert_key_move("libtorrent_resume", *libtorrent_resume_object);
|
||||
|
||||
} else {
|
||||
// We only allow session torrents to keep their
|
||||
// 'rtorrent/libtorrent' sections. The "fast_resume" section
|
||||
@@ -247,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());
|
||||
@@ -275,6 +245,10 @@ DownloadFactory::receive_success() {
|
||||
if (!rpc::call_command_value("trackers.use_udp"))
|
||||
download->enable_udp_trackers(false);
|
||||
|
||||
// Skip forcing trackers to scrape when rtorrent starts
|
||||
if (m_initLoad && rpc::call_command_value("trackers.delay_scrape"))
|
||||
download->set_resume_flags(torrent::Download::start_skip_tracker);
|
||||
|
||||
// Check first if we already have these values set in the session
|
||||
// torrent, so that it is safe to change the values.
|
||||
//
|
||||
@@ -315,8 +289,9 @@ DownloadFactory::receive_success() {
|
||||
if (torrent::log_groups[torrent::LOG_TORRENT_DEBUG].valid())
|
||||
log_created(download, rtorrent);
|
||||
|
||||
std::for_each(m_commands.begin(), m_commands.end(),
|
||||
rak::bind2nd(std::ptr_fun(&rpc::parse_command_multiple_std), rpc::make_target(download)));
|
||||
std::for_each(m_commands.begin(), m_commands.end(), [&download](const std::string& cmd) {
|
||||
rpc::parse_command_multiple_std(cmd, rpc::make_target(download));
|
||||
});
|
||||
|
||||
if (m_manager->download_list()->find(infohash) == m_manager->download_list()->end())
|
||||
throw torrent::input_error("The newly created download was removed.");
|
||||
@@ -332,7 +307,7 @@ DownloadFactory::receive_success() {
|
||||
|
||||
if (m_printLog)
|
||||
m_manager->push_log_std(msg);
|
||||
|
||||
|
||||
if (m_manager->download_list()->find(infohash) != m_manager->download_list()->end()) {
|
||||
// Should stop it, mark it bad. Perhaps even delete it?
|
||||
download->set_hash_failed(true);
|
||||
@@ -381,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());
|
||||
}
|
||||
|
||||
@@ -407,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"));
|
||||
|
||||
|
||||
+19
-49
@@ -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.
|
||||
@@ -41,15 +5,17 @@
|
||||
#ifndef RTORRENT_CORE_DOWNLOAD_FACTORY_H
|
||||
#define RTORRENT_CORE_DOWNLOAD_FACTORY_H
|
||||
|
||||
#include <functional>
|
||||
#include <iosfwd>
|
||||
#include <rak/priority_queue_default.h>
|
||||
|
||||
#include <torrent/object.h>
|
||||
#include lt_tr1_functional
|
||||
#include <torrent/utils/scheduler.h>
|
||||
|
||||
#include "http_queue.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
class Download;
|
||||
class Manager;
|
||||
|
||||
class DownloadFactory {
|
||||
@@ -77,6 +43,9 @@ public:
|
||||
bool get_start() const { return m_start; }
|
||||
void set_start(bool v) { m_start = v; }
|
||||
|
||||
bool get_init_load() const { return m_initLoad; }
|
||||
void set_init_load(bool v) { m_initLoad = v; }
|
||||
|
||||
bool print_log() const { return m_printLog; }
|
||||
void set_print_log(bool v) { m_printLog = v; }
|
||||
|
||||
@@ -94,24 +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_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);
|
||||
|
||||
+47
-61
@@ -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>
|
||||
@@ -63,6 +26,7 @@
|
||||
#include "download.h"
|
||||
#include "download_list.h"
|
||||
#include "download_store.h"
|
||||
#include "ui/root.h"
|
||||
|
||||
#define DL_TRIGGER_EVENT(download, event_name) \
|
||||
rpc::commands.call_catch(event_name, rpc::make_target(download), torrent::Object(), "Event '" event_name "' failed: ");
|
||||
@@ -70,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.");
|
||||
@@ -79,25 +43,43 @@ 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.");
|
||||
|
||||
control->dht_manager()->save_dht_cache();
|
||||
control->ui()->save_input_history();
|
||||
}
|
||||
|
||||
DownloadList::iterator
|
||||
DownloadList::find(const torrent::HashString& hash) {
|
||||
return std::find_if(begin(), end(), rak::equal(hash, rak::on(std::mem_fun(&Download::info), std::mem_fun(&torrent::DownloadInfo::hash))));
|
||||
return std::find_if(begin(), end(), [hash](Download* d) { return hash == d->info()->hash(); });
|
||||
}
|
||||
|
||||
DownloadList::iterator
|
||||
@@ -107,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*
|
||||
@@ -118,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;
|
||||
}
|
||||
|
||||
@@ -139,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()) {
|
||||
@@ -157,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;
|
||||
@@ -185,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");
|
||||
|
||||
@@ -219,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;
|
||||
@@ -249,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"))
|
||||
@@ -288,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
|
||||
@@ -368,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()) {
|
||||
@@ -450,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.
|
||||
@@ -548,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");
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -37,9 +37,9 @@
|
||||
#ifndef RTORRENT_CORE_DOWNLOAD_SLOT_MAP_H
|
||||
#define RTORRENT_CORE_DOWNLOAD_SLOT_MAP_H
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include lt_tr1_functional
|
||||
|
||||
#include "download.h"
|
||||
|
||||
|
||||
+22
-39
@@ -1,45 +1,10 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
// DownloadStore handles the saving and listing of session torrents.
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <rak/error_number.h>
|
||||
#include <rak/path.h>
|
||||
@@ -55,6 +20,7 @@
|
||||
|
||||
#include "download.h"
|
||||
#include "download_store.h"
|
||||
#include "rpc/parse_commands.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
@@ -100,6 +66,7 @@ DownloadStore::set_path(const std::string& path) {
|
||||
|
||||
bool
|
||||
DownloadStore::write_bencode(const std::string& filename, const torrent::Object& obj, uint32_t skip_mask) {
|
||||
int fd;
|
||||
torrent::Object tmp;
|
||||
std::fstream output(filename.c_str(), std::ios::out | std::ios::trunc);
|
||||
|
||||
@@ -121,6 +88,22 @@ DownloadStore::write_bencode(const std::string& filename, const torrent::Object&
|
||||
goto download_store_save_error;
|
||||
|
||||
output.close();
|
||||
|
||||
// Ensure that the new file is actually written to the disk
|
||||
fd = ::open(filename.c_str(), O_WRONLY);
|
||||
if (fd < 0)
|
||||
goto download_store_save_error;
|
||||
|
||||
if (rpc::call_command_value("system.files.session.fdatasync")) {
|
||||
#ifdef __APPLE__
|
||||
fsync(fd);
|
||||
#else
|
||||
fdatasync(fd);
|
||||
#endif
|
||||
}
|
||||
|
||||
::close(fd);
|
||||
|
||||
return true;
|
||||
|
||||
download_store_save_error:
|
||||
@@ -162,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());
|
||||
@@ -183,7 +166,7 @@ DownloadStore::remove(Download* d) {
|
||||
// This also needs to check that it isn't a directory.
|
||||
bool
|
||||
not_correct_format(const utils::directory_entry& entry) {
|
||||
return !DownloadStore::is_correct_format(entry.d_name);
|
||||
return !DownloadStore::is_correct_format(entry.s_name);
|
||||
}
|
||||
|
||||
utils::Directory
|
||||
@@ -196,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(¬_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;
|
||||
}
|
||||
|
||||
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RTORRENT_CORE_DOWNLOAD_STORE_H
|
||||
#define RTORRENT_CORE_DOWNLOAD_STORE_H
|
||||
|
||||
|
||||
+2
-39
@@ -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);
|
||||
|
||||
+5
-41
@@ -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
|
||||
|
||||
#ifndef RTORRENT_CORE_HTTP_QUEUE_H
|
||||
#define RTORRENT_CORE_HTTP_QUEUE_H
|
||||
|
||||
#include <list>
|
||||
#include <functional>
|
||||
#include <iosfwd>
|
||||
#include lt_tr1_functional
|
||||
#include <list>
|
||||
|
||||
namespace core {
|
||||
|
||||
@@ -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
|
||||
|
||||
+99
-89
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <cstdio>
|
||||
@@ -53,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 {
|
||||
@@ -86,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);
|
||||
@@ -103,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));
|
||||
@@ -124,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;
|
||||
@@ -143,41 +99,71 @@ 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
|
||||
Manager::retrieve_throttle_value(const torrent::Object::string_type& name, bool rate, bool up) {
|
||||
ThrottleMap::iterator itr = throttles().find(name);
|
||||
|
||||
if (itr == throttles().end()) {
|
||||
return (int64_t)-1;
|
||||
} else {
|
||||
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 == nullptr)
|
||||
return (int64_t)-1;
|
||||
|
||||
int64_t throttle_max = (int64_t)throttle->max_rate();
|
||||
|
||||
if (rate) {
|
||||
|
||||
if (throttle_max > 0)
|
||||
return (int64_t)throttle->rate()->rate();
|
||||
else
|
||||
return (int64_t)-1;
|
||||
|
||||
} else {
|
||||
return throttle_max;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 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_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(), std::bind1st(std::mem_fun(&DownloadList::pause_default), m_downloadList));
|
||||
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(), std::bind1st(std::mem_fun(&DownloadList::close_quick), m_downloadList));
|
||||
std::for_each(m_download_list->begin(), m_download_list->end(), [this](Download* d) { m_download_list->close_quick(d); });
|
||||
}
|
||||
|
||||
void
|
||||
@@ -193,7 +179,7 @@ Manager::listen_open() {
|
||||
if (portRange.is_string()) {
|
||||
if (std::sscanf(portRange.as_string().c_str(), "%i-%i", &portFirst, &portLast) != 2)
|
||||
throw torrent::input_error("Invalid port_range argument.");
|
||||
|
||||
|
||||
// } else if (portRange.is_list()) {
|
||||
|
||||
} else {
|
||||
@@ -231,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) {
|
||||
@@ -243,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);
|
||||
|
||||
@@ -266,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());
|
||||
@@ -288,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.");
|
||||
@@ -298,14 +284,14 @@ Manager::set_proxy_address(const std::string& addr) {
|
||||
if (err == 1)
|
||||
port = 80;
|
||||
|
||||
if ((err = rak::address_info::get_address_info(buf, PF_INET, SOCK_STREAM, &ai)) != 0)
|
||||
if ((err = rak::address_info::get_address_info(buf.data(), PF_INET, SOCK_STREAM, &ai)) != 0)
|
||||
throw torrent::input_error("Could not set proxy address: " + std::string(rak::address_info::strerror(err)) + ".");
|
||||
|
||||
|
||||
try {
|
||||
|
||||
ai->address()->set_port(port);
|
||||
torrent::connection_manager()->set_proxy_address(ai->address()->c_sockaddr());
|
||||
|
||||
|
||||
rak::address_info::free_address_info(ai);
|
||||
|
||||
} catch (torrent::input_error& e) {
|
||||
@@ -319,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.
|
||||
@@ -326,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;
|
||||
|
||||
@@ -337,12 +339,18 @@ Manager::try_create_download(const std::string& uri, int flags, const command_li
|
||||
|
||||
f->set_start(flags & create_start);
|
||||
f->set_print_log(!(flags & create_quiet));
|
||||
f->slot_finished(std::bind(&rak::call_delete_func<core::DownloadFactory>, f));
|
||||
f->slot_finished([f]() { delete f; });
|
||||
|
||||
if (flags & create_raw_data)
|
||||
if (is_data_uri(uri)) {
|
||||
// Allow the use of data URIs, primarily for JSON-RPC which
|
||||
// doesn't have a defined mechanism for binary data
|
||||
f->load_raw_data(decode_data_uri(uri));
|
||||
f->variables()["tied_to_file"] = (int64_t)false;
|
||||
} else if (flags & create_raw_data) {
|
||||
f->load_raw_data(uri);
|
||||
else
|
||||
} else {
|
||||
f->load(uri);
|
||||
}
|
||||
|
||||
f->commit();
|
||||
}
|
||||
@@ -361,7 +369,7 @@ Manager::try_create_download_from_meta_download(torrent::Object* bencode, const
|
||||
|
||||
f->set_start(meta.get_key_value("start"));
|
||||
f->set_print_log(meta.get_key_value("print_log"));
|
||||
f->slot_finished(std::bind(&rak::call_delete_func<core::DownloadFactory>, f));
|
||||
f->slot_finished([f]() { delete f; });
|
||||
|
||||
// Bit of a waste to create the bencode repesentation here
|
||||
// only to have the DownloadFactory decode it.
|
||||
@@ -374,7 +382,7 @@ Manager::try_create_download_from_meta_download(torrent::Object* bencode, const
|
||||
|
||||
utils::Directory
|
||||
path_expand_transform(std::string path, const utils::directory_entry& entry) {
|
||||
return path + entry.d_name;
|
||||
return path + entry.s_name;
|
||||
}
|
||||
|
||||
// Move this somewhere better.
|
||||
@@ -385,7 +393,7 @@ path_expand(std::vector<std::string>* paths, const std::string& pattern) {
|
||||
|
||||
rak::split_iterator_t<std::string> first = rak::split_iterator(pattern, '/');
|
||||
rak::split_iterator_t<std::string> last = rak::split_iterator(pattern);
|
||||
|
||||
|
||||
if (first == last)
|
||||
return;
|
||||
|
||||
@@ -414,16 +422,18 @@ path_expand(std::vector<std::string>* paths, const std::string& pattern) {
|
||||
// Only include filenames starting with '.' if the pattern
|
||||
// starts with the same.
|
||||
itr->update((r.pattern()[0] != '.') ? utils::Directory::update_hide_dot : 0);
|
||||
itr->erase(std::remove_if(itr->begin(), itr->end(), rak::on(rak::mem_ref(&utils::directory_entry::d_name), std::not1(r))), itr->end());
|
||||
itr->erase(std::remove_if(itr->begin(), itr->end(), [r](const utils::directory_entry& entry) { return !r(entry.s_name); }), itr->end());
|
||||
|
||||
std::transform(itr->begin(), itr->end(), std::back_inserter(nextCache), rak::bind1st(std::ptr_fun(&path_expand_transform), itr->path() + (itr->path() == "/" ? "" : "/")));
|
||||
std::transform(itr->begin(), itr->end(), std::back_inserter(nextCache), [itr](const utils::directory_entry& entry) {
|
||||
return path_expand_transform(itr->path() + (itr->path() == "/" ? "" : "/"), entry);
|
||||
});
|
||||
}
|
||||
|
||||
currentCache.clear();
|
||||
currentCache.swap(nextCache);
|
||||
}
|
||||
|
||||
std::transform(currentCache.begin(), currentCache.end(), std::back_inserter(*paths), std::mem_fun_ref(&utils::Directory::path));
|
||||
std::transform(currentCache.begin(), currentCache.end(), std::back_inserter(*paths), std::mem_fn(&utils::Directory::path));
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -457,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;
|
||||
|
||||
@@ -476,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
|
||||
|
||||
+20
-56
@@ -1,50 +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
|
||||
|
||||
#ifndef RTORRENT_CORE_MANAGER_H
|
||||
#define RTORRENT_CORE_MANAGER_H
|
||||
|
||||
#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 {
|
||||
@@ -57,6 +21,7 @@ class FileStatusCache;
|
||||
|
||||
namespace core {
|
||||
|
||||
class CurlStack;
|
||||
class DownloadStore;
|
||||
class HttpQueue;
|
||||
|
||||
@@ -69,28 +34,27 @@ 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);
|
||||
|
||||
torrent::log_buffer* log_important() { return m_log_important; }
|
||||
torrent::log_buffer* log_complete() { return m_log_complete; }
|
||||
torrent::log_buffer* log_important() { return m_log_important.get(); }
|
||||
torrent::log_buffer* log_complete() { return m_log_complete.get(); }
|
||||
|
||||
ThrottleMap& throttles() { return m_throttles; }
|
||||
torrent::ThrottlePair get_throttle(const std::string& name);
|
||||
|
||||
int64_t retrieve_throttle_value(const torrent::Object::string_type& name, bool rate, bool up);
|
||||
|
||||
// Use custom throttle for the given range of IP addresses.
|
||||
void set_address_throttle(uint32_t begin, uint32_t end, torrent::ThrottlePair throttles);
|
||||
torrent::ThrottlePair get_address_throttle(const sockaddr* addr);
|
||||
@@ -141,19 +105,19 @@ 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;
|
||||
|
||||
torrent::log_buffer* m_log_important;
|
||||
torrent::log_buffer* m_log_complete;
|
||||
torrent::log_buffer_ptr m_log_important;
|
||||
torrent::log_buffer_ptr m_log_complete;
|
||||
};
|
||||
|
||||
// Meh, cleanup.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -49,13 +49,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;
|
||||
|
||||
+85
-82
@@ -1,63 +1,26 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <rak/functional.h>
|
||||
#include <rak/functional_fun.h>
|
||||
#include <torrent/download.h>
|
||||
#include <torrent/exceptions.h>
|
||||
|
||||
#include "rpc/parse_commands.h"
|
||||
#include "rpc/object_storage.h"
|
||||
#include "control.h"
|
||||
#include "download.h"
|
||||
#include "download_list.h"
|
||||
#include "manager.h"
|
||||
#include "rpc/object_storage.h"
|
||||
#include "rpc/parse_commands.h"
|
||||
#include "view.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
// Also add focus thingie here?
|
||||
struct view_downloads_compare : std::binary_function<Download*, Download*, bool> {
|
||||
view_downloads_compare(const torrent::Object& cmd) : m_command(cmd) {}
|
||||
struct view_downloads_compare : std::function<bool (Download*, Download*)> {
|
||||
view_downloads_compare(const torrent::Object& cmd) :
|
||||
m_command(cmd) {}
|
||||
|
||||
bool operator () (Download* d1, Download* d2) const {
|
||||
bool operator()(Download* d1, Download* d2) const {
|
||||
try {
|
||||
if (m_command.is_empty())
|
||||
return false;
|
||||
@@ -75,8 +38,7 @@ struct view_downloads_compare : std::binary_function<Download*, Download*, bool>
|
||||
// return rpc::commands.call_command(tmp_command.as_dict_key().c_str(), tmp_command.as_dict_obj(),
|
||||
// rpc::make_target_pair(d1, d2)).as_value();
|
||||
|
||||
return rpc::commands.call_command(m_command.as_dict_key().c_str(), m_command.as_dict_obj(),
|
||||
rpc::make_target_pair(d1, d2)).as_value();
|
||||
return rpc::commands.call_command(m_command.as_dict_key().c_str(), m_command.as_dict_obj(), rpc::make_target_pair(d1, d2)).as_value();
|
||||
|
||||
} catch (torrent::input_error& e) {
|
||||
control->core()->push_log(e.what());
|
||||
@@ -88,18 +50,23 @@ struct view_downloads_compare : std::binary_function<Download*, Download*, bool>
|
||||
const torrent::Object& m_command;
|
||||
};
|
||||
|
||||
struct view_downloads_filter : std::unary_function<Download*, bool> {
|
||||
view_downloads_filter(const torrent::Object& cmd) : m_command(cmd) {}
|
||||
struct view_downloads_filter : std::function<bool (Download*)> {
|
||||
view_downloads_filter(const torrent::Object& cmd, const torrent::Object& cmd2) :
|
||||
m_command(cmd), m_command2(cmd2) {}
|
||||
|
||||
bool operator () (Download* d1) const {
|
||||
if (m_command.is_empty())
|
||||
bool operator()(Download* d1) const {
|
||||
return this->evalCmd(m_command, d1) && this->evalCmd(m_command2, d1);
|
||||
}
|
||||
|
||||
bool evalCmd(const torrent::Object& cmd, Download* d1) const {
|
||||
if (cmd.is_empty())
|
||||
return true;
|
||||
|
||||
try {
|
||||
torrent::Object result;
|
||||
|
||||
if (m_command.is_dict_key()) {
|
||||
// torrent::Object tmp_command = m_command;
|
||||
if (cmd.is_dict_key()) {
|
||||
// torrent::Object tmp_command = cmd;
|
||||
|
||||
// uint32_t flags = tmp_command.flags() & torrent::Object::mask_function;
|
||||
// tmp_command.unset_flags(torrent::Object::mask_function);
|
||||
@@ -109,19 +76,24 @@ struct view_downloads_filter : std::unary_function<Download*, bool> {
|
||||
// result = rpc::commands.call_command(tmp_command.as_dict_key().c_str(), tmp_command.as_dict_obj(),
|
||||
// rpc::make_target(d1));
|
||||
|
||||
result = rpc::commands.call_command(m_command.as_dict_key().c_str(), m_command.as_dict_obj(), rpc::make_target(d1));
|
||||
result = rpc::commands.call_command(cmd.as_dict_key().c_str(), cmd.as_dict_obj(), rpc::make_target(d1));
|
||||
|
||||
} else {
|
||||
result = rpc::parse_command_single(rpc::make_target(d1), m_command.as_string());
|
||||
result = rpc::parse_command_single(rpc::make_target(d1), cmd.as_string());
|
||||
}
|
||||
|
||||
switch (result.type()) {
|
||||
// case torrent::Object::TYPE_RAW_BENCODE: return !result.as_raw_bencode().empty();
|
||||
case torrent::Object::TYPE_VALUE: return result.as_value();
|
||||
case torrent::Object::TYPE_STRING: return !result.as_string().empty();
|
||||
case torrent::Object::TYPE_LIST: return !result.as_list().empty();
|
||||
case torrent::Object::TYPE_MAP: return !result.as_map().empty();
|
||||
default: return false;
|
||||
case torrent::Object::TYPE_VALUE:
|
||||
return result.as_value();
|
||||
case torrent::Object::TYPE_STRING:
|
||||
return !result.as_string().empty();
|
||||
case torrent::Object::TYPE_LIST:
|
||||
return !result.as_list().empty();
|
||||
case torrent::Object::TYPE_MAP:
|
||||
return !result.as_map().empty();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// The default filter action is to return true, to not filter
|
||||
@@ -135,13 +107,13 @@ struct view_downloads_filter : std::unary_function<Download*, bool> {
|
||||
}
|
||||
}
|
||||
|
||||
const torrent::Object& m_command;
|
||||
const torrent::Object& m_command;
|
||||
const torrent::Object& m_command2;
|
||||
};
|
||||
|
||||
void
|
||||
View::emit_changed() {
|
||||
priority_queue_erase(&taskScheduler, &m_delayChanged);
|
||||
priority_queue_insert(&taskScheduler, &m_delayChanged, cachedTime);
|
||||
torrent::this_thread::scheduler()->update_wait_for(&m_delay_changed, 0ms);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -155,7 +127,7 @@ View::~View() {
|
||||
return;
|
||||
|
||||
clear_filter_on();
|
||||
priority_queue_erase(&taskScheduler, &m_delayChanged);
|
||||
torrent::this_thread::scheduler()->erase(&m_delay_changed);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -171,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_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
|
||||
@@ -227,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();
|
||||
}
|
||||
|
||||
@@ -262,12 +258,12 @@ View::filter() {
|
||||
return;
|
||||
|
||||
// Parition the list in two steps so we know which elements changed.
|
||||
iterator splitVisible = std::stable_partition(begin_visible(), end_visible(), view_downloads_filter(m_filter));
|
||||
iterator splitFiltered = std::stable_partition(begin_filtered(), end_filtered(), view_downloads_filter(m_filter));
|
||||
iterator splitVisible = std::stable_partition(begin_visible(), end_visible(), view_downloads_filter(m_filter, m_temp_filter));
|
||||
iterator splitFiltered = std::stable_partition(begin_filtered(), end_filtered(), view_downloads_filter(m_filter, m_temp_filter));
|
||||
|
||||
base_type changed(splitVisible, splitFiltered);
|
||||
iterator splitChanged = changed.begin() + std::distance(splitVisible, end_visible());
|
||||
|
||||
iterator splitChanged = changed.begin() + std::distance(splitVisible, end_visible());
|
||||
|
||||
m_size = std::distance(begin(), std::copy(splitChanged, changed.end(), splitVisible));
|
||||
std::copy(changed.begin(), splitChanged, begin_filtered());
|
||||
|
||||
@@ -285,16 +281,24 @@ View::filter() {
|
||||
// set the elements to NULL as we trigger commands on them. Or
|
||||
// perhaps always clear them, thus not throwing anything.
|
||||
if (!m_event_removed.is_empty())
|
||||
std::for_each(changed.begin(), splitChanged,
|
||||
std::bind(&rpc::call_object_d_nothrow, m_event_removed, std::placeholders::_1));
|
||||
std::for_each(changed.begin(), splitChanged, std::bind(&rpc::call_object_d_nothrow, m_event_removed, std::placeholders::_1));
|
||||
|
||||
if (!m_event_added.is_empty())
|
||||
std::for_each(changed.begin(), splitChanged,
|
||||
std::bind(&rpc::call_object_d_nothrow, m_event_added, std::placeholders::_1));
|
||||
std::for_each(changed.begin(), splitChanged, std::bind(&rpc::call_object_d_nothrow, m_event_added, std::placeholders::_1));
|
||||
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
void
|
||||
View::filter_by(const torrent::Object& condition, View::base_type& result) {
|
||||
// std::copy_if(begin_visible(), end_visible(), result.begin(), view_downloads_filter(condition));
|
||||
view_downloads_filter matches = view_downloads_filter(condition, m_temp_filter);
|
||||
|
||||
for (iterator itr = begin_visible(); itr != end_visible(); ++itr)
|
||||
if (matches(*itr))
|
||||
result.push_back(*itr);
|
||||
}
|
||||
|
||||
void
|
||||
View::filter_download(core::Download* download) {
|
||||
iterator itr = std::find(base_type::begin(), base_type::end(), download);
|
||||
@@ -302,8 +306,7 @@ View::filter_download(core::Download* download) {
|
||||
if (itr == base_type::end())
|
||||
throw torrent::internal_error("View::filter_download(...) could not find download.");
|
||||
|
||||
if (view_downloads_filter(m_filter)(download)) {
|
||||
|
||||
if (view_downloads_filter(m_filter, m_temp_filter)(download)) {
|
||||
if (itr >= end_visible()) {
|
||||
erase_internal(itr);
|
||||
insert_visible(download);
|
||||
@@ -344,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));
|
||||
@@ -363,4 +366,4 @@ View::erase_internal(iterator itr) {
|
||||
base_type::erase(itr);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace core
|
||||
|
||||
+76
-101
@@ -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.
|
||||
//
|
||||
@@ -49,11 +13,12 @@
|
||||
#ifndef RTORRENT_CORE_VIEW_DOWNLOADS_H
|
||||
#define RTORRENT_CORE_VIEW_DOWNLOADS_H
|
||||
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <rak/timer.h>
|
||||
#include <torrent/object.h>
|
||||
#include lt_tr1_functional
|
||||
#include <torrent/utils/scheduler.h>
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
@@ -63,74 +28,83 @@ class Download;
|
||||
|
||||
class View : private std::vector<Download*> {
|
||||
public:
|
||||
typedef std::vector<Download*> base_type;
|
||||
typedef std::function<void ()> slot_void;
|
||||
typedef std::list<slot_void> signal_void;
|
||||
typedef std::vector<Download*> base_type;
|
||||
typedef std::function<void()> slot_void;
|
||||
typedef std::list<slot_void> signal_void;
|
||||
|
||||
using base_type::iterator;
|
||||
using base_type::const_iterator;
|
||||
using base_type::reverse_iterator;
|
||||
using base_type::const_reverse_iterator;
|
||||
|
||||
using base_type::iterator;
|
||||
using base_type::reverse_iterator;
|
||||
|
||||
using base_type::size_type;
|
||||
|
||||
View() {}
|
||||
View() = default;
|
||||
~View();
|
||||
|
||||
void initialize(const std::string& name);
|
||||
void initialize(const std::string& name);
|
||||
|
||||
const std::string& name() const { return m_name; }
|
||||
const std::string& name() const { return m_name; }
|
||||
|
||||
bool empty_visible() const { return m_size == 0; }
|
||||
bool empty_visible() const { return m_size == 0; }
|
||||
|
||||
size_type size() const { return m_size; }
|
||||
size_type size_visible() const { return m_size; }
|
||||
size_type size_not_visible() const { return base_type::size() - m_size; }
|
||||
size_type size() const { return m_size; }
|
||||
size_type size_visible() const { return m_size; }
|
||||
size_type size_not_visible() const { return base_type::size() - m_size; }
|
||||
|
||||
// Perhaps this should be renamed?
|
||||
iterator begin_visible() { return begin(); }
|
||||
const_iterator begin_visible() const { return begin(); }
|
||||
iterator begin_visible() { return begin(); }
|
||||
const_iterator begin_visible() const { return begin(); }
|
||||
|
||||
iterator end_visible() { return begin() + m_size; }
|
||||
const_iterator end_visible() const { return begin() + m_size; }
|
||||
iterator end_visible() { return begin() + m_size; }
|
||||
const_iterator end_visible() const { return begin() + m_size; }
|
||||
|
||||
iterator begin_filtered() { return begin() + m_size; }
|
||||
const_iterator begin_filtered() const { return begin() + m_size; }
|
||||
iterator begin_filtered() { return begin() + m_size; }
|
||||
const_iterator begin_filtered() const { return begin() + m_size; }
|
||||
|
||||
iterator end_filtered() { return base_type::end(); }
|
||||
const_iterator end_filtered() const { return base_type::end(); }
|
||||
iterator end_filtered() { return base_type::end(); }
|
||||
const_iterator end_filtered() const { return base_type::end(); }
|
||||
|
||||
iterator focus() { return begin() + m_focus; }
|
||||
const_iterator focus() const { return begin() + m_focus; }
|
||||
void set_focus(iterator itr) { m_focus = position(itr); emit_changed(); }
|
||||
iterator focus() { return begin() + m_focus; }
|
||||
const_iterator focus() const { return begin() + m_focus; }
|
||||
void set_focus(iterator itr) {
|
||||
m_focus = position(itr);
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
void insert(Download* download) { base_type::push_back(download); }
|
||||
void erase(Download* download);
|
||||
void insert(Download* download) { base_type::push_back(download); }
|
||||
void erase(Download* download);
|
||||
|
||||
void set_visible(Download* download);
|
||||
void set_not_visible(Download* download);
|
||||
void set_visible(Download* download);
|
||||
void set_not_visible(Download* download);
|
||||
|
||||
void next_focus();
|
||||
void prev_focus();
|
||||
void next_focus(unsigned int i);
|
||||
void prev_focus(unsigned int i);
|
||||
|
||||
void sort();
|
||||
void next_focus() { next_focus(1); }
|
||||
void prev_focus() { prev_focus(1); }
|
||||
|
||||
void set_sort_new(const torrent::Object& s) { m_sortNew = s; }
|
||||
void set_sort_current(const torrent::Object& s) { m_sortCurrent = s; }
|
||||
void sort();
|
||||
|
||||
void set_sort_new(const torrent::Object& s) { m_sortNew = s; }
|
||||
void set_sort_current(const torrent::Object& s) { m_sortCurrent = s; }
|
||||
|
||||
// Need to explicity trigger filtering.
|
||||
void filter();
|
||||
void filter_download(core::Download* download);
|
||||
void filter();
|
||||
void filter_by(const torrent::Object& condition, base_type& result);
|
||||
void filter_download(core::Download* download);
|
||||
|
||||
const torrent::Object& get_filter() const { return m_filter; }
|
||||
void set_filter(const torrent::Object& s) { m_filter = s; }
|
||||
void set_filter_on_event(const std::string& event);
|
||||
void set_filter(const torrent::Object& s) { m_filter = s; }
|
||||
const torrent::Object& get_filter_temp() const { return m_temp_filter; }
|
||||
void set_filter_temp(const torrent::Object& s) { m_temp_filter = s; }
|
||||
void set_filter_on_event(const std::string& event);
|
||||
|
||||
void clear_filter_on();
|
||||
void clear_filter_on();
|
||||
|
||||
const torrent::Object& event_added() const { return m_event_added; }
|
||||
const torrent::Object& event_removed() const { return m_event_removed; }
|
||||
void set_event_added(const torrent::Object& cmd) { m_event_added = cmd; }
|
||||
const torrent::Object& event_added() const { return m_event_added; }
|
||||
const torrent::Object& event_removed() const { return m_event_removed; }
|
||||
void set_event_added(const torrent::Object& cmd) { m_event_added = cmd; }
|
||||
void set_event_removed(const torrent::Object& cmd) { m_event_removed = cmd; }
|
||||
|
||||
// The time of the last change to the view, semantics of this is
|
||||
@@ -139,49 +113,50 @@ public:
|
||||
//
|
||||
// Currently initialized to rak::timer(), though perhaps we should
|
||||
// use cachedTimer.
|
||||
rak::timer last_changed() const { return m_lastChanged; }
|
||||
void set_last_changed(const rak::timer& t = ::cachedTime) { m_lastChanged = t; }
|
||||
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.
|
||||
signal_void& signal_changed() { return m_signal_changed; }
|
||||
signal_void& signal_changed() { return m_signal_changed; }
|
||||
|
||||
private:
|
||||
View(const View&);
|
||||
void operator = (const View&);
|
||||
void operator=(const View&);
|
||||
|
||||
void push_back(Download* d) { base_type::push_back(d); }
|
||||
void push_back(Download* d) { base_type::push_back(d); }
|
||||
|
||||
inline void insert_visible(Download* d);
|
||||
inline void erase_internal(iterator itr);
|
||||
inline void insert_visible(Download* d);
|
||||
inline void erase_internal(iterator itr);
|
||||
|
||||
void emit_changed();
|
||||
void emit_changed_now();
|
||||
void emit_changed();
|
||||
void emit_changed_now();
|
||||
|
||||
size_type position(const_iterator itr) const { return itr - begin(); }
|
||||
size_type position(const_iterator itr) const { return itr - begin(); }
|
||||
|
||||
// An received thing for changed status so we can sort and filter.
|
||||
|
||||
std::string m_name;
|
||||
std::string m_name;
|
||||
|
||||
size_type m_size;
|
||||
size_type m_focus;
|
||||
size_type m_size;
|
||||
size_type m_focus;
|
||||
|
||||
// These should be replaced by a faster non-string command type.
|
||||
torrent::Object m_sortNew;
|
||||
torrent::Object m_sortCurrent;
|
||||
torrent::Object m_sortNew;
|
||||
torrent::Object m_sortCurrent;
|
||||
|
||||
torrent::Object m_filter;
|
||||
torrent::Object m_filter;
|
||||
torrent::Object m_temp_filter; // Temporary view filter (eg: name based filter)
|
||||
|
||||
torrent::Object m_event_added;
|
||||
torrent::Object m_event_removed;
|
||||
torrent::Object m_event_added;
|
||||
torrent::Object m_event_removed;
|
||||
|
||||
rak::timer m_lastChanged;
|
||||
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
|
||||
|
||||
#endif
|
||||
|
||||
+12
-41
@@ -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?
|
||||
@@ -109,6 +72,14 @@ ViewManager::set_filter(const std::string& name, const torrent::Object& cmd) {
|
||||
(*viewItr)->filter();
|
||||
}
|
||||
|
||||
void
|
||||
ViewManager::set_filter_temp(const std::string& name, const torrent::Object& cmd) {
|
||||
iterator viewItr = find_throw(name);
|
||||
|
||||
(*viewItr)->set_filter_temp(cmd);
|
||||
(*viewItr)->filter();
|
||||
}
|
||||
|
||||
void
|
||||
ViewManager::set_filter_on(const std::string& name, const filter_args& args) {
|
||||
iterator viewItr = find_throw(name);
|
||||
|
||||
+4
-39
@@ -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
|
||||
@@ -93,6 +57,7 @@ public:
|
||||
void set_sort_current(const std::string& name, const torrent::Object& cmd) { (*find_throw(name))->set_sort_current(cmd); }
|
||||
|
||||
void set_filter(const std::string& name, const torrent::Object& cmd);
|
||||
void set_filter_temp(const std::string& name, const torrent::Object& cmd);
|
||||
void set_filter_on(const std::string& name, const filter_args& args);
|
||||
|
||||
void set_event_added(const std::string& name, const torrent::Object& cmd) { (*find_throw(name))->set_event_added(cmd); }
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
noinst_LIBRARIES = libsub_display.a
|
||||
|
||||
libsub_display_a_SOURCES = \
|
||||
attributes.h \
|
||||
canvas.cc \
|
||||
canvas.h \
|
||||
frame.cc \
|
||||
frame.h \
|
||||
manager.cc \
|
||||
manager.h \
|
||||
utils.cc \
|
||||
utils.h \
|
||||
text_element.h \
|
||||
text_element_list.cc \
|
||||
text_element_list.h \
|
||||
text_element_string.cc \
|
||||
text_element_string.h \
|
||||
text_element_value.cc \
|
||||
text_element_value.h \
|
||||
window.cc \
|
||||
window.h \
|
||||
window_download_chunks_seen.cc \
|
||||
window_download_chunks_seen.h \
|
||||
window_download_list.cc \
|
||||
window_download_list.h \
|
||||
window_download_statusbar.cc \
|
||||
window_download_statusbar.h \
|
||||
window_download_transfer_list.cc \
|
||||
window_download_transfer_list.h \
|
||||
window_file_list.cc \
|
||||
window_file_list.h \
|
||||
window_http_queue.cc \
|
||||
window_http_queue.h \
|
||||
window_input.cc \
|
||||
window_input.h \
|
||||
window_log.cc \
|
||||
window_log.h \
|
||||
window_log_complete.cc \
|
||||
window_log_complete.h \
|
||||
window_peer_list.cc \
|
||||
window_peer_list.h \
|
||||
window_statusbar.cc \
|
||||
window_statusbar.h \
|
||||
window_string_list.cc \
|
||||
window_string_list.h \
|
||||
window_text.cc \
|
||||
window_text.h \
|
||||
window_title.cc \
|
||||
window_title.h \
|
||||
window_tracker_list.cc \
|
||||
window_tracker_list.h
|
||||
|
||||
AM_CPPFLAGS = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir)
|
||||
@@ -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_ATTRIBUTES_H
|
||||
#define RTORRENT_DISPLAY_ATTRIBUTES_H
|
||||
|
||||
@@ -71,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
@@ -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
@@ -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
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user