├── .gitmodules ├── Jamfile ├── Jamroot.jam ├── README.rst ├── bt ├── dashboard.html ├── libtorrent-graph.js ├── libtorrent-webui.js ├── test.html ├── test_files.html ├── test_settings.html ├── test_stats.html ├── test_stats_graphs.html └── test_torrent_updates.html ├── build.sh ├── docs ├── libtorrent-webui.rst └── mainpage.md ├── doxygen.conf ├── makefile ├── parse_session_stats.py ├── run_debug.sh ├── run_release.sh ├── snmp.cpp ├── src ├── alert_handler.cpp ├── alert_handler.hpp ├── alert_observer.hpp ├── auth.cpp ├── auth.hpp ├── auth_interface.hpp ├── auth_localhost.cpp ├── auth_localhost.hpp ├── auto_load.cpp ├── auto_load.hpp ├── base64.cpp ├── base64.hpp ├── cdecode.c ├── cdecode.h ├── disk_space.cpp ├── disk_space.hpp ├── error_logger.cpp ├── error_logger.hpp ├── escape_json.cpp ├── escape_json.hpp ├── file_downloader.cpp ├── file_downloader.hpp ├── file_requests.cpp ├── file_requests.hpp ├── hex.cpp ├── hex.hpp ├── http_whitelist.cpp ├── http_whitelist.hpp ├── jsmn.c ├── jsmn.h ├── json_util.cpp ├── json_util.hpp ├── libtorrent_webui.cpp ├── libtorrent_webui.hpp ├── load_config.cpp ├── load_config.hpp ├── local_mongoose.h ├── mongoose.c ├── no_auth.cpp ├── no_auth.hpp ├── pam_auth.cpp ├── pam_auth.hpp ├── rencode.cpp ├── rencode.hpp ├── response_buffer.hpp ├── save_resume.cpp ├── save_resume.hpp ├── save_settings.cpp ├── save_settings.hpp ├── stats_logging.cpp ├── stats_logging.hpp ├── text_ui.cpp ├── text_ui.hpp ├── torrent_history.cpp ├── torrent_history.hpp ├── torrent_post.cpp ├── torrent_post.hpp ├── utorrent_webui.cpp ├── utorrent_webui.hpp ├── websocket_handler.cpp ├── websocket_handler.hpp ├── webui.cpp └── webui.hpp ├── test.cpp ├── test_range.py ├── tests ├── Jamfile ├── test.hpp ├── test_rencode.cpp └── test_rss_filter.cpp └── tools └── add_user.cpp /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libtorrent"] 2 | path = libtorrent 3 | url = https://github.com/arvidn/libtorrent.git 4 | -------------------------------------------------------------------------------- /Jamfile: -------------------------------------------------------------------------------- 1 | import modules ; 2 | import feature : feature ; 3 | 4 | BOOST_ROOT = [ modules.peek : BOOST_ROOT ] ; 5 | 6 | feature pam : off on : composite ; 7 | 8 | feature use-boost : system source : composite ; 9 | 10 | project libtorrent-webui : requirements 17 ; 11 | 12 | use-project /torrent : libtorrent ; 13 | lib sqlite : : sqlite3 /opt/local/lib : /opt/local/include ; 14 | lib libiconv : : iconv shared /usr/local/lib ; 15 | 16 | if $(BOOST_ROOT) 17 | { 18 | use-project /boost : $(BOOST_ROOT) ; 19 | } 20 | 21 | SOURCES = 22 | webui 23 | libtorrent_webui 24 | json_util 25 | file_downloader 26 | torrent_post 27 | rencode 28 | disk_space 29 | base64 30 | escape_json 31 | auto_load 32 | save_settings 33 | save_resume 34 | torrent_history 35 | auth 36 | no_auth 37 | auth_localhost 38 | load_config 39 | http_whitelist 40 | error_logger 41 | websocket_handler 42 | alert_handler 43 | file_requests 44 | stats_logging 45 | hex 46 | utorrent_webui 47 | ; 48 | 49 | lib torrent-webui 50 | : # sources 51 | src/$(SOURCES).cpp src/mongoose.c src/jsmn.c src/cdecode.c 52 | 53 | : # requirements 54 | /torrent//torrent 55 | zlib 56 | sqlite 57 | # libiconv 58 | on:pam 59 | on:src/pam_auth.cpp 60 | USE_WEBSOCKET=1 61 | 62 | : # default build 63 | static 64 | 65 | : # usage-requirements 66 | src 67 | linux:pthread 68 | linux:rt 69 | linux:dynamic-linker 70 | ; 71 | 72 | lib zlib : : z /usr/local/lib ; 73 | lib pthread : : pthread /usr/local/lib shared ; 74 | lib rt : : rt /usr/local/lib shared ; 75 | lib pam : : pam /usr/local/lib ; 76 | lib dynamic-linker : : dl shared ; 77 | 78 | exe webui_test : test.cpp : torrent-webui /torrent//torrent ; 79 | 80 | exe add_user : tools/add_user.cpp : torrent-webui /torrent//torrent ; 81 | exe snmp_test : snmp.cpp 82 | : /torrent//torrent 83 | torrent-webui 84 | src 85 | "-L/opt/local/lib -L/opt/local/lib -L/opt/local/lib -lnetsnmpmibs -lnetsnmpagent -lnetsnmp -lcrypto" ; 86 | 87 | explicit snmp_test ; 88 | 89 | install stage_add_user : add_user : . ; 90 | 91 | -------------------------------------------------------------------------------- /Jamroot.jam: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arvidn/libtorrent-webui/4709cf476aa711a205efa5667aa4f2bc76c307d4/Jamroot.jam -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | High level utility classes for use with libtorrent (libtorrent.org), 2 | primarily centered around web UI support. 3 | 4 | Currently supported web UIs: 5 | 6 | * librorrent native 7 | * uTorrent 8 | 9 | (patches for improving support or new web UIs are welcome). 10 | 11 | Supported features: 12 | 13 | * save/load settings (including custom settings) 14 | * save/load resume data regularly 15 | * HTTP basic authorization 16 | * post .torrent files to be added 17 | * download torrent content (via ``/proxy``, like uTorrent) 18 | * auto-load directory 19 | * torrent update queue, to return only torrents that have 20 | changed since last check-in 21 | * serving files off of filesystem 22 | * RSS feed filters, with episode parsing 23 | 24 | The main web UI framework leverages mongoose web server and 25 | jsmn JSON parser. 26 | 27 | For example usage, see the test_ program. 28 | 29 | arvid@rasterbar.com 30 | 31 | .. _test: https://github.com/arvidn/libtorrent-webui/blob/master/test.cpp 32 | 33 | -------------------------------------------------------------------------------- /bt/dashboard.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | libtorrent websocket test 4 | 5 | 6 | 216 | 217 |
218 | 219 | 220 | 221 | 222 | -------------------------------------------------------------------------------- /bt/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | libtorrent websocket test 4 | 5 | 6 | 131 | 132 | 133 | dashboard | 134 | stats (graph) | 135 | stats (numbers) 136 | 137 |
controlsNameProgress
138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /bt/test_files.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | libtorrent websocket test 4 | 5 | 65 | 66 | 67 |

68 | 69 | 70 |
NameSizeProgressDownloaded
71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /bt/test_settings.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | libtorrent websocket test 4 | 5 | 107 | 108 | 109 | 110 | 111 |
IDNameTypeValue
112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /bt/test_stats.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | libtorrent websocket test 4 | 5 | 6 | 89 | 90 | 91 | 92 | 93 |
NameTypeValue
94 | 95 | 96 |
NameTypeValue
97 | 98 | 99 |
NameTypeValue
100 | 101 | 102 |
NameTypeValue
103 | 104 | 105 |
NameTypeValue
106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /bt/test_stats_graphs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | libtorrent websocket test 4 | 5 | 6 | 90 | 91 |
92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /bt/test_torrent_updates.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | libtorrent websocket test 6 | 7 | 95 | 96 | 97 | 98 | 99 | 100 |
controlsNameProgressDownload rateUpload ratePeersErrorflagsstate
101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | bjam -j2 encryption=openssl link=static invariant-checks=off 2 | bjam -j2 encryption=openssl link=static release debug-symbols=on cflags=-fno-omit-frame-pointer 3 | 4 | -------------------------------------------------------------------------------- /docs/mainpage.md: -------------------------------------------------------------------------------- 1 | libtorrent-webui provides useful primitives when building bittorrent clients, or bittorrent functionality, on top of libtorrent. 2 | 3 | Despite its name, it provides more than just web interfaces. It also provides the followng key features: 4 | 5 | * save/load settings (``save_settings`` class). 6 | * auto-load director (``auto_load`` class). 7 | * load plain text configuration (``load_config``). 8 | * utorrent compatible web UI (``utorrent_webui``). 9 | * general purpose web server (based on mongoose, ``webui``). 10 | * authentication module with varying levels of access permissions (``auth_interface``, ``auth``, ``permissions_interface``). 11 | * PAM baed authentication module (``pam_auth``) 12 | * save/restore torren states, i.e. resume data (``save_resume``). 13 | * mechanism to keep a history of torrent updates, to efficiently provide "send updates since X" (``torrent_history``). Used by the web UIs. 14 | * HTTP post support to add .torrent files (``torrent_post``). 15 | 16 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | all: bt/lt.js.gz bt/lt-g.js.gz 2 | 3 | bt/lt.js: bt/libtorrent-webui.js 4 | java -jar compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --js bt/libtorrent-webui.js --js_output_file bt/lt.js 5 | 6 | bt/lt-g.js: bt/libtorrent-graph.js 7 | java -jar compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --js bt/libtorrent-graph.js --js_output_file bt/lt-g.js 8 | 9 | %.js.gz: %.js 10 | gzip -9 $< -c >$@ 11 | 12 | -------------------------------------------------------------------------------- /run_debug.sh: -------------------------------------------------------------------------------- 1 | gdb bin/gcc-4.6/debug/encryption-openssl/invariant-checks-off/link-static/statistics-on/webui_test 2 | 3 | -------------------------------------------------------------------------------- /run_release.sh: -------------------------------------------------------------------------------- 1 | gdb bin/gcc-4.6/release/asserts-production/debug-symbols-on/encryption-openssl/link-static/statistics-on/webui_test 2 | 3 | -------------------------------------------------------------------------------- /src/alert_handler.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012-2014, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #include "libtorrent/config.hpp" 34 | #include "libtorrent/session.hpp" 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include "alert_handler.hpp" 43 | #include "alert_observer.hpp" 44 | 45 | namespace libtorrent 46 | { 47 | 48 | alert_handler::alert_handler(lt::session& ses) 49 | : m_abort(false) 50 | , m_ses(ses) 51 | {} 52 | 53 | void alert_handler::subscribe(alert_observer* o, int const flags, ...) 54 | { 55 | std::array types; 56 | types.fill(0); 57 | va_list l; 58 | va_start(l, flags); 59 | int t = va_arg(l, int); 60 | int i = 0; 61 | while (t != 0 && i < 64) 62 | { 63 | types[i] = t; 64 | ++i; 65 | t = va_arg(l, int); 66 | } 67 | va_end(l); 68 | subscribe_impl(types.data(), i, o, flags); 69 | } 70 | 71 | void alert_handler::dispatch_alerts(std::vector& alerts) const 72 | { 73 | for (alert* a : alerts) 74 | { 75 | int const type = a->type(); 76 | 77 | // copy this vector since handlers may unsubscribe while we're looping 78 | std::vector alert_dispatchers = m_observers[type]; 79 | for (auto* h : alert_dispatchers) 80 | h->handle_alert(a); 81 | } 82 | alerts.clear(); 83 | } 84 | 85 | void alert_handler::dispatch_alerts() const 86 | { 87 | std::vector alert_queue; 88 | m_ses.pop_alerts(&alert_queue); 89 | dispatch_alerts(alert_queue); 90 | } 91 | 92 | void alert_handler::unsubscribe(alert_observer* o) 93 | { 94 | for (int i = 0; i < o->num_types; ++i) 95 | { 96 | int const type = o->types[i]; 97 | if (type == 0) continue; 98 | TORRENT_ASSERT(type >= 0); 99 | TORRENT_ASSERT(type < int(m_observers.size())); 100 | if (type < 0 || type >= int(m_observers.size())) continue; 101 | auto& alert_observers = m_observers[type]; 102 | auto j = std::find(alert_observers.begin(), alert_observers.end(), o); 103 | if (j != alert_observers.end()) alert_observers.erase(j); 104 | } 105 | o->num_types = 0; 106 | } 107 | 108 | // TODO: use span 109 | void alert_handler::subscribe_impl(int const* type_list, int const num_types 110 | , alert_observer* o, int const flags) 111 | { 112 | o->types.fill(0); 113 | o->flags = flags; 114 | for (int i = 0; i < num_types; ++i) 115 | { 116 | int const type = type_list[i]; 117 | if (type == 0) break; 118 | 119 | // only subscribe once per observer per type 120 | if (std::count(o->types.data(), o->types.data() + o->num_types, type) > 0) continue; 121 | 122 | TORRENT_ASSERT(type >= 0); 123 | TORRENT_ASSERT(type < int(m_observers.size())); 124 | if (type < 0 || type >= int(m_observers.size())) continue; 125 | 126 | o->types[o->num_types++] = type; 127 | m_observers[type].push_back(o); 128 | TORRENT_ASSERT(o->num_types < 64); 129 | } 130 | } 131 | 132 | void alert_handler::abort() 133 | { 134 | m_abort = true; 135 | } 136 | 137 | } 138 | 139 | -------------------------------------------------------------------------------- /src/alert_handler.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012-2013, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TORRENT_ALERT_HANDLER_HPP_INCLUDED 34 | #define TORRENT_ALERT_HANDLER_HPP_INCLUDED 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include "libtorrent/fwd.hpp" 42 | #include "libtorrent/alert_types.hpp" // for num_alert_types 43 | 44 | namespace libtorrent 45 | { 46 | 47 | struct alert_observer; 48 | 49 | struct TORRENT_EXPORT alert_handler 50 | { 51 | alert_handler(lt::session& ses); 52 | 53 | // TODO 2: move the responsibility of picking which 54 | // alert types to subscribe to to the observer 55 | // TODO 3: make subscriptions automatically enable 56 | // the corresponding category of alerts in the session somehow 57 | // TODO: 3 make this a variadic template 58 | void subscribe(alert_observer* o, int flags = 0, ...); 59 | void dispatch_alerts(std::vector& alerts) const; 60 | void dispatch_alerts() const; 61 | void unsubscribe(alert_observer* o); 62 | 63 | void abort(); 64 | 65 | private: 66 | 67 | void subscribe_impl(int const* type_list, int num_types, alert_observer* o, int flags); 68 | 69 | std::array, num_alert_types> m_observers; 70 | 71 | // when set to true, all outstanding (std::future-based) subscriptions 72 | // are cancelled, and new such subscriptions are disabled, by failing 73 | // immediately 74 | bool m_abort; 75 | 76 | session& m_ses; 77 | }; 78 | 79 | } 80 | 81 | #endif // TORRENT_ALERT_HANDLER_HPP_INCLUDED 82 | 83 | -------------------------------------------------------------------------------- /src/alert_observer.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2015, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | 34 | #ifndef TORRENT_ALERT_OBSERVER_HPP_INCLUDED 35 | #define TORRENT_ALERT_OBSERVER_HPP_INCLUDED 36 | 37 | #include 38 | #include 39 | 40 | #include "libtorrent/fwd.hpp" 41 | 42 | namespace libtorrent 43 | { 44 | 45 | struct alert_observer 46 | { 47 | friend struct alert_handler; 48 | 49 | alert_observer() = default; 50 | alert_observer(alert_observer const&) = delete; 51 | 52 | virtual void handle_alert(alert const* a) = 0; 53 | private: 54 | std::array types; 55 | int num_types = 0; 56 | int flags = 0; 57 | }; 58 | 59 | } 60 | 61 | #endif // TORRENT_ALERT_OBSERVER_HPP_INCLUDED 62 | 63 | -------------------------------------------------------------------------------- /src/auth.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TORRENT_AUTH_HPP 34 | #define TORRENT_AUTH_HPP 35 | 36 | #include "auth_interface.hpp" 37 | 38 | #include "libtorrent/peer_id.hpp" // sha1_hash 39 | #include "libtorrent/error_code.hpp" 40 | #include // for mutex 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | struct mg_connection; 47 | 48 | namespace libtorrent 49 | { 50 | permissions_interface const* parse_http_auth(mg_connection* conn, auth_interface const* auth); 51 | 52 | /** 53 | Implements simple access control. Users can be added, removed, saved and load from 54 | a plain text file. Access permissions are controlled via groups. There are two default 55 | groups. 0=full access, 1=read-only access. Groups can be re-definied using the set_group() 56 | function. Any user belonging to an undefined group will be denied any access. 57 | 58 | This object is thread safe. It is synchronized internally. 59 | */ 60 | struct auth : auth_interface 61 | { 62 | auth(); 63 | void add_account(std::string const& user, std::string const& pwd, int group); 64 | void remove_account(std::string const& user); 65 | std::vector users() const; 66 | 67 | void save_accounts(std::string const& filename, error_code& ec) const; 68 | void load_accounts(std::string const& filename, error_code& ec); 69 | 70 | void set_group(int g, permissions_interface const* perms); 71 | 72 | permissions_interface const* find_user(std::string username, std::string password) const; 73 | 74 | private: 75 | 76 | struct account_t 77 | { 78 | sha1_hash password_hash(std::string const& pwd) const; 79 | 80 | sha1_hash hash; 81 | std::array salt; 82 | int group; 83 | }; 84 | 85 | mutable std::mutex m_mutex; 86 | std::map m_accounts; 87 | 88 | // the permissions for each group 89 | std::vector m_groups; 90 | }; 91 | } 92 | 93 | #endif 94 | 95 | -------------------------------------------------------------------------------- /src/auth_localhost.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2013, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #include "auth_localhost.hpp" 34 | 35 | extern "C" { 36 | #include "local_mongoose.h" 37 | } 38 | 39 | #include 40 | 41 | namespace libtorrent 42 | { 43 | 44 | bool auth_localhost::handle_http(mg_connection* conn, mg_request_info const* request_info) 45 | { 46 | // we might as well be extra strict and only allow 127.0.0.1, instead 47 | // of 127.x.x.x 48 | if (request_info->remote_ip == 0x7f000001) 49 | return false; 50 | 51 | mg_printf(conn, "HTTP/1.1 401 Unauthorized\r\n" 52 | "WWW-Authenticate: Basic realm=\"BitTorrent\"\r\n" 53 | "Content-Length: 0\r\n\r\n"); 54 | return true; 55 | } 56 | 57 | } 58 | 59 | -------------------------------------------------------------------------------- /src/auth_localhost.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2013, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #include "webui.hpp" // for http_handler 34 | 35 | namespace libtorrent 36 | { 37 | 38 | // this http_handler only lets requests from 127.0.0.1 through 39 | // any other request is unauthorized 40 | struct auth_localhost : http_handler 41 | { 42 | bool handle_http(mg_connection* conn, mg_request_info const* request_info); 43 | }; 44 | } 45 | 46 | -------------------------------------------------------------------------------- /src/auto_load.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TORRENT_AUTO_LOAD_HPP 34 | #define TORRENT_AUTO_LOAD_HPP 35 | 36 | #include "libtorrent/session.hpp" 37 | #include "libtorrent/io_context.hpp" 38 | #include "boost/asio/high_resolution_timer.hpp" 39 | #include 40 | #include 41 | #include 42 | 43 | namespace libtorrent 44 | { 45 | struct save_settings_interface; 46 | 47 | struct auto_load 48 | { 49 | auto_load(session& s, save_settings_interface* sett = NULL); 50 | ~auto_load(); 51 | 52 | void set_params_model(add_torrent_params const& p); 53 | add_torrent_params params_model() const; 54 | 55 | void set_auto_load_dir(std::string const& dir); 56 | std::string const& auto_load_dir() const { return m_dir; } 57 | 58 | std::chrono::seconds scan_interval() const { return m_scan_interval; } 59 | void set_scan_interval(std::chrono::seconds s); 60 | 61 | void set_remove_files(bool r); 62 | bool remove_files() const; 63 | 64 | private: 65 | 66 | void on_scan(error_code const& ec); 67 | 68 | void thread_fun(); 69 | 70 | session& m_ses; 71 | boost::asio::io_context m_ios; 72 | boost::asio::high_resolution_timer m_timer; 73 | save_settings_interface* m_settings; 74 | 75 | // whether or not to remove .torrent files 76 | // as they are loaded 77 | bool m_remove_files; 78 | 79 | // when not removing files, keep track of 80 | // the ones we've already loaded to not 81 | // add them again 82 | std::set m_already_loaded; 83 | 84 | add_torrent_params m_params_model; 85 | std::string m_dir; 86 | std::chrono::seconds m_scan_interval; 87 | bool m_abort; 88 | 89 | // used to protect m_abort, m_scan_interval, m_dir, 90 | // m_remove_files and m_params_model 91 | mutable std::mutex m_mutex; 92 | 93 | // this needs to be last in order to be initialized 94 | // last in the constructor. This way the object is 95 | // guaranteed to be completely constructed by the time 96 | // the thread function is started 97 | std::thread m_thread; 98 | }; 99 | } 100 | 101 | #endif 102 | 103 | -------------------------------------------------------------------------------- /src/base64.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #include 34 | #include 35 | 36 | extern "C" { 37 | #include "cdecode.h" 38 | } 39 | 40 | namespace libtorrent 41 | { 42 | 43 | std::string base64decode(std::string const& in) 44 | { 45 | std::string ret; 46 | if (in.size() < 4) return ret; 47 | 48 | // approximate length of output 49 | ret.resize(in.size() * 6 / 8 + 1); 50 | 51 | base64_decodestate ctx; 52 | base64_init_decodestate(&ctx); 53 | int len = base64_decode_block(in.c_str(), in.size(), &ret[0], &ctx); 54 | ret.resize(len); 55 | return ret; 56 | } 57 | 58 | } 59 | 60 | -------------------------------------------------------------------------------- /src/base64.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TORRENT_BASE64_HPP 34 | #define TORRENT_BASE64_HPP 35 | 36 | #include 37 | 38 | namespace libtorrent 39 | { 40 | std::string base64decode(std::string const& in); 41 | } 42 | 43 | #endif 44 | 45 | -------------------------------------------------------------------------------- /src/cdecode.c: -------------------------------------------------------------------------------- 1 | /* 2 | cdecoder.c - c source to a base64 decoding algorithm implementation 3 | 4 | This is part of the libb64 project, and has been placed in the public domain. 5 | For details, see http://sourceforge.net/projects/libb64 6 | */ 7 | 8 | #include "cdecode.h" 9 | 10 | int base64_decode_value(char value_in) 11 | { 12 | static const signed char decoding[] = { 13 | 62,-1,-1,-1,63,52,53,54,55,56, 14 | 57,58,59,60,61,-1,-1,-1,-2,-1, 15 | -1,-1,0,1,2,3,4,5,6,7, 16 | 8,9,10,11,12,13,14,15,16,17, 17 | 18,19,20,21,22,23,24,25,-1,-1, 18 | -1,-1,-1,-1,26,27,28,29,30,31, 19 | 32,33,34,35,36,37,38,39,40,41, 20 | 42,43,44,45,46,47,48,49,50,51}; 21 | static const char decoding_size = sizeof(decoding); 22 | value_in -= 43; 23 | if (value_in < 0 || value_in > decoding_size) return -1; 24 | return decoding[(int)value_in]; 25 | } 26 | 27 | void base64_init_decodestate(base64_decodestate* state_in) 28 | { 29 | state_in->step = step_a; 30 | state_in->plainchar = 0; 31 | } 32 | 33 | int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in) 34 | { 35 | const char* codechar = code_in; 36 | char* plainchar = plaintext_out; 37 | signed char fragment; 38 | 39 | *plainchar = state_in->plainchar; 40 | 41 | switch (state_in->step) 42 | { 43 | while (1) 44 | { 45 | case step_a: 46 | do { 47 | if (codechar == code_in+length_in) 48 | { 49 | state_in->step = step_a; 50 | state_in->plainchar = *plainchar; 51 | return plainchar - plaintext_out; 52 | } 53 | fragment = (signed char)base64_decode_value(*codechar++); 54 | } while (fragment < 0); 55 | *plainchar = (fragment & 0x03f) << 2; 56 | case step_b: 57 | do { 58 | if (codechar == code_in+length_in) 59 | { 60 | state_in->step = step_b; 61 | state_in->plainchar = *plainchar; 62 | return plainchar - plaintext_out; 63 | } 64 | fragment = (signed char)base64_decode_value(*codechar++); 65 | } while (fragment < 0); 66 | *plainchar++ |= (fragment & 0x030) >> 4; 67 | *plainchar = (fragment & 0x00f) << 4; 68 | case step_c: 69 | do { 70 | if (codechar == code_in+length_in) 71 | { 72 | state_in->step = step_c; 73 | state_in->plainchar = *plainchar; 74 | return plainchar - plaintext_out; 75 | } 76 | fragment = (signed char)base64_decode_value(*codechar++); 77 | } while (fragment < 0); 78 | *plainchar++ |= (fragment & 0x03c) >> 2; 79 | *plainchar = (fragment & 0x003) << 6; 80 | case step_d: 81 | do { 82 | if (codechar == code_in+length_in) 83 | { 84 | state_in->step = step_d; 85 | state_in->plainchar = *plainchar; 86 | return plainchar - plaintext_out; 87 | } 88 | fragment = (signed char)base64_decode_value(*codechar++); 89 | } while (fragment < 0); 90 | *plainchar++ |= (fragment & 0x03f); 91 | } 92 | } 93 | /* control should not reach here */ 94 | return plainchar - plaintext_out; 95 | } 96 | 97 | -------------------------------------------------------------------------------- /src/cdecode.h: -------------------------------------------------------------------------------- 1 | /* 2 | cdecode.h - c header for a base64 decoding algorithm 3 | 4 | This is part of the libb64 project, and has been placed in the public domain. 5 | For details, see http://sourceforge.net/projects/libb64 6 | */ 7 | 8 | #ifndef BASE64_CDECODE_H 9 | #define BASE64_CDECODE_H 10 | 11 | typedef enum 12 | { 13 | step_a, step_b, step_c, step_d 14 | } base64_decodestep; 15 | 16 | typedef struct 17 | { 18 | base64_decodestep step; 19 | char plainchar; 20 | } base64_decodestate; 21 | 22 | void base64_init_decodestate(base64_decodestate* state_in); 23 | 24 | int base64_decode_value(char value_in); 25 | 26 | int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in); 27 | 28 | #endif /* BASE64_CDECODE_H */ 29 | -------------------------------------------------------------------------------- /src/disk_space.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | // for statfs() 34 | #include 35 | #include 36 | #ifdef __linux__ 37 | #include 38 | #endif 39 | 40 | #include "disk_space.hpp" 41 | 42 | namespace libtorrent 43 | { 44 | 45 | std::int64_t free_disk_space(std::string const& path) 46 | { 47 | // TODO: support windows 48 | 49 | struct statfs fs; 50 | int ret = statfs(path.c_str(), &fs); 51 | if (ret < 0) return -1; 52 | 53 | return std::int64_t(fs.f_bavail) * fs.f_bsize; 54 | } 55 | 56 | } 57 | 58 | -------------------------------------------------------------------------------- /src/disk_space.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TORRENT_DISK_SPACE_HPP 34 | #define TORRENT_DISK_SPACE_HPP 35 | 36 | #include 37 | #include 38 | 39 | namespace libtorrent 40 | { 41 | std::int64_t free_disk_space(std::string const& path); 42 | } 43 | 44 | #endif // TORRENT_DISK_SPACE_HPP 45 | 46 | -------------------------------------------------------------------------------- /src/error_logger.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2013, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TORRENT_ERROR_LOGGER_HPP 34 | #define TORRENT_ERROR_LOGGER_HPP 35 | 36 | #include "alert_observer.hpp" 37 | #include 38 | #include // for FILE 39 | 40 | namespace libtorrent 41 | { 42 | 43 | struct alert_handler; 44 | 45 | struct error_logger : libtorrent::alert_observer 46 | { 47 | error_logger(alert_handler* alerts, std::string const& log_file, bool redirect_stderr); 48 | ~error_logger(); 49 | 50 | void handle_alert(alert const* a); 51 | 52 | private: 53 | FILE* m_file; 54 | alert_handler* m_alerts; 55 | }; 56 | 57 | } 58 | 59 | #endif 60 | 61 | -------------------------------------------------------------------------------- /src/escape_json.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #include "escape_json.hpp" 42 | #include "libtorrent/assert.hpp" 43 | 44 | namespace libtorrent 45 | { 46 | 47 | std::string escape_json(string_view input) 48 | { 49 | if (input.empty()) return ""; 50 | std::string ret; 51 | for (auto const s : input) 52 | { 53 | if (s > 0x1f && s < 0x80 && s != '"' && s != '\\') 54 | { 55 | ret += s; 56 | } 57 | else 58 | { 59 | ret += '\\'; 60 | switch(s) 61 | { 62 | case '"': ret += '"'; break; 63 | case '\\': ret += '\\'; break; 64 | case '\n': ret += '\n'; break; 65 | default: 66 | { 67 | char buf[20]; 68 | snprintf(buf, sizeof(buf), "u%04x", std::uint16_t(s)); 69 | ret += buf; 70 | } 71 | } 72 | } 73 | } 74 | return ret; 75 | } 76 | 77 | } 78 | 79 | -------------------------------------------------------------------------------- /src/escape_json.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TORRENT_ESCAPE_JSON_HPP 34 | #define TORRENT_ESCAPE_JSON_HPP 35 | 36 | #include 37 | #include "libtorrent/string_view.hpp" 38 | 39 | namespace libtorrent 40 | { 41 | std::string escape_json(string_view in); 42 | } 43 | 44 | #endif 45 | 46 | -------------------------------------------------------------------------------- /src/file_downloader.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TORRENT_FILE_DOWNLOADER_HPP 34 | #define TORRENT_FILE_DOWNLOADER_HPP 35 | 36 | #include 37 | #include "webui.hpp" 38 | #include 39 | #include 40 | 41 | #include "libtorrent/fwd.hpp" 42 | 43 | namespace libtorrent 44 | { 45 | struct auth_interface; 46 | struct piece_alert_dispatch; 47 | struct request_t; 48 | 49 | struct file_downloader : http_handler 50 | { 51 | file_downloader(session& s, auth_interface const* auth = nullptr); 52 | 53 | virtual bool handle_http(mg_connection* conn, 54 | mg_request_info const* request_info); 55 | 56 | void set_disposition(bool attachment) { m_attachment = attachment; } 57 | void debug_print_requests() const; 58 | 59 | private: 60 | 61 | session& m_ses; 62 | auth_interface const* m_auth; 63 | 64 | std::shared_ptr m_dispatch; 65 | 66 | int m_queue_size; 67 | 68 | // controls the content disposition of files. Defaults to true 69 | // which asks the browser to save the file rather than to render it. 70 | bool m_attachment; 71 | 72 | mutable std::mutex m_mutex; 73 | std::set m_requests; 74 | }; 75 | } 76 | 77 | #endif 78 | 79 | -------------------------------------------------------------------------------- /src/file_requests.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2013, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #include 34 | 35 | #include "file_requests.hpp" 36 | 37 | #include "libtorrent/alert_types.hpp" 38 | #include "libtorrent/aux_/torrent.hpp" 39 | 40 | //#define DLOG printf 41 | #define DLOG if (false) printf 42 | 43 | using namespace libtorrent; 44 | 45 | std::size_t file_requests::hash_value(piece_request const& r) const 46 | { 47 | sha1_hash const& h = r.info_hash.get_best(); 48 | return (h[0] | (h[1] << 8) | (h[2] << 16) | (h[3] << 24)) ^ static_cast(r.piece); 49 | } 50 | 51 | file_requests::file_requests() 52 | : m_next_timeout(m_requests.begin()) 53 | { 54 | } 55 | 56 | void file_requests::on_alert(alert const* a) 57 | { 58 | read_piece_alert const* p = alert_cast(a); 59 | if (p) 60 | { 61 | std::shared_ptr t = p->handle.native_handle(); 62 | 63 | piece_request rq; 64 | rq.info_hash = t->info_hash(); 65 | rq.piece = p->piece; 66 | typedef requests_t::iterator iter; 67 | 68 | DLOG("read_piece_alert: %d (%s)\n", static_cast(p->piece), p->error.message().c_str()); 69 | std::unique_lock l(m_mutex); 70 | std::pair range = m_requests.equal_range(rq); 71 | if (range.first == m_requests.end()) return; 72 | 73 | piece_entry pe; 74 | pe.buffer = p->buffer; 75 | pe.piece = p->piece; 76 | pe.size = p->size; 77 | for (iter i = range.first; i != range.second; ++i) 78 | { 79 | i->promise->set_value(pe); 80 | if (m_next_timeout == i) 81 | ++m_next_timeout; 82 | } 83 | m_requests.erase(range.first, range.second); 84 | 85 | DLOG("outstanding requests: "); 86 | for (iter i = m_requests.begin(); i != m_requests.end(); ++i) 87 | { 88 | TORRENT_ASSERT(i->info_hash != rq.info_hash || i->piece != rq.piece); 89 | DLOG("(%02x%02x, %d) ", i->info_hash.get_best()[0], i->info_hash.get_best()[1], static_cast(i->piece)); 90 | } 91 | DLOG("\n"); 92 | return; 93 | } 94 | 95 | piece_finished_alert const* pf = alert_cast(a); 96 | if (pf) 97 | { 98 | DLOG("piece_finished: %d\n", static_cast(pf->piece_index)); 99 | std::shared_ptr t = pf->handle.native_handle(); 100 | piece_request rq; 101 | rq.info_hash = t->info_hash(); 102 | rq.piece = pf->piece_index; 103 | using iter = requests_t::iterator; 104 | m_have_pieces[rq.info_hash].insert(pf->piece_index); 105 | 106 | std::unique_lock l(m_mutex); 107 | std::pair range = m_requests.equal_range(rq); 108 | if (range.first == m_requests.end()) return; 109 | l.unlock(); 110 | 111 | DLOG("read_piece: %d\n", static_cast(pf->piece_index)); 112 | pf->handle.read_piece(pf->piece_index); 113 | return; 114 | } 115 | 116 | // if a torrent is stopped or removed, abort any piece requests 117 | piece_request rq; 118 | torrent_removed_alert const* tr = alert_cast(a); 119 | torrent_paused_alert const* tp = alert_cast(a); 120 | if (tr) 121 | { 122 | rq.info_hash = tr->info_hashes; 123 | } 124 | else if (tp) 125 | { 126 | rq.info_hash = tp->handle.info_hashes(); 127 | } 128 | else return; 129 | 130 | // remove all requests for the torrent 131 | rq.piece = piece_index_t{0}; 132 | typedef requests_t::iterator iter; 133 | 134 | std::unique_lock l(m_mutex); 135 | iter first = m_requests.lower_bound(rq); 136 | rq.piece = piece_index_t{INT_MAX}; 137 | iter last = m_requests.upper_bound(rq); 138 | if (first == last) return; 139 | 140 | for (iter i = first; i != last; ++i) 141 | { 142 | if (i != m_next_timeout) continue; 143 | m_next_timeout = last; 144 | break; 145 | } 146 | 147 | m_requests.erase(first, last); 148 | 149 | } 150 | 151 | void file_requests::on_tick() 152 | { 153 | std::unique_lock l(m_mutex); 154 | 155 | if (m_next_timeout == m_requests.end()) 156 | m_next_timeout = m_requests.begin(); 157 | 158 | auto const now = lt::clock_type::now(); 159 | 160 | if (m_next_timeout != m_requests.end()) 161 | { 162 | if (m_next_timeout->timeout < now) 163 | { 164 | auto to_remove = m_next_timeout; 165 | ++m_next_timeout; 166 | m_requests.erase(to_remove); 167 | } 168 | else 169 | { 170 | ++m_next_timeout; 171 | } 172 | } 173 | } 174 | 175 | std::shared_future file_requests::read_piece( 176 | torrent_handle const& h 177 | , lt::piece_index_t const piece 178 | , lt::clock_type::duration const timeout_ms) 179 | { 180 | TORRENT_ASSERT(piece >= piece_index_t{0}); 181 | TORRENT_ASSERT(piece < h.torrent_file()->end_piece()); 182 | 183 | piece_request rq; 184 | rq.info_hash = h.info_hashes(); 185 | rq.piece = piece; 186 | rq.promise.reset(new std::promise()); 187 | rq.timeout = lt::clock_type::now() + timeout_ms; 188 | 189 | std::unique_lock l(m_mutex); 190 | m_requests.insert(rq); 191 | l.unlock(); 192 | 193 | DLOG("piece_priority: %d <- 7\n", static_cast(piece)); 194 | h.piece_priority(piece, lt::top_priority); 195 | // h.set_piece_deadline(piece, 0, torrent_handle::alert_when_available); 196 | if (m_have_pieces[rq.info_hash].count(piece)) 197 | { 198 | DLOG("read_piece: %d\n", static_cast(piece)); 199 | h.read_piece(piece); 200 | } 201 | return std::shared_future(rq.promise->get_future()); 202 | } 203 | 204 | -------------------------------------------------------------------------------- /src/file_requests.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2013, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef FILE_REQUESTS_HPP_ 34 | #define FILE_REQUESTS_HPP_ 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #include // for mutex 42 | #include "libtorrent/torrent_handle.hpp" 43 | #include "libtorrent/peer_id.hpp" // for sha1_hash 44 | #include "libtorrent/extensions.hpp" // for plugin 45 | #include "libtorrent/time.hpp" // for time_point 46 | #include "libtorrent/info_hash.hpp" 47 | 48 | using lt::sha1_hash; 49 | using std::mutex; 50 | 51 | namespace libtorrent { 52 | 53 | struct piece_entry 54 | { 55 | boost::shared_array buffer; 56 | int size; 57 | piece_index_t piece; 58 | }; 59 | 60 | // this is a session plugin which wraps the concept of reading pieces 61 | // from torrents, returning futures for when those pieces are complete 62 | struct file_requests : lt::plugin 63 | { 64 | file_requests(); 65 | void on_alert(lt::alert const* a) override; 66 | void on_tick() override; 67 | std::shared_future read_piece(lt::torrent_handle const& h 68 | , lt::piece_index_t piece, lt::clock_type::duration timeout_ms); 69 | 70 | feature_flags_t implemented_features() override 71 | { return lt::plugin::alert_feature | lt::plugin::tick_feature; } 72 | 73 | private: 74 | 75 | struct piece_request 76 | { 77 | info_hash_t info_hash; 78 | lt::piece_index_t piece; 79 | std::shared_ptr > promise; 80 | lt::clock_type::time_point timeout; 81 | bool operator==(piece_request const& rq) const 82 | { return rq.info_hash == info_hash && rq.piece == piece; } 83 | bool operator<(piece_request const& rq) const 84 | { return info_hash == rq.info_hash ? piece < rq.piece : info_hash < rq.info_hash; } 85 | }; 86 | 87 | std::size_t hash_value(piece_request const& r) const; 88 | 89 | std::mutex m_mutex; 90 | typedef std::multiset requests_t; 91 | requests_t m_requests; 92 | requests_t::iterator m_next_timeout; 93 | 94 | // TOOD: figure out a way to clear out info-hashes 95 | std::map > m_have_pieces; 96 | }; 97 | 98 | } 99 | 100 | #endif // FILE_REQUESTS_HPP_ 101 | 102 | -------------------------------------------------------------------------------- /src/hex.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2017, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #include "hex.hpp" 34 | #include 35 | 36 | namespace libtorrent { 37 | 38 | int hex_to_int(char in) 39 | { 40 | if (in >= '0' && in <= '9') return int(in) - '0'; 41 | if (in >= 'A' && in <= 'F') return int(in) - 'A' + 10; 42 | if (in >= 'a' && in <= 'f') return int(in) - 'a' + 10; 43 | return -1; 44 | } 45 | 46 | bool is_hex(span in) 47 | { 48 | for (char const c : in) 49 | { 50 | int const t = hex_to_int(c); 51 | if (t == -1) return false; 52 | } 53 | return true; 54 | } 55 | 56 | bool from_hex(span in, char* out) 57 | { 58 | for (auto i = in.begin(), end = in.end(); i != end; ++i, ++out) 59 | { 60 | int const t1 = hex_to_int(*i); 61 | if (t1 == -1) return false; 62 | *out = char(t1 << 4); 63 | ++i; 64 | int const t2 = hex_to_int(*i); 65 | if (t2 == -1) return false; 66 | *out |= t2 & 15; 67 | } 68 | return true; 69 | } 70 | 71 | extern char const hex_chars[]; 72 | 73 | char const hex_chars[] = "0123456789abcdef"; 74 | void to_hex(char const* in, size_t const len, char* out) 75 | { 76 | int idx = 0; 77 | for (size_t i=0; i < len; ++i) 78 | { 79 | out[idx++] = hex_chars[std::uint8_t(in[i]) >> 4]; 80 | out[idx++] = hex_chars[std::uint8_t(in[i]) & 0xf]; 81 | } 82 | } 83 | 84 | std::string to_hex(span in) 85 | { 86 | std::string ret; 87 | if (!in.empty()) 88 | { 89 | ret.resize(in.size() * 2); 90 | to_hex(in.data(), in.size(), &ret[0]); 91 | } 92 | return ret; 93 | } 94 | 95 | void to_hex(span in, char* out) 96 | { 97 | to_hex(in.data(), in.size(), out); 98 | out[in.size() * 2] = '\0'; 99 | } 100 | 101 | } 102 | 103 | -------------------------------------------------------------------------------- /src/hex.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2017, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TORRENT_HEX_HPP 34 | #define TORRENT_HEX_HPP 35 | 36 | #include "libtorrent/span.hpp" 37 | #include "libtorrent/info_hash.hpp" 38 | #include 39 | #include 40 | 41 | namespace libtorrent { 42 | 43 | std::string to_hex(span in); 44 | void to_hex(span in, char* out); 45 | bool from_hex(span in, char* out); 46 | 47 | template 48 | typename std::enable_if::value, std::string>::type 49 | to_hex(T const& ih) 50 | { 51 | return to_hex(ih.get_best()); 52 | } 53 | 54 | } 55 | 56 | #endif 57 | 58 | -------------------------------------------------------------------------------- /src/http_whitelist.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2013, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #include "http_whitelist.hpp" 34 | #include "libtorrent/aux_/path.hpp" 35 | 36 | extern "C" { 37 | #include "local_mongoose.h" 38 | } 39 | 40 | namespace libtorrent 41 | { 42 | // TODO: get rid of these dependencies 43 | using lt::lsplit_path; 44 | 45 | http_whitelist::http_whitelist() {} 46 | http_whitelist::~http_whitelist() {} 47 | 48 | void http_whitelist::add_allowed_prefix(std::string const& prefix) 49 | { 50 | m_whitelist.insert(prefix); 51 | } 52 | 53 | bool http_whitelist::handle_http(mg_connection* conn 54 | , mg_request_info const* request_info) 55 | { 56 | std::string request = request_info->uri; 57 | const auto split = lsplit_path(request); 58 | std::string first_element(split.first); 59 | 60 | if (m_whitelist.count(first_element) == 0) 61 | { 62 | mg_printf(conn, "HTTP/1.1 404 Not Found\r\n" 63 | "Content-Length: 0\r\n\r\n"); 64 | return true; 65 | } 66 | 67 | // forward in the handler chain 68 | return false; 69 | } 70 | 71 | } 72 | 73 | -------------------------------------------------------------------------------- /src/http_whitelist.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2013, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #include "webui.hpp" 34 | #include 35 | #include 36 | 37 | namespace libtorrent 38 | { 39 | 40 | struct http_whitelist : http_handler 41 | { 42 | http_whitelist(); 43 | ~http_whitelist(); 44 | 45 | void add_allowed_prefix(std::string const& prefix); 46 | 47 | virtual bool handle_http(mg_connection* conn 48 | , mg_request_info const* request_info); 49 | 50 | private: 51 | 52 | std::set m_whitelist; 53 | }; 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/jsmn.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "jsmn.h" 4 | 5 | /** 6 | * Allocates a fresh unused token from the token pull. 7 | */ 8 | static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, 9 | jsmntok_t *tokens, size_t num_tokens) { 10 | unsigned int i; 11 | for (i = parser->toknext; i < num_tokens; i++) { 12 | if (tokens[i].start == -1 && tokens[i].end == -1) { 13 | parser->toknext = i + 1; 14 | return &tokens[i]; 15 | } 16 | } 17 | return NULL; 18 | } 19 | 20 | /** 21 | * Fills token type and boundaries. 22 | */ 23 | static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, 24 | int start, int end) { 25 | token->type = type; 26 | token->start = start; 27 | token->end = end; 28 | token->size = 0; 29 | } 30 | 31 | /** 32 | * Fills next available token with JSON primitive. 33 | */ 34 | static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, 35 | jsmntok_t *tokens, size_t num_tokens) { 36 | jsmntok_t *token; 37 | int start; 38 | 39 | start = parser->pos; 40 | 41 | for (; js[parser->pos] != '\0'; parser->pos++) { 42 | switch (js[parser->pos]) { 43 | #ifndef JSMN_STRICT 44 | /* In strict mode primitive must be followed by "," or "}" or "]" */ 45 | case '\t' : case '\r' : case '\n' : case ' ' : case ':': 46 | #endif 47 | case ',' : case ']' : case '}' : 48 | goto found; 49 | } 50 | if (js[parser->pos] < 32 || js[parser->pos] >= 127) { 51 | parser->pos = start; 52 | return JSMN_ERROR_INVAL; 53 | } 54 | } 55 | #ifdef JSMN_STRICT 56 | /* In strict mode primitive must be followed by a comma/object/array */ 57 | parser->pos = start; 58 | return JSMN_ERROR_PART; 59 | #endif 60 | 61 | found: 62 | token = jsmn_alloc_token(parser, tokens, num_tokens); 63 | if (token == NULL) { 64 | parser->pos = start; 65 | return JSMN_ERROR_NOMEM; 66 | } 67 | jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); 68 | parser->pos--; 69 | return JSMN_SUCCESS; 70 | } 71 | 72 | /** 73 | * Filsl next token with JSON string. 74 | */ 75 | static int jsmn_parse_string(jsmn_parser *parser, const char *js, 76 | jsmntok_t *tokens, size_t num_tokens) { 77 | jsmntok_t *token; 78 | 79 | int start = parser->pos; 80 | 81 | parser->pos++; 82 | 83 | /* Skip starting quote */ 84 | for (; js[parser->pos] != '\0'; parser->pos++) { 85 | char c = js[parser->pos]; 86 | 87 | /* Quote: end of string */ 88 | if (c == '\"') { 89 | token = jsmn_alloc_token(parser, tokens, num_tokens); 90 | if (token == NULL) { 91 | parser->pos = start; 92 | return JSMN_ERROR_NOMEM; 93 | } 94 | jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos); 95 | return JSMN_SUCCESS; 96 | } 97 | 98 | /* Backslash: Quoted symbol expected */ 99 | if (c == '\\') { 100 | parser->pos++; 101 | switch (js[parser->pos]) { 102 | /* Allowed escaped symbols */ 103 | case '\"': case '/' : case '\\' : case 'b' : 104 | case 'f' : case 'r' : case 'n' : case 't' : 105 | break; 106 | /* Allows escaped symbol \uXXXX */ 107 | case 'u': 108 | /* TODO */ 109 | break; 110 | /* Unexpected symbol */ 111 | default: 112 | parser->pos = start; 113 | return JSMN_ERROR_INVAL; 114 | } 115 | } 116 | } 117 | parser->pos = start; 118 | return JSMN_ERROR_PART; 119 | } 120 | 121 | /** 122 | * Parse JSON string and fill tokens. 123 | */ 124 | jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, jsmntok_t *tokens, 125 | unsigned int num_tokens) { 126 | int r; 127 | int i; 128 | jsmntok_t *token; 129 | 130 | /* initialize the rest of tokens (they could be reallocated) */ 131 | for (i = parser->toknext; i < num_tokens; i++) { 132 | jsmn_fill_token(&tokens[i], JSMN_PRIMITIVE, -1, -1); 133 | } 134 | 135 | for (; js[parser->pos] != '\0'; parser->pos++) { 136 | char c; 137 | jsmntype_t type; 138 | 139 | c = js[parser->pos]; 140 | switch (c) { 141 | case '{': case '[': 142 | token = jsmn_alloc_token(parser, tokens, num_tokens); 143 | if (token == NULL) 144 | return JSMN_ERROR_NOMEM; 145 | if (parser->toksuper != -1) 146 | tokens[parser->toksuper].size++; 147 | token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); 148 | token->start = parser->pos; 149 | parser->toksuper = parser->toknext - 1; 150 | break; 151 | case '}': case ']': 152 | type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); 153 | for (i = parser->toknext - 1; i >= 0; i--) { 154 | token = &tokens[i]; 155 | if (token->start != -1 && token->end == -1) { 156 | if (token->type != type) { 157 | return JSMN_ERROR_INVAL; 158 | } 159 | parser->toksuper = -1; 160 | token->end = parser->pos + 1; 161 | break; 162 | } 163 | } 164 | /* Error if unmatched closing bracket */ 165 | if (i == -1) return JSMN_ERROR_INVAL; 166 | for (; i >= 0; i--) { 167 | token = &tokens[i]; 168 | if (token->start != -1 && token->end == -1) { 169 | parser->toksuper = i; 170 | break; 171 | } 172 | } 173 | break; 174 | case '\"': 175 | r = jsmn_parse_string(parser, js, tokens, num_tokens); 176 | if (r < 0) return r; 177 | if (parser->toksuper != -1) 178 | tokens[parser->toksuper].size++; 179 | break; 180 | case '\t' : case '\r' : case '\n' : case ':' : case ',': case ' ': 181 | break; 182 | #ifdef JSMN_STRICT 183 | /* In strict mode primitives are: numbers and booleans */ 184 | case '-': case '0': case '1' : case '2': case '3' : case '4': 185 | case '5': case '6': case '7' : case '8': case '9': 186 | case 't': case 'f': case 'n' : 187 | #else 188 | /* In non-strict mode every unquoted value is a primitive */ 189 | default: 190 | #endif 191 | r = jsmn_parse_primitive(parser, js, tokens, num_tokens); 192 | if (r < 0) return r; 193 | if (parser->toksuper != -1) 194 | tokens[parser->toksuper].size++; 195 | break; 196 | 197 | #ifdef JSMN_STRICT 198 | /* Unexpected char in strict mode */ 199 | default: 200 | return JSMN_ERROR_INVAL; 201 | #endif 202 | 203 | } 204 | } 205 | 206 | for (i = parser->toknext - 1; i >= 0; i--) { 207 | /* Unmatched opened object or array */ 208 | if (tokens[i].start != -1 && tokens[i].end == -1) { 209 | return JSMN_ERROR_PART; 210 | } 211 | } 212 | 213 | return JSMN_SUCCESS; 214 | } 215 | 216 | /** 217 | * Creates a new parser based over a given buffer with an array of tokens 218 | * available. 219 | */ 220 | void jsmn_init(jsmn_parser *parser) { 221 | parser->pos = 0; 222 | parser->toknext = 0; 223 | parser->toksuper = -1; 224 | } 225 | 226 | -------------------------------------------------------------------------------- /src/jsmn.h: -------------------------------------------------------------------------------- 1 | #ifndef __JSMN_H_ 2 | #define __JSMN_H_ 3 | 4 | /** 5 | * JSON type identifier. Basic types are: 6 | * o Object 7 | * o Array 8 | * o String 9 | * o Other primitive: number, boolean (true/false) or null 10 | */ 11 | typedef enum { 12 | JSMN_PRIMITIVE = 0, 13 | JSMN_OBJECT = 1, 14 | JSMN_ARRAY = 2, 15 | JSMN_STRING = 3 16 | } jsmntype_t; 17 | 18 | typedef enum { 19 | /* Not enough tokens were provided */ 20 | JSMN_ERROR_NOMEM = -1, 21 | /* Invalid character inside JSON string */ 22 | JSMN_ERROR_INVAL = -2, 23 | /* The string is not a full JSON packet, more bytes expected */ 24 | JSMN_ERROR_PART = -3, 25 | /* Everything was fine */ 26 | JSMN_SUCCESS = 0 27 | } jsmnerr_t; 28 | 29 | /** 30 | * JSON token description. 31 | * @param type type (object, array, string etc.) 32 | * @param start start position in JSON data string 33 | * @param end end position in JSON data string 34 | */ 35 | typedef struct jsmntok_t { 36 | jsmntype_t type; 37 | int start; 38 | int end; 39 | int size; 40 | } jsmntok_t; 41 | 42 | /** 43 | * JSON parser. Contains an array of token blocks available. Also stores 44 | * the string being parsed now and current position in that string 45 | */ 46 | typedef struct { 47 | unsigned int pos; /* offset in the JSON string */ 48 | int toknext; /* next token to allocate */ 49 | int toksuper; /* suporior token node, e.g parent object or array */ 50 | } jsmn_parser; 51 | 52 | /** 53 | * Create JSON parser over an array of tokens 54 | */ 55 | void jsmn_init(jsmn_parser *parser); 56 | 57 | /** 58 | * Run JSON parser. It parses a JSON data string into and array of tokens, each describing 59 | * a single JSON object. 60 | */ 61 | jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, 62 | jsmntok_t *tokens, unsigned int num_tokens); 63 | 64 | #endif /* __JSMN_H_ */ 65 | -------------------------------------------------------------------------------- /src/json_util.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | 34 | #include "json_util.hpp" 35 | #include // for strcmp() 36 | #include // for strtoll() 37 | 38 | namespace libtorrent { 39 | 40 | // skip i. if i points to an object or an array, this function 41 | // needs to make recursive calls to skip its members too 42 | jsmntok_t* skip_item(jsmntok_t* i) 43 | { 44 | int n = i->size; 45 | ++i; 46 | // if it's a literal, just skip it, and we're done 47 | if (n == 0) return i; 48 | // if it's a container, we need to skip n items 49 | for (int k = 0; k < n; ++k) 50 | i = skip_item(i); 51 | return i; 52 | } 53 | 54 | jsmntok_t* find_key(jsmntok_t* tokens, char* buf, char const* key, int type) 55 | { 56 | if (tokens[0].type != JSMN_OBJECT) return NULL; 57 | // size is the number of tokens at the object level. 58 | // half of them are keys, the other half 59 | int num_keys = tokens[0].size / 2; 60 | // we skip two items at a time, first the key then the value 61 | for (jsmntok_t* i = &tokens[1]; num_keys > 0; i = skip_item(skip_item(i)), --num_keys) 62 | { 63 | if (i->type != JSMN_STRING) continue; 64 | buf[i->end] = 0; 65 | if (strcmp(key, buf + i->start)) continue; 66 | if (i[1].type != type) continue; 67 | return i + 1; 68 | } 69 | return NULL; 70 | } 71 | 72 | char const* find_string(jsmntok_t* tokens, char* buf, char const* key, bool* found) 73 | { 74 | jsmntok_t* k = find_key(tokens, buf, key, JSMN_STRING); 75 | if (k == NULL) 76 | { 77 | if (found) *found = false; 78 | return ""; 79 | } 80 | if (found) *found = true; 81 | buf[k->end] = '\0'; 82 | return buf + k->start; 83 | } 84 | 85 | std::int64_t find_int(jsmntok_t* tokens, char* buf, char const* key, bool* found) 86 | { 87 | jsmntok_t* k = find_key(tokens, buf, key, JSMN_PRIMITIVE); 88 | if (k == NULL) 89 | { 90 | if (found) *found = false; 91 | return 0; 92 | } 93 | buf[k->end] = '\0'; 94 | if (found) *found = true; 95 | return strtoll(buf + k->start, NULL, 10); 96 | } 97 | 98 | bool find_bool(jsmntok_t* tokens, char* buf, char const* key) 99 | { 100 | jsmntok_t* k = find_key(tokens, buf, key, JSMN_PRIMITIVE); 101 | if (k == NULL) return false; 102 | buf[k->end] = '\0'; 103 | return strcmp(buf + k->start, "true") == 0; 104 | } 105 | 106 | } 107 | 108 | -------------------------------------------------------------------------------- /src/json_util.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | 34 | #ifndef TORRENT_JSON_UTIL_HPP_ 35 | #define TORRENT_JSON_UTIL_HPP_ 36 | 37 | #include 38 | 39 | extern "C" { 40 | #include "jsmn.h" 41 | } 42 | 43 | #include 44 | 45 | namespace libtorrent { 46 | 47 | jsmntok_t* skip_item(jsmntok_t* i); 48 | jsmntok_t* find_key(jsmntok_t* tokens, char* buf, char const* key, int type); 49 | char const* find_string(jsmntok_t* tokens, char* buf, char const* key, bool* found = NULL); 50 | std::int64_t find_int(jsmntok_t* tokens, char* buf, char const* key, bool* found = NULL); 51 | bool find_bool(jsmntok_t* tokens, char* buf, char const* key); 52 | 53 | } 54 | 55 | #endif 56 | 57 | -------------------------------------------------------------------------------- /src/libtorrent_webui.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2013, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TORRENT_LIBTORRENT_WEBUI_HPP 34 | #define TORRENT_LIBTORRENT_WEBUI_HPP 35 | 36 | #include "websocket_handler.hpp" 37 | #include "torrent_history.hpp" // for frame_t 38 | #include "libtorrent/torrent_handle.hpp" 39 | #include "libtorrent/fwd.hpp" 40 | #include "alert_observer.hpp" 41 | #include 42 | 43 | struct mg_connection; 44 | 45 | namespace libtorrent 46 | { 47 | struct permissions_interface; 48 | struct torrent_history; 49 | struct auth_interface; 50 | struct alert_handler; 51 | 52 | struct libtorrent_webui : websocket_handler, alert_observer 53 | { 54 | libtorrent_webui(session& ses, torrent_history const* hist 55 | , auth_interface const* auth, alert_handler* alerts); 56 | ~libtorrent_webui(); 57 | 58 | virtual bool handle_websocket_connect(mg_connection* conn, 59 | mg_request_info const* request_info); 60 | virtual bool handle_websocket_data(mg_connection* conn 61 | , int bits, char* data, size_t length); 62 | 63 | struct conn_state 64 | { 65 | mg_connection* conn; 66 | int function_id; 67 | std::uint16_t transaction_id; 68 | char* data; 69 | int len; 70 | permissions_interface const* perms; 71 | }; 72 | 73 | void handle_alert(alert const* a) override; 74 | 75 | bool get_torrent_updates(conn_state* st); 76 | bool start(conn_state* st); 77 | bool stop(conn_state* st); 78 | bool set_auto_managed(conn_state* st); 79 | bool clear_auto_managed(conn_state* st); 80 | bool queue_up(conn_state* st); 81 | bool queue_down(conn_state* st); 82 | bool queue_top(conn_state* st); 83 | bool queue_bottom(conn_state* st); 84 | bool remove(conn_state* st); 85 | bool remove_and_data(conn_state* st); 86 | bool force_recheck(conn_state* st); 87 | bool set_sequential_download(conn_state* st); 88 | bool clear_sequential_download(conn_state* st); 89 | 90 | bool list_settings(conn_state* st); 91 | bool set_settings(conn_state* st); 92 | bool get_settings(conn_state* st); 93 | 94 | bool list_stats(conn_state* st); 95 | bool get_stats(conn_state* st); 96 | 97 | bool get_file_updates(conn_state* st); 98 | 99 | bool call_rpc(mg_connection* conn, int function, char const* data, int len); 100 | 101 | bool respond(conn_state* st, int error, int val); 102 | 103 | // respond with an error to an RPC 104 | bool error(conn_state* st, int error); 105 | 106 | enum error_t 107 | { 108 | no_error, 109 | no_such_function, 110 | invalid_number_of_args, 111 | invalid_argument_type, 112 | invalid_argument, 113 | truncated_message, 114 | resource_not_found 115 | }; 116 | 117 | private: 118 | 119 | // parse the arguments to the simple torrent commands 120 | template 121 | bool apply_torrent_fun(conn_state* st, Fun const& f); 122 | 123 | session& m_ses; 124 | torrent_history const* m_hist; 125 | auth_interface const* m_auth; 126 | alert_handler* m_alert; 127 | std::atomic m_transaction_id; 128 | 129 | std::mutex m_stats_mutex; 130 | // TODO: factor this out into its own class 131 | // the frame numbers where the stats counters changed 132 | std::vector > m_stats; 133 | // the current stats frame (incremented every time) stats 134 | // are requested 135 | frame_t m_stats_frame = 0; 136 | 137 | }; 138 | } 139 | 140 | #endif 141 | 142 | 143 | -------------------------------------------------------------------------------- /src/load_config.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2013, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include "libtorrent/settings_pack.hpp" 38 | #include "load_config.hpp" 39 | 40 | 41 | namespace libtorrent 42 | { 43 | 44 | // this function lets you load libtorrent configurations straight from a 45 | // simple text file, where each line is a key value pair. The keys are 46 | // the keys used by libtorrent. The values are either strings, integers 47 | // or booleans. 48 | void load_config(std::string const& config_file, settings_pack& p, error_code& ec) 49 | { 50 | static time_t last_load = 0; 51 | 52 | struct ::stat st; 53 | if (::stat(config_file.c_str(), &st) < 0) 54 | { 55 | ec = error_code(errno, system_category()); 56 | return; 57 | } 58 | 59 | // if the config file hasn't changed, don't do anything 60 | if (st.st_mtime == last_load) return; 61 | last_load = st.st_mtime; 62 | 63 | FILE* f = fopen(config_file.c_str(), "r"); 64 | if (f == NULL) 65 | { 66 | ec = error_code(errno, system_category()); 67 | return; 68 | } 69 | 70 | char key[512]; 71 | char value[512]; 72 | 73 | while (fscanf(f, "%512s %512s\n", key, value) == 2) 74 | { 75 | int setting_name = setting_by_name(key); 76 | if (setting_name < 0) continue; 77 | 78 | int type = setting_name & settings_pack::type_mask; 79 | switch (type) 80 | { 81 | case settings_pack::string_type_base: 82 | p.set_str(setting_name, value); 83 | break; 84 | case settings_pack::int_type_base: 85 | p.set_int(setting_name, atoi(value)); 86 | break; 87 | case settings_pack::bool_type_base: 88 | p.set_bool(setting_name, atoi(value)); 89 | break; 90 | }; 91 | } 92 | 93 | fclose(f); 94 | } 95 | 96 | } 97 | 98 | -------------------------------------------------------------------------------- /src/load_config.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2013, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TORRENT_LOAD_CONFIG_HPP 34 | #define TORRENT_LOAD_CONFIG_HPP 35 | 36 | #include 37 | 38 | #include "libtorrent/error_code.hpp" 39 | #include "libtorrent/fwd.hpp" 40 | 41 | namespace libtorrent 42 | { 43 | void load_config(std::string const& config_file, settings_pack& pack, error_code& ec); 44 | } 45 | 46 | #endif 47 | 48 | -------------------------------------------------------------------------------- /src/no_auth.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2013, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #include "auth_interface.hpp" 34 | #include "no_auth.hpp" 35 | 36 | namespace libtorrent 37 | { 38 | 39 | permissions_interface const* no_auth::find_user(std::string username, std::string password) const 40 | { 41 | const static full_permissions full_perms; 42 | return &full_perms; 43 | } 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /src/no_auth.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2013, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TORRENT_NO_AUTH_HPP 34 | #define TORRENT_NO_AUTH_HPP 35 | 36 | #include 37 | 38 | #include "auth_interface.hpp" 39 | 40 | namespace libtorrent 41 | { 42 | 43 | struct no_auth : auth_interface 44 | { 45 | no_auth() {} 46 | virtual permissions_interface const* find_user(std::string username, std::string password) const; 47 | }; 48 | 49 | } 50 | 51 | #endif // TORRENT_NO_AUTH_HPP 52 | 53 | -------------------------------------------------------------------------------- /src/pam_auth.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2013, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #include "pam_auth.hpp" 34 | #include 35 | #include "libtorrent/string_util.hpp" 36 | 37 | namespace libtorrent 38 | { 39 | pam_auth::pam_auth(std::string service_name) 40 | : m_service_name(service_name) 41 | {} 42 | 43 | pam_auth::~pam_auth() {} 44 | 45 | permissions_interface const* fail(int ret, pam_handle_t* h) 46 | { 47 | pam_end(h, ret); 48 | return NULL; 49 | } 50 | 51 | struct auth_context 52 | { 53 | std::string username; 54 | std::string password; 55 | }; 56 | 57 | int pam_conversation(int num_msgs, const struct pam_message** msg, struct pam_response** r, void* user) 58 | { 59 | auth_context* ctx = (auth_context*)user; 60 | 61 | if (num_msgs == 0) return PAM_SUCCESS; 62 | 63 | // allocate an array for responses. 64 | // memory freed is by PAM. 65 | *r = (pam_response*)calloc(num_msgs, sizeof(pam_response)); 66 | if (*r == NULL) return PAM_BUF_ERR; 67 | 68 | for (int i = 0; i < num_msgs; ++i) 69 | { 70 | switch (msg[i]->msg_style) 71 | { 72 | // echo on is code for "username" 73 | case PAM_PROMPT_ECHO_ON: 74 | r[i]->resp = allocate_string_copy(ctx->username.c_str()); 75 | break; 76 | 77 | // echo off is code for "password" 78 | case PAM_PROMPT_ECHO_OFF: 79 | r[i]->resp = allocate_string_copy(ctx->password.c_str()); 80 | break; 81 | 82 | case PAM_ERROR_MSG: 83 | fprintf(stderr, "authentication error: %s\n", msg[i]->msg); 84 | break; 85 | 86 | case PAM_TEXT_INFO: 87 | fprintf(stderr, "auth: %s\n", msg[i]->msg); 88 | break; 89 | } 90 | } 91 | return PAM_SUCCESS; 92 | } 93 | 94 | permissions_interface const* pam_auth::find_user(std::string username, std::string password) const 95 | { 96 | pam_handle_t* handle; 97 | 98 | auth_context ctx; 99 | ctx.username = username; 100 | ctx.password = password; 101 | 102 | pam_conv c; 103 | c.conv = &pam_conversation; 104 | c.appdata_ptr = &ctx; 105 | int ret = pam_start(m_service_name.c_str(), username.c_str(), &c, &handle); 106 | if (ret != PAM_SUCCESS) return fail(ret, handle); 107 | 108 | ret = pam_set_item(handle, PAM_RUSER, (void *)username.c_str()); 109 | if (ret != PAM_SUCCESS) return fail(ret, handle); 110 | 111 | ret = pam_set_item(handle, PAM_RHOST, "localhost"); 112 | if (ret != PAM_SUCCESS) return fail(ret, handle); 113 | 114 | ret = pam_authenticate(handle, 0); 115 | if (ret != PAM_SUCCESS) return fail(ret, handle); 116 | 117 | ret = pam_acct_mgmt(handle, 0); 118 | if (ret != PAM_SUCCESS) return fail(ret, handle); 119 | 120 | pam_end(handle, ret); 121 | 122 | std::map::const_iterator i = m_users.find(username); 123 | if (i != m_users.end()) return i->second; 124 | 125 | static full_permissions full; 126 | return m_perms ? m_perms : &full; 127 | } 128 | 129 | } 130 | 131 | -------------------------------------------------------------------------------- /src/pam_auth.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2013, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TORRENT_PAM_AUTH_HPP 34 | #define TORRENT_PAM_AUTH_HPP 35 | 36 | #include "auth_interface.hpp" 37 | #include 38 | #include 39 | 40 | namespace libtorrent 41 | { 42 | struct pam_auth : auth_interface 43 | { 44 | pam_auth(std::string service_name); 45 | ~pam_auth(); 46 | 47 | // these are the permissions the user receives 48 | // if successfully authenticated 49 | void set_permissions(permissions_interface* perms) { m_perms = perms; } 50 | 51 | void set_user_permissions(std::string username, permissions_interface* p) 52 | { m_users[username] = p; } 53 | 54 | permissions_interface const* find_user(std::string username, std::string password) const; 55 | 56 | private: 57 | 58 | permissions_interface* m_perms; 59 | std::string m_service_name; 60 | // if some users have different permissions than the default 61 | // users, they have an entry in this map. Users not in this 62 | // map that successfully authenticate will still get the 63 | // default permissions in m_perms (which defaults to full permissions) 64 | std::map m_users; 65 | }; 66 | } 67 | 68 | #endif 69 | 70 | -------------------------------------------------------------------------------- /src/rencode.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TORRENT_RENCODE_HPP 34 | #define TORRENT_RENCODE_HPP 35 | 36 | #include 37 | #include 38 | #include 39 | 40 | namespace libtorrent { 41 | 42 | enum renc_type_t 43 | { 44 | type_integer = 0, 45 | type_string = 1, 46 | type_list = 2, 47 | type_dict = 3, 48 | type_float = 4, 49 | type_none = 5, 50 | type_bool = 6 51 | }; 52 | 53 | struct rtok_t 54 | { 55 | friend int rdecode(rtok_t* tokens, int num_tokens, char const* buffer, int len); 56 | friend int decode_token(char const* buffer, char const*& cursor, rtok_t* tokens, int num_tokens); 57 | 58 | renc_type_t type() const; 59 | // parse out the value of an integer 60 | std::int64_t integer(char const* buffer) const; 61 | // parse out the value of a string 62 | std::string string(char const* buffer) const; 63 | bool boolean(char const* buffer) const; 64 | double floating_point(char const* buffer) const; 65 | int num_items() const { return m_num_items; } 66 | private: 67 | int m_offset; 68 | std::uint8_t m_typecode; 69 | // for dicts, this is the number of key-value pairs 70 | // for lists, this is the number of elements 71 | std::uint16_t m_num_items; 72 | }; 73 | 74 | int rdecode(rtok_t* tokens, int num_tokens, char const* buffer, int len); 75 | 76 | int print_rtok(rtok_t const* tokens, char const* buf); 77 | 78 | rtok_t* skip_item(rtok_t* i); 79 | inline rtok_t const* skip_item(rtok_t const* i) { return skip_item((rtok_t*)i); } 80 | 81 | rtok_t* find_key(rtok_t* tokens, char* buf, char const* key, int type); 82 | std::string find_string(rtok_t* tokens, char* buf, char const* key, bool* found); 83 | std::int64_t find_int(rtok_t* tokens, char* buf, char const* key, bool* found); 84 | bool find_bool(rtok_t* tokens, char* buf, char const* key); 85 | 86 | bool validate_structure(rtok_t const* tokens, char const* fmt); 87 | 88 | struct rencoder 89 | { 90 | bool append_list(int size = -1); 91 | bool append_dict(int size = -1); 92 | void append_int(std::int64_t i); 93 | void append_float(float f); 94 | void append_none(); 95 | void append_bool(bool b); 96 | void append_string(std::string const& s); 97 | void append_term(); 98 | 99 | char const* data() const { return &m_buffer[0]; } 100 | int len() const { return m_buffer.size(); } 101 | 102 | void clear() { m_buffer.clear(); } 103 | private: 104 | std::vector m_buffer; 105 | }; 106 | 107 | } 108 | 109 | #endif 110 | 111 | -------------------------------------------------------------------------------- /src/response_buffer.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TORRENT_RESPONSE_BUFFER_HPP 34 | #define TORRENT_RESPONSE_BUFFER_HPP 35 | 36 | #include 37 | #include 38 | 39 | namespace libtorrent 40 | { 41 | inline void appendf(std::vector& target, char const* fmt, ...) 42 | { 43 | char* buf; 44 | va_list args; 45 | va_start(args, fmt); 46 | int len = vasprintf(&buf, fmt, args); 47 | va_end(args); 48 | 49 | if (len < 0) return; 50 | 51 | target.insert(target.end(), buf, buf + len); 52 | free(buf); 53 | } 54 | } 55 | 56 | #endif 57 | 58 | -------------------------------------------------------------------------------- /src/save_resume.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TORRENT_SAVE_RESUME_HPP 34 | #define TORRENT_SAVE_RESUME_HPP 35 | 36 | #include "libtorrent/session.hpp" 37 | #include "libtorrent/error_code.hpp" 38 | #include "alert_observer.hpp" 39 | 40 | #include 41 | #include 42 | #include 43 | 44 | #include 45 | 46 | namespace libtorrent 47 | { 48 | struct alert_handler; 49 | 50 | struct save_resume : alert_observer 51 | { 52 | save_resume(session& s, std::string const& resume_file, alert_handler* alerts); 53 | ~save_resume(); 54 | 55 | void load(error_code& ec, add_torrent_params model); 56 | 57 | // implements alert_observer 58 | virtual void handle_alert(alert const* a); 59 | 60 | void save_all(); 61 | bool ok_to_quit() const; 62 | 63 | private: 64 | 65 | session& m_ses; 66 | alert_handler* m_alerts; 67 | sqlite3* m_db; 68 | 69 | // all torrents currently loaded 70 | std::unordered_set m_torrents; 71 | 72 | // the next torrent to save (may point to end) 73 | std::unordered_set::iterator m_cursor; 74 | 75 | // the last time we visited a torrent to potentially 76 | // save its fast-resume 77 | time_point m_last_save; 78 | 79 | // save resum data for all torrents every X seconds 80 | // must be at least 1 81 | time_duration m_interval; 82 | 83 | int m_num_in_flight; 84 | 85 | // when set, we stop saving periodically, and just wait 86 | // for all outstanding saves to return. 87 | bool m_shutting_down; 88 | }; 89 | } 90 | 91 | #endif 92 | 93 | -------------------------------------------------------------------------------- /src/save_settings.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #include "save_settings.hpp" 34 | 35 | #include 36 | #include 37 | #include // for boost::tie 38 | 39 | #include "libtorrent/add_torrent_params.hpp" 40 | #include "libtorrent/session.hpp" 41 | #include "libtorrent/error_code.hpp" 42 | #include "libtorrent/entry.hpp" 43 | #include "libtorrent/bencode.hpp" 44 | #include "libtorrent/aux_/path.hpp" 45 | 46 | namespace libtorrent 47 | { 48 | 49 | // TODO: get rid of these dependencies 50 | using lt::exists; 51 | using lt::remove; 52 | 53 | std::vector load_file(char const* filename) 54 | { 55 | std::ifstream ifs(filename, std::ios_base::binary); 56 | ifs.unsetf(std::ios_base::skipws); 57 | return {std::istream_iterator(ifs), std::istream_iterator()}; 58 | } 59 | 60 | int save_file(std::string const& filename, std::vector const& v) 61 | { 62 | std::fstream f(filename, std::ios_base::trunc | std::ios_base::out | std::ios_base::binary); 63 | f.write(v.data(), v.size()); 64 | return !f.fail(); 65 | } 66 | 67 | save_settings::save_settings(session& s, settings_pack const& sett 68 | , std::string const& settings_file) 69 | : m_ses(s) 70 | , m_settings_file(settings_file) 71 | { 72 | for (int i = settings_pack::string_type_base; 73 | i < settings_pack::string_type_base 74 | + settings_pack::num_string_settings; ++i) 75 | { 76 | if (!sett.has_val(i)) continue; 77 | m_strings[name_for_setting(i)] = sett.get_str(i); 78 | } 79 | for (int i = settings_pack::bool_type_base; 80 | i < settings_pack::bool_type_base 81 | + settings_pack::num_bool_settings; ++i) 82 | { 83 | if (!sett.has_val(i)) continue; 84 | m_ints[name_for_setting(i)] = sett.get_bool(i); 85 | } 86 | for (int i = settings_pack::int_type_base; 87 | i < settings_pack::int_type_base 88 | + settings_pack::num_int_settings; ++i) 89 | { 90 | if (!sett.has_val(i)) continue; 91 | m_ints[name_for_setting(i)] = sett.get_int(i); 92 | } 93 | } 94 | 95 | save_settings::~save_settings() {} 96 | 97 | void save_settings::save(error_code& ec) const 98 | { 99 | // back-up current settings file as .bak before saving the new one 100 | std::string backup = m_settings_file + ".bak"; 101 | bool const has_settings = exists(m_settings_file, ec); 102 | bool const has_backup = exists(backup, ec); 103 | 104 | if (has_settings && has_backup) 105 | remove(backup, ec); 106 | 107 | if (has_settings) 108 | rename(m_settings_file, backup, ec); 109 | 110 | ec.clear(); 111 | 112 | entry sett; 113 | m_ses.save_state(sett); 114 | 115 | for (auto const& i : m_ints) 116 | { 117 | sett[i.first] = i.second; 118 | } 119 | 120 | for (auto const& i : m_strings) 121 | { 122 | sett[i.first] = i.second; 123 | } 124 | std::vector buf; 125 | bencode(std::back_inserter(buf), sett); 126 | save_file(m_settings_file, buf); 127 | } 128 | 129 | namespace { 130 | void load_settings_impl(session_params& params, std::string const& filename 131 | , error_code& ec) 132 | { 133 | ec.clear(); 134 | std::vector buf = load_file(filename.c_str()); 135 | 136 | bdecode_node sett = bdecode(buf, ec); 137 | if (ec) return; 138 | 139 | // load the custom int and string keys 140 | if (sett.type() != bdecode_node::dict_t) return; 141 | 142 | bdecode_node dht = sett.dict_find_dict("dht"); 143 | if (dht) 144 | { 145 | params.dht_settings = dht::read_dht_settings(dht); 146 | } 147 | 148 | bdecode_node dht_state = sett.dict_find_dict("dht state"); 149 | if (dht_state) 150 | { 151 | params.dht_state = dht::read_dht_state(dht_state); 152 | } 153 | 154 | int num_items = sett.dict_size(); 155 | for (int i = 0; i < num_items; ++i) 156 | { 157 | bdecode_node item; 158 | string_view key; 159 | boost::tie(key, item) = sett.dict_at(i); 160 | 161 | int const n = setting_by_name(std::string(key)); 162 | if (n < 0) continue; 163 | if ((n & settings_pack::type_mask) == settings_pack::int_type_base) 164 | { 165 | if (item.type() != bdecode_node::int_t) continue; 166 | params.settings.set_int(n, item.int_value()); 167 | } 168 | else if ((n & settings_pack::type_mask) == settings_pack::bool_type_base) 169 | { 170 | if (item.type() != bdecode_node::int_t) continue; 171 | params.settings.set_bool(n, item.int_value() != 0); 172 | } 173 | else if ((n & settings_pack::type_mask) == settings_pack::string_type_base) 174 | { 175 | if (item.type() != bdecode_node::string_t) continue; 176 | params.settings.set_str(n, std::string(item.string_value())); 177 | } 178 | } 179 | } 180 | } 181 | 182 | void load_settings(session_params& params 183 | , std::string const& filename 184 | , error_code& ec) 185 | { 186 | ec.clear(); 187 | load_settings_impl(params, filename, ec); 188 | if (!ec) return; 189 | std::string const backup = filename + ".bak"; 190 | load_settings_impl(params, backup, ec); 191 | } 192 | 193 | void save_settings::set_int(char const* key, int val) 194 | { 195 | m_ints[key] = val; 196 | } 197 | 198 | void save_settings::set_str(char const* key, std::string val) 199 | { 200 | m_strings[key] = val; 201 | } 202 | 203 | int save_settings::get_int(char const* key, int def) const 204 | { 205 | std::map::const_iterator i = m_ints.find(key); 206 | if (i == m_ints.end()) return def; 207 | return i->second; 208 | } 209 | 210 | std::string save_settings::get_str(char const* key, char const* def) const 211 | { 212 | auto const i = m_strings.find(key); 213 | if (i == m_strings.end()) return def; 214 | return i->second; 215 | } 216 | 217 | } 218 | 219 | -------------------------------------------------------------------------------- /src/save_settings.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TORRENT_SAVE_SETTINGS_HPP 34 | #define TORRENT_SAVE_SETTINGS_HPP 35 | 36 | #include "libtorrent/session.hpp" 37 | #include 38 | #include "libtorrent/error_code.hpp" 39 | 40 | #include 41 | #include 42 | 43 | namespace libtorrent 44 | { 45 | struct save_settings_interface 46 | { 47 | virtual void save(error_code& ec) const = 0; 48 | virtual void set_int(char const* key, int val) = 0; 49 | virtual void set_str(char const* key, std::string val) = 0; 50 | virtual int get_int(char const* key, int def = 0) const = 0; 51 | virtual std::string get_str(char const* key, char const* def = "") const = 0; 52 | }; 53 | 54 | struct save_settings : save_settings_interface 55 | { 56 | save_settings(session& s, settings_pack const& sp 57 | , std::string const& settings_file); 58 | ~save_settings(); 59 | 60 | void save(error_code& ec) const; 61 | 62 | void set_int(char const* key, int val); 63 | void set_str(char const* key, std::string val); 64 | 65 | int get_int(char const* key, int def) const; 66 | std::string get_str(char const* key, char const* def = "") const; 67 | 68 | private: 69 | 70 | session& m_ses; 71 | std::string m_settings_file; 72 | std::map m_ints; 73 | std::map m_strings; 74 | }; 75 | 76 | void load_settings(session_params& params, std::string const& filename 77 | , error_code& ec); 78 | 79 | std::vector load_file(char const* filename); 80 | int save_file(std::string const& filename, std::vector const& v); 81 | 82 | } 83 | 84 | #endif 85 | 86 | -------------------------------------------------------------------------------- /src/stats_logging.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2014, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #include 34 | #include 35 | 36 | #include "stats_logging.hpp" 37 | #include "libtorrent/session.hpp" 38 | #include "alert_handler.hpp" 39 | #include "libtorrent/session_stats.hpp" 40 | #include "libtorrent/aux_/path.hpp" 41 | 42 | namespace libtorrent { 43 | 44 | using namespace std::placeholders; 45 | 46 | // TODO: get rid of these dependencies 47 | using lt::create_directories; 48 | 49 | stats_logging::stats_logging(session& s, alert_handler* h) 50 | : m_alerts(h) 51 | , m_ses(s) 52 | , m_stats_logger(NULL) 53 | , m_log_seq(0) 54 | { 55 | m_alerts->subscribe(this, 0 56 | , session_stats_alert::alert_type 57 | , stats_alert::alert_type 58 | , 0); 59 | rotate_stats_log(); 60 | } 61 | 62 | stats_logging::~stats_logging() 63 | { 64 | m_alerts->unsubscribe(this); 65 | } 66 | 67 | void stats_logging::rotate_stats_log() 68 | { 69 | if (m_stats_logger) 70 | { 71 | ++m_log_seq; 72 | fclose(m_stats_logger); 73 | } 74 | 75 | error_code ec; 76 | char filename[100]; 77 | create_directory("session_stats", ec); 78 | #ifdef TORRENT_WINDOWS 79 | const int pid = GetCurrentProcessId(); 80 | #else 81 | const int pid = getpid(); 82 | #endif 83 | snprintf(filename, sizeof(filename), "session_stats/%d.%04d.log", pid, m_log_seq); 84 | m_stats_logger = fopen(filename, "w+"); 85 | m_last_log_rotation = lt::clock_type::now(); 86 | if (m_stats_logger == 0) 87 | { 88 | fprintf(stderr, "Failed to create session stats log file \"%s\": (%d) %s\n" 89 | , filename, errno, strerror(errno)); 90 | return; 91 | } 92 | 93 | std::vector cnts = session_stats_metrics(); 94 | std::sort(cnts.begin(), cnts.end() 95 | , [](stats_metric const& lhs, stats_metric const& rhs) 96 | { return lhs.value_index < rhs.value_index; }); 97 | 98 | int idx = 0; 99 | fputs("second", m_stats_logger); 100 | for (auto const c : cnts) 101 | { 102 | // just in case there are some indices that don't have names 103 | // (it shouldn't really happen) 104 | while (idx < c.value_index) 105 | { 106 | fprintf(m_stats_logger, ":"); 107 | ++idx; 108 | } 109 | 110 | fprintf(m_stats_logger, ":%s", c.name); 111 | ++idx; 112 | } 113 | fputs("\n\n", m_stats_logger); 114 | } 115 | 116 | void stats_logging::handle_alert(alert const* a) 117 | { 118 | session_stats_alert const* s = alert_cast(a); 119 | 120 | if (s == NULL) 121 | { 122 | m_ses.post_session_stats(); 123 | return; 124 | } 125 | 126 | if (lt::clock_type::now() - m_last_log_rotation > hours(1)) 127 | rotate_stats_log(); 128 | 129 | fprintf(m_stats_logger, "%f", double(total_microseconds(s->timestamp() - m_last_log_rotation)) / 1000000.0); 130 | for (auto const v : s->counters()) 131 | fprintf(m_stats_logger, "\t%" PRId64, v); 132 | fprintf(m_stats_logger, "\n"); 133 | } 134 | 135 | } 136 | 137 | -------------------------------------------------------------------------------- /src/stats_logging.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2014, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TORRENT_STATS_LOGGING_HPP 34 | #define TORRENT_STATS_LOGGING_HPP 35 | 36 | #include "alert_observer.hpp" 37 | #include "libtorrent/time.hpp" 38 | #include "libtorrent/fwd.hpp" 39 | #include 40 | 41 | namespace libtorrent 42 | { 43 | struct alert_handler; 44 | 45 | /// writes logs to directory 'session_stats' in current working directory. 46 | /// logs are rotated each hour. Use parse_session_stats.py to parse logs. 47 | struct stats_logging : alert_observer 48 | { 49 | stats_logging(session& s, alert_handler* h); 50 | ~stats_logging(); 51 | 52 | private: 53 | 54 | void rotate_stats_log(); 55 | void handle_alert(alert const* a); 56 | 57 | alert_handler* m_alerts; 58 | 59 | // the last time we rotated the log file 60 | time_point m_last_log_rotation; 61 | 62 | session& m_ses; 63 | 64 | FILE* m_stats_logger; 65 | // sequence number for log file. Log files are 66 | // rotated every hour and the sequence number is 67 | // incremented by one 68 | int m_log_seq; 69 | }; 70 | 71 | } 72 | 73 | #endif 74 | 75 | -------------------------------------------------------------------------------- /src/text_ui.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2014, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #include "text_ui.hpp" 34 | #include "libtorrent/alert_types.hpp" 35 | 36 | #include "alert_handler.hpp" 37 | 38 | extern "C" { 39 | #include 40 | #include 41 | } 42 | 43 | namespace libtorrent 44 | { 45 | 46 | screen::screen() 47 | { 48 | WINDOW* scr = initscr(); 49 | m_screen = initCDKScreen(scr); 50 | initCDKColor(); 51 | } 52 | 53 | screen::~screen() 54 | { 55 | eraseCDKScreen(m_screen); 56 | endCDK(); 57 | } 58 | 59 | int screen::width() const 60 | { 61 | int h, w; 62 | getmaxyx(m_screen->window, h, w); 63 | return w; 64 | } 65 | 66 | int screen::height() const 67 | { 68 | int h, w; 69 | getmaxyx(m_screen->window, h, w); 70 | return h; 71 | } 72 | 73 | void screen::refresh() 74 | { 75 | refreshCDKScreen(m_screen); 76 | } 77 | 78 | log_window::log_window(screen& scr, int x, int y, int w, int h) 79 | : m_win(newCDKSwindow(scr.native_handle(), x, y, h, w, "", 100, 1, 0)) 80 | { 81 | } 82 | 83 | log_window::~log_window() 84 | { 85 | destroyCDKSwindow(m_win); 86 | } 87 | 88 | int log_window::width() const 89 | { 90 | int h, w; 91 | getmaxyx(m_win->win, h, w); 92 | return w; 93 | } 94 | 95 | int log_window::height() const 96 | { 97 | int h, w; 98 | getmaxyx(m_win->win, h, w); 99 | return h; 100 | } 101 | 102 | void log_window::set_pos(int x, int y, int w, int h) 103 | { 104 | wresize(m_win->win, w, h); 105 | moveCDKSwindow(m_win, x, y, 1, 0); 106 | } 107 | 108 | void log_window::log_line(std::string l) 109 | { 110 | addCDKSwindow(m_win, (char*)l.c_str(), BOTTOM); 111 | } 112 | 113 | error_log::error_log(screen& scr, int x, int y, int w, int h 114 | , alert_handler* alerts) 115 | : log_window(scr, x, y, w, h) 116 | , m_alerts(alerts) 117 | { 118 | m_alerts->subscribe(this, 0 119 | , add_torrent_alert::alert_type 120 | , rss_alert::alert_type 121 | , read_piece_alert::alert_type 122 | , mmap_cache_alert::alert_type 123 | , dht_error_alert::alert_type 124 | , torrent_need_cert_alert::alert_type 125 | , file_rename_failed_alert::alert_type 126 | , tracker_error_alert::alert_type 127 | , scrape_failed_alert::alert_type 128 | , storage_moved_failed_alert::alert_type 129 | , torrent_delete_failed_alert::alert_type 130 | , save_resume_data_failed_alert::alert_type 131 | , url_seed_alert::alert_type 132 | , file_error_alert::alert_type 133 | , metadata_failed_alert::alert_type 134 | , udp_error_alert::alert_type 135 | , listen_failed_alert::alert_type 136 | , portmap_error_alert::alert_type 137 | , fastresume_rejected_alert::alert_type 138 | , torrent_error_alert::alert_type, 0); 139 | } 140 | 141 | void error_log::handle_alert(alert const* a) 142 | { 143 | // we're just interested in errors 144 | read_piece_alert const* rpa = alert_cast(a); 145 | if (rpa && !rpa->ec) return; 146 | 147 | add_torrent_alert const* ata = alert_cast(a); 148 | if (ata && !ata->error) return; 149 | 150 | rss_alert const* ra = alert_cast(a); 151 | if (ra && !ra->error) return; 152 | 153 | log_line(a->message()); 154 | } 155 | 156 | error_log::~error_log() 157 | { 158 | m_alerts->unsubscribe(this); 159 | } 160 | 161 | } 162 | 163 | -------------------------------------------------------------------------------- /src/text_ui.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2014, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TORRENT_TEXT_UI_HPP 34 | #define TORRENT_TEXT_UI_HPP 35 | 36 | #include 37 | #include "alert_observer.hpp" 38 | 39 | extern "C" { 40 | #include 41 | #include 42 | } 43 | 44 | namespace libtorrent 45 | { 46 | struct alert_handler; 47 | 48 | struct screen 49 | { 50 | screen(); 51 | ~screen(); 52 | 53 | CDKSCREEN* native_handle() { return m_screen; } 54 | 55 | int width() const; 56 | int height() const; 57 | 58 | void refresh(); 59 | private: 60 | CDKSCREEN* m_screen; 61 | }; 62 | 63 | struct window 64 | { 65 | virtual int width() const = 0; 66 | virtual int height() const = 0; 67 | virtual void set_pos(int x, int y, int width, int height) = 0; 68 | virtual ~window() {} 69 | }; 70 | 71 | struct log_window : window 72 | { 73 | log_window(screen& scr, int x, int y, int width, int height); 74 | ~log_window(); 75 | 76 | void log_line(std::string l); 77 | 78 | CDKSWINDOW* native_handle() { return m_win; } 79 | 80 | virtual int width() const; 81 | virtual int height() const; 82 | virtual void set_pos(int x, int y, int width, int height); 83 | private: 84 | CDKSWINDOW* m_win; 85 | }; 86 | 87 | struct error_log : log_window, alert_observer 88 | { 89 | error_log(screen& scr, int x, int y, int width, int height 90 | , alert_handler* alerts); 91 | ~error_log(); 92 | 93 | private: 94 | virtual void handle_alert(alert const* a); 95 | alert_handler* m_alerts; 96 | }; 97 | 98 | struct torrent_list : window, alert_observer 99 | { 100 | 101 | private: 102 | virtual void handle_alert(alert const* a); 103 | alert_handler* m_alerts; 104 | }; 105 | } 106 | 107 | #endif 108 | 109 | -------------------------------------------------------------------------------- /src/torrent_history.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TORRENT_TORRENT_HISTORY_HPP 34 | #define TORRENT_TORRENT_HISTORY_HPP 35 | 36 | #include "alert_observer.hpp" 37 | #include "libtorrent/torrent_status.hpp" 38 | #include // for mutex 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | namespace libtorrent 45 | { 46 | struct alert_handler; 47 | 48 | using frame_t = std::uint32_t; 49 | 50 | // this is the type that keeps track of frame counters for each 51 | // field in torrent_status. The frame counters indicate which frame 52 | // they were last modified in. This is used to send minimal updates 53 | // of changes to torrents. 54 | struct torrent_history_entry 55 | { 56 | // this is the current state of the torrent 57 | torrent_status status; 58 | 59 | void update_status(torrent_status const& s, frame_t frame); 60 | 61 | bool operator==(torrent_history_entry const& e) const { return e.status.info_hash == status.info_hash; } 62 | 63 | enum 64 | { 65 | state, 66 | flags, 67 | is_seeding, 68 | is_finished, 69 | has_metadata, 70 | progress, 71 | progress_ppm, 72 | errc, 73 | error_file, 74 | save_path, 75 | name, 76 | next_announce, 77 | current_tracker, 78 | total_download, 79 | total_upload, 80 | total_payload_download, 81 | total_payload_upload, 82 | total_failed_bytes, 83 | total_redundant_bytes, 84 | download_rate, 85 | upload_rate, 86 | download_payload_rate, 87 | upload_payload_rate, 88 | num_seeds, 89 | num_peers, 90 | num_complete, 91 | num_incomplete, 92 | list_seeds, 93 | list_peers, 94 | connect_candidates, 95 | num_pieces, 96 | total_done, 97 | total, 98 | total_wanted_done, 99 | total_wanted, 100 | distributed_full_copies, 101 | distributed_fraction, 102 | block_size, 103 | num_uploads, 104 | num_connections, 105 | num_undead_peers, 106 | uploads_limit, 107 | connections_limit, 108 | storage_mode, 109 | up_bandwidth_queue, 110 | down_bandwidth_queue, 111 | all_time_upload, 112 | all_time_download, 113 | active_duration, 114 | finished_duration, 115 | seeding_duration, 116 | seed_rank, 117 | has_incoming, 118 | added_time, 119 | completed_time, 120 | last_seen_complete, 121 | last_upload, 122 | last_download, 123 | queue_position, 124 | moving_storage, 125 | announcing_to_trackers, 126 | announcing_to_lsd, 127 | announcing_to_dht, 128 | 129 | num_fields, 130 | }; 131 | 132 | // these are the frames each individual field was last changed 133 | std::array frame; 134 | 135 | torrent_history_entry() {} 136 | 137 | torrent_history_entry(torrent_status const& st, frame_t const f) 138 | : status(st) 139 | { 140 | frame.fill(f); 141 | } 142 | 143 | void debug_print(frame_t current_frame) const; 144 | }; 145 | 146 | inline std::size_t hash_value(torrent_history_entry const& te) 147 | { return std::hash{}(te.status.info_hash); } 148 | 149 | struct torrent_history : alert_observer 150 | { 151 | 152 | torrent_history(alert_handler* h); 153 | ~torrent_history(); 154 | 155 | // returns the info-hashes of the torrents that have been 156 | // removed since the specified frame number 157 | void removed_since(frame_t frame, std::vector& torrents) const; 158 | 159 | // returns the torrent_status structures for the torrents 160 | // that have changed since the specified frame number 161 | void updated_since(frame_t frame, std::vector& torrents) const; 162 | 163 | void updated_fields_since(frame_t frame, std::vector& torrents) const; 164 | 165 | torrent_status get_torrent_status(sha1_hash const& ih) const; 166 | 167 | // the current frame number 168 | frame_t frame() const; 169 | 170 | virtual void handle_alert(alert const* a); 171 | 172 | private: 173 | 174 | // first is the frame this torrent was last 175 | // seen modified in, second is the information 176 | // about the torrent that was modified 177 | typedef boost::bimap 178 | , boost::bimaps::unordered_set_of > queue_t; 179 | 180 | mutable std::mutex m_mutex; 181 | 182 | queue_t m_queue; 183 | 184 | std::deque > m_removed; 185 | 186 | alert_handler* m_alerts; 187 | 188 | // frame counter. This is incremented every 189 | // time we get a status update for torrents 190 | mutable frame_t m_frame; 191 | 192 | // if we haven't gotten any status updates 193 | // but we have received add or delete alerts, 194 | // we increment the frame counter on access, 195 | // in order to make added and deleted event also 196 | // fall into distinct time-slots, instead of being 197 | // potentially returned twice, once when they 198 | // happen and once after we've received an 199 | // update and increment the frame counter 200 | mutable bool m_deferred_frame_count; 201 | }; 202 | } 203 | 204 | #endif 205 | 206 | -------------------------------------------------------------------------------- /src/torrent_post.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #include "torrent_post.hpp" 34 | #include "transmission_webui.hpp" 35 | #include "libtorrent/aux_/http_parser.hpp" // for http_parser 36 | #include "libtorrent/torrent_info.hpp" 37 | 38 | extern "C" { 39 | #include "local_mongoose.h" 40 | } 41 | 42 | using namespace libtorrent; 43 | 44 | bool parse_torrent_post(mg_connection* conn, add_torrent_params& params, error_code& ec) 45 | { 46 | char const* cl = mg_get_header(conn, "content-length"); 47 | if (cl == nullptr) return false; 48 | 49 | std::vector post_body; 50 | 51 | int content_length = atoi(cl); 52 | if (content_length <= 0) 53 | { 54 | ec = error_code(boost::system::errc::invalid_argument, boost::system::generic_category()); 55 | return false; 56 | } 57 | 58 | if (content_length > 10 * 1024 * 1024) 59 | { 60 | ec = error_code(boost::system::errc::file_too_large, boost::system::generic_category()); 61 | return false; 62 | } 63 | 64 | post_body.resize(content_length + 1); 65 | // minus one here since we shouldn't read the null terminator 66 | mg_read(conn, &post_body[0], content_length); 67 | post_body[content_length] = 0; 68 | // null terminate 69 | 70 | // expect a multipart message here 71 | char const* content_type = mg_get_header(conn, "content-type"); 72 | if (strstr(content_type, "multipart/form-data") == nullptr) return false; 73 | 74 | char const* boundary = strstr(content_type, "boundary="); 75 | if (boundary == nullptr) return false; 76 | 77 | boundary += 9; 78 | 79 | char const* body_end = &post_body[0] + content_length; 80 | 81 | char const* part_start = strstr(&post_body[0], boundary); 82 | if (part_start == nullptr) return false; 83 | 84 | part_start += strlen(boundary); 85 | char const* part_end = nullptr; 86 | 87 | // loop through all parts 88 | for(; part_start < body_end; part_start = (std::min)(body_end, part_end + strlen(boundary))) 89 | { 90 | part_end = strstr(part_start, boundary); 91 | if (part_end == nullptr) part_end = body_end; 92 | 93 | aux::http_parser part; 94 | bool error = false; 95 | part.incoming(span(part_start, part_end - part_start), error); 96 | /* 97 | std::multimap const& part_headers = part.headers(); 98 | for (std::multimap::const_iterator i = part_headers.begin() 99 | , end(part_headers.end()); i != end; ++i) 100 | { 101 | printf(" %s: %s\n", i->first.c_str(), i->second.c_str()); 102 | } 103 | */ 104 | std::string const& disposition = part.header("content-type"); 105 | if (disposition != "application/octet-stream" 106 | && disposition != "application/x-bittorrent") continue; 107 | 108 | char const* torrent_start = part.get_body().data(); 109 | params.ti = std::make_shared(span{torrent_start, part_end - torrent_start}, ec, from_span); 110 | if (ec) return false; 111 | return true; 112 | } 113 | 114 | return false; 115 | } 116 | 117 | -------------------------------------------------------------------------------- /src/torrent_post.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TORRENT_TORRENT_POST_HPP 34 | #define TORRENT_TORRENT_POST_HPP 35 | 36 | #include "webui.hpp" 37 | #include "libtorrent/session.hpp" 38 | #include "libtorrent/error_code.hpp" 39 | #include "libtorrent/add_torrent_params.hpp" 40 | 41 | bool parse_torrent_post(mg_connection* conn, libtorrent::add_torrent_params& p, libtorrent::error_code& ec); 42 | 43 | #endif 44 | 45 | -------------------------------------------------------------------------------- /src/utorrent_webui.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TORRENT_UT_WEBUI_HPP 34 | #define TORRENT_UT_WEBUI_HPP 35 | 36 | #include "webui.hpp" 37 | #include "libtorrent/torrent_handle.hpp" 38 | #include "libtorrent/add_torrent_params.hpp" 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | namespace libtorrent 45 | { 46 | struct auto_load; 47 | struct save_settings_interface; 48 | struct torrent_history; 49 | struct permissions_interface; 50 | struct auth_interface; 51 | 52 | struct utorrent_webui : http_handler 53 | { 54 | utorrent_webui(session& s, save_settings_interface* sett = NULL 55 | , auto_load* al = NULL, torrent_history* hist = NULL 56 | , auth_interface const* auth = NULL); 57 | ~utorrent_webui(); 58 | 59 | void set_params_model(add_torrent_params const& p) 60 | { m_params_model = p; } 61 | 62 | virtual bool handle_http(mg_connection* conn 63 | , mg_request_info const* request_info); 64 | 65 | void start(std::vector&, char const* args, permissions_interface const* p); 66 | void stop(std::vector&, char const* args, permissions_interface const* p); 67 | void force_start(std::vector&, char const* args, permissions_interface const* p); 68 | void recheck(std::vector&, char const* args, permissions_interface const* p); 69 | void remove_torrent(std::vector&, char const* args, permissions_interface const* p); 70 | void remove_torrent_and_data(std::vector&, char const* args, permissions_interface const* p); 71 | void list_dirs(std::vector&, char const* args, permissions_interface const* p); 72 | void set_file_priority(std::vector&, char const* args, permissions_interface const* p); 73 | 74 | void queue_up(std::vector&, char const* args, permissions_interface const* p); 75 | void queue_down(std::vector&, char const* args, permissions_interface const* p); 76 | void queue_top(std::vector&, char const* args, permissions_interface const* p); 77 | void queue_bottom(std::vector&, char const* args, permissions_interface const* p); 78 | 79 | void get_settings(std::vector&, char const* args, permissions_interface const* p); 80 | void set_settings(std::vector&, char const* args, permissions_interface const* p); 81 | 82 | void get_properties(std::vector&, char const* args, permissions_interface const* p); 83 | void add_url(std::vector&, char const* args, permissions_interface const* p); 84 | 85 | void send_file_list(std::vector&, char const* args, permissions_interface const* p); 86 | void send_torrent_list(std::vector&, char const* args, permissions_interface const* p); 87 | void send_peer_list(std::vector& response, char const* args, permissions_interface const* p); 88 | 89 | void get_version(std::vector& response, char const* args, permissions_interface const* p); 90 | 91 | void send_rss_list(std::vector&, char const* args, permissions_interface const* p); 92 | /* 93 | void rss_update(std::vector& response, char const* args, permissions_interface const* p); 94 | void rss_remove(std::vector& response, char const* args, permissions_interface const* p); 95 | void rss_filter_update(std::vector& response, char const* args, permissions_interface const* p); 96 | void rss_filter_remove(std::vector& response, char const* args, permissions_interface const* p); 97 | */ 98 | private: 99 | 100 | std::vector parse_torrents(char const* args) const; 101 | template 102 | void apply_fun(char const* args, Fun const& f); 103 | 104 | time_t m_start_time; 105 | session& m_ses; 106 | add_torrent_params m_params_model; 107 | std::string m_webui_cookie; 108 | 109 | // optional auto loader, controllable 110 | // via webui settings 111 | auto_load* m_al; 112 | 113 | auth_interface const* m_auth; 114 | 115 | save_settings_interface* m_settings; 116 | 117 | // a list of the most recent rss filter rules that were 118 | // removed. first = cid, second rss_ident. 119 | std::deque > m_removed_rss_filters; 120 | 121 | // used to detect which torrents have been updated 122 | // since last time 123 | torrent_history* m_hist; 124 | 125 | int m_version; 126 | std::string m_token; 127 | webui_base* m_listener; 128 | }; 129 | } 130 | 131 | #endif 132 | 133 | -------------------------------------------------------------------------------- /src/websocket_handler.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2013, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #include "websocket_handler.hpp" 34 | #include "libtorrent/aux_/io_bytes.hpp" 35 | #include "local_mongoose.h" 36 | 37 | namespace libtorrent 38 | { 39 | // TODO: this should be a writev-like function 40 | bool websocket_handler::send_packet(mg_connection* conn, int type, char const* buffer, int len) 41 | { 42 | std::unique_lock l(m_mutex); 43 | 44 | namespace io = libtorrent::aux; 45 | 46 | auto i = m_open_sockets.find(conn); 47 | if (i == m_open_sockets.end()) 48 | { 49 | fprintf(stderr, "ERROR: send_packet, socket not open\n"); 50 | return false; 51 | } 52 | std::mutex& m = *i->second; 53 | std::unique_lock l2(m); 54 | l.unlock(); 55 | 56 | // header 57 | int header_len = 2; 58 | std::uint8_t h[20]; 59 | h[0] = 0x80 | (type & 0xf); 60 | if (len < 126) 61 | h[1] = len; 62 | else if (len < 65536) 63 | { 64 | h[1] = 126; 65 | std::uint8_t* ptr = &h[2]; 66 | io::write_uint16(len, ptr); 67 | header_len = 4; 68 | } 69 | else 70 | { 71 | h[1] = 127; 72 | std::uint8_t* ptr = &h[2]; 73 | io::write_uint64(len, ptr); 74 | header_len = 10; 75 | } 76 | 77 | // TODO: it would be nice to have an mg_writev() 78 | int ret = mg_write(conn, h, header_len); 79 | if (ret < header_len) 80 | { 81 | fprintf(stderr, "ERROR: send_packet, short write (%d < %d)\n", ret, header_len); 82 | return false; 83 | } 84 | 85 | if (len > 0) 86 | { 87 | ret = mg_write(conn, buffer, len); 88 | if (ret < len) 89 | { 90 | fprintf(stderr, "ERROR: send_packet, short write (%d < %d)\n", ret, len); 91 | return false; 92 | } 93 | } 94 | return true; 95 | } 96 | 97 | bool websocket_handler::handle_websocket_connect(mg_connection* conn 98 | , mg_request_info const* request_info) 99 | { 100 | std::unique_lock l(m_mutex); 101 | m_open_sockets.insert(std::make_pair(conn, std::unique_ptr(new std::mutex()))); 102 | return true; 103 | } 104 | 105 | // TODO: it would be nice to have a layer that merges fragments. 106 | // there need to be a number of fragments per frame limit and 107 | // a total size limit per frame 108 | // This layer should also handle ping messages 109 | // bool libtorrent_webui::handle_websocket_data(mg_connection* conn 110 | // , int bits, char* data, size_t length) 111 | // { 112 | // } 113 | 114 | void websocket_handler::handle_end_request(mg_connection* conn) 115 | { 116 | std::unique_lock l(m_mutex); 117 | auto i = m_open_sockets.find(conn); 118 | if (i == m_open_sockets.end()) return; 119 | 120 | m_open_sockets.erase(i); 121 | } 122 | } 123 | 124 | -------------------------------------------------------------------------------- /src/websocket_handler.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2013, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TORRENT_WEBSOCKET_HPP 34 | #define TORRENT_WEBSOCKET_HPP 35 | 36 | #include "webui.hpp" 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | namespace libtorrent 43 | { 44 | struct websocket_handler : http_handler 45 | { 46 | bool send_packet(mg_connection* conn, int type, char const* buffer, int len); 47 | virtual bool handle_websocket_connect(mg_connection* conn, 48 | mg_request_info const* request_info); 49 | virtual void handle_end_request(mg_connection* conn); 50 | 51 | private: 52 | 53 | // all currently alive web sockets 54 | std::map> m_open_sockets; 55 | 56 | // serialize access to the map itself 57 | std::mutex m_mutex; 58 | 59 | }; 60 | } 61 | 62 | #endif 63 | 64 | -------------------------------------------------------------------------------- /src/webui.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #include 34 | #include // for getopt_long 35 | #include // for daemon() 36 | #include 37 | #include 38 | 39 | #include "libtorrent/session.hpp" 40 | #include "libtorrent/alert_types.hpp" 41 | #include "webui.hpp" 42 | 43 | extern "C" { 44 | #include "local_mongoose.h" 45 | } 46 | 47 | using namespace libtorrent; 48 | 49 | static int handle_http_request(mg_connection* conn) 50 | { 51 | const mg_request_info *request_info = mg_get_request_info(conn); 52 | if (request_info->user_data == nullptr) return 0; 53 | 54 | return reinterpret_cast(request_info->user_data)->handle_http( 55 | conn, request_info); 56 | } 57 | 58 | static int log_message(const mg_connection*, const char* msg) 59 | { 60 | fprintf(stderr, "%s\n", msg); 61 | return 1; 62 | } 63 | 64 | // return 1 to disconnect 65 | static int websocket_connect(mg_connection const* c) 66 | { 67 | mg_connection* conn = const_cast(c); 68 | const mg_request_info *request_info = mg_get_request_info(conn); 69 | if (request_info->user_data == nullptr) 70 | return 1; 71 | 72 | return reinterpret_cast(request_info->user_data)->handle_websocket_connect( 73 | conn, request_info) ? 0 : 1; 74 | } 75 | 76 | // return 0 to disconnect 77 | static int websocket_data(mg_connection* conn, int bits 78 | , char *data, size_t data_len) 79 | { 80 | const mg_request_info *request_info = mg_get_request_info(conn); 81 | if (request_info->user_data == nullptr) 82 | return 0; 83 | 84 | return reinterpret_cast(request_info->user_data)->handle_websocket_data( 85 | conn, bits, data, data_len) ? 1 : 0; 86 | } 87 | 88 | static void end_request(mg_connection const* c, int reply_status_code) 89 | { 90 | mg_connection* conn = const_cast(c); 91 | const mg_request_info *request_info = mg_get_request_info(conn); 92 | if (request_info->user_data == nullptr) return; 93 | 94 | reinterpret_cast(request_info->user_data)->handle_end_request(conn); 95 | } 96 | 97 | webui_base::webui_base() {} 98 | webui_base::~webui_base() {} 99 | 100 | void webui_base::remove_handler(http_handler* h) 101 | { 102 | auto i = std::find(m_handlers.begin(), m_handlers.end(), h); 103 | if (i != m_handlers.end()) m_handlers.erase(i); 104 | } 105 | 106 | bool webui_base::handle_http(mg_connection* conn 107 | , mg_request_info const* request_info) 108 | { 109 | for (auto* h : m_handlers) 110 | if (h->handle_http(conn, request_info)) return true; 111 | return false; 112 | } 113 | 114 | bool webui_base::handle_websocket_connect(mg_connection* conn 115 | , mg_request_info const* request_info) 116 | { 117 | for (auto* h : m_handlers) 118 | if (h->handle_websocket_connect(conn, request_info)) return true; 119 | return false; 120 | } 121 | 122 | bool webui_base::handle_websocket_data(mg_connection* conn 123 | , int bits, char* data, size_t data_len) 124 | { 125 | for (auto* h : m_handlers) 126 | if (h->handle_websocket_data(conn, bits, data, data_len)) return true; 127 | return false; 128 | } 129 | 130 | void webui_base::handle_end_request(mg_connection* conn) 131 | { 132 | for (auto* h : m_handlers) 133 | h->handle_end_request(conn); 134 | } 135 | 136 | bool webui_base::is_running() const 137 | { 138 | return m_ctx; 139 | } 140 | 141 | void webui_base::start(int port, char const* cert_path, int num_threads) 142 | { 143 | if (m_ctx) mg_stop(m_ctx); 144 | 145 | m_listen_port = port; 146 | 147 | // start web interface 148 | char port_str[20]; 149 | snprintf(port_str, sizeof(port_str), "%d%s", port, cert_path ? "s" : ""); 150 | const char *options[20]; 151 | memset(options, 0, sizeof(options)); 152 | int i = 0; 153 | options[i++] = "document_root"; 154 | options[i++] = m_document_root.c_str(); 155 | options[i++] = "enable_keep_alive"; 156 | options[i++] = "yes"; 157 | if (cert_path) 158 | { 159 | options[i++] = "ssl_certificate"; 160 | options[i++] = cert_path; 161 | } 162 | options[i++] = "listening_ports"; 163 | options[i++] = port_str; 164 | 165 | char threads_str[20]; 166 | snprintf(threads_str, sizeof(threads_str), "%d", num_threads); 167 | options[i++] = "num_threads"; 168 | options[i++] = threads_str; 169 | options[i++] = nullptr; 170 | 171 | mg_callbacks cb; 172 | memset(&cb, 0, sizeof(cb)); 173 | cb.begin_request = &handle_http_request; 174 | cb.log_message = &log_message; 175 | cb.websocket_connect = &websocket_connect; 176 | cb.websocket_data = &websocket_data; 177 | cb.end_request = &end_request; 178 | 179 | m_ctx = mg_start(&cb, this, options); 180 | } 181 | 182 | void webui_base::stop() 183 | { 184 | if (m_ctx) mg_stop(m_ctx); 185 | m_ctx = nullptr; 186 | } 187 | 188 | -------------------------------------------------------------------------------- /src/webui.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TORRENT_WEBUI_HPP 34 | #define TORRENT_WEBUI_HPP 35 | 36 | #include 37 | #include 38 | #include "libtorrent/fwd.hpp" 39 | 40 | struct mg_context; 41 | struct mg_connection; 42 | struct mg_request_info; 43 | 44 | struct http_handler 45 | { 46 | virtual bool handle_http(mg_connection* conn, 47 | mg_request_info const* request_info) { return false; } 48 | virtual bool handle_websocket_connect(mg_connection* conn, 49 | mg_request_info const* request_info) { return false; } 50 | virtual bool handle_websocket_data(mg_connection* conn 51 | , int bits, char* data, size_t length) { return false; } 52 | virtual void handle_end_request(mg_connection* conn) {} 53 | }; 54 | 55 | namespace libtorrent 56 | { 57 | struct webui_base 58 | { 59 | webui_base(); 60 | ~webui_base(); 61 | 62 | void add_handler(http_handler* h) 63 | { m_handlers.push_back(h); } 64 | 65 | void remove_handler(http_handler* h); 66 | 67 | void start(int port, char const* cert_path = 0, int num_threads = 10); 68 | void stop(); 69 | bool is_running() const; 70 | 71 | bool handle_http(mg_connection* conn 72 | , mg_request_info const* request_info); 73 | bool handle_websocket_connect(mg_connection* conn 74 | , mg_request_info const* request_info); 75 | bool handle_websocket_data(mg_connection* conn, int bits, char* data, size_t length); 76 | void handle_end_request(mg_connection* conn); 77 | 78 | void set_document_root(std::string r) { m_document_root = r; } 79 | 80 | int listen_port() const { return m_listen_port; } 81 | 82 | private: 83 | 84 | std::vector m_handlers; 85 | std::string m_document_root = "."; 86 | 87 | mg_context* m_ctx = nullptr; 88 | int m_listen_port; 89 | }; 90 | 91 | } 92 | 93 | #endif 94 | 95 | -------------------------------------------------------------------------------- /test.cpp: -------------------------------------------------------------------------------- 1 | #include "utorrent_webui.hpp" 2 | #include "libtorrent_webui.hpp" 3 | #include "file_downloader.hpp" 4 | #include "auto_load.hpp" 5 | #include "save_settings.hpp" 6 | #include "save_resume.hpp" 7 | #include "torrent_history.hpp" 8 | #include "auth.hpp" 9 | #include "pam_auth.hpp" 10 | //#include "text_ui.hpp" 11 | 12 | #include "libtorrent/session.hpp" 13 | #include "alert_handler.hpp" 14 | #include "stats_logging.hpp" 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | bool quit = false; 22 | bool force_quit = false; 23 | 24 | void sighandler(int s) 25 | { 26 | quit = true; 27 | } 28 | 29 | void sighandler_forcequit(int s) 30 | { 31 | force_quit = true; 32 | } 33 | 34 | using namespace libtorrent; 35 | 36 | namespace lt = libtorrent; 37 | 38 | struct external_ip_observer : alert_observer 39 | { 40 | external_ip_observer(lt::session& s, alert_handler* h) 41 | : m_alerts(h) 42 | , m_ses(s) 43 | { 44 | m_alerts->subscribe(this, 0, external_ip_alert::alert_type, 0); 45 | } 46 | 47 | ~external_ip_observer() 48 | { 49 | m_alerts->unsubscribe(this); 50 | } 51 | 52 | void handle_alert(alert const* a) 53 | { 54 | external_ip_alert const* ip = alert_cast(a); 55 | if (ip == NULL) return; 56 | 57 | error_code ec; 58 | printf("EXTERNAL IP: %s\n", ip->external_address.to_string().c_str()); 59 | 60 | if (m_last_known_addr != address() 61 | && m_last_known_addr != ip->external_address) 62 | { 63 | // our external IP changed. stop the session. 64 | printf("pausing session\n"); 65 | m_ses.pause(); 66 | return; 67 | } 68 | 69 | if (m_ses.is_paused() && m_last_known_addr == ip->external_address) 70 | { 71 | printf("resuming session\n"); 72 | m_ses.resume(); 73 | return; 74 | } 75 | 76 | m_last_known_addr = ip->external_address; 77 | } 78 | 79 | alert_handler* m_alerts; 80 | lt::session& m_ses; 81 | address m_last_known_addr; 82 | }; 83 | 84 | int main(int argc, char *const argv[]) 85 | { 86 | session_params s; 87 | error_code ec; 88 | s.settings.set_str(settings_pack::listen_interfaces, "0.0.0.0:6881"); 89 | s.settings.set_int(settings_pack::alert_mask, 0xffffffff); 90 | 91 | load_settings(s, "settings.dat", ec); 92 | if (ec) std::cout << "Failed to load settings: " << ec.message() << '\n'; 93 | 94 | lt::session ses(s); 95 | 96 | alert_handler alerts(ses); 97 | 98 | save_settings sett(ses, s.settings, "settings.dat"); 99 | 100 | torrent_history hist(&alerts); 101 | auth authorizer; 102 | ec.clear(); 103 | authorizer.load_accounts("users.conf", ec); 104 | if (ec) 105 | authorizer.add_account("admin", "test", 0); 106 | ec.clear(); 107 | // pam_auth authorizer("bittorrent"); 108 | 109 | save_resume resume(ses, "resume.dat", &alerts); 110 | add_torrent_params p; 111 | p.save_path = sett.get_str("save_path", "."); 112 | resume.load(ec, p); 113 | 114 | // external_ip_observer eip(ses, &alerts); 115 | 116 | auto_load al(ses, &sett); 117 | 118 | utorrent_webui ut_handler(ses, &sett, &al, &hist, &authorizer); 119 | file_downloader file_handler(ses, &authorizer); 120 | libtorrent_webui lt_handler(ses, &hist, &authorizer, &alerts); 121 | stats_logging log(ses, &alerts); 122 | 123 | webui_base webport; 124 | webport.add_handler(<_handler); 125 | webport.add_handler(&ut_handler); 126 | webport.add_handler(&file_handler); 127 | webport.start(8090, "server.pem"); 128 | if (!webport.is_running()) 129 | { 130 | fprintf(stderr, "failed to start web server\n"); 131 | return 1; 132 | } 133 | 134 | signal(SIGTERM, &sighandler); 135 | signal(SIGINT, &sighandler); 136 | 137 | bool shutting_down = false; 138 | while (!quit || !resume.ok_to_quit()) 139 | { 140 | std::this_thread::sleep_for(std::chrono::milliseconds(500)); 141 | alerts.dispatch_alerts(); 142 | if (!shutting_down) ses.post_torrent_updates(); 143 | if (quit && !shutting_down) 144 | { 145 | resume.save_all(); 146 | shutting_down = true; 147 | fprintf(stderr, "saving resume data\n"); 148 | signal(SIGTERM, &sighandler_forcequit); 149 | signal(SIGINT, &sighandler_forcequit); 150 | } 151 | if (force_quit) 152 | { 153 | fprintf(stderr, "force quitting\n"); 154 | break; 155 | } 156 | } 157 | 158 | fprintf(stderr, "abort alerts\n"); 159 | // it's important to disable any more alert subscriptions 160 | // and cancel the ones in flught now, otherwise the webport 161 | // may dead-lock. Some of its threads may be blocked waiting 162 | // for alerts. Those alerts aren't likely to ever arrive at 163 | // this point. 164 | alerts.abort(); 165 | fprintf(stderr, "closing web server\n"); 166 | webport.stop(); 167 | 168 | fprintf(stderr, "saving settings\n"); 169 | sett.save(ec); 170 | 171 | fprintf(stderr, "destructing session\n"); 172 | return 0; 173 | } 174 | 175 | -------------------------------------------------------------------------------- /test_range.py: -------------------------------------------------------------------------------- 1 | import urllib2 2 | import sys 3 | 4 | url = sys.argv[1] 5 | 6 | r = urllib2.Request(url) 7 | resp = urllib2.urlopen(r) 8 | data = resp.read(8192) 9 | f = open('single_request', 'wb+') 10 | while len(data) > 0: 11 | f.write(data) 12 | data = resp.read(8192) 13 | full_size = int(resp.info()['Content-Length']) 14 | f.close() 15 | 16 | print 'file size: %d' % full_size 17 | 18 | f = open('multi_request', 'wb+') 19 | rng = 1 20 | start = 0 21 | while full_size > 0: 22 | r = urllib2.Request(url) 23 | rng = min(rng, full_size) 24 | r.add_header('Range', 'bytes=%d-%d' % (start, start + rng - 1)) 25 | print '%d-%d' % (start, start + rng - 1) 26 | full_size -= rng 27 | start += rng 28 | resp = urllib2.urlopen(r) 29 | data = resp.read(8192) 30 | 31 | request_size = 0 32 | while len(data) > 0: 33 | request_size += len(data) 34 | f.write(data) 35 | data = resp.read(8192) 36 | 37 | print 'received %d bytes' % request_size 38 | if request_size != rng: 39 | print 'received %d bytes, expected %d' % (request_size, rng) 40 | print 'http status: %d' % (resp.getcode()) 41 | print resp.info() 42 | break 43 | 44 | rng *= 2 45 | 46 | f.close() 47 | 48 | -------------------------------------------------------------------------------- /tests/Jamfile: -------------------------------------------------------------------------------- 1 | import testing ; 2 | 3 | use-project /torrent : ../../libtorrent_aio ; 4 | use-project /torrent-webui : .. ; 5 | 6 | project 7 | : requirements 8 | /torrent//torrent 9 | /torrent-webui//torrent-webui 10 | # main.cpp 11 | : default-build 12 | multi 13 | on 14 | ; 15 | 16 | test-suite libtorrent : 17 | [ run test_rencode.cpp ] 18 | [ run test_rss_filter.cpp ] 19 | ; 20 | 21 | 22 | -------------------------------------------------------------------------------- /tests/test.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #ifndef TEST_HPP 34 | #define TEST_HPP 35 | 36 | extern int main_ret; 37 | 38 | #define TEST_CHECK(cond) \ 39 | if (!(cond)) { \ 40 | fprintf(stderr, "ERROR: (%s:%d) %s\n", __FILE__, __LINE__, #cond); \ 41 | ++main_ret; \ 42 | } 43 | 44 | #endif 45 | 46 | -------------------------------------------------------------------------------- /tests/test_rencode.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #include "rencode.hpp" 34 | 35 | #include "test.hpp" 36 | 37 | enum renc_typecode 38 | { 39 | CHR_LIST = 59, 40 | CHR_DICT = 60, 41 | CHR_INT = 61, 42 | CHR_INT1 = 62, 43 | CHR_INT2 = 63, 44 | CHR_INT4 = 64, 45 | CHR_INT8 = 65, 46 | CHR_FLOAT32 = 66, 47 | CHR_FLOAT64 = 44, 48 | CHR_TRUE = 67, 49 | CHR_FALSE = 68, 50 | CHR_NONE = 69, 51 | CHR_TERM = 127, 52 | // Positive integers with value embedded in typecode. 53 | INT_POS_FIXED_START = 0, 54 | INT_POS_FIXED_COUNT = 44, 55 | // Dictionaries with length embedded in typecode. 56 | DICT_FIXED_START = 102, 57 | DICT_FIXED_COUNT = 25, 58 | // Negative integers with value embedded in typecode. 59 | INT_NEG_FIXED_START = 70, 60 | INT_NEG_FIXED_COUNT = 32, 61 | // Strings with length embedded in typecode. 62 | STR_FIXED_START = 128, 63 | STR_FIXED_COUNT = 64, 64 | // Lists with length embedded in typecode. 65 | LIST_FIXED_START = STR_FIXED_START+STR_FIXED_COUNT, 66 | LIST_FIXED_COUNT = 64, 67 | }; 68 | 69 | using namespace libtorrent; 70 | 71 | int main_ret = 0; 72 | 73 | int main(int argc, char* argv[]) 74 | { 75 | rtok_t tokens[100]; 76 | int ret; 77 | 78 | char input1[] = { CHR_INT1, 0x40 }; 79 | ret = rdecode(tokens, 100, input1, 2); 80 | print_rtok(tokens, input1); 81 | printf("\n"); 82 | TEST_CHECK(ret == 1); 83 | TEST_CHECK(tokens[0].type() == type_integer); 84 | TEST_CHECK(tokens[0].integer(input1) == 0x40); 85 | 86 | char input2[] = { CHR_INT2, 0x40, 0x80 }; 87 | ret = rdecode(tokens, 100, input2, 3); 88 | print_rtok(tokens, input2); 89 | printf("\n"); 90 | TEST_CHECK(ret == 1); 91 | TEST_CHECK(tokens[0].type() == type_integer); 92 | TEST_CHECK(tokens[0].integer(input2) == 0x4080); 93 | 94 | char input3[] = { CHR_TRUE }; 95 | ret = rdecode(tokens, 100, input3, 1); 96 | print_rtok(tokens, input3); 97 | printf("\n"); 98 | TEST_CHECK(ret == 1); 99 | TEST_CHECK(tokens[0].type() == type_bool); 100 | TEST_CHECK(tokens[0].boolean(input3) == true); 101 | 102 | char input4[] = { CHR_FALSE }; 103 | ret = rdecode(tokens, 100, input4, 1); 104 | print_rtok(tokens, input4); 105 | printf("\n"); 106 | TEST_CHECK(ret == 1); 107 | TEST_CHECK(tokens[0].type() == type_bool); 108 | TEST_CHECK(tokens[0].boolean(input4) == false); 109 | 110 | char input5[] = { CHR_DICT, '3', ':', 'f', 'o', 'o', CHR_LIST, CHR_TRUE, CHR_FALSE, CHR_TERM, CHR_TERM }; 111 | ret = rdecode(tokens, 100, input5, sizeof(input5)); 112 | print_rtok(tokens, input5); 113 | printf("\n"); 114 | TEST_CHECK(ret == 5); 115 | TEST_CHECK(tokens[0].type() == type_dict); 116 | TEST_CHECK(tokens[0].num_items() == 1); 117 | TEST_CHECK(tokens[1].type() == type_string); 118 | TEST_CHECK(tokens[1].string(input5) == "foo"); 119 | TEST_CHECK(tokens[2].type() == type_list); 120 | TEST_CHECK(tokens[2].num_items() == 2); 121 | TEST_CHECK(tokens[3].type() == type_bool); 122 | TEST_CHECK(tokens[3].boolean(input5) == true); 123 | TEST_CHECK(tokens[4].type() == type_bool); 124 | TEST_CHECK(tokens[4].boolean(input5) == false); 125 | 126 | char input6[] = "6:foobar"; 127 | ret = rdecode(tokens, 100, input6, sizeof(input6)); 128 | print_rtok(tokens, input6); 129 | printf("\n"); 130 | TEST_CHECK(ret == 1); 131 | TEST_CHECK(tokens[0].type() == type_string); 132 | TEST_CHECK(tokens[0].string(input6) == "foobar"); 133 | 134 | char input7[] = { CHR_INT, '2', '1', CHR_TERM}; 135 | ret = rdecode(tokens, 100, input7, sizeof(input7)); 136 | print_rtok(tokens, input7); 137 | printf("\n"); 138 | TEST_CHECK(ret == 1); 139 | TEST_CHECK(tokens[0].type() == type_integer); 140 | TEST_CHECK(tokens[0].integer(input7) == 21); 141 | 142 | char input8[] = { DICT_FIXED_START+1, '3', ':', 'f', 'o', 'o', LIST_FIXED_START+2, CHR_TRUE, CHR_FALSE }; 143 | ret = rdecode(tokens, 100, input8, sizeof(input8)); 144 | print_rtok(tokens, input8); 145 | printf("\n"); 146 | TEST_CHECK(ret == 5); 147 | TEST_CHECK(tokens[0].type() == type_dict); 148 | TEST_CHECK(tokens[0].num_items() == 1); 149 | TEST_CHECK(tokens[1].type() == type_string); 150 | TEST_CHECK(tokens[1].string(input8) == "foo"); 151 | TEST_CHECK(tokens[2].type() == type_list); 152 | TEST_CHECK(tokens[2].num_items() == 2); 153 | TEST_CHECK(tokens[3].type() == type_bool); 154 | TEST_CHECK(tokens[3].boolean(input8) == true); 155 | TEST_CHECK(tokens[4].type() == type_bool); 156 | TEST_CHECK(tokens[4].boolean(input8) == false); 157 | 158 | char input9[] = { CHR_NONE }; 159 | ret = rdecode(tokens, 100, input9, 1); 160 | print_rtok(tokens, input9); 161 | printf("\n"); 162 | TEST_CHECK(ret == 1); 163 | TEST_CHECK(tokens[0].type() == type_none); 164 | 165 | char input10[] = { DICT_FIXED_START }; 166 | ret = rdecode(tokens, 100, input10, 1); 167 | print_rtok(tokens, input10); 168 | printf("\n"); 169 | TEST_CHECK(ret == 1); 170 | TEST_CHECK(tokens[0].type() == type_dict); 171 | TEST_CHECK(tokens[0].num_items() == 0); 172 | 173 | return main_ret; 174 | } 175 | 176 | -------------------------------------------------------------------------------- /tests/test_rss_filter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2013, Arvid Norberg 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the distribution. 15 | * Neither the name of the author nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | #include "rencode.hpp" 34 | 35 | #include "test.hpp" 36 | #include "rss_filter.hpp" 37 | 38 | using namespace libtorrent; 39 | 40 | int main_ret = 0; 41 | 42 | int main(int argc, char* argv[]) 43 | { 44 | item_properties p; 45 | 46 | parse_name("Foo Bar 3x7 [HDTV - 2HD]", p); 47 | printf("s: %d e: %d\n", p.season, p.episode); 48 | TEST_CHECK(p.season == 3); 49 | TEST_CHECK(p.episode == 7); 50 | TEST_CHECK(p.quality == item_properties::hd720); 51 | TEST_CHECK(p.source == item_properties::tv); 52 | 53 | parse_name("Foo.Bar.S10E23.HDTV", p); 54 | printf("s: %d e: %d\n", p.season, p.episode); 55 | TEST_CHECK(p.season == 10); 56 | TEST_CHECK(p.episode == 23); 57 | TEST_CHECK(p.quality == item_properties::hd720); 58 | TEST_CHECK(p.source == item_properties::tv); 59 | 60 | parse_name("Foo_Bar_2013-05-13_[brrip.1080p]", p); 61 | printf("s: %d e: %d\n", p.season, p.episode); 62 | TEST_CHECK(p.season == 2013); 63 | TEST_CHECK(p.episode == 513); 64 | TEST_CHECK(p.quality == item_properties::hd1080); 65 | TEST_CHECK(p.source == item_properties::bluray); 66 | 67 | parse_name("Foo_Bar 2013 05 13", p); 68 | printf("s: %d e: %d\n", p.season, p.episode); 69 | TEST_CHECK(p.season == 2013); 70 | TEST_CHECK(p.episode == 513); 71 | 72 | parse_name("Foo_Bar 2013.05.13", p); 73 | printf("s: %d e: %d\n", p.season, p.episode); 74 | TEST_CHECK(p.season == 2013); 75 | TEST_CHECK(p.episode == 513); 76 | 77 | TEST_CHECK(normalize_title("Foo.. Bar.>< [hdtv] __ test") == "foo bar hdtv test"); 78 | TEST_CHECK(normalize_title("Foo_Bar_2013-05-13_[brrip.1080p]") == "foo bar 2013-05-13 brrip 1080p"); 79 | 80 | return main_ret; 81 | } 82 | -------------------------------------------------------------------------------- /tools/add_user.cpp: -------------------------------------------------------------------------------- 1 | #include "auth.hpp" 2 | #include 3 | #include 4 | 5 | using namespace libtorrent; 6 | 7 | int main(int argc, char* argv[]) 8 | { 9 | if (argc != 3 || atoi(argv[2]) < 0 || atoi(argv[2]) > 10000) 10 | { 11 | fprintf(stderr, "usage:\n" 12 | "add_user username group-number\n\n" 13 | "the user is added to users.conf in\n" 14 | "current working directory.\n" 15 | "group numbers may not be negative.\n"); 16 | return 1; 17 | } 18 | 19 | auth authorizer; 20 | 21 | char password[1024]; 22 | printf("enter password: "); 23 | fflush(stdout); 24 | if (fgets(password, 1024, stdin) == NULL) 25 | return 1; 26 | 27 | int pwdlen = strlen(password); 28 | while (pwdlen > 0 && password[pwdlen-1] == '\n') 29 | { 30 | --pwdlen; 31 | password[pwdlen] = '\0'; 32 | } 33 | 34 | error_code ec; 35 | authorizer.load_accounts("./users.conf", ec); 36 | authorizer.add_account(argv[1], password, atoi(argv[2])); 37 | ec.clear(); 38 | authorizer.save_accounts("./users.conf", ec); 39 | if (ec) 40 | { 41 | fprintf(stderr, "failed to save users file: %s\n", ec.message().c_str()); 42 | } 43 | return 0; 44 | } 45 | 46 | --------------------------------------------------------------------------------