Compare commits

...

61 Commits

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

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

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

`std::sort(transferChunks.begin(), transferChunks.end());`
2025-01-12 14:30:01 -05:00
Jari Sundell 2b73c92a3e Merge pull request #1372 from stickz/remove-rak-mem-fun
cleanup: Remove rak mem_fun
2025-01-12 18:43:15 +01:00
stickz c5563d65c5 cleanup: Remove rak mem_fun
This commit removes rak:mem_fun and replaces it with std::function and lambdas.
2025-01-12 10:18:50 -05:00
Jari Sundell d412caea66 Merge pull request #1370 from stickz/remove-rak-call-delete
cleanup: Replace rak::call_delete with lambdas
2025-01-12 11:40:10 +01:00
stickz 9c92bfc7e2 cleanup: Remove rak::call_delete 2025-01-11 21:22:40 -05:00
Jari Sundell 4a074adc7b Merge pull request #1369 from rakshasa/kannibalox-feature/color
Kannibalox feature/color
2025-01-09 17:12:23 +01:00
rakshasa 3bf494dbc6 Merge branch 'master' into kannibalox-feature/color 2025-01-09 15:55:11 +00:00
rakshasa b193fedc65 Moved inlined functions out of class declaration. 2025-01-09 15:51:04 +00:00
kannibalox 6c5a6a3bb3 Manually include config.h for clang-tidy
Specifically this fixes errors related to undefined macros in headers, since those aren't recorded
in compile_commands.json
2025-01-09 15:28:20 +00:00
kannibalox 7534b02815 Add page up/down and home/end bindings to download list 2025-01-09 15:28:16 +00:00
kannibalox 6d8c214d09 Manually include config.h for clang-tidy
Specifically this fixes errors related to undefined macros in headers, since those aren't recorded
in compile_commands.json
2025-01-08 19:49:59 +01:00
rakshasa 525b038dbb Inline test data instead of using separate text file. 2025-01-08 17:58:09 +00:00
kannibalox 06741a7578 Update XMLRPC unit tests to include <data> for arrays 2025-01-08 17:58:09 +00:00
rakshasa 4cc79590be Release 0.15.1. 2025-01-08 17:58:09 +00:00
simonc56 452397b8af tinyxml2: array with data for dict type 2025-01-08 17:58:09 +00:00
simonc56 c9a8a1e35c tinyxml2: in xmlrpc an array must include values in a data element 2025-01-08 17:58:09 +00:00
stickz 8f77d87994 tinyxml2: Change from i4 to i8
We need to follow the same specification as xmlrpc-c until we deprecate it. It is breaking various software such as sonarr. We can't have xmlrpc using i8 and tinyxml2 using i4, while we allow both to be used.
2025-01-08 17:58:09 +00:00
rakshasa 842edaa201 Added missing base64.h header. 2025-01-08 17:58:09 +00:00
kannibalox 4876301cf4 Add page up/down and home/end bindings to download list 2025-01-08 18:46:09 +01:00
rakshasa c2c6a4be26 Inline test data instead of using separate text file. 2025-01-03 06:04:09 +09:00
kannibalox 350d03ca04 Update XMLRPC unit tests to include <data> for arrays 2025-01-03 05:26:55 +09:00
rakshasa 31602917b7 Release 0.15.1. 2025-01-01 12:59:06 +00:00
rakshasa a9898c6ef6 Merge branch 'master' of github.com:rakshasa/rtorrent 2025-01-01 12:34:15 +00:00
simonc56 2bf81aa8f5 tinyxml2: array with data for dict type 2025-01-01 21:33:30 +09:00
simonc56 a9c0b65b9d tinyxml2: in xmlrpc an array must include values in a data element 2025-01-01 21:33:30 +09:00
stickz 73fed24459 tinyxml2: Change from i4 to i8
We need to follow the same specification as xmlrpc-c until we deprecate it. It is breaking various software such as sonarr. We can't have xmlrpc using i8 and tinyxml2 using i4, while we allow both to be used.
2025-01-01 21:32:23 +09:00
rakshasa f906e9a966 Added missing base64.h header. 2025-01-01 12:15:54 +00:00
kannibalox 090b3889ce Add color support for the TUI
Closes #398
2024-12-26 16:32:42 -05:00
123 changed files with 29444 additions and 3663 deletions
-132
View File
@@ -1,132 +0,0 @@
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
- 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
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
@@ -0,0 +1,93 @@
# Secure workflow with access to repository secrets and GitHub token for posting analysis results
name: Post the static analysis results
on:
workflow_run:
workflows: [ "Static analysis" ]
types: [ completed ]
jobs:
clang-tidy-results:
# Trigger the job only if the previous (insecure) workflow completed successfully
if: ${{ github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-22.04
permissions:
pull-requests: write
# OPTIONAL: auto-closing conversations requires the `contents` permission
contents: write
steps:
- name: Download analysis results
uses: actions/github-script@v7
with:
script: |
const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: ${{ github.event.workflow_run.id }},
});
const matchArtifact = artifacts.data.artifacts.filter((artifact) => {
return artifact.name == "clang-tidy-result"
})[0];
const download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: matchArtifact.id,
archive_format: "zip",
});
const fs = require("fs");
fs.writeFileSync("${{ github.workspace }}/clang-tidy-result.zip", Buffer.from(download.data));
- name: Extract analysis results
run: |
mkdir clang-tidy-result
unzip -j clang-tidy-result.zip -d clang-tidy-result
- name: Set environment variables
uses: actions/github-script@v7
with:
script: |
const assert = require("node:assert").strict;
const fs = require("fs");
function exportVar(varName, fileName, regEx) {
const val = fs.readFileSync("${{ github.workspace }}/clang-tidy-result/" + fileName, {
encoding: "ascii"
}).trimEnd();
assert.ok(regEx.test(val), "Invalid value format for " + varName);
core.exportVariable(varName, val);
}
exportVar("PR_ID", "pr-id.txt", /^[0-9]+$/);
exportVar("PR_HEAD_REPO", "pr-head-repo.txt", /^[-./0-9A-Z_a-z]+$/);
exportVar("PR_HEAD_SHA", "pr-head-sha.txt", /^[0-9A-Fa-f]+$/);
- uses: actions/checkout@v4
with:
repository: ${{ env.PR_HEAD_REPO }}
ref: ${{ env.PR_HEAD_SHA }}
persist-credentials: false
- name: Redownload analysis results
uses: actions/github-script@v7
with:
script: |
const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: ${{ github.event.workflow_run.id }},
});
const matchArtifact = artifacts.data.artifacts.filter((artifact) => {
return artifact.name == "clang-tidy-result"
})[0];
const download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: matchArtifact.id,
archive_format: "zip",
});
const fs = require("fs");
fs.writeFileSync("${{ github.workspace }}/clang-tidy-result.zip", Buffer.from(download.data));
- name: Extract analysis results
run: |
mkdir clang-tidy-result
unzip -j clang-tidy-result.zip -d clang-tidy-result
- name: Run clang-tidy-pr-comments action
uses: platisd/clang-tidy-pr-comments@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
clang_tidy_fixes: clang-tidy-result/fixes.yml
pull_request_id: ${{ env.PR_ID }}
+80
View File
@@ -0,0 +1,80 @@
name: Static analysis
on: pull_request
jobs:
clang-tidy:
runs-on: ubuntu-22.04
steps:
- name: Update Packages
run: |
sudo apt-get update
- name: Fetch libtorrent
run: |
git clone https://github.com/rakshasa/libtorrent
- name: Build libtorrent
run: |
cd libtorrent
libtoolize
aclocal -I scripts
autoconf -i
autoheader
automake --add-missing
./configure
make
sudo make install
cd ..
rm -rf libtorrent
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- name: Fetch base branch
run: |
git remote add upstream "https://github.com/${{ github.event.pull_request.base.repo.full_name }}"
git fetch --no-tags --no-recurse-submodules upstream "${{ github.event.pull_request.base.ref }}"
- name: Install Dependencies
run: |
sudo apt-get install -y bear clang-tidy libcurl4-openssl-dev
- name: Configure Project
run: |
libtoolize
aclocal -I scripts
autoconf -i
autoheader
automake --add-missing
./configure
- name: Prepare compile_commands.json
run: |
bear -- make
- name: Create results directory
run: |
mkdir clang-tidy-result
- name: Analyze
run: |
git diff -U0 "$(git merge-base HEAD "upstream/${{ github.event.pull_request.base.ref }}")" | clang-tidy-diff -p1 -path build -export-fixes clang-tidy-result/fixes.yml "-extra-arg=-include/${PWD}/config.h"
- name: Save PR metadata
run: |
echo "${{ github.event.number }}" > clang-tidy-result/pr-id.txt
echo "${{ github.event.pull_request.head.repo.full_name }}" > clang-tidy-result/pr-head-repo.txt
echo "${{ github.event.pull_request.head.sha }}" > clang-tidy-result/pr-head-sha.txt
- uses: actions/upload-artifact@v4
with:
name: clang-tidy-result
path: clang-tidy-result/
# - name: Run clang-tidy-pr-comments action
# uses: platisd/clang-tidy-pr-comments@v1
# with:
# # The GitHub token (or a personal access token)
# github_token: ${{ secrets.GITHUB_TOKEN }}
# # The path to the clang-tidy fixes generated previously
# clang_tidy_fixes: clang-tidy-result/fixes.yml
# # Optionally set to true if you want the Action to request
# # changes in case warnings are found
# request_changes: true
# # Optionally set the number of comments per review
# # to avoid GitHub API timeouts for heavily loaded
# # pull requests
# suggestions_per_comment: 10
+56
View File
@@ -0,0 +1,56 @@
name: Static analysis
on: pull_request
jobs:
unit-tests:
runs-on: ubuntu-22.04
steps:
- name: Update Packages
run: |
sudo apt-get update
- name: Fetch libtorrent
run: |
git clone https://github.com/rakshasa/libtorrent
- name: Build libtorrent
run: |
cd libtorrent
libtoolize
aclocal -I scripts
autoconf -i
autoheader
automake --add-missing
./configure
make
sudo make install
cd ..
rm -rf libtorrent
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- name: Fetch base branch
run: |
git remote add upstream "https://github.com/${{ github.event.pull_request.base.repo.full_name }}"
git fetch --no-tags --no-recurse-submodules upstream "${{ github.event.pull_request.base.ref }}"
- name: Install Dependencies
run: |
sudo apt-get install -y \
libcppunit-dev \
libcurl4-openssl-dev
- name: Configure Project
run: |
libtoolize
aclocal -I scripts
autoconf -i
autoheader
automake --add-missing
./configure
- name: Build Project
run: |
make
- name: Run Unit Tests
run: |
make check
+2 -2
View File
@@ -18,6 +18,7 @@
.libs
Makefile
aclocal.m4
ar-lib
autom4te.cache
compile
config.h
@@ -67,6 +68,5 @@ TAGS
# rTorrent specific files
###########################
src/rtorrent
test/rtorrentTest
test/rtorrent_Test*
test-driver
test/rtorrentTest.trs
-1
View File
@@ -10,7 +10,6 @@ EXTRA_DIST= \
rak/error_number.h \
rak/file_stat.h \
rak/fs_stat.h \
rak/functional.h \
rak/path.h \
rak/partial_queue.h \
rak/priority_queue.h \
+12 -8
View File
@@ -1,20 +1,23 @@
m4_pattern_allow([PKG_CHECK_EXISTS])
AC_INIT([rtorrent],[0.15.0],[sundell.software@gmail.com])
AC_INIT([rtorrent],[0.15.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])
AC_PROG_RANLIB
AC_PROG_CXX
AC_SYS_LARGEFILE
LT_INIT
AX_CXX_COMPILE_STDCXX([14], [noext], [mandatory])
AC_PROG_CXX
AC_DEFINE([API_VERSION], [11], [api version])
# Filter out unwanted flags added by autoconf on some systems, e.g. MacOS.
TORRENT_REMOVE_UNWANTED(CXX, $CXX, -std=c++11 -std=gnu++11)
AX_CXX_COMPILE_STDCXX([17], [noext], [mandatory])
AC_SYS_LARGEFILE
RAK_CHECK_CFLAGS
RAK_CHECK_CXXFLAGS
@@ -51,12 +54,13 @@ fi
PKG_CHECK_MODULES([LIBCURL], [libcurl],, [LIBCURL_CHECK_CONFIG])
PKG_CHECK_MODULES([CPPUNIT], [cppunit],, [no_cppunit="yes"])
PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.15.0])
PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.15.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
-4
View File
@@ -499,10 +499,6 @@ Number of attempts to check the hash while using the mincore status,
before forcing. Overworked systems might need lower values to get a
decent hash checking rate.
.TP
\fBsafe_sync = \fIyes|no\fB\fR
Always use MS_SYNC rather than MS_ASYNC when syncing chunks. This may
be nessesary in case of filesystem bugs like NFS in linux ~2.6.13.
.TP
\fBmax_open_files = \fIvalue\fB\fR
Number of files to simultaneously keep open. LibTorrent dynamically
opens and closes files as necessary when mapping files to
-10
View File
@@ -978,16 +978,6 @@ decent hash checking rate.
</para></listitem>
</varlistentry>
<varlistentry>
<term>safe_sync = <replaceable>yes|no</replaceable></term>
<listitem><para>
Always use MS_SYNC rather than MS_ASYNC when syncing chunks. This may
be nessesary in case of filesystem bugs like NFS in linux ~2.6.13.
</para></listitem>
</varlistentry>
<varlistentry>
<term>max_open_files = <replaceable>value</replaceable></term>
<listitem><para>
+1 -1
View File
@@ -115,7 +115,7 @@ advance_backward(_InputIter __first, _InputIter __last, _Distance __distance) {
}
template <typename _Value>
struct compare_base : public std::binary_function<_Value, _Value, bool> {
struct compare_base : public std::function<bool(_Value, _Value)> {
bool operator () (const _Value& complete, const _Value& base) const {
return !complete.compare(0, base.size(), base);
}
-683
View File
@@ -1,683 +0,0 @@
// rak - Rakshasa's toolbox
// Copyright (C) 2005-2007, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RAK_FUNCTIONAL_H
#define RAK_FUNCTIONAL_H
#include <cstddef>
#include <functional>
namespace rak {
template <typename Type>
struct reference_fix {
typedef Type type;
};
template <typename Type>
struct reference_fix<Type&> {
typedef Type type;
};
template <typename Type>
struct value_t {
value_t(Type v) : m_v(v) {}
Type operator () () const { return m_v; }
Type m_v;
};
template <typename Type>
inline value_t<Type>
value(Type v) {
return value_t<Type>(v);
}
template <typename Type, typename Ftor>
struct accumulate_t {
accumulate_t(Type t, Ftor f) : result(t), m_f(f) {}
template <typename Arg>
void operator () (const Arg& a) { result += m_f(a); }
Type result;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline accumulate_t<Type, Ftor>
accumulate(Type t, Ftor f) {
return accumulate_t<Type, Ftor>(t, f);
}
// Operators:
template <typename Type, typename Ftor>
struct equal_t {
typedef bool result_type;
equal_t(Type t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (Arg& a) {
return m_t == m_f(a);
}
Type m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline equal_t<Type, Ftor>
equal(Type t, Ftor f) {
return equal_t<Type, Ftor>(t, f);
}
template <typename Type, typename Ftor>
struct equal_ptr_t {
typedef bool result_type;
equal_ptr_t(Type* t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (const Arg& a) {
return *m_t == *m_f(a);
}
Type* m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline equal_ptr_t<Type, Ftor>
equal_ptr(Type* t, Ftor f) {
return equal_ptr_t<Type, Ftor>(t, f);
}
template <typename Type, typename Ftor>
struct not_equal_t {
typedef bool result_type;
not_equal_t(Type t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (Arg& a) {
return m_t != m_f(a);
}
Type m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline not_equal_t<Type, Ftor>
not_equal(Type t, Ftor f) {
return not_equal_t<Type, Ftor>(t, f);
}
template <typename Type, typename Ftor>
struct less_t {
typedef bool result_type;
less_t(Type t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (Arg& a) {
return m_t < m_f(a);
}
Type m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline less_t<Type, Ftor>
less(Type t, Ftor f) {
return less_t<Type, Ftor>(t, f);
}
template <typename FtorA, typename FtorB>
struct less2_t : public std::binary_function<typename FtorA::argument_type, typename FtorB::argument_type, bool> {
less2_t(FtorA f_a, FtorB f_b) : m_f_a(f_a), m_f_b(f_b) {}
bool operator () (typename FtorA::argument_type a, typename FtorB::argument_type b) {
return m_f_a(a) < m_f_b(b);
}
FtorA m_f_a;
FtorB m_f_b;
};
template <typename FtorA, typename FtorB>
inline less2_t<FtorA, FtorB>
less2(FtorA f_a, FtorB f_b) {
return less2_t<FtorA,FtorB>(f_a,f_b);
}
template <typename Type, typename Ftor>
struct _greater {
typedef bool result_type;
_greater(Type t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (Arg& a) {
return m_t > m_f(a);
}
Type m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline _greater<Type, Ftor>
greater(Type t, Ftor f) {
return _greater<Type, Ftor>(t, f);
}
template <typename FtorA, typename FtorB>
struct greater2_t : public std::binary_function<typename FtorA::argument_type, typename FtorB::argument_type, bool> {
greater2_t(FtorA f_a, FtorB f_b) : m_f_a(f_a), m_f_b(f_b) {}
bool operator () (typename FtorA::argument_type a, typename FtorB::argument_type b) {
return m_f_a(a) > m_f_b(b);
}
FtorA m_f_a;
FtorB m_f_b;
};
template <typename FtorA, typename FtorB>
inline greater2_t<FtorA, FtorB>
greater2(FtorA f_a, FtorB f_b) {
return greater2_t<FtorA,FtorB>(f_a,f_b);
}
template <typename Type, typename Ftor>
struct less_equal_t {
typedef bool result_type;
less_equal_t(Type t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (Arg& a) {
return m_t <= m_f(a);
}
Type m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline less_equal_t<Type, Ftor>
less_equal(Type t, Ftor f) {
return less_equal_t<Type, Ftor>(t, f);
}
template <typename Type, typename Ftor>
struct greater_equal_t {
typedef bool result_type;
greater_equal_t(Type t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (Arg& a) {
return m_t >= m_f(a);
}
Type m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline greater_equal_t<Type, Ftor>
greater_equal(Type t, Ftor f) {
return greater_equal_t<Type, Ftor>(t, f);
}
template<typename Tp>
struct invert : public std::unary_function<Tp, Tp> {
Tp
operator () (const Tp& x) const { return ~x; }
};
template <typename Src, typename Dest>
struct on_t : public std::unary_function<typename Src::argument_type, typename Dest::result_type> {
typedef typename Dest::result_type result_type;
on_t(Src s, Dest d) : m_dest(d), m_src(s) {}
result_type operator () (typename reference_fix<typename Src::argument_type>::type arg) {
return m_dest(m_src(arg));
}
Dest m_dest;
Src m_src;
};
template <typename Src, typename Dest>
inline on_t<Src, Dest>
on(Src s, Dest d) {
return on_t<Src, Dest>(s, d);
}
template <typename Src, typename Dest>
struct on2_t : public std::binary_function<typename Src::argument_type, typename Dest::second_argument_type, typename Dest::result_type> {
typedef typename Dest::result_type result_type;
on2_t(Src s, Dest d) : m_dest(d), m_src(s) {}
result_type operator () (typename reference_fix<typename Src::argument_type>::type first, typename reference_fix<typename Dest::second_argument_type>::type second) {
return m_dest(m_src(first), second);
}
Dest m_dest;
Src m_src;
};
template <typename Src, typename Dest>
inline on2_t<Src, Dest>
on2(Src s, Dest d) {
return on2_t<Src, Dest>(s, d);
}
// Creates a functor for accessing a member.
template <typename Class, typename Member>
struct mem_ptr_t : public std::unary_function<Class*, Member&> {
mem_ptr_t(Member Class::*m) : m_member(m) {}
Member& operator () (Class* c) {
return c->*m_member;
}
const Member& operator () (const Class* c) {
return c->*m_member;
}
Member Class::*m_member;
};
template <typename Class, typename Member>
inline mem_ptr_t<Class, Member>
mem_ptr(Member Class::*m) {
return mem_ptr_t<Class, Member>(m);
}
template <typename Class, typename Member>
struct mem_ref_t : public std::unary_function<Class&, Member&> {
mem_ref_t(Member Class::*m) : m_member(m) {}
Member& operator () (Class& c) {
return c.*m_member;
}
Member Class::*m_member;
};
template <typename Class, typename Member>
struct const_mem_ref_t : public std::unary_function<const Class&, const Member&> {
const_mem_ref_t(const Member Class::*m) : m_member(m) {}
const Member& operator () (const Class& c) {
return c.*m_member;
}
const Member Class::*m_member;
};
template <typename Class, typename Member>
inline mem_ref_t<Class, Member>
mem_ref(Member Class::*m) {
return mem_ref_t<Class, Member>(m);
}
template <typename Class, typename Member>
inline const_mem_ref_t<Class, Member>
const_mem_ref(const Member Class::*m) {
return const_mem_ref_t<Class, Member>(m);
}
template <typename Cond, typename Then>
struct if_then_t {
if_then_t(Cond c, Then t) : m_cond(c), m_then(t) {}
template <typename Arg>
void operator () (Arg& a) {
if (m_cond(a))
m_then(a);
}
Cond m_cond;
Then m_then;
};
template <typename Cond, typename Then>
inline if_then_t<Cond, Then>
if_then(Cond c, Then t) {
return if_then_t<Cond, Then>(c, t);
}
template <typename T>
struct call_delete : public std::unary_function<T*, void> {
void operator () (T* t) {
delete t;
}
};
template <typename T>
inline void
call_delete_func(T* t) {
delete t;
}
template <typename Operation>
class bind1st_t : public std::unary_function<typename Operation::second_argument_type, typename Operation::result_type> {
public:
typedef typename reference_fix<typename Operation::first_argument_type>::type value_type;
typedef typename reference_fix<typename Operation::second_argument_type>::type argument_type;
bind1st_t(const Operation& op, const value_type v) :
m_op(op), m_value(v) {}
typename Operation::result_type
operator () (const argument_type arg) {
return m_op(m_value, arg);
}
protected:
Operation m_op;
value_type m_value;
};
template <typename Operation, typename Type>
inline bind1st_t<Operation>
bind1st(const Operation& op, const Type& val) {
return bind1st_t<Operation>(op, val);
}
template <typename Operation>
class bind2nd_t : public std::unary_function<typename Operation::first_argument_type, typename Operation::result_type> {
public:
typedef typename reference_fix<typename Operation::first_argument_type>::type argument_type;
typedef typename reference_fix<typename Operation::second_argument_type>::type value_type;
bind2nd_t(const Operation& op, const value_type v) :
m_op(op), m_value(v) {}
typename Operation::result_type
operator () (argument_type arg) {
return m_op(arg, m_value);
}
protected:
Operation m_op;
value_type m_value;
};
template <typename Operation, typename Type>
inline bind2nd_t<Operation>
bind2nd(const Operation& op, const Type& val) {
return bind2nd_t<Operation>(op, val);
}
// Lightweight callback function including pointer to object. Should
// be replaced by TR1 stuff later. Requires an object to bind, instead
// of using a seperate functor for that.
template <typename Ret>
class ptr_fun0 {
public:
typedef Ret result_type;
typedef Ret (*Function)();
ptr_fun0() {}
ptr_fun0(Function f) : m_function(f) {}
bool is_valid() const { return m_function; }
Ret operator () () { return m_function(); }
private:
Function m_function;
};
template <typename Object, typename Ret>
class mem_fun0 {
public:
typedef Ret result_type;
typedef Ret (Object::*Function)();
mem_fun0() : m_object(NULL) {}
mem_fun0(Object* o, Function f) : m_object(o), m_function(f) {}
bool is_valid() const { return m_object; }
Ret operator () () { return (m_object->*m_function)(); }
private:
Object* m_object;
Function m_function;
};
template <typename Object, typename Ret>
class const_mem_fun0 {
public:
typedef Ret result_type;
typedef Ret (Object::*Function)() const;
const_mem_fun0() : m_object(NULL) {}
const_mem_fun0(const Object* o, Function f) : m_object(o), m_function(f) {}
bool is_valid() const { return m_object; }
Ret operator () () const { return (m_object->*m_function)(); }
private:
const Object* m_object;
Function m_function;
};
template <typename Object, typename Ret, typename Arg1>
class mem_fun1 {
public:
typedef Ret result_type;
typedef Ret (Object::*Function)(Arg1);
mem_fun1() : m_object(NULL) {}
mem_fun1(Object* o, Function f) : m_object(o), m_function(f) {}
bool is_valid() const { return m_object; }
Ret operator () (Arg1 a1) { return (m_object->*m_function)(a1); }
private:
Object* m_object;
Function m_function;
};
template <typename Object, typename Ret, typename Arg1>
class const_mem_fun1 {
public:
typedef Ret result_type;
typedef Ret (Object::*Function)(Arg1) const;
const_mem_fun1() : m_object(NULL) {}
const_mem_fun1(const Object* o, Function f) : m_object(o), m_function(f) {}
bool is_valid() const { return m_object; }
Ret operator () (Arg1 a1) const { return (m_object->*m_function)(a1); }
private:
const Object* m_object;
Function m_function;
};
template <typename Object, typename Ret, typename Arg1, typename Arg2>
class mem_fun2 : public std::binary_function<Arg1, Arg2, Ret> {
public:
typedef Ret result_type;
typedef Ret (Object::*Function)(Arg1, Arg2);
typedef Object object_type;
mem_fun2() : m_object(NULL) {}
mem_fun2(Object* o, Function f) : m_object(o), m_function(f) {}
bool is_valid() const { return m_object; }
object_type* object() { return m_object; }
const object_type* object() const { return m_object; }
Ret operator () (Arg1 a1, Arg2 a2) { return (m_object->*m_function)(a1, a2); }
private:
Object* m_object;
Function m_function;
};
template <typename Object, typename Ret, typename Arg1, typename Arg2, typename Arg3>
class mem_fun3 {
public:
typedef Ret result_type;
typedef Ret (Object::*Function)(Arg1, Arg2, Arg3);
mem_fun3() : m_object(NULL) {}
mem_fun3(Object* o, Function f) : m_object(o), m_function(f) {}
bool is_valid() const { return m_object; }
Ret operator () (Arg1 a1, Arg2 a2, Arg3 a3) { return (m_object->*m_function)(a1, a2, a3); }
private:
Object* m_object;
Function m_function;
};
template <typename Ret>
inline ptr_fun0<Ret>
ptr_fun(Ret (*f)()) { return ptr_fun0<Ret>(f); }
template <typename Object, typename Ret>
inline mem_fun0<Object, Ret>
make_mem_fun(Object* o, Ret (Object::*f)()) {
return mem_fun0<Object, Ret>(o, f);
}
template <typename Object, typename Ret>
inline const_mem_fun0<Object, Ret>
make_mem_fun(const Object* o, Ret (Object::*f)() const) {
return const_mem_fun0<Object, Ret>(o, f);
}
template <typename Object, typename Ret, typename Arg1>
inline mem_fun1<Object, Ret, Arg1>
make_mem_fun(Object* o, Ret (Object::*f)(Arg1)) {
return mem_fun1<Object, Ret, Arg1>(o, f);
}
template <typename Object, typename Ret, typename Arg1>
inline const_mem_fun1<Object, Ret, Arg1>
make_mem_fun(const Object* o, Ret (Object::*f)(Arg1) const) {
return const_mem_fun1<Object, Ret, Arg1>(o, f);
}
template <typename Object, typename Ret, typename Arg1, typename Arg2>
inline mem_fun2<Object, Ret, Arg1, Arg2>
make_mem_fun(Object* o, Ret (Object::*f)(Arg1, Arg2)) {
return mem_fun2<Object, Ret, Arg1, Arg2>(o, f);
}
template <typename Object, typename Ret, typename Arg1, typename Arg2, typename Arg3>
inline mem_fun3<Object, Ret, Arg1, Arg2, Arg3>
make_mem_fun(Object* o, Ret (Object::*f)(Arg1, Arg2, Arg3)) {
return mem_fun3<Object, Ret, Arg1, Arg2, Arg3>(o, f);
}
template <typename Container>
inline void
slot_list_call(const Container& slot_list) {
if (slot_list.empty())
return;
typename Container::const_iterator first = slot_list.begin();
typename Container::const_iterator next = slot_list.begin();
while (++next != slot_list.end()) {
(*first)();
first = next;
}
(*first)();
}
template <typename Container, typename Arg1>
inline void
slot_list_call(const Container& slot_list, Arg1 arg1) {
if (slot_list.empty())
return;
typename Container::const_iterator first = slot_list.begin();
typename Container::const_iterator next = slot_list.begin();
while (++next != slot_list.end()) {
(*first)(arg1);
first = next;
}
(*first)(arg1);
}
template <typename Container, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
inline void
slot_list_call(const Container& slot_list, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) {
if (slot_list.empty())
return;
typename Container::const_iterator first = slot_list.begin();
typename Container::const_iterator next = slot_list.begin();
while (++next != slot_list.end()) {
(*first)(arg1, arg2, arg3, arg4);
first = next;
}
(*first)(arg1, arg2, arg3, arg4);
}
}
#endif
+3 -3
View File
@@ -10,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;
+5 -43
View File
@@ -1,44 +1,8 @@
// rak - Rakshasa's toolbox
// Copyright (C) 2005-2007, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RAK_PRIORITY_QUEUE_DEFAULT_H
#define RAK_PRIORITY_QUEUE_DEFAULT_H
#include <cassert>
#include <functional>
#include <rak/allocators.h>
#include <rak/priority_queue.h>
#include <rak/timer.h>
@@ -52,8 +16,7 @@ public:
priority_item() {}
~priority_item() {
if (is_queued())
throw torrent::internal_error("priority_item::~priority_item() called on a queued item.");
assert(!is_queued() && "priority_item::~priority_item() called on a queued item.");
m_time = timer();
m_slot = slot_void();
@@ -85,8 +48,7 @@ struct priority_compare {
};
typedef std::equal_to<priority_item*> priority_equal;
typedef priority_queue<priority_item*, priority_compare, priority_equal,
cacheline_allocator<priority_item*> > priority_queue_default;
typedef priority_queue<priority_item*, priority_compare, priority_equal> priority_queue_default;
inline void
priority_queue_perform(priority_queue_default* queue, timer t) {
@@ -137,10 +99,10 @@ priority_queue_erase(priority_queue_default* queue, priority_item* item) {
inline void
priority_queue_update(priority_queue_default* queue, priority_item* item, timer t) {
if (t == timer())
throw torrent::internal_error("priority_queue_update(...) received a bad timer.");
throw torrent::internal_error("priority_queue_insert(...) received a bad timer.");
if (!item->is_valid())
throw torrent::internal_error("priority_queue_update(...) called on an invalid item.");
throw torrent::internal_error("priority_queue_insert(...) called on an invalid item.");
if (queue->find(item) == queue->end()) {
if (item->is_queued())
+1 -1
View File
@@ -50,7 +50,7 @@
namespace rak {
class regex : public std::unary_function<std::string, bool> {
class regex : public std::function<bool (std::string)> {
public:
regex() {}
regex(const std::string& p) : m_pattern(p) {}
+42
View File
@@ -0,0 +1,42 @@
-- the "rtorrent" table is passed in by the C++ code, modify and
-- return it for loading.
local args = {...}
local rtorrent = args[1]
-- Autocall
-- Allows syntax like `rtorrent.autocall.system.hostname()`
local mt = {}
function mt.__call (t, ...)
name = table.concat(rawget(t, "__namestack"), ".")
success, ret = pcall(rtorrent.call, name, ...)
if not success then error(name..": "..ret, 2) end
return ret
end
function mt.__index (t, key)
ns = rawget(t, "__namestack") or {}
table.insert(ns, key)
return setmetatable({__namestack=ns}, mt)
end
rtorrent["autocall"] = setmetatable({}, mt)
-- Autocall-config Same as autocall, but passes an empty first target
-- implicitly, for syntax like `rtorrent.autocall_config.session.directory.set("/tmp/")`
local mt = {}
function mt.__call (t, ...)
name = table.concat(rawget(t, "__namestack"), ".")
success, ret = pcall(rtorrent.call, name, "", ...)
if not success then error(name..": "..ret, 2) end
return ret
end
function mt.__index (t, key)
ns = rawget(t, "__namestack")
if ns == nil then
if _G[key] ~= nil then return _G[key] end
ns = {}
end
table.insert(ns, key)
return setmetatable({__namestack=ns}, mt)
end
rtorrent["autocall_config"] = setmetatable({}, mt)
return rtorrent
+661
View File
@@ -0,0 +1,661 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_lua.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_PROG_LUA[([MINIMUM-VERSION], [TOO-BIG-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])]
# AX_LUA_HEADERS[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])]
# AX_LUA_LIBS[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])]
# AX_LUA_READLINE[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])]
#
# DESCRIPTION
#
# Detect a Lua interpreter, optionally specifying a minimum and maximum
# version number. Set up important Lua paths, such as the directories in
# which to install scripts and modules (shared libraries).
#
# Also detect Lua headers and libraries. The Lua version contained in the
# header is checked to match the Lua interpreter version exactly. When
# searching for Lua libraries, the version number is used as a suffix.
# This is done with the goal of supporting multiple Lua installs (5.1,
# 5.2, and 5.3 side-by-side).
#
# A note on compatibility with previous versions: This file has been
# mostly rewritten for serial 18. Most developers should be able to use
# these macros without needing to modify configure.ac. Care has been taken
# to preserve each macro's behavior, but there are some differences:
#
# 1) AX_WITH_LUA is deprecated; it now expands to the exact same thing as
# AX_PROG_LUA with no arguments.
#
# 2) AX_LUA_HEADERS now checks that the version number defined in lua.h
# matches the interpreter version. AX_LUA_HEADERS_VERSION is therefore
# unnecessary, so it is deprecated and does not expand to anything.
#
# 3) The configure flag --with-lua-suffix no longer exists; the user
# should instead specify the LUA precious variable on the command line.
# See the AX_PROG_LUA description for details.
#
# Please read the macro descriptions below for more information.
#
# This file was inspired by Andrew Dalke's and James Henstridge's
# python.m4 and Tom Payne's, Matthieu Moy's, and Reuben Thomas's ax_lua.m4
# (serial 17). Basically, this file is a mash-up of those two files. I
# like to think it combines the best of the two!
#
# AX_PROG_LUA: Search for the Lua interpreter, and set up important Lua
# paths. Adds precious variable LUA, which may contain the path of the Lua
# interpreter. If LUA is blank, the user's path is searched for an
# suitable interpreter.
#
# If MINIMUM-VERSION is supplied, then only Lua interpreters with a
# version number greater or equal to MINIMUM-VERSION will be accepted. If
# TOO-BIG-VERSION is also supplied, then only Lua interpreters with a
# version number greater or equal to MINIMUM-VERSION and less than
# TOO-BIG-VERSION will be accepted.
#
# The Lua version number, LUA_VERSION, is found from the interpreter, and
# substituted. LUA_PLATFORM is also found, but not currently supported (no
# standard representation).
#
# Finally, the macro finds four paths:
#
# luadir Directory to install Lua scripts.
# pkgluadir $luadir/$PACKAGE
# luaexecdir Directory to install Lua modules.
# pkgluaexecdir $luaexecdir/$PACKAGE
#
# These paths are found based on $prefix, $exec_prefix, Lua's
# package.path, and package.cpath. The first path of package.path
# beginning with $prefix is selected as luadir. The first path of
# package.cpath beginning with $exec_prefix is used as luaexecdir. This
# should work on all reasonable Lua installations. If a path cannot be
# determined, a default path is used. Of course, the user can override
# these later when invoking make.
#
# luadir Default: $prefix/share/lua/$LUA_VERSION
# luaexecdir Default: $exec_prefix/lib/lua/$LUA_VERSION
#
# These directories can be used by Automake as install destinations. The
# variable name minus 'dir' needs to be used as a prefix to the
# appropriate Automake primary, e.g. lua_SCRIPS or luaexec_LIBRARIES.
#
# If an acceptable Lua interpreter is found, then ACTION-IF-FOUND is
# performed, otherwise ACTION-IF-NOT-FOUND is preformed. If ACTION-IF-NOT-
# FOUND is blank, then it will default to printing an error. To prevent
# the default behavior, give ':' as an action.
#
# AX_LUA_HEADERS: Search for Lua headers. Requires that AX_PROG_LUA be
# expanded before this macro. Adds precious variable LUA_INCLUDE, which
# may contain Lua specific include flags, e.g. -I/usr/include/lua5.1. If
# LUA_INCLUDE is blank, then this macro will attempt to find suitable
# flags.
#
# LUA_INCLUDE can be used by Automake to compile Lua modules or
# executables with embedded interpreters. The *_CPPFLAGS variables should
# be used for this purpose, e.g. myprog_CPPFLAGS = $(LUA_INCLUDE).
#
# This macro searches for the header lua.h (and others). The search is
# performed with a combination of CPPFLAGS, CPATH, etc, and LUA_INCLUDE.
# If the search is unsuccessful, then some common directories are tried.
# If the headers are then found, then LUA_INCLUDE is set accordingly.
#
# The paths automatically searched are:
#
# * /usr/include/luaX.Y
# * /usr/include/lua/X.Y
# * /usr/include/luaXY
# * /usr/local/include/luaX.Y
# * /usr/local/include/lua-X.Y
# * /usr/local/include/lua/X.Y
# * /usr/local/include/luaXY
#
# (Where X.Y is the Lua version number, e.g. 5.1.)
#
# The Lua version number found in the headers is always checked to match
# the Lua interpreter's version number. Lua headers with mismatched
# version numbers are not accepted.
#
# If headers are found, then ACTION-IF-FOUND is performed, otherwise
# ACTION-IF-NOT-FOUND is performed. If ACTION-IF-NOT-FOUND is blank, then
# it will default to printing an error. To prevent the default behavior,
# set the action to ':'.
#
# AX_LUA_LIBS: Search for Lua libraries. Requires that AX_PROG_LUA be
# expanded before this macro. Adds precious variable LUA_LIB, which may
# contain Lua specific linker flags, e.g. -llua5.1. If LUA_LIB is blank,
# then this macro will attempt to find suitable flags.
#
# LUA_LIB can be used by Automake to link Lua modules or executables with
# embedded interpreters. The *_LIBADD and *_LDADD variables should be used
# for this purpose, e.g. mymod_LIBADD = $(LUA_LIB).
#
# This macro searches for the Lua library. More technically, it searches
# for a library containing the function lua_load. The search is performed
# with a combination of LIBS, LIBRARY_PATH, and LUA_LIB.
#
# If the search determines that some linker flags are missing, then those
# flags will be added to LUA_LIB.
#
# If libraries are found, then ACTION-IF-FOUND is performed, otherwise
# ACTION-IF-NOT-FOUND is performed. If ACTION-IF-NOT-FOUND is blank, then
# it will default to printing an error. To prevent the default behavior,
# set the action to ':'.
#
# AX_LUA_READLINE: Search for readline headers and libraries. Requires the
# AX_LIB_READLINE macro, which is provided by ax_lib_readline.m4 from the
# Autoconf Archive.
#
# If a readline compatible library is found, then ACTION-IF-FOUND is
# performed, otherwise ACTION-IF-NOT-FOUND is performed.
#
# LICENSE
#
# Copyright (c) 2015 Reuben Thomas <rrt@sc3d.org>
# Copyright (c) 2014 Tim Perkins <tprk77@gmail.com>
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <https://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 42
dnl =========================================================================
dnl AX_PROG_LUA([MINIMUM-VERSION], [TOO-BIG-VERSION],
dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
dnl =========================================================================
AC_DEFUN([AX_PROG_LUA],
[
dnl Check for required tools.
AC_REQUIRE([AC_PROG_GREP])
AC_REQUIRE([AC_PROG_SED])
dnl Make LUA a precious variable.
AC_ARG_VAR([LUA], [The Lua interpreter, e.g. /usr/bin/lua5.1])
dnl Find a Lua interpreter.
m4_define_default([_AX_LUA_INTERPRETER_LIST],
[lua lua5.3 lua53 lua5.2 lua52 lua5.1 lua51 lua50])
m4_if([$1], [],
[ dnl No version check is needed. Find any Lua interpreter.
AS_IF([test "x$LUA" = 'x'],
[AC_PATH_PROGS([LUA], [_AX_LUA_INTERPRETER_LIST], [:])])
ax_display_LUA='lua'
AS_IF([test "x$LUA" != 'x:'],
[ dnl At least check if this is a Lua interpreter.
AC_MSG_CHECKING([if $LUA is a Lua interpreter])
_AX_LUA_CHK_IS_INTRP([$LUA],
[AC_MSG_RESULT([yes])],
[ AC_MSG_RESULT([no])
AC_MSG_ERROR([not a Lua interpreter])
])
])
],
[ dnl A version check is needed.
AS_IF([test "x$LUA" != 'x'],
[ dnl Check if this is a Lua interpreter.
AC_MSG_CHECKING([if $LUA is a Lua interpreter])
_AX_LUA_CHK_IS_INTRP([$LUA],
[AC_MSG_RESULT([yes])],
[ AC_MSG_RESULT([no])
AC_MSG_ERROR([not a Lua interpreter])
])
dnl Check the version.
m4_if([$2], [],
[_ax_check_text="whether $LUA version >= $1"],
[_ax_check_text="whether $LUA version >= $1, < $2"])
AC_MSG_CHECKING([$_ax_check_text])
_AX_LUA_CHK_VER([$LUA], [$1], [$2],
[AC_MSG_RESULT([yes])],
[ AC_MSG_RESULT([no])
AC_MSG_ERROR([version is out of range for specified LUA])])
ax_display_LUA=$LUA
],
[ dnl Try each interpreter until we find one that satisfies VERSION.
m4_if([$2], [],
[_ax_check_text="for a Lua interpreter with version >= $1"],
[_ax_check_text="for a Lua interpreter with version >= $1, < $2"])
AC_CACHE_CHECK([$_ax_check_text],
[ax_cv_pathless_LUA],
[ for ax_cv_pathless_LUA in _AX_LUA_INTERPRETER_LIST none; do
test "x$ax_cv_pathless_LUA" = 'xnone' && break
_AX_LUA_CHK_IS_INTRP([$ax_cv_pathless_LUA], [], [continue])
_AX_LUA_CHK_VER([$ax_cv_pathless_LUA], [$1], [$2], [break])
done
])
dnl Set $LUA to the absolute path of $ax_cv_pathless_LUA.
AS_IF([test "x$ax_cv_pathless_LUA" = 'xnone'],
[LUA=':'],
[AC_PATH_PROG([LUA], [$ax_cv_pathless_LUA])])
ax_display_LUA=$ax_cv_pathless_LUA
])
])
AS_IF([test "x$LUA" = 'x:'],
[ dnl Run any user-specified action, or abort.
m4_default([$4], [AC_MSG_ERROR([cannot find suitable Lua interpreter])])
],
[ dnl Query Lua for its version number.
AC_CACHE_CHECK([for $ax_display_LUA version],
[ax_cv_lua_version],
[ dnl Get the interpreter version in X.Y format. This should work for
dnl interpreters version 5.0 and beyond.
ax_cv_lua_version=[`$LUA -e '
-- return a version number in X.Y format
local _, _, ver = string.find(_VERSION, "^Lua (%d+%.%d+)")
print(ver)'`]
])
AS_IF([test "x$ax_cv_lua_version" = 'x'],
[AC_MSG_ERROR([invalid Lua version number])])
AC_SUBST([LUA_VERSION], [$ax_cv_lua_version])
AC_SUBST([LUA_SHORT_VERSION], [`echo "$LUA_VERSION" | $SED 's|\.||'`])
dnl The following check is not supported:
dnl At times (like when building shared libraries) you may want to know
dnl which OS platform Lua thinks this is.
AC_CACHE_CHECK([for $ax_display_LUA platform],
[ax_cv_lua_platform],
[ax_cv_lua_platform=[`$LUA -e 'print("unknown")'`]])
AC_SUBST([LUA_PLATFORM], [$ax_cv_lua_platform])
dnl Use the values of $prefix and $exec_prefix for the corresponding
dnl values of LUA_PREFIX and LUA_EXEC_PREFIX. These are made distinct
dnl variables so they can be overridden if need be. However, the general
dnl consensus is that you shouldn't need this ability.
AC_SUBST([LUA_PREFIX], ['${prefix}'])
AC_SUBST([LUA_EXEC_PREFIX], ['${exec_prefix}'])
dnl Lua provides no way to query the script directory, and instead
dnl provides LUA_PATH. However, we should be able to make a safe educated
dnl guess. If the built-in search path contains a directory which is
dnl prefixed by $prefix, then we can store scripts there. The first
dnl matching path will be used.
AC_CACHE_CHECK([for $ax_display_LUA script directory],
[ax_cv_lua_luadir],
[ AS_IF([test "x$prefix" = 'xNONE'],
[ax_lua_prefix=$ac_default_prefix],
[ax_lua_prefix=$prefix])
dnl Initialize to the default path.
ax_cv_lua_luadir="$LUA_PREFIX/share/lua/$LUA_VERSION"
dnl Try to find a path with the prefix.
_AX_LUA_FND_PRFX_PTH([$LUA], [$ax_lua_prefix], [script])
AS_IF([test "x$ax_lua_prefixed_path" != 'x'],
[ dnl Fix the prefix.
_ax_strip_prefix=`echo "$ax_lua_prefix" | $SED 's|.|.|g'`
ax_cv_lua_luadir=`echo "$ax_lua_prefixed_path" | \
$SED "s|^$_ax_strip_prefix|$LUA_PREFIX|"`
])
])
AC_SUBST([luadir], [$ax_cv_lua_luadir])
AC_SUBST([pkgluadir], [\${luadir}/$PACKAGE])
dnl Lua provides no way to query the module directory, and instead
dnl provides LUA_PATH. However, we should be able to make a safe educated
dnl guess. If the built-in search path contains a directory which is
dnl prefixed by $exec_prefix, then we can store modules there. The first
dnl matching path will be used.
AC_CACHE_CHECK([for $ax_display_LUA module directory],
[ax_cv_lua_luaexecdir],
[ AS_IF([test "x$exec_prefix" = 'xNONE'],
[ax_lua_exec_prefix=$ax_lua_prefix],
[ax_lua_exec_prefix=$exec_prefix])
dnl Initialize to the default path.
ax_cv_lua_luaexecdir="$LUA_EXEC_PREFIX/lib/lua/$LUA_VERSION"
dnl Try to find a path with the prefix.
_AX_LUA_FND_PRFX_PTH([$LUA],
[$ax_lua_exec_prefix], [module])
AS_IF([test "x$ax_lua_prefixed_path" != 'x'],
[ dnl Fix the prefix.
_ax_strip_prefix=`echo "$ax_lua_exec_prefix" | $SED 's|.|.|g'`
ax_cv_lua_luaexecdir=`echo "$ax_lua_prefixed_path" | \
$SED "s|^$_ax_strip_prefix|$LUA_EXEC_PREFIX|"`
])
])
AC_SUBST([luaexecdir], [$ax_cv_lua_luaexecdir])
AC_SUBST([pkgluaexecdir], [\${luaexecdir}/$PACKAGE])
dnl Run any user specified action.
$3
])
])
dnl AX_WITH_LUA is now the same thing as AX_PROG_LUA.
AC_DEFUN([AX_WITH_LUA],
[
AC_MSG_WARN([[$0 is deprecated, please use AX_PROG_LUA instead]])
AX_PROG_LUA
])
dnl =========================================================================
dnl _AX_LUA_CHK_IS_INTRP(PROG, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
dnl =========================================================================
AC_DEFUN([_AX_LUA_CHK_IS_INTRP],
[
dnl A minimal Lua factorial to prove this is an interpreter. This should work
dnl for Lua interpreters version 5.0 and beyond.
_ax_lua_factorial=[`$1 2>/dev/null -e '
-- a simple factorial
function fact (n)
if n == 0 then
return 1
else
return n * fact(n-1)
end
end
print("fact(5) is " .. fact(5))'`]
AS_IF([test "$_ax_lua_factorial" = 'fact(5) is 120'],
[$2], [$3])
])
dnl =========================================================================
dnl _AX_LUA_CHK_VER(PROG, MINIMUM-VERSION, [TOO-BIG-VERSION],
dnl [ACTION-IF-TRUE], [ACTION-IF-FALSE])
dnl =========================================================================
AC_DEFUN([_AX_LUA_CHK_VER],
[
dnl Check that the Lua version is within the bounds. Only the major and minor
dnl version numbers are considered. This should work for Lua interpreters
dnl version 5.0 and beyond.
_ax_lua_good_version=[`$1 -e '
-- a script to compare versions
function verstr2num(verstr)
local _, _, majorver, minorver = string.find(verstr, "^(%d+)%.(%d+)")
if majorver and minorver then
return tonumber(majorver) * 100 + tonumber(minorver)
end
end
local minver = verstr2num("$2")
local _, _, trimver = string.find(_VERSION, "^Lua (.*)")
local ver = verstr2num(trimver)
local maxver = verstr2num("$3") or 1e9
if minver <= ver and ver < maxver then
print("yes")
else
print("no")
end'`]
AS_IF([test "x$_ax_lua_good_version" = "xyes"],
[$4], [$5])
])
dnl =========================================================================
dnl _AX_LUA_FND_PRFX_PTH(PROG, PREFIX, SCRIPT-OR-MODULE-DIR)
dnl =========================================================================
AC_DEFUN([_AX_LUA_FND_PRFX_PTH],
[
dnl Get the script or module directory by querying the Lua interpreter,
dnl filtering on the given prefix, and selecting the shallowest path. If no
dnl path is found matching the prefix, the result will be an empty string.
dnl The third argument determines the type of search, it can be 'script' or
dnl 'module'. Supplying 'script' will perform the search with package.path
dnl and LUA_PATH, and supplying 'module' will search with package.cpath and
dnl LUA_CPATH. This is done for compatibility with Lua 5.0.
ax_lua_prefixed_path=[`$1 -e '
-- get the path based on search type
local searchtype = "$3"
local paths = ""
if searchtype == "script" then
paths = (package and package.path) or LUA_PATH
elseif searchtype == "module" then
paths = (package and package.cpath) or LUA_CPATH
end
-- search for the prefix
local prefix = "'$2'"
local minpath = ""
local mindepth = 1e9
string.gsub(paths, "(@<:@^;@:>@+)",
function (path)
path = string.gsub(path, "%?.*$", "")
path = string.gsub(path, "/@<:@^/@:>@*$", "")
if string.find(path, prefix) then
local depth = string.len(string.gsub(path, "@<:@^/@:>@", ""))
if depth < mindepth then
minpath = path
mindepth = depth
end
end
end)
print(minpath)'`]
])
dnl =========================================================================
dnl AX_LUA_HEADERS([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
dnl =========================================================================
AC_DEFUN([AX_LUA_HEADERS],
[
dnl Check for LUA_VERSION.
AC_MSG_CHECKING([if LUA_VERSION is defined])
AS_IF([test "x$LUA_VERSION" != 'x'],
[AC_MSG_RESULT([yes])],
[ AC_MSG_RESULT([no])
AC_MSG_ERROR([cannot check Lua headers without knowing LUA_VERSION])
])
dnl Make LUA_INCLUDE a precious variable.
AC_ARG_VAR([LUA_INCLUDE], [The Lua includes, e.g. -I/usr/include/lua5.1])
dnl Some default directories to search.
LUA_SHORT_VERSION=`echo "$LUA_VERSION" | $SED 's|\.||'`
m4_define_default([_AX_LUA_INCLUDE_LIST],
[ /usr/include/lua$LUA_VERSION \
/usr/include/lua-$LUA_VERSION \
/usr/include/lua/$LUA_VERSION \
/usr/include/lua$LUA_SHORT_VERSION \
/usr/local/include/lua$LUA_VERSION \
/usr/local/include/lua-$LUA_VERSION \
/usr/local/include/lua/$LUA_VERSION \
/usr/local/include/lua$LUA_SHORT_VERSION \
])
dnl Try to find the headers.
_ax_lua_saved_cppflags=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $LUA_INCLUDE"
AC_CHECK_HEADERS([lua.h lualib.h lauxlib.h luaconf.h])
CPPFLAGS=$_ax_lua_saved_cppflags
dnl Try some other directories if LUA_INCLUDE was not set.
AS_IF([test "x$LUA_INCLUDE" = 'x' &&
test "x$ac_cv_header_lua_h" != 'xyes'],
[ dnl Try some common include paths.
for _ax_include_path in _AX_LUA_INCLUDE_LIST; do
test ! -d "$_ax_include_path" && continue
AC_MSG_CHECKING([for Lua headers in])
AC_MSG_RESULT([$_ax_include_path])
AS_UNSET([ac_cv_header_lua_h])
AS_UNSET([ac_cv_header_lualib_h])
AS_UNSET([ac_cv_header_lauxlib_h])
AS_UNSET([ac_cv_header_luaconf_h])
_ax_lua_saved_cppflags=$CPPFLAGS
CPPFLAGS="$CPPFLAGS -I$_ax_include_path"
AC_CHECK_HEADERS([lua.h lualib.h lauxlib.h luaconf.h])
CPPFLAGS=$_ax_lua_saved_cppflags
AS_IF([test "x$ac_cv_header_lua_h" = 'xyes'],
[ LUA_INCLUDE="-I$_ax_include_path"
break
])
done
])
AS_IF([test "x$ac_cv_header_lua_h" = 'xyes'],
[ dnl Make a program to print LUA_VERSION defined in the header.
dnl TODO It would be really nice if we could do this without compiling a
dnl program, then it would work when cross compiling. But I'm not sure how
dnl to do this reliably. For now, assume versions match when cross compiling.
AS_IF([test "x$cross_compiling" != 'xyes'],
[ AC_CACHE_CHECK([for Lua header version],
[ax_cv_lua_header_version],
[ _ax_lua_saved_cppflags=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $LUA_INCLUDE"
AC_COMPUTE_INT(ax_cv_lua_header_version_major,[LUA_VERSION_NUM/100],[AC_INCLUDES_DEFAULT
#include <lua.h>
],[ax_cv_lua_header_version_major=unknown])
AC_COMPUTE_INT(ax_cv_lua_header_version_minor,[LUA_VERSION_NUM%100],[AC_INCLUDES_DEFAULT
#include <lua.h>
],[ax_cv_lua_header_version_minor=unknown])
AS_IF([test "x$ax_cv_lua_header_version_major" = xunknown || test "x$ax_cv_lua_header_version_minor" = xunknown],[
ax_cv_lua_header_version=unknown
],[
ax_cv_lua_header_version="$ax_cv_lua_header_version_major.$ax_cv_lua_header_version_minor"
])
CPPFLAGS=$_ax_lua_saved_cppflags
])
dnl Compare this to the previously found LUA_VERSION.
AC_MSG_CHECKING([if Lua header version matches $LUA_VERSION])
AS_IF([test "x$ax_cv_lua_header_version" = "x$LUA_VERSION"],
[ AC_MSG_RESULT([yes])
ax_header_version_match='yes'
],
[ AC_MSG_RESULT([no])
ax_header_version_match='no'
])
],
[ AC_MSG_WARN([cross compiling so assuming header version number matches])
ax_header_version_match='yes'
])
])
dnl Was LUA_INCLUDE specified?
AS_IF([test "x$ax_header_version_match" != 'xyes' &&
test "x$LUA_INCLUDE" != 'x'],
[AC_MSG_ERROR([cannot find headers for specified LUA_INCLUDE])])
dnl Test the final result and run user code.
AS_IF([test "x$ax_header_version_match" = 'xyes'], [$1],
[m4_default([$2], [AC_MSG_ERROR([cannot find Lua includes])])])
])
dnl AX_LUA_HEADERS_VERSION no longer exists, use AX_LUA_HEADERS.
AC_DEFUN([AX_LUA_HEADERS_VERSION],
[
AC_MSG_WARN([[$0 is deprecated, please use AX_LUA_HEADERS instead]])
])
dnl =========================================================================
dnl AX_LUA_LIBS([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
dnl =========================================================================
AC_DEFUN([AX_LUA_LIBS],
[
dnl TODO Should this macro also check various -L flags?
dnl Check for LUA_VERSION.
AC_MSG_CHECKING([if LUA_VERSION is defined])
AS_IF([test "x$LUA_VERSION" != 'x'],
[AC_MSG_RESULT([yes])],
[ AC_MSG_RESULT([no])
AC_MSG_ERROR([cannot check Lua libs without knowing LUA_VERSION])
])
dnl Make LUA_LIB a precious variable.
AC_ARG_VAR([LUA_LIB], [The Lua library, e.g. -llua5.1])
AS_IF([test "x$LUA_LIB" != 'x'],
[ dnl Check that LUA_LIBS works.
_ax_lua_saved_libs=$LIBS
LIBS="$LIBS $LUA_LIB"
AC_SEARCH_LIBS([lua_load], [],
[_ax_found_lua_libs='yes'],
[_ax_found_lua_libs='no'])
LIBS=$_ax_lua_saved_libs
dnl Check the result.
AS_IF([test "x$_ax_found_lua_libs" != 'xyes'],
[AC_MSG_ERROR([cannot find libs for specified LUA_LIB])])
],
[ dnl First search for extra libs.
_ax_lua_extra_libs=''
_ax_lua_saved_libs=$LIBS
LIBS="$LIBS $LUA_LIB"
AC_SEARCH_LIBS([exp], [m])
AC_SEARCH_LIBS([dlopen], [dl])
LIBS=$_ax_lua_saved_libs
AS_IF([test "x$ac_cv_search_exp" != 'xno' &&
test "x$ac_cv_search_exp" != 'xnone required'],
[_ax_lua_extra_libs="$_ax_lua_extra_libs $ac_cv_search_exp"])
AS_IF([test "x$ac_cv_search_dlopen" != 'xno' &&
test "x$ac_cv_search_dlopen" != 'xnone required'],
[_ax_lua_extra_libs="$_ax_lua_extra_libs $ac_cv_search_dlopen"])
dnl Try to find the Lua libs.
_ax_lua_saved_libs=$LIBS
LIBS="$LIBS $LUA_LIB"
AC_SEARCH_LIBS([lua_load],
[ lua$LUA_VERSION \
lua$LUA_SHORT_VERSION \
lua-$LUA_VERSION \
lua-$LUA_SHORT_VERSION \
:liblua-$LUA_VERSION.so.0 \
:liblua-$LUA_SHORT_VERSION.so.0 \
lua \
],
[_ax_found_lua_libs='yes'],
[_ax_found_lua_libs='no'],
[$_ax_lua_extra_libs])
LIBS=$_ax_lua_saved_libs
AS_IF([test "x$ac_cv_search_lua_load" != 'xno' &&
test "x$ac_cv_search_lua_load" != 'xnone required'],
[LUA_LIB="$ac_cv_search_lua_load $_ax_lua_extra_libs"])
])
dnl Test the result and run user code.
AS_IF([test "x$_ax_found_lua_libs" = 'xyes'], [$1],
[m4_default([$2], [AC_MSG_ERROR([cannot find Lua libs])])])
])
dnl =========================================================================
dnl AX_LUA_READLINE([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
dnl =========================================================================
AC_DEFUN([AX_LUA_READLINE],
[
AX_LIB_READLINE
AS_IF([test "x$ac_cv_header_readline_readline_h" != 'x' &&
test "x$ac_cv_header_readline_history_h" != 'x'],
[ LUA_LIBS_CFLAGS="-DLUA_USE_READLINE $LUA_LIBS_CFLAGS"
$1
],
[$2])
])
+20 -1
View File
@@ -400,7 +400,7 @@ AC_DEFUN([TORRENT_WITH_XMLRPC_C], [
else
xmlrpc_cc_prg="$withval"
fi
if eval $xmlrpc_cc_prg --version 2>/dev/null >/dev/null; then
CXXFLAGS="$CXXFLAGS `$xmlrpc_cc_prg --cflags server-util`"
LIBS="$LIBS `$xmlrpc_cc_prg server-util --libs`"
@@ -439,6 +439,25 @@ AC_DEFUN([TORRENT_WITH_TINYXML2], [
])
])
AC_DEFUN([TORRENT_WITH_LUA], [
AC_ARG_WITH(lua,
AS_HELP_STRING([--with-lua],[enable LUA support]),
[
if test "$withval" = "no"; then
AC_MSG_RESULT(no)
else
AX_PROG_LUA
AX_LUA_LIBS
AX_LUA_HEADERS
AC_DEFINE(HAVE_LUA, 1, Use LUA.)
LIBS="$LIBS $LUA_LIB"
CXXFLAGS="$CXXFLAGS $LUA_INCLUDE"
fi
],[
AC_MSG_RESULT(ignored)
])
])
AC_DEFUN([TORRENT_WITH_INOTIFY], [
AC_LANG_PUSH(C++)
+14 -1
View File
@@ -13,7 +13,7 @@ AC_DEFUN([TORRENT_WITH_SYSROOT], [
AC_MSG_ERROR(The sysroot option must point to a directory, like f.ex "/Developer/SDKs/MacOSX10.4u.sdk".)
else
AC_MSG_RESULT($withval)
CXXFLAGS="$CXXFLAGS -isysroot $withval"
LDFLAGS="$LDFLAGS -Wl,-syslibroot,$withval"
fi
@@ -21,6 +21,19 @@ AC_DEFUN([TORRENT_WITH_SYSROOT], [
])
AC_DEFUN([TORRENT_REMOVE_UNWANTED],
[
values_to_check=`for i in $2; do echo $i; done`
unwanted_values=`for i in $3; do echo $i; done`
if test -z "${unwanted_values}"; then
$1="$2"
else
result=`echo "${values_to_check}" | $GREP -Fvx -- "${unwanted_values}" | $GREP -v '^$'`
$1=${result//$'\n'/ }
fi
])
AC_DEFUN([TORRENT_ENABLE_ARCH], [
AC_ARG_ENABLE(arch,
AS_HELP_STRING([--enable-arch=ARCH],
+11
View File
@@ -37,6 +37,7 @@ libsub_root_a_SOURCES = \
display/attributes.h \
display/canvas.cc \
display/canvas.h \
display/color_map.h \
display/frame.cc \
display/frame.h \
display/manager.cc \
@@ -107,6 +108,12 @@ libsub_root_a_SOURCES = \
rpc/exec_file.h \
rpc/fixed_key.h \
rpc/ip_table_list.h \
rpc/lua.h \
rpc/lua.cc \
rpc/jsonrpc.cc \
rpc/jsonrpc.h \
rpc/rpc_manager.cc \
rpc/rpc_manager.h \
rpc/object_storage.cc \
rpc/object_storage.h \
rpc/parse.cc \
@@ -125,6 +132,7 @@ libsub_root_a_SOURCES = \
rpc/xmlrpc_tinyxml2.cc \
rpc/tinyxml2/tinyxml2.h \
rpc/tinyxml2/tinyxml2.cc \
rpc/nlohmann/json.h \
\
ui/download.cc \
ui/download.h \
@@ -155,10 +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 \
+26 -64
View File
@@ -1,44 +1,9 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <functional>
#include <unistd.h>
#include <cstdio>
#include <functional>
#include <netdb.h>
#include <unistd.h>
#include <rak/file_stat.h>
#include <rak/error_number.h>
#include <rak/path.h>
@@ -47,14 +12,16 @@
#include <rak/regex.h>
#include <torrent/rate.h>
#include <torrent/throttle.h>
#include <torrent/tracker.h>
#include <torrent/tracker_controller.h>
#include <torrent/tracker_list.h>
#include <torrent/tracker/tracker.h>
#include <torrent/connection_manager.h>
#include <torrent/data/download_data.h>
#include <torrent/data/file.h>
#include <torrent/data/file_list.h>
#include <torrent/download/resource_manager.h>
#include <torrent/net/resolver.h>
#include <torrent/net/types.h>
#include <torrent/peer/connection_list.h>
#include <torrent/peer/peer_list.h>
#include <torrent/utils/log.h>
@@ -104,7 +71,7 @@ apply_d_change_link(core::Download* download, const torrent::Object::list_type&
const std::string& type = (itr++)->as_string();
const std::string& prefix = (itr++)->as_string();
const std::string& postfix = (itr++)->as_string();
if (type.empty())
throw torrent::input_error("Invalid arguments.");
@@ -319,21 +286,6 @@ retrieve_d_bitfield(core::Download* download) {
return torrent::Object(rak::transform_hex(bitField->begin(), bitField->end()));
}
struct call_add_d_peer_t {
call_add_d_peer_t(core::Download* d, int port) : m_download(d), m_port(port) { }
void operator() (const sockaddr* sa, int err) {
if (sa == NULL) {
lt_log_print(torrent::LOG_TORRENT_WARN, "could not resolve hostname for added peer");
} else {
m_download->download()->add_peer(sa, m_port);
}
}
core::Download* m_download;
int m_port;
};
void
apply_d_add_peer(core::Download* download, const std::string& arg) {
int port, ret;
@@ -356,7 +308,15 @@ apply_d_add_peer(core::Download* download, const std::string& arg) {
if (port < 1 || port > 65535)
throw torrent::input_error("Invalid port number.");
torrent::connection_manager()->resolver()(host, (int)rak::socket_address::pf_unspec, SOCK_STREAM, call_add_d_peer_t(download, port));
// Currently discarding SOCK_STREAM.
torrent::main_thread()->resolver()->resolve_preferred(NULL, host, AF_UNSPEC, AF_INET, [download, port](torrent::c_sa_shared_ptr sa, int err) {
if (sa == nullptr) {
lt_log_print(torrent::LOG_TORRENT_WARN, "could not resolve hostname for added peer: %s", gai_strerror(err));
return;
}
download->download()->add_peer(sa.get(), port);
});
}
torrent::Object
@@ -410,7 +370,7 @@ f_multicall(core::Download* download, const torrent::Object::list_type& args) {
for (torrent::Object::list_const_iterator cItr = ++args.begin(); cItr != args.end(); cItr++) {
const std::string& cmd = cItr->as_string();
row.push_back(rpc::parse_command(rpc::make_target(*itr), cmd.c_str(), cmd.c_str() + cmd.size()).first);
row.push_back(rpc::parse_command(rpc::make_target(itr->get()), cmd.c_str(), cmd.c_str() + cmd.size()).first);
}
}
@@ -435,9 +395,9 @@ t_multicall(core::Download* download, const torrent::Object::list_type& args) {
for (torrent::Object::list_const_iterator cItr = ++args.begin(); cItr != args.end(); cItr++) {
const std::string& cmd = cItr->as_string();
torrent::Tracker* t = download->tracker_list()->at(itr);
auto t = download->tracker_list()->at(itr);
row.push_back(rpc::parse_command(rpc::make_target(t), cmd.c_str(), cmd.c_str() + cmd.size()).first);
row.push_back(rpc::parse_command(rpc::make_target(&t), cmd.c_str(), cmd.c_str() + cmd.size()).first);
}
}
@@ -627,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)
@@ -871,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));
@@ -880,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));
+2 -2
View File
@@ -187,7 +187,7 @@ system_method_insert_object(const torrent::Object::list_type& args, int flags) {
if (!(flags & rpc::object_storage::flag_static))
cmd_flags |= rpc::CommandMap::flag_modifiable;
if (!(flags & rpc::object_storage::flag_private))
cmd_flags |= rpc::CommandMap::flag_public_xmlrpc;
cmd_flags |= rpc::CommandMap::flag_public_rpc;
if ((flags & rpc::object_storage::mask_type) == rpc::object_storage::flag_list_type) {
torrent::Object valueList = torrent::Object::create_list();
@@ -360,7 +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(new_key, dest_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_modifiable);
rpc::commands.create_redirect(new_key, dest_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_modifiable);
return torrent::Object();
}
+18 -54
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <functional>
@@ -66,14 +30,14 @@ apply_on_ratio(const torrent::Object& rawArgs) {
const std::string& groupName = rawArgs.as_string();
char buffer[32 + groupName.size()];
sprintf(buffer, "group2.%s.view", groupName.c_str());
snprintf(buffer, sizeof(buffer), "group2.%s.view", groupName.c_str());
core::ViewManager::iterator viewItr = control->view_manager()->find(rpc::commands.call(buffer, rpc::make_target()).as_string());
if (viewItr == control->view_manager()->end())
throw torrent::input_error("Could not find view.");
char* bufferStart = buffer + sprintf(buffer, "group2.%s.ratio.", groupName.c_str());
char* bufferStart = buffer + snprintf(buffer, sizeof(buffer), "group2.%s.ratio.", groupName.c_str());
// first argument: minimum ratio to reach
// second argument: minimum upload amount to reach [optional]
@@ -103,7 +67,7 @@ apply_on_ratio(const torrent::Object& rawArgs) {
downloads.push_back(*itr);
}
sprintf(buffer, "group.%s.ratio.command", groupName.c_str());
snprintf(buffer, sizeof(buffer), "group.%s.ratio.command", groupName.c_str());
for (std::vector<core::Download*>::iterator itr = downloads.begin(), last = downloads.end(); itr != last; itr++) {
// rpc::commands.call("print", rpc::make_target(*itr), "Calling ratio command.");
@@ -216,28 +180,27 @@ void apply_import(const std::string& path) { if (!rpc::parse_command_file(pa
void apply_try_import(const std::string& path) { if (!rpc::parse_command_file(path)) control->core()->push_log_std("Could not read resource file: " + path); }
torrent::Object
apply_close_low_diskspace(int64_t arg) {
core::DownloadList* downloadList = control->core()->download_list();
apply_close_low_diskspace(int64_t arg, uint32_t skip_priority) {
bool closed = false;
core::Manager::DListItr itr = downloadList->begin();
while ((itr = std::find_if(itr, downloadList->end(), std::mem_fun(&core::Download::is_downloading)))
!= downloadList->end()) {
if ((*itr)->file_list()->free_diskspace() < (uint64_t)arg) {
downloadList->close(*itr);
for (auto download : *control->core()->download_list()) {
if (!download->is_downloading())
continue;
if (download->priority() >= skip_priority)
continue;
if (download->file_list()->free_diskspace() >= (uint64_t)arg)
continue;
(*itr)->set_hash_failed(true);
(*itr)->set_message(std::string("Low diskspace."));
control->core()->download_list()->close(download);
closed = true;
}
download->set_hash_failed(true);
download->set_message(std::string("Low diskspace."));
++itr;
closed = true;
}
if (closed)
lt_log_print(torrent::LOG_TORRENT_ERROR, "Closed torrents due to low diskspace.");
lt_log_print(torrent::LOG_TORRENT_ERROR, "Closed torrents due to low diskspace.");
return torrent::Object();
}
@@ -391,7 +354,8 @@ initialize_command_events() {
core::Manager::create_quiet | core::Manager::create_start | core::Manager::create_raw_data));
CMD2_ANY_LIST ("load.raw_start_verbose", std::bind(&apply_load, std::placeholders::_2, core::Manager::create_start | core::Manager::create_raw_data));
CMD2_ANY_VALUE ("close_low_diskspace", std::bind(&apply_close_low_diskspace, std::placeholders::_2));
CMD2_ANY_VALUE ("close_low_diskspace", std::bind(&apply_close_low_diskspace, std::placeholders::_2, 99));
CMD2_ANY_VALUE ("close_low_diskspace.normal", std::bind(&apply_close_low_diskspace, std::placeholders::_2, 3));
CMD2_ANY_LIST ("download_list", std::bind(&apply_download_list, std::placeholders::_2));
CMD2_ANY_LIST ("d.multicall2", std::bind(&d_multicall, std::placeholders::_2));
+9 -45
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_UTILS_COMMAND_HELPERS_H
#define RTORRENT_UTILS_COMMAND_HELPERS_H
@@ -49,7 +13,7 @@ void initialize_commands();
#define CMD2_A_FUNCTION(key, function, slot, parm, doc) \
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::function>::type>(key, slot, &rpc::function, \
rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_xmlrpc, NULL, NULL);
rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_rpc, NULL, NULL);
#define CMD2_A_FUNCTION_PRIVATE(key, function, slot, parm, doc) \
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::function>::type>(key, slot, &rpc::function, \
@@ -92,9 +56,9 @@ void initialize_commands();
#define CMD2_PEER_V(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::Peer*>, object_convert_void(slot), "i:", "")
#define CMD2_PEER_VALUE_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_value<torrent::Peer*>, object_convert_void(slot), "i:i", "")
#define CMD2_TRACKER(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::Tracker*>, slot, "i:", "")
#define CMD2_TRACKER_V(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::Tracker*>, object_convert_void(slot), "i:", "")
#define CMD2_TRACKER_VALUE_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_value<torrent::Tracker*>, object_convert_void(slot), "i:i", "")
#define CMD2_TRACKER(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::tracker::Tracker*>, slot, "i:", "")
#define CMD2_TRACKER_V(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::tracker::Tracker*>, object_convert_void(slot), "i:", "")
#define CMD2_TRACKER_VALUE_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_value<torrent::tracker::Tracker*>, object_convert_void(slot), "i:i", "")
#define CMD2_VAR_BOOL(key, value) \
control->object_storage()->insert_c_str(key, int64_t(value), rpc::object_storage::flag_bool_type); \
@@ -137,19 +101,19 @@ void initialize_commands();
std::placeholders::_1, std::placeholders::_2));
#define CMD2_REDIRECT(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_dont_delete);
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_dont_delete);
#define CMD2_REDIRECT_GENERIC(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_dont_delete);
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_dont_delete);
#define CMD2_REDIRECT_GENERIC_NO_EXPORT(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_dont_delete);
#define CMD2_REDIRECT_FILE(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_file_target | rpc::CommandMap::flag_dont_delete);
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_file_target | rpc::CommandMap::flag_dont_delete);
#define CMD2_REDIRECT_TRACKER(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_tracker_target | rpc::CommandMap::flag_dont_delete);
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_tracker_target | rpc::CommandMap::flag_dont_delete);
#define CMD2_REDIRECT_GENERIC_STR(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, \
rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_no_target);
rpc::CommandMap::flag_public_rpc | rpc::CommandMap::flag_no_target);
#define CMD2_REDIRECT_GENERIC_STR_NO_EXPORT(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, \
+13 -36
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <fcntl.h>
@@ -60,6 +24,7 @@
#include "utils/file_status_cache.h"
#include "globals.h"
#include "rpc/lua.h"
#include "control.h"
#include "command_helpers.h"
@@ -241,6 +206,7 @@ initialize_command_local() {
CMD2_VAR_C_STRING("system.api_version", (int64_t)API_VERSION);
CMD2_VAR_C_STRING("system.client_version", PACKAGE_VERSION);
CMD2_VAR_C_STRING("system.library_version", torrent::version());
CMD2_VAR_VALUE ("system.file.allocate", 0);
CMD2_VAR_VALUE ("system.file.max_size", (int64_t)512 << 30);
CMD2_VAR_VALUE ("system.file.split_size", -1);
@@ -254,6 +220,10 @@ initialize_command_local() {
CMD2_VAR_LIST ("file.prioritize_toc.first");
CMD2_VAR_LIST ("file.prioritize_toc.last");
CMD2_ANY ("system.files.advise_random", std::bind(&FM_t::advise_random, fileManager));
CMD2_ANY_VALUE_V ("system.files.advise_random.set", std::bind(&FM_t::set_advise_random, fileManager, std::placeholders::_2));
CMD2_VAR_BOOL ("system.files.session.fdatasync", true);
CMD2_ANY ("system.files.opened_counter", std::bind(&FM_t::files_opened_counter, fileManager));
CMD2_ANY ("system.files.closed_counter", std::bind(&FM_t::files_closed_counter, fileManager));
CMD2_ANY ("system.files.failed_counter", std::bind(&FM_t::files_failed_counter, fileManager));
@@ -315,6 +285,13 @@ initialize_command_local() {
CMD2_ANY_V ("session.save", std::bind(&core::DownloadList::session_save, dList));
#ifdef HAVE_LUA
rpc::LuaEngine* lua_engine = control->lua_engine();
CMD2_ANY ("lua.execute", std::bind(&rpc::execute_lua, lua_engine, std::placeholders::_1, std::placeholders::_2, 0));
CMD2_ANY ("lua.execute.str", std::bind(&rpc::execute_lua, lua_engine, std::placeholders::_1, std::placeholders::_2, rpc::LuaEngine::flag_string));
#endif
#define CMD2_EXECUTE(key, flags) \
CMD2_ANY(key, std::bind(&rpc::ExecFile::execute_object, &rpc::execFile, std::placeholders::_2, flags));
+2 -1
View File
@@ -142,5 +142,6 @@ initialize_command_logging() {
CMD2_ANY_STRING ("log.execute", std::bind(&apply_log, std::placeholders::_2, 0));
CMD2_ANY_STRING ("log.vmmap.dump", std::bind(&log_vmmap_dump, std::placeholders::_2));
CMD2_ANY_STRING_V("log.xmlrpc", std::bind(&ThreadWorker::set_xmlrpc_log, worker_thread, std::placeholders::_2));
CMD2_ANY_STRING_V("log.rpc", std::bind(&ThreadWorker::set_rpc_log, worker_thread, std::placeholders::_2));
CMD2_REDIRECT ("log.xmlrpc", "log.rpc"); // For backwards compatibility
}
+38 -79
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <functional>
@@ -42,8 +6,8 @@
#include <rak/address_info.h>
#include <rak/path.h>
#include <torrent/connection_manager.h>
#include <torrent/tracker.h>
#include <torrent/tracker_list.h>
#include <torrent/tracker/tracker.h>
#include <torrent/torrent.h>
#include <torrent/rate.h>
#include <torrent/data/file_manager.h>
@@ -94,51 +58,44 @@ apply_tos(const torrent::Object::string_type& arg) {
torrent::Object apply_encoding_list(const std::string& arg) { torrent::encoding_list()->push_back(arg); return torrent::Object(); }
torrent::File*
xmlrpc_find_file(core::Download* download, uint32_t index) {
if (index >= download->file_list()->size_files())
return NULL;
return (*download->file_list())[index];
}
// Ergh... time to update the Tracker API to allow proper ptrs.
torrent::Tracker*
xmlrpc_find_tracker(core::Download* download, uint32_t index) {
if (index >= download->tracker_list()->size())
return NULL;
return download->tracker_list()->at(index);
}
torrent::Peer*
xmlrpc_find_peer(core::Download* download, const torrent::HashString& hash) {
torrent::ConnectionList::iterator itr = download->connection_list()->find(hash.c_str());
if (itr == download->connection_list()->end())
return NULL;
return *itr;
}
void
initialize_xmlrpc() {
rpc::xmlrpc.initialize();
rpc::xmlrpc.slot_find_download() = std::bind(&core::DownloadList::find_hex_ptr, control->core()->download_list(), std::placeholders::_1);
rpc::xmlrpc.slot_find_file() = std::bind(&xmlrpc_find_file, std::placeholders::_1, std::placeholders::_2);
rpc::xmlrpc.slot_find_tracker() = std::bind(&xmlrpc_find_tracker, std::placeholders::_1, std::placeholders::_2);
rpc::xmlrpc.slot_find_peer() = std::bind(&xmlrpc_find_peer, std::placeholders::_1, std::placeholders::_2);
initialize_rpc() {
rpc::rpc.initialize();
rpc::rpc.slot_find_download() = [](const char* hash) {
return control->core()->download_list()->find_hex_ptr(hash);
};
rpc::rpc.slot_find_file() = [](core::Download* d, uint32_t index) -> torrent::File* {
if (index >= d->file_list()->size_files())
throw torrent::input_error("invalid parameters: index not found");
return (*d->file_list())[index].get();
};
rpc::rpc.slot_find_tracker() = [](core::Download* d, uint32_t index) -> torrent::tracker::Tracker {
if (index >= d->tracker_list()->size())
throw torrent::input_error("invalid parameters: index not found");
return d->tracker_list()->at(index);
};
rpc::rpc.slot_find_peer() = [](core::Download* d, const torrent::HashString& hash) -> torrent::Peer* {
auto itr = d->connection_list()->find(hash.c_str());
if (itr == d->connection_list()->end())
throw torrent::input_error("invalid parameters: hash not found");
return *itr;
};
unsigned int count = 0;
for (rpc::CommandMap::const_iterator itr = rpc::commands.begin(), last = rpc::commands.end(); itr != last; itr++, count++) {
if (!(itr->second.m_flags & rpc::CommandMap::flag_public_xmlrpc))
if (!(itr->second.m_flags & rpc::CommandMap::flag_public_rpc))
continue;
rpc::xmlrpc.insert_command(itr->first.c_str(), itr->second.m_parm, itr->second.m_doc);
rpc::rpc.insert_command(itr->first.c_str(), itr->second.m_parm, itr->second.m_doc);
}
lt_log_print(torrent::LOG_RPC_EVENTS, "XMLRPC initialized with %u functions.", count);
lt_log_print(torrent::LOG_RPC_EVENTS, "RPC initialized with %u functions.", count);
}
torrent::Object
@@ -146,8 +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, rpc::xmlrpc));
CMD2_ANY_VALUE_V ("network.xmlrpc.size_limit.set", std::bind(&rpc::XmlRpc::set_size_limit, rpc::xmlrpc, std::placeholders::_2));
CMD2_ANY_STRING ("network.xmlrpc.dialect.set", [](const auto&, const auto& arg) { return apply_xmlrpc_dialect(arg); })
CMD2_ANY ("network.xmlrpc.size_limit", [](const auto&, const auto&){ return rpc::rpc.size_limit(); });
CMD2_ANY_VALUE_V ("network.xmlrpc.size_limit.set", [](const auto&, const auto& arg){ return rpc::rpc.set_size_limit(arg); });
CMD2_VAR_BOOL ("network.rpc.use_xmlrpc", true);
CMD2_VAR_BOOL ("network.rpc.use_jsonrpc", true);
CMD2_ANY ("network.block.ipv4", std::bind(&torrent::ConnectionManager::is_block_ipv4, cm));
CMD2_ANY_VALUE_V ("network.block.ipv4.set", std::bind(&torrent::ConnectionManager::set_block_ipv4, cm, std::placeholders::_2));
+51 -90
View File
@@ -1,46 +1,12 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <cstdio>
#include <netdb.h>
#include <rak/address_info.h>
#include <rak/error_number.h>
#include <torrent/dht_manager.h>
#include <torrent/tracker.h>
#include <torrent/net/resolver.h>
#include <torrent/tracker/dht_controller.h>
#include <torrent/tracker/tracker.h>
#include <torrent/utils/log.h>
#include "core/download.h"
@@ -52,30 +18,16 @@
#include "core/dht_manager.h"
void
tracker_set_enabled(torrent::Tracker* tracker, bool state) {
tracker_set_enabled(torrent::tracker::Tracker* tracker, bool state) {
if (state)
tracker->enable();
else
tracker->disable();
}
struct call_add_node_t {
call_add_node_t(int port) : m_port(port) { }
void operator() (const sockaddr* sa, int err) {
if (sa == NULL) {
lt_log_print(torrent::LOG_DHT_WARN, "Could not resolve host.");
} else {
torrent::dht_manager()->add_node(sa, m_port);
}
}
int m_port;
};
torrent::Object
apply_dht_add_node(const std::string& arg) {
if (!torrent::dht_manager()->is_valid())
if (!torrent::dht_controller()->is_valid())
throw torrent::input_error("DHT not enabled.");
int port, ret;
@@ -92,68 +44,77 @@ apply_dht_add_node(const std::string& arg) {
if (port < 1 || port > 65535)
throw torrent::input_error("Invalid port number.");
torrent::connection_manager()->resolver()(host, (int)rak::socket_address::pf_inet, SOCK_DGRAM, call_add_node_t(port));
// Currently discarding SOCK_STREAM.
torrent::main_thread()->resolver()->resolve_specific(nullptr, host, PF_INET, [port](torrent::c_sa_shared_ptr sa, int err) {
if (sa == nullptr) {
lt_log_print(torrent::LOG_DHT_WARN, "Could not resolve host: %s", gai_strerror(err));
return;
}
torrent::dht_controller()->add_node(sa.get(), port);
});
return torrent::Object();
}
torrent::Object
apply_enable_trackers(int64_t arg) {
for (core::Manager::DListItr itr = control->core()->download_list()->begin(), last = control->core()->download_list()->end(); itr != last; ++itr) {
std::for_each((*itr)->tracker_list()->begin(), (*itr)->tracker_list()->end(),
arg ? std::mem_fun(&torrent::Tracker::enable) : std::mem_fun(&torrent::Tracker::disable));
std::for_each((*itr)->tracker_list()->begin(), (*itr)->tracker_list()->end(), std::mem_fn(arg ? &torrent::tracker::Tracker::enable : &torrent::tracker::Tracker::disable));
if (arg && !rpc::call_command_value("trackers.use_udp"))
(*itr)->enable_udp_trackers(false);
}
}
return torrent::Object();
}
void
initialize_command_tracker() {
CMD2_TRACKER ("t.is_open", std::bind(&torrent::Tracker::is_busy, std::placeholders::_1));
CMD2_TRACKER ("t.is_enabled", std::bind(&torrent::Tracker::is_enabled, std::placeholders::_1));
CMD2_TRACKER ("t.is_usable", std::bind(&torrent::Tracker::is_usable, std::placeholders::_1));
CMD2_TRACKER ("t.is_busy", std::bind(&torrent::Tracker::is_busy, std::placeholders::_1));
CMD2_TRACKER ("t.is_extra_tracker", std::bind(&torrent::Tracker::is_extra_tracker, std::placeholders::_1));
CMD2_TRACKER ("t.can_scrape", std::bind(&torrent::Tracker::can_scrape, std::placeholders::_1));
CMD2_TRACKER ("t.is_busy", std::bind(&torrent::tracker::Tracker::is_busy, std::placeholders::_1));
CMD2_TRACKER ("t.is_enabled", std::bind(&torrent::tracker::Tracker::is_enabled, std::placeholders::_1));
CMD2_TRACKER ("t.is_extra_tracker", std::bind(&torrent::tracker::Tracker::is_extra_tracker, std::placeholders::_1));
CMD2_TRACKER ("t.is_open", std::bind(&torrent::tracker::Tracker::is_busy, std::placeholders::_1));
CMD2_TRACKER ("t.is_scrapable", std::bind(&torrent::tracker::Tracker::is_scrapable, std::placeholders::_1));
CMD2_TRACKER ("t.is_usable", std::bind(&torrent::tracker::Tracker::is_usable, std::placeholders::_1));
CMD2_TRACKER_V ("t.enable", std::bind(&torrent::Tracker::enable, std::placeholders::_1));
CMD2_TRACKER_V ("t.disable", std::bind(&torrent::Tracker::disable, std::placeholders::_1));
// TODO: Deprecate.
CMD2_TRACKER ("t.can_scrape", std::bind(&torrent::tracker::Tracker::is_scrapable, std::placeholders::_1));
CMD2_TRACKER_V ("t.enable", std::bind(&torrent::tracker::Tracker::enable, std::placeholders::_1));
CMD2_TRACKER_V ("t.disable", std::bind(&torrent::tracker::Tracker::disable, std::placeholders::_1));
CMD2_TRACKER_VALUE_V("t.is_enabled.set", std::bind(&tracker_set_enabled, std::placeholders::_1, std::placeholders::_2));
CMD2_TRACKER ("t.url", std::bind(&torrent::Tracker::url, std::placeholders::_1));
CMD2_TRACKER ("t.group", std::bind(&torrent::Tracker::group, std::placeholders::_1));
CMD2_TRACKER ("t.type", std::bind(&torrent::Tracker::type, std::placeholders::_1));
CMD2_TRACKER ("t.id", std::bind(&torrent::Tracker::tracker_id, std::placeholders::_1));
CMD2_TRACKER ("t.url", std::bind(&torrent::tracker::Tracker::url, std::placeholders::_1));
CMD2_TRACKER ("t.group", std::bind(&torrent::tracker::Tracker::group, std::placeholders::_1));
CMD2_TRACKER ("t.type", std::bind(&torrent::tracker::Tracker::type, std::placeholders::_1));
CMD2_TRACKER ("t.id", std::bind(&torrent::tracker::Tracker::tracker_id, std::placeholders::_1));
CMD2_TRACKER ("t.latest_event", std::bind(&torrent::Tracker::latest_event, std::placeholders::_1));
CMD2_TRACKER ("t.latest_new_peers", std::bind(&torrent::Tracker::latest_new_peers, std::placeholders::_1));
CMD2_TRACKER ("t.latest_sum_peers", std::bind(&torrent::Tracker::latest_sum_peers, std::placeholders::_1));
CMD2_TRACKER ("t.latest_event", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().latest_event(); });
CMD2_TRACKER ("t.latest_new_peers", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().latest_new_peers(); });
CMD2_TRACKER ("t.latest_sum_peers", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().latest_sum_peers(); });
// Time since last connection, connection attempt.
CMD2_TRACKER ("t.normal_interval", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().normal_interval(); });
CMD2_TRACKER ("t.min_interval", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().min_interval(); });
CMD2_TRACKER ("t.normal_interval", std::bind(&torrent::Tracker::normal_interval, std::placeholders::_1));
CMD2_TRACKER ("t.min_interval", std::bind(&torrent::Tracker::min_interval, std::placeholders::_1));
CMD2_TRACKER ("t.activity_time_next", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().activity_time_next(); });
CMD2_TRACKER ("t.activity_time_last", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().activity_time_last(); });
CMD2_TRACKER ("t.activity_time_next", std::bind(&torrent::Tracker::activity_time_next, std::placeholders::_1));
CMD2_TRACKER ("t.activity_time_last", std::bind(&torrent::Tracker::activity_time_last, std::placeholders::_1));
CMD2_TRACKER ("t.success_time_next", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().success_time_next(); });
CMD2_TRACKER ("t.success_time_last", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().success_time_last(); });
CMD2_TRACKER ("t.success_counter", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().success_counter(); });
CMD2_TRACKER ("t.success_time_next", std::bind(&torrent::Tracker::success_time_next, std::placeholders::_1));
CMD2_TRACKER ("t.success_time_last", std::bind(&torrent::Tracker::success_time_last, std::placeholders::_1));
CMD2_TRACKER ("t.success_counter", std::bind(&torrent::Tracker::success_counter, std::placeholders::_1));
CMD2_TRACKER ("t.failed_time_next", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().failed_time_next(); });
CMD2_TRACKER ("t.failed_time_last", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().failed_time_last(); });
CMD2_TRACKER ("t.failed_counter", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().failed_counter(); });
CMD2_TRACKER ("t.failed_time_next", std::bind(&torrent::Tracker::failed_time_next, std::placeholders::_1));
CMD2_TRACKER ("t.failed_time_last", std::bind(&torrent::Tracker::failed_time_last, std::placeholders::_1));
CMD2_TRACKER ("t.failed_counter", std::bind(&torrent::Tracker::failed_counter, std::placeholders::_1));
CMD2_TRACKER ("t.scrape_time_last", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().scrape_time_last(); });
CMD2_TRACKER ("t.scrape_counter", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().scrape_counter(); });
CMD2_TRACKER ("t.scrape_time_last", std::bind(&torrent::Tracker::scrape_time_last, std::placeholders::_1));
CMD2_TRACKER ("t.scrape_counter", std::bind(&torrent::Tracker::scrape_counter, std::placeholders::_1));
CMD2_TRACKER ("t.scrape_complete", std::bind(&torrent::Tracker::scrape_complete, std::placeholders::_1));
CMD2_TRACKER ("t.scrape_incomplete", std::bind(&torrent::Tracker::scrape_incomplete, std::placeholders::_1));
CMD2_TRACKER ("t.scrape_downloaded", std::bind(&torrent::Tracker::scrape_downloaded, std::placeholders::_1));
CMD2_TRACKER ("t.scrape_complete", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().scrape_complete(); });
CMD2_TRACKER ("t.scrape_incomplete", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().scrape_incomplete(); });
CMD2_TRACKER ("t.scrape_downloaded", [](torrent::tracker::Tracker* tracker, [[maybe_unused]] auto o) -> auto { return tracker->state().scrape_downloaded(); });
CMD2_ANY_VALUE ("trackers.enable", std::bind(&apply_enable_trackers, int64_t(1)));
CMD2_ANY_VALUE ("trackers.disable", std::bind(&apply_enable_trackers, int64_t(0)));
+36 -51
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <sys/types.h>
@@ -42,13 +6,14 @@
#include <regex>
#include <rak/algorithm.h>
#include <rak/functional.h>
#include <torrent/utils/log.h>
#include "core/manager.h"
#include "core/view_manager.h"
#include "display/canvas.h"
#include "ui/root.h"
#include "ui/download_list.h"
#include "display/color_map.h"
#include "rpc/parse.h"
#include "globals.h"
@@ -63,7 +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.");
@@ -134,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);
@@ -143,7 +108,7 @@ apply_print(rpc::target_type target, const torrent::Object& rawArgs) {
}
torrent::Object
apply_cat(rpc::target_type target, const torrent::Object& rawArgs) {
apply_cat([[maybe_unused]] rpc::target_type target, const torrent::Object& rawArgs) {
std::string result;
rpc::print_object_std(&result, &rawArgs, 0);
@@ -151,7 +116,7 @@ apply_cat(rpc::target_type target, const torrent::Object& rawArgs) {
}
torrent::Object
apply_value(rpc::target_type target, const torrent::Object::list_type& args) {
apply_value([[maybe_unused]] rpc::target_type target, const torrent::Object::list_type& args) {
if (args.size() < 1)
throw torrent::input_error("'value' takes at least a number argument!");
if (args.size() > 2)
@@ -219,7 +184,7 @@ apply_not(rpc::target_type target, const torrent::Object& rawArgs) {
}
torrent::Object
apply_false(rpc::target_type target, const torrent::Object& rawArgs) {
apply_false([[maybe_unused]] rpc::target_type target, [[maybe_unused]] const torrent::Object& rawArgs) {
return (int64_t)0;
}
@@ -234,10 +199,10 @@ apply_and(rpc::target_type target, const torrent::Object& rawArgs) {
return (int64_t)false;
} else if (itr->is_value()) {
if (!itr->as_value())
if (!itr->as_value())
return (int64_t)false;
} else {
} else {
// TODO: Switch to new versions that only accept the new command syntax.
if (!as_boolean(rpc::parse_command_single(target, itr->as_string())))
return (int64_t)false;
@@ -257,10 +222,10 @@ apply_or(rpc::target_type target, const torrent::Object& rawArgs) {
return (int64_t)true;
} else if (itr->is_value()) {
if (itr->as_value())
if (itr->as_value())
return (int64_t)true;
} else {
} else {
if (as_boolean(rpc::parse_command_single(target, itr->as_string())))
return (int64_t)true;
}
@@ -297,7 +262,7 @@ apply_cmp(rpc::target_type target, const torrent::Object::list_type& args) {
if (result1.type() != result2.type())
throw torrent::input_error("Type mismatch.");
switch (result1.type()) {
case torrent::Object::TYPE_VALUE: return result1.as_value() - result2.as_value();
case torrent::Object::TYPE_STRING: return result1.as_string().compare(result2.as_string());
@@ -426,7 +391,7 @@ apply_to_time(const torrent::Object& rawArgs, int flags) {
u = std::localtime(&t);
else
u = std::gmtime(&t);
if (u == NULL)
return torrent::Object();
@@ -469,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));
@@ -485,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)
@@ -583,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.");
@@ -796,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");
@@ -843,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));
@@ -893,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]);
});
}
}
+11 -40
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#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),
@@ -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);
+3
View File
@@ -67,6 +67,7 @@ namespace rpc {
class CommandScheduler;
class XmlRpc;
class object_storage;
class LuaEngine;
}
namespace torrent {
@@ -102,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; }
@@ -126,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;
+5 -4
View File
@@ -1,11 +1,13 @@
#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"
@@ -15,7 +17,7 @@
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;
@@ -58,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
-1
View File
@@ -4,7 +4,6 @@
#include <curl/multi.h>
#include <torrent/exceptions.h>
#include "rak/functional.h"
#include "curl_get.h"
#include "curl_socket.h"
#include "curl_stack.h"
+23 -59
View File
@@ -1,47 +1,11 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <fstream>
#include <sstream>
#include <torrent/object.h>
#include <torrent/dht_manager.h>
#include <torrent/object_stream.h>
#include <torrent/rate.h>
#include <torrent/tracker/dht_controller.h>
#include <torrent/utils/log.h>
#include "rpc/parse_commands.h"
@@ -94,7 +58,7 @@ DhtManager::load_dht_cache() {
LT_LOG_THIS("could not open cache file (path:%s)", cache_filename.c_str());
}
torrent::dht_manager()->initialize(cache);
torrent::dht_controller()->initialize(cache);
if (m_start == dht_on)
start_dht();
@@ -104,31 +68,31 @@ void
DhtManager::start_dht() {
priority_queue_erase(&taskScheduler, &m_stopTimeout);
if (!torrent::dht_manager()->is_valid()) {
if (!torrent::dht_controller()->is_valid()) {
LT_LOG_THIS("server start skipped, manager is uninitialized", 0);
return;
}
if (torrent::dht_manager()->is_active()) {
if (torrent::dht_controller()->is_active()) {
LT_LOG_THIS("server start skipped, already active", 0);
return;
}
torrent::ThrottlePair throttles = control->core()->get_throttle(m_throttleName);
torrent::dht_manager()->set_upload_throttle(throttles.first);
torrent::dht_manager()->set_download_throttle(throttles.second);
torrent::dht_controller()->set_upload_throttle(throttles.first);
torrent::dht_controller()->set_download_throttle(throttles.second);
int port = rpc::call_command_value("dht.port");
if (port <= 0)
return;
if (!torrent::dht_manager()->start(port)) {
if (!torrent::dht_controller()->start(port)) {
m_start = dht_off;
return;
}
torrent::dht_manager()->reset_statistics();
torrent::dht_controller()->reset_statistics();
m_updateTimeout.slot() = std::bind(&DhtManager::update, this);
priority_queue_insert(&taskScheduler, &m_updateTimeout, (cachedTime + rak::timer::from_seconds(60)).round_seconds());
@@ -146,17 +110,17 @@ DhtManager::stop_dht() {
priority_queue_erase(&taskScheduler, &m_updateTimeout);
priority_queue_erase(&taskScheduler, &m_stopTimeout);
if (torrent::dht_manager()->is_active()) {
if (torrent::dht_controller()->is_active()) {
LT_LOG_THIS("stopping server", 0);
log_statistics(true);
torrent::dht_manager()->stop();
torrent::dht_controller()->stop();
}
}
void
DhtManager::save_dht_cache() {
if (!control->core()->download_store()->is_enabled() || !torrent::dht_manager()->is_valid())
if (!control->core()->download_store()->is_enabled() || !torrent::dht_controller()->is_valid())
return;
std::string filename = control->core()->download_store()->path() + "rtorrent.dht_cache";
@@ -167,7 +131,7 @@ DhtManager::save_dht_cache() {
return;
torrent::Object cache = torrent::Object::create_map();
cache_file << *torrent::dht_manager()->store_cache(&cache);
cache_file << *torrent::dht_controller()->store_cache(&cache);
if (!cache_file.good())
return;
@@ -198,7 +162,7 @@ DhtManager::set_mode(const std::string& arg) {
void
DhtManager::update() {
if (!torrent::dht_manager()->is_active())
if (!torrent::dht_controller()->is_active())
throw torrent::internal_error("DhtManager::update called with DHT inactive.");
if (m_start == dht_auto && !m_stopTimeout.is_queued()) {
@@ -207,7 +171,7 @@ DhtManager::update() {
for (itr = control->core()->download_list()->begin(), end = control->core()->download_list()->end(); itr != end; ++itr)
if ((*itr)->download()->info()->is_active() && !(*itr)->download()->info()->is_private())
break;
if (itr == end) {
m_stopTimeout.slot() = std::bind(&DhtManager::stop_dht, this);
priority_queue_insert(&taskScheduler, &m_stopTimeout, (cachedTime + rak::timer::from_seconds(15 * 60)).round_seconds());
@@ -223,17 +187,17 @@ DhtManager::update() {
bool
DhtManager::log_statistics(bool force) {
torrent::DhtManager::statistics_type stats = torrent::dht_manager()->get_statistics();
auto stats = torrent::dht_controller()->get_statistics();
// Check for firewall problems.
if (stats.cycle > 2 && stats.queries_sent - m_dhtPrevQueriesSent > 100 && stats.queries_received == m_dhtPrevQueriesReceived) {
// We should have had clients ping us at least but have received
// nothing, that means the UDP port is probably unreachable.
if (torrent::dht_manager()->can_receive_queries())
if (torrent::dht_controller()->is_receiving_requests())
LT_LOG_THIS("listening port appears to be unreachable, no queries received", 0);
torrent::dht_manager()->set_can_receive(false);
torrent::dht_controller()->set_receive_requests(false);
}
if (stats.queries_sent - m_dhtPrevQueriesSent > stats.num_nodes * 2 + 20 && stats.replies_received == m_dhtPrevRepliesReceived) {
@@ -248,7 +212,7 @@ DhtManager::log_statistics(bool force) {
m_warned = false;
if (stats.queries_received > m_dhtPrevQueriesReceived)
torrent::dht_manager()->set_can_receive(true);
torrent::dht_controller()->set_receive_requests(true);
// Nothing to log while bootstrapping, but check again every minute.
if (stats.cycle <= 1) {
@@ -269,7 +233,7 @@ DhtManager::log_statistics(bool force) {
// afterwards (i.e. every 2 hours), or when forced.
if ((force && stats.cycle != m_dhtPrevCycle) || stats.cycle == 3 || stats.cycle > m_dhtPrevCycle + 7) {
char buffer[256];
snprintf(buffer, sizeof(buffer),
snprintf(buffer, sizeof(buffer),
"DHT statistics: %d queries in, %d queries out, %d replies received, %lld bytes read, %lld bytes sent, "
"%d known nodes in %d buckets, %d peers (highest: %d) tracked in %d torrents.",
stats.queries_received - m_dhtPrevQueriesReceived,
@@ -301,11 +265,11 @@ DhtManager::dht_statistics() {
torrent::Object dhtStats = torrent::Object::create_map();
dhtStats.insert_key("dht", dht_settings[m_start]);
dhtStats.insert_key("active", torrent::dht_manager()->is_active());
dhtStats.insert_key("active", torrent::dht_controller()->is_active());
dhtStats.insert_key("throttle", m_throttleName);
if (torrent::dht_manager()->is_active()) {
torrent::DhtManager::statistics_type stats = torrent::dht_manager()->get_statistics();
if (torrent::dht_controller()->is_active()) {
auto stats = torrent::dht_controller()->get_statistics();
dhtStats.insert_key("cycle", stats.cycle);
dhtStats.insert_key("queries_received", stats.queries_received);
@@ -327,7 +291,7 @@ DhtManager::dht_statistics() {
void
DhtManager::set_throttle_name(const std::string& throttleName) {
if (torrent::dht_manager()->is_active())
if (torrent::dht_controller()->is_active())
throw torrent::input_error("Cannot set DHT throttle while active.");
m_throttleName = throttleName;
-36
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_CORE_DHT_MANAGER_H
#define RTORRENT_CORE_DHT_MANAGER_H
+4 -41
View File
@@ -1,50 +1,13 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <list>
#include <rak/file_stat.h>
#include <rak/functional.h>
#include <rak/path.h>
#include <torrent/exceptions.h>
#include <torrent/rate.h>
#include <torrent/torrent.h>
#include <torrent/tracker.h>
#include <torrent/tracker_list.h>
#include <torrent/tracker/tracker.h>
#include <torrent/data/file_list.h>
#include "rpc/parse_commands.h"
@@ -76,11 +39,11 @@ Download::~Download() {
void
Download::enable_udp_trackers(bool state) {
for (torrent::TrackerList::iterator itr = m_download.tracker_list()->begin(), last = m_download.tracker_list()->end(); itr != last; ++itr)
if ((*itr)->type() == torrent::Tracker::TRACKER_UDP) {
if (itr->type() == torrent::TRACKER_UDP) {
if (state)
(*itr)->enable();
itr->enable();
else
(*itr)->disable();
itr->disable();
}
}
+7 -49
View File
@@ -1,42 +1,7 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_CORE_DOWNLOAD_H
#define RTORRENT_CORE_DOWNLOAD_H
#include <torrent/common.h>
#include <torrent/download.h>
#include <torrent/download_info.h>
#include <torrent/hash_string.h>
@@ -46,11 +11,6 @@
#include "globals.h"
namespace torrent {
class PeerList;
class TrackerList;
}
namespace core {
class Download {
@@ -59,7 +19,6 @@ public:
typedef torrent::FileList file_list_type;
typedef torrent::PeerList peer_list_type;
typedef torrent::TrackerList tracker_list_type;
typedef torrent::TrackerController tracker_controller_type;
typedef torrent::ConnectionList connection_list_type;
typedef download_type::ConnectionType connection_type;
@@ -71,10 +30,10 @@ public:
Download(download_type d);
~Download();
const torrent::DownloadInfo* info() const { return m_download.info(); }
const torrent::download_data* data() const { return m_download.data(); }
auto info() const { return m_download.info(); }
auto data() const { return m_download.data(); }
torrent::DownloadMain* main() { return m_download.main(); }
auto main() { return m_download.main(); }
bool is_open() const { return m_download.info()->is_open(); }
bool is_active() const { return m_download.info()->is_active(); }
@@ -102,13 +61,12 @@ public:
torrent::Object* bencode() { return m_download.bencode(); }
auto tracker_controller() { return m_download.tracker_controller(); }
tracker_list_type* tracker_list() { return m_download.tracker_list(); }
uint32_t tracker_list_size() const { return m_download.tracker_list()->size(); }
tracker_controller_type* tracker_controller() { return m_download.tracker_controller(); }
connection_list_type* connection_list() { return m_download.connection_list(); }
uint32_t connection_list_size() const;
auto connection_list() { return m_download.connection_list(); }
uint32_t connection_list_size() const;
const std::string& message() const { return m_message; }
void set_message(const std::string& msg) { m_message = msg; }
+26 -20
View File
@@ -37,21 +37,20 @@ is_network_uri(const std::string& uri) {
std::strncmp(uri.c_str(), "ftp://", 6) == 0;
}
static bool
download_factory_add_stream(torrent::Object* root, const char* key, const char* filename) {
static std::unique_ptr<torrent::Object>
download_factory_load_stream(const char* filename) {
std::fstream stream(filename, std::ios::in | std::ios::binary);
if (!stream.is_open())
return false;
return std::unique_ptr<torrent::Object>();
torrent::Object obj;
stream >> obj;
auto obj = std::make_unique<torrent::Object>();
stream >> *obj;
if (!stream.good())
return false;
return std::unique_ptr<torrent::Object>();
root->insert_key_move(key, obj);
return true;
return obj;
}
bool
@@ -173,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;
@@ -200,8 +209,11 @@ DownloadFactory::receive_success() {
}
if (m_session) {
download_factory_add_stream(root, "rtorrent", (rak::path_expand(m_uri) + ".rtorrent").c_str());
download_factory_add_stream(root, "libtorrent_resume", (rak::path_expand(m_uri) + ".libtorrent_resume").c_str());
if (rtorrent_object)
root->insert_key_move("rtorrent", *rtorrent_object);
if (libtorrent_resume_object)
root->insert_key_move("libtorrent_resume", *libtorrent_resume_object);
} else {
// We only allow session torrents to keep their
@@ -213,6 +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());
@@ -378,14 +392,6 @@ DownloadFactory::initialize_rtorrent(Download* download, torrent::Object* rtorre
else
rpc::call_command("d.priority.set", (int64_t)2, rpc::make_target(download));
if (rtorrent->has_key_value("key")) {
download->tracker_list()->set_key(rtorrent->get_key_value("key"));
} else {
download->tracker_list()->set_key(random() % (std::numeric_limits<uint32_t>::max() - 1) + 1);
rtorrent->insert_key("key", download->tracker_list()->key());
}
if (rtorrent->has_key_value("total_uploaded"))
download->info()->mutable_up_rate()->set_total(rtorrent->get_key_value("total_uploaded"));
+16 -53
View File
@@ -1,45 +1,8 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <algorithm>
#include <fstream>
#include <iostream>
#include <rak/functional.h>
#include <rak/string_manip.h>
#include <torrent/data/file.h>
#include <torrent/utils/resume.h>
@@ -71,7 +34,7 @@
namespace core {
inline void
DownloadList::check_contains(Download* d) {
DownloadList::check_contains([[maybe_unused]] Download* d) {
#ifdef USE_EXTRA_DEBUG
if (std::find(begin(), end(), d) == end())
throw torrent::internal_error("DownloadList::check_contains(...) failed.");
@@ -80,15 +43,15 @@ DownloadList::check_contains(Download* d) {
void
DownloadList::clear() {
std::for_each(begin(), end(), std::bind1st(std::mem_fun(&DownloadList::close), this));
std::for_each(begin(), end(), rak::call_delete<Download>());
std::for_each(begin(), end(), [&](Download* d) { close(d); });
std::for_each(begin(), end(), [](Download* d) { delete d; });
base_type::clear();
}
void
DownloadList::session_save() {
unsigned int c = std::count_if(begin(), end(), std::bind1st(std::mem_fun(&DownloadStore::save_resume), control->core()->download_store()));
unsigned int c = std::count_if(begin(), end(), [&](Download* d) { return control->core()->download_store()->save_resume(d); });
if (c != size())
lt_log_print(torrent::LOG_ERROR, "Failed to save session torrents.");
@@ -99,7 +62,7 @@ DownloadList::session_save() {
DownloadList::iterator
DownloadList::find(const torrent::HashString& hash) {
return std::find_if(begin(), end(), rak::equal(hash, rak::on(std::mem_fun(&Download::info), std::mem_fun(&torrent::DownloadInfo::hash))));
return std::find_if(begin(), end(), [hash](Download* d) { return hash == d->info()->hash(); });
}
DownloadList::iterator
@@ -109,7 +72,7 @@ DownloadList::find_hex(const char* hash) {
for (torrent::HashString::iterator itr = key.begin(), last = key.end(); itr != last; itr++, hash += 2)
*itr = (rak::hexchar_to_value(*hash) << 4) + rak::hexchar_to_value(*(hash + 1));
return std::find_if(begin(), end(), rak::equal(key, rak::on(std::mem_fun(&Download::info), std::mem_fun(&torrent::DownloadInfo::hash))));
return std::find_if(begin(), end(), [key](Download* d) { return key == d->info()->hash(); });
}
Download*
@@ -120,11 +83,11 @@ DownloadList::find_hex_ptr(const char* hash) {
}
Download*
DownloadList::create(torrent::Object* obj, bool printLog) {
DownloadList::create(torrent::Object* obj, uint32_t tracker_key, bool printLog) {
torrent::Download download;
try {
download = torrent::download_add(obj);
download = torrent::download_add(obj, tracker_key);
} catch (torrent::local_error& e) {
delete obj;
@@ -141,13 +104,13 @@ DownloadList::create(torrent::Object* obj, bool printLog) {
}
Download*
DownloadList::create(std::istream* str, bool printLog) {
DownloadList::create(std::istream* str, uint32_t tracker_key, bool printLog) {
torrent::Object* object = new torrent::Object;
torrent::Download download;
try {
*str >> *object;
// Don't throw input_error from here as gcc-3.3.5 produces bad
// code.
if (str->fail()) {
@@ -159,7 +122,7 @@ DownloadList::create(std::istream* str, bool printLog) {
return NULL;
}
download = torrent::download_add(object);
download = torrent::download_add(object, tracker_key);
} catch (torrent::local_error& e) {
delete object;
@@ -187,8 +150,8 @@ DownloadList::insert(Download* download) {
// This needs to be separated into two different calls to ensure
// the download remains in the view.
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), std::bind2nd(std::mem_fun(&View::insert), download));
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), std::bind2nd(std::mem_fun(&View::filter_download), download));
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), [&download](View* v) { v->insert(download); });
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), [&download](View* v) { v->filter_download(download); });
DL_TRIGGER_EVENT(*itr, "event.download.inserted");
@@ -221,7 +184,7 @@ DownloadList::erase(iterator itr) {
control->core()->download_store()->remove(*itr);
DL_TRIGGER_EVENT(*itr, "event.download.erased");
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), std::bind2nd(std::mem_fun(&View::erase), *itr));
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), [itr](View* v) { v->erase(*itr); });
torrent::download_remove(*(*itr)->download());
delete *itr;
@@ -550,8 +513,8 @@ DownloadList::hash_done(Download* download) {
if (download->is_done()) {
confirm_finished(download);
} else {
download->set_message("Hash check on download completion found bad chunks, consider using \"safe_sync\".");
lt_log_print(torrent::LOG_TORRENT_ERROR, "Hash check on download completion found bad chunks, consider using \"safe_sync\".");
download->set_message("Hash check on download completion found bad chunks.");
lt_log_print(torrent::LOG_TORRENT_ERROR, "Hash check on download completion found bad chunks.");
DL_TRIGGER_EVENT(download, "event.download.hash_final_failed");
}
+3 -38
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_CORE_DOWNLOAD_LIST_H
#define RTORRENT_CORE_DOWNLOAD_LIST_H
@@ -43,6 +7,7 @@
namespace torrent {
class HashString;
class Object;
}
namespace core {
@@ -86,8 +51,8 @@ public:
Download* find_hex_ptr(const char* hash);
// Might move this to DownloadFactory.
Download* create(std::istream* str, bool printLog);
Download* create(torrent::Object* obj, bool printLog);
Download* create(std::istream* str, uint32_t tracker_key, bool printLog);
Download* create(torrent::Object* obj, uint32_t tracker_key, bool printLog);
iterator insert(Download* d);
+8 -5
View File
@@ -20,6 +20,7 @@
#include "download.h"
#include "download_store.h"
#include "rpc/parse_commands.h"
namespace core {
@@ -93,12 +94,14 @@ DownloadStore::write_bencode(const std::string& filename, const torrent::Object&
if (fd < 0)
goto download_store_save_error;
if (rpc::call_command_value("system.files.session.fdatasync")) {
#ifdef __APPLE__
fsync(fd);
fsync(fd);
#else
fdatasync(fd);
fdatasync(fd);
#endif
::close(fd);
::close(fd);
}
return true;
@@ -141,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());
@@ -175,7 +178,7 @@ DownloadStore::get_formated_entries() {
if (!d.update(utils::Directory::update_hide_dot))
throw torrent::storage_error("core::DownloadStore::update() could not open directory \"" + m_path + "\"");
d.erase(std::remove_if(d.begin(), d.end(), std::ptr_fun(&not_correct_format)), d.end());
d.erase(std::remove_if(d.begin(), d.end(), [&](const utils::directory_entry& entry) { return not_correct_format(entry); }), d.end());
return d;
}
+1 -2
View File
@@ -40,7 +40,6 @@
#include <sstream>
#include <torrent/http.h>
#include "rak/functional.h"
#include "http_queue.h"
#include "curl_get.h"
@@ -48,7 +47,7 @@ namespace core {
HttpQueue::iterator
HttpQueue::insert(const std::string& url, std::iostream* s) {
std::auto_ptr<CurlGet> h(m_slot_factory());
std::unique_ptr<CurlGet> h(m_slot_factory());
h->set_url(url);
h->set_stream(s);
+27 -4
View File
@@ -23,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"
@@ -313,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.
@@ -320,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;
@@ -333,10 +350,16 @@ Manager::try_create_download(const std::string& uri, int flags, const command_li
f->set_print_log(!(flags & create_quiet));
f->slot_finished([f]() { delete f; });
if (flags & create_raw_data)
if (is_data_uri(uri)) {
// Allow the use of data URIs, primarily for JSON-RPC which
// doesn't have a defined mechanism for binary data
f->load_raw_data(decode_data_uri(uri));
f->variables()["tied_to_file"] = (int64_t)false;
} else if (flags & create_raw_data) {
f->load_raw_data(uri);
else
} else {
f->load(uri);
}
f->commit();
}
@@ -419,7 +442,7 @@ path_expand(std::vector<std::string>* paths, const std::string& pattern) {
currentCache.swap(nextCache);
}
std::transform(currentCache.begin(), currentCache.end(), std::back_inserter(*paths), std::mem_fun_ref(&utils::Directory::path));
std::transform(currentCache.begin(), currentCache.end(), std::back_inserter(*paths), std::mem_fn(&utils::Directory::path));
}
bool
@@ -453,7 +476,7 @@ Manager::try_create_download_expand(const std::string& uri, int flags, command_l
void
Manager::receive_hashing_changed() {
bool foundHashing = std::find_if(m_hashingView->begin_visible(), m_hashingView->end_visible(),
std::mem_fun(&Download::is_hash_checking)) != m_hashingView->end_visible();
std::mem_fn(&Download::is_hash_checking)) != m_hashingView->end_visible();
// Try quick hashing all those with hashing == initial, set them to
// something else when failed.
+4 -2
View File
@@ -49,10 +49,12 @@ namespace core {
template<typename Key, typename T, typename Compare = std::less<Key>,
typename Alloc = std::allocator<std::pair<const Key, T> > >
class RangeMap : private std::map<Key, std::pair<Key, T>, Compare,
typename Alloc::template rebind<std::pair<const Key, std::pair<Key, T> > >::other> {
typename std::allocator_traits<Alloc>::template rebind_alloc<std::pair<const Key, std::pair<Key, T>>>> {
typedef std::map<Key, std::pair<Key, T>, Compare,
typename Alloc::template rebind<std::pair<const Key, std::pair<Key, T> > >::other> base_type;
typename std::allocator_traits<Alloc>::template rebind_alloc<std::pair<const Key, std::pair<Key, T>>>> base_type;
//std::allocator_traits<Alloc>::template rebind_alloc<std::pair<const Key, std::pair<Key, T>>>
public:
RangeMap() {}
+33 -45
View File
@@ -1,44 +1,7 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <algorithm>
#include <functional>
#include <rak/functional.h>
#include <torrent/download.h>
#include <torrent/exceptions.h>
@@ -53,7 +16,7 @@
namespace core {
// Also add focus thingie here?
struct view_downloads_compare : std::binary_function<Download*, Download*, bool> {
struct view_downloads_compare : std::function<bool (Download*, Download*)> {
view_downloads_compare(const torrent::Object& cmd) :
m_command(cmd) {}
@@ -87,7 +50,7 @@ struct view_downloads_compare : std::binary_function<Download*, Download*, bool>
const torrent::Object& m_command;
};
struct view_downloads_filter : std::unary_function<Download*, bool> {
struct view_downloads_filter : std::function<bool (Download*)> {
view_downloads_filter(const torrent::Object& cmd, const torrent::Object& cmd2) :
m_command(cmd), m_command2(cmd2) {}
@@ -180,7 +143,7 @@ View::initialize(const std::string& name) {
m_name = name;
// Urgh, wrong. No filtering being done.
std::for_each(dlist->begin(), dlist->end(), rak::bind1st(std::mem_fun(&View::push_back), this));
std::for_each(dlist->begin(), dlist->end(), [&](Download* d) { push_back(d); });
m_size = base_type::size();
m_focus = 0;
@@ -236,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();
}
@@ -360,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));
+5 -38
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Provides a filtered and sorted list of downloads that can be
// updated auto-magically.
//
@@ -114,8 +78,11 @@ public:
void set_visible(Download* download);
void set_not_visible(Download* download);
void next_focus();
void prev_focus();
void next_focus(unsigned int i);
void prev_focus(unsigned int i);
void next_focus() { next_focus(1); }
void prev_focus() { prev_focus(1); }
void sort();
+3 -4
View File
@@ -37,7 +37,6 @@
#include "config.h"
#include <algorithm>
#include <rak/functional.h>
#include <torrent/exceptions.h>
#include <torrent/object.h>
@@ -55,7 +54,7 @@ namespace core {
void
ViewManager::clear() {
std::for_each(begin(), end(), rak::call_delete<View>());
std::for_each(begin(), end(), [](View* v) { delete v; });
base_type::clear();
}
@@ -76,12 +75,12 @@ ViewManager::insert(const std::string& name) {
ViewManager::iterator
ViewManager::find(const std::string& name) {
return std::find_if(begin(), end(), rak::equal(name, std::mem_fun(&View::name)));
return std::find_if(begin(), end(), [name](View* v){ return name == v->name(); });
}
ViewManager::iterator
ViewManager::find_throw(const std::string& name) {
iterator itr = std::find_if(begin(), end(), rak::equal(name, std::mem_fun(&View::name)));
iterator itr = std::find_if(begin(), end(), [name](View* v){ return name == v->name(); });
if (itr == end())
throw torrent::input_error("Could not find view: " + name);
+120 -43
View File
@@ -1,45 +1,9 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <unistd.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <torrent/exceptions.h>
#include <unistd.h>
#include "rpc/parse_commands.h"
@@ -48,14 +12,16 @@
namespace display {
bool Canvas::m_isInitialized = false;
bool Canvas::m_isDaemon = false;
bool Canvas::m_isDaemon = false;
// Maps ncurses color IDs to a ncurses attribute int
std::unordered_map<int, int> Canvas::m_attr_map = {};
Canvas::Canvas(int x, int y, int width, int height) {
if (!m_isDaemon) {
m_window = newwin(height, width, y, x);
m_window = newwin(height, width, y, x);
if (m_window == NULL)
throw torrent::internal_error("Could not allocate ncurses canvas.");
if (m_window == NULL)
throw torrent::internal_error("Could not allocate ncurses canvas.");
}
}
@@ -73,7 +39,7 @@ Canvas::print_attributes(unsigned int x, unsigned int y, const char* first, cons
move(x, y);
attr_t org_attr;
short org_pair;
short org_pair;
wattr_get(m_window, &org_attr, &org_pair, NULL);
attributes_list::const_iterator attrItr = attributes->begin();
@@ -111,6 +77,9 @@ Canvas::initialize() {
if (!m_isDaemon) {
initscr();
start_color();
use_default_colors();
Canvas::build_colors();
raw();
noecho();
nodelay(stdscr, TRUE);
@@ -119,6 +88,114 @@ Canvas::initialize() {
}
}
// Function wrapper for what possibly is a macro
int
get_colors() {
return COLORS;
}
// Turns the string color definitions from the "ui.color.*" RPC
// commands into valid ncurses color pairs
void
Canvas::build_colors() {
// This may get called early in the start process by the config
// file, so we need to delay building until initscr() has a chance
// to run
if (!m_isInitialized || m_isDaemon)
return;
// basic color names, index maps to ncurses COLOR_*
static const char* color_names[] = {
"black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"};
// Those hold the background colors of "odd" and "even"
int bg_odd = -1;
int bg_even = -1;
for (int k = 1; k < RCOLOR_MAX; k++) {
init_pair(k, -1, -1);
std::string color_def = rpc::call_command_string(color_vars[k]);
if (color_def.empty())
continue; // Use terminal default if definition is empty
short color[2] = {-1, -1}; // fg, bg
short color_idx = 0; // 0 = fg; 1 = bg
short bright = 0;
unsigned long attr = A_NORMAL;
// Process string as space-separated words
size_t start = 0, end = 0;
while (true) {
end = color_def.find(' ', start);
std::string word = color_def.substr(start, end - start);
if (word == "bold")
attr |= A_BOLD;
else if (word == "standout")
attr |= A_STANDOUT;
else if (word == "underline")
attr |= A_UNDERLINE;
else if (word == "reverse")
attr |= A_REVERSE;
else if (word == "blink")
attr |= A_BLINK;
else if (word == "dim")
attr |= A_DIM;
else if (word == "on") {
color_idx = 1;
bright = 0;
} // Switch to background color
else if (word == "gray" || word == "grey")
color[color_idx] = bright ? 7 : 8; // Bright gray is white
else if (word == "bright")
bright = 8;
else if (word.find_first_not_of("0123456789") == std::string::npos) {
// Handle numeric index
short c = -1;
sscanf(word.c_str(), "%hd", &c);
color[color_idx] = c;
} else
for (short c = 0; c < 8; c++) { // Check for basic color names
if (word == color_names[c]) {
color[color_idx] = bright + c;
break;
}
}
if (end == std::string::npos)
break;
start = end + 1;
}
// Check that fg & bg color index is valid
if ((color[0] != -1 && color[0] >= get_colors()) || (color[1] != -1 && color[1] >= get_colors())) {
char buf[33];
sprintf(buf, "%d", get_colors());
Canvas::cleanup();
throw torrent::input_error(color_def + ": your terminal only supports " + buf + " colors.");
}
m_attr_map[k] = attr; // overwrite or insert the value
init_pair(k, color[0], color[1]);
if (k == RCOLOR_EVEN)
bg_even = color[1];
if (k == RCOLOR_ODD)
bg_odd = color[1];
}
// Now make copies of the basic colors with the "odd" and "even" definitions mixed in
for (int k = 1; k < RCOLOR_MAX; k++) {
short fg, bg;
pair_content(k, &fg, &bg);
// Replace the background color, and mix in the attributes
m_attr_map[k + 1 * RCOLOR_MAX] = m_attr_map[k] | m_attr_map[RCOLOR_EVEN];
m_attr_map[k + 2 * RCOLOR_MAX] = m_attr_map[k] | m_attr_map[RCOLOR_ODD];
init_pair(k + 1 * RCOLOR_MAX, fg, bg == -1 ? bg_even : bg);
init_pair(k + 2 * RCOLOR_MAX, fg, bg == -1 ? bg_odd : bg);
}
}
void
Canvas::cleanup() {
if (!m_isInitialized)
@@ -143,4 +220,4 @@ Canvas::term_size() {
return std::pair<int, int>(80, 24);
}
}
} // namespace display
+227 -84
View File
@@ -1,125 +1,204 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_DISPLAY_CANVAS_H
#define RTORRENT_DISPLAY_CANVAS_H
#include <string>
#include <unordered_map>
#include <vector>
#include "attributes.h"
#include "color_map.h"
namespace display {
class Canvas {
public:
typedef std::vector<Attributes> attributes_list;
typedef std::vector<Attributes> attributes_list;
typedef std::unordered_map<int, int> attributes_map;
Canvas(int x = 0, int y = 0, int width = 0, int height = 0);
~Canvas() { if (!m_isDaemon) { delwin(m_window); } }
~Canvas();
void refresh() { if (!m_isDaemon) { wnoutrefresh(m_window); } }
static void refresh_std() { if (!m_isDaemon) { wnoutrefresh(stdscr); } }
void redraw() { if (!m_isDaemon) { redrawwin(m_window); } }
static void redraw_std() { if (!m_isDaemon) { redrawwin(stdscr); } }
void refresh();
void redraw();
void resize(int w, int h);
void resize(int x, int y, int w, int h);
void resize(int w, int h) { if (!m_isDaemon) { wresize(m_window, h, w); } }
void resize(int x, int y, int w, int h);
static void refresh_std();
static void redraw_std();
static void resize_term(int x, int y);
static void resize_term(std::pair<int, int> dim);
static void resize_term(int x, int y) { if (!m_isDaemon) { resizeterm(y, x); } }
static void resize_term(std::pair<int, int> dim) { if (!m_isDaemon) { resizeterm(dim.second, dim.first); } }
unsigned int get_x();
unsigned int get_y();
unsigned int width();
unsigned int height();
unsigned int get_x() { int x, __UNUSED y; if (!m_isDaemon) { getyx(m_window, y, x); } else { x=1; } return x; }
unsigned int get_y() { int x, y; if (!m_isDaemon) { getyx(m_window, y, x); } else { y=1; } return y; }
unsigned int width() { int x, __UNUSED y; if (!m_isDaemon) { getmaxyx(m_window, y, x); } else { x=80; } return x; }
unsigned int height() { int x, y; if (!m_isDaemon) { getmaxyx(m_window, y, x); } else { y=24; } return y; }
void move(unsigned int x, unsigned int y) { if (!m_isDaemon) { wmove(m_window, y, x); } }
chtype get_background() { chtype bg=0; if (!m_isDaemon) { bg=getbkgd(m_window); } return bg; }
void set_background(chtype c) { if (!m_isDaemon) { return wbkgdset(m_window, c); } }
void erase() { if (!m_isDaemon) { werase(m_window); } }
static void erase_std() { if (!m_isDaemon) { werase(stdscr); } }
void print_border(chtype ls, chtype rs,
chtype ts, chtype bs,
chtype tl, chtype tr,
chtype bl, chtype br) { if (!m_isDaemon) { wborder(m_window, ls, rs, ts, bs, tl, tr, bl, br); } }
void move(unsigned int x, unsigned int y);
void erase();
static void erase_std();
// The format string is non-const, but that will not be a problem
// since the string shall always be a C string choosen at
// compiletime. Might cause extra copying of the string?
void print(const char* str, ...);
void print(unsigned int x, unsigned int y, const char* str, ...);
void print(const char* str, ...);
void print(unsigned int x, unsigned int y, const char* str, ...);
void print_attributes(unsigned int x, unsigned int y, const char* first, const char* last, const attributes_list* attributes);
void print_char(const chtype ch);
void print_char(unsigned int x, unsigned int y, const chtype ch);
void print_attributes(unsigned int x, unsigned int y, const char* first, const char* last, const attributes_list* attributes);
void print_char(const chtype ch) { if (!m_isDaemon) { waddch(m_window, ch); } }
void print_char(unsigned int x, unsigned int y, const chtype ch) { if (!m_isDaemon) { mvwaddch(m_window, y, x, ch); } }
void set_attr(unsigned int x, unsigned int y, unsigned int n, int attr, int color) { if (!m_isDaemon) { mvwchgat(m_window, y, x, n, attr, color, NULL); } }
void set_default_attributes(int attr) { if (!m_isDaemon) { (void)wattrset(m_window, attr); } }
void set_attr(unsigned int x, unsigned int y, unsigned int n, int attr, int color);
void set_attr(unsigned int x, unsigned int y, unsigned int n, ColorKind k);
void set_default_attributes(int attr);
// Initialize stdscr.
static void initialize();
static void cleanup();
static void initialize();
static void build_colors();
static void cleanup();
static int get_screen_width() { int x, __UNUSED y; if (!m_isDaemon) { getmaxyx(stdscr, y, x); } else { x=80; } return x; }
static int get_screen_height() { int x, y; if (!m_isDaemon) { getmaxyx(stdscr, y, x); } else { y=24;} return y; }
static int get_screen_width();
static int get_screen_height();
static std::pair<int, int> term_size();
static void do_update() { if (!m_isDaemon) { doupdate(); } }
static void do_update();
static bool daemon() { return m_isDaemon; }
static bool daemon() { return m_isDaemon; }
static const attributes_map& attr_map() { return m_attr_map; }
private:
Canvas(const Canvas&);
void operator = (const Canvas&);
void operator=(const Canvas&);
static bool m_isInitialized;
static bool m_isDaemon;
static bool m_isInitialized;
static bool m_isDaemon;
WINDOW* m_window;
// Maps ncurses color IDs to a ncurses attribute int
static std::unordered_map<int, int> m_attr_map;
WINDOW* m_window;
};
inline Canvas::~Canvas() {
if (!m_isDaemon) {
delwin(m_window);
}
}
inline void
Canvas::refresh() {
if (!m_isDaemon) {
wnoutrefresh(m_window);
}
}
inline void
Canvas::refresh_std() {
if (!m_isDaemon) {
wnoutrefresh(stdscr);
}
}
inline void
Canvas::redraw() {
if (!m_isDaemon) {
redrawwin(m_window);
}
}
inline void
Canvas::redraw_std() {
if (!m_isDaemon) {
redrawwin(stdscr);
}
}
inline void
Canvas::resize(int w, int h) {
if (!m_isDaemon) {
wresize(m_window, h, w);
}
}
inline void
Canvas::resize_term(int x, int y) {
if (!m_isDaemon) {
resizeterm(y, x);
}
}
inline void
Canvas::resize_term(std::pair<int, int> dim) {
if (!m_isDaemon) {
resizeterm(dim.second, dim.first);
}
}
inline unsigned int
Canvas::get_x() {
int x, __UNUSED y;
if (!m_isDaemon) {
getyx(m_window, y, x);
} else {
x = 1;
}
return x;
}
inline unsigned int
Canvas::get_y() {
int x, y;
if (!m_isDaemon) {
getyx(m_window, y, x);
} else {
y = 1;
}
return y;
}
inline unsigned int
Canvas::width() {
int x, __UNUSED y;
if (!m_isDaemon) {
getmaxyx(m_window, y, x);
} else {
x = 80;
}
return x;
}
inline unsigned int
Canvas::height() {
int x, y;
if (!m_isDaemon) {
getmaxyx(m_window, y, x);
} else {
y = 24;
}
return y;
}
inline void
Canvas::move(unsigned int x, unsigned int y) {
if (!m_isDaemon) {
wmove(m_window, y, x);
}
}
inline void
Canvas::erase() {
if (!m_isDaemon) {
werase(m_window);
}
}
inline void
Canvas::erase_std() {
if (!m_isDaemon) {
werase(stdscr);
}
}
inline void
Canvas::print(const char* str, ...) {
va_list arglist;
@@ -143,6 +222,70 @@ Canvas::print(unsigned int x, unsigned int y, const char* str, ...) {
}
}
inline void
Canvas::print_char(const chtype ch) {
if (!m_isDaemon) {
waddch(m_window, ch);
}
}
inline void
Canvas::print_char(unsigned int x, unsigned int y, const chtype ch) {
if (!m_isDaemon) {
mvwaddch(m_window, y, x, ch);
}
}
inline void
Canvas::set_attr(unsigned int x, unsigned int y, unsigned int n, int attr, int color) {
if (!m_isDaemon) {
mvwchgat(m_window, y, x, n, attr, color, NULL);
}
}
inline void
Canvas::set_attr(unsigned int x, unsigned int y, unsigned int n, ColorKind k) {
if (!m_isDaemon) {
mvwchgat(m_window, y, x, n, m_attr_map[k], k, NULL);
}
}
inline void
Canvas::set_default_attributes(int attr) {
if (!m_isDaemon) {
(void)wattrset(m_window, attr);
}
}
inline int
Canvas::get_screen_width() {
int x, __UNUSED y;
if (!m_isDaemon) {
getmaxyx(stdscr, y, x);
} else {
x = 80;
}
return x;
}
inline int
Canvas::get_screen_height() {
int x, y;
if (!m_isDaemon) {
getmaxyx(stdscr, y, x);
} else {
y = 24;
}
return y;
}
inline void
Canvas::do_update() {
if (!m_isDaemon) {
doupdate();
}
}
} // namespace display
#endif
+48
View File
@@ -0,0 +1,48 @@
#ifndef RTORRENT_DISPLAY_COLOR_MAP_H
#define RTORRENT_DISPLAY_COLOR_MAP_H
#include <map>
#include <curses.h>
namespace display {
enum ColorKind {
RCOLOR_NCURSES_DEFAULT, // Color 0 is reserved by ncurses and cannot be changed
RCOLOR_TITLE,
RCOLOR_FOOTER,
RCOLOR_FOCUS,
RCOLOR_LABEL,
RCOLOR_INFO,
RCOLOR_ALARM,
RCOLOR_COMPLETE,
RCOLOR_SEEDING,
RCOLOR_STOPPED,
RCOLOR_QUEUED,
RCOLOR_INCOMPLETE,
RCOLOR_LEECHING,
RCOLOR_ODD,
RCOLOR_EVEN,
RCOLOR_MAX,
};
static const char* color_vars[RCOLOR_MAX] = {
0,
"ui.color.title",
"ui.color.footer",
"ui.color.focus",
"ui.color.label",
"ui.color.info",
"ui.color.alarm",
"ui.color.complete",
"ui.color.seeding",
"ui.color.stopped",
"ui.color.queued",
"ui.color.incomplete",
"ui.color.leeching",
"ui.color.odd",
"ui.color.even",
};
} // namespace display
#endif
-1
View File
@@ -38,7 +38,6 @@
#include <stdexcept>
#include <algorithm>
#include <rak/functional.h>
#include "canvas.h"
#include "globals.h"
+1 -2
View File
@@ -37,7 +37,6 @@
#include "config.h"
#include <algorithm>
#include <rak/functional.h>
#include <torrent/exceptions.h>
#include "text_element_list.h"
@@ -46,7 +45,7 @@ namespace display {
void
TextElementList::clear() {
std::for_each(begin(), end(), rak::call_delete<TextElement>());
std::for_each(begin(), end(), [](TextElement* t) { delete t; });
base_type::clear();
}
+6 -43
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <cstring>
@@ -47,8 +11,8 @@
#include <torrent/rate.h>
#include <torrent/throttle.h>
#include <torrent/torrent.h>
#include <torrent/tracker.h>
#include <torrent/tracker_list.h>
#include <torrent/tracker/tracker.h>
#include <torrent/data/file_list.h>
#include <torrent/data/file_manager.h>
#include <torrent/download/resource_manager.h>
@@ -88,7 +52,7 @@ print_hhmmss(char* first, char* last, time_t t) {
char*
print_hhmmss_local(char* first, char* last, time_t t) {
std::tm *u = std::localtime(&t);
if (u == NULL)
//return "inv_time";
throw torrent::internal_error("print_hhmmss_local(...) failed.");
@@ -107,7 +71,7 @@ print_ddhhmm(char* first, char* last, time_t t) {
char*
print_ddmmyyyy(char* first, char* last, time_t t) {
std::tm *u = std::gmtime(&t);
if (u == NULL)
//return "inv_time";
throw torrent::internal_error("print_ddmmyyyy(...) failed.");
@@ -199,12 +163,11 @@ print_download_status(char* first, char* last, core::Download* d) {
} else if (d->tracker_list()->has_active_not_scrape()) {
torrent::TrackerList::iterator itr =
std::find_if(d->tracker_list()->begin(), d->tracker_list()->end(),
std::mem_fun(&torrent::Tracker::is_busy_not_scrape));
char status[128];
std::mem_fn(&torrent::tracker::Tracker::is_busy_not_scrape));
auto status = itr->status();
(*itr)->get_status(status, sizeof(status));
first = print_buffer(first, last, "Tracker[%i:%i]: Connecting to %s %s",
(*itr)->group(), std::distance(d->tracker_list()->begin(), itr), (*itr)->url().c_str(), status);
itr->group(), std::distance(d->tracker_list()->begin(), itr), itr->url().c_str(), status.c_str());
} else if (!d->message().empty()) {
first = print_buffer(first, last, "%s", d->message().c_str());
+4 -5
View File
@@ -38,7 +38,7 @@
#define RTORRENT_WINDOW_BASE_H
#include <rak/timer.h>
#include <rak/functional.h>
#include <functional>
#include "canvas.h"
#include "globals.h"
@@ -46,15 +46,14 @@
namespace display {
class Canvas;
class Manager;
class Window {
public:
typedef uint32_t extent_type;
typedef rak::mem_fun0<Manager, void> Slot;
typedef rak::mem_fun1<Manager, void, Window*> SlotWindow;
typedef rak::mem_fun2<Manager, void, Window*, rak::timer> SlotTimer;
typedef std::function<void()> Slot;
typedef std::function<void(Window*)> SlotWindow;
typedef std::function<void(Window*, rak::timer)> SlotTimer;
static const int flag_active = (1 << 0);
static const int flag_offscreen = (1 << 1);
+2 -3
View File
@@ -38,7 +38,6 @@
#include <cmath>
#include <stdexcept>
#include <rak/functional.h>
#include <rak/string_manip.h>
#include <torrent/bitfield.h>
#include <torrent/data/block.h>
@@ -95,7 +94,7 @@ WindowDownloadChunksSeen::redraw() {
std::vector<torrent::BlockList*> transferChunks(transfers->size(), 0);
std::copy(transfers->begin(), transfers->end(), transferChunks.begin());
std::sort(transferChunks.begin(), transferChunks.end(), rak::less2(std::mem_fun(&torrent::BlockList::index), std::mem_fun(&torrent::BlockList::index)));
std::sort(transferChunks.begin(), transferChunks.end());
std::vector<torrent::BlockList*>::const_iterator itrTransfer = transferChunks.begin();
@@ -111,7 +110,7 @@ WindowDownloadChunksSeen::redraw() {
if (bitfield->get(chunk - seen)) {
attr = A_NORMAL;
} else if (itrTransfer != transferChunks.end() && (uint32_t)(chunk - seen) == (*itrTransfer)->index()) {
if (std::find_if((*itrTransfer)->begin(), (*itrTransfer)->end(), std::mem_fun_ref(&torrent::Block::is_transfering)) != (*itrTransfer)->end())
if (std::any_of((*itrTransfer)->begin(), (*itrTransfer)->end(), std::mem_fn(&torrent::Block::is_transfering)))
attr = A_REVERSE;
else
attr = A_BOLD | A_UNDERLINE;
+65 -56
View File
@@ -1,41 +1,6 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include "display/color_map.h"
#include <rak/algorithm.h>
#include "core/download.h"
@@ -57,7 +22,7 @@ WindowDownloadList::WindowDownloadList() :
WindowDownloadList::~WindowDownloadList() {
if (m_view != NULL)
m_view->signal_changed().erase(m_changed_itr);
m_view = NULL;
}
@@ -72,8 +37,47 @@ WindowDownloadList::set_view(core::View* l) {
m_changed_itr = m_view->signal_changed().insert(m_view->signal_changed().begin(), std::bind(&Window::mark_dirty, this));
}
// Return a pair of ints, representing a) the ncurses attributes and b) the ncurses color pair ID to use
std::pair<int, int>
WindowDownloadList::get_attr_color(core::View::iterator selected) {
core::Download* item = *selected;
unsigned long focus_attr = selected == m_view->focus() ? m_canvas->attr_map().at(RCOLOR_FOCUS) : 0;
int offset = (((selected - m_view->begin_visible()) & 1) + 1) * RCOLOR_MAX; // Determine the even/odd offset for the color pair
bool active = item->is_open() && item->is_active();
int title_color;
if (item->is_done())
title_color = (active ? item->info()->up_rate()->rate() ? RCOLOR_SEEDING : RCOLOR_COMPLETE : RCOLOR_STOPPED) + offset;
else
title_color = (active ? item->info()->down_rate()->rate() ? RCOLOR_LEECHING : RCOLOR_INCOMPLETE : RCOLOR_QUEUED) + offset;
return std::make_pair(m_canvas->attr_map().at(title_color) | focus_attr, title_color);
}
int
WindowDownloadList::page_size(const std::string layout_name) {
// Calculate the page size for torrents. This is a public method
// because it's also used to determine the default size for page
// up/down actions.
int layout_height;
if (layout_name == "full") {
layout_height = 3;
} else if (layout_name == "compact") {
layout_height = 1;
} else {
return 0;
}
return m_canvas->height() / layout_height;
}
int
WindowDownloadList::page_size() {
return page_size(rpc::call_command_string("ui.torrent_list.layout"));
}
void
WindowDownloadList::redraw() {
if (m_canvas->daemon())
return;
m_slotSchedule(this, (cachedTime + rak::timer::from_seconds(1)).round_seconds());
m_canvas->erase();
@@ -95,24 +99,16 @@ WindowDownloadList::redraw() {
m_canvas->print(m_canvas->width() - 16, 0, "[%5d of %-5d]", item_idx + 1, m_view->size());
}
int layout_height;
const std::string layout_name = rpc::call_command_string("ui.torrent_list.layout");
m_canvas->set_attr(0, 0, -1, RCOLOR_TITLE);
if (layout_name == "full") {
layout_height = 3;
} else if (layout_name == "compact") {
layout_height = 1;
} else {
m_canvas->print(0, 0, "INVALID ui.torrent_list.layout '%s'", layout_name.c_str());
return;
}
const std::string layout_name = rpc::call_command_string("ui.torrent_list.layout");
typedef std::pair<core::View::iterator, core::View::iterator> Range;
Range range = rak::advance_bidirectional(m_view->begin_visible(),
m_view->focus() != m_view->end_visible() ? m_view->focus() : m_view->begin_visible(),
m_view->end_visible(),
m_canvas->height() / layout_height);
page_size(layout_name));
// Make sure we properly fill out the last lines so it looks like
// there are more torrents, yet don't hide it if we got the last one
@@ -120,8 +116,8 @@ WindowDownloadList::redraw() {
if (range.second != m_view->end_visible())
++range.second;
int pos = 1;
char buffer[m_canvas->width() + 1];
int pos = 1;
char buffer[m_canvas->width() + 1];
char* last = buffer + m_canvas->width() - 2 + 1;
// Add a proper 'column info' method.
@@ -134,25 +130,38 @@ WindowDownloadList::redraw() {
if (layout_name == "full") {
while (range.first != range.second) {
bool is_focused = range.first == m_view->focus();
char focus_char = is_focused ? '*' : ' ';
ColorKind focus_color = is_focused ? RCOLOR_FOCUS : RCOLOR_LABEL;
auto attr_color = get_attr_color(range.first);
print_download_title(buffer, last, *range.first);
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
m_canvas->print(0, pos, "%c %s", focus_char, buffer);
m_canvas->set_attr(2, pos++, -1, attr_color.first, attr_color.second);
print_download_info_full(buffer, last, *range.first);
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
m_canvas->print(0, pos, "%c %s", focus_char, buffer);
m_canvas->set_attr(2, pos++, -1, focus_color);
print_download_status(buffer, last, *range.first);
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
m_canvas->print(0, pos, "%c %s", focus_char, buffer);
m_canvas->set_attr(2, pos++, -1, focus_color);
range.first++;
}
} else {
while (range.first != range.second) {
char focus_char = range.first == m_view->focus() ? '*' : ' ';
auto attr_color = get_attr_color(range.first);
print_download_info_compact(buffer, last, *range.first);
m_canvas->set_default_attributes(range.first == m_view->focus() ? A_REVERSE : A_NORMAL);
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
m_canvas->print(0, pos, "%c %s", focus_char, buffer);
m_canvas->set_attr(2, pos++, -1, attr_color.first, attr_color.second);
range.first++;
}
}
}
}
} // namespace display
+5 -36
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_DISPLAY_WINDOW_DOWNLOAD_LIST_H
#define RTORRENT_DISPLAY_WINDOW_DOWNLOAD_LIST_H
@@ -47,6 +11,7 @@ namespace display {
class WindowDownloadList : public Window {
public:
typedef core::View::signal_void::iterator signal_void_itr;
typedef std::pair<core::View::iterator, core::View::iterator> ViewRange;
WindowDownloadList();
~WindowDownloadList();
@@ -55,9 +20,13 @@ public:
void set_view(core::View* l);
int page_size(const std::string layout_name);
int page_size();
private:
core::View* m_view;
std::pair<int, int> get_attr_color(core::View::iterator selected);
signal_void_itr m_changed_itr;
};
+4 -37
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <torrent/rate.h>
@@ -59,6 +23,9 @@ WindowDownloadStatusbar::WindowDownloadStatusbar(core::Download* d) :
void
WindowDownloadStatusbar::redraw() {
if (m_canvas->daemon())
return;
m_slotSchedule(this, (cachedTime + rak::timer::from_seconds(1)).round_seconds());
m_canvas->erase();
@@ -91,7 +58,7 @@ WindowDownloadStatusbar::redraw() {
print_download_status(buffer, last, m_download);
m_canvas->print(0, 2, "[%c:%i] %s",
m_download->tracker_list()->has_active() ? 'C' : ' ',
(int)(m_download->download()->tracker_controller()->seconds_to_next_timeout()),
(int)(m_download->download()->tracker_controller().seconds_to_next_timeout()),
buffer);
}
+4 -40
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <locale>
@@ -83,7 +47,7 @@ wstring_width(const std::string& i_str, int width) {
// Limit to width if it's too wide already.
if (swidth == -1 || swidth > width) {
length = swidth = 0;
while (result[length]) {
int next = ::wcwidth(result[length]);
@@ -172,13 +136,13 @@ WindowFileList::redraw() {
} else if (itr.is_entering()) {
m_canvas->print(0, pos, "%*c %ls", 16 + itr.depth(), '\\',
itr.depth() < (*itr)->path()->size() ? wstring_width((*itr)->path()->at(itr.depth()), filenameWidth - itr.depth() - 1).c_str() : L"UNKNOWN");
itr.depth() < itr.file()->path()->size() ? wstring_width(itr.file()->path()->at(itr.depth()), filenameWidth - itr.depth() - 1).c_str() : L"UNKNOWN");
} else if (itr.is_leaving()) {
m_canvas->print(0, pos, "%*c %-*s", 16 + (itr.depth() - 1), '/', filenameWidth - (itr.depth() - 1), "");
} else if (itr.is_file()) {
torrent::File* e = *itr;
torrent::File* e = itr.file();
const char* priority;
@@ -203,7 +167,7 @@ WindowFileList::redraw() {
m_canvas->print(8, pos, "%5.1f T", (double)val / (int64_t(1) << 40));
m_canvas->print(15, pos, "%*c %ls", 1 + itr.depth(), '|',
itr.depth() < (*itr)->path()->size() ? wstring_width((*itr)->path()->at(itr.depth()), filenameWidth - itr.depth() - 1).c_str() : L"UNKNOWN");
itr.depth() < itr.file()->path()->size() ? wstring_width(itr.file()->path()->at(itr.depth()), filenameWidth - itr.depth() - 1).c_str() : L"UNKNOWN");
} else {
m_canvas->print(0, pos, "BORK BORK");
+1 -2
View File
@@ -42,7 +42,6 @@
#include "core/http_queue.h"
#include "canvas.h"
#include "rak/functional.h"
#include "window_http_queue.h"
namespace display {
@@ -145,7 +144,7 @@ WindowHttpQueue::receive_insert(core::CurlGet* h) {
void
WindowHttpQueue::receive_erase(core::CurlGet* h) {
Container::iterator itr = std::find_if(m_container.begin(), m_container.end(), rak::equal(h, std::mem_fun_ref(&Node::get_http)));
Container::iterator itr = std::find_if(m_container.begin(), m_container.end(), [h](Node n) { return h == n.get_http(); });
if (itr == m_container.end())
throw std::logic_error("WindowHttpQueue::receive_erase(...) tried to remove an object we don't have");
+4 -38
View File
@@ -1,44 +1,8 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <ctime>
#include <torrent/torrent.h>
#include <torrent/utils/thread_base.h>
#include <torrent/utils/thread.h>
#include "canvas.h"
#include "utils.h"
@@ -54,7 +18,9 @@ WindowLog::WindowLog(torrent::log_buffer* l) :
unsigned int signal_index = torrent::main_thread()->signal_bitfield()->add_signal(std::bind(&WindowLog::receive_update, this));
m_log->lock_and_set_update_slot(std::bind(&torrent::thread_base::send_event_signal, torrent::main_thread(), signal_index, false));
m_log->lock_and_set_update_slot([signal_index]() {
torrent::main_thread()->send_event_signal(signal_index, false);
});
}
WindowLog::~WindowLog() {
+2 -36
View File
@@ -1,41 +1,6 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include "display/color_map.h"
#include <torrent/rate.h>
#include <torrent/torrent.h>
@@ -66,6 +31,7 @@ WindowStatusbar::redraw() {
position = print_status_extra(buffer, last);
m_canvas->print(m_canvas->width() - (position - buffer), 0, "%s", buffer);
}
m_canvas->set_attr(0, 0, -1, RCOLOR_FOOTER);
m_lastTick = control->tick();
}
+1 -37
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include "canvas.h"
@@ -64,7 +28,7 @@ WindowStringList::redraw() {
if (ypos == (size_t)m_canvas->height()) {
ypos = 0;
xpos += width + 2;
if (xpos + 20 >= (size_t)m_canvas->width())
break;
+1 -2
View File
@@ -37,7 +37,6 @@
#include "config.h"
#include <algorithm>
#include <rak/functional.h>
#include "canvas.h"
#include "utils.h"
@@ -55,7 +54,7 @@ WindowText::WindowText(rpc::target_type target, extent_type margin) :
void
WindowText::clear() {
std::for_each(begin(), end(), rak::call_delete<TextElement>());
std::for_each(begin(), end(), [](TextElement* text) { delete text; });
base_type::clear();
delete m_errorHandler;
+5 -39
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include "canvas.h"
@@ -43,11 +7,13 @@ namespace display {
void
WindowTitle::redraw() {
if (m_canvas->daemon())
return;
m_slotSchedule(this, (cachedTime + rak::timer::from_seconds(1)).round_seconds());
m_canvas->erase();
m_canvas->print(std::max(0, ((int)m_canvas->width() - (int)m_title.size()) / 2 - 4), 0,
"*** %s ***", m_title.c_str());
m_canvas->print(std::max(0, ((int)m_canvas->width() - (int)m_title.size()) / 2 - 4), 0, "*** %s ***", m_title.c_str());
}
}
} // namespace display
+25 -59
View File
@@ -1,47 +1,11 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <rak/algorithm.h>
#include <rak/string_manip.h>
#include <torrent/exceptions.h>
#include <torrent/tracker.h>
#include <torrent/tracker_list.h>
#include <torrent/tracker_controller.h>
#include <torrent/tracker/tracker.h>
#include "core/download.h"
@@ -62,14 +26,14 @@ WindowTrackerList::redraw() {
m_canvas->erase();
unsigned int pos = 0;
torrent::TrackerList* tl = m_download->tracker_list();
torrent::TrackerController* tc = m_download->tracker_controller();
auto tl = m_download->tracker_list();
auto tc = m_download->tracker_controller();
m_canvas->print(2, pos, "Trackers: [Key: %08x] [%s %s %s]",
tl->key(),
tc->is_requesting() ? "req" : " ",
tc->is_promiscuous_mode() ? "prom" : " ",
tc->is_failure_mode() ? "fail" : " ");
tc.is_requesting() ? "req" : " ",
tc.is_promiscuous_mode() ? "prom" : " ",
tc.is_failure_mode() ? "fail" : " ");
++pos;
if (tl->size() == 0 || *m_focus >= tl->size())
@@ -78,39 +42,41 @@ WindowTrackerList::redraw() {
typedef std::pair<unsigned int, unsigned int> Range;
Range range = rak::advance_bidirectional<unsigned int>(0, *m_focus, tl->size(), (m_canvas->height() - 1) / 2);
unsigned int group = tl->at(range.first)->group();
unsigned int group = tl->at(range.first).group();
while (range.first != range.second) {
torrent::Tracker* tracker = tl->at(range.first);
auto tracker = tl->at(range.first);
if (tracker->group() == group)
if (tracker.group() == group)
m_canvas->print(0, pos, "%2i:", group++);
m_canvas->print(4, pos++, "%s",
tracker->url().c_str());
tracker.url().c_str());
if (pos < m_canvas->height()) {
const char* state;
if (tracker->is_busy_not_scrape())
if (tracker.is_busy_not_scrape())
state = "req ";
else if (tracker->is_busy())
else if (tracker.is_busy())
state = "scr ";
else
state = " ";
auto tracker_state = tracker.state();
m_canvas->print(0, pos++, "%s Id: %s Counters: %uf / %us (%u) %s S/L/D: %u/%u/%u (%u/%u)",
state,
rak::copy_escape_html(tracker->tracker_id()).c_str(),
tracker->failed_counter(),
tracker->success_counter(),
tracker->scrape_counter(),
tracker->is_usable() ? " on" : tracker->is_enabled() ? "err" : "off",
tracker->scrape_complete(),
tracker->scrape_incomplete(),
tracker->scrape_downloaded(),
tracker->latest_new_peers(),
tracker->latest_sum_peers());
rak::copy_escape_html(tracker.tracker_id()).c_str(),
tracker_state.failed_counter(),
tracker_state.success_counter(),
tracker_state.scrape_counter(),
tracker.is_usable() ? " on" : tracker.is_enabled() ? "err" : "off",
tracker_state.scrape_complete(),
tracker_state.scrape_incomplete(),
tracker_state.scrape_downloaded(),
tracker_state.latest_new_peers(),
tracker_state.latest_sum_peers());
}
if (range.first == *m_focus) {
@@ -118,7 +84,7 @@ WindowTrackerList::redraw() {
m_canvas->set_attr(4, pos - 1, m_canvas->width(), is_focused() ? A_REVERSE : A_BOLD, COLOR_PAIR(0));
}
if (tracker->is_busy()) {
if (tracker.is_busy()) {
m_canvas->set_attr(0, pos - 2, 4, A_REVERSE, COLOR_PAIR(0));
m_canvas->set_attr(0, pos - 1, 4, A_REVERSE, COLOR_PAIR(0));
}
+1 -1
View File
@@ -64,7 +64,7 @@ Manager::pressed(int key) {
if (m_textInput != NULL)
m_textInput->pressed(key);
else
std::find_if(rbegin(), rend(), std::bind2nd(std::mem_fun(&Bindings::pressed), key));
std::find_if(rbegin(), rend(), [&key](Bindings* bind) { return bind->pressed(key); });
}
}
+7 -4
View File
@@ -38,7 +38,6 @@
#include <functional>
#include <rak/algorithm.h>
#include <rak/functional.h>
#include <rak/path.h>
#include <dirent.h>
@@ -105,7 +104,7 @@ PathInput::receive_do_complete() {
if (r.first == r.second)
return; // Show some nice colors here.
std::string base = rak::make_base<std::string>(r.first, r.second, rak::const_mem_ref(&utils::directory_entry::s_name));
std::string base = rak::make_base<std::string>(r.first, r.second, std::mem_fn(&utils::directory_entry::s_name));
// Clear the path after the cursor to make this code cleaner. It's
// not really nessesary to add the complexity just because someone
@@ -154,8 +153,12 @@ PathInput::range_type
PathInput::find_incomplete(utils::Directory& d, const std::string& f) {
range_type r;
r.first = std::find_if(d.begin(), d.end(), rak::bind2nd(std::ptr_fun(&find_complete_not_compare), f));
r.second = std::find_if(r.first, d.end(), rak::bind2nd(std::ptr_fun(&find_complete_compare), f));
r.first = std::find_if(d.begin(), d.end(), [f](const utils::directory_entry& de) {
return find_complete_not_compare(de, f);
});
r.second = std::find_if(r.first, d.end(), [f](const utils::directory_entry& de) {
return find_complete_compare(de, f);
});
return r;
}
+9 -46
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#define __STDC_FORMAT_MACROS
@@ -50,7 +14,6 @@
#include <torrent/poll.h>
#include <torrent/data/chunk_utils.h>
#include <torrent/utils/log.h>
#include <rak/functional.h>
#include <rak/error_number.h>
#ifdef HAVE_BACKTRACE
@@ -136,7 +99,7 @@ load_session_torrents() {
// Replace with session torrent flag.
f->set_session(true);
f->set_init_load(true);
f->slot_finished(std::bind(&rak::call_delete_func<core::DownloadFactory>, f));
f->slot_finished([f](){ delete f; });
f->load(entries.path() + first->s_name);
f->commit();
}
@@ -151,7 +114,7 @@ load_arg_torrents(char** first, char** last) {
// Replace with session torrent flag.
f->set_start(true);
f->set_init_load(true);
f->slot_finished(std::bind(&rak::call_delete_func<core::DownloadFactory>, f));
f->slot_finished([f](){ delete f; });
f->load(*first);
f->commit();
}
@@ -195,7 +158,7 @@ main(int argc, char** argv) {
torrent::log_initialize();
control = new Control;
unsigned int random_seed = cachedTime.seconds() ^ cachedTime.usec() ^ (getpid() << 16) ^ getppid();
srandom(random_seed);
@@ -219,7 +182,7 @@ main(int argc, char** argv) {
// platforms that do not properly pass signals to the target
// threads. Use '--enable-interrupt-socket' when configuring
// LibTorrent to enable this workaround.
if (torrent::thread_base::should_handle_sigusr1())
if (torrent::utils::Thread::should_handle_sigusr1())
SignalHandler::set_handler(SIGUSR1, std::bind(&do_nothing));
torrent::log_add_group_output(torrent::LOG_NOTICE, "important");
@@ -269,7 +232,7 @@ main(int argc, char** argv) {
"method.insert = event.download.closed,multi|rlookup|static\n"
"method.insert = event.download.resumed,multi|rlookup|static\n"
"method.insert = event.download.paused,multi|rlookup|static\n"
"method.insert = event.download.finished,multi|rlookup|static\n"
"method.insert = event.download.hash_done,multi|rlookup|static\n"
"method.insert = event.download.hash_failed,multi|rlookup|static\n"
@@ -494,7 +457,7 @@ main(int argc, char** argv) {
rpc::commands.call_catch("event.system.startup_done", rpc::make_target(), "startup_done", "System startup_done event action failed: ");
torrent::thread_base::event_loop(torrent::main_thread());
torrent::utils::Thread::event_loop(torrent::main_thread());
control->core()->download_list()->session_save();
control->cleanup();
@@ -525,7 +488,7 @@ main(int argc, char** argv) {
}
void
handle_sigbus(int signum, siginfo_t* sa, void* ptr) {
handle_sigbus(int signum, siginfo_t* sa, [[maybe_unused]] void* ptr) {
if (signum != SIGBUS)
do_panic(signum);
@@ -605,7 +568,7 @@ do_panic(int signum) {
std::stringstream output;
output << "Caught " << SignalHandler::as_string(signum) << ", dumping stack:" << std::endl;
#ifdef HAVE_BACKTRACE
void* stackPtrs[20];
@@ -619,7 +582,7 @@ do_panic(int signum) {
#else
output << "Stack dump not enabled." << std::endl;
#endif
if (signum == SIGBUS)
output << "A bus error probably means you ran out of diskspace." << std::endl;
+1 -1
View File
@@ -88,7 +88,7 @@ bool
OptionParser::has_flag(char flag, int argc, char** argv) {
char options[3] = { '-', flag, '\0' };
return std::find_if(argv, argv + argc, std::not1(std::bind1st(std::ptr_fun(&std::strcmp), options))) != argv + argc;
return std::find_if(argv, argv + argc, [&options](char* c) { return std::strcmp(c, options) == 0; }) != argv + argc;
}
std::string
+1 -37
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include "core/download.h"
@@ -45,7 +9,7 @@
template const torrent::Object func_name<target_type>(command_base* rawCommand, target_type target, const torrent::Object& args); \
template const torrent::Object func_name<core::Download*>(command_base* rawCommand, target_type target, const torrent::Object& args); \
template const torrent::Object func_name<torrent::Peer*>(command_base* rawCommand, target_type target, const torrent::Object& args); \
template const torrent::Object func_name<torrent::Tracker*>(command_base* rawCommand, target_type target, const torrent::Object& args); \
template const torrent::Object func_name<torrent::tracker::Tracker*>(command_base* rawCommand, target_type target, const torrent::Object& args); \
template const torrent::Object func_name<torrent::File*>(command_base* rawCommand, target_type target, const torrent::Object& args); \
template const torrent::Object func_name<torrent::FileListIterator*>(command_base* rawCommand, target_type target, const torrent::Object& args);
+8 -14
View File
@@ -3,6 +3,7 @@
#include <functional>
#include <limits>
#include <torrent/common.h>
#include <torrent/object.h>
#include <torrent/data/file_list_iterator.h>
@@ -11,13 +12,6 @@ namespace core {
class Download;
}
namespace torrent {
class File;
class FileListIterator;
class Peer;
class Tracker;
}
namespace rpc {
template <typename Target>
@@ -89,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&);
@@ -138,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;
}
@@ -190,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); }
@@ -213,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; };
@@ -230,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);
+1 -1
View File
@@ -20,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; };
+6 -7
View File
@@ -48,8 +48,7 @@
#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 {
@@ -64,8 +63,8 @@ CommandMap::insert(const key_type& key, int flags, const char* parm, const char*
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))
rpc::xmlrpc.insert_command(key.c_str(), 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)));
}
@@ -102,11 +101,11 @@ CommandMap::create_redirect(const key_type& key_new, const key_type& key_dest, i
dest_itr->second.m_flags |= flag_has_redirects;
flags |= dest_itr->second.m_flags & ~(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.c_str(), 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,
+3 -39
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_RPC_COMMAND_MAP_H
#define RTORRENT_RPC_COMMAND_MAP_H
@@ -59,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;
@@ -86,7 +50,7 @@ public:
using base_type::find;
static const int flag_dont_delete = 0x1;
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;
@@ -124,7 +88,7 @@ public:
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, const mapped_type& arg) { return call_command(key, arg, target_type((int)command_base::target_tracker, tracker)); }
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:
+2 -3
View File
@@ -39,7 +39,6 @@
#include <algorithm>
#include <cstdlib>
#include <time.h>
#include <rak/functional.h>
#include <rak/string_manip.h>
#include <torrent/exceptions.h>
@@ -50,12 +49,12 @@
namespace rpc {
CommandScheduler::~CommandScheduler() {
std::for_each(begin(), end(), rak::call_delete<CommandSchedulerItem>());
std::for_each(begin(), end(), [](CommandSchedulerItem* item) { delete item; });
}
CommandScheduler::iterator
CommandScheduler::find(const std::string& key) {
return std::find_if(begin(), end(), rak::equal(key, std::mem_fun(&CommandSchedulerItem::key)));
return std::find_if(begin(), end(), [key](CommandSchedulerItem* item) { return key == item->key(); });
}
CommandScheduler::iterator
+244
View File
@@ -0,0 +1,244 @@
#include "config.h"
#include "rpc/jsonrpc.h"
#include <cstdint>
#include <string>
#include <torrent/common.h>
#include <torrent/torrent.h>
#include "thread_base.h"
#include "rpc/rpc_manager.h"
#include "rpc/command.h"
#include "rpc/command_map.h"
#include "rpc/nlohmann/json.h"
#include "rpc/parse_commands.h"
#include "torrent/exceptions.h"
#include "torrent/object.h"
#include "utils/functional.h"
namespace rpc {
// Taken from https://www.jsonrpc.org/specification
constexpr int JSONRPC_PARSE_ERROR = -32700;
constexpr int JSONRPC_INVALID_REQUEST_ERROR = -32600;
constexpr int JSONRPC_METHOD_NOT_FOUND_ERROR = -32601;
constexpr int JSONRPC_INVALID_PARAMS_ERROR = -32602;
constexpr int JSONRPC_INTERNAL_ERROR = -32000;
using json = nlohmann::json;
torrent::Object
json_to_object(const json& value) {
switch (value.type()) {
case json::value_t::number_unsigned:
case json::value_t::number_integer:
return torrent::Object(value.get<int64_t>());
case json::value_t::boolean:
return value.get<bool>() ? torrent::Object(int64_t(1)) : torrent::Object(int64_t(0));
case json::value_t::string:
return torrent::Object(value.get<std::string>());
case json::value_t::array: {
auto array_raw = torrent::Object::create_list();
auto& array = array_raw.as_list();
for (const auto& entry : value) {
array.push_back(json_to_object(entry));
}
return array_raw;
}
case json::value_t::object: {
auto map_raw = torrent::Object::create_map();
auto& map = map_raw.as_map();
for (const auto& entry : value.items()) {
map[entry.key()] = json_to_object(entry.value());
}
return map_raw;
}
case json::value_t::number_float:
// type_name() for floats returns 'number', which is accurate for JSON but misleading
throw torrent::input_error("invalid parameters: unexpected data type float");
default:
throw torrent::input_error("invalid parameters: unexpected data type " + std::string(value.type_name()));
}
}
json
object_to_json(const torrent::Object& object) noexcept {
switch (object.type()) {
case torrent::Object::TYPE_VALUE:
return object.as_value();
case torrent::Object::TYPE_STRING:
return object.as_string();
case torrent::Object::TYPE_LIST: {
json result = json::array();
std::transform(object.as_list().cbegin(), object.as_list().cend(), std::back_inserter(result), [](const torrent::Object& element) {
return object_to_json(element);
});
return result;
}
case torrent::Object::TYPE_MAP: {
json result = json::object();
for (const auto& entry : object.as_map()) {
result.emplace(entry.first, object_to_json(entry.second));
}
return result;
}
case torrent::Object::TYPE_DICT_KEY: {
json result = json::array();
result.push_back(object_to_json(object.as_dict_key()));
const auto& dict_obj = object.as_dict_obj();
if (dict_obj.is_list()) {
std::transform(dict_obj.as_list().cbegin(), dict_obj.as_list().cend(), std::back_inserter(result), [](const torrent::Object& element) {
return object_to_json(element);
});
} else {
result.push_back(object_to_json(dict_obj));
}
return result;
}
default:
return 0;
}
}
json
jsonrpc_call_command(const std::string& method, const json& params) {
if (params.type() == json::value_t::object) {
// Named parameters is valid JSON-RPC, rtorrent just doesn't support it
throw rpc_error(JSONRPC_INVALID_PARAMS_ERROR, "invalid parameter: procedure named parameter not supported");
} else if (params.type() != json::value_t::array) {
throw rpc_error(JSONRPC_INVALID_REQUEST_ERROR, "invalid request: params field must be an array");
}
CommandMap::iterator itr = commands.find(method.c_str());
if (itr == commands.end()) {
throw rpc_error(JSONRPC_METHOD_NOT_FOUND_ERROR, "method not found: " + method);
}
torrent::Object params_object = json_to_object(params);
auto& params_object_list = params_object.as_list();
rpc::target_type target = rpc::make_target();
std::function<void()> deleter = []() {};
utils::scope_guard guard([&deleter]() { deleter(); });
if (!(itr->second.m_flags & CommandMap::flag_no_target)) {
// Provide a blank target if none was provided
if (params_object_list.empty())
params_object_list.push_back("");
if (!params_object_list.begin()->is_string())
throw torrent::input_error("invalid parameters: target must be a string");
RpcManager::object_to_target(params_object_list.begin()->as_string(), itr->second.m_flags, &target, &deleter);
params_object_list.erase(params_object_list.begin());
}
const auto& result = rpc::commands.call_command(itr, params_object, target);
return object_to_json(result);
}
json
json_error(int code, const std::string& msg, json id) {
return json{{"jsonrpc", "2.0"}, {"id", id}, {"error", {{"code", code}, {"message", msg}}}};
}
json
handle_request(const json& request) {
json response = {{"jsonrpc", "2.0"}, {"id", nullptr}};
try {
if (!request["id"].is_number() && !request["id"].is_string() && !request["id"].is_null())
return json_error(JSONRPC_INVALID_REQUEST_ERROR, "request id is invalid type " + std::string(request["id"].type_name()), response["id"]);
response["id"] = request["id"];
if (!request.contains("method") || !request["method"].is_string())
return json_error(JSONRPC_INVALID_REQUEST_ERROR, "method string not present", response["id"]);
if (request.contains("params"))
response["result"] = jsonrpc_call_command(request["method"], request["params"]);
else
response["result"] = jsonrpc_call_command(request["method"], json::array({""}));
return response;
} catch (rpc_error& e) {
return json_error(e.type(), e.what(), response["id"]);
} catch (torrent::input_error& e) {
return json_error(JSONRPC_INVALID_PARAMS_ERROR, e.what(), response["id"]);
} catch (torrent::local_error& e) {
return json_error(JSONRPC_INTERNAL_ERROR, e.what(), response["id"]);
}
}
// Notifications are basically the same as requests, except we can
// just drop the message on the floor if there are any errors
void
handle_notification(const json& request) noexcept {
if (!request.contains("method") || !request["method"].is_string())
return;
try {
if (request.contains("params"))
jsonrpc_call_command(request["method"], request["params"]);
else
jsonrpc_call_command(request["method"], json::array({""}));
} catch (std::exception& e) {
}
}
bool
JsonRpc::process(const char* in_buffer, uint32_t length, slot_write callback) {
json response;
json body;
try {
body = json::parse(in_buffer, in_buffer + length);
switch (body.type()) {
case json::value_t::object: {
if (!body.contains("id")) {
handle_notification(body);
return callback("", 0);
} else {
response = handle_request(body);
}
break;
}
case json::value_t::array: {
// Empty batch requests are invalid as per the spec
if (body.empty()) {
response = json_error(JSONRPC_INVALID_REQUEST_ERROR, "invalid request: empty batch", nullptr);
break;
}
response = json::array();
for (const auto& sub_body : body) {
if (!sub_body.contains("id"))
handle_notification(sub_body);
else
response.push_back(handle_request(sub_body));
}
// This indicates the batch was composed entirely of
// notifications, in which case nothing is returned
if (response.empty())
return callback("", 0);
break;
}
default:
response = json_error(JSONRPC_PARSE_ERROR, "message type " + std::string(body.type_name()) + " unsupported", nullptr);
}
std::string response_str = response.dump();
return callback(response_str.c_str(), response_str.size());
} catch (json::parse_error& e) {
auto err_str = json_error(JSONRPC_PARSE_ERROR, e.what(), nullptr).dump(-1, ' ', false, json::error_handler_t::replace);
return callback(err_str.c_str(), err_str.size());
} catch (json::type_error& e) {
// Type errors may be caused by invalid UTF-8 strings in exception strings, hence the ::replace
auto err_str = json_error(JSONRPC_PARSE_ERROR, e.what(), nullptr).dump(-1, ' ', false, json::error_handler_t::replace);
return callback(err_str.c_str(), err_str.size());
}
}
} // namespace rpc
+24
View File
@@ -0,0 +1,24 @@
#ifndef RTORRENT_RPC_JSONRPC_H
#define RTORRENT_RPC_JSONRPC_H
#include <functional>
#include <cstdint>
namespace rpc {
class JsonRpc {
public:
using slot_write = std::function<bool(const char*, uint32_t)>;
void initialize() {};
void cleanup() {};
bool process(const char* in_buffer, uint32_t length, slot_write callback);
void insert_command(const char* name, const char* parm, const char* doc) {};
};
} // namespace rpc
#endif
+399
View File
@@ -0,0 +1,399 @@
#include "config.h"
#include <fstream>
#include <string>
#include <sys/stat.h>
#include <unistd.h>
#include "rpc/lua.h"
#ifdef HAVE_LUA
#include <lua.hpp>
#endif
#include <rak/error_number.h>
#include <rak/path.h>
#include <rak/string_manip.h>
#include <torrent/object.h>
#include "core/download.h"
#include "rpc/command.h"
#include "rpc/command_map.h"
#include "rpc/parse_commands.h"
#include "rpc/xmlrpc.h"
namespace rpc {
const int LuaEngine::flag_string;
const std::string LuaEngine::module_name = "rtorrent";
#ifdef HAVE_LUA
LuaEngine::LuaEngine() {
m_luaState = luaL_newstate();
luaL_openlibs(m_luaState);
set_package_preload();
}
LuaEngine::~LuaEngine() { lua_close(m_luaState); }
void
LuaEngine::set_package_preload() {
auto l_state = m_luaState;
lua_getglobal(l_state, "package");
lua_getfield(l_state, -1, "preload");
lua_pushcfunction(l_state, LuaEngine::lua_init_module);
lua_setfield(l_state, -2, LuaEngine::module_name.c_str());
lua_pop(l_state, 2);
}
void
check_lua_status(lua_State* l_state, int status) {
if (status != LUA_OK) {
throw torrent::input_error(lua_tostring(l_state, -1));
}
}
std::string
LuaEngine::search_lua_path(lua_State* l_state) {
// Get package.path
lua_getglobal(l_state, "package");
lua_getfield(l_state, -1, "path");
std::string lua_path(lua_tostring(l_state, -1));
lua_pop(l_state, 2);
// Use lambda here to ensure file closes as soon as it goes out of scope
auto file_exists = [](const std::string& path) -> bool {
std::ifstream file(path);
return file.is_open();
};
// Tokenize path using ';' as delimiter
size_t pos = 0, end;
while ((end = lua_path.find(';', pos)) != std::string::npos) {
std::string file_path(lua_path.substr(pos, end - pos));
size_t ppos = 0;
while ((ppos = file_path.find('?')) != std::string::npos) {
file_path.replace(ppos, 1, LuaEngine::module_name);
}
if (file_exists(file_path)) {
return file_path;
}
}
return "";
}
int
LuaEngine::lua_rtorrent_call(lua_State* l_state) {
auto method = lua_tostring(l_state, 1);
lua_remove(l_state, 1);
torrent::Object object;
rpc::target_type target = rpc::make_target();
;
rpc::CommandMap::iterator itr = rpc::commands.find(std::string(method).c_str());
if (itr == rpc::commands.end()) {
throw torrent::input_error("method not found: " + std::string(method));
}
object = lua_callstack_to_object(l_state, itr->second.m_flags, &target);
try {
const auto& result = rpc::commands.call_command(itr, object, target);
object_to_lua(l_state, result);
return 1;
} catch (torrent::base_error& e) {
throw luaL_error(l_state, e.what());
}
}
int
LuaEngine::lua_init_module(lua_State* l_state) {
// Should this throw if it fails to find the file?
auto lua_file = search_lua_path(l_state);
if (!lua_file.empty()) {
check_lua_status(l_state, luaL_loadfile(l_state, lua_file.c_str()));
}
lua_createtable(l_state, 0, 1);
// Assign functions
lua_pushliteral(l_state, "call");
lua_pushcfunction(l_state, LuaEngine::lua_rtorrent_call);
lua_settable(l_state, -3);
if (!lua_file.empty()) {
check_lua_status(l_state, lua_pcall(l_state, 1, 1, 0));
}
return 1;
}
void
object_to_target(const torrent::Object& obj, int call_flags, rpc::target_type* target) {
if (!obj.is_string()) {
throw torrent::input_error("invalid parameters: target must be a string");
}
std::string target_string = obj.as_string();
bool require_index = (call_flags & (CommandMap::flag_tracker_target | CommandMap::flag_file_target));
if (target_string.empty() && !require_index) {
return;
}
// Length of SHA1 hash is 40
if (target_string.size() < 40) {
throw torrent::input_error("invalid parameters: invalid target");
}
char type = 'd';
std::string hash;
std::string index;
const auto& delim_pos = target_string.find_first_of(':', 40);
if (delim_pos == target_string.npos || delim_pos + 2 >= target_string.size()) {
if (require_index) {
throw torrent::input_error("invalid parameters: no index");
}
hash = target_string;
} else {
hash = target_string.substr(0, delim_pos);
type = target_string[delim_pos + 1];
index = target_string.substr(delim_pos + 2);
}
core::Download* download = rpc.slot_find_download()(hash.c_str());
if (download == nullptr)
throw torrent::input_error("invalid parameters: info-hash not found");
try {
switch (type) {
case 'd':
*target = rpc::make_target(download);
break;
case 'f':
*target = rpc::make_target(command_base::target_file, rpc.slot_find_file()(download, std::stoi(std::string(index))));
break;
case 't':
*target =
rpc::make_target(command_base::target_tracker, rpc.slot_find_tracker()(download, std::stoi(std::string(index))));
break;
case 'p': {
if (index.size() < 40) {
throw torrent::input_error("Not a hash string.");
}
torrent::HashString hash;
torrent::hash_string_from_hex_c_str(index.c_str(), hash);
*target = rpc::make_target(command_base::target_peer, rpc.slot_find_peer()(download, hash));
break;
}
default:
throw torrent::input_error("invalid parameters: unexpected target type");
}
} catch (const std::logic_error&) {
throw torrent::input_error("invalid parameters: invalid index");
}
}
void
object_to_lua(lua_State* l_state, torrent::Object const& object) {
// Converts an object to a single Lua stack object
switch (object.type()) {
case torrent::Object::TYPE_VALUE:
lua_pushnumber(l_state, static_cast<double>(object.as_value()));
break;
case torrent::Object::TYPE_NONE:
lua_pushnil(l_state);
break;
case torrent::Object::TYPE_STRING:
lua_pushstring(l_state, object.as_string().c_str());
break;
case torrent::Object::TYPE_LIST: {
int index = 1;
auto object_list = object.as_list();
lua_createtable(l_state, static_cast<int>(object_list.size()), 0);
int table_idx = lua_gettop(l_state);
for (const auto& itr : object_list) {
object_to_lua(l_state, itr);
lua_rawseti(l_state, table_idx, lua_Integer(index++));
}
break;
}
case torrent::Object::TYPE_MAP: {
auto object_map = object.as_map();
lua_createtable(l_state, 0, static_cast<int>(object_map.size()));
int table_idx = lua_gettop(l_state);
for (const auto& itr : object_map) {
object_to_lua(l_state, itr.second);
lua_pushlstring(l_state, itr.first.c_str(), itr.first.size());
lua_rawset(l_state, table_idx);
}
break;
}
default:
lua_pushnumber(l_state, lua_Number(object.type()));
break;
}
}
torrent::Object
lua_to_object(lua_State* l_state) {
switch (lua_type(l_state, -1)) {
case LUA_TNUMBER:
return torrent::Object(lua_tonumber(l_state, -1));
case LUA_TSTRING:
return torrent::Object(lua_tostring(l_state, -1));
case LUA_TBOOLEAN:
return torrent::Object(lua_toboolean(l_state, -1));
case LUA_TNIL:
return torrent::Object((torrent::Object::value_type)0);
case LUA_TTABLE: {
lua_pushnil(l_state);
int status = lua_next(l_state, -2);
if (status == 0)
return torrent::Object::create_map();
// If the table starts at 1, assume it's an array
if (lua_isnumber(l_state, -2) && (lua_tonumber(l_state, -2) == 1)) {
torrent::Object list = torrent::Object::create_list();
list.insert_back(lua_to_object(l_state));
lua_pop(l_state, 1);
while (lua_next(l_state, -2) != 0) {
list.insert_back(lua_to_object(l_state));
lua_pop(l_state, 1);
}
return list;
} else {
torrent::Object map = torrent::Object::create_map();
// Reset the stack and start from the first element
lua_pop(l_state, 2);
lua_pushnil(l_state);
while (lua_next(l_state, -2) != 0) {
std::string key;
switch (lua_type(l_state, -2)) {
case LUA_TSTRING:
key = lua_tostring(l_state, -2);
break;
default:
// Bencode dictionaries require string keys, but naively
// calling lua_tostring will auto-convert any other object
// (particularly numbers) to strings in-place, which would
// throw off lua_next, so we copy the value and only then
// get the string.
// https://www.lua.org/manual/5.3/manual.html#lua_tolstring
lua_pushvalue(l_state, -2);
key = lua_tostring(l_state, -1);
lua_pop(l_state, 1);
break;
}
map.insert_key(key, lua_to_object(l_state));
lua_pop(l_state, 1);
}
return map;
}
return torrent::Object(lua_tostring(l_state, -1));
}
default:
std::string result = lua_tostring(l_state, -1);
lua_pop(l_state, 1);
return torrent::Object(result);
}
}
torrent::Object
lua_callstack_to_object(lua_State* l_state, int command_flags, rpc::target_type* target) {
torrent::Object object;
if (lua_gettop(l_state) == 0) {
return torrent::Object();
}
if (!lua_isstring(l_state, 1)) {
throw torrent::input_error("invalid parameters: target must be a string");
}
object_to_target(torrent::Object(lua_tostring(l_state, 1)), command_flags, target);
// start from the second argument since the first is the target
lua_remove(l_state, 1);
if (lua_gettop(l_state) == 0) {
return torrent::Object();
} else {
torrent::Object result = torrent::Object::create_list();
torrent::Object::list_type& list_ref = result.as_list();
while (lua_gettop(l_state) != 0) {
list_ref.insert(list_ref.begin(), lua_to_object(l_state));
lua_remove(l_state, -1);
}
return result;
}
return object;
}
int
lua_rtorrent_call(lua_State* l_state) {
torrent::Object object;
rpc::target_type target = rpc::make_target();
auto method = lua_tostring(l_state, 1);
lua_remove(l_state, 1);
rpc::CommandMap::iterator itr = rpc::commands.find(method);
if (itr == rpc::commands.end()) {
throw torrent::input_error("method not found: " + std::string(method));
}
object = lua_callstack_to_object(l_state, itr->second.m_flags, &target);
try {
const auto& result = rpc::commands.call_command(itr, object, target);
object_to_lua(l_state, result);
return 1;
} catch (torrent::base_error& e) {
throw luaL_error(l_state, e.what());
}
}
torrent::Object
execute_lua(LuaEngine* engine, rpc::target_type target_type, torrent::Object const& raw_args, int flags) {
size_t lua_argc = 1; // Target is always present, even if empty
lua_State* l_state = engine->state();
std::string target_string;
switch (target_type.first) {
case (command_base::target_download):
core::Download* dl_target = (core::Download*)target_type.second;
torrent::HashString infohash = dl_target->info()->hash();
target_string = rak::transform_hex_str(infohash);
break;
}
switch (raw_args.type()) {
case torrent::Object::TYPE_LIST: {
const torrent::Object::list_type& args = raw_args.as_list();
if (flags & LuaEngine::flag_string) {
check_lua_status(l_state, luaL_loadstring(l_state, args.begin()->as_string().c_str()));
} else {
check_lua_status(l_state, luaL_loadfile(l_state, args.begin()->as_string().c_str()));
}
object_to_lua(l_state, target_string);
for (torrent::Object::list_const_iterator itr = std::next(args.begin()), last = args.end(); itr != last; itr++) {
object_to_lua(l_state, *itr);
}
lua_argc += args.size() - 1;
break;
}
case torrent::Object::TYPE_STRING: {
const torrent::Object::string_type& target = raw_args.as_string();
if (flags & LuaEngine::flag_string) {
check_lua_status(l_state, luaL_loadstring(l_state, target.c_str()));
} else {
check_lua_status(l_state, luaL_loadfile(l_state, target.c_str()));
}
object_to_lua(l_state, target_string);
break;
}
default:
throw torrent::input_error("execute_lua(...): cannot call lua with arg type " + std::to_string(raw_args.type()));
}
check_lua_status(l_state, lua_pcall(l_state, lua_argc, LUA_MULTRET, 0));
return lua_to_object(l_state);
}
#else
torrent::Object
execute_lua(LuaEngine* engine, torrent::Object const& rawArgs, int flags) {
throw torrent::input_error("Lua support not enabled");
return torrent::Object();
}
LuaEngine::LuaEngine() {}
LuaEngine::~LuaEngine() {}
#endif
} // namespace rpc
+45
View File
@@ -0,0 +1,45 @@
#ifndef RTORRENT_LUA_H
#define RTORRENT_LUA_H
#include "rpc/command.h"
#include <torrent/object.h>
#ifdef HAVE_LUA
#include <lua.hpp>
#endif
namespace rpc {
class LuaEngine {
public:
static const int flag_string = 0x1;
static const std::string module_name;
LuaEngine();
~LuaEngine();
#ifdef HAVE_LUA
// lua_CFunctions
static int lua_init_module(lua_State* l_state);
static int lua_rtorrent_call(lua_State* l_state);
void set_package_preload();
lua_State* state() { return m_luaState; }
private:
static std::string search_lua_path(lua_State* l_state);
lua_State* m_luaState;
#endif
};
torrent::Object execute_lua(LuaEngine* engine, rpc::target_type target, const torrent::Object& raw_args, int flags);
#ifdef HAVE_LUA
int rtorrent_call(lua_State* l_state);
void init_rtorrent_module(lua_State* l_state);
void object_to_lua(lua_State* l_state, torrent::Object const& object);
void check_lua_status(lua_State* l_state, int status);
torrent::Object lua_to_object(lua_State* l_state);
torrent::Object lua_callstack_to_object(lua_State* l_state, int command_flags, rpc::target_type* target);
#endif
} // namespace rpc
#endif
+2
View File
@@ -0,0 +1,2 @@
# third-party library, disable all checks in this folder.
Checks: '-*'
File diff suppressed because it is too large Load Diff
+3 -6
View File
@@ -38,7 +38,6 @@
#include "object_storage.h"
#include "rak/functional.h"
#include "parse.h"
#include "parse_commands.h"
@@ -223,8 +222,7 @@ object_storage::erase_multi_key(const torrent::raw_string& key, const std::strin
if (r_itr == m_rlookup.end())
return;
rlookup_mapped_iterator rm_itr = std::find_if(r_itr->second.begin(), r_itr->second.end(),
rak::equal(key, rak::mem_ptr(&value_type::first)));
rlookup_mapped_iterator rm_itr = std::find_if(r_itr->second.begin(), r_itr->second.end(), [key](value_type* type) { return key == type->first; });
if (rm_itr != r_itr->second.end())
r_itr->second.erase(rm_itr);
@@ -243,8 +241,7 @@ object_storage::set_multi_key_obj(const torrent::raw_string& key, const std::str
if (r_itr == m_rlookup.end())
r_itr = m_rlookup.insert(std::make_pair(cmd_key, rlookup_type::mapped_type())).first;
if (std::find_if(r_itr->second.begin(), r_itr->second.end(),
rak::equal(key, rak::mem_ptr(&value_type::first))) == r_itr->second.end())
if (std::find_if(r_itr->second.begin(), r_itr->second.end(), [key](value_type* type) { return key == type->first; }) == r_itr->second.end())
r_itr->second.push_back(&*itr);
}
@@ -259,7 +256,7 @@ object_storage::rlookup_list(const std::string& cmd_key) {
if (r_itr != m_rlookup.end())
std::transform(r_itr->second.begin(), r_itr->second.end(), std::back_inserter(result),
std::bind(&key_type::c_str, std::bind(rak::mem_ptr(&value_type::first), std::placeholders::_1)));
std::bind(&key_type::c_str, std::bind(std::mem_fn(&value_type::first), std::placeholders::_1)));
return result;
}
+12 -19
View File
@@ -39,30 +39,23 @@
#include <algorithm>
#include <fstream>
#include <string>
#include <rak/functional.h>
#include <functional>
#include <rak/path.h>
#include <torrent/exceptions.h>
#include "parse.h"
#include "parse_commands.h"
#include "rpc/rpc_manager.h"
namespace rpc {
CommandMap commands;
XmlRpc xmlrpc;
ExecFile execFile;
inline bool command_map_is_space(char c) {
return c == ' ' || c == '\t';
}
struct command_map_is_space : std::unary_function<char, bool> {
bool operator () (char c) const {
return c == ' ' || c == '\t';
}
};
struct command_map_is_newline : std::unary_function<char, bool> {
bool operator () (char c) const {
return c == '\n' || c == '\0' || c == ';';
}
};
inline bool command_map_is_newline(char c) {
return c == '\n' || c == '\0' || c == ';';
}
// Only escape eol on odd number of escape characters. We know that
// there can't be any characters in between, so this should work for
@@ -131,7 +124,7 @@ parse_command_name(const char* first, const char* last, char* dest_first, char*
// the code below for both cases.
parse_command_type
parse_command(target_type target, const char* first, const char* last) {
first = std::find_if(first, last, std::not1(command_map_is_space()));
first = std::find_if(first, last, [&](char c) { return !command_map_is_space(c); });
if (first == last || *first == '#')
return std::make_pair(torrent::Object(), first);
@@ -139,7 +132,7 @@ parse_command(target_type target, const char* first, const char* last) {
char key[128];
first = parse_command_name(first, last, key, key + 128);
first = std::find_if(first, last, std::not1(command_map_is_space()));
first = std::find_if(first, last, [&](char c) { return !command_map_is_space(c); });
if (first == last || *first != '=')
throw torrent::input_error("Could not find '=' in command '" + std::string(key) + "'.");
@@ -150,10 +143,10 @@ parse_command(target_type target, const char* first, const char* last) {
// Find the last character that is part of this command, skipping
// the whitespace at the end. This ensures us that the caller
// doesn't need to do this nor check for junk at the end.
first = std::find_if(first, last, std::not1(command_map_is_space()));
first = std::find_if(first, last, [&](char c) { return !command_map_is_space(c); });
if (first != last) {
if (*first != '\n' && *first != ';' && *first != '\0')
if (!command_map_is_newline(*first))
throw torrent::input_error("Junk at end of input.");
first++;
+1 -7
View File
@@ -40,9 +40,8 @@
#include <string>
#include <cstring>
#include "command_map.h"
#include "exec_file.h"
#include "xmlrpc.h"
#include "rpc_manager.h"
namespace core {
class Download;
@@ -50,11 +49,6 @@ namespace core {
namespace rpc {
// Move to another file?
extern CommandMap commands;
extern XmlRpc xmlrpc;
extern ExecFile execFile;
typedef std::pair<torrent::Object, const char*> parse_command_type;
// The generic parse command function, used by the rest. At some point
+166
View File
@@ -0,0 +1,166 @@
#include "config.h"
#include <cstring>
#include <torrent/exceptions.h>
#include "parse_commands.h"
#include "rpc/rpc_manager.h"
namespace rpc {
CommandMap commands;
RpcManager rpc;
ExecFile execFile;
void
RpcManager::object_to_target(const torrent::Object& obj, int call_flags, rpc::target_type* target, std::function<void()>* deleter) {
if (call_flags & CommandMap::flag_no_target)
return;
if (!obj.is_string()) {
throw torrent::input_error("invalid parameters: target must be a string");
}
std::string target_string = obj.as_string();
bool require_index = (call_flags & (CommandMap::flag_tracker_target | CommandMap::flag_file_target));
if (target_string.size() == 0 && !require_index) {
return;
}
// Length of SHA1 hash is 40
if (target_string.size() < 40) {
throw torrent::input_error("invalid parameters: invalid target");
}
char type = 'd';
std::string hash;
std::string index;
const auto& delim_pos = target_string.find_first_of(':', 40);
if (delim_pos == target_string.npos ||
delim_pos + 2 >= target_string.size()) {
if (require_index) {
throw torrent::input_error("invalid parameters: no index");
}
hash = target_string;
} else {
hash = target_string.substr(0, delim_pos);
type = target_string[delim_pos + 1];
index = target_string.substr(delim_pos + 2);
}
core::Download* download = rpc.slot_find_download()(hash.c_str());
if (download == nullptr)
throw torrent::input_error("invalid parameters: info-hash not found");
try {
torrent::tracker::Tracker* tracker;
switch (type) {
case 'd':
*target = rpc::make_target(download);
break;
case 'f':
*target = rpc::make_target(command_base::target_file,
rpc.slot_find_file()(download, std::stoi(std::string(index))));
break;
case 't':
tracker = new torrent::tracker::Tracker(rpc.slot_find_tracker()(download, std::stoi(std::string(index))));
*target = rpc::make_target(command_base::target_tracker, tracker);
*deleter = [tracker]() { delete tracker; };
break;
case 'p': {
if (index.size() < 40) {
throw torrent::input_error("invalid parameters: not a hash string.");
}
torrent::HashString hash;
torrent::hash_string_from_hex_c_str(index.c_str(), hash);
*target = rpc::make_target(command_base::target_peer,
rpc.slot_find_peer()(download, hash));
break;
}
default:
throw torrent::input_error("invalid parameters: unexpected target type");
}
} catch (const std::logic_error&) {
throw torrent::input_error("invalid parameters: invalid index");
}
}
bool
RpcManager::process(RPCType type, const char* in_buffer, uint32_t length, slot_response_callback callback) {
switch (type) {
case RPCType::XML: {
if (m_xmlrpc.is_valid() && rpc::call_command_value("network.rpc.use_xmlrpc")) {
return m_xmlrpc.process(in_buffer, length, callback);
} else {
const std::string response = "<?xml version=\"1.0\"?><methodResponse><fault><struct><member><name>faultCode</name><value><i8>-501</i8></value></member><member><name>faultString</name><value><string>XML-RPC not supported</string></value></member></struct></fault></methodResponse>";
return callback(response.c_str(), response.size());
}
}
case RPCType::JSON: {
if (rpc::call_command_value("network.rpc.use_jsonrpc")) {
return m_jsonrpc.process(in_buffer, length, callback);
} else {
const std::string response = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32601,\"message\":\"JSON-RPC not supported\"},\"id\":null}";
return callback(response.c_str(), response.size());
}
}
}
}
void
RpcManager::initialize() {
m_xmlrpc.initialize();
m_jsonrpc.initialize();
m_initialized = true;
}
void
RpcManager::cleanup() {
m_xmlrpc.cleanup();
m_jsonrpc.cleanup();
}
bool
RpcManager::is_type_enabled(RPCType type) const {
switch (type) {
case RPCType::XML:
return m_is_xmlrpc_enabled;
case RPCType::JSON:
return m_is_jsonrpc_enabled;
}
}
void
RpcManager::set_type_enabled(RPCType type, bool enabled) {
switch (type) {
case RPCType::XML:
m_is_xmlrpc_enabled = enabled;
case RPCType::JSON:
m_is_jsonrpc_enabled = enabled;
}
}
bool
RpcManager::is_initialized() const {
return m_initialized;
}
void
RpcManager::insert_command(const char* name, const char* parm, const char* doc) {
m_xmlrpc.insert_command(name, parm, doc);
m_jsonrpc.insert_command(name, parm, doc);
}
} // namespace rpc
+92
View File
@@ -0,0 +1,92 @@
#ifndef RTORRENT_RPC_MANAGER_H
#define RTORRENT_RPC_MANAGER_H
#include <cstdint>
#include <functional>
#include <torrent/common.h>
#include "rpc/command.h"
#include "rpc/command_map.h"
#include "rpc/exec_file.h"
#include "rpc/jsonrpc.h"
#include "rpc/xmlrpc.h"
namespace core {
class Download;
}
namespace rpc {
extern ExecFile execFile;
extern CommandMap commands;
class rpc_error : public torrent::base_error {
public:
rpc_error(int type, std::string msg) :
m_type(type), m_msg(msg) {}
virtual ~rpc_error() throw() {}
virtual int type() const throw() { return m_type; }
virtual const char* what() const throw() { return m_msg.c_str(); }
private:
int m_type;
std::string m_msg;
};
class RpcManager {
public:
using slot_download = std::function<core::Download*(const char*)>;
using slot_file = std::function<torrent::File*(core::Download*, uint32_t)>;
using slot_tracker = std::function<torrent::tracker::Tracker(core::Download*, uint32_t)>;
using slot_peer = std::function<torrent::Peer*(core::Download*, const torrent::HashString&)>;
using slot_response_callback = std::function<bool(const char*, uint32_t)>;
enum RPCType { XML,
JSON };
RpcManager() = default;
~RpcManager() = default;
void initialize();
void cleanup();
bool is_initialized() const;
int64_t size_limit() { return m_xmlrpc.size_limit(); };
void set_size_limit(uint64_t size) { m_xmlrpc.set_size_limit(size); };
int dialect() { return m_xmlrpc.dialect(); }
void set_dialect(int dialect) { m_xmlrpc.set_dialect(dialect); }
bool is_type_enabled(RPCType type) const;
void set_type_enabled(RPCType type, bool enabled);
bool process(RPCType type, const char* in_buffer, uint32_t length, slot_response_callback callback);
void insert_command(const char* name, const char* parm, const char* doc);
slot_download& slot_find_download() { return m_slot_find_download; }
slot_file& slot_find_file() { return m_slot_find_file; }
slot_tracker& slot_find_tracker() { return m_slot_find_tracker; }
slot_peer& slot_find_peer() { return m_slot_find_peer; }
static void object_to_target(const torrent::Object& obj, int callFlags, rpc::target_type* target, std::function<void()>* deleter);
private:
XmlRpc m_xmlrpc;
JsonRpc m_jsonrpc;
bool m_initialized = false;
bool m_is_jsonrpc_enabled = true;
bool m_is_xmlrpc_enabled = true;
slot_download m_slot_find_download;
slot_file m_slot_find_file;
slot_tracker m_slot_find_tracker;
slot_peer m_slot_find_peer;
};
extern RpcManager rpc;
} // namespace rpc
#endif
+15 -41
View File
@@ -1,41 +1,6 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include "rpc/scgi_task.h"
#include <rak/error_number.h>
#include <rak/socket_address.h>
#include <sys/un.h>
@@ -142,14 +107,14 @@ SCgi::event_read() {
utils::SocketFd fd;
while ((fd = get_fd().accept(&sa)).is_valid()) {
SCgiTask* task = std::find_if(m_task, m_task + max_tasks, std::mem_fun_ref(&SCgiTask::is_available));
SCgiTask* task = std::find_if(m_task, m_task + max_tasks, std::mem_fn(&SCgiTask::is_available));
if (task == m_task + max_tasks) {
// Ergh... just closing for now.
fd.close();
continue;
}
task->open(this, fd.get_fd());
}
}
@@ -166,12 +131,21 @@ SCgi::event_error() {
bool
SCgi::receive_call(SCgiTask* task, const char* buffer, uint32_t length) {
torrent::thread_base::acquire_global_lock();
bool result = false;
torrent::utils::Thread::acquire_global_lock();
torrent::main_thread()->interrupt();
bool result = xmlrpc.process(buffer, length, [task](const char* b, uint32_t l) { return task->receive_write(b, l); });
switch (task->content_type()) {
case rpc::SCgiTask::ContentType::JSON:
result = rpc.process(RpcManager::RPCType::JSON, buffer, length, [task](const char* b, uint32_t l) { return task->receive_write(b, l); });
break;
case rpc::SCgiTask::ContentType::XML:
result = rpc.process(RpcManager::RPCType::XML, buffer, length, [task](const char* b, uint32_t l) { return task->receive_write(b, l); });
break;
torrent::thread_base::release_global_lock();
}
torrent::utils::Thread::release_global_lock();
return result;
}
+76 -60
View File
@@ -1,44 +1,9 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <rak/allocators.h>
#include <rak/error_number.h>
#include <cstdio>
#include <vector>
#include <sys/types.h>
#include <sys/socket.h>
#include <torrent/exceptions.h>
@@ -126,47 +91,94 @@ SCgiTask::event_read() {
// receive all the data we need the first time.
char* current;
int contentSize;
int headerSize = strtol(m_buffer, &current, 0);
int header_size = strtol(m_buffer, &current, 0);
if (current == m_position)
return;
// If the request doesn't start with an integer or if it didn't
// end in ':', then close the connection.
if (current == m_buffer || *current != ':' || headerSize < 17 || headerSize > max_header_size)
if (current == m_buffer || *current != ':' || header_size < 17 || header_size > max_header_size)
goto event_read_failed;
if (std::distance(++current, m_position) < headerSize + 1)
if (std::distance(++current, m_position) < header_size + 1)
return;
// We'll parse this fully below, but the SCGI spec requires it to
// be the first header.
if (std::memcmp(current, "CONTENT_LENGTH", 15) != 0)
goto event_read_failed;
char* contentPos;
contentSize = strtol(current + 15, &contentPos, 0);
std::string content_type = "";
size_t content_length = 0;
const char* header_end = current + header_size;
if (*contentPos != '\0' || contentSize <= 0 || contentSize > max_content_size)
// Parse out the null-terminated header keys and values, with
// checks to ensure it doesn't scan beyond the limits of the
// header
while (current < header_end) {
char* key = current;
char* key_end = static_cast<char*>(std::memchr(current, '\0', header_end - current));
if (!key_end)
goto event_read_failed;
current = key_end + 1;
if (current >= header_end)
goto event_read_failed;
char* value = current;
char* value_end = static_cast<char*>(std::memchr(current, '\0', header_end - current));
if (!value_end)
goto event_read_failed;
current = value_end + 1;
if (strcmp(key, "CONTENT_LENGTH") == 0) {
char* content_pos;
content_length = strtol(value, &content_pos, 10);
if (*content_pos != '\0' || content_length <= 0 || content_length > max_content_size)
goto event_read_failed;
} else if (strcmp(key, "CONTENT_TYPE") == 0) {
content_type = value;
}
}
if (current != header_end)
goto event_read_failed;
m_body = current + headerSize + 1;
headerSize = std::distance(m_buffer, m_body);
if (content_length <= 0)
goto event_read_failed;
if ((unsigned int)(contentSize + headerSize) < m_bufferSize) {
m_bufferSize = contentSize + headerSize;
m_body = current + 1;
header_size = std::distance(m_buffer, m_body);
} else if ((unsigned int)contentSize <= default_buffer_size) {
m_bufferSize = contentSize;
if (content_type == "") {
// If no CONTENT_TYPE was supplied, peek at the body to check if it's JSON
// { is a single request object, while [ is a batch array
if (*m_body == '{' || *m_body == '[')
m_content_type = ContentType::JSON;
} else if (content_type == "application/json") {
m_content_type = ContentType::JSON;
} else if (content_type == "text/xml") {
m_content_type = ContentType::XML;
} else {
goto event_read_failed;
}
if ((unsigned int)(content_length + header_size) < m_bufferSize) {
m_bufferSize = content_length + header_size;
} else if ((unsigned int)content_length <= default_buffer_size) {
m_bufferSize = content_length;
std::memmove(m_buffer, m_body, std::distance(m_body, m_position));
m_position = m_buffer + std::distance(m_body, m_position);
m_body = m_buffer;
m_body = m_buffer;
} else {
realloc_buffer((m_bufferSize = contentSize) + 1, m_body, std::distance(m_body, m_position));
realloc_buffer((m_bufferSize = content_length) + 1, m_body, std::distance(m_body, m_position));
m_position = m_buffer + std::distance(m_body, m_position);
m_body = m_buffer;
m_body = m_buffer;
}
}
@@ -193,14 +205,14 @@ SCgiTask::event_read() {
return;
event_read_failed:
// throw torrent::internal_error("SCgiTask::event_read() fault not handled.");
event_read_failed:
// throw torrent::internal_error("SCgiTask::event_read() fault not handled.");
close();
}
void
SCgiTask::event_write() {
// Apple and Solaris do not support MSG_NOSIGNAL,
// Apple and Solaris do not support MSG_NOSIGNAL,
// so disable this fix until we find a better solution
#if defined(__APPLE__) || defined(__sun__)
int bytes = ::send(m_fileDesc, m_position, m_bufferSize, 0);
@@ -236,12 +248,16 @@ SCgiTask::receive_write(const char* buffer, uint32_t length) {
if (length + 256 > std::max(m_bufferSize, (unsigned int)default_buffer_size))
realloc_buffer(length + 256, NULL, 0);
// Who ever bothers to check the return value?
int headerSize = sprintf(m_buffer, "Status: 200 OK\r\nContent-Type: text/xml\r\nContent-Length: %i\r\n\r\n", length);
const auto header = m_content_type == ContentType::JSON
? "Status: 200 OK\r\nContent-Type: application/json\r\nContent-Length: %i\r\n\r\n"
: "Status: 200 OK\r\nContent-Type: text/xml\r\nContent-Length: %i\r\n\r\n";
m_position = m_buffer;
// Who ever bothers to check the return value?
int headerSize = sprintf(m_buffer, header, length);
m_position = m_buffer;
m_bufferSize = length + headerSize;
std::memcpy(m_buffer + headerSize, buffer, length);
if (m_parent->log_fd() >= 0) {
@@ -258,4 +274,4 @@ SCgiTask::receive_write(const char* buffer, uint32_t length) {
return true;
}
}
} // namespace rpc
+6
View File
@@ -53,6 +53,8 @@ public:
static const int max_header_size = 2000;
static const int max_content_size = (2 << 23);
enum ContentType { XML, JSON };
SCgiTask() { m_fileDesc = -1; }
bool is_open() const { return m_fileDesc != -1; }
@@ -61,6 +63,8 @@ public:
void open(SCgi* parent, int fd);
void close();
ContentType content_type() const { return m_content_type; }
virtual void event_read();
virtual void event_write();
virtual void event_error();
@@ -79,6 +83,8 @@ private:
char* m_body;
unsigned int m_bufferSize;
ContentType m_content_type{ XML };
};
}
+1 -125
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include "xmlrpc.h"
@@ -44,98 +8,10 @@
namespace rpc {
class xmlrpc_error : public torrent::base_error {
public:
xmlrpc_error(int type, std::string msg) : m_type(type), m_msg(msg) {}
virtual ~xmlrpc_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;
};
void
XmlRpc::object_to_target(const torrent::Object& obj, int callFlags, rpc::target_type* target) {
if (callFlags & 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 = (callFlags & (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 = xmlrpc.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,
xmlrpc.slot_find_file()(download, std::stoi(std::string(index))));
break;
case 't':
*target = rpc::make_target(
command_base::target_tracker,
xmlrpc.slot_find_tracker()(download, std::stoi(std::string(index))));
break;
case 'p': {
if (index.size() < 40) {
// -501 == XMLRPC_TYPE_ERROR, used here directly to avoid
// conflicts between tinyxml2 and xmlrpc-c
throw xmlrpc_error(-501, "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,
xmlrpc.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");
}
}
#ifndef HAVE_XMLRPC_C
#ifndef HAVE_XMLRPC_TINYXML2
void XmlRpc::initialize() { throw torrent::resource_error("XMLRPC not supported."); }
void XmlRpc::initialize() {}
void XmlRpc::cleanup() {}
void XmlRpc::insert_command(__UNUSED const char* name, __UNUSED const char* parm, __UNUSED const char* doc) {}
+7 -48
View File
@@ -1,68 +1,27 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_RPC_XMLRPC_H
#define RTORRENT_RPC_XMLRPC_H
#include <functional>
#include <torrent/common.h>
#include <torrent/hash_string.h>
#include <torrent/tracker/tracker.h>
#include "command.h"
#include "scgi_task.h"
#include <torrent/hash_string.h>
namespace core {
class Download;
}
namespace torrent {
class File;
class Object;
class Tracker;
}
namespace rpc {
class XmlRpc {
public:
typedef std::function<core::Download* (const char*)> slot_download;
typedef std::function<torrent::File* (core::Download*, uint32_t)> slot_file;
typedef std::function<torrent::Tracker* (core::Download*, uint32_t)> slot_tracker;
typedef std::function<core::Download* (const char*)> slot_download;
typedef std::function<torrent::File* (core::Download*, uint32_t)> slot_file;
typedef std::function<torrent::tracker::Tracker (core::Download*, uint32_t)> slot_tracker;
typedef std::function<torrent::Peer* (core::Download*, const torrent::HashString&)> slot_peer;
typedef std::function<bool (const char*, uint32_t)> slot_write;
typedef std::function<bool (const char*, uint32_t)> slot_write;
static const int dialect_generic = 0;
static const int dialect_i8 = 1;
+67 -84
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#ifdef HAVE_XMLRPC_C
@@ -43,16 +7,16 @@
#include <cctype>
#include <string>
#include <stdlib.h>
#include <xmlrpc-c/server.h>
#include <rak/string_manip.h>
#include <torrent/object.h>
#include <torrent/exceptions.h>
#include <xmlrpc-c/server.h>
#include "rpc_manager.h"
#include "xmlrpc.h"
#include "parse_commands.h"
#include "utils/functional.h"
namespace rpc {
@@ -70,7 +34,7 @@ private:
const char* m_msg;
};
torrent::Object xmlrpc_to_object(xmlrpc_env* env, xmlrpc_value* value, int callType = 0, rpc::target_type* target = NULL);
torrent::Object xmlrpc_to_object(xmlrpc_env* env, xmlrpc_value* value, int call_type = 0, rpc::target_type* target = NULL, std::function<void()>* deleter = NULL);
inline torrent::Object
xmlrpc_list_entry_to_object(xmlrpc_env* env, xmlrpc_value* src, int index) {
@@ -134,59 +98,70 @@ xmlrpc_list_entry_to_value(xmlrpc_env* env, xmlrpc_value* src, int index) {
}
}
rpc::target_type
xmlrpc_to_target(xmlrpc_env* env, xmlrpc_value* value, int callType) {
std::pair<rpc::target_type, std::function<void()>>
xmlrpc_to_target(xmlrpc_env* env, xmlrpc_value* value, int call_type) {
rpc::target_type target;
std::function<void()> deleter = []() {};
XmlRpc::object_to_target(xmlrpc_to_object(env, value, -1, nullptr), callType, &target);
return target;
RpcManager::object_to_target(xmlrpc_to_object(env, value, -1, nullptr), call_type, &target, &deleter);
return std::make_pair(target, deleter);
}
rpc::target_type
xmlrpc_to_index_type(int index, int callType, core::Download* download) {
void* result;
std::pair<rpc::target_type, std::function<void()>>
xmlrpc_to_index_type(int index, int call_type, core::Download* download) {
void* result = nullptr;
std::function<void()> deleter = []() {};
switch (callType) {
case XmlRpc::call_file: result = xmlrpc.slot_find_file()(download, index); break;
case XmlRpc::call_tracker: result = xmlrpc.slot_find_tracker()(download, index); break;
default: result = NULL; break;
try {
switch (call_type) {
case XmlRpc::call_file:
result = rpc.slot_find_file()(download, index);
break;
case XmlRpc::call_tracker:
result = new torrent::tracker::Tracker(rpc.slot_find_tracker()(download, index));
deleter = [result]() { delete (torrent::tracker::Tracker*)result; };
break;
default:
throw torrent::input_error("invalid parameters: unexpected target type");
break;
}
} catch (const torrent::input_error& e) {
throw xmlrpc_error_c(XMLRPC_TYPE_ERROR, e.what());
}
if (result == NULL)
throw xmlrpc_error_c(XMLRPC_TYPE_ERROR, "Invalid index.");
return rpc::make_target(callType, result);
return std::make_pair(rpc::make_target(call_type, result), deleter);
}
torrent::Object
xmlrpc_to_object(xmlrpc_env* env, xmlrpc_value* value, int callType, rpc::target_type* target) {
xmlrpc_to_object(xmlrpc_env* env, xmlrpc_value* value, int call_type, rpc::target_type* target, std::function<void()>* deleter) {
switch (xmlrpc_value_type(value)) {
case XMLRPC_TYPE_INT:
int v;
xmlrpc_read_int(env, value, &v);
return torrent::Object((int64_t)v);
#ifdef XMLRPC_HAVE_I8
case XMLRPC_TYPE_I8:
xmlrpc_int64 v2;
xmlrpc_read_i8(env, value, &v2);
return torrent::Object((int64_t)v2);
#endif
// case XMLRPC_TYPE_BOOL:
// case XMLRPC_TYPE_DOUBLE:
// case XMLRPC_TYPE_DATETIME:
case XMLRPC_TYPE_STRING:
if (callType != XmlRpc::call_generic && target != nullptr) {
if (call_type != XmlRpc::call_generic && target != nullptr) {
// When the call type is not supposed to be void, we'll try to
// convert it to a command target. It's not that important that
// it is converted to the right type here, as an mismatch will
// be caught when executing the command.
*target = xmlrpc_to_target(env, value, callType);
std::tie(*target, *deleter) = xmlrpc_to_target(env, value, call_type);
return torrent::Object();
} else {
@@ -198,7 +173,6 @@ xmlrpc_to_object(xmlrpc_env* env, xmlrpc_value* value, int callType, rpc::target
torrent::Object result = torrent::Object(std::string(valueString));
// Urgh, seriously?
::free((void*)valueString);
return result;
}
@@ -215,7 +189,6 @@ xmlrpc_to_object(xmlrpc_env* env, xmlrpc_value* value, int callType, rpc::target
torrent::Object result = torrent::Object(std::string(valueString, valueSize));
// Urgh, seriously?
::free((void*)valueString);
return result;
}
@@ -228,7 +201,7 @@ xmlrpc_to_object(xmlrpc_env* env, xmlrpc_value* value, int callType, rpc::target
if (env->fault_occurred)
throw xmlrpc_error_c(env);
if (callType != XmlRpc::call_generic && last != 0) {
if (call_type != XmlRpc::call_generic && last != 0) {
if (last < 1)
throw xmlrpc_error_c(XMLRPC_TYPE_ERROR, "Too few arguments.");
@@ -239,14 +212,15 @@ xmlrpc_to_object(xmlrpc_env* env, xmlrpc_value* value, int callType, rpc::target
throw xmlrpc_error_c(env);
if (target != nullptr)
*target = xmlrpc_to_target(env, tmp, callType);
std::tie(*target, *deleter) = xmlrpc_to_target(env, tmp, call_type);
xmlrpc_DECREF(tmp);
if (env->fault_occurred)
throw xmlrpc_error_c(env);
if (target->first == XmlRpc::call_download &&
(callType == XmlRpc::call_file || callType == XmlRpc::call_tracker)) {
(call_type == XmlRpc::call_file || call_type == XmlRpc::call_tracker)) {
// If we have a download target and the call type requires
// another contained type, then we try to use the next
// parameter as the index to support old-style calls.
@@ -254,7 +228,17 @@ xmlrpc_to_object(xmlrpc_env* env, xmlrpc_value* value, int callType, rpc::target
if (current == last)
throw xmlrpc_error_c(XMLRPC_TYPE_ERROR, "Too few arguments, missing index.");
*target = xmlrpc_to_index_type(xmlrpc_list_entry_to_value(env, value, current++), callType, (core::Download*)target->second);
{
std::function<void()> old_deleter, tmp_deleter;
std::tie(*target, tmp_deleter) = xmlrpc_to_index_type(xmlrpc_list_entry_to_value(env, value, current++),
call_type,
(core::Download*)target->second);
old_deleter.swap(*deleter);
*deleter = [old_deleter, tmp_deleter]() {
tmp_deleter();
old_deleter();
};
}
}
}
@@ -275,10 +259,6 @@ xmlrpc_to_object(xmlrpc_env* env, xmlrpc_value* value, int callType, rpc::target
}
}
// case XMLRPC_TYPE_STRUCT:
// case XMLRPC_TYPE_C_PTR:
// case XMLRPC_TYPE_NIL:
// case XMLRPC_TYPE_DEAD:
default:
throw xmlrpc_error_c(XMLRPC_TYPE_ERROR, "Unsupported type found.");
}
@@ -290,7 +270,7 @@ object_to_xmlrpc(xmlrpc_env* env, const torrent::Object& object) {
case torrent::Object::TYPE_VALUE:
#ifdef XMLRPC_HAVE_I8
if (xmlrpc.dialect() != XmlRpc::dialect_generic)
if (rpc.dialect() != XmlRpc::dialect_generic)
return xmlrpc_i8_new(env, object.as_value());
#else
return xmlrpc_int_new(env, object.as_value());
@@ -328,7 +308,7 @@ object_to_xmlrpc(xmlrpc_env* env, const torrent::Object& object) {
case torrent::Object::TYPE_LIST:
{
xmlrpc_value* result = xmlrpc_array_new(env);
for (torrent::Object::list_const_iterator itr = object.as_list().begin(), last = object.as_list().end(); itr != last; itr++) {
xmlrpc_value* item = object_to_xmlrpc(env, *itr);
xmlrpc_array_append_item(env, result, item);
@@ -341,7 +321,7 @@ object_to_xmlrpc(xmlrpc_env* env, const torrent::Object& object) {
case torrent::Object::TYPE_MAP:
{
xmlrpc_value* result = xmlrpc_struct_new(env);
for (torrent::Object::map_const_iterator itr = object.as_map().begin(), last = object.as_map().end(); itr != last; itr++) {
xmlrpc_value* item = object_to_xmlrpc(env, itr->second);
xmlrpc_struct_set_value(env, result, itr->first.c_str(), item);
@@ -354,11 +334,11 @@ object_to_xmlrpc(xmlrpc_env* env, const torrent::Object& object) {
case torrent::Object::TYPE_DICT_KEY:
{
xmlrpc_value* result = xmlrpc_array_new(env);
xmlrpc_value* key_item = object_to_xmlrpc(env, object.as_dict_key());
xmlrpc_array_append_item(env, result, key_item);
xmlrpc_DECREF(key_item);
if (object.as_dict_obj().is_list()) {
for (torrent::Object::list_const_iterator
itr = object.as_dict_obj().as_list().begin(),
@@ -391,18 +371,21 @@ xmlrpc_call_command(xmlrpc_env* env, xmlrpc_value* args, void* voidServerInfo) {
return NULL;
}
std::function<void()> deleter = []() {};
utils::scope_guard guard([&deleter]() { deleter(); });
try {
torrent::Object object;
rpc::target_type target = rpc::make_target();
if (itr->second.m_flags & CommandMap::flag_no_target)
xmlrpc_to_object(env, args, XmlRpc::call_generic, &target).swap(object);
xmlrpc_to_object(env, args, XmlRpc::call_generic, &target, &deleter).swap(object);
else if (itr->second.m_flags & CommandMap::flag_file_target)
xmlrpc_to_object(env, args, XmlRpc::call_file, &target).swap(object);
xmlrpc_to_object(env, args, XmlRpc::call_file, &target, &deleter).swap(object);
else if (itr->second.m_flags & CommandMap::flag_tracker_target)
xmlrpc_to_object(env, args, XmlRpc::call_tracker, &target).swap(object);
xmlrpc_to_object(env, args, XmlRpc::call_tracker, &target, &deleter).swap(object);
else
xmlrpc_to_object(env, args, XmlRpc::call_any, &target).swap(object);
xmlrpc_to_object(env, args, XmlRpc::call_any, &target, &deleter).swap(object);
if (env->fault_occurred)
return NULL;
@@ -424,7 +407,7 @@ XmlRpc::initialize() {
#ifndef XMLRPC_HAVE_I8
m_dialect = dialect_generic;
#endif
m_env = new xmlrpc_env;
xmlrpc_env_init((xmlrpc_env*)m_env);
+46 -46
View File
@@ -17,6 +17,7 @@
#include "parse_commands.h"
#include "rpc/tinyxml2/tinyxml2.h"
#include "rpc/rpc_manager.h"
#include "utils/base64.h"
#include "xmlrpc.h"
@@ -25,29 +26,15 @@ namespace rpc {
// Taken from xmlrpc-c
const int XMLRPC_INTERNAL_ERROR = -500;
const int XMLRPC_TYPE_ERROR = -501;
const int XMLRPC_INDEX_ERROR = -502;
// const int XMLRPC_INDEX_ERROR = -502;
const int XMLRPC_PARSE_ERROR = -503;
const int XMLRPC_NETWORK_ERROR = -504;
const int XMLRPC_TIMEOUT_ERROR = -505;
// const int XMLRPC_NETWORK_ERROR = -504;
// const int XMLRPC_TIMEOUT_ERROR = -505;
const int XMLRPC_NO_SUCH_METHOD_ERROR = -506;
const int XMLRPC_REQUEST_REFUSED_ERROR = -507;
const int XMLRPC_INTROSPECTION_DISABLED_ERROR = -508;
// const int XMLRPC_REQUEST_REFUSED_ERROR = -507;
// const int XMLRPC_INTROSPECTION_DISABLED_ERROR = -508;
const int XMLRPC_LIMIT_EXCEEDED_ERROR = -509;
const int XMLRPC_INVALID_UTF8_ERROR = -510;
class xmlrpc_error : public torrent::base_error {
public:
xmlrpc_error(int type, std::string msg) :
m_type(type), m_msg(msg) {}
virtual ~xmlrpc_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;
};
// const int XMLRPC_INVALID_UTF8_ERROR = -510;
const tinyxml2::XMLElement*
element_access(const tinyxml2::XMLElement* elem, std::initializer_list<std::string> names) {
@@ -56,7 +43,7 @@ element_access(const tinyxml2::XMLElement* elem, std::initializer_list<std::stri
for (auto itr : names) {
result = result->FirstChildElement(itr.c_str());
if (result == nullptr) {
throw xmlrpc_error(XMLRPC_PARSE_ERROR, "could not find expected element " + itr);
throw rpc_error(XMLRPC_PARSE_ERROR, "could not find expected element " + itr);
}
}
return result;
@@ -66,22 +53,22 @@ long long
element_to_int(const tinyxml2::XMLNode* elem) {
char* pos;
if (elem->FirstChild() == nullptr) {
throw xmlrpc_error(XMLRPC_TYPE_ERROR, "unable to parse empty integer");
throw rpc_error(XMLRPC_TYPE_ERROR, "unable to parse empty integer");
}
auto str = elem->FirstChild()->ToText()->Value();
auto result = std::strtoll(str, &pos, 10);
if (pos == str || *pos != '\0')
throw xmlrpc_error(XMLRPC_TYPE_ERROR, "unable to parse integer value");
throw rpc_error(XMLRPC_TYPE_ERROR, "unable to parse integer value");
return result;
}
torrent::Object
xml_value_to_object(const tinyxml2::XMLNode* elem) {
if (elem == nullptr) {
throw xmlrpc_error(XMLRPC_INTERNAL_ERROR, "received null element to convert");
throw rpc_error(XMLRPC_INTERNAL_ERROR, "received null element to convert");
}
if (std::strncmp(elem->Value(), "value", sizeof("value")) != 0) {
throw xmlrpc_error(XMLRPC_INTERNAL_ERROR, "received non-value element to convert");
throw rpc_error(XMLRPC_INTERNAL_ERROR, "received non-value element to convert");
}
auto root_element = elem->FirstChild();
auto root_type = root_element->Value();
@@ -102,13 +89,13 @@ xml_value_to_object(const tinyxml2::XMLNode* elem) {
} else if (boolean_text == "0") {
return torrent::Object((int64_t)0);
}
throw xmlrpc_error(XMLRPC_TYPE_ERROR, "unknown boolean value: " + boolean_text);
throw rpc_error(XMLRPC_TYPE_ERROR, "unknown boolean value: " + boolean_text);
} else if (std::strncmp(root_type, "array", sizeof("array")) == 0) {
auto array_raw = torrent::Object::create_list();
auto& array = array_raw.as_list();
auto data_element = root_element->ToElement()->FirstChildElement("data");
if (data_element == nullptr)
throw xmlrpc_error(XMLRPC_PARSE_ERROR, "could not find expected data element in array");
throw rpc_error(XMLRPC_PARSE_ERROR, "could not find expected data element in array");
for (auto child = data_element->FirstChildElement("value"); child; child = child->NextSiblingElement("value")) {
array.push_back(xml_value_to_object(child));
}
@@ -128,7 +115,7 @@ xml_value_to_object(const tinyxml2::XMLNode* elem) {
}
return torrent::Object(utils::decode_base64(utils::remove_newlines(child_element->ToText()->Value())));
} else {
throw xmlrpc_error(XMLRPC_INTERNAL_ERROR, "received unsupported value type: " + std::string(root_type));
throw rpc_error(XMLRPC_INTERNAL_ERROR, "received unsupported value type: " + std::string(root_type));
}
return torrent::Object();
}
@@ -142,22 +129,20 @@ print_object_xml(const torrent::Object& obj, tinyxml2::XMLPrinter* printer) {
printer->CloseElement(true);
break;
case torrent::Object::TYPE_VALUE:
if (obj.as_value() > ((torrent::Object::value_type)2 << 30) || obj.as_value() < -((torrent::Object::value_type)2 << 30)) {
printer->OpenElement("i8", true);
} else {
printer->OpenElement("i4", true);
}
printer->OpenElement("i8", true);
printer->PushText(std::to_string(obj.as_value()).c_str());
printer->CloseElement(true);
break;
case torrent::Object::TYPE_LIST:
printer->OpenElement("array", true);
printer->OpenElement("data", true);
for (const auto& itr : obj.as_list()) {
printer->OpenElement("value", true);
print_object_xml(itr, printer);
printer->CloseElement(true);
}
printer->CloseElement(true);
printer->CloseElement(true);
break;
case torrent::Object::TYPE_MAP:
printer->OpenElement("struct", true);
@@ -175,7 +160,7 @@ print_object_xml(const torrent::Object& obj, tinyxml2::XMLPrinter* printer) {
break;
case torrent::Object::TYPE_DICT_KEY:
printer->OpenElement("array", true);
printer->OpenElement("data", true);
printer->OpenElement("value", true);
print_object_xml(obj.as_dict_key(), printer);
printer->CloseElement(true);
@@ -192,9 +177,10 @@ print_object_xml(const torrent::Object& obj, tinyxml2::XMLPrinter* printer) {
printer->CloseElement(true);
}
printer->CloseElement(true);
printer->CloseElement(true);
break;
default:
printer->OpenElement("i4", true);
printer->OpenElement("i8", true);
printer->PushText(0);
printer->CloseElement(true);
}
@@ -203,35 +189,47 @@ print_object_xml(const torrent::Object& obj, tinyxml2::XMLPrinter* printer) {
torrent::Object
execute_command(std::string method_name, const tinyxml2::XMLElement* params_element) {
CommandMap::iterator cmd_itr = commands.find(method_name.c_str());
if (cmd_itr == commands.end() || !(cmd_itr->second.m_flags & CommandMap::flag_public_xmlrpc)) {
throw xmlrpc_error(XMLRPC_NO_SUCH_METHOD_ERROR, "method '" + method_name + "' not defined");
if (cmd_itr == commands.end() || !(cmd_itr->second.m_flags & CommandMap::flag_public_rpc)) {
throw rpc_error(XMLRPC_NO_SUCH_METHOD_ERROR, "method '" + method_name + "' not defined");
}
torrent::Object params_raw = torrent::Object::create_list();
torrent::Object::list_type& params = params_raw.as_list();
rpc::target_type target = rpc::make_target();
if (params_element != nullptr) {
if (std::strncmp(params_element->Name(), "params", sizeof("params")) == 0) {
// Parse out the target if available
const auto* child = params_element->FirstChildElement("param");
if (child != nullptr) {
if (!(cmd_itr->second.m_flags & CommandMap::flag_no_target)) {
XmlRpc::object_to_target(xml_value_to_object(child->FirstChildElement("value")), cmd_itr->second.m_flags, &target);
std::function<void()> deleter = []() {};
RpcManager::object_to_target(xml_value_to_object(child->FirstChildElement("value")), cmd_itr->second.m_flags, &target, &deleter);
child = child->NextSiblingElement("param");
}
// Parse out any other params
while (child != nullptr) {
params.push_back(xml_value_to_object(child->FirstChildElement("value")));
child = child->NextSiblingElement("param");
}
}
} else if (params_element->FirstChildElement("data") != nullptr) {
// If it's not a <params>, it's probably a <array> passed in via system.multicall
const auto* child = params_element->FirstChildElement("data")->FirstChildElement("value");
if (child != nullptr) {
if (!(cmd_itr->second.m_flags & CommandMap::flag_no_target)) {
XmlRpc::object_to_target(xml_value_to_object(child), cmd_itr->second.m_flags, &target);
std::function<void()> deleter = []() {};
RpcManager::object_to_target(xml_value_to_object(child), cmd_itr->second.m_flags, &target, &deleter);
child = child->NextSiblingElement("value");
}
while (child != nullptr) {
params.push_back(xml_value_to_object(child));
child = child->NextSiblingElement("value");
@@ -239,20 +237,22 @@ execute_command(std::string method_name, const tinyxml2::XMLElement* params_elem
}
}
}
if (params.empty() && (cmd_itr->second.m_flags & (CommandMap::flag_file_target | CommandMap::flag_tracker_target))) {
throw xmlrpc_error(XMLRPC_TYPE_ERROR, "invalid parameters: too few");
throw rpc_error(XMLRPC_TYPE_ERROR, "invalid parameters: too few");
}
return rpc::commands.call_command(cmd_itr, params_raw, target);
}
void
process_document(const tinyxml2::XMLDocument* doc, tinyxml2::XMLPrinter* printer) {
if (doc->Error())
throw xmlrpc_error(XMLRPC_PARSE_ERROR, doc->ErrorStr());
throw rpc_error(XMLRPC_PARSE_ERROR, doc->ErrorStr());
if (doc->FirstChildElement("methodCall") == nullptr)
throw xmlrpc_error(XMLRPC_PARSE_ERROR, "methodCall element not found");
throw rpc_error(XMLRPC_PARSE_ERROR, "methodCall element not found");
if (doc->FirstChildElement("methodCall")->FirstChildElement("methodName") == nullptr)
throw xmlrpc_error(XMLRPC_PARSE_ERROR, "methodName element not found");
throw rpc_error(XMLRPC_PARSE_ERROR, "methodName element not found");
auto method_name = doc->FirstChildElement("methodCall")->FirstChildElement("methodName")->GetText();
torrent::Object result;
@@ -277,7 +277,7 @@ process_document(const tinyxml2::XMLDocument* doc, tinyxml2::XMLPrinter* printer
auto sub_result = torrent::Object::create_list();
sub_result.as_list().push_back(execute_command(sub_method_name, sub_params));
result_list.push_back(sub_result);
} catch (xmlrpc_error& e) {
} catch (rpc_error& e) {
auto fault = torrent::Object::create_map();
fault.as_map()["faultString"] = e.what();
fault.as_map()["faultCode"] = e.type();
@@ -320,7 +320,7 @@ print_xmlrpc_fault(int faultCode, std::string faultString, tinyxml2::XMLPrinter*
printer->PushText("faultCode");
printer->CloseElement(true);
printer->OpenElement("value", true);
printer->OpenElement("i4", true);
printer->OpenElement("i8", true);
printer->PushText(faultCode);
printer->CloseElement(true);
printer->CloseElement(true);
@@ -358,7 +358,7 @@ XmlRpc::process(const char* inBuffer, uint32_t length, slot_write slotWrite) {
tinyxml2::XMLPrinter printer(nullptr, true, 0);
process_document(&doc, &printer);
return slotWrite(printer.CStr(), printer.CStrSize() - 1);
} catch (xmlrpc_error& e) {
} catch (rpc_error& e) {
tinyxml2::XMLPrinter printer(nullptr, true, 0);
print_xmlrpc_fault(e.type(), e.what(), &printer);
return slotWrite(printer.CStr(), printer.CStrSize() - 1);
+2
View File
@@ -91,6 +91,8 @@ ThreadBase::call_events() {
call_queued_items();
rak::priority_queue_perform(&m_taskScheduler, cachedTime);
process_callbacks();
}
void
+2 -38
View File
@@ -1,46 +1,10 @@
// libTorrent - BitTorrent library
// 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_THREAD_BASE_H
#define RTORRENT_UTILS_THREAD_BASE_H
#include <memory>
#include <pthread.h>
#include <sys/types.h>
#include <torrent/utils/thread_base.h>
#include <torrent/utils/thread.h>
#include "rak/priority_queue_default.h"
#include "core/poll_manager.h"
@@ -49,7 +13,7 @@
class thread_queue_hack;
class ThreadBase : public torrent::thread_base {
class ThreadBase : public torrent::utils::Thread {
public:
typedef rak::priority_queue_default priority_queue;
typedef void (*thread_base_func)(ThreadBase*);
+14 -53
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent library
// 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 "thread_worker.h"
@@ -45,15 +9,12 @@
#include <cassert>
#include <rak/path.h>
#include <torrent/exceptions.h>
#include <torrent/poll.h>
#include "core/manager.h"
#include "rpc/scgi.h"
#include "rpc/xmlrpc.h"
#include "rpc/parse_commands.h"
ThreadWorker::ThreadWorker() {
}
ThreadWorker::~ThreadWorker() {
if (m_scgi)
m_scgi.load()->deactivate();
@@ -61,7 +22,7 @@ ThreadWorker::~ThreadWorker() {
void
ThreadWorker::init_thread() {
m_poll = core::create_poll();
m_poll = std::unique_ptr<torrent::Poll>(core::create_poll());
m_state = STATE_INITIALIZED;
}
@@ -71,17 +32,17 @@ ThreadWorker::set_scgi(rpc::SCgi* scgi) {
if (!m_scgi.compare_exchange_strong(expected, scgi))
return false;
change_xmlrpc_log();
change_rpc_log();
queue_item((thread_base_func)&start_scgi);
return true;
}
void
ThreadWorker::set_xmlrpc_log(const std::string& filename) {
m_xmlrpcLog = filename;
ThreadWorker::set_rpc_log(const std::string& filename) {
m_rpcLog = filename;
queue_item((thread_base_func)&msg_change_xmlrpc_log);
queue_item((thread_base_func)&msg_change_rpc_log);
}
void
@@ -95,34 +56,34 @@ ThreadWorker::start_scgi(ThreadBase* baseThread) {
}
void
ThreadWorker::msg_change_xmlrpc_log(ThreadBase* baseThread) {
ThreadWorker::msg_change_rpc_log(ThreadBase* baseThread) {
ThreadWorker* thread = (ThreadWorker*)baseThread;
acquire_global_lock();
thread->change_xmlrpc_log();
thread->change_rpc_log();
release_global_lock();
}
void
ThreadWorker::change_xmlrpc_log() {
ThreadWorker::change_rpc_log() {
if (scgi() == NULL)
return;
if (scgi()->log_fd() != -1) {
::close(scgi()->log_fd());
scgi()->set_log_fd(-1);
control->core()->push_log("Closed XMLRPC log.");
control->core()->push_log("Closed RPC log.");
}
if (m_xmlrpcLog.empty())
if (m_rpcLog.empty())
return;
scgi()->set_log_fd(open(rak::path_expand(m_xmlrpcLog).c_str(), O_WRONLY | O_APPEND | O_CREAT, 0644));
scgi()->set_log_fd(open(rak::path_expand(m_rpcLog).c_str(), O_WRONLY | O_APPEND | O_CREAT, 0644));
if (scgi()->log_fd() == -1) {
control->core()->push_log_std("Could not open XMLRPC log file '" + m_xmlrpcLog + "'.");
control->core()->push_log_std("Could not open RPC log file '" + m_rpcLog + "'.");
return;
}
control->core()->push_log_std("Logging XMLRPC events to '" + m_xmlrpcLog + "'.");
control->core()->push_log_std("Logging RPC events to '" + m_rpcLog + "'.");
}
+9 -45
View File
@@ -1,46 +1,10 @@
// rTorrent - BitTorrent library
// 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_THREAD_WORKER_H
#define RTORRENT_THREAD_WORKER_H
#include <atomic>
#include "thread_base.h"
#include <rak/priority_queue_default.h>
#include "thread_base.h"
#include "rak/priority_queue_default.h"
namespace rpc {
class SCgi;
@@ -49,9 +13,9 @@ class SCgi;
// Check if cacheline aligned with inheritance ends up taking two
// cachelines.
class lt_cacheline_aligned ThreadWorker : public ThreadBase {
class ThreadWorker : public ThreadBase {
public:
ThreadWorker();
ThreadWorker() = default;
~ThreadWorker();
const char* name() const { return "rtorrent scgi"; }
@@ -60,22 +24,22 @@ public:
rpc::SCgi* scgi() { return m_scgi; }
bool set_scgi(rpc::SCgi* scgi);
void set_xmlrpc_log(const std::string& filename);
void set_rpc_log(const std::string& filename);
static void start_scgi(ThreadBase* thread);
static void msg_change_xmlrpc_log(ThreadBase* thread);
static void msg_change_rpc_log(ThreadBase* thread);
private:
void task_touch_log();
void change_xmlrpc_log();
void change_rpc_log();
std::atomic<rpc::SCgi*> m_scgi{ nullptr };
// The following types shall only be modified while holding the
// global lock.
std::string m_xmlrpcLog;
std::string m_rpcLog;
};
#endif
+5 -41
View File
@@ -1,42 +1,7 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <rak/functional.h>
#include <cassert>
#include <rak/string_manip.h>
#include <torrent/exceptions.h>
#include <torrent/chunk_manager.h>
@@ -97,10 +62,9 @@ Download::Download(core::Download* d) :
}
Download::~Download() {
if (is_active())
throw torrent::internal_error("ui::Download::~Download() called on an active object.");
assert(!is_active() && "ui::Download::~Download() called on an active object.");
std::for_each(m_uiArray, m_uiArray + DISPLAY_MAX_SIZE, rak::call_delete<ElementBase>());
std::for_each(m_uiArray, m_uiArray + DISPLAY_MAX_SIZE, [](ElementBase* eb) { delete eb; });
delete m_windowDownloadStatus;
}
@@ -203,7 +167,7 @@ Download::create_info() {
}
void
Download::activate(display::Frame* frame, bool focus) {
Download::activate(display::Frame* frame, [[maybe_unused]] bool focus) {
if (is_active())
throw torrent::internal_error("ui::Download::activate() called on an already activated object.");
+4 -41
View File
@@ -1,44 +1,8 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <cassert>
#include <sstream>
#include <rak/functional.h>
#include <rak/string_manip.h>
#include <torrent/exceptions.h>
#include <torrent/torrent.h>
@@ -83,16 +47,15 @@ DownloadList::DownloadList() :
}
DownloadList::~DownloadList() {
if (is_active())
throw std::logic_error("ui::DownloadList::~DownloadList() called on an active object");
assert(!is_active() && "ui::DownloadList::~DownloadList() called on an active object");
std::for_each(m_uiArray, m_uiArray + DISPLAY_MAX_SIZE, rak::call_delete<ElementBase>());
std::for_each(m_uiArray, m_uiArray + DISPLAY_MAX_SIZE, [](ElementBase* eb) { delete eb; });
delete m_windowLog;
}
void
DownloadList::activate(display::Frame* frame, bool focus) {
DownloadList::activate(display::Frame* frame, [[maybe_unused]] bool focus) {
if (is_active())
throw torrent::internal_error("ui::DownloadList::activate() called on an already activated object");
+69 -70
View File
@@ -1,39 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <torrent/exceptions.h>
@@ -55,8 +19,8 @@
namespace ui {
ElementDownloadList::ElementDownloadList() :
m_window(NULL),
m_view(NULL) {
m_window(NULL),
m_view(NULL) {
receive_change_view("main");
@@ -67,40 +31,42 @@ ElementDownloadList::ElementDownloadList() :
m_bindings['\x04'] = std::bind(&ElementDownloadList::receive_command, this, "branch=d.state=,d.stop=,d.erase=");
m_bindings['\x0B'] = std::bind(&ElementDownloadList::receive_command, this, "d.ignore_commands.set=1; d.stop=; d.close=");
m_bindings['\x12'] = std::bind(&ElementDownloadList::receive_command, this, "d.complete.set=0; d.check_hash=");
m_bindings['\x05'] = std::bind(&ElementDownloadList::receive_command, this,
"f.multicall=,f.set_create_queued=0,f.set_resize_queued=0; print=\"Queued create/resize of files in torrent.\"");
m_bindings['\x05'] = std::bind(&ElementDownloadList::receive_command, this, "f.multicall=,f.set_create_queued=0,f.set_resize_queued=0; print=\"Queued create/resize of files in torrent.\"");
m_bindings['+'] = std::bind(&ElementDownloadList::receive_next_priority, this);
m_bindings['-'] = std::bind(&ElementDownloadList::receive_prev_priority, this);
m_bindings['T'-'@']= std::bind(&ElementDownloadList::receive_cycle_throttle, this);
m_bindings['I'] = std::bind(&ElementDownloadList::receive_command, this,
"branch=d.ignore_commands=,"
"{d.ignore_commands.set=0, print=\"Torrent set to heed commands.\"},"
"{d.ignore_commands.set=1, print=\"Torrent set to ignore commands.\"}");
m_bindings['B'-'@']= std::bind(&ElementDownloadList::receive_command, this,
"branch=d.is_active=,"
"{print=\"Cannot enable initial seeding on an active download.\"},"
"{d.connection_seed.set=initial_seed, print=\"Enabled initial seeding for the selected download.\"}");
m_bindings['+'] = std::bind(&ElementDownloadList::receive_next_priority, this);
m_bindings['-'] = std::bind(&ElementDownloadList::receive_prev_priority, this);
m_bindings['T' - '@'] = std::bind(&ElementDownloadList::receive_cycle_throttle, this);
m_bindings['I'] = std::bind(&ElementDownloadList::receive_command, this, "branch=d.ignore_commands=,"
"{d.ignore_commands.set=0, print=\"Torrent set to heed commands.\"},"
"{d.ignore_commands.set=1, print=\"Torrent set to ignore commands.\"}");
m_bindings['B' - '@'] = std::bind(&ElementDownloadList::receive_command, this, "branch=d.is_active=,"
"{print=\"Cannot enable initial seeding on an active download.\"},"
"{d.connection_seed.set=initial_seed, print=\"Enabled initial seeding for the selected download.\"}");
m_bindings['U'] = std::bind(&ElementDownloadList::receive_command, this,
"d.delete_tied=; print=\"Cleared tied to file association for the selected download.\"");
m_bindings['U'] = std::bind(&ElementDownloadList::receive_command, this, "d.delete_tied=; print=\"Cleared tied to file association for the selected download.\"");
// These should also be commands.
m_bindings['1'] = std::bind(&ElementDownloadList::receive_change_view, this, "main");
m_bindings['2'] = std::bind(&ElementDownloadList::receive_change_view, this, "name");
m_bindings['3'] = std::bind(&ElementDownloadList::receive_change_view, this, "started");
m_bindings['4'] = std::bind(&ElementDownloadList::receive_change_view, this, "stopped");
m_bindings['5'] = std::bind(&ElementDownloadList::receive_change_view, this, "complete");
m_bindings['6'] = std::bind(&ElementDownloadList::receive_change_view, this, "incomplete");
m_bindings['7'] = std::bind(&ElementDownloadList::receive_change_view, this, "hashing");
m_bindings['8'] = std::bind(&ElementDownloadList::receive_change_view, this, "seeding");
m_bindings['9'] = std::bind(&ElementDownloadList::receive_change_view, this, "leeching");
m_bindings['0'] = std::bind(&ElementDownloadList::receive_change_view, this, "active");
m_bindings['1'] = std::bind(&ElementDownloadList::receive_change_view, this, "main");
m_bindings['2'] = std::bind(&ElementDownloadList::receive_change_view, this, "name");
m_bindings['3'] = std::bind(&ElementDownloadList::receive_change_view, this, "started");
m_bindings['4'] = std::bind(&ElementDownloadList::receive_change_view, this, "stopped");
m_bindings['5'] = std::bind(&ElementDownloadList::receive_change_view, this, "complete");
m_bindings['6'] = std::bind(&ElementDownloadList::receive_change_view, this, "incomplete");
m_bindings['7'] = std::bind(&ElementDownloadList::receive_change_view, this, "hashing");
m_bindings['8'] = std::bind(&ElementDownloadList::receive_change_view, this, "seeding");
m_bindings['9'] = std::bind(&ElementDownloadList::receive_change_view, this, "leeching");
m_bindings['0'] = std::bind(&ElementDownloadList::receive_change_view, this, "active");
m_bindings[KEY_UP] = m_bindings['P' - '@'] = std::bind(&ElementDownloadList::receive_prev, this);
m_bindings[KEY_UP] = m_bindings['P' - '@'] = std::bind(&ElementDownloadList::receive_prev, this);
m_bindings[KEY_DOWN] = m_bindings['N' - '@'] = std::bind(&ElementDownloadList::receive_next, this);
m_bindings['L'] = std::bind(&ElementDownloadList::toggle_layout, this);
m_bindings[KEY_PPAGE] = m_bindings['U' - '@'] = [this] { receive_pageprev(); };
m_bindings[KEY_NPAGE] = m_bindings['H' - '@'] = [this] { receive_pagenext(); };
m_bindings[KEY_HOME] = m_bindings['A' - '@'] = [this] { receive_home(); };
m_bindings[KEY_END] = m_bindings['E' - '@'] = [this] { receive_end(); };
m_bindings['L'] = std::bind(&ElementDownloadList::toggle_layout, this);
}
void
@@ -172,6 +138,41 @@ ElementDownloadList::receive_prev() {
m_view->set_last_changed();
}
int
ElementDownloadList::page_size() {
int rpc_page_size = rpc::call_command_value("ui.focus.page_size");
if (rpc_page_size > 0)
return rpc_page_size;
int auto_page_size = m_window->page_size() - 1;
if (auto_page_size > 0)
return auto_page_size;
return 50;
}
void
ElementDownloadList::receive_pagenext() {
m_view->next_focus(page_size());
m_view->set_last_changed();
}
void
ElementDownloadList::receive_pageprev() {
m_view->prev_focus(page_size());
m_view->set_last_changed();
}
void
ElementDownloadList::receive_home() {
m_view->set_focus(m_view->begin_visible());
m_view->set_last_changed();
}
void
ElementDownloadList::receive_end() {
m_view->set_focus(m_view->end_visible() - 1);
m_view->set_last_changed();
}
void
ElementDownloadList::receive_next_priority() {
if (m_view->focus() == m_view->end_visible())
@@ -222,12 +223,10 @@ ElementDownloadList::receive_change_view(const std::string& name) {
std::string old_name = view() ? view()->name() : "";
if (!old_name.empty())
rpc::commands.call_catch("event.view.hide", rpc::make_target(), name,
"View hide event action failed: ");
rpc::commands.call_catch("event.view.hide", rpc::make_target(), name, "View hide event action failed: ");
set_view(*itr);
if (!old_name.empty())
rpc::commands.call_catch("event.view.show", rpc::make_target(), old_name,
"View show event action failed: ");
rpc::commands.call_catch("event.view.show", rpc::make_target(), old_name, "View show event action failed: ");
}
void
@@ -240,4 +239,4 @@ ElementDownloadList::toggle_layout() {
rpc::call_command("ui.torrent_list.layout.set", "full");
}
}
}
} // namespace ui

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