From 6916388615fa4ad8f85a287ee6ebc9dd5b1668cb Mon Sep 17 00:00:00 2001 From: P2P-Next Date: Fri, 6 Aug 2010 17:12:36 +0300 Subject: [PATCH] instrumentation: add hrktorrent --- instrumentation/hrktorrent/CHANGELOG | 101 ++++++ instrumentation/hrktorrent/CONTRIBUTORS | 4 + instrumentation/hrktorrent/LICENSE | 24 ++ instrumentation/hrktorrent/Makefile | 30 ++ instrumentation/hrktorrent/README | 20 ++ instrumentation/hrktorrent/core.cpp | 321 ++++++++++++++++++ instrumentation/hrktorrent/core.h | 34 ++ instrumentation/hrktorrent/hrktorrent.1 | 68 ++++ instrumentation/hrktorrent/hrktorrent.h | 31 ++ .../hrktorrent/hrktorrent.rc.example | 15 + instrumentation/hrktorrent/ipfilter.cpp | 86 +++++ instrumentation/hrktorrent/ipfilter.h | 22 ++ instrumentation/hrktorrent/main.cpp | 191 +++++++++++ instrumentation/hrktorrent/settings.cpp | 84 +++++ instrumentation/hrktorrent/settings.h | 36 ++ instrumentation/hrktorrent/utils.cpp | 12 + instrumentation/hrktorrent/utils.h | 6 + instrumentation/hrktorrent/vars.mk | 14 + instrumentation/hrktorrent/version.h | 11 + 19 files changed, 1110 insertions(+) create mode 100644 instrumentation/hrktorrent/CHANGELOG create mode 100644 instrumentation/hrktorrent/CONTRIBUTORS create mode 100644 instrumentation/hrktorrent/LICENSE create mode 100644 instrumentation/hrktorrent/Makefile create mode 100644 instrumentation/hrktorrent/README create mode 100644 instrumentation/hrktorrent/core.cpp create mode 100644 instrumentation/hrktorrent/core.h create mode 100644 instrumentation/hrktorrent/hrktorrent.1 create mode 100644 instrumentation/hrktorrent/hrktorrent.h create mode 100644 instrumentation/hrktorrent/hrktorrent.rc.example create mode 100644 instrumentation/hrktorrent/ipfilter.cpp create mode 100644 instrumentation/hrktorrent/ipfilter.h create mode 100644 instrumentation/hrktorrent/main.cpp create mode 100644 instrumentation/hrktorrent/settings.cpp create mode 100644 instrumentation/hrktorrent/settings.h create mode 100644 instrumentation/hrktorrent/utils.cpp create mode 100644 instrumentation/hrktorrent/utils.h create mode 100644 instrumentation/hrktorrent/vars.mk create mode 100644 instrumentation/hrktorrent/version.h diff --git a/instrumentation/hrktorrent/CHANGELOG b/instrumentation/hrktorrent/CHANGELOG new file mode 100644 index 0000000..0de8625 --- /dev/null +++ b/instrumentation/hrktorrent/CHANGELOG @@ -0,0 +1,101 @@ +hrktorrent changelog: + +----------------------- +0.3.5 [2009-Aug-14] +----------------------- +- Updated author name and email address +- Actually terminate hrktorrent on CTRL+C +- Better rule parsing, bugfix and speedup +- Improved exception handling +- Use libtorrent-rasterbar pkg-config package +- Get rid of deprecated function references, comply to latest libtorrent + standards + + +----------------------- +0.3.4 [2008-Oct-21] +----------------------- +- Adopt code to style guidelines (James Munro) +- Print the count of imported ipfilter.dat entries +- Continue processing after error (Razvan Deaconescu) +- Use std::cout for debug messages in constructor (Razvan Deaconescu) +- Use ctrl+c for termination and fix another bug (Razvan Deaconescu) +- Make 'make' output prettier + +----------------------- +0.3.3 [2008-Aug-26] +----------------------- +- The CSettings class now supports integers and strings as setting types +- Added the option "downloaddir" to set the target directory +- Added Razvan Deaconescu's patch to ignore colum checking when hrktorrent is not being + run in a tty. Thanks! +- Improved cleaning up the program +- Fixed the Makefile +- More verbosity +- Support libtorrent's UPnP implementation + +----------------------- +0.3.2 [2008-Jun-28] +----------------------- +- Fixed the multiple instances with DHT bug +- DHT now uses public routers to bootstrap (bittorrent.com, bitcomet.com, utorrent.com) +- Fixed "'add_torrent' is deprecated" warning when compiling +- Fixed the line-feed problem in consoles + +----------------------- +0.3.1 [2008-Mar-14] +----------------------- +- Configuration is now loaded from ~/.hrktorrent/hrktorrent.rc, as well as the ipfilter +- DHT nodes are now being loaded and saved to the hrktorrent dir +- Fixed a bug where you could run hrktorrent only once with DHT enabled +- IPFilter has been improved + +----------------------- +0.3.0 [2007-Dec-24] +----------------------- +- Added an IPFilter (loading from ~/.ipfilter.dat) [lots of code by xen, thanks!] +- Major code cleanups + +----------------------- +0.2.3 [2007-Dec-02] +----------------------- +- Added forcereannounce option for speed increasement +- hrktorrent now sends it's own id (HT) +- Made the Makefile distribution friendlier (thanks to drac's patch) +- The amount of uploaded data is now being displayed + +----------------------- +0.2.2 [2007-Nov-25 ] +----------------------- +- Added ETA +- Output will now be truncated with dots, if it is longer than the terminal width +- tuqs was so kind to write a manpage +- Changed the Makefile so it doesn't strip the binary anymore + +----------------------- +0.2.1 [2007-Nov-22 ] +----------------------- +- Fixed a crash bug [thanks to nico] + +----------------------- +0.2 [ 2007-Nov-22 ] +----------------------- +- README written +- LICENSE added (please please please correct mistakes, I'm not good at this!) +- Complete rewrite +- Major code cleanup +- Config file support (~/.hrktorrent.rc) +- Rewritten console output +- DHT enabled +- 'seed' option +- 'verbose' option +- Minor bugfixes +- Improved commandline switches + +----------------------- +0.1 [ 2007-Nov-18 ] +----------------------- +- Initial release +- Basic torrent downloading with status output +- Option to define the port range +- Option to define the maximum upload speed diff --git a/instrumentation/hrktorrent/CONTRIBUTORS b/instrumentation/hrktorrent/CONTRIBUTORS new file mode 100644 index 0000000..7164af5 --- /dev/null +++ b/instrumentation/hrktorrent/CONTRIBUTORS @@ -0,0 +1,4 @@ +James Munro +Nico R. Wohlgemuth +Razvan Deaconescu +Sebastian Mair diff --git a/instrumentation/hrktorrent/LICENSE b/instrumentation/hrktorrent/LICENSE new file mode 100644 index 0000000..9516e3b --- /dev/null +++ b/instrumentation/hrktorrent/LICENSE @@ -0,0 +1,24 @@ +* Copyright (c) <2007>, +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the names of the company nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/instrumentation/hrktorrent/Makefile b/instrumentation/hrktorrent/Makefile new file mode 100644 index 0000000..a5f04db --- /dev/null +++ b/instrumentation/hrktorrent/Makefile @@ -0,0 +1,30 @@ +include vars.mk + +all: $(OUT) $(OUT)-static + +.cpp.o: + @echo [CXX] $< + @$(CXX) $(CXXFLAGS) -c -o $@ $< + +$(OUT): $(OBJ) + @echo [LD] $@ + $(CXX) $(LDFLAGS) $(OBJ) $(LIBS) -o $(OUT) + +$(OUT)-static: $(OBJ) + @echo [LD] $@ + $(CXX) $(OBJ) ../libtorrent-rasterbar/lib/libtorrent-rasterbar.a $(EXTRA_LIBS) -o $@ + +clean: + -rm -rf $(OBJ) $(OUT) $(OUT)-static *~ + +install: all + @install hrktorrent ${PREFIX}/bin + @mkdir -p ${PREFIX}/share/examples/hrktorrent + @install -m 644 hrktorrent.rc.example ${PREFIX}/share/examples/hrktorrent/hrktorrent.rc + @mkdir -p ${MANPREFIX}/man1 + @install -m 644 hrktorrent.1 ${MANPREFIX}/man1/hrktorrent.1 + +uninstall: + -@rm -f ${PREFIX}/bin/hrktorrent + -@rm -f ${MANPREFIX}/man1/hrktorrent.1 + -@rm -r ${PREFIX}/share/examples/hrktorrent/ diff --git a/instrumentation/hrktorrent/README b/instrumentation/hrktorrent/README new file mode 100644 index 0000000..2a04adf --- /dev/null +++ b/instrumentation/hrktorrent/README @@ -0,0 +1,20 @@ +<- + hrktorrent 0.3.5 + http://50hz.ws/hrktorrent/ + LICENSE: BSD + Report bugs to: irc://irc.rizon.net #/dev/null (hrkfdn) + + Thanks to rasterbar's libtorrent! +-> + +To compile hrktorrent you need: +a) boost +b) asio header files +c) libtorrent (the one by rasterbar: http://www.rasterbar.com/products/libtorrent/index.html) + +To use a config file, put it in your $HOME/.hrktorrent dir and name it "hrktorrent.rc", there is an example included. +NOTE: Commandline switches override configuration file settings. + +For IP-Filtering, make sure it is enabled and copy the ipfilter.dat file to ~/.hrktorrent/ipfilter.dat + +Help is available by just running hrktorrent. diff --git a/instrumentation/hrktorrent/core.cpp b/instrumentation/hrktorrent/core.cpp new file mode 100644 index 0000000..c21bb64 --- /dev/null +++ b/instrumentation/hrktorrent/core.cpp @@ -0,0 +1,321 @@ +#include "hrktorrent.h" + +CCore* Core = 0; +pthread_t statusthread; + +/* constructor. init torrent session! */ +CCore::CCore(int argc, char** argv) +{ + _argc = argc; + _argv = argv; + _running = true; + + Settings = new CSettings(); + std::cout << "Initializing " << APPNAME << " " << VERSION << std::endl; + + Settings->LoadConfig(); +} + +/* destructor. free/delete garbage! */ +CCore::~CCore() +{ + VerbosePrint("Core", "Destructing core class."); + delete _session; +} + +unsigned int +GetETA(libtorrent::size_type done, libtorrent::size_type wanted, libtorrent::size_type downspeed) +{ + libtorrent::size_type delta = wanted - done; + if(downspeed > 0) + return (delta / downspeed); + else + return 0; +} + + +void* +CCore::StatusLoop(void* data) +{ + int curx, cury; + std::string s_output; + std::stringstream output; + + struct winsize ws; + + libtorrent::session* s = Core->GetSession(); + libtorrent::torrent_handle* t = Core->GetTorrent(); + + libtorrent::session_status sstatus; + libtorrent::torrent_status tstatus; + bool finished = false; + int eta = 0, columns = 0, loopcount = 0; + bool stdout_is_tty = false; + + stdout_is_tty = (isatty(STDOUT_FILENO) == 1); + if (stdout_is_tty) { + if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) < 0) { + char errbuf[128]; + + strerror_r(errno, errbuf, 128); + std::cerr << "ioctl error: " << errbuf << std::endl; + + exit(EXIT_FAILURE); + } + columns = ws.ws_col; + } + + + while(Core->isRunning()) { + if(Settings->GetI("forcereannounce") > 0 && loopcount >= Settings->GetI("forcereannounce")*60) { + loopcount = 0; + t->force_reannounce(); + Core->VerbosePrint("Core", "Reannouncing!\n"); + } + + sstatus = s->status(); + tstatus = t->status(); + eta = GetETA(tstatus.total_done, tstatus.total_wanted, (libtorrent::size_type)sstatus.download_rate); + + if(!finished && tstatus.total_wanted != 0 && tstatus.total_done == tstatus.total_wanted) { + std::cout << "\nTorrent finished!" << std::endl; + if(Settings->GetI("seed") == 0) { + statusthread = 0; + exit(EXIT_SUCCESS); + } + finished = true; + } + + output << "ps: " << sstatus.num_peers; + if(Settings->GetI("dht") > 0) + output << ", dht: " << sstatus.dht_nodes; + output << " <> "; + output << "dl: " << Round(sstatus.download_rate/1024, 2) << "kb/s, "; + output << "ul: " << Round(sstatus.upload_rate/1024, 2) << "kb/s <> "; + output << "dld: " << tstatus.total_done/1048576 << "mb, "; + output << "uld: " << sstatus.total_payload_upload/1048576 << "mb, "; + output << "size: " << tstatus.total_wanted/1048576 << "mb <> "; + output << "eta: "; + if(eta > 216000) { + output << eta/216000 << "d "; + eta -= (eta/216000)*216000; + } + if(eta > 3600) { + output << eta/3600 << "h "; + eta -= (eta/3600)*3600; + } + if(eta > 60) { + output << eta/60 << "m "; + eta -= (eta/60)*60; + } + output << eta << "s"; + s_output = output.str(); + + if (stdout_is_tty) { + if(s_output.length() > columns) { + s_output.resize(columns - 3); + s_output.append(".."); + } + else if(s_output.length() < columns) { + for(int i = 0; i < s_output.length() - columns; i++) + s_output.append(" "); + } + } + if (stdout_is_tty) { + std::cout << s_output.c_str() << "\r"; + } + else { + std::cout << s_output.c_str() << std::endl; + } + + + std::cout.flush(); + output.str(""); + + sleep(1); + loopcount++; + } + + return 0; +} + +void +CCore::LoadDHT() +{ + std::string path = *Settings->getDir(); + path.append("dhtnodes"); + + std::ifstream nodefile(path.c_str(), std::ios_base::binary); + if(!nodefile.is_open()) { + mkdir(Settings->getDir()->c_str(), 0755); + VerbosePrint("DHT", "Could not load the nodefile."); + _session->start_dht(); + return; + } + + nodefile.unsetf(std::ios_base::skipws); + + try { + libtorrent::entry state = libtorrent::bdecode(std::istream_iterator(nodefile), + std::istream_iterator()); + _session->start_dht(state); + VerbosePrint("DHT", "DHT started with a nodefile."); + } + catch(std::exception& e) { + std::cout << e.what() << std::endl; + _session->start_dht(); + } + nodefile.close(); +} + +void +CCore::SaveDHT() +{ + std::string path = *Settings->getDir(); + path.append("dhtnodes"); + + std::ofstream nodefile(path.c_str(), std::ios_base::binary); + if(!nodefile.is_open()) { + VerbosePrint("DHT", "Could not save the nodefile."); + return; + } + + nodefile.unsetf(std::ios_base::skipws); + + libtorrent::entry state = _session->dht_state(); + libtorrent::bencode(std::ostream_iterator(nodefile), state); + VerbosePrint("DHT", "Saved nodes."); + nodefile.close(); +} + +static void +SignalHandler(int signo) +{ + Core->VerbosePrint("Core", "Received signal."); + Core->Shutdown(); +} + +void +CCore::ScheduleSignal(int signo) +{ + struct sigaction sa; + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SignalHandler; + sa.sa_flags = SA_RESETHAND; + + if (sigaction(signo, &sa, NULL) < 0) { + char errbuf[128]; + + strerror_r(errno, errbuf, 128); + + std::cerr << "sigaction error: " << errbuf << std::endl; + exit(EXIT_FAILURE); + } +} + +void +CCore::Shutdown() +{ + _running = false; + if(Settings->GetI("dht") > 0) { + SaveDHT(); + _session->stop_dht(); + } + + if(statusthread) pthread_cancel(statusthread); + std::cout << "\nShutting down hrktorrent. Please wait." << std::endl; + + exit(EXIT_SUCCESS); +} + +int +CCore::Run() +{ + _verbose = (Settings->GetI("verbose") > 0); + VerbosePrint("Core", "Verbose enabled."); + VerbosePrint("Core", "Starting torrent session!"); + + IPFilter = new CIPFilter(); + + _session = new libtorrent::session(libtorrent::fingerprint("HT", MAJOR, MINOR, REVISION, TAG)); + + if(Settings->GetI("upnp") > 0) + _session->start_upnp(); + + _session->listen_on(std::make_pair(Settings->GetI("minport"), Settings->GetI("maxport"))); + if(Settings->GetI("maxup") > 0) { + _session->set_upload_rate_limit(Settings->GetI("maxup")*1024); + _session->set_local_upload_rate_limit(Settings->GetI("maxup")*1024); + } + if(Settings->GetI("maxdown") > 0){ + _session->set_download_rate_limit(Settings->GetI("maxdown")*1024); + _session->set_local_download_rate_limit(Settings->GetI("maxdown")*1024); + } + try { + libtorrent::add_torrent_params parms; + + boost::intrusive_ptr info = new libtorrent::torrent_info(_argv[_argc-1]); + boost::filesystem::path p(Settings->GetS("downloaddir")); + boost::filesystem::create_directory(p); + if(!boost::filesystem::exists(p)) { + std::cerr << "Download directory does not exist/could not be created." << std::endl; + return EXIT_FAILURE; + } + + parms.save_path = p; + parms.ti = info; + parms.paused = false; + + _torrent = _session->add_torrent(parms); + } catch(std::exception& e) { + std::cerr << "Could not add torrent (" << e.what() <<")" << std::endl; + return EXIT_FAILURE; + } + + if(Settings->GetI("dht") > 0) { + VerbosePrint("Core", "Starting DHT."); + libtorrent::dht_settings dset; + dset.service_port = _session->listen_port(); + _session->set_dht_settings(dset); + LoadDHT(); + + // known dht routers for bootstrapping + _session->add_dht_router(std::make_pair(std::string("router.bittorrent.com"), 6881)); + _session->add_dht_router(std::make_pair(std::string("router.utorrent.com"), 6881)); + _session->add_dht_router(std::make_pair(std::string("router.bitcomet.com"), 6881)); + } + + if(Settings->GetI("ipfilter") > 0 && IPFilter->IsActive()) { + _session->set_ip_filter(IPFilter->getFilter()); + } + + ScheduleSignal(SIGINT); + std::cout << "\"CTRL-C\" shuts hrktorrent down.\n" << std::endl; + + pthread_create(&statusthread, NULL, StatusLoop, NULL); + + /* + * reading stdin does not work with output redirection or running the + * program in background + */ + /* + char input; + std::cin.unsetf(std::ios_base::skipws); + std::cin >> input; + */ + + /* wait for signal */ + pause(); + + Shutdown(); +} + +void +CCore::VerbosePrint(std::string source, std::string message) +{ + if(!_verbose) return; + std::cout << "[" << source << "] "; + std::cout << message << std::endl; +} + diff --git a/instrumentation/hrktorrent/core.h b/instrumentation/hrktorrent/core.h new file mode 100644 index 0000000..04adbd3 --- /dev/null +++ b/instrumentation/hrktorrent/core.h @@ -0,0 +1,34 @@ +#ifndef _CORE_H +#define _CORE_H + +class CCore +{ + public: + CCore(int argc, char** argv); + ~CCore(); + + int Run(); + void Shutdown(); + void VerbosePrint(std::string source, std::string message); + static void* StatusLoop(void* data); + + inline libtorrent::session* GetSession() { return _session; } + inline libtorrent::torrent_handle* GetTorrent() { return &_torrent; } + inline bool isRunning() { return _running == true; } + private: + bool _running; + libtorrent::session* _session; + libtorrent::torrent_handle _torrent; // TODO: multiple torrents? + + void LoadDHT(); + void SaveDHT(); + void ScheduleSignal(int signo); + + int _argc; + char** _argv; + + bool _verbose; +}; +extern CCore* Core; + +#endif diff --git a/instrumentation/hrktorrent/hrktorrent.1 b/instrumentation/hrktorrent/hrktorrent.1 new file mode 100644 index 0000000..26117c2 --- /dev/null +++ b/instrumentation/hrktorrent/hrktorrent.1 @@ -0,0 +1,68 @@ +.\" hrktorrent.1 +.TH hrktorrent 0.3.4 +.SH NAME +hrktorrent - a slim console torrent application supporting DHT +.SH SYNOPSIS +hrktorrent [--options] \fIfile.torrent\fR +.SH DESCRIPTION +hrktorrent is a slim rb_torrent based console torrent application supporting DHT. +.SH OPTIONS +.fi +\fB--minport\fR - start port range (default: 6881) + +\fB--maxport\fR - end port range (default: 6999) + +\fB--maxdown\fR - download speed limit (in kb/s) (default: unlimited) + +\fB--maxup\fR - upload speed limit (in kb/s) (default: unlimited) + +\fB--nodht\fR - disable dht (default: on) + +\fB--noupnp\fR - disable upnp (default: on) + +\fB--noseed\fR - disable seeding (default: on) + +\fB--forcereannounce\fR - reannounce every X minutes (default: 2) + +\fB--ipfilter\fR - enable ip filtering (default: off) + +\fB--downloaddir\fR - set the directory you want the downloads saved to (default: .) + +\fB--verbose\fR - print verbose messages (default: off) +.nf +.SH CONFIGURATION FILE +Any configuration files or files that hrktorrent creates are stored in ~/.hrktorrent + +.fi +\fB~/.hrktorrent/hrktorrent.rc\fR + +minport \fIint\fR # minimum port + +maxport \fIint\fR # maximum port + +verbose \fIbool\fR # verbose mode + +maxup \fIint\fR # max. upload speed + +maxdown \fIint\fR # max. download speed + +dht \fIbool\fR # dht + +upnp \fIbool\fR # upnp port lookup + +seed \fIbool\fR # seed after finishing downloading + +forcereannounce \fIint\fR # update peers every X minutes (be careful with this value!) + +ipfilter \fIbool\fR # enable ip filtering + +downloaddir \fIstring\fR # the directory you want the downloads saved to. default is pwd + +\fBbools have to be set to anything higher than 0 to indicate them as true!\fR +.nf +.SH IPFILTER +To use the IPFilter of libtorrent, you need to provide an ipfilter.dat file and copy it to ~/.hrktorrent/ +.SH EXAMPLE +hrktorrent --minport6500 --maxport6600 --nodht file.torrent +.SH AUTHOR +Henrik Friedrichsen diff --git a/instrumentation/hrktorrent/hrktorrent.h b/instrumentation/hrktorrent/hrktorrent.h new file mode 100644 index 0000000..7544da9 --- /dev/null +++ b/instrumentation/hrktorrent/hrktorrent.h @@ -0,0 +1,31 @@ +#ifndef _HRKTORRENT_H +#define _HRKTORRENT_H + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "version.h" +#include "core.h" +#include "settings.h" +#include "utils.h" +#include "ipfilter.h" + +#endif diff --git a/instrumentation/hrktorrent/hrktorrent.rc.example b/instrumentation/hrktorrent/hrktorrent.rc.example new file mode 100644 index 0000000..8d097c1 --- /dev/null +++ b/instrumentation/hrktorrent/hrktorrent.rc.example @@ -0,0 +1,15 @@ +# please use only the following scheme +minport 60100 # minimum port +maxport 60200 # maximum port + +verbose 0 # verbose mode + +maxup 10 # max. upload speed +maxdown 0 # max. download speed + +dht 1 # dht +upnp 1 # upnp port lookup +seed 1 # seed after finishing downloading +forcereannounce 2 # update peers every X minutes (be careful with this value!) +ipfilter 1 # enable ip filtering +downloaddir ~/incoming # set default download dir diff --git a/instrumentation/hrktorrent/ipfilter.cpp b/instrumentation/hrktorrent/ipfilter.cpp new file mode 100644 index 0000000..d320cf9 --- /dev/null +++ b/instrumentation/hrktorrent/ipfilter.cpp @@ -0,0 +1,86 @@ +#include "hrktorrent.h" + +CIPFilter* IPFilter = 0; + +CIPFilter::CIPFilter() +{ + if(!Settings->GetI("ipfilter")) { + _active = false; + return; + } + else + _active = true; + + std::string path = *Settings->getDir(); + path.append("ipfilter.dat"); + + std::ifstream config(path.c_str(), std::ifstream::in); + if(!config.is_open()) { + Core->VerbosePrint("Settings", "Unable to load ip filter from file. Aborting."); + return; + } + + std::cout << "Loading IPFilter. This could probably take a while!" << std::endl; + + while(config.good()) { + std::string line; + getline(config, line); + ParseFilterLine(line); + } + + libtorrent::ip_filter::filter_tuple_t filters = _ipfilter.export_filter(); + unsigned int entrycount = filters.get<0>().size() + filters.get<1>().size(); + std::cout << entrycount << " entries imported." << std::endl; + + config.close(); +} + +CIPFilter::~CIPFilter() +{ + Core->VerbosePrint("IPFilter", "Destroying IPFilter class."); +} + + +bool +CIPFilter::AddRule(std::string start, std::string end) +{ + if(start.empty() || end.empty() || !_active) return false; + + libtorrent::address astart, aend; + try { + astart = libtorrent::address::from_string(start); + aend = libtorrent::address::from_string(end); + } catch(boost::system::system_error& e) { + return false; // invalid rule + } + + try { + _ipfilter.add_rule(astart, aend, libtorrent::ip_filter::blocked); + } catch(std::exception& e) { + return false; + } + + return true; +} + +void +CIPFilter::ParseFilterLine(std::string line) +{ + if(line.size() == 0 || line.size() < 5 ) return; + + std::string start; + std::string end; + + std::string::size_type loc = line.find_first_of("-"); + std::string::size_type loc2 = line.find_first_of(","); + + start.assign(line); + start.resize(loc-1); + + end.assign(line); + end.erase(0,loc+2); + end.resize(loc-1); + + if(!AddRule(start,end)) + Core->VerbosePrint("Settings", "Error adding line to ip filter."); +} diff --git a/instrumentation/hrktorrent/ipfilter.h b/instrumentation/hrktorrent/ipfilter.h new file mode 100644 index 0000000..6b18df5 --- /dev/null +++ b/instrumentation/hrktorrent/ipfilter.h @@ -0,0 +1,22 @@ +#ifndef _IPFILTER_H +#define _IPFILTER_H + +class CIPFilter +{ + public: + CIPFilter(); + ~CIPFilter(); + bool AddRule(std::string start, std::string end); + libtorrent::ip_filter getFilter() { return _ipfilter; } + bool IsActive() { return (_active == true); } + + private: + void ParseFilterLine(std::string line); + libtorrent::ip_filter _ipfilter; + + bool _active; +}; + +extern CIPFilter* IPFilter; + +#endif diff --git a/instrumentation/hrktorrent/main.cpp b/instrumentation/hrktorrent/main.cpp new file mode 100644 index 0000000..a6ab88b --- /dev/null +++ b/instrumentation/hrktorrent/main.cpp @@ -0,0 +1,191 @@ +#include "hrktorrent.h" +#include +void +printusage() +{ + std::cout << APPNAME << " " << VERSION << " by hrkfdn (hrkfdn A T gmail D O T com) and other contributors\n"; + std::cout << "usage: " << APPNAME << " [options] torrent-file\n"; + std::cout << "NOTE: options provided by the commandline override configuration file entries!\n\n"; + + std::cout << "\t--minport\t\t- start port range (default: 6881)\n"; + std::cout << "\t--maxport\t\t- end port range (default: 6999)\n"; + + std::cout << "\t--maxdown\t\t- download speed limit (in kb/s) (default: unlimited)\n"; + std::cout << "\t--maxup\t\t\t- upload speed limit (in kb/s) (default: unlimited)\n"; + + std::cout << "\t--nodht\t\t\t- disable dht (default: on)\n"; + std::cout << "\t--noupnp\t\t\t- disable upnp (default: on)\n"; + std::cout << "\t--noseed\t\t- disable seeding (default: on)\n"; + std::cout << "\t--forcereannounce\t- reannounce every X minutes (default: 2)\n"; + std::cout << "\t--downloaddir\t- set the target directory (default: .)\n"; + std::cout << "\t--ipfilter\t\t- enable ip filtering (default: off)\n\n"; + std::cout << "\t--verbose\t\t- print verbose messages (default: off)\n\n"; + + std::cout << "example: hrktorrent --minport6500 --maxport6600 --nodht file.torrent\n"; + + std::cout << std::endl; +} + +void +parseargs(int argc, char** argv) +{ + int longval; + int option_index = 0; + int opt; + static struct option long_options[] = { + {"help", 0, NULL, 'h'}, + {"ipfilter", 0, NULL, 'i'}, + {"limitlocal", 0, NULL, 'l'}, + {"nodht", 0, NULL, 't'}, + {"noupnp", 0, NULL, 'n'}, + {"noseed", 0, NULL, 's'}, + {"verbose", 0, NULL, 'v'}, + {"version", 0, NULL, 'V'}, + {"minport", 1, NULL,'p'}, + {"maxport", 1, NULL, 'P'}, + {"maxdown", 1, NULL, 'd'}, + {"maxup", 1, NULL, 'u'}, + {"forcereannounce", 1, NULL, 'f'}, + {"outputdir", 1, NULL, 'o'}, + {0,0,0,0} + }; + + while (1) { + opt = getopt_long(argc, argv, "hnsiv:p:P:M:u:f:d:",long_options, &option_index); + if (opt == -1) + break; + + switch(opt) + { + case 1: + /* If this option set a flag, do nothing else now. */ + if (long_options[option_index].flag != 0) + break; + //long_opt = long_options[option_index].name; + printf ("option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + break; + case 'p': + std::cout << opt << " "<< optarg<Set("nodht", 1); + break; + case 'n': + std::cout << opt << " "<< optarg<Set("noupnp", 1); + break; + case 's': + std::cout << opt << " "<< optarg<Set("noseed", 1); + break; + case 'd': + std::cout << opt << " "<< optarg<Set("ipfilter", 1); + break; + case 'v': + std::cout << opt << " "<< optarg<Set("verbose", 1); + break; + default: + std::cout <<"wtf"<<" "<Set("seed", 0); + continue; + } + else if(strstr(parg, "--nodht")) { + Settings->Set("dht", 0); + continue; + } + else if(strstr(parg, "--noupnp")) { + Settings->Set("upnp", 0); + continue; + } + else if(strstr(parg, "--verbose")) { + Settings->Set("verbose", 1); + continue; + } + else if(strstr(parg, "--ipfilter")) { + Settings->Set("ipfilter", 1); + continue; + } + + + parg += 2; + + std::map::iterator it; + for(it = Settings->getSettingMap()->begin(); it != Settings->getSettingMap()->end(); it++) { + if(strstr(parg, it->first.c_str())) { + char* val = parg + strlen(it->first.c_str()); + switch(it->second.type) { + case TYPE_INT: + it->second.ival = atoi(val); + break; + case TYPE_STRING: + it->second.sval = val; + break; + } + std::cout << it->first.c_str()<< "=(" << it->second.ival << ", "<second.sval <<")" << std::endl; + } + } + } +} +*/ +#define CLEAN(x) if(x) delete x +void +close() +{ + CLEAN(Settings); + CLEAN(IPFilter); + + /* make sure this is always the last class to cleanup */ + CLEAN(Core); +} + +int +main(int argc, char* argv[]) +{ + atexit(close); + + using namespace std; + int runstate = EXIT_FAILURE; + + if(argc < 2) { + printusage(); + return EXIT_FAILURE; + } + +// Core = new CCore(argc, argv); + parseargs(argc, argv); +// runstate = Core->Run(); + +// return runstate; + return 0; +} diff --git a/instrumentation/hrktorrent/settings.cpp b/instrumentation/hrktorrent/settings.cpp new file mode 100644 index 0000000..f799f04 --- /dev/null +++ b/instrumentation/hrktorrent/settings.cpp @@ -0,0 +1,84 @@ +#include "hrktorrent.h" + +CSettings* Settings = 0; + +CSettings::CSettings() +{ + /* apply default settings */ + Set("verbose", 1); + + Set("minport", 6881); + Set("maxport", 6999); + + Set("maxup", 0); + Set("maxdown", 0); + + Set("dht", 1); + Set("upnp", 1); + Set("seed", 1); + Set("forcereannounce", 2); + Set("ipfilter", 1); + + Set("downloaddir", "."); +} + +CSettings::~CSettings() +{ + Core->VerbosePrint("Settings", "Destroying Settings class."); +} + +void +CSettings::LoadConfig() +{ + _dir = getenv("HOME"); + _dir.append("/.hrktorrent/"); + + std::string path = _dir; + path.append("hrktorrent.rc"); + + std::ifstream config(path.c_str(), std::ifstream::in); + if(!config.is_open()) { + /* workaround: Core->VerbosePrint uses non-initialized Core */ + std::cout << "[Settings] Could not load config file. Will use default values." << std::endl; + + /* cannot do: Core may not be properly initialized */ + /* Core->VerbosePrint("Settings", "Could not load config file. Will use default values.");*/ + return; + } + + while(config.good()) { + std::string line; + getline(config, line); + ParseLine(line); + } + + config.close(); +} + +void +CSettings::ParseLine(std::string line) +{ + std::string var; + std::string value; + std::stringstream linestream; + + std::string::size_type loc = line.find_first_of("#"); + if(loc < line.size()) + line.resize(loc); + + linestream.str(line); + + linestream >> var; + linestream >> value; + if(var.empty()) return; + + switch(settings[var].type) { + case TYPE_INT: + Set(var, atoi(value.c_str())); + break; + case TYPE_STRING: + Set(var, value); + break; + } +} + diff --git a/instrumentation/hrktorrent/settings.h b/instrumentation/hrktorrent/settings.h new file mode 100644 index 0000000..e9a9a08 --- /dev/null +++ b/instrumentation/hrktorrent/settings.h @@ -0,0 +1,36 @@ +#ifndef _SETTINGS_H +#define _SETTINGS_H + +enum { TYPE_INT = 0, TYPE_STRING }; + +typedef struct +{ + int type; + int ival; + std::string sval; +} setting_t; + +class CSettings +{ + public: + CSettings(); + ~CSettings(); + void LoadConfig(); + void ParseLine(std::string line); + + void Set(std::string name, int ival) { settings[name].type = TYPE_INT; settings[name].ival = ival; } + void Set(std::string name, std::string sval) { settings[name].type = TYPE_STRING; settings[name].sval = sval; } + + int GetI(std::string name) { return settings[name].ival; } + std::string GetS(std::string name) { return settings[name].sval; } + + inline std::string* getDir() { return &_dir; } + + inline std::map* getSettingMap() { return &settings; } + private: + std::map settings; + std::string _dir; +}; +extern CSettings* Settings; + +#endif diff --git a/instrumentation/hrktorrent/utils.cpp b/instrumentation/hrktorrent/utils.cpp new file mode 100644 index 0000000..d768327 --- /dev/null +++ b/instrumentation/hrktorrent/utils.cpp @@ -0,0 +1,12 @@ +#include "hrktorrent.h" + +float +Round(float Value, int NumPlaces) +{ + float Factor; + int Temp; + + Factor = pow(10.0, NumPlaces); + Temp = (int)(Value * Factor + 0.5f); + return Temp / Factor; +} diff --git a/instrumentation/hrktorrent/utils.h b/instrumentation/hrktorrent/utils.h new file mode 100644 index 0000000..1383350 --- /dev/null +++ b/instrumentation/hrktorrent/utils.h @@ -0,0 +1,6 @@ +#ifndef _UTILS_H +#define _UTILS_H + +extern float Round(float Value, int NumPlaces); + +#endif diff --git a/instrumentation/hrktorrent/vars.mk b/instrumentation/hrktorrent/vars.mk new file mode 100644 index 0000000..fe39492 --- /dev/null +++ b/instrumentation/hrktorrent/vars.mk @@ -0,0 +1,14 @@ +PREFIX = /usr/local +MANPREFIX = ${PREFIX}/man +CXX? = g++ +OBJ = main.o core.o settings.o utils.o ipfilter.o +EXTRA_OBJ = ../libtorrent-rasterbar/lib/libtorrent-rasterbar.a +OUT = hrktorrent +CXXFLAGS += `PKG_CONFIG_PATH=../libtorrent-rasterbar pkg-config --cflags libtorrent-rasterbar` +LIBS = `PKG_CONFIG_PATH=../libtorrent-rasterbar pkg-config --libs libtorrent-rasterbar` -lpthread +EXTRA_LIBS = -lpthread -lboost_thread -lssl -lcrypto -lz -lm -lboost_system -lboost_filesystem -lrt + +#LIBS = -lpthread +#CXXFLAGS += `pkg-config --cflags libtorrent-rasterbar` +#LIBS = `pkg-config --libs libtorrent-rasterbar` -lpthread + diff --git a/instrumentation/hrktorrent/version.h b/instrumentation/hrktorrent/version.h new file mode 100644 index 0000000..07ce386 --- /dev/null +++ b/instrumentation/hrktorrent/version.h @@ -0,0 +1,11 @@ +#ifndef _VERSION_H +#define _VERSION_H + +#define APPNAME "hrktorrent" +#define MAJOR 0 +#define MINOR 3 +#define REVISION 5 +#define TAG 0 +#define VERSION "0.3.5" + +#endif -- 2.20.1