├── .clang-format ├── .clang-tidy ├── .dir-locals.el ├── .github ├── FUNDING.yml └── workflows │ ├── post-static-analysis.yml │ ├── static-analysis.yml │ └── unit-tests.yml ├── .gitignore ├── .travis.yml ├── AUTHORS ├── COPYING ├── ChangeLog ├── INSTALL ├── Makefile.am ├── NEWS ├── README ├── README.md ├── configure.ac ├── doc ├── Makefile.am ├── debugging ├── faq.xml ├── log_proc_vmmap.sh ├── log_rtorrent.sh ├── log_stats.plot ├── log_vmmap.sh ├── manual │ ├── choke_groups.md │ ├── ip_filtering.md │ ├── ip_filtering.tex │ ├── logging.md │ └── logging.tex ├── old │ ├── rtorrent.1 │ └── rtorrent.1.xml ├── plot │ ├── instrumentation_mincore.sh │ └── instrumentation_transfers.sh ├── rtorrent.rc ├── rtorrent.rc-example ├── rtorrent_fast_resume.pl ├── scripts │ ├── init │ │ ├── rtorrentInitScreen.bash │ │ ├── rtorrentInitScreen.sh │ │ └── rtorrentInitTmux.bash │ ├── print_option_string.sh │ └── update_commands_0.9.sed └── torrent_data ├── rak ├── address_info.h ├── algorithm.h ├── error_number.h ├── file_stat.h ├── fs_stat.h ├── partial_queue.h ├── path.h ├── regex.h ├── socket_address.h ├── string_manip.h └── unordered_vector.h ├── rtorrent.lua ├── scripts ├── attributes.m4 ├── ax_check_zlib.m4 ├── ax_cxx_compile_stdcxx.m4 ├── ax_execinfo.m4 ├── ax_lua.m4 ├── ax_pthread.m4 ├── ax_require_defined.m4 ├── ax_with_curses.m4 ├── checks.m4 ├── common.m4 ├── rak_compiler.m4 └── ssl.m4 ├── src ├── Makefile.am ├── command_download.cc ├── command_dynamic.cc ├── command_events.cc ├── command_file.cc ├── command_groups.cc ├── command_helpers.cc ├── command_helpers.h ├── command_ip.cc ├── command_local.cc ├── command_logging.cc ├── command_network.cc ├── command_peer.cc ├── command_scheduler.cc ├── command_throttle.cc ├── command_tracker.cc ├── command_ui.cc ├── control.cc ├── control.h ├── core │ ├── curl_get.cc │ ├── curl_get.h │ ├── curl_socket.cc │ ├── curl_socket.h │ ├── curl_stack.cc │ ├── curl_stack.h │ ├── dht_manager.cc │ ├── dht_manager.h │ ├── download.cc │ ├── download.h │ ├── download_factory.cc │ ├── download_factory.h │ ├── download_list.cc │ ├── download_list.h │ ├── download_slot_map.h │ ├── download_store.cc │ ├── download_store.h │ ├── http_queue.cc │ ├── http_queue.h │ ├── manager.cc │ ├── manager.h │ ├── range_map.h │ ├── view.cc │ ├── view.h │ ├── view_manager.cc │ └── view_manager.h ├── display │ ├── attributes.h │ ├── canvas.cc │ ├── canvas.h │ ├── color_map.h │ ├── frame.cc │ ├── frame.h │ ├── manager.cc │ ├── manager.h │ ├── text_element.h │ ├── text_element_list.cc │ ├── text_element_list.h │ ├── text_element_string.cc │ ├── text_element_string.h │ ├── text_element_value.cc │ ├── text_element_value.h │ ├── utils.cc │ ├── utils.h │ ├── window.cc │ ├── window.h │ ├── window_download_chunks_seen.cc │ ├── window_download_chunks_seen.h │ ├── window_download_list.cc │ ├── window_download_list.h │ ├── window_download_statusbar.cc │ ├── window_download_statusbar.h │ ├── window_download_transfer_list.cc │ ├── window_download_transfer_list.h │ ├── window_file_list.cc │ ├── window_file_list.h │ ├── window_http_queue.cc │ ├── window_http_queue.h │ ├── window_input.cc │ ├── window_input.h │ ├── window_log.cc │ ├── window_log.h │ ├── window_log_complete.cc │ ├── window_log_complete.h │ ├── window_peer_list.cc │ ├── window_peer_list.h │ ├── window_statusbar.cc │ ├── window_statusbar.h │ ├── window_string_list.cc │ ├── window_string_list.h │ ├── window_text.cc │ ├── window_text.h │ ├── window_title.cc │ ├── window_title.h │ ├── window_tracker_list.cc │ └── window_tracker_list.h ├── globals.cc ├── globals.h ├── input │ ├── bindings.cc │ ├── bindings.h │ ├── input_event.cc │ ├── input_event.h │ ├── manager.cc │ ├── manager.h │ ├── path_input.cc │ ├── path_input.h │ ├── text_input.cc │ └── text_input.h ├── main.cc ├── option_parser.cc ├── option_parser.h ├── rpc │ ├── command.cc │ ├── command.h │ ├── command_impl.h │ ├── command_map.cc │ ├── command_map.h │ ├── command_scheduler.cc │ ├── command_scheduler.h │ ├── command_scheduler_item.cc │ ├── command_scheduler_item.h │ ├── exec_file.cc │ ├── exec_file.h │ ├── fixed_key.h │ ├── ip_table_list.h │ ├── jsonrpc.cc │ ├── jsonrpc.h │ ├── lua.cc │ ├── lua.h │ ├── nlohmann │ │ ├── .clang-tidy │ │ └── json.h │ ├── object_storage.cc │ ├── object_storage.h │ ├── parse.cc │ ├── parse.h │ ├── parse_commands.cc │ ├── parse_commands.h │ ├── parse_options.cc │ ├── parse_options.h │ ├── rpc_manager.cc │ ├── rpc_manager.h │ ├── scgi.cc │ ├── scgi.h │ ├── scgi_task.cc │ ├── scgi_task.h │ ├── tinyxml2 │ │ ├── tinyxml2.cc │ │ └── tinyxml2.h │ ├── xmlrpc.cc │ ├── xmlrpc.h │ ├── xmlrpc_c.cc │ └── xmlrpc_tinyxml2.cc ├── signal_handler.cc ├── signal_handler.h ├── thread_worker.cc ├── thread_worker.h ├── ui │ ├── download.cc │ ├── download.h │ ├── download_list.cc │ ├── download_list.h │ ├── element_base.cc │ ├── element_base.h │ ├── element_chunks_seen.cc │ ├── element_chunks_seen.h │ ├── element_download_list.cc │ ├── element_download_list.h │ ├── element_file_list.cc │ ├── element_file_list.h │ ├── element_log_complete.cc │ ├── element_log_complete.h │ ├── element_menu.cc │ ├── element_menu.h │ ├── element_peer_list.cc │ ├── element_peer_list.h │ ├── element_string_list.cc │ ├── element_string_list.h │ ├── element_text.cc │ ├── element_text.h │ ├── element_tracker_list.cc │ ├── element_tracker_list.h │ ├── element_transfer_list.cc │ ├── element_transfer_list.h │ ├── root.cc │ └── root.h └── utils │ ├── base64.cc │ ├── base64.h │ ├── directory.cc │ ├── directory.h │ ├── file_status_cache.cc │ ├── file_status_cache.h │ ├── functional.h │ ├── list_focus.h │ ├── lockfile.cc │ ├── lockfile.h │ ├── socket_fd.cc │ └── socket_fd.h └── test ├── Makefile.am ├── helpers ├── assert.h ├── mock_compare.h ├── mock_function.cc ├── mock_function.h ├── progress_listener.cc ├── progress_listener.h ├── protectors.cc ├── protectors.h ├── test_fixture.cc ├── test_fixture.h ├── test_main_thread.cc ├── test_main_thread.h ├── test_thread.cc ├── test_thread.h ├── test_utils.h └── utils.h ├── main.cc ├── rpc ├── test_command.cc ├── test_command.h ├── test_command_map.cc ├── test_command_map.h ├── test_command_slot.cc ├── test_command_slot.h ├── test_jsonrpc.cc ├── test_jsonrpc.h ├── test_object_storage.cc ├── test_object_storage.h ├── test_parse_options.cc ├── test_parse_options.h ├── test_xmlrpc.cc └── test_xmlrpc.h └── src ├── test_command_dynamic.cc └── test_command_dynamic.h /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: LLVM 3 | Standard: c++14 4 | 5 | AllowShortFunctionsOnASingleLine: All 6 | AllowShortLambdasOnASingleLine: All 7 | AlwaysBreakAfterReturnType: TopLevelDefinitions 8 | BinPackArguments: false 9 | BinPackParameters: false 10 | BreakConstructorInitializers: AfterColon 11 | BreakStringLiterals: false 12 | ColumnLimit: 0 13 | ContinuationIndentWidth: 2 14 | IndentCaseLabels: false 15 | IndentWidth: 2 16 | PenaltyReturnTypeOnItsOwnLine: 130 17 | PointerAlignment: Left 18 | 19 | AlignEscapedNewlines: Right 20 | AlignConsecutiveDeclarations: 21 | Enabled: true 22 | AcrossEmptyLines: true 23 | AcrossComments: false 24 | AlignConsecutiveMacros: 25 | Enabled: true 26 | AlignConsecutiveAssignments: 27 | Enabled: true 28 | 29 | IncludeCategories: 30 | - Regex: "^(config|globals)\\.h" 31 | Priority: -1 32 | - Regex: "^torrent/.*" 33 | Priority: 1 34 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | --- 2 | Checks: '-*,readability-identifier-naming' 3 | FormatStyle: 'file' 4 | CheckOptions: 5 | - key: readability-identifier-naming.LocalVariableCase 6 | value: lower_case 7 | - key: readability-identifier-naming.ParameterCase 8 | value: lower_case 9 | - key: readability-identifier-naming.FunctionCase 10 | value: lower_case 11 | - key: readability-identifier-naming.PrivateMemberPrefix 12 | value: m_ 13 | - key: readability-identifier-naming.PrivateMemberCase 14 | value: lower_case 15 | - key: readability-identifier-naming.ClassConstantCase 16 | value: lower_case 17 | -------------------------------------------------------------------------------- /.dir-locals.el: -------------------------------------------------------------------------------- 1 | ;;; Directory Local Variables 2 | ;;; For more information see (info "(emacs) Directory Variables") 3 | 4 | ((c++-mode 5 | (flycheck-clang-language-standard . "c++11") 6 | (flycheck-gcc-language-standard . "c++11"))) 7 | 8 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [rakshasa] 4 | patreon: rtorrent 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: ['https://rakshasa.github.io/rtorrent/donate.html'] 14 | -------------------------------------------------------------------------------- /.github/workflows/static-analysis.yml: -------------------------------------------------------------------------------- 1 | name: Static analysis 2 | 3 | on: pull_request 4 | 5 | jobs: 6 | 7 | clang-tidy: 8 | runs-on: ubuntu-22.04 9 | 10 | steps: 11 | - name: Update Packages 12 | run: | 13 | sudo apt-get update 14 | - name: Fetch libtorrent 15 | run: | 16 | git clone https://github.com/rakshasa/libtorrent 17 | - name: Build libtorrent 18 | run: | 19 | cd libtorrent 20 | libtoolize 21 | aclocal -I scripts 22 | autoconf -i 23 | autoheader 24 | automake --add-missing 25 | ./configure 26 | make 27 | sudo make install 28 | cd .. 29 | rm -rf libtorrent 30 | - uses: actions/checkout@v4 31 | with: 32 | ref: ${{ github.event.pull_request.head.sha }} 33 | fetch-depth: 0 34 | - name: Fetch base branch 35 | run: | 36 | git remote add upstream "https://github.com/${{ github.event.pull_request.base.repo.full_name }}" 37 | git fetch --no-tags --no-recurse-submodules upstream "${{ github.event.pull_request.base.ref }}" 38 | - name: Install Dependencies 39 | run: | 40 | sudo apt-get install -y bear clang-tidy libcurl4-openssl-dev 41 | - name: Configure Project 42 | run: | 43 | libtoolize 44 | aclocal -I scripts 45 | autoconf -i 46 | autoheader 47 | automake --add-missing 48 | ./configure 49 | - name: Prepare compile_commands.json 50 | run: | 51 | bear -- make 52 | - name: Create results directory 53 | run: | 54 | mkdir clang-tidy-result 55 | - name: Analyze 56 | run: | 57 | 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" 58 | - name: Save PR metadata 59 | run: | 60 | echo "${{ github.event.number }}" > clang-tidy-result/pr-id.txt 61 | echo "${{ github.event.pull_request.head.repo.full_name }}" > clang-tidy-result/pr-head-repo.txt 62 | echo "${{ github.event.pull_request.head.sha }}" > clang-tidy-result/pr-head-sha.txt 63 | - uses: actions/upload-artifact@v4 64 | with: 65 | name: clang-tidy-result 66 | path: clang-tidy-result/ 67 | # - name: Run clang-tidy-pr-comments action 68 | # uses: platisd/clang-tidy-pr-comments@v1 69 | # with: 70 | # # The GitHub token (or a personal access token) 71 | # github_token: ${{ secrets.GITHUB_TOKEN }} 72 | # # The path to the clang-tidy fixes generated previously 73 | # clang_tidy_fixes: clang-tidy-result/fixes.yml 74 | # # Optionally set to true if you want the Action to request 75 | # # changes in case warnings are found 76 | # request_changes: true 77 | # # Optionally set the number of comments per review 78 | # # to avoid GitHub API timeouts for heavily loaded 79 | # # pull requests 80 | # suggestions_per_comment: 10 81 | -------------------------------------------------------------------------------- /.github/workflows/unit-tests.yml: -------------------------------------------------------------------------------- 1 | name: Static analysis 2 | 3 | on: pull_request 4 | 5 | jobs: 6 | 7 | unit-tests: 8 | runs-on: ubuntu-22.04 9 | 10 | steps: 11 | - name: Update Packages 12 | run: | 13 | sudo apt-get update 14 | - name: Fetch libtorrent 15 | run: | 16 | git clone https://github.com/rakshasa/libtorrent 17 | - name: Build libtorrent 18 | run: | 19 | cd libtorrent 20 | libtoolize 21 | aclocal -I scripts 22 | autoconf -i 23 | autoheader 24 | automake --add-missing 25 | ./configure 26 | make 27 | sudo make install 28 | cd .. 29 | rm -rf libtorrent 30 | - uses: actions/checkout@v4 31 | with: 32 | ref: ${{ github.event.pull_request.head.sha }} 33 | fetch-depth: 0 34 | - name: Fetch base branch 35 | run: | 36 | git remote add upstream "https://github.com/${{ github.event.pull_request.base.repo.full_name }}" 37 | git fetch --no-tags --no-recurse-submodules upstream "${{ github.event.pull_request.base.ref }}" 38 | - name: Install Dependencies 39 | run: | 40 | sudo apt-get install -y \ 41 | libcppunit-dev \ 42 | libcurl4-openssl-dev 43 | - name: Configure Project 44 | run: | 45 | libtoolize 46 | aclocal -I scripts 47 | autoconf -i 48 | autoheader 49 | automake --add-missing 50 | ./configure 51 | - name: Build Project 52 | run: | 53 | make 54 | - name: Run Unit Tests 55 | run: | 56 | make check 57 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.o 4 | *.lo 5 | *.a 6 | *.la 7 | *.so 8 | *.in 9 | *.sub 10 | *.pc 11 | *.orig 12 | *.rej 13 | 14 | # Autoconf files # 15 | ################## 16 | 17 | .deps 18 | .libs 19 | Makefile 20 | aclocal.m4 21 | ar-lib 22 | autom4te.cache 23 | compile 24 | config.h 25 | config.guess 26 | config.status 27 | confdefs.h 28 | conftest.dir 29 | configure 30 | depcomp 31 | install-sh 32 | libtool 33 | ltmain.sh 34 | missing 35 | stamp-h1 36 | 37 | src/rtorrent 38 | scripts/libtool.m4 39 | scripts/lt*.m4 40 | 41 | # Editor poo # 42 | ############## 43 | .#* 44 | \#*# 45 | *~ 46 | 47 | # Packages # 48 | ############ 49 | # it's better to unpack these files and commit the raw source 50 | # git has its own built in compression methods 51 | *.gz 52 | *.tar 53 | *.zip 54 | 55 | # Logs and databases # 56 | ###################### 57 | *.log 58 | 59 | # OS generated files # 60 | ###################### 61 | .DS_Store? 62 | .dirstamp 63 | ehthumbs.db 64 | Icon? 65 | Thumbs.db 66 | TAGS 67 | 68 | # rTorrent specific files 69 | ########################### 70 | src/rtorrent 71 | test/rtorrent_Test* 72 | test-driver 73 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | env: 4 | global: 5 | - MAKEFLAGS="-j 12" 6 | 7 | matrix: 8 | include: 9 | - compiler: clang 10 | env: COMPILER=clang++ SKIP_CHECK=true 11 | - compiler: clang 12 | env: COMPILER=clang++ 13 | addons: 14 | apt: 15 | packages: 16 | - libcppunit-dev 17 | - compiler: clang 18 | env: COMPILER=clang++-3.6 19 | addons: 20 | apt: 21 | sources: 22 | - ubuntu-toolchain-r-test 23 | - llvm-toolchain-precise-3.6 24 | packages: 25 | - clang-3.6 26 | - libcppunit-dev 27 | - compiler: clang 28 | env: COMPILER=clang++-3.7 29 | addons: 30 | apt: 31 | sources: 32 | - ubuntu-toolchain-r-test 33 | - llvm-toolchain-precise-3.7 34 | packages: 35 | - clang-3.7 36 | - libcppunit-dev 37 | - compiler: clang 38 | env: COMPILER=clang++-3.8 39 | addons: 40 | apt: 41 | sources: 42 | - ubuntu-toolchain-r-test 43 | - llvm-toolchain-precise-3.8 44 | packages: 45 | - clang-3.8 46 | - libcppunit-dev 47 | - compiler: gcc 48 | env: COMPILER=g++-4.7 SKIP_CHECK=true 49 | addons: 50 | apt: 51 | sources: ubuntu-toolchain-r-test 52 | packages: 53 | - g++-4.7 54 | - compiler: gcc 55 | env: COMPILER=g++-4.7 56 | addons: 57 | apt: 58 | sources: ubuntu-toolchain-r-test 59 | packages: 60 | - g++-4.7 61 | - libcppunit-dev 62 | - compiler: gcc 63 | env: COMPILER=g++-4.8 64 | addons: 65 | apt: 66 | sources: ubuntu-toolchain-r-test 67 | packages: 68 | - g++-4.8 69 | - libcppunit-dev 70 | 71 | # TODO: Use the same branch name if libtorrent has it. 72 | before_install: 73 | - git clone https://github.com/rakshasa/libtorrent.git 74 | - | 75 | pushd libtorrent \ 76 | && (git checkout ${TRAVIS_BRANCH} || true) \ 77 | && ./autogen.sh \ 78 | && CXX="$COMPILER" ./configure --prefix=/usr \ 79 | && make \ 80 | && sudo make install \ 81 | && popd 82 | 83 | script: 84 | - ./autogen.sh && CXX="$COMPILER" ./configure && make 85 | - if [ ! $SKIP_CHECK ]; then make check; fi 86 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Jari Sundell 2 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakshasa/rtorrent/231606afc16eef08ec1a344a7aaef7504343bb71/ChangeLog -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = \ 2 | doc \ 3 | src \ 4 | test 5 | 6 | EXTRA_DIST= \ 7 | rtorrent.lua \ 8 | rak/address_info.h \ 9 | rak/algorithm.h \ 10 | rak/error_number.h \ 11 | rak/file_stat.h \ 12 | rak/fs_stat.h \ 13 | rak/path.h \ 14 | rak/partial_queue.h \ 15 | rak/regex.h \ 16 | rak/socket_address.h \ 17 | rak/string_manip.h \ 18 | rak/unordered_vector.h \ 19 | scripts/checks.m4 \ 20 | scripts/common.m4 \ 21 | scripts/attributes.m4 22 | 23 | ACLOCAL_AMFLAGS = -I scripts 24 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakshasa/rtorrent/231606afc16eef08ec1a344a7aaef7504343bb71/NEWS -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | BUILDING 2 | 3 | Run "aclocal -I scripts && autoconf -i && autoheader && automake --add-missing" 4 | to generate the configure scripts if necessary. The man page "doc/rtorrent.1" 5 | must be generated with "docbook2man rtorrent.1.xml" if it is missing. 6 | 7 | Note that rtorrent follows the development of libtorrent closely, and 8 | thus the versions must be in sync. This should not be nessesary in the 9 | future, when the library API stabilizes. 10 | 11 | USAGE 12 | 13 | See the man page or website for instructions. 14 | 15 | LICENSE 16 | 17 | GNU GPL, see COPYING. "libtorrent/src/utils/sha_fast.{cc,h}" is 18 | originally from the Mozilla NSS and is under a triple license; MPL, 19 | LGPL and GPL. An exception to non-NSS code has been added for linking 20 | to OpenSSL as requested by Debian, though the author considers that 21 | library to be part of the Operative System and thus linking is allowed 22 | according to the GPL. 23 | 24 | Use whatever fits your purpose, the code required to compile with 25 | Mozilla's NSS implementation of SHA1 has been retained and can be 26 | compiled if the user wishes to avoid using OpenSSL. 27 | 28 | DEPENDENCIES 29 | 30 | libcurl >= 7.12.0 31 | ncurses 32 | 33 | CONTACT 34 | 35 | Jari Sundell 36 | 37 | Skomakerveien 33 38 | 3185 Skoppum, NORWAY 39 | 40 | Send bug reports, suggestions and patches to 41 | or to the mailinglist. 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Donate](https://rakshasa.github.io/rtorrent/donate_paypal_green.svg)](https://paypal.me/jarisundelljp) 2 | 3 | RTorrent BitTorrent Client 4 | ======== 5 | 6 | Introduction 7 | ------------ 8 | 9 | To learn how to use rTorrent visit the [Wiki](https://github.com/rakshasa/rtorrent/wiki). 10 | 11 | Stable 12 | ------ 13 | 14 | * [https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.13.8.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.13.8.tar.gz) 15 | * [https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.9.8.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.9.8.tar.gz) 16 | 17 | Unstable 18 | ------ 19 | 20 | * [https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.14.0.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.14.0.tar.gz) 21 | * [https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.10.0.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.10.0.tar.gz) 22 | 23 | Related Projects 24 | ---------------- 25 | 26 | * [https://github.com/rakshasa/rbedit](https://github.com/rakshasa/rbedit): A dependency-free bencode editor. 27 | 28 | Donate to rTorrent development 29 | ------------------------------ 30 | 31 | * [Paypal](https://paypal.me/jarisundellno) 32 | * [Patreon](https://www.patreon.com/rtorrent) 33 | * [SubscribeStar](https://www.subscribestar.com/rtorrent) 34 | * Bitcoin: 1MpmXm5AHtdBoDaLZstJw8nupJJaeKu8V8 35 | * Ethereum: 0x9AB1e3C3d8a875e870f161b3e9287Db0E6DAfF78 36 | * Litecoin: LdyaVR67LBnTf6mAT4QJnjSG2Zk67qxmfQ 37 | * Cardano: addr1qytaslmqmk6dspltw06sp0zf83dh09u79j49ceh5y26zdcccgq4ph7nmx6kgmzeldauj43254ey97f3x4xw49d86aguqwfhlte 38 | 39 | 40 | Help keep rTorrent development going by donating to its creator. 41 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | m4_pattern_allow([PKG_CHECK_EXISTS]) 2 | 3 | AC_INIT([rtorrent],[0.15.4],[sundell.software@gmail.com]) 4 | 5 | AC_CONFIG_HEADERS([config.h]) 6 | AC_CONFIG_MACRO_DIRS([scripts]) 7 | AM_INIT_AUTOMAKE([foreign subdir-objects]) 8 | AM_PROG_AR 9 | 10 | LT_INIT 11 | 12 | AC_PROG_CXX 13 | AC_DEFINE([API_VERSION], [14], [api version]) 14 | 15 | # Filter out unwanted flags added by autoconf on some systems, e.g. MacOS. 16 | TORRENT_REMOVE_UNWANTED(CXX, $CXX, -std=c++11 -std=gnu++11) 17 | 18 | AX_CXX_COMPILE_STDCXX([17], [noext], [mandatory]) 19 | 20 | AC_SYS_LARGEFILE 21 | 22 | RAK_CHECK_CFLAGS 23 | RAK_CHECK_CXXFLAGS 24 | RAK_ENABLE_DEBUG 25 | RAK_ENABLE_EXTRA_DEBUG 26 | RAK_ENABLE_WERROR 27 | 28 | TORRENT_DISABLE_IPV6 29 | 30 | TORRENT_ENABLE_ARCH 31 | TORRENT_WITH_SYSROOT 32 | 33 | TORRENT_WITHOUT_VARIABLE_FDSET 34 | TORRENT_WITHOUT_STATVFS 35 | TORRENT_WITHOUT_STATFS 36 | 37 | AC_ARG_ENABLE(execinfo, 38 | AS_HELP_STRING([--disable-execinfo], 39 | [disable libexecinfo [[default=enable]]]), 40 | [ 41 | if test "$enableval" = "yes"; then 42 | AX_EXECINFO 43 | fi 44 | ],[ 45 | AX_EXECINFO 46 | ]) 47 | 48 | AX_PTHREAD([], AC_MSG_ERROR([requires pthread])) 49 | AX_WITH_CURSES 50 | 51 | if test "x$ax_cv_ncursesw" != xyes && test "x$ax_cv_ncurses" != xyes; then 52 | AC_MSG_ERROR([requires either NcursesW or Ncurses library]) 53 | fi 54 | 55 | PKG_CHECK_MODULES([LIBCURL], [libcurl],, [LIBCURL_CHECK_CONFIG]) 56 | PKG_CHECK_MODULES([CPPUNIT], [cppunit],, [no_cppunit="yes"]) 57 | PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.15.4]) 58 | 59 | AC_LANG_PUSH(C++) 60 | TORRENT_WITH_XMLRPC_C 61 | AC_LANG_POP(C++) 62 | 63 | TORRENT_WITH_LUA 64 | TORRENT_WITH_TINYXML2 65 | 66 | if test ${with_xmlrpc_c+y} && test ${with_xmlrpc_tinyxml2+y}; then 67 | AC_MSG_ERROR([--with-xmlrpc-c and --with-xmlrpc-tinyxml2 cannot be used together. Please choose only one]) 68 | fi 69 | 70 | AC_DEFINE(HAVE_CONFIG_H, 1, true if config.h was included) 71 | AC_DEFINE(USER_AGENT, [std::string(PACKAGE "/" VERSION "/") + torrent::version()], Http user agent) 72 | 73 | AC_CHECK_FUNCS(posix_memalign) 74 | 75 | dnl Only update global build variables immediately before generating the output, 76 | dnl to avoid affecting the global build environment for other autoconf checks. 77 | LIBS="$PTHREAD_LIBS $CURSES_LIB $CURSES_LIBS $LIBCURL $LIBCURL_LIBS $DEPENDENCIES_LIBS $LIBS" 78 | CFLAGS="$CFLAGS $PTHREAD_CFLAGS $LIBCURL_CPPFLAGS $LIBCURL_CFLAGS $DEPENDENCIES_CFLAGS $CURSES_CFLAGS" 79 | CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS $LIBCURL_CPPFLAGS $LIBCURL_CFLAGS $DEPENDENCIES_CFLAGS $CURSES_CFLAGS" 80 | 81 | TORRENT_CHECK_CACHELINE() 82 | TORRENT_CHECK_POPCOUNT() 83 | 84 | AC_CONFIG_FILES([ 85 | Makefile 86 | doc/Makefile 87 | src/Makefile 88 | test/Makefile 89 | ]) 90 | 91 | AC_OUTPUT 92 | -------------------------------------------------------------------------------- /doc/Makefile.am: -------------------------------------------------------------------------------- 1 | EXTRA_DIST= \ 2 | rtorrent.rc 3 | -------------------------------------------------------------------------------- /doc/debugging: -------------------------------------------------------------------------------- 1 | === Dumping core files on mac == 2 | 3 | ulimit -c unlimited 4 | sysctl kern.corefile 5 | 6 | 7 | schedule = log_vmmap,5,600,"execute_nothrow=/Users/rakshasa/trunk/rtorrent/doc/log_vmmap.sh,\"$cat=/Users/rakshasa/Downloads/session/vmmap.system.,$system.pid="; log.vmmap.dump=\"$cat=/Users/rakshasa/Downloads/session/vmmap.rtorrent.,$system.pid=\"" 8 | 9 | log.vmmap.dump="$cat=/Users/rakshasa/Downloads/session/vmmap.rtorrent.,$system.pid=" 10 | 11 | print="$cat=/Users/rakshasa/Downloads/session/vmmap.rtorrent.,$system.pid=" 12 | -------------------------------------------------------------------------------- /doc/log_proc_vmmap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cat /proc/$PPID/maps > $1 3 | -------------------------------------------------------------------------------- /doc/log_rtorrent.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | args=($@) 3 | echo "${args[@]:1}" >> $1 4 | -------------------------------------------------------------------------------- /doc/log_vmmap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | vmmap -interleaved $PPID > $1 3 | -------------------------------------------------------------------------------- /doc/manual/choke_groups.md: -------------------------------------------------------------------------------- 1 | # Choke Groups 2 | 3 | ## Settings 4 | 5 | choke_group.insert = "leech_fast" 6 | 7 | Create a new group named "leech_fast", accessible by the string or 8 | index / reverse index according to order of insertion. E.g. '-1' 9 | refers to the last inserted choke group, while 0 refers to the first. 10 | 11 | All commands that applies to a group requires the first argument to be 12 | the index, reverse index or the group name. 13 | 14 | choke_group.tracker.mode.set = -1,"aggressive" 15 | 16 | Set the tracker mode for torrents in this group. 17 | 18 | choke_group.up.heuristics.set = -1,"upload_leech_experimental" 19 | choke_group.down.heuristics.set = -1,"download_leech" 20 | 21 | Set the heuristics used when deciding on which peers to choke and 22 | unchoke. Use "strings.choke_heuristics{,.upload,.download}" to get a 23 | list of the available heuristics. 24 | 25 | choke_group.up.max.set = -1,250 26 | choke_group.down.max.set = -1,500 27 | 28 | Set the max total number of unchoked peers for all torrents in this choke group. 29 | -------------------------------------------------------------------------------- /doc/manual/ip_filtering.md: -------------------------------------------------------------------------------- 1 | # IP filtering 2 | 3 | ## Introduction 4 | 5 | ## Make a new ip table 6 | 7 | ip_tables.insert_table = 8 | 9 | Create a new empty table with the name ’table\_name’, with the default 10 | value returned being $0$. 11 | 12 | There is currently no use of the generic ip tables commands. 13 | 14 | ## Add a new address block 15 | 16 | ip_tables.add_address = , 10.0.0.0/8, 17 | 18 | Set for all addresses in the address block, overwriting prior 19 | values. 20 | 21 | ## Add a new address block 22 | 23 | ip_tables.load = , ~/foo.txt, 24 | 25 | Set for all addresses in the file ’foo.txt’ separated by 26 | newline, similar to ’add\_address’. 27 | 28 | ## Get value for address 29 | 30 | ip_tables.get = , 10.10.10.10 31 | 32 | Returns the value set for an address, or the address block it belongs 33 | to. The default is $0$. 34 | 35 | ## Size of data structures 36 | 37 | ip_tables.size_data = 38 | 39 | Returns the size in bytes of all data structures for this table, 40 | excluding the root class object itself. Note that the in-memory table is 41 | dynamically consolidated, as such memory use will always be based on 42 | actual fragmentation. 43 | 44 | The table is a b-tree with 1024 nodes per branch. 45 | 46 | ## IPv4 filtering table 47 | 48 | ipv4_filter.add_address = 10.0.0.0/8, unwanted 49 | ipv4_filter.add_address = 11.0.0.0/8, preferred 50 | ipv4_filter.load = ~/filters.txt, unwanted 51 | ipv4_filter.get = 10.10.10.10 52 | ipv4_filter.size_data = 53 | 54 | The main ip filter, currently supporting ’unwanted’ (do not allow 55 | connections) and ’preferred’ (currently used only in private code). 56 | 57 | ## Constants 58 | 59 | strings.ip_filter = 60 | => 61 | { "unwanted", PeerInfo::flag_unwanted }, 62 | { "preferred", PeerInfo::flag_preferred }, 63 | 64 | Constants used by ipv4\_filter values. 65 | -------------------------------------------------------------------------------- /doc/manual/ip_filtering.tex: -------------------------------------------------------------------------------- 1 | \section{IP filtering} 2 | 3 | \subsection{Introduction} 4 | 5 | \subsection{Make a new ip table} 6 | 7 | \begin{verbatim} 8 | ip_tables.insert_table = 9 | \end{verbatim} 10 | 11 | Create a new empty table with the name 'table\_name', with the default 12 | value returned being $0$. 13 | 14 | There is currently no use of the generic ip tables commands. 15 | 16 | 17 | \subsection{Add a new address block} 18 | 19 | \begin{verbatim} 20 | ip_tables.add_address = , 10.0.0.0/8, 21 | \end{verbatim} 22 | 23 | Set for all addresses in the address block, overwriting prior 24 | values. 25 | 26 | 27 | \subsection{Add a new address block} 28 | 29 | \begin{verbatim} 30 | ip_tables.load = , ~/foo.txt, 31 | \end{verbatim} 32 | 33 | Set for all addresses in the file 'foo.txt' separated by 34 | newline, similar to 'add\_address'. 35 | 36 | 37 | \subsection{Get value for address} 38 | 39 | \begin{verbatim} 40 | ip_tables.get = , 10.10.10.10 41 | \end{verbatim} 42 | 43 | Returns the value set for an address, or the address block it belongs 44 | to. The default is $0$. 45 | 46 | 47 | \subsection{Size of data structures} 48 | 49 | \begin{verbatim} 50 | ip_tables.size_data = 51 | \end{verbatim} 52 | 53 | Returns the size in bytes of all data structures for this table, 54 | excluding the root class object itself. Note that the in-memory table 55 | is dynamically consolidated, as such memory use will always be based 56 | on actual fragmentation. 57 | 58 | The table is a b-tree with 1024 nodes per branch. 59 | 60 | 61 | \subsection{IPv4 filtering table} 62 | 63 | \begin{verbatim} 64 | ipv4_filter.add_address = 10.0.0.0/8, unwanted 65 | ipv4_filter.add_address = 11.0.0.0/8, preferred 66 | ipv4_filter.load = ~/filters.txt, unwanted 67 | ipv4_filter.get = 10.10.10.10 68 | ipv4_filter.size_data = 69 | \end{verbatim} 70 | 71 | The main ip filter, currently supporting 'unwanted' (do not allow 72 | connections) and 'preferred' (currently used only in private code). 73 | 74 | 75 | 76 | \subsection{Constants} 77 | 78 | \begin{verbatim} 79 | strings.ip_filter = 80 | => 81 | { "unwanted", PeerInfo::flag_unwanted }, 82 | { "preferred", PeerInfo::flag_preferred }, 83 | \end{verbatim} 84 | 85 | Constants used by ipv4_filter values. 86 | -------------------------------------------------------------------------------- /doc/manual/logging.md: -------------------------------------------------------------------------------- 1 | # Logging 2 | 3 | ## Opening log files 4 | 5 | # log.open_file = "log name", "file path" 6 | 7 | log.open_file = "rtorrent.log", (cat,/tmp/rtorrent.log.,(system.pid)) 8 | 9 | A newly opened log file is not connected to any logging events. 10 | 11 | Some control over formatting will be provided at a later date. 12 | 13 | ## Adding outputs to events 14 | 15 | # log.add_output = "logging event", "log name" 16 | 17 | log.add_output = "info", "rtorrent.log" 18 | 19 | log.add_output = "dht_debug", "tracker.log" 20 | log.add_output = "tracker_debug", "tracker.log" 21 | 22 | Each log handle can be added to multiple different logging events. 23 | 24 | ## Logging events 25 | 26 | "critical" 27 | "error" 28 | "warn" 29 | "notice" 30 | "info" 31 | "debug" 32 | 33 | The above events receive logging events from all the sub-groups 34 | displayed below, and each event also reciving events from the event 35 | above in importance. 36 | 37 | Thus some high-volume sub-group events such as “tracker\_debug” are not 38 | part of “debug” and every “warn” event will receive events from “error”, 39 | “critical”. 40 | 41 | "connection_*" 42 | "dht_*" 43 | "peer_*" 44 | "rpc_*" 45 | "storage_*" 46 | "thread_*" 47 | "tracker_*" 48 | "torrent_*" 49 | 50 | All sub-groups have events from “critical” to “debug” defined. 51 | -------------------------------------------------------------------------------- /doc/manual/logging.tex: -------------------------------------------------------------------------------- 1 | \section{Logging} 2 | 3 | \subsection{Opening log files} 4 | 5 | \begin{verbatim} 6 | # log.open_file = "log name", "file path" 7 | 8 | log.open_file = "rtorrent.log", (cat,/tmp/rtorrent.log.,(system.pid)) 9 | \end{verbatim} 10 | 11 | A newly opened log file is not connected to any logging events. 12 | 13 | Some control over formatting will be provided at a later date. 14 | 15 | 16 | \subsection{Adding outputs to events} 17 | 18 | \begin{verbatim} 19 | # log.add_output = "logging event", "log name" 20 | 21 | log.add_output = "info", "rtorrent.log" 22 | 23 | log.add_output = "dht_debug", "tracker.log" 24 | log.add_output = "tracker_debug", "tracker.log" 25 | \end{verbatim} 26 | 27 | Each log handle can be added to multiple different logging events. 28 | 29 | 30 | \subsection{Logging events} 31 | 32 | \begin{verbatim} 33 | "critical" 34 | "error" 35 | "warn" 36 | "notice" 37 | "info" 38 | "debug" 39 | \end{verbatim} 40 | 41 | The above events receive logging events from all the sub-groups 42 | displayed below, and each event also reciving events from the event 43 | above in importance. 44 | 45 | Thus some high-volume sub-group events such as ``tracker\_debug'' are 46 | not part of ``debug'' and every ``warn'' event will receive events 47 | from ``error'', ``critical''. 48 | 49 | \begin{verbatim} 50 | "connection_*" 51 | "dht_*" 52 | "peer_*" 53 | "rpc_*" 54 | "storage_*" 55 | "thread_*" 56 | "tracker_*" 57 | "torrent_*" 58 | \end{verbatim} 59 | 60 | All sub-groups have events from ``critical'' to ``debug'' defined. 61 | 62 | -------------------------------------------------------------------------------- /doc/plot/instrumentation_mincore.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | gnuplot << EOF 3 | 4 | set terminal png size 1024 * 1, 768 enhanced 5 | set xdata time 6 | set timefmt "%s" 7 | set format x "%H:%M" 8 | set y2tics 9 | set autoscale xfix 10 | set key autotitle columnhead 11 | 12 | set format y "%.0f" 13 | set format y2 "%.0f" 14 | 15 | set output "output_$1_incore_sync.png" 16 | plot \ 17 | "instrumentation_mincore.log.$1" using 1:6 title 'success' with lines lw 4 axis x1y1,\ 18 | "instrumentation_mincore.log.$1" using 1:7 title 'failed' with lines lw 4 axis x1y1,\ 19 | "instrumentation_mincore.log.$1" using 1:8 title 'not synced' with lines lw 4 axis x1y2,\ 20 | "instrumentation_mincore.log.$1" using 1:9 title 'not deallocated' with lines lw 4 axis x1y2 21 | 22 | set format y "%.0g" 23 | 24 | set output "output_$1_incore_alloc.png" 25 | plot \ 26 | "instrumentation_mincore.log.$1" using 1:12 title 'allocations' with lines lw 2 axis x1y1,\ 27 | "instrumentation_mincore.log.$1" using 1:13 title 'deallocations' with lines lw 4 axis x1y1,\ 28 | "instrumentation_mincore.log.$1" using 1:10 title 'alloc failed' with lines lw 2 axis x1y2 29 | 30 | EOF 31 | -------------------------------------------------------------------------------- /doc/plot/instrumentation_transfers.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | gnuplot << EOF 3 | 4 | set terminal png size 1024,768 enhanced 5 | set xdata time 6 | set timefmt "%s" 7 | set format x "%H:%M" 8 | set y2tics 9 | set autoscale xfix 10 | set key autotitle columnhead 11 | 12 | # set datafile missing '0' 13 | 14 | set format y "%.0f" 15 | set format y2 "%.0f" 16 | 17 | set yrange [0:] 18 | set y2range [0:] 19 | 20 | set output "output_$1_transfer_requests.png" 21 | plot \ 22 | "instrumentation_transfers.log.$1" using 1:2 title 'delegated' with lines lw 4 axis x1y1,\ 23 | "instrumentation_transfers.log.$1" using 1:3 title 'downloading' with lines lw 4 axis x1y1,\ 24 | "instrumentation_transfers.log.$1" using 1:4 title 'finished' with lines lw 4 axis x1y1,\ 25 | "instrumentation_transfers.log.$1" using 1:5 title 'skipped' with lines lw 2 axis x1y2,\ 26 | "instrumentation_transfers.log.$1" using 1:6 title 'unknown' with lines lw 2 axis x1y2,\ 27 | "instrumentation_transfers.log.$1" using 1:7 title 'unordered' with lines lw 2 axis x1y2,\ 28 | "instrumentation_transfers.log.$1" using 1:19 title 'unaccounted' with lines lw 2 axis x1y2 29 | 30 | set output "output_$1_transfer_queues.png" 31 | plot \ 32 | "instrumentation_transfers.log.$1" using 1:8 title 'queue added' with lines lw 2 axis x1y1,\ 33 | "instrumentation_transfers.log.$1" using 1:9 title 'queue moved' with lines lw 2 axis x1y1,\ 34 | "instrumentation_transfers.log.$1" using 1:10 title 'queue removed' with lines lw 2 axis x1y1,\ 35 | "instrumentation_transfers.log.$1" using 1:11 title 'queue total' with lines lw 4 axis x1y2,\ 36 | "instrumentation_transfers.log.$1" using 1:12 title 'unordered added' with lines lw 2 axis x1y1,\ 37 | "instrumentation_transfers.log.$1" using 1:13 title 'unordered moved' with lines lw 2 axis x1y1,\ 38 | "instrumentation_transfers.log.$1" using 1:14 title 'unordered removed' with lines lw 2 axis x1y1,\ 39 | "instrumentation_transfers.log.$1" using 1:15 title 'unordered total' with lines lw 4 axis x1y2,\ 40 | "instrumentation_transfers.log.$1" using 1:16 title 'stalled added' with lines lw 2 axis x1y1,\ 41 | "instrumentation_transfers.log.$1" using 1:17 title 'stalled moved' with lines lw 2 axis x1y1,\ 42 | "instrumentation_transfers.log.$1" using 1:18 title 'stalled removed' with lines lw 2 axis x1y1,\ 43 | "instrumentation_transfers.log.$1" using 1:19 title 'stalled total' with lines lw 4 axis x1y2,\ 44 | "instrumentation_transfers.log.$1" using 1:20 title 'choked added' with lines lw 2 axis x1y1,\ 45 | "instrumentation_transfers.log.$1" using 1:21 title 'choked moved' with lines lw 2 axis x1y1,\ 46 | "instrumentation_transfers.log.$1" using 1:22 title 'choked removed' with lines lw 2 axis x1y1,\ 47 | "instrumentation_transfers.log.$1" using 1:23 title 'choked total' with lines lw 4 axis x1y2 48 | 49 | EOF 50 | -------------------------------------------------------------------------------- /doc/scripts/print_option_string.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PORT_NUMBER=${1:-5001} 4 | 5 | echo "Option Strings" 6 | echo "==============" 7 | echo 8 | echo "Introduction" 9 | echo "------------" 10 | echo 11 | echo "Client version: " `xmlrpc2scgi.py -p scgi://127.0.0.1:${PORT_NUMBER} system.client_version` 12 | echo 13 | echo "Generated by 'rtorrent/doc/scripts/print_option_string.sh' on `date -u`." 14 | 15 | for i in strings.choke_heuristics strings.choke_heuristics.upload strings.choke_heuristics.download strings.connection_type strings.encryption strings.ip_filter strings.ip_tos strings.log_group strings.tracker_event strings.tracker_mode; do 16 | echo 17 | echo $i 18 | echo `echo $i | tr 'a-z_.' '-'` 19 | echo 20 | echo '```' 21 | xmlrpc2scgi.py -p scgi://127.0.0.1:${PORT_NUMBER} $i | tr , '\n' | tr '[' ' ' | tr ']' ' ' 22 | echo '```' 23 | done 24 | -------------------------------------------------------------------------------- /doc/torrent_data: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Perl script to read torrent data 4 | 5 | use strict; 6 | use warnings; 7 | use Convert::Bencode_XS qw(bdecode); 8 | use Data::Dumper; 9 | 10 | $/ = undef; 11 | $| = 1; 12 | 13 | my $in; 14 | my $in_file = $ARGV[0]; 15 | if ($in_file) { open($in, '<', $in_file) || die "Cannot open $in_file for input!\n"; } 16 | else { $in = *STDIN; } 17 | 18 | print "Total input torrent size: ".sprintf('%.2f', (-s $in_file) / 1024)." KB\n" if $in_file; 19 | print "Decoding ".($in_file || 'torrent from standard input')."..."; 20 | my $t = bdecode(scalar <$in>); 21 | print "done\n\n"; 22 | 23 | print Data::Dumper->new([$t], ['*Torrent'])->Indent(1)->Useqq(1)->Quotekeys(0)->Sortkeys(1)->Dump; 24 | -------------------------------------------------------------------------------- /rtorrent.lua: -------------------------------------------------------------------------------- 1 | -- the "rtorrent" table is passed in by the C++ code, modify and 2 | -- return it for loading. 3 | local args = {...} 4 | local rtorrent = args[1] 5 | 6 | -- Autocall 7 | -- Allows syntax like `rtorrent.autocall.system.hostname()` 8 | local mt = {} 9 | function mt.__call (t, ...) 10 | name = table.concat(rawget(t, "__namestack"), ".") 11 | success, ret = pcall(rtorrent.call, name, ...) 12 | if not success then error(name..": "..ret, 2) end 13 | return ret 14 | end 15 | function mt.__index (t, key) 16 | ns = rawget(t, "__namestack") or {} 17 | table.insert(ns, key) 18 | return setmetatable({__namestack=ns}, mt) 19 | end 20 | rtorrent["autocall"] = setmetatable({}, mt) 21 | 22 | -- Autocall-config Same as autocall, but passes an empty first target 23 | -- implicitly, for syntax like `rtorrent.autocall_config.session.directory.set("/tmp/")` 24 | local mt = {} 25 | function mt.__call (t, ...) 26 | name = table.concat(rawget(t, "__namestack"), ".") 27 | success, ret = pcall(rtorrent.call, name, "", ...) 28 | if not success then error(name..": "..ret, 2) end 29 | return ret 30 | end 31 | function mt.__index (t, key) 32 | ns = rawget(t, "__namestack") 33 | if ns == nil then 34 | if _G[key] ~= nil then return _G[key] end 35 | ns = {} 36 | end 37 | table.insert(ns, key) 38 | return setmetatable({__namestack=ns}, mt) 39 | end 40 | rtorrent["autocall_config"] = setmetatable({}, mt) 41 | 42 | return rtorrent 43 | -------------------------------------------------------------------------------- /scripts/ax_execinfo.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_execinfo.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_EXECINFO([ACTION-IF-EXECINFO-H-IS-FOUND], [ACTION-IF-EXECINFO-H-IS-NOT-FOUND], [ADDITIONAL-TYPES-LIST]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Checks for execinfo.h header and if the len parameter/return type can be 12 | # found from a list, also define backtrace_size_t to that type. 13 | # 14 | # By default the list of types to try contains int and size_t, but should 15 | # some yet undiscovered system use e.g. unsigned, the 3rd argument can be 16 | # used for extensions. I'd like to hear of further suggestions. 17 | # 18 | # Executes ACTION-IF-EXECINFO-H-IS-FOUND when present and the execinfo.h 19 | # header is found or ACTION-IF-EXECINFO-H-IS-NOT-FOUND in case the header 20 | # seems unavailable. 21 | # 22 | # Also adds -lexecinfo to LIBS on BSD if needed. 23 | # 24 | # LICENSE 25 | # 26 | # Copyright (c) 2014 Thomas Jahns 27 | # 28 | # Copying and distribution of this file, with or without modification, are 29 | # permitted in any medium without royalty provided the copyright notice 30 | # and this notice are preserved. This file is offered as-is, without any 31 | # warranty. 32 | 33 | #serial 2 34 | 35 | AC_DEFUN([AX_EXECINFO], 36 | [AC_CHECK_HEADERS([execinfo.h]) 37 | AS_IF([test x"$ac_cv_header_execinfo_h" = xyes], 38 | [AC_CACHE_CHECK([size parameter type for backtrace()], 39 | [ax_cv_proto_backtrace_type], 40 | [AC_LANG_PUSH([C]) 41 | for ax_cv_proto_backtrace_type in size_t int m4_ifnblank([$3],[$3 ])none; do 42 | AS_IF([test "${ax_cv_proto_backtrace_type}" = none], 43 | [ax_cv_proto_backtrace_type= ; break]) 44 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ 45 | #include 46 | extern 47 | ${ax_cv_proto_backtrace_type} backtrace(void **addrlist, ${ax_cv_proto_backtrace_type} len); 48 | char **backtrace_symbols(void *const *buffer, ${ax_cv_proto_backtrace_type} size); 49 | ])], 50 | [break]) 51 | done 52 | AC_LANG_POP([C])])]) 53 | AS_IF([test x${ax_cv_proto_backtrace_type} != x], 54 | [AC_DEFINE_UNQUOTED([backtrace_size_t], [$ax_cv_proto_backtrace_type], 55 | [Defined to return type of backtrace().])]) 56 | AC_SEARCH_LIBS([backtrace],[execinfo]) 57 | AS_IF([test x"${ax_cv_proto_backtrace_type}" != x -a x"$ac_cv_header_execinfo_h" = xyes -a x"$ac_cv_search_backtrace" != xno], 58 | [AC_DEFINE([HAVE_BACKTRACE],[1], 59 | [Defined if backtrace() could be fully identified.]) 60 | ]m4_ifnblank([$1],[$1 61 | ]),m4_ifnblank([$2],[$2 62 | ]))]) 63 | dnl 64 | dnl Local Variables: 65 | dnl mode: autoconf 66 | dnl End: 67 | dnl 68 | -------------------------------------------------------------------------------- /scripts/ax_require_defined.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_require_defined.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_REQUIRE_DEFINED(MACRO) 8 | # 9 | # DESCRIPTION 10 | # 11 | # AX_REQUIRE_DEFINED is a simple helper for making sure other macros have 12 | # been defined and thus are available for use. This avoids random issues 13 | # where a macro isn't expanded. Instead the configure script emits a 14 | # non-fatal: 15 | # 16 | # ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found 17 | # 18 | # It's like AC_REQUIRE except it doesn't expand the required macro. 19 | # 20 | # Here's an example: 21 | # 22 | # AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) 23 | # 24 | # LICENSE 25 | # 26 | # Copyright (c) 2014 Mike Frysinger 27 | # 28 | # Copying and distribution of this file, with or without modification, are 29 | # permitted in any medium without royalty provided the copyright notice 30 | # and this notice are preserved. This file is offered as-is, without any 31 | # warranty. 32 | 33 | #serial 2 34 | 35 | AC_DEFUN([AX_REQUIRE_DEFINED], [dnl 36 | m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])]) 37 | ])dnl AX_REQUIRE_DEFINED 38 | -------------------------------------------------------------------------------- /scripts/rak_compiler.m4: -------------------------------------------------------------------------------- 1 | AC_DEFUN([RAK_CHECK_CFLAGS], [ 2 | 3 | AC_MSG_CHECKING([for user-defined CFLAGS]) 4 | 5 | if test "$CFLAGS" = ""; then 6 | unset CFLAGS 7 | AC_MSG_RESULT([undefined]) 8 | else 9 | AC_MSG_RESULT([user-defined "$CFLAGS"]) 10 | fi 11 | ]) 12 | 13 | 14 | AC_DEFUN([RAK_CHECK_CXXFLAGS], [ 15 | 16 | AC_MSG_CHECKING([for user-defined CXXFLAGS]) 17 | 18 | if test "$CXXFLAGS" = ""; then 19 | unset CXXFLAGS 20 | AC_MSG_RESULT([undefined]) 21 | else 22 | AC_MSG_RESULT([user-defined "$CXXFLAGS"]) 23 | fi 24 | ]) 25 | 26 | 27 | AC_DEFUN([RAK_ENABLE_DEBUG], [ 28 | AC_ARG_ENABLE(debug, 29 | AS_HELP_STRING([--enable-debug],[enable debug information [[default=yes]]]), 30 | [ 31 | if test "$enableval" = "yes"; then 32 | CXXFLAGS="$CXXFLAGS -g -DDEBUG" 33 | else 34 | CXXFLAGS="$CXXFLAGS -DNDEBUG" 35 | fi 36 | ],[ 37 | CXXFLAGS="$CXXFLAGS -g -DDEBUG" 38 | ]) 39 | ]) 40 | 41 | 42 | AC_DEFUN([RAK_ENABLE_WERROR], [ 43 | AC_ARG_ENABLE(werror, 44 | AS_HELP_STRING([--enable-werror],[enable the -Werror and -Wall flags [[default -Wall only]]]), 45 | [ 46 | if test "$enableval" = "yes"; then 47 | CXXFLAGS="$CXXFLAGS -Werror -Wall" 48 | fi 49 | ],[ 50 | CXXFLAGS="$CXXFLAGS -Wall" 51 | ]) 52 | ]) 53 | 54 | 55 | AC_DEFUN([RAK_ENABLE_EXTRA_DEBUG], [ 56 | AC_ARG_ENABLE(extra-debug, 57 | AS_HELP_STRING([--enable-extra-debug],[enable extra debugging checks [[default=no]]]), 58 | [ 59 | if test "$enableval" = "yes"; then 60 | AC_DEFINE(USE_EXTRA_DEBUG, 1, Enable extra debugging checks.) 61 | fi 62 | ]) 63 | ]) 64 | -------------------------------------------------------------------------------- /scripts/ssl.m4: -------------------------------------------------------------------------------- 1 | AC_DEFUN([TORRENT_CHECK_OPENSSL], 2 | [ 3 | PKG_CHECK_MODULES(OPENSSL, libcrypto, 4 | CXXFLAGS="$CXXFLAGS $OPENSSL_CFLAGS"; 5 | LIBS="$LIBS $OPENSSL_LIBS") 6 | 7 | AC_DEFINE(USE_OPENSSL, 1, Using OpenSSL.) 8 | AC_DEFINE(USE_OPENSSL_SHA, 1, Using OpenSSL's SHA1 implementation.) 9 | ] 10 | ) 11 | 12 | AC_DEFUN([TORRENT_ARG_OPENSSL], 13 | [ 14 | AC_ARG_ENABLE(openssl, 15 | [ --disable-openssl Don't use OpenSSL's SHA1 implementation.], 16 | [ 17 | if test "$enableval" = "yes"; then 18 | TORRENT_CHECK_OPENSSL 19 | else 20 | AC_DEFINE(USE_NSS_SHA, 1, Using Mozilla's SHA1 implementation.) 21 | fi 22 | ],[ 23 | TORRENT_CHECK_OPENSSL 24 | ]) 25 | ] 26 | ) 27 | 28 | AC_DEFUN([TORRENT_ARG_CYRUS_RC4], 29 | [ 30 | AC_ARG_ENABLE(cyrus-rc4, 31 | [ --enable-cyrus-rc4=PFX Use Cyrus RC4 implementation.], 32 | [ 33 | CXXFLAGS="$CXXFLAGS -I${enableval}/include"; 34 | LIBS="$LIBS -lrc4 -L${enableval}/lib" 35 | AC_DEFINE(USE_CYRUS_RC4, 1, Using Cyrus RC4 implementation.) 36 | ]) 37 | ] 38 | ) 39 | -------------------------------------------------------------------------------- /src/command_helpers.cc: -------------------------------------------------------------------------------- 1 | // rTorrent - BitTorrent client 2 | // Copyright (C) 2005-2011, Jari Sundell 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | // 18 | // In addition, as a special exception, the copyright holders give 19 | // permission to link the code of portions of this program with the 20 | // OpenSSL library under certain conditions as described in each 21 | // individual source file, and distribute linked combinations 22 | // including the two. 23 | // 24 | // You must obey the GNU General Public License in all respects for 25 | // all of the code used other than OpenSSL. If you modify file(s) 26 | // with this exception, you may extend this exception to your version 27 | // of the file(s), but you are not obligated to do so. If you do not 28 | // wish to do so, delete this exception statement from your version. 29 | // If you delete this exception statement from all source files in the 30 | // program, then also delete it here. 31 | // 32 | // Contact: Jari Sundell 33 | // 34 | // Skomakerveien 33 35 | // 3185 Skoppum, NORWAY 36 | 37 | #include "config.h" 38 | 39 | #include 40 | 41 | #include "globals.h" 42 | #include "control.h" 43 | #include "command_helpers.h" 44 | 45 | void initialize_command_dynamic(); 46 | void initialize_command_download(); 47 | void initialize_command_events(); 48 | void initialize_command_file(); 49 | void initialize_command_ip(); 50 | void initialize_command_peer(); 51 | void initialize_command_local(); 52 | void initialize_command_logging(); 53 | void initialize_command_network(); 54 | void initialize_command_groups(); 55 | void initialize_command_throttle(); 56 | void initialize_command_tracker(); 57 | void initialize_command_scheduler(); 58 | void initialize_command_ui(); 59 | 60 | void 61 | initialize_commands() { 62 | initialize_command_dynamic(); 63 | initialize_command_events(); 64 | initialize_command_network(); 65 | initialize_command_groups(); 66 | initialize_command_local(); 67 | initialize_command_logging(); 68 | initialize_command_ui(); 69 | initialize_command_download(); 70 | initialize_command_file(); 71 | initialize_command_ip(); 72 | initialize_command_peer(); 73 | initialize_command_throttle(); 74 | initialize_command_tracker(); 75 | initialize_command_scheduler(); 76 | } 77 | -------------------------------------------------------------------------------- /src/command_scheduler.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include 4 | 5 | #include "core/manager.h" 6 | #include "core/download.h" 7 | #include "core/download_list.h" 8 | #include "core/view.h" 9 | #include "core/view_manager.h" 10 | 11 | #include "globals.h" 12 | #include "control.h" 13 | #include "command_helpers.h" 14 | 15 | torrent::Object 16 | cmd_scheduler_simple_added(core::Download* download) { 17 | unsigned int numActive = (*control->view_manager()->find("active"))->size_visible(); 18 | int64_t maxActive = rpc::call_command("scheduler.max_active", torrent::Object()).as_value(); 19 | 20 | if (numActive < (uint64_t)maxActive) 21 | control->core()->download_list()->resume(download); 22 | 23 | return torrent::Object(); 24 | } 25 | 26 | torrent::Object 27 | cmd_scheduler_simple_removed(core::Download* download) { 28 | control->core()->download_list()->pause(download); 29 | 30 | core::View* viewActive = *control->view_manager()->find("active"); 31 | int64_t maxActive = rpc::call_command("scheduler.max_active", torrent::Object()).as_value(); 32 | 33 | if ((int64_t)viewActive->size_visible() >= maxActive) 34 | return torrent::Object(); 35 | 36 | // The 'started' view contains all the views we may choose amongst. 37 | core::View* viewStarted = *control->view_manager()->find("started"); 38 | 39 | for (core::View::iterator itr = viewStarted->begin_visible(), last = viewStarted->end_visible(); itr != last; itr++) { 40 | if ((*itr)->is_active()) 41 | continue; 42 | 43 | control->core()->download_list()->resume(*itr); 44 | } 45 | 46 | return torrent::Object(); 47 | } 48 | 49 | torrent::Object 50 | cmd_scheduler_simple_update([[maybe_unused]] core::Download* download) { 51 | core::View* viewActive = *control->view_manager()->find("active"); 52 | core::View* viewStarted = *control->view_manager()->find("started"); 53 | 54 | unsigned int numActive = viewActive->size_visible(); 55 | uint64_t maxActive = rpc::call_command("scheduler.max_active", torrent::Object()).as_value(); 56 | 57 | if (viewActive->size_visible() < maxActive) { 58 | for (core::View::iterator itr = viewStarted->begin_visible(), last = viewStarted->end_visible(); itr != last; itr++) { 59 | if ((*itr)->is_active()) 60 | continue; 61 | 62 | control->core()->download_list()->resume(*itr); 63 | 64 | if (++numActive >= maxActive) 65 | break; 66 | } 67 | 68 | } else { 69 | while (viewActive->size_visible() > maxActive) 70 | control->core()->download_list()->pause(*viewActive->begin_visible()); 71 | } 72 | 73 | return torrent::Object(); 74 | } 75 | 76 | void 77 | initialize_command_scheduler() { 78 | CMD2_VAR_VALUE("scheduler.max_active", int64_t(-1)); 79 | 80 | CMD2_DL("scheduler.simple.added", std::bind(&cmd_scheduler_simple_added, std::placeholders::_1)); 81 | CMD2_DL("scheduler.simple.removed", std::bind(&cmd_scheduler_simple_removed, std::placeholders::_1)); 82 | CMD2_DL("scheduler.simple.update", std::bind(&cmd_scheduler_simple_update, std::placeholders::_1)); 83 | } 84 | -------------------------------------------------------------------------------- /src/core/curl_get.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_CORE_CURL_GET_H 2 | #define RTORRENT_CORE_CURL_GET_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace core { 11 | 12 | class CurlStack; 13 | 14 | class CurlGet : public torrent::Http { 15 | public: 16 | CurlGet(CurlStack* s); 17 | virtual ~CurlGet(); 18 | 19 | void start(); 20 | void close(); 21 | 22 | bool is_using_ipv6() { return m_ipv6; } 23 | void retry_ipv6(); 24 | 25 | bool is_busy() const { return m_handle; } 26 | bool is_active() const { return m_active; } 27 | 28 | void set_active(bool a) { m_active = a; } 29 | 30 | curl_off_t size_done(); 31 | curl_off_t size_total(); 32 | 33 | CURL* handle() { return m_handle; } 34 | 35 | private: 36 | friend class CurlStack; 37 | 38 | CurlGet(const CurlGet&) = delete; 39 | void operator = (const CurlGet&) = delete; 40 | 41 | void receive_timeout(); 42 | 43 | bool m_active{}; 44 | bool m_ipv6; 45 | 46 | torrent::utils::SchedulerEntry m_task_timeout; 47 | 48 | CURL* m_handle{}; 49 | CurlStack* m_stack; 50 | }; 51 | 52 | } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /src/core/curl_socket.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include "curl_socket.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "control.h" 12 | #include "core/curl_stack.h" 13 | 14 | namespace core { 15 | 16 | int 17 | CurlSocket::receive_socket([[maybe_unused]] void* easy_handle, curl_socket_t fd, int what, void* userp, void* socketp) { 18 | CurlStack* stack = (CurlStack*)userp; 19 | CurlSocket* socket = (CurlSocket*)socketp; 20 | 21 | if (!stack->is_running()) 22 | return 0; 23 | 24 | if (what == CURL_POLL_REMOVE) { 25 | // We also probably need the special code here as we're not 26 | // guaranteed that the fd will be closed, afaik. 27 | if (socket != NULL) 28 | socket->close(); 29 | 30 | // TODO: Consider the possibility that we'll need to set the 31 | // fd-associated pointer curl holds to NULL. 32 | 33 | delete socket; 34 | return 0; 35 | } 36 | 37 | if (socket == NULL) { 38 | socket = stack->new_socket(fd); 39 | torrent::this_thread::poll()->open(socket); 40 | 41 | // No interface for libcurl to signal when it's interested in error events. 42 | // Assume that hence it must always be interested in them. 43 | torrent::this_thread::poll()->insert_error(socket); 44 | } 45 | 46 | if (what == CURL_POLL_NONE || what == CURL_POLL_OUT) 47 | torrent::this_thread::poll()->remove_read(socket); 48 | else 49 | torrent::this_thread::poll()->insert_read(socket); 50 | 51 | if (what == CURL_POLL_NONE || what == CURL_POLL_IN) 52 | torrent::this_thread::poll()->remove_write(socket); 53 | else 54 | torrent::this_thread::poll()->insert_write(socket); 55 | 56 | return 0; 57 | } 58 | 59 | CurlSocket::~CurlSocket() { 60 | assert(m_fileDesc == -1 && "CurlSocket::~CurlSocket() m_fileDesc != -1."); 61 | } 62 | 63 | void 64 | CurlSocket::close() { 65 | if (m_fileDesc == -1) 66 | throw torrent::internal_error("CurlSocket::close() m_fileDesc == -1."); 67 | 68 | torrent::this_thread::poll()->closed(this); 69 | m_fileDesc = -1; 70 | } 71 | 72 | void 73 | CurlSocket::event_read() { 74 | #if (LIBCURL_VERSION_NUM >= 0x071003) 75 | return m_stack->receive_action(this, CURL_CSELECT_IN); 76 | #else 77 | return m_stack->receive_action(this, 0); 78 | #endif 79 | } 80 | 81 | void 82 | CurlSocket::event_write() { 83 | #if (LIBCURL_VERSION_NUM >= 0x071003) 84 | return m_stack->receive_action(this, CURL_CSELECT_OUT); 85 | #else 86 | return m_stack->receive_action(this, 0); 87 | #endif 88 | } 89 | 90 | void 91 | CurlSocket::event_error() { 92 | #if (LIBCURL_VERSION_NUM >= 0x071003) 93 | return m_stack->receive_action(this, CURL_CSELECT_ERR); 94 | #else 95 | return m_stack->receive_action(this, 0); 96 | #endif 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /src/core/curl_socket.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_CORE_CURL_SOCKET_H 2 | #define RTORRENT_CORE_CURL_SOCKET_H 3 | 4 | #include 5 | #include 6 | 7 | #include "globals.h" 8 | 9 | namespace core { 10 | 11 | class CurlStack; 12 | 13 | class CurlSocket : public torrent::Event { 14 | public: 15 | CurlSocket(int fd, CurlStack* stack) : m_stack(stack) { m_fileDesc = fd; } 16 | ~CurlSocket(); 17 | 18 | const char* type_name() const { return "curl"; } 19 | 20 | void close(); 21 | 22 | static int receive_socket(void* easy_handle, curl_socket_t fd, int what, void* userp, void* socketp); 23 | 24 | private: 25 | CurlSocket(const CurlSocket&); 26 | void operator = (const CurlSocket&); 27 | 28 | virtual void event_read(); 29 | virtual void event_write(); 30 | virtual void event_error(); 31 | 32 | CurlStack* m_stack; 33 | }; 34 | 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/core/dht_manager.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_CORE_DHT_MANAGER_H 2 | #define RTORRENT_CORE_DHT_MANAGER_H 3 | 4 | #include 5 | #include 6 | 7 | namespace core { 8 | 9 | class DhtManager { 10 | public: 11 | ~DhtManager(); 12 | 13 | void load_dht_cache(); 14 | void save_dht_cache(); 15 | torrent::Object dht_statistics(); 16 | 17 | void start_dht(); 18 | void stop_dht(); 19 | void auto_start() { if (m_start == dht_auto) start_dht(); } 20 | 21 | void set_mode(const std::string& arg); 22 | 23 | void set_throttle_name(const std::string& throttleName); 24 | const std::string& throttle_name() const { return m_throttleName; } 25 | 26 | private: 27 | static const int dht_disable = 0; 28 | static const int dht_off = 1; 29 | static const int dht_auto = 2; 30 | static const int dht_on = 3; 31 | 32 | static const int dht_settings_num = 4; 33 | static const char* dht_settings[dht_settings_num]; 34 | 35 | void update(); 36 | bool log_statistics(bool force); 37 | 38 | unsigned int m_dhtPrevCycle; 39 | unsigned int m_dhtPrevQueriesSent; 40 | unsigned int m_dhtPrevRepliesReceived; 41 | unsigned int m_dhtPrevQueriesReceived; 42 | uint64_t m_dhtPrevBytesUp; 43 | uint64_t m_dhtPrevBytesDown; 44 | 45 | torrent::utils::SchedulerEntry m_update_timeout; 46 | torrent::utils::SchedulerEntry m_stop_timeout; 47 | 48 | bool m_warned{}; 49 | 50 | int m_start{dht_off}; 51 | std::string m_throttleName; 52 | }; 53 | 54 | } 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /src/core/download_slot_map.h: -------------------------------------------------------------------------------- 1 | // rTorrent - BitTorrent client 2 | // Copyright (C) 2005-2011, Jari Sundell 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | // 18 | // In addition, as a special exception, the copyright holders give 19 | // permission to link the code of portions of this program with the 20 | // OpenSSL library under certain conditions as described in each 21 | // individual source file, and distribute linked combinations 22 | // including the two. 23 | // 24 | // You must obey the GNU General Public License in all respects for 25 | // all of the code used other than OpenSSL. If you modify file(s) 26 | // with this exception, you may extend this exception to your version 27 | // of the file(s), but you are not obligated to do so. If you do not 28 | // wish to do so, delete this exception statement from your version. 29 | // If you delete this exception statement from all source files in the 30 | // program, then also delete it here. 31 | // 32 | // Contact: Jari Sundell 33 | // 34 | // Skomakerveien 33 35 | // 3185 Skoppum, NORWAY 36 | 37 | #ifndef RTORRENT_CORE_DOWNLOAD_SLOT_MAP_H 38 | #define RTORRENT_CORE_DOWNLOAD_SLOT_MAP_H 39 | 40 | #include 41 | #include 42 | #include 43 | 44 | #include "download.h" 45 | 46 | namespace core { 47 | 48 | class DownloadSlotMap : public std::map > { 49 | public: 50 | typedef std::function slot_download; 51 | typedef std::map Base; 52 | 53 | void insert(const std::string& key, slot_download s) { Base::operator[](key) = s; } 54 | void erase(const std::string& key) { Base::erase(key); } 55 | 56 | void for_each(Download* d); 57 | }; 58 | 59 | inline void 60 | DownloadSlotMap::for_each(Download* d) { 61 | for (iterator itr = begin(), last = end(); itr != last; ++itr) 62 | itr->second(d); 63 | } 64 | 65 | } 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /src/core/download_store.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_CORE_DOWNLOAD_STORE_H 2 | #define RTORRENT_CORE_DOWNLOAD_STORE_H 3 | 4 | #include 5 | 6 | #include "utils/lockfile.h" 7 | 8 | namespace utils { 9 | class Directory; 10 | } 11 | 12 | namespace core { 13 | 14 | class Download; 15 | 16 | class DownloadStore { 17 | public: 18 | static const int flag_skip_static = 0x1; 19 | 20 | bool is_enabled() { return m_lockfile.is_locked(); } 21 | 22 | void enable(bool lock); 23 | void disable(); 24 | 25 | const std::string& path() const { return m_path; } 26 | void set_path(const std::string& path); 27 | 28 | bool save(Download* d, int flags); 29 | bool save_full(Download* d) { return save(d, 0); } 30 | bool save_resume(Download* d) { return save(d, flag_skip_static); } 31 | void remove(Download* d); 32 | 33 | // Currently shows all entries in the correct format. 34 | utils::Directory get_formated_entries(); 35 | 36 | static bool is_correct_format(const std::string& f); 37 | 38 | private: 39 | std::string create_filename(Download* d); 40 | 41 | bool write_bencode(const std::string& filename, const torrent::Object& obj, uint32_t skip_mask); 42 | 43 | std::string m_path; 44 | utils::Lockfile m_lockfile; 45 | }; 46 | 47 | } 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/core/http_queue.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "http_queue.h" 8 | #include "curl_get.h" 9 | 10 | namespace core { 11 | 12 | HttpQueue::iterator 13 | HttpQueue::insert(const std::string& url, std::iostream* s) { 14 | std::unique_ptr h(m_slot_factory()); 15 | 16 | h->set_url(url); 17 | h->set_stream(s); 18 | h->set_timeout(5 * 60); 19 | 20 | iterator signal_itr = base_type::insert(end(), h.get()); 21 | 22 | h->signal_done().push_back(std::bind(&HttpQueue::erase, this, signal_itr)); 23 | h->signal_failed().push_back(std::bind(&HttpQueue::erase, this, signal_itr)); 24 | 25 | (*signal_itr)->start(); 26 | 27 | h.release(); 28 | 29 | for (signal_curl_get::iterator itr = m_signal_insert.begin(), last = m_signal_insert.end(); itr != last; itr++) 30 | (*itr)(*signal_itr); 31 | 32 | return signal_itr; 33 | } 34 | 35 | void 36 | HttpQueue::erase(iterator signal_itr) { 37 | for (signal_curl_get::iterator itr = m_signal_erase.begin(), last = m_signal_erase.end(); itr != last; itr++) 38 | (*itr)(*signal_itr); 39 | 40 | delete *signal_itr; 41 | base_type::erase(signal_itr); 42 | } 43 | 44 | void 45 | HttpQueue::clear() { 46 | while (!empty()) 47 | erase(begin()); 48 | 49 | base_type::clear(); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/core/http_queue.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_CORE_HTTP_QUEUE_H 2 | #define RTORRENT_CORE_HTTP_QUEUE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace core { 9 | 10 | class CurlGet; 11 | 12 | class HttpQueue : private std::list { 13 | public: 14 | typedef std::list base_type; 15 | typedef std::function slot_factory; 16 | typedef std::function slot_curl_get; 17 | typedef std::list signal_curl_get; 18 | 19 | using base_type::iterator; 20 | using base_type::const_iterator; 21 | using base_type::reverse_iterator; 22 | using base_type::const_reverse_iterator; 23 | 24 | using base_type::begin; 25 | using base_type::end; 26 | using base_type::rbegin; 27 | using base_type::rend; 28 | 29 | using base_type::empty; 30 | using base_type::size; 31 | 32 | HttpQueue() = default; 33 | ~HttpQueue() { clear(); } 34 | 35 | // Note that any slots connected to the CurlGet signals must be 36 | // pushed in front of the erase slot added by HttpQueue::insert. 37 | // 38 | // Consider adding a flag to indicate whetever HttpQueue should 39 | // delete the stream. 40 | iterator insert(const std::string& url, std::iostream* s); 41 | void erase(iterator itr); 42 | 43 | void clear(); 44 | 45 | void set_slot_factory(slot_factory s) { m_slot_factory = s; } 46 | 47 | signal_curl_get& signal_insert() { return m_signal_insert; } 48 | signal_curl_get& signal_erase() { return m_signal_erase; } 49 | 50 | private: 51 | slot_factory m_slot_factory; 52 | signal_curl_get m_signal_insert; 53 | signal_curl_get m_signal_erase; 54 | }; 55 | 56 | } 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /src/core/view_manager.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "globals.h" 8 | #include "control.h" 9 | #include "rpc/parse_commands.h" 10 | 11 | #include "download.h" 12 | #include "download_list.h" 13 | #include "manager.h" 14 | #include "view.h" 15 | #include "view_manager.h" 16 | 17 | namespace core { 18 | 19 | void 20 | ViewManager::clear() { 21 | std::for_each(begin(), end(), [](View* v) { delete v; }); 22 | 23 | base_type::clear(); 24 | } 25 | 26 | ViewManager::iterator 27 | ViewManager::insert(const std::string& name) { 28 | if (name.empty()) 29 | throw torrent::input_error("View with empty name not supported."); 30 | 31 | if (find(name) != end()) 32 | throw torrent::input_error("View with same name already inserted."); 33 | 34 | View* view = new View(); 35 | view->initialize(name); 36 | 37 | return base_type::insert(end(), view); 38 | } 39 | 40 | ViewManager::iterator 41 | ViewManager::find(const std::string& name) { 42 | return std::find_if(begin(), end(), [name](View* v){ return name == v->name(); }); 43 | } 44 | 45 | ViewManager::iterator 46 | ViewManager::find_throw(const std::string& name) { 47 | iterator itr = std::find_if(begin(), end(), [name](View* v){ return name == v->name(); }); 48 | 49 | if (itr == end()) 50 | throw torrent::input_error("Could not find view: " + name); 51 | 52 | return itr; 53 | } 54 | 55 | void 56 | ViewManager::sort(const std::string& name, uint32_t timeout) { 57 | iterator viewItr = find_throw(name); 58 | 59 | if ((*viewItr)->last_changed() + std::chrono::seconds(timeout) > torrent::this_thread::cached_time()) 60 | return; 61 | 62 | // Should we rename sort, or add a seperate function? 63 | (*viewItr)->filter(); 64 | (*viewItr)->sort(); 65 | } 66 | 67 | void 68 | ViewManager::set_filter(const std::string& name, const torrent::Object& cmd) { 69 | iterator viewItr = find_throw(name); 70 | 71 | (*viewItr)->set_filter(cmd); 72 | (*viewItr)->filter(); 73 | } 74 | 75 | void 76 | ViewManager::set_filter_temp(const std::string& name, const torrent::Object& cmd) { 77 | iterator viewItr = find_throw(name); 78 | 79 | (*viewItr)->set_filter_temp(cmd); 80 | (*viewItr)->filter(); 81 | } 82 | 83 | void 84 | ViewManager::set_filter_on(const std::string& name, const filter_args& args) { 85 | iterator viewItr = find_throw(name); 86 | 87 | (*viewItr)->clear_filter_on(); 88 | 89 | // TODO: Ensure the filter keys are rlookup. 90 | 91 | for (filter_args::const_iterator itr = args.begin(); itr != args.end(); ++itr) 92 | (*viewItr)->set_filter_on_event(*itr); 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /src/core/view_manager.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_CORE_VIEW_MANAGER_H 2 | #define RTORRENT_CORE_VIEW_MANAGER_H 3 | 4 | #include 5 | #include 6 | 7 | #include "view.h" 8 | 9 | namespace core { 10 | 11 | class ViewManager : public rak::unordered_vector { 12 | public: 13 | typedef rak::unordered_vector base_type; 14 | typedef std::list filter_args; 15 | 16 | using base_type::iterator; 17 | using base_type::const_iterator; 18 | using base_type::reverse_iterator; 19 | using base_type::const_reverse_iterator; 20 | 21 | using base_type::size_type; 22 | 23 | using base_type::begin; 24 | using base_type::end; 25 | using base_type::rbegin; 26 | using base_type::rend; 27 | 28 | using base_type::empty; 29 | using base_type::size; 30 | 31 | ViewManager() = default; 32 | ~ViewManager() { clear(); } 33 | 34 | // Ffff... Just throwing together an interface, need to think some 35 | // more on this. 36 | 37 | void clear(); 38 | 39 | iterator insert(const std::string& name); 40 | void insert_throw(const std::string& name) { insert(name); } 41 | 42 | // When erasing, just 'disable' the view so that the users won't 43 | // suddenly find their pointer dangling? 44 | 45 | iterator find(const std::string& name); 46 | iterator find_throw(const std::string& name); 47 | View* find_ptr_throw(const std::string& name) { return *find_throw(name); } 48 | 49 | // If View::last_changed() is less than 'timeout' seconds ago, don't 50 | // sort. 51 | // 52 | // Find a better name for 'timeout'. 53 | void sort(const std::string& name, uint32_t timeout = 0); 54 | 55 | // These could be moved to where the command is implemented. 56 | void set_sort_new(const std::string& name, const torrent::Object& cmd) { (*find_throw(name))->set_sort_new(cmd); } 57 | void set_sort_current(const std::string& name, const torrent::Object& cmd) { (*find_throw(name))->set_sort_current(cmd); } 58 | 59 | void set_filter(const std::string& name, const torrent::Object& cmd); 60 | void set_filter_temp(const std::string& name, const torrent::Object& cmd); 61 | void set_filter_on(const std::string& name, const filter_args& args); 62 | 63 | void set_event_added(const std::string& name, const torrent::Object& cmd) { (*find_throw(name))->set_event_added(cmd); } 64 | void set_event_removed(const std::string& name, const torrent::Object& cmd) { (*find_throw(name))->set_event_removed(cmd); } 65 | }; 66 | 67 | } 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /src/display/attributes.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_DISPLAY_ATTRIBUTES_H 2 | #define RTORRENT_DISPLAY_ATTRIBUTES_H 3 | 4 | #include 5 | #include 6 | 7 | #if defined(HAVE_NCURSESW_CURSES_H) 8 | #include 9 | #elif defined(HAVE_NCURSESW_H) 10 | #include 11 | #elif defined(HAVE_NCURSES_CURSES_H) 12 | #include 13 | #elif defined(HAVE_NCURSES_H) 14 | #include 15 | #elif defined(HAVE_CURSES_H) 16 | #include 17 | #else 18 | #error "SysV or X/Open-compatible Curses header file required" 19 | #endif 20 | 21 | // Let us hail the creators of curses for being idiots. The only 22 | // clever move they made was in the naming. 23 | #undef timeout 24 | #undef move 25 | 26 | namespace display { 27 | 28 | class Attributes { 29 | public: 30 | static const int a_invalid = ~int(); 31 | static const int a_normal = A_NORMAL; 32 | static const int a_bold = A_BOLD; 33 | static const int a_reverse = A_REVERSE; 34 | 35 | static const int color_invalid = ~int(); 36 | static const int color_default = 0; 37 | 38 | Attributes() = default; 39 | Attributes(const char* pos, int attr, int col) : 40 | m_position(pos), m_attributes(attr), m_colors(col) {} 41 | Attributes(const char* pos, const Attributes& old) : 42 | m_position(pos), m_attributes(old.m_attributes), m_colors(old.m_colors) {} 43 | 44 | const char* position() const { return m_position; } 45 | void set_position(const char* pos) { m_position = pos; } 46 | 47 | int attributes() const { return m_attributes; } 48 | void set_attributes(int attr) { m_attributes = attr; } 49 | 50 | int colors() const { return m_colors; } 51 | void set_colors(int col) { m_colors = col; } 52 | 53 | private: 54 | const char* m_position; 55 | int m_attributes; 56 | int m_colors; 57 | }; 58 | 59 | } 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /src/display/color_map.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_DISPLAY_COLOR_MAP_H 2 | #define RTORRENT_DISPLAY_COLOR_MAP_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace display { 10 | 11 | enum ColorKind { 12 | RCOLOR_NCURSES_DEFAULT, // Color 0 is reserved by ncurses and cannot be changed 13 | RCOLOR_TITLE, 14 | RCOLOR_FOOTER, 15 | RCOLOR_FOCUS, 16 | RCOLOR_LABEL, 17 | RCOLOR_INFO, 18 | RCOLOR_ALARM, 19 | RCOLOR_COMPLETE, 20 | RCOLOR_SEEDING, 21 | RCOLOR_STOPPED, 22 | RCOLOR_QUEUED, 23 | RCOLOR_INCOMPLETE, 24 | RCOLOR_LEECHING, 25 | RCOLOR_ODD, 26 | RCOLOR_EVEN, 27 | RCOLOR_MAX, 28 | }; 29 | 30 | static const std::array color_vars{ 31 | nullptr, 32 | "ui.color.title", 33 | "ui.color.footer", 34 | "ui.color.focus", 35 | "ui.color.label", 36 | "ui.color.info", 37 | "ui.color.alarm", 38 | "ui.color.complete", 39 | "ui.color.seeding", 40 | "ui.color.stopped", 41 | "ui.color.queued", 42 | "ui.color.incomplete", 43 | "ui.color.leeching", 44 | "ui.color.odd", 45 | "ui.color.even", 46 | }; 47 | 48 | } // namespace display 49 | #endif 50 | -------------------------------------------------------------------------------- /src/display/manager.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "canvas.h" 7 | #include "globals.h" 8 | #include "manager.h" 9 | #include "window.h" 10 | 11 | namespace display { 12 | 13 | Manager::Manager() { 14 | m_scheduler.external_set_thread_id(std::this_thread::get_id()); 15 | 16 | m_task_update.slot() = std::bind(&Manager::receive_update, this); 17 | } 18 | 19 | Manager::~Manager() { 20 | torrent::this_thread::scheduler()->erase(&m_task_update); 21 | } 22 | 23 | void 24 | Manager::force_redraw() { 25 | m_force_redraw = true; 26 | } 27 | 28 | void 29 | Manager::schedule(Window* w, std::chrono::microseconds t) { 30 | m_scheduler.external_set_cached_time(torrent::this_thread::cached_time()); 31 | m_scheduler.update_wait_until(w->task_update(), t); 32 | 33 | schedule_update(50ms); 34 | } 35 | 36 | void 37 | Manager::unschedule(Window* w) { 38 | m_scheduler.external_set_cached_time(torrent::this_thread::cached_time()); 39 | m_scheduler.erase(w->task_update()); 40 | 41 | schedule_update(50ms); 42 | } 43 | 44 | void 45 | Manager::adjust_layout() { 46 | Canvas::redraw_std(); 47 | m_root_frame.balance(0, 0, Canvas::get_screen_width(), Canvas::get_screen_height()); 48 | 49 | schedule_update(0ms); 50 | } 51 | 52 | void 53 | Manager::receive_update() { 54 | if (m_force_redraw) { 55 | m_force_redraw = false; 56 | 57 | display::Canvas::resize_term(display::Canvas::term_size()); 58 | Canvas::redraw_std(); 59 | 60 | adjust_layout(); 61 | m_root_frame.redraw(); 62 | } 63 | 64 | Canvas::refresh_std(); 65 | 66 | m_scheduler.external_perform(torrent::this_thread::cached_time()); 67 | m_root_frame.refresh(); 68 | 69 | Canvas::do_update(); 70 | 71 | m_time_last_update = torrent::this_thread::cached_time(); 72 | schedule_update(50ms); 73 | } 74 | 75 | void 76 | Manager::schedule_update(std::chrono::microseconds min_interval) { 77 | if (m_scheduler.empty()) { 78 | torrent::this_thread::scheduler()->erase(&m_task_update); 79 | return; 80 | } 81 | 82 | if (m_task_update.is_scheduled() && m_task_update.time() <= m_scheduler.front()->time()) 83 | return; 84 | 85 | torrent::this_thread::scheduler()->update_wait_until(&m_task_update, std::max(m_scheduler.front()->time(), m_time_last_update + min_interval)); 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /src/display/manager.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_DISPLAY_MANAGER_H 2 | #define RTORRENT_DISPLAY_MANAGER_H 3 | 4 | #include 5 | 6 | #include "frame.h" 7 | 8 | namespace display { 9 | 10 | class Window; 11 | 12 | class Manager { 13 | public: 14 | Manager(); 15 | ~Manager(); 16 | 17 | void force_redraw(); 18 | 19 | void schedule(Window* w, std::chrono::microseconds t); 20 | void unschedule(Window* w); 21 | 22 | void adjust_layout(); 23 | void receive_update(); 24 | 25 | // New interface. 26 | Frame* root_frame() { return &m_root_frame; } 27 | 28 | private: 29 | void schedule_update(std::chrono::microseconds min_interval); 30 | 31 | bool m_force_redraw{false}; 32 | Frame m_root_frame; 33 | 34 | std::chrono::microseconds m_time_last_update{}; 35 | torrent::utils::ExternalScheduler m_scheduler; 36 | torrent::utils::SchedulerEntry m_task_update; 37 | }; 38 | 39 | } 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/display/text_element.h: -------------------------------------------------------------------------------- 1 | // rTorrent - BitTorrent client 2 | // Copyright (C) 2005-2011, Jari Sundell 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | // 18 | // In addition, as a special exception, the copyright holders give 19 | // permission to link the code of portions of this program with the 20 | // OpenSSL library under certain conditions as described in each 21 | // individual source file, and distribute linked combinations 22 | // including the two. 23 | // 24 | // You must obey the GNU General Public License in all respects for 25 | // all of the code used other than OpenSSL. If you modify file(s) 26 | // with this exception, you may extend this exception to your version 27 | // of the file(s), but you are not obligated to do so. If you do not 28 | // wish to do so, delete this exception statement from your version. 29 | // If you delete this exception statement from all source files in the 30 | // program, then also delete it here. 31 | // 32 | // Contact: Jari Sundell 33 | // 34 | // Skomakerveien 33 35 | // 3185 Skoppum, NORWAY 36 | 37 | #ifndef RTORRENT_DISPLAY_TEXT_ELEMENT_H 38 | #define RTORRENT_DISPLAY_TEXT_ELEMENT_H 39 | 40 | #include 41 | #include 42 | 43 | #include "display/canvas.h" 44 | #include "rpc/command_map.h" 45 | 46 | namespace display { 47 | 48 | class TextElement { 49 | public: 50 | typedef uint32_t extent_type; 51 | 52 | static const extent_type extent_full = ~extent_type(); 53 | 54 | TextElement() = default; 55 | virtual ~TextElement() = default; 56 | 57 | // The last element must point to a valid memory location into which 58 | // the caller must write a '\0' to terminate the c string. The 59 | // attributes must contain at least one attribute. 60 | virtual char* print(char* first, char* last, Canvas::attributes_list* attributes, rpc::target_type target) = 0; 61 | 62 | virtual extent_type max_length() = 0; 63 | 64 | static void push_attribute(Canvas::attributes_list* attributes, Attributes value); 65 | 66 | private: 67 | TextElement(const TextElement&); 68 | void operator = (const TextElement&); 69 | }; 70 | 71 | } 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /src/display/window.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include "window.h" 4 | 5 | #include 6 | 7 | namespace display { 8 | 9 | Window::SlotTimer Window::m_slot_schedule; 10 | Window::SlotWindow Window::m_slot_unschedule; 11 | Window::Slot Window::m_slot_adjust; 12 | 13 | // When constructing the window we set flag_offscreen so that redraw 14 | // doesn't get triggered until after a successful Frame::balance call. 15 | 16 | Window::Window(Canvas* canvas, int flags, extent_type min_width, extent_type min_height, extent_type max_width, extent_type max_height) : 17 | m_canvas(canvas), 18 | m_flags(flags | flag_offscreen), 19 | 20 | m_min_width(min_width), 21 | m_min_height(min_height), 22 | 23 | m_max_width(max_width), 24 | m_max_height(max_height) { 25 | 26 | m_task_update.slot() = [this] { redraw(); }; 27 | } 28 | 29 | Window::~Window() { 30 | if (is_active()) 31 | m_slot_unschedule(this); 32 | 33 | delete m_canvas; 34 | } 35 | 36 | void 37 | Window::set_active(bool state) { 38 | if (state == is_active()) 39 | return; 40 | 41 | if (state) { 42 | // Set offscreen so we don't try rendering before Frame::balance 43 | // has been called. 44 | m_flags |= flag_active | flag_offscreen; 45 | mark_dirty(); 46 | 47 | } else { 48 | m_flags &= ~flag_active; 49 | m_slot_unschedule(this); 50 | } 51 | } 52 | 53 | void 54 | Window::resize(int x, int y, int w, int h) { 55 | if (x < 0 || y < 0) 56 | throw std::logic_error("Window::resize(...) bad x or y position"); 57 | 58 | if (w <= 0 || h <= 0) 59 | throw std::logic_error("Window::resize(...) bad size"); 60 | 61 | m_canvas->resize(x, y, w, h); 62 | } 63 | 64 | void 65 | Window::schedule_update(unsigned int wait_seconds) { 66 | if (wait_seconds == 0) { 67 | m_slot_schedule(this, torrent::utils::ceil_seconds(torrent::this_thread::cached_time() + 100ms)); 68 | return; 69 | } 70 | 71 | m_slot_schedule(this, torrent::utils::ceil_seconds(torrent::this_thread::cached_time() + 1s*wait_seconds)); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/display/window_download_chunks_seen.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_DISPLAY_WINDOW_DOWNLOAD_CHUNKS_SEEN_H 2 | #define RTORRENT_DISPLAY_WINDOW_DOWNLOAD_CHUNKS_SEEN_H 3 | 4 | #include 5 | 6 | #include "window.h" 7 | 8 | namespace core { 9 | class Download; 10 | } 11 | 12 | namespace display { 13 | 14 | class WindowDownloadChunksSeen : public Window { 15 | public: 16 | WindowDownloadChunksSeen(core::Download* d, unsigned int* focus); 17 | 18 | virtual void redraw(); 19 | 20 | unsigned int rows() const; 21 | unsigned int chunks_per_row() const { return (width() - 6) / 11 * 10; } 22 | 23 | unsigned int max_focus() const { return std::max(rows() - height() / 2 + 1, 0); } 24 | 25 | private: 26 | core::Download* m_download; 27 | 28 | unsigned int* m_focus; 29 | }; 30 | 31 | } 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/display/window_download_list.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_DISPLAY_WINDOW_DOWNLOAD_LIST_H 2 | #define RTORRENT_DISPLAY_WINDOW_DOWNLOAD_LIST_H 3 | 4 | #include "window.h" 5 | 6 | #include "core/download_list.h" 7 | #include "core/view.h" 8 | 9 | namespace display { 10 | 11 | class WindowDownloadList : public Window { 12 | public: 13 | typedef core::View::signal_void::iterator signal_void_itr; 14 | typedef std::pair ViewRange; 15 | 16 | WindowDownloadList(); 17 | ~WindowDownloadList(); 18 | 19 | virtual void redraw(); 20 | 21 | void set_view(core::View* l); 22 | 23 | int page_size(const std::string layout_name); 24 | int page_size(); 25 | 26 | private: 27 | core::View* m_view{}; 28 | 29 | std::pair get_attr_color(core::View::iterator selected); 30 | signal_void_itr m_changed_itr; 31 | }; 32 | 33 | } 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/display/window_download_statusbar.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include "window_download_statusbar.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "canvas.h" 11 | #include "globals.h" 12 | #include "utils.h" 13 | #include "core/download.h" 14 | 15 | namespace display { 16 | 17 | WindowDownloadStatusbar::WindowDownloadStatusbar(core::Download* d) : 18 | Window(new Canvas, 0, 0, 3, extent_full, extent_static), 19 | m_download(d) { 20 | } 21 | 22 | void 23 | WindowDownloadStatusbar::redraw() { 24 | if (m_canvas->daemon()) 25 | return; 26 | 27 | schedule_update(); 28 | 29 | m_canvas->erase(); 30 | 31 | std::string buffer(m_canvas->width(), ' '); 32 | char* last = buffer.data() + m_canvas->width() - 2; 33 | 34 | print_download_info_full(buffer.data(), last, m_download); 35 | m_canvas->print(0, 0, "%s", buffer.data()); 36 | 37 | snprintf(buffer.data(), last - buffer.data(), "Peers: %i(%i) Min/Max: %i/%i Slots: U:%i/%i D:%i/%i U/I/C/A: %i/%i/%i/%i Unchoked: %u/%u Failed: %i", 38 | (int)m_download->download()->connection_list()->size(), 39 | (int)m_download->download()->peer_list()->available_list_size(), 40 | (int)m_download->download()->connection_list()->min_size(), 41 | (int)m_download->download()->connection_list()->max_size(), 42 | (int)m_download->download()->uploads_min(), 43 | (int)m_download->download()->uploads_max(), 44 | (int)m_download->download()->downloads_min(), 45 | (int)m_download->download()->downloads_max(), 46 | (int)m_download->download()->peers_currently_unchoked(), 47 | (int)m_download->download()->peers_currently_interested(), 48 | (int)m_download->download()->peers_complete(), 49 | (int)m_download->download()->peers_accounted(), 50 | (int)m_download->info()->upload_unchoked(), 51 | (int)m_download->info()->download_unchoked(), 52 | (int)m_download->download()->transfer_list()->failed_count()); 53 | 54 | m_canvas->print(0, 1, "%s", buffer.data()); 55 | 56 | print_download_status(buffer.data(), last, m_download); 57 | m_canvas->print(0, 2, "[%c:%i] %s", 58 | m_download->tracker_controller().has_active_trackers() ? 'C' : ' ', 59 | (int)(m_download->download()->tracker_controller().seconds_to_next_timeout()), 60 | buffer.data()); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/display/window_download_statusbar.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_WINDOW_DOWNLOAD_STATUSBAR_H 2 | #define RTORRENT_WINDOW_DOWNLOAD_STATUSBAR_H 3 | 4 | #include "window.h" 5 | 6 | namespace core { 7 | class Download; 8 | } 9 | 10 | namespace display { 11 | 12 | class WindowDownloadStatusbar : public Window { 13 | public: 14 | WindowDownloadStatusbar(core::Download* d); 15 | 16 | virtual void redraw(); 17 | 18 | private: 19 | core::Download* m_download; 20 | }; 21 | 22 | } 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/display/window_download_transfer_list.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_DISPLAY_WINDOW_DOWNLOAD_TRANSFER_LIST_H 2 | #define RTORRENT_DISPLAY_WINDOW_DOWNLOAD_TRANSFER_LIST_H 3 | 4 | #include 5 | #include 6 | 7 | #include "window.h" 8 | 9 | namespace core { 10 | class Download; 11 | } 12 | 13 | namespace display { 14 | 15 | class WindowDownloadTransferList : public Window { 16 | public: 17 | struct assigned_type { 18 | assigned_type(torrent::BlockTransfer::key_type key, uint32_t last, char id) : m_key(key), m_last(last), m_id(id) { } 19 | 20 | torrent::BlockTransfer::key_type m_key; 21 | uint32_t m_last; 22 | char m_id; 23 | }; 24 | 25 | typedef std::vector assigned_vector; 26 | 27 | WindowDownloadTransferList(core::Download* d, unsigned int* focus); 28 | 29 | virtual void redraw(); 30 | 31 | unsigned int rows() const; 32 | unsigned int max_focus() const { return std::max(rows() - height() + 1, 0); } 33 | 34 | private: 35 | char key_id(torrent::BlockTransfer::key_type key); 36 | 37 | core::Download* m_download; 38 | assigned_vector m_assigned; 39 | }; 40 | 41 | } 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /src/display/window_file_list.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_DISPLAY_FILE_LIST_H 2 | #define RTORRENT_DISPLAY_FILE_LIST_H 3 | 4 | #include "window.h" 5 | 6 | namespace ui { 7 | class ElementFileList; 8 | } 9 | 10 | namespace torrent { 11 | class File; 12 | class FileListIterator; 13 | class file_list_collapsed_iterator; 14 | } 15 | 16 | namespace display { 17 | 18 | class WindowFileList : public Window { 19 | public: 20 | typedef torrent::FileListIterator iterator; 21 | typedef torrent::file_list_collapsed_iterator collapsed_iterator; 22 | 23 | WindowFileList(const ui::ElementFileList* element); 24 | 25 | virtual void redraw(); 26 | 27 | private: 28 | int done_percentage(torrent::File* e); 29 | 30 | const ui::ElementFileList* m_element; 31 | }; 32 | 33 | } 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/display/window_http_queue.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_DISPLAY_WINDOW_HTTP_QUEUE_H 2 | #define RTORRENT_DISPLAY_WINDOW_HTTP_QUEUE_H 3 | 4 | #include 5 | #include 6 | 7 | #include "window.h" 8 | 9 | namespace core { 10 | class CurlGet; 11 | class HttpQueue; 12 | } 13 | 14 | namespace display { 15 | 16 | class WindowHttpQueue : public Window { 17 | public: 18 | typedef std::function slot_curl_get; 19 | typedef std::list signal_curl_get; 20 | 21 | WindowHttpQueue(core::HttpQueue* q); 22 | ~WindowHttpQueue() override; 23 | 24 | void redraw() override; 25 | 26 | private: 27 | struct Node { 28 | Node(core::CurlGet* h, const std::string& n) : m_http(h), m_name(n) {} 29 | 30 | core::CurlGet* m_http{}; 31 | std::string m_name; 32 | std::chrono::microseconds m_timer{}; 33 | }; 34 | 35 | typedef std::list Container; 36 | 37 | void cleanup_list(); 38 | 39 | void receive_insert(core::CurlGet* h); 40 | void receive_erase(core::CurlGet* h); 41 | 42 | static std::string create_name(core::CurlGet* h); 43 | 44 | core::HttpQueue* m_queue; 45 | Container m_container; 46 | 47 | signal_curl_get::iterator m_conn_insert; 48 | signal_curl_get::iterator m_conn_erase; 49 | 50 | torrent::utils::SchedulerEntry m_task_deactivate; 51 | }; 52 | 53 | } 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /src/display/window_input.cc: -------------------------------------------------------------------------------- 1 | // rTorrent - BitTorrent client 2 | // Copyright (C) 2005-2011, Jari Sundell 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | // 18 | // In addition, as a special exception, the copyright holders give 19 | // permission to link the code of portions of this program with the 20 | // OpenSSL library under certain conditions as described in each 21 | // individual source file, and distribute linked combinations 22 | // including the two. 23 | // 24 | // You must obey the GNU General Public License in all respects for 25 | // all of the code used other than OpenSSL. If you modify file(s) 26 | // with this exception, you may extend this exception to your version 27 | // of the file(s), but you are not obligated to do so. If you do not 28 | // wish to do so, delete this exception statement from your version. 29 | // If you delete this exception statement from all source files in the 30 | // program, then also delete it here. 31 | // 32 | // Contact: Jari Sundell 33 | // 34 | // Skomakerveien 33 35 | // 3185 Skoppum, NORWAY 36 | 37 | #include "config.h" 38 | 39 | #include "canvas.h" 40 | #include "window_input.h" 41 | 42 | #include "input/text_input.h" 43 | 44 | namespace display { 45 | 46 | void 47 | WindowInput::redraw() { 48 | m_canvas->erase(); 49 | m_canvas->print(0, 0, "%s> %s", m_title.c_str(), m_input != NULL ? m_input->c_str() : ""); 50 | 51 | if (m_focus) 52 | m_canvas->set_attr(m_input->get_pos() + 2 + m_title.size(), 0, 1, A_REVERSE, COLOR_PAIR(0)); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/display/window_input.h: -------------------------------------------------------------------------------- 1 | // rTorrent - BitTorrent client 2 | // Copyright (C) 2005-2011, Jari Sundell 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | // 18 | // In addition, as a special exception, the copyright holders give 19 | // permission to link the code of portions of this program with the 20 | // OpenSSL library under certain conditions as described in each 21 | // individual source file, and distribute linked combinations 22 | // including the two. 23 | // 24 | // You must obey the GNU General Public License in all respects for 25 | // all of the code used other than OpenSSL. If you modify file(s) 26 | // with this exception, you may extend this exception to your version 27 | // of the file(s), but you are not obligated to do so. If you do not 28 | // wish to do so, delete this exception statement from your version. 29 | // If you delete this exception statement from all source files in the 30 | // program, then also delete it here. 31 | // 32 | // Contact: Jari Sundell 33 | // 34 | // Skomakerveien 33 35 | // 3185 Skoppum, NORWAY 36 | 37 | #ifndef RTORRENT_DISPLAY_WINDOW_INPUT_H 38 | #define RTORRENT_DISPLAY_WINDOW_INPUT_H 39 | 40 | #include 41 | 42 | #include "window.h" 43 | 44 | namespace input { 45 | class TextInput; 46 | } 47 | 48 | namespace display { 49 | 50 | class WindowInput : public Window { 51 | public: 52 | WindowInput() : 53 | Window(new Canvas, 0, 0, 1, extent_full, 1) {} 54 | 55 | input::TextInput* input() { return m_input; } 56 | void set_input(input::TextInput* input) { m_input = input; } 57 | 58 | const std::string& title() const { return m_title; } 59 | void set_title(const std::string& str) { m_title = str; } 60 | 61 | bool focus() const { return m_focus; } 62 | void set_focus(bool f) { m_focus = f; if (is_active()) mark_dirty(); } 63 | 64 | virtual void redraw(); 65 | 66 | private: 67 | input::TextInput* m_input{}; 68 | std::string m_title; 69 | 70 | bool m_focus{}; 71 | }; 72 | 73 | } 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /src/display/window_log.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "canvas.h" 8 | #include "utils.h" 9 | #include "window_log.h" 10 | 11 | namespace display { 12 | 13 | WindowLog::WindowLog(torrent::log_buffer* l) : 14 | Window(new Canvas, 0, 0, 0, extent_full, extent_static), 15 | m_log(l) { 16 | 17 | m_task_update.slot() = std::bind(&WindowLog::receive_update, this); 18 | 19 | unsigned int signal_index = torrent::main_thread::thread()->signal_bitfield()->add_signal(std::bind(&WindowLog::receive_update, this)); 20 | 21 | m_log->lock_and_set_update_slot([signal_index]() { 22 | torrent::main_thread::thread()->send_event_signal(signal_index, false); 23 | }); 24 | } 25 | 26 | WindowLog::~WindowLog() { 27 | torrent::this_thread::scheduler()->erase(&m_task_update); 28 | } 29 | 30 | WindowLog::iterator 31 | WindowLog::find_older() { 32 | return m_log->find_older(torrent::this_thread::cached_seconds().count() - 60); 33 | } 34 | 35 | void 36 | WindowLog::redraw() { 37 | m_canvas->erase(); 38 | 39 | int pos = m_canvas->height(); 40 | 41 | for (iterator itr = m_log->end(), last = find_older(); itr != last && pos > 0; --pos) { 42 | itr--; 43 | 44 | char buffer[16]; 45 | print_hhmmss_local(buffer, buffer + 16, static_cast(itr->timestamp)); 46 | 47 | m_canvas->print(0, pos - 1, "(%s) %s", buffer, itr->message.c_str()); 48 | } 49 | } 50 | 51 | // When WindowLog is activated, call receive_update() to ensure it 52 | // gets updated. 53 | void 54 | WindowLog::receive_update() { 55 | if (!is_active()) 56 | return; 57 | 58 | iterator itr = find_older(); 59 | extent_type height = std::min(std::distance(itr, (iterator)m_log->end()), (std::iterator_traits::difference_type)10); 60 | 61 | if (height != m_max_height) { 62 | m_min_height = height != 0 ? 1 : 0; 63 | m_max_height = height; 64 | mark_dirty(); 65 | m_slot_adjust(); 66 | 67 | } else { 68 | mark_dirty(); 69 | } 70 | 71 | if (height == 0) { 72 | torrent::this_thread::scheduler()->erase(&m_task_update); 73 | return; 74 | } 75 | 76 | torrent::this_thread::scheduler()->update_wait_for_ceil_seconds(&m_task_update, 5s); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/display/window_log.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_DISPLAY_WINDOW_LOG_H 2 | #define RTORRENT_DISPLAY_WINDOW_LOG_H 3 | 4 | #include 5 | #include 6 | 7 | #include "window.h" 8 | 9 | namespace display { 10 | 11 | class WindowLog : public Window { 12 | public: 13 | typedef torrent::log_buffer::const_iterator iterator; 14 | 15 | WindowLog(torrent::log_buffer* l); 16 | ~WindowLog(); 17 | 18 | virtual void redraw(); 19 | 20 | void receive_update(); 21 | 22 | private: 23 | inline iterator find_older(); 24 | 25 | torrent::log_buffer* m_log; 26 | torrent::utils::SchedulerEntry m_task_update; 27 | }; 28 | 29 | } 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/display/window_log_complete.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include 4 | 5 | #include "canvas.h" 6 | #include "utils.h" 7 | #include "window_log_complete.h" 8 | 9 | namespace display { 10 | 11 | WindowLogComplete::WindowLogComplete(torrent::log_buffer* l) : 12 | Window(new Canvas, 0, 30, 1, extent_full, extent_full), 13 | m_log(l) { 14 | } 15 | 16 | WindowLogComplete::~WindowLogComplete() = default; 17 | 18 | WindowLogComplete::iterator 19 | WindowLogComplete::find_older() { 20 | return m_log->find_older(torrent::this_thread::cached_seconds().count() - 60); 21 | } 22 | 23 | void 24 | WindowLogComplete::redraw() { 25 | m_canvas->erase(); 26 | 27 | if (m_canvas->width() < 16) 28 | return; 29 | 30 | int pos = m_canvas->height(); 31 | 32 | for (iterator itr = m_log->end(), last = m_log->begin(); itr != last && pos > 0; ) { 33 | itr--; 34 | 35 | char buffer[16]; 36 | 37 | // Use an arbitrary min width of 60 for allowing multiple 38 | // lines. This should ensure we don't mess up the display when the 39 | // screen is shrunk too much. 40 | unsigned int timeWidth = 3 + print_hhmmss_local(buffer, buffer + 16, static_cast(itr->timestamp)) - buffer; 41 | 42 | unsigned int logWidth = m_canvas->width() > 60 ? (m_canvas->width() - timeWidth) : (60 - timeWidth); 43 | unsigned int logHeight = (itr->message.size() + logWidth - 1) / logWidth; 44 | 45 | for (unsigned int j = logHeight; j > 0 && pos > 0; --j, --pos) 46 | if (j == 1) 47 | m_canvas->print(0, pos - 1, "(%s) %s", buffer, itr->message.substr(0, m_canvas->width() - timeWidth).c_str()); 48 | else 49 | m_canvas->print(timeWidth, pos - 1, "%s", itr->message.substr(logWidth * (j - 1), m_canvas->width() - timeWidth).c_str()); 50 | } 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/display/window_log_complete.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_DISPLAY_WINDOW_LOG_COMPLETE_H 2 | #define RTORRENT_DISPLAY_WINDOW_LOG_COMPLETE_H 3 | 4 | #include 5 | 6 | #include "window.h" 7 | 8 | namespace display { 9 | 10 | class WindowLogComplete : public Window { 11 | public: 12 | typedef torrent::log_buffer::const_iterator iterator; 13 | 14 | WindowLogComplete(torrent::log_buffer* l); 15 | ~WindowLogComplete(); 16 | 17 | virtual void redraw(); 18 | 19 | private: 20 | inline iterator find_older(); 21 | 22 | torrent::log_buffer* m_log; 23 | }; 24 | 25 | } 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/display/window_peer_list.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_DISPLAY_PEER_LIST_H 2 | #define RTORRENT_DISPLAY_PEER_LIST_H 3 | 4 | #include 5 | #include 6 | 7 | #include "window.h" 8 | 9 | namespace core { 10 | class Download; 11 | } 12 | 13 | namespace display { 14 | 15 | class WindowPeerList : public Window { 16 | public: 17 | typedef std::list PList; 18 | 19 | WindowPeerList(core::Download* d, PList* l, PList::iterator* f); 20 | 21 | virtual void redraw(); 22 | 23 | private: 24 | int done_percentage(torrent::Peer* p); 25 | 26 | core::Download* m_download; 27 | 28 | PList* m_list; 29 | PList::iterator* m_focus; 30 | }; 31 | 32 | } 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/display/window_statusbar.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include "display/color_map.h" 4 | #include 5 | #include 6 | 7 | #include "control.h" 8 | #include "canvas.h" 9 | #include "utils.h" 10 | #include "window_statusbar.h" 11 | 12 | namespace display { 13 | 14 | void 15 | WindowStatusbar::redraw() { 16 | schedule_update(); 17 | 18 | m_canvas->erase(); 19 | 20 | std::vector buffer(m_canvas->width() + 1); 21 | char* position; 22 | char* last = buffer.data() + m_canvas->width(); 23 | 24 | position = print_status_info(buffer.data(), last); 25 | m_canvas->print(0, 0, "%s", buffer.data()); 26 | 27 | last = last - (position - buffer.data()); 28 | 29 | if (last > buffer.data()) { 30 | position = print_status_extra(buffer.data(), last); 31 | m_canvas->print(m_canvas->width() - (position - buffer.data()), 0, "%s", buffer.data()); 32 | } 33 | 34 | m_canvas->set_attr(0, 0, -1, RCOLOR_FOOTER); 35 | 36 | m_lastTick = control->tick(); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/display/window_statusbar.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_DISPLAY_WINDOW_STATUSBAR_H 2 | #define RTORRENT_DISPLAY_WINDOW_STATUSBAR_H 3 | 4 | #include 5 | 6 | #include "window.h" 7 | 8 | namespace display { 9 | 10 | class WindowStatusbar : public Window { 11 | public: 12 | WindowStatusbar() : 13 | Window(new Canvas, 0, 0, 1, extent_full, extent_static) {} 14 | 15 | virtual void redraw(); 16 | 17 | private: 18 | uint64_t m_lastTick{}; 19 | }; 20 | 21 | } 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/display/window_string_list.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include "canvas.h" 4 | #include "utils.h" 5 | #include "window_string_list.h" 6 | 7 | namespace display { 8 | 9 | WindowStringList::WindowStringList() : 10 | Window(new Canvas, 0, 0, 0, extent_full, extent_full) { 11 | } 12 | 13 | WindowStringList::~WindowStringList() = default; 14 | 15 | void 16 | WindowStringList::redraw() { 17 | m_canvas->erase(); 18 | 19 | size_t ypos = 0; 20 | size_t xpos = 1; 21 | size_t width = 0; 22 | 23 | iterator itr = m_first; 24 | 25 | while (itr != m_last) { 26 | 27 | if (ypos == (size_t)m_canvas->height()) { 28 | ypos = 0; 29 | xpos += width + 2; 30 | 31 | if (xpos + 20 >= (size_t)m_canvas->width()) 32 | break; 33 | 34 | width = 0; 35 | } 36 | 37 | width = std::max(itr->size(), width); 38 | 39 | if (xpos + itr->size() <= (size_t)m_canvas->width()) 40 | m_canvas->print(xpos, ypos++, "%s", itr->c_str()); 41 | else 42 | m_canvas->print(xpos, ypos++, "%s", itr->substr(0, m_canvas->width() - xpos).c_str()); 43 | 44 | ++itr; 45 | } 46 | 47 | m_drawEnd = itr; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/display/window_string_list.h: -------------------------------------------------------------------------------- 1 | // rTorrent - BitTorrent client 2 | // Copyright (C) 2005-2011, Jari Sundell 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | // 18 | // In addition, as a special exception, the copyright holders give 19 | // permission to link the code of portions of this program with the 20 | // OpenSSL library under certain conditions as described in each 21 | // individual source file, and distribute linked combinations 22 | // including the two. 23 | // 24 | // You must obey the GNU General Public License in all respects for 25 | // all of the code used other than OpenSSL. If you modify file(s) 26 | // with this exception, you may extend this exception to your version 27 | // of the file(s), but you are not obligated to do so. If you do not 28 | // wish to do so, delete this exception statement from your version. 29 | // If you delete this exception statement from all source files in the 30 | // program, then also delete it here. 31 | // 32 | // Contact: Jari Sundell 33 | // 34 | // Skomakerveien 33 35 | // 3185 Skoppum, NORWAY 36 | 37 | #ifndef RTORRENT_DISPLAY_WINDOW_STRING_LIST_H 38 | #define RTORRENT_DISPLAY_WINDOW_STRING_LIST_H 39 | 40 | #include 41 | #include 42 | 43 | #include "window.h" 44 | 45 | namespace display { 46 | 47 | class WindowStringList : public Window { 48 | public: 49 | typedef std::list::iterator iterator; 50 | 51 | WindowStringList(); 52 | ~WindowStringList(); 53 | 54 | iterator get_draw_end() { return m_drawEnd; } 55 | 56 | void set_range(iterator first, iterator last) { m_first = m_drawEnd = first; m_last = last; } 57 | 58 | virtual void redraw(); 59 | 60 | private: 61 | iterator m_first; 62 | iterator m_last; 63 | 64 | iterator m_drawEnd; 65 | }; 66 | 67 | } 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /src/display/window_text.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include 4 | 5 | #include "canvas.h" 6 | #include "utils.h" 7 | #include "window_text.h" 8 | 9 | namespace display { 10 | 11 | WindowText::WindowText(rpc::target_type target, extent_type margin) : 12 | Window(new Canvas, 0, 0, 0, extent_static, extent_static), 13 | m_target(target), 14 | m_margin(margin) { 15 | } 16 | 17 | void 18 | WindowText::clear() { 19 | std::for_each(begin(), end(), [](TextElement* text) { delete text; }); 20 | base_type::clear(); 21 | 22 | delete m_errorHandler; 23 | m_errorHandler = NULL; 24 | } 25 | 26 | void 27 | WindowText::push_back(TextElement* element) { 28 | base_type::push_back(element); 29 | 30 | // m_min_height = size(); 31 | m_max_height = size(); 32 | 33 | if (element != NULL) { 34 | extent_type width = element->max_length(); 35 | 36 | if (width == extent_full) 37 | m_max_width = extent_full; 38 | else 39 | m_max_width = std::max(m_max_width, element->max_length() + m_margin); 40 | } 41 | 42 | // Check if active, if so do the update thingie. Or be lazy? 43 | } 44 | 45 | void 46 | WindowText::redraw() { 47 | if (m_interval != 0) 48 | schedule_update(m_interval); 49 | 50 | m_canvas->erase(); 51 | 52 | unsigned int position = 0; 53 | 54 | if (m_canvas->height() == 0) 55 | return; 56 | 57 | if (m_errorHandler != NULL && m_target.second == NULL) { 58 | std::string buffer(m_canvas->width() + 1, ' '); 59 | 60 | Canvas::attributes_list attributes; 61 | attributes.push_back(Attributes(buffer.data(), Attributes::a_normal, Attributes::color_default)); 62 | 63 | char* last = m_errorHandler->print(buffer.data(), buffer.data() + m_canvas->width(), &attributes, m_target); 64 | 65 | m_canvas->print_attributes(0, position, buffer.data(), last, &attributes); 66 | return; 67 | } 68 | 69 | for (iterator itr = begin(); itr != end() && position < m_canvas->height(); ++itr, ++position) { 70 | if (*itr == NULL) 71 | continue; 72 | 73 | std::string buffer(m_canvas->width() + 1, ' '); 74 | 75 | Canvas::attributes_list attributes; 76 | attributes.push_back(Attributes(buffer.data(), Attributes::a_normal, Attributes::color_default)); 77 | 78 | char* last = (*itr)->print(buffer.data(), buffer.data() + m_canvas->width(), &attributes, m_target); 79 | 80 | m_canvas->print_attributes(0, position, buffer.data(), last, &attributes); 81 | } 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /src/display/window_text.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_DISPLAY_WINDOW_TEXT_H 2 | #define RTORRENT_DISPLAY_WINDOW_TEXT_H 3 | 4 | #include 5 | 6 | #include "text_element.h" 7 | #include "window.h" 8 | 9 | namespace display { 10 | 11 | class WindowText : public Window, public std::vector { 12 | public: 13 | typedef std::vector base_type; 14 | 15 | typedef base_type::value_type value_type; 16 | typedef base_type::reference reference; 17 | typedef base_type::iterator iterator; 18 | typedef base_type::const_iterator const_iterator; 19 | typedef base_type::reverse_iterator reverse_iterator; 20 | 21 | using base_type::empty; 22 | using base_type::size; 23 | 24 | using base_type::begin; 25 | using base_type::end; 26 | using base_type::rbegin; 27 | using base_type::rend; 28 | 29 | WindowText(rpc::target_type target = rpc::make_target(), extent_type margin = 0); 30 | ~WindowText() { clear(); } 31 | 32 | void clear(); 33 | 34 | rpc::target_type target() const { return m_target; } 35 | void set_target(rpc::target_type target) { m_target = target; } 36 | 37 | uint32_t interval() const { return m_interval; } 38 | void set_interval(uint32_t i) { m_interval = i; } 39 | 40 | void push_back(TextElement* element); 41 | 42 | // Set an error handler if targets pointing to NULL elements should 43 | // be handled separately to avoid throwing errors. 44 | void set_error_handler(TextElement* element) { m_errorHandler = element; } 45 | 46 | virtual void redraw(); 47 | 48 | private: 49 | rpc::target_type m_target; 50 | TextElement* m_errorHandler{}; 51 | 52 | extent_type m_margin; 53 | uint32_t m_interval{}; 54 | }; 55 | 56 | } 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /src/display/window_title.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include "canvas.h" 4 | #include "window_title.h" 5 | 6 | namespace display { 7 | 8 | void 9 | WindowTitle::redraw() { 10 | if (m_canvas->daemon()) 11 | return; 12 | 13 | schedule_update(); 14 | m_canvas->erase(); 15 | 16 | m_canvas->print(std::max(0, ((int)m_canvas->width() - (int)m_title.size()) / 2 - 4), 0, "*** %s ***", m_title.c_str()); 17 | } 18 | 19 | } // namespace display 20 | -------------------------------------------------------------------------------- /src/display/window_title.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_DISPLAY_WINDOW_TITLE_H 2 | #define RTORRENT_DISPLAY_WINDOW_TITLE_H 3 | 4 | #include 5 | #include "window.h" 6 | 7 | namespace display { 8 | 9 | class WindowTitle : public Window { 10 | public: 11 | WindowTitle() : Window(new Canvas, 0, 0, 1, extent_full, extent_static) {} 12 | 13 | const std::string& title() const { return m_title; } 14 | void set_title(const std::string& title) { m_title = title; mark_dirty(); } 15 | 16 | virtual void redraw(); 17 | 18 | private: 19 | std::string m_title; 20 | }; 21 | 22 | } 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/display/window_tracker_list.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_DISPLAY_TRACKER_LIST_H 2 | #define RTORRENT_DISPLAY_TRACKER_LIST_H 3 | 4 | #include "window.h" 5 | 6 | namespace core { 7 | class Download; 8 | } 9 | 10 | namespace display { 11 | 12 | class WindowTrackerList : public Window { 13 | public: 14 | WindowTrackerList(core::Download* d, unsigned int* focus); 15 | 16 | virtual void redraw(); 17 | 18 | private: 19 | core::Download* m_download; 20 | 21 | unsigned int* m_focus; 22 | }; 23 | 24 | } 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/globals.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include "globals.h" 4 | 5 | rpc::ip_table_list ip_tables; 6 | 7 | Control* control{}; 8 | ThreadWorker* worker_thread{}; 9 | -------------------------------------------------------------------------------- /src/globals.h: -------------------------------------------------------------------------------- 1 | #ifndef TORRENT_GLOBALS_H 2 | #define TORRENT_GLOBALS_H 3 | 4 | #include "thread_worker.h" 5 | #include "rpc/ip_table_list.h" 6 | 7 | class Control; 8 | 9 | extern rpc::ip_table_list ip_tables; 10 | 11 | extern Control* control; 12 | extern ThreadWorker* worker_thread; 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/input/bindings.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include 4 | 5 | #include "bindings.h" 6 | 7 | namespace input { 8 | 9 | bool 10 | Bindings::pressed(int key) { 11 | if (!m_enabled) 12 | return false; 13 | 14 | const_iterator itr = find(key); 15 | 16 | if (itr == end()) 17 | return false; 18 | 19 | itr->second(); 20 | return true; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/input/bindings.h: -------------------------------------------------------------------------------- 1 | // rTorrent - BitTorrent client 2 | // Copyright (C) 2005-2011, Jari Sundell 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | // 18 | // In addition, as a special exception, the copyright holders give 19 | // permission to link the code of portions of this program with the 20 | // OpenSSL library under certain conditions as described in each 21 | // individual source file, and distribute linked combinations 22 | // including the two. 23 | // 24 | // You must obey the GNU General Public License in all respects for 25 | // all of the code used other than OpenSSL. If you modify file(s) 26 | // with this exception, you may extend this exception to your version 27 | // of the file(s), but you are not obligated to do so. If you do not 28 | // wish to do so, delete this exception statement from your version. 29 | // If you delete this exception statement from all source files in the 30 | // program, then also delete it here. 31 | // 32 | // Contact: Jari Sundell 33 | // 34 | // Skomakerveien 33 35 | // 3185 Skoppum, NORWAY 36 | 37 | #ifndef RTORRENT_INPUT_BINDINGS_H 38 | #define RTORRENT_INPUT_BINDINGS_H 39 | 40 | #include 41 | #include 42 | 43 | #include "display/attributes.h" 44 | 45 | namespace input { 46 | 47 | class Bindings : private std::map > { 48 | public: 49 | typedef std::function slot_void; 50 | typedef std::map base_type; 51 | 52 | using base_type::iterator; 53 | using base_type::const_iterator; 54 | using base_type::reverse_iterator; 55 | using base_type::const_reverse_iterator; 56 | 57 | using base_type::begin; 58 | using base_type::end; 59 | using base_type::rbegin; 60 | using base_type::rend; 61 | using base_type::find; 62 | 63 | using base_type::erase; 64 | 65 | using base_type::operator[]; 66 | 67 | Bindings() = default; 68 | 69 | void enable() { m_enabled = true; } 70 | void disable() { m_enabled = false; } 71 | 72 | bool pressed(int key); 73 | 74 | void ignore(int key) { (*this)[key] = slot_void(); } 75 | 76 | private: 77 | bool m_enabled{true}; 78 | }; 79 | 80 | } 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /src/input/input_event.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include "input_event.h" 4 | 5 | #include "display/attributes.h" 6 | 7 | namespace input { 8 | 9 | void 10 | InputEvent::insert(torrent::Poll* p) { 11 | p->open(this); 12 | p->insert_read(this); 13 | } 14 | 15 | void 16 | InputEvent::remove(torrent::Poll* p) { 17 | p->remove_read(this); 18 | p->close(this); 19 | } 20 | 21 | void 22 | InputEvent::event_read() { 23 | int c; 24 | 25 | while ((c = getch()) != ERR) 26 | m_slotPressed(c); 27 | } 28 | 29 | void 30 | InputEvent::event_write() { 31 | } 32 | 33 | void 34 | InputEvent::event_error() { 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/input/input_event.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_INPUT_INPUT_EVENT_H 2 | #define RTORRENT_INPUT_INPUT_EVENT_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | namespace input { 10 | 11 | class InputEvent : public torrent::Event { 12 | public: 13 | typedef std::function slot_int; 14 | 15 | InputEvent(int fd) { m_fileDesc = fd; } 16 | 17 | void insert(torrent::Poll* p); 18 | void remove(torrent::Poll* p); 19 | 20 | void event_read(); 21 | void event_write(); 22 | void event_error(); 23 | 24 | void slot_pressed(slot_int s) { m_slotPressed = s; } 25 | 26 | private: 27 | slot_int m_slotPressed; 28 | }; 29 | 30 | } 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/input/manager.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "manager.h" 8 | #include "bindings.h" 9 | #include "text_input.h" 10 | 11 | namespace input { 12 | 13 | void 14 | Manager::erase(Bindings* b) { 15 | iterator itr = std::find(begin(), end(), b); 16 | 17 | if (itr == end()) 18 | return; 19 | 20 | Base::erase(itr); 21 | 22 | if (std::find(begin(), end(), b) != end()) 23 | throw torrent::internal_error("Manager::erase(...) found duplicate bindings."); 24 | } 25 | 26 | void 27 | Manager::pressed(int key) { 28 | if (m_textInput != NULL) 29 | m_textInput->pressed(key); 30 | else 31 | [[maybe_unused]] auto result = std::find_if(rbegin(), rend(), [&key](Bindings* bind) { return bind->pressed(key); }); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/input/manager.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_INPUT_MANAGER_H 2 | #define RTORRENT_INPUT_MANAGER_H 3 | 4 | #include 5 | 6 | namespace input { 7 | 8 | class Bindings; 9 | class TextInput; 10 | 11 | class Manager : private std::vector { 12 | public: 13 | typedef std::vector Base; 14 | 15 | using Base::iterator; 16 | using Base::const_iterator; 17 | using Base::reverse_iterator; 18 | using Base::const_reverse_iterator; 19 | 20 | using Base::begin; 21 | using Base::end; 22 | using Base::rbegin; 23 | using Base::rend; 24 | 25 | using Base::push_back; 26 | 27 | void erase(Bindings* b); 28 | 29 | void pressed(int key); 30 | 31 | void set_text_input(TextInput* input = nullptr) { m_textInput = input; } 32 | 33 | private: 34 | TextInput* m_textInput{}; 35 | }; 36 | 37 | } 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/input/path_input.h: -------------------------------------------------------------------------------- 1 | // rTorrent - BitTorrent client 2 | // Copyright (C) 2005-2011, Jari Sundell 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | // 18 | // In addition, as a special exception, the copyright holders give 19 | // permission to link the code of portions of this program with the 20 | // OpenSSL library under certain conditions as described in each 21 | // individual source file, and distribute linked combinations 22 | // including the two. 23 | // 24 | // You must obey the GNU General Public License in all respects for 25 | // all of the code used other than OpenSSL. If you modify file(s) 26 | // with this exception, you may extend this exception to your version 27 | // of the file(s), but you are not obligated to do so. If you do not 28 | // wish to do so, delete this exception statement from your version. 29 | // If you delete this exception statement from all source files in the 30 | // program, then also delete it here. 31 | // 32 | // Contact: Jari Sundell 33 | // 34 | // Skomakerveien 33 35 | // 3185 Skoppum, NORWAY 36 | 37 | #ifndef RTORRENT_INPUT_PATH_INPUT_H 38 | #define RTORRENT_INPUT_PATH_INPUT_H 39 | 40 | #include 41 | #include 42 | 43 | #include "utils/directory.h" 44 | #include "text_input.h" 45 | 46 | namespace input { 47 | 48 | class PathInput : public TextInput { 49 | public: 50 | typedef utils::Directory::iterator directory_itr; 51 | typedef std::pair range_type; 52 | 53 | typedef std::function slot_void; 54 | typedef std::function slot_itr_itr; 55 | typedef std::list signal_void; 56 | typedef std::list signal_itr_itr; 57 | 58 | virtual ~PathInput() = default; 59 | 60 | signal_void& signal_show_next() { return m_signal_show_next; } 61 | signal_itr_itr& signal_show_range() { return m_signal_show_range; } 62 | 63 | virtual bool pressed(int key); 64 | 65 | private: 66 | void receive_do_complete(); 67 | 68 | size_type find_last_delim(); 69 | range_type find_incomplete(utils::Directory& d, const std::string& f); 70 | 71 | bool m_showNext{}; 72 | 73 | signal_void m_signal_show_next; 74 | signal_itr_itr m_signal_show_range; 75 | }; 76 | 77 | } 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /src/input/text_input.h: -------------------------------------------------------------------------------- 1 | // rTorrent - BitTorrent client 2 | // Copyright (C) 2005-2011, Jari Sundell 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | // 18 | // In addition, as a special exception, the copyright holders give 19 | // permission to link the code of portions of this program with the 20 | // OpenSSL library under certain conditions as described in each 21 | // individual source file, and distribute linked combinations 22 | // including the two. 23 | // 24 | // You must obey the GNU General Public License in all respects for 25 | // all of the code used other than OpenSSL. If you modify file(s) 26 | // with this exception, you may extend this exception to your version 27 | // of the file(s), but you are not obligated to do so. If you do not 28 | // wish to do so, delete this exception statement from your version. 29 | // If you delete this exception statement from all source files in the 30 | // program, then also delete it here. 31 | // 32 | // Contact: Jari Sundell 33 | // 34 | // Skomakerveien 33 35 | // 3185 Skoppum, NORWAY 36 | 37 | #ifndef RTORRENT_INPUT_TEXT_INPUT_H 38 | #define RTORRENT_INPUT_TEXT_INPUT_H 39 | 40 | #include 41 | 42 | #include "bindings.h" 43 | 44 | namespace input { 45 | 46 | class TextInput : private std::string { 47 | public: 48 | typedef std::string Base; 49 | typedef std::function slot_void; 50 | 51 | using Base::c_str; 52 | using Base::empty; 53 | using Base::size; 54 | using Base::size_type; 55 | using Base::npos; 56 | 57 | virtual ~TextInput() = default; 58 | 59 | size_type get_pos() { return m_pos; } 60 | void set_pos(size_type pos) { m_pos = pos; } 61 | 62 | virtual bool pressed(int key); 63 | 64 | void clear() { m_pos = 0; Base::clear(); } 65 | 66 | void slot_dirty(slot_void s) { m_slot_dirty = s; } 67 | void mark_dirty() { if (m_slot_dirty) m_slot_dirty(); } 68 | 69 | std::string& str() { return *this; } 70 | 71 | Bindings& bindings() { return m_bindings; } 72 | 73 | private: 74 | size_type m_pos{}; 75 | 76 | slot_void m_slot_dirty; 77 | 78 | Bindings m_bindings; 79 | }; 80 | 81 | } 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /src/rpc/command_scheduler.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_COMMAND_SCHEDULER_H 2 | #define RTORRENT_COMMAND_SCHEDULER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace torrent { 10 | class Object; 11 | } 12 | 13 | namespace rpc { 14 | 15 | class CommandSchedulerItem; 16 | 17 | class CommandScheduler : public std::vector { 18 | public: 19 | typedef std::function SlotString; 20 | typedef std::pair Time; 21 | typedef std::vector base_type; 22 | 23 | using base_type::value_type; 24 | using base_type::begin; 25 | using base_type::end; 26 | 27 | CommandScheduler() = default; 28 | ~CommandScheduler(); 29 | 30 | void set_slot_error_message(SlotString s) { m_slotErrorMessage = s; } 31 | 32 | // slot_error_message or something. 33 | 34 | iterator find(const std::string& key); 35 | 36 | // If the key already exists then the old item is deleted. It is 37 | // safe to call erase on end(). 38 | iterator insert(const std::string& key); 39 | void erase(iterator itr); 40 | void erase_str(const std::string& key) { erase(find(key)); } 41 | 42 | void parse(const std::string& key, const std::string& bufAbsolute, 43 | const std::string& bufInterval, const torrent::Object& command); 44 | 45 | static uint32_t parse_absolute(const char* str); 46 | static uint32_t parse_interval(const char* str); 47 | 48 | static Time parse_time(const char* str); 49 | 50 | private: 51 | void call_item(value_type item); 52 | 53 | SlotString m_slotErrorMessage; 54 | }; 55 | 56 | } 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /src/rpc/command_scheduler_item.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include "rpc/command_scheduler_item.h" 4 | 5 | #include 6 | 7 | namespace rpc { 8 | 9 | CommandSchedulerItem::~CommandSchedulerItem() { 10 | torrent::this_thread::scheduler()->erase(&m_task); 11 | } 12 | 13 | void 14 | CommandSchedulerItem::enable(std::chrono::microseconds t) { 15 | if (t == std::chrono::microseconds()) 16 | throw torrent::internal_error("CommandSchedulerItem::enable() t == 0."); 17 | 18 | if (is_queued()) 19 | disable(); 20 | 21 | // If 'first' is zero then we execute the task 22 | // immediately. ''interval()'' will not return zero so we never end 23 | // up in an infinit loop. 24 | m_time_scheduled = t; 25 | 26 | torrent::this_thread::scheduler()->wait_until(&m_task, t); 27 | } 28 | 29 | void 30 | CommandSchedulerItem::disable() { 31 | m_time_scheduled = std::chrono::microseconds(); 32 | torrent::this_thread::scheduler()->erase(&m_task); 33 | } 34 | 35 | std::chrono::microseconds 36 | CommandSchedulerItem::next_time_scheduled() const { 37 | if (m_interval == 0) 38 | return std::chrono::microseconds(); 39 | 40 | if (m_time_scheduled == std::chrono::microseconds()) 41 | throw torrent::internal_error("CommandSchedulerItem::next_time_scheduled() m_time_scheduled == 0."); 42 | 43 | auto next = m_time_scheduled; 44 | 45 | // This should be done in a non-looping manner. 46 | do { 47 | next += std::chrono::seconds(m_interval); 48 | } while (next <= torrent::utils::ceil_seconds(torrent::this_thread::cached_time())); 49 | 50 | return next; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/rpc/command_scheduler_item.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_COMMAND_SCHEDULER_ITEM_H 2 | #define RTORRENT_COMMAND_SCHEDULER_ITEM_H 3 | 4 | #include "globals.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace rpc { 11 | 12 | class CommandSchedulerItem { 13 | public: 14 | typedef std::function slot_void; 15 | 16 | CommandSchedulerItem(const std::string& key) : m_key(key) {} 17 | ~CommandSchedulerItem(); 18 | 19 | bool is_queued() const { return m_task.is_scheduled(); } 20 | 21 | void enable(std::chrono::microseconds t); 22 | void disable(); 23 | 24 | const std::string& key() const { return m_key; } 25 | torrent::Object& command() { return m_command; } 26 | 27 | // 'interval()' should in the future return some more dynamic values. 28 | uint32_t interval() const { return m_interval; } 29 | void set_interval(uint32_t v) { m_interval = v; } 30 | 31 | std::chrono::microseconds time_scheduled() const { return m_time_scheduled; } 32 | std::chrono::microseconds next_time_scheduled() const; 33 | 34 | slot_void& slot() { return m_task.slot(); } 35 | 36 | private: 37 | CommandSchedulerItem(const CommandSchedulerItem&); 38 | void operator = (const CommandSchedulerItem&); 39 | 40 | std::string m_key; 41 | torrent::Object m_command; 42 | 43 | uint32_t m_interval{}; 44 | std::chrono::microseconds m_time_scheduled; 45 | 46 | torrent::utils::SchedulerEntry m_task; 47 | 48 | // Flags for various things. 49 | }; 50 | 51 | } 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/rpc/exec_file.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_RPC_EXEC_FILE_H 2 | #define RTORRENT_RPC_EXEC_FILE_H 3 | 4 | #include 5 | 6 | namespace rpc { 7 | 8 | class ExecFile { 9 | public: 10 | static constexpr unsigned int max_args = 128; 11 | static constexpr unsigned int buffer_size = 4096; 12 | 13 | static constexpr int flag_expand_tilde = 0x1; 14 | static constexpr int flag_throw = 0x2; 15 | static constexpr int flag_capture = 0x4; 16 | static constexpr int flag_background = 0x8; 17 | 18 | int log_fd() const { return m_log_fd; } 19 | void set_log_fd(int fd) { m_log_fd = fd; } 20 | 21 | int execute(const char* file, char* const* argv, int flags); 22 | torrent::Object execute_object(const torrent::Object& rawArgs, int flags); 23 | 24 | private: 25 | int m_log_fd{-1}; 26 | std::string m_capture; 27 | }; 28 | 29 | } 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/rpc/ip_table_list.h: -------------------------------------------------------------------------------- 1 | // rTorrent - BitTorrent client 2 | // Copyright (C) 2005-2011, Jari Sundell 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | // 18 | // In addition, as a special exception, the copyright holders give 19 | // permission to link the code of portions of this program with the 20 | // OpenSSL library under certain conditions as described in each 21 | // individual source file, and distribute linked combinations 22 | // including the two. 23 | // 24 | // You must obey the GNU General Public License in all respects for 25 | // all of the code used other than OpenSSL. If you modify file(s) 26 | // with this exception, you may extend this exception to your version 27 | // of the file(s), but you are not obligated to do so. If you do not 28 | // wish to do so, delete this exception statement from your version. 29 | // If you delete this exception statement from all source files in the 30 | // program, then also delete it here. 31 | // 32 | // Contact: Jari Sundell 33 | // 34 | // Skomakerveien 33 35 | // 3185 Skoppum, NORWAY 36 | 37 | #ifndef RTORRENT_RPC_IP_TABLE_LISTS_H 38 | #define RTORRENT_RPC_IP_TABLE_LISTS_H 39 | 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | namespace rpc { 47 | 48 | typedef torrent::extents ipv4_table; 49 | 50 | struct ip_table_node { 51 | std::string name; 52 | ipv4_table table; 53 | 54 | bool equal_name(const std::string& str) const { return str == name; } 55 | }; 56 | 57 | class ip_table_list : private std::vector { 58 | public: 59 | typedef std::vector base_type; 60 | 61 | using base_type::iterator; 62 | using base_type::const_iterator; 63 | using base_type::value_type; 64 | 65 | using base_type::begin; 66 | using base_type::end; 67 | 68 | iterator insert(const std::string& name); 69 | iterator find(const std::string& name); 70 | }; 71 | 72 | inline ip_table_list::iterator 73 | ip_table_list::insert(const std::string& name) { 74 | ip_table_node tmp = { name }; 75 | 76 | return base_type::insert(end(), tmp); 77 | } 78 | 79 | inline ip_table_list::iterator 80 | ip_table_list::find(const std::string& name) { 81 | for (iterator itr = begin(), last = end(); itr != last; itr++) 82 | if (itr->equal_name(name)) 83 | return itr; 84 | 85 | return end(); 86 | } 87 | 88 | } 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /src/rpc/jsonrpc.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_RPC_JSONRPC_H 2 | #define RTORRENT_RPC_JSONRPC_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace rpc { 9 | 10 | class JsonRpc { 11 | public: 12 | using slot_write = std::function; 13 | 14 | void initialize() {}; 15 | void cleanup() {}; 16 | 17 | bool process(const char* in_buffer, uint32_t length, slot_write callback); 18 | 19 | void insert_command(const char* name, const char* parm, const char* doc) {}; 20 | }; 21 | 22 | } // namespace rpc 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/rpc/lua.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_LUA_H 2 | #define RTORRENT_LUA_H 3 | 4 | #include "rpc/command.h" 5 | #include 6 | 7 | #ifdef HAVE_LUA 8 | #include 9 | #endif 10 | 11 | namespace rpc { 12 | 13 | class LuaEngine { 14 | public: 15 | static const int flag_string = 0x1; 16 | static const std::string module_name; 17 | 18 | LuaEngine(); 19 | ~LuaEngine(); 20 | 21 | #ifdef HAVE_LUA 22 | // lua_CFunctions 23 | static int lua_init_module(lua_State* l_state); 24 | static int lua_rtorrent_call(lua_State* l_state); 25 | void set_package_preload(); 26 | lua_State* state() { return m_luaState; } 27 | 28 | private: 29 | static std::string search_lua_path(lua_State* l_state); 30 | lua_State* m_luaState; 31 | #endif 32 | }; 33 | 34 | torrent::Object execute_lua(LuaEngine* engine, rpc::target_type target, const torrent::Object& raw_args, int flags); 35 | 36 | #ifdef HAVE_LUA 37 | 38 | int rtorrent_call(lua_State* l_state); 39 | void init_rtorrent_module(lua_State* l_state); 40 | void object_to_lua(lua_State* l_state, torrent::Object const& object); 41 | void check_lua_status(lua_State* l_state, int status); 42 | torrent::Object lua_to_object(lua_State* l_state); 43 | torrent::Object lua_callstack_to_object(lua_State* l_state, int command_flags, rpc::target_type* target, std::function* deleter); 44 | 45 | #endif 46 | 47 | } // namespace rpc 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/rpc/nlohmann/.clang-tidy: -------------------------------------------------------------------------------- 1 | # third-party library, disable all checks in this folder. 2 | Checks: '-*' 3 | -------------------------------------------------------------------------------- /src/rpc/parse_options.h: -------------------------------------------------------------------------------- 1 | // rTorrent - BitTorrent client 2 | // Copyright (C) 2005-2011, Jari Sundell 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | // 18 | // In addition, as a special exception, the copyright holders give 19 | // permission to link the code of portions of this program with the 20 | // OpenSSL library under certain conditions as described in each 21 | // individual source file, and distribute linked combinations 22 | // including the two. 23 | // 24 | // You must obey the GNU General Public License in all respects for 25 | // all of the code used other than OpenSSL. If you modify file(s) 26 | // with this exception, you may extend this exception to your version 27 | // of the file(s), but you are not obligated to do so. If you do not 28 | // wish to do so, delete this exception statement from your version. 29 | // If you delete this exception statement from all source files in the 30 | // program, then also delete it here. 31 | // 32 | // Contact: Jari Sundell 33 | // 34 | // Skomakerveien 33 35 | // 3185 Skoppum, NORWAY 36 | 37 | #ifndef RTORRENT_RPC_PARSE_OPTIONS_H 38 | #define RTORRENT_RPC_PARSE_OPTIONS_H 39 | 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | namespace rpc { 46 | 47 | // If a flag returned by the functor is negative it is treated as a 48 | // negation of the flag. 49 | 50 | typedef std::function parse_option_flag_type; 51 | typedef std::function parse_option_rflag_type; 52 | 53 | int parse_option_flag(const std::string& option, parse_option_flag_type ftor); 54 | int parse_option_flags(const std::string& option, parse_option_flag_type ftor, int flags = int()); 55 | 56 | void parse_option_for_each(const std::string& option, parse_option_flag_type ftor); 57 | 58 | std::string parse_option_print_vector(int flags, const std::vector>& flag_list); 59 | std::string parse_option_print_flags(unsigned int flags, parse_option_rflag_type ftor); 60 | 61 | } 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /src/rpc/scgi.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_RPC_SCGI_H 2 | #define RTORRENT_RPC_SCGI_H 3 | 4 | #include 5 | #include 6 | 7 | #include "rpc/scgi_task.h" 8 | #include "utils/socket_fd.h" 9 | 10 | namespace utils { 11 | class SocketFd; 12 | } 13 | 14 | namespace rpc { 15 | 16 | class SCgi : public torrent::Event { 17 | public: 18 | static const int max_tasks = 100; 19 | 20 | ~SCgi() override; 21 | 22 | const char* type_name() const override { return "scgi"; } 23 | 24 | void open_port(void* sa, unsigned int length, bool dontRoute); 25 | void open_named(const std::string& filename); 26 | 27 | void activate(); 28 | void deactivate(); 29 | 30 | const std::string& path() const { return m_path; } 31 | 32 | int log_fd() const { return m_logFd; } 33 | void set_log_fd(int fd) { m_logFd = fd; } 34 | 35 | void event_read() override; 36 | void event_write() override; 37 | void event_error() override; 38 | 39 | utils::SocketFd& get_fd() { return *reinterpret_cast(&m_fileDesc); } 40 | 41 | private: 42 | void open(void* sa, unsigned int length); 43 | 44 | std::string m_path; 45 | int m_logFd{-1}; 46 | SCgiTask m_task[max_tasks]; 47 | }; 48 | 49 | } 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /src/rpc/scgi_task.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_RPC_SCGI_TASK_H 2 | #define RTORRENT_RPC_SCGI_TASK_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace utils { 9 | class SocketFd; 10 | } 11 | 12 | namespace rpc { 13 | 14 | class SCgi; 15 | 16 | class SCgiTask : public torrent::Event { 17 | public: 18 | static const unsigned int default_buffer_size = 2047; 19 | static const int max_header_size = 2000; 20 | static const int max_content_size = (2 << 23); 21 | 22 | enum ContentType { XML, JSON }; 23 | 24 | SCgiTask() { m_fileDesc = -1; } 25 | 26 | bool is_open() const { return m_fileDesc != -1; } 27 | bool is_available() const { return m_fileDesc == -1; } 28 | 29 | void open(SCgi* parent, int fd); 30 | void close(); 31 | 32 | ContentType content_type() const { return m_content_type; } 33 | 34 | virtual void event_read(); 35 | virtual void event_write(); 36 | virtual void event_error(); 37 | 38 | utils::SocketFd& get_fd() { return *reinterpret_cast(&m_fileDesc); } 39 | 40 | private: 41 | bool detect_content_type(const std::string& content_type); 42 | void realloc_buffer(uint32_t size, const char* buffer, uint32_t bufferSize); 43 | 44 | void receive_call(const char* buffer, uint32_t length); 45 | void receive_write(const char* buffer, uint32_t length); 46 | 47 | SCgi* m_parent; 48 | 49 | std::mutex m_result_mutex; 50 | 51 | char* m_buffer{nullptr}; 52 | char* m_position{nullptr}; 53 | char* m_body{nullptr}; 54 | 55 | unsigned int m_buffer_size{0}; 56 | 57 | ContentType m_content_type{ XML }; 58 | }; 59 | 60 | } 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /src/rpc/xmlrpc.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include "xmlrpc.h" 4 | 5 | #include "parse_commands.h" 6 | 7 | #include 8 | 9 | namespace rpc { 10 | 11 | #ifndef HAVE_XMLRPC_C 12 | #ifndef HAVE_XMLRPC_TINYXML2 13 | 14 | void XmlRpc::initialize() {} 15 | void XmlRpc::cleanup() {} 16 | 17 | void XmlRpc::insert_command(const char*, const char*, const char*) {} 18 | void XmlRpc::set_dialect(int) {} 19 | 20 | bool XmlRpc::process(const char*, uint32_t, slot_write) { return false; } 21 | 22 | int64_t XmlRpc::size_limit() { return 0; } 23 | void XmlRpc::set_size_limit(uint64_t size) {} 24 | 25 | bool XmlRpc::is_valid() const { return false; } 26 | 27 | #endif 28 | #endif 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/rpc/xmlrpc.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_RPC_XMLRPC_H 2 | #define RTORRENT_RPC_XMLRPC_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "command.h" 10 | #include "scgi_task.h" 11 | 12 | namespace core { 13 | class Download; 14 | } 15 | 16 | namespace rpc { 17 | 18 | class XmlRpc { 19 | public: 20 | typedef std::function slot_download; 21 | typedef std::function slot_file; 22 | typedef std::function slot_tracker; 23 | typedef std::function slot_peer; 24 | typedef std::function slot_write; 25 | 26 | static const int dialect_generic = 0; 27 | static const int dialect_i8 = 1; 28 | static const int dialect_apache = 2; 29 | 30 | // These need to match CommandMap type values. 31 | static const int call_generic = 0; 32 | static const int call_any = 1; 33 | static const int call_download = 2; 34 | static const int call_peer = 3; 35 | static const int call_tracker = 4; 36 | static const int call_file = 5; 37 | static const int call_file_itr = 6; 38 | 39 | static void object_to_target(const torrent::Object& obj, int callFlags, rpc::target_type* target); 40 | 41 | bool is_valid() const; 42 | 43 | void initialize(); 44 | void cleanup(); 45 | 46 | bool process(const char* inBuffer, uint32_t length, slot_write slotWrite); 47 | 48 | void insert_command(const char* name, const char* parm, const char* doc); 49 | 50 | int dialect() { return m_dialect; } 51 | void set_dialect(int dialect); 52 | 53 | slot_download& slot_find_download() { return m_slotFindDownload; } 54 | slot_file& slot_find_file() { return m_slotFindFile; } 55 | slot_tracker& slot_find_tracker() { return m_slotFindTracker; } 56 | slot_peer& slot_find_peer() { return m_slotFindPeer; } 57 | 58 | int64_t size_limit(); 59 | void set_size_limit(uint64_t size); 60 | 61 | private: 62 | slot_download m_slotFindDownload; 63 | slot_file m_slotFindFile; 64 | slot_tracker m_slotFindTracker; 65 | slot_peer m_slotFindPeer; 66 | 67 | // Only used by xmlrpc-c 68 | void* m_env{}; 69 | void* m_registry{}; 70 | 71 | int m_dialect{dialect_i8}; 72 | 73 | // Only used by tinyxml2 74 | bool m_isValid; 75 | uint64_t m_sizeLimit{SCgiTask::max_content_size}; 76 | 77 | }; 78 | 79 | } 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /src/signal_handler.h: -------------------------------------------------------------------------------- 1 | // rTorrent - BitTorrent client 2 | // Copyright (C) 2005-2011, Jari Sundell 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | // 18 | // In addition, as a special exception, the copyright holders give 19 | // permission to link the code of portions of this program with the 20 | // OpenSSL library under certain conditions as described in each 21 | // individual source file, and distribute linked combinations 22 | // including the two. 23 | // 24 | // You must obey the GNU General Public License in all respects for 25 | // all of the code used other than OpenSSL. If you modify file(s) 26 | // with this exception, you may extend this exception to your version 27 | // of the file(s), but you are not obligated to do so. If you do not 28 | // wish to do so, delete this exception statement from your version. 29 | // If you delete this exception statement from all source files in the 30 | // program, then also delete it here. 31 | // 32 | // Contact: Jari Sundell 33 | // 34 | // Skomakerveien 33 35 | // 3185 Skoppum, NORWAY 36 | 37 | #ifndef RTORRENT_SIGNAL_HANDLER_H 38 | #define RTORRENT_SIGNAL_HANDLER_H 39 | 40 | #include 41 | #include 42 | 43 | class SignalHandler { 44 | public: 45 | typedef std::function slot_void; 46 | 47 | // typedef void (*handler_slot)(int, siginfo_t *info, ucontext_t *uap); 48 | typedef void (*handler_slot)(int, siginfo_t*, void*); 49 | 50 | #ifdef NSIG 51 | static const unsigned int HIGHEST_SIGNAL = NSIG; 52 | #else 53 | // Let's be on the safe side. 54 | static const unsigned int HIGHEST_SIGNAL = 32; 55 | #endif 56 | 57 | static void set_default(unsigned int signum); 58 | static void set_ignore(unsigned int signum); 59 | static void set_handler(unsigned int signum, slot_void slot); 60 | 61 | static void set_sigaction_handler(unsigned int signum, handler_slot slot); 62 | 63 | static const char* as_string(unsigned int signum); 64 | 65 | private: 66 | static void caught(int signum); 67 | 68 | static slot_void m_handlers[HIGHEST_SIGNAL]; 69 | }; 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /src/thread_worker.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include "thread_worker.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "globals.h" 12 | #include "control.h" 13 | #include "core/manager.h" 14 | #include "rpc/scgi.h" 15 | #include "rpc/parse_commands.h" 16 | 17 | ThreadWorker::~ThreadWorker() = default; 18 | 19 | void 20 | ThreadWorker::init_thread() { 21 | m_state = STATE_INITIALIZED; 22 | } 23 | 24 | void 25 | ThreadWorker::cleanup_thread() { 26 | if (m_scgi != nullptr) 27 | m_scgi.load()->deactivate(); 28 | } 29 | 30 | bool 31 | ThreadWorker::set_scgi(rpc::SCgi* scgi) { 32 | rpc::SCgi* expected = nullptr; 33 | 34 | if (!m_scgi.compare_exchange_strong(expected, scgi)) 35 | return false; 36 | 37 | change_rpc_log(); 38 | 39 | callback(nullptr, [this]() { 40 | if (m_scgi == NULL) 41 | throw torrent::internal_error("Tried to start SCGI but object was not present."); 42 | 43 | m_scgi.load()->activate(); 44 | }); 45 | 46 | return true; 47 | } 48 | 49 | void 50 | ThreadWorker::set_rpc_log(const std::string& filename) { 51 | callback(nullptr, [this, filename]() { 52 | m_rpc_log_filename = filename; 53 | change_rpc_log(); 54 | }); 55 | } 56 | 57 | void 58 | ThreadWorker::change_rpc_log() { 59 | if (scgi() == NULL) 60 | return; 61 | 62 | if (scgi()->log_fd() != -1) { 63 | ::close(scgi()->log_fd()); 64 | scgi()->set_log_fd(-1); 65 | control->core()->push_log("Closed RPC log."); 66 | } 67 | 68 | if (m_rpc_log_filename.empty()) 69 | return; 70 | 71 | scgi()->set_log_fd(open(rak::path_expand(m_rpc_log_filename).c_str(), O_WRONLY | O_APPEND | O_CREAT, 0644)); 72 | 73 | if (scgi()->log_fd() == -1) { 74 | control->core()->push_log_std("Could not open RPC log file '" + m_rpc_log_filename + "'."); 75 | return; 76 | } 77 | 78 | control->core()->push_log_std("Logging RPC events to '" + m_rpc_log_filename + "'."); 79 | } 80 | 81 | void 82 | ThreadWorker::call_events() { 83 | if ((m_flags & flag_do_shutdown)) { 84 | if ((m_flags & flag_did_shutdown)) 85 | throw torrent::internal_error("Already trigged shutdown."); 86 | 87 | m_flags |= flag_did_shutdown; 88 | throw torrent::shutdown_exception(); 89 | } 90 | 91 | process_callbacks(); 92 | } 93 | 94 | std::chrono::microseconds 95 | ThreadWorker::next_timeout() { 96 | return std::chrono::microseconds(10min); 97 | } 98 | -------------------------------------------------------------------------------- /src/thread_worker.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_THREAD_WORKER_H 2 | #define RTORRENT_THREAD_WORKER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace rpc { 9 | class SCgi; 10 | } 11 | 12 | class ThreadWorker : public torrent::utils::Thread { 13 | public: 14 | ThreadWorker() = default; 15 | ~ThreadWorker(); 16 | 17 | const char* name() const override { return "rtorrent scgi"; } 18 | 19 | void init_thread() override; 20 | void cleanup_thread() override; 21 | 22 | rpc::SCgi* scgi() { return m_scgi; } 23 | bool set_scgi(rpc::SCgi* scgi); 24 | 25 | void set_rpc_log(const std::string& filename); 26 | 27 | private: 28 | void task_touch_log(); 29 | void change_rpc_log(); 30 | 31 | void call_events() override; 32 | std::chrono::microseconds next_timeout() override; 33 | 34 | std::atomic m_scgi{nullptr}; 35 | std::string m_rpc_log_filename; 36 | }; 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/ui/element_base.cc: -------------------------------------------------------------------------------- 1 | // rTorrent - BitTorrent client 2 | // Copyright (C) 2005-2011, Jari Sundell 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | // 18 | // In addition, as a special exception, the copyright holders give 19 | // permission to link the code of portions of this program with the 20 | // OpenSSL library under certain conditions as described in each 21 | // individual source file, and distribute linked combinations 22 | // including the two. 23 | // 24 | // You must obey the GNU General Public License in all respects for 25 | // all of the code used other than OpenSSL. If you modify file(s) 26 | // with this exception, you may extend this exception to your version 27 | // of the file(s), but you are not obligated to do so. If you do not 28 | // wish to do so, delete this exception statement from your version. 29 | // If you delete this exception statement from all source files in the 30 | // program, then also delete it here. 31 | // 32 | // Contact: Jari Sundell 33 | // 34 | // Skomakerveien 33 35 | // 3185 Skoppum, NORWAY 36 | 37 | #include "config.h" 38 | 39 | #include 40 | 41 | #include "display/frame.h" 42 | #include "display/window.h" 43 | 44 | #include "element_base.h" 45 | 46 | namespace ui { 47 | 48 | void 49 | ElementBase::mark_dirty() { 50 | if (is_active()) 51 | m_frame->window()->mark_dirty(); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/ui/element_base.h: -------------------------------------------------------------------------------- 1 | // rTorrent - BitTorrent client 2 | // Copyright (C) 2005-2011, Jari Sundell 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | // 18 | // In addition, as a special exception, the copyright holders give 19 | // permission to link the code of portions of this program with the 20 | // OpenSSL library under certain conditions as described in each 21 | // individual source file, and distribute linked combinations 22 | // including the two. 23 | // 24 | // You must obey the GNU General Public License in all respects for 25 | // all of the code used other than OpenSSL. If you modify file(s) 26 | // with this exception, you may extend this exception to your version 27 | // of the file(s), but you are not obligated to do so. If you do not 28 | // wish to do so, delete this exception statement from your version. 29 | // If you delete this exception statement from all source files in the 30 | // program, then also delete it here. 31 | // 32 | // Contact: Jari Sundell 33 | // 34 | // Skomakerveien 33 35 | // 3185 Skoppum, NORWAY 36 | 37 | #ifndef RTORRENT_UI_ELEMENT_BASE_H 38 | #define RTORRENT_UI_ELEMENT_BASE_H 39 | 40 | #include "input/bindings.h" 41 | 42 | namespace display { 43 | class Frame; 44 | class Window; 45 | } 46 | 47 | namespace ui { 48 | 49 | class ElementBase { 50 | public: 51 | typedef std::function slot_type; 52 | 53 | virtual ~ElementBase() = default; 54 | 55 | bool is_active() const { return m_frame != NULL; } 56 | 57 | input::Bindings& bindings() { return m_bindings; } 58 | 59 | virtual void activate(display::Frame* frame, bool focus = true) = 0; 60 | virtual void disable() = 0; 61 | 62 | void slot_exit(const slot_type& s) { m_slot_exit = s; } 63 | 64 | void mark_dirty(); 65 | 66 | protected: 67 | display::Frame* m_frame{}; 68 | bool m_focus{}; 69 | 70 | input::Bindings m_bindings; 71 | slot_type m_slot_exit; 72 | }; 73 | 74 | } 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /src/ui/element_chunks_seen.h: -------------------------------------------------------------------------------- 1 | // rTorrent - BitTorrent client 2 | // Copyright (C) 2005-2011, Jari Sundell 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | // 18 | // In addition, as a special exception, the copyright holders give 19 | // permission to link the code of portions of this program with the 20 | // OpenSSL library under certain conditions as described in each 21 | // individual source file, and distribute linked combinations 22 | // including the two. 23 | // 24 | // You must obey the GNU General Public License in all respects for 25 | // all of the code used other than OpenSSL. If you modify file(s) 26 | // with this exception, you may extend this exception to your version 27 | // of the file(s), but you are not obligated to do so. If you do not 28 | // wish to do so, delete this exception statement from your version. 29 | // If you delete this exception statement from all source files in the 30 | // program, then also delete it here. 31 | // 32 | // Contact: Jari Sundell 33 | // 34 | // Skomakerveien 33 35 | // 3185 Skoppum, NORWAY 36 | 37 | #ifndef RTORRENT_UI_ELEMENT_CHUNKS_SEEN_H 38 | #define RTORRENT_UI_ELEMENT_CHUNKS_SEEN_H 39 | 40 | #include "core/download.h" 41 | 42 | #include "element_base.h" 43 | 44 | class Control; 45 | 46 | namespace display { 47 | class WindowDownloadChunksSeen; 48 | } 49 | 50 | namespace ui { 51 | 52 | class ElementChunksSeen : public ElementBase { 53 | public: 54 | typedef display::WindowDownloadChunksSeen WChunksSeen; 55 | 56 | ElementChunksSeen(core::Download* d); 57 | 58 | void activate(display::Frame* frame, bool focus = true); 59 | void disable(); 60 | 61 | display::Window* window(); 62 | 63 | private: 64 | // void receive_disable(); 65 | void receive_next(); 66 | void receive_prev(); 67 | void receive_pagenext(); 68 | void receive_pageprev(); 69 | 70 | core::Download* m_download; 71 | WChunksSeen* m_window{}; 72 | 73 | unsigned int m_focus{}; 74 | }; 75 | 76 | } 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /src/ui/element_download_list.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_UI_ELEMENT_DOWNLOAD_LIST_H 2 | #define RTORRENT_UI_ELEMENT_DOWNLOAD_LIST_H 3 | 4 | #include "display/window_download_list.h" 5 | 6 | #include "element_base.h" 7 | 8 | class Control; 9 | 10 | namespace core { 11 | class View; 12 | } 13 | 14 | namespace ui { 15 | 16 | class ElementDownloadList : public ElementBase { 17 | public: 18 | typedef display::WindowDownloadList WDownloadList; 19 | 20 | ElementDownloadList(); 21 | 22 | void activate(display::Frame* frame, bool focus = true); 23 | void disable(); 24 | 25 | core::View* view() { return m_view; } 26 | void set_view(core::View* l); 27 | 28 | void receive_command(const char* cmd); 29 | 30 | void receive_next(); 31 | void receive_prev(); 32 | 33 | int page_size(); 34 | void receive_pagenext(); 35 | void receive_pageprev(); 36 | 37 | void receive_home(); 38 | void receive_end(); 39 | 40 | void receive_stop_download(); 41 | void receive_close_download(); 42 | 43 | void receive_next_priority(); 44 | void receive_prev_priority(); 45 | 46 | void receive_cycle_throttle(); 47 | 48 | void receive_change_view(const std::string& name); 49 | 50 | void toggle_layout(); 51 | 52 | private: 53 | WDownloadList* m_window{}; 54 | core::View* m_view{}; 55 | }; 56 | 57 | } // namespace ui 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /src/ui/element_log_complete.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "display/frame.h" 8 | #include "display/manager.h" 9 | #include "display/window_log_complete.h" 10 | #include "input/manager.h" 11 | 12 | #include "control.h" 13 | #include "element_log_complete.h" 14 | 15 | namespace ui { 16 | 17 | ElementLogComplete::ElementLogComplete(torrent::log_buffer* l) : 18 | m_log(l) { 19 | 20 | unsigned int signal_index = torrent::main_thread::thread()->signal_bitfield()->add_signal(std::bind(&ElementLogComplete::received_update, this)); 21 | 22 | m_log->lock_and_set_update_slot([signal_index]() { 23 | torrent::main_thread::thread()->send_event_signal(signal_index, false); 24 | }); 25 | } 26 | 27 | void 28 | ElementLogComplete::activate(display::Frame* frame, [[maybe_unused]] bool focus) { 29 | if (is_active()) 30 | throw torrent::internal_error("ui::ElementLogComplete::activate(...) is_active()."); 31 | 32 | control->input()->push_back(&m_bindings); 33 | 34 | m_window = new WLogComplete(m_log); 35 | m_window->set_active(true); 36 | 37 | m_frame = frame; 38 | m_frame->initialize_window(m_window); 39 | } 40 | 41 | void 42 | ElementLogComplete::disable() { 43 | if (!is_active()) 44 | throw torrent::internal_error("ui::ElementLogComplete::disable(...) !is_active()."); 45 | 46 | control->input()->erase(&m_bindings); 47 | 48 | m_frame->clear(); 49 | m_frame = NULL; 50 | 51 | delete m_window; 52 | m_window = NULL; 53 | } 54 | 55 | display::Window* 56 | ElementLogComplete::window() { 57 | return m_window; 58 | } 59 | 60 | void 61 | ElementLogComplete::received_update() { 62 | if (m_window != NULL) 63 | m_window->mark_dirty(); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/ui/element_log_complete.h: -------------------------------------------------------------------------------- 1 | // rTorrent - BitTorrent client 2 | // Copyright (C) 2005-2011, Jari Sundell 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | // 18 | // In addition, as a special exception, the copyright holders give 19 | // permission to link the code of portions of this program with the 20 | // OpenSSL library under certain conditions as described in each 21 | // individual source file, and distribute linked combinations 22 | // including the two. 23 | // 24 | // You must obey the GNU General Public License in all respects for 25 | // all of the code used other than OpenSSL. If you modify file(s) 26 | // with this exception, you may extend this exception to your version 27 | // of the file(s), but you are not obligated to do so. If you do not 28 | // wish to do so, delete this exception statement from your version. 29 | // If you delete this exception statement from all source files in the 30 | // program, then also delete it here. 31 | // 32 | // Contact: Jari Sundell 33 | // 34 | // Skomakerveien 33 35 | // 3185 Skoppum, NORWAY 36 | 37 | #ifndef RTORRENT_UI_ELEMENT_LOG_COMPLETE_H 38 | #define RTORRENT_UI_ELEMENT_LOG_COMPLETE_H 39 | 40 | #include 41 | 42 | #include "element_base.h" 43 | 44 | class Control; 45 | 46 | namespace display { 47 | class WindowLogComplete; 48 | } 49 | 50 | namespace ui { 51 | 52 | class ElementLogComplete : public ElementBase { 53 | public: 54 | typedef display::WindowLogComplete WLogComplete; 55 | 56 | ElementLogComplete(torrent::log_buffer* l); 57 | 58 | void activate(display::Frame* frame, bool focus = true); 59 | void disable(); 60 | 61 | display::Window* window(); 62 | 63 | private: 64 | void received_update(); 65 | 66 | WLogComplete* m_window{}; 67 | 68 | torrent::log_buffer* m_log; 69 | }; 70 | 71 | } 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /src/ui/element_tracker_list.h: -------------------------------------------------------------------------------- 1 | // rTorrent - BitTorrent client 2 | // Copyright (C) 2005-2011, Jari Sundell 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | // 18 | // In addition, as a special exception, the copyright holders give 19 | // permission to link the code of portions of this program with the 20 | // OpenSSL library under certain conditions as described in each 21 | // individual source file, and distribute linked combinations 22 | // including the two. 23 | // 24 | // You must obey the GNU General Public License in all respects for 25 | // all of the code used other than OpenSSL. If you modify file(s) 26 | // with this exception, you may extend this exception to your version 27 | // of the file(s), but you are not obligated to do so. If you do not 28 | // wish to do so, delete this exception statement from your version. 29 | // If you delete this exception statement from all source files in the 30 | // program, then also delete it here. 31 | // 32 | // Contact: Jari Sundell 33 | // 34 | // Skomakerveien 33 35 | // 3185 Skoppum, NORWAY 36 | 37 | #ifndef RTORRENT_UI_ELEMENT_TRACKER_LIST_H 38 | #define RTORRENT_UI_ELEMENT_TRACKER_LIST_H 39 | 40 | #include "core/download.h" 41 | 42 | #include "element_base.h" 43 | 44 | class Control; 45 | 46 | namespace display { 47 | class WindowTrackerList; 48 | } 49 | 50 | namespace ui { 51 | 52 | class ElementTrackerList : public ElementBase { 53 | public: 54 | typedef display::WindowTrackerList WTrackerList; 55 | 56 | ElementTrackerList(core::Download* d); 57 | 58 | void activate(display::Frame* frame, bool focus = true); 59 | void disable(); 60 | 61 | display::Window* window(); 62 | 63 | private: 64 | void receive_next(); 65 | void receive_prev(); 66 | 67 | void receive_disable(); 68 | 69 | void receive_cycle_group(); 70 | 71 | core::Download* m_download; 72 | WTrackerList* m_window{}; 73 | 74 | // Change to unsigned, please. 75 | unsigned int m_focus{}; 76 | }; 77 | 78 | } 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /src/ui/element_transfer_list.h: -------------------------------------------------------------------------------- 1 | // rTorrent - BitTorrent client 2 | // Copyright (C) 2005-2011, Jari Sundell 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | // 18 | // In addition, as a special exception, the copyright holders give 19 | // permission to link the code of portions of this program with the 20 | // OpenSSL library under certain conditions as described in each 21 | // individual source file, and distribute linked combinations 22 | // including the two. 23 | // 24 | // You must obey the GNU General Public License in all respects for 25 | // all of the code used other than OpenSSL. If you modify file(s) 26 | // with this exception, you may extend this exception to your version 27 | // of the file(s), but you are not obligated to do so. If you do not 28 | // wish to do so, delete this exception statement from your version. 29 | // If you delete this exception statement from all source files in the 30 | // program, then also delete it here. 31 | // 32 | // Contact: Jari Sundell 33 | // 34 | // Skomakerveien 33 35 | // 3185 Skoppum, NORWAY 36 | 37 | #ifndef RTORRENT_UI_ELEMENT_TRANSFER_LIST_H 38 | #define RTORRENT_UI_ELEMENT_TRANSFER_LIST_H 39 | 40 | #include "core/download.h" 41 | 42 | #include "element_base.h" 43 | 44 | class Control; 45 | 46 | namespace display { 47 | class WindowDownloadTransferList; 48 | } 49 | 50 | namespace ui { 51 | 52 | class ElementTransferList : public ElementBase { 53 | public: 54 | typedef display::WindowDownloadTransferList WTransferList; 55 | 56 | ElementTransferList(core::Download* d); 57 | 58 | void activate(display::Frame* frame, bool focus = true); 59 | void disable(); 60 | 61 | display::Window* window(); 62 | 63 | private: 64 | // void receive_disable(); 65 | void receive_next(); 66 | void receive_prev(); 67 | void receive_pagenext(); 68 | void receive_pageprev(); 69 | 70 | core::Download* m_download; 71 | WTransferList* m_window{}; 72 | 73 | unsigned int m_focus{}; 74 | }; 75 | 76 | } 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /src/utils/base64.cc: -------------------------------------------------------------------------------- 1 | #include "base64.h" 2 | 3 | #include 4 | 5 | namespace utils { 6 | 7 | std::string 8 | remove_newlines(const std::string& str) { 9 | std::string result; 10 | for (auto& itr : str) { 11 | if (itr != '\n' || itr != '\n') 12 | result.push_back(itr); 13 | } 14 | return result; 15 | } 16 | 17 | // Modified from the public domain code in 18 | // https://en.wikibooks.org/wiki/Algorithm_Implementation/Miscellaneous/Base64#C++_2 19 | constexpr static char base64_pad_character = '='; 20 | 21 | std::string 22 | decode_base64(const std::string& input) { 23 | if (input.length() % 4) // Sanity check 24 | throw torrent::input_error("Invalid base64."); 25 | size_t padding = 0; 26 | if (input.length()) { 27 | if (input[input.length() - 1] == base64_pad_character) 28 | padding++; 29 | if (input[input.length() - 2] == base64_pad_character) 30 | padding++; 31 | } 32 | // Setup a vector to hold the result 33 | std::string decodedBytes; 34 | decodedBytes.reserve(((input.length() / 4) * 3) - padding); 35 | long temp = 0; // Holds decoded quanta 36 | std::string::const_iterator cursor = input.begin(); 37 | while (cursor < input.end()) { 38 | for (size_t quantumPosition = 0; quantumPosition < 4; quantumPosition++) { 39 | temp <<= 6; 40 | if (*cursor >= 0x41 && *cursor <= 0x5A) // This area will need tweaking if 41 | temp |= *cursor - 0x41; // you are using an alternate alphabet 42 | else if (*cursor >= 0x61 && *cursor <= 0x7A) 43 | temp |= *cursor - 0x47; 44 | else if (*cursor >= 0x30 && *cursor <= 0x39) 45 | temp |= *cursor + 0x04; 46 | else if (*cursor == 0x2B) 47 | temp |= 0x3E; // change to 0x2D for URL alphabet 48 | else if (*cursor == 0x2F) 49 | temp |= 0x3F; // change to 0x5F for URL alphabet 50 | else if (*cursor == base64_pad_character) // pad 51 | { 52 | switch (input.end() - cursor) { 53 | case 1: // One pad character 54 | decodedBytes.push_back((temp >> 16) & 0x000000FF); 55 | decodedBytes.push_back((temp >> 8) & 0x000000FF); 56 | return decodedBytes; 57 | case 2: // Two pad characters 58 | decodedBytes.push_back((temp >> 10) & 0x000000FF); 59 | return decodedBytes; 60 | default: 61 | throw torrent::input_error("Invalid padding in base64."); 62 | } 63 | } else 64 | throw torrent::input_error("Invalid character in base64."); 65 | cursor++; 66 | } 67 | decodedBytes.push_back((temp >> 16) & 0x000000FF); 68 | decodedBytes.push_back((temp >> 8) & 0x000000FF); 69 | decodedBytes.push_back((temp) & 0x000000FF); 70 | } 71 | return decodedBytes; 72 | } 73 | } // namespace utils 74 | -------------------------------------------------------------------------------- /src/utils/base64.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_UTILS_BASE64_H 2 | #define RTORRENT_UTILS_BASE64_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace utils { 9 | 10 | std::string remove_newlines(const std::string& str); 11 | std::string decode_base64(const std::string& input); 12 | 13 | } // namespace utils 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/utils/file_status_cache.h: -------------------------------------------------------------------------------- 1 | // rTorrent - BitTorrent client 2 | // Copyright (C) 2005-2011, Jari Sundell 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | // 18 | // In addition, as a special exception, the copyright holders give 19 | // permission to link the code of portions of this program with the 20 | // OpenSSL library under certain conditions as described in each 21 | // individual source file, and distribute linked combinations 22 | // including the two. 23 | // 24 | // You must obey the GNU General Public License in all respects for 25 | // all of the code used other than OpenSSL. If you modify file(s) 26 | // with this exception, you may extend this exception to your version 27 | // of the file(s), but you are not obligated to do so. If you do not 28 | // wish to do so, delete this exception statement from your version. 29 | // If you delete this exception statement from all source files in the 30 | // program, then also delete it here. 31 | // 32 | // Contact: Jari Sundell 33 | // 34 | // Skomakerveien 33 35 | // 3185 Skoppum, NORWAY 36 | 37 | #ifndef RTORRENT_UTILS_FILE_STATUS_CACHE_H 38 | #define RTORRENT_UTILS_FILE_STATUS_CACHE_H 39 | 40 | #include 41 | #include 42 | 43 | namespace utils { 44 | 45 | struct file_status { 46 | int m_flags; 47 | uint32_t m_mtime; 48 | }; 49 | 50 | class FileStatusCache : public std::map { 51 | public: 52 | typedef std::map base_type; 53 | 54 | using base_type::iterator; 55 | using base_type::const_iterator; 56 | using base_type::reverse_iterator; 57 | using base_type::const_reverse_iterator; 58 | using base_type::value_type; 59 | 60 | using base_type::begin; 61 | using base_type::end; 62 | using base_type::rbegin; 63 | using base_type::rend; 64 | 65 | using base_type::empty; 66 | using base_type::size; 67 | 68 | using base_type::erase; 69 | 70 | // static int flag_ 71 | 72 | // Insert and return true if the entry does not exist or the new 73 | // file's mtime is more recent. 74 | bool insert(const std::string& path, int flags); 75 | 76 | // Add a function for pruning a sorted list of paths. 77 | 78 | // Function for pruning entries that no longer points to a file, or 79 | // has a different mtime. 80 | void prune(); 81 | }; 82 | 83 | } 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /src/utils/functional.h: -------------------------------------------------------------------------------- 1 | #ifndef RTORRENT_UTILS_FUNCTIONAL_H 2 | #define RTORRENT_UTILS_FUNCTIONAL_H 3 | 4 | #include 5 | 6 | namespace utils { 7 | 8 | // Create a class that calls a std::function when returning or exiting a scope. 9 | class scope_guard { 10 | public: 11 | scope_guard(std::function on_exit_scope) : m_on_exit_scope(on_exit_scope) {} 12 | ~scope_guard() { m_on_exit_scope(); } 13 | 14 | private: 15 | std::function m_on_exit_scope; 16 | }; 17 | 18 | } // namespace utils 19 | 20 | #endif 21 | 22 | -------------------------------------------------------------------------------- /src/utils/lockfile.h: -------------------------------------------------------------------------------- 1 | // rTorrent - BitTorrent client 2 | // Copyright (C) 2005-2011, Jari Sundell 3 | // 4 | // This program is free software; you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation; either version 2 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | // 18 | // In addition, as a special exception, the copyright holders give 19 | // permission to link the code of portions of this program with the 20 | // OpenSSL library under certain conditions as described in each 21 | // individual source file, and distribute linked combinations 22 | // including the two. 23 | // 24 | // You must obey the GNU General Public License in all respects for 25 | // all of the code used other than OpenSSL. If you modify file(s) 26 | // with this exception, you may extend this exception to your version 27 | // of the file(s), but you are not obligated to do so. If you do not 28 | // wish to do so, delete this exception statement from your version. 29 | // If you delete this exception statement from all source files in the 30 | // program, then also delete it here. 31 | // 32 | // Contact: Jari Sundell 33 | // 34 | // Skomakerveien 33 35 | // 3185 Skoppum, NORWAY 36 | 37 | // A simple, and not guaranteed atomic, lockfile implementation. It 38 | // saves the hostname and pid in the lock file, which may be accessed 39 | // by Lockfile::locked_by(). If the path is an empty string then no 40 | // lockfile will be created when Lockfile::try_lock() is called, still 41 | // it will set the locked state of the Lockfile instance. 42 | 43 | #ifndef RTORRENT_UTILS_LOCKFILE_H 44 | #define RTORRENT_UTILS_LOCKFILE_H 45 | 46 | #include 47 | #include 48 | 49 | namespace utils { 50 | 51 | class Lockfile { 52 | public: 53 | typedef std::pair process_type; 54 | 55 | bool is_locked() const { return m_locked; } 56 | bool is_stale(); 57 | 58 | // If the path is empty no lock file will be created, although 59 | // is_locked() will return true. 60 | bool try_lock(); 61 | bool unlock(); 62 | 63 | const std::string& path() const { return m_path; } 64 | void set_path(const std::string& path) { m_path = path; } 65 | 66 | std::string locked_by_as_string() const; 67 | process_type locked_by() const; 68 | 69 | private: 70 | std::string m_path; 71 | bool m_locked{}; 72 | }; 73 | 74 | } 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /test/Makefile.am: -------------------------------------------------------------------------------- 1 | TESTS = \ 2 | rtorrent_Test_Rpc \ 3 | rtorrent_Test_Src 4 | 5 | check_PROGRAMS = $(TESTS) 6 | 7 | rtorrent_Test_LDADD = \ 8 | ../src/libsub_root.a 9 | 10 | rtorrent_Test_Rpc_LDADD = $(rtorrent_Test_LDADD) 11 | rtorrent_Test_Src_LDADD = $(rtorrent_Test_LDADD) 12 | 13 | rtorrent_Test_Common = \ 14 | main.cc \ 15 | \ 16 | helpers/assert.h \ 17 | helpers/mock_compare.h \ 18 | helpers/mock_function.cc \ 19 | helpers/mock_function.h \ 20 | helpers/progress_listener.cc \ 21 | helpers/progress_listener.h \ 22 | helpers/protectors.cc \ 23 | helpers/protectors.h \ 24 | helpers/test_fixture.cc \ 25 | helpers/test_fixture.h \ 26 | helpers/test_main_thread.cc \ 27 | helpers/test_main_thread.h \ 28 | helpers/test_thread.cc \ 29 | helpers/test_thread.h \ 30 | helpers/test_utils.h \ 31 | helpers/utils.h 32 | 33 | rtorrent_Test_Rpc_SOURCES = $(rtorrent_Test_Common) \ 34 | rpc/test_command.cc \ 35 | rpc/test_command.h \ 36 | rpc/test_command_map.cc \ 37 | rpc/test_command_map.h \ 38 | rpc/test_jsonrpc.cc \ 39 | rpc/test_jsonrpc.h \ 40 | rpc/test_xmlrpc.cc \ 41 | rpc/test_xmlrpc.h \ 42 | rpc/test_command_slot.cc \ 43 | rpc/test_command_slot.h \ 44 | rpc/test_object_storage.cc \ 45 | rpc/test_object_storage.h \ 46 | rpc/test_parse_options.cc \ 47 | rpc/test_parse_options.h 48 | 49 | rtorrent_Test_Src_SOURCES = $(rtorrent_Test_Common) \ 50 | src/test_command_dynamic.cc \ 51 | src/test_command_dynamic.h 52 | 53 | rtorrent_Test_Rpc_CXXFLAGS = $(CPPUNIT_CFLAGS) 54 | rtorrent_Test_Rpc_LDFLAGS = $(CPPUNIT_LIBS) -ldl 55 | rtorrent_Test_Src_CXXFLAGS = $(CPPUNIT_CFLAGS) 56 | rtorrent_Test_Src_LDFLAGS = $(CPPUNIT_LIBS) -ldl 57 | 58 | AM_CPPFLAGS = -I$(srcdir) -I$(top_srcdir) -I$(top_srcdir)/src 59 | -------------------------------------------------------------------------------- /test/helpers/assert.h: -------------------------------------------------------------------------------- 1 | #ifndef HELPERS_ASSERT_H 2 | #define HELPERS_ASSERT_H 3 | 4 | #define ASSERT_CATCH_INPUT_ERROR(some_code) \ 5 | try { some_code; CPPUNIT_ASSERT("torrent::input_error not caught" && false); } catch (torrent::input_error& e) { } 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /test/helpers/progress_listener.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include "progress_listener.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "torrent/utils/log.h" 11 | #include "torrent/utils/log_buffer.h" 12 | 13 | static std::string 14 | get_test_path(const test_list_type& tl) { 15 | if (tl.size() < 2) 16 | return ""; 17 | 18 | return std::accumulate(std::next(tl.begin()), std::prev(tl.end()), std::string(), [](std::string result, CppUnit::Test* test) { 19 | return std::move(result) + test->getName() + "::"; 20 | }); 21 | } 22 | 23 | void 24 | progress_listener::startTest(CppUnit::Test *test) { 25 | std::cout << get_test_path(m_test_path) << test->getName() << std::flush; 26 | 27 | torrent::log_cleanup(); 28 | 29 | m_last_test_failed = false; 30 | m_current_log_buffer = torrent::log_open_log_buffer("test_output"); 31 | } 32 | 33 | void 34 | progress_listener::addFailure(const CppUnit::TestFailure &failure) { 35 | // AddFailure is called for parent test suits, so only deal with leafs. 36 | if (m_current_log_buffer == nullptr) 37 | return; 38 | 39 | std::cout << " : " << (failure.isError() ? "error" : "assertion") << std::flush; 40 | 41 | m_last_test_failed = true; 42 | m_failures.push_back(failure_type{ failure.failedTestName(), std::move(m_current_log_buffer) }); 43 | } 44 | 45 | void 46 | progress_listener::endTest(CppUnit::Test *test) { 47 | std::cout << (m_last_test_failed ? "" : " : OK") << std::endl; 48 | 49 | m_current_log_buffer.reset(); 50 | torrent::log_cleanup(); 51 | } 52 | 53 | void 54 | progress_listener::startSuite(CppUnit::Test *suite) { 55 | m_test_path.push_back(suite); 56 | 57 | if (suite->countTestCases() > 0) 58 | std::cout << std::endl << get_test_path(m_test_path) << suite->getName() << ":" << std::endl; 59 | } 60 | 61 | void 62 | progress_listener::endSuite(CppUnit::Test *suite) { 63 | m_test_path.pop_back(); 64 | } 65 | -------------------------------------------------------------------------------- /test/helpers/progress_listener.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "torrent/utils/log_buffer.h" 8 | 9 | struct failure_type { 10 | std::string name; 11 | torrent::log_buffer_ptr log; 12 | }; 13 | 14 | typedef std::unique_ptr test_failure_ptr; 15 | typedef std::vector test_list_type; 16 | typedef std::vector failure_list_type; 17 | 18 | class progress_listener : public CppUnit::TestListener { 19 | public: 20 | progress_listener() : m_last_test_failed(false) {} 21 | 22 | void startTest(CppUnit::Test *test) override; 23 | void addFailure(const CppUnit::TestFailure &failure) override; 24 | void endTest(CppUnit::Test *test) override; 25 | 26 | void startSuite(CppUnit::Test *suite) override; 27 | void endSuite(CppUnit::Test *suite) override; 28 | 29 | //Called by a TestRunner before running the test. 30 | // void startTestRun(CppUnit::Test *test, CppUnit::TestResult *event_manager) override; 31 | 32 | // Called by a TestRunner after running the test. 33 | // void endTestRun(CppUnit::Test *test, CppUnit::TestResult *event_manager) override; 34 | 35 | const failure_list_type& failures() { return m_failures; } 36 | failure_list_type&& move_failures() { return std::move(m_failures); } 37 | 38 | private: 39 | progress_listener(const progress_listener& rhs) = delete; 40 | void operator =(const progress_listener& rhs) = delete; 41 | 42 | test_list_type m_test_path; 43 | failure_list_type m_failures; 44 | bool m_last_test_failed; 45 | 46 | torrent::log_buffer_ptr m_current_log_buffer; 47 | }; 48 | -------------------------------------------------------------------------------- /test/helpers/protectors.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | bool 9 | ExceptionProtector::protect(const CppUnit::Functor& functor, const CppUnit::ProtectorContext& context) { 10 | try { 11 | return functor(); 12 | 13 | } catch (CppUnit::Exception &failure) { 14 | reportFailure( context, failure ); 15 | 16 | } catch (torrent::base_error& e) { 17 | std::string short_description("uncaught exception of base type torrent::base_error: " + std::string(typeid(e).name())); 18 | 19 | CppUnit::Message message(short_description, e.what()); 20 | reportError(context, message); 21 | 22 | } catch ( std::exception &e ) { 23 | std::string short_description("uncaught exception of type "); 24 | 25 | short_description += CppUnit::TypeInfoHelper::getClassName(typeid(e)); 26 | 27 | CppUnit::Message message(short_description, e.what()); 28 | reportError(context, message); 29 | 30 | } catch ( ... ) { 31 | reportError(context, CppUnit::Message("uncaught exception of unknown type")); 32 | } 33 | 34 | return false; 35 | } 36 | -------------------------------------------------------------------------------- /test/helpers/protectors.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBTORRENT_HELPER_PROTECTORS_H 2 | #define LIBTORRENT_HELPER_PROTECTORS_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class ExceptionProtector : public CppUnit::Protector { 9 | public: 10 | bool protect(const CppUnit::Functor &functor, const CppUnit::ProtectorContext &context) override; 11 | }; 12 | 13 | #endif // LIBTORRENT_HELPER_PROTECTORS_H 14 | -------------------------------------------------------------------------------- /test/helpers/test_fixture.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include "test_fixture.h" 4 | 5 | #include "torrent/utils/log.h" 6 | 7 | #include 8 | 9 | void 10 | test_fixture::setUp() { 11 | mock_init(); 12 | 13 | log_add_group_output(torrent::LOG_CONNECTION_BIND, "test_output"); 14 | log_add_group_output(torrent::LOG_CONNECTION_FD, "test_output"); 15 | } 16 | 17 | void 18 | test_fixture::tearDown() { 19 | mock_cleanup(); 20 | } 21 | -------------------------------------------------------------------------------- /test/helpers/test_fixture.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBTORRENT_HELPER_TEST_FIXTURE_H 2 | #define LIBTORRENT_HELPER_TEST_FIXTURE_H 3 | 4 | #include 5 | 6 | #include "test/helpers/mock_function.h" 7 | 8 | class test_fixture : public CppUnit::TestFixture { 9 | public: 10 | void setUp(); 11 | void tearDown(); 12 | }; 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /test/helpers/test_main_thread.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include "test_main_thread.h" 4 | 5 | #include 6 | 7 | #include "test/helpers/mock_function.h" 8 | #include "torrent/exceptions.h" 9 | #include "torrent/net/resolver.h" 10 | #include "torrent/utils/log.h" 11 | #include "torrent/utils/scheduler.h" 12 | 13 | std::unique_ptr 14 | TestMainThread::create() { 15 | // Needs to be called before Thread is created. 16 | mock_redirect_defaults(); 17 | return std::unique_ptr(new TestMainThread()); 18 | } 19 | 20 | std::unique_ptr 21 | TestMainThread::create_with_mock() { 22 | return std::unique_ptr(new TestMainThread()); 23 | } 24 | 25 | void 26 | TestMainThread::init_thread() { 27 | m_resolver = std::make_unique(); 28 | m_state = STATE_INITIALIZED; 29 | 30 | //m_instrumentation_index = INSTRUMENTATION_POLLING_DO_POLL_MAIN - INSTRUMENTATION_POLLING_DO_POLL; 31 | 32 | init_thread_local(); 33 | } 34 | 35 | void 36 | TestMainThread::cleanup_thread() { 37 | } 38 | 39 | void 40 | TestMainThread::call_events() { 41 | process_callbacks(); 42 | } 43 | 44 | std::chrono::microseconds 45 | TestMainThread::next_timeout() { 46 | return 10min; 47 | } 48 | 49 | void 50 | TestFixtureWithMainThread::setUp() { 51 | test_fixture::setUp(); 52 | 53 | m_main_thread = TestMainThread::create(); 54 | m_main_thread->init_thread(); 55 | } 56 | 57 | void 58 | TestFixtureWithMainThread::tearDown() { 59 | m_main_thread.reset(); 60 | 61 | test_fixture::tearDown(); 62 | } 63 | 64 | void 65 | TestFixtureWithMockAndMainThread::setUp() { 66 | test_fixture::setUp(); 67 | 68 | m_main_thread = TestMainThread::create_with_mock(); 69 | m_main_thread->init_thread(); 70 | } 71 | 72 | void 73 | TestFixtureWithMockAndMainThread::tearDown() { 74 | m_main_thread.reset(); 75 | 76 | test_fixture::tearDown(); 77 | } 78 | 79 | -------------------------------------------------------------------------------- /test/helpers/test_main_thread.h: -------------------------------------------------------------------------------- 1 | #ifndef TEST_HELPERS_TEST_MAIN_THREAD_H 2 | #define TEST_HELPERS_TEST_MAIN_THREAD_H 3 | 4 | #include 5 | 6 | #include "test/helpers/test_fixture.h" 7 | #include "test/helpers/test_thread.h" 8 | #include "torrent/common.h" 9 | #include "torrent/utils/thread.h" 10 | 11 | class TestMainThread : public torrent::utils::Thread { 12 | public: 13 | static std::unique_ptr create(); 14 | static std::unique_ptr create_with_mock(); 15 | 16 | const char* name() const override { return "rtorrent test main"; } 17 | 18 | void init_thread() override; 19 | void cleanup_thread() override; 20 | 21 | void test_set_cached_time(std::chrono::microseconds t) { set_cached_time(365 * 24h + t); } 22 | void test_add_cached_time(std::chrono::microseconds t) { set_cached_time(cached_time() + t); } 23 | void test_process_events_without_cached_time() { process_events_without_cached_time(); } 24 | 25 | private: 26 | TestMainThread() = default; 27 | 28 | void call_events() override; 29 | std::chrono::microseconds next_timeout() override; 30 | }; 31 | 32 | class TestFixtureWithMainThread : public test_fixture { 33 | public: 34 | void setUp(); 35 | void tearDown(); 36 | 37 | std::unique_ptr m_main_thread; 38 | }; 39 | 40 | class TestFixtureWithMainAndDiskThread : public test_fixture { 41 | public: 42 | void setUp(); 43 | void tearDown(); 44 | 45 | std::unique_ptr m_main_thread; 46 | }; 47 | 48 | class TestFixtureWithMainAndTrackerThread : public test_fixture { 49 | public: 50 | void setUp(); 51 | void tearDown(); 52 | 53 | std::unique_ptr m_main_thread; 54 | }; 55 | 56 | class TestFixtureWithMockAndMainThread : public test_fixture { 57 | public: 58 | void setUp(); 59 | void tearDown(); 60 | 61 | std::unique_ptr m_main_thread; 62 | }; 63 | 64 | #endif // TEST_HELPERS_TEST_MAIN_THREAD_H 65 | -------------------------------------------------------------------------------- /test/helpers/test_thread.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include "test_thread.h" 4 | 5 | #include 6 | 7 | #include "test/helpers/mock_function.h" 8 | #include "torrent/exceptions.h" 9 | #include "torrent/poll.h" 10 | 11 | const int test_thread::test_flag_pre_stop; 12 | const int test_thread::test_flag_long_timeout; 13 | 14 | const int test_thread::test_flag_do_work; 15 | const int test_thread::test_flag_pre_poke; 16 | const int test_thread::test_flag_post_poke; 17 | 18 | std::unique_ptr 19 | test_thread::create() { 20 | // Needs to be called before Thread is created. 21 | mock_redirect_defaults(); 22 | 23 | auto thread = new test_thread(); 24 | return std::unique_ptr(thread); 25 | } 26 | 27 | test_thread::test_thread() : 28 | m_test_state(TEST_NONE), 29 | m_test_flags(0) { 30 | } 31 | 32 | test_thread::~test_thread() { 33 | if (is_active()) 34 | stop_thread_wait(); 35 | } 36 | 37 | void 38 | test_thread::init_thread() { 39 | m_state = STATE_INITIALIZED; 40 | m_test_state = TEST_PRE_START; 41 | } 42 | 43 | void 44 | test_thread::cleanup_thread() { 45 | } 46 | 47 | void 48 | test_thread::call_events() { 49 | m_loop_count++; 50 | 51 | if ((m_test_flags & test_flag_pre_stop) && m_test_state == TEST_PRE_START && m_state == STATE_ACTIVE) 52 | m_test_state = TEST_PRE_STOP; 53 | 54 | if ((m_flags & flag_do_shutdown)) { 55 | if ((m_flags & flag_did_shutdown)) 56 | throw torrent::internal_error("Already trigged shutdown."); 57 | 58 | m_flags |= flag_did_shutdown; 59 | throw torrent::shutdown_exception(); 60 | } 61 | 62 | if ((m_test_flags & test_flag_pre_poke)) { 63 | } 64 | 65 | if ((m_test_flags & test_flag_do_work)) { 66 | usleep(10 * 1000); // TODO: Don't just sleep, as that give up core. 67 | m_test_flags &= ~test_flag_do_work; 68 | } 69 | 70 | if ((m_test_flags & test_flag_post_poke)) { 71 | } 72 | 73 | process_callbacks(); 74 | } 75 | 76 | std::chrono::microseconds 77 | test_thread::next_timeout() { 78 | if ((m_test_flags & test_flag_long_timeout)) 79 | return std::chrono::microseconds(10s); 80 | else 81 | return std::chrono::microseconds(100ms); 82 | } 83 | -------------------------------------------------------------------------------- /test/helpers/test_thread.h: -------------------------------------------------------------------------------- 1 | #ifndef TEST_HELPERS_TEST_THREAD_H 2 | #define TEST_HELPERS_TEST_THREAD_H 3 | 4 | #include 5 | #include 6 | 7 | #include "test/helpers/test_utils.h" 8 | #include "torrent/common.h" 9 | #include "torrent/utils/thread.h" 10 | 11 | class test_thread : public torrent::utils::Thread { 12 | public: 13 | enum test_state { 14 | TEST_NONE, 15 | TEST_PRE_START, 16 | TEST_PRE_STOP, 17 | TEST_STOP 18 | }; 19 | 20 | static const int test_flag_pre_stop = 0x1; 21 | static const int test_flag_long_timeout = 0x2; 22 | 23 | static const int test_flag_do_work = 0x100; 24 | static const int test_flag_pre_poke = 0x200; 25 | static const int test_flag_post_poke = 0x400; 26 | 27 | static std::unique_ptr create(); 28 | 29 | ~test_thread() override; 30 | 31 | int test_state() const { return m_test_state; } 32 | 33 | bool is_state(int state) const { return m_state == state; } 34 | bool is_test_state(int state) const { return m_test_state == state; } 35 | bool is_test_flags(int flags) const { return (m_test_flags & flags) == flags; } 36 | bool is_not_test_flags(int flags) const { return !(m_test_flags & flags); } 37 | 38 | // Loop count increments twice each loop. 39 | int loop_count() const { return m_loop_count; } 40 | 41 | const char* name() const override { return "test_thread"; } 42 | 43 | void init_thread() override; 44 | void cleanup_thread() override; 45 | 46 | void set_pre_stop() { m_test_flags |= test_flag_pre_stop; } 47 | void set_test_flag(int flags) { m_test_flags |= flags; } 48 | 49 | private: 50 | test_thread(); 51 | 52 | void call_events() override; 53 | std::chrono::microseconds next_timeout() override; 54 | 55 | std::atomic_int m_test_state; 56 | std::atomic_int m_test_flags; 57 | std::atomic_int m_loop_count{0}; 58 | }; 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /test/helpers/test_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBTORRENT_TEST_UTILS_H 2 | #define LIBTORRENT_TEST_UTILS_H 3 | 4 | #include 5 | #include 6 | 7 | inline bool 8 | wait_for_true(std::function test_function) { 9 | int i = 100; 10 | 11 | do { 12 | if (test_function()) 13 | return true; 14 | 15 | usleep(10 * 1000); 16 | } while (--i); 17 | 18 | return false; 19 | } 20 | 21 | #endif // LIBTORRENT_TEST_UTILS_H 22 | -------------------------------------------------------------------------------- /test/helpers/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBTORRENT_HELPER_UTILS_H 2 | #define LIBTORRENT_HELPER_UTILS_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | static void 10 | dump_failure_log(const failure_type& failure) { 11 | if (failure.log->empty()) 12 | return; 13 | 14 | std::cout << std::endl << failure.name << std::endl; 15 | 16 | // Doesn't print dump messages as log_buffer drops them. 17 | std::for_each(failure.log->begin(), failure.log->end(), [](const torrent::log_entry& entry) { 18 | std::cout << entry.timestamp << ' ' << entry.message << '\n'; 19 | }); 20 | 21 | std::cout << std::flush; 22 | } 23 | 24 | static void 25 | dump_failures(const failure_list_type& failures) { 26 | if (failures.empty()) 27 | return; 28 | 29 | std::cout << std::endl 30 | << "=================" << std::endl 31 | << "Failed Test Logs:" << std::endl 32 | << "=================" << std::endl; 33 | 34 | std::for_each(failures.begin(), failures.end(), [](const failure_type& failure) { 35 | dump_failure_log(failure); 36 | }); 37 | std::cout << std::endl; 38 | } 39 | 40 | static 41 | void add_tests(CppUnit::TextUi::TestRunner& runner, const char* c_test_names) { 42 | if (c_test_names == NULL || std::string(c_test_names).empty()) { 43 | runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest()); 44 | return; 45 | } 46 | 47 | const std::string& test_names(c_test_names); 48 | 49 | size_t pos = 0; 50 | size_t next = 0; 51 | 52 | while ((next = test_names.find(',', pos)) < test_names.size()) { 53 | runner.addTest(CppUnit::TestFactoryRegistry::getRegistry(test_names.substr(pos, next - pos)).makeTest()); 54 | pos = next + 1; 55 | } 56 | 57 | runner.addTest(CppUnit::TestFactoryRegistry::getRegistry(test_names.substr(pos)).makeTest()); 58 | } 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /test/main.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #ifdef HAVE_BACKTRACE 16 | #include 17 | #endif 18 | 19 | #include "helpers/progress_listener.h" 20 | #include "helpers/protectors.h" 21 | #include "helpers/utils.h" 22 | 23 | CPPUNIT_REGISTRY_ADD_TO_DEFAULT("rpc"); 24 | CPPUNIT_REGISTRY_ADD_TO_DEFAULT("src"); 25 | 26 | void 27 | do_test_panic(int signum) { 28 | signal(signum, SIG_DFL); 29 | 30 | std::cout << std::endl << std::endl << "Caught " << strsignal(signum) << ", dumping stack:" << std::endl << std::endl; 31 | 32 | #ifdef HAVE_BACKTRACE 33 | void* stackPtrs[20]; 34 | 35 | // Print the stack and exit. 36 | int stackSize = backtrace(stackPtrs, 20); 37 | char** stackStrings = backtrace_symbols(stackPtrs, stackSize); 38 | 39 | for (int i = 0; i < stackSize; ++i) 40 | std::cout << stackStrings[i] << std::endl; 41 | 42 | #else 43 | std::cout << "Stack dump not enabled." << std::endl; 44 | #endif 45 | 46 | std::cout << std::endl; 47 | torrent::log_cleanup(); 48 | std::abort(); 49 | } 50 | 51 | void 52 | register_signal_handlers() { 53 | struct sigaction sa; 54 | sigemptyset(&sa.sa_mask); 55 | sa.sa_flags = SA_RESTART; 56 | sa.sa_handler = &do_test_panic; 57 | 58 | if (sigaction(SIGSEGV, &sa, NULL) == -1) { 59 | std::cout << "Could not register signal handlers." << std::endl; 60 | exit(-1); 61 | } 62 | } 63 | 64 | int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) { 65 | register_signal_handlers(); 66 | 67 | CppUnit::TestResult controller; 68 | CppUnit::TestResultCollector result; 69 | progress_listener progress; 70 | 71 | controller.addListener(&result); 72 | controller.addListener(&progress); 73 | 74 | controller.popProtector(); 75 | controller.pushProtector(new ExceptionProtector()); 76 | 77 | CppUnit::TextUi::TestRunner runner; 78 | add_tests(runner, std::getenv("TEST_NAME")); 79 | 80 | try { 81 | std::cout << "Running "; 82 | runner.run( controller ); 83 | 84 | // TODO: Make outputter. 85 | dump_failures(progress.failures()); 86 | 87 | // Print test in a compiler compatible format. 88 | CppUnit::CompilerOutputter outputter( &result, std::cerr ); 89 | outputter.write(); 90 | 91 | } catch ( std::invalid_argument &e ) { // Test path not resolved 92 | std::cerr << std::endl << "ERROR: " << e.what() << std::endl; 93 | return 1; 94 | } 95 | 96 | return result.wasSuccessful() ? 0 : 1; 97 | } 98 | -------------------------------------------------------------------------------- /test/rpc/test_command.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include "test/rpc/test_command.h" 4 | 5 | #include "rpc/command.h" 6 | 7 | CPPUNIT_TEST_SUITE_REGISTRATION(TestCommand); 8 | 9 | bool 10 | command_stack_all_empty() { 11 | return std::all_of(rpc::command_base::stack_begin(), rpc::command_base::stack_end(), 12 | [](auto& obj) { return obj.is_empty(); }); 13 | } 14 | 15 | void 16 | TestCommand::test_stack() { 17 | torrent::Object::list_type args; 18 | rpc::command_base::stack_type stack; 19 | torrent::Object* last_stack; 20 | 21 | // Test empty stack. 22 | CPPUNIT_ASSERT(command_stack_all_empty()); 23 | 24 | last_stack = rpc::command_base::push_stack(args, &stack); 25 | CPPUNIT_ASSERT(command_stack_all_empty()); 26 | 27 | rpc::command_base::pop_stack(&stack, last_stack); 28 | CPPUNIT_ASSERT(command_stack_all_empty()); 29 | 30 | // Test stack with one. 31 | args.push_back(int64_t(1)); 32 | 33 | last_stack = rpc::command_base::push_stack(args, &stack); 34 | CPPUNIT_ASSERT(!command_stack_all_empty()); 35 | CPPUNIT_ASSERT(rpc::command_base::stack_begin()->as_value() == 1); 36 | 37 | rpc::command_base::pop_stack(&stack, last_stack); 38 | CPPUNIT_ASSERT(command_stack_all_empty()); 39 | 40 | // Test stack with two 41 | args.clear(); 42 | args.push_back(int64_t(2)); 43 | args.push_back(int64_t(3)); 44 | 45 | last_stack = rpc::command_base::push_stack(args, &stack); 46 | CPPUNIT_ASSERT(!command_stack_all_empty()); 47 | CPPUNIT_ASSERT(rpc::command_base::current_stack[0].as_value() == 2); 48 | CPPUNIT_ASSERT(rpc::command_base::current_stack[1].as_value() == 3); 49 | 50 | rpc::command_base::pop_stack(&stack, last_stack); 51 | CPPUNIT_ASSERT(command_stack_all_empty()); 52 | } 53 | 54 | void 55 | TestCommand::test_stack_double() { 56 | torrent::Object::list_type args; 57 | rpc::command_base::stack_type stack_first; 58 | rpc::command_base::stack_type stack_second; 59 | torrent::Object* last_stack_first; 60 | torrent::Object* last_stack_second; 61 | 62 | // Test double-stacked. 63 | args.push_back(int64_t(1)); 64 | 65 | last_stack_first = rpc::command_base::push_stack(args, &stack_first); 66 | CPPUNIT_ASSERT(!command_stack_all_empty()); 67 | CPPUNIT_ASSERT(rpc::command_base::current_stack[0].as_value() == 1); 68 | 69 | args.clear(); 70 | args.push_back(int64_t(2)); 71 | args.push_back(int64_t(3)); 72 | 73 | last_stack_second = rpc::command_base::push_stack(args, &stack_second); 74 | CPPUNIT_ASSERT(!command_stack_all_empty()); 75 | 76 | CPPUNIT_ASSERT(rpc::command_base::current_stack[0].as_value() == 2); 77 | CPPUNIT_ASSERT(rpc::command_base::current_stack[1].as_value() == 3); 78 | 79 | rpc::command_base::pop_stack(&stack_second, last_stack_second); 80 | CPPUNIT_ASSERT(!command_stack_all_empty()); 81 | CPPUNIT_ASSERT(rpc::command_base::current_stack[0].as_value() == 1); 82 | 83 | rpc::command_base::pop_stack(&stack_first, last_stack_first); 84 | CPPUNIT_ASSERT(command_stack_all_empty()); 85 | } 86 | -------------------------------------------------------------------------------- /test/rpc/test_command.h: -------------------------------------------------------------------------------- 1 | #include "test/helpers/test_fixture.h" 2 | 3 | class TestCommand : public test_fixture { 4 | CPPUNIT_TEST_SUITE(TestCommand); 5 | 6 | CPPUNIT_TEST(test_stack); 7 | CPPUNIT_TEST(test_stack_double); 8 | 9 | CPPUNIT_TEST_SUITE_END(); 10 | 11 | public: 12 | void test_stack(); 13 | void test_stack_double(); 14 | }; 15 | -------------------------------------------------------------------------------- /test/rpc/test_command_map.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include "test/rpc/test_command_map.h" 4 | 5 | #include "command_helpers.h" 6 | #include "rpc/command_map.h" 7 | 8 | CPPUNIT_TEST_SUITE_REGISTRATION(TestCommandMap); 9 | 10 | #undef CMD2_A_FUNCTION 11 | 12 | #define CMD2_A_FUNCTION(key, function, slot, parm, doc) \ 13 | m_map.insert_slot::type>(key, slot, &rpc::function, \ 14 | rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_rpc, NULL, NULL); 15 | 16 | torrent::Object cmd_test_map_a([[maybe_unused]] rpc::target_type t, const torrent::Object& obj) { return obj; } 17 | torrent::Object cmd_test_map_b([[maybe_unused]] rpc::target_type t, [[maybe_unused]] const torrent::Object& obj, uint64_t c) { return torrent::Object(c); } 18 | 19 | torrent::Object cmd_test_any_string([[maybe_unused]] rpc::target_type target, [[maybe_unused]] const std::string& rawArgs) { return (int64_t)3; } 20 | 21 | void 22 | TestCommandMap::test_basics() { 23 | CMD2_ANY("test_a", &cmd_test_map_a); 24 | CMD2_ANY("test_b", std::bind(&cmd_test_map_b, std::placeholders::_1, std::placeholders::_2, (uint64_t)2)); 25 | CMD2_ANY_STRING("any_string", &cmd_test_any_string); 26 | 27 | CPPUNIT_ASSERT(m_map.call_command("test_a", (int64_t)1).as_value() == 1); 28 | CPPUNIT_ASSERT(m_map.call_command("test_b", (int64_t)1).as_value() == 2); 29 | CPPUNIT_ASSERT(m_map.call_command("any_string", "").as_value() == 3); 30 | } 31 | -------------------------------------------------------------------------------- /test/rpc/test_command_map.h: -------------------------------------------------------------------------------- 1 | #include "test/helpers/test_fixture.h" 2 | 3 | #include "rpc/command_map.h" 4 | 5 | class TestCommandMap : public test_fixture { 6 | CPPUNIT_TEST_SUITE(TestCommandMap); 7 | 8 | CPPUNIT_TEST(test_basics); 9 | 10 | CPPUNIT_TEST_SUITE_END(); 11 | 12 | public: 13 | static const int cmd_size = 256; 14 | 15 | void setUp() { m_commandItr = m_commands; } 16 | 17 | void test_basics(); 18 | 19 | private: 20 | rpc::CommandMap m_map; 21 | 22 | rpc::command_base m_commands[cmd_size]; 23 | rpc::command_base* m_commandItr; 24 | }; 25 | -------------------------------------------------------------------------------- /test/rpc/test_command_slot.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include "test/rpc/test_command_slot.h" 4 | 5 | #include 6 | #include 7 | 8 | #include "rpc/command_map.h" 9 | 10 | CPPUNIT_TEST_SUITE_REGISTRATION(TestCommandSlot); 11 | 12 | torrent::Object cmd_test_a([[maybe_unused]] rpc::target_type t, const torrent::Object& obj) { return obj; } 13 | torrent::Object cmd_test_b([[maybe_unused]] rpc::target_type t, [[maybe_unused]] const torrent::Object& obj, uint64_t c) { return torrent::Object(c); } 14 | 15 | torrent::Object cmd_test_list([[maybe_unused]] rpc::target_type t, const torrent::Object::list_type& obj) { return torrent::Object(obj.front()); } 16 | 17 | void cmd_test_convert_void([[maybe_unused]] rpc::target_type t, [[maybe_unused]] const torrent::Object& obj) {} 18 | int32_t cmd_test_convert_int32_t([[maybe_unused]] rpc::target_type t, [[maybe_unused]] const torrent::Object& obj) { return 9; } 19 | int64_t cmd_test_convert_int64_t([[maybe_unused]] rpc::target_type t, [[maybe_unused]] const torrent::Object& obj) { return 10; } 20 | std::string cmd_test_convert_string([[maybe_unused]] rpc::target_type t, [[maybe_unused]] const torrent::Object& obj) { return "test_1"; } 21 | const std::string& cmd_test_convert_const_string([[maybe_unused]] rpc::target_type t, [[maybe_unused]] const torrent::Object& obj) { static const std::string ret = "test_2"; return ret; } 22 | 23 | void 24 | TestCommandSlot::test_basics() { 25 | // rpc::command_base test_any; 26 | // test_any.set_function(&cmd_test_a); 27 | // CPPUNIT_ASSERT(rpc::command_base_call_any(&test_any, rpc::make_target(), (int64_t)1).as_value() == 1); 28 | 29 | // test_any.set_function(std::bind(&cmd_test_b, std::placeholders::_1, std::placeholders::_2, (uint64_t)2)); 30 | // CPPUNIT_ASSERT(rpc::command_base_call_any(&test_any, rpc::make_target(), (int64_t)1).as_value() == 2); 31 | 32 | // test_any.set_function(&cmd_test_list); 33 | // CPPUNIT_ASSERT(rpc::command_base_call_any_list(&test_any, rpc::make_target(), (int64_t)3).as_value() == 3); 34 | } 35 | 36 | void 37 | TestCommandSlot::test_type_validity() { 38 | // CPPUNIT_ASSERT((rpc::command_base_is_type::value)); 39 | // CPPUNIT_ASSERT((rpc::command_base_is_type::value)); 40 | } 41 | 42 | void 43 | TestCommandSlot::test_convert_return() { 44 | // rpc::command_base test_any; 45 | 46 | // test_any.set_function(&cmd_test_convert_string); 47 | // CPPUNIT_ASSERT(rpc::command_base_call_any(&test_any, rpc::make_target(), (int64_t)1).as_string() == "test_1"); 48 | 49 | // test_any.set_function(&cmd_test_convert_const_string); 50 | // CPPUNIT_ASSERT(rpc::command_base_call_any(&test_any, rpc::make_target(), (int64_t)1).as_string() == "test_2"); 51 | 52 | // test_any.set_function(object_convert_void(&cmd_test_convert_void)); 53 | // CPPUNIT_ASSERT(rpc::command_base_call_any(&test_any, rpc::make_target(), (int64_t)1).is_empty()); 54 | } 55 | -------------------------------------------------------------------------------- /test/rpc/test_command_slot.h: -------------------------------------------------------------------------------- 1 | #include "test/helpers/test_fixture.h" 2 | 3 | class TestCommandSlot : public test_fixture { 4 | CPPUNIT_TEST_SUITE(TestCommandSlot); 5 | 6 | CPPUNIT_TEST(test_basics); 7 | CPPUNIT_TEST(test_type_validity); 8 | CPPUNIT_TEST(test_convert_return); 9 | 10 | CPPUNIT_TEST_SUITE_END(); 11 | 12 | public: 13 | void test_basics(); 14 | void test_type_validity(); 15 | void test_convert_return(); 16 | }; 17 | -------------------------------------------------------------------------------- /test/rpc/test_jsonrpc.h: -------------------------------------------------------------------------------- 1 | #include "test/helpers/test_fixture.h" 2 | #include "test/helpers/test_main_thread.h" 3 | 4 | #include "rpc/command_map.h" 5 | #include "rpc/jsonrpc.h" 6 | 7 | class TestJsonrpc : public test_fixture { 8 | CPPUNIT_TEST_SUITE(TestJsonrpc); 9 | 10 | CPPUNIT_TEST(test_basics); 11 | 12 | CPPUNIT_TEST_SUITE_END(); 13 | 14 | public: 15 | void setUp(); 16 | void tearDown(); 17 | 18 | void test_basics(); 19 | 20 | private: 21 | std::unique_ptr m_test_main_thread; 22 | 23 | rpc::JsonRpc m_jsonrpc; 24 | }; 25 | -------------------------------------------------------------------------------- /test/rpc/test_object_storage.h: -------------------------------------------------------------------------------- 1 | #include "test/helpers/test_fixture.h" 2 | 3 | #include "rpc/object_storage.h" 4 | 5 | class TestObjectStorage : public test_fixture { 6 | CPPUNIT_TEST_SUITE(TestObjectStorage); 7 | 8 | CPPUNIT_TEST(test_basics); 9 | CPPUNIT_TEST(test_conversions); 10 | CPPUNIT_TEST(test_validate_keys); 11 | CPPUNIT_TEST(test_access); 12 | 13 | CPPUNIT_TEST_SUITE_END(); 14 | 15 | public: 16 | void test_basics(); 17 | 18 | void test_conversions(); 19 | void test_validate_keys(); 20 | 21 | void test_access(); 22 | 23 | private: 24 | rpc::object_storage m_storage; 25 | }; 26 | -------------------------------------------------------------------------------- /test/rpc/test_parse_options.h: -------------------------------------------------------------------------------- 1 | #include "test/helpers/test_fixture.h" 2 | 3 | class TestParseOptions : public test_fixture { 4 | CPPUNIT_TEST_SUITE(TestParseOptions); 5 | 6 | CPPUNIT_TEST(test_flag_basic); 7 | CPPUNIT_TEST(test_flag_error); 8 | 9 | CPPUNIT_TEST(test_flags_basic); 10 | CPPUNIT_TEST(test_flags_error); 11 | CPPUNIT_TEST(test_flags_complex); 12 | 13 | CPPUNIT_TEST(test_flags_print_vector); 14 | CPPUNIT_TEST(test_flags_print_flags); 15 | 16 | CPPUNIT_TEST(test_flag_libtorrent); 17 | CPPUNIT_TEST(test_flags_libtorrent); 18 | 19 | CPPUNIT_TEST_SUITE_END(); 20 | 21 | public: 22 | void test_flag_basic(); 23 | void test_flag_error(); 24 | 25 | void test_flags_basic(); 26 | void test_flags_error(); 27 | void test_flags_complex(); 28 | 29 | void test_flags_print_vector(); 30 | void test_flags_print_flags(); 31 | 32 | void test_flag_libtorrent(); 33 | void test_flags_libtorrent(); 34 | }; 35 | -------------------------------------------------------------------------------- /test/rpc/test_xmlrpc.h: -------------------------------------------------------------------------------- 1 | #include "test/helpers/test_fixture.h" 2 | #include "test/helpers/test_main_thread.h" 3 | 4 | #include "rpc/command_map.h" 5 | #include "rpc/xmlrpc.h" 6 | 7 | class TestXmlrpc : public test_fixture { 8 | CPPUNIT_TEST_SUITE(TestXmlrpc); 9 | 10 | CPPUNIT_TEST(test_basics); 11 | CPPUNIT_TEST(test_invalid_utf8); 12 | CPPUNIT_TEST(test_size_limit); 13 | 14 | CPPUNIT_TEST_SUITE_END(); 15 | 16 | public: 17 | static const int cmd_size = 256; 18 | 19 | void setUp(); 20 | void tearDown(); 21 | 22 | void test_basics(); 23 | void test_invalid_utf8(); 24 | void test_size_limit(); 25 | 26 | private: 27 | std::unique_ptr m_test_main_thread; 28 | 29 | rpc::XmlRpc m_xmlrpc; 30 | rpc::CommandMap m_map; 31 | rpc::command_base m_commands[cmd_size]; 32 | }; 33 | -------------------------------------------------------------------------------- /test/src/test_command_dynamic.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include "test/src/test_command_dynamic.h" 4 | 5 | #include "control.h" 6 | #include "globals.h" 7 | #include "rpc/parse_commands.h" 8 | 9 | CPPUNIT_TEST_SUITE_REGISTRATION(TestCommandDynamic); 10 | 11 | void initialize_command_dynamic(); 12 | void initialize_command_ui(); 13 | 14 | void 15 | TestCommandDynamic::setUp() { 16 | m_test_main_thread = TestMainThread::create(); 17 | m_test_main_thread->init_thread(); 18 | 19 | if (rpc::commands.find("method.insert") == rpc::commands.end()) { 20 | setlocale(LC_ALL, ""); 21 | // cachedTime = rak::timer::current(); 22 | control = new Control; 23 | 24 | initialize_command_dynamic(); 25 | initialize_command_ui(); 26 | } 27 | } 28 | 29 | void 30 | TestCommandDynamic::tearDown() { 31 | m_test_main_thread.reset(); 32 | } 33 | 34 | void 35 | TestCommandDynamic::test_basics() { 36 | rpc::commands.call_command("method.insert.value", rpc::create_object_list("test_basics.1", int64_t(1))); 37 | CPPUNIT_ASSERT(rpc::commands.call_command("test_basics.1", torrent::Object()).as_value() == 1); 38 | } 39 | 40 | void 41 | TestCommandDynamic::test_get_set() { 42 | rpc::commands.call_command("method.insert.simple", rpc::create_object_list("test_get_set.1", "cat=1")); 43 | CPPUNIT_ASSERT(rpc::commands.call_command("test_get_set.1", torrent::Object()).as_string() == "1"); 44 | CPPUNIT_ASSERT(rpc::commands.call_command("method.get", "test_get_set.1").as_string() == "cat=1"); 45 | 46 | rpc::commands.call_command("method.set", rpc::create_object_list("test_get_set.1", "cat=2")); 47 | CPPUNIT_ASSERT(rpc::commands.call_command("method.get", "test_get_set.1").as_string() == "cat=2"); 48 | } 49 | 50 | void 51 | TestCommandDynamic::test_old_style() { 52 | rpc::commands.call_command("method.insert", rpc::create_object_list("test_old_style.1", "value", int64_t(1))); 53 | CPPUNIT_ASSERT(rpc::commands.call_command("test_old_style.1", torrent::Object()).as_value() == 1); 54 | 55 | rpc::commands.call_command("method.insert", rpc::create_object_list("test_old_style.2", "bool", int64_t(5))); 56 | CPPUNIT_ASSERT(rpc::commands.call_command("test_old_style.2", torrent::Object()).as_value() == 1); 57 | 58 | rpc::commands.call_command("method.insert", rpc::create_object_list("test_old_style.3", "string", "test.2")); 59 | CPPUNIT_ASSERT(rpc::commands.call_command("test_old_style.3", torrent::Object()).as_string() == "test.2"); 60 | 61 | rpc::commands.call_command("method.insert", rpc::create_object_list("test_old_style.4", "simple", "cat=test.3")); 62 | CPPUNIT_ASSERT(rpc::commands.call_command("test_old_style.4", torrent::Object()).as_string() == "test.3"); 63 | } 64 | -------------------------------------------------------------------------------- /test/src/test_command_dynamic.h: -------------------------------------------------------------------------------- 1 | #include "test/helpers/test_fixture.h" 2 | #include "test/helpers/test_main_thread.h" 3 | 4 | class TestCommandDynamic : public test_fixture { 5 | CPPUNIT_TEST_SUITE(TestCommandDynamic); 6 | 7 | CPPUNIT_TEST(test_basics); 8 | CPPUNIT_TEST(test_get_set); 9 | CPPUNIT_TEST(test_old_style); 10 | 11 | CPPUNIT_TEST_SUITE_END(); 12 | 13 | public: 14 | void setUp(); 15 | void tearDown(); 16 | 17 | void test_basics(); 18 | void test_get_set(); 19 | 20 | void test_old_style(); 21 | 22 | private: 23 | std::unique_ptr m_test_main_thread; 24 | }; 25 | --------------------------------------------------------------------------------