mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-08-06 18:22:32 +00:00
Compare commits
61 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 34bc18940a | |||
| cde78f2353 | |||
| cc59125116 | |||
| 8ac31afd06 | |||
| 8d991b4ce5 | |||
| 3a227c190f | |||
| 9a2ce2b231 | |||
| f33fc331ce | |||
| 47af28aecd | |||
| c6ebdf876a | |||
| 5797ed9e7a | |||
| 9465c94b31 | |||
| 0adfc17335 | |||
| 37a5b7bccb | |||
| 80ef2e076d | |||
| 4ac7313ff1 | |||
| 6139217033 | |||
| 89b35af7a6 | |||
| 851ac469c3 | |||
| 1811248691 | |||
| bacf60af89 | |||
| 1f01b7e94d | |||
| d514e525ca | |||
| b2b723f248 | |||
| e3ab913f9a | |||
| 787e23a25d | |||
| 9f48226663 | |||
| 78915746ee | |||
| e7fc891f11 | |||
| 2e0a417367 | |||
| b5a6ee33a1 | |||
| 3378355b64 | |||
| 6f5d06907b | |||
| 712e7e5db0 | |||
| 2b73c92a3e | |||
| c5563d65c5 | |||
| d412caea66 | |||
| 9c92bfc7e2 | |||
| 4a074adc7b | |||
| 3bf494dbc6 | |||
| b193fedc65 | |||
| 6c5a6a3bb3 | |||
| 7534b02815 | |||
| 6d8c214d09 | |||
| 525b038dbb | |||
| 06741a7578 | |||
| 4cc79590be | |||
| 452397b8af | |||
| c9a8a1e35c | |||
| 8f77d87994 | |||
| 842edaa201 | |||
| 4876301cf4 | |||
| c2c6a4be26 | |||
| 350d03ca04 | |||
| 31602917b7 | |||
| a9898c6ef6 | |||
| 2bf81aa8f5 | |||
| a9c0b65b9d | |||
| 73fed24459 | |||
| f906e9a966 | |||
| 090b3889ce |
@@ -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 }}
|
||||
@@ -0,0 +1,80 @@
|
||||
name: Static analysis
|
||||
|
||||
on: pull_request
|
||||
|
||||
jobs:
|
||||
|
||||
clang-tidy:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Update Packages
|
||||
run: |
|
||||
sudo apt-get update
|
||||
- name: Fetch libtorrent
|
||||
run: |
|
||||
git clone https://github.com/rakshasa/libtorrent
|
||||
- name: Build libtorrent
|
||||
run: |
|
||||
cd libtorrent
|
||||
libtoolize
|
||||
aclocal -I scripts
|
||||
autoconf -i
|
||||
autoheader
|
||||
automake --add-missing
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
cd ..
|
||||
rm -rf libtorrent
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
- name: Fetch base branch
|
||||
run: |
|
||||
git remote add upstream "https://github.com/${{ github.event.pull_request.base.repo.full_name }}"
|
||||
git fetch --no-tags --no-recurse-submodules upstream "${{ github.event.pull_request.base.ref }}"
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get install -y bear clang-tidy libcurl4-openssl-dev
|
||||
- name: Configure Project
|
||||
run: |
|
||||
libtoolize
|
||||
aclocal -I scripts
|
||||
autoconf -i
|
||||
autoheader
|
||||
automake --add-missing
|
||||
./configure
|
||||
- name: Prepare compile_commands.json
|
||||
run: |
|
||||
bear -- make
|
||||
- name: Create results directory
|
||||
run: |
|
||||
mkdir clang-tidy-result
|
||||
- name: Analyze
|
||||
run: |
|
||||
git diff -U0 "$(git merge-base HEAD "upstream/${{ github.event.pull_request.base.ref }}")" | clang-tidy-diff -p1 -path build -export-fixes clang-tidy-result/fixes.yml "-extra-arg=-include/${PWD}/config.h"
|
||||
- name: Save PR metadata
|
||||
run: |
|
||||
echo "${{ github.event.number }}" > clang-tidy-result/pr-id.txt
|
||||
echo "${{ github.event.pull_request.head.repo.full_name }}" > clang-tidy-result/pr-head-repo.txt
|
||||
echo "${{ github.event.pull_request.head.sha }}" > clang-tidy-result/pr-head-sha.txt
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: clang-tidy-result
|
||||
path: clang-tidy-result/
|
||||
# - name: Run clang-tidy-pr-comments action
|
||||
# uses: platisd/clang-tidy-pr-comments@v1
|
||||
# with:
|
||||
# # The GitHub token (or a personal access token)
|
||||
# github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# # The path to the clang-tidy fixes generated previously
|
||||
# clang_tidy_fixes: clang-tidy-result/fixes.yml
|
||||
# # Optionally set to true if you want the Action to request
|
||||
# # changes in case warnings are found
|
||||
# request_changes: true
|
||||
# # Optionally set the number of comments per review
|
||||
# # to avoid GitHub API timeouts for heavily loaded
|
||||
# # pull requests
|
||||
# suggestions_per_comment: 10
|
||||
@@ -0,0 +1,56 @@
|
||||
name: Static analysis
|
||||
|
||||
on: pull_request
|
||||
|
||||
jobs:
|
||||
|
||||
unit-tests:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Update Packages
|
||||
run: |
|
||||
sudo apt-get update
|
||||
- name: Fetch libtorrent
|
||||
run: |
|
||||
git clone https://github.com/rakshasa/libtorrent
|
||||
- name: Build libtorrent
|
||||
run: |
|
||||
cd libtorrent
|
||||
libtoolize
|
||||
aclocal -I scripts
|
||||
autoconf -i
|
||||
autoheader
|
||||
automake --add-missing
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
cd ..
|
||||
rm -rf libtorrent
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
- name: Fetch base branch
|
||||
run: |
|
||||
git remote add upstream "https://github.com/${{ github.event.pull_request.base.repo.full_name }}"
|
||||
git fetch --no-tags --no-recurse-submodules upstream "${{ github.event.pull_request.base.ref }}"
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get install -y \
|
||||
libcppunit-dev \
|
||||
libcurl4-openssl-dev
|
||||
- name: Configure Project
|
||||
run: |
|
||||
libtoolize
|
||||
aclocal -I scripts
|
||||
autoconf -i
|
||||
autoheader
|
||||
automake --add-missing
|
||||
./configure
|
||||
- name: Build Project
|
||||
run: |
|
||||
make
|
||||
- name: Run Unit Tests
|
||||
run: |
|
||||
make check
|
||||
+2
-2
@@ -18,6 +18,7 @@
|
||||
.libs
|
||||
Makefile
|
||||
aclocal.m4
|
||||
ar-lib
|
||||
autom4te.cache
|
||||
compile
|
||||
config.h
|
||||
@@ -67,6 +68,5 @@ TAGS
|
||||
# rTorrent specific files
|
||||
###########################
|
||||
src/rtorrent
|
||||
test/rtorrentTest
|
||||
test/rtorrent_Test*
|
||||
test-driver
|
||||
test/rtorrentTest.trs
|
||||
|
||||
@@ -10,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
@@ -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
|
||||
|
||||
@@ -499,10 +499,6 @@ Number of attempts to check the hash while using the mincore status,
|
||||
before forcing. Overworked systems might need lower values to get a
|
||||
decent hash checking rate.
|
||||
.TP
|
||||
\fBsafe_sync = \fIyes|no\fB\fR
|
||||
Always use MS_SYNC rather than MS_ASYNC when syncing chunks. This may
|
||||
be nessesary in case of filesystem bugs like NFS in linux ~2.6.13.
|
||||
.TP
|
||||
\fBmax_open_files = \fIvalue\fB\fR
|
||||
Number of files to simultaneously keep open. LibTorrent dynamically
|
||||
opens and closes files as necessary when mapping files to
|
||||
|
||||
@@ -978,16 +978,6 @@ decent hash checking rate.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>safe_sync = <replaceable>yes|no</replaceable></term>
|
||||
<listitem><para>
|
||||
|
||||
Always use MS_SYNC rather than MS_ASYNC when syncing chunks. This may
|
||||
be nessesary in case of filesystem bugs like NFS in linux ~2.6.13.
|
||||
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>max_open_files = <replaceable>value</replaceable></term>
|
||||
<listitem><para>
|
||||
|
||||
+1
-1
@@ -115,7 +115,7 @@ advance_backward(_InputIter __first, _InputIter __last, _Distance __distance) {
|
||||
}
|
||||
|
||||
template <typename _Value>
|
||||
struct compare_base : public std::binary_function<_Value, _Value, bool> {
|
||||
struct compare_base : public std::function<bool(_Value, _Value)> {
|
||||
bool operator () (const _Value& complete, const _Value& base) const {
|
||||
return !complete.compare(0, base.size(), base);
|
||||
}
|
||||
|
||||
@@ -1,683 +0,0 @@
|
||||
// rak - Rakshasa's toolbox
|
||||
// Copyright (C) 2005-2007, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RAK_FUNCTIONAL_H
|
||||
#define RAK_FUNCTIONAL_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
|
||||
namespace rak {
|
||||
|
||||
template <typename Type>
|
||||
struct reference_fix {
|
||||
typedef Type type;
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
struct reference_fix<Type&> {
|
||||
typedef Type type;
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
struct value_t {
|
||||
value_t(Type v) : m_v(v) {}
|
||||
|
||||
Type operator () () const { return m_v; }
|
||||
|
||||
Type m_v;
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
inline value_t<Type>
|
||||
value(Type v) {
|
||||
return value_t<Type>(v);
|
||||
}
|
||||
|
||||
template <typename Type, typename Ftor>
|
||||
struct accumulate_t {
|
||||
accumulate_t(Type t, Ftor f) : result(t), m_f(f) {}
|
||||
|
||||
template <typename Arg>
|
||||
void operator () (const Arg& a) { result += m_f(a); }
|
||||
|
||||
Type result;
|
||||
Ftor m_f;
|
||||
};
|
||||
|
||||
template <typename Type, typename Ftor>
|
||||
inline accumulate_t<Type, Ftor>
|
||||
accumulate(Type t, Ftor f) {
|
||||
return accumulate_t<Type, Ftor>(t, f);
|
||||
}
|
||||
|
||||
// Operators:
|
||||
|
||||
template <typename Type, typename Ftor>
|
||||
struct equal_t {
|
||||
typedef bool result_type;
|
||||
|
||||
equal_t(Type t, Ftor f) : m_t(t), m_f(f) {}
|
||||
|
||||
template <typename Arg>
|
||||
bool operator () (Arg& a) {
|
||||
return m_t == m_f(a);
|
||||
}
|
||||
|
||||
Type m_t;
|
||||
Ftor m_f;
|
||||
};
|
||||
|
||||
template <typename Type, typename Ftor>
|
||||
inline equal_t<Type, Ftor>
|
||||
equal(Type t, Ftor f) {
|
||||
return equal_t<Type, Ftor>(t, f);
|
||||
}
|
||||
|
||||
template <typename Type, typename Ftor>
|
||||
struct equal_ptr_t {
|
||||
typedef bool result_type;
|
||||
|
||||
equal_ptr_t(Type* t, Ftor f) : m_t(t), m_f(f) {}
|
||||
|
||||
template <typename Arg>
|
||||
bool operator () (const Arg& a) {
|
||||
return *m_t == *m_f(a);
|
||||
}
|
||||
|
||||
Type* m_t;
|
||||
Ftor m_f;
|
||||
};
|
||||
|
||||
template <typename Type, typename Ftor>
|
||||
inline equal_ptr_t<Type, Ftor>
|
||||
equal_ptr(Type* t, Ftor f) {
|
||||
return equal_ptr_t<Type, Ftor>(t, f);
|
||||
}
|
||||
|
||||
template <typename Type, typename Ftor>
|
||||
struct not_equal_t {
|
||||
typedef bool result_type;
|
||||
|
||||
not_equal_t(Type t, Ftor f) : m_t(t), m_f(f) {}
|
||||
|
||||
template <typename Arg>
|
||||
bool operator () (Arg& a) {
|
||||
return m_t != m_f(a);
|
||||
}
|
||||
|
||||
Type m_t;
|
||||
Ftor m_f;
|
||||
};
|
||||
|
||||
template <typename Type, typename Ftor>
|
||||
inline not_equal_t<Type, Ftor>
|
||||
not_equal(Type t, Ftor f) {
|
||||
return not_equal_t<Type, Ftor>(t, f);
|
||||
}
|
||||
|
||||
template <typename Type, typename Ftor>
|
||||
struct less_t {
|
||||
typedef bool result_type;
|
||||
|
||||
less_t(Type t, Ftor f) : m_t(t), m_f(f) {}
|
||||
|
||||
template <typename Arg>
|
||||
bool operator () (Arg& a) {
|
||||
return m_t < m_f(a);
|
||||
}
|
||||
|
||||
Type m_t;
|
||||
Ftor m_f;
|
||||
};
|
||||
|
||||
template <typename Type, typename Ftor>
|
||||
inline less_t<Type, Ftor>
|
||||
less(Type t, Ftor f) {
|
||||
return less_t<Type, Ftor>(t, f);
|
||||
}
|
||||
|
||||
template <typename FtorA, typename FtorB>
|
||||
struct less2_t : public std::binary_function<typename FtorA::argument_type, typename FtorB::argument_type, bool> {
|
||||
less2_t(FtorA f_a, FtorB f_b) : m_f_a(f_a), m_f_b(f_b) {}
|
||||
|
||||
bool operator () (typename FtorA::argument_type a, typename FtorB::argument_type b) {
|
||||
return m_f_a(a) < m_f_b(b);
|
||||
}
|
||||
|
||||
FtorA m_f_a;
|
||||
FtorB m_f_b;
|
||||
};
|
||||
|
||||
template <typename FtorA, typename FtorB>
|
||||
inline less2_t<FtorA, FtorB>
|
||||
less2(FtorA f_a, FtorB f_b) {
|
||||
return less2_t<FtorA,FtorB>(f_a,f_b);
|
||||
}
|
||||
|
||||
template <typename Type, typename Ftor>
|
||||
struct _greater {
|
||||
typedef bool result_type;
|
||||
|
||||
_greater(Type t, Ftor f) : m_t(t), m_f(f) {}
|
||||
|
||||
template <typename Arg>
|
||||
bool operator () (Arg& a) {
|
||||
return m_t > m_f(a);
|
||||
}
|
||||
|
||||
Type m_t;
|
||||
Ftor m_f;
|
||||
};
|
||||
|
||||
template <typename Type, typename Ftor>
|
||||
inline _greater<Type, Ftor>
|
||||
greater(Type t, Ftor f) {
|
||||
return _greater<Type, Ftor>(t, f);
|
||||
}
|
||||
|
||||
template <typename FtorA, typename FtorB>
|
||||
struct greater2_t : public std::binary_function<typename FtorA::argument_type, typename FtorB::argument_type, bool> {
|
||||
greater2_t(FtorA f_a, FtorB f_b) : m_f_a(f_a), m_f_b(f_b) {}
|
||||
|
||||
bool operator () (typename FtorA::argument_type a, typename FtorB::argument_type b) {
|
||||
return m_f_a(a) > m_f_b(b);
|
||||
}
|
||||
|
||||
FtorA m_f_a;
|
||||
FtorB m_f_b;
|
||||
};
|
||||
|
||||
template <typename FtorA, typename FtorB>
|
||||
inline greater2_t<FtorA, FtorB>
|
||||
greater2(FtorA f_a, FtorB f_b) {
|
||||
return greater2_t<FtorA,FtorB>(f_a,f_b);
|
||||
}
|
||||
|
||||
template <typename Type, typename Ftor>
|
||||
struct less_equal_t {
|
||||
typedef bool result_type;
|
||||
|
||||
less_equal_t(Type t, Ftor f) : m_t(t), m_f(f) {}
|
||||
|
||||
template <typename Arg>
|
||||
bool operator () (Arg& a) {
|
||||
return m_t <= m_f(a);
|
||||
}
|
||||
|
||||
Type m_t;
|
||||
Ftor m_f;
|
||||
};
|
||||
|
||||
template <typename Type, typename Ftor>
|
||||
inline less_equal_t<Type, Ftor>
|
||||
less_equal(Type t, Ftor f) {
|
||||
return less_equal_t<Type, Ftor>(t, f);
|
||||
}
|
||||
|
||||
template <typename Type, typename Ftor>
|
||||
struct greater_equal_t {
|
||||
typedef bool result_type;
|
||||
|
||||
greater_equal_t(Type t, Ftor f) : m_t(t), m_f(f) {}
|
||||
|
||||
template <typename Arg>
|
||||
bool operator () (Arg& a) {
|
||||
return m_t >= m_f(a);
|
||||
}
|
||||
|
||||
Type m_t;
|
||||
Ftor m_f;
|
||||
};
|
||||
|
||||
template <typename Type, typename Ftor>
|
||||
inline greater_equal_t<Type, Ftor>
|
||||
greater_equal(Type t, Ftor f) {
|
||||
return greater_equal_t<Type, Ftor>(t, f);
|
||||
}
|
||||
|
||||
template<typename Tp>
|
||||
struct invert : public std::unary_function<Tp, Tp> {
|
||||
Tp
|
||||
operator () (const Tp& x) const { return ~x; }
|
||||
};
|
||||
|
||||
template <typename Src, typename Dest>
|
||||
struct on_t : public std::unary_function<typename Src::argument_type, typename Dest::result_type> {
|
||||
typedef typename Dest::result_type result_type;
|
||||
|
||||
on_t(Src s, Dest d) : m_dest(d), m_src(s) {}
|
||||
|
||||
result_type operator () (typename reference_fix<typename Src::argument_type>::type arg) {
|
||||
return m_dest(m_src(arg));
|
||||
}
|
||||
|
||||
Dest m_dest;
|
||||
Src m_src;
|
||||
};
|
||||
|
||||
template <typename Src, typename Dest>
|
||||
inline on_t<Src, Dest>
|
||||
on(Src s, Dest d) {
|
||||
return on_t<Src, Dest>(s, d);
|
||||
}
|
||||
|
||||
template <typename Src, typename Dest>
|
||||
struct on2_t : public std::binary_function<typename Src::argument_type, typename Dest::second_argument_type, typename Dest::result_type> {
|
||||
typedef typename Dest::result_type result_type;
|
||||
|
||||
on2_t(Src s, Dest d) : m_dest(d), m_src(s) {}
|
||||
|
||||
result_type operator () (typename reference_fix<typename Src::argument_type>::type first, typename reference_fix<typename Dest::second_argument_type>::type second) {
|
||||
return m_dest(m_src(first), second);
|
||||
}
|
||||
|
||||
Dest m_dest;
|
||||
Src m_src;
|
||||
};
|
||||
|
||||
template <typename Src, typename Dest>
|
||||
inline on2_t<Src, Dest>
|
||||
on2(Src s, Dest d) {
|
||||
return on2_t<Src, Dest>(s, d);
|
||||
}
|
||||
|
||||
// Creates a functor for accessing a member.
|
||||
template <typename Class, typename Member>
|
||||
struct mem_ptr_t : public std::unary_function<Class*, Member&> {
|
||||
mem_ptr_t(Member Class::*m) : m_member(m) {}
|
||||
|
||||
Member& operator () (Class* c) {
|
||||
return c->*m_member;
|
||||
}
|
||||
|
||||
const Member& operator () (const Class* c) {
|
||||
return c->*m_member;
|
||||
}
|
||||
|
||||
Member Class::*m_member;
|
||||
};
|
||||
|
||||
template <typename Class, typename Member>
|
||||
inline mem_ptr_t<Class, Member>
|
||||
mem_ptr(Member Class::*m) {
|
||||
return mem_ptr_t<Class, Member>(m);
|
||||
}
|
||||
|
||||
template <typename Class, typename Member>
|
||||
struct mem_ref_t : public std::unary_function<Class&, Member&> {
|
||||
mem_ref_t(Member Class::*m) : m_member(m) {}
|
||||
|
||||
Member& operator () (Class& c) {
|
||||
return c.*m_member;
|
||||
}
|
||||
|
||||
Member Class::*m_member;
|
||||
};
|
||||
|
||||
template <typename Class, typename Member>
|
||||
struct const_mem_ref_t : public std::unary_function<const Class&, const Member&> {
|
||||
const_mem_ref_t(const Member Class::*m) : m_member(m) {}
|
||||
|
||||
const Member& operator () (const Class& c) {
|
||||
return c.*m_member;
|
||||
}
|
||||
|
||||
const Member Class::*m_member;
|
||||
};
|
||||
|
||||
template <typename Class, typename Member>
|
||||
inline mem_ref_t<Class, Member>
|
||||
mem_ref(Member Class::*m) {
|
||||
return mem_ref_t<Class, Member>(m);
|
||||
}
|
||||
|
||||
template <typename Class, typename Member>
|
||||
inline const_mem_ref_t<Class, Member>
|
||||
const_mem_ref(const Member Class::*m) {
|
||||
return const_mem_ref_t<Class, Member>(m);
|
||||
}
|
||||
|
||||
template <typename Cond, typename Then>
|
||||
struct if_then_t {
|
||||
if_then_t(Cond c, Then t) : m_cond(c), m_then(t) {}
|
||||
|
||||
template <typename Arg>
|
||||
void operator () (Arg& a) {
|
||||
if (m_cond(a))
|
||||
m_then(a);
|
||||
}
|
||||
|
||||
Cond m_cond;
|
||||
Then m_then;
|
||||
};
|
||||
|
||||
template <typename Cond, typename Then>
|
||||
inline if_then_t<Cond, Then>
|
||||
if_then(Cond c, Then t) {
|
||||
return if_then_t<Cond, Then>(c, t);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct call_delete : public std::unary_function<T*, void> {
|
||||
void operator () (T* t) {
|
||||
delete t;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline void
|
||||
call_delete_func(T* t) {
|
||||
delete t;
|
||||
}
|
||||
|
||||
template <typename Operation>
|
||||
class bind1st_t : public std::unary_function<typename Operation::second_argument_type, typename Operation::result_type> {
|
||||
public:
|
||||
typedef typename reference_fix<typename Operation::first_argument_type>::type value_type;
|
||||
typedef typename reference_fix<typename Operation::second_argument_type>::type argument_type;
|
||||
|
||||
bind1st_t(const Operation& op, const value_type v) :
|
||||
m_op(op), m_value(v) {}
|
||||
|
||||
typename Operation::result_type
|
||||
operator () (const argument_type arg) {
|
||||
return m_op(m_value, arg);
|
||||
}
|
||||
|
||||
protected:
|
||||
Operation m_op;
|
||||
value_type m_value;
|
||||
};
|
||||
|
||||
template <typename Operation, typename Type>
|
||||
inline bind1st_t<Operation>
|
||||
bind1st(const Operation& op, const Type& val) {
|
||||
return bind1st_t<Operation>(op, val);
|
||||
}
|
||||
|
||||
template <typename Operation>
|
||||
class bind2nd_t : public std::unary_function<typename Operation::first_argument_type, typename Operation::result_type> {
|
||||
public:
|
||||
typedef typename reference_fix<typename Operation::first_argument_type>::type argument_type;
|
||||
typedef typename reference_fix<typename Operation::second_argument_type>::type value_type;
|
||||
|
||||
bind2nd_t(const Operation& op, const value_type v) :
|
||||
m_op(op), m_value(v) {}
|
||||
|
||||
typename Operation::result_type
|
||||
operator () (argument_type arg) {
|
||||
return m_op(arg, m_value);
|
||||
}
|
||||
|
||||
protected:
|
||||
Operation m_op;
|
||||
value_type m_value;
|
||||
};
|
||||
|
||||
template <typename Operation, typename Type>
|
||||
inline bind2nd_t<Operation>
|
||||
bind2nd(const Operation& op, const Type& val) {
|
||||
return bind2nd_t<Operation>(op, val);
|
||||
}
|
||||
|
||||
// Lightweight callback function including pointer to object. Should
|
||||
// be replaced by TR1 stuff later. Requires an object to bind, instead
|
||||
// of using a seperate functor for that.
|
||||
|
||||
template <typename Ret>
|
||||
class ptr_fun0 {
|
||||
public:
|
||||
typedef Ret result_type;
|
||||
typedef Ret (*Function)();
|
||||
|
||||
ptr_fun0() {}
|
||||
ptr_fun0(Function f) : m_function(f) {}
|
||||
|
||||
bool is_valid() const { return m_function; }
|
||||
|
||||
Ret operator () () { return m_function(); }
|
||||
|
||||
private:
|
||||
Function m_function;
|
||||
};
|
||||
|
||||
template <typename Object, typename Ret>
|
||||
class mem_fun0 {
|
||||
public:
|
||||
typedef Ret result_type;
|
||||
typedef Ret (Object::*Function)();
|
||||
|
||||
mem_fun0() : m_object(NULL) {}
|
||||
mem_fun0(Object* o, Function f) : m_object(o), m_function(f) {}
|
||||
|
||||
bool is_valid() const { return m_object; }
|
||||
|
||||
Ret operator () () { return (m_object->*m_function)(); }
|
||||
|
||||
private:
|
||||
Object* m_object;
|
||||
Function m_function;
|
||||
};
|
||||
|
||||
template <typename Object, typename Ret>
|
||||
class const_mem_fun0 {
|
||||
public:
|
||||
typedef Ret result_type;
|
||||
typedef Ret (Object::*Function)() const;
|
||||
|
||||
const_mem_fun0() : m_object(NULL) {}
|
||||
const_mem_fun0(const Object* o, Function f) : m_object(o), m_function(f) {}
|
||||
|
||||
bool is_valid() const { return m_object; }
|
||||
|
||||
Ret operator () () const { return (m_object->*m_function)(); }
|
||||
|
||||
private:
|
||||
const Object* m_object;
|
||||
Function m_function;
|
||||
};
|
||||
|
||||
template <typename Object, typename Ret, typename Arg1>
|
||||
class mem_fun1 {
|
||||
public:
|
||||
typedef Ret result_type;
|
||||
typedef Ret (Object::*Function)(Arg1);
|
||||
|
||||
mem_fun1() : m_object(NULL) {}
|
||||
mem_fun1(Object* o, Function f) : m_object(o), m_function(f) {}
|
||||
|
||||
bool is_valid() const { return m_object; }
|
||||
|
||||
Ret operator () (Arg1 a1) { return (m_object->*m_function)(a1); }
|
||||
|
||||
private:
|
||||
Object* m_object;
|
||||
Function m_function;
|
||||
};
|
||||
|
||||
template <typename Object, typename Ret, typename Arg1>
|
||||
class const_mem_fun1 {
|
||||
public:
|
||||
typedef Ret result_type;
|
||||
typedef Ret (Object::*Function)(Arg1) const;
|
||||
|
||||
const_mem_fun1() : m_object(NULL) {}
|
||||
const_mem_fun1(const Object* o, Function f) : m_object(o), m_function(f) {}
|
||||
|
||||
bool is_valid() const { return m_object; }
|
||||
|
||||
Ret operator () (Arg1 a1) const { return (m_object->*m_function)(a1); }
|
||||
|
||||
private:
|
||||
const Object* m_object;
|
||||
Function m_function;
|
||||
};
|
||||
|
||||
template <typename Object, typename Ret, typename Arg1, typename Arg2>
|
||||
class mem_fun2 : public std::binary_function<Arg1, Arg2, Ret> {
|
||||
public:
|
||||
typedef Ret result_type;
|
||||
typedef Ret (Object::*Function)(Arg1, Arg2);
|
||||
typedef Object object_type;
|
||||
|
||||
mem_fun2() : m_object(NULL) {}
|
||||
mem_fun2(Object* o, Function f) : m_object(o), m_function(f) {}
|
||||
|
||||
bool is_valid() const { return m_object; }
|
||||
|
||||
object_type* object() { return m_object; }
|
||||
const object_type* object() const { return m_object; }
|
||||
|
||||
Ret operator () (Arg1 a1, Arg2 a2) { return (m_object->*m_function)(a1, a2); }
|
||||
|
||||
private:
|
||||
Object* m_object;
|
||||
Function m_function;
|
||||
};
|
||||
|
||||
template <typename Object, typename Ret, typename Arg1, typename Arg2, typename Arg3>
|
||||
class mem_fun3 {
|
||||
public:
|
||||
typedef Ret result_type;
|
||||
typedef Ret (Object::*Function)(Arg1, Arg2, Arg3);
|
||||
|
||||
mem_fun3() : m_object(NULL) {}
|
||||
mem_fun3(Object* o, Function f) : m_object(o), m_function(f) {}
|
||||
|
||||
bool is_valid() const { return m_object; }
|
||||
|
||||
Ret operator () (Arg1 a1, Arg2 a2, Arg3 a3) { return (m_object->*m_function)(a1, a2, a3); }
|
||||
|
||||
private:
|
||||
Object* m_object;
|
||||
Function m_function;
|
||||
};
|
||||
|
||||
template <typename Ret>
|
||||
inline ptr_fun0<Ret>
|
||||
ptr_fun(Ret (*f)()) { return ptr_fun0<Ret>(f); }
|
||||
|
||||
template <typename Object, typename Ret>
|
||||
inline mem_fun0<Object, Ret>
|
||||
make_mem_fun(Object* o, Ret (Object::*f)()) {
|
||||
return mem_fun0<Object, Ret>(o, f);
|
||||
}
|
||||
|
||||
template <typename Object, typename Ret>
|
||||
inline const_mem_fun0<Object, Ret>
|
||||
make_mem_fun(const Object* o, Ret (Object::*f)() const) {
|
||||
return const_mem_fun0<Object, Ret>(o, f);
|
||||
}
|
||||
|
||||
template <typename Object, typename Ret, typename Arg1>
|
||||
inline mem_fun1<Object, Ret, Arg1>
|
||||
make_mem_fun(Object* o, Ret (Object::*f)(Arg1)) {
|
||||
return mem_fun1<Object, Ret, Arg1>(o, f);
|
||||
}
|
||||
|
||||
template <typename Object, typename Ret, typename Arg1>
|
||||
inline const_mem_fun1<Object, Ret, Arg1>
|
||||
make_mem_fun(const Object* o, Ret (Object::*f)(Arg1) const) {
|
||||
return const_mem_fun1<Object, Ret, Arg1>(o, f);
|
||||
}
|
||||
|
||||
template <typename Object, typename Ret, typename Arg1, typename Arg2>
|
||||
inline mem_fun2<Object, Ret, Arg1, Arg2>
|
||||
make_mem_fun(Object* o, Ret (Object::*f)(Arg1, Arg2)) {
|
||||
return mem_fun2<Object, Ret, Arg1, Arg2>(o, f);
|
||||
}
|
||||
|
||||
template <typename Object, typename Ret, typename Arg1, typename Arg2, typename Arg3>
|
||||
inline mem_fun3<Object, Ret, Arg1, Arg2, Arg3>
|
||||
make_mem_fun(Object* o, Ret (Object::*f)(Arg1, Arg2, Arg3)) {
|
||||
return mem_fun3<Object, Ret, Arg1, Arg2, Arg3>(o, f);
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
inline void
|
||||
slot_list_call(const Container& slot_list) {
|
||||
if (slot_list.empty())
|
||||
return;
|
||||
|
||||
typename Container::const_iterator first = slot_list.begin();
|
||||
typename Container::const_iterator next = slot_list.begin();
|
||||
|
||||
while (++next != slot_list.end()) {
|
||||
(*first)();
|
||||
first = next;
|
||||
}
|
||||
|
||||
(*first)();
|
||||
}
|
||||
|
||||
template <typename Container, typename Arg1>
|
||||
inline void
|
||||
slot_list_call(const Container& slot_list, Arg1 arg1) {
|
||||
if (slot_list.empty())
|
||||
return;
|
||||
|
||||
typename Container::const_iterator first = slot_list.begin();
|
||||
typename Container::const_iterator next = slot_list.begin();
|
||||
|
||||
while (++next != slot_list.end()) {
|
||||
(*first)(arg1);
|
||||
first = next;
|
||||
}
|
||||
|
||||
(*first)(arg1);
|
||||
}
|
||||
|
||||
template <typename Container, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
|
||||
inline void
|
||||
slot_list_call(const Container& slot_list, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) {
|
||||
if (slot_list.empty())
|
||||
return;
|
||||
|
||||
typename Container::const_iterator first = slot_list.begin();
|
||||
typename Container::const_iterator next = slot_list.begin();
|
||||
|
||||
while (++next != slot_list.end()) {
|
||||
(*first)(arg1, arg2, arg3, arg4);
|
||||
first = next;
|
||||
}
|
||||
|
||||
(*first)(arg1, arg2, arg3, arg4);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -50,7 +50,7 @@
|
||||
|
||||
namespace rak {
|
||||
|
||||
class regex : public std::unary_function<std::string, bool> {
|
||||
class regex : public std::function<bool (std::string)> {
|
||||
public:
|
||||
regex() {}
|
||||
regex(const std::string& p) : m_pattern(p) {}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
-- the "rtorrent" table is passed in by the C++ code, modify and
|
||||
-- return it for loading.
|
||||
local args = {...}
|
||||
local rtorrent = args[1]
|
||||
|
||||
-- Autocall
|
||||
-- Allows syntax like `rtorrent.autocall.system.hostname()`
|
||||
local mt = {}
|
||||
function mt.__call (t, ...)
|
||||
name = table.concat(rawget(t, "__namestack"), ".")
|
||||
success, ret = pcall(rtorrent.call, name, ...)
|
||||
if not success then error(name..": "..ret, 2) end
|
||||
return ret
|
||||
end
|
||||
function mt.__index (t, key)
|
||||
ns = rawget(t, "__namestack") or {}
|
||||
table.insert(ns, key)
|
||||
return setmetatable({__namestack=ns}, mt)
|
||||
end
|
||||
rtorrent["autocall"] = setmetatable({}, mt)
|
||||
|
||||
-- Autocall-config Same as autocall, but passes an empty first target
|
||||
-- implicitly, for syntax like `rtorrent.autocall_config.session.directory.set("/tmp/")`
|
||||
local mt = {}
|
||||
function mt.__call (t, ...)
|
||||
name = table.concat(rawget(t, "__namestack"), ".")
|
||||
success, ret = pcall(rtorrent.call, name, "", ...)
|
||||
if not success then error(name..": "..ret, 2) end
|
||||
return ret
|
||||
end
|
||||
function mt.__index (t, key)
|
||||
ns = rawget(t, "__namestack")
|
||||
if ns == nil then
|
||||
if _G[key] ~= nil then return _G[key] end
|
||||
ns = {}
|
||||
end
|
||||
table.insert(ns, key)
|
||||
return setmetatable({__namestack=ns}, mt)
|
||||
end
|
||||
rtorrent["autocall_config"] = setmetatable({}, mt)
|
||||
|
||||
return rtorrent
|
||||
@@ -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
@@ -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
@@ -13,7 +13,7 @@ AC_DEFUN([TORRENT_WITH_SYSROOT], [
|
||||
AC_MSG_ERROR(The sysroot option must point to a directory, like f.ex "/Developer/SDKs/MacOSX10.4u.sdk".)
|
||||
else
|
||||
AC_MSG_RESULT($withval)
|
||||
|
||||
|
||||
CXXFLAGS="$CXXFLAGS -isysroot $withval"
|
||||
LDFLAGS="$LDFLAGS -Wl,-syslibroot,$withval"
|
||||
fi
|
||||
@@ -21,6 +21,19 @@ AC_DEFUN([TORRENT_WITH_SYSROOT], [
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN([TORRENT_REMOVE_UNWANTED],
|
||||
[
|
||||
values_to_check=`for i in $2; do echo $i; done`
|
||||
unwanted_values=`for i in $3; do echo $i; done`
|
||||
if test -z "${unwanted_values}"; then
|
||||
$1="$2"
|
||||
else
|
||||
result=`echo "${values_to_check}" | $GREP -Fvx -- "${unwanted_values}" | $GREP -v '^$'`
|
||||
$1=${result//$'\n'/ }
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN([TORRENT_ENABLE_ARCH], [
|
||||
AC_ARG_ENABLE(arch,
|
||||
AS_HELP_STRING([--enable-arch=ARCH],
|
||||
|
||||
@@ -37,6 +37,7 @@ libsub_root_a_SOURCES = \
|
||||
display/attributes.h \
|
||||
display/canvas.cc \
|
||||
display/canvas.h \
|
||||
display/color_map.h \
|
||||
display/frame.cc \
|
||||
display/frame.h \
|
||||
display/manager.cc \
|
||||
@@ -107,6 +108,12 @@ libsub_root_a_SOURCES = \
|
||||
rpc/exec_file.h \
|
||||
rpc/fixed_key.h \
|
||||
rpc/ip_table_list.h \
|
||||
rpc/lua.h \
|
||||
rpc/lua.cc \
|
||||
rpc/jsonrpc.cc \
|
||||
rpc/jsonrpc.h \
|
||||
rpc/rpc_manager.cc \
|
||||
rpc/rpc_manager.h \
|
||||
rpc/object_storage.cc \
|
||||
rpc/object_storage.h \
|
||||
rpc/parse.cc \
|
||||
@@ -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
@@ -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));
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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));
|
||||
|
||||
|
||||
@@ -142,5 +142,6 @@ initialize_command_logging() {
|
||||
|
||||
CMD2_ANY_STRING ("log.execute", std::bind(&apply_log, std::placeholders::_2, 0));
|
||||
CMD2_ANY_STRING ("log.vmmap.dump", std::bind(&log_vmmap_dump, std::placeholders::_2));
|
||||
CMD2_ANY_STRING_V("log.xmlrpc", std::bind(&ThreadWorker::set_xmlrpc_log, worker_thread, std::placeholders::_2));
|
||||
CMD2_ANY_STRING_V("log.rpc", std::bind(&ThreadWorker::set_rpc_log, worker_thread, std::placeholders::_2));
|
||||
CMD2_REDIRECT ("log.xmlrpc", "log.rpc"); // For backwards compatibility
|
||||
}
|
||||
|
||||
+38
-79
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <functional>
|
||||
@@ -42,8 +6,8 @@
|
||||
#include <rak/address_info.h>
|
||||
#include <rak/path.h>
|
||||
#include <torrent/connection_manager.h>
|
||||
#include <torrent/tracker.h>
|
||||
#include <torrent/tracker_list.h>
|
||||
#include <torrent/tracker/tracker.h>
|
||||
#include <torrent/torrent.h>
|
||||
#include <torrent/rate.h>
|
||||
#include <torrent/data/file_manager.h>
|
||||
@@ -94,51 +58,44 @@ apply_tos(const torrent::Object::string_type& arg) {
|
||||
|
||||
torrent::Object apply_encoding_list(const std::string& arg) { torrent::encoding_list()->push_back(arg); return torrent::Object(); }
|
||||
|
||||
torrent::File*
|
||||
xmlrpc_find_file(core::Download* download, uint32_t index) {
|
||||
if (index >= download->file_list()->size_files())
|
||||
return NULL;
|
||||
|
||||
return (*download->file_list())[index];
|
||||
}
|
||||
|
||||
// Ergh... time to update the Tracker API to allow proper ptrs.
|
||||
torrent::Tracker*
|
||||
xmlrpc_find_tracker(core::Download* download, uint32_t index) {
|
||||
if (index >= download->tracker_list()->size())
|
||||
return NULL;
|
||||
|
||||
return download->tracker_list()->at(index);
|
||||
}
|
||||
|
||||
torrent::Peer*
|
||||
xmlrpc_find_peer(core::Download* download, const torrent::HashString& hash) {
|
||||
torrent::ConnectionList::iterator itr = download->connection_list()->find(hash.c_str());
|
||||
|
||||
if (itr == download->connection_list()->end())
|
||||
return NULL;
|
||||
|
||||
return *itr;
|
||||
}
|
||||
|
||||
void
|
||||
initialize_xmlrpc() {
|
||||
rpc::xmlrpc.initialize();
|
||||
rpc::xmlrpc.slot_find_download() = std::bind(&core::DownloadList::find_hex_ptr, control->core()->download_list(), std::placeholders::_1);
|
||||
rpc::xmlrpc.slot_find_file() = std::bind(&xmlrpc_find_file, std::placeholders::_1, std::placeholders::_2);
|
||||
rpc::xmlrpc.slot_find_tracker() = std::bind(&xmlrpc_find_tracker, std::placeholders::_1, std::placeholders::_2);
|
||||
rpc::xmlrpc.slot_find_peer() = std::bind(&xmlrpc_find_peer, std::placeholders::_1, std::placeholders::_2);
|
||||
initialize_rpc() {
|
||||
rpc::rpc.initialize();
|
||||
|
||||
rpc::rpc.slot_find_download() = [](const char* hash) {
|
||||
return control->core()->download_list()->find_hex_ptr(hash);
|
||||
};
|
||||
rpc::rpc.slot_find_file() = [](core::Download* d, uint32_t index) -> torrent::File* {
|
||||
if (index >= d->file_list()->size_files())
|
||||
throw torrent::input_error("invalid parameters: index not found");
|
||||
|
||||
return (*d->file_list())[index].get();
|
||||
};
|
||||
rpc::rpc.slot_find_tracker() = [](core::Download* d, uint32_t index) -> torrent::tracker::Tracker {
|
||||
if (index >= d->tracker_list()->size())
|
||||
throw torrent::input_error("invalid parameters: index not found");
|
||||
|
||||
return d->tracker_list()->at(index);
|
||||
};
|
||||
rpc::rpc.slot_find_peer() = [](core::Download* d, const torrent::HashString& hash) -> torrent::Peer* {
|
||||
auto itr = d->connection_list()->find(hash.c_str());
|
||||
|
||||
if (itr == d->connection_list()->end())
|
||||
throw torrent::input_error("invalid parameters: hash not found");
|
||||
|
||||
return *itr;
|
||||
};
|
||||
|
||||
unsigned int count = 0;
|
||||
|
||||
for (rpc::CommandMap::const_iterator itr = rpc::commands.begin(), last = rpc::commands.end(); itr != last; itr++, count++) {
|
||||
if (!(itr->second.m_flags & rpc::CommandMap::flag_public_xmlrpc))
|
||||
if (!(itr->second.m_flags & rpc::CommandMap::flag_public_rpc))
|
||||
continue;
|
||||
|
||||
rpc::xmlrpc.insert_command(itr->first.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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -1,47 +1,11 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <torrent/object.h>
|
||||
#include <torrent/dht_manager.h>
|
||||
#include <torrent/object_stream.h>
|
||||
#include <torrent/rate.h>
|
||||
#include <torrent/tracker/dht_controller.h>
|
||||
#include <torrent/utils/log.h>
|
||||
|
||||
#include "rpc/parse_commands.h"
|
||||
@@ -94,7 +58,7 @@ DhtManager::load_dht_cache() {
|
||||
LT_LOG_THIS("could not open cache file (path:%s)", cache_filename.c_str());
|
||||
}
|
||||
|
||||
torrent::dht_manager()->initialize(cache);
|
||||
torrent::dht_controller()->initialize(cache);
|
||||
|
||||
if (m_start == dht_on)
|
||||
start_dht();
|
||||
@@ -104,31 +68,31 @@ void
|
||||
DhtManager::start_dht() {
|
||||
priority_queue_erase(&taskScheduler, &m_stopTimeout);
|
||||
|
||||
if (!torrent::dht_manager()->is_valid()) {
|
||||
if (!torrent::dht_controller()->is_valid()) {
|
||||
LT_LOG_THIS("server start skipped, manager is uninitialized", 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (torrent::dht_manager()->is_active()) {
|
||||
if (torrent::dht_controller()->is_active()) {
|
||||
LT_LOG_THIS("server start skipped, already active", 0);
|
||||
return;
|
||||
}
|
||||
|
||||
torrent::ThrottlePair throttles = control->core()->get_throttle(m_throttleName);
|
||||
torrent::dht_manager()->set_upload_throttle(throttles.first);
|
||||
torrent::dht_manager()->set_download_throttle(throttles.second);
|
||||
torrent::dht_controller()->set_upload_throttle(throttles.first);
|
||||
torrent::dht_controller()->set_download_throttle(throttles.second);
|
||||
|
||||
int port = rpc::call_command_value("dht.port");
|
||||
|
||||
if (port <= 0)
|
||||
return;
|
||||
|
||||
if (!torrent::dht_manager()->start(port)) {
|
||||
if (!torrent::dht_controller()->start(port)) {
|
||||
m_start = dht_off;
|
||||
return;
|
||||
}
|
||||
|
||||
torrent::dht_manager()->reset_statistics();
|
||||
torrent::dht_controller()->reset_statistics();
|
||||
|
||||
m_updateTimeout.slot() = std::bind(&DhtManager::update, this);
|
||||
priority_queue_insert(&taskScheduler, &m_updateTimeout, (cachedTime + rak::timer::from_seconds(60)).round_seconds());
|
||||
@@ -146,17 +110,17 @@ DhtManager::stop_dht() {
|
||||
priority_queue_erase(&taskScheduler, &m_updateTimeout);
|
||||
priority_queue_erase(&taskScheduler, &m_stopTimeout);
|
||||
|
||||
if (torrent::dht_manager()->is_active()) {
|
||||
if (torrent::dht_controller()->is_active()) {
|
||||
LT_LOG_THIS("stopping server", 0);
|
||||
|
||||
log_statistics(true);
|
||||
torrent::dht_manager()->stop();
|
||||
torrent::dht_controller()->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DhtManager::save_dht_cache() {
|
||||
if (!control->core()->download_store()->is_enabled() || !torrent::dht_manager()->is_valid())
|
||||
if (!control->core()->download_store()->is_enabled() || !torrent::dht_controller()->is_valid())
|
||||
return;
|
||||
|
||||
std::string filename = control->core()->download_store()->path() + "rtorrent.dht_cache";
|
||||
@@ -167,7 +131,7 @@ DhtManager::save_dht_cache() {
|
||||
return;
|
||||
|
||||
torrent::Object cache = torrent::Object::create_map();
|
||||
cache_file << *torrent::dht_manager()->store_cache(&cache);
|
||||
cache_file << *torrent::dht_controller()->store_cache(&cache);
|
||||
|
||||
if (!cache_file.good())
|
||||
return;
|
||||
@@ -198,7 +162,7 @@ DhtManager::set_mode(const std::string& arg) {
|
||||
|
||||
void
|
||||
DhtManager::update() {
|
||||
if (!torrent::dht_manager()->is_active())
|
||||
if (!torrent::dht_controller()->is_active())
|
||||
throw torrent::internal_error("DhtManager::update called with DHT inactive.");
|
||||
|
||||
if (m_start == dht_auto && !m_stopTimeout.is_queued()) {
|
||||
@@ -207,7 +171,7 @@ DhtManager::update() {
|
||||
for (itr = control->core()->download_list()->begin(), end = control->core()->download_list()->end(); itr != end; ++itr)
|
||||
if ((*itr)->download()->info()->is_active() && !(*itr)->download()->info()->is_private())
|
||||
break;
|
||||
|
||||
|
||||
if (itr == end) {
|
||||
m_stopTimeout.slot() = std::bind(&DhtManager::stop_dht, this);
|
||||
priority_queue_insert(&taskScheduler, &m_stopTimeout, (cachedTime + rak::timer::from_seconds(15 * 60)).round_seconds());
|
||||
@@ -223,17 +187,17 @@ DhtManager::update() {
|
||||
|
||||
bool
|
||||
DhtManager::log_statistics(bool force) {
|
||||
torrent::DhtManager::statistics_type stats = torrent::dht_manager()->get_statistics();
|
||||
auto stats = torrent::dht_controller()->get_statistics();
|
||||
|
||||
// Check for firewall problems.
|
||||
|
||||
if (stats.cycle > 2 && stats.queries_sent - m_dhtPrevQueriesSent > 100 && stats.queries_received == m_dhtPrevQueriesReceived) {
|
||||
// We should have had clients ping us at least but have received
|
||||
// nothing, that means the UDP port is probably unreachable.
|
||||
if (torrent::dht_manager()->can_receive_queries())
|
||||
if (torrent::dht_controller()->is_receiving_requests())
|
||||
LT_LOG_THIS("listening port appears to be unreachable, no queries received", 0);
|
||||
|
||||
torrent::dht_manager()->set_can_receive(false);
|
||||
torrent::dht_controller()->set_receive_requests(false);
|
||||
}
|
||||
|
||||
if (stats.queries_sent - m_dhtPrevQueriesSent > stats.num_nodes * 2 + 20 && stats.replies_received == m_dhtPrevRepliesReceived) {
|
||||
@@ -248,7 +212,7 @@ DhtManager::log_statistics(bool force) {
|
||||
m_warned = false;
|
||||
|
||||
if (stats.queries_received > m_dhtPrevQueriesReceived)
|
||||
torrent::dht_manager()->set_can_receive(true);
|
||||
torrent::dht_controller()->set_receive_requests(true);
|
||||
|
||||
// Nothing to log while bootstrapping, but check again every minute.
|
||||
if (stats.cycle <= 1) {
|
||||
@@ -269,7 +233,7 @@ DhtManager::log_statistics(bool force) {
|
||||
// afterwards (i.e. every 2 hours), or when forced.
|
||||
if ((force && stats.cycle != m_dhtPrevCycle) || stats.cycle == 3 || stats.cycle > m_dhtPrevCycle + 7) {
|
||||
char buffer[256];
|
||||
snprintf(buffer, sizeof(buffer),
|
||||
snprintf(buffer, sizeof(buffer),
|
||||
"DHT statistics: %d queries in, %d queries out, %d replies received, %lld bytes read, %lld bytes sent, "
|
||||
"%d known nodes in %d buckets, %d peers (highest: %d) tracked in %d torrents.",
|
||||
stats.queries_received - m_dhtPrevQueriesReceived,
|
||||
@@ -301,11 +265,11 @@ DhtManager::dht_statistics() {
|
||||
torrent::Object dhtStats = torrent::Object::create_map();
|
||||
|
||||
dhtStats.insert_key("dht", dht_settings[m_start]);
|
||||
dhtStats.insert_key("active", torrent::dht_manager()->is_active());
|
||||
dhtStats.insert_key("active", torrent::dht_controller()->is_active());
|
||||
dhtStats.insert_key("throttle", m_throttleName);
|
||||
|
||||
if (torrent::dht_manager()->is_active()) {
|
||||
torrent::DhtManager::statistics_type stats = torrent::dht_manager()->get_statistics();
|
||||
if (torrent::dht_controller()->is_active()) {
|
||||
auto stats = torrent::dht_controller()->get_statistics();
|
||||
|
||||
dhtStats.insert_key("cycle", stats.cycle);
|
||||
dhtStats.insert_key("queries_received", stats.queries_received);
|
||||
@@ -327,7 +291,7 @@ DhtManager::dht_statistics() {
|
||||
|
||||
void
|
||||
DhtManager::set_throttle_name(const std::string& throttleName) {
|
||||
if (torrent::dht_manager()->is_active())
|
||||
if (torrent::dht_controller()->is_active())
|
||||
throw torrent::input_error("Cannot set DHT throttle while active.");
|
||||
|
||||
m_throttleName = throttleName;
|
||||
|
||||
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RTORRENT_CORE_DHT_MANAGER_H
|
||||
#define RTORRENT_CORE_DHT_MANAGER_H
|
||||
|
||||
|
||||
+4
-41
@@ -1,50 +1,13 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <list>
|
||||
#include <rak/file_stat.h>
|
||||
#include <rak/functional.h>
|
||||
#include <rak/path.h>
|
||||
#include <torrent/exceptions.h>
|
||||
#include <torrent/rate.h>
|
||||
#include <torrent/torrent.h>
|
||||
#include <torrent/tracker.h>
|
||||
#include <torrent/tracker_list.h>
|
||||
#include <torrent/tracker/tracker.h>
|
||||
#include <torrent/data/file_list.h>
|
||||
|
||||
#include "rpc/parse_commands.h"
|
||||
@@ -76,11 +39,11 @@ Download::~Download() {
|
||||
void
|
||||
Download::enable_udp_trackers(bool state) {
|
||||
for (torrent::TrackerList::iterator itr = m_download.tracker_list()->begin(), last = m_download.tracker_list()->end(); itr != last; ++itr)
|
||||
if ((*itr)->type() == torrent::Tracker::TRACKER_UDP) {
|
||||
if (itr->type() == torrent::TRACKER_UDP) {
|
||||
if (state)
|
||||
(*itr)->enable();
|
||||
itr->enable();
|
||||
else
|
||||
(*itr)->disable();
|
||||
itr->disable();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-49
@@ -1,42 +1,7 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RTORRENT_CORE_DOWNLOAD_H
|
||||
#define RTORRENT_CORE_DOWNLOAD_H
|
||||
|
||||
#include <torrent/common.h>
|
||||
#include <torrent/download.h>
|
||||
#include <torrent/download_info.h>
|
||||
#include <torrent/hash_string.h>
|
||||
@@ -46,11 +11,6 @@
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
namespace torrent {
|
||||
class PeerList;
|
||||
class TrackerList;
|
||||
}
|
||||
|
||||
namespace core {
|
||||
|
||||
class Download {
|
||||
@@ -59,7 +19,6 @@ public:
|
||||
typedef torrent::FileList file_list_type;
|
||||
typedef torrent::PeerList peer_list_type;
|
||||
typedef torrent::TrackerList tracker_list_type;
|
||||
typedef torrent::TrackerController tracker_controller_type;
|
||||
typedef torrent::ConnectionList connection_list_type;
|
||||
typedef download_type::ConnectionType connection_type;
|
||||
|
||||
@@ -71,10 +30,10 @@ public:
|
||||
Download(download_type d);
|
||||
~Download();
|
||||
|
||||
const torrent::DownloadInfo* info() const { return m_download.info(); }
|
||||
const torrent::download_data* data() const { return m_download.data(); }
|
||||
auto info() const { return m_download.info(); }
|
||||
auto data() const { return m_download.data(); }
|
||||
|
||||
torrent::DownloadMain* main() { return m_download.main(); }
|
||||
auto main() { return m_download.main(); }
|
||||
|
||||
bool is_open() const { return m_download.info()->is_open(); }
|
||||
bool is_active() const { return m_download.info()->is_active(); }
|
||||
@@ -102,13 +61,12 @@ public:
|
||||
|
||||
torrent::Object* bencode() { return m_download.bencode(); }
|
||||
|
||||
auto tracker_controller() { return m_download.tracker_controller(); }
|
||||
tracker_list_type* tracker_list() { return m_download.tracker_list(); }
|
||||
uint32_t tracker_list_size() const { return m_download.tracker_list()->size(); }
|
||||
|
||||
tracker_controller_type* tracker_controller() { return m_download.tracker_controller(); }
|
||||
|
||||
connection_list_type* connection_list() { return m_download.connection_list(); }
|
||||
uint32_t connection_list_size() const;
|
||||
auto connection_list() { return m_download.connection_list(); }
|
||||
uint32_t connection_list_size() const;
|
||||
|
||||
const std::string& message() const { return m_message; }
|
||||
void set_message(const std::string& msg) { m_message = msg; }
|
||||
|
||||
@@ -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
@@ -1,45 +1,8 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <rak/functional.h>
|
||||
#include <rak/string_manip.h>
|
||||
#include <torrent/data/file.h>
|
||||
#include <torrent/utils/resume.h>
|
||||
@@ -71,7 +34,7 @@
|
||||
namespace core {
|
||||
|
||||
inline void
|
||||
DownloadList::check_contains(Download* d) {
|
||||
DownloadList::check_contains([[maybe_unused]] Download* d) {
|
||||
#ifdef USE_EXTRA_DEBUG
|
||||
if (std::find(begin(), end(), d) == end())
|
||||
throw torrent::internal_error("DownloadList::check_contains(...) failed.");
|
||||
@@ -80,15 +43,15 @@ DownloadList::check_contains(Download* d) {
|
||||
|
||||
void
|
||||
DownloadList::clear() {
|
||||
std::for_each(begin(), end(), std::bind1st(std::mem_fun(&DownloadList::close), this));
|
||||
std::for_each(begin(), end(), rak::call_delete<Download>());
|
||||
std::for_each(begin(), end(), [&](Download* d) { close(d); });
|
||||
std::for_each(begin(), end(), [](Download* d) { delete d; });
|
||||
|
||||
base_type::clear();
|
||||
}
|
||||
|
||||
void
|
||||
DownloadList::session_save() {
|
||||
unsigned int c = std::count_if(begin(), end(), std::bind1st(std::mem_fun(&DownloadStore::save_resume), control->core()->download_store()));
|
||||
unsigned int c = std::count_if(begin(), end(), [&](Download* d) { return control->core()->download_store()->save_resume(d); });
|
||||
|
||||
if (c != size())
|
||||
lt_log_print(torrent::LOG_ERROR, "Failed to save session torrents.");
|
||||
@@ -99,7 +62,7 @@ DownloadList::session_save() {
|
||||
|
||||
DownloadList::iterator
|
||||
DownloadList::find(const torrent::HashString& hash) {
|
||||
return std::find_if(begin(), end(), rak::equal(hash, rak::on(std::mem_fun(&Download::info), std::mem_fun(&torrent::DownloadInfo::hash))));
|
||||
return std::find_if(begin(), end(), [hash](Download* d) { return hash == d->info()->hash(); });
|
||||
}
|
||||
|
||||
DownloadList::iterator
|
||||
@@ -109,7 +72,7 @@ DownloadList::find_hex(const char* hash) {
|
||||
for (torrent::HashString::iterator itr = key.begin(), last = key.end(); itr != last; itr++, hash += 2)
|
||||
*itr = (rak::hexchar_to_value(*hash) << 4) + rak::hexchar_to_value(*(hash + 1));
|
||||
|
||||
return std::find_if(begin(), end(), rak::equal(key, rak::on(std::mem_fun(&Download::info), std::mem_fun(&torrent::DownloadInfo::hash))));
|
||||
return std::find_if(begin(), end(), [key](Download* d) { return key == d->info()->hash(); });
|
||||
}
|
||||
|
||||
Download*
|
||||
@@ -120,11 +83,11 @@ DownloadList::find_hex_ptr(const char* hash) {
|
||||
}
|
||||
|
||||
Download*
|
||||
DownloadList::create(torrent::Object* obj, bool printLog) {
|
||||
DownloadList::create(torrent::Object* obj, uint32_t tracker_key, bool printLog) {
|
||||
torrent::Download download;
|
||||
|
||||
try {
|
||||
download = torrent::download_add(obj);
|
||||
download = torrent::download_add(obj, tracker_key);
|
||||
|
||||
} catch (torrent::local_error& e) {
|
||||
delete obj;
|
||||
@@ -141,13 +104,13 @@ DownloadList::create(torrent::Object* obj, bool printLog) {
|
||||
}
|
||||
|
||||
Download*
|
||||
DownloadList::create(std::istream* str, bool printLog) {
|
||||
DownloadList::create(std::istream* str, uint32_t tracker_key, bool printLog) {
|
||||
torrent::Object* object = new torrent::Object;
|
||||
torrent::Download download;
|
||||
|
||||
try {
|
||||
*str >> *object;
|
||||
|
||||
|
||||
// Don't throw input_error from here as gcc-3.3.5 produces bad
|
||||
// code.
|
||||
if (str->fail()) {
|
||||
@@ -159,7 +122,7 @@ DownloadList::create(std::istream* str, bool printLog) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
download = torrent::download_add(object);
|
||||
download = torrent::download_add(object, tracker_key);
|
||||
|
||||
} catch (torrent::local_error& e) {
|
||||
delete object;
|
||||
@@ -187,8 +150,8 @@ DownloadList::insert(Download* download) {
|
||||
|
||||
// This needs to be separated into two different calls to ensure
|
||||
// the download remains in the view.
|
||||
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), std::bind2nd(std::mem_fun(&View::insert), download));
|
||||
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), std::bind2nd(std::mem_fun(&View::filter_download), download));
|
||||
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), [&download](View* v) { v->insert(download); });
|
||||
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), [&download](View* v) { v->filter_download(download); });
|
||||
|
||||
DL_TRIGGER_EVENT(*itr, "event.download.inserted");
|
||||
|
||||
@@ -221,7 +184,7 @@ DownloadList::erase(iterator itr) {
|
||||
control->core()->download_store()->remove(*itr);
|
||||
|
||||
DL_TRIGGER_EVENT(*itr, "event.download.erased");
|
||||
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), std::bind2nd(std::mem_fun(&View::erase), *itr));
|
||||
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), [itr](View* v) { v->erase(*itr); });
|
||||
|
||||
torrent::download_remove(*(*itr)->download());
|
||||
delete *itr;
|
||||
@@ -550,8 +513,8 @@ DownloadList::hash_done(Download* download) {
|
||||
if (download->is_done()) {
|
||||
confirm_finished(download);
|
||||
} else {
|
||||
download->set_message("Hash check on download completion found bad chunks, consider using \"safe_sync\".");
|
||||
lt_log_print(torrent::LOG_TORRENT_ERROR, "Hash check on download completion found bad chunks, consider using \"safe_sync\".");
|
||||
download->set_message("Hash check on download completion found bad chunks.");
|
||||
lt_log_print(torrent::LOG_TORRENT_ERROR, "Hash check on download completion found bad chunks.");
|
||||
DL_TRIGGER_EVENT(download, "event.download.hash_final_failed");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RTORRENT_CORE_DOWNLOAD_LIST_H
|
||||
#define RTORRENT_CORE_DOWNLOAD_LIST_H
|
||||
|
||||
@@ -43,6 +7,7 @@
|
||||
|
||||
namespace torrent {
|
||||
class HashString;
|
||||
class Object;
|
||||
}
|
||||
|
||||
namespace core {
|
||||
@@ -86,8 +51,8 @@ public:
|
||||
Download* find_hex_ptr(const char* hash);
|
||||
|
||||
// Might move this to DownloadFactory.
|
||||
Download* create(std::istream* str, bool printLog);
|
||||
Download* create(torrent::Object* obj, bool printLog);
|
||||
Download* create(std::istream* str, uint32_t tracker_key, bool printLog);
|
||||
Download* create(torrent::Object* obj, uint32_t tracker_key, bool printLog);
|
||||
|
||||
iterator insert(Download* d);
|
||||
|
||||
|
||||
@@ -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(¬_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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -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
@@ -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
@@ -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();
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <rak/functional.h>
|
||||
#include <torrent/exceptions.h>
|
||||
#include <torrent/object.h>
|
||||
|
||||
@@ -55,7 +54,7 @@ namespace core {
|
||||
|
||||
void
|
||||
ViewManager::clear() {
|
||||
std::for_each(begin(), end(), rak::call_delete<View>());
|
||||
std::for_each(begin(), end(), [](View* v) { delete v; });
|
||||
|
||||
base_type::clear();
|
||||
}
|
||||
@@ -76,12 +75,12 @@ ViewManager::insert(const std::string& name) {
|
||||
|
||||
ViewManager::iterator
|
||||
ViewManager::find(const std::string& name) {
|
||||
return std::find_if(begin(), end(), rak::equal(name, std::mem_fun(&View::name)));
|
||||
return std::find_if(begin(), end(), [name](View* v){ return name == v->name(); });
|
||||
}
|
||||
|
||||
ViewManager::iterator
|
||||
ViewManager::find_throw(const std::string& name) {
|
||||
iterator itr = std::find_if(begin(), end(), rak::equal(name, std::mem_fun(&View::name)));
|
||||
iterator itr = std::find_if(begin(), end(), [name](View* v){ return name == v->name(); });
|
||||
|
||||
if (itr == end())
|
||||
throw torrent::input_error("Could not find view: " + name);
|
||||
|
||||
+120
-43
@@ -1,45 +1,9 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <termios.h>
|
||||
#include <torrent/exceptions.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "rpc/parse_commands.h"
|
||||
|
||||
@@ -48,14 +12,16 @@
|
||||
namespace display {
|
||||
|
||||
bool Canvas::m_isInitialized = false;
|
||||
bool Canvas::m_isDaemon = false;
|
||||
bool Canvas::m_isDaemon = false;
|
||||
// Maps ncurses color IDs to a ncurses attribute int
|
||||
std::unordered_map<int, int> Canvas::m_attr_map = {};
|
||||
|
||||
Canvas::Canvas(int x, int y, int width, int height) {
|
||||
if (!m_isDaemon) {
|
||||
m_window = newwin(height, width, y, x);
|
||||
m_window = newwin(height, width, y, x);
|
||||
|
||||
if (m_window == NULL)
|
||||
throw torrent::internal_error("Could not allocate ncurses canvas.");
|
||||
if (m_window == NULL)
|
||||
throw torrent::internal_error("Could not allocate ncurses canvas.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +39,7 @@ Canvas::print_attributes(unsigned int x, unsigned int y, const char* first, cons
|
||||
move(x, y);
|
||||
|
||||
attr_t org_attr;
|
||||
short org_pair;
|
||||
short org_pair;
|
||||
wattr_get(m_window, &org_attr, &org_pair, NULL);
|
||||
|
||||
attributes_list::const_iterator attrItr = attributes->begin();
|
||||
@@ -111,6 +77,9 @@ Canvas::initialize() {
|
||||
|
||||
if (!m_isDaemon) {
|
||||
initscr();
|
||||
start_color();
|
||||
use_default_colors();
|
||||
Canvas::build_colors();
|
||||
raw();
|
||||
noecho();
|
||||
nodelay(stdscr, TRUE);
|
||||
@@ -119,6 +88,114 @@ Canvas::initialize() {
|
||||
}
|
||||
}
|
||||
|
||||
// Function wrapper for what possibly is a macro
|
||||
int
|
||||
get_colors() {
|
||||
return COLORS;
|
||||
}
|
||||
|
||||
// Turns the string color definitions from the "ui.color.*" RPC
|
||||
// commands into valid ncurses color pairs
|
||||
void
|
||||
Canvas::build_colors() {
|
||||
|
||||
// This may get called early in the start process by the config
|
||||
// file, so we need to delay building until initscr() has a chance
|
||||
// to run
|
||||
if (!m_isInitialized || m_isDaemon)
|
||||
return;
|
||||
|
||||
// basic color names, index maps to ncurses COLOR_*
|
||||
static const char* color_names[] = {
|
||||
"black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"};
|
||||
|
||||
// Those hold the background colors of "odd" and "even"
|
||||
int bg_odd = -1;
|
||||
int bg_even = -1;
|
||||
|
||||
for (int k = 1; k < RCOLOR_MAX; k++) {
|
||||
init_pair(k, -1, -1);
|
||||
std::string color_def = rpc::call_command_string(color_vars[k]);
|
||||
if (color_def.empty())
|
||||
continue; // Use terminal default if definition is empty
|
||||
|
||||
short color[2] = {-1, -1}; // fg, bg
|
||||
short color_idx = 0; // 0 = fg; 1 = bg
|
||||
short bright = 0;
|
||||
unsigned long attr = A_NORMAL;
|
||||
|
||||
// Process string as space-separated words
|
||||
size_t start = 0, end = 0;
|
||||
while (true) {
|
||||
end = color_def.find(' ', start);
|
||||
std::string word = color_def.substr(start, end - start);
|
||||
|
||||
if (word == "bold")
|
||||
attr |= A_BOLD;
|
||||
else if (word == "standout")
|
||||
attr |= A_STANDOUT;
|
||||
else if (word == "underline")
|
||||
attr |= A_UNDERLINE;
|
||||
else if (word == "reverse")
|
||||
attr |= A_REVERSE;
|
||||
else if (word == "blink")
|
||||
attr |= A_BLINK;
|
||||
else if (word == "dim")
|
||||
attr |= A_DIM;
|
||||
else if (word == "on") {
|
||||
color_idx = 1;
|
||||
bright = 0;
|
||||
} // Switch to background color
|
||||
else if (word == "gray" || word == "grey")
|
||||
color[color_idx] = bright ? 7 : 8; // Bright gray is white
|
||||
else if (word == "bright")
|
||||
bright = 8;
|
||||
else if (word.find_first_not_of("0123456789") == std::string::npos) {
|
||||
// Handle numeric index
|
||||
short c = -1;
|
||||
sscanf(word.c_str(), "%hd", &c);
|
||||
color[color_idx] = c;
|
||||
} else
|
||||
for (short c = 0; c < 8; c++) { // Check for basic color names
|
||||
if (word == color_names[c]) {
|
||||
color[color_idx] = bright + c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (end == std::string::npos)
|
||||
break;
|
||||
start = end + 1;
|
||||
}
|
||||
|
||||
// Check that fg & bg color index is valid
|
||||
if ((color[0] != -1 && color[0] >= get_colors()) || (color[1] != -1 && color[1] >= get_colors())) {
|
||||
char buf[33];
|
||||
sprintf(buf, "%d", get_colors());
|
||||
Canvas::cleanup();
|
||||
throw torrent::input_error(color_def + ": your terminal only supports " + buf + " colors.");
|
||||
}
|
||||
|
||||
m_attr_map[k] = attr; // overwrite or insert the value
|
||||
init_pair(k, color[0], color[1]);
|
||||
if (k == RCOLOR_EVEN)
|
||||
bg_even = color[1];
|
||||
if (k == RCOLOR_ODD)
|
||||
bg_odd = color[1];
|
||||
}
|
||||
|
||||
// Now make copies of the basic colors with the "odd" and "even" definitions mixed in
|
||||
for (int k = 1; k < RCOLOR_MAX; k++) {
|
||||
short fg, bg;
|
||||
pair_content(k, &fg, &bg);
|
||||
|
||||
// Replace the background color, and mix in the attributes
|
||||
m_attr_map[k + 1 * RCOLOR_MAX] = m_attr_map[k] | m_attr_map[RCOLOR_EVEN];
|
||||
m_attr_map[k + 2 * RCOLOR_MAX] = m_attr_map[k] | m_attr_map[RCOLOR_ODD];
|
||||
init_pair(k + 1 * RCOLOR_MAX, fg, bg == -1 ? bg_even : bg);
|
||||
init_pair(k + 2 * RCOLOR_MAX, fg, bg == -1 ? bg_odd : bg);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Canvas::cleanup() {
|
||||
if (!m_isInitialized)
|
||||
@@ -143,4 +220,4 @@ Canvas::term_size() {
|
||||
return std::pair<int, int>(80, 24);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace display
|
||||
|
||||
+227
-84
@@ -1,125 +1,204 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RTORRENT_DISPLAY_CANVAS_H
|
||||
#define RTORRENT_DISPLAY_CANVAS_H
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "attributes.h"
|
||||
#include "color_map.h"
|
||||
|
||||
namespace display {
|
||||
|
||||
class Canvas {
|
||||
public:
|
||||
typedef std::vector<Attributes> attributes_list;
|
||||
typedef std::vector<Attributes> attributes_list;
|
||||
typedef std::unordered_map<int, int> attributes_map;
|
||||
|
||||
Canvas(int x = 0, int y = 0, int width = 0, int height = 0);
|
||||
~Canvas() { if (!m_isDaemon) { delwin(m_window); } }
|
||||
~Canvas();
|
||||
|
||||
void refresh() { if (!m_isDaemon) { wnoutrefresh(m_window); } }
|
||||
static void refresh_std() { if (!m_isDaemon) { wnoutrefresh(stdscr); } }
|
||||
void redraw() { if (!m_isDaemon) { redrawwin(m_window); } }
|
||||
static void redraw_std() { if (!m_isDaemon) { redrawwin(stdscr); } }
|
||||
void refresh();
|
||||
void redraw();
|
||||
void resize(int w, int h);
|
||||
void resize(int x, int y, int w, int h);
|
||||
|
||||
void resize(int w, int h) { if (!m_isDaemon) { wresize(m_window, h, w); } }
|
||||
void resize(int x, int y, int w, int h);
|
||||
static void refresh_std();
|
||||
static void redraw_std();
|
||||
static void resize_term(int x, int y);
|
||||
static void resize_term(std::pair<int, int> dim);
|
||||
|
||||
static void resize_term(int x, int y) { if (!m_isDaemon) { resizeterm(y, x); } }
|
||||
static void resize_term(std::pair<int, int> dim) { if (!m_isDaemon) { resizeterm(dim.second, dim.first); } }
|
||||
unsigned int get_x();
|
||||
unsigned int get_y();
|
||||
unsigned int width();
|
||||
unsigned int height();
|
||||
|
||||
unsigned int get_x() { int x, __UNUSED y; if (!m_isDaemon) { getyx(m_window, y, x); } else { x=1; } return x; }
|
||||
unsigned int get_y() { int x, y; if (!m_isDaemon) { getyx(m_window, y, x); } else { y=1; } return y; }
|
||||
|
||||
unsigned int width() { int x, __UNUSED y; if (!m_isDaemon) { getmaxyx(m_window, y, x); } else { x=80; } return x; }
|
||||
unsigned int height() { int x, y; if (!m_isDaemon) { getmaxyx(m_window, y, x); } else { y=24; } return y; }
|
||||
|
||||
void move(unsigned int x, unsigned int y) { if (!m_isDaemon) { wmove(m_window, y, x); } }
|
||||
|
||||
chtype get_background() { chtype bg=0; if (!m_isDaemon) { bg=getbkgd(m_window); } return bg; }
|
||||
void set_background(chtype c) { if (!m_isDaemon) { return wbkgdset(m_window, c); } }
|
||||
|
||||
void erase() { if (!m_isDaemon) { werase(m_window); } }
|
||||
static void erase_std() { if (!m_isDaemon) { werase(stdscr); } }
|
||||
|
||||
void print_border(chtype ls, chtype rs,
|
||||
chtype ts, chtype bs,
|
||||
chtype tl, chtype tr,
|
||||
chtype bl, chtype br) { if (!m_isDaemon) { wborder(m_window, ls, rs, ts, bs, tl, tr, bl, br); } }
|
||||
void move(unsigned int x, unsigned int y);
|
||||
void erase();
|
||||
static void erase_std();
|
||||
|
||||
// The format string is non-const, but that will not be a problem
|
||||
// since the string shall always be a C string choosen at
|
||||
// compiletime. Might cause extra copying of the string?
|
||||
|
||||
void print(const char* str, ...);
|
||||
void print(unsigned int x, unsigned int y, const char* str, ...);
|
||||
void print(const char* str, ...);
|
||||
void print(unsigned int x, unsigned int y, const char* str, ...);
|
||||
void print_attributes(unsigned int x, unsigned int y, const char* first, const char* last, const attributes_list* attributes);
|
||||
void print_char(const chtype ch);
|
||||
void print_char(unsigned int x, unsigned int y, const chtype ch);
|
||||
|
||||
void print_attributes(unsigned int x, unsigned int y, const char* first, const char* last, const attributes_list* attributes);
|
||||
|
||||
void print_char(const chtype ch) { if (!m_isDaemon) { waddch(m_window, ch); } }
|
||||
void print_char(unsigned int x, unsigned int y, const chtype ch) { if (!m_isDaemon) { mvwaddch(m_window, y, x, ch); } }
|
||||
|
||||
void set_attr(unsigned int x, unsigned int y, unsigned int n, int attr, int color) { if (!m_isDaemon) { mvwchgat(m_window, y, x, n, attr, color, NULL); } }
|
||||
|
||||
void set_default_attributes(int attr) { if (!m_isDaemon) { (void)wattrset(m_window, attr); } }
|
||||
void set_attr(unsigned int x, unsigned int y, unsigned int n, int attr, int color);
|
||||
void set_attr(unsigned int x, unsigned int y, unsigned int n, ColorKind k);
|
||||
void set_default_attributes(int attr);
|
||||
|
||||
// Initialize stdscr.
|
||||
static void initialize();
|
||||
static void cleanup();
|
||||
static void initialize();
|
||||
static void build_colors();
|
||||
static void cleanup();
|
||||
|
||||
static int get_screen_width() { int x, __UNUSED y; if (!m_isDaemon) { getmaxyx(stdscr, y, x); } else { x=80; } return x; }
|
||||
static int get_screen_height() { int x, y; if (!m_isDaemon) { getmaxyx(stdscr, y, x); } else { y=24;} return y; }
|
||||
static int get_screen_width();
|
||||
static int get_screen_height();
|
||||
|
||||
static std::pair<int, int> term_size();
|
||||
|
||||
static void do_update() { if (!m_isDaemon) { doupdate(); } }
|
||||
static void do_update();
|
||||
|
||||
static bool daemon() { return m_isDaemon; }
|
||||
static bool daemon() { return m_isDaemon; }
|
||||
static const attributes_map& attr_map() { return m_attr_map; }
|
||||
|
||||
private:
|
||||
Canvas(const Canvas&);
|
||||
void operator = (const Canvas&);
|
||||
void operator=(const Canvas&);
|
||||
|
||||
static bool m_isInitialized;
|
||||
static bool m_isDaemon;
|
||||
static bool m_isInitialized;
|
||||
static bool m_isDaemon;
|
||||
|
||||
WINDOW* m_window;
|
||||
// Maps ncurses color IDs to a ncurses attribute int
|
||||
static std::unordered_map<int, int> m_attr_map;
|
||||
|
||||
WINDOW* m_window;
|
||||
};
|
||||
|
||||
inline Canvas::~Canvas() {
|
||||
if (!m_isDaemon) {
|
||||
delwin(m_window);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::refresh() {
|
||||
if (!m_isDaemon) {
|
||||
wnoutrefresh(m_window);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::refresh_std() {
|
||||
if (!m_isDaemon) {
|
||||
wnoutrefresh(stdscr);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::redraw() {
|
||||
if (!m_isDaemon) {
|
||||
redrawwin(m_window);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::redraw_std() {
|
||||
if (!m_isDaemon) {
|
||||
redrawwin(stdscr);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::resize(int w, int h) {
|
||||
if (!m_isDaemon) {
|
||||
wresize(m_window, h, w);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::resize_term(int x, int y) {
|
||||
if (!m_isDaemon) {
|
||||
resizeterm(y, x);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::resize_term(std::pair<int, int> dim) {
|
||||
if (!m_isDaemon) {
|
||||
resizeterm(dim.second, dim.first);
|
||||
}
|
||||
}
|
||||
|
||||
inline unsigned int
|
||||
Canvas::get_x() {
|
||||
int x, __UNUSED y;
|
||||
if (!m_isDaemon) {
|
||||
getyx(m_window, y, x);
|
||||
} else {
|
||||
x = 1;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
inline unsigned int
|
||||
Canvas::get_y() {
|
||||
int x, y;
|
||||
if (!m_isDaemon) {
|
||||
getyx(m_window, y, x);
|
||||
} else {
|
||||
y = 1;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
inline unsigned int
|
||||
Canvas::width() {
|
||||
int x, __UNUSED y;
|
||||
if (!m_isDaemon) {
|
||||
getmaxyx(m_window, y, x);
|
||||
} else {
|
||||
x = 80;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
inline unsigned int
|
||||
Canvas::height() {
|
||||
int x, y;
|
||||
if (!m_isDaemon) {
|
||||
getmaxyx(m_window, y, x);
|
||||
} else {
|
||||
y = 24;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::move(unsigned int x, unsigned int y) {
|
||||
if (!m_isDaemon) {
|
||||
wmove(m_window, y, x);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::erase() {
|
||||
if (!m_isDaemon) {
|
||||
werase(m_window);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::erase_std() {
|
||||
if (!m_isDaemon) {
|
||||
werase(stdscr);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::print(const char* str, ...) {
|
||||
va_list arglist;
|
||||
@@ -143,6 +222,70 @@ Canvas::print(unsigned int x, unsigned int y, const char* str, ...) {
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::print_char(const chtype ch) {
|
||||
if (!m_isDaemon) {
|
||||
waddch(m_window, ch);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::print_char(unsigned int x, unsigned int y, const chtype ch) {
|
||||
if (!m_isDaemon) {
|
||||
mvwaddch(m_window, y, x, ch);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::set_attr(unsigned int x, unsigned int y, unsigned int n, int attr, int color) {
|
||||
if (!m_isDaemon) {
|
||||
mvwchgat(m_window, y, x, n, attr, color, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::set_attr(unsigned int x, unsigned int y, unsigned int n, ColorKind k) {
|
||||
if (!m_isDaemon) {
|
||||
mvwchgat(m_window, y, x, n, m_attr_map[k], k, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::set_default_attributes(int attr) {
|
||||
if (!m_isDaemon) {
|
||||
(void)wattrset(m_window, attr);
|
||||
}
|
||||
}
|
||||
|
||||
inline int
|
||||
Canvas::get_screen_width() {
|
||||
int x, __UNUSED y;
|
||||
if (!m_isDaemon) {
|
||||
getmaxyx(stdscr, y, x);
|
||||
} else {
|
||||
x = 80;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
inline int
|
||||
Canvas::get_screen_height() {
|
||||
int x, y;
|
||||
if (!m_isDaemon) {
|
||||
getmaxyx(stdscr, y, x);
|
||||
} else {
|
||||
y = 24;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
inline void
|
||||
Canvas::do_update() {
|
||||
if (!m_isDaemon) {
|
||||
doupdate();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace display
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef RTORRENT_DISPLAY_COLOR_MAP_H
|
||||
#define RTORRENT_DISPLAY_COLOR_MAP_H
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <curses.h>
|
||||
|
||||
namespace display {
|
||||
|
||||
enum ColorKind {
|
||||
RCOLOR_NCURSES_DEFAULT, // Color 0 is reserved by ncurses and cannot be changed
|
||||
RCOLOR_TITLE,
|
||||
RCOLOR_FOOTER,
|
||||
RCOLOR_FOCUS,
|
||||
RCOLOR_LABEL,
|
||||
RCOLOR_INFO,
|
||||
RCOLOR_ALARM,
|
||||
RCOLOR_COMPLETE,
|
||||
RCOLOR_SEEDING,
|
||||
RCOLOR_STOPPED,
|
||||
RCOLOR_QUEUED,
|
||||
RCOLOR_INCOMPLETE,
|
||||
RCOLOR_LEECHING,
|
||||
RCOLOR_ODD,
|
||||
RCOLOR_EVEN,
|
||||
RCOLOR_MAX,
|
||||
};
|
||||
|
||||
static const char* color_vars[RCOLOR_MAX] = {
|
||||
0,
|
||||
"ui.color.title",
|
||||
"ui.color.footer",
|
||||
"ui.color.focus",
|
||||
"ui.color.label",
|
||||
"ui.color.info",
|
||||
"ui.color.alarm",
|
||||
"ui.color.complete",
|
||||
"ui.color.seeding",
|
||||
"ui.color.stopped",
|
||||
"ui.color.queued",
|
||||
"ui.color.incomplete",
|
||||
"ui.color.leeching",
|
||||
"ui.color.odd",
|
||||
"ui.color.even",
|
||||
};
|
||||
|
||||
} // namespace display
|
||||
#endif
|
||||
@@ -38,7 +38,6 @@
|
||||
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <rak/functional.h>
|
||||
|
||||
#include "canvas.h"
|
||||
#include "globals.h"
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <rak/functional.h>
|
||||
#include <torrent/exceptions.h>
|
||||
|
||||
#include "text_element_list.h"
|
||||
@@ -46,7 +45,7 @@ namespace display {
|
||||
|
||||
void
|
||||
TextElementList::clear() {
|
||||
std::for_each(begin(), end(), rak::call_delete<TextElement>());
|
||||
std::for_each(begin(), end(), [](TextElement* t) { delete t; });
|
||||
base_type::clear();
|
||||
}
|
||||
|
||||
|
||||
+6
-43
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <cstring>
|
||||
@@ -47,8 +11,8 @@
|
||||
#include <torrent/rate.h>
|
||||
#include <torrent/throttle.h>
|
||||
#include <torrent/torrent.h>
|
||||
#include <torrent/tracker.h>
|
||||
#include <torrent/tracker_list.h>
|
||||
#include <torrent/tracker/tracker.h>
|
||||
#include <torrent/data/file_list.h>
|
||||
#include <torrent/data/file_manager.h>
|
||||
#include <torrent/download/resource_manager.h>
|
||||
@@ -88,7 +52,7 @@ print_hhmmss(char* first, char* last, time_t t) {
|
||||
char*
|
||||
print_hhmmss_local(char* first, char* last, time_t t) {
|
||||
std::tm *u = std::localtime(&t);
|
||||
|
||||
|
||||
if (u == NULL)
|
||||
//return "inv_time";
|
||||
throw torrent::internal_error("print_hhmmss_local(...) failed.");
|
||||
@@ -107,7 +71,7 @@ print_ddhhmm(char* first, char* last, time_t t) {
|
||||
char*
|
||||
print_ddmmyyyy(char* first, char* last, time_t t) {
|
||||
std::tm *u = std::gmtime(&t);
|
||||
|
||||
|
||||
if (u == NULL)
|
||||
//return "inv_time";
|
||||
throw torrent::internal_error("print_ddmmyyyy(...) failed.");
|
||||
@@ -199,12 +163,11 @@ print_download_status(char* first, char* last, core::Download* d) {
|
||||
} else if (d->tracker_list()->has_active_not_scrape()) {
|
||||
torrent::TrackerList::iterator itr =
|
||||
std::find_if(d->tracker_list()->begin(), d->tracker_list()->end(),
|
||||
std::mem_fun(&torrent::Tracker::is_busy_not_scrape));
|
||||
char status[128];
|
||||
std::mem_fn(&torrent::tracker::Tracker::is_busy_not_scrape));
|
||||
auto status = itr->status();
|
||||
|
||||
(*itr)->get_status(status, sizeof(status));
|
||||
first = print_buffer(first, last, "Tracker[%i:%i]: Connecting to %s %s",
|
||||
(*itr)->group(), std::distance(d->tracker_list()->begin(), itr), (*itr)->url().c_str(), status);
|
||||
itr->group(), std::distance(d->tracker_list()->begin(), itr), itr->url().c_str(), status.c_str());
|
||||
|
||||
} else if (!d->message().empty()) {
|
||||
first = print_buffer(first, last, "%s", d->message().c_str());
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
#define RTORRENT_WINDOW_BASE_H
|
||||
|
||||
#include <rak/timer.h>
|
||||
#include <rak/functional.h>
|
||||
#include <functional>
|
||||
|
||||
#include "canvas.h"
|
||||
#include "globals.h"
|
||||
@@ -46,15 +46,14 @@
|
||||
namespace display {
|
||||
|
||||
class Canvas;
|
||||
class Manager;
|
||||
|
||||
class Window {
|
||||
public:
|
||||
typedef uint32_t extent_type;
|
||||
|
||||
typedef rak::mem_fun0<Manager, void> Slot;
|
||||
typedef rak::mem_fun1<Manager, void, Window*> SlotWindow;
|
||||
typedef rak::mem_fun2<Manager, void, Window*, rak::timer> SlotTimer;
|
||||
typedef std::function<void()> Slot;
|
||||
typedef std::function<void(Window*)> SlotWindow;
|
||||
typedef std::function<void(Window*, rak::timer)> SlotTimer;
|
||||
|
||||
static const int flag_active = (1 << 0);
|
||||
static const int flag_offscreen = (1 << 1);
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
|
||||
#include <cmath>
|
||||
#include <stdexcept>
|
||||
#include <rak/functional.h>
|
||||
#include <rak/string_manip.h>
|
||||
#include <torrent/bitfield.h>
|
||||
#include <torrent/data/block.h>
|
||||
@@ -95,7 +94,7 @@ WindowDownloadChunksSeen::redraw() {
|
||||
std::vector<torrent::BlockList*> transferChunks(transfers->size(), 0);
|
||||
|
||||
std::copy(transfers->begin(), transfers->end(), transferChunks.begin());
|
||||
std::sort(transferChunks.begin(), transferChunks.end(), rak::less2(std::mem_fun(&torrent::BlockList::index), std::mem_fun(&torrent::BlockList::index)));
|
||||
std::sort(transferChunks.begin(), transferChunks.end());
|
||||
|
||||
std::vector<torrent::BlockList*>::const_iterator itrTransfer = transferChunks.begin();
|
||||
|
||||
@@ -111,7 +110,7 @@ WindowDownloadChunksSeen::redraw() {
|
||||
if (bitfield->get(chunk - seen)) {
|
||||
attr = A_NORMAL;
|
||||
} else if (itrTransfer != transferChunks.end() && (uint32_t)(chunk - seen) == (*itrTransfer)->index()) {
|
||||
if (std::find_if((*itrTransfer)->begin(), (*itrTransfer)->end(), std::mem_fun_ref(&torrent::Block::is_transfering)) != (*itrTransfer)->end())
|
||||
if (std::any_of((*itrTransfer)->begin(), (*itrTransfer)->end(), std::mem_fn(&torrent::Block::is_transfering)))
|
||||
attr = A_REVERSE;
|
||||
else
|
||||
attr = A_BOLD | A_UNDERLINE;
|
||||
|
||||
@@ -1,41 +1,6 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "display/color_map.h"
|
||||
#include <rak/algorithm.h>
|
||||
|
||||
#include "core/download.h"
|
||||
@@ -57,7 +22,7 @@ WindowDownloadList::WindowDownloadList() :
|
||||
WindowDownloadList::~WindowDownloadList() {
|
||||
if (m_view != NULL)
|
||||
m_view->signal_changed().erase(m_changed_itr);
|
||||
|
||||
|
||||
m_view = NULL;
|
||||
}
|
||||
|
||||
@@ -72,8 +37,47 @@ WindowDownloadList::set_view(core::View* l) {
|
||||
m_changed_itr = m_view->signal_changed().insert(m_view->signal_changed().begin(), std::bind(&Window::mark_dirty, this));
|
||||
}
|
||||
|
||||
// Return a pair of ints, representing a) the ncurses attributes and b) the ncurses color pair ID to use
|
||||
std::pair<int, int>
|
||||
WindowDownloadList::get_attr_color(core::View::iterator selected) {
|
||||
core::Download* item = *selected;
|
||||
unsigned long focus_attr = selected == m_view->focus() ? m_canvas->attr_map().at(RCOLOR_FOCUS) : 0;
|
||||
int offset = (((selected - m_view->begin_visible()) & 1) + 1) * RCOLOR_MAX; // Determine the even/odd offset for the color pair
|
||||
bool active = item->is_open() && item->is_active();
|
||||
int title_color;
|
||||
if (item->is_done())
|
||||
title_color = (active ? item->info()->up_rate()->rate() ? RCOLOR_SEEDING : RCOLOR_COMPLETE : RCOLOR_STOPPED) + offset;
|
||||
else
|
||||
title_color = (active ? item->info()->down_rate()->rate() ? RCOLOR_LEECHING : RCOLOR_INCOMPLETE : RCOLOR_QUEUED) + offset;
|
||||
return std::make_pair(m_canvas->attr_map().at(title_color) | focus_attr, title_color);
|
||||
}
|
||||
|
||||
int
|
||||
WindowDownloadList::page_size(const std::string layout_name) {
|
||||
// Calculate the page size for torrents. This is a public method
|
||||
// because it's also used to determine the default size for page
|
||||
// up/down actions.
|
||||
int layout_height;
|
||||
if (layout_name == "full") {
|
||||
layout_height = 3;
|
||||
} else if (layout_name == "compact") {
|
||||
layout_height = 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return m_canvas->height() / layout_height;
|
||||
}
|
||||
|
||||
int
|
||||
WindowDownloadList::page_size() {
|
||||
return page_size(rpc::call_command_string("ui.torrent_list.layout"));
|
||||
}
|
||||
|
||||
void
|
||||
WindowDownloadList::redraw() {
|
||||
if (m_canvas->daemon())
|
||||
return;
|
||||
|
||||
m_slotSchedule(this, (cachedTime + rak::timer::from_seconds(1)).round_seconds());
|
||||
|
||||
m_canvas->erase();
|
||||
@@ -95,24 +99,16 @@ WindowDownloadList::redraw() {
|
||||
m_canvas->print(m_canvas->width() - 16, 0, "[%5d of %-5d]", item_idx + 1, m_view->size());
|
||||
}
|
||||
|
||||
int layout_height;
|
||||
const std::string layout_name = rpc::call_command_string("ui.torrent_list.layout");
|
||||
m_canvas->set_attr(0, 0, -1, RCOLOR_TITLE);
|
||||
|
||||
if (layout_name == "full") {
|
||||
layout_height = 3;
|
||||
} else if (layout_name == "compact") {
|
||||
layout_height = 1;
|
||||
} else {
|
||||
m_canvas->print(0, 0, "INVALID ui.torrent_list.layout '%s'", layout_name.c_str());
|
||||
return;
|
||||
}
|
||||
const std::string layout_name = rpc::call_command_string("ui.torrent_list.layout");
|
||||
|
||||
typedef std::pair<core::View::iterator, core::View::iterator> Range;
|
||||
|
||||
Range range = rak::advance_bidirectional(m_view->begin_visible(),
|
||||
m_view->focus() != m_view->end_visible() ? m_view->focus() : m_view->begin_visible(),
|
||||
m_view->end_visible(),
|
||||
m_canvas->height() / layout_height);
|
||||
page_size(layout_name));
|
||||
|
||||
// Make sure we properly fill out the last lines so it looks like
|
||||
// there are more torrents, yet don't hide it if we got the last one
|
||||
@@ -120,8 +116,8 @@ WindowDownloadList::redraw() {
|
||||
if (range.second != m_view->end_visible())
|
||||
++range.second;
|
||||
|
||||
int pos = 1;
|
||||
char buffer[m_canvas->width() + 1];
|
||||
int pos = 1;
|
||||
char buffer[m_canvas->width() + 1];
|
||||
char* last = buffer + m_canvas->width() - 2 + 1;
|
||||
|
||||
// Add a proper 'column info' method.
|
||||
@@ -134,25 +130,38 @@ WindowDownloadList::redraw() {
|
||||
|
||||
if (layout_name == "full") {
|
||||
while (range.first != range.second) {
|
||||
bool is_focused = range.first == m_view->focus();
|
||||
char focus_char = is_focused ? '*' : ' ';
|
||||
ColorKind focus_color = is_focused ? RCOLOR_FOCUS : RCOLOR_LABEL;
|
||||
auto attr_color = get_attr_color(range.first);
|
||||
|
||||
print_download_title(buffer, last, *range.first);
|
||||
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
|
||||
m_canvas->print(0, pos, "%c %s", focus_char, buffer);
|
||||
m_canvas->set_attr(2, pos++, -1, attr_color.first, attr_color.second);
|
||||
|
||||
print_download_info_full(buffer, last, *range.first);
|
||||
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
|
||||
m_canvas->print(0, pos, "%c %s", focus_char, buffer);
|
||||
m_canvas->set_attr(2, pos++, -1, focus_color);
|
||||
|
||||
print_download_status(buffer, last, *range.first);
|
||||
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
|
||||
m_canvas->print(0, pos, "%c %s", focus_char, buffer);
|
||||
m_canvas->set_attr(2, pos++, -1, focus_color);
|
||||
|
||||
range.first++;
|
||||
}
|
||||
|
||||
} else {
|
||||
while (range.first != range.second) {
|
||||
char focus_char = range.first == m_view->focus() ? '*' : ' ';
|
||||
auto attr_color = get_attr_color(range.first);
|
||||
|
||||
print_download_info_compact(buffer, last, *range.first);
|
||||
m_canvas->set_default_attributes(range.first == m_view->focus() ? A_REVERSE : A_NORMAL);
|
||||
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
|
||||
m_canvas->print(0, pos, "%c %s", focus_char, buffer);
|
||||
m_canvas->set_attr(2, pos++, -1, attr_color.first, attr_color.second);
|
||||
|
||||
range.first++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace display
|
||||
|
||||
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RTORRENT_DISPLAY_WINDOW_DOWNLOAD_LIST_H
|
||||
#define RTORRENT_DISPLAY_WINDOW_DOWNLOAD_LIST_H
|
||||
|
||||
@@ -47,6 +11,7 @@ namespace display {
|
||||
class WindowDownloadList : public Window {
|
||||
public:
|
||||
typedef core::View::signal_void::iterator signal_void_itr;
|
||||
typedef std::pair<core::View::iterator, core::View::iterator> ViewRange;
|
||||
|
||||
WindowDownloadList();
|
||||
~WindowDownloadList();
|
||||
@@ -55,9 +20,13 @@ public:
|
||||
|
||||
void set_view(core::View* l);
|
||||
|
||||
int page_size(const std::string layout_name);
|
||||
int page_size();
|
||||
|
||||
private:
|
||||
core::View* m_view;
|
||||
|
||||
std::pair<int, int> get_attr_color(core::View::iterator selected);
|
||||
signal_void_itr m_changed_itr;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <torrent/rate.h>
|
||||
@@ -59,6 +23,9 @@ WindowDownloadStatusbar::WindowDownloadStatusbar(core::Download* d) :
|
||||
|
||||
void
|
||||
WindowDownloadStatusbar::redraw() {
|
||||
if (m_canvas->daemon())
|
||||
return;
|
||||
|
||||
m_slotSchedule(this, (cachedTime + rak::timer::from_seconds(1)).round_seconds());
|
||||
|
||||
m_canvas->erase();
|
||||
@@ -91,7 +58,7 @@ WindowDownloadStatusbar::redraw() {
|
||||
print_download_status(buffer, last, m_download);
|
||||
m_canvas->print(0, 2, "[%c:%i] %s",
|
||||
m_download->tracker_list()->has_active() ? 'C' : ' ',
|
||||
(int)(m_download->download()->tracker_controller()->seconds_to_next_timeout()),
|
||||
(int)(m_download->download()->tracker_controller().seconds_to_next_timeout()),
|
||||
buffer);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <locale>
|
||||
@@ -83,7 +47,7 @@ wstring_width(const std::string& i_str, int width) {
|
||||
// Limit to width if it's too wide already.
|
||||
if (swidth == -1 || swidth > width) {
|
||||
length = swidth = 0;
|
||||
|
||||
|
||||
while (result[length]) {
|
||||
int next = ::wcwidth(result[length]);
|
||||
|
||||
@@ -172,13 +136,13 @@ WindowFileList::redraw() {
|
||||
|
||||
} else if (itr.is_entering()) {
|
||||
m_canvas->print(0, pos, "%*c %ls", 16 + itr.depth(), '\\',
|
||||
itr.depth() < (*itr)->path()->size() ? wstring_width((*itr)->path()->at(itr.depth()), filenameWidth - itr.depth() - 1).c_str() : L"UNKNOWN");
|
||||
itr.depth() < itr.file()->path()->size() ? wstring_width(itr.file()->path()->at(itr.depth()), filenameWidth - itr.depth() - 1).c_str() : L"UNKNOWN");
|
||||
|
||||
} else if (itr.is_leaving()) {
|
||||
m_canvas->print(0, pos, "%*c %-*s", 16 + (itr.depth() - 1), '/', filenameWidth - (itr.depth() - 1), "");
|
||||
|
||||
} else if (itr.is_file()) {
|
||||
torrent::File* e = *itr;
|
||||
torrent::File* e = itr.file();
|
||||
|
||||
const char* priority;
|
||||
|
||||
@@ -203,7 +167,7 @@ WindowFileList::redraw() {
|
||||
m_canvas->print(8, pos, "%5.1f T", (double)val / (int64_t(1) << 40));
|
||||
|
||||
m_canvas->print(15, pos, "%*c %ls", 1 + itr.depth(), '|',
|
||||
itr.depth() < (*itr)->path()->size() ? wstring_width((*itr)->path()->at(itr.depth()), filenameWidth - itr.depth() - 1).c_str() : L"UNKNOWN");
|
||||
itr.depth() < itr.file()->path()->size() ? wstring_width(itr.file()->path()->at(itr.depth()), filenameWidth - itr.depth() - 1).c_str() : L"UNKNOWN");
|
||||
|
||||
} else {
|
||||
m_canvas->print(0, pos, "BORK BORK");
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
#include "core/http_queue.h"
|
||||
|
||||
#include "canvas.h"
|
||||
#include "rak/functional.h"
|
||||
#include "window_http_queue.h"
|
||||
|
||||
namespace display {
|
||||
@@ -145,7 +144,7 @@ WindowHttpQueue::receive_insert(core::CurlGet* h) {
|
||||
|
||||
void
|
||||
WindowHttpQueue::receive_erase(core::CurlGet* h) {
|
||||
Container::iterator itr = std::find_if(m_container.begin(), m_container.end(), rak::equal(h, std::mem_fun_ref(&Node::get_http)));
|
||||
Container::iterator itr = std::find_if(m_container.begin(), m_container.end(), [h](Node n) { return h == n.get_http(); });
|
||||
|
||||
if (itr == m_container.end())
|
||||
throw std::logic_error("WindowHttpQueue::receive_erase(...) tried to remove an object we don't have");
|
||||
|
||||
@@ -1,44 +1,8 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <ctime>
|
||||
#include <torrent/torrent.h>
|
||||
#include <torrent/utils/thread_base.h>
|
||||
#include <torrent/utils/thread.h>
|
||||
|
||||
#include "canvas.h"
|
||||
#include "utils.h"
|
||||
@@ -54,7 +18,9 @@ WindowLog::WindowLog(torrent::log_buffer* l) :
|
||||
|
||||
unsigned int signal_index = torrent::main_thread()->signal_bitfield()->add_signal(std::bind(&WindowLog::receive_update, this));
|
||||
|
||||
m_log->lock_and_set_update_slot(std::bind(&torrent::thread_base::send_event_signal, torrent::main_thread(), signal_index, false));
|
||||
m_log->lock_and_set_update_slot([signal_index]() {
|
||||
torrent::main_thread()->send_event_signal(signal_index, false);
|
||||
});
|
||||
}
|
||||
|
||||
WindowLog::~WindowLog() {
|
||||
|
||||
@@ -1,41 +1,6 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "display/color_map.h"
|
||||
#include <torrent/rate.h>
|
||||
#include <torrent/torrent.h>
|
||||
|
||||
@@ -66,6 +31,7 @@ WindowStatusbar::redraw() {
|
||||
position = print_status_extra(buffer, last);
|
||||
m_canvas->print(m_canvas->width() - (position - buffer), 0, "%s", buffer);
|
||||
}
|
||||
m_canvas->set_attr(0, 0, -1, RCOLOR_FOOTER);
|
||||
|
||||
m_lastTick = control->tick();
|
||||
}
|
||||
|
||||
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "canvas.h"
|
||||
@@ -64,7 +28,7 @@ WindowStringList::redraw() {
|
||||
if (ypos == (size_t)m_canvas->height()) {
|
||||
ypos = 0;
|
||||
xpos += width + 2;
|
||||
|
||||
|
||||
if (xpos + 20 >= (size_t)m_canvas->width())
|
||||
break;
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <rak/functional.h>
|
||||
|
||||
#include "canvas.h"
|
||||
#include "utils.h"
|
||||
@@ -55,7 +54,7 @@ WindowText::WindowText(rpc::target_type target, extent_type margin) :
|
||||
|
||||
void
|
||||
WindowText::clear() {
|
||||
std::for_each(begin(), end(), rak::call_delete<TextElement>());
|
||||
std::for_each(begin(), end(), [](TextElement* text) { delete text; });
|
||||
base_type::clear();
|
||||
|
||||
delete m_errorHandler;
|
||||
|
||||
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "canvas.h"
|
||||
@@ -43,11 +7,13 @@ namespace display {
|
||||
|
||||
void
|
||||
WindowTitle::redraw() {
|
||||
if (m_canvas->daemon())
|
||||
return;
|
||||
|
||||
m_slotSchedule(this, (cachedTime + rak::timer::from_seconds(1)).round_seconds());
|
||||
m_canvas->erase();
|
||||
|
||||
m_canvas->print(std::max(0, ((int)m_canvas->width() - (int)m_title.size()) / 2 - 4), 0,
|
||||
"*** %s ***", m_title.c_str());
|
||||
m_canvas->print(std::max(0, ((int)m_canvas->width() - (int)m_title.size()) / 2 - 4), 0, "*** %s ***", m_title.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace display
|
||||
|
||||
@@ -1,47 +1,11 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <rak/algorithm.h>
|
||||
#include <rak/string_manip.h>
|
||||
#include <torrent/exceptions.h>
|
||||
#include <torrent/tracker.h>
|
||||
#include <torrent/tracker_list.h>
|
||||
#include <torrent/tracker_controller.h>
|
||||
#include <torrent/tracker/tracker.h>
|
||||
|
||||
#include "core/download.h"
|
||||
|
||||
@@ -62,14 +26,14 @@ WindowTrackerList::redraw() {
|
||||
m_canvas->erase();
|
||||
|
||||
unsigned int pos = 0;
|
||||
torrent::TrackerList* tl = m_download->tracker_list();
|
||||
torrent::TrackerController* tc = m_download->tracker_controller();
|
||||
auto tl = m_download->tracker_list();
|
||||
auto tc = m_download->tracker_controller();
|
||||
|
||||
m_canvas->print(2, pos, "Trackers: [Key: %08x] [%s %s %s]",
|
||||
tl->key(),
|
||||
tc->is_requesting() ? "req" : " ",
|
||||
tc->is_promiscuous_mode() ? "prom" : " ",
|
||||
tc->is_failure_mode() ? "fail" : " ");
|
||||
tc.is_requesting() ? "req" : " ",
|
||||
tc.is_promiscuous_mode() ? "prom" : " ",
|
||||
tc.is_failure_mode() ? "fail" : " ");
|
||||
++pos;
|
||||
|
||||
if (tl->size() == 0 || *m_focus >= tl->size())
|
||||
@@ -78,39 +42,41 @@ WindowTrackerList::redraw() {
|
||||
typedef std::pair<unsigned int, unsigned int> Range;
|
||||
|
||||
Range range = rak::advance_bidirectional<unsigned int>(0, *m_focus, tl->size(), (m_canvas->height() - 1) / 2);
|
||||
unsigned int group = tl->at(range.first)->group();
|
||||
unsigned int group = tl->at(range.first).group();
|
||||
|
||||
while (range.first != range.second) {
|
||||
torrent::Tracker* tracker = tl->at(range.first);
|
||||
auto tracker = tl->at(range.first);
|
||||
|
||||
if (tracker->group() == group)
|
||||
if (tracker.group() == group)
|
||||
m_canvas->print(0, pos, "%2i:", group++);
|
||||
|
||||
m_canvas->print(4, pos++, "%s",
|
||||
tracker->url().c_str());
|
||||
tracker.url().c_str());
|
||||
|
||||
if (pos < m_canvas->height()) {
|
||||
const char* state;
|
||||
|
||||
if (tracker->is_busy_not_scrape())
|
||||
if (tracker.is_busy_not_scrape())
|
||||
state = "req ";
|
||||
else if (tracker->is_busy())
|
||||
else if (tracker.is_busy())
|
||||
state = "scr ";
|
||||
else
|
||||
state = " ";
|
||||
|
||||
auto tracker_state = tracker.state();
|
||||
|
||||
m_canvas->print(0, pos++, "%s Id: %s Counters: %uf / %us (%u) %s S/L/D: %u/%u/%u (%u/%u)",
|
||||
state,
|
||||
rak::copy_escape_html(tracker->tracker_id()).c_str(),
|
||||
tracker->failed_counter(),
|
||||
tracker->success_counter(),
|
||||
tracker->scrape_counter(),
|
||||
tracker->is_usable() ? " on" : tracker->is_enabled() ? "err" : "off",
|
||||
tracker->scrape_complete(),
|
||||
tracker->scrape_incomplete(),
|
||||
tracker->scrape_downloaded(),
|
||||
tracker->latest_new_peers(),
|
||||
tracker->latest_sum_peers());
|
||||
rak::copy_escape_html(tracker.tracker_id()).c_str(),
|
||||
tracker_state.failed_counter(),
|
||||
tracker_state.success_counter(),
|
||||
tracker_state.scrape_counter(),
|
||||
tracker.is_usable() ? " on" : tracker.is_enabled() ? "err" : "off",
|
||||
tracker_state.scrape_complete(),
|
||||
tracker_state.scrape_incomplete(),
|
||||
tracker_state.scrape_downloaded(),
|
||||
tracker_state.latest_new_peers(),
|
||||
tracker_state.latest_sum_peers());
|
||||
}
|
||||
|
||||
if (range.first == *m_focus) {
|
||||
@@ -118,7 +84,7 @@ WindowTrackerList::redraw() {
|
||||
m_canvas->set_attr(4, pos - 1, m_canvas->width(), is_focused() ? A_REVERSE : A_BOLD, COLOR_PAIR(0));
|
||||
}
|
||||
|
||||
if (tracker->is_busy()) {
|
||||
if (tracker.is_busy()) {
|
||||
m_canvas->set_attr(0, pos - 2, 4, A_REVERSE, COLOR_PAIR(0));
|
||||
m_canvas->set_attr(0, pos - 1, 4, A_REVERSE, COLOR_PAIR(0));
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ Manager::pressed(int key) {
|
||||
if (m_textInput != NULL)
|
||||
m_textInput->pressed(key);
|
||||
else
|
||||
std::find_if(rbegin(), rend(), std::bind2nd(std::mem_fun(&Bindings::pressed), key));
|
||||
std::find_if(rbegin(), rend(), [&key](Bindings* bind) { return bind->pressed(key); });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
|
||||
#include <functional>
|
||||
#include <rak/algorithm.h>
|
||||
#include <rak/functional.h>
|
||||
#include <rak/path.h>
|
||||
|
||||
#include <dirent.h>
|
||||
@@ -105,7 +104,7 @@ PathInput::receive_do_complete() {
|
||||
if (r.first == r.second)
|
||||
return; // Show some nice colors here.
|
||||
|
||||
std::string base = rak::make_base<std::string>(r.first, r.second, rak::const_mem_ref(&utils::directory_entry::s_name));
|
||||
std::string base = rak::make_base<std::string>(r.first, r.second, std::mem_fn(&utils::directory_entry::s_name));
|
||||
|
||||
// Clear the path after the cursor to make this code cleaner. It's
|
||||
// not really nessesary to add the complexity just because someone
|
||||
@@ -154,8 +153,12 @@ PathInput::range_type
|
||||
PathInput::find_incomplete(utils::Directory& d, const std::string& f) {
|
||||
range_type r;
|
||||
|
||||
r.first = std::find_if(d.begin(), d.end(), rak::bind2nd(std::ptr_fun(&find_complete_not_compare), f));
|
||||
r.second = std::find_if(r.first, d.end(), rak::bind2nd(std::ptr_fun(&find_complete_compare), f));
|
||||
r.first = std::find_if(d.begin(), d.end(), [f](const utils::directory_entry& de) {
|
||||
return find_complete_not_compare(de, f);
|
||||
});
|
||||
r.second = std::find_if(r.first, d.end(), [f](const utils::directory_entry& de) {
|
||||
return find_complete_compare(de, f);
|
||||
});
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
+9
-46
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define __STDC_FORMAT_MACROS
|
||||
@@ -50,7 +14,6 @@
|
||||
#include <torrent/poll.h>
|
||||
#include <torrent/data/chunk_utils.h>
|
||||
#include <torrent/utils/log.h>
|
||||
#include <rak/functional.h>
|
||||
#include <rak/error_number.h>
|
||||
|
||||
#ifdef HAVE_BACKTRACE
|
||||
@@ -136,7 +99,7 @@ load_session_torrents() {
|
||||
// Replace with session torrent flag.
|
||||
f->set_session(true);
|
||||
f->set_init_load(true);
|
||||
f->slot_finished(std::bind(&rak::call_delete_func<core::DownloadFactory>, f));
|
||||
f->slot_finished([f](){ delete f; });
|
||||
f->load(entries.path() + first->s_name);
|
||||
f->commit();
|
||||
}
|
||||
@@ -151,7 +114,7 @@ load_arg_torrents(char** first, char** last) {
|
||||
// Replace with session torrent flag.
|
||||
f->set_start(true);
|
||||
f->set_init_load(true);
|
||||
f->slot_finished(std::bind(&rak::call_delete_func<core::DownloadFactory>, f));
|
||||
f->slot_finished([f](){ delete f; });
|
||||
f->load(*first);
|
||||
f->commit();
|
||||
}
|
||||
@@ -195,7 +158,7 @@ main(int argc, char** argv) {
|
||||
torrent::log_initialize();
|
||||
|
||||
control = new Control;
|
||||
|
||||
|
||||
unsigned int random_seed = cachedTime.seconds() ^ cachedTime.usec() ^ (getpid() << 16) ^ getppid();
|
||||
|
||||
srandom(random_seed);
|
||||
@@ -219,7 +182,7 @@ main(int argc, char** argv) {
|
||||
// platforms that do not properly pass signals to the target
|
||||
// threads. Use '--enable-interrupt-socket' when configuring
|
||||
// LibTorrent to enable this workaround.
|
||||
if (torrent::thread_base::should_handle_sigusr1())
|
||||
if (torrent::utils::Thread::should_handle_sigusr1())
|
||||
SignalHandler::set_handler(SIGUSR1, std::bind(&do_nothing));
|
||||
|
||||
torrent::log_add_group_output(torrent::LOG_NOTICE, "important");
|
||||
@@ -269,7 +232,7 @@ main(int argc, char** argv) {
|
||||
"method.insert = event.download.closed,multi|rlookup|static\n"
|
||||
"method.insert = event.download.resumed,multi|rlookup|static\n"
|
||||
"method.insert = event.download.paused,multi|rlookup|static\n"
|
||||
|
||||
|
||||
"method.insert = event.download.finished,multi|rlookup|static\n"
|
||||
"method.insert = event.download.hash_done,multi|rlookup|static\n"
|
||||
"method.insert = event.download.hash_failed,multi|rlookup|static\n"
|
||||
@@ -494,7 +457,7 @@ main(int argc, char** argv) {
|
||||
|
||||
rpc::commands.call_catch("event.system.startup_done", rpc::make_target(), "startup_done", "System startup_done event action failed: ");
|
||||
|
||||
torrent::thread_base::event_loop(torrent::main_thread());
|
||||
torrent::utils::Thread::event_loop(torrent::main_thread());
|
||||
|
||||
control->core()->download_list()->session_save();
|
||||
control->cleanup();
|
||||
@@ -525,7 +488,7 @@ main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
void
|
||||
handle_sigbus(int signum, siginfo_t* sa, void* ptr) {
|
||||
handle_sigbus(int signum, siginfo_t* sa, [[maybe_unused]] void* ptr) {
|
||||
if (signum != SIGBUS)
|
||||
do_panic(signum);
|
||||
|
||||
@@ -605,7 +568,7 @@ do_panic(int signum) {
|
||||
std::stringstream output;
|
||||
|
||||
output << "Caught " << SignalHandler::as_string(signum) << ", dumping stack:" << std::endl;
|
||||
|
||||
|
||||
#ifdef HAVE_BACKTRACE
|
||||
void* stackPtrs[20];
|
||||
|
||||
@@ -619,7 +582,7 @@ do_panic(int signum) {
|
||||
#else
|
||||
output << "Stack dump not enabled." << std::endl;
|
||||
#endif
|
||||
|
||||
|
||||
if (signum == SIGBUS)
|
||||
output << "A bus error probably means you ran out of diskspace." << std::endl;
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ bool
|
||||
OptionParser::has_flag(char flag, int argc, char** argv) {
|
||||
char options[3] = { '-', flag, '\0' };
|
||||
|
||||
return std::find_if(argv, argv + argc, std::not1(std::bind1st(std::ptr_fun(&std::strcmp), options))) != argv + argc;
|
||||
return std::find_if(argv, argv + argc, [&options](char* c) { return std::strcmp(c, options) == 0; }) != argv + argc;
|
||||
}
|
||||
|
||||
std::string
|
||||
|
||||
+1
-37
@@ -1,39 +1,3 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "core/download.h"
|
||||
@@ -45,7 +9,7 @@
|
||||
template const torrent::Object func_name<target_type>(command_base* rawCommand, target_type target, const torrent::Object& args); \
|
||||
template const torrent::Object func_name<core::Download*>(command_base* rawCommand, target_type target, const torrent::Object& args); \
|
||||
template const torrent::Object func_name<torrent::Peer*>(command_base* rawCommand, target_type target, const torrent::Object& args); \
|
||||
template const torrent::Object func_name<torrent::Tracker*>(command_base* rawCommand, target_type target, const torrent::Object& args); \
|
||||
template const torrent::Object func_name<torrent::tracker::Tracker*>(command_base* rawCommand, target_type target, const torrent::Object& args); \
|
||||
template const torrent::Object func_name<torrent::File*>(command_base* rawCommand, target_type target, const torrent::Object& args); \
|
||||
template const torrent::Object func_name<torrent::FileListIterator*>(command_base* rawCommand, target_type target, const torrent::Object& args);
|
||||
|
||||
|
||||
+8
-14
@@ -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);
|
||||
|
||||
@@ -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; };
|
||||
|
||||
|
||||
@@ -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
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "rpc/jsonrpc.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <torrent/common.h>
|
||||
#include <torrent/torrent.h>
|
||||
|
||||
#include "thread_base.h"
|
||||
#include "rpc/rpc_manager.h"
|
||||
#include "rpc/command.h"
|
||||
#include "rpc/command_map.h"
|
||||
#include "rpc/nlohmann/json.h"
|
||||
#include "rpc/parse_commands.h"
|
||||
#include "torrent/exceptions.h"
|
||||
#include "torrent/object.h"
|
||||
#include "utils/functional.h"
|
||||
|
||||
namespace rpc {
|
||||
|
||||
// Taken from https://www.jsonrpc.org/specification
|
||||
constexpr int JSONRPC_PARSE_ERROR = -32700;
|
||||
constexpr int JSONRPC_INVALID_REQUEST_ERROR = -32600;
|
||||
constexpr int JSONRPC_METHOD_NOT_FOUND_ERROR = -32601;
|
||||
constexpr int JSONRPC_INVALID_PARAMS_ERROR = -32602;
|
||||
constexpr int JSONRPC_INTERNAL_ERROR = -32000;
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
torrent::Object
|
||||
json_to_object(const json& value) {
|
||||
switch (value.type()) {
|
||||
case json::value_t::number_unsigned:
|
||||
case json::value_t::number_integer:
|
||||
return torrent::Object(value.get<int64_t>());
|
||||
case json::value_t::boolean:
|
||||
return value.get<bool>() ? torrent::Object(int64_t(1)) : torrent::Object(int64_t(0));
|
||||
case json::value_t::string:
|
||||
return torrent::Object(value.get<std::string>());
|
||||
case json::value_t::array: {
|
||||
auto array_raw = torrent::Object::create_list();
|
||||
auto& array = array_raw.as_list();
|
||||
for (const auto& entry : value) {
|
||||
array.push_back(json_to_object(entry));
|
||||
}
|
||||
return array_raw;
|
||||
}
|
||||
case json::value_t::object: {
|
||||
auto map_raw = torrent::Object::create_map();
|
||||
auto& map = map_raw.as_map();
|
||||
for (const auto& entry : value.items()) {
|
||||
map[entry.key()] = json_to_object(entry.value());
|
||||
}
|
||||
return map_raw;
|
||||
}
|
||||
case json::value_t::number_float:
|
||||
// type_name() for floats returns 'number', which is accurate for JSON but misleading
|
||||
throw torrent::input_error("invalid parameters: unexpected data type float");
|
||||
default:
|
||||
throw torrent::input_error("invalid parameters: unexpected data type " + std::string(value.type_name()));
|
||||
}
|
||||
}
|
||||
|
||||
json
|
||||
object_to_json(const torrent::Object& object) noexcept {
|
||||
switch (object.type()) {
|
||||
case torrent::Object::TYPE_VALUE:
|
||||
return object.as_value();
|
||||
case torrent::Object::TYPE_STRING:
|
||||
return object.as_string();
|
||||
case torrent::Object::TYPE_LIST: {
|
||||
json result = json::array();
|
||||
std::transform(object.as_list().cbegin(), object.as_list().cend(), std::back_inserter(result), [](const torrent::Object& element) {
|
||||
return object_to_json(element);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
case torrent::Object::TYPE_MAP: {
|
||||
json result = json::object();
|
||||
for (const auto& entry : object.as_map()) {
|
||||
result.emplace(entry.first, object_to_json(entry.second));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
case torrent::Object::TYPE_DICT_KEY: {
|
||||
json result = json::array();
|
||||
result.push_back(object_to_json(object.as_dict_key()));
|
||||
|
||||
const auto& dict_obj = object.as_dict_obj();
|
||||
if (dict_obj.is_list()) {
|
||||
std::transform(dict_obj.as_list().cbegin(), dict_obj.as_list().cend(), std::back_inserter(result), [](const torrent::Object& element) {
|
||||
return object_to_json(element);
|
||||
});
|
||||
} else {
|
||||
result.push_back(object_to_json(dict_obj));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
json
|
||||
jsonrpc_call_command(const std::string& method, const json& params) {
|
||||
if (params.type() == json::value_t::object) {
|
||||
// Named parameters is valid JSON-RPC, rtorrent just doesn't support it
|
||||
throw rpc_error(JSONRPC_INVALID_PARAMS_ERROR, "invalid parameter: procedure named parameter not supported");
|
||||
} else if (params.type() != json::value_t::array) {
|
||||
throw rpc_error(JSONRPC_INVALID_REQUEST_ERROR, "invalid request: params field must be an array");
|
||||
}
|
||||
|
||||
CommandMap::iterator itr = commands.find(method.c_str());
|
||||
|
||||
if (itr == commands.end()) {
|
||||
throw rpc_error(JSONRPC_METHOD_NOT_FOUND_ERROR, "method not found: " + method);
|
||||
}
|
||||
|
||||
torrent::Object params_object = json_to_object(params);
|
||||
auto& params_object_list = params_object.as_list();
|
||||
rpc::target_type target = rpc::make_target();
|
||||
|
||||
std::function<void()> deleter = []() {};
|
||||
utils::scope_guard guard([&deleter]() { deleter(); });
|
||||
|
||||
if (!(itr->second.m_flags & CommandMap::flag_no_target)) {
|
||||
// Provide a blank target if none was provided
|
||||
if (params_object_list.empty())
|
||||
params_object_list.push_back("");
|
||||
|
||||
if (!params_object_list.begin()->is_string())
|
||||
throw torrent::input_error("invalid parameters: target must be a string");
|
||||
|
||||
RpcManager::object_to_target(params_object_list.begin()->as_string(), itr->second.m_flags, &target, &deleter);
|
||||
|
||||
params_object_list.erase(params_object_list.begin());
|
||||
}
|
||||
|
||||
const auto& result = rpc::commands.call_command(itr, params_object, target);
|
||||
|
||||
return object_to_json(result);
|
||||
}
|
||||
|
||||
json
|
||||
json_error(int code, const std::string& msg, json id) {
|
||||
return json{{"jsonrpc", "2.0"}, {"id", id}, {"error", {{"code", code}, {"message", msg}}}};
|
||||
}
|
||||
|
||||
json
|
||||
handle_request(const json& request) {
|
||||
json response = {{"jsonrpc", "2.0"}, {"id", nullptr}};
|
||||
|
||||
try {
|
||||
if (!request["id"].is_number() && !request["id"].is_string() && !request["id"].is_null())
|
||||
return json_error(JSONRPC_INVALID_REQUEST_ERROR, "request id is invalid type " + std::string(request["id"].type_name()), response["id"]);
|
||||
response["id"] = request["id"];
|
||||
if (!request.contains("method") || !request["method"].is_string())
|
||||
return json_error(JSONRPC_INVALID_REQUEST_ERROR, "method string not present", response["id"]);
|
||||
if (request.contains("params"))
|
||||
response["result"] = jsonrpc_call_command(request["method"], request["params"]);
|
||||
else
|
||||
response["result"] = jsonrpc_call_command(request["method"], json::array({""}));
|
||||
return response;
|
||||
} catch (rpc_error& e) {
|
||||
return json_error(e.type(), e.what(), response["id"]);
|
||||
} catch (torrent::input_error& e) {
|
||||
return json_error(JSONRPC_INVALID_PARAMS_ERROR, e.what(), response["id"]);
|
||||
} catch (torrent::local_error& e) {
|
||||
return json_error(JSONRPC_INTERNAL_ERROR, e.what(), response["id"]);
|
||||
}
|
||||
}
|
||||
|
||||
// Notifications are basically the same as requests, except we can
|
||||
// just drop the message on the floor if there are any errors
|
||||
void
|
||||
handle_notification(const json& request) noexcept {
|
||||
if (!request.contains("method") || !request["method"].is_string())
|
||||
return;
|
||||
try {
|
||||
if (request.contains("params"))
|
||||
jsonrpc_call_command(request["method"], request["params"]);
|
||||
else
|
||||
jsonrpc_call_command(request["method"], json::array({""}));
|
||||
} catch (std::exception& e) {
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
JsonRpc::process(const char* in_buffer, uint32_t length, slot_write callback) {
|
||||
json response;
|
||||
json body;
|
||||
|
||||
try {
|
||||
body = json::parse(in_buffer, in_buffer + length);
|
||||
switch (body.type()) {
|
||||
case json::value_t::object: {
|
||||
if (!body.contains("id")) {
|
||||
handle_notification(body);
|
||||
return callback("", 0);
|
||||
} else {
|
||||
response = handle_request(body);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case json::value_t::array: {
|
||||
// Empty batch requests are invalid as per the spec
|
||||
if (body.empty()) {
|
||||
response = json_error(JSONRPC_INVALID_REQUEST_ERROR, "invalid request: empty batch", nullptr);
|
||||
break;
|
||||
}
|
||||
response = json::array();
|
||||
for (const auto& sub_body : body) {
|
||||
if (!sub_body.contains("id"))
|
||||
handle_notification(sub_body);
|
||||
else
|
||||
response.push_back(handle_request(sub_body));
|
||||
}
|
||||
// This indicates the batch was composed entirely of
|
||||
// notifications, in which case nothing is returned
|
||||
if (response.empty())
|
||||
return callback("", 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
response = json_error(JSONRPC_PARSE_ERROR, "message type " + std::string(body.type_name()) + " unsupported", nullptr);
|
||||
}
|
||||
|
||||
std::string response_str = response.dump();
|
||||
|
||||
return callback(response_str.c_str(), response_str.size());
|
||||
|
||||
} catch (json::parse_error& e) {
|
||||
auto err_str = json_error(JSONRPC_PARSE_ERROR, e.what(), nullptr).dump(-1, ' ', false, json::error_handler_t::replace);
|
||||
return callback(err_str.c_str(), err_str.size());
|
||||
} catch (json::type_error& e) {
|
||||
// Type errors may be caused by invalid UTF-8 strings in exception strings, hence the ::replace
|
||||
auto err_str = json_error(JSONRPC_PARSE_ERROR, e.what(), nullptr).dump(-1, ' ', false, json::error_handler_t::replace);
|
||||
return callback(err_str.c_str(), err_str.size());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace rpc
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef RTORRENT_RPC_JSONRPC_H
|
||||
#define RTORRENT_RPC_JSONRPC_H
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace rpc {
|
||||
|
||||
class JsonRpc {
|
||||
public:
|
||||
using slot_write = std::function<bool(const char*, uint32_t)>;
|
||||
|
||||
void initialize() {};
|
||||
void cleanup() {};
|
||||
|
||||
bool process(const char* in_buffer, uint32_t length, slot_write callback);
|
||||
|
||||
void insert_command(const char* name, const char* parm, const char* doc) {};
|
||||
};
|
||||
|
||||
} // namespace rpc
|
||||
|
||||
#endif
|
||||
+399
@@ -0,0 +1,399 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "rpc/lua.h"
|
||||
#ifdef HAVE_LUA
|
||||
#include <lua.hpp>
|
||||
#endif
|
||||
|
||||
#include <rak/error_number.h>
|
||||
#include <rak/path.h>
|
||||
#include <rak/string_manip.h>
|
||||
#include <torrent/object.h>
|
||||
|
||||
#include "core/download.h"
|
||||
#include "rpc/command.h"
|
||||
#include "rpc/command_map.h"
|
||||
#include "rpc/parse_commands.h"
|
||||
#include "rpc/xmlrpc.h"
|
||||
|
||||
namespace rpc {
|
||||
|
||||
const int LuaEngine::flag_string;
|
||||
const std::string LuaEngine::module_name = "rtorrent";
|
||||
|
||||
#ifdef HAVE_LUA
|
||||
|
||||
LuaEngine::LuaEngine() {
|
||||
m_luaState = luaL_newstate();
|
||||
luaL_openlibs(m_luaState);
|
||||
set_package_preload();
|
||||
}
|
||||
|
||||
LuaEngine::~LuaEngine() { lua_close(m_luaState); }
|
||||
|
||||
void
|
||||
LuaEngine::set_package_preload() {
|
||||
auto l_state = m_luaState;
|
||||
lua_getglobal(l_state, "package");
|
||||
lua_getfield(l_state, -1, "preload");
|
||||
lua_pushcfunction(l_state, LuaEngine::lua_init_module);
|
||||
lua_setfield(l_state, -2, LuaEngine::module_name.c_str());
|
||||
lua_pop(l_state, 2);
|
||||
}
|
||||
|
||||
void
|
||||
check_lua_status(lua_State* l_state, int status) {
|
||||
if (status != LUA_OK) {
|
||||
throw torrent::input_error(lua_tostring(l_state, -1));
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
LuaEngine::search_lua_path(lua_State* l_state) {
|
||||
// Get package.path
|
||||
lua_getglobal(l_state, "package");
|
||||
lua_getfield(l_state, -1, "path");
|
||||
std::string lua_path(lua_tostring(l_state, -1));
|
||||
lua_pop(l_state, 2);
|
||||
|
||||
// Use lambda here to ensure file closes as soon as it goes out of scope
|
||||
auto file_exists = [](const std::string& path) -> bool {
|
||||
std::ifstream file(path);
|
||||
return file.is_open();
|
||||
};
|
||||
|
||||
// Tokenize path using ';' as delimiter
|
||||
size_t pos = 0, end;
|
||||
while ((end = lua_path.find(';', pos)) != std::string::npos) {
|
||||
std::string file_path(lua_path.substr(pos, end - pos));
|
||||
size_t ppos = 0;
|
||||
while ((ppos = file_path.find('?')) != std::string::npos) {
|
||||
file_path.replace(ppos, 1, LuaEngine::module_name);
|
||||
}
|
||||
if (file_exists(file_path)) {
|
||||
return file_path;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
int
|
||||
LuaEngine::lua_rtorrent_call(lua_State* l_state) {
|
||||
auto method = lua_tostring(l_state, 1);
|
||||
lua_remove(l_state, 1);
|
||||
torrent::Object object;
|
||||
rpc::target_type target = rpc::make_target();
|
||||
;
|
||||
rpc::CommandMap::iterator itr = rpc::commands.find(std::string(method).c_str());
|
||||
if (itr == rpc::commands.end()) {
|
||||
throw torrent::input_error("method not found: " + std::string(method));
|
||||
}
|
||||
object = lua_callstack_to_object(l_state, itr->second.m_flags, &target);
|
||||
try {
|
||||
const auto& result = rpc::commands.call_command(itr, object, target);
|
||||
object_to_lua(l_state, result);
|
||||
return 1;
|
||||
} catch (torrent::base_error& e) {
|
||||
throw luaL_error(l_state, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
LuaEngine::lua_init_module(lua_State* l_state) {
|
||||
// Should this throw if it fails to find the file?
|
||||
auto lua_file = search_lua_path(l_state);
|
||||
if (!lua_file.empty()) {
|
||||
check_lua_status(l_state, luaL_loadfile(l_state, lua_file.c_str()));
|
||||
}
|
||||
lua_createtable(l_state, 0, 1);
|
||||
// Assign functions
|
||||
lua_pushliteral(l_state, "call");
|
||||
lua_pushcfunction(l_state, LuaEngine::lua_rtorrent_call);
|
||||
lua_settable(l_state, -3);
|
||||
if (!lua_file.empty()) {
|
||||
check_lua_status(l_state, lua_pcall(l_state, 1, 1, 0));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
object_to_target(const torrent::Object& obj, int call_flags, rpc::target_type* target) {
|
||||
if (!obj.is_string()) {
|
||||
throw torrent::input_error("invalid parameters: target must be a string");
|
||||
}
|
||||
std::string target_string = obj.as_string();
|
||||
bool require_index = (call_flags & (CommandMap::flag_tracker_target | CommandMap::flag_file_target));
|
||||
if (target_string.empty() && !require_index) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Length of SHA1 hash is 40
|
||||
if (target_string.size() < 40) {
|
||||
throw torrent::input_error("invalid parameters: invalid target");
|
||||
}
|
||||
|
||||
char type = 'd';
|
||||
std::string hash;
|
||||
std::string index;
|
||||
const auto& delim_pos = target_string.find_first_of(':', 40);
|
||||
if (delim_pos == target_string.npos || delim_pos + 2 >= target_string.size()) {
|
||||
if (require_index) {
|
||||
throw torrent::input_error("invalid parameters: no index");
|
||||
}
|
||||
hash = target_string;
|
||||
} else {
|
||||
hash = target_string.substr(0, delim_pos);
|
||||
type = target_string[delim_pos + 1];
|
||||
index = target_string.substr(delim_pos + 2);
|
||||
}
|
||||
core::Download* download = rpc.slot_find_download()(hash.c_str());
|
||||
|
||||
if (download == nullptr)
|
||||
throw torrent::input_error("invalid parameters: info-hash not found");
|
||||
|
||||
try {
|
||||
switch (type) {
|
||||
case 'd':
|
||||
*target = rpc::make_target(download);
|
||||
break;
|
||||
case 'f':
|
||||
*target = rpc::make_target(command_base::target_file, rpc.slot_find_file()(download, std::stoi(std::string(index))));
|
||||
break;
|
||||
case 't':
|
||||
*target =
|
||||
rpc::make_target(command_base::target_tracker, rpc.slot_find_tracker()(download, std::stoi(std::string(index))));
|
||||
break;
|
||||
case 'p': {
|
||||
if (index.size() < 40) {
|
||||
throw torrent::input_error("Not a hash string.");
|
||||
}
|
||||
torrent::HashString hash;
|
||||
torrent::hash_string_from_hex_c_str(index.c_str(), hash);
|
||||
*target = rpc::make_target(command_base::target_peer, rpc.slot_find_peer()(download, hash));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw torrent::input_error("invalid parameters: unexpected target type");
|
||||
}
|
||||
} catch (const std::logic_error&) {
|
||||
throw torrent::input_error("invalid parameters: invalid index");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
object_to_lua(lua_State* l_state, torrent::Object const& object) {
|
||||
// Converts an object to a single Lua stack object
|
||||
switch (object.type()) {
|
||||
case torrent::Object::TYPE_VALUE:
|
||||
lua_pushnumber(l_state, static_cast<double>(object.as_value()));
|
||||
break;
|
||||
case torrent::Object::TYPE_NONE:
|
||||
lua_pushnil(l_state);
|
||||
break;
|
||||
case torrent::Object::TYPE_STRING:
|
||||
lua_pushstring(l_state, object.as_string().c_str());
|
||||
break;
|
||||
case torrent::Object::TYPE_LIST: {
|
||||
int index = 1;
|
||||
auto object_list = object.as_list();
|
||||
|
||||
lua_createtable(l_state, static_cast<int>(object_list.size()), 0);
|
||||
int table_idx = lua_gettop(l_state);
|
||||
for (const auto& itr : object_list) {
|
||||
object_to_lua(l_state, itr);
|
||||
lua_rawseti(l_state, table_idx, lua_Integer(index++));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case torrent::Object::TYPE_MAP: {
|
||||
auto object_map = object.as_map();
|
||||
lua_createtable(l_state, 0, static_cast<int>(object_map.size()));
|
||||
int table_idx = lua_gettop(l_state);
|
||||
for (const auto& itr : object_map) {
|
||||
object_to_lua(l_state, itr.second);
|
||||
lua_pushlstring(l_state, itr.first.c_str(), itr.first.size());
|
||||
lua_rawset(l_state, table_idx);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
lua_pushnumber(l_state, lua_Number(object.type()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
lua_to_object(lua_State* l_state) {
|
||||
switch (lua_type(l_state, -1)) {
|
||||
case LUA_TNUMBER:
|
||||
return torrent::Object(lua_tonumber(l_state, -1));
|
||||
case LUA_TSTRING:
|
||||
return torrent::Object(lua_tostring(l_state, -1));
|
||||
case LUA_TBOOLEAN:
|
||||
return torrent::Object(lua_toboolean(l_state, -1));
|
||||
case LUA_TNIL:
|
||||
return torrent::Object((torrent::Object::value_type)0);
|
||||
case LUA_TTABLE: {
|
||||
lua_pushnil(l_state);
|
||||
int status = lua_next(l_state, -2);
|
||||
if (status == 0)
|
||||
return torrent::Object::create_map();
|
||||
// If the table starts at 1, assume it's an array
|
||||
if (lua_isnumber(l_state, -2) && (lua_tonumber(l_state, -2) == 1)) {
|
||||
torrent::Object list = torrent::Object::create_list();
|
||||
list.insert_back(lua_to_object(l_state));
|
||||
lua_pop(l_state, 1);
|
||||
while (lua_next(l_state, -2) != 0) {
|
||||
list.insert_back(lua_to_object(l_state));
|
||||
lua_pop(l_state, 1);
|
||||
}
|
||||
return list;
|
||||
} else {
|
||||
torrent::Object map = torrent::Object::create_map();
|
||||
// Reset the stack and start from the first element
|
||||
lua_pop(l_state, 2);
|
||||
lua_pushnil(l_state);
|
||||
while (lua_next(l_state, -2) != 0) {
|
||||
std::string key;
|
||||
switch (lua_type(l_state, -2)) {
|
||||
case LUA_TSTRING:
|
||||
key = lua_tostring(l_state, -2);
|
||||
break;
|
||||
default:
|
||||
// Bencode dictionaries require string keys, but naively
|
||||
// calling lua_tostring will auto-convert any other object
|
||||
// (particularly numbers) to strings in-place, which would
|
||||
// throw off lua_next, so we copy the value and only then
|
||||
// get the string.
|
||||
// https://www.lua.org/manual/5.3/manual.html#lua_tolstring
|
||||
lua_pushvalue(l_state, -2);
|
||||
key = lua_tostring(l_state, -1);
|
||||
lua_pop(l_state, 1);
|
||||
break;
|
||||
}
|
||||
map.insert_key(key, lua_to_object(l_state));
|
||||
lua_pop(l_state, 1);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
return torrent::Object(lua_tostring(l_state, -1));
|
||||
}
|
||||
default:
|
||||
std::string result = lua_tostring(l_state, -1);
|
||||
lua_pop(l_state, 1);
|
||||
return torrent::Object(result);
|
||||
}
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
lua_callstack_to_object(lua_State* l_state, int command_flags, rpc::target_type* target) {
|
||||
torrent::Object object;
|
||||
if (lua_gettop(l_state) == 0) {
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
if (!lua_isstring(l_state, 1)) {
|
||||
throw torrent::input_error("invalid parameters: target must be a string");
|
||||
}
|
||||
object_to_target(torrent::Object(lua_tostring(l_state, 1)), command_flags, target);
|
||||
|
||||
// start from the second argument since the first is the target
|
||||
lua_remove(l_state, 1);
|
||||
|
||||
if (lua_gettop(l_state) == 0) {
|
||||
return torrent::Object();
|
||||
} else {
|
||||
torrent::Object result = torrent::Object::create_list();
|
||||
torrent::Object::list_type& list_ref = result.as_list();
|
||||
while (lua_gettop(l_state) != 0) {
|
||||
list_ref.insert(list_ref.begin(), lua_to_object(l_state));
|
||||
lua_remove(l_state, -1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
int
|
||||
lua_rtorrent_call(lua_State* l_state) {
|
||||
torrent::Object object;
|
||||
rpc::target_type target = rpc::make_target();
|
||||
auto method = lua_tostring(l_state, 1);
|
||||
lua_remove(l_state, 1);
|
||||
|
||||
rpc::CommandMap::iterator itr = rpc::commands.find(method);
|
||||
if (itr == rpc::commands.end()) {
|
||||
throw torrent::input_error("method not found: " + std::string(method));
|
||||
}
|
||||
object = lua_callstack_to_object(l_state, itr->second.m_flags, &target);
|
||||
try {
|
||||
const auto& result = rpc::commands.call_command(itr, object, target);
|
||||
object_to_lua(l_state, result);
|
||||
return 1;
|
||||
} catch (torrent::base_error& e) {
|
||||
throw luaL_error(l_state, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
execute_lua(LuaEngine* engine, rpc::target_type target_type, torrent::Object const& raw_args, int flags) {
|
||||
size_t lua_argc = 1; // Target is always present, even if empty
|
||||
lua_State* l_state = engine->state();
|
||||
std::string target_string;
|
||||
|
||||
switch (target_type.first) {
|
||||
case (command_base::target_download):
|
||||
core::Download* dl_target = (core::Download*)target_type.second;
|
||||
torrent::HashString infohash = dl_target->info()->hash();
|
||||
target_string = rak::transform_hex_str(infohash);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (raw_args.type()) {
|
||||
case torrent::Object::TYPE_LIST: {
|
||||
const torrent::Object::list_type& args = raw_args.as_list();
|
||||
if (flags & LuaEngine::flag_string) {
|
||||
check_lua_status(l_state, luaL_loadstring(l_state, args.begin()->as_string().c_str()));
|
||||
} else {
|
||||
check_lua_status(l_state, luaL_loadfile(l_state, args.begin()->as_string().c_str()));
|
||||
}
|
||||
object_to_lua(l_state, target_string);
|
||||
for (torrent::Object::list_const_iterator itr = std::next(args.begin()), last = args.end(); itr != last; itr++) {
|
||||
object_to_lua(l_state, *itr);
|
||||
}
|
||||
lua_argc += args.size() - 1;
|
||||
break;
|
||||
}
|
||||
case torrent::Object::TYPE_STRING: {
|
||||
const torrent::Object::string_type& target = raw_args.as_string();
|
||||
if (flags & LuaEngine::flag_string) {
|
||||
check_lua_status(l_state, luaL_loadstring(l_state, target.c_str()));
|
||||
} else {
|
||||
check_lua_status(l_state, luaL_loadfile(l_state, target.c_str()));
|
||||
}
|
||||
object_to_lua(l_state, target_string);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw torrent::input_error("execute_lua(...): cannot call lua with arg type " + std::to_string(raw_args.type()));
|
||||
}
|
||||
check_lua_status(l_state, lua_pcall(l_state, lua_argc, LUA_MULTRET, 0));
|
||||
return lua_to_object(l_state);
|
||||
}
|
||||
|
||||
#else
|
||||
torrent::Object
|
||||
execute_lua(LuaEngine* engine, torrent::Object const& rawArgs, int flags) {
|
||||
throw torrent::input_error("Lua support not enabled");
|
||||
return torrent::Object();
|
||||
}
|
||||
LuaEngine::LuaEngine() {}
|
||||
LuaEngine::~LuaEngine() {}
|
||||
#endif
|
||||
} // namespace rpc
|
||||
@@ -0,0 +1,45 @@
|
||||
#ifndef RTORRENT_LUA_H
|
||||
#define RTORRENT_LUA_H
|
||||
|
||||
#include "rpc/command.h"
|
||||
#include <torrent/object.h>
|
||||
|
||||
#ifdef HAVE_LUA
|
||||
#include <lua.hpp>
|
||||
#endif
|
||||
|
||||
namespace rpc {
|
||||
|
||||
class LuaEngine {
|
||||
public:
|
||||
static const int flag_string = 0x1;
|
||||
static const std::string module_name;
|
||||
|
||||
LuaEngine();
|
||||
~LuaEngine();
|
||||
#ifdef HAVE_LUA
|
||||
// lua_CFunctions
|
||||
static int lua_init_module(lua_State* l_state);
|
||||
static int lua_rtorrent_call(lua_State* l_state);
|
||||
void set_package_preload();
|
||||
lua_State* state() { return m_luaState; }
|
||||
|
||||
private:
|
||||
static std::string search_lua_path(lua_State* l_state);
|
||||
lua_State* m_luaState;
|
||||
#endif
|
||||
};
|
||||
torrent::Object execute_lua(LuaEngine* engine, rpc::target_type target, const torrent::Object& raw_args, int flags);
|
||||
|
||||
#ifdef HAVE_LUA
|
||||
int rtorrent_call(lua_State* l_state);
|
||||
void init_rtorrent_module(lua_State* l_state);
|
||||
void object_to_lua(lua_State* l_state, torrent::Object const& object);
|
||||
void check_lua_status(lua_State* l_state, int status);
|
||||
torrent::Object lua_to_object(lua_State* l_state);
|
||||
torrent::Object lua_callstack_to_object(lua_State* l_state, int command_flags, rpc::target_type* target);
|
||||
#endif
|
||||
|
||||
} // namespace rpc
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,2 @@
|
||||
# third-party library, disable all checks in this folder.
|
||||
Checks: '-*'
|
||||
+25427
File diff suppressed because it is too large
Load Diff
@@ -38,7 +38,6 @@
|
||||
|
||||
#include "object_storage.h"
|
||||
|
||||
#include "rak/functional.h"
|
||||
#include "parse.h"
|
||||
#include "parse_commands.h"
|
||||
|
||||
@@ -223,8 +222,7 @@ object_storage::erase_multi_key(const torrent::raw_string& key, const std::strin
|
||||
if (r_itr == m_rlookup.end())
|
||||
return;
|
||||
|
||||
rlookup_mapped_iterator rm_itr = std::find_if(r_itr->second.begin(), r_itr->second.end(),
|
||||
rak::equal(key, rak::mem_ptr(&value_type::first)));
|
||||
rlookup_mapped_iterator rm_itr = std::find_if(r_itr->second.begin(), r_itr->second.end(), [key](value_type* type) { return key == type->first; });
|
||||
|
||||
if (rm_itr != r_itr->second.end())
|
||||
r_itr->second.erase(rm_itr);
|
||||
@@ -243,8 +241,7 @@ object_storage::set_multi_key_obj(const torrent::raw_string& key, const std::str
|
||||
if (r_itr == m_rlookup.end())
|
||||
r_itr = m_rlookup.insert(std::make_pair(cmd_key, rlookup_type::mapped_type())).first;
|
||||
|
||||
if (std::find_if(r_itr->second.begin(), r_itr->second.end(),
|
||||
rak::equal(key, rak::mem_ptr(&value_type::first))) == r_itr->second.end())
|
||||
if (std::find_if(r_itr->second.begin(), r_itr->second.end(), [key](value_type* type) { return key == type->first; }) == r_itr->second.end())
|
||||
r_itr->second.push_back(&*itr);
|
||||
}
|
||||
|
||||
@@ -259,7 +256,7 @@ object_storage::rlookup_list(const std::string& cmd_key) {
|
||||
|
||||
if (r_itr != m_rlookup.end())
|
||||
std::transform(r_itr->second.begin(), r_itr->second.end(), std::back_inserter(result),
|
||||
std::bind(&key_type::c_str, std::bind(rak::mem_ptr(&value_type::first), std::placeholders::_1)));
|
||||
std::bind(&key_type::c_str, std::bind(std::mem_fn(&value_type::first), std::placeholders::_1)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
+12
-19
@@ -39,30 +39,23 @@
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <rak/functional.h>
|
||||
#include <functional>
|
||||
#include <rak/path.h>
|
||||
#include <torrent/exceptions.h>
|
||||
|
||||
#include "parse.h"
|
||||
#include "parse_commands.h"
|
||||
#include "rpc/rpc_manager.h"
|
||||
|
||||
namespace rpc {
|
||||
|
||||
CommandMap commands;
|
||||
XmlRpc xmlrpc;
|
||||
ExecFile execFile;
|
||||
inline bool command_map_is_space(char c) {
|
||||
return c == ' ' || c == '\t';
|
||||
}
|
||||
|
||||
struct command_map_is_space : std::unary_function<char, bool> {
|
||||
bool operator () (char c) const {
|
||||
return c == ' ' || c == '\t';
|
||||
}
|
||||
};
|
||||
|
||||
struct command_map_is_newline : std::unary_function<char, bool> {
|
||||
bool operator () (char c) const {
|
||||
return c == '\n' || c == '\0' || c == ';';
|
||||
}
|
||||
};
|
||||
inline bool command_map_is_newline(char c) {
|
||||
return c == '\n' || c == '\0' || c == ';';
|
||||
}
|
||||
|
||||
// Only escape eol on odd number of escape characters. We know that
|
||||
// there can't be any characters in between, so this should work for
|
||||
@@ -131,7 +124,7 @@ parse_command_name(const char* first, const char* last, char* dest_first, char*
|
||||
// the code below for both cases.
|
||||
parse_command_type
|
||||
parse_command(target_type target, const char* first, const char* last) {
|
||||
first = std::find_if(first, last, std::not1(command_map_is_space()));
|
||||
first = std::find_if(first, last, [&](char c) { return !command_map_is_space(c); });
|
||||
|
||||
if (first == last || *first == '#')
|
||||
return std::make_pair(torrent::Object(), first);
|
||||
@@ -139,7 +132,7 @@ parse_command(target_type target, const char* first, const char* last) {
|
||||
char key[128];
|
||||
|
||||
first = parse_command_name(first, last, key, key + 128);
|
||||
first = std::find_if(first, last, std::not1(command_map_is_space()));
|
||||
first = std::find_if(first, last, [&](char c) { return !command_map_is_space(c); });
|
||||
|
||||
if (first == last || *first != '=')
|
||||
throw torrent::input_error("Could not find '=' in command '" + std::string(key) + "'.");
|
||||
@@ -150,10 +143,10 @@ parse_command(target_type target, const char* first, const char* last) {
|
||||
// Find the last character that is part of this command, skipping
|
||||
// the whitespace at the end. This ensures us that the caller
|
||||
// doesn't need to do this nor check for junk at the end.
|
||||
first = std::find_if(first, last, std::not1(command_map_is_space()));
|
||||
first = std::find_if(first, last, [&](char c) { return !command_map_is_space(c); });
|
||||
|
||||
if (first != last) {
|
||||
if (*first != '\n' && *first != ';' && *first != '\0')
|
||||
if (!command_map_is_newline(*first))
|
||||
throw torrent::input_error("Junk at end of input.");
|
||||
|
||||
first++;
|
||||
|
||||
@@ -40,9 +40,8 @@
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
|
||||
#include "command_map.h"
|
||||
#include "exec_file.h"
|
||||
#include "xmlrpc.h"
|
||||
#include "rpc_manager.h"
|
||||
|
||||
namespace core {
|
||||
class Download;
|
||||
@@ -50,11 +49,6 @@ namespace core {
|
||||
|
||||
namespace rpc {
|
||||
|
||||
// Move to another file?
|
||||
extern CommandMap commands;
|
||||
extern XmlRpc xmlrpc;
|
||||
extern ExecFile execFile;
|
||||
|
||||
typedef std::pair<torrent::Object, const char*> parse_command_type;
|
||||
|
||||
// The generic parse command function, used by the rest. At some point
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <torrent/exceptions.h>
|
||||
|
||||
#include "parse_commands.h"
|
||||
#include "rpc/rpc_manager.h"
|
||||
|
||||
namespace rpc {
|
||||
|
||||
CommandMap commands;
|
||||
RpcManager rpc;
|
||||
ExecFile execFile;
|
||||
|
||||
void
|
||||
RpcManager::object_to_target(const torrent::Object& obj, int call_flags, rpc::target_type* target, std::function<void()>* deleter) {
|
||||
if (call_flags & CommandMap::flag_no_target)
|
||||
return;
|
||||
|
||||
if (!obj.is_string()) {
|
||||
throw torrent::input_error("invalid parameters: target must be a string");
|
||||
}
|
||||
std::string target_string = obj.as_string();
|
||||
bool require_index = (call_flags & (CommandMap::flag_tracker_target | CommandMap::flag_file_target));
|
||||
if (target_string.size() == 0 && !require_index) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Length of SHA1 hash is 40
|
||||
if (target_string.size() < 40) {
|
||||
throw torrent::input_error("invalid parameters: invalid target");
|
||||
}
|
||||
|
||||
char type = 'd';
|
||||
std::string hash;
|
||||
std::string index;
|
||||
|
||||
const auto& delim_pos = target_string.find_first_of(':', 40);
|
||||
if (delim_pos == target_string.npos ||
|
||||
delim_pos + 2 >= target_string.size()) {
|
||||
if (require_index) {
|
||||
throw torrent::input_error("invalid parameters: no index");
|
||||
}
|
||||
hash = target_string;
|
||||
} else {
|
||||
hash = target_string.substr(0, delim_pos);
|
||||
type = target_string[delim_pos + 1];
|
||||
index = target_string.substr(delim_pos + 2);
|
||||
}
|
||||
core::Download* download = rpc.slot_find_download()(hash.c_str());
|
||||
|
||||
if (download == nullptr)
|
||||
throw torrent::input_error("invalid parameters: info-hash not found");
|
||||
|
||||
try {
|
||||
torrent::tracker::Tracker* tracker;
|
||||
|
||||
switch (type) {
|
||||
case 'd':
|
||||
*target = rpc::make_target(download);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
*target = rpc::make_target(command_base::target_file,
|
||||
rpc.slot_find_file()(download, std::stoi(std::string(index))));
|
||||
|
||||
break;
|
||||
|
||||
case 't':
|
||||
tracker = new torrent::tracker::Tracker(rpc.slot_find_tracker()(download, std::stoi(std::string(index))));
|
||||
|
||||
*target = rpc::make_target(command_base::target_tracker, tracker);
|
||||
*deleter = [tracker]() { delete tracker; };
|
||||
break;
|
||||
|
||||
case 'p': {
|
||||
if (index.size() < 40) {
|
||||
throw torrent::input_error("invalid parameters: not a hash string.");
|
||||
}
|
||||
|
||||
torrent::HashString hash;
|
||||
torrent::hash_string_from_hex_c_str(index.c_str(), hash);
|
||||
|
||||
*target = rpc::make_target(command_base::target_peer,
|
||||
rpc.slot_find_peer()(download, hash));
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw torrent::input_error("invalid parameters: unexpected target type");
|
||||
}
|
||||
|
||||
} catch (const std::logic_error&) {
|
||||
throw torrent::input_error("invalid parameters: invalid index");
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
RpcManager::process(RPCType type, const char* in_buffer, uint32_t length, slot_response_callback callback) {
|
||||
switch (type) {
|
||||
case RPCType::XML: {
|
||||
if (m_xmlrpc.is_valid() && rpc::call_command_value("network.rpc.use_xmlrpc")) {
|
||||
return m_xmlrpc.process(in_buffer, length, callback);
|
||||
} else {
|
||||
const std::string response = "<?xml version=\"1.0\"?><methodResponse><fault><struct><member><name>faultCode</name><value><i8>-501</i8></value></member><member><name>faultString</name><value><string>XML-RPC not supported</string></value></member></struct></fault></methodResponse>";
|
||||
return callback(response.c_str(), response.size());
|
||||
}
|
||||
}
|
||||
case RPCType::JSON: {
|
||||
if (rpc::call_command_value("network.rpc.use_jsonrpc")) {
|
||||
return m_jsonrpc.process(in_buffer, length, callback);
|
||||
} else {
|
||||
const std::string response = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32601,\"message\":\"JSON-RPC not supported\"},\"id\":null}";
|
||||
return callback(response.c_str(), response.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RpcManager::initialize() {
|
||||
m_xmlrpc.initialize();
|
||||
m_jsonrpc.initialize();
|
||||
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
void
|
||||
RpcManager::cleanup() {
|
||||
m_xmlrpc.cleanup();
|
||||
m_jsonrpc.cleanup();
|
||||
}
|
||||
|
||||
bool
|
||||
RpcManager::is_type_enabled(RPCType type) const {
|
||||
switch (type) {
|
||||
case RPCType::XML:
|
||||
return m_is_xmlrpc_enabled;
|
||||
case RPCType::JSON:
|
||||
return m_is_jsonrpc_enabled;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RpcManager::set_type_enabled(RPCType type, bool enabled) {
|
||||
switch (type) {
|
||||
case RPCType::XML:
|
||||
m_is_xmlrpc_enabled = enabled;
|
||||
case RPCType::JSON:
|
||||
m_is_jsonrpc_enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
RpcManager::is_initialized() const {
|
||||
return m_initialized;
|
||||
}
|
||||
|
||||
void
|
||||
RpcManager::insert_command(const char* name, const char* parm, const char* doc) {
|
||||
m_xmlrpc.insert_command(name, parm, doc);
|
||||
m_jsonrpc.insert_command(name, parm, doc);
|
||||
}
|
||||
|
||||
} // namespace rpc
|
||||
@@ -0,0 +1,92 @@
|
||||
#ifndef RTORRENT_RPC_MANAGER_H
|
||||
#define RTORRENT_RPC_MANAGER_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <torrent/common.h>
|
||||
|
||||
#include "rpc/command.h"
|
||||
#include "rpc/command_map.h"
|
||||
#include "rpc/exec_file.h"
|
||||
#include "rpc/jsonrpc.h"
|
||||
#include "rpc/xmlrpc.h"
|
||||
|
||||
namespace core {
|
||||
class Download;
|
||||
}
|
||||
|
||||
namespace rpc {
|
||||
|
||||
extern ExecFile execFile;
|
||||
extern CommandMap commands;
|
||||
|
||||
class rpc_error : public torrent::base_error {
|
||||
public:
|
||||
rpc_error(int type, std::string msg) :
|
||||
m_type(type), m_msg(msg) {}
|
||||
virtual ~rpc_error() throw() {}
|
||||
|
||||
virtual int type() const throw() { return m_type; }
|
||||
virtual const char* what() const throw() { return m_msg.c_str(); }
|
||||
|
||||
private:
|
||||
int m_type;
|
||||
std::string m_msg;
|
||||
};
|
||||
|
||||
class RpcManager {
|
||||
public:
|
||||
using slot_download = std::function<core::Download*(const char*)>;
|
||||
using slot_file = std::function<torrent::File*(core::Download*, uint32_t)>;
|
||||
using slot_tracker = std::function<torrent::tracker::Tracker(core::Download*, uint32_t)>;
|
||||
using slot_peer = std::function<torrent::Peer*(core::Download*, const torrent::HashString&)>;
|
||||
using slot_response_callback = std::function<bool(const char*, uint32_t)>;
|
||||
|
||||
enum RPCType { XML,
|
||||
JSON };
|
||||
|
||||
RpcManager() = default;
|
||||
~RpcManager() = default;
|
||||
|
||||
void initialize();
|
||||
void cleanup();
|
||||
bool is_initialized() const;
|
||||
|
||||
int64_t size_limit() { return m_xmlrpc.size_limit(); };
|
||||
void set_size_limit(uint64_t size) { m_xmlrpc.set_size_limit(size); };
|
||||
int dialect() { return m_xmlrpc.dialect(); }
|
||||
void set_dialect(int dialect) { m_xmlrpc.set_dialect(dialect); }
|
||||
|
||||
bool is_type_enabled(RPCType type) const;
|
||||
void set_type_enabled(RPCType type, bool enabled);
|
||||
|
||||
bool process(RPCType type, const char* in_buffer, uint32_t length, slot_response_callback callback);
|
||||
|
||||
void insert_command(const char* name, const char* parm, const char* doc);
|
||||
|
||||
slot_download& slot_find_download() { return m_slot_find_download; }
|
||||
slot_file& slot_find_file() { return m_slot_find_file; }
|
||||
slot_tracker& slot_find_tracker() { return m_slot_find_tracker; }
|
||||
slot_peer& slot_find_peer() { return m_slot_find_peer; }
|
||||
|
||||
static void object_to_target(const torrent::Object& obj, int callFlags, rpc::target_type* target, std::function<void()>* deleter);
|
||||
|
||||
private:
|
||||
XmlRpc m_xmlrpc;
|
||||
JsonRpc m_jsonrpc;
|
||||
|
||||
bool m_initialized = false;
|
||||
bool m_is_jsonrpc_enabled = true;
|
||||
bool m_is_xmlrpc_enabled = true;
|
||||
|
||||
slot_download m_slot_find_download;
|
||||
slot_file m_slot_find_file;
|
||||
slot_tracker m_slot_find_tracker;
|
||||
slot_peer m_slot_find_peer;
|
||||
};
|
||||
|
||||
extern RpcManager rpc;
|
||||
|
||||
} // namespace rpc
|
||||
|
||||
#endif
|
||||
+15
-41
@@ -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
@@ -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, ¤t, 0);
|
||||
int header_size = strtol(m_buffer, ¤t, 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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -91,6 +91,8 @@ ThreadBase::call_events() {
|
||||
call_queued_items();
|
||||
|
||||
rak::priority_queue_perform(&m_taskScheduler, cachedTime);
|
||||
|
||||
process_callbacks();
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
+2
-38
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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");
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user