mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-08-07 02:32:32 +00:00
Compare commits
158 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 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 |
@@ -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,93 @@
|
||||
# Secure workflow with access to repository secrets and GitHub token for posting analysis results
|
||||
name: Post the static analysis results
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: [ "Static analysis" ]
|
||||
types: [ completed ]
|
||||
|
||||
jobs:
|
||||
clang-tidy-results:
|
||||
# Trigger the job only if the previous (insecure) workflow completed successfully
|
||||
if: ${{ github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' }}
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
pull-requests: write
|
||||
# OPTIONAL: auto-closing conversations requires the `contents` permission
|
||||
contents: write
|
||||
steps:
|
||||
- name: Download analysis results
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
run_id: ${{ github.event.workflow_run.id }},
|
||||
});
|
||||
const matchArtifact = artifacts.data.artifacts.filter((artifact) => {
|
||||
return artifact.name == "clang-tidy-result"
|
||||
})[0];
|
||||
const download = await github.rest.actions.downloadArtifact({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
artifact_id: matchArtifact.id,
|
||||
archive_format: "zip",
|
||||
});
|
||||
const fs = require("fs");
|
||||
fs.writeFileSync("${{ github.workspace }}/clang-tidy-result.zip", Buffer.from(download.data));
|
||||
- name: Extract analysis results
|
||||
run: |
|
||||
mkdir clang-tidy-result
|
||||
unzip -j clang-tidy-result.zip -d clang-tidy-result
|
||||
- name: Set environment variables
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const assert = require("node:assert").strict;
|
||||
const fs = require("fs");
|
||||
function exportVar(varName, fileName, regEx) {
|
||||
const val = fs.readFileSync("${{ github.workspace }}/clang-tidy-result/" + fileName, {
|
||||
encoding: "ascii"
|
||||
}).trimEnd();
|
||||
assert.ok(regEx.test(val), "Invalid value format for " + varName);
|
||||
core.exportVariable(varName, val);
|
||||
}
|
||||
exportVar("PR_ID", "pr-id.txt", /^[0-9]+$/);
|
||||
exportVar("PR_HEAD_REPO", "pr-head-repo.txt", /^[-./0-9A-Z_a-z]+$/);
|
||||
exportVar("PR_HEAD_SHA", "pr-head-sha.txt", /^[0-9A-Fa-f]+$/);
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: ${{ env.PR_HEAD_REPO }}
|
||||
ref: ${{ env.PR_HEAD_SHA }}
|
||||
persist-credentials: false
|
||||
- name: Redownload analysis results
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
run_id: ${{ github.event.workflow_run.id }},
|
||||
});
|
||||
const matchArtifact = artifacts.data.artifacts.filter((artifact) => {
|
||||
return artifact.name == "clang-tidy-result"
|
||||
})[0];
|
||||
const download = await github.rest.actions.downloadArtifact({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
artifact_id: matchArtifact.id,
|
||||
archive_format: "zip",
|
||||
});
|
||||
const fs = require("fs");
|
||||
fs.writeFileSync("${{ github.workspace }}/clang-tidy-result.zip", Buffer.from(download.data));
|
||||
- name: Extract analysis results
|
||||
run: |
|
||||
mkdir clang-tidy-result
|
||||
unzip -j clang-tidy-result.zip -d clang-tidy-result
|
||||
- name: Run clang-tidy-pr-comments action
|
||||
uses: platisd/clang-tidy-pr-comments@v1
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
clang_tidy_fixes: clang-tidy-result/fixes.yml
|
||||
pull_request_id: ${{ env.PR_ID }}
|
||||
@@ -0,0 +1,80 @@
|
||||
name: Static analysis
|
||||
|
||||
on: pull_request
|
||||
|
||||
jobs:
|
||||
|
||||
clang-tidy:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Update Packages
|
||||
run: |
|
||||
sudo apt-get update
|
||||
- name: Fetch libtorrent
|
||||
run: |
|
||||
git clone https://github.com/rakshasa/libtorrent
|
||||
- name: Build libtorrent
|
||||
run: |
|
||||
cd libtorrent
|
||||
libtoolize
|
||||
aclocal -I scripts
|
||||
autoconf -i
|
||||
autoheader
|
||||
automake --add-missing
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
cd ..
|
||||
rm -rf libtorrent
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
- name: Fetch base branch
|
||||
run: |
|
||||
git remote add upstream "https://github.com/${{ github.event.pull_request.base.repo.full_name }}"
|
||||
git fetch --no-tags --no-recurse-submodules upstream "${{ github.event.pull_request.base.ref }}"
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get install -y bear clang-tidy libcurl4-openssl-dev
|
||||
- name: Configure Project
|
||||
run: |
|
||||
libtoolize
|
||||
aclocal -I scripts
|
||||
autoconf -i
|
||||
autoheader
|
||||
automake --add-missing
|
||||
./configure
|
||||
- name: Prepare compile_commands.json
|
||||
run: |
|
||||
bear -- make
|
||||
- name: Create results directory
|
||||
run: |
|
||||
mkdir clang-tidy-result
|
||||
- name: Analyze
|
||||
run: |
|
||||
git diff -U0 "$(git merge-base HEAD "upstream/${{ github.event.pull_request.base.ref }}")" | clang-tidy-diff -p1 -path build -export-fixes clang-tidy-result/fixes.yml "-extra-arg=-include/${PWD}/config.h"
|
||||
- name: Save PR metadata
|
||||
run: |
|
||||
echo "${{ github.event.number }}" > clang-tidy-result/pr-id.txt
|
||||
echo "${{ github.event.pull_request.head.repo.full_name }}" > clang-tidy-result/pr-head-repo.txt
|
||||
echo "${{ github.event.pull_request.head.sha }}" > clang-tidy-result/pr-head-sha.txt
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: clang-tidy-result
|
||||
path: clang-tidy-result/
|
||||
# - name: Run clang-tidy-pr-comments action
|
||||
# uses: platisd/clang-tidy-pr-comments@v1
|
||||
# with:
|
||||
# # The GitHub token (or a personal access token)
|
||||
# github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# # The path to the clang-tidy fixes generated previously
|
||||
# clang_tidy_fixes: clang-tidy-result/fixes.yml
|
||||
# # Optionally set to true if you want the Action to request
|
||||
# # changes in case warnings are found
|
||||
# request_changes: true
|
||||
# # Optionally set the number of comments per review
|
||||
# # to avoid GitHub API timeouts for heavily loaded
|
||||
# # pull requests
|
||||
# suggestions_per_comment: 10
|
||||
@@ -0,0 +1,56 @@
|
||||
name: Static analysis
|
||||
|
||||
on: pull_request
|
||||
|
||||
jobs:
|
||||
|
||||
unit-tests:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Update Packages
|
||||
run: |
|
||||
sudo apt-get update
|
||||
- name: Fetch libtorrent
|
||||
run: |
|
||||
git clone https://github.com/rakshasa/libtorrent
|
||||
- name: Build libtorrent
|
||||
run: |
|
||||
cd libtorrent
|
||||
libtoolize
|
||||
aclocal -I scripts
|
||||
autoconf -i
|
||||
autoheader
|
||||
automake --add-missing
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
cd ..
|
||||
rm -rf libtorrent
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
- name: Fetch base branch
|
||||
run: |
|
||||
git remote add upstream "https://github.com/${{ github.event.pull_request.base.repo.full_name }}"
|
||||
git fetch --no-tags --no-recurse-submodules upstream "${{ github.event.pull_request.base.ref }}"
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get install -y \
|
||||
libcppunit-dev \
|
||||
libcurl4-openssl-dev
|
||||
- name: Configure Project
|
||||
run: |
|
||||
libtoolize
|
||||
aclocal -I scripts
|
||||
autoconf -i
|
||||
autoheader
|
||||
automake --add-missing
|
||||
./configure
|
||||
- name: Build Project
|
||||
run: |
|
||||
make
|
||||
- name: Run Unit Tests
|
||||
run: |
|
||||
make check
|
||||
+2
-2
@@ -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
|
||||
|
||||
@@ -10,8 +10,6 @@ EXTRA_DIST= \
|
||||
rak/error_number.h \
|
||||
rak/file_stat.h \
|
||||
rak/fs_stat.h \
|
||||
rak/functional.h \
|
||||
rak/functional_fun.h \
|
||||
rak/path.h \
|
||||
rak/partial_queue.h \
|
||||
rak/priority_queue.h \
|
||||
|
||||
@@ -14,6 +14,12 @@ Stable
|
||||
* [https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.13.8.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.13.8.tar.gz)
|
||||
* [https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.9.8.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.9.8.tar.gz)
|
||||
|
||||
Unstable
|
||||
------
|
||||
|
||||
* [https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.14.0.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.14.0.tar.gz)
|
||||
* [https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.10.0.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.10.0.tar.gz)
|
||||
|
||||
Related Projects
|
||||
----------------
|
||||
|
||||
@@ -26,7 +32,7 @@ Donate to rTorrent development
|
||||
* [Patreon](https://www.patreon.com/rtorrent)
|
||||
* [SubscribeStar](https://www.subscribestar.com/rtorrent)
|
||||
* Bitcoin: 1MpmXm5AHtdBoDaLZstJw8nupJJaeKu8V8
|
||||
* Etherium: 0x9AB1e3C3d8a875e870f161b3e9287Db0E6DAfF78
|
||||
* Ethereum: 0x9AB1e3C3d8a875e870f161b3e9287Db0E6DAfF78
|
||||
* Litecoin: LdyaVR67LBnTf6mAT4QJnjSG2Zk67qxmfQ
|
||||
* Cardano: addr1qytaslmqmk6dspltw06sp0zf83dh09u79j49ceh5y26zdcccgq4ph7nmx6kgmzeldauj43254ey97f3x4xw49d86aguqwfhlte
|
||||
|
||||
|
||||
Executable → Regular
+21
-9
@@ -1,18 +1,23 @@
|
||||
m4_pattern_allow([PKG_CHECK_EXISTS])
|
||||
|
||||
AC_INIT([rtorrent], [0.10.0], [sundell.software@gmail.com])
|
||||
AC_INIT([rtorrent],[0.15.2],[sundell.software@gmail.com])
|
||||
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_MACRO_DIRS([scripts])
|
||||
AM_INIT_AUTOMAKE([foreign subdir-objects])
|
||||
AM_PROG_AR
|
||||
|
||||
AC_DEFINE([API_VERSION], [10], [api version])
|
||||
LT_INIT
|
||||
|
||||
AC_PROG_RANLIB
|
||||
AC_PROG_CXX
|
||||
AC_SYS_LARGEFILE
|
||||
AC_DEFINE([API_VERSION], [11], [api version])
|
||||
|
||||
AX_CXX_COMPILE_STDCXX([14], [noext], [mandatory])
|
||||
# Filter out unwanted flags added by autoconf on some systems, e.g. MacOS.
|
||||
TORRENT_REMOVE_UNWANTED(CXX, $CXX, -std=c++11 -std=gnu++11)
|
||||
|
||||
AX_CXX_COMPILE_STDCXX([17], [noext], [mandatory])
|
||||
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
RAK_CHECK_CFLAGS
|
||||
RAK_CHECK_CXXFLAGS
|
||||
@@ -49,12 +54,19 @@ fi
|
||||
|
||||
PKG_CHECK_MODULES([LIBCURL], [libcurl],, [LIBCURL_CHECK_CONFIG])
|
||||
PKG_CHECK_MODULES([CPPUNIT], [cppunit],, [no_cppunit="yes"])
|
||||
PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.14.0])
|
||||
PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.15.2])
|
||||
|
||||
AC_LANG_PUSH(C++)
|
||||
TORRENT_WITH_XMLRPC_C
|
||||
AC_LANG_POP(C++)
|
||||
|
||||
TORRENT_WITH_LUA
|
||||
TORRENT_WITH_TINYXML2
|
||||
|
||||
if test ${with_xmlrpc_c+y} && test ${with_xmlrpc_tinyxml2+y}; then
|
||||
AC_MSG_ERROR([--with-xmlrpc-c and --with-xmlrpc-tinyxml2 cannot be used together. Please choose only one])
|
||||
fi
|
||||
|
||||
AC_DEFINE(HAVE_CONFIG_H, 1, true if config.h was included)
|
||||
AC_DEFINE(USER_AGENT, [std::string(PACKAGE "/" VERSION "/") + torrent::version()], Http user agent)
|
||||
|
||||
@@ -69,9 +81,9 @@ CC_ATTRIBUTE_UNUSED(
|
||||
|
||||
dnl Only update global build variables immediately before generating the output,
|
||||
dnl to avoid affecting the global build environment for other autoconf checks.
|
||||
LIBS="$PTHREAD_LIBS $CURSES_LIB $CURSES_LIBS $CPPUNIT_LIBS $LIBCURL $LIBCURL_LIBS $DEPENDENCIES_LIBS $LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS $CPPUNIT_CFLAGS $LIBCURL_CPPFLAGS $LIBCURL_CFLAGS $DEPENDENCIES_CFLAGS $CURSES_CFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS $CPPUNIT_CFLAGS $LIBCURL_CPPFLAGS $LIBCURL_CFLAGS $DEPENDENCIES_CFLAGS $CURSES_CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS $CURSES_LIB $CURSES_LIBS $LIBCURL $LIBCURL_LIBS $DEPENDENCIES_LIBS $LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS $LIBCURL_CPPFLAGS $LIBCURL_CFLAGS $DEPENDENCIES_CFLAGS $CURSES_CFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS $LIBCURL_CPPFLAGS $LIBCURL_CFLAGS $DEPENDENCIES_CFLAGS $CURSES_CFLAGS"
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
|
||||
@@ -499,10 +499,6 @@ Number of attempts to check the hash while using the mincore status,
|
||||
before forcing. Overworked systems might need lower values to get a
|
||||
decent hash checking rate.
|
||||
.TP
|
||||
\fBsafe_sync = \fIyes|no\fB\fR
|
||||
Always use MS_SYNC rather than MS_ASYNC when syncing chunks. This may
|
||||
be nessesary in case of filesystem bugs like NFS in linux ~2.6.13.
|
||||
.TP
|
||||
\fBmax_open_files = \fIvalue\fB\fR
|
||||
Number of files to simultaneously keep open. LibTorrent dynamically
|
||||
opens and closes files as necessary when mapping files to
|
||||
|
||||
@@ -978,16 +978,6 @@ decent hash checking rate.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>safe_sync = <replaceable>yes|no</replaceable></term>
|
||||
<listitem><para>
|
||||
|
||||
Always use MS_SYNC rather than MS_ASYNC when syncing chunks. This may
|
||||
be nessesary in case of filesystem bugs like NFS in linux ~2.6.13.
|
||||
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>max_open_files = <replaceable>value</replaceable></term>
|
||||
<listitem><para>
|
||||
|
||||
+1
-1
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,655 +0,0 @@
|
||||
// rak - Rakshasa's toolbox
|
||||
// Copyright (C) 2005-2007, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
// This file contains functors that wrap function pointers and member
|
||||
// function pointers.
|
||||
//
|
||||
// 'fn' functors are polymorphic and derives from 'rak::function' and
|
||||
// thus is less strict about types, this adds the cost of calling a
|
||||
// virtual function.
|
||||
//
|
||||
// 'fun' functors are non-polymorphic and thus cheaper, but requires
|
||||
// the target object's type in the functor's template arguments.
|
||||
//
|
||||
// This should be replaced with TR1 stuff when it becomes widely
|
||||
// available. At the moment it behaves like std::auto_ptr, so be
|
||||
// careful when copying.
|
||||
|
||||
#ifndef RAK_FUNCTIONAL_FUN_H
|
||||
#define RAK_FUNCTIONAL_FUN_H
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace rak {
|
||||
|
||||
template <typename Result>
|
||||
class function_base0 {
|
||||
public:
|
||||
virtual ~function_base0() {}
|
||||
|
||||
virtual Result operator () () = 0;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1>
|
||||
class function_base1 : public std::unary_function<Arg1, Result> {
|
||||
public:
|
||||
virtual ~function_base1() {}
|
||||
|
||||
virtual Result operator () (Arg1 arg1) = 0;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1, typename Arg2>
|
||||
class function_base2 : public std::binary_function<Arg1, Arg2, Result> {
|
||||
public:
|
||||
virtual ~function_base2() {}
|
||||
|
||||
virtual Result operator () (Arg1 arg1, Arg2 arg2) = 0;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1, typename Arg2, typename Arg3>
|
||||
class function_base3 {
|
||||
public:
|
||||
virtual ~function_base3() {}
|
||||
|
||||
virtual Result operator () (Arg1 arg1, Arg2 arg2, Arg3 arg3) = 0;
|
||||
};
|
||||
|
||||
template <typename Result>
|
||||
class function0 {
|
||||
public:
|
||||
typedef Result result_type;
|
||||
typedef function_base0<Result> base_type;
|
||||
|
||||
bool is_valid() const { return m_base.get() != NULL; }
|
||||
|
||||
void set(base_type* base) { m_base = std::shared_ptr<base_type>(base); }
|
||||
base_type* release() { return m_base.release(); }
|
||||
|
||||
Result operator () () { return (*m_base)(); }
|
||||
|
||||
private:
|
||||
std::shared_ptr<base_type> m_base;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1>
|
||||
class function1 {
|
||||
public:
|
||||
typedef Result result_type;
|
||||
typedef function_base1<Result, Arg1> base_type;
|
||||
|
||||
bool is_valid() const { return m_base.get() != NULL; }
|
||||
|
||||
void set(base_type* base) { m_base = std::shared_ptr<base_type>(base); }
|
||||
base_type* release() { return m_base.release(); }
|
||||
|
||||
Result operator () (Arg1 arg1) { return (*m_base)(arg1); }
|
||||
|
||||
private:
|
||||
std::shared_ptr<base_type> m_base;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1, typename Arg2>
|
||||
class function2 {
|
||||
public:
|
||||
typedef Result result_type;
|
||||
typedef function_base2<Result, Arg1, Arg2> base_type;
|
||||
|
||||
bool is_valid() const { return m_base.get() != NULL; }
|
||||
|
||||
void set(base_type* base) { m_base = std::shared_ptr<base_type>(base); }
|
||||
base_type* release() { return m_base.release(); }
|
||||
|
||||
Result operator () (Arg1 arg1, Arg2 arg2) { return (*m_base)(arg1, arg2); }
|
||||
|
||||
private:
|
||||
std::shared_ptr<base_type> m_base;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg2>
|
||||
class function2<Result, void, Arg2> {
|
||||
public:
|
||||
typedef Result result_type;
|
||||
typedef function_base1<Result, Arg2> base_type;
|
||||
|
||||
bool is_valid() const { return m_base.get() != NULL; }
|
||||
|
||||
void set(base_type* base) { m_base = std::shared_ptr<base_type>(base); }
|
||||
base_type* release() { return m_base.release(); }
|
||||
|
||||
Result operator () (Arg2 arg2) { return (*m_base)(arg2); }
|
||||
|
||||
template <typename Discard>
|
||||
Result operator () (Discard discard, Arg2 arg2) { return (*m_base)(arg2); }
|
||||
|
||||
private:
|
||||
std::shared_ptr<base_type> m_base;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1, typename Arg2, typename Arg3>
|
||||
class function3 {
|
||||
public:
|
||||
typedef Result result_type;
|
||||
typedef function_base3<Result, Arg1, Arg2, Arg3> base_type;
|
||||
|
||||
bool is_valid() const { return m_base.get() != NULL; }
|
||||
|
||||
void set(base_type* base) { m_base = std::shared_ptr<base_type>(base); }
|
||||
base_type* release() { return m_base.release(); }
|
||||
|
||||
Result operator () (Arg1 arg1, Arg2 arg2, Arg3 arg3) { return (*m_base)(arg1, arg2, arg3); }
|
||||
|
||||
private:
|
||||
std::shared_ptr<base_type> m_base;
|
||||
};
|
||||
|
||||
template <typename Result>
|
||||
class ptr_fn0_t : public function_base0<Result> {
|
||||
public:
|
||||
typedef Result (*Func)();
|
||||
|
||||
ptr_fn0_t(Func func) : m_func(func) {}
|
||||
virtual ~ptr_fn0_t() {}
|
||||
|
||||
virtual Result operator () () { return m_func(); }
|
||||
|
||||
private:
|
||||
Func m_func;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1>
|
||||
class ptr_fn1_t : public function_base1<Result, Arg1> {
|
||||
public:
|
||||
typedef Result (*Func)(Arg1);
|
||||
|
||||
ptr_fn1_t(Func func) : m_func(func) {}
|
||||
virtual ~ptr_fn1_t() {}
|
||||
|
||||
virtual Result operator () (Arg1 arg1) { return m_func(arg1); }
|
||||
|
||||
private:
|
||||
Func m_func;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1, typename Arg2>
|
||||
class ptr_fn2_t : public function_base2<Result, Arg1, Arg2> {
|
||||
public:
|
||||
typedef Result (*Func)(Arg1, Arg2);
|
||||
|
||||
ptr_fn2_t(Func func) : m_func(func) {}
|
||||
virtual ~ptr_fn2_t() {}
|
||||
|
||||
virtual Result operator () (Arg1 arg1, Arg2 arg2) { return m_func(arg1, arg2); }
|
||||
|
||||
private:
|
||||
Func m_func;
|
||||
};
|
||||
|
||||
template <typename Object, typename Result>
|
||||
class mem_fn0_t : public function_base0<Result> {
|
||||
public:
|
||||
typedef Result (Object::*Func)();
|
||||
|
||||
mem_fn0_t(Object* object, Func func) : m_object(object), m_func(func) {}
|
||||
virtual ~mem_fn0_t() {}
|
||||
|
||||
virtual Result operator () () { return (m_object->*m_func)(); }
|
||||
|
||||
private:
|
||||
Object* m_object;
|
||||
Func m_func;
|
||||
};
|
||||
|
||||
template <typename Object, typename Result, typename Arg1>
|
||||
class mem_fn1_t : public function_base1<Result, Arg1> {
|
||||
public:
|
||||
typedef Result (Object::*Func)(Arg1);
|
||||
|
||||
mem_fn1_t(Object* object, Func func) : m_object(object), m_func(func) {}
|
||||
virtual ~mem_fn1_t() {}
|
||||
|
||||
virtual Result operator () (Arg1 arg1) { return (m_object->*m_func)(arg1); }
|
||||
|
||||
private:
|
||||
Object* m_object;
|
||||
Func m_func;
|
||||
};
|
||||
|
||||
template <typename Object, typename Result, typename Arg1, typename Arg2, typename Arg3>
|
||||
class mem_fn3_t : public function_base3<Result, Arg1, Arg2, Arg3> {
|
||||
public:
|
||||
typedef Result (Object::*Func)(Arg1, Arg2, Arg3);
|
||||
|
||||
mem_fn3_t(Object* object, Func func) : m_object(object), m_func(func) {}
|
||||
virtual ~mem_fn3_t() {}
|
||||
|
||||
virtual Result operator () (Arg1 arg1, Arg2 arg2, Arg3 arg3) { return (m_object->*m_func)(arg1, arg2, arg3); }
|
||||
|
||||
private:
|
||||
Object* m_object;
|
||||
Func m_func;
|
||||
};
|
||||
|
||||
template <typename Object, typename Result, typename Arg1, typename Arg2>
|
||||
class mem_fn2_t : public function_base2<Result, Arg1, Arg2> {
|
||||
public:
|
||||
typedef Result (Object::*Func)(Arg1, Arg2);
|
||||
|
||||
mem_fn2_t(Object* object, Func func) : m_object(object), m_func(func) {}
|
||||
virtual ~mem_fn2_t() {}
|
||||
|
||||
virtual Result operator () (Arg1 arg1, Arg2 arg2) { return (m_object->*m_func)(arg1, arg2); }
|
||||
|
||||
private:
|
||||
Object* m_object;
|
||||
Func m_func;
|
||||
};
|
||||
|
||||
template <typename Object, typename Result>
|
||||
class const_mem_fn0_t : public function_base0<Result> {
|
||||
public:
|
||||
typedef Result (Object::*Func)() const;
|
||||
|
||||
const_mem_fn0_t(const Object* object, Func func) : m_object(object), m_func(func) {}
|
||||
virtual ~const_mem_fn0_t() {}
|
||||
|
||||
virtual Result operator () () { return (m_object->*m_func)(); }
|
||||
|
||||
private:
|
||||
const Object* m_object;
|
||||
Func m_func;
|
||||
};
|
||||
|
||||
template <typename Object, typename Result, typename Arg1>
|
||||
class const_mem_fn1_t : public function_base1<Result, Arg1> {
|
||||
public:
|
||||
typedef Result (Object::*Func)(Arg1) const;
|
||||
|
||||
const_mem_fn1_t(const Object* object, Func func) : m_object(object), m_func(func) {}
|
||||
virtual ~const_mem_fn1_t() {}
|
||||
|
||||
virtual Result operator () (Arg1 arg1) { return (m_object->*m_func)(arg1); }
|
||||
|
||||
private:
|
||||
const Object* m_object;
|
||||
Func m_func;
|
||||
};
|
||||
|
||||
// Unary functor with a bound argument.
|
||||
template <typename Object, typename Result, typename Arg1>
|
||||
class mem_fn0_b1_t : public function_base0<Result> {
|
||||
public:
|
||||
typedef Result (Object::*Func)(Arg1);
|
||||
|
||||
mem_fn0_b1_t(Object* object, Func func, const Arg1 arg1) : m_object(object), m_func(func), m_arg1(arg1) {}
|
||||
virtual ~mem_fn0_b1_t() {}
|
||||
|
||||
virtual Result operator () () { return (m_object->*m_func)(m_arg1); }
|
||||
|
||||
private:
|
||||
Object* m_object;
|
||||
Func m_func;
|
||||
const Arg1 m_arg1;
|
||||
};
|
||||
|
||||
template <typename Object, typename Result, typename Arg1, typename Arg2>
|
||||
class mem_fn1_b1_t : public function_base1<Result, Arg2> {
|
||||
public:
|
||||
typedef Result (Object::*Func)(Arg1, Arg2);
|
||||
|
||||
mem_fn1_b1_t(Object* object, Func func, const Arg1 arg1) : m_object(object), m_func(func), m_arg1(arg1) {}
|
||||
virtual ~mem_fn1_b1_t() {}
|
||||
|
||||
virtual Result operator () (const Arg2 arg2) { return (m_object->*m_func)(m_arg1, arg2); }
|
||||
|
||||
private:
|
||||
Object* m_object;
|
||||
Func m_func;
|
||||
const Arg1 m_arg1;
|
||||
};
|
||||
|
||||
template <typename Object, typename Result, typename Arg1, typename Arg2>
|
||||
class mem_fn1_b2_t : public function_base1<Result, Arg1> {
|
||||
public:
|
||||
typedef Result (Object::*Func)(Arg1, Arg2);
|
||||
|
||||
mem_fn1_b2_t(Object* object, Func func, const Arg2 arg2) : m_object(object), m_func(func), m_arg2(arg2) {}
|
||||
virtual ~mem_fn1_b2_t() {}
|
||||
|
||||
virtual Result operator () (const Arg1 arg1) { return (m_object->*m_func)(arg1, m_arg2); }
|
||||
|
||||
private:
|
||||
Object* m_object;
|
||||
Func m_func;
|
||||
const Arg2 m_arg2;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1>
|
||||
class ptr_fn0_b1_t : public function_base0<Result> {
|
||||
public:
|
||||
typedef Result (*Func)(Arg1);
|
||||
|
||||
ptr_fn0_b1_t(Func func, const Arg1 arg1) : m_func(func), m_arg1(arg1) {}
|
||||
virtual ~ptr_fn0_b1_t() {}
|
||||
|
||||
virtual Result operator () () { return m_func(m_arg1); }
|
||||
|
||||
private:
|
||||
Func m_func;
|
||||
Arg1 m_arg1;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1, typename Arg2>
|
||||
class ptr_fn1_b1_t : public function_base1<Result, Arg2> {
|
||||
public:
|
||||
typedef Result (*Func)(Arg1, Arg2);
|
||||
|
||||
ptr_fn1_b1_t(Func func, const Arg1 arg1) : m_func(func), m_arg1(arg1) {}
|
||||
virtual ~ptr_fn1_b1_t() {}
|
||||
|
||||
virtual Result operator () (Arg2 arg2) { return m_func(m_arg1, arg2); }
|
||||
|
||||
private:
|
||||
Func m_func;
|
||||
Arg1 m_arg1;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1, typename Arg2, typename Arg3>
|
||||
class ptr_fn2_b1_t : public function_base2<Result, Arg2, Arg3> {
|
||||
public:
|
||||
typedef Result (*Func)(Arg1, Arg2, Arg3);
|
||||
|
||||
ptr_fn2_b1_t(Func func, const Arg1 arg1) : m_func(func), m_arg1(arg1) {}
|
||||
virtual ~ptr_fn2_b1_t() {}
|
||||
|
||||
virtual Result operator () (Arg2 arg2, Arg3 arg3) { return m_func(m_arg1, arg2, arg3); }
|
||||
|
||||
private:
|
||||
Func m_func;
|
||||
Arg1 m_arg1;
|
||||
};
|
||||
|
||||
template <typename Ftor>
|
||||
class ftor_fn1_t : public function_base1<typename Ftor::result_type, typename Ftor::argument_type> {
|
||||
public:
|
||||
typedef typename Ftor::result_type result_type;
|
||||
typedef typename Ftor::argument_type argument_type;
|
||||
|
||||
ftor_fn1_t(Ftor ftor) : m_ftor(ftor) {}
|
||||
virtual ~ftor_fn1_t() {}
|
||||
|
||||
virtual result_type operator () (argument_type arg1) { return m_ftor(arg1); }
|
||||
|
||||
private:
|
||||
Ftor m_ftor;
|
||||
};
|
||||
|
||||
template <typename Ftor>
|
||||
class ftor_fn2_t : public function_base2<typename Ftor::result_type, typename Ftor::first_argument_type, typename Ftor::second_argument_type> {
|
||||
public:
|
||||
typedef typename Ftor::result_type result_type;
|
||||
typedef typename Ftor::first_argument_type first_argument_type;
|
||||
typedef typename Ftor::second_argument_type second_argument_type;
|
||||
|
||||
ftor_fn2_t(Ftor ftor) : m_ftor(ftor) {}
|
||||
virtual ~ftor_fn2_t() {}
|
||||
|
||||
virtual result_type operator () (first_argument_type arg1, second_argument_type arg2) { return m_ftor(arg1, arg2); }
|
||||
|
||||
private:
|
||||
Ftor m_ftor;
|
||||
};
|
||||
|
||||
template <typename Result>
|
||||
class value_fn0_t : public function_base0<Result> {
|
||||
public:
|
||||
value_fn0_t(const Result& val) : m_value(val) {}
|
||||
|
||||
virtual Result operator () () { return m_value; }
|
||||
|
||||
private:
|
||||
Result m_value;
|
||||
};
|
||||
|
||||
template <typename Result, typename SrcResult>
|
||||
class convert_fn0_t : public function_base0<Result> {
|
||||
public:
|
||||
typedef function0<SrcResult> src_type;
|
||||
|
||||
convert_fn0_t(typename src_type::base_type* object) { m_object.set(object); }
|
||||
virtual ~convert_fn0_t() {}
|
||||
|
||||
virtual Result operator () () {
|
||||
return m_object();
|
||||
}
|
||||
|
||||
private:
|
||||
src_type m_object;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1, typename SrcResult, typename SrcArg1>
|
||||
class convert_fn1_t : public function_base1<Result, Arg1> {
|
||||
public:
|
||||
typedef function1<SrcResult, SrcArg1> src_type;
|
||||
|
||||
convert_fn1_t(typename src_type::base_type* object) { m_object.set(object); }
|
||||
virtual ~convert_fn1_t() {}
|
||||
|
||||
virtual Result operator () (Arg1 arg1) {
|
||||
return m_object(arg1);
|
||||
}
|
||||
|
||||
private:
|
||||
src_type m_object;
|
||||
};
|
||||
|
||||
template <typename Result, typename Arg1, typename Arg2, typename SrcResult, typename SrcArg1, typename SrcArg2>
|
||||
class convert_fn2_t : public function_base2<Result, Arg1, Arg2> {
|
||||
public:
|
||||
typedef function2<SrcResult, SrcArg1, SrcArg2> src_type;
|
||||
|
||||
convert_fn2_t(typename src_type::base_type* object) { m_object.set(object); }
|
||||
virtual ~convert_fn2_t() {}
|
||||
|
||||
virtual Result operator () (Arg1 arg1, Arg2 arg2) {
|
||||
return m_object(arg1, arg2);
|
||||
}
|
||||
|
||||
private:
|
||||
src_type m_object;
|
||||
};
|
||||
|
||||
template <typename Result>
|
||||
inline function_base0<Result>*
|
||||
ptr_fn(Result (*func)()) {
|
||||
return new ptr_fn0_t<Result>(func);
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Result>
|
||||
inline function_base1<Result, Arg1>*
|
||||
ptr_fn(Result (*func)(Arg1)) {
|
||||
return new ptr_fn1_t<Result, Arg1>(func);
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Arg2, typename Result>
|
||||
inline function_base2<Result, Arg1, Arg2>*
|
||||
ptr_fn(Result (*func)(Arg1, Arg2)) {
|
||||
return new ptr_fn2_t<Result, Arg1, Arg2>(func);
|
||||
}
|
||||
|
||||
template <typename Result, typename Object>
|
||||
inline function_base0<Result>*
|
||||
mem_fn(Object* object, Result (Object::*func)()) {
|
||||
return new mem_fn0_t<Object, Result>(object, func);
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Result, typename Object>
|
||||
inline function_base1<Result, Arg1>*
|
||||
mem_fn(Object* object, Result (Object::*func)(Arg1)) {
|
||||
return new mem_fn1_t<Object, Result, Arg1>(object, func);
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Arg2, typename Result, typename Object>
|
||||
inline function_base2<Result, Arg1, Arg2>*
|
||||
mem_fn(Object* object, Result (Object::*func)(Arg1, Arg2)) {
|
||||
return new mem_fn2_t<Object, Result, Arg1, Arg2>(object, func);
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Arg2, typename Arg3, typename Result, typename Object>
|
||||
inline function_base3<Result, Arg1, Arg2, Arg3>*
|
||||
mem_fn(Object* object, Result (Object::*func)(Arg1, Arg2, Arg3)) {
|
||||
return new mem_fn3_t<Object, Result, Arg1, Arg2, Arg3>(object, func);
|
||||
}
|
||||
|
||||
template <typename Result, typename Object>
|
||||
inline function_base0<Result>*
|
||||
mem_fn(const Object* object, Result (Object::*func)() const) {
|
||||
return new const_mem_fn0_t<Object, Result>(object, func);
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Result, typename Object>
|
||||
inline function_base1<Result, Arg1>*
|
||||
mem_fn(const Object* object, Result (Object::*func)(Arg1) const) {
|
||||
return new const_mem_fn1_t<Object, Result, Arg1>(object, func);
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Result, typename Object>
|
||||
inline function_base0<Result>*
|
||||
bind_mem_fn(Object* object, Result (Object::*func)(Arg1), const Arg1 arg1) {
|
||||
return new mem_fn0_b1_t<Object, Result, Arg1>(object, func, arg1);
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Arg2, typename Result, typename Object>
|
||||
inline function_base1<Result, Arg2>*
|
||||
bind_mem_fn(Object* object, Result (Object::*func)(Arg1, Arg2), const Arg1 arg1) {
|
||||
return new mem_fn1_b1_t<Object, Result, Arg1, Arg2>(object, func, arg1);
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Arg2, typename Result, typename Object>
|
||||
inline function_base1<Result, Arg1>*
|
||||
bind2_mem_fn(Object* object, Result (Object::*func)(Arg1, Arg2), const Arg2 arg2) {
|
||||
return new mem_fn1_b2_t<Object, Result, Arg1, Arg2>(object, func, arg2);
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Result>
|
||||
inline function_base0<Result>*
|
||||
bind_ptr_fn(Result (*func)(Arg1), const Arg1 arg1) {
|
||||
return new ptr_fn0_b1_t<Result, Arg1>(func, arg1);
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Arg2, typename Result>
|
||||
inline function_base1<Result, Arg2>*
|
||||
bind_ptr_fn(Result (*func)(Arg1, Arg2), const Arg1 arg1) {
|
||||
return new ptr_fn1_b1_t<Result, Arg1, Arg2>(func, arg1);
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Arg2, typename Arg3, typename Result>
|
||||
inline function_base2<Result, Arg2, Arg3>*
|
||||
bind_ptr_fn(Result (*func)(Arg1, Arg2, Arg3), const Arg1 arg1) {
|
||||
return new ptr_fn2_b1_t<Result, Arg1, Arg2, Arg3>(func, arg1);
|
||||
}
|
||||
|
||||
template <typename Ftor>
|
||||
inline function_base1<typename Ftor::result_type, typename Ftor::argument_type>*
|
||||
ftor_fn1(Ftor ftor) {
|
||||
return new ftor_fn1_t<Ftor>(ftor);
|
||||
}
|
||||
|
||||
template <typename Ftor>
|
||||
inline function_base2<typename Ftor::result_type, typename Ftor::first_argument_type, typename Ftor::second_argument_type>*
|
||||
ftor_fn2(Ftor ftor) {
|
||||
return new ftor_fn2_t<Ftor>(ftor);
|
||||
}
|
||||
|
||||
template <typename Result>
|
||||
inline function_base0<Result>*
|
||||
value_fn(const Result& val) {
|
||||
return new value_fn0_t<Result>(val);
|
||||
}
|
||||
|
||||
template <typename A, typename B>
|
||||
struct equal_types_t {
|
||||
typedef A first_type;
|
||||
typedef B second_type;
|
||||
|
||||
const static int result = 0;
|
||||
};
|
||||
|
||||
template <typename A>
|
||||
struct equal_types_t<A, A> {
|
||||
typedef A first_type;
|
||||
typedef A second_type;
|
||||
|
||||
const static int result = 1;
|
||||
};
|
||||
|
||||
template <typename Result, typename SrcResult>
|
||||
inline function_base0<Result>*
|
||||
convert_fn(function_base0<SrcResult>* src) {
|
||||
if (equal_types_t<function_base0<Result>, function_base0<SrcResult> >::result)
|
||||
// The pointer cast never gets done if the types are different,
|
||||
// but needs to be here to pleasant the compiler.
|
||||
return reinterpret_cast<typename equal_types_t<function_base0<Result>, function_base0<SrcResult> >::first_type*>(src);
|
||||
else
|
||||
return new convert_fn0_t<Result, SrcResult>(src);
|
||||
}
|
||||
|
||||
template <typename Result, typename Arg1, typename SrcResult, typename SrcArg1>
|
||||
inline function_base1<Result, Arg1>*
|
||||
convert_fn(function_base1<SrcResult, SrcArg1>* src) {
|
||||
if (equal_types_t<function_base1<Result, Arg1>, function_base1<SrcResult, SrcArg1> >::result)
|
||||
// The pointer cast never gets done if the types are different,
|
||||
// but needs to be here to pleasant the compiler.
|
||||
return reinterpret_cast<typename equal_types_t<function_base1<Result, Arg1>, function_base1<SrcResult, SrcArg1> >::first_type*>(src);
|
||||
else
|
||||
return new convert_fn1_t<Result, Arg1, SrcResult, SrcArg1>(src);
|
||||
}
|
||||
|
||||
template <typename Result, typename Arg1, typename Arg2, typename SrcResult, typename SrcArg1, typename SrcArg2>
|
||||
inline function_base2<Result, Arg1, Arg2>*
|
||||
convert_fn(function_base2<SrcResult, SrcArg1, SrcArg2>* src) {
|
||||
if (equal_types_t<function_base2<Result, Arg1, Arg2>, function_base2<SrcResult, SrcArg1, SrcArg2> >::result)
|
||||
// The pointer cast never gets done if the types are different,
|
||||
// but needs to be here to pleasant the compiler.
|
||||
return reinterpret_cast<typename equal_types_t<function_base2<Result, Arg1, Arg2>, function_base2<SrcResult, SrcArg1, SrcArg2> >::first_type*>(src);
|
||||
else
|
||||
return new convert_fn2_t<Result, Arg1, Arg2, SrcResult, SrcArg1, SrcArg2>(src);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+3
-2
@@ -37,6 +37,7 @@
|
||||
#ifndef RAK_PARTIAL_QUEUE_H
|
||||
#define RAK_PARTIAL_QUEUE_H
|
||||
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <cinttypes>
|
||||
@@ -107,7 +108,7 @@ private:
|
||||
size_type m_index;
|
||||
size_type m_ceiling;
|
||||
|
||||
size_pair_type m_layers[num_layers];
|
||||
std::array<size_pair_type, num_layers> m_layers;
|
||||
};
|
||||
|
||||
inline void
|
||||
@@ -137,7 +138,7 @@ partial_queue::clear() {
|
||||
m_index = 0;
|
||||
m_ceiling = ceiling(num_layers - 1);
|
||||
|
||||
std::memset(m_layers, 0, num_layers * sizeof(size_pair_type));
|
||||
m_layers = {};
|
||||
}
|
||||
|
||||
inline bool
|
||||
|
||||
+9
-75
@@ -1,39 +1,3 @@
|
||||
// rak - Rakshasa's toolbox
|
||||
// Copyright (C) 2005-2007, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
// priority_queue is a priority queue implemented using a binary
|
||||
// heap. It can contain multiple instances of a value.
|
||||
|
||||
@@ -46,10 +10,10 @@
|
||||
|
||||
namespace rak {
|
||||
|
||||
template <typename Value, typename Compare, typename Equal, typename Alloc = std::allocator<Value> >
|
||||
class priority_queue : public std::vector<Value, Alloc> {
|
||||
template <typename Value, typename Compare, typename Equal>
|
||||
class priority_queue : public std::vector<Value> {
|
||||
public:
|
||||
typedef std::vector<Value, Alloc> base_type;
|
||||
typedef std::vector<Value> base_type;
|
||||
typedef typename base_type::reference reference;
|
||||
typedef typename base_type::const_reference const_reference;
|
||||
typedef typename base_type::iterator iterator;
|
||||
@@ -74,6 +38,10 @@ public:
|
||||
base_type::pop_back();
|
||||
}
|
||||
|
||||
void update() {
|
||||
std::make_heap(begin(), end(), m_compare);
|
||||
}
|
||||
|
||||
void push(const value_type& value) {
|
||||
base_type::push_back(value);
|
||||
std::push_heap(begin(), end(), m_compare);
|
||||
@@ -81,7 +49,7 @@ public:
|
||||
|
||||
template <typename Key>
|
||||
iterator find(const Key& key) {
|
||||
return std::find_if(begin(), end(), std::bind2nd(m_equal, key));
|
||||
return std::find_if(begin(), end(), [&](auto& value) { return m_equal(value, key); });
|
||||
}
|
||||
|
||||
template <typename Key>
|
||||
@@ -95,12 +63,8 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
// Removes 'itr' from the queue. This assumes 'itr' has been
|
||||
// modified such that it has a higher priority than any other
|
||||
// element in the queue.
|
||||
// Removes 'itr' from the queue.
|
||||
void erase(iterator itr) {
|
||||
// std::push_heap(begin(), ++itr, m_compare);
|
||||
// pop();
|
||||
base_type::erase(itr);
|
||||
std::make_heap(begin(), end(), m_compare);
|
||||
}
|
||||
@@ -110,36 +74,6 @@ private:
|
||||
Equal m_equal;
|
||||
};
|
||||
|
||||
// Iterate while the top node has higher priority, as 'Compare'
|
||||
// returns false.
|
||||
template <typename Queue, typename Compare>
|
||||
class queue_pop_iterator
|
||||
: public std::iterator<std::forward_iterator_tag, void, void, void, void> {
|
||||
public:
|
||||
typedef Queue container_type;
|
||||
|
||||
queue_pop_iterator() : m_queue(NULL) {}
|
||||
queue_pop_iterator(Queue* q, Compare c) : m_queue(q), m_compare(c) {}
|
||||
|
||||
queue_pop_iterator& operator ++ () { m_queue->pop(); return *this; }
|
||||
queue_pop_iterator& operator ++ (int) { m_queue->pop(); return *this; }
|
||||
|
||||
typename container_type::const_reference operator * () { return m_queue->top(); }
|
||||
|
||||
bool operator != (const queue_pop_iterator& itr) { return !m_queue->empty() && !m_compare(m_queue->top()); }
|
||||
bool operator == (const queue_pop_iterator& itr) { return m_queue->empty() || m_compare(m_queue->top()); }
|
||||
|
||||
private:
|
||||
Queue* m_queue;
|
||||
Compare m_compare;
|
||||
};
|
||||
|
||||
template <typename Queue, typename Compare>
|
||||
inline queue_pop_iterator<Queue, Compare>
|
||||
queue_popper(Queue& queue, Compare comp) {
|
||||
return queue_pop_iterator<Queue, Compare>(&queue, comp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,44 +1,8 @@
|
||||
// rak - Rakshasa's toolbox
|
||||
// Copyright (C) 2005-2007, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RAK_PRIORITY_QUEUE_DEFAULT_H
|
||||
#define RAK_PRIORITY_QUEUE_DEFAULT_H
|
||||
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <rak/allocators.h>
|
||||
#include <rak/priority_queue.h>
|
||||
#include <rak/timer.h>
|
||||
|
||||
@@ -52,8 +16,7 @@ public:
|
||||
|
||||
priority_item() {}
|
||||
~priority_item() {
|
||||
if (is_queued())
|
||||
throw torrent::internal_error("priority_item::~priority_item() called on a queued item.");
|
||||
assert(!is_queued() && "priority_item::~priority_item() called on a queued item.");
|
||||
|
||||
m_time = timer();
|
||||
m_slot = slot_void();
|
||||
@@ -85,8 +48,7 @@ struct priority_compare {
|
||||
};
|
||||
|
||||
typedef std::equal_to<priority_item*> priority_equal;
|
||||
typedef priority_queue<priority_item*, priority_compare, priority_equal,
|
||||
cacheline_allocator<priority_item*> > priority_queue_default;
|
||||
typedef priority_queue<priority_item*, priority_compare, priority_equal> priority_queue_default;
|
||||
|
||||
inline void
|
||||
priority_queue_perform(priority_queue_default* queue, timer t) {
|
||||
@@ -127,14 +89,32 @@ priority_queue_erase(priority_queue_default* queue, priority_item* item) {
|
||||
if (!item->is_valid())
|
||||
throw torrent::internal_error("priority_queue_erase(...) called on an invalid item.");
|
||||
|
||||
// Clear time before erasing to force it to the top.
|
||||
// Unqueue it before erasing.
|
||||
item->clear_time();
|
||||
|
||||
|
||||
if (!queue->erase(item))
|
||||
throw torrent::internal_error("priority_queue_erase(...) could not find item in queue.");
|
||||
}
|
||||
|
||||
if (queue->find(item) != queue->end())
|
||||
throw torrent::internal_error("priority_queue_erase(...) item still in queue.");
|
||||
inline void
|
||||
priority_queue_update(priority_queue_default* queue, priority_item* item, timer t) {
|
||||
if (t == timer())
|
||||
throw torrent::internal_error("priority_queue_insert(...) received a bad timer.");
|
||||
|
||||
if (!item->is_valid())
|
||||
throw torrent::internal_error("priority_queue_insert(...) called on an invalid item.");
|
||||
|
||||
if (queue->find(item) == queue->end()) {
|
||||
if (item->is_queued())
|
||||
throw torrent::internal_error("priority_queue_update(...) cannot insert an already queued item.");
|
||||
|
||||
item->set_time(t);
|
||||
queue->push(item);
|
||||
|
||||
} else {
|
||||
item->set_time(t);
|
||||
queue->update();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -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) {}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
-- the "rtorrent" table is passed in by the C++ code, modify and
|
||||
-- return it for loading.
|
||||
local args = {...}
|
||||
local rtorrent = args[1]
|
||||
|
||||
-- Autocall
|
||||
-- Allows syntax like `rtorrent.autocall.system.hostname()`
|
||||
local mt = {}
|
||||
function mt.__call (t, ...)
|
||||
name = table.concat(rawget(t, "__namestack"), ".")
|
||||
success, ret = pcall(rtorrent.call, name, ...)
|
||||
if not success then error(name..": "..ret, 2) end
|
||||
return ret
|
||||
end
|
||||
function mt.__index (t, key)
|
||||
ns = rawget(t, "__namestack") or {}
|
||||
table.insert(ns, key)
|
||||
return setmetatable({__namestack=ns}, mt)
|
||||
end
|
||||
rtorrent["autocall"] = setmetatable({}, mt)
|
||||
|
||||
-- Autocall-config Same as autocall, but passes an empty first target
|
||||
-- implicitly, for syntax like `rtorrent.autocall_config.session.directory.set("/tmp/")`
|
||||
local mt = {}
|
||||
function mt.__call (t, ...)
|
||||
name = table.concat(rawget(t, "__namestack"), ".")
|
||||
success, ret = pcall(rtorrent.call, name, "", ...)
|
||||
if not success then error(name..": "..ret, 2) end
|
||||
return ret
|
||||
end
|
||||
function mt.__index (t, key)
|
||||
ns = rawget(t, "__namestack")
|
||||
if ns == nil then
|
||||
if _G[key] ~= nil then return _G[key] end
|
||||
ns = {}
|
||||
end
|
||||
table.insert(ns, key)
|
||||
return setmetatable({__namestack=ns}, mt)
|
||||
end
|
||||
rtorrent["autocall_config"] = setmetatable({}, mt)
|
||||
|
||||
return rtorrent
|
||||
Executable → Regular
Executable → Regular
@@ -0,0 +1,661 @@
|
||||
# ===========================================================================
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_lua.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_PROG_LUA[([MINIMUM-VERSION], [TOO-BIG-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])]
|
||||
# AX_LUA_HEADERS[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])]
|
||||
# AX_LUA_LIBS[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])]
|
||||
# AX_LUA_READLINE[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])]
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Detect a Lua interpreter, optionally specifying a minimum and maximum
|
||||
# version number. Set up important Lua paths, such as the directories in
|
||||
# which to install scripts and modules (shared libraries).
|
||||
#
|
||||
# Also detect Lua headers and libraries. The Lua version contained in the
|
||||
# header is checked to match the Lua interpreter version exactly. When
|
||||
# searching for Lua libraries, the version number is used as a suffix.
|
||||
# This is done with the goal of supporting multiple Lua installs (5.1,
|
||||
# 5.2, and 5.3 side-by-side).
|
||||
#
|
||||
# A note on compatibility with previous versions: This file has been
|
||||
# mostly rewritten for serial 18. Most developers should be able to use
|
||||
# these macros without needing to modify configure.ac. Care has been taken
|
||||
# to preserve each macro's behavior, but there are some differences:
|
||||
#
|
||||
# 1) AX_WITH_LUA is deprecated; it now expands to the exact same thing as
|
||||
# AX_PROG_LUA with no arguments.
|
||||
#
|
||||
# 2) AX_LUA_HEADERS now checks that the version number defined in lua.h
|
||||
# matches the interpreter version. AX_LUA_HEADERS_VERSION is therefore
|
||||
# unnecessary, so it is deprecated and does not expand to anything.
|
||||
#
|
||||
# 3) The configure flag --with-lua-suffix no longer exists; the user
|
||||
# should instead specify the LUA precious variable on the command line.
|
||||
# See the AX_PROG_LUA description for details.
|
||||
#
|
||||
# Please read the macro descriptions below for more information.
|
||||
#
|
||||
# This file was inspired by Andrew Dalke's and James Henstridge's
|
||||
# python.m4 and Tom Payne's, Matthieu Moy's, and Reuben Thomas's ax_lua.m4
|
||||
# (serial 17). Basically, this file is a mash-up of those two files. I
|
||||
# like to think it combines the best of the two!
|
||||
#
|
||||
# AX_PROG_LUA: Search for the Lua interpreter, and set up important Lua
|
||||
# paths. Adds precious variable LUA, which may contain the path of the Lua
|
||||
# interpreter. If LUA is blank, the user's path is searched for an
|
||||
# suitable interpreter.
|
||||
#
|
||||
# If MINIMUM-VERSION is supplied, then only Lua interpreters with a
|
||||
# version number greater or equal to MINIMUM-VERSION will be accepted. If
|
||||
# TOO-BIG-VERSION is also supplied, then only Lua interpreters with a
|
||||
# version number greater or equal to MINIMUM-VERSION and less than
|
||||
# TOO-BIG-VERSION will be accepted.
|
||||
#
|
||||
# The Lua version number, LUA_VERSION, is found from the interpreter, and
|
||||
# substituted. LUA_PLATFORM is also found, but not currently supported (no
|
||||
# standard representation).
|
||||
#
|
||||
# Finally, the macro finds four paths:
|
||||
#
|
||||
# luadir Directory to install Lua scripts.
|
||||
# pkgluadir $luadir/$PACKAGE
|
||||
# luaexecdir Directory to install Lua modules.
|
||||
# pkgluaexecdir $luaexecdir/$PACKAGE
|
||||
#
|
||||
# These paths are found based on $prefix, $exec_prefix, Lua's
|
||||
# package.path, and package.cpath. The first path of package.path
|
||||
# beginning with $prefix is selected as luadir. The first path of
|
||||
# package.cpath beginning with $exec_prefix is used as luaexecdir. This
|
||||
# should work on all reasonable Lua installations. If a path cannot be
|
||||
# determined, a default path is used. Of course, the user can override
|
||||
# these later when invoking make.
|
||||
#
|
||||
# luadir Default: $prefix/share/lua/$LUA_VERSION
|
||||
# luaexecdir Default: $exec_prefix/lib/lua/$LUA_VERSION
|
||||
#
|
||||
# These directories can be used by Automake as install destinations. The
|
||||
# variable name minus 'dir' needs to be used as a prefix to the
|
||||
# appropriate Automake primary, e.g. lua_SCRIPS or luaexec_LIBRARIES.
|
||||
#
|
||||
# If an acceptable Lua interpreter is found, then ACTION-IF-FOUND is
|
||||
# performed, otherwise ACTION-IF-NOT-FOUND is preformed. If ACTION-IF-NOT-
|
||||
# FOUND is blank, then it will default to printing an error. To prevent
|
||||
# the default behavior, give ':' as an action.
|
||||
#
|
||||
# AX_LUA_HEADERS: Search for Lua headers. Requires that AX_PROG_LUA be
|
||||
# expanded before this macro. Adds precious variable LUA_INCLUDE, which
|
||||
# may contain Lua specific include flags, e.g. -I/usr/include/lua5.1. If
|
||||
# LUA_INCLUDE is blank, then this macro will attempt to find suitable
|
||||
# flags.
|
||||
#
|
||||
# LUA_INCLUDE can be used by Automake to compile Lua modules or
|
||||
# executables with embedded interpreters. The *_CPPFLAGS variables should
|
||||
# be used for this purpose, e.g. myprog_CPPFLAGS = $(LUA_INCLUDE).
|
||||
#
|
||||
# This macro searches for the header lua.h (and others). The search is
|
||||
# performed with a combination of CPPFLAGS, CPATH, etc, and LUA_INCLUDE.
|
||||
# If the search is unsuccessful, then some common directories are tried.
|
||||
# If the headers are then found, then LUA_INCLUDE is set accordingly.
|
||||
#
|
||||
# The paths automatically searched are:
|
||||
#
|
||||
# * /usr/include/luaX.Y
|
||||
# * /usr/include/lua/X.Y
|
||||
# * /usr/include/luaXY
|
||||
# * /usr/local/include/luaX.Y
|
||||
# * /usr/local/include/lua-X.Y
|
||||
# * /usr/local/include/lua/X.Y
|
||||
# * /usr/local/include/luaXY
|
||||
#
|
||||
# (Where X.Y is the Lua version number, e.g. 5.1.)
|
||||
#
|
||||
# The Lua version number found in the headers is always checked to match
|
||||
# the Lua interpreter's version number. Lua headers with mismatched
|
||||
# version numbers are not accepted.
|
||||
#
|
||||
# If headers are found, then ACTION-IF-FOUND is performed, otherwise
|
||||
# ACTION-IF-NOT-FOUND is performed. If ACTION-IF-NOT-FOUND is blank, then
|
||||
# it will default to printing an error. To prevent the default behavior,
|
||||
# set the action to ':'.
|
||||
#
|
||||
# AX_LUA_LIBS: Search for Lua libraries. Requires that AX_PROG_LUA be
|
||||
# expanded before this macro. Adds precious variable LUA_LIB, which may
|
||||
# contain Lua specific linker flags, e.g. -llua5.1. If LUA_LIB is blank,
|
||||
# then this macro will attempt to find suitable flags.
|
||||
#
|
||||
# LUA_LIB can be used by Automake to link Lua modules or executables with
|
||||
# embedded interpreters. The *_LIBADD and *_LDADD variables should be used
|
||||
# for this purpose, e.g. mymod_LIBADD = $(LUA_LIB).
|
||||
#
|
||||
# This macro searches for the Lua library. More technically, it searches
|
||||
# for a library containing the function lua_load. The search is performed
|
||||
# with a combination of LIBS, LIBRARY_PATH, and LUA_LIB.
|
||||
#
|
||||
# If the search determines that some linker flags are missing, then those
|
||||
# flags will be added to LUA_LIB.
|
||||
#
|
||||
# If libraries are found, then ACTION-IF-FOUND is performed, otherwise
|
||||
# ACTION-IF-NOT-FOUND is performed. If ACTION-IF-NOT-FOUND is blank, then
|
||||
# it will default to printing an error. To prevent the default behavior,
|
||||
# set the action to ':'.
|
||||
#
|
||||
# AX_LUA_READLINE: Search for readline headers and libraries. Requires the
|
||||
# AX_LIB_READLINE macro, which is provided by ax_lib_readline.m4 from the
|
||||
# Autoconf Archive.
|
||||
#
|
||||
# If a readline compatible library is found, then ACTION-IF-FOUND is
|
||||
# performed, otherwise ACTION-IF-NOT-FOUND is performed.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2015 Reuben Thomas <rrt@sc3d.org>
|
||||
# Copyright (c) 2014 Tim Perkins <tprk77@gmail.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
# Free Software Foundation, either version 3 of the License, or (at your
|
||||
# option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||
# gives unlimited permission to copy, distribute and modify the configure
|
||||
# scripts that are the output of Autoconf when processing the Macro. You
|
||||
# need not follow the terms of the GNU General Public License when using
|
||||
# or distributing such scripts, even though portions of the text of the
|
||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
||||
# all other use of the material that constitutes the Autoconf Macro.
|
||||
#
|
||||
# This special exception to the GPL applies to versions of the Autoconf
|
||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
#serial 42
|
||||
|
||||
dnl =========================================================================
|
||||
dnl AX_PROG_LUA([MINIMUM-VERSION], [TOO-BIG-VERSION],
|
||||
dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
dnl =========================================================================
|
||||
AC_DEFUN([AX_PROG_LUA],
|
||||
[
|
||||
dnl Check for required tools.
|
||||
AC_REQUIRE([AC_PROG_GREP])
|
||||
AC_REQUIRE([AC_PROG_SED])
|
||||
|
||||
dnl Make LUA a precious variable.
|
||||
AC_ARG_VAR([LUA], [The Lua interpreter, e.g. /usr/bin/lua5.1])
|
||||
|
||||
dnl Find a Lua interpreter.
|
||||
m4_define_default([_AX_LUA_INTERPRETER_LIST],
|
||||
[lua lua5.3 lua53 lua5.2 lua52 lua5.1 lua51 lua50])
|
||||
|
||||
m4_if([$1], [],
|
||||
[ dnl No version check is needed. Find any Lua interpreter.
|
||||
AS_IF([test "x$LUA" = 'x'],
|
||||
[AC_PATH_PROGS([LUA], [_AX_LUA_INTERPRETER_LIST], [:])])
|
||||
ax_display_LUA='lua'
|
||||
|
||||
AS_IF([test "x$LUA" != 'x:'],
|
||||
[ dnl At least check if this is a Lua interpreter.
|
||||
AC_MSG_CHECKING([if $LUA is a Lua interpreter])
|
||||
_AX_LUA_CHK_IS_INTRP([$LUA],
|
||||
[AC_MSG_RESULT([yes])],
|
||||
[ AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([not a Lua interpreter])
|
||||
])
|
||||
])
|
||||
],
|
||||
[ dnl A version check is needed.
|
||||
AS_IF([test "x$LUA" != 'x'],
|
||||
[ dnl Check if this is a Lua interpreter.
|
||||
AC_MSG_CHECKING([if $LUA is a Lua interpreter])
|
||||
_AX_LUA_CHK_IS_INTRP([$LUA],
|
||||
[AC_MSG_RESULT([yes])],
|
||||
[ AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([not a Lua interpreter])
|
||||
])
|
||||
dnl Check the version.
|
||||
m4_if([$2], [],
|
||||
[_ax_check_text="whether $LUA version >= $1"],
|
||||
[_ax_check_text="whether $LUA version >= $1, < $2"])
|
||||
AC_MSG_CHECKING([$_ax_check_text])
|
||||
_AX_LUA_CHK_VER([$LUA], [$1], [$2],
|
||||
[AC_MSG_RESULT([yes])],
|
||||
[ AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([version is out of range for specified LUA])])
|
||||
ax_display_LUA=$LUA
|
||||
],
|
||||
[ dnl Try each interpreter until we find one that satisfies VERSION.
|
||||
m4_if([$2], [],
|
||||
[_ax_check_text="for a Lua interpreter with version >= $1"],
|
||||
[_ax_check_text="for a Lua interpreter with version >= $1, < $2"])
|
||||
AC_CACHE_CHECK([$_ax_check_text],
|
||||
[ax_cv_pathless_LUA],
|
||||
[ for ax_cv_pathless_LUA in _AX_LUA_INTERPRETER_LIST none; do
|
||||
test "x$ax_cv_pathless_LUA" = 'xnone' && break
|
||||
_AX_LUA_CHK_IS_INTRP([$ax_cv_pathless_LUA], [], [continue])
|
||||
_AX_LUA_CHK_VER([$ax_cv_pathless_LUA], [$1], [$2], [break])
|
||||
done
|
||||
])
|
||||
dnl Set $LUA to the absolute path of $ax_cv_pathless_LUA.
|
||||
AS_IF([test "x$ax_cv_pathless_LUA" = 'xnone'],
|
||||
[LUA=':'],
|
||||
[AC_PATH_PROG([LUA], [$ax_cv_pathless_LUA])])
|
||||
ax_display_LUA=$ax_cv_pathless_LUA
|
||||
])
|
||||
])
|
||||
|
||||
AS_IF([test "x$LUA" = 'x:'],
|
||||
[ dnl Run any user-specified action, or abort.
|
||||
m4_default([$4], [AC_MSG_ERROR([cannot find suitable Lua interpreter])])
|
||||
],
|
||||
[ dnl Query Lua for its version number.
|
||||
AC_CACHE_CHECK([for $ax_display_LUA version],
|
||||
[ax_cv_lua_version],
|
||||
[ dnl Get the interpreter version in X.Y format. This should work for
|
||||
dnl interpreters version 5.0 and beyond.
|
||||
ax_cv_lua_version=[`$LUA -e '
|
||||
-- return a version number in X.Y format
|
||||
local _, _, ver = string.find(_VERSION, "^Lua (%d+%.%d+)")
|
||||
print(ver)'`]
|
||||
])
|
||||
AS_IF([test "x$ax_cv_lua_version" = 'x'],
|
||||
[AC_MSG_ERROR([invalid Lua version number])])
|
||||
AC_SUBST([LUA_VERSION], [$ax_cv_lua_version])
|
||||
AC_SUBST([LUA_SHORT_VERSION], [`echo "$LUA_VERSION" | $SED 's|\.||'`])
|
||||
|
||||
dnl The following check is not supported:
|
||||
dnl At times (like when building shared libraries) you may want to know
|
||||
dnl which OS platform Lua thinks this is.
|
||||
AC_CACHE_CHECK([for $ax_display_LUA platform],
|
||||
[ax_cv_lua_platform],
|
||||
[ax_cv_lua_platform=[`$LUA -e 'print("unknown")'`]])
|
||||
AC_SUBST([LUA_PLATFORM], [$ax_cv_lua_platform])
|
||||
|
||||
dnl Use the values of $prefix and $exec_prefix for the corresponding
|
||||
dnl values of LUA_PREFIX and LUA_EXEC_PREFIX. These are made distinct
|
||||
dnl variables so they can be overridden if need be. However, the general
|
||||
dnl consensus is that you shouldn't need this ability.
|
||||
AC_SUBST([LUA_PREFIX], ['${prefix}'])
|
||||
AC_SUBST([LUA_EXEC_PREFIX], ['${exec_prefix}'])
|
||||
|
||||
dnl Lua provides no way to query the script directory, and instead
|
||||
dnl provides LUA_PATH. However, we should be able to make a safe educated
|
||||
dnl guess. If the built-in search path contains a directory which is
|
||||
dnl prefixed by $prefix, then we can store scripts there. The first
|
||||
dnl matching path will be used.
|
||||
AC_CACHE_CHECK([for $ax_display_LUA script directory],
|
||||
[ax_cv_lua_luadir],
|
||||
[ AS_IF([test "x$prefix" = 'xNONE'],
|
||||
[ax_lua_prefix=$ac_default_prefix],
|
||||
[ax_lua_prefix=$prefix])
|
||||
|
||||
dnl Initialize to the default path.
|
||||
ax_cv_lua_luadir="$LUA_PREFIX/share/lua/$LUA_VERSION"
|
||||
|
||||
dnl Try to find a path with the prefix.
|
||||
_AX_LUA_FND_PRFX_PTH([$LUA], [$ax_lua_prefix], [script])
|
||||
AS_IF([test "x$ax_lua_prefixed_path" != 'x'],
|
||||
[ dnl Fix the prefix.
|
||||
_ax_strip_prefix=`echo "$ax_lua_prefix" | $SED 's|.|.|g'`
|
||||
ax_cv_lua_luadir=`echo "$ax_lua_prefixed_path" | \
|
||||
$SED "s|^$_ax_strip_prefix|$LUA_PREFIX|"`
|
||||
])
|
||||
])
|
||||
AC_SUBST([luadir], [$ax_cv_lua_luadir])
|
||||
AC_SUBST([pkgluadir], [\${luadir}/$PACKAGE])
|
||||
|
||||
dnl Lua provides no way to query the module directory, and instead
|
||||
dnl provides LUA_PATH. However, we should be able to make a safe educated
|
||||
dnl guess. If the built-in search path contains a directory which is
|
||||
dnl prefixed by $exec_prefix, then we can store modules there. The first
|
||||
dnl matching path will be used.
|
||||
AC_CACHE_CHECK([for $ax_display_LUA module directory],
|
||||
[ax_cv_lua_luaexecdir],
|
||||
[ AS_IF([test "x$exec_prefix" = 'xNONE'],
|
||||
[ax_lua_exec_prefix=$ax_lua_prefix],
|
||||
[ax_lua_exec_prefix=$exec_prefix])
|
||||
|
||||
dnl Initialize to the default path.
|
||||
ax_cv_lua_luaexecdir="$LUA_EXEC_PREFIX/lib/lua/$LUA_VERSION"
|
||||
|
||||
dnl Try to find a path with the prefix.
|
||||
_AX_LUA_FND_PRFX_PTH([$LUA],
|
||||
[$ax_lua_exec_prefix], [module])
|
||||
AS_IF([test "x$ax_lua_prefixed_path" != 'x'],
|
||||
[ dnl Fix the prefix.
|
||||
_ax_strip_prefix=`echo "$ax_lua_exec_prefix" | $SED 's|.|.|g'`
|
||||
ax_cv_lua_luaexecdir=`echo "$ax_lua_prefixed_path" | \
|
||||
$SED "s|^$_ax_strip_prefix|$LUA_EXEC_PREFIX|"`
|
||||
])
|
||||
])
|
||||
AC_SUBST([luaexecdir], [$ax_cv_lua_luaexecdir])
|
||||
AC_SUBST([pkgluaexecdir], [\${luaexecdir}/$PACKAGE])
|
||||
|
||||
dnl Run any user specified action.
|
||||
$3
|
||||
])
|
||||
])
|
||||
|
||||
dnl AX_WITH_LUA is now the same thing as AX_PROG_LUA.
|
||||
AC_DEFUN([AX_WITH_LUA],
|
||||
[
|
||||
AC_MSG_WARN([[$0 is deprecated, please use AX_PROG_LUA instead]])
|
||||
AX_PROG_LUA
|
||||
])
|
||||
|
||||
|
||||
dnl =========================================================================
|
||||
dnl _AX_LUA_CHK_IS_INTRP(PROG, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
|
||||
dnl =========================================================================
|
||||
AC_DEFUN([_AX_LUA_CHK_IS_INTRP],
|
||||
[
|
||||
dnl A minimal Lua factorial to prove this is an interpreter. This should work
|
||||
dnl for Lua interpreters version 5.0 and beyond.
|
||||
_ax_lua_factorial=[`$1 2>/dev/null -e '
|
||||
-- a simple factorial
|
||||
function fact (n)
|
||||
if n == 0 then
|
||||
return 1
|
||||
else
|
||||
return n * fact(n-1)
|
||||
end
|
||||
end
|
||||
print("fact(5) is " .. fact(5))'`]
|
||||
AS_IF([test "$_ax_lua_factorial" = 'fact(5) is 120'],
|
||||
[$2], [$3])
|
||||
])
|
||||
|
||||
|
||||
dnl =========================================================================
|
||||
dnl _AX_LUA_CHK_VER(PROG, MINIMUM-VERSION, [TOO-BIG-VERSION],
|
||||
dnl [ACTION-IF-TRUE], [ACTION-IF-FALSE])
|
||||
dnl =========================================================================
|
||||
AC_DEFUN([_AX_LUA_CHK_VER],
|
||||
[
|
||||
dnl Check that the Lua version is within the bounds. Only the major and minor
|
||||
dnl version numbers are considered. This should work for Lua interpreters
|
||||
dnl version 5.0 and beyond.
|
||||
_ax_lua_good_version=[`$1 -e '
|
||||
-- a script to compare versions
|
||||
function verstr2num(verstr)
|
||||
local _, _, majorver, minorver = string.find(verstr, "^(%d+)%.(%d+)")
|
||||
if majorver and minorver then
|
||||
return tonumber(majorver) * 100 + tonumber(minorver)
|
||||
end
|
||||
end
|
||||
local minver = verstr2num("$2")
|
||||
local _, _, trimver = string.find(_VERSION, "^Lua (.*)")
|
||||
local ver = verstr2num(trimver)
|
||||
local maxver = verstr2num("$3") or 1e9
|
||||
if minver <= ver and ver < maxver then
|
||||
print("yes")
|
||||
else
|
||||
print("no")
|
||||
end'`]
|
||||
AS_IF([test "x$_ax_lua_good_version" = "xyes"],
|
||||
[$4], [$5])
|
||||
])
|
||||
|
||||
|
||||
dnl =========================================================================
|
||||
dnl _AX_LUA_FND_PRFX_PTH(PROG, PREFIX, SCRIPT-OR-MODULE-DIR)
|
||||
dnl =========================================================================
|
||||
AC_DEFUN([_AX_LUA_FND_PRFX_PTH],
|
||||
[
|
||||
dnl Get the script or module directory by querying the Lua interpreter,
|
||||
dnl filtering on the given prefix, and selecting the shallowest path. If no
|
||||
dnl path is found matching the prefix, the result will be an empty string.
|
||||
dnl The third argument determines the type of search, it can be 'script' or
|
||||
dnl 'module'. Supplying 'script' will perform the search with package.path
|
||||
dnl and LUA_PATH, and supplying 'module' will search with package.cpath and
|
||||
dnl LUA_CPATH. This is done for compatibility with Lua 5.0.
|
||||
|
||||
ax_lua_prefixed_path=[`$1 -e '
|
||||
-- get the path based on search type
|
||||
local searchtype = "$3"
|
||||
local paths = ""
|
||||
if searchtype == "script" then
|
||||
paths = (package and package.path) or LUA_PATH
|
||||
elseif searchtype == "module" then
|
||||
paths = (package and package.cpath) or LUA_CPATH
|
||||
end
|
||||
-- search for the prefix
|
||||
local prefix = "'$2'"
|
||||
local minpath = ""
|
||||
local mindepth = 1e9
|
||||
string.gsub(paths, "(@<:@^;@:>@+)",
|
||||
function (path)
|
||||
path = string.gsub(path, "%?.*$", "")
|
||||
path = string.gsub(path, "/@<:@^/@:>@*$", "")
|
||||
if string.find(path, prefix) then
|
||||
local depth = string.len(string.gsub(path, "@<:@^/@:>@", ""))
|
||||
if depth < mindepth then
|
||||
minpath = path
|
||||
mindepth = depth
|
||||
end
|
||||
end
|
||||
end)
|
||||
print(minpath)'`]
|
||||
])
|
||||
|
||||
|
||||
dnl =========================================================================
|
||||
dnl AX_LUA_HEADERS([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
dnl =========================================================================
|
||||
AC_DEFUN([AX_LUA_HEADERS],
|
||||
[
|
||||
dnl Check for LUA_VERSION.
|
||||
AC_MSG_CHECKING([if LUA_VERSION is defined])
|
||||
AS_IF([test "x$LUA_VERSION" != 'x'],
|
||||
[AC_MSG_RESULT([yes])],
|
||||
[ AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([cannot check Lua headers without knowing LUA_VERSION])
|
||||
])
|
||||
|
||||
dnl Make LUA_INCLUDE a precious variable.
|
||||
AC_ARG_VAR([LUA_INCLUDE], [The Lua includes, e.g. -I/usr/include/lua5.1])
|
||||
|
||||
dnl Some default directories to search.
|
||||
LUA_SHORT_VERSION=`echo "$LUA_VERSION" | $SED 's|\.||'`
|
||||
m4_define_default([_AX_LUA_INCLUDE_LIST],
|
||||
[ /usr/include/lua$LUA_VERSION \
|
||||
/usr/include/lua-$LUA_VERSION \
|
||||
/usr/include/lua/$LUA_VERSION \
|
||||
/usr/include/lua$LUA_SHORT_VERSION \
|
||||
/usr/local/include/lua$LUA_VERSION \
|
||||
/usr/local/include/lua-$LUA_VERSION \
|
||||
/usr/local/include/lua/$LUA_VERSION \
|
||||
/usr/local/include/lua$LUA_SHORT_VERSION \
|
||||
])
|
||||
|
||||
dnl Try to find the headers.
|
||||
_ax_lua_saved_cppflags=$CPPFLAGS
|
||||
CPPFLAGS="$CPPFLAGS $LUA_INCLUDE"
|
||||
AC_CHECK_HEADERS([lua.h lualib.h lauxlib.h luaconf.h])
|
||||
CPPFLAGS=$_ax_lua_saved_cppflags
|
||||
|
||||
dnl Try some other directories if LUA_INCLUDE was not set.
|
||||
AS_IF([test "x$LUA_INCLUDE" = 'x' &&
|
||||
test "x$ac_cv_header_lua_h" != 'xyes'],
|
||||
[ dnl Try some common include paths.
|
||||
for _ax_include_path in _AX_LUA_INCLUDE_LIST; do
|
||||
test ! -d "$_ax_include_path" && continue
|
||||
|
||||
AC_MSG_CHECKING([for Lua headers in])
|
||||
AC_MSG_RESULT([$_ax_include_path])
|
||||
|
||||
AS_UNSET([ac_cv_header_lua_h])
|
||||
AS_UNSET([ac_cv_header_lualib_h])
|
||||
AS_UNSET([ac_cv_header_lauxlib_h])
|
||||
AS_UNSET([ac_cv_header_luaconf_h])
|
||||
|
||||
_ax_lua_saved_cppflags=$CPPFLAGS
|
||||
CPPFLAGS="$CPPFLAGS -I$_ax_include_path"
|
||||
AC_CHECK_HEADERS([lua.h lualib.h lauxlib.h luaconf.h])
|
||||
CPPFLAGS=$_ax_lua_saved_cppflags
|
||||
|
||||
AS_IF([test "x$ac_cv_header_lua_h" = 'xyes'],
|
||||
[ LUA_INCLUDE="-I$_ax_include_path"
|
||||
break
|
||||
])
|
||||
done
|
||||
])
|
||||
|
||||
AS_IF([test "x$ac_cv_header_lua_h" = 'xyes'],
|
||||
[ dnl Make a program to print LUA_VERSION defined in the header.
|
||||
dnl TODO It would be really nice if we could do this without compiling a
|
||||
dnl program, then it would work when cross compiling. But I'm not sure how
|
||||
dnl to do this reliably. For now, assume versions match when cross compiling.
|
||||
|
||||
AS_IF([test "x$cross_compiling" != 'xyes'],
|
||||
[ AC_CACHE_CHECK([for Lua header version],
|
||||
[ax_cv_lua_header_version],
|
||||
[ _ax_lua_saved_cppflags=$CPPFLAGS
|
||||
CPPFLAGS="$CPPFLAGS $LUA_INCLUDE"
|
||||
AC_COMPUTE_INT(ax_cv_lua_header_version_major,[LUA_VERSION_NUM/100],[AC_INCLUDES_DEFAULT
|
||||
#include <lua.h>
|
||||
],[ax_cv_lua_header_version_major=unknown])
|
||||
AC_COMPUTE_INT(ax_cv_lua_header_version_minor,[LUA_VERSION_NUM%100],[AC_INCLUDES_DEFAULT
|
||||
#include <lua.h>
|
||||
],[ax_cv_lua_header_version_minor=unknown])
|
||||
AS_IF([test "x$ax_cv_lua_header_version_major" = xunknown || test "x$ax_cv_lua_header_version_minor" = xunknown],[
|
||||
ax_cv_lua_header_version=unknown
|
||||
],[
|
||||
ax_cv_lua_header_version="$ax_cv_lua_header_version_major.$ax_cv_lua_header_version_minor"
|
||||
])
|
||||
CPPFLAGS=$_ax_lua_saved_cppflags
|
||||
])
|
||||
|
||||
dnl Compare this to the previously found LUA_VERSION.
|
||||
AC_MSG_CHECKING([if Lua header version matches $LUA_VERSION])
|
||||
AS_IF([test "x$ax_cv_lua_header_version" = "x$LUA_VERSION"],
|
||||
[ AC_MSG_RESULT([yes])
|
||||
ax_header_version_match='yes'
|
||||
],
|
||||
[ AC_MSG_RESULT([no])
|
||||
ax_header_version_match='no'
|
||||
])
|
||||
],
|
||||
[ AC_MSG_WARN([cross compiling so assuming header version number matches])
|
||||
ax_header_version_match='yes'
|
||||
])
|
||||
])
|
||||
|
||||
dnl Was LUA_INCLUDE specified?
|
||||
AS_IF([test "x$ax_header_version_match" != 'xyes' &&
|
||||
test "x$LUA_INCLUDE" != 'x'],
|
||||
[AC_MSG_ERROR([cannot find headers for specified LUA_INCLUDE])])
|
||||
|
||||
dnl Test the final result and run user code.
|
||||
AS_IF([test "x$ax_header_version_match" = 'xyes'], [$1],
|
||||
[m4_default([$2], [AC_MSG_ERROR([cannot find Lua includes])])])
|
||||
])
|
||||
|
||||
dnl AX_LUA_HEADERS_VERSION no longer exists, use AX_LUA_HEADERS.
|
||||
AC_DEFUN([AX_LUA_HEADERS_VERSION],
|
||||
[
|
||||
AC_MSG_WARN([[$0 is deprecated, please use AX_LUA_HEADERS instead]])
|
||||
])
|
||||
|
||||
|
||||
dnl =========================================================================
|
||||
dnl AX_LUA_LIBS([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
dnl =========================================================================
|
||||
AC_DEFUN([AX_LUA_LIBS],
|
||||
[
|
||||
dnl TODO Should this macro also check various -L flags?
|
||||
|
||||
dnl Check for LUA_VERSION.
|
||||
AC_MSG_CHECKING([if LUA_VERSION is defined])
|
||||
AS_IF([test "x$LUA_VERSION" != 'x'],
|
||||
[AC_MSG_RESULT([yes])],
|
||||
[ AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([cannot check Lua libs without knowing LUA_VERSION])
|
||||
])
|
||||
|
||||
dnl Make LUA_LIB a precious variable.
|
||||
AC_ARG_VAR([LUA_LIB], [The Lua library, e.g. -llua5.1])
|
||||
|
||||
AS_IF([test "x$LUA_LIB" != 'x'],
|
||||
[ dnl Check that LUA_LIBS works.
|
||||
_ax_lua_saved_libs=$LIBS
|
||||
LIBS="$LIBS $LUA_LIB"
|
||||
AC_SEARCH_LIBS([lua_load], [],
|
||||
[_ax_found_lua_libs='yes'],
|
||||
[_ax_found_lua_libs='no'])
|
||||
LIBS=$_ax_lua_saved_libs
|
||||
|
||||
dnl Check the result.
|
||||
AS_IF([test "x$_ax_found_lua_libs" != 'xyes'],
|
||||
[AC_MSG_ERROR([cannot find libs for specified LUA_LIB])])
|
||||
],
|
||||
[ dnl First search for extra libs.
|
||||
_ax_lua_extra_libs=''
|
||||
|
||||
_ax_lua_saved_libs=$LIBS
|
||||
LIBS="$LIBS $LUA_LIB"
|
||||
AC_SEARCH_LIBS([exp], [m])
|
||||
AC_SEARCH_LIBS([dlopen], [dl])
|
||||
LIBS=$_ax_lua_saved_libs
|
||||
|
||||
AS_IF([test "x$ac_cv_search_exp" != 'xno' &&
|
||||
test "x$ac_cv_search_exp" != 'xnone required'],
|
||||
[_ax_lua_extra_libs="$_ax_lua_extra_libs $ac_cv_search_exp"])
|
||||
|
||||
AS_IF([test "x$ac_cv_search_dlopen" != 'xno' &&
|
||||
test "x$ac_cv_search_dlopen" != 'xnone required'],
|
||||
[_ax_lua_extra_libs="$_ax_lua_extra_libs $ac_cv_search_dlopen"])
|
||||
|
||||
dnl Try to find the Lua libs.
|
||||
_ax_lua_saved_libs=$LIBS
|
||||
LIBS="$LIBS $LUA_LIB"
|
||||
AC_SEARCH_LIBS([lua_load],
|
||||
[ lua$LUA_VERSION \
|
||||
lua$LUA_SHORT_VERSION \
|
||||
lua-$LUA_VERSION \
|
||||
lua-$LUA_SHORT_VERSION \
|
||||
:liblua-$LUA_VERSION.so.0 \
|
||||
:liblua-$LUA_SHORT_VERSION.so.0 \
|
||||
lua \
|
||||
],
|
||||
[_ax_found_lua_libs='yes'],
|
||||
[_ax_found_lua_libs='no'],
|
||||
[$_ax_lua_extra_libs])
|
||||
LIBS=$_ax_lua_saved_libs
|
||||
|
||||
AS_IF([test "x$ac_cv_search_lua_load" != 'xno' &&
|
||||
test "x$ac_cv_search_lua_load" != 'xnone required'],
|
||||
[LUA_LIB="$ac_cv_search_lua_load $_ax_lua_extra_libs"])
|
||||
])
|
||||
|
||||
dnl Test the result and run user code.
|
||||
AS_IF([test "x$_ax_found_lua_libs" = 'xyes'], [$1],
|
||||
[m4_default([$2], [AC_MSG_ERROR([cannot find Lua libs])])])
|
||||
])
|
||||
|
||||
|
||||
dnl =========================================================================
|
||||
dnl AX_LUA_READLINE([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
dnl =========================================================================
|
||||
AC_DEFUN([AX_LUA_READLINE],
|
||||
[
|
||||
AX_LIB_READLINE
|
||||
AS_IF([test "x$ac_cv_header_readline_readline_h" != 'x' &&
|
||||
test "x$ac_cv_header_readline_history_h" != 'x'],
|
||||
[ LUA_LIBS_CFLAGS="-DLUA_USE_READLINE $LUA_LIBS_CFLAGS"
|
||||
$1
|
||||
],
|
||||
[$2])
|
||||
])
|
||||
Executable → Regular
@@ -0,0 +1,37 @@
|
||||
# ===========================================================================
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_require_defined.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_REQUIRE_DEFINED(MACRO)
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# AX_REQUIRE_DEFINED is a simple helper for making sure other macros have
|
||||
# been defined and thus are available for use. This avoids random issues
|
||||
# where a macro isn't expanded. Instead the configure script emits a
|
||||
# non-fatal:
|
||||
#
|
||||
# ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found
|
||||
#
|
||||
# It's like AC_REQUIRE except it doesn't expand the required macro.
|
||||
#
|
||||
# Here's an example:
|
||||
#
|
||||
# AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2014 Mike Frysinger <vapier@gentoo.org>
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification, are
|
||||
# permitted in any medium without royalty provided the copyright notice
|
||||
# and this notice are preserved. This file is offered as-is, without any
|
||||
# warranty.
|
||||
|
||||
#serial 2
|
||||
|
||||
AC_DEFUN([AX_REQUIRE_DEFINED], [dnl
|
||||
m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])])
|
||||
])dnl AX_REQUIRE_DEFINED
|
||||
Executable → Regular
+32
-1
@@ -400,7 +400,7 @@ AC_DEFUN([TORRENT_WITH_XMLRPC_C], [
|
||||
else
|
||||
xmlrpc_cc_prg="$withval"
|
||||
fi
|
||||
|
||||
|
||||
if eval $xmlrpc_cc_prg --version 2>/dev/null >/dev/null; then
|
||||
CXXFLAGS="$CXXFLAGS `$xmlrpc_cc_prg --cflags server-util`"
|
||||
LIBS="$LIBS `$xmlrpc_cc_prg server-util --libs`"
|
||||
@@ -426,6 +426,37 @@ AC_DEFUN([TORRENT_WITH_XMLRPC_C], [
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([TORRENT_WITH_TINYXML2], [
|
||||
AC_MSG_CHECKING(for tinyxml2)
|
||||
|
||||
AC_ARG_WITH(xmlrpc-tinyxml2,
|
||||
AS_HELP_STRING([--with-xmlrpc-tinyxml2],[enable XMLRPC support via tinyxml2]),
|
||||
[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_XMLRPC_TINYXML2, 1, Support for XMLRPC via tinyxml2.)
|
||||
],[
|
||||
AC_MSG_RESULT(ignored)
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([TORRENT_WITH_LUA], [
|
||||
AC_ARG_WITH(lua,
|
||||
AS_HELP_STRING([--with-lua],[enable LUA support]),
|
||||
[
|
||||
if test "$withval" = "no"; then
|
||||
AC_MSG_RESULT(no)
|
||||
else
|
||||
AX_PROG_LUA
|
||||
AX_LUA_LIBS
|
||||
AX_LUA_HEADERS
|
||||
AC_DEFINE(HAVE_LUA, 1, Use LUA.)
|
||||
LIBS="$LIBS $LUA_LIB"
|
||||
CXXFLAGS="$CXXFLAGS $LUA_INCLUDE"
|
||||
fi
|
||||
],[
|
||||
AC_MSG_RESULT(ignored)
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([TORRENT_WITH_INOTIFY], [
|
||||
AC_LANG_PUSH(C++)
|
||||
|
||||
+14
-1
@@ -13,7 +13,7 @@ AC_DEFUN([TORRENT_WITH_SYSROOT], [
|
||||
AC_MSG_ERROR(The sysroot option must point to a directory, like f.ex "/Developer/SDKs/MacOSX10.4u.sdk".)
|
||||
else
|
||||
AC_MSG_RESULT($withval)
|
||||
|
||||
|
||||
CXXFLAGS="$CXXFLAGS -isysroot $withval"
|
||||
LDFLAGS="$LDFLAGS -Wl,-syslibroot,$withval"
|
||||
fi
|
||||
@@ -21,6 +21,19 @@ AC_DEFUN([TORRENT_WITH_SYSROOT], [
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN([TORRENT_REMOVE_UNWANTED],
|
||||
[
|
||||
values_to_check=`for i in $2; do echo $i; done`
|
||||
unwanted_values=`for i in $3; do echo $i; done`
|
||||
if test -z "${unwanted_values}"; then
|
||||
$1="$2"
|
||||
else
|
||||
result=`echo "${values_to_check}" | $GREP -Fvx -- "${unwanted_values}" | $GREP -v '^$'`
|
||||
$1=${result//$'\n'/ }
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN([TORRENT_ENABLE_ARCH], [
|
||||
AC_ARG_ENABLE(arch,
|
||||
AS_HELP_STRING([--enable-arch=ARCH],
|
||||
|
||||
@@ -37,6 +37,7 @@ libsub_root_a_SOURCES = \
|
||||
display/attributes.h \
|
||||
display/canvas.cc \
|
||||
display/canvas.h \
|
||||
display/color_map.h \
|
||||
display/frame.cc \
|
||||
display/frame.h \
|
||||
display/manager.cc \
|
||||
@@ -107,6 +108,12 @@ libsub_root_a_SOURCES = \
|
||||
rpc/exec_file.h \
|
||||
rpc/fixed_key.h \
|
||||
rpc/ip_table_list.h \
|
||||
rpc/lua.h \
|
||||
rpc/lua.cc \
|
||||
rpc/jsonrpc.cc \
|
||||
rpc/jsonrpc.h \
|
||||
rpc/rpc_manager.cc \
|
||||
rpc/rpc_manager.h \
|
||||
rpc/object_storage.cc \
|
||||
rpc/object_storage.h \
|
||||
rpc/parse.cc \
|
||||
@@ -121,6 +128,11 @@ libsub_root_a_SOURCES = \
|
||||
rpc/scgi_task.h \
|
||||
rpc/xmlrpc.h \
|
||||
rpc/xmlrpc.cc \
|
||||
rpc/xmlrpc_c.cc \
|
||||
rpc/xmlrpc_tinyxml2.cc \
|
||||
rpc/tinyxml2/tinyxml2.h \
|
||||
rpc/tinyxml2/tinyxml2.cc \
|
||||
rpc/nlohmann/json.h \
|
||||
\
|
||||
ui/download.cc \
|
||||
ui/download.h \
|
||||
@@ -151,10 +163,13 @@ libsub_root_a_SOURCES = \
|
||||
ui/root.cc \
|
||||
ui/root.h \
|
||||
\
|
||||
utils/base64.cc \
|
||||
utils/base64.h \
|
||||
utils/directory.cc \
|
||||
utils/directory.h \
|
||||
utils/file_status_cache.cc \
|
||||
utils/file_status_cache.h \
|
||||
utils/functional.h \
|
||||
utils/list_focus.h \
|
||||
utils/lockfile.cc \
|
||||
utils/lockfile.h \
|
||||
@@ -190,4 +205,5 @@ libsub_root_a_SOURCES = \
|
||||
thread_worker.cc \
|
||||
thread_worker.h
|
||||
|
||||
|
||||
AM_CPPFLAGS = -I$(srcdir) -I$(top_srcdir)
|
||||
|
||||
+30
-70
@@ -1,44 +1,9 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <functional>
|
||||
#include <unistd.h>
|
||||
#include <cstdio>
|
||||
#include <functional>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <rak/file_stat.h>
|
||||
#include <rak/error_number.h>
|
||||
#include <rak/path.h>
|
||||
@@ -47,14 +12,16 @@
|
||||
#include <rak/regex.h>
|
||||
#include <torrent/rate.h>
|
||||
#include <torrent/throttle.h>
|
||||
#include <torrent/tracker.h>
|
||||
#include <torrent/tracker_controller.h>
|
||||
#include <torrent/tracker_list.h>
|
||||
#include <torrent/tracker/tracker.h>
|
||||
#include <torrent/connection_manager.h>
|
||||
#include <torrent/data/download_data.h>
|
||||
#include <torrent/data/file.h>
|
||||
#include <torrent/data/file_list.h>
|
||||
#include <torrent/download/resource_manager.h>
|
||||
#include <torrent/net/resolver.h>
|
||||
#include <torrent/net/types.h>
|
||||
#include <torrent/peer/connection_list.h>
|
||||
#include <torrent/peer/peer_list.h>
|
||||
#include <torrent/utils/log.h>
|
||||
@@ -104,7 +71,7 @@ apply_d_change_link(core::Download* download, const torrent::Object::list_type&
|
||||
const std::string& type = (itr++)->as_string();
|
||||
const std::string& prefix = (itr++)->as_string();
|
||||
const std::string& postfix = (itr++)->as_string();
|
||||
|
||||
|
||||
if (type.empty())
|
||||
throw torrent::input_error("Invalid arguments.");
|
||||
|
||||
@@ -319,21 +286,6 @@ retrieve_d_bitfield(core::Download* download) {
|
||||
return torrent::Object(rak::transform_hex(bitField->begin(), bitField->end()));
|
||||
}
|
||||
|
||||
struct call_add_d_peer_t {
|
||||
call_add_d_peer_t(core::Download* d, int port) : m_download(d), m_port(port) { }
|
||||
|
||||
void operator() (const sockaddr* sa, int err) {
|
||||
if (sa == NULL) {
|
||||
lt_log_print(torrent::LOG_TORRENT_WARN, "could not resolve hostname for added peer");
|
||||
} else {
|
||||
m_download->download()->add_peer(sa, m_port);
|
||||
}
|
||||
}
|
||||
|
||||
core::Download* m_download;
|
||||
int m_port;
|
||||
};
|
||||
|
||||
void
|
||||
apply_d_add_peer(core::Download* download, const std::string& arg) {
|
||||
int port, ret;
|
||||
@@ -356,7 +308,15 @@ apply_d_add_peer(core::Download* download, const std::string& arg) {
|
||||
if (port < 1 || port > 65535)
|
||||
throw torrent::input_error("Invalid port number.");
|
||||
|
||||
torrent::connection_manager()->resolver()(host, (int)rak::socket_address::pf_unspec, SOCK_STREAM, call_add_d_peer_t(download, port));
|
||||
// Currently discarding SOCK_STREAM.
|
||||
torrent::main_thread()->resolver()->resolve_preferred(NULL, host, AF_UNSPEC, AF_INET, [download, port](torrent::c_sa_shared_ptr sa, int err) {
|
||||
if (sa == nullptr) {
|
||||
lt_log_print(torrent::LOG_TORRENT_WARN, "could not resolve hostname for added peer: %s", gai_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
download->download()->add_peer(sa.get(), port);
|
||||
});
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
@@ -410,7 +370,7 @@ f_multicall(core::Download* download, const torrent::Object::list_type& args) {
|
||||
|
||||
for (torrent::Object::list_const_iterator cItr = ++args.begin(); cItr != args.end(); cItr++) {
|
||||
const std::string& cmd = cItr->as_string();
|
||||
row.push_back(rpc::parse_command(rpc::make_target(*itr), cmd.c_str(), cmd.c_str() + cmd.size()).first);
|
||||
row.push_back(rpc::parse_command(rpc::make_target(itr->get()), cmd.c_str(), cmd.c_str() + cmd.size()).first);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -435,9 +395,9 @@ t_multicall(core::Download* download, const torrent::Object::list_type& args) {
|
||||
|
||||
for (torrent::Object::list_const_iterator cItr = ++args.begin(); cItr != args.end(); cItr++) {
|
||||
const std::string& cmd = cItr->as_string();
|
||||
torrent::Tracker* t = download->tracker_list()->at(itr);
|
||||
auto t = download->tracker_list()->at(itr);
|
||||
|
||||
row.push_back(rpc::parse_command(rpc::make_target(t), cmd.c_str(), cmd.c_str() + cmd.size()).first);
|
||||
row.push_back(rpc::parse_command(rpc::make_target(&t), cmd.c_str(), cmd.c_str() + cmd.size()).first);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -593,8 +553,7 @@ d_list_push_back_unique(core::Download* download, const torrent::Object& rawArgs
|
||||
const torrent::Object& args = (rawArgs.is_list() && !rawArgs.as_list().empty()) ? rawArgs.as_list().front() : rawArgs;
|
||||
torrent::Object::list_type& list = download_get_variable(download, first_key, second_key).as_list();
|
||||
|
||||
if (std::find_if(list.begin(), list.end(),
|
||||
rak::bind1st(std::ptr_fun(&torrent::object_equal), args)) == list.end())
|
||||
if (std::find_if(list.begin(), list.end(), [args](const torrent::Object& obj) { return torrent::object_equal(obj, args); }) == list.end())
|
||||
list.push_back(rawArgs);
|
||||
|
||||
return torrent::Object();
|
||||
@@ -605,8 +564,7 @@ d_list_has(core::Download* download, const torrent::Object& rawArgs, const char*
|
||||
const torrent::Object& args = (rawArgs.is_list() && !rawArgs.as_list().empty()) ? rawArgs.as_list().front() : rawArgs;
|
||||
torrent::Object::list_type& list = download_get_variable(download, first_key, second_key).as_list();
|
||||
|
||||
return (int64_t)(std::find_if(list.begin(), list.end(),
|
||||
rak::bind1st(std::ptr_fun(&torrent::object_equal), args)) != list.end());
|
||||
return (int64_t)(std::find_if(list.begin(), list.end(), [args](const torrent::Object& obj) { return torrent::object_equal(obj, args); }) != list.end());
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
@@ -614,7 +572,7 @@ d_list_remove(core::Download* download, const torrent::Object& rawArgs, const ch
|
||||
const torrent::Object& args = (rawArgs.is_list() && !rawArgs.as_list().empty()) ? rawArgs.as_list().front() : rawArgs;
|
||||
torrent::Object::list_type& list = download_get_variable(download, first_key, second_key).as_list();
|
||||
|
||||
list.erase(std::remove_if(list.begin(), list.end(), rak::bind1st(std::ptr_fun(&torrent::object_equal), args)), list.end());
|
||||
list.erase(std::remove_if(list.begin(), list.end(), [args](const torrent::Object& obj) { return torrent::object_equal(obj, args); }), list.end());
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
@@ -629,7 +587,6 @@ d_list_remove(core::Download* download, const torrent::Object& rawArgs, const ch
|
||||
#define CMD2_BIND_FL std::bind(&core::Download::file_list, std::placeholders::_1)
|
||||
#define CMD2_BIND_PL std::bind(&core::Download::c_peer_list, std::placeholders::_1)
|
||||
#define CMD2_BIND_TL std::bind(&core::Download::tracker_list, std::placeholders::_1)
|
||||
#define CMD2_BIND_TC std::bind(&core::Download::tracker_controller, std::placeholders::_1)
|
||||
|
||||
#define CMD2_BIND_INFO std::bind(&core::Download::info, std::placeholders::_1)
|
||||
#define CMD2_BIND_DATA std::bind(&core::Download::data, std::placeholders::_1)
|
||||
@@ -873,8 +830,8 @@ initialize_command_download() {
|
||||
CMD2_DL ("d.wanted_chunks", CMD2_ON_DATA(wanted_chunks));
|
||||
|
||||
// Do not exposre d.tracker_announce.force to regular users.
|
||||
CMD2_DL_V ("d.tracker_announce", std::bind(&torrent::Download::manual_request, CMD2_BIND_DL, false));
|
||||
CMD2_DL_V ("d.tracker_announce.force", std::bind(&torrent::Download::manual_request, CMD2_BIND_DL, true));
|
||||
CMD2_DL_V ("d.tracker_announce", std::bind(&torrent::Download::manual_request, CMD2_BIND_DL, false));
|
||||
CMD2_DL_V ("d.tracker_announce.force", std::bind(&torrent::Download::manual_request, CMD2_BIND_DL, true));
|
||||
|
||||
CMD2_DL ("d.tracker_numwant", std::bind(&torrent::TrackerList::numwant, CMD2_BIND_TL));
|
||||
CMD2_DL_VALUE_V ("d.tracker_numwant.set", std::bind(&torrent::TrackerList::set_numwant, CMD2_BIND_TL, std::placeholders::_2));
|
||||
@@ -882,8 +839,11 @@ initialize_command_download() {
|
||||
CMD2_DL ("d.tracker_focus", std::bind(&core::Download::tracker_list_size, std::placeholders::_1));
|
||||
CMD2_DL ("d.tracker_size", std::bind(&core::Download::tracker_list_size, std::placeholders::_1));
|
||||
|
||||
CMD2_DL_LIST ("d.tracker.insert", std::bind(&download_tracker_insert, std::placeholders::_1, std::placeholders::_2));
|
||||
CMD2_DL_VALUE_V ("d.tracker.send_scrape", std::bind(&torrent::TrackerController::scrape_request, CMD2_BIND_TC, std::placeholders::_2));
|
||||
CMD2_DL ("d.tracker.has_active", std::bind(&torrent::TrackerList::has_active, CMD2_BIND_TL));
|
||||
CMD2_DL ("d.tracker.has_active_not_scrape", std::bind(&torrent::TrackerList::has_active_not_scrape, CMD2_BIND_TL));
|
||||
CMD2_DL ("d.tracker.has_usable", std::bind(&torrent::TrackerList::has_usable, CMD2_BIND_TL));
|
||||
CMD2_DL_LIST ("d.tracker.insert", std::bind(&download_tracker_insert, std::placeholders::_1, std::placeholders::_2));
|
||||
CMD2_DL_VALUE_V ("d.tracker.send_scrape", [](auto download, uint64_t arg) { download->tracker_controller().scrape_request(arg); });
|
||||
|
||||
CMD2_DL ("d.directory", CMD2_ON_FL(root_dir));
|
||||
CMD2_DL_STRING_V("d.directory.set", std::bind(&apply_d_directory, std::placeholders::_1, std::placeholders::_2));
|
||||
@@ -905,7 +865,7 @@ initialize_command_download() {
|
||||
// CG_GROUP_INDEX()));
|
||||
|
||||
CMD2_DL ("d.group", std::bind(&cg_d_group, std::placeholders::_1));
|
||||
CMD2_DL ("d.group.name", std::bind(&cg_d_group, std::placeholders::_1));
|
||||
CMD2_DL ("d.group.name", std::bind(&cg_d_group_name, std::placeholders::_1));
|
||||
CMD2_DL_V ("d.group.set", std::bind(&cg_d_group_set, std::placeholders::_1, std::placeholders::_2));
|
||||
|
||||
CMD2_DL_LIST ("f.multicall", std::bind(&f_multicall, std::placeholders::_1, std::placeholders::_2));
|
||||
|
||||
+105
-85
@@ -5,12 +5,12 @@
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
@@ -40,25 +40,24 @@
|
||||
#include <torrent/utils/log.h>
|
||||
#include <torrent/utils/option_strings.h>
|
||||
|
||||
#include "globals.h"
|
||||
#include "control.h"
|
||||
#include "command_helpers.h"
|
||||
#include "control.h"
|
||||
#include "globals.h"
|
||||
#include "rpc/parse.h"
|
||||
#include "rpc/parse_options.h"
|
||||
|
||||
static std::vector<std::pair<const char*, int>> object_storage_flags = {
|
||||
{ "multi", rpc::object_storage::flag_multi_type },
|
||||
{ "simple", rpc::object_storage::flag_function_type },
|
||||
{ "value", rpc::object_storage::flag_value_type },
|
||||
{ "bool", rpc::object_storage::flag_bool_type },
|
||||
{ "string", rpc::object_storage::flag_string_type },
|
||||
{ "list", rpc::object_storage::flag_list_type },
|
||||
{"multi", rpc::object_storage::flag_multi_type},
|
||||
{"simple", rpc::object_storage::flag_function_type},
|
||||
{"value", rpc::object_storage::flag_value_type},
|
||||
{"bool", rpc::object_storage::flag_bool_type},
|
||||
{"string", rpc::object_storage::flag_string_type},
|
||||
{"list", rpc::object_storage::flag_list_type},
|
||||
|
||||
{ "static", rpc::object_storage::flag_static },
|
||||
{ "private", rpc::object_storage::flag_private },
|
||||
{ "const", rpc::object_storage::flag_constant },
|
||||
{ "rlookup", rpc::object_storage::flag_rlookup }
|
||||
};
|
||||
{"static", rpc::object_storage::flag_static},
|
||||
{"private", rpc::object_storage::flag_private},
|
||||
{"const", rpc::object_storage::flag_constant},
|
||||
{"rlookup", rpc::object_storage::flag_rlookup}};
|
||||
|
||||
static int
|
||||
object_storage_parse_flag(const std::string& flag) {
|
||||
@@ -109,7 +108,7 @@ system_method_generate_command2(torrent::Object* object, torrent::Object::list_c
|
||||
if (first + 1 == last) {
|
||||
if (!first->is_dict_key())
|
||||
throw torrent::input_error("New command of wrong type.");
|
||||
|
||||
|
||||
*object = *first;
|
||||
|
||||
uint32_t flags = object->flags() & torrent::Object::mask_function;
|
||||
@@ -122,9 +121,9 @@ system_method_generate_command2(torrent::Object* object, torrent::Object::list_c
|
||||
while (first != last) {
|
||||
if (!first->is_dict_key())
|
||||
throw torrent::input_error("New command of wrong type.");
|
||||
|
||||
|
||||
object->as_list().push_back(*first++);
|
||||
|
||||
|
||||
uint32_t flags = object->as_list().back().flags() & torrent::Object::mask_function;
|
||||
object->as_list().back().unset_flags(torrent::Object::mask_function);
|
||||
object->as_list().back().set_flags((flags >> 1) & torrent::Object::mask_function);
|
||||
@@ -134,20 +133,32 @@ system_method_generate_command2(torrent::Object* object, torrent::Object::list_c
|
||||
|
||||
// torrent::Object
|
||||
// system_method_insert_function(const torrent::Object::list_type& args, int flags) {
|
||||
|
||||
|
||||
// }
|
||||
|
||||
// This is only used by tinyxml2, xmlrpc-c intercepts the call internally
|
||||
torrent::Object
|
||||
system_listMethods() {
|
||||
torrent::Object resultRaw = torrent::Object::create_list();
|
||||
torrent::Object::list_type& result = resultRaw.as_list();
|
||||
result.push_back("system.multicall"); // Handled directly by the XMLRPC code
|
||||
for (auto itr : rpc::commands) {
|
||||
result.push_back(itr.first);
|
||||
}
|
||||
return resultRaw;
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
system_method_insert_object(const torrent::Object::list_type& args, int flags) {
|
||||
if (args.empty())
|
||||
throw torrent::input_error("Invalid argument count.");
|
||||
|
||||
torrent::Object::list_const_iterator itrArgs = args.begin();
|
||||
const std::string& rawKey = (itrArgs++)->as_string();
|
||||
const std::string& raw_key = (itrArgs++)->as_string();
|
||||
|
||||
if (rawKey.empty() ||
|
||||
control->object_storage()->find_raw_string(torrent::raw_string::from_string(rawKey)) != control->object_storage()->end() ||
|
||||
rpc::commands.has(rawKey) || rpc::commands.has(rawKey + ".set"))
|
||||
if (raw_key.empty() ||
|
||||
control->object_storage()->find_raw_string(torrent::raw_string::from_string(raw_key)) != control->object_storage()->end() ||
|
||||
rpc::commands.has(raw_key) || rpc::commands.has(raw_key + ".set"))
|
||||
throw torrent::input_error("Invalid key.");
|
||||
|
||||
torrent::Object value;
|
||||
@@ -171,90 +182,101 @@ system_method_insert_object(const torrent::Object::list_type& args, int flags) {
|
||||
throw torrent::input_error("Invalid type.");
|
||||
}
|
||||
|
||||
// We must initialize this varriable to prevent a critical memory leak
|
||||
int cmd_flags = rpc::CommandMap::flag_delete_key;
|
||||
int cmd_flags = 0;
|
||||
|
||||
if (!(flags & rpc::object_storage::flag_static))
|
||||
cmd_flags |= rpc::CommandMap::flag_modifiable;
|
||||
if (!(flags & rpc::object_storage::flag_private))
|
||||
cmd_flags |= rpc::CommandMap::flag_public_xmlrpc;
|
||||
cmd_flags |= rpc::CommandMap::flag_public_rpc;
|
||||
|
||||
if ((flags & rpc::object_storage::mask_type) == rpc::object_storage::flag_list_type) {
|
||||
torrent::Object valueList = torrent::Object::create_list();
|
||||
torrent::Object valueList = torrent::Object::create_list();
|
||||
torrent::Object::list_type& valueListType = valueList.as_list();
|
||||
|
||||
if ((itrArgs)->is_list())
|
||||
valueListType = (itrArgs)->as_list();
|
||||
|
||||
control->object_storage()->insert_str(rawKey, valueList, flags);
|
||||
control->object_storage()->insert_str(raw_key, valueList, flags);
|
||||
} else {
|
||||
control->object_storage()->insert_str(rawKey, value, flags);
|
||||
control->object_storage()->insert_str(raw_key, value, flags);
|
||||
}
|
||||
|
||||
if ((flags & rpc::object_storage::mask_type) == rpc::object_storage::flag_function_type ||
|
||||
(flags & rpc::object_storage::mask_type) == rpc::object_storage::flag_multi_type) {
|
||||
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call<rpc::target_type> >::type>
|
||||
(create_new_key(rawKey),
|
||||
std::bind(&rpc::object_storage::call_function_str, control->object_storage(),
|
||||
rawKey, std::placeholders::_1, std::placeholders::_2),
|
||||
&rpc::command_base_call<rpc::target_type>,
|
||||
cmd_flags, NULL, NULL);
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call<rpc::target_type>>::type>(
|
||||
raw_key,
|
||||
std::bind(&rpc::object_storage::call_function_str, control->object_storage(), raw_key, std::placeholders::_1, std::placeholders::_2),
|
||||
&rpc::command_base_call<rpc::target_type>,
|
||||
cmd_flags,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
} else {
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call<rpc::target_type> >::type>
|
||||
(create_new_key(rawKey),
|
||||
std::bind(&rpc::object_storage::get_str, control->object_storage(), rawKey),
|
||||
&rpc::command_base_call<rpc::target_type>,
|
||||
cmd_flags, NULL, NULL);
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call<rpc::target_type>>::type>(
|
||||
raw_key,
|
||||
std::bind(&rpc::object_storage::get_str, control->object_storage(), raw_key),
|
||||
&rpc::command_base_call<rpc::target_type>,
|
||||
cmd_flags,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
// Not the right argument.
|
||||
// if (flags & rpc::object_storage::flag_rlookup) {
|
||||
// rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_string<rpc::target_type> >::type>
|
||||
// (create_new_key<9>(rawKey, ".rlookup"),
|
||||
// std::bind(&rpc::object_storage::rlookup_obj_list, control->object_storage(), rawKey),
|
||||
// (create_new_key<9>(raw_key, ".rlookup"),
|
||||
// std::bind(&rpc::object_storage::rlookup_obj_list, control->object_storage(), raw_key),
|
||||
// &rpc::command_base_call_string<rpc::target_type>,
|
||||
// cmd_flags, NULL, NULL);
|
||||
// }
|
||||
|
||||
// TODO: Next... Make test class for this.
|
||||
|
||||
// // Ehm... no proper handling if these throw.
|
||||
// // Ehm... no proper handling if these throw.
|
||||
|
||||
if (!(flags & rpc::object_storage::flag_constant)) {
|
||||
switch (flags & rpc::object_storage::mask_type) {
|
||||
case rpc::object_storage::flag_bool_type:
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_value<rpc::target_type> >::type>
|
||||
(create_new_key<5>(rawKey, ".set"),
|
||||
std::bind(&rpc::object_storage::set_str_bool, control->object_storage(), rawKey, std::placeholders::_2),
|
||||
&rpc::command_base_call_value<rpc::target_type>,
|
||||
cmd_flags, NULL, NULL);
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_value<rpc::target_type>>::type>(
|
||||
raw_key + ".set",
|
||||
std::bind(&rpc::object_storage::set_str_bool, control->object_storage(), raw_key, std::placeholders::_2),
|
||||
&rpc::command_base_call_value<rpc::target_type>,
|
||||
cmd_flags,
|
||||
NULL,
|
||||
NULL);
|
||||
break;
|
||||
case rpc::object_storage::flag_value_type:
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_value<rpc::target_type> >::type>
|
||||
(create_new_key<5>(rawKey, ".set"),
|
||||
std::bind(&rpc::object_storage::set_str_value, control->object_storage(), rawKey, std::placeholders::_2),
|
||||
&rpc::command_base_call_value<rpc::target_type>,
|
||||
cmd_flags, NULL, NULL);
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_value<rpc::target_type>>::type>(
|
||||
raw_key + ".set",
|
||||
std::bind(&rpc::object_storage::set_str_value, control->object_storage(), raw_key, std::placeholders::_2),
|
||||
&rpc::command_base_call_value<rpc::target_type>,
|
||||
cmd_flags,
|
||||
NULL,
|
||||
NULL);
|
||||
break;
|
||||
case rpc::object_storage::flag_string_type:
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_string<rpc::target_type> >::type>
|
||||
(create_new_key<5>(rawKey, ".set"),
|
||||
std::bind(&rpc::object_storage::set_str_string, control->object_storage(), rawKey, std::placeholders::_2),
|
||||
&rpc::command_base_call_string<rpc::target_type>,
|
||||
cmd_flags, NULL, NULL);
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_string<rpc::target_type>>::type>(
|
||||
raw_key + ".set",
|
||||
std::bind(&rpc::object_storage::set_str_string, control->object_storage(), raw_key, std::placeholders::_2),
|
||||
&rpc::command_base_call_string<rpc::target_type>,
|
||||
cmd_flags,
|
||||
NULL,
|
||||
NULL);
|
||||
break;
|
||||
case rpc::object_storage::flag_list_type:
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_list<rpc::target_type> >::type>
|
||||
(create_new_key<5>(rawKey, ".set"),
|
||||
std::bind(&rpc::object_storage::set_str_list, control->object_storage(), rawKey, std::placeholders::_2),
|
||||
&rpc::command_base_call_list<rpc::target_type>,
|
||||
cmd_flags, NULL, NULL);
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_list<rpc::target_type>>::type>(
|
||||
raw_key + ".set",
|
||||
std::bind(&rpc::object_storage::set_str_list, control->object_storage(), raw_key, std::placeholders::_2),
|
||||
&rpc::command_base_call_list<rpc::target_type>,
|
||||
cmd_flags,
|
||||
NULL,
|
||||
NULL);
|
||||
break;
|
||||
case rpc::object_storage::flag_function_type:
|
||||
case rpc::object_storage::flag_multi_type:
|
||||
default: break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,22 +304,15 @@ system_method_insert(const torrent::Object::list_type& args) {
|
||||
throw torrent::input_error("Invalid argument count.");
|
||||
|
||||
torrent::Object::list_const_iterator itrArgs = args.begin();
|
||||
const std::string& rawKey = (itrArgs++)->as_string();
|
||||
const std::string& raw_key = (itrArgs++)->as_string();
|
||||
|
||||
if (rawKey.empty() || rpc::commands.has(rawKey))
|
||||
if (raw_key.empty() || rpc::commands.has(raw_key))
|
||||
throw torrent::input_error("Invalid key.");
|
||||
|
||||
int flags = rpc::CommandMap::flag_delete_key | rpc::CommandMap::flag_modifiable | rpc::CommandMap::flag_public_xmlrpc;
|
||||
int new_flags = rpc::parse_option_flags(itrArgs->as_string(), std::bind(&object_storage_parse_flag, std::placeholders::_1));
|
||||
|
||||
if ((new_flags & rpc::object_storage::flag_private))
|
||||
flags &= ~rpc::CommandMap::flag_public_xmlrpc;
|
||||
|
||||
if ((new_flags & rpc::object_storage::flag_constant))
|
||||
flags &= ~rpc::CommandMap::flag_modifiable;
|
||||
|
||||
torrent::Object::list_type new_args;
|
||||
new_args.push_back(rawKey);
|
||||
new_args.push_back(raw_key);
|
||||
|
||||
if ((new_flags & rpc::object_storage::flag_function_type) ||
|
||||
(new_flags & rpc::object_storage::flag_multi_type)) {
|
||||
@@ -345,8 +360,7 @@ system_method_redirect(const torrent::Object::list_type& args) {
|
||||
std::string new_key = torrent::object_create_string(args.front());
|
||||
std::string dest_key = torrent::object_create_string(args.back());
|
||||
|
||||
rpc::commands.create_redirect(create_new_key(new_key), create_new_key(dest_key),
|
||||
rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_delete_key | rpc::CommandMap::flag_modifiable);
|
||||
rpc::commands.create_redirect(new_key, dest_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_modifiable);
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
@@ -372,9 +386,9 @@ system_method_has_key(const torrent::Object::list_type& args) {
|
||||
throw torrent::input_error("Invalid argument count.");
|
||||
|
||||
torrent::Object::list_const_iterator itrArgs = args.begin();
|
||||
const std::string& key = (itrArgs++)->as_string();
|
||||
const std::string& cmd_key = (itrArgs++)->as_string();
|
||||
|
||||
const std::string& key = (itrArgs++)->as_string();
|
||||
const std::string& cmd_key = (itrArgs++)->as_string();
|
||||
|
||||
return control->object_storage()->has_str_multi_key(key, cmd_key);
|
||||
}
|
||||
|
||||
@@ -384,9 +398,9 @@ system_method_set_key(const torrent::Object::list_type& args) {
|
||||
throw torrent::input_error("Invalid argument count.");
|
||||
|
||||
torrent::Object::list_const_iterator itrArgs = args.begin();
|
||||
const std::string& key = (itrArgs++)->as_string();
|
||||
const std::string& cmd_key = (itrArgs++)->as_string();
|
||||
|
||||
const std::string& key = (itrArgs++)->as_string();
|
||||
const std::string& cmd_key = (itrArgs++)->as_string();
|
||||
|
||||
if (itrArgs == args.end()) {
|
||||
control->object_storage()->erase_str_multi_key(key, cmd_key);
|
||||
return torrent::Object();
|
||||
@@ -403,9 +417,9 @@ system_method_set_key(const torrent::Object::list_type& args) {
|
||||
torrent::Object
|
||||
system_method_list_keys(const torrent::Object::string_type& args) {
|
||||
const torrent::Object::map_type& multi_cmd = control->object_storage()->get_str(args).as_map();
|
||||
|
||||
torrent::Object rawResult = torrent::Object::create_list();
|
||||
torrent::Object::list_type& result = rawResult.as_list();
|
||||
|
||||
torrent::Object rawResult = torrent::Object::create_list();
|
||||
torrent::Object::list_type& result = rawResult.as_list();
|
||||
|
||||
for (torrent::Object::map_const_iterator itr = multi_cmd.begin(), last = multi_cmd.end(); itr != last; itr++)
|
||||
result.push_back(itr->first);
|
||||
@@ -428,6 +442,11 @@ cmd_catch(rpc::target_type target, const torrent::Object& args) {
|
||||
|
||||
void
|
||||
initialize_command_dynamic() {
|
||||
// clang-format off
|
||||
#ifdef HAVE_XMLRPC_TINYXML2
|
||||
CMD2_ANY ("system.listMethods", std::bind(&system_listMethods)); // only used by tinyxml2
|
||||
#endif
|
||||
|
||||
CMD2_VAR_BOOL ("method.use_deprecated", true);
|
||||
CMD2_VAR_VALUE ("method.use_intermediate", 1);
|
||||
|
||||
@@ -472,4 +491,5 @@ initialize_command_dynamic() {
|
||||
CMD2_ANY ("strings.log_group", std::bind(&torrent::option_list_strings, torrent::OPTION_LOG_GROUP));
|
||||
CMD2_ANY ("strings.tracker_event", std::bind(&torrent::option_list_strings, torrent::OPTION_TRACKER_EVENT));
|
||||
CMD2_ANY ("strings.tracker_mode", std::bind(&torrent::option_list_strings, torrent::OPTION_TRACKER_MODE));
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
+18
-54
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <functional>
|
||||
@@ -66,14 +30,14 @@ apply_on_ratio(const torrent::Object& rawArgs) {
|
||||
const std::string& groupName = rawArgs.as_string();
|
||||
|
||||
char buffer[32 + groupName.size()];
|
||||
sprintf(buffer, "group2.%s.view", groupName.c_str());
|
||||
snprintf(buffer, sizeof(buffer), "group2.%s.view", groupName.c_str());
|
||||
|
||||
core::ViewManager::iterator viewItr = control->view_manager()->find(rpc::commands.call(buffer, rpc::make_target()).as_string());
|
||||
|
||||
if (viewItr == control->view_manager()->end())
|
||||
throw torrent::input_error("Could not find view.");
|
||||
|
||||
char* bufferStart = buffer + sprintf(buffer, "group2.%s.ratio.", groupName.c_str());
|
||||
char* bufferStart = buffer + snprintf(buffer, sizeof(buffer), "group2.%s.ratio.", groupName.c_str());
|
||||
|
||||
// first argument: minimum ratio to reach
|
||||
// second argument: minimum upload amount to reach [optional]
|
||||
@@ -103,7 +67,7 @@ apply_on_ratio(const torrent::Object& rawArgs) {
|
||||
downloads.push_back(*itr);
|
||||
}
|
||||
|
||||
sprintf(buffer, "group.%s.ratio.command", groupName.c_str());
|
||||
snprintf(buffer, sizeof(buffer), "group.%s.ratio.command", groupName.c_str());
|
||||
|
||||
for (std::vector<core::Download*>::iterator itr = downloads.begin(), last = downloads.end(); itr != last; itr++) {
|
||||
// rpc::commands.call("print", rpc::make_target(*itr), "Calling ratio command.");
|
||||
@@ -216,28 +180,27 @@ void apply_import(const std::string& path) { if (!rpc::parse_command_file(pa
|
||||
void apply_try_import(const std::string& path) { if (!rpc::parse_command_file(path)) control->core()->push_log_std("Could not read resource file: " + path); }
|
||||
|
||||
torrent::Object
|
||||
apply_close_low_diskspace(int64_t arg) {
|
||||
core::DownloadList* downloadList = control->core()->download_list();
|
||||
|
||||
apply_close_low_diskspace(int64_t arg, uint32_t skip_priority) {
|
||||
bool closed = false;
|
||||
core::Manager::DListItr itr = downloadList->begin();
|
||||
|
||||
while ((itr = std::find_if(itr, downloadList->end(), std::mem_fun(&core::Download::is_downloading)))
|
||||
!= downloadList->end()) {
|
||||
if ((*itr)->file_list()->free_diskspace() < (uint64_t)arg) {
|
||||
downloadList->close(*itr);
|
||||
for (auto download : *control->core()->download_list()) {
|
||||
if (!download->is_downloading())
|
||||
continue;
|
||||
if (download->priority() >= skip_priority)
|
||||
continue;
|
||||
if (download->file_list()->free_diskspace() >= (uint64_t)arg)
|
||||
continue;
|
||||
|
||||
(*itr)->set_hash_failed(true);
|
||||
(*itr)->set_message(std::string("Low diskspace."));
|
||||
control->core()->download_list()->close(download);
|
||||
|
||||
closed = true;
|
||||
}
|
||||
download->set_hash_failed(true);
|
||||
download->set_message(std::string("Low diskspace."));
|
||||
|
||||
++itr;
|
||||
closed = true;
|
||||
}
|
||||
|
||||
if (closed)
|
||||
lt_log_print(torrent::LOG_TORRENT_ERROR, "Closed torrents due to low diskspace.");
|
||||
lt_log_print(torrent::LOG_TORRENT_ERROR, "Closed torrents due to low diskspace.");
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
@@ -391,7 +354,8 @@ initialize_command_events() {
|
||||
core::Manager::create_quiet | core::Manager::create_start | core::Manager::create_raw_data));
|
||||
CMD2_ANY_LIST ("load.raw_start_verbose", std::bind(&apply_load, std::placeholders::_2, core::Manager::create_start | core::Manager::create_raw_data));
|
||||
|
||||
CMD2_ANY_VALUE ("close_low_diskspace", std::bind(&apply_close_low_diskspace, std::placeholders::_2));
|
||||
CMD2_ANY_VALUE ("close_low_diskspace", std::bind(&apply_close_low_diskspace, std::placeholders::_2, 99));
|
||||
CMD2_ANY_VALUE ("close_low_diskspace.normal", std::bind(&apply_close_low_diskspace, std::placeholders::_2, 3));
|
||||
|
||||
CMD2_ANY_LIST ("download_list", std::bind(&apply_download_list, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("d.multicall2", std::bind(&d_multicall, std::placeholders::_2));
|
||||
|
||||
+11
-11
@@ -69,7 +69,7 @@ cg_d_group_set(core::Download* download, const torrent::Object& arg) {
|
||||
torrent::Object
|
||||
apply_cg_list() {
|
||||
torrent::Object::list_type result;
|
||||
|
||||
|
||||
for (torrent::ResourceManager::group_iterator
|
||||
itr = torrent::resource_manager()->group_begin(),
|
||||
last = torrent::resource_manager()->group_end(); itr != last; itr++)
|
||||
@@ -121,8 +121,7 @@ cg_get_index(const torrent::Object& raw_args) {
|
||||
|
||||
if (arg.is_string()) {
|
||||
if (!rpc::parse_whole_value_nothrow(arg.as_string().c_str(), &index)) {
|
||||
std::vector<torrent::choke_group*>::iterator itr = std::find_if(cg_list_hack.begin(), cg_list_hack.end(),
|
||||
rak::equal(arg.as_string(), std::mem_fun(&torrent::choke_group::name)));
|
||||
auto itr = std::find_if(cg_list_hack.begin(), cg_list_hack.end(), [&arg](torrent::choke_group* cg) { return arg.as_string() == cg->name(); });
|
||||
|
||||
if (itr == cg_list_hack.end())
|
||||
throw torrent::input_error("Choke group not found.");
|
||||
@@ -154,14 +153,17 @@ cg_get_group(const torrent::Object& raw_args) {
|
||||
}
|
||||
|
||||
int64_t cg_d_group(core::Download* download) { return download->group(); }
|
||||
const std::string& cg_d_group_name(core::Download* download) {
|
||||
return cg_list_hack.at(download->group())->name();
|
||||
}
|
||||
void cg_d_group_set(core::Download* download, const torrent::Object& arg) { download->set_group(cg_get_index(arg)); }
|
||||
|
||||
torrent::Object
|
||||
apply_cg_list() {
|
||||
torrent::Object::list_type result;
|
||||
|
||||
for (std::vector<torrent::choke_group*>::iterator itr = cg_list_hack.begin(), last = cg_list_hack.end(); itr != last; itr++)
|
||||
result.push_back((*itr)->name());
|
||||
|
||||
for (auto itr : cg_list_hack)
|
||||
result.push_back(itr->name());
|
||||
|
||||
return torrent::Object::from_list(result);
|
||||
}
|
||||
@@ -179,8 +181,7 @@ apply_cg_insert(const std::string& arg) {
|
||||
throw torrent::input_error("Cannot use a value string as choke group name.");
|
||||
|
||||
if (arg.empty() ||
|
||||
std::find_if(cg_list_hack.begin(), cg_list_hack.end(),
|
||||
rak::equal(arg, std::mem_fun(&torrent::choke_group::name))) != cg_list_hack.end())
|
||||
std::find_if(cg_list_hack.begin(), cg_list_hack.end(), [&arg](torrent::choke_group* cg) { return arg == cg->name(); }) != cg_list_hack.end())
|
||||
throw torrent::input_error("Duplicate name for choke group.");
|
||||
|
||||
cg_list_hack.push_back(new torrent::choke_group());
|
||||
@@ -194,8 +195,7 @@ apply_cg_insert(const std::string& arg) {
|
||||
|
||||
torrent::Object
|
||||
apply_cg_index_of(const std::string& arg) {
|
||||
std::vector<torrent::choke_group*>::iterator itr =
|
||||
std::find_if(cg_list_hack.begin(), cg_list_hack.end(), rak::equal(arg, std::mem_fun(&torrent::choke_group::name)));
|
||||
auto itr = std::find_if(cg_list_hack.begin(), cg_list_hack.end(), [&arg](torrent::choke_group* cg) { return arg == cg->name(); });
|
||||
|
||||
if (itr == cg_list_hack.end())
|
||||
throw torrent::input_error("Choke group not found.");
|
||||
@@ -340,7 +340,7 @@ void
|
||||
initialize_command_groups() {
|
||||
CMD2_ANY ("choke_group.list", std::bind(&apply_cg_list));
|
||||
CMD2_ANY_STRING ("choke_group.insert", std::bind(&apply_cg_insert, std::placeholders::_2));
|
||||
|
||||
|
||||
#if USE_CHOKE_GROUP
|
||||
CMD2_ANY ("choke_group.size", std::bind(&torrent::ResourceManager::group_size, torrent::resource_manager()));
|
||||
CMD2_ANY_STRING ("choke_group.index_of", std::bind(&torrent::ResourceManager::group_index_of, torrent::resource_manager(), std::placeholders::_2));
|
||||
|
||||
+12
-68
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RTORRENT_UTILS_COMMAND_HELPERS_H
|
||||
#define RTORRENT_UTILS_COMMAND_HELPERS_H
|
||||
|
||||
@@ -49,7 +13,7 @@ void initialize_commands();
|
||||
|
||||
#define CMD2_A_FUNCTION(key, function, slot, parm, doc) \
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::function>::type>(key, slot, &rpc::function, \
|
||||
rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_xmlrpc, NULL, NULL);
|
||||
rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_rpc, NULL, NULL);
|
||||
|
||||
#define CMD2_A_FUNCTION_PRIVATE(key, function, slot, parm, doc) \
|
||||
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::function>::type>(key, slot, &rpc::function, \
|
||||
@@ -92,9 +56,9 @@ void initialize_commands();
|
||||
#define CMD2_PEER_V(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::Peer*>, object_convert_void(slot), "i:", "")
|
||||
#define CMD2_PEER_VALUE_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_value<torrent::Peer*>, object_convert_void(slot), "i:i", "")
|
||||
|
||||
#define CMD2_TRACKER(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::Tracker*>, slot, "i:", "")
|
||||
#define CMD2_TRACKER_V(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::Tracker*>, object_convert_void(slot), "i:", "")
|
||||
#define CMD2_TRACKER_VALUE_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_value<torrent::Tracker*>, object_convert_void(slot), "i:i", "")
|
||||
#define CMD2_TRACKER(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::tracker::Tracker*>, slot, "i:", "")
|
||||
#define CMD2_TRACKER_V(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::tracker::Tracker*>, object_convert_void(slot), "i:", "")
|
||||
#define CMD2_TRACKER_VALUE_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_value<torrent::tracker::Tracker*>, object_convert_void(slot), "i:i", "")
|
||||
|
||||
#define CMD2_VAR_BOOL(key, value) \
|
||||
control->object_storage()->insert_c_str(key, int64_t(value), rpc::object_storage::flag_bool_type); \
|
||||
@@ -137,23 +101,23 @@ void initialize_commands();
|
||||
std::placeholders::_1, std::placeholders::_2));
|
||||
|
||||
#define CMD2_REDIRECT(from_key, to_key) \
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_dont_delete);
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_dont_delete);
|
||||
#define CMD2_REDIRECT_GENERIC(from_key, to_key) \
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_dont_delete);
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_dont_delete);
|
||||
#define CMD2_REDIRECT_GENERIC_NO_EXPORT(from_key, to_key) \
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_dont_delete);
|
||||
#define CMD2_REDIRECT_FILE(from_key, to_key) \
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_file_target | rpc::CommandMap::flag_dont_delete);
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_file_target | rpc::CommandMap::flag_dont_delete);
|
||||
#define CMD2_REDIRECT_TRACKER(from_key, to_key) \
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_tracker_target | rpc::CommandMap::flag_dont_delete);
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_tracker_target | rpc::CommandMap::flag_dont_delete);
|
||||
|
||||
#define CMD2_REDIRECT_GENERIC_STR(from_key, to_key) \
|
||||
rpc::commands.create_redirect(create_new_key(from_key), create_new_key(to_key), \
|
||||
rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_delete_key);
|
||||
rpc::commands.create_redirect(from_key, to_key, \
|
||||
rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_no_target);
|
||||
|
||||
#define CMD2_REDIRECT_GENERIC_STR_NO_EXPORT(from_key, to_key) \
|
||||
rpc::commands.create_redirect(create_new_key(from_key), create_new_key(to_key), \
|
||||
rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_delete_key);
|
||||
rpc::commands.create_redirect(from_key, to_key, \
|
||||
rpc::CommandMap::flag_no_target);
|
||||
|
||||
//
|
||||
// Conversion of return types:
|
||||
@@ -188,24 +152,4 @@ template <typename T>
|
||||
object_convert_type<T, void>
|
||||
object_convert_void(T f) { return f; }
|
||||
|
||||
//
|
||||
// Key creation:
|
||||
//
|
||||
|
||||
template <int postfix_size>
|
||||
inline const char*
|
||||
create_new_key(const std::string& key, const char postfix[postfix_size]) {
|
||||
char *buffer = new char[key.size() + std::max(postfix_size, 1)];
|
||||
std::memcpy(buffer, key.c_str(), key.size() + 1);
|
||||
std::memcpy(buffer + key.size(), postfix, postfix_size);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
inline const char*
|
||||
create_new_key(const std::string& key) {
|
||||
char *buffer = new char[key.size() + 1];
|
||||
std::memcpy(buffer, key.c_str(), key.size() + 1);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+13
-36
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
@@ -60,6 +24,7 @@
|
||||
#include "utils/file_status_cache.h"
|
||||
|
||||
#include "globals.h"
|
||||
#include "rpc/lua.h"
|
||||
#include "control.h"
|
||||
#include "command_helpers.h"
|
||||
|
||||
@@ -241,6 +206,7 @@ initialize_command_local() {
|
||||
CMD2_VAR_C_STRING("system.api_version", (int64_t)API_VERSION);
|
||||
CMD2_VAR_C_STRING("system.client_version", PACKAGE_VERSION);
|
||||
CMD2_VAR_C_STRING("system.library_version", torrent::version());
|
||||
|
||||
CMD2_VAR_VALUE ("system.file.allocate", 0);
|
||||
CMD2_VAR_VALUE ("system.file.max_size", (int64_t)512 << 30);
|
||||
CMD2_VAR_VALUE ("system.file.split_size", -1);
|
||||
@@ -254,6 +220,10 @@ initialize_command_local() {
|
||||
CMD2_VAR_LIST ("file.prioritize_toc.first");
|
||||
CMD2_VAR_LIST ("file.prioritize_toc.last");
|
||||
|
||||
CMD2_ANY ("system.files.advise_random", std::bind(&FM_t::advise_random, fileManager));
|
||||
CMD2_ANY_VALUE_V ("system.files.advise_random.set", std::bind(&FM_t::set_advise_random, fileManager, std::placeholders::_2));
|
||||
CMD2_VAR_BOOL ("system.files.session.fdatasync", true);
|
||||
|
||||
CMD2_ANY ("system.files.opened_counter", std::bind(&FM_t::files_opened_counter, fileManager));
|
||||
CMD2_ANY ("system.files.closed_counter", std::bind(&FM_t::files_closed_counter, fileManager));
|
||||
CMD2_ANY ("system.files.failed_counter", std::bind(&FM_t::files_failed_counter, fileManager));
|
||||
@@ -315,6 +285,13 @@ initialize_command_local() {
|
||||
|
||||
CMD2_ANY_V ("session.save", std::bind(&core::DownloadList::session_save, dList));
|
||||
|
||||
#ifdef HAVE_LUA
|
||||
rpc::LuaEngine* lua_engine = control->lua_engine();
|
||||
|
||||
CMD2_ANY ("lua.execute", std::bind(&rpc::execute_lua, lua_engine, std::placeholders::_1, std::placeholders::_2, 0));
|
||||
CMD2_ANY ("lua.execute.str", std::bind(&rpc::execute_lua, lua_engine, std::placeholders::_1, std::placeholders::_2, rpc::LuaEngine::flag_string));
|
||||
#endif
|
||||
|
||||
#define CMD2_EXECUTE(key, flags) \
|
||||
CMD2_ANY(key, std::bind(&rpc::ExecFile::execute_object, &rpc::execFile, std::placeholders::_2, flags));
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ torrent::Object
|
||||
apply_log_open(int output_flags, const torrent::Object::list_type& args) {
|
||||
if (args.size() < 2)
|
||||
throw torrent::input_error("Invalid number of arguments.");
|
||||
|
||||
|
||||
torrent::Object::list_const_iterator itr = args.begin();
|
||||
|
||||
std::string output_id = (itr++)->as_string();
|
||||
@@ -142,5 +142,6 @@ initialize_command_logging() {
|
||||
|
||||
CMD2_ANY_STRING ("log.execute", std::bind(&apply_log, std::placeholders::_2, 0));
|
||||
CMD2_ANY_STRING ("log.vmmap.dump", std::bind(&log_vmmap_dump, std::placeholders::_2));
|
||||
CMD2_ANY_STRING_V("log.xmlrpc", std::bind(&ThreadWorker::set_xmlrpc_log, worker_thread, std::placeholders::_2));
|
||||
CMD2_ANY_STRING_V("log.rpc", std::bind(&ThreadWorker::set_rpc_log, worker_thread, std::placeholders::_2));
|
||||
CMD2_REDIRECT ("log.xmlrpc", "log.rpc"); // For backwards compatibility
|
||||
}
|
||||
|
||||
+38
-79
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <functional>
|
||||
@@ -42,8 +6,8 @@
|
||||
#include <rak/address_info.h>
|
||||
#include <rak/path.h>
|
||||
#include <torrent/connection_manager.h>
|
||||
#include <torrent/tracker.h>
|
||||
#include <torrent/tracker_list.h>
|
||||
#include <torrent/tracker/tracker.h>
|
||||
#include <torrent/torrent.h>
|
||||
#include <torrent/rate.h>
|
||||
#include <torrent/data/file_manager.h>
|
||||
@@ -94,51 +58,44 @@ apply_tos(const torrent::Object::string_type& arg) {
|
||||
|
||||
torrent::Object apply_encoding_list(const std::string& arg) { torrent::encoding_list()->push_back(arg); return torrent::Object(); }
|
||||
|
||||
torrent::File*
|
||||
xmlrpc_find_file(core::Download* download, uint32_t index) {
|
||||
if (index >= download->file_list()->size_files())
|
||||
return NULL;
|
||||
|
||||
return (*download->file_list())[index];
|
||||
}
|
||||
|
||||
// Ergh... time to update the Tracker API to allow proper ptrs.
|
||||
torrent::Tracker*
|
||||
xmlrpc_find_tracker(core::Download* download, uint32_t index) {
|
||||
if (index >= download->tracker_list()->size())
|
||||
return NULL;
|
||||
|
||||
return download->tracker_list()->at(index);
|
||||
}
|
||||
|
||||
torrent::Peer*
|
||||
xmlrpc_find_peer(core::Download* download, const torrent::HashString& hash) {
|
||||
torrent::ConnectionList::iterator itr = download->connection_list()->find(hash.c_str());
|
||||
|
||||
if (itr == download->connection_list()->end())
|
||||
return NULL;
|
||||
|
||||
return *itr;
|
||||
}
|
||||
|
||||
void
|
||||
initialize_xmlrpc() {
|
||||
rpc::xmlrpc.initialize();
|
||||
rpc::xmlrpc.slot_find_download() = std::bind(&core::DownloadList::find_hex_ptr, control->core()->download_list(), std::placeholders::_1);
|
||||
rpc::xmlrpc.slot_find_file() = std::bind(&xmlrpc_find_file, std::placeholders::_1, std::placeholders::_2);
|
||||
rpc::xmlrpc.slot_find_tracker() = std::bind(&xmlrpc_find_tracker, std::placeholders::_1, std::placeholders::_2);
|
||||
rpc::xmlrpc.slot_find_peer() = std::bind(&xmlrpc_find_peer, std::placeholders::_1, std::placeholders::_2);
|
||||
initialize_rpc() {
|
||||
rpc::rpc.initialize();
|
||||
|
||||
rpc::rpc.slot_find_download() = [](const char* hash) {
|
||||
return control->core()->download_list()->find_hex_ptr(hash);
|
||||
};
|
||||
rpc::rpc.slot_find_file() = [](core::Download* d, uint32_t index) -> torrent::File* {
|
||||
if (index >= d->file_list()->size_files())
|
||||
throw torrent::input_error("invalid parameters: index not found");
|
||||
|
||||
return (*d->file_list())[index].get();
|
||||
};
|
||||
rpc::rpc.slot_find_tracker() = [](core::Download* d, uint32_t index) -> torrent::tracker::Tracker {
|
||||
if (index >= d->tracker_list()->size())
|
||||
throw torrent::input_error("invalid parameters: index not found");
|
||||
|
||||
return d->tracker_list()->at(index);
|
||||
};
|
||||
rpc::rpc.slot_find_peer() = [](core::Download* d, const torrent::HashString& hash) -> torrent::Peer* {
|
||||
auto itr = d->connection_list()->find(hash.c_str());
|
||||
|
||||
if (itr == d->connection_list()->end())
|
||||
throw torrent::input_error("invalid parameters: hash not found");
|
||||
|
||||
return *itr;
|
||||
};
|
||||
|
||||
unsigned int count = 0;
|
||||
|
||||
for (rpc::CommandMap::const_iterator itr = rpc::commands.begin(), last = rpc::commands.end(); itr != last; itr++, count++) {
|
||||
if (!(itr->second.m_flags & rpc::CommandMap::flag_public_xmlrpc))
|
||||
if (!(itr->second.m_flags & rpc::CommandMap::flag_public_rpc))
|
||||
continue;
|
||||
|
||||
rpc::xmlrpc.insert_command(itr->first, itr->second.m_parm, itr->second.m_doc);
|
||||
rpc::rpc.insert_command(itr->first.c_str(), itr->second.m_parm, itr->second.m_doc);
|
||||
}
|
||||
|
||||
lt_log_print(torrent::LOG_RPC_EVENTS, "XMLRPC initialized with %u functions.", count);
|
||||
lt_log_print(torrent::LOG_RPC_EVENTS, "RPC initialized with %u functions.", count);
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
@@ -146,8 +103,7 @@ apply_scgi(const std::string& arg, int type) {
|
||||
if (worker_thread->scgi() != NULL)
|
||||
throw torrent::input_error("SCGI already enabled.");
|
||||
|
||||
if (!rpc::xmlrpc.is_valid())
|
||||
initialize_xmlrpc();
|
||||
initialize_rpc();
|
||||
|
||||
rpc::SCgi* scgi = new rpc::SCgi;
|
||||
|
||||
@@ -225,7 +181,7 @@ apply_xmlrpc_dialect(const std::string& arg) {
|
||||
else
|
||||
value = -1;
|
||||
|
||||
rpc::xmlrpc.set_dialect(value);
|
||||
rpc::rpc.set_dialect(value);
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
@@ -298,9 +254,12 @@ initialize_command_network() {
|
||||
CMD2_ANY_STRING ("network.scgi.open_local", std::bind(&apply_scgi, std::placeholders::_2, 2));
|
||||
CMD2_VAR_BOOL ("network.scgi.dont_route", false);
|
||||
|
||||
CMD2_ANY_STRING ("network.xmlrpc.dialect.set", std::bind(&apply_xmlrpc_dialect, std::placeholders::_2));
|
||||
CMD2_ANY ("network.xmlrpc.size_limit", std::bind(&rpc::XmlRpc::size_limit));
|
||||
CMD2_ANY_VALUE_V ("network.xmlrpc.size_limit.set", std::bind(&rpc::XmlRpc::set_size_limit, std::placeholders::_2));
|
||||
CMD2_ANY_STRING ("network.xmlrpc.dialect.set", [](const auto&, const auto& arg) { return apply_xmlrpc_dialect(arg); })
|
||||
CMD2_ANY ("network.xmlrpc.size_limit", [](const auto&, const auto&){ return rpc::rpc.size_limit(); });
|
||||
CMD2_ANY_VALUE_V ("network.xmlrpc.size_limit.set", [](const auto&, const auto& arg){ return rpc::rpc.set_size_limit(arg); });
|
||||
|
||||
CMD2_VAR_BOOL ("network.rpc.use_xmlrpc", true);
|
||||
CMD2_VAR_BOOL ("network.rpc.use_jsonrpc", true);
|
||||
|
||||
CMD2_ANY ("network.block.ipv4", std::bind(&torrent::ConnectionManager::is_block_ipv4, cm));
|
||||
CMD2_ANY_VALUE_V ("network.block.ipv4.set", std::bind(&torrent::ConnectionManager::set_block_ipv4, cm, std::placeholders::_2));
|
||||
|
||||
+51
-90
@@ -1,46 +1,12 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <netdb.h>
|
||||
#include <rak/address_info.h>
|
||||
#include <rak/error_number.h>
|
||||
#include <torrent/dht_manager.h>
|
||||
#include <torrent/tracker.h>
|
||||
#include <torrent/net/resolver.h>
|
||||
#include <torrent/tracker/dht_controller.h>
|
||||
#include <torrent/tracker/tracker.h>
|
||||
#include <torrent/utils/log.h>
|
||||
|
||||
#include "core/download.h"
|
||||
@@ -52,30 +18,16 @@
|
||||
#include "core/dht_manager.h"
|
||||
|
||||
void
|
||||
tracker_set_enabled(torrent::Tracker* tracker, bool state) {
|
||||
tracker_set_enabled(torrent::tracker::Tracker* tracker, bool state) {
|
||||
if (state)
|
||||
tracker->enable();
|
||||
else
|
||||
tracker->disable();
|
||||
}
|
||||
|
||||
struct call_add_node_t {
|
||||
call_add_node_t(int port) : m_port(port) { }
|
||||
|
||||
void operator() (const sockaddr* sa, int err) {
|
||||
if (sa == NULL) {
|
||||
lt_log_print(torrent::LOG_DHT_WARN, "Could not resolve host.");
|
||||
} else {
|
||||
torrent::dht_manager()->add_node(sa, m_port);
|
||||
}
|
||||
}
|
||||
|
||||
int m_port;
|
||||
};
|
||||
|
||||
torrent::Object
|
||||
apply_dht_add_node(const std::string& arg) {
|
||||
if (!torrent::dht_manager()->is_valid())
|
||||
if (!torrent::dht_controller()->is_valid())
|
||||
throw torrent::input_error("DHT not enabled.");
|
||||
|
||||
int port, ret;
|
||||
@@ -92,68 +44,77 @@ apply_dht_add_node(const std::string& arg) {
|
||||
if (port < 1 || port > 65535)
|
||||
throw torrent::input_error("Invalid port number.");
|
||||
|
||||
torrent::connection_manager()->resolver()(host, (int)rak::socket_address::pf_inet, SOCK_DGRAM, call_add_node_t(port));
|
||||
// Currently discarding SOCK_STREAM.
|
||||
torrent::main_thread()->resolver()->resolve_specific(nullptr, host, PF_INET, [port](torrent::c_sa_shared_ptr sa, int err) {
|
||||
if (sa == nullptr) {
|
||||
lt_log_print(torrent::LOG_DHT_WARN, "Could not resolve host: %s", gai_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
torrent::dht_controller()->add_node(sa.get(), port);
|
||||
});
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_enable_trackers(int64_t arg) {
|
||||
for (core::Manager::DListItr itr = control->core()->download_list()->begin(), last = control->core()->download_list()->end(); itr != last; ++itr) {
|
||||
std::for_each((*itr)->tracker_list()->begin(), (*itr)->tracker_list()->end(),
|
||||
arg ? std::mem_fun(&torrent::Tracker::enable) : std::mem_fun(&torrent::Tracker::disable));
|
||||
std::for_each((*itr)->tracker_list()->begin(), (*itr)->tracker_list()->end(), std::mem_fn(arg ? &torrent::tracker::Tracker::enable : &torrent::tracker::Tracker::disable));
|
||||
|
||||
if (arg && !rpc::call_command_value("trackers.use_udp"))
|
||||
(*itr)->enable_udp_trackers(false);
|
||||
}
|
||||
}
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
void
|
||||
initialize_command_tracker() {
|
||||
CMD2_TRACKER ("t.is_open", std::bind(&torrent::Tracker::is_busy, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.is_enabled", std::bind(&torrent::Tracker::is_enabled, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.is_usable", std::bind(&torrent::Tracker::is_usable, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.is_busy", std::bind(&torrent::Tracker::is_busy, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.is_extra_tracker", std::bind(&torrent::Tracker::is_extra_tracker, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.can_scrape", std::bind(&torrent::Tracker::can_scrape, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.is_busy", std::bind(&torrent::tracker::Tracker::is_busy, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.is_enabled", std::bind(&torrent::tracker::Tracker::is_enabled, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.is_extra_tracker", std::bind(&torrent::tracker::Tracker::is_extra_tracker, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.is_open", std::bind(&torrent::tracker::Tracker::is_busy, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.is_scrapable", std::bind(&torrent::tracker::Tracker::is_scrapable, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.is_usable", std::bind(&torrent::tracker::Tracker::is_usable, std::placeholders::_1));
|
||||
|
||||
CMD2_TRACKER_V ("t.enable", std::bind(&torrent::Tracker::enable, std::placeholders::_1));
|
||||
CMD2_TRACKER_V ("t.disable", std::bind(&torrent::Tracker::disable, std::placeholders::_1));
|
||||
// TODO: Deprecate.
|
||||
CMD2_TRACKER ("t.can_scrape", std::bind(&torrent::tracker::Tracker::is_scrapable, std::placeholders::_1));
|
||||
|
||||
CMD2_TRACKER_V ("t.enable", std::bind(&torrent::tracker::Tracker::enable, std::placeholders::_1));
|
||||
CMD2_TRACKER_V ("t.disable", std::bind(&torrent::tracker::Tracker::disable, std::placeholders::_1));
|
||||
|
||||
CMD2_TRACKER_VALUE_V("t.is_enabled.set", std::bind(&tracker_set_enabled, std::placeholders::_1, std::placeholders::_2));
|
||||
|
||||
CMD2_TRACKER ("t.url", std::bind(&torrent::Tracker::url, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.group", std::bind(&torrent::Tracker::group, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.type", std::bind(&torrent::Tracker::type, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.id", std::bind(&torrent::Tracker::tracker_id, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.url", std::bind(&torrent::tracker::Tracker::url, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.group", std::bind(&torrent::tracker::Tracker::group, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.type", std::bind(&torrent::tracker::Tracker::type, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.id", std::bind(&torrent::tracker::Tracker::tracker_id, std::placeholders::_1));
|
||||
|
||||
CMD2_TRACKER ("t.latest_event", std::bind(&torrent::Tracker::latest_event, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.latest_new_peers", std::bind(&torrent::Tracker::latest_new_peers, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.latest_sum_peers", std::bind(&torrent::Tracker::latest_sum_peers, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.latest_event", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().latest_event(); });
|
||||
CMD2_TRACKER ("t.latest_new_peers", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().latest_new_peers(); });
|
||||
CMD2_TRACKER ("t.latest_sum_peers", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().latest_sum_peers(); });
|
||||
|
||||
// Time since last connection, connection attempt.
|
||||
CMD2_TRACKER ("t.normal_interval", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().normal_interval(); });
|
||||
CMD2_TRACKER ("t.min_interval", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().min_interval(); });
|
||||
|
||||
CMD2_TRACKER ("t.normal_interval", std::bind(&torrent::Tracker::normal_interval, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.min_interval", std::bind(&torrent::Tracker::min_interval, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.activity_time_next", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().activity_time_next(); });
|
||||
CMD2_TRACKER ("t.activity_time_last", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().activity_time_last(); });
|
||||
|
||||
CMD2_TRACKER ("t.activity_time_next", std::bind(&torrent::Tracker::activity_time_next, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.activity_time_last", std::bind(&torrent::Tracker::activity_time_last, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.success_time_next", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().success_time_next(); });
|
||||
CMD2_TRACKER ("t.success_time_last", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().success_time_last(); });
|
||||
CMD2_TRACKER ("t.success_counter", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().success_counter(); });
|
||||
|
||||
CMD2_TRACKER ("t.success_time_next", std::bind(&torrent::Tracker::success_time_next, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.success_time_last", std::bind(&torrent::Tracker::success_time_last, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.success_counter", std::bind(&torrent::Tracker::success_counter, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.failed_time_next", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().failed_time_next(); });
|
||||
CMD2_TRACKER ("t.failed_time_last", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().failed_time_last(); });
|
||||
CMD2_TRACKER ("t.failed_counter", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().failed_counter(); });
|
||||
|
||||
CMD2_TRACKER ("t.failed_time_next", std::bind(&torrent::Tracker::failed_time_next, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.failed_time_last", std::bind(&torrent::Tracker::failed_time_last, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.failed_counter", std::bind(&torrent::Tracker::failed_counter, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.scrape_time_last", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().scrape_time_last(); });
|
||||
CMD2_TRACKER ("t.scrape_counter", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().scrape_counter(); });
|
||||
|
||||
CMD2_TRACKER ("t.scrape_time_last", std::bind(&torrent::Tracker::scrape_time_last, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.scrape_counter", std::bind(&torrent::Tracker::scrape_counter, std::placeholders::_1));
|
||||
|
||||
CMD2_TRACKER ("t.scrape_complete", std::bind(&torrent::Tracker::scrape_complete, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.scrape_incomplete", std::bind(&torrent::Tracker::scrape_incomplete, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.scrape_downloaded", std::bind(&torrent::Tracker::scrape_downloaded, std::placeholders::_1));
|
||||
CMD2_TRACKER ("t.scrape_complete", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().scrape_complete(); });
|
||||
CMD2_TRACKER ("t.scrape_incomplete", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().scrape_incomplete(); });
|
||||
CMD2_TRACKER ("t.scrape_downloaded", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().scrape_downloaded(); });
|
||||
|
||||
CMD2_ANY_VALUE ("trackers.enable", std::bind(&apply_enable_trackers, int64_t(1)));
|
||||
CMD2_ANY_VALUE ("trackers.disable", std::bind(&apply_enable_trackers, int64_t(0)));
|
||||
|
||||
+36
-52
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
@@ -42,14 +6,14 @@
|
||||
#include <regex>
|
||||
|
||||
#include <rak/algorithm.h>
|
||||
#include <rak/functional.h>
|
||||
#include <rak/functional_fun.h>
|
||||
#include <torrent/utils/log.h>
|
||||
|
||||
#include "core/manager.h"
|
||||
#include "core/view_manager.h"
|
||||
#include "display/canvas.h"
|
||||
#include "ui/root.h"
|
||||
#include "ui/download_list.h"
|
||||
#include "display/color_map.h"
|
||||
#include "rpc/parse.h"
|
||||
|
||||
#include "globals.h"
|
||||
@@ -64,7 +28,7 @@ apply_view_filter_on(const torrent::Object::list_type& args) {
|
||||
throw torrent::input_error("Too few arguments.");
|
||||
|
||||
const std::string& name = args.front().as_string();
|
||||
|
||||
|
||||
if (name.empty())
|
||||
throw torrent::input_error("First argument must be a string.");
|
||||
|
||||
@@ -135,7 +99,7 @@ apply_view_set(const torrent::Object::list_type& args) {
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_print(rpc::target_type target, const torrent::Object& rawArgs) {
|
||||
apply_print([[maybe_unused]] rpc::target_type target, const torrent::Object& rawArgs) {
|
||||
char buffer[1024];
|
||||
rpc::print_object(buffer, buffer + 1024, &rawArgs, 0);
|
||||
|
||||
@@ -144,7 +108,7 @@ apply_print(rpc::target_type target, const torrent::Object& rawArgs) {
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_cat(rpc::target_type target, const torrent::Object& rawArgs) {
|
||||
apply_cat([[maybe_unused]] rpc::target_type target, const torrent::Object& rawArgs) {
|
||||
std::string result;
|
||||
|
||||
rpc::print_object_std(&result, &rawArgs, 0);
|
||||
@@ -152,7 +116,7 @@ apply_cat(rpc::target_type target, const torrent::Object& rawArgs) {
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_value(rpc::target_type target, const torrent::Object::list_type& args) {
|
||||
apply_value([[maybe_unused]] rpc::target_type target, const torrent::Object::list_type& args) {
|
||||
if (args.size() < 1)
|
||||
throw torrent::input_error("'value' takes at least a number argument!");
|
||||
if (args.size() > 2)
|
||||
@@ -220,7 +184,7 @@ apply_not(rpc::target_type target, const torrent::Object& rawArgs) {
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_false(rpc::target_type target, const torrent::Object& rawArgs) {
|
||||
apply_false([[maybe_unused]] rpc::target_type target, [[maybe_unused]] const torrent::Object& rawArgs) {
|
||||
return (int64_t)0;
|
||||
}
|
||||
|
||||
@@ -235,10 +199,10 @@ apply_and(rpc::target_type target, const torrent::Object& rawArgs) {
|
||||
return (int64_t)false;
|
||||
|
||||
} else if (itr->is_value()) {
|
||||
if (!itr->as_value())
|
||||
if (!itr->as_value())
|
||||
return (int64_t)false;
|
||||
|
||||
} else {
|
||||
} else {
|
||||
// TODO: Switch to new versions that only accept the new command syntax.
|
||||
if (!as_boolean(rpc::parse_command_single(target, itr->as_string())))
|
||||
return (int64_t)false;
|
||||
@@ -258,10 +222,10 @@ apply_or(rpc::target_type target, const torrent::Object& rawArgs) {
|
||||
return (int64_t)true;
|
||||
|
||||
} else if (itr->is_value()) {
|
||||
if (itr->as_value())
|
||||
if (itr->as_value())
|
||||
return (int64_t)true;
|
||||
|
||||
} else {
|
||||
} else {
|
||||
if (as_boolean(rpc::parse_command_single(target, itr->as_string())))
|
||||
return (int64_t)true;
|
||||
}
|
||||
@@ -298,7 +262,7 @@ apply_cmp(rpc::target_type target, const torrent::Object::list_type& args) {
|
||||
|
||||
if (result1.type() != result2.type())
|
||||
throw torrent::input_error("Type mismatch.");
|
||||
|
||||
|
||||
switch (result1.type()) {
|
||||
case torrent::Object::TYPE_VALUE: return result1.as_value() - result2.as_value();
|
||||
case torrent::Object::TYPE_STRING: return result1.as_string().compare(result2.as_string());
|
||||
@@ -427,7 +391,7 @@ apply_to_time(const torrent::Object& rawArgs, int flags) {
|
||||
u = std::localtime(&t);
|
||||
else
|
||||
u = std::gmtime(&t);
|
||||
|
||||
|
||||
if (u == NULL)
|
||||
return torrent::Object();
|
||||
|
||||
@@ -470,7 +434,7 @@ apply_to_mb(const torrent::Object& rawArgs) {
|
||||
torrent::Object
|
||||
apply_to_xb(const torrent::Object& rawArgs) {
|
||||
char buffer[48];
|
||||
int64_t arg = rawArgs.as_value();
|
||||
int64_t arg = rawArgs.as_value();
|
||||
|
||||
if (arg < (int64_t(1000) << 10))
|
||||
snprintf(buffer, 48, "%5.1f KB", (double)arg / (int64_t(1) << 10));
|
||||
@@ -486,7 +450,7 @@ apply_to_xb(const torrent::Object& rawArgs) {
|
||||
|
||||
torrent::Object
|
||||
apply_to_throttle(const torrent::Object& rawArgs) {
|
||||
int64_t arg = rawArgs.as_value();
|
||||
int64_t arg = rawArgs.as_value();
|
||||
if (arg < 0)
|
||||
return "---";
|
||||
else if (arg == 0)
|
||||
@@ -584,7 +548,7 @@ cmd_view_size_not_visible(const torrent::Object::string_type& args) {
|
||||
torrent::Object
|
||||
cmd_view_persistent(const torrent::Object::string_type& args) {
|
||||
core::View* view = *control->view_manager()->find_throw(args);
|
||||
|
||||
|
||||
if (!view->get_filter().is_empty() || !view->event_added().is_empty() || !view->event_removed().is_empty())
|
||||
throw torrent::input_error("Cannot set modified views as persitent.");
|
||||
|
||||
@@ -797,6 +761,13 @@ cmd_status_throttle_names(bool up, const torrent::Object::list_type& args) {
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_set_color(int color_id, const torrent::Object::string_type& color_str) {
|
||||
control->object_storage()->set_str_string(display::color_vars[color_id], color_str);
|
||||
display::Canvas::build_colors();
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
void
|
||||
initialize_command_ui() {
|
||||
CMD2_VAR_STRING("keys.layout", "qwerty");
|
||||
@@ -844,6 +815,8 @@ initialize_command_ui() {
|
||||
CMD2_VAR_VALUE ("ui.throttle.global.step.medium", 50);
|
||||
CMD2_VAR_VALUE ("ui.throttle.global.step.large", 500);
|
||||
|
||||
CMD2_VAR_VALUE ("ui.focus.page_size", 0);
|
||||
|
||||
CMD2_ANY_LIST ("ui.status.throttle.up.set", std::bind(&cmd_status_throttle_names, true, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("ui.status.throttle.down.set", std::bind(&cmd_status_throttle_names, false, std::placeholders::_2));
|
||||
|
||||
@@ -894,4 +867,15 @@ initialize_command_ui() {
|
||||
|
||||
CMD2_ANY_LIST ("elapsed.less", std::bind(&apply_elapsed_less, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("elapsed.greater", std::bind(&apply_elapsed_greater, std::placeholders::_2));
|
||||
|
||||
// Build set/get methods for all color definitions
|
||||
for (int color_id = 1; color_id < display::RCOLOR_MAX; color_id++) {
|
||||
control->object_storage()->insert_str(display::color_vars[color_id], "", rpc::object_storage::flag_string_type);
|
||||
CMD2_ANY_STRING(std::string(display::color_vars[color_id]) + ".set", [color_id](const auto&, const auto& arg) {
|
||||
return apply_set_color(color_id, arg);
|
||||
});
|
||||
CMD2_ANY(display::color_vars[color_id], [color_id](const auto&, const auto&) {
|
||||
return control->object_storage()->get_str(display::color_vars[color_id]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+12
-41
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <unistd.h>
|
||||
@@ -49,10 +13,15 @@
|
||||
|
||||
#include "display/canvas.h"
|
||||
#include "display/window.h"
|
||||
#include "display/window_http_queue.h"
|
||||
#include "display/window_input.h"
|
||||
#include "display/window_statusbar.h"
|
||||
#include "display/window_title.h"
|
||||
#include "display/manager.h"
|
||||
#include "input/manager.h"
|
||||
#include "input/input_event.h"
|
||||
#include "rpc/command_scheduler.h"
|
||||
#include "rpc/lua.h"
|
||||
#include "rpc/parse_commands.h"
|
||||
#include "rpc/scgi.h"
|
||||
#include "rpc/object_storage.h"
|
||||
@@ -68,6 +37,7 @@ Control::Control() :
|
||||
|
||||
m_commandScheduler(new rpc::CommandScheduler()),
|
||||
m_objectStorage(new rpc::object_storage()),
|
||||
m_lua_engine(new rpc::LuaEngine()),
|
||||
m_directory_events(new torrent::directory_events()),
|
||||
|
||||
m_tick(0),
|
||||
@@ -82,7 +52,7 @@ Control::Control() :
|
||||
|
||||
m_taskShutdown.slot() = std::bind(&Control::handle_shutdown, this);
|
||||
|
||||
m_commandScheduler->set_slot_error_message(rak::mem_fn(m_core, &core::Manager::push_log_std));
|
||||
m_commandScheduler->set_slot_error_message([this](const std::string& msg) { m_core->push_log_std(msg); });
|
||||
}
|
||||
|
||||
Control::~Control() {
|
||||
@@ -99,14 +69,15 @@ Control::~Control() {
|
||||
delete m_directory_events;
|
||||
delete m_commandScheduler;
|
||||
delete m_objectStorage;
|
||||
delete m_lua_engine;
|
||||
}
|
||||
|
||||
void
|
||||
Control::initialize() {
|
||||
display::Canvas::initialize();
|
||||
display::Window::slot_schedule(rak::make_mem_fun(m_display, &display::Manager::schedule));
|
||||
display::Window::slot_unschedule(rak::make_mem_fun(m_display, &display::Manager::unschedule));
|
||||
display::Window::slot_adjust(rak::make_mem_fun(m_display, &display::Manager::adjust_layout));
|
||||
display::Window::slot_schedule([this](display::Window* w, rak::timer t) { m_display->schedule(w, t); });
|
||||
display::Window::slot_unschedule([this](display::Window* w) { m_display->unschedule(w); });
|
||||
display::Window::slot_adjust([this]() { m_display->adjust_layout(); });
|
||||
|
||||
m_core->http_stack()->set_user_agent(USER_AGENT);
|
||||
|
||||
@@ -126,7 +97,7 @@ Control::initialize() {
|
||||
void
|
||||
Control::cleanup() {
|
||||
// delete m_scgi; m_scgi = NULL;
|
||||
rpc::xmlrpc.cleanup();
|
||||
rpc::rpc.cleanup();
|
||||
|
||||
priority_queue_erase(&taskScheduler, &m_taskShutdown);
|
||||
|
||||
|
||||
+8
-4
@@ -37,6 +37,7 @@
|
||||
#ifndef RTORRENT_CONTROL_H
|
||||
#define RTORRENT_CONTROL_H
|
||||
|
||||
#include <atomic>
|
||||
#include <cinttypes>
|
||||
#include <sys/types.h>
|
||||
#include <rak/timer.h>
|
||||
@@ -66,6 +67,7 @@ namespace rpc {
|
||||
class CommandScheduler;
|
||||
class XmlRpc;
|
||||
class object_storage;
|
||||
class LuaEngine;
|
||||
}
|
||||
|
||||
namespace torrent {
|
||||
@@ -87,8 +89,8 @@ public:
|
||||
|
||||
void handle_shutdown();
|
||||
|
||||
void receive_normal_shutdown() { m_shutdownReceived = true; __sync_synchronize(); }
|
||||
void receive_quick_shutdown() { m_shutdownReceived = true; m_shutdownQuick = true; __sync_synchronize(); }
|
||||
void receive_normal_shutdown() { m_shutdownReceived = true; }
|
||||
void receive_quick_shutdown() { m_shutdownReceived = true; m_shutdownQuick = true; }
|
||||
|
||||
core::Manager* core() { return m_core; }
|
||||
core::ViewManager* view_manager() { return m_viewManager; }
|
||||
@@ -101,6 +103,7 @@ public:
|
||||
|
||||
rpc::CommandScheduler* command_scheduler() { return m_commandScheduler; }
|
||||
rpc::object_storage* object_storage() { return m_objectStorage; }
|
||||
rpc::LuaEngine* lua_engine() { return m_lua_engine; }
|
||||
|
||||
torrent::directory_events* directory_events() { return m_directory_events; }
|
||||
|
||||
@@ -125,6 +128,7 @@ private:
|
||||
|
||||
rpc::CommandScheduler* m_commandScheduler;
|
||||
rpc::object_storage* m_objectStorage;
|
||||
rpc::LuaEngine* m_lua_engine;
|
||||
torrent::directory_events* m_directory_events;
|
||||
|
||||
uint64_t m_tick;
|
||||
@@ -134,8 +138,8 @@ private:
|
||||
|
||||
rak::priority_item m_taskShutdown;
|
||||
|
||||
bool m_shutdownReceived lt_cacheline_aligned;
|
||||
bool m_shutdownQuick lt_cacheline_aligned;
|
||||
std::atomic<bool> m_shutdownReceived;
|
||||
std::atomic<bool> m_shutdownQuick;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -67,6 +67,9 @@ CurlGet::start() {
|
||||
if (m_stream == NULL)
|
||||
throw torrent::internal_error("Tried to call CurlGet::start without a valid output stream.");
|
||||
|
||||
if (!m_stack->is_running())
|
||||
return;
|
||||
|
||||
m_handle = curl_easy_init();
|
||||
|
||||
if (m_handle == NULL)
|
||||
@@ -83,8 +86,7 @@ CurlGet::start() {
|
||||
// Normally libcurl should handle the timeout. But sometimes that doesn't
|
||||
// work right so we do a fallback timeout that just aborts the transfer.
|
||||
m_taskTimeout.slot() = std::bind(&CurlGet::receive_timeout, this);
|
||||
priority_queue_erase(&taskScheduler, &m_taskTimeout);
|
||||
priority_queue_insert(&taskScheduler, &m_taskTimeout, cachedTime + rak::timer::from_seconds(m_timeout + 5));
|
||||
priority_queue_update(&taskScheduler, &m_taskTimeout, cachedTime + rak::timer::from_seconds(m_timeout + 5));
|
||||
}
|
||||
|
||||
curl_easy_setopt(m_handle, CURLOPT_FORBID_REUSE, (long)1);
|
||||
|
||||
+9
-41
@@ -1,47 +1,13 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2008, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <curl/multi.h>
|
||||
|
||||
#include <torrent/poll.h>
|
||||
#include <torrent/exceptions.h>
|
||||
#include <torrent/utils/thread_base.h>
|
||||
#include <torrent/utils/thread.h>
|
||||
|
||||
#include "control.h"
|
||||
|
||||
@@ -51,10 +17,13 @@
|
||||
namespace core {
|
||||
|
||||
int
|
||||
CurlSocket::receive_socket(void* easy_handle, curl_socket_t fd, int what, void* userp, void* socketp) {
|
||||
CurlSocket::receive_socket([[maybe_unused]] void* easy_handle, curl_socket_t fd, int what, void* userp, void* socketp) {
|
||||
CurlStack* stack = (CurlStack*)userp;
|
||||
CurlSocket* socket = (CurlSocket*)socketp;
|
||||
|
||||
if (!stack->is_running())
|
||||
return 0;
|
||||
|
||||
if (what == CURL_POLL_REMOVE) {
|
||||
// We also probably need the special code here as we're not
|
||||
// guaranteed that the fd will be closed, afaik.
|
||||
@@ -75,7 +44,7 @@ CurlSocket::receive_socket(void* easy_handle, curl_socket_t fd, int what, void*
|
||||
// No interface for libcurl to signal when it's interested in error events.
|
||||
// Assume that hence it must always be interested in them.
|
||||
torrent::main_thread()->poll()->insert_error(socket);
|
||||
}
|
||||
}
|
||||
|
||||
if (what == CURL_POLL_NONE || what == CURL_POLL_OUT)
|
||||
torrent::main_thread()->poll()->remove_read(socket);
|
||||
@@ -91,8 +60,7 @@ CurlSocket::receive_socket(void* easy_handle, curl_socket_t fd, int what, void*
|
||||
}
|
||||
|
||||
CurlSocket::~CurlSocket() {
|
||||
if (m_fileDesc != -1)
|
||||
throw torrent::internal_error("CurlSocket::~CurlSocket() m_fileDesc != -1.");
|
||||
assert(m_fileDesc == -1 && "CurlSocket::~CurlSocket() m_fileDesc != -1.");
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
+39
-70
@@ -1,61 +1,18 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <curl/multi.h>
|
||||
#include <torrent/exceptions.h>
|
||||
|
||||
#include "rak/functional.h"
|
||||
#include "curl_get.h"
|
||||
#include "curl_socket.h"
|
||||
#include "curl_stack.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
CurlStack::CurlStack() :
|
||||
m_handle((void*)curl_multi_init()),
|
||||
m_active(0),
|
||||
m_maxActive(32),
|
||||
m_ssl_verify_host(true),
|
||||
m_ssl_verify_peer(true),
|
||||
m_dns_timeout(60) {
|
||||
|
||||
m_taskTimeout.slot() = std::bind(&CurlStack::receive_timeout, this);
|
||||
CurlStack::CurlStack() {
|
||||
m_handle = (void*)curl_multi_init();
|
||||
m_task_timeout.slot() = std::bind(&CurlStack::receive_timeout, this);
|
||||
|
||||
#if (LIBCURL_VERSION_NUM >= 0x071000)
|
||||
curl_multi_setopt((CURLM*)m_handle, CURLMOPT_TIMERDATA, this);
|
||||
@@ -66,11 +23,21 @@ CurlStack::CurlStack() :
|
||||
}
|
||||
|
||||
CurlStack::~CurlStack() {
|
||||
shutdown();
|
||||
}
|
||||
|
||||
void
|
||||
CurlStack::shutdown() {
|
||||
if (!m_running)
|
||||
return;
|
||||
|
||||
m_running = false;
|
||||
|
||||
while (!empty())
|
||||
front()->close();
|
||||
|
||||
curl_multi_cleanup((CURLM*)m_handle);
|
||||
priority_queue_erase(&taskScheduler, &m_taskTimeout);
|
||||
priority_queue_erase(&taskScheduler, &m_task_timeout);
|
||||
}
|
||||
|
||||
CurlGet*
|
||||
@@ -80,6 +47,9 @@ CurlStack::new_object() {
|
||||
|
||||
CurlSocket*
|
||||
CurlStack::new_socket(int fd) {
|
||||
if (!m_running)
|
||||
throw torrent::internal_error("CurlStack::new_socket() called when not running.");
|
||||
|
||||
CurlSocket* socket = new CurlSocket(fd, this);
|
||||
curl_multi_assign((CURLM*)m_handle, fd, socket);
|
||||
return socket;
|
||||
@@ -115,7 +85,7 @@ CurlStack::receive_action(CurlSocket* socket, int events) {
|
||||
; // Do nothing.
|
||||
|
||||
if (empty())
|
||||
priority_queue_erase(&taskScheduler, &m_taskTimeout);
|
||||
priority_queue_erase(&taskScheduler, &m_task_timeout);
|
||||
}
|
||||
|
||||
} while (code == CURLM_CALL_MULTI_PERFORM);
|
||||
@@ -133,11 +103,11 @@ CurlStack::process_done_handle() {
|
||||
throw torrent::internal_error("CurlStack::receive_action() msg->msg != CURLMSG_DONE.");
|
||||
|
||||
if (msg->data.result == CURLE_COULDNT_RESOLVE_HOST) {
|
||||
iterator itr = std::find_if(begin(), end(), rak::equal(msg->easy_handle, std::mem_fun(&CurlGet::handle)));
|
||||
|
||||
iterator itr = std::find_if(begin(), end(), [&msg](CurlGet* get) { return get->handle() == msg->easy_handle; });
|
||||
|
||||
if (itr == end())
|
||||
throw torrent::internal_error("Could not find CurlGet when calling CurlStack::receive_action.");
|
||||
|
||||
|
||||
if (!(*itr)->is_using_ipv6()) {
|
||||
(*itr)->retry_ipv6();
|
||||
|
||||
@@ -155,7 +125,7 @@ CurlStack::process_done_handle() {
|
||||
|
||||
void
|
||||
CurlStack::transfer_done(void* handle, const char* msg) {
|
||||
iterator itr = std::find_if(begin(), end(), rak::equal(handle, std::mem_fun(&CurlGet::handle)));
|
||||
iterator itr = std::find_if(begin(), end(), [&handle](CurlGet* get) { return get->handle() == handle; });
|
||||
|
||||
if (itr == end())
|
||||
throw torrent::internal_error("Could not find CurlGet with the right easy_handle.");
|
||||
@@ -171,30 +141,30 @@ CurlStack::receive_timeout() {
|
||||
receive_action(NULL, 0);
|
||||
|
||||
// Sometimes libcurl forgets to reset the timeout. Try to poll the value in that case, or use 10 seconds.
|
||||
if (!empty() && !m_taskTimeout.is_queued()) {
|
||||
if (!empty() && !m_task_timeout.is_queued()) {
|
||||
long timeout;
|
||||
curl_multi_timeout((CURLM*)m_handle, &timeout);
|
||||
priority_queue_insert(&taskScheduler, &m_taskTimeout,
|
||||
priority_queue_insert(&taskScheduler, &m_task_timeout,
|
||||
cachedTime + rak::timer::from_milliseconds(std::max<unsigned long>(timeout, 10000)));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CurlStack::add_get(CurlGet* get) {
|
||||
if (!m_userAgent.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_USERAGENT, m_userAgent.c_str());
|
||||
if (!m_user_agent.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_USERAGENT, m_user_agent.c_str());
|
||||
|
||||
if (!m_httpProxy.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_PROXY, m_httpProxy.c_str());
|
||||
if (!m_http_proxy.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_PROXY, m_http_proxy.c_str());
|
||||
|
||||
if (!m_bindAddress.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_INTERFACE, m_bindAddress.c_str());
|
||||
if (!m_bind_address.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_INTERFACE, m_bind_address.c_str());
|
||||
|
||||
if (!m_httpCaPath.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_CAPATH, m_httpCaPath.c_str());
|
||||
if (!m_http_ca_path.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_CAPATH, m_http_ca_path.c_str());
|
||||
|
||||
if (!m_httpCaCert.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_CAINFO, m_httpCaCert.c_str());
|
||||
if (!m_http_ca_cert.empty())
|
||||
curl_easy_setopt(get->handle(), CURLOPT_CAINFO, m_http_ca_cert.c_str());
|
||||
|
||||
curl_easy_setopt(get->handle(), CURLOPT_SSL_VERIFYHOST, (long)(m_ssl_verify_host ? 2 : 0));
|
||||
curl_easy_setopt(get->handle(), CURLOPT_SSL_VERIFYPEER, (long)(m_ssl_verify_peer ? 1 : 0));
|
||||
@@ -202,12 +172,12 @@ CurlStack::add_get(CurlGet* get) {
|
||||
|
||||
base_type::push_back(get);
|
||||
|
||||
if (m_active >= m_maxActive)
|
||||
if (m_active >= m_max_active)
|
||||
return;
|
||||
|
||||
m_active++;
|
||||
get->set_active(true);
|
||||
|
||||
|
||||
if (curl_multi_add_handle((CURLM*)m_handle, get->handle()) > 0)
|
||||
throw torrent::internal_error("Error calling curl_multi_add_handle.");
|
||||
|
||||
@@ -234,8 +204,8 @@ CurlStack::remove_get(CurlGet* get) {
|
||||
if (curl_multi_remove_handle((CURLM*)m_handle, get->handle()) > 0)
|
||||
throw torrent::internal_error("Error calling curl_multi_remove_handle.");
|
||||
|
||||
if (m_active == m_maxActive &&
|
||||
(itr = std::find_if(begin(), end(), std::not1(std::mem_fun(&CurlGet::is_active)))) != end()) {
|
||||
if (m_active == m_max_active &&
|
||||
(itr = std::find_if(begin(), end(), [](CurlGet* get) { return !get->is_active(); })) != end()) {
|
||||
(*itr)->set_active(true);
|
||||
|
||||
if (curl_multi_add_handle((CURLM*)m_handle, (*itr)->handle()) > 0)
|
||||
@@ -262,8 +232,7 @@ int
|
||||
CurlStack::set_timeout(void* handle, long timeout_ms, void* userp) {
|
||||
CurlStack* stack = (CurlStack*)userp;
|
||||
|
||||
priority_queue_erase(&taskScheduler, &stack->m_taskTimeout);
|
||||
priority_queue_insert(&taskScheduler, &stack->m_taskTimeout, cachedTime + rak::timer::from_milliseconds(timeout_ms));
|
||||
priority_queue_update(&taskScheduler, &stack->m_task_timeout, cachedTime + rak::timer::from_milliseconds(timeout_ms));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+28
-59
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RTORRENT_CORE_CURL_STACK_H
|
||||
#define RTORRENT_CORE_CURL_STACK_H
|
||||
|
||||
@@ -81,24 +45,27 @@ class CurlStack : std::deque<CurlGet*> {
|
||||
CurlStack();
|
||||
~CurlStack();
|
||||
|
||||
void shutdown();
|
||||
bool is_running() const { return m_running; }
|
||||
|
||||
CurlGet* new_object();
|
||||
CurlSocket* new_socket(int fd);
|
||||
|
||||
unsigned int active() const { return m_active; }
|
||||
unsigned int max_active() const { return m_maxActive; }
|
||||
void set_max_active(unsigned int a) { m_maxActive = a; }
|
||||
unsigned int max_active() const { return m_max_active; }
|
||||
void set_max_active(unsigned int a) { m_max_active = a; }
|
||||
|
||||
const std::string& user_agent() const { return m_userAgent; }
|
||||
const std::string& http_proxy() const { return m_httpProxy; }
|
||||
const std::string& bind_address() const { return m_bindAddress; }
|
||||
const std::string& http_capath() const { return m_httpCaPath; }
|
||||
const std::string& http_cacert() const { return m_httpCaCert; }
|
||||
const std::string& user_agent() const { return m_user_agent; }
|
||||
const std::string& http_proxy() const { return m_http_proxy; }
|
||||
const std::string& bind_address() const { return m_bind_address; }
|
||||
const std::string& http_capath() const { return m_http_ca_path; }
|
||||
const std::string& http_cacert() const { return m_http_ca_cert; }
|
||||
|
||||
void set_user_agent(const std::string& s) { m_userAgent = s; }
|
||||
void set_http_proxy(const std::string& s) { m_httpProxy = s; }
|
||||
void set_bind_address(const std::string& s) { m_bindAddress = s; }
|
||||
void set_http_capath(const std::string& s) { m_httpCaPath = s; }
|
||||
void set_http_cacert(const std::string& s) { m_httpCaCert = s; }
|
||||
void set_user_agent(const std::string& s) { m_user_agent = s; }
|
||||
void set_http_proxy(const std::string& s) { m_http_proxy = s; }
|
||||
void set_bind_address(const std::string& s) { m_bind_address = s; }
|
||||
void set_http_capath(const std::string& s) { m_http_ca_path = s; }
|
||||
void set_http_cacert(const std::string& s) { m_http_ca_cert = s; }
|
||||
|
||||
bool ssl_verify_host() const { return m_ssl_verify_host; }
|
||||
bool ssl_verify_peer() const { return m_ssl_verify_peer; }
|
||||
@@ -131,20 +98,22 @@ class CurlStack : std::deque<CurlGet*> {
|
||||
|
||||
void* m_handle;
|
||||
|
||||
unsigned int m_active;
|
||||
unsigned int m_maxActive;
|
||||
bool m_running{true};
|
||||
|
||||
rak::priority_item m_taskTimeout;
|
||||
unsigned int m_active{0};
|
||||
unsigned int m_max_active{32};
|
||||
|
||||
std::string m_userAgent;
|
||||
std::string m_httpProxy;
|
||||
std::string m_bindAddress;
|
||||
std::string m_httpCaPath;
|
||||
std::string m_httpCaCert;
|
||||
rak::priority_item m_task_timeout;
|
||||
|
||||
bool m_ssl_verify_host;
|
||||
bool m_ssl_verify_peer;
|
||||
long m_dns_timeout;
|
||||
std::string m_user_agent;
|
||||
std::string m_http_proxy;
|
||||
std::string m_bind_address;
|
||||
std::string m_http_ca_path;
|
||||
std::string m_http_ca_cert;
|
||||
|
||||
bool m_ssl_verify_host{true};
|
||||
bool m_ssl_verify_peer{true};
|
||||
long m_dns_timeout{60};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+23
-59
@@ -1,47 +1,11 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <torrent/object.h>
|
||||
#include <torrent/dht_manager.h>
|
||||
#include <torrent/object_stream.h>
|
||||
#include <torrent/rate.h>
|
||||
#include <torrent/tracker/dht_controller.h>
|
||||
#include <torrent/utils/log.h>
|
||||
|
||||
#include "rpc/parse_commands.h"
|
||||
@@ -94,7 +58,7 @@ DhtManager::load_dht_cache() {
|
||||
LT_LOG_THIS("could not open cache file (path:%s)", cache_filename.c_str());
|
||||
}
|
||||
|
||||
torrent::dht_manager()->initialize(cache);
|
||||
torrent::dht_controller()->initialize(cache);
|
||||
|
||||
if (m_start == dht_on)
|
||||
start_dht();
|
||||
@@ -104,31 +68,31 @@ void
|
||||
DhtManager::start_dht() {
|
||||
priority_queue_erase(&taskScheduler, &m_stopTimeout);
|
||||
|
||||
if (!torrent::dht_manager()->is_valid()) {
|
||||
if (!torrent::dht_controller()->is_valid()) {
|
||||
LT_LOG_THIS("server start skipped, manager is uninitialized", 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (torrent::dht_manager()->is_active()) {
|
||||
if (torrent::dht_controller()->is_active()) {
|
||||
LT_LOG_THIS("server start skipped, already active", 0);
|
||||
return;
|
||||
}
|
||||
|
||||
torrent::ThrottlePair throttles = control->core()->get_throttle(m_throttleName);
|
||||
torrent::dht_manager()->set_upload_throttle(throttles.first);
|
||||
torrent::dht_manager()->set_download_throttle(throttles.second);
|
||||
torrent::dht_controller()->set_upload_throttle(throttles.first);
|
||||
torrent::dht_controller()->set_download_throttle(throttles.second);
|
||||
|
||||
int port = rpc::call_command_value("dht.port");
|
||||
|
||||
if (port <= 0)
|
||||
return;
|
||||
|
||||
if (!torrent::dht_manager()->start(port)) {
|
||||
if (!torrent::dht_controller()->start(port)) {
|
||||
m_start = dht_off;
|
||||
return;
|
||||
}
|
||||
|
||||
torrent::dht_manager()->reset_statistics();
|
||||
torrent::dht_controller()->reset_statistics();
|
||||
|
||||
m_updateTimeout.slot() = std::bind(&DhtManager::update, this);
|
||||
priority_queue_insert(&taskScheduler, &m_updateTimeout, (cachedTime + rak::timer::from_seconds(60)).round_seconds());
|
||||
@@ -146,17 +110,17 @@ DhtManager::stop_dht() {
|
||||
priority_queue_erase(&taskScheduler, &m_updateTimeout);
|
||||
priority_queue_erase(&taskScheduler, &m_stopTimeout);
|
||||
|
||||
if (torrent::dht_manager()->is_active()) {
|
||||
if (torrent::dht_controller()->is_active()) {
|
||||
LT_LOG_THIS("stopping server", 0);
|
||||
|
||||
log_statistics(true);
|
||||
torrent::dht_manager()->stop();
|
||||
torrent::dht_controller()->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DhtManager::save_dht_cache() {
|
||||
if (!control->core()->download_store()->is_enabled() || !torrent::dht_manager()->is_valid())
|
||||
if (!control->core()->download_store()->is_enabled() || !torrent::dht_controller()->is_valid())
|
||||
return;
|
||||
|
||||
std::string filename = control->core()->download_store()->path() + "rtorrent.dht_cache";
|
||||
@@ -167,7 +131,7 @@ DhtManager::save_dht_cache() {
|
||||
return;
|
||||
|
||||
torrent::Object cache = torrent::Object::create_map();
|
||||
cache_file << *torrent::dht_manager()->store_cache(&cache);
|
||||
cache_file << *torrent::dht_controller()->store_cache(&cache);
|
||||
|
||||
if (!cache_file.good())
|
||||
return;
|
||||
@@ -198,7 +162,7 @@ DhtManager::set_mode(const std::string& arg) {
|
||||
|
||||
void
|
||||
DhtManager::update() {
|
||||
if (!torrent::dht_manager()->is_active())
|
||||
if (!torrent::dht_controller()->is_active())
|
||||
throw torrent::internal_error("DhtManager::update called with DHT inactive.");
|
||||
|
||||
if (m_start == dht_auto && !m_stopTimeout.is_queued()) {
|
||||
@@ -207,7 +171,7 @@ DhtManager::update() {
|
||||
for (itr = control->core()->download_list()->begin(), end = control->core()->download_list()->end(); itr != end; ++itr)
|
||||
if ((*itr)->download()->info()->is_active() && !(*itr)->download()->info()->is_private())
|
||||
break;
|
||||
|
||||
|
||||
if (itr == end) {
|
||||
m_stopTimeout.slot() = std::bind(&DhtManager::stop_dht, this);
|
||||
priority_queue_insert(&taskScheduler, &m_stopTimeout, (cachedTime + rak::timer::from_seconds(15 * 60)).round_seconds());
|
||||
@@ -223,17 +187,17 @@ DhtManager::update() {
|
||||
|
||||
bool
|
||||
DhtManager::log_statistics(bool force) {
|
||||
torrent::DhtManager::statistics_type stats = torrent::dht_manager()->get_statistics();
|
||||
auto stats = torrent::dht_controller()->get_statistics();
|
||||
|
||||
// Check for firewall problems.
|
||||
|
||||
if (stats.cycle > 2 && stats.queries_sent - m_dhtPrevQueriesSent > 100 && stats.queries_received == m_dhtPrevQueriesReceived) {
|
||||
// We should have had clients ping us at least but have received
|
||||
// nothing, that means the UDP port is probably unreachable.
|
||||
if (torrent::dht_manager()->can_receive_queries())
|
||||
if (torrent::dht_controller()->is_receiving_requests())
|
||||
LT_LOG_THIS("listening port appears to be unreachable, no queries received", 0);
|
||||
|
||||
torrent::dht_manager()->set_can_receive(false);
|
||||
torrent::dht_controller()->set_receive_requests(false);
|
||||
}
|
||||
|
||||
if (stats.queries_sent - m_dhtPrevQueriesSent > stats.num_nodes * 2 + 20 && stats.replies_received == m_dhtPrevRepliesReceived) {
|
||||
@@ -248,7 +212,7 @@ DhtManager::log_statistics(bool force) {
|
||||
m_warned = false;
|
||||
|
||||
if (stats.queries_received > m_dhtPrevQueriesReceived)
|
||||
torrent::dht_manager()->set_can_receive(true);
|
||||
torrent::dht_controller()->set_receive_requests(true);
|
||||
|
||||
// Nothing to log while bootstrapping, but check again every minute.
|
||||
if (stats.cycle <= 1) {
|
||||
@@ -269,7 +233,7 @@ DhtManager::log_statistics(bool force) {
|
||||
// afterwards (i.e. every 2 hours), or when forced.
|
||||
if ((force && stats.cycle != m_dhtPrevCycle) || stats.cycle == 3 || stats.cycle > m_dhtPrevCycle + 7) {
|
||||
char buffer[256];
|
||||
snprintf(buffer, sizeof(buffer),
|
||||
snprintf(buffer, sizeof(buffer),
|
||||
"DHT statistics: %d queries in, %d queries out, %d replies received, %lld bytes read, %lld bytes sent, "
|
||||
"%d known nodes in %d buckets, %d peers (highest: %d) tracked in %d torrents.",
|
||||
stats.queries_received - m_dhtPrevQueriesReceived,
|
||||
@@ -301,11 +265,11 @@ DhtManager::dht_statistics() {
|
||||
torrent::Object dhtStats = torrent::Object::create_map();
|
||||
|
||||
dhtStats.insert_key("dht", dht_settings[m_start]);
|
||||
dhtStats.insert_key("active", torrent::dht_manager()->is_active());
|
||||
dhtStats.insert_key("active", torrent::dht_controller()->is_active());
|
||||
dhtStats.insert_key("throttle", m_throttleName);
|
||||
|
||||
if (torrent::dht_manager()->is_active()) {
|
||||
torrent::DhtManager::statistics_type stats = torrent::dht_manager()->get_statistics();
|
||||
if (torrent::dht_controller()->is_active()) {
|
||||
auto stats = torrent::dht_controller()->get_statistics();
|
||||
|
||||
dhtStats.insert_key("cycle", stats.cycle);
|
||||
dhtStats.insert_key("queries_received", stats.queries_received);
|
||||
@@ -327,7 +291,7 @@ DhtManager::dht_statistics() {
|
||||
|
||||
void
|
||||
DhtManager::set_throttle_name(const std::string& throttleName) {
|
||||
if (torrent::dht_manager()->is_active())
|
||||
if (torrent::dht_controller()->is_active())
|
||||
throw torrent::input_error("Cannot set DHT throttle while active.");
|
||||
|
||||
m_throttleName = throttleName;
|
||||
|
||||
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RTORRENT_CORE_DHT_MANAGER_H
|
||||
#define RTORRENT_CORE_DHT_MANAGER_H
|
||||
|
||||
|
||||
+4
-41
@@ -1,50 +1,13 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <list>
|
||||
#include <rak/file_stat.h>
|
||||
#include <rak/functional.h>
|
||||
#include <rak/path.h>
|
||||
#include <torrent/exceptions.h>
|
||||
#include <torrent/rate.h>
|
||||
#include <torrent/torrent.h>
|
||||
#include <torrent/tracker.h>
|
||||
#include <torrent/tracker_list.h>
|
||||
#include <torrent/tracker/tracker.h>
|
||||
#include <torrent/data/file_list.h>
|
||||
|
||||
#include "rpc/parse_commands.h"
|
||||
@@ -76,11 +39,11 @@ Download::~Download() {
|
||||
void
|
||||
Download::enable_udp_trackers(bool state) {
|
||||
for (torrent::TrackerList::iterator itr = m_download.tracker_list()->begin(), last = m_download.tracker_list()->end(); itr != last; ++itr)
|
||||
if ((*itr)->type() == torrent::Tracker::TRACKER_UDP) {
|
||||
if (itr->type() == torrent::TRACKER_UDP) {
|
||||
if (state)
|
||||
(*itr)->enable();
|
||||
itr->enable();
|
||||
else
|
||||
(*itr)->disable();
|
||||
itr->disable();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-49
@@ -1,42 +1,7 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RTORRENT_CORE_DOWNLOAD_H
|
||||
#define RTORRENT_CORE_DOWNLOAD_H
|
||||
|
||||
#include <torrent/common.h>
|
||||
#include <torrent/download.h>
|
||||
#include <torrent/download_info.h>
|
||||
#include <torrent/hash_string.h>
|
||||
@@ -46,11 +11,6 @@
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
namespace torrent {
|
||||
class PeerList;
|
||||
class TrackerList;
|
||||
}
|
||||
|
||||
namespace core {
|
||||
|
||||
class Download {
|
||||
@@ -59,7 +19,6 @@ public:
|
||||
typedef torrent::FileList file_list_type;
|
||||
typedef torrent::PeerList peer_list_type;
|
||||
typedef torrent::TrackerList tracker_list_type;
|
||||
typedef torrent::TrackerController tracker_controller_type;
|
||||
typedef torrent::ConnectionList connection_list_type;
|
||||
typedef download_type::ConnectionType connection_type;
|
||||
|
||||
@@ -71,10 +30,10 @@ public:
|
||||
Download(download_type d);
|
||||
~Download();
|
||||
|
||||
const torrent::DownloadInfo* info() const { return m_download.info(); }
|
||||
const torrent::download_data* data() const { return m_download.data(); }
|
||||
auto info() const { return m_download.info(); }
|
||||
auto data() const { return m_download.data(); }
|
||||
|
||||
torrent::DownloadMain* main() { return m_download.main(); }
|
||||
auto main() { return m_download.main(); }
|
||||
|
||||
bool is_open() const { return m_download.info()->is_open(); }
|
||||
bool is_active() const { return m_download.info()->is_active(); }
|
||||
@@ -102,13 +61,12 @@ public:
|
||||
|
||||
torrent::Object* bencode() { return m_download.bencode(); }
|
||||
|
||||
auto tracker_controller() { return m_download.tracker_controller(); }
|
||||
tracker_list_type* tracker_list() { return m_download.tracker_list(); }
|
||||
uint32_t tracker_list_size() const { return m_download.tracker_list()->size(); }
|
||||
|
||||
tracker_controller_type* tracker_controller() { return m_download.tracker_controller(); }
|
||||
|
||||
connection_list_type* connection_list() { return m_download.connection_list(); }
|
||||
uint32_t connection_list_size() const;
|
||||
auto connection_list() { return m_download.connection_list(); }
|
||||
uint32_t connection_list_size() const;
|
||||
|
||||
const std::string& message() const { return m_message; }
|
||||
void set_message(const std::string& msg) { m_message = msg; }
|
||||
|
||||
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <cstdlib>
|
||||
@@ -73,21 +37,20 @@ is_network_uri(const std::string& uri) {
|
||||
std::strncmp(uri.c_str(), "ftp://", 6) == 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
download_factory_add_stream(torrent::Object* root, const char* key, const char* filename) {
|
||||
static std::unique_ptr<torrent::Object>
|
||||
download_factory_load_stream(const char* filename) {
|
||||
std::fstream stream(filename, std::ios::in | std::ios::binary);
|
||||
|
||||
if (!stream.is_open())
|
||||
return false;
|
||||
|
||||
torrent::Object obj;
|
||||
stream >> obj;
|
||||
if (!stream.is_open())
|
||||
return std::unique_ptr<torrent::Object>();
|
||||
|
||||
auto obj = std::make_unique<torrent::Object>();
|
||||
stream >> *obj;
|
||||
|
||||
if (!stream.good())
|
||||
return false;
|
||||
return std::unique_ptr<torrent::Object>();
|
||||
|
||||
root->insert_key_move(key, obj);
|
||||
return true;
|
||||
return obj;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -209,9 +172,19 @@ DownloadFactory::receive_commit() {
|
||||
|
||||
void
|
||||
DownloadFactory::receive_success() {
|
||||
auto rtorrent_object = download_factory_load_stream((rak::path_expand(m_uri) + ".rtorrent").c_str());
|
||||
auto libtorrent_resume_object = download_factory_load_stream((rak::path_expand(m_uri) + ".libtorrent_resume").c_str());
|
||||
|
||||
uint32_t tracker_key;
|
||||
|
||||
if (rtorrent_object && rtorrent_object->has_key_value("key"))
|
||||
tracker_key = rtorrent_object->get_key_value("key");
|
||||
else
|
||||
tracker_key = random() % (std::numeric_limits<uint32_t>::max() - 1) + 1;
|
||||
|
||||
Download* download = m_stream != NULL ?
|
||||
m_manager->download_list()->create(m_stream, m_printLog) :
|
||||
m_manager->download_list()->create(m_object, m_printLog);
|
||||
m_manager->download_list()->create(m_stream, tracker_key, m_printLog) :
|
||||
m_manager->download_list()->create(m_object, tracker_key, m_printLog);
|
||||
|
||||
m_object = NULL;
|
||||
|
||||
@@ -228,7 +201,7 @@ DownloadFactory::receive_success() {
|
||||
torrent::Object& meta = root->insert_key("rtorrent_meta_download", torrent::Object::create_map());
|
||||
meta.insert_key("start", m_start);
|
||||
meta.insert_key("print_log", m_printLog);
|
||||
|
||||
|
||||
torrent::Object::list_type& commands = meta.insert_key("commands", torrent::Object::create_list()).as_list();
|
||||
|
||||
for (command_list_type::iterator itr = m_commands.begin(); itr != m_commands.end(); ++itr)
|
||||
@@ -236,9 +209,12 @@ DownloadFactory::receive_success() {
|
||||
}
|
||||
|
||||
if (m_session) {
|
||||
download_factory_add_stream(root, "rtorrent", (rak::path_expand(m_uri) + ".rtorrent").c_str());
|
||||
download_factory_add_stream(root, "libtorrent_resume", (rak::path_expand(m_uri) + ".libtorrent_resume").c_str());
|
||||
|
||||
if (rtorrent_object)
|
||||
root->insert_key_move("rtorrent", *rtorrent_object);
|
||||
|
||||
if (libtorrent_resume_object)
|
||||
root->insert_key_move("libtorrent_resume", *libtorrent_resume_object);
|
||||
|
||||
} else {
|
||||
// We only allow session torrents to keep their
|
||||
// 'rtorrent/libtorrent' sections. The "fast_resume" section
|
||||
@@ -249,6 +225,8 @@ DownloadFactory::receive_success() {
|
||||
torrent::Object* rtorrent = &root->insert_preserve_copy("rtorrent", torrent::Object::create_map()).first->second;
|
||||
torrent::Object& resumeObject = root->insert_preserve_copy("libtorrent_resume", torrent::Object::create_map()).first->second;
|
||||
|
||||
rtorrent->insert_key("key", download->tracker_list()->key());
|
||||
|
||||
initialize_rtorrent(download, rtorrent);
|
||||
|
||||
if (!rtorrent->has_key_string("custom1")) rtorrent->insert_key("custom1", std::string());
|
||||
@@ -321,8 +299,9 @@ DownloadFactory::receive_success() {
|
||||
if (torrent::log_groups[torrent::LOG_TORRENT_DEBUG].valid())
|
||||
log_created(download, rtorrent);
|
||||
|
||||
std::for_each(m_commands.begin(), m_commands.end(),
|
||||
rak::bind2nd(std::ptr_fun(&rpc::parse_command_multiple_std), rpc::make_target(download)));
|
||||
std::for_each(m_commands.begin(), m_commands.end(), [&download](const std::string& cmd) {
|
||||
rpc::parse_command_multiple_std(cmd, rpc::make_target(download));
|
||||
});
|
||||
|
||||
if (m_manager->download_list()->find(infohash) == m_manager->download_list()->end())
|
||||
throw torrent::input_error("The newly created download was removed.");
|
||||
@@ -338,7 +317,7 @@ DownloadFactory::receive_success() {
|
||||
|
||||
if (m_printLog)
|
||||
m_manager->push_log_std(msg);
|
||||
|
||||
|
||||
if (m_manager->download_list()->find(infohash) != m_manager->download_list()->end()) {
|
||||
// Should stop it, mark it bad. Perhaps even delete it?
|
||||
download->set_hash_failed(true);
|
||||
@@ -413,14 +392,6 @@ DownloadFactory::initialize_rtorrent(Download* download, torrent::Object* rtorre
|
||||
else
|
||||
rpc::call_command("d.priority.set", (int64_t)2, rpc::make_target(download));
|
||||
|
||||
if (rtorrent->has_key_value("key")) {
|
||||
download->tracker_list()->set_key(rtorrent->get_key_value("key"));
|
||||
|
||||
} else {
|
||||
download->tracker_list()->set_key(random() % (std::numeric_limits<uint32_t>::max() - 1) + 1);
|
||||
rtorrent->insert_key("key", download->tracker_list()->key());
|
||||
}
|
||||
|
||||
if (rtorrent->has_key_value("total_uploaded"))
|
||||
download->info()->mutable_up_rate()->set_total(rtorrent->get_key_value("total_uploaded"));
|
||||
|
||||
|
||||
+16
-53
@@ -1,45 +1,8 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <rak/functional.h>
|
||||
#include <rak/string_manip.h>
|
||||
#include <torrent/data/file.h>
|
||||
#include <torrent/utils/resume.h>
|
||||
@@ -71,7 +34,7 @@
|
||||
namespace core {
|
||||
|
||||
inline void
|
||||
DownloadList::check_contains(Download* d) {
|
||||
DownloadList::check_contains([[maybe_unused]] Download* d) {
|
||||
#ifdef USE_EXTRA_DEBUG
|
||||
if (std::find(begin(), end(), d) == end())
|
||||
throw torrent::internal_error("DownloadList::check_contains(...) failed.");
|
||||
@@ -80,15 +43,15 @@ DownloadList::check_contains(Download* d) {
|
||||
|
||||
void
|
||||
DownloadList::clear() {
|
||||
std::for_each(begin(), end(), std::bind1st(std::mem_fun(&DownloadList::close), this));
|
||||
std::for_each(begin(), end(), rak::call_delete<Download>());
|
||||
std::for_each(begin(), end(), [&](Download* d) { close(d); });
|
||||
std::for_each(begin(), end(), [](Download* d) { delete d; });
|
||||
|
||||
base_type::clear();
|
||||
}
|
||||
|
||||
void
|
||||
DownloadList::session_save() {
|
||||
unsigned int c = std::count_if(begin(), end(), std::bind1st(std::mem_fun(&DownloadStore::save_resume), control->core()->download_store()));
|
||||
unsigned int c = std::count_if(begin(), end(), [&](Download* d) { return control->core()->download_store()->save_resume(d); });
|
||||
|
||||
if (c != size())
|
||||
lt_log_print(torrent::LOG_ERROR, "Failed to save session torrents.");
|
||||
@@ -99,7 +62,7 @@ DownloadList::session_save() {
|
||||
|
||||
DownloadList::iterator
|
||||
DownloadList::find(const torrent::HashString& hash) {
|
||||
return std::find_if(begin(), end(), rak::equal(hash, rak::on(std::mem_fun(&Download::info), std::mem_fun(&torrent::DownloadInfo::hash))));
|
||||
return std::find_if(begin(), end(), [hash](Download* d) { return hash == d->info()->hash(); });
|
||||
}
|
||||
|
||||
DownloadList::iterator
|
||||
@@ -109,7 +72,7 @@ DownloadList::find_hex(const char* hash) {
|
||||
for (torrent::HashString::iterator itr = key.begin(), last = key.end(); itr != last; itr++, hash += 2)
|
||||
*itr = (rak::hexchar_to_value(*hash) << 4) + rak::hexchar_to_value(*(hash + 1));
|
||||
|
||||
return std::find_if(begin(), end(), rak::equal(key, rak::on(std::mem_fun(&Download::info), std::mem_fun(&torrent::DownloadInfo::hash))));
|
||||
return std::find_if(begin(), end(), [key](Download* d) { return key == d->info()->hash(); });
|
||||
}
|
||||
|
||||
Download*
|
||||
@@ -120,11 +83,11 @@ DownloadList::find_hex_ptr(const char* hash) {
|
||||
}
|
||||
|
||||
Download*
|
||||
DownloadList::create(torrent::Object* obj, bool printLog) {
|
||||
DownloadList::create(torrent::Object* obj, uint32_t tracker_key, bool printLog) {
|
||||
torrent::Download download;
|
||||
|
||||
try {
|
||||
download = torrent::download_add(obj);
|
||||
download = torrent::download_add(obj, tracker_key);
|
||||
|
||||
} catch (torrent::local_error& e) {
|
||||
delete obj;
|
||||
@@ -141,13 +104,13 @@ DownloadList::create(torrent::Object* obj, bool printLog) {
|
||||
}
|
||||
|
||||
Download*
|
||||
DownloadList::create(std::istream* str, bool printLog) {
|
||||
DownloadList::create(std::istream* str, uint32_t tracker_key, bool printLog) {
|
||||
torrent::Object* object = new torrent::Object;
|
||||
torrent::Download download;
|
||||
|
||||
try {
|
||||
*str >> *object;
|
||||
|
||||
|
||||
// Don't throw input_error from here as gcc-3.3.5 produces bad
|
||||
// code.
|
||||
if (str->fail()) {
|
||||
@@ -159,7 +122,7 @@ DownloadList::create(std::istream* str, bool printLog) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
download = torrent::download_add(object);
|
||||
download = torrent::download_add(object, tracker_key);
|
||||
|
||||
} catch (torrent::local_error& e) {
|
||||
delete object;
|
||||
@@ -187,8 +150,8 @@ DownloadList::insert(Download* download) {
|
||||
|
||||
// This needs to be separated into two different calls to ensure
|
||||
// the download remains in the view.
|
||||
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), std::bind2nd(std::mem_fun(&View::insert), download));
|
||||
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), std::bind2nd(std::mem_fun(&View::filter_download), download));
|
||||
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), [&download](View* v) { v->insert(download); });
|
||||
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), [&download](View* v) { v->filter_download(download); });
|
||||
|
||||
DL_TRIGGER_EVENT(*itr, "event.download.inserted");
|
||||
|
||||
@@ -221,7 +184,7 @@ DownloadList::erase(iterator itr) {
|
||||
control->core()->download_store()->remove(*itr);
|
||||
|
||||
DL_TRIGGER_EVENT(*itr, "event.download.erased");
|
||||
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), std::bind2nd(std::mem_fun(&View::erase), *itr));
|
||||
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), [itr](View* v) { v->erase(*itr); });
|
||||
|
||||
torrent::download_remove(*(*itr)->download());
|
||||
delete *itr;
|
||||
@@ -550,8 +513,8 @@ DownloadList::hash_done(Download* download) {
|
||||
if (download->is_done()) {
|
||||
confirm_finished(download);
|
||||
} else {
|
||||
download->set_message("Hash check on download completion found bad chunks, consider using \"safe_sync\".");
|
||||
lt_log_print(torrent::LOG_TORRENT_ERROR, "Hash check on download completion found bad chunks, consider using \"safe_sync\".");
|
||||
download->set_message("Hash check on download completion found bad chunks.");
|
||||
lt_log_print(torrent::LOG_TORRENT_ERROR, "Hash check on download completion found bad chunks.");
|
||||
DL_TRIGGER_EVENT(download, "event.download.hash_final_failed");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RTORRENT_CORE_DOWNLOAD_LIST_H
|
||||
#define RTORRENT_CORE_DOWNLOAD_LIST_H
|
||||
|
||||
@@ -43,6 +7,7 @@
|
||||
|
||||
namespace torrent {
|
||||
class HashString;
|
||||
class Object;
|
||||
}
|
||||
|
||||
namespace core {
|
||||
@@ -86,8 +51,8 @@ public:
|
||||
Download* find_hex_ptr(const char* hash);
|
||||
|
||||
// Might move this to DownloadFactory.
|
||||
Download* create(std::istream* str, bool printLog);
|
||||
Download* create(torrent::Object* obj, bool printLog);
|
||||
Download* create(std::istream* str, uint32_t tracker_key, bool printLog);
|
||||
Download* create(torrent::Object* obj, uint32_t tracker_key, bool printLog);
|
||||
|
||||
iterator insert(Download* d);
|
||||
|
||||
|
||||
+11
-40
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
// DownloadStore handles the saving and listing of session torrents.
|
||||
|
||||
#include "config.h"
|
||||
@@ -56,6 +20,7 @@
|
||||
|
||||
#include "download.h"
|
||||
#include "download_store.h"
|
||||
#include "rpc/parse_commands.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
@@ -129,8 +94,14 @@ DownloadStore::write_bencode(const std::string& filename, const torrent::Object&
|
||||
if (fd < 0)
|
||||
goto download_store_save_error;
|
||||
|
||||
fdatasync(fd);
|
||||
::close(fd);
|
||||
if (rpc::call_command_value("system.files.session.fdatasync")) {
|
||||
#ifdef __APPLE__
|
||||
fsync(fd);
|
||||
#else
|
||||
fdatasync(fd);
|
||||
#endif
|
||||
::close(fd);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -173,7 +144,7 @@ DownloadStore::save(Download* d, int flags) {
|
||||
|
||||
::rename((base_filename + ".libtorrent_resume.new").c_str(), (base_filename + ".libtorrent_resume").c_str());
|
||||
::rename((base_filename + ".rtorrent.new").c_str(), (base_filename + ".rtorrent").c_str());
|
||||
|
||||
|
||||
if (!(flags & flag_skip_static) &&
|
||||
write_bencode(base_filename + ".new", *d->bencode(), torrent::Object::flag_session_data))
|
||||
::rename((base_filename + ".new").c_str(), base_filename.c_str());
|
||||
@@ -207,7 +178,7 @@ DownloadStore::get_formated_entries() {
|
||||
if (!d.update(utils::Directory::update_hide_dot))
|
||||
throw torrent::storage_error("core::DownloadStore::update() could not open directory \"" + m_path + "\"");
|
||||
|
||||
d.erase(std::remove_if(d.begin(), d.end(), std::ptr_fun(¬_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
|
||||
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
#include <sstream>
|
||||
#include <torrent/http.h>
|
||||
|
||||
#include "rak/functional.h"
|
||||
#include "http_queue.h"
|
||||
#include "curl_get.h"
|
||||
|
||||
@@ -48,7 +47,7 @@ namespace core {
|
||||
|
||||
HttpQueue::iterator
|
||||
HttpQueue::insert(const std::string& url, std::iostream* s) {
|
||||
std::auto_ptr<CurlGet> h(m_slot_factory());
|
||||
std::unique_ptr<CurlGet> h(m_slot_factory());
|
||||
|
||||
h->set_url(url);
|
||||
h->set_stream(s);
|
||||
|
||||
+41
-51
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <cstdio>
|
||||
@@ -59,6 +23,7 @@
|
||||
|
||||
#include "rpc/parse_commands.h"
|
||||
#include "utils/directory.h"
|
||||
#include "utils/base64.h"
|
||||
#include "utils/file_status_cache.h"
|
||||
|
||||
#include "globals.h"
|
||||
@@ -186,6 +151,8 @@ Manager::initialize_second() {
|
||||
|
||||
void
|
||||
Manager::cleanup() {
|
||||
m_httpStack->shutdown();
|
||||
|
||||
// Need to disconnect log signals? Not really since we won't receive
|
||||
// any more.
|
||||
|
||||
@@ -198,15 +165,14 @@ Manager::cleanup() {
|
||||
|
||||
delete m_httpStack;
|
||||
CurlStack::global_cleanup();
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
Manager::shutdown(bool force) {
|
||||
if (!force)
|
||||
std::for_each(m_downloadList->begin(), m_downloadList->end(), std::bind1st(std::mem_fun(&DownloadList::pause_default), m_downloadList));
|
||||
std::for_each(m_downloadList->begin(), m_downloadList->end(), [this](Download* d) { m_downloadList->pause_default(d); });
|
||||
else
|
||||
std::for_each(m_downloadList->begin(), m_downloadList->end(), std::bind1st(std::mem_fun(&DownloadList::close_quick), m_downloadList));
|
||||
std::for_each(m_downloadList->begin(), m_downloadList->end(), [this](Download* d) { m_downloadList->close_quick(d); });
|
||||
}
|
||||
|
||||
void
|
||||
@@ -222,7 +188,7 @@ Manager::listen_open() {
|
||||
if (portRange.is_string()) {
|
||||
if (std::sscanf(portRange.as_string().c_str(), "%i-%i", &portFirst, &portLast) != 2)
|
||||
throw torrent::input_error("Invalid port_range argument.");
|
||||
|
||||
|
||||
// } else if (portRange.is_list()) {
|
||||
|
||||
} else {
|
||||
@@ -329,12 +295,12 @@ Manager::set_proxy_address(const std::string& addr) {
|
||||
|
||||
if ((err = rak::address_info::get_address_info(buf, PF_INET, SOCK_STREAM, &ai)) != 0)
|
||||
throw torrent::input_error("Could not set proxy address: " + std::string(rak::address_info::strerror(err)) + ".");
|
||||
|
||||
|
||||
try {
|
||||
|
||||
ai->address()->set_port(port);
|
||||
torrent::connection_manager()->set_proxy_address(ai->address()->c_sockaddr());
|
||||
|
||||
|
||||
rak::address_info::free_address_info(ai);
|
||||
|
||||
} catch (torrent::input_error& e) {
|
||||
@@ -348,6 +314,21 @@ Manager::receive_http_failed(std::string msg) {
|
||||
push_log_std("Http download error: \"" + msg + "\"");
|
||||
}
|
||||
|
||||
bool
|
||||
is_data_uri(const std::string& uri) {
|
||||
return std::strncmp(uri.c_str(), "data:", 5) == 0;
|
||||
}
|
||||
|
||||
std::string
|
||||
decode_data_uri(const std::string& uri) {
|
||||
const auto start = uri.find("base64,", 5) + 7;
|
||||
if (start == std::string::npos)
|
||||
throw torrent::input_error("Invalid data uri: not base64 encoded.");
|
||||
if (start >= uri.size())
|
||||
throw torrent::input_error("Empty base64.");
|
||||
return utils::decode_base64(uri.substr(start));
|
||||
}
|
||||
|
||||
void
|
||||
Manager::try_create_download(const std::string& uri, int flags, const command_list_type& commands) {
|
||||
// If the path was attempted loaded before, skip it.
|
||||
@@ -355,6 +336,7 @@ Manager::try_create_download(const std::string& uri, int flags, const command_li
|
||||
!(flags & create_raw_data) &&
|
||||
!is_network_uri(uri) &&
|
||||
!is_magnet_uri(uri) &&
|
||||
!is_data_uri(uri) &&
|
||||
!file_status_cache()->insert(uri, 0))
|
||||
return;
|
||||
|
||||
@@ -366,12 +348,18 @@ Manager::try_create_download(const std::string& uri, int flags, const command_li
|
||||
|
||||
f->set_start(flags & create_start);
|
||||
f->set_print_log(!(flags & create_quiet));
|
||||
f->slot_finished(std::bind(&rak::call_delete_func<core::DownloadFactory>, f));
|
||||
f->slot_finished([f]() { delete f; });
|
||||
|
||||
if (flags & create_raw_data)
|
||||
if (is_data_uri(uri)) {
|
||||
// Allow the use of data URIs, primarily for JSON-RPC which
|
||||
// doesn't have a defined mechanism for binary data
|
||||
f->load_raw_data(decode_data_uri(uri));
|
||||
f->variables()["tied_to_file"] = (int64_t)false;
|
||||
} else if (flags & create_raw_data) {
|
||||
f->load_raw_data(uri);
|
||||
else
|
||||
} else {
|
||||
f->load(uri);
|
||||
}
|
||||
|
||||
f->commit();
|
||||
}
|
||||
@@ -390,7 +378,7 @@ Manager::try_create_download_from_meta_download(torrent::Object* bencode, const
|
||||
|
||||
f->set_start(meta.get_key_value("start"));
|
||||
f->set_print_log(meta.get_key_value("print_log"));
|
||||
f->slot_finished(std::bind(&rak::call_delete_func<core::DownloadFactory>, f));
|
||||
f->slot_finished([f]() { delete f; });
|
||||
|
||||
// Bit of a waste to create the bencode repesentation here
|
||||
// only to have the DownloadFactory decode it.
|
||||
@@ -414,7 +402,7 @@ path_expand(std::vector<std::string>* paths, const std::string& pattern) {
|
||||
|
||||
rak::split_iterator_t<std::string> first = rak::split_iterator(pattern, '/');
|
||||
rak::split_iterator_t<std::string> last = rak::split_iterator(pattern);
|
||||
|
||||
|
||||
if (first == last)
|
||||
return;
|
||||
|
||||
@@ -443,16 +431,18 @@ path_expand(std::vector<std::string>* paths, const std::string& pattern) {
|
||||
// Only include filenames starting with '.' if the pattern
|
||||
// starts with the same.
|
||||
itr->update((r.pattern()[0] != '.') ? utils::Directory::update_hide_dot : 0);
|
||||
itr->erase(std::remove_if(itr->begin(), itr->end(), rak::on(rak::mem_ref(&utils::directory_entry::s_name), std::not1(r))), itr->end());
|
||||
itr->erase(std::remove_if(itr->begin(), itr->end(), [r](const utils::directory_entry& entry) { return !r(entry.s_name); }), itr->end());
|
||||
|
||||
std::transform(itr->begin(), itr->end(), std::back_inserter(nextCache), rak::bind1st(std::ptr_fun(&path_expand_transform), itr->path() + (itr->path() == "/" ? "" : "/")));
|
||||
std::transform(itr->begin(), itr->end(), std::back_inserter(nextCache), [itr](const utils::directory_entry& entry) {
|
||||
return path_expand_transform(itr->path() + (itr->path() == "/" ? "" : "/"), entry);
|
||||
});
|
||||
}
|
||||
|
||||
currentCache.clear();
|
||||
currentCache.swap(nextCache);
|
||||
}
|
||||
|
||||
std::transform(currentCache.begin(), currentCache.end(), std::back_inserter(*paths), std::mem_fun_ref(&utils::Directory::path));
|
||||
std::transform(currentCache.begin(), currentCache.end(), std::back_inserter(*paths), std::mem_fn(&utils::Directory::path));
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -486,7 +476,7 @@ Manager::try_create_download_expand(const std::string& uri, int flags, command_l
|
||||
void
|
||||
Manager::receive_hashing_changed() {
|
||||
bool foundHashing = std::find_if(m_hashingView->begin_visible(), m_hashingView->end_visible(),
|
||||
std::mem_fun(&Download::is_hash_checking)) != m_hashingView->end_visible();
|
||||
std::mem_fn(&Download::is_hash_checking)) != m_hashingView->end_visible();
|
||||
|
||||
// Try quick hashing all those with hashing == initial, set them to
|
||||
// something else when failed.
|
||||
|
||||
@@ -49,10 +49,12 @@ namespace core {
|
||||
template<typename Key, typename T, typename Compare = std::less<Key>,
|
||||
typename Alloc = std::allocator<std::pair<const Key, T> > >
|
||||
class RangeMap : private std::map<Key, std::pair<Key, T>, Compare,
|
||||
typename Alloc::template rebind<std::pair<const Key, std::pair<Key, T> > >::other> {
|
||||
typename std::allocator_traits<Alloc>::template rebind_alloc<std::pair<const Key, std::pair<Key, T>>>> {
|
||||
|
||||
typedef std::map<Key, std::pair<Key, T>, Compare,
|
||||
typename Alloc::template rebind<std::pair<const Key, std::pair<Key, T> > >::other> base_type;
|
||||
typename std::allocator_traits<Alloc>::template rebind_alloc<std::pair<const Key, std::pair<Key, T>>>> base_type;
|
||||
|
||||
//std::allocator_traits<Alloc>::template rebind_alloc<std::pair<const Key, std::pair<Key, T>>>
|
||||
|
||||
public:
|
||||
RangeMap() {}
|
||||
|
||||
+63
-73
@@ -1,63 +1,26 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <rak/functional.h>
|
||||
#include <rak/functional_fun.h>
|
||||
#include <torrent/download.h>
|
||||
#include <torrent/exceptions.h>
|
||||
|
||||
#include "rpc/parse_commands.h"
|
||||
#include "rpc/object_storage.h"
|
||||
#include "control.h"
|
||||
#include "download.h"
|
||||
#include "download_list.h"
|
||||
#include "manager.h"
|
||||
#include "rpc/object_storage.h"
|
||||
#include "rpc/parse_commands.h"
|
||||
#include "view.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
// Also add focus thingie here?
|
||||
struct view_downloads_compare : std::binary_function<Download*, Download*, bool> {
|
||||
view_downloads_compare(const torrent::Object& cmd) : m_command(cmd) {}
|
||||
struct view_downloads_compare : std::function<bool (Download*, Download*)> {
|
||||
view_downloads_compare(const torrent::Object& cmd) :
|
||||
m_command(cmd) {}
|
||||
|
||||
bool operator () (Download* d1, Download* d2) const {
|
||||
bool operator()(Download* d1, Download* d2) const {
|
||||
try {
|
||||
if (m_command.is_empty())
|
||||
return false;
|
||||
@@ -75,8 +38,7 @@ struct view_downloads_compare : std::binary_function<Download*, Download*, bool>
|
||||
// return rpc::commands.call_command(tmp_command.as_dict_key().c_str(), tmp_command.as_dict_obj(),
|
||||
// rpc::make_target_pair(d1, d2)).as_value();
|
||||
|
||||
return rpc::commands.call_command(m_command.as_dict_key().c_str(), m_command.as_dict_obj(),
|
||||
rpc::make_target_pair(d1, d2)).as_value();
|
||||
return rpc::commands.call_command(m_command.as_dict_key().c_str(), m_command.as_dict_obj(), rpc::make_target_pair(d1, d2)).as_value();
|
||||
|
||||
} catch (torrent::input_error& e) {
|
||||
control->core()->push_log(e.what());
|
||||
@@ -88,10 +50,11 @@ struct view_downloads_compare : std::binary_function<Download*, Download*, bool>
|
||||
const torrent::Object& m_command;
|
||||
};
|
||||
|
||||
struct view_downloads_filter : std::unary_function<Download*, bool> {
|
||||
view_downloads_filter(const torrent::Object& cmd, const torrent::Object& cmd2) : m_command(cmd), m_command2(cmd2) {}
|
||||
struct view_downloads_filter : std::function<bool (Download*)> {
|
||||
view_downloads_filter(const torrent::Object& cmd, const torrent::Object& cmd2) :
|
||||
m_command(cmd), m_command2(cmd2) {}
|
||||
|
||||
bool operator () (Download* d1) const {
|
||||
bool operator()(Download* d1) const {
|
||||
return this->evalCmd(m_command, d1) && this->evalCmd(m_command2, d1);
|
||||
}
|
||||
|
||||
@@ -121,11 +84,16 @@ struct view_downloads_filter : std::unary_function<Download*, bool> {
|
||||
|
||||
switch (result.type()) {
|
||||
// case torrent::Object::TYPE_RAW_BENCODE: return !result.as_raw_bencode().empty();
|
||||
case torrent::Object::TYPE_VALUE: return result.as_value();
|
||||
case torrent::Object::TYPE_STRING: return !result.as_string().empty();
|
||||
case torrent::Object::TYPE_LIST: return !result.as_list().empty();
|
||||
case torrent::Object::TYPE_MAP: return !result.as_map().empty();
|
||||
default: return false;
|
||||
case torrent::Object::TYPE_VALUE:
|
||||
return result.as_value();
|
||||
case torrent::Object::TYPE_STRING:
|
||||
return !result.as_string().empty();
|
||||
case torrent::Object::TYPE_LIST:
|
||||
return !result.as_list().empty();
|
||||
case torrent::Object::TYPE_MAP:
|
||||
return !result.as_map().empty();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// The default filter action is to return true, to not filter
|
||||
@@ -139,14 +107,13 @@ struct view_downloads_filter : std::unary_function<Download*, bool> {
|
||||
}
|
||||
}
|
||||
|
||||
const torrent::Object& m_command;
|
||||
const torrent::Object& m_command2;
|
||||
const torrent::Object& m_command;
|
||||
const torrent::Object& m_command2;
|
||||
};
|
||||
|
||||
void
|
||||
View::emit_changed() {
|
||||
priority_queue_erase(&taskScheduler, &m_delayChanged);
|
||||
priority_queue_insert(&taskScheduler, &m_delayChanged, cachedTime);
|
||||
priority_queue_update(&taskScheduler, &m_delayChanged, cachedTime);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -176,9 +143,9 @@ View::initialize(const std::string& name) {
|
||||
m_name = name;
|
||||
|
||||
// Urgh, wrong. No filtering being done.
|
||||
std::for_each(dlist->begin(), dlist->end(), rak::bind1st(std::mem_fun(&View::push_back), this));
|
||||
std::for_each(dlist->begin(), dlist->end(), [&](Download* d) { push_back(d); });
|
||||
|
||||
m_size = base_type::size();
|
||||
m_size = base_type::size();
|
||||
m_focus = 0;
|
||||
|
||||
set_last_changed(rak::timer());
|
||||
@@ -232,20 +199,45 @@ View::set_not_visible(Download* download) {
|
||||
}
|
||||
|
||||
void
|
||||
View::next_focus() {
|
||||
View::next_focus(unsigned int i) {
|
||||
if (empty())
|
||||
return;
|
||||
|
||||
m_focus = (m_focus + 1) % (size() + 1);
|
||||
// If at the boundary, roll over
|
||||
if (m_focus == size() - 1) {
|
||||
m_focus = size();
|
||||
emit_changed();
|
||||
return;
|
||||
}
|
||||
|
||||
// Move forward, stop at the boundary
|
||||
if (m_focus == size()) // Needs special handling to ensure it's not off by one
|
||||
m_focus = i - 1;
|
||||
else
|
||||
m_focus += i;
|
||||
if (m_focus > size() - 1)
|
||||
m_focus = size() - 1;
|
||||
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
void
|
||||
View::prev_focus() {
|
||||
View::prev_focus(unsigned int i) {
|
||||
if (empty())
|
||||
return;
|
||||
|
||||
m_focus = (m_focus - 1 + size() + 1) % (size() + 1);
|
||||
// If at the boundary, roll over
|
||||
if (m_focus == size()) {
|
||||
m_focus = size() - 1;
|
||||
emit_changed();
|
||||
return;
|
||||
}
|
||||
|
||||
// Move backward, stop at the boundary
|
||||
m_focus -= i;
|
||||
if (m_focus < 0 || m_focus > size())
|
||||
m_focus = size();
|
||||
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
@@ -267,12 +259,12 @@ View::filter() {
|
||||
return;
|
||||
|
||||
// Parition the list in two steps so we know which elements changed.
|
||||
iterator splitVisible = std::stable_partition(begin_visible(), end_visible(), view_downloads_filter(m_filter, m_temp_filter));
|
||||
iterator splitFiltered = std::stable_partition(begin_filtered(), end_filtered(), view_downloads_filter(m_filter, m_temp_filter));
|
||||
iterator splitVisible = std::stable_partition(begin_visible(), end_visible(), view_downloads_filter(m_filter, m_temp_filter));
|
||||
iterator splitFiltered = std::stable_partition(begin_filtered(), end_filtered(), view_downloads_filter(m_filter, m_temp_filter));
|
||||
|
||||
base_type changed(splitVisible, splitFiltered);
|
||||
iterator splitChanged = changed.begin() + std::distance(splitVisible, end_visible());
|
||||
|
||||
iterator splitChanged = changed.begin() + std::distance(splitVisible, end_visible());
|
||||
|
||||
m_size = std::distance(begin(), std::copy(splitChanged, changed.end(), splitVisible));
|
||||
std::copy(changed.begin(), splitChanged, begin_filtered());
|
||||
|
||||
@@ -290,12 +282,10 @@ View::filter() {
|
||||
// set the elements to NULL as we trigger commands on them. Or
|
||||
// perhaps always clear them, thus not throwing anything.
|
||||
if (!m_event_removed.is_empty())
|
||||
std::for_each(changed.begin(), splitChanged,
|
||||
std::bind(&rpc::call_object_d_nothrow, m_event_removed, std::placeholders::_1));
|
||||
std::for_each(changed.begin(), splitChanged, std::bind(&rpc::call_object_d_nothrow, m_event_removed, std::placeholders::_1));
|
||||
|
||||
if (!m_event_added.is_empty())
|
||||
std::for_each(changed.begin(), splitChanged,
|
||||
std::bind(&rpc::call_object_d_nothrow, m_event_added, std::placeholders::_1));
|
||||
std::for_each(changed.begin(), splitChanged, std::bind(&rpc::call_object_d_nothrow, m_event_added, std::placeholders::_1));
|
||||
|
||||
emit_changed();
|
||||
}
|
||||
@@ -358,7 +348,7 @@ View::clear_filter_on() {
|
||||
|
||||
inline void
|
||||
View::insert_visible(Download* d) {
|
||||
iterator itr = std::find_if(begin_visible(), end_visible(), std::bind1st(view_downloads_compare(m_sortNew), d));
|
||||
iterator itr = std::find_if(begin_visible(), end_visible(), [&d, this](Download* d2) { return view_downloads_compare(m_sortNew)(d, d2); });
|
||||
|
||||
m_size++;
|
||||
m_focus += (m_focus >= position(itr));
|
||||
@@ -377,4 +367,4 @@ View::erase_internal(iterator itr) {
|
||||
base_type::erase(itr);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace core
|
||||
|
||||
+71
-101
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
// Provides a filtered and sorted list of downloads that can be
|
||||
// updated auto-magically.
|
||||
//
|
||||
@@ -64,77 +28,83 @@ class Download;
|
||||
|
||||
class View : private std::vector<Download*> {
|
||||
public:
|
||||
typedef std::vector<Download*> base_type;
|
||||
typedef std::function<void ()> slot_void;
|
||||
typedef std::list<slot_void> signal_void;
|
||||
typedef std::vector<Download*> base_type;
|
||||
typedef std::function<void()> slot_void;
|
||||
typedef std::list<slot_void> signal_void;
|
||||
|
||||
using base_type::iterator;
|
||||
using base_type::const_iterator;
|
||||
using base_type::reverse_iterator;
|
||||
using base_type::const_reverse_iterator;
|
||||
|
||||
using base_type::iterator;
|
||||
using base_type::reverse_iterator;
|
||||
|
||||
using base_type::size_type;
|
||||
|
||||
View() {}
|
||||
~View();
|
||||
|
||||
void initialize(const std::string& name);
|
||||
void initialize(const std::string& name);
|
||||
|
||||
const std::string& name() const { return m_name; }
|
||||
const std::string& name() const { return m_name; }
|
||||
|
||||
bool empty_visible() const { return m_size == 0; }
|
||||
bool empty_visible() const { return m_size == 0; }
|
||||
|
||||
size_type size() const { return m_size; }
|
||||
size_type size_visible() const { return m_size; }
|
||||
size_type size_not_visible() const { return base_type::size() - m_size; }
|
||||
size_type size() const { return m_size; }
|
||||
size_type size_visible() const { return m_size; }
|
||||
size_type size_not_visible() const { return base_type::size() - m_size; }
|
||||
|
||||
// Perhaps this should be renamed?
|
||||
iterator begin_visible() { return begin(); }
|
||||
const_iterator begin_visible() const { return begin(); }
|
||||
iterator begin_visible() { return begin(); }
|
||||
const_iterator begin_visible() const { return begin(); }
|
||||
|
||||
iterator end_visible() { return begin() + m_size; }
|
||||
const_iterator end_visible() const { return begin() + m_size; }
|
||||
iterator end_visible() { return begin() + m_size; }
|
||||
const_iterator end_visible() const { return begin() + m_size; }
|
||||
|
||||
iterator begin_filtered() { return begin() + m_size; }
|
||||
const_iterator begin_filtered() const { return begin() + m_size; }
|
||||
iterator begin_filtered() { return begin() + m_size; }
|
||||
const_iterator begin_filtered() const { return begin() + m_size; }
|
||||
|
||||
iterator end_filtered() { return base_type::end(); }
|
||||
const_iterator end_filtered() const { return base_type::end(); }
|
||||
iterator end_filtered() { return base_type::end(); }
|
||||
const_iterator end_filtered() const { return base_type::end(); }
|
||||
|
||||
iterator focus() { return begin() + m_focus; }
|
||||
const_iterator focus() const { return begin() + m_focus; }
|
||||
void set_focus(iterator itr) { m_focus = position(itr); emit_changed(); }
|
||||
iterator focus() { return begin() + m_focus; }
|
||||
const_iterator focus() const { return begin() + m_focus; }
|
||||
void set_focus(iterator itr) {
|
||||
m_focus = position(itr);
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
void insert(Download* download) { base_type::push_back(download); }
|
||||
void erase(Download* download);
|
||||
void insert(Download* download) { base_type::push_back(download); }
|
||||
void erase(Download* download);
|
||||
|
||||
void set_visible(Download* download);
|
||||
void set_not_visible(Download* download);
|
||||
void set_visible(Download* download);
|
||||
void set_not_visible(Download* download);
|
||||
|
||||
void next_focus();
|
||||
void prev_focus();
|
||||
void next_focus(unsigned int i);
|
||||
void prev_focus(unsigned int i);
|
||||
|
||||
void sort();
|
||||
void next_focus() { next_focus(1); }
|
||||
void prev_focus() { prev_focus(1); }
|
||||
|
||||
void set_sort_new(const torrent::Object& s) { m_sortNew = s; }
|
||||
void set_sort_current(const torrent::Object& s) { m_sortCurrent = s; }
|
||||
void sort();
|
||||
|
||||
void set_sort_new(const torrent::Object& s) { m_sortNew = s; }
|
||||
void set_sort_current(const torrent::Object& s) { m_sortCurrent = s; }
|
||||
|
||||
// Need to explicity trigger filtering.
|
||||
void filter();
|
||||
void filter_by(const torrent::Object& condition, base_type& result);
|
||||
void filter_download(core::Download* download);
|
||||
void filter();
|
||||
void filter_by(const torrent::Object& condition, base_type& result);
|
||||
void filter_download(core::Download* download);
|
||||
|
||||
const torrent::Object& get_filter() const { return m_filter; }
|
||||
void set_filter(const torrent::Object& s) { m_filter = s; }
|
||||
void set_filter(const torrent::Object& s) { m_filter = s; }
|
||||
const torrent::Object& get_filter_temp() const { return m_temp_filter; }
|
||||
void set_filter_temp(const torrent::Object& s) { m_temp_filter = s; }
|
||||
void set_filter_on_event(const std::string& event);
|
||||
void set_filter_temp(const torrent::Object& s) { m_temp_filter = s; }
|
||||
void set_filter_on_event(const std::string& event);
|
||||
|
||||
void clear_filter_on();
|
||||
void clear_filter_on();
|
||||
|
||||
const torrent::Object& event_added() const { return m_event_added; }
|
||||
const torrent::Object& event_removed() const { return m_event_removed; }
|
||||
void set_event_added(const torrent::Object& cmd) { m_event_added = cmd; }
|
||||
const torrent::Object& event_added() const { return m_event_added; }
|
||||
const torrent::Object& event_removed() const { return m_event_removed; }
|
||||
void set_event_added(const torrent::Object& cmd) { m_event_added = cmd; }
|
||||
void set_event_removed(const torrent::Object& cmd) { m_event_removed = cmd; }
|
||||
|
||||
// The time of the last change to the view, semantics of this is
|
||||
@@ -143,50 +113,50 @@ public:
|
||||
//
|
||||
// Currently initialized to rak::timer(), though perhaps we should
|
||||
// use cachedTimer.
|
||||
rak::timer last_changed() const { return m_lastChanged; }
|
||||
void set_last_changed(const rak::timer& t = ::cachedTime) { m_lastChanged = t; }
|
||||
rak::timer last_changed() const { return m_lastChanged; }
|
||||
void set_last_changed(const rak::timer& t = ::cachedTime) { m_lastChanged = t; }
|
||||
|
||||
// Don't connect any slots until after initialize else it get's
|
||||
// triggered when adding the Download's in DownloadList.
|
||||
signal_void& signal_changed() { return m_signal_changed; }
|
||||
signal_void& signal_changed() { return m_signal_changed; }
|
||||
|
||||
private:
|
||||
View(const View&);
|
||||
void operator = (const View&);
|
||||
void operator=(const View&);
|
||||
|
||||
void push_back(Download* d) { base_type::push_back(d); }
|
||||
void push_back(Download* d) { base_type::push_back(d); }
|
||||
|
||||
inline void insert_visible(Download* d);
|
||||
inline void erase_internal(iterator itr);
|
||||
inline void insert_visible(Download* d);
|
||||
inline void erase_internal(iterator itr);
|
||||
|
||||
void emit_changed();
|
||||
void emit_changed_now();
|
||||
void emit_changed();
|
||||
void emit_changed_now();
|
||||
|
||||
size_type position(const_iterator itr) const { return itr - begin(); }
|
||||
size_type position(const_iterator itr) const { return itr - begin(); }
|
||||
|
||||
// An received thing for changed status so we can sort and filter.
|
||||
|
||||
std::string m_name;
|
||||
std::string m_name;
|
||||
|
||||
size_type m_size;
|
||||
size_type m_focus;
|
||||
size_type m_size;
|
||||
size_type m_focus;
|
||||
|
||||
// These should be replaced by a faster non-string command type.
|
||||
torrent::Object m_sortNew;
|
||||
torrent::Object m_sortCurrent;
|
||||
torrent::Object m_sortNew;
|
||||
torrent::Object m_sortCurrent;
|
||||
|
||||
torrent::Object m_filter;
|
||||
torrent::Object m_temp_filter; // Temporary view filter (eg: name based filter)
|
||||
torrent::Object m_filter;
|
||||
torrent::Object m_temp_filter; // Temporary view filter (eg: name based filter)
|
||||
|
||||
torrent::Object m_event_added;
|
||||
torrent::Object m_event_removed;
|
||||
torrent::Object m_event_added;
|
||||
torrent::Object m_event_removed;
|
||||
|
||||
rak::timer m_lastChanged;
|
||||
rak::timer m_lastChanged;
|
||||
|
||||
signal_void m_signal_changed;
|
||||
rak::priority_item m_delayChanged;
|
||||
signal_void m_signal_changed;
|
||||
rak::priority_item m_delayChanged;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace core
|
||||
|
||||
#endif
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <rak/functional.h>
|
||||
#include <torrent/exceptions.h>
|
||||
#include <torrent/object.h>
|
||||
|
||||
@@ -55,7 +54,7 @@ namespace core {
|
||||
|
||||
void
|
||||
ViewManager::clear() {
|
||||
std::for_each(begin(), end(), rak::call_delete<View>());
|
||||
std::for_each(begin(), end(), [](View* v) { delete v; });
|
||||
|
||||
base_type::clear();
|
||||
}
|
||||
@@ -76,12 +75,12 @@ ViewManager::insert(const std::string& name) {
|
||||
|
||||
ViewManager::iterator
|
||||
ViewManager::find(const std::string& name) {
|
||||
return std::find_if(begin(), end(), rak::equal(name, std::mem_fun(&View::name)));
|
||||
return std::find_if(begin(), end(), [name](View* v){ return name == v->name(); });
|
||||
}
|
||||
|
||||
ViewManager::iterator
|
||||
ViewManager::find_throw(const std::string& name) {
|
||||
iterator itr = std::find_if(begin(), end(), rak::equal(name, std::mem_fun(&View::name)));
|
||||
iterator itr = std::find_if(begin(), end(), [name](View* v){ return name == v->name(); });
|
||||
|
||||
if (itr == end())
|
||||
throw torrent::input_error("Could not find view: " + name);
|
||||
|
||||
+120
-43
@@ -1,45 +1,9 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <termios.h>
|
||||
#include <torrent/exceptions.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "rpc/parse_commands.h"
|
||||
|
||||
@@ -48,14 +12,16 @@
|
||||
namespace display {
|
||||
|
||||
bool Canvas::m_isInitialized = false;
|
||||
bool Canvas::m_isDaemon = false;
|
||||
bool Canvas::m_isDaemon = false;
|
||||
// Maps ncurses color IDs to a ncurses attribute int
|
||||
std::unordered_map<int, int> Canvas::m_attr_map = {};
|
||||
|
||||
Canvas::Canvas(int x, int y, int width, int height) {
|
||||
if (!m_isDaemon) {
|
||||
m_window = newwin(height, width, y, x);
|
||||
m_window = newwin(height, width, y, x);
|
||||
|
||||
if (m_window == NULL)
|
||||
throw torrent::internal_error("Could not allocate ncurses canvas.");
|
||||
if (m_window == NULL)
|
||||
throw torrent::internal_error("Could not allocate ncurses canvas.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +39,7 @@ Canvas::print_attributes(unsigned int x, unsigned int y, const char* first, cons
|
||||
move(x, y);
|
||||
|
||||
attr_t org_attr;
|
||||
short org_pair;
|
||||
short org_pair;
|
||||
wattr_get(m_window, &org_attr, &org_pair, NULL);
|
||||
|
||||
attributes_list::const_iterator attrItr = attributes->begin();
|
||||
@@ -111,6 +77,9 @@ Canvas::initialize() {
|
||||
|
||||
if (!m_isDaemon) {
|
||||
initscr();
|
||||
start_color();
|
||||
use_default_colors();
|
||||
Canvas::build_colors();
|
||||
raw();
|
||||
noecho();
|
||||
nodelay(stdscr, TRUE);
|
||||
@@ -119,6 +88,114 @@ Canvas::initialize() {
|
||||
}
|
||||
}
|
||||
|
||||
// Function wrapper for what possibly is a macro
|
||||
int
|
||||
get_colors() {
|
||||
return COLORS;
|
||||
}
|
||||
|
||||
// Turns the string color definitions from the "ui.color.*" RPC
|
||||
// commands into valid ncurses color pairs
|
||||
void
|
||||
Canvas::build_colors() {
|
||||
|
||||
// This may get called early in the start process by the config
|
||||
// file, so we need to delay building until initscr() has a chance
|
||||
// to run
|
||||
if (!m_isInitialized || m_isDaemon)
|
||||
return;
|
||||
|
||||
// basic color names, index maps to ncurses COLOR_*
|
||||
static const char* color_names[] = {
|
||||
"black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"};
|
||||
|
||||
// Those hold the background colors of "odd" and "even"
|
||||
int bg_odd = -1;
|
||||
int bg_even = -1;
|
||||
|
||||
for (int k = 1; k < RCOLOR_MAX; k++) {
|
||||
init_pair(k, -1, -1);
|
||||
std::string color_def = rpc::call_command_string(color_vars[k]);
|
||||
if (color_def.empty())
|
||||
continue; // Use terminal default if definition is empty
|
||||
|
||||
short color[2] = {-1, -1}; // fg, bg
|
||||
short color_idx = 0; // 0 = fg; 1 = bg
|
||||
short bright = 0;
|
||||
unsigned long attr = A_NORMAL;
|
||||
|
||||
// Process string as space-separated words
|
||||
size_t start = 0, end = 0;
|
||||
while (true) {
|
||||
end = color_def.find(' ', start);
|
||||
std::string word = color_def.substr(start, end - start);
|
||||
|
||||
if (word == "bold")
|
||||
attr |= A_BOLD;
|
||||
else if (word == "standout")
|
||||
attr |= A_STANDOUT;
|
||||
else if (word == "underline")
|
||||
attr |= A_UNDERLINE;
|
||||
else if (word == "reverse")
|
||||
attr |= A_REVERSE;
|
||||
else if (word == "blink")
|
||||
attr |= A_BLINK;
|
||||
else if (word == "dim")
|
||||
attr |= A_DIM;
|
||||
else if (word == "on") {
|
||||
color_idx = 1;
|
||||
bright = 0;
|
||||
} // Switch to background color
|
||||
else if (word == "gray" || word == "grey")
|
||||
color[color_idx] = bright ? 7 : 8; // Bright gray is white
|
||||
else if (word == "bright")
|
||||
bright = 8;
|
||||
else if (word.find_first_not_of("0123456789") == std::string::npos) {
|
||||
// Handle numeric index
|
||||
short c = -1;
|
||||
sscanf(word.c_str(), "%hd", &c);
|
||||
color[color_idx] = c;
|
||||
} else
|
||||
for (short c = 0; c < 8; c++) { // Check for basic color names
|
||||
if (word == color_names[c]) {
|
||||
color[color_idx] = bright + c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (end == std::string::npos)
|
||||
break;
|
||||
start = end + 1;
|
||||
}
|
||||
|
||||
// Check that fg & bg color index is valid
|
||||
if ((color[0] != -1 && color[0] >= get_colors()) || (color[1] != -1 && color[1] >= get_colors())) {
|
||||
char buf[33];
|
||||
sprintf(buf, "%d", get_colors());
|
||||
Canvas::cleanup();
|
||||
throw torrent::input_error(color_def + ": your terminal only supports " + buf + " colors.");
|
||||
}
|
||||
|
||||
m_attr_map[k] = attr; // overwrite or insert the value
|
||||
init_pair(k, color[0], color[1]);
|
||||
if (k == RCOLOR_EVEN)
|
||||
bg_even = color[1];
|
||||
if (k == RCOLOR_ODD)
|
||||
bg_odd = color[1];
|
||||
}
|
||||
|
||||
// Now make copies of the basic colors with the "odd" and "even" definitions mixed in
|
||||
for (int k = 1; k < RCOLOR_MAX; k++) {
|
||||
short fg, bg;
|
||||
pair_content(k, &fg, &bg);
|
||||
|
||||
// Replace the background color, and mix in the attributes
|
||||
m_attr_map[k + 1 * RCOLOR_MAX] = m_attr_map[k] | m_attr_map[RCOLOR_EVEN];
|
||||
m_attr_map[k + 2 * RCOLOR_MAX] = m_attr_map[k] | m_attr_map[RCOLOR_ODD];
|
||||
init_pair(k + 1 * RCOLOR_MAX, fg, bg == -1 ? bg_even : bg);
|
||||
init_pair(k + 2 * RCOLOR_MAX, fg, bg == -1 ? bg_odd : bg);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Canvas::cleanup() {
|
||||
if (!m_isInitialized)
|
||||
@@ -143,4 +220,4 @@ Canvas::term_size() {
|
||||
return std::pair<int, int>(80, 24);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace display
|
||||
|
||||
+227
-84
@@ -1,125 +1,204 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RTORRENT_DISPLAY_CANVAS_H
|
||||
#define RTORRENT_DISPLAY_CANVAS_H
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "attributes.h"
|
||||
#include "color_map.h"
|
||||
|
||||
namespace display {
|
||||
|
||||
class Canvas {
|
||||
public:
|
||||
typedef std::vector<Attributes> attributes_list;
|
||||
typedef std::vector<Attributes> attributes_list;
|
||||
typedef std::unordered_map<int, int> attributes_map;
|
||||
|
||||
Canvas(int x = 0, int y = 0, int width = 0, int height = 0);
|
||||
~Canvas() { if (!m_isDaemon) { delwin(m_window); } }
|
||||
~Canvas();
|
||||
|
||||
void refresh() { if (!m_isDaemon) { wnoutrefresh(m_window); } }
|
||||
static void refresh_std() { if (!m_isDaemon) { wnoutrefresh(stdscr); } }
|
||||
void redraw() { if (!m_isDaemon) { redrawwin(m_window); } }
|
||||
static void redraw_std() { if (!m_isDaemon) { redrawwin(stdscr); } }
|
||||
void refresh();
|
||||
void redraw();
|
||||
void resize(int w, int h);
|
||||
void resize(int x, int y, int w, int h);
|
||||
|
||||
void resize(int w, int h) { if (!m_isDaemon) { wresize(m_window, h, w); } }
|
||||
void resize(int x, int y, int w, int h);
|
||||
static void refresh_std();
|
||||
static void redraw_std();
|
||||
static void resize_term(int x, int y);
|
||||
static void resize_term(std::pair<int, int> dim);
|
||||
|
||||
static void resize_term(int x, int y) { if (!m_isDaemon) { resizeterm(y, x); } }
|
||||
static void resize_term(std::pair<int, int> dim) { if (!m_isDaemon) { resizeterm(dim.second, dim.first); } }
|
||||
unsigned int get_x();
|
||||
unsigned int get_y();
|
||||
unsigned int width();
|
||||
unsigned int height();
|
||||
|
||||
unsigned int get_x() { int x, __UNUSED y; if (!m_isDaemon) { getyx(m_window, y, x); } else { x=1; } return x; }
|
||||
unsigned int get_y() { int x, y; if (!m_isDaemon) { getyx(m_window, y, x); } else { y=1; } return y; }
|
||||
|
||||
unsigned int width() { int x, __UNUSED y; if (!m_isDaemon) { getmaxyx(m_window, y, x); } else { x=80; } return x; }
|
||||
unsigned int height() { int x, y; if (!m_isDaemon) { getmaxyx(m_window, y, x); } else { y=24; } return y; }
|
||||
|
||||
void move(unsigned int x, unsigned int y) { if (!m_isDaemon) { wmove(m_window, y, x); } }
|
||||
|
||||
chtype get_background() { chtype bg=0; if (!m_isDaemon) { bg=getbkgd(m_window); } return bg; }
|
||||
void set_background(chtype c) { if (!m_isDaemon) { return wbkgdset(m_window, c); } }
|
||||
|
||||
void erase() { if (!m_isDaemon) { werase(m_window); } }
|
||||
static void erase_std() { if (!m_isDaemon) { werase(stdscr); } }
|
||||
|
||||
void print_border(chtype ls, chtype rs,
|
||||
chtype ts, chtype bs,
|
||||
chtype tl, chtype tr,
|
||||
chtype bl, chtype br) { if (!m_isDaemon) { wborder(m_window, ls, rs, ts, bs, tl, tr, bl, br); } }
|
||||
void move(unsigned int x, unsigned int y);
|
||||
void erase();
|
||||
static void erase_std();
|
||||
|
||||
// The format string is non-const, but that will not be a problem
|
||||
// since the string shall always be a C string choosen at
|
||||
// compiletime. Might cause extra copying of the string?
|
||||
|
||||
void print(const char* str, ...);
|
||||
void print(unsigned int x, unsigned int y, const char* str, ...);
|
||||
void print(const char* str, ...);
|
||||
void print(unsigned int x, unsigned int y, const char* str, ...);
|
||||
void print_attributes(unsigned int x, unsigned int y, const char* first, const char* last, const attributes_list* attributes);
|
||||
void print_char(const chtype ch);
|
||||
void print_char(unsigned int x, unsigned int y, const chtype ch);
|
||||
|
||||
void print_attributes(unsigned int x, unsigned int y, const char* first, const char* last, const attributes_list* attributes);
|
||||
|
||||
void print_char(const chtype ch) { if (!m_isDaemon) { waddch(m_window, ch); } }
|
||||
void print_char(unsigned int x, unsigned int y, const chtype ch) { if (!m_isDaemon) { mvwaddch(m_window, y, x, ch); } }
|
||||
|
||||
void set_attr(unsigned int x, unsigned int y, unsigned int n, int attr, int color) { if (!m_isDaemon) { mvwchgat(m_window, y, x, n, attr, color, NULL); } }
|
||||
|
||||
void set_default_attributes(int attr) { if (!m_isDaemon) { (void)wattrset(m_window, attr); } }
|
||||
void set_attr(unsigned int x, unsigned int y, unsigned int n, int attr, int color);
|
||||
void set_attr(unsigned int x, unsigned int y, unsigned int n, ColorKind k);
|
||||
void set_default_attributes(int attr);
|
||||
|
||||
// Initialize stdscr.
|
||||
static void initialize();
|
||||
static void cleanup();
|
||||
static void initialize();
|
||||
static void build_colors();
|
||||
static void cleanup();
|
||||
|
||||
static int get_screen_width() { int x, __UNUSED y; if (!m_isDaemon) { getmaxyx(stdscr, y, x); } else { x=80; } return x; }
|
||||
static int get_screen_height() { int x, y; if (!m_isDaemon) { getmaxyx(stdscr, y, x); } else { y=24;} return y; }
|
||||
static int get_screen_width();
|
||||
static int get_screen_height();
|
||||
|
||||
static std::pair<int, int> term_size();
|
||||
|
||||
static void do_update() { if (!m_isDaemon) { doupdate(); } }
|
||||
static void do_update();
|
||||
|
||||
static bool daemon() { return m_isDaemon; }
|
||||
static bool daemon() { return m_isDaemon; }
|
||||
static const attributes_map& attr_map() { return m_attr_map; }
|
||||
|
||||
private:
|
||||
Canvas(const Canvas&);
|
||||
void operator = (const Canvas&);
|
||||
void operator=(const Canvas&);
|
||||
|
||||
static bool m_isInitialized;
|
||||
static bool m_isDaemon;
|
||||
static bool m_isInitialized;
|
||||
static bool m_isDaemon;
|
||||
|
||||
WINDOW* m_window;
|
||||
// Maps ncurses color IDs to a ncurses attribute int
|
||||
static std::unordered_map<int, int> m_attr_map;
|
||||
|
||||
WINDOW* m_window;
|
||||
};
|
||||
|
||||
inline Canvas::~Canvas() {
|
||||
if (!m_isDaemon) {
|
||||
delwin(m_window);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::refresh() {
|
||||
if (!m_isDaemon) {
|
||||
wnoutrefresh(m_window);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::refresh_std() {
|
||||
if (!m_isDaemon) {
|
||||
wnoutrefresh(stdscr);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::redraw() {
|
||||
if (!m_isDaemon) {
|
||||
redrawwin(m_window);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::redraw_std() {
|
||||
if (!m_isDaemon) {
|
||||
redrawwin(stdscr);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::resize(int w, int h) {
|
||||
if (!m_isDaemon) {
|
||||
wresize(m_window, h, w);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::resize_term(int x, int y) {
|
||||
if (!m_isDaemon) {
|
||||
resizeterm(y, x);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::resize_term(std::pair<int, int> dim) {
|
||||
if (!m_isDaemon) {
|
||||
resizeterm(dim.second, dim.first);
|
||||
}
|
||||
}
|
||||
|
||||
inline unsigned int
|
||||
Canvas::get_x() {
|
||||
int x, __UNUSED y;
|
||||
if (!m_isDaemon) {
|
||||
getyx(m_window, y, x);
|
||||
} else {
|
||||
x = 1;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
inline unsigned int
|
||||
Canvas::get_y() {
|
||||
int x, y;
|
||||
if (!m_isDaemon) {
|
||||
getyx(m_window, y, x);
|
||||
} else {
|
||||
y = 1;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
inline unsigned int
|
||||
Canvas::width() {
|
||||
int x, __UNUSED y;
|
||||
if (!m_isDaemon) {
|
||||
getmaxyx(m_window, y, x);
|
||||
} else {
|
||||
x = 80;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
inline unsigned int
|
||||
Canvas::height() {
|
||||
int x, y;
|
||||
if (!m_isDaemon) {
|
||||
getmaxyx(m_window, y, x);
|
||||
} else {
|
||||
y = 24;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::move(unsigned int x, unsigned int y) {
|
||||
if (!m_isDaemon) {
|
||||
wmove(m_window, y, x);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::erase() {
|
||||
if (!m_isDaemon) {
|
||||
werase(m_window);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::erase_std() {
|
||||
if (!m_isDaemon) {
|
||||
werase(stdscr);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::print(const char* str, ...) {
|
||||
va_list arglist;
|
||||
@@ -143,6 +222,70 @@ Canvas::print(unsigned int x, unsigned int y, const char* str, ...) {
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::print_char(const chtype ch) {
|
||||
if (!m_isDaemon) {
|
||||
waddch(m_window, ch);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::print_char(unsigned int x, unsigned int y, const chtype ch) {
|
||||
if (!m_isDaemon) {
|
||||
mvwaddch(m_window, y, x, ch);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::set_attr(unsigned int x, unsigned int y, unsigned int n, int attr, int color) {
|
||||
if (!m_isDaemon) {
|
||||
mvwchgat(m_window, y, x, n, attr, color, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::set_attr(unsigned int x, unsigned int y, unsigned int n, ColorKind k) {
|
||||
if (!m_isDaemon) {
|
||||
mvwchgat(m_window, y, x, n, m_attr_map[k], k, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::set_default_attributes(int attr) {
|
||||
if (!m_isDaemon) {
|
||||
(void)wattrset(m_window, attr);
|
||||
}
|
||||
}
|
||||
|
||||
inline int
|
||||
Canvas::get_screen_width() {
|
||||
int x, __UNUSED y;
|
||||
if (!m_isDaemon) {
|
||||
getmaxyx(stdscr, y, x);
|
||||
} else {
|
||||
x = 80;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
inline int
|
||||
Canvas::get_screen_height() {
|
||||
int x, y;
|
||||
if (!m_isDaemon) {
|
||||
getmaxyx(stdscr, y, x);
|
||||
} else {
|
||||
y = 24;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::do_update() {
|
||||
if (!m_isDaemon) {
|
||||
doupdate();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace display
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef RTORRENT_DISPLAY_COLOR_MAP_H
|
||||
#define RTORRENT_DISPLAY_COLOR_MAP_H
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <curses.h>
|
||||
|
||||
namespace display {
|
||||
|
||||
enum ColorKind {
|
||||
RCOLOR_NCURSES_DEFAULT, // Color 0 is reserved by ncurses and cannot be changed
|
||||
RCOLOR_TITLE,
|
||||
RCOLOR_FOOTER,
|
||||
RCOLOR_FOCUS,
|
||||
RCOLOR_LABEL,
|
||||
RCOLOR_INFO,
|
||||
RCOLOR_ALARM,
|
||||
RCOLOR_COMPLETE,
|
||||
RCOLOR_SEEDING,
|
||||
RCOLOR_STOPPED,
|
||||
RCOLOR_QUEUED,
|
||||
RCOLOR_INCOMPLETE,
|
||||
RCOLOR_LEECHING,
|
||||
RCOLOR_ODD,
|
||||
RCOLOR_EVEN,
|
||||
RCOLOR_MAX,
|
||||
};
|
||||
|
||||
static const char* color_vars[RCOLOR_MAX] = {
|
||||
0,
|
||||
"ui.color.title",
|
||||
"ui.color.footer",
|
||||
"ui.color.focus",
|
||||
"ui.color.label",
|
||||
"ui.color.info",
|
||||
"ui.color.alarm",
|
||||
"ui.color.complete",
|
||||
"ui.color.seeding",
|
||||
"ui.color.stopped",
|
||||
"ui.color.queued",
|
||||
"ui.color.incomplete",
|
||||
"ui.color.leeching",
|
||||
"ui.color.odd",
|
||||
"ui.color.even",
|
||||
};
|
||||
|
||||
} // namespace display
|
||||
#endif
|
||||
@@ -38,7 +38,6 @@
|
||||
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <rak/functional.h>
|
||||
|
||||
#include "canvas.h"
|
||||
#include "globals.h"
|
||||
@@ -64,8 +63,7 @@ Manager::force_redraw() {
|
||||
|
||||
void
|
||||
Manager::schedule(Window* w, rak::timer t) {
|
||||
rak::priority_queue_erase(&m_scheduler, w->task_update());
|
||||
rak::priority_queue_insert(&m_scheduler, w->task_update(), t);
|
||||
rak::priority_queue_update(&m_scheduler, w->task_update(), t);
|
||||
schedule_update(50000);
|
||||
}
|
||||
|
||||
@@ -114,8 +112,7 @@ Manager::schedule_update(uint32_t minInterval) {
|
||||
}
|
||||
|
||||
if (!m_taskUpdate.is_queued() || m_taskUpdate.time() > m_scheduler.top()->time()) {
|
||||
rak::priority_queue_erase(&taskScheduler, &m_taskUpdate);
|
||||
rak::priority_queue_insert(&taskScheduler, &m_taskUpdate, std::max(m_scheduler.top()->time(), m_timeLastUpdate + minInterval));
|
||||
rak::priority_queue_update(&taskScheduler, &m_taskUpdate, std::max(m_scheduler.top()->time(), m_timeLastUpdate + minInterval));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <rak/functional.h>
|
||||
#include <torrent/exceptions.h>
|
||||
|
||||
#include "text_element_list.h"
|
||||
@@ -46,7 +45,7 @@ namespace display {
|
||||
|
||||
void
|
||||
TextElementList::clear() {
|
||||
std::for_each(begin(), end(), rak::call_delete<TextElement>());
|
||||
std::for_each(begin(), end(), [](TextElement* t) { delete t; });
|
||||
base_type::clear();
|
||||
}
|
||||
|
||||
|
||||
+6
-43
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <cstring>
|
||||
@@ -47,8 +11,8 @@
|
||||
#include <torrent/rate.h>
|
||||
#include <torrent/throttle.h>
|
||||
#include <torrent/torrent.h>
|
||||
#include <torrent/tracker.h>
|
||||
#include <torrent/tracker_list.h>
|
||||
#include <torrent/tracker/tracker.h>
|
||||
#include <torrent/data/file_list.h>
|
||||
#include <torrent/data/file_manager.h>
|
||||
#include <torrent/download/resource_manager.h>
|
||||
@@ -88,7 +52,7 @@ print_hhmmss(char* first, char* last, time_t t) {
|
||||
char*
|
||||
print_hhmmss_local(char* first, char* last, time_t t) {
|
||||
std::tm *u = std::localtime(&t);
|
||||
|
||||
|
||||
if (u == NULL)
|
||||
//return "inv_time";
|
||||
throw torrent::internal_error("print_hhmmss_local(...) failed.");
|
||||
@@ -107,7 +71,7 @@ print_ddhhmm(char* first, char* last, time_t t) {
|
||||
char*
|
||||
print_ddmmyyyy(char* first, char* last, time_t t) {
|
||||
std::tm *u = std::gmtime(&t);
|
||||
|
||||
|
||||
if (u == NULL)
|
||||
//return "inv_time";
|
||||
throw torrent::internal_error("print_ddmmyyyy(...) failed.");
|
||||
@@ -199,12 +163,11 @@ print_download_status(char* first, char* last, core::Download* d) {
|
||||
} else if (d->tracker_list()->has_active_not_scrape()) {
|
||||
torrent::TrackerList::iterator itr =
|
||||
std::find_if(d->tracker_list()->begin(), d->tracker_list()->end(),
|
||||
std::mem_fun(&torrent::Tracker::is_busy_not_scrape));
|
||||
char status[128];
|
||||
std::mem_fn(&torrent::tracker::Tracker::is_busy_not_scrape));
|
||||
auto status = itr->status();
|
||||
|
||||
(*itr)->get_status(status, sizeof(status));
|
||||
first = print_buffer(first, last, "Tracker[%i:%i]: Connecting to %s %s",
|
||||
(*itr)->group(), std::distance(d->tracker_list()->begin(), itr), (*itr)->url().c_str(), status);
|
||||
itr->group(), std::distance(d->tracker_list()->begin(), itr), itr->url().c_str(), status.c_str());
|
||||
|
||||
} else if (!d->message().empty()) {
|
||||
first = print_buffer(first, last, "%s", d->message().c_str());
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
#define RTORRENT_WINDOW_BASE_H
|
||||
|
||||
#include <rak/timer.h>
|
||||
#include <rak/functional.h>
|
||||
#include <functional>
|
||||
|
||||
#include "canvas.h"
|
||||
#include "globals.h"
|
||||
@@ -46,15 +46,14 @@
|
||||
namespace display {
|
||||
|
||||
class Canvas;
|
||||
class Manager;
|
||||
|
||||
class Window {
|
||||
public:
|
||||
typedef uint32_t extent_type;
|
||||
|
||||
typedef rak::mem_fun0<Manager, void> Slot;
|
||||
typedef rak::mem_fun1<Manager, void, Window*> SlotWindow;
|
||||
typedef rak::mem_fun2<Manager, void, Window*, rak::timer> SlotTimer;
|
||||
typedef std::function<void()> Slot;
|
||||
typedef std::function<void(Window*)> SlotWindow;
|
||||
typedef std::function<void(Window*, rak::timer)> SlotTimer;
|
||||
|
||||
static const int flag_active = (1 << 0);
|
||||
static const int flag_offscreen = (1 << 1);
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
|
||||
#include <cmath>
|
||||
#include <stdexcept>
|
||||
#include <rak/functional.h>
|
||||
#include <rak/string_manip.h>
|
||||
#include <torrent/bitfield.h>
|
||||
#include <torrent/data/block.h>
|
||||
@@ -95,7 +94,7 @@ WindowDownloadChunksSeen::redraw() {
|
||||
std::vector<torrent::BlockList*> transferChunks(transfers->size(), 0);
|
||||
|
||||
std::copy(transfers->begin(), transfers->end(), transferChunks.begin());
|
||||
std::sort(transferChunks.begin(), transferChunks.end(), rak::less2(std::mem_fun(&torrent::BlockList::index), std::mem_fun(&torrent::BlockList::index)));
|
||||
std::sort(transferChunks.begin(), transferChunks.end());
|
||||
|
||||
std::vector<torrent::BlockList*>::const_iterator itrTransfer = transferChunks.begin();
|
||||
|
||||
@@ -111,7 +110,7 @@ WindowDownloadChunksSeen::redraw() {
|
||||
if (bitfield->get(chunk - seen)) {
|
||||
attr = A_NORMAL;
|
||||
} else if (itrTransfer != transferChunks.end() && (uint32_t)(chunk - seen) == (*itrTransfer)->index()) {
|
||||
if (std::find_if((*itrTransfer)->begin(), (*itrTransfer)->end(), std::mem_fun_ref(&torrent::Block::is_transfering)) != (*itrTransfer)->end())
|
||||
if (std::any_of((*itrTransfer)->begin(), (*itrTransfer)->end(), std::mem_fn(&torrent::Block::is_transfering)))
|
||||
attr = A_REVERSE;
|
||||
else
|
||||
attr = A_BOLD | A_UNDERLINE;
|
||||
|
||||
@@ -1,41 +1,6 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "display/color_map.h"
|
||||
#include <rak/algorithm.h>
|
||||
|
||||
#include "core/download.h"
|
||||
@@ -57,7 +22,7 @@ WindowDownloadList::WindowDownloadList() :
|
||||
WindowDownloadList::~WindowDownloadList() {
|
||||
if (m_view != NULL)
|
||||
m_view->signal_changed().erase(m_changed_itr);
|
||||
|
||||
|
||||
m_view = NULL;
|
||||
}
|
||||
|
||||
@@ -72,8 +37,47 @@ WindowDownloadList::set_view(core::View* l) {
|
||||
m_changed_itr = m_view->signal_changed().insert(m_view->signal_changed().begin(), std::bind(&Window::mark_dirty, this));
|
||||
}
|
||||
|
||||
// Return a pair of ints, representing a) the ncurses attributes and b) the ncurses color pair ID to use
|
||||
std::pair<int, int>
|
||||
WindowDownloadList::get_attr_color(core::View::iterator selected) {
|
||||
core::Download* item = *selected;
|
||||
unsigned long focus_attr = selected == m_view->focus() ? m_canvas->attr_map().at(RCOLOR_FOCUS) : 0;
|
||||
int offset = (((selected - m_view->begin_visible()) & 1) + 1) * RCOLOR_MAX; // Determine the even/odd offset for the color pair
|
||||
bool active = item->is_open() && item->is_active();
|
||||
int title_color;
|
||||
if (item->is_done())
|
||||
title_color = (active ? item->info()->up_rate()->rate() ? RCOLOR_SEEDING : RCOLOR_COMPLETE : RCOLOR_STOPPED) + offset;
|
||||
else
|
||||
title_color = (active ? item->info()->down_rate()->rate() ? RCOLOR_LEECHING : RCOLOR_INCOMPLETE : RCOLOR_QUEUED) + offset;
|
||||
return std::make_pair(m_canvas->attr_map().at(title_color) | focus_attr, title_color);
|
||||
}
|
||||
|
||||
int
|
||||
WindowDownloadList::page_size(const std::string layout_name) {
|
||||
// Calculate the page size for torrents. This is a public method
|
||||
// because it's also used to determine the default size for page
|
||||
// up/down actions.
|
||||
int layout_height;
|
||||
if (layout_name == "full") {
|
||||
layout_height = 3;
|
||||
} else if (layout_name == "compact") {
|
||||
layout_height = 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return m_canvas->height() / layout_height;
|
||||
}
|
||||
|
||||
int
|
||||
WindowDownloadList::page_size() {
|
||||
return page_size(rpc::call_command_string("ui.torrent_list.layout"));
|
||||
}
|
||||
|
||||
void
|
||||
WindowDownloadList::redraw() {
|
||||
if (m_canvas->daemon())
|
||||
return;
|
||||
|
||||
m_slotSchedule(this, (cachedTime + rak::timer::from_seconds(1)).round_seconds());
|
||||
|
||||
m_canvas->erase();
|
||||
@@ -95,24 +99,16 @@ WindowDownloadList::redraw() {
|
||||
m_canvas->print(m_canvas->width() - 16, 0, "[%5d of %-5d]", item_idx + 1, m_view->size());
|
||||
}
|
||||
|
||||
int layout_height;
|
||||
const std::string layout_name = rpc::call_command_string("ui.torrent_list.layout");
|
||||
m_canvas->set_attr(0, 0, -1, RCOLOR_TITLE);
|
||||
|
||||
if (layout_name == "full") {
|
||||
layout_height = 3;
|
||||
} else if (layout_name == "compact") {
|
||||
layout_height = 1;
|
||||
} else {
|
||||
m_canvas->print(0, 0, "INVALID ui.torrent_list.layout '%s'", layout_name.c_str());
|
||||
return;
|
||||
}
|
||||
const std::string layout_name = rpc::call_command_string("ui.torrent_list.layout");
|
||||
|
||||
typedef std::pair<core::View::iterator, core::View::iterator> Range;
|
||||
|
||||
Range range = rak::advance_bidirectional(m_view->begin_visible(),
|
||||
m_view->focus() != m_view->end_visible() ? m_view->focus() : m_view->begin_visible(),
|
||||
m_view->end_visible(),
|
||||
m_canvas->height() / layout_height);
|
||||
page_size(layout_name));
|
||||
|
||||
// Make sure we properly fill out the last lines so it looks like
|
||||
// there are more torrents, yet don't hide it if we got the last one
|
||||
@@ -120,8 +116,8 @@ WindowDownloadList::redraw() {
|
||||
if (range.second != m_view->end_visible())
|
||||
++range.second;
|
||||
|
||||
int pos = 1;
|
||||
char buffer[m_canvas->width() + 1];
|
||||
int pos = 1;
|
||||
char buffer[m_canvas->width() + 1];
|
||||
char* last = buffer + m_canvas->width() - 2 + 1;
|
||||
|
||||
// Add a proper 'column info' method.
|
||||
@@ -134,25 +130,38 @@ WindowDownloadList::redraw() {
|
||||
|
||||
if (layout_name == "full") {
|
||||
while (range.first != range.second) {
|
||||
bool is_focused = range.first == m_view->focus();
|
||||
char focus_char = is_focused ? '*' : ' ';
|
||||
ColorKind focus_color = is_focused ? RCOLOR_FOCUS : RCOLOR_LABEL;
|
||||
auto attr_color = get_attr_color(range.first);
|
||||
|
||||
print_download_title(buffer, last, *range.first);
|
||||
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
|
||||
m_canvas->print(0, pos, "%c %s", focus_char, buffer);
|
||||
m_canvas->set_attr(2, pos++, -1, attr_color.first, attr_color.second);
|
||||
|
||||
print_download_info_full(buffer, last, *range.first);
|
||||
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
|
||||
m_canvas->print(0, pos, "%c %s", focus_char, buffer);
|
||||
m_canvas->set_attr(2, pos++, -1, focus_color);
|
||||
|
||||
print_download_status(buffer, last, *range.first);
|
||||
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
|
||||
m_canvas->print(0, pos, "%c %s", focus_char, buffer);
|
||||
m_canvas->set_attr(2, pos++, -1, focus_color);
|
||||
|
||||
range.first++;
|
||||
}
|
||||
|
||||
} else {
|
||||
while (range.first != range.second) {
|
||||
char focus_char = range.first == m_view->focus() ? '*' : ' ';
|
||||
auto attr_color = get_attr_color(range.first);
|
||||
|
||||
print_download_info_compact(buffer, last, *range.first);
|
||||
m_canvas->set_default_attributes(range.first == m_view->focus() ? A_REVERSE : A_NORMAL);
|
||||
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
|
||||
m_canvas->print(0, pos, "%c %s", focus_char, buffer);
|
||||
m_canvas->set_attr(2, pos++, -1, attr_color.first, attr_color.second);
|
||||
|
||||
range.first++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace display
|
||||
|
||||
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RTORRENT_DISPLAY_WINDOW_DOWNLOAD_LIST_H
|
||||
#define RTORRENT_DISPLAY_WINDOW_DOWNLOAD_LIST_H
|
||||
|
||||
@@ -47,6 +11,7 @@ namespace display {
|
||||
class WindowDownloadList : public Window {
|
||||
public:
|
||||
typedef core::View::signal_void::iterator signal_void_itr;
|
||||
typedef std::pair<core::View::iterator, core::View::iterator> ViewRange;
|
||||
|
||||
WindowDownloadList();
|
||||
~WindowDownloadList();
|
||||
@@ -55,9 +20,13 @@ public:
|
||||
|
||||
void set_view(core::View* l);
|
||||
|
||||
int page_size(const std::string layout_name);
|
||||
int page_size();
|
||||
|
||||
private:
|
||||
core::View* m_view;
|
||||
|
||||
std::pair<int, int> get_attr_color(core::View::iterator selected);
|
||||
signal_void_itr m_changed_itr;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <torrent/rate.h>
|
||||
@@ -59,6 +23,9 @@ WindowDownloadStatusbar::WindowDownloadStatusbar(core::Download* d) :
|
||||
|
||||
void
|
||||
WindowDownloadStatusbar::redraw() {
|
||||
if (m_canvas->daemon())
|
||||
return;
|
||||
|
||||
m_slotSchedule(this, (cachedTime + rak::timer::from_seconds(1)).round_seconds());
|
||||
|
||||
m_canvas->erase();
|
||||
@@ -91,7 +58,7 @@ WindowDownloadStatusbar::redraw() {
|
||||
print_download_status(buffer, last, m_download);
|
||||
m_canvas->print(0, 2, "[%c:%i] %s",
|
||||
m_download->tracker_list()->has_active() ? 'C' : ' ',
|
||||
(int)(m_download->download()->tracker_controller()->seconds_to_next_timeout()),
|
||||
(int)(m_download->download()->tracker_controller().seconds_to_next_timeout()),
|
||||
buffer);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <locale>
|
||||
@@ -83,7 +47,7 @@ wstring_width(const std::string& i_str, int width) {
|
||||
// Limit to width if it's too wide already.
|
||||
if (swidth == -1 || swidth > width) {
|
||||
length = swidth = 0;
|
||||
|
||||
|
||||
while (result[length]) {
|
||||
int next = ::wcwidth(result[length]);
|
||||
|
||||
@@ -172,13 +136,13 @@ WindowFileList::redraw() {
|
||||
|
||||
} else if (itr.is_entering()) {
|
||||
m_canvas->print(0, pos, "%*c %ls", 16 + itr.depth(), '\\',
|
||||
itr.depth() < (*itr)->path()->size() ? wstring_width((*itr)->path()->at(itr.depth()), filenameWidth - itr.depth() - 1).c_str() : L"UNKNOWN");
|
||||
itr.depth() < itr.file()->path()->size() ? wstring_width(itr.file()->path()->at(itr.depth()), filenameWidth - itr.depth() - 1).c_str() : L"UNKNOWN");
|
||||
|
||||
} else if (itr.is_leaving()) {
|
||||
m_canvas->print(0, pos, "%*c %-*s", 16 + (itr.depth() - 1), '/', filenameWidth - (itr.depth() - 1), "");
|
||||
|
||||
} else if (itr.is_file()) {
|
||||
torrent::File* e = *itr;
|
||||
torrent::File* e = itr.file();
|
||||
|
||||
const char* priority;
|
||||
|
||||
@@ -203,7 +167,7 @@ WindowFileList::redraw() {
|
||||
m_canvas->print(8, pos, "%5.1f T", (double)val / (int64_t(1) << 40));
|
||||
|
||||
m_canvas->print(15, pos, "%*c %ls", 1 + itr.depth(), '|',
|
||||
itr.depth() < (*itr)->path()->size() ? wstring_width((*itr)->path()->at(itr.depth()), filenameWidth - itr.depth() - 1).c_str() : L"UNKNOWN");
|
||||
itr.depth() < itr.file()->path()->size() ? wstring_width(itr.file()->path()->at(itr.depth()), filenameWidth - itr.depth() - 1).c_str() : L"UNKNOWN");
|
||||
|
||||
} else {
|
||||
m_canvas->print(0, pos, "BORK BORK");
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
#include "core/http_queue.h"
|
||||
|
||||
#include "canvas.h"
|
||||
#include "rak/functional.h"
|
||||
#include "window_http_queue.h"
|
||||
|
||||
namespace display {
|
||||
@@ -145,7 +144,7 @@ WindowHttpQueue::receive_insert(core::CurlGet* h) {
|
||||
|
||||
void
|
||||
WindowHttpQueue::receive_erase(core::CurlGet* h) {
|
||||
Container::iterator itr = std::find_if(m_container.begin(), m_container.end(), rak::equal(h, std::mem_fun_ref(&Node::get_http)));
|
||||
Container::iterator itr = std::find_if(m_container.begin(), m_container.end(), [h](Node n) { return h == n.get_http(); });
|
||||
|
||||
if (itr == m_container.end())
|
||||
throw std::logic_error("WindowHttpQueue::receive_erase(...) tried to remove an object we don't have");
|
||||
|
||||
@@ -1,44 +1,8 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <ctime>
|
||||
#include <torrent/torrent.h>
|
||||
#include <torrent/utils/thread_base.h>
|
||||
#include <torrent/utils/thread.h>
|
||||
|
||||
#include "canvas.h"
|
||||
#include "utils.h"
|
||||
@@ -54,7 +18,9 @@ WindowLog::WindowLog(torrent::log_buffer* l) :
|
||||
|
||||
unsigned int signal_index = torrent::main_thread()->signal_bitfield()->add_signal(std::bind(&WindowLog::receive_update, this));
|
||||
|
||||
m_log->lock_and_set_update_slot(std::bind(&torrent::thread_base::send_event_signal, torrent::main_thread(), signal_index, false));
|
||||
m_log->lock_and_set_update_slot([signal_index]() {
|
||||
torrent::main_thread()->send_event_signal(signal_index, false);
|
||||
});
|
||||
}
|
||||
|
||||
WindowLog::~WindowLog() {
|
||||
|
||||
@@ -1,41 +1,6 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "display/color_map.h"
|
||||
#include <torrent/rate.h>
|
||||
#include <torrent/torrent.h>
|
||||
|
||||
@@ -66,6 +31,7 @@ WindowStatusbar::redraw() {
|
||||
position = print_status_extra(buffer, last);
|
||||
m_canvas->print(m_canvas->width() - (position - buffer), 0, "%s", buffer);
|
||||
}
|
||||
m_canvas->set_attr(0, 0, -1, RCOLOR_FOOTER);
|
||||
|
||||
m_lastTick = control->tick();
|
||||
}
|
||||
|
||||
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "canvas.h"
|
||||
@@ -64,7 +28,7 @@ WindowStringList::redraw() {
|
||||
if (ypos == (size_t)m_canvas->height()) {
|
||||
ypos = 0;
|
||||
xpos += width + 2;
|
||||
|
||||
|
||||
if (xpos + 20 >= (size_t)m_canvas->width())
|
||||
break;
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <rak/functional.h>
|
||||
|
||||
#include "canvas.h"
|
||||
#include "utils.h"
|
||||
@@ -55,7 +54,7 @@ WindowText::WindowText(rpc::target_type target, extent_type margin) :
|
||||
|
||||
void
|
||||
WindowText::clear() {
|
||||
std::for_each(begin(), end(), rak::call_delete<TextElement>());
|
||||
std::for_each(begin(), end(), [](TextElement* text) { delete text; });
|
||||
base_type::clear();
|
||||
|
||||
delete m_errorHandler;
|
||||
|
||||
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "canvas.h"
|
||||
@@ -43,11 +7,13 @@ namespace display {
|
||||
|
||||
void
|
||||
WindowTitle::redraw() {
|
||||
if (m_canvas->daemon())
|
||||
return;
|
||||
|
||||
m_slotSchedule(this, (cachedTime + rak::timer::from_seconds(1)).round_seconds());
|
||||
m_canvas->erase();
|
||||
|
||||
m_canvas->print(std::max(0, ((int)m_canvas->width() - (int)m_title.size()) / 2 - 4), 0,
|
||||
"*** %s ***", m_title.c_str());
|
||||
m_canvas->print(std::max(0, ((int)m_canvas->width() - (int)m_title.size()) / 2 - 4), 0, "*** %s ***", m_title.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace display
|
||||
|
||||
@@ -1,47 +1,11 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <rak/algorithm.h>
|
||||
#include <rak/string_manip.h>
|
||||
#include <torrent/exceptions.h>
|
||||
#include <torrent/tracker.h>
|
||||
#include <torrent/tracker_list.h>
|
||||
#include <torrent/tracker_controller.h>
|
||||
#include <torrent/tracker/tracker.h>
|
||||
|
||||
#include "core/download.h"
|
||||
|
||||
@@ -62,14 +26,14 @@ WindowTrackerList::redraw() {
|
||||
m_canvas->erase();
|
||||
|
||||
unsigned int pos = 0;
|
||||
torrent::TrackerList* tl = m_download->tracker_list();
|
||||
torrent::TrackerController* tc = m_download->tracker_controller();
|
||||
auto tl = m_download->tracker_list();
|
||||
auto tc = m_download->tracker_controller();
|
||||
|
||||
m_canvas->print(2, pos, "Trackers: [Key: %08x] [%s %s %s]",
|
||||
tl->key(),
|
||||
tc->is_requesting() ? "req" : " ",
|
||||
tc->is_promiscuous_mode() ? "prom" : " ",
|
||||
tc->is_failure_mode() ? "fail" : " ");
|
||||
tc.is_requesting() ? "req" : " ",
|
||||
tc.is_promiscuous_mode() ? "prom" : " ",
|
||||
tc.is_failure_mode() ? "fail" : " ");
|
||||
++pos;
|
||||
|
||||
if (tl->size() == 0 || *m_focus >= tl->size())
|
||||
@@ -78,39 +42,41 @@ WindowTrackerList::redraw() {
|
||||
typedef std::pair<unsigned int, unsigned int> Range;
|
||||
|
||||
Range range = rak::advance_bidirectional<unsigned int>(0, *m_focus, tl->size(), (m_canvas->height() - 1) / 2);
|
||||
unsigned int group = tl->at(range.first)->group();
|
||||
unsigned int group = tl->at(range.first).group();
|
||||
|
||||
while (range.first != range.second) {
|
||||
torrent::Tracker* tracker = tl->at(range.first);
|
||||
auto tracker = tl->at(range.first);
|
||||
|
||||
if (tracker->group() == group)
|
||||
if (tracker.group() == group)
|
||||
m_canvas->print(0, pos, "%2i:", group++);
|
||||
|
||||
m_canvas->print(4, pos++, "%s",
|
||||
tracker->url().c_str());
|
||||
tracker.url().c_str());
|
||||
|
||||
if (pos < m_canvas->height()) {
|
||||
const char* state;
|
||||
|
||||
if (tracker->is_busy_not_scrape())
|
||||
if (tracker.is_busy_not_scrape())
|
||||
state = "req ";
|
||||
else if (tracker->is_busy())
|
||||
else if (tracker.is_busy())
|
||||
state = "scr ";
|
||||
else
|
||||
state = " ";
|
||||
|
||||
auto tracker_state = tracker.state();
|
||||
|
||||
m_canvas->print(0, pos++, "%s Id: %s Counters: %uf / %us (%u) %s S/L/D: %u/%u/%u (%u/%u)",
|
||||
state,
|
||||
rak::copy_escape_html(tracker->tracker_id()).c_str(),
|
||||
tracker->failed_counter(),
|
||||
tracker->success_counter(),
|
||||
tracker->scrape_counter(),
|
||||
tracker->is_usable() ? " on" : tracker->is_enabled() ? "err" : "off",
|
||||
tracker->scrape_complete(),
|
||||
tracker->scrape_incomplete(),
|
||||
tracker->scrape_downloaded(),
|
||||
tracker->latest_new_peers(),
|
||||
tracker->latest_sum_peers());
|
||||
rak::copy_escape_html(tracker.tracker_id()).c_str(),
|
||||
tracker_state.failed_counter(),
|
||||
tracker_state.success_counter(),
|
||||
tracker_state.scrape_counter(),
|
||||
tracker.is_usable() ? " on" : tracker.is_enabled() ? "err" : "off",
|
||||
tracker_state.scrape_complete(),
|
||||
tracker_state.scrape_incomplete(),
|
||||
tracker_state.scrape_downloaded(),
|
||||
tracker_state.latest_new_peers(),
|
||||
tracker_state.latest_sum_peers());
|
||||
}
|
||||
|
||||
if (range.first == *m_focus) {
|
||||
@@ -118,7 +84,7 @@ WindowTrackerList::redraw() {
|
||||
m_canvas->set_attr(4, pos - 1, m_canvas->width(), is_focused() ? A_REVERSE : A_BOLD, COLOR_PAIR(0));
|
||||
}
|
||||
|
||||
if (tracker->is_busy()) {
|
||||
if (tracker.is_busy()) {
|
||||
m_canvas->set_attr(0, pos - 2, 4, A_REVERSE, COLOR_PAIR(0));
|
||||
m_canvas->set_attr(0, pos - 1, 4, A_REVERSE, COLOR_PAIR(0));
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ Manager::pressed(int key) {
|
||||
if (m_textInput != NULL)
|
||||
m_textInput->pressed(key);
|
||||
else
|
||||
std::find_if(rbegin(), rend(), std::bind2nd(std::mem_fun(&Bindings::pressed), key));
|
||||
std::find_if(rbegin(), rend(), [&key](Bindings* bind) { return bind->pressed(key); });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
|
||||
#include <functional>
|
||||
#include <rak/algorithm.h>
|
||||
#include <rak/functional.h>
|
||||
#include <rak/path.h>
|
||||
|
||||
#include <dirent.h>
|
||||
@@ -105,7 +104,7 @@ PathInput::receive_do_complete() {
|
||||
if (r.first == r.second)
|
||||
return; // Show some nice colors here.
|
||||
|
||||
std::string base = rak::make_base<std::string>(r.first, r.second, rak::const_mem_ref(&utils::directory_entry::s_name));
|
||||
std::string base = rak::make_base<std::string>(r.first, r.second, std::mem_fn(&utils::directory_entry::s_name));
|
||||
|
||||
// Clear the path after the cursor to make this code cleaner. It's
|
||||
// not really nessesary to add the complexity just because someone
|
||||
@@ -154,8 +153,12 @@ PathInput::range_type
|
||||
PathInput::find_incomplete(utils::Directory& d, const std::string& f) {
|
||||
range_type r;
|
||||
|
||||
r.first = std::find_if(d.begin(), d.end(), rak::bind2nd(std::ptr_fun(&find_complete_not_compare), f));
|
||||
r.second = std::find_if(r.first, d.end(), rak::bind2nd(std::ptr_fun(&find_complete_compare), f));
|
||||
r.first = std::find_if(d.begin(), d.end(), [f](const utils::directory_entry& de) {
|
||||
return find_complete_not_compare(de, f);
|
||||
});
|
||||
r.second = std::find_if(r.first, d.end(), [f](const utils::directory_entry& de) {
|
||||
return find_complete_compare(de, f);
|
||||
});
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
+9
-46
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define __STDC_FORMAT_MACROS
|
||||
@@ -50,7 +14,6 @@
|
||||
#include <torrent/poll.h>
|
||||
#include <torrent/data/chunk_utils.h>
|
||||
#include <torrent/utils/log.h>
|
||||
#include <rak/functional.h>
|
||||
#include <rak/error_number.h>
|
||||
|
||||
#ifdef HAVE_BACKTRACE
|
||||
@@ -136,7 +99,7 @@ load_session_torrents() {
|
||||
// Replace with session torrent flag.
|
||||
f->set_session(true);
|
||||
f->set_init_load(true);
|
||||
f->slot_finished(std::bind(&rak::call_delete_func<core::DownloadFactory>, f));
|
||||
f->slot_finished([f](){ delete f; });
|
||||
f->load(entries.path() + first->s_name);
|
||||
f->commit();
|
||||
}
|
||||
@@ -151,7 +114,7 @@ load_arg_torrents(char** first, char** last) {
|
||||
// Replace with session torrent flag.
|
||||
f->set_start(true);
|
||||
f->set_init_load(true);
|
||||
f->slot_finished(std::bind(&rak::call_delete_func<core::DownloadFactory>, f));
|
||||
f->slot_finished([f](){ delete f; });
|
||||
f->load(*first);
|
||||
f->commit();
|
||||
}
|
||||
@@ -195,7 +158,7 @@ main(int argc, char** argv) {
|
||||
torrent::log_initialize();
|
||||
|
||||
control = new Control;
|
||||
|
||||
|
||||
unsigned int random_seed = cachedTime.seconds() ^ cachedTime.usec() ^ (getpid() << 16) ^ getppid();
|
||||
|
||||
srandom(random_seed);
|
||||
@@ -219,7 +182,7 @@ main(int argc, char** argv) {
|
||||
// platforms that do not properly pass signals to the target
|
||||
// threads. Use '--enable-interrupt-socket' when configuring
|
||||
// LibTorrent to enable this workaround.
|
||||
if (torrent::thread_base::should_handle_sigusr1())
|
||||
if (torrent::utils::Thread::should_handle_sigusr1())
|
||||
SignalHandler::set_handler(SIGUSR1, std::bind(&do_nothing));
|
||||
|
||||
torrent::log_add_group_output(torrent::LOG_NOTICE, "important");
|
||||
@@ -269,7 +232,7 @@ main(int argc, char** argv) {
|
||||
"method.insert = event.download.closed,multi|rlookup|static\n"
|
||||
"method.insert = event.download.resumed,multi|rlookup|static\n"
|
||||
"method.insert = event.download.paused,multi|rlookup|static\n"
|
||||
|
||||
|
||||
"method.insert = event.download.finished,multi|rlookup|static\n"
|
||||
"method.insert = event.download.hash_done,multi|rlookup|static\n"
|
||||
"method.insert = event.download.hash_failed,multi|rlookup|static\n"
|
||||
@@ -494,7 +457,7 @@ main(int argc, char** argv) {
|
||||
|
||||
rpc::commands.call_catch("event.system.startup_done", rpc::make_target(), "startup_done", "System startup_done event action failed: ");
|
||||
|
||||
torrent::thread_base::event_loop(torrent::main_thread());
|
||||
torrent::utils::Thread::event_loop(torrent::main_thread());
|
||||
|
||||
control->core()->download_list()->session_save();
|
||||
control->cleanup();
|
||||
@@ -525,7 +488,7 @@ main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
void
|
||||
handle_sigbus(int signum, siginfo_t* sa, void* ptr) {
|
||||
handle_sigbus(int signum, siginfo_t* sa, [[maybe_unused]] void* ptr) {
|
||||
if (signum != SIGBUS)
|
||||
do_panic(signum);
|
||||
|
||||
@@ -605,7 +568,7 @@ do_panic(int signum) {
|
||||
std::stringstream output;
|
||||
|
||||
output << "Caught " << SignalHandler::as_string(signum) << ", dumping stack:" << std::endl;
|
||||
|
||||
|
||||
#ifdef HAVE_BACKTRACE
|
||||
void* stackPtrs[20];
|
||||
|
||||
@@ -619,7 +582,7 @@ do_panic(int signum) {
|
||||
#else
|
||||
output << "Stack dump not enabled." << std::endl;
|
||||
#endif
|
||||
|
||||
|
||||
if (signum == SIGBUS)
|
||||
output << "A bus error probably means you ran out of diskspace." << std::endl;
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ bool
|
||||
OptionParser::has_flag(char flag, int argc, char** argv) {
|
||||
char options[3] = { '-', flag, '\0' };
|
||||
|
||||
return std::find_if(argv, argv + argc, std::not1(std::bind1st(std::ptr_fun(&std::strcmp), options))) != argv + argc;
|
||||
return std::find_if(argv, argv + argc, [&options](char* c) { return std::strcmp(c, options) == 0; }) != argv + argc;
|
||||
}
|
||||
|
||||
std::string
|
||||
|
||||
+1
-37
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "core/download.h"
|
||||
@@ -45,7 +9,7 @@
|
||||
template const torrent::Object func_name<target_type>(command_base* rawCommand, target_type target, const torrent::Object& args); \
|
||||
template const torrent::Object func_name<core::Download*>(command_base* rawCommand, target_type target, const torrent::Object& args); \
|
||||
template const torrent::Object func_name<torrent::Peer*>(command_base* rawCommand, target_type target, const torrent::Object& args); \
|
||||
template const torrent::Object func_name<torrent::Tracker*>(command_base* rawCommand, target_type target, const torrent::Object& args); \
|
||||
template const torrent::Object func_name<torrent::tracker::Tracker*>(command_base* rawCommand, target_type target, const torrent::Object& args); \
|
||||
template const torrent::Object func_name<torrent::File*>(command_base* rawCommand, target_type target, const torrent::Object& args); \
|
||||
template const torrent::Object func_name<torrent::FileListIterator*>(command_base* rawCommand, target_type target, const torrent::Object& args);
|
||||
|
||||
|
||||
+12
-56
@@ -1,46 +1,9 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RTORRENT_RPC_COMMAND_H
|
||||
#define RTORRENT_RPC_COMMAND_H
|
||||
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <torrent/object.h>
|
||||
|
||||
#include <torrent/common.h>
|
||||
#include <torrent/object.h>
|
||||
#include <torrent/data/file_list_iterator.h>
|
||||
|
||||
@@ -49,18 +12,11 @@ namespace core {
|
||||
class Download;
|
||||
}
|
||||
|
||||
namespace torrent {
|
||||
class File;
|
||||
class FileListIterator;
|
||||
class Peer;
|
||||
class Tracker;
|
||||
}
|
||||
|
||||
namespace rpc {
|
||||
|
||||
template <typename Target>
|
||||
struct target_wrapper {
|
||||
typedef Target target_type;
|
||||
typedef Target target_type;
|
||||
typedef Target cleaned_type;
|
||||
};
|
||||
|
||||
@@ -68,7 +24,7 @@ template <>
|
||||
struct target_wrapper<void> {
|
||||
struct no_type {};
|
||||
|
||||
typedef void target_type;
|
||||
typedef void target_type;
|
||||
typedef no_type* cleaned_type;
|
||||
};
|
||||
|
||||
@@ -127,7 +83,7 @@ public:
|
||||
typedef const torrent::Object (*file_slot) (command_base*, torrent::File*, const torrent::Object&);
|
||||
typedef const torrent::Object (*file_itr_slot) (command_base*, torrent::FileListIterator*, const torrent::Object&);
|
||||
typedef const torrent::Object (*peer_slot) (command_base*, torrent::Peer*, const torrent::Object&);
|
||||
typedef const torrent::Object (*tracker_slot) (command_base*, torrent::Tracker*, const torrent::Object&);
|
||||
typedef const torrent::Object (*tracker_slot) (command_base*, torrent::tracker::Tracker*, const torrent::Object&);
|
||||
|
||||
typedef const torrent::Object (*download_pair_slot) (command_base*, core::Download*, core::Download*, const torrent::Object&);
|
||||
|
||||
@@ -146,10 +102,10 @@ public:
|
||||
struct stack_type {
|
||||
torrent::Object* begin() { return reinterpret_cast<torrent::Object*>(buffer); }
|
||||
torrent::Object* end() { return reinterpret_cast<torrent::Object*>(buffer) + max_arguments; }
|
||||
|
||||
|
||||
const torrent::Object* begin() const { return reinterpret_cast<const torrent::Object*>(buffer); }
|
||||
const torrent::Object* end() const { return reinterpret_cast<const torrent::Object*>(buffer) + max_arguments; }
|
||||
|
||||
|
||||
torrent::Object& operator [] (unsigned int idx) { return *(begin() + idx); }
|
||||
const torrent::Object& operator [] (unsigned int idx) const { return *(begin() + idx); }
|
||||
|
||||
@@ -176,10 +132,10 @@ public:
|
||||
static void pop_stack(stack_type* stack, torrent::Object* last_stack);
|
||||
|
||||
template <typename T>
|
||||
void set_function(T s, int value = command_base_is_valid<T>::value) { _pod<T>() = s; }
|
||||
void set_function(T s, [[maybe_unused]] int value = command_base_is_valid<T>::value) { _pod<T>() = s; }
|
||||
|
||||
template <command_base_call_type T>
|
||||
void set_function_2(typename command_base_is_type<T>::type s, int value = command_base_is_valid<typename command_base_is_type<T>::type>::value) {
|
||||
void set_function_2(typename command_base_is_type<T>::type s, [[maybe_unused]] int value = command_base_is_valid<typename command_base_is_type<T>::type>::value) {
|
||||
_pod<typename command_base_is_type<T>::type>() = s;
|
||||
}
|
||||
|
||||
@@ -228,7 +184,7 @@ is_target_compatible(const target_type& target) { return target.first == target_
|
||||
inline bool is_target_pair(const target_type& target) { return target.first >= command_base::target_download_pair; }
|
||||
|
||||
template <typename T> inline T
|
||||
get_target_cast(target_type target, int type = target_type_id<T>::value) { return (T)target.second; }
|
||||
get_target_cast(target_type target, [[maybe_unused]] int type = target_type_id<T>::value) { return (T)target.second; }
|
||||
|
||||
inline target_type get_target_left(const target_type& target) { return target_type(target.first - 5, target.second); }
|
||||
inline target_type get_target_right(const target_type& target) { return target_type(target.first - 5, target.third); }
|
||||
@@ -251,7 +207,7 @@ command_base::_call(command_base* cmd, target_type target, Args args) {
|
||||
template <> struct command_base_is_valid<func_type<target_type>::type> { static const int value = 1; }; \
|
||||
template <> struct command_base_is_valid<func_type<core::Download*>::type> { static const int value = 1; }; \
|
||||
template <> struct command_base_is_valid<func_type<torrent::Peer*>::type> { static const int value = 1; }; \
|
||||
template <> struct command_base_is_valid<func_type<torrent::Tracker*>::type> { static const int value = 1; }; \
|
||||
template <> struct command_base_is_valid<func_type<torrent::tracker::Tracker*>::type> { static const int value = 1; }; \
|
||||
template <> struct command_base_is_valid<func_type<torrent::File*>::type> { static const int value = 1; }; \
|
||||
template <> struct command_base_is_valid<func_type<torrent::FileListIterator*>::type> { static const int value = 1; };
|
||||
|
||||
@@ -268,8 +224,8 @@ COMMAND_BASE_TEMPLATE_TYPE(command_list_function, torrent::Object (T, const to
|
||||
template <> struct command_base_is_type<func_name<target_type> > { static const int value = 1; typedef func_type<target_type>::type type; }; \
|
||||
template <> struct command_base_is_type<func_name<core::Download*> > { static const int value = 1; typedef func_type<core::Download*>::type type; }; \
|
||||
template <> struct command_base_is_type<func_name<torrent::Peer*> > { static const int value = 1; typedef func_type<torrent::Peer*>::type type; }; \
|
||||
template <> struct command_base_is_type<func_name<torrent::Tracker*> > { static const int value = 1; typedef func_type<torrent::Tracker*>::type type; }; \
|
||||
template <> struct command_base_is_type<func_name<torrent::File*> > { static const int value = 1; typedef func_type<torrent::File*>::type type; }; \
|
||||
template <> struct command_base_is_type<func_name<torrent::tracker::Tracker*> > { static const int value = 1; typedef func_type<torrent::tracker::Tracker*>::type type; }; \
|
||||
template <> struct command_base_is_type<func_name<torrent::File*> > { static const int value = 1; typedef func_type<torrent::File*>::type type; }; \
|
||||
template <> struct command_base_is_type<func_name<torrent::FileListIterator*> > { static const int value = 1; typedef func_type<torrent::FileListIterator*>::type type; };
|
||||
|
||||
COMMAND_BASE_TEMPLATE_CALL(command_base_call, command_function);
|
||||
|
||||
+4
-38
@@ -1,42 +1,8 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RTORRENT_RPC_COMMAND_IMPL_H
|
||||
#define RTORRENT_RPC_COMMAND_IMPL_H
|
||||
|
||||
#include "rpc/command.h"
|
||||
|
||||
namespace rpc {
|
||||
|
||||
//template <> struct target_type_id<command_base::generic_slot> { static const int value = command_base::target_generic; };
|
||||
@@ -54,7 +20,7 @@ template <> struct target_type_id<> { static const in
|
||||
template <> struct target_type_id<target_type> { static const int value = command_base::target_any; static const int proper_type = 1; };
|
||||
template <> struct target_type_id<core::Download*> { static const int value = command_base::target_download; static const int proper_type = 1; };
|
||||
template <> struct target_type_id<torrent::Peer*> { static const int value = command_base::target_peer; static const int proper_type = 1; };
|
||||
template <> struct target_type_id<torrent::Tracker*> { static const int value = command_base::target_tracker; static const int proper_type = 1; };
|
||||
template <> struct target_type_id<torrent::tracker::Tracker*> { static const int value = command_base::target_tracker; static const int proper_type = 1; };
|
||||
template <> struct target_type_id<torrent::File*> { static const int value = command_base::target_file; static const int proper_type = 1; };
|
||||
template <> struct target_type_id<torrent::FileListIterator*> { static const int value = command_base::target_file_itr; static const int proper_type = 1; };
|
||||
|
||||
@@ -63,7 +29,7 @@ template <> struct target_type_id<core::Download*, core::Download*> { static con
|
||||
template <> inline bool
|
||||
is_target_compatible<target_type>(const target_type& target) { return true; }
|
||||
template <> inline bool
|
||||
is_target_compatible<torrent::File*>(const target_type& target) { return target.first == command_base::target_file || command_base::target_file_itr; }
|
||||
is_target_compatible<torrent::File*>(const target_type& target) { return target.first == command_base::target_file || target.first == command_base::target_file_itr; }
|
||||
|
||||
template <> inline target_type
|
||||
get_target_cast<target_type>(target_type target, int type) { return target; }
|
||||
|
||||
+11
-45
@@ -36,7 +36,6 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <vector>
|
||||
#include <torrent/exceptions.h>
|
||||
#include <torrent/object.h>
|
||||
#include <torrent/data/file_list_iterator.h>
|
||||
@@ -49,57 +48,27 @@
|
||||
#include "command.h"
|
||||
#include "command_map.h"
|
||||
|
||||
// For XMLRPC stuff, clean up.
|
||||
#include "xmlrpc.h"
|
||||
#include "rpc_manager.h"
|
||||
#include "parse_commands.h"
|
||||
|
||||
namespace rpc {
|
||||
|
||||
command_base::stack_type command_base::current_stack;
|
||||
|
||||
CommandMap::~CommandMap() {
|
||||
std::vector<const char*> keys;
|
||||
|
||||
for (iterator itr = base_type::begin(), last = base_type::end(); itr != last; itr++) {
|
||||
// if (!(itr->second.m_flags & flag_dont_delete))
|
||||
// delete itr->second.m_variable;
|
||||
|
||||
if (itr->second.m_flags & flag_delete_key)
|
||||
keys.push_back(itr->first);
|
||||
}
|
||||
|
||||
for (std::vector<const char*>::iterator itr = keys.begin(), last = keys.end(); itr != last; itr++)
|
||||
delete [] *itr;
|
||||
}
|
||||
|
||||
CommandMap::iterator
|
||||
CommandMap::insert(key_type key, int flags, const char* parm, const char* doc) {
|
||||
CommandMap::insert(const key_type& key, int flags, const char* parm, const char* doc) {
|
||||
iterator itr = base_type::find(key);
|
||||
|
||||
if (itr != base_type::end())
|
||||
throw torrent::internal_error("CommandMap::insert(...) tried to insert an already existing key.");
|
||||
|
||||
// TODO: This is not honoring the public_xmlrpc flags!!!
|
||||
if (rpc::xmlrpc.is_valid() && (flags & flag_public_xmlrpc))
|
||||
// if (rpc::xmlrpc.is_valid())
|
||||
rpc::xmlrpc.insert_command(key, parm, doc);
|
||||
if (rpc::rpc.is_initialized() && (flags & flag_public_rpc))
|
||||
rpc::rpc.insert_command(key.c_str(), parm, doc);
|
||||
|
||||
return base_type::insert(itr, value_type(key, command_map_data_type(flags, parm, doc)));
|
||||
}
|
||||
|
||||
// void
|
||||
// CommandMap::insert(key_type key, const command_map_data_type src) {
|
||||
// iterator itr = base_type::find(key);
|
||||
|
||||
// if (itr != base_type::end())
|
||||
// throw torrent::internal_error("CommandMap::insert(...) tried to insert an already existing key.");
|
||||
|
||||
// itr = base_type::insert(itr, value_type(key, command_map_data_type(src.m_variable, src.m_flags | flag_dont_delete, src.m_parm, src.m_doc)));
|
||||
|
||||
// // We can assume all the slots are the same size.
|
||||
// itr->second.m_anySlot = src.m_anySlot;
|
||||
// }
|
||||
|
||||
void
|
||||
CommandMap::erase(iterator itr) {
|
||||
if (itr == end())
|
||||
@@ -112,14 +81,11 @@ CommandMap::erase(iterator itr) {
|
||||
// if (!(itr->second.m_flags & flag_dont_delete))
|
||||
// delete itr->second.m_variable;
|
||||
|
||||
const char* key = itr->second.m_flags & flag_delete_key ? itr->first : NULL;
|
||||
|
||||
base_type::erase(itr);
|
||||
delete [] key;
|
||||
}
|
||||
|
||||
void
|
||||
CommandMap::create_redirect(key_type key_new, key_type key_dest, int flags) {
|
||||
CommandMap::create_redirect(const key_type& key_new, const key_type& key_dest, int flags) {
|
||||
iterator new_itr = base_type::find(key_new);
|
||||
iterator dest_itr = base_type::find(key_dest);
|
||||
|
||||
@@ -135,11 +101,11 @@ CommandMap::create_redirect(key_type key_new, key_type key_dest, int flags) {
|
||||
|
||||
dest_itr->second.m_flags |= flag_has_redirects;
|
||||
|
||||
flags |= dest_itr->second.m_flags & ~(flag_delete_key | flag_has_redirects | flag_public_xmlrpc);
|
||||
flags |= dest_itr->second.m_flags & ~(flag_has_redirects | flag_public_rpc);
|
||||
|
||||
// TODO: This is not honoring the public_xmlrpc flags!!!
|
||||
if (rpc::xmlrpc.is_valid() && (flags & flag_public_xmlrpc))
|
||||
rpc::xmlrpc.insert_command(key_new, dest_itr->second.m_parm, dest_itr->second.m_doc);
|
||||
if (rpc::rpc.is_initialized() && (flags & flag_public_rpc))
|
||||
rpc::rpc.insert_command(key_new.c_str(), dest_itr->second.m_parm, dest_itr->second.m_doc);
|
||||
|
||||
iterator itr = base_type::insert(base_type::end(),
|
||||
value_type(key_new, command_map_data_type(flags,
|
||||
@@ -152,7 +118,7 @@ CommandMap::create_redirect(key_type key_new, key_type key_dest, int flags) {
|
||||
}
|
||||
|
||||
const CommandMap::mapped_type
|
||||
CommandMap::call_catch(key_type key, target_type target, const mapped_type& args, const char* err) {
|
||||
CommandMap::call_catch(const key_type& key, const target_type& target, const mapped_type& args, const char* err) {
|
||||
try {
|
||||
return call_command(key, args, target);
|
||||
} catch (torrent::input_error& e) {
|
||||
@@ -162,7 +128,7 @@ CommandMap::call_catch(key_type key, target_type target, const mapped_type& args
|
||||
}
|
||||
|
||||
const CommandMap::mapped_type
|
||||
CommandMap::call_command(key_type key, const mapped_type& arg, target_type target) {
|
||||
CommandMap::call_command(const key_type& key, const mapped_type& arg, const target_type& target) {
|
||||
iterator itr = base_type::find(key);
|
||||
|
||||
if (itr == base_type::end())
|
||||
@@ -172,7 +138,7 @@ CommandMap::call_command(key_type key, const mapped_type& arg, target_type targe
|
||||
}
|
||||
|
||||
const CommandMap::mapped_type
|
||||
CommandMap::call_command(iterator itr, const mapped_type& arg, target_type target) {
|
||||
CommandMap::call_command(iterator itr, const mapped_type& arg, const target_type& target) {
|
||||
return itr->second.m_anySlot(&itr->second.m_variable, target, arg);
|
||||
}
|
||||
|
||||
|
||||
+19
-63
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RTORRENT_RPC_COMMAND_MAP_H
|
||||
#define RTORRENT_RPC_COMMAND_MAP_H
|
||||
|
||||
@@ -46,10 +10,6 @@
|
||||
|
||||
namespace rpc {
|
||||
|
||||
struct command_map_comp : public std::binary_function<const char*, const char*, bool> {
|
||||
bool operator () (const char* arg1, const char* arg2) const { return std::strcmp(arg1, arg2) < 0; }
|
||||
};
|
||||
|
||||
struct command_map_data_type {
|
||||
// Some commands will need to share data, like get/set a variable. So
|
||||
// instead of using a single virtual member function, each command
|
||||
@@ -63,7 +23,7 @@ struct command_map_data_type {
|
||||
command_map_data_type(const command_map_data_type& src) :
|
||||
m_variable(src.m_variable), m_anySlot(src.m_anySlot),
|
||||
m_flags(src.m_flags), m_parm(src.m_parm), m_doc(src.m_doc) {}
|
||||
|
||||
|
||||
command_base m_variable;
|
||||
command_base::any_slot m_anySlot;
|
||||
|
||||
@@ -73,9 +33,9 @@ struct command_map_data_type {
|
||||
const char* m_doc;
|
||||
};
|
||||
|
||||
class CommandMap : public std::map<const char*, command_map_data_type, command_map_comp> {
|
||||
class CommandMap : public std::map<std::string, command_map_data_type> {
|
||||
public:
|
||||
typedef std::map<const char*, command_map_data_type, command_map_comp> base_type;
|
||||
typedef std::map<std::string, command_map_data_type> base_type;
|
||||
|
||||
typedef torrent::Object mapped_type;
|
||||
typedef mapped_type::value_type mapped_value_type;
|
||||
@@ -90,8 +50,7 @@ public:
|
||||
using base_type::find;
|
||||
|
||||
static const int flag_dont_delete = 0x1;
|
||||
static const int flag_delete_key = 0x2;
|
||||
static const int flag_public_xmlrpc = 0x4;
|
||||
static const int flag_public_rpc = 0x4;
|
||||
static const int flag_modifiable = 0x10;
|
||||
static const int flag_is_redirect = 0x20;
|
||||
static const int flag_has_redirects = 0x40;
|
||||
@@ -101,39 +60,36 @@ public:
|
||||
static const int flag_tracker_target = 0x400;
|
||||
|
||||
CommandMap() {}
|
||||
~CommandMap();
|
||||
|
||||
bool has(const char* key) const { return base_type::find(key) != base_type::end(); }
|
||||
bool has(const std::string& key) const { return has(key.c_str()); }
|
||||
bool has(const std::string& key) const { return base_type::find(key) != base_type::end(); }
|
||||
|
||||
bool is_modifiable(const_iterator itr) { return itr != end() && (itr->second.m_flags & flag_modifiable); }
|
||||
|
||||
iterator insert(key_type key, int flags, const char* parm, const char* doc);
|
||||
iterator insert(const key_type& key, int flags, const char* parm, const char* doc);
|
||||
|
||||
template <typename T, typename Slot>
|
||||
void
|
||||
insert_slot(key_type key, Slot variable, command_base::any_slot targetSlot, int flags, const char* parm, const char* doc) {
|
||||
insert_slot(const key_type& key, Slot variable, command_base::any_slot target_slot, int flags, const char* parm, const char* doc) {
|
||||
iterator itr = insert(key, flags, parm, doc);
|
||||
itr->second.m_variable.set_function<T>(variable);
|
||||
itr->second.m_anySlot = targetSlot;
|
||||
itr->second.m_anySlot = target_slot;
|
||||
}
|
||||
|
||||
// void insert(key_type key, const command_map_data_type src);
|
||||
void erase(iterator itr);
|
||||
|
||||
void create_redirect(key_type key_new, key_type key_dest, int flags);
|
||||
void create_redirect(const key_type& key_new, const key_type& key_dest, int flags);
|
||||
|
||||
const mapped_type call(key_type key, const mapped_type& args = mapped_type());
|
||||
const mapped_type call(key_type key, target_type target, const mapped_type& args = mapped_type()) { return call_command(key, args, target); }
|
||||
const mapped_type call_catch(key_type key, target_type target, const mapped_type& args = mapped_type(), const char* err = "Command failed: ");
|
||||
const mapped_type call(const key_type& key, const mapped_type& args = mapped_type());
|
||||
const mapped_type call(const key_type& key, const target_type& target, const mapped_type& args = mapped_type()) { return call_command(key, args, target); }
|
||||
const mapped_type call_catch(const key_type& key, const target_type& target, const mapped_type& args = mapped_type(), const char* err = "Command failed: ");
|
||||
|
||||
const mapped_type call_command (key_type key, const mapped_type& arg, target_type target = target_type((int)command_base::target_generic, NULL));
|
||||
const mapped_type call_command (iterator itr, const mapped_type& arg, target_type target = target_type((int)command_base::target_generic, NULL));
|
||||
const mapped_type call_command (const key_type& key, const mapped_type& arg, const target_type& target = target_type((int)command_base::target_generic, NULL));
|
||||
const mapped_type call_command (iterator itr, const mapped_type& arg, const target_type& target = target_type((int)command_base::target_generic, NULL));
|
||||
|
||||
const mapped_type call_command_d(key_type key, core::Download* download, const mapped_type& arg) { return call_command(key, arg, target_type((int)command_base::target_download, download)); }
|
||||
const mapped_type call_command_p(key_type key, torrent::Peer* peer, const mapped_type& arg) { return call_command(key, arg, target_type((int)command_base::target_peer, peer)); }
|
||||
const mapped_type call_command_t(key_type key, torrent::Tracker* tracker, const mapped_type& arg) { return call_command(key, arg, target_type((int)command_base::target_tracker, tracker)); }
|
||||
const mapped_type call_command_f(key_type key, torrent::File* file, const mapped_type& arg) { return call_command(key, arg, target_type((int)command_base::target_file, file)); }
|
||||
const mapped_type call_command_d(const key_type& key, core::Download* download, const mapped_type& arg) { return call_command(key, arg, target_type((int)command_base::target_download, download)); }
|
||||
const mapped_type call_command_p(const key_type& key, torrent::Peer* peer, const mapped_type& arg) { return call_command(key, arg, target_type((int)command_base::target_peer, peer)); }
|
||||
const mapped_type call_command_t(const key_type& key, torrent::tracker::Tracker* tracker, const mapped_type& arg) { return call_command(key, arg, target_type((int)command_base::target_tracker, tracker)); }
|
||||
const mapped_type call_command_f(const key_type& key, torrent::File* file, const mapped_type& arg) { return call_command(key, arg, target_type((int)command_base::target_file, file)); }
|
||||
|
||||
private:
|
||||
CommandMap(const CommandMap&);
|
||||
@@ -175,7 +131,7 @@ create_object_list(const torrent::Object& o1, const torrent::Object& o2, const t
|
||||
}
|
||||
|
||||
inline const CommandMap::mapped_type
|
||||
CommandMap::call(key_type key, const mapped_type& args) {
|
||||
CommandMap::call(const key_type& key, const mapped_type& args) {
|
||||
return call_command(key, args, make_target());
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <time.h>
|
||||
#include <rak/functional.h>
|
||||
#include <rak/string_manip.h>
|
||||
#include <torrent/exceptions.h>
|
||||
|
||||
@@ -50,12 +49,12 @@
|
||||
namespace rpc {
|
||||
|
||||
CommandScheduler::~CommandScheduler() {
|
||||
std::for_each(begin(), end(), rak::call_delete<CommandSchedulerItem>());
|
||||
std::for_each(begin(), end(), [](CommandSchedulerItem* item) { delete item; });
|
||||
}
|
||||
|
||||
CommandScheduler::iterator
|
||||
CommandScheduler::find(const std::string& key) {
|
||||
return std::find_if(begin(), end(), rak::equal(key, std::mem_fun(&CommandSchedulerItem::key)));
|
||||
return std::find_if(begin(), end(), [key](CommandSchedulerItem* item) { return key == item->key(); });
|
||||
}
|
||||
|
||||
CommandScheduler::iterator
|
||||
@@ -100,7 +99,7 @@ CommandScheduler::call_item(value_type item) {
|
||||
rpc::call_object(item->command());
|
||||
|
||||
} catch (torrent::input_error& e) {
|
||||
if (m_slotErrorMessage.is_valid())
|
||||
if (m_slotErrorMessage)
|
||||
m_slotErrorMessage("Scheduled command failed: " + item->key() + ": " + e.what());
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <rak/functional_fun.h>
|
||||
|
||||
namespace torrent {
|
||||
class Object;
|
||||
@@ -52,7 +51,7 @@ class CommandSchedulerItem;
|
||||
|
||||
class CommandScheduler : public std::vector<CommandSchedulerItem*> {
|
||||
public:
|
||||
typedef rak::function1<void, const std::string&> SlotString;
|
||||
typedef std::function<void (const std::string&)> SlotString;
|
||||
typedef std::pair<int, int> Time;
|
||||
typedef std::vector<CommandSchedulerItem*> base_type;
|
||||
|
||||
@@ -63,7 +62,7 @@ public:
|
||||
CommandScheduler() {}
|
||||
~CommandScheduler();
|
||||
|
||||
void set_slot_error_message(SlotString::base_type* s) { m_slotErrorMessage.set(s); }
|
||||
void set_slot_error_message(SlotString s) { m_slotErrorMessage = s; }
|
||||
|
||||
// slot_error_message or something.
|
||||
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "rpc/jsonrpc.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <torrent/common.h>
|
||||
#include <torrent/torrent.h>
|
||||
|
||||
#include "thread_base.h"
|
||||
#include "rpc/rpc_manager.h"
|
||||
#include "rpc/command.h"
|
||||
#include "rpc/command_map.h"
|
||||
#include "rpc/nlohmann/json.h"
|
||||
#include "rpc/parse_commands.h"
|
||||
#include "torrent/exceptions.h"
|
||||
#include "torrent/object.h"
|
||||
#include "utils/functional.h"
|
||||
|
||||
namespace rpc {
|
||||
|
||||
// Taken from https://www.jsonrpc.org/specification
|
||||
constexpr int JSONRPC_PARSE_ERROR = -32700;
|
||||
constexpr int JSONRPC_INVALID_REQUEST_ERROR = -32600;
|
||||
constexpr int JSONRPC_METHOD_NOT_FOUND_ERROR = -32601;
|
||||
constexpr int JSONRPC_INVALID_PARAMS_ERROR = -32602;
|
||||
constexpr int JSONRPC_INTERNAL_ERROR = -32000;
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
torrent::Object
|
||||
json_to_object(const json& value) {
|
||||
switch (value.type()) {
|
||||
case json::value_t::number_unsigned:
|
||||
case json::value_t::number_integer:
|
||||
return torrent::Object(value.get<int64_t>());
|
||||
case json::value_t::boolean:
|
||||
return value.get<bool>() ? torrent::Object(int64_t(1)) : torrent::Object(int64_t(0));
|
||||
case json::value_t::string:
|
||||
return torrent::Object(value.get<std::string>());
|
||||
case json::value_t::array: {
|
||||
auto array_raw = torrent::Object::create_list();
|
||||
auto& array = array_raw.as_list();
|
||||
for (const auto& entry : value) {
|
||||
array.push_back(json_to_object(entry));
|
||||
}
|
||||
return array_raw;
|
||||
}
|
||||
case json::value_t::object: {
|
||||
auto map_raw = torrent::Object::create_map();
|
||||
auto& map = map_raw.as_map();
|
||||
for (const auto& entry : value.items()) {
|
||||
map[entry.key()] = json_to_object(entry.value());
|
||||
}
|
||||
return map_raw;
|
||||
}
|
||||
case json::value_t::number_float:
|
||||
// type_name() for floats returns 'number', which is accurate for JSON but misleading
|
||||
throw torrent::input_error("invalid parameters: unexpected data type float");
|
||||
default:
|
||||
throw torrent::input_error("invalid parameters: unexpected data type " + std::string(value.type_name()));
|
||||
}
|
||||
}
|
||||
|
||||
json
|
||||
object_to_json(const torrent::Object& object) noexcept {
|
||||
switch (object.type()) {
|
||||
case torrent::Object::TYPE_VALUE:
|
||||
return object.as_value();
|
||||
case torrent::Object::TYPE_STRING:
|
||||
return object.as_string();
|
||||
case torrent::Object::TYPE_LIST: {
|
||||
json result = json::array();
|
||||
std::transform(object.as_list().cbegin(), object.as_list().cend(), std::back_inserter(result), [](const torrent::Object& element) {
|
||||
return object_to_json(element);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
case torrent::Object::TYPE_MAP: {
|
||||
json result = json::object();
|
||||
for (const auto& entry : object.as_map()) {
|
||||
result.emplace(entry.first, object_to_json(entry.second));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
case torrent::Object::TYPE_DICT_KEY: {
|
||||
json result = json::array();
|
||||
result.push_back(object_to_json(object.as_dict_key()));
|
||||
|
||||
const auto& dict_obj = object.as_dict_obj();
|
||||
if (dict_obj.is_list()) {
|
||||
std::transform(dict_obj.as_list().cbegin(), dict_obj.as_list().cend(), std::back_inserter(result), [](const torrent::Object& element) {
|
||||
return object_to_json(element);
|
||||
});
|
||||
} else {
|
||||
result.push_back(object_to_json(dict_obj));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
json
|
||||
jsonrpc_call_command(const std::string& method, const json& params) {
|
||||
if (params.type() == json::value_t::object) {
|
||||
// Named parameters is valid JSON-RPC, rtorrent just doesn't support it
|
||||
throw rpc_error(JSONRPC_INVALID_PARAMS_ERROR, "invalid parameter: procedure named parameter not supported");
|
||||
} else if (params.type() != json::value_t::array) {
|
||||
throw rpc_error(JSONRPC_INVALID_REQUEST_ERROR, "invalid request: params field must be an array");
|
||||
}
|
||||
|
||||
CommandMap::iterator itr = commands.find(method.c_str());
|
||||
|
||||
if (itr == commands.end()) {
|
||||
throw rpc_error(JSONRPC_METHOD_NOT_FOUND_ERROR, "method not found: " + method);
|
||||
}
|
||||
|
||||
torrent::Object params_object = json_to_object(params);
|
||||
auto& params_object_list = params_object.as_list();
|
||||
rpc::target_type target = rpc::make_target();
|
||||
|
||||
std::function<void()> deleter = []() {};
|
||||
utils::scope_guard guard([&deleter]() { deleter(); });
|
||||
|
||||
if (!(itr->second.m_flags & CommandMap::flag_no_target)) {
|
||||
// Provide a blank target if none was provided
|
||||
if (params_object_list.empty())
|
||||
params_object_list.push_back("");
|
||||
|
||||
if (!params_object_list.begin()->is_string())
|
||||
throw torrent::input_error("invalid parameters: target must be a string");
|
||||
|
||||
RpcManager::object_to_target(params_object_list.begin()->as_string(), itr->second.m_flags, &target, &deleter);
|
||||
|
||||
params_object_list.erase(params_object_list.begin());
|
||||
}
|
||||
|
||||
const auto& result = rpc::commands.call_command(itr, params_object, target);
|
||||
|
||||
return object_to_json(result);
|
||||
}
|
||||
|
||||
json
|
||||
json_error(int code, const std::string& msg, json id) {
|
||||
return json{{"jsonrpc", "2.0"}, {"id", id}, {"error", {{"code", code}, {"message", msg}}}};
|
||||
}
|
||||
|
||||
json
|
||||
handle_request(const json& request) {
|
||||
json response = {{"jsonrpc", "2.0"}, {"id", nullptr}};
|
||||
|
||||
try {
|
||||
if (!request["id"].is_number() && !request["id"].is_string() && !request["id"].is_null())
|
||||
return json_error(JSONRPC_INVALID_REQUEST_ERROR, "request id is invalid type " + std::string(request["id"].type_name()), response["id"]);
|
||||
response["id"] = request["id"];
|
||||
if (!request.contains("method") || !request["method"].is_string())
|
||||
return json_error(JSONRPC_INVALID_REQUEST_ERROR, "method string not present", response["id"]);
|
||||
if (request.contains("params"))
|
||||
response["result"] = jsonrpc_call_command(request["method"], request["params"]);
|
||||
else
|
||||
response["result"] = jsonrpc_call_command(request["method"], json::array({""}));
|
||||
return response;
|
||||
} catch (rpc_error& e) {
|
||||
return json_error(e.type(), e.what(), response["id"]);
|
||||
} catch (torrent::input_error& e) {
|
||||
return json_error(JSONRPC_INVALID_PARAMS_ERROR, e.what(), response["id"]);
|
||||
} catch (torrent::local_error& e) {
|
||||
return json_error(JSONRPC_INTERNAL_ERROR, e.what(), response["id"]);
|
||||
}
|
||||
}
|
||||
|
||||
// Notifications are basically the same as requests, except we can
|
||||
// just drop the message on the floor if there are any errors
|
||||
void
|
||||
handle_notification(const json& request) noexcept {
|
||||
if (!request.contains("method") || !request["method"].is_string())
|
||||
return;
|
||||
try {
|
||||
if (request.contains("params"))
|
||||
jsonrpc_call_command(request["method"], request["params"]);
|
||||
else
|
||||
jsonrpc_call_command(request["method"], json::array({""}));
|
||||
} catch (std::exception& e) {
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
JsonRpc::process(const char* in_buffer, uint32_t length, slot_write callback) {
|
||||
json response;
|
||||
json body;
|
||||
|
||||
try {
|
||||
body = json::parse(in_buffer, in_buffer + length);
|
||||
switch (body.type()) {
|
||||
case json::value_t::object: {
|
||||
if (!body.contains("id")) {
|
||||
handle_notification(body);
|
||||
return callback("", 0);
|
||||
} else {
|
||||
response = handle_request(body);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case json::value_t::array: {
|
||||
// Empty batch requests are invalid as per the spec
|
||||
if (body.empty()) {
|
||||
response = json_error(JSONRPC_INVALID_REQUEST_ERROR, "invalid request: empty batch", nullptr);
|
||||
break;
|
||||
}
|
||||
response = json::array();
|
||||
for (const auto& sub_body : body) {
|
||||
if (!sub_body.contains("id"))
|
||||
handle_notification(sub_body);
|
||||
else
|
||||
response.push_back(handle_request(sub_body));
|
||||
}
|
||||
// This indicates the batch was composed entirely of
|
||||
// notifications, in which case nothing is returned
|
||||
if (response.empty())
|
||||
return callback("", 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
response = json_error(JSONRPC_PARSE_ERROR, "message type " + std::string(body.type_name()) + " unsupported", nullptr);
|
||||
}
|
||||
|
||||
std::string response_str = response.dump();
|
||||
|
||||
return callback(response_str.c_str(), response_str.size());
|
||||
|
||||
} catch (json::parse_error& e) {
|
||||
auto err_str = json_error(JSONRPC_PARSE_ERROR, e.what(), nullptr).dump(-1, ' ', false, json::error_handler_t::replace);
|
||||
return callback(err_str.c_str(), err_str.size());
|
||||
} catch (json::type_error& e) {
|
||||
// Type errors may be caused by invalid UTF-8 strings in exception strings, hence the ::replace
|
||||
auto err_str = json_error(JSONRPC_PARSE_ERROR, e.what(), nullptr).dump(-1, ' ', false, json::error_handler_t::replace);
|
||||
return callback(err_str.c_str(), err_str.size());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace rpc
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef RTORRENT_RPC_JSONRPC_H
|
||||
#define RTORRENT_RPC_JSONRPC_H
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace rpc {
|
||||
|
||||
class JsonRpc {
|
||||
public:
|
||||
using slot_write = std::function<bool(const char*, uint32_t)>;
|
||||
|
||||
void initialize() {};
|
||||
void cleanup() {};
|
||||
|
||||
bool process(const char* in_buffer, uint32_t length, slot_write callback);
|
||||
|
||||
void insert_command(const char* name, const char* parm, const char* doc) {};
|
||||
};
|
||||
|
||||
} // namespace rpc
|
||||
|
||||
#endif
|
||||
+399
@@ -0,0 +1,399 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "rpc/lua.h"
|
||||
#ifdef HAVE_LUA
|
||||
#include <lua.hpp>
|
||||
#endif
|
||||
|
||||
#include <rak/error_number.h>
|
||||
#include <rak/path.h>
|
||||
#include <rak/string_manip.h>
|
||||
#include <torrent/object.h>
|
||||
|
||||
#include "core/download.h"
|
||||
#include "rpc/command.h"
|
||||
#include "rpc/command_map.h"
|
||||
#include "rpc/parse_commands.h"
|
||||
#include "rpc/xmlrpc.h"
|
||||
|
||||
namespace rpc {
|
||||
|
||||
const int LuaEngine::flag_string;
|
||||
const std::string LuaEngine::module_name = "rtorrent";
|
||||
|
||||
#ifdef HAVE_LUA
|
||||
|
||||
LuaEngine::LuaEngine() {
|
||||
m_luaState = luaL_newstate();
|
||||
luaL_openlibs(m_luaState);
|
||||
set_package_preload();
|
||||
}
|
||||
|
||||
LuaEngine::~LuaEngine() { lua_close(m_luaState); }
|
||||
|
||||
void
|
||||
LuaEngine::set_package_preload() {
|
||||
auto l_state = m_luaState;
|
||||
lua_getglobal(l_state, "package");
|
||||
lua_getfield(l_state, -1, "preload");
|
||||
lua_pushcfunction(l_state, LuaEngine::lua_init_module);
|
||||
lua_setfield(l_state, -2, LuaEngine::module_name.c_str());
|
||||
lua_pop(l_state, 2);
|
||||
}
|
||||
|
||||
void
|
||||
check_lua_status(lua_State* l_state, int status) {
|
||||
if (status != LUA_OK) {
|
||||
throw torrent::input_error(lua_tostring(l_state, -1));
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
LuaEngine::search_lua_path(lua_State* l_state) {
|
||||
// Get package.path
|
||||
lua_getglobal(l_state, "package");
|
||||
lua_getfield(l_state, -1, "path");
|
||||
std::string lua_path(lua_tostring(l_state, -1));
|
||||
lua_pop(l_state, 2);
|
||||
|
||||
// Use lambda here to ensure file closes as soon as it goes out of scope
|
||||
auto file_exists = [](const std::string& path) -> bool {
|
||||
std::ifstream file(path);
|
||||
return file.is_open();
|
||||
};
|
||||
|
||||
// Tokenize path using ';' as delimiter
|
||||
size_t pos = 0, end;
|
||||
while ((end = lua_path.find(';', pos)) != std::string::npos) {
|
||||
std::string file_path(lua_path.substr(pos, end - pos));
|
||||
size_t ppos = 0;
|
||||
while ((ppos = file_path.find('?')) != std::string::npos) {
|
||||
file_path.replace(ppos, 1, LuaEngine::module_name);
|
||||
}
|
||||
if (file_exists(file_path)) {
|
||||
return file_path;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
int
|
||||
LuaEngine::lua_rtorrent_call(lua_State* l_state) {
|
||||
auto method = lua_tostring(l_state, 1);
|
||||
lua_remove(l_state, 1);
|
||||
torrent::Object object;
|
||||
rpc::target_type target = rpc::make_target();
|
||||
;
|
||||
rpc::CommandMap::iterator itr = rpc::commands.find(std::string(method).c_str());
|
||||
if (itr == rpc::commands.end()) {
|
||||
throw torrent::input_error("method not found: " + std::string(method));
|
||||
}
|
||||
object = lua_callstack_to_object(l_state, itr->second.m_flags, &target);
|
||||
try {
|
||||
const auto& result = rpc::commands.call_command(itr, object, target);
|
||||
object_to_lua(l_state, result);
|
||||
return 1;
|
||||
} catch (torrent::base_error& e) {
|
||||
throw luaL_error(l_state, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
LuaEngine::lua_init_module(lua_State* l_state) {
|
||||
// Should this throw if it fails to find the file?
|
||||
auto lua_file = search_lua_path(l_state);
|
||||
if (!lua_file.empty()) {
|
||||
check_lua_status(l_state, luaL_loadfile(l_state, lua_file.c_str()));
|
||||
}
|
||||
lua_createtable(l_state, 0, 1);
|
||||
// Assign functions
|
||||
lua_pushliteral(l_state, "call");
|
||||
lua_pushcfunction(l_state, LuaEngine::lua_rtorrent_call);
|
||||
lua_settable(l_state, -3);
|
||||
if (!lua_file.empty()) {
|
||||
check_lua_status(l_state, lua_pcall(l_state, 1, 1, 0));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
object_to_target(const torrent::Object& obj, int call_flags, rpc::target_type* target) {
|
||||
if (!obj.is_string()) {
|
||||
throw torrent::input_error("invalid parameters: target must be a string");
|
||||
}
|
||||
std::string target_string = obj.as_string();
|
||||
bool require_index = (call_flags & (CommandMap::flag_tracker_target | CommandMap::flag_file_target));
|
||||
if (target_string.empty() && !require_index) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Length of SHA1 hash is 40
|
||||
if (target_string.size() < 40) {
|
||||
throw torrent::input_error("invalid parameters: invalid target");
|
||||
}
|
||||
|
||||
char type = 'd';
|
||||
std::string hash;
|
||||
std::string index;
|
||||
const auto& delim_pos = target_string.find_first_of(':', 40);
|
||||
if (delim_pos == target_string.npos || delim_pos + 2 >= target_string.size()) {
|
||||
if (require_index) {
|
||||
throw torrent::input_error("invalid parameters: no index");
|
||||
}
|
||||
hash = target_string;
|
||||
} else {
|
||||
hash = target_string.substr(0, delim_pos);
|
||||
type = target_string[delim_pos + 1];
|
||||
index = target_string.substr(delim_pos + 2);
|
||||
}
|
||||
core::Download* download = rpc.slot_find_download()(hash.c_str());
|
||||
|
||||
if (download == nullptr)
|
||||
throw torrent::input_error("invalid parameters: info-hash not found");
|
||||
|
||||
try {
|
||||
switch (type) {
|
||||
case 'd':
|
||||
*target = rpc::make_target(download);
|
||||
break;
|
||||
case 'f':
|
||||
*target = rpc::make_target(command_base::target_file, rpc.slot_find_file()(download, std::stoi(std::string(index))));
|
||||
break;
|
||||
case 't':
|
||||
*target =
|
||||
rpc::make_target(command_base::target_tracker, rpc.slot_find_tracker()(download, std::stoi(std::string(index))));
|
||||
break;
|
||||
case 'p': {
|
||||
if (index.size() < 40) {
|
||||
throw torrent::input_error("Not a hash string.");
|
||||
}
|
||||
torrent::HashString hash;
|
||||
torrent::hash_string_from_hex_c_str(index.c_str(), hash);
|
||||
*target = rpc::make_target(command_base::target_peer, rpc.slot_find_peer()(download, hash));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw torrent::input_error("invalid parameters: unexpected target type");
|
||||
}
|
||||
} catch (const std::logic_error&) {
|
||||
throw torrent::input_error("invalid parameters: invalid index");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
object_to_lua(lua_State* l_state, torrent::Object const& object) {
|
||||
// Converts an object to a single Lua stack object
|
||||
switch (object.type()) {
|
||||
case torrent::Object::TYPE_VALUE:
|
||||
lua_pushnumber(l_state, static_cast<double>(object.as_value()));
|
||||
break;
|
||||
case torrent::Object::TYPE_NONE:
|
||||
lua_pushnil(l_state);
|
||||
break;
|
||||
case torrent::Object::TYPE_STRING:
|
||||
lua_pushstring(l_state, object.as_string().c_str());
|
||||
break;
|
||||
case torrent::Object::TYPE_LIST: {
|
||||
int index = 1;
|
||||
auto object_list = object.as_list();
|
||||
|
||||
lua_createtable(l_state, static_cast<int>(object_list.size()), 0);
|
||||
int table_idx = lua_gettop(l_state);
|
||||
for (const auto& itr : object_list) {
|
||||
object_to_lua(l_state, itr);
|
||||
lua_rawseti(l_state, table_idx, lua_Integer(index++));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case torrent::Object::TYPE_MAP: {
|
||||
auto object_map = object.as_map();
|
||||
lua_createtable(l_state, 0, static_cast<int>(object_map.size()));
|
||||
int table_idx = lua_gettop(l_state);
|
||||
for (const auto& itr : object_map) {
|
||||
object_to_lua(l_state, itr.second);
|
||||
lua_pushlstring(l_state, itr.first.c_str(), itr.first.size());
|
||||
lua_rawset(l_state, table_idx);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
lua_pushnumber(l_state, lua_Number(object.type()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
lua_to_object(lua_State* l_state) {
|
||||
switch (lua_type(l_state, -1)) {
|
||||
case LUA_TNUMBER:
|
||||
return torrent::Object(lua_tonumber(l_state, -1));
|
||||
case LUA_TSTRING:
|
||||
return torrent::Object(lua_tostring(l_state, -1));
|
||||
case LUA_TBOOLEAN:
|
||||
return torrent::Object(lua_toboolean(l_state, -1));
|
||||
case LUA_TNIL:
|
||||
return torrent::Object((torrent::Object::value_type)0);
|
||||
case LUA_TTABLE: {
|
||||
lua_pushnil(l_state);
|
||||
int status = lua_next(l_state, -2);
|
||||
if (status == 0)
|
||||
return torrent::Object::create_map();
|
||||
// If the table starts at 1, assume it's an array
|
||||
if (lua_isnumber(l_state, -2) && (lua_tonumber(l_state, -2) == 1)) {
|
||||
torrent::Object list = torrent::Object::create_list();
|
||||
list.insert_back(lua_to_object(l_state));
|
||||
lua_pop(l_state, 1);
|
||||
while (lua_next(l_state, -2) != 0) {
|
||||
list.insert_back(lua_to_object(l_state));
|
||||
lua_pop(l_state, 1);
|
||||
}
|
||||
return list;
|
||||
} else {
|
||||
torrent::Object map = torrent::Object::create_map();
|
||||
// Reset the stack and start from the first element
|
||||
lua_pop(l_state, 2);
|
||||
lua_pushnil(l_state);
|
||||
while (lua_next(l_state, -2) != 0) {
|
||||
std::string key;
|
||||
switch (lua_type(l_state, -2)) {
|
||||
case LUA_TSTRING:
|
||||
key = lua_tostring(l_state, -2);
|
||||
break;
|
||||
default:
|
||||
// Bencode dictionaries require string keys, but naively
|
||||
// calling lua_tostring will auto-convert any other object
|
||||
// (particularly numbers) to strings in-place, which would
|
||||
// throw off lua_next, so we copy the value and only then
|
||||
// get the string.
|
||||
// https://www.lua.org/manual/5.3/manual.html#lua_tolstring
|
||||
lua_pushvalue(l_state, -2);
|
||||
key = lua_tostring(l_state, -1);
|
||||
lua_pop(l_state, 1);
|
||||
break;
|
||||
}
|
||||
map.insert_key(key, lua_to_object(l_state));
|
||||
lua_pop(l_state, 1);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
return torrent::Object(lua_tostring(l_state, -1));
|
||||
}
|
||||
default:
|
||||
std::string result = lua_tostring(l_state, -1);
|
||||
lua_pop(l_state, 1);
|
||||
return torrent::Object(result);
|
||||
}
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
lua_callstack_to_object(lua_State* l_state, int command_flags, rpc::target_type* target) {
|
||||
torrent::Object object;
|
||||
if (lua_gettop(l_state) == 0) {
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
if (!lua_isstring(l_state, 1)) {
|
||||
throw torrent::input_error("invalid parameters: target must be a string");
|
||||
}
|
||||
object_to_target(torrent::Object(lua_tostring(l_state, 1)), command_flags, target);
|
||||
|
||||
// start from the second argument since the first is the target
|
||||
lua_remove(l_state, 1);
|
||||
|
||||
if (lua_gettop(l_state) == 0) {
|
||||
return torrent::Object();
|
||||
} else {
|
||||
torrent::Object result = torrent::Object::create_list();
|
||||
torrent::Object::list_type& list_ref = result.as_list();
|
||||
while (lua_gettop(l_state) != 0) {
|
||||
list_ref.insert(list_ref.begin(), lua_to_object(l_state));
|
||||
lua_remove(l_state, -1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
int
|
||||
lua_rtorrent_call(lua_State* l_state) {
|
||||
torrent::Object object;
|
||||
rpc::target_type target = rpc::make_target();
|
||||
auto method = lua_tostring(l_state, 1);
|
||||
lua_remove(l_state, 1);
|
||||
|
||||
rpc::CommandMap::iterator itr = rpc::commands.find(method);
|
||||
if (itr == rpc::commands.end()) {
|
||||
throw torrent::input_error("method not found: " + std::string(method));
|
||||
}
|
||||
object = lua_callstack_to_object(l_state, itr->second.m_flags, &target);
|
||||
try {
|
||||
const auto& result = rpc::commands.call_command(itr, object, target);
|
||||
object_to_lua(l_state, result);
|
||||
return 1;
|
||||
} catch (torrent::base_error& e) {
|
||||
throw luaL_error(l_state, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
execute_lua(LuaEngine* engine, rpc::target_type target_type, torrent::Object const& raw_args, int flags) {
|
||||
size_t lua_argc = 1; // Target is always present, even if empty
|
||||
lua_State* l_state = engine->state();
|
||||
std::string target_string;
|
||||
|
||||
switch (target_type.first) {
|
||||
case (command_base::target_download):
|
||||
core::Download* dl_target = (core::Download*)target_type.second;
|
||||
torrent::HashString infohash = dl_target->info()->hash();
|
||||
target_string = rak::transform_hex_str(infohash);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (raw_args.type()) {
|
||||
case torrent::Object::TYPE_LIST: {
|
||||
const torrent::Object::list_type& args = raw_args.as_list();
|
||||
if (flags & LuaEngine::flag_string) {
|
||||
check_lua_status(l_state, luaL_loadstring(l_state, args.begin()->as_string().c_str()));
|
||||
} else {
|
||||
check_lua_status(l_state, luaL_loadfile(l_state, args.begin()->as_string().c_str()));
|
||||
}
|
||||
object_to_lua(l_state, target_string);
|
||||
for (torrent::Object::list_const_iterator itr = std::next(args.begin()), last = args.end(); itr != last; itr++) {
|
||||
object_to_lua(l_state, *itr);
|
||||
}
|
||||
lua_argc += args.size() - 1;
|
||||
break;
|
||||
}
|
||||
case torrent::Object::TYPE_STRING: {
|
||||
const torrent::Object::string_type& target = raw_args.as_string();
|
||||
if (flags & LuaEngine::flag_string) {
|
||||
check_lua_status(l_state, luaL_loadstring(l_state, target.c_str()));
|
||||
} else {
|
||||
check_lua_status(l_state, luaL_loadfile(l_state, target.c_str()));
|
||||
}
|
||||
object_to_lua(l_state, target_string);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw torrent::input_error("execute_lua(...): cannot call lua with arg type " + std::to_string(raw_args.type()));
|
||||
}
|
||||
check_lua_status(l_state, lua_pcall(l_state, lua_argc, LUA_MULTRET, 0));
|
||||
return lua_to_object(l_state);
|
||||
}
|
||||
|
||||
#else
|
||||
torrent::Object
|
||||
execute_lua(LuaEngine* engine, torrent::Object const& rawArgs, int flags) {
|
||||
throw torrent::input_error("Lua support not enabled");
|
||||
return torrent::Object();
|
||||
}
|
||||
LuaEngine::LuaEngine() {}
|
||||
LuaEngine::~LuaEngine() {}
|
||||
#endif
|
||||
} // namespace rpc
|
||||
@@ -0,0 +1,45 @@
|
||||
#ifndef RTORRENT_LUA_H
|
||||
#define RTORRENT_LUA_H
|
||||
|
||||
#include "rpc/command.h"
|
||||
#include <torrent/object.h>
|
||||
|
||||
#ifdef HAVE_LUA
|
||||
#include <lua.hpp>
|
||||
#endif
|
||||
|
||||
namespace rpc {
|
||||
|
||||
class LuaEngine {
|
||||
public:
|
||||
static const int flag_string = 0x1;
|
||||
static const std::string module_name;
|
||||
|
||||
LuaEngine();
|
||||
~LuaEngine();
|
||||
#ifdef HAVE_LUA
|
||||
// lua_CFunctions
|
||||
static int lua_init_module(lua_State* l_state);
|
||||
static int lua_rtorrent_call(lua_State* l_state);
|
||||
void set_package_preload();
|
||||
lua_State* state() { return m_luaState; }
|
||||
|
||||
private:
|
||||
static std::string search_lua_path(lua_State* l_state);
|
||||
lua_State* m_luaState;
|
||||
#endif
|
||||
};
|
||||
torrent::Object execute_lua(LuaEngine* engine, rpc::target_type target, const torrent::Object& raw_args, int flags);
|
||||
|
||||
#ifdef HAVE_LUA
|
||||
int rtorrent_call(lua_State* l_state);
|
||||
void init_rtorrent_module(lua_State* l_state);
|
||||
void object_to_lua(lua_State* l_state, torrent::Object const& object);
|
||||
void check_lua_status(lua_State* l_state, int status);
|
||||
torrent::Object lua_to_object(lua_State* l_state);
|
||||
torrent::Object lua_callstack_to_object(lua_State* l_state, int command_flags, rpc::target_type* target);
|
||||
#endif
|
||||
|
||||
} // namespace rpc
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,2 @@
|
||||
# third-party library, disable all checks in this folder.
|
||||
Checks: '-*'
|
||||
+25427
File diff suppressed because it is too large
Load Diff
@@ -38,7 +38,6 @@
|
||||
|
||||
#include "object_storage.h"
|
||||
|
||||
#include "rak/functional.h"
|
||||
#include "parse.h"
|
||||
#include "parse_commands.h"
|
||||
|
||||
@@ -223,8 +222,7 @@ object_storage::erase_multi_key(const torrent::raw_string& key, const std::strin
|
||||
if (r_itr == m_rlookup.end())
|
||||
return;
|
||||
|
||||
rlookup_mapped_iterator rm_itr = std::find_if(r_itr->second.begin(), r_itr->second.end(),
|
||||
rak::equal(key, rak::mem_ptr(&value_type::first)));
|
||||
rlookup_mapped_iterator rm_itr = std::find_if(r_itr->second.begin(), r_itr->second.end(), [key](value_type* type) { return key == type->first; });
|
||||
|
||||
if (rm_itr != r_itr->second.end())
|
||||
r_itr->second.erase(rm_itr);
|
||||
@@ -243,8 +241,7 @@ object_storage::set_multi_key_obj(const torrent::raw_string& key, const std::str
|
||||
if (r_itr == m_rlookup.end())
|
||||
r_itr = m_rlookup.insert(std::make_pair(cmd_key, rlookup_type::mapped_type())).first;
|
||||
|
||||
if (std::find_if(r_itr->second.begin(), r_itr->second.end(),
|
||||
rak::equal(key, rak::mem_ptr(&value_type::first))) == r_itr->second.end())
|
||||
if (std::find_if(r_itr->second.begin(), r_itr->second.end(), [key](value_type* type) { return key == type->first; }) == r_itr->second.end())
|
||||
r_itr->second.push_back(&*itr);
|
||||
}
|
||||
|
||||
@@ -259,7 +256,7 @@ object_storage::rlookup_list(const std::string& cmd_key) {
|
||||
|
||||
if (r_itr != m_rlookup.end())
|
||||
std::transform(r_itr->second.begin(), r_itr->second.end(), std::back_inserter(result),
|
||||
std::bind(&key_type::c_str, std::bind(rak::mem_ptr(&value_type::first), std::placeholders::_1)));
|
||||
std::bind(&key_type::c_str, std::bind(std::mem_fn(&value_type::first), std::placeholders::_1)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
+12
-19
@@ -39,30 +39,23 @@
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <rak/functional.h>
|
||||
#include <functional>
|
||||
#include <rak/path.h>
|
||||
#include <torrent/exceptions.h>
|
||||
|
||||
#include "parse.h"
|
||||
#include "parse_commands.h"
|
||||
#include "rpc/rpc_manager.h"
|
||||
|
||||
namespace rpc {
|
||||
|
||||
CommandMap commands;
|
||||
XmlRpc xmlrpc;
|
||||
ExecFile execFile;
|
||||
inline bool command_map_is_space(char c) {
|
||||
return c == ' ' || c == '\t';
|
||||
}
|
||||
|
||||
struct command_map_is_space : std::unary_function<char, bool> {
|
||||
bool operator () (char c) const {
|
||||
return c == ' ' || c == '\t';
|
||||
}
|
||||
};
|
||||
|
||||
struct command_map_is_newline : std::unary_function<char, bool> {
|
||||
bool operator () (char c) const {
|
||||
return c == '\n' || c == '\0' || c == ';';
|
||||
}
|
||||
};
|
||||
inline bool command_map_is_newline(char c) {
|
||||
return c == '\n' || c == '\0' || c == ';';
|
||||
}
|
||||
|
||||
// Only escape eol on odd number of escape characters. We know that
|
||||
// there can't be any characters in between, so this should work for
|
||||
@@ -131,7 +124,7 @@ parse_command_name(const char* first, const char* last, char* dest_first, char*
|
||||
// the code below for both cases.
|
||||
parse_command_type
|
||||
parse_command(target_type target, const char* first, const char* last) {
|
||||
first = std::find_if(first, last, std::not1(command_map_is_space()));
|
||||
first = std::find_if(first, last, [&](char c) { return !command_map_is_space(c); });
|
||||
|
||||
if (first == last || *first == '#')
|
||||
return std::make_pair(torrent::Object(), first);
|
||||
@@ -139,7 +132,7 @@ parse_command(target_type target, const char* first, const char* last) {
|
||||
char key[128];
|
||||
|
||||
first = parse_command_name(first, last, key, key + 128);
|
||||
first = std::find_if(first, last, std::not1(command_map_is_space()));
|
||||
first = std::find_if(first, last, [&](char c) { return !command_map_is_space(c); });
|
||||
|
||||
if (first == last || *first != '=')
|
||||
throw torrent::input_error("Could not find '=' in command '" + std::string(key) + "'.");
|
||||
@@ -150,10 +143,10 @@ parse_command(target_type target, const char* first, const char* last) {
|
||||
// Find the last character that is part of this command, skipping
|
||||
// the whitespace at the end. This ensures us that the caller
|
||||
// doesn't need to do this nor check for junk at the end.
|
||||
first = std::find_if(first, last, std::not1(command_map_is_space()));
|
||||
first = std::find_if(first, last, [&](char c) { return !command_map_is_space(c); });
|
||||
|
||||
if (first != last) {
|
||||
if (*first != '\n' && *first != ';' && *first != '\0')
|
||||
if (!command_map_is_newline(*first))
|
||||
throw torrent::input_error("Junk at end of input.");
|
||||
|
||||
first++;
|
||||
|
||||
@@ -40,9 +40,8 @@
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
|
||||
#include "command_map.h"
|
||||
#include "exec_file.h"
|
||||
#include "xmlrpc.h"
|
||||
#include "rpc_manager.h"
|
||||
|
||||
namespace core {
|
||||
class Download;
|
||||
@@ -50,11 +49,6 @@ namespace core {
|
||||
|
||||
namespace rpc {
|
||||
|
||||
// Move to another file?
|
||||
extern CommandMap commands;
|
||||
extern XmlRpc xmlrpc;
|
||||
extern ExecFile execFile;
|
||||
|
||||
typedef std::pair<torrent::Object, const char*> parse_command_type;
|
||||
|
||||
// The generic parse command function, used by the rest. At some point
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <torrent/exceptions.h>
|
||||
|
||||
#include "parse_commands.h"
|
||||
#include "rpc/rpc_manager.h"
|
||||
|
||||
namespace rpc {
|
||||
|
||||
CommandMap commands;
|
||||
RpcManager rpc;
|
||||
ExecFile execFile;
|
||||
|
||||
void
|
||||
RpcManager::object_to_target(const torrent::Object& obj, int call_flags, rpc::target_type* target, std::function<void()>* deleter) {
|
||||
if (call_flags & CommandMap::flag_no_target)
|
||||
return;
|
||||
|
||||
if (!obj.is_string()) {
|
||||
throw torrent::input_error("invalid parameters: target must be a string");
|
||||
}
|
||||
std::string target_string = obj.as_string();
|
||||
bool require_index = (call_flags & (CommandMap::flag_tracker_target | CommandMap::flag_file_target));
|
||||
if (target_string.size() == 0 && !require_index) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Length of SHA1 hash is 40
|
||||
if (target_string.size() < 40) {
|
||||
throw torrent::input_error("invalid parameters: invalid target");
|
||||
}
|
||||
|
||||
char type = 'd';
|
||||
std::string hash;
|
||||
std::string index;
|
||||
|
||||
const auto& delim_pos = target_string.find_first_of(':', 40);
|
||||
if (delim_pos == target_string.npos ||
|
||||
delim_pos + 2 >= target_string.size()) {
|
||||
if (require_index) {
|
||||
throw torrent::input_error("invalid parameters: no index");
|
||||
}
|
||||
hash = target_string;
|
||||
} else {
|
||||
hash = target_string.substr(0, delim_pos);
|
||||
type = target_string[delim_pos + 1];
|
||||
index = target_string.substr(delim_pos + 2);
|
||||
}
|
||||
core::Download* download = rpc.slot_find_download()(hash.c_str());
|
||||
|
||||
if (download == nullptr)
|
||||
throw torrent::input_error("invalid parameters: info-hash not found");
|
||||
|
||||
try {
|
||||
torrent::tracker::Tracker* tracker;
|
||||
|
||||
switch (type) {
|
||||
case 'd':
|
||||
*target = rpc::make_target(download);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
*target = rpc::make_target(command_base::target_file,
|
||||
rpc.slot_find_file()(download, std::stoi(std::string(index))));
|
||||
|
||||
break;
|
||||
|
||||
case 't':
|
||||
tracker = new torrent::tracker::Tracker(rpc.slot_find_tracker()(download, std::stoi(std::string(index))));
|
||||
|
||||
*target = rpc::make_target(command_base::target_tracker, tracker);
|
||||
*deleter = [tracker]() { delete tracker; };
|
||||
break;
|
||||
|
||||
case 'p': {
|
||||
if (index.size() < 40) {
|
||||
throw torrent::input_error("invalid parameters: not a hash string.");
|
||||
}
|
||||
|
||||
torrent::HashString hash;
|
||||
torrent::hash_string_from_hex_c_str(index.c_str(), hash);
|
||||
|
||||
*target = rpc::make_target(command_base::target_peer,
|
||||
rpc.slot_find_peer()(download, hash));
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw torrent::input_error("invalid parameters: unexpected target type");
|
||||
}
|
||||
|
||||
} catch (const std::logic_error&) {
|
||||
throw torrent::input_error("invalid parameters: invalid index");
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
RpcManager::process(RPCType type, const char* in_buffer, uint32_t length, slot_response_callback callback) {
|
||||
switch (type) {
|
||||
case RPCType::XML: {
|
||||
if (m_xmlrpc.is_valid() && rpc::call_command_value("network.rpc.use_xmlrpc")) {
|
||||
return m_xmlrpc.process(in_buffer, length, callback);
|
||||
} else {
|
||||
const std::string response = "<?xml version=\"1.0\"?><methodResponse><fault><struct><member><name>faultCode</name><value><i8>-501</i8></value></member><member><name>faultString</name><value><string>XML-RPC not supported</string></value></member></struct></fault></methodResponse>";
|
||||
return callback(response.c_str(), response.size());
|
||||
}
|
||||
}
|
||||
case RPCType::JSON: {
|
||||
if (rpc::call_command_value("network.rpc.use_jsonrpc")) {
|
||||
return m_jsonrpc.process(in_buffer, length, callback);
|
||||
} else {
|
||||
const std::string response = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32601,\"message\":\"JSON-RPC not supported\"},\"id\":null}";
|
||||
return callback(response.c_str(), response.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RpcManager::initialize() {
|
||||
m_xmlrpc.initialize();
|
||||
m_jsonrpc.initialize();
|
||||
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
void
|
||||
RpcManager::cleanup() {
|
||||
m_xmlrpc.cleanup();
|
||||
m_jsonrpc.cleanup();
|
||||
}
|
||||
|
||||
bool
|
||||
RpcManager::is_type_enabled(RPCType type) const {
|
||||
switch (type) {
|
||||
case RPCType::XML:
|
||||
return m_is_xmlrpc_enabled;
|
||||
case RPCType::JSON:
|
||||
return m_is_jsonrpc_enabled;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RpcManager::set_type_enabled(RPCType type, bool enabled) {
|
||||
switch (type) {
|
||||
case RPCType::XML:
|
||||
m_is_xmlrpc_enabled = enabled;
|
||||
case RPCType::JSON:
|
||||
m_is_jsonrpc_enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
RpcManager::is_initialized() const {
|
||||
return m_initialized;
|
||||
}
|
||||
|
||||
void
|
||||
RpcManager::insert_command(const char* name, const char* parm, const char* doc) {
|
||||
m_xmlrpc.insert_command(name, parm, doc);
|
||||
m_jsonrpc.insert_command(name, parm, doc);
|
||||
}
|
||||
|
||||
} // namespace rpc
|
||||
@@ -0,0 +1,92 @@
|
||||
#ifndef RTORRENT_RPC_MANAGER_H
|
||||
#define RTORRENT_RPC_MANAGER_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <torrent/common.h>
|
||||
|
||||
#include "rpc/command.h"
|
||||
#include "rpc/command_map.h"
|
||||
#include "rpc/exec_file.h"
|
||||
#include "rpc/jsonrpc.h"
|
||||
#include "rpc/xmlrpc.h"
|
||||
|
||||
namespace core {
|
||||
class Download;
|
||||
}
|
||||
|
||||
namespace rpc {
|
||||
|
||||
extern ExecFile execFile;
|
||||
extern CommandMap commands;
|
||||
|
||||
class rpc_error : public torrent::base_error {
|
||||
public:
|
||||
rpc_error(int type, std::string msg) :
|
||||
m_type(type), m_msg(msg) {}
|
||||
virtual ~rpc_error() throw() {}
|
||||
|
||||
virtual int type() const throw() { return m_type; }
|
||||
virtual const char* what() const throw() { return m_msg.c_str(); }
|
||||
|
||||
private:
|
||||
int m_type;
|
||||
std::string m_msg;
|
||||
};
|
||||
|
||||
class RpcManager {
|
||||
public:
|
||||
using slot_download = std::function<core::Download*(const char*)>;
|
||||
using slot_file = std::function<torrent::File*(core::Download*, uint32_t)>;
|
||||
using slot_tracker = std::function<torrent::tracker::Tracker(core::Download*, uint32_t)>;
|
||||
using slot_peer = std::function<torrent::Peer*(core::Download*, const torrent::HashString&)>;
|
||||
using slot_response_callback = std::function<bool(const char*, uint32_t)>;
|
||||
|
||||
enum RPCType { XML,
|
||||
JSON };
|
||||
|
||||
RpcManager() = default;
|
||||
~RpcManager() = default;
|
||||
|
||||
void initialize();
|
||||
void cleanup();
|
||||
bool is_initialized() const;
|
||||
|
||||
int64_t size_limit() { return m_xmlrpc.size_limit(); };
|
||||
void set_size_limit(uint64_t size) { m_xmlrpc.set_size_limit(size); };
|
||||
int dialect() { return m_xmlrpc.dialect(); }
|
||||
void set_dialect(int dialect) { m_xmlrpc.set_dialect(dialect); }
|
||||
|
||||
bool is_type_enabled(RPCType type) const;
|
||||
void set_type_enabled(RPCType type, bool enabled);
|
||||
|
||||
bool process(RPCType type, const char* in_buffer, uint32_t length, slot_response_callback callback);
|
||||
|
||||
void insert_command(const char* name, const char* parm, const char* doc);
|
||||
|
||||
slot_download& slot_find_download() { return m_slot_find_download; }
|
||||
slot_file& slot_find_file() { return m_slot_find_file; }
|
||||
slot_tracker& slot_find_tracker() { return m_slot_find_tracker; }
|
||||
slot_peer& slot_find_peer() { return m_slot_find_peer; }
|
||||
|
||||
static void object_to_target(const torrent::Object& obj, int callFlags, rpc::target_type* target, std::function<void()>* deleter);
|
||||
|
||||
private:
|
||||
XmlRpc m_xmlrpc;
|
||||
JsonRpc m_jsonrpc;
|
||||
|
||||
bool m_initialized = false;
|
||||
bool m_is_jsonrpc_enabled = true;
|
||||
bool m_is_xmlrpc_enabled = true;
|
||||
|
||||
slot_download m_slot_find_download;
|
||||
slot_file m_slot_find_file;
|
||||
slot_tracker m_slot_find_tracker;
|
||||
slot_peer m_slot_find_peer;
|
||||
};
|
||||
|
||||
extern RpcManager rpc;
|
||||
|
||||
} // namespace rpc
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user