--- /dev/null
+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
--- /dev/null
+James Munro
+Nico R. Wohlgemuth
+Razvan Deaconescu
+Sebastian Mair
--- /dev/null
+* Copyright (c) <2007>, <Henrik Friedrichsen>
+* 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 <Henrik Friedrichsen> ``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 <Henrik Friedrichsen> 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.
--- /dev/null
+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/
--- /dev/null
+<-
+ 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.
--- /dev/null
+#include "hrktorrent.h"\r
+\r
+CCore* Core = 0;\r
+pthread_t statusthread;\r
+\r
+/* constructor. init torrent session! */\r
+CCore::CCore(int argc, char** argv)\r
+{\r
+ _argc = argc;\r
+ _argv = argv;\r
+ _running = true;\r
+\r
+ Settings = new CSettings();\r
+ std::cout << "Initializing " << APPNAME << " " << VERSION << std::endl;\r
+\r
+ Settings->LoadConfig();\r
+}\r
+\r
+/* destructor. free/delete garbage! */\r
+CCore::~CCore()\r
+{\r
+ VerbosePrint("Core", "Destructing core class.");\r
+ delete _session;\r
+}\r
+\r
+unsigned int\r
+GetETA(libtorrent::size_type done, libtorrent::size_type wanted, libtorrent::size_type downspeed)\r
+{\r
+ libtorrent::size_type delta = wanted - done;\r
+ if(downspeed > 0)\r
+ return (delta / downspeed);\r
+ else\r
+ return 0;\r
+}\r
+ \r
+\r
+void*\r
+CCore::StatusLoop(void* data)\r
+{\r
+ int curx, cury;\r
+ std::string s_output;\r
+ std::stringstream output;\r
+ \r
+ struct winsize ws;\r
+\r
+ libtorrent::session* s = Core->GetSession();\r
+ libtorrent::torrent_handle* t = Core->GetTorrent();\r
+\r
+ libtorrent::session_status sstatus;\r
+ libtorrent::torrent_status tstatus;\r
+ bool finished = false;\r
+ int eta = 0, columns = 0, loopcount = 0;\r
+ bool stdout_is_tty = false;\r
+\r
+ stdout_is_tty = (isatty(STDOUT_FILENO) == 1);\r
+ if (stdout_is_tty) {\r
+ if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) < 0) {\r
+ char errbuf[128];\r
+\r
+ strerror_r(errno, errbuf, 128);\r
+ std::cerr << "ioctl error: " << errbuf << std::endl;\r
+\r
+ exit(EXIT_FAILURE);\r
+ }\r
+ columns = ws.ws_col;\r
+ }\r
+\r
+\r
+ while(Core->isRunning()) {\r
+ if(Settings->GetI("forcereannounce") > 0 && loopcount >= Settings->GetI("forcereannounce")*60) {\r
+ loopcount = 0;\r
+ t->force_reannounce();\r
+ Core->VerbosePrint("Core", "Reannouncing!\n");\r
+ }\r
+\r
+ sstatus = s->status();\r
+ tstatus = t->status();\r
+ eta = GetETA(tstatus.total_done, tstatus.total_wanted, (libtorrent::size_type)sstatus.download_rate);\r
+\r
+ if(!finished && tstatus.total_wanted != 0 && tstatus.total_done == tstatus.total_wanted) {\r
+ std::cout << "\nTorrent finished!" << std::endl;\r
+ if(Settings->GetI("seed") == 0) {\r
+ statusthread = 0;\r
+ exit(EXIT_SUCCESS);\r
+ }\r
+ finished = true;\r
+ }\r
+\r
+ output << "ps: " << sstatus.num_peers;\r
+ if(Settings->GetI("dht") > 0) \r
+ output << ", dht: " << sstatus.dht_nodes;\r
+ output << " <> ";\r
+ output << "dl: " << Round(sstatus.download_rate/1024, 2) << "kb/s, ";\r
+ output << "ul: " << Round(sstatus.upload_rate/1024, 2) << "kb/s <> ";\r
+ output << "dld: " << tstatus.total_done/1048576 << "mb, ";\r
+ output << "uld: " << sstatus.total_payload_upload/1048576 << "mb, ";\r
+ output << "size: " << tstatus.total_wanted/1048576 << "mb <> ";\r
+ output << "eta: ";\r
+ if(eta > 216000) {\r
+ output << eta/216000 << "d ";\r
+ eta -= (eta/216000)*216000;\r
+ }\r
+ if(eta > 3600) {\r
+ output << eta/3600 << "h ";\r
+ eta -= (eta/3600)*3600;\r
+ }\r
+ if(eta > 60) {\r
+ output << eta/60 << "m ";\r
+ eta -= (eta/60)*60;\r
+ }\r
+ output << eta << "s";\r
+ s_output = output.str();\r
+\r
+ if (stdout_is_tty) {\r
+ if(s_output.length() > columns) {\r
+ s_output.resize(columns - 3);\r
+ s_output.append("..");\r
+ }\r
+ else if(s_output.length() < columns) {\r
+ for(int i = 0; i < s_output.length() - columns; i++)\r
+ s_output.append(" ");\r
+ }\r
+ }\r
+ if (stdout_is_tty) {\r
+ std::cout << s_output.c_str() << "\r";\r
+ }\r
+ else {\r
+ std::cout << s_output.c_str() << std::endl;\r
+ }\r
+\r
+ \r
+ std::cout.flush();\r
+ output.str("");\r
+\r
+ sleep(1);\r
+ loopcount++;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+void\r
+CCore::LoadDHT()\r
+{\r
+ std::string path = *Settings->getDir();\r
+ path.append("dhtnodes");\r
+ \r
+ std::ifstream nodefile(path.c_str(), std::ios_base::binary);\r
+ if(!nodefile.is_open()) {\r
+ mkdir(Settings->getDir()->c_str(), 0755);\r
+ VerbosePrint("DHT", "Could not load the nodefile.");\r
+ _session->start_dht();\r
+ return;\r
+ }\r
+\r
+ nodefile.unsetf(std::ios_base::skipws);\r
+\r
+ try {\r
+ libtorrent::entry state = libtorrent::bdecode(std::istream_iterator<char>(nodefile),\r
+ std::istream_iterator<char>());\r
+ _session->start_dht(state);\r
+ VerbosePrint("DHT", "DHT started with a nodefile.");\r
+ }\r
+ catch(std::exception& e) {\r
+ std::cout << e.what() << std::endl;\r
+ _session->start_dht();\r
+ }\r
+ nodefile.close();\r
+}\r
+\r
+void\r
+CCore::SaveDHT()\r
+{\r
+ std::string path = *Settings->getDir();\r
+ path.append("dhtnodes");\r
+\r
+ std::ofstream nodefile(path.c_str(), std::ios_base::binary);\r
+ if(!nodefile.is_open()) {\r
+ VerbosePrint("DHT", "Could not save the nodefile.");\r
+ return;\r
+ }\r
+\r
+ nodefile.unsetf(std::ios_base::skipws);\r
+\r
+ libtorrent::entry state = _session->dht_state();\r
+ libtorrent::bencode(std::ostream_iterator<char>(nodefile), state);\r
+ VerbosePrint("DHT", "Saved nodes.");\r
+ nodefile.close();\r
+}\r
+\r
+static void\r
+SignalHandler(int signo)\r
+{\r
+ Core->VerbosePrint("Core", "Received signal.");\r
+ Core->Shutdown();\r
+}\r
+\r
+void\r
+CCore::ScheduleSignal(int signo)\r
+{\r
+ struct sigaction sa;\r
+\r
+ memset(&sa, 0, sizeof(sa));\r
+ sa.sa_handler = SignalHandler;\r
+ sa.sa_flags = SA_RESETHAND;\r
+\r
+ if (sigaction(signo, &sa, NULL) < 0) {\r
+ char errbuf[128];\r
+\r
+ strerror_r(errno, errbuf, 128);\r
+\r
+ std::cerr << "sigaction error: " << errbuf << std::endl;\r
+ exit(EXIT_FAILURE);\r
+ }\r
+}\r
+\r
+void\r
+CCore::Shutdown()\r
+{\r
+ _running = false;\r
+ if(Settings->GetI("dht") > 0) {\r
+ SaveDHT();\r
+ _session->stop_dht();\r
+ }\r
+\r
+ if(statusthread) pthread_cancel(statusthread);\r
+ std::cout << "\nShutting down hrktorrent. Please wait." << std::endl;\r
+\r
+ exit(EXIT_SUCCESS);\r
+}\r
+\r
+int\r
+CCore::Run()\r
+{\r
+ _verbose = (Settings->GetI("verbose") > 0);\r
+ VerbosePrint("Core", "Verbose enabled.");\r
+ VerbosePrint("Core", "Starting torrent session!");\r
+\r
+ IPFilter = new CIPFilter();\r
+\r
+ _session = new libtorrent::session(libtorrent::fingerprint("HT", MAJOR, MINOR, REVISION, TAG));\r
+\r
+ if(Settings->GetI("upnp") > 0)\r
+ _session->start_upnp();\r
+\r
+ _session->listen_on(std::make_pair(Settings->GetI("minport"), Settings->GetI("maxport")));\r
+ if(Settings->GetI("maxup") > 0) {\r
+ _session->set_upload_rate_limit(Settings->GetI("maxup")*1024);\r
+ _session->set_local_upload_rate_limit(Settings->GetI("maxup")*1024);\r
+ }\r
+ if(Settings->GetI("maxdown") > 0){\r
+ _session->set_download_rate_limit(Settings->GetI("maxdown")*1024);\r
+ _session->set_local_download_rate_limit(Settings->GetI("maxdown")*1024);\r
+ }\r
+ try {\r
+ libtorrent::add_torrent_params parms;\r
+\r
+ boost::intrusive_ptr<libtorrent::torrent_info> info = new libtorrent::torrent_info(_argv[_argc-1]);\r
+ boost::filesystem::path p(Settings->GetS("downloaddir"));\r
+ boost::filesystem::create_directory(p);\r
+ if(!boost::filesystem::exists(p)) {\r
+ std::cerr << "Download directory does not exist/could not be created." << std::endl;\r
+ return EXIT_FAILURE;\r
+ }\r
+\r
+ parms.save_path = p;\r
+ parms.ti = info;\r
+ parms.paused = false;\r
+\r
+ _torrent = _session->add_torrent(parms);\r
+ } catch(std::exception& e) {\r
+ std::cerr << "Could not add torrent (" << e.what() <<")" << std::endl;\r
+ return EXIT_FAILURE;\r
+ }\r
+ \r
+ if(Settings->GetI("dht") > 0) {\r
+ VerbosePrint("Core", "Starting DHT.");\r
+ libtorrent::dht_settings dset;\r
+ dset.service_port = _session->listen_port();\r
+ _session->set_dht_settings(dset);\r
+ LoadDHT();\r
+\r
+ // known dht routers for bootstrapping\r
+ _session->add_dht_router(std::make_pair(std::string("router.bittorrent.com"), 6881));\r
+ _session->add_dht_router(std::make_pair(std::string("router.utorrent.com"), 6881));\r
+ _session->add_dht_router(std::make_pair(std::string("router.bitcomet.com"), 6881));\r
+ }\r
+\r
+ if(Settings->GetI("ipfilter") > 0 && IPFilter->IsActive()) {\r
+ _session->set_ip_filter(IPFilter->getFilter());\r
+ }\r
+\r
+ ScheduleSignal(SIGINT);\r
+ std::cout << "\"CTRL-C\" shuts hrktorrent down.\n" << std::endl;\r
+\r
+ pthread_create(&statusthread, NULL, StatusLoop, NULL);\r
+\r
+ /*\r
+ * reading stdin does not work with output redirection or running the\r
+ * program in background\r
+ */\r
+ /*\r
+ char input;\r
+ std::cin.unsetf(std::ios_base::skipws);\r
+ std::cin >> input;\r
+ */\r
+\r
+ /* wait for signal */\r
+ pause();\r
+\r
+ Shutdown();\r
+}\r
+\r
+void\r
+CCore::VerbosePrint(std::string source, std::string message)\r
+{\r
+ if(!_verbose) return;\r
+ std::cout << "[" << source << "] ";\r
+ std::cout << message << std::endl;\r
+}\r
+\r
--- /dev/null
+#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
--- /dev/null
+.\" 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 <hrkfrd@gmail.com>
--- /dev/null
+#ifndef _HRKTORRENT_H
+#define _HRKTORRENT_H
+
+#include <iostream>
+#include <fstream>
+#include <iterator>
+#include <exception>
+
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <boost/format.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/tuple/tuple.hpp>
+
+#include <libtorrent/entry.hpp>
+#include <libtorrent/bencode.hpp>
+#include <libtorrent/session.hpp>
+#include <libtorrent/session_settings.hpp>
+#include <libtorrent/ip_filter.hpp>
+
+#include "version.h"
+#include "core.h"
+#include "settings.h"
+#include "utils.h"
+#include "ipfilter.h"
+
+#endif
--- /dev/null
+# 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
--- /dev/null
+#include "hrktorrent.h"\r
+\r
+CIPFilter* IPFilter = 0;\r
+\r
+CIPFilter::CIPFilter()\r
+{\r
+ if(!Settings->GetI("ipfilter")) {\r
+ _active = false;\r
+ return;\r
+ }\r
+ else\r
+ _active = true;\r
+\r
+ std::string path = *Settings->getDir();\r
+ path.append("ipfilter.dat");\r
+\r
+ std::ifstream config(path.c_str(), std::ifstream::in);\r
+ if(!config.is_open()) {\r
+ Core->VerbosePrint("Settings", "Unable to load ip filter from file. Aborting.");\r
+ return;\r
+ }\r
+\r
+ std::cout << "Loading IPFilter. This could probably take a while!" << std::endl;\r
+ \r
+ while(config.good()) {\r
+ std::string line;\r
+ getline(config, line);\r
+ ParseFilterLine(line);\r
+ }\r
+\r
+ libtorrent::ip_filter::filter_tuple_t filters = _ipfilter.export_filter();\r
+ unsigned int entrycount = filters.get<0>().size() + filters.get<1>().size();\r
+ std::cout << entrycount << " entries imported." << std::endl;\r
+\r
+ config.close();\r
+}\r
+\r
+CIPFilter::~CIPFilter()\r
+{\r
+ Core->VerbosePrint("IPFilter", "Destroying IPFilter class.");\r
+}\r
+\r
+\r
+bool\r
+CIPFilter::AddRule(std::string start, std::string end)\r
+{\r
+ if(start.empty() || end.empty() || !_active) return false;\r
+\r
+ libtorrent::address astart, aend;\r
+ try {\r
+ astart = libtorrent::address::from_string(start);\r
+ aend = libtorrent::address::from_string(end);\r
+ } catch(boost::system::system_error& e) {\r
+ return false; // invalid rule\r
+ }\r
+\r
+ try {\r
+ _ipfilter.add_rule(astart, aend, libtorrent::ip_filter::blocked);\r
+ } catch(std::exception& e) {\r
+ return false;\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
+void\r
+CIPFilter::ParseFilterLine(std::string line)\r
+{\r
+ if(line.size() == 0 || line.size() < 5 ) return;\r
+\r
+ std::string start;\r
+ std::string end;\r
+\r
+ std::string::size_type loc = line.find_first_of("-");\r
+ std::string::size_type loc2 = line.find_first_of(",");\r
+\r
+ start.assign(line);\r
+ start.resize(loc-1);\r
+\r
+ end.assign(line);\r
+ end.erase(0,loc+2);\r
+ end.resize(loc-1);\r
+\r
+ if(!AddRule(start,end))\r
+ Core->VerbosePrint("Settings", "Error adding line to ip filter.");\r
+}\r
--- /dev/null
+#ifndef _IPFILTER_H\r
+#define _IPFILTER_H\r
+\r
+class CIPFilter\r
+{\r
+ public:\r
+ CIPFilter();\r
+ ~CIPFilter();\r
+ bool AddRule(std::string start, std::string end);\r
+ libtorrent::ip_filter getFilter() { return _ipfilter; }\r
+ bool IsActive() { return (_active == true); }\r
+\r
+ private:\r
+ void ParseFilterLine(std::string line);\r
+ libtorrent::ip_filter _ipfilter;\r
+\r
+ bool _active;\r
+};\r
+\r
+extern CIPFilter* IPFilter;\r
+\r
+#endif\r
--- /dev/null
+#include "hrktorrent.h"
+#include <getopt.h>
+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<<std::endl;
+ break;
+ case 'P':
+ std::cout << opt << " "<< optarg<<std::endl;
+ break;
+ case 'M':
+ std::cout << opt << " "<< optarg<<std::endl;
+ break;
+ case 'u':
+ std::cout << opt << " "<< optarg<<std::endl;
+ break;
+ case 'h':
+ std::cout << opt << " "<< optarg<<std::endl;
+ Settings->Set("nodht", 1);
+ break;
+ case 'n':
+ std::cout << opt << " "<< optarg<<std::endl;
+ Settings->Set("noupnp", 1);
+ break;
+ case 's':
+ std::cout << opt << " "<< optarg<<std::endl;
+ Settings->Set("noseed", 1);
+ break;
+ case 'd':
+ std::cout << opt << " "<< optarg<<std::endl;
+ break;
+ case 'i':
+ std::cout << opt << " "<< optarg<<std::endl;
+ Settings->Set("ipfilter", 1);
+ break;
+ case 'v':
+ std::cout << opt << " "<< optarg<<std::endl;
+ Settings->Set("verbose", 1);
+ break;
+ default:
+ std::cout <<"wtf"<<" "<<opt<<std::endl;
+
+ }
+
+ }
+
+}
+/*
+void
+parseargs(int argc, char** argv)
+{
+ for(unsigned int i = 1; i < argc; i++) {
+ char* parg = argv[i];
+ if(strstr(parg, "--noseed")) {
+ Settings->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<std::string, setting_t>::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 << ", "<<it->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;
+}
--- /dev/null
+#include "hrktorrent.h"\r
+\r
+CSettings* Settings = 0;\r
+\r
+CSettings::CSettings()\r
+{\r
+ /* apply default settings */\r
+ Set("verbose", 1);\r
+\r
+ Set("minport", 6881);\r
+ Set("maxport", 6999);\r
+\r
+ Set("maxup", 0);\r
+ Set("maxdown", 0);\r
+\r
+ Set("dht", 1);\r
+ Set("upnp", 1);\r
+ Set("seed", 1);\r
+ Set("forcereannounce", 2);\r
+ Set("ipfilter", 1);\r
+\r
+ Set("downloaddir", ".");\r
+}\r
+\r
+CSettings::~CSettings()\r
+{\r
+ Core->VerbosePrint("Settings", "Destroying Settings class.");\r
+}\r
+\r
+void\r
+CSettings::LoadConfig()\r
+{\r
+ _dir = getenv("HOME");\r
+ _dir.append("/.hrktorrent/");\r
+ \r
+ std::string path = _dir;\r
+ path.append("hrktorrent.rc");\r
+\r
+ std::ifstream config(path.c_str(), std::ifstream::in);\r
+ if(!config.is_open()) {\r
+ /* workaround: Core->VerbosePrint uses non-initialized Core */\r
+ std::cout << "[Settings] Could not load config file. Will use default values." << std::endl;\r
+\r
+ /* cannot do: Core may not be properly initialized */\r
+ /* Core->VerbosePrint("Settings", "Could not load config file. Will use default values.");*/\r
+ return;\r
+ }\r
+\r
+ while(config.good()) {\r
+ std::string line;\r
+ getline(config, line);\r
+ ParseLine(line);\r
+ }\r
+\r
+ config.close();\r
+}\r
+\r
+void\r
+CSettings::ParseLine(std::string line)\r
+{\r
+ std::string var;\r
+ std::string value;\r
+ std::stringstream linestream;\r
+\r
+ std::string::size_type loc = line.find_first_of("#");\r
+ if(loc < line.size())\r
+ line.resize(loc);\r
+\r
+ linestream.str(line);\r
+\r
+ linestream >> var;\r
+ linestream >> value;\r
+ if(var.empty()) return;\r
+\r
+ switch(settings[var].type) {\r
+ case TYPE_INT:\r
+ Set(var, atoi(value.c_str()));\r
+ break;\r
+ case TYPE_STRING:\r
+ Set(var, value);\r
+ break;\r
+ }\r
+}\r
+\r
--- /dev/null
+#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<std::string, setting_t>* getSettingMap() { return &settings; }
+ private:
+ std::map<std::string, setting_t> settings;
+ std::string _dir;
+};
+extern CSettings* Settings;
+
+#endif
--- /dev/null
+#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;
+}
--- /dev/null
+#ifndef _UTILS_H
+#define _UTILS_H
+
+extern float Round(float Value, int NumPlaces);
+
+#endif
--- /dev/null
+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
+
--- /dev/null
+#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