Compare commits

..

40 Commits

Author SHA1 Message Date
Jari Sundell b2fbbcbfc4 Update libtorrent and rtorrent version to 0.16.13 2026-06-04 18:21:48 +09:00
Jari Sundell 2ca10396b4 Update links to libtorrent and rtorrent versions 2026-05-01 19:51:54 +09:00
Jari Sundell d15dc9d677 Create CNAME 2026-01-01 18:36:54 +09:00
Jari Sundell 356e8041de Upgrade libtorrent and rtorrent links to 0.16.5
Updated links to libtorrent and rtorrent to version 0.16.5.
2025-12-03 06:20:03 +09:00
Jari Sundell 24c44fbb11 Update links to libtorrent and rtorrent versions 2025-11-25 20:12:21 +09:00
Jari Sundell c933cee460 Update download links to version 0.16.3
Updated download links for libtorrent and rtorrent to version 0.16.3.
2025-11-21 23:58:35 +09:00
Jari Sundell a6ab3f0ede Update development links to version 0.16.2
Updated links to libtorrent and rtorrent to version 0.16.2.
2025-11-05 05:06:03 +09:00
Jari Sundell 8adbba62a9 Update download links to version 0.16.1
Updated download links for libtorrent and rtorrent to version 0.16.1.
2025-10-16 18:53:59 +09:00
Jari Sundell 96b2dc6693 Add links for libtorrent and rtorrent 0.16.0
Added links for libtorrent and rtorrent version 0.16.0 under the Development section.
2025-09-05 19:00:04 +09:00
Jari Sundell 7498e77e90 Update stable links to version 0.15.7 2025-09-05 17:06:01 +09:00
Jari Sundell 0e3ade18ad Update stable links and remove unstable versions
Updated stable version links for libtorrent and rtorrent to 0.15.6. Removed unstable version links.
2025-08-31 15:15:17 +09:00
Jari Sundell dba865549f Update index.md 2025-01-22 03:19:19 +09:00
Josh Ellithorpe 5c8087494e Update donate.md Ethereum spelling. 2024-10-29 22:45:10 +09:00
Jari Sundell 2d7ae2c834 Update index.md 2024-09-29 22:59:53 +09:00
Jari Sundell 6c7d75cadb Updated paypal link 2022-09-08 05:03:45 +09:00
Jari Sundell 73544b9d9e Updated paypal link 2022-09-08 05:03:13 +09:00
Jari Sundell 2dd794f982 Added rbEdit to front page. 2021-12-13 04:08:31 +09:00
Jari Sundell 77bb87a9e9 Updated ADA donation address. 2021-11-25 02:14:07 +09:00
Jari Sundell 582bb8a2ad Updated ADA donation address. 2021-11-25 02:13:48 +09:00
Jari Sundell be2a52f825 Updated package links. 2021-08-04 14:24:05 +09:00
Jari Sundell 2b5361e6af Update index.md 2021-07-20 10:34:39 +09:00
Jari Sundell 1419a6664e Update donate.md 2021-07-20 10:34:13 +09:00
Jari Sundell 5547d048e4 Marked 0.9.8 as stable. 2021-03-24 15:53:55 +09:00
Jari Sundell 2663f8050c Update donate.md 2019-12-27 12:45:38 +09:00
Jari Sundell 98d5c169fa Update index.md 2019-12-25 23:41:35 +09:00
Jari Sundell 1478213e90 Update donate.md 2019-12-25 23:40:35 +09:00
Jari Sundell 6b5bdd4d9e Added donation button. 2019-10-03 13:15:50 +09:00
rakshasa e736672f55 Confirmation. 2019-09-22 18:48:21 +09:00
rakshasa 852f6de363 Added donation information to index page. 2019-08-21 23:37:15 +09:00
rakshasa dd85b663a7 Bumped version. 2019-07-19 14:27:49 +02:00
rakshasa 04ddd9af22 Fixed donate links. 2019-07-19 12:58:37 +02:00
rakshasa 1e37d9db6a Added donate page. 2019-07-19 12:56:07 +02:00
Jari Sundell 0c9969960f Update index.md 2019-07-19 12:27:37 +02:00
Jari Sundell da7bbeedb1 Fixed theme 2019-07-19 12:25:07 +02:00
Jari Sundell 836dc60116 Set theme jekyll-theme-minimal and migrate Page Generator content 2019-07-19 12:22:53 +02:00
Jari Sundell b7e0a68eed Update index.html
Links to 0.8.7 added.
2018-07-19 14:47:02 +09:00
Jari Sundell 839fb0cf0b Create gh-pages branch via GitHub 2015-09-04 20:10:20 +09:00
Jari Sundell 9e6a8f39ce Create gh-pages branch via GitHub 2014-05-16 01:17:26 +09:00
Jari Sundell b23b65c907 Create gh-pages branch via GitHub 2014-05-15 23:20:48 +09:00
Jari Sundell 0fb89786a3 Create gh-pages branch via GitHub 2014-05-15 22:41:43 +09:00
262 changed files with 948 additions and 39082 deletions
-69
View File
@@ -1,69 +0,0 @@
# Compiled source #
###################
*.o
*.lo
*.a
*.la
*.so
*.in
*.sub
*.pc
*.orig
*.rej
# Autoconf files #
##################
.deps
.libs
Makefile
aclocal.m4
autom4te.cache
compile
config.h
config.guess
config.status
confdefs.h
conftest.dir
configure
depcomp
install-sh
libtool
ltmain.sh
missing
stamp-h1
scripts/libtool.m4
scripts/lt*.m4
# Editor poo #
##############
.#*
\#*#
*~
# Packages #
############
# it's better to unpack these files and commit the raw source
# git has its own built in compression methods
*.gz
*.tar
*.zip
# Logs and databases #
######################
*.log
# OS generated files #
######################
.DS_Store?
ehthumbs.db
Icon?
Thumbs.db
TAGS
# rTorrent specific files
###########################
src/rtorrent
test/rtorrentTest
test-driver
test/rtorrentTest.trs
-1
View File
@@ -1 +0,0 @@
Jari Sundell <jaris@ifi.uio.no>
+1
View File
@@ -0,0 +1 @@
rtorrent.net
-340
View File
@@ -1,340 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
View File
-229
View File
@@ -1,229 +0,0 @@
Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
Foundation, Inc.
This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it.
Basic Installation
==================
These are generic installation instructions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. (Caching is
disabled by default to prevent problems with accidental use of stale
cache files.)
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You only need
`configure.ac' if you want to change it or regenerate `configure' using
a newer version of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. Run `./configure --help'
for details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not support the `VPATH'
variable, you have to compile the package for one architecture at a
time in the source code directory. After you have installed the
package for one architecture, use `make distclean' before reconfiguring
for another architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=PATH' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' cannot figure out
automatically, but needs to determine by the type of machine the package
will run on. Usually, assuming the package is built to be run on the
_same_ architectures, `configure' can figure that out, but if it prints
a message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the `--target=TYPE' option to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
will cause the specified gcc to be used as the C compiler (unless it is
overridden in the site shell script).
`configure' Invocation
======================
`configure' recognizes the following options to control how it
operates.
`--help'
`-h'
Print a summary of the options to `configure', and exit.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.
-29
View File
@@ -1,29 +0,0 @@
SUBDIRS = \
doc \
src \
test
EXTRA_DIST= \
autogen.sh \
rak/address_info.h \
rak/algorithm.h \
rak/allocators.h \
rak/error_number.h \
rak/file_stat.h \
rak/fs_stat.h \
rak/functional.h \
rak/functional_fun.h \
rak/path.h \
rak/partial_queue.h \
rak/priority_queue.h \
rak/priority_queue_default.h \
rak/regex.h \
rak/socket_address.h \
rak/string_manip.h \
rak/timer.h \
rak/unordered_vector.h \
scripts/checks.m4 \
scripts/common.m4 \
scripts/attributes.m4
ACLOCAL_AMFLAGS = -I scripts
View File
-36
View File
@@ -1,36 +0,0 @@
BUILDING
Run "./autogen.sh" to generate the configure scripts if
nessesary. The man page "doc/rtorrent.1" must be generated with
"docbook2man rtorrent.1.xml" if it is missing.
Note that rtorrent follows the development of libtorrent closely, and
thus the versions must be in sync. This should not be nessesary in the
future, when the library API stabilizes.
USAGE
See the man page or website for instructions.
LICENSE
GNU GPL, see COPYING. "libtorrent/src/utils/sha_fast.{cc,h}" is
originally from the Mozilla NSS and is under a triple license; MPL,
LGPL and GPL. An exception to non-NSS code has been added for linking
to OpenSSL as requested by Debian, though the author considers that
library to be part of the Operative System and thus linking is allowed
according to the GPL.
Use whatever fits your purpose, the code required to compile with
Mozilla's NSS implementation of SHA1 has been retained and can be
compiled if the user wishes to avoid using OpenSSL.
DEPENDENCIES
libcurl >= 7.12.0
ncurses
CONTACT
Send bug reports, suggestions and patches to <jaris@ifi.uio.no> or
to the mailinglist.
+8
View File
@@ -0,0 +1,8 @@
title: Rtorrent
description: rTorrent BitTorrent client
google_analytics:
show_downloads: true
theme: jekyll-theme-minimal
gems:
- jekyll-mentions
-51
View File
@@ -1,51 +0,0 @@
#! /bin/sh
echo aclocal...
(aclocal --version) < /dev/null > /dev/null 2>&1 || {
echo aclocal not found
exit 1
}
aclocal -I ./scripts -I . ${ACLOCAL_FLAGS} || exit 1
echo autoheader...
(autoheader --version) < /dev/null > /dev/null 2>&1 || {
echo autoheader not found
exit 1
}
autoheader || exit 1
echo -n "libtoolize... "
if ( (glibtoolize --version) < /dev/null > /dev/null 2>&1 ); then
echo "using glibtoolize"
glibtoolize --automake --copy --force || exit 1
elif ( (libtoolize --version) < /dev/null > /dev/null 2>&1 ) ; then
echo "using libtoolize"
libtoolize --automake --copy --force || exit 1
else
echo "libtoolize nor glibtoolize not found"
exit 1
fi
echo automake...
(automake --version) < /dev/null > /dev/null 2>&1 || {
echo automake not found
exit 1
}
automake --add-missing --copy --gnu || exit 1
echo autoconf...
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
echo autoconf not found
exit 1
}
autoconf || exit 1
echo ready to configure
exit 0
-79
View File
@@ -1,79 +0,0 @@
AC_INIT(rtorrent, 0.9.4, sundell.software@gmail.com)
AC_DEFINE(API_VERSION, 8, api version)
AM_INIT_AUTOMAKE
AC_CONFIG_HEADERS(config.h)
AM_PATH_CPPUNIT(1.9.6)
AC_PROG_CXX
AC_PROG_LIBTOOL
TORRENT_CHECK_CXXFLAGS()
TORRENT_ENABLE_DEBUG()
TORRENT_ENABLE_EXTRA_DEBUG()
TORRENT_ENABLE_WERROR()
TORRENT_ENABLE_TR1()
TORRENT_ENABLE_CXX11()
TORRENT_DISABLE_IPV6
AC_SYS_LARGEFILE
TORRENT_CHECK_EXECINFO()
TORRENT_OTFD()
TORRENT_ENABLE_ARCH
TORRENT_WITH_SYSROOT
TORRENT_WITHOUT_VARIABLE_FDSET()
TORRENT_WITHOUT_STATVFS()
TORRENT_WITHOUT_STATFS()
AX_PTHREAD([], AC_MSG_ERROR([requires pthread]))
AX_WITH_CURSES()
if test "x$ax_cv_ncursesw" != xyes && test "x$ax_cv_ncurses" != xyes; then
AC_MSG_ERROR([requires either NcursesW or Ncurses library])
fi
CFLAGS="$CFLAGS $PTHREAD_CFLAGS $CURSES_CFLAGS"
CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS $CURSES_CFLAGS"
LIBS="$PTHREAD_LIBS $CURSES_LIB $LIBS"
PKG_CHECK_MODULES([libcurl], libcurl >= 7.15.4,
CXXFLAGS="$CXXFLAGS $libcurl_CFLAGS";
LIBS="$LIBS $libcurl_LIBS")
PKG_CHECK_MODULES([libtorrent], libtorrent >= 0.13.4,
CXXFLAGS="$CXXFLAGS $libtorrent_CFLAGS";
LIBS="$LIBS $libtorrent_LIBS")
AC_LANG_PUSH(C++)
TORRENT_WITH_XMLRPC_C
AC_LANG_POP(C++)
AC_DEFINE(HAVE_CONFIG_H, 1, true if config.h was included)
AC_DEFINE(USER_AGENT, [std::string(PACKAGE "/" VERSION "/") + torrent::version()], Http user agent)
AC_CHECK_FUNCS(posix_memalign)
TORRENT_CHECK_CACHELINE()
TORRENT_CHECK_POPCOUNT()
CC_ATTRIBUTE_UNUSED(
AC_DEFINE([__UNUSED], [__attribute__((unused))], [Wrapper around unused attribute]),
AC_DEFINE([__UNUSED], [], [Null-wrapper if unused attribute is unsupported])
)
AC_OUTPUT([
Makefile
doc/Makefile
src/Makefile
src/core/Makefile
src/display/Makefile
src/input/Makefile
src/rpc/Makefile
src/ui/Makefile
src/utils/Makefile
test/Makefile
])
+4
View File
@@ -0,0 +1,4 @@
Reddit
======
Yes, I'm 'rasatsu'.
-2
View File
@@ -1,2 +0,0 @@
EXTRA_DIST= \
rtorrent.rc
-11
View File
@@ -1,11 +0,0 @@
=== Dumping core files on mac ==
ulimit -c unlimited
sysctl kern.corefile
schedule = log_vmmap,5,600,"execute_nothrow=/Users/rakshasa/trunk/rtorrent/doc/log_vmmap.sh,\"$cat=/Users/rakshasa/Downloads/session/vmmap.system.,$system.pid="; log.vmmap.dump=\"$cat=/Users/rakshasa/Downloads/session/vmmap.rtorrent.,$system.pid=\""
log.vmmap.dump="$cat=/Users/rakshasa/Downloads/session/vmmap.rtorrent.,$system.pid="
print="$cat=/Users/rakshasa/Downloads/session/vmmap.rtorrent.,$system.pid="
-106
View File
@@ -1,106 +0,0 @@
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
<article>
<title>rTorrent Frequently Asked Questions</title>
<para>
This is the user FAQ for Rakshasa's BitTorrent client. RTorrent is
an ncurses based client that uses libTorrent and is written in
C++. Efficiency and good code is the main goal of both projects.
</para>
<qandaset>
<qandaentry>
<question><para>
How do I add new torrents while the client is running?
</para></question>
<answer><para>
Use the backspace key to enter file input mode. The bottom
line will change into a prompt which allows you to enter URL's
or file paths to torrents. File name completion and directory
listing is supported with the tab key.
</para></answer>
</qandaentry>
<qandaentry>
<question><para>
I got the message "Could not create download, failed to parse the bencoded data" when adding a torrent, what does it mean?
</para></question>
<answer><para>
The torrent data the library received was not a valid torrent
file. If this was a direct http download, try downloading the
torrent file and add it manually. This usually happens when
the torrent link uses some form of redirection that libcurl
does not automatically redirect. If the failure still happens,
make sure the file is infact an uncorrupted torrent.
</para></answer>
</qandaentry>
<qandaentry>
<question><para>
How does the session feature work?
</para></question>
<answer><para>
When you start the client you can use the "-s" switch to
specify a session directory. The client will save all
currently running torrents in the session directory and fast
resume data will be written when the client exits. Upon
restarting the client it will resume all the torrents in the
session directory.
</para></answer>
</qandaentry>
<qandaentry>
<question><para>
How do i query the tracker for more peers?
</para></question>
<answer><para>
Go into the download view screen and press 't' to initiate a
new tracker request. If the tracker requires a minimum timeout
between requests you can override this by using the capital
'T'. Don't abuse this feature.
</para></answer>
</qandaentry>
<qandaentry>
<question><para>
Why do I sometimes need to press ctrl-Q twice to exit the client?
</para></question>
<answer><para>
The first time you press ctrl-q you initiate the
shutdown. This causes rTorrent to send a stop message to the
trackers of each torrent, and if the tracker is slow it might
take more than a few seconds or until the requests time
out. The second time ctrl-q is pressed forces the client to
shutdown.
</para></answer>
</qandaentry>
<qandaentry>
<question><para>
It doesn't help how much i press ctrl-q, it still won't quit.
</para></question>
<answer><para>
Perhaps your terminal sends a different key-code to the
application. There's no configuration files for keys yet, so
modify rtorrent/src/ui/root.cc:56 to use whatever key you want
for quitting.
</para></answer>
</qandaentry>
<qandaentry>
<question><para>
When I try downloading a torrent the client aborts (SIGABRT), what should I do?
</para></question>
<answer><para>
Make sure you arn't using "-fomit-frame-pointer" when
compiling libtorrent and rtorrent, this is known to produce
bad code for C++ exception handling. If this doesn't help, run
the client in gdb and use "bt -20" to get a backtrace. Send
this with a bug report.
</para></answer>
</qandaentry>
</qandaset>
</article>
-2
View File
@@ -1,2 +0,0 @@
#!/bin/bash
cat /proc/$PPID/maps > $1
-3
View File
@@ -1,3 +0,0 @@
#!/bin/bash
args=($@)
echo "${args[@]:1}" >> $1
-149
View File
@@ -1,149 +0,0 @@
#/bin/bash
gnuplot << EOF
# 1) system.time_seconds=
#
# 2) throttle.global_up.rate
# 3) throttle.global_up.total
# 4) throttle.global_down.rate
# 5) throttle.global_down.total
#
# 6) pieces.memory.current
# 7) pieces.memory.sync_queue
# 8) pieces.memory.block_count
# 9) pieces.stats.total_size
# 10) pieces.hash.queue_size
#
# file.append = (cat,/foo/bandwidth_stats.,(system.pid)),"timestamp","\"upload rate\"","\"upload total\"","\"download rate\"","\"download total\"","\"memory usage\"","\"sync queue\"","\"block count\"","\"total size\"","\"hash queue size\""
# schedule = log_bandwidth_stats,5,10,((file.append,((cat,/foo/bandwidth_stats.,((system.pid)))),((system.time_seconds)),((throttle.global_up.rate)),((throttle.global_up.total)),((throttle.global_down.rate)),((throttle.global_down.total)),((pieces.memory.current)),((pieces.memory.sync_queue)),((pieces.memory.block_count)),((pieces.stats.total_size)),((pieces.hash.queue_size))))
#
# 1) system.time_seconds
#
# 2) throttle.unchoked_uploads
# 3) throttle.unchoked_downloads
# 4) network.open_sockets
#
# 5) view.size,leeching
# 6) view.size,seeding
# 7) view.size,active
#
# file.append = (cat,/foo/peer_stats.,(system.pid)),"timestamp","\"upload unchoked\"","\"download unchoked\"","\"open sockets\"","leeching","seeding","active"
# schedule = log_peer_stats,5,10,((file.append,((cat,/foo/peer_stats.,((system.pid)))),((system.time_seconds)),((throttle.unchoked_uploads)),((throttle.unchoked_downloads)),((network.open_sockets)),((view.size,leeching)),((view.size,seeding)),((view.size,active))))
#
# Choke groups:
#
# file.append = (cat,/foo/choke_group_stats.,(system.pid)),"timestamp",\
# "\"default up unchoked\"","\"default up queued\"","\"default up rate\"",\
# "\"default down unchoked\"","\"default down queued\"","\"default down rate\"","\"default torrents\"",\
# "\"leech up unchoked\"","\"leech up queued\"","\"leech up rate\"",\
# "\"leech down unchoked\"","\"leech down queued\"","\"leech down rate\"","\"leech torrents\"",\
# "\"seed boost up unchoked\"","\"seed boost up queued\"","\"seed boost up rate\"",\
# "\"seed boost down unchoked\"","\"seed boost down queued\"","\"seed boost down rate\"","\"seed boost torrents\"",\
# "\"seed up unchoked\"","\"seed up queued\"","\"seed up rate\"",\
# "\"seed down unchoked\"","\"seed down queued\"","\"seed down rate\"","\"seed torrents\""
#
# schedule = log_choke_group_stats,5,10,((file.append,((cat,/foo/choke_group_stats.,((system.pid)))),((system.time_seconds)),\
# ((choke_group.up.unchoked,0)),((choke_group.up.queued,0)),((choke_group.up.rate,0)),((choke_group.down.unchoked,0)),((choke_group.down.queued,0)),((choke_group.down.rate,0)),((choke_group.size,0)),\
# ((choke_group.up.unchoked,1)),((choke_group.up.queued,1)),((choke_group.up.rate,1)),((choke_group.down.unchoked,1)),((choke_group.down.queued,1)),((choke_group.down.rate,1)),((choke_group.size,1)),\
# ((choke_group.up.unchoked,2)),((choke_group.up.queued,2)),((choke_group.up.rate,2)),((choke_group.down.unchoked,2)),((choke_group.down.queued,2)),((choke_group.down.rate,2)),((choke_group.size,2)),\
# ((choke_group.up.unchoked,3)),((choke_group.up.queued,3)),((choke_group.up.rate,3)),((choke_group.down.unchoked,3)),((choke_group.down.queued,3)),((choke_group.down.rate,3)),((choke_group.size,3)) ))
#
# Mincore stats:
#
# file.append = (cat,/foo/mincore_stats.,(system.pid)),"timestamp","\"incore cont. /10s\"","\"not incore cont. /10s\"","\"incore new /10s\"","\"not incore new /10s\"","\"incore break /10s\"","\"sync success /10s\"","\"sync failed /10s\"","\"sync not synced /10s\"","\"sync not deallocated /10s\"","\"alloc failed /10s\"","\"allocate velocity /10s\"","\"deallocate velocity /10s\""
# log.libtorrent = mincore_stats,(cat,"/foo/mincore_stats.",(system.pid))
set terminal png size 1024,768 enhanced
#set terminal png size 2*1024,768 enhanced
set xdata time
set timefmt "%s"
set format x "%H:%M"
set format y2 "%.0f"
set y2tics
set autoscale xfix
set key autotitle columnhead
set output "output_$1_sockets.png"
plot "peer_stats.$1" using 1:7 smooth sbezier with lines lw 4,\
"peer_stats.$1" using 1:5 smooth sbezier with lines lw 4,\
"peer_stats.$1" using 1:6 smooth sbezier with lines lw 4,\
"<awk '{x=1000; if (\$4 < 1000) x=\$4; print \$1,x}' peer_stats.$1" using 1:2 smooth sbezier with lines title "open sockets" lw 2 axis x1y2,\
"peer_stats.$1" using 1:2 smooth sbezier with lines lw 2 axis x1y2,\
"peer_stats.$1" using 1:3 smooth sbezier with lines lw 2 axis x1y2
set output "output_$1_groups.png"
plot "choke_group_stats.$1" \
using 1:8 smooth sbezier with lines lw 4,\
"" using 1:8+7*1 smooth sbezier with lines lw 4,\
"" using 1:8+7*2 smooth sbezier with lines lw 4,\
"" using 1:8+7*3 smooth sbezier with lines lw 4\
set format y "%.0s %cb"
set output "output_$1_bandwidth.png"
plot "bandwidth_stats.$1" using 1:2 smooth sbezier with lines lw 4,\
"bandwidth_stats.$1" using 1:4 smooth sbezier with lines lw 4,\
"choke_group_stats.$1" using 1:4+7*1 smooth sbezier with lines lw 3,\
"choke_group_stats.$1" using 1:7+7*1 smooth sbezier with lines lw 3,\
"choke_group_stats.$1" using 1:4+7*2 smooth sbezier with lines lw 3,\
"choke_group_stats.$1" using 1:4+7*3 smooth sbezier with lines lw 3,\
"peer_stats.$1" using 1:2 smooth sbezier with lines lw 2 axis x1y2,\
"peer_stats.$1" using 1:3 smooth sbezier with lines lw 2 axis x1y2
set output "output_$1_memory.png"
plot "bandwidth_stats.$1" using 1:6 smooth sbezier with lines lw 4 axis x1y1,\
"peer_stats.$1" using 1:2 smooth sbezier with lines lw 2 axis x1y2,\
"peer_stats.$1" using 1:3 smooth sbezier with lines lw 2 axis x1y2
#set yrange [0:3900000000.0]
#set y2range [0:2000]
set output "output_$1_pieces.png"
plot "bandwidth_stats.$1" using 1:6 smooth sbezier with lines lw 4 axis x1y1,\
"bandwidth_stats.$1" using 1:7 smooth sbezier with lines lw 4 axis x1y1,\
"<awk '{x=\$12*10; print \$1,x}' mincore_stats.$1" using 1:2 smooth sbezier with lines lw 4 title 'alloc /100s' axis x1y1,\
"<awk '{x=\$13*10; print \$1,x}' mincore_stats.$1" using 1:2 smooth sbezier with lines lw 4 title 'dealloc /100s' axis x1y1,\
"mincore_stats.$1" using 1:7 smooth sbezier with lines lw 2 axis x1y2,\
"mincore_stats.$1" using 1:8 smooth sbezier with lines lw 2 axis x1y2,\
"mincore_stats.$1" using 1:11 smooth sbezier with lines lw 2 axis x1y2,\
"<awk '{x=\$8/10; print \$1,x}' bandwidth_stats.$1" using 1:2 smooth sbezier with lines lw 2 title 'block count /10' axis x1y2,\
"bandwidth_stats.$1" using 1:10 smooth sbezier with lines lw 2 axis x1y2
#set yrange [*:*]
#set y2range [*:*]
set format y2 "%.0s %cb"
set output "output_$1_torrents.png"
plot "bandwidth_stats.$1" using 1:6 smooth sbezier with lines lw 4 axis x1y1,\
"bandwidth_stats.$1" using 1:9 smooth sbezier with lines lw 2 axis x1y2
set format y "%.0f"
set format y2 "%.0f"
set output "output_$1_incore.png"
#plot "bandwidth_stats.$1" using 1:(0) smooth sbezier with lines,
plot \
"mincore_stats.$1" using 1:2 smooth sbezier with lines lw 2 axis x1y1,\
"mincore_stats.$1" using 1:3 smooth sbezier with lines lw 4 axis x1y2,\
"mincore_stats.$1" using 1:4 smooth sbezier with lines lw 2 axis x1y1,\
"mincore_stats.$1" using 1:5 smooth sbezier with lines lw 4 axis x1y2
#
# Updated:
#
set output "output_$1_choke.png"
set style histogram columnstacked
plot "choke_group_stats.$1" \
using 1:2+7*1 smooth sbezier with lines lw 2 axis x1y2,\
"" using 1:3+7*1 smooth sbezier with lines lw 2 axis x1y2,\
"" using 1:5+7*1 smooth sbezier with lines lw 2 axis x1y2,\
"" using 1:6+7*1 smooth sbezier with lines lw 2 axis x1y2,\
"" using 1:2+7*2 smooth sbezier with lines lw 2 axis x1y2,\
"" using 1:3+7*2 smooth sbezier with lines lw 2 axis x1y2,\
"" using 1:2+7*3 smooth sbezier with lines lw 2 axis x1y2,\
"" using 1:3+7*3 smooth sbezier with lines lw 2 axis x1y2
EOF
-2
View File
@@ -1,2 +0,0 @@
#!/bin/bash
vmmap -interleaved $PPID > $1
-28
View File
@@ -1,28 +0,0 @@
# Choke Groups
## Settings
choke_group.insert = "leech_fast"
Create a new group named "leech_fast", accessible by the string or
index / reverse index according to order of insertion. E.g. '-1'
refers to the last inserted choke group, while 0 refers to the first.
All commands that applies to a group requires the first argument to be
the index, reverse index or the group name.
choke_group.tracker.mode.set = -1,"aggressive"
Set the tracker mode for torrents in this group.
choke_group.up.heuristics.set = -1,"upload_leech_experimental"
choke_group.down.heuristics.set = -1,"download_leech"
Set the heuristics used when deciding on which peers to choke and
unchoke. Use "strings.choke_heuristics{,.upload,.download}" to get a
list of the available heuristics.
choke_group.up.max.set = -1,250
choke_group.down.max.set = -1,500
Set the max total number of unchoked peers for all torrents in this choke group.
-64
View File
@@ -1,64 +0,0 @@
# IP filtering
## Introduction
## Make a new ip table
ip_tables.insert_table = <table_name>
Create a new empty table with the name table\_name, with the default
value returned being $0$.
There is currently no use of the generic ip tables commands.
## Add a new address block
ip_tables.add_address = <table_name>, 10.0.0.0/8, <value>
Set <value\> for all addresses in the address block, overwriting prior
values.
## Add a new address block
ip_tables.load = <table_name>, ~/foo.txt, <value>
Set <value\> for all addresses in the file foo.txt separated by
newline, similar to add\_address.
## Get value for address
ip_tables.get = <table_name>, 10.10.10.10
Returns the value set for an address, or the address block it belongs
to. The default is $0$.
## Size of data structures
ip_tables.size_data = <table_name>
Returns the size in bytes of all data structures for this table,
excluding the root class object itself. Note that the in-memory table is
dynamically consolidated, as such memory use will always be based on
actual fragmentation.
The table is a b-tree with 1024 nodes per branch.
## IPv4 filtering table
ipv4_filter.add_address = 10.0.0.0/8, unwanted
ipv4_filter.add_address = 11.0.0.0/8, preferred
ipv4_filter.load = ~/filters.txt, unwanted
ipv4_filter.get = 10.10.10.10
ipv4_filter.size_data =
The main ip filter, currently supporting unwanted (do not allow
connections) and preferred (currently used only in private code).
## Constants
strings.ip_filter =
=>
{ "unwanted", PeerInfo::flag_unwanted },
{ "preferred", PeerInfo::flag_preferred },
Constants used by ipv4\_filter values.
-85
View File
@@ -1,85 +0,0 @@
\section{IP filtering}
\subsection{Introduction}
\subsection{Make a new ip table}
\begin{verbatim}
ip_tables.insert_table = <table_name>
\end{verbatim}
Create a new empty table with the name 'table\_name', with the default
value returned being $0$.
There is currently no use of the generic ip tables commands.
\subsection{Add a new address block}
\begin{verbatim}
ip_tables.add_address = <table_name>, 10.0.0.0/8, <value>
\end{verbatim}
Set <value> for all addresses in the address block, overwriting prior
values.
\subsection{Add a new address block}
\begin{verbatim}
ip_tables.load = <table_name>, ~/foo.txt, <value>
\end{verbatim}
Set <value> for all addresses in the file 'foo.txt' separated by
newline, similar to 'add\_address'.
\subsection{Get value for address}
\begin{verbatim}
ip_tables.get = <table_name>, 10.10.10.10
\end{verbatim}
Returns the value set for an address, or the address block it belongs
to. The default is $0$.
\subsection{Size of data structures}
\begin{verbatim}
ip_tables.size_data = <table_name>
\end{verbatim}
Returns the size in bytes of all data structures for this table,
excluding the root class object itself. Note that the in-memory table
is dynamically consolidated, as such memory use will always be based
on actual fragmentation.
The table is a b-tree with 1024 nodes per branch.
\subsection{IPv4 filtering table}
\begin{verbatim}
ipv4_filter.add_address = 10.0.0.0/8, unwanted
ipv4_filter.add_address = 11.0.0.0/8, preferred
ipv4_filter.load = ~/filters.txt, unwanted
ipv4_filter.get = 10.10.10.10
ipv4_filter.size_data =
\end{verbatim}
The main ip filter, currently supporting 'unwanted' (do not allow
connections) and 'preferred' (currently used only in private code).
\subsection{Constants}
\begin{verbatim}
strings.ip_filter =
=>
{ "unwanted", PeerInfo::flag_unwanted },
{ "preferred", PeerInfo::flag_preferred },
\end{verbatim}
Constants used by ipv4_filter values.
-50
View File
@@ -1,50 +0,0 @@
# Logging
## Opening log files
# log.open_file = "log name", "file path"
log.open_file = "rtorrent.log", (cat,/tmp/rtorrent.log.,(system.pid))
A newly opened log file is not connected to any logging events.
Some control over formatting will be provided at a later date.
## Adding outputs to events
# log.add_output = "logging event", "log name"
log.add_output = "info", "rtorrent.log"
log.add_output = "dht_debug", "tracker.log"
log.add_output = "tracker_debug", "tracker.log"
Each log handle can be added to multiple different logging events.
## Logging events
"critical"
"error"
"warn"
"notice"
"info"
"debug"
The above events receive logging events from all the sub-groups
displayed below, and each event also reciving events from the event
above in importance.
Thus some high-volume sub-group events such as “tracker\_debug” are not
part of “debug” and every “warn” event will receive events from “error”,
“critical”.
"connection_*"
"dht_*"
"peer_*"
"rpc_*"
"storage_*"
"thread_*"
"tracker_*"
"torrent_*"
All sub-groups have events from “critical” to “debug” defined.
-61
View File
@@ -1,61 +0,0 @@
\section{Logging}
\subsection{Opening log files}
\begin{verbatim}
# log.open_file = "log name", "file path"
log.open_file = "rtorrent.log", (cat,/tmp/rtorrent.log.,(system.pid))
\end{verbatim}
A newly opened log file is not connected to any logging events.
Some control over formatting will be provided at a later date.
\subsection{Adding outputs to events}
\begin{verbatim}
# log.add_output = "logging event", "log name"
log.add_output = "info", "rtorrent.log"
log.add_output = "dht_debug", "tracker.log"
log.add_output = "tracker_debug", "tracker.log"
\end{verbatim}
Each log handle can be added to multiple different logging events.
\subsection{Logging events}
\begin{verbatim}
"critical"
"error"
"warn"
"notice"
"info"
"debug"
\end{verbatim}
The above events receive logging events from all the sub-groups
displayed below, and each event also reciving events from the event
above in importance.
Thus some high-volume sub-group events such as ``tracker\_debug'' are
not part of ``debug'' and every ``warn'' event will receive events
from ``error'', ``critical''.
\begin{verbatim}
"connection_*"
"dht_*"
"peer_*"
"rpc_*"
"storage_*"
"thread_*"
"tracker_*"
"torrent_*"
\end{verbatim}
All sub-groups have events from ``critical'' to ``debug'' defined.
-560
View File
@@ -1,560 +0,0 @@
.\" This manpage has been automatically generated by docbook2man
.\" from a DocBook document. This tool can be found at:
.\" <http://shell.ipoline.com/~elmert/comp/docbook2X/>
.\" Please send any bug reports, improvements, comments, patches,
.\" etc. to Steve Cheng <steve@ggi-project.org>.
.TH "RTORRENT" "1" "14 May 2009" "BitTorrent client for ncurses" ""
.SH NAME
rtorrent \- a BitTorrent client for ncurses
.SH SYNOPSIS
\fBrtorrent\fR [ \fB-h\fR ] [ \fB-n\fR ] [ \fB-o key1=opt1,...\fR ] [ \fB-O key=opt\fR ] [ \fBURL | FILE\fR\fI ...\fR ]
.SH "DESCRIPTION"
.PP
\fBrtorrent\fR is a BitTorrent client for ncurses, using
the \fBlibtorrent\fR library. The client and library is
written in C++ with emphasis on speed and efficiency, while delivering
equivalent features to those found in GUI based clients in an ncurses
client.
.PP
Most of the options below have their own default unit in addition to
supporting B, K, M and G suffixes.
.SH "KEYBOARD CONTROL"
.PP
.SS "GLOBAL KEYS"
.TP
\fB^q\fR
Initiate shutdown, press again to force the shutdown and
skip sending the stop signal to trackers.
.TP
\fBup | down | left | right arrow keys\fR
.TP
\fB^P | ^N | ^B | ^F\fR
Select entries or change windows. The right arrow key or ^F is often
used for viewing details about the selected entry, while the left
arrow key or ^B often returns to the previous screen.
.TP
\fBa | s | d\fR
Increase the upload throttle by 1/5/50 KB.
.TP
\fBA | S | D\fR
Increase the download throttle by 1/5/50 KB.
.TP
\fBz | x | c\fR
Decrease the upload throttle by 1/5/50 KB.
.TP
\fBZ | X | C\fR
Decrease the download throttle by 1/5/50 KB.
.SS "MAIN VIEW KEYS"
.TP
\fB->\fR
View download.
.TP
\fB1 - 7\fR
Change view.
.TP
\fB^S\fR
Start download.
.TP
\fB^D\fR
Stop an active download, or remove a stopped download.
.TP
\fB^K\fR
Close a torrent and its files.
.TP
\fB^E\fR
Set the 'create/resize queued' flags on all files in a torrent. This
is necessary if the underlying files in a torrent have been deleted or
truncated, and thus rtorrent must recreate them.
.TP
\fB^R\fR
Initiate hash check of torrent.
.TP
\fB^O\fR
Change the destination directory of the download. The torrent must be
closed.
.TP
\fB^X\fR
Call commands or change settings.
.TP
\fB^B\fR
Set download to perform initial seeding. Only use when
you are the first and only seeder so far for the download.
.TP
\fB+ | -\fR
Change the priority of the download.
.TP
\fBbackspace\fR
Add torrent using an URL or file path. Use
\fBtab\fR to view directory content and do
auto-complete.
.TP
\fBl\fR
View log. Exit by pressing the space-bar.
.TP
\fBU\fR
Delete the file the torrent is tied to, and clear the association.
.TP
\fBI\fR
Toggle whether torrent ignores ratio settings.
.SS "DOWNLOAD VIEW KEYS"
.TP
\fB->\fR
View torrent file list. Use the space-bar to change the file priority
and \fB*\fR to change the priority of all
files. Use \fB/\fR to collapse the directories. OUTDATED
.TP
\fB1 | 2\fR
Adjust max uploads.
.TP
\fB3 | 4\fR
Adjust min peers.
.TP
\fB5 | 6\fR
Adjust max peers.
.TP
\fBu\fR
Display transfering blocks.
.TP
\fBi\fR
Display chunk rarity.
.TP
\fBo\fR
Display the tracker list. Cycle the trackers in a group with the
space-bar.
.TP
\fBp\fR
View peer and torrent information.
.TP
\fBt | T\fR
Initiate tracker request. Use capital T to force the request, ignoring
the "min interval" set by the tracker.
.TP
\fBk\fR
Disconnect peer.
.TP
\fB*\fR
Choke/Snub peer.
.SH "OPTIONS"
.TP
\fB-b \fIa.b.c.d\fB\fR
Bind listening socket and outgoing connections to this network
interface address.
.TP
\fB-d \fIdirectory\fB\fR
Set the default download directory. Defaults to "./".
.TP
\fB-h\fR
Display help and exit.
.TP
\fB-i \fIa.b.c.d\fB\fR
Set the address reported to the tracker.
.TP
\fB-n\fR
Don't load ~/.rtorrent.rc on startup.
.TP
\fB-o key1=opt1,...\fR
.TP
\fB-O key=opt\fR
Set any number of options, see the SETTINGS section. The options given
here override the resource files. Use capital \fB-O\fR
to allow comma in the option.
.TP
\fB-p \fIa-b\fB\fR
Try to open a listening port in the range \fBa\fR up to
and including \fBb\fR\&.
.TP
\fB-s \fIdirectory\fB\fR
Session management will be enabled and the torrent files for all open
downloads will be stored in this directory. Only one instance of
rtorrent should be used with each session directory, though at the
moment no locking is done. An empty string will disable the session
directory.
.SH "GENERAL SETTINGS"
.PP
.TP
\fBbind = \fIa.b.c.d\fB\fR
Bind listening socket and outgoing connections to this network
interface address.
.TP
\fBip = \fIa.b.c.d\fB\fR
.TP
\fBip = \fIhostname\fB\fR
Set the address reported to the tracker.
.TP
\fBport_range = \fIa-b\fB\fR
Try to open a listening port in the range \fBa\fR up to
and including \fBb\fR\&.
.TP
\fBport_random = \fIyes | no\fB\fR
Open the listening port at a random position in the port range.
.TP
\fBcheck_hash = \fIyes | no\fB\fR
Perform hash check on torrents that have finished downloading.
.TP
\fBdirectory = \fIdirectory\fB\fR
Set the default download directory. Defaults to "./".
.TP
\fBsession = \fIdirectory\fB\fR
Session management will be enabled and the torrent files for all open
downloads will be stored in this directory. Only one instance of
rtorrent can be used per session directory. An empty string will
disable the session directory.
.TP
\fBhttp_proxy = \fIurl\fB\fR
Use a http proxy. Use an empty string to disable.
.TP
\fBencoding_list = \fIencoding\fB\fR
Add a preferred filename encoding to the list. The encodings are
attempted in the order they are inserted, if none match the torrent
default is used.
.TP
\fBencryption = \fIoption\fB,\fI\&...\fB\fR
Set how rtorrent should deal with encrypted Bittorrent connections. By
default, encryption is disabled, equivalent to specifying the option
\fBnone\fR\&. Alternatively, any number of the following
options may be specified:
\fBallow_incoming\fR (allow incoming encrypted connections),
\fBtry_outgoing\fR (use encryption for outgoing connections),
\fBrequire\fR (disable unencrypted handshakes),
\fBrequire_RC4\fR (also disable plaintext transmission after the
initial encrypted handshake),
\fBenable_retry\fR (if the initial outgoing connection fails, retry
with encryption turned on if it was off or off if it was on),
\fBprefer_plaintext\fR (choose plaintext when peer offers a choice
between plaintext transmission and RC4 encryption, otherwise RC4 will be used).
.TP
\fBpeer_exchange = \fIyes | no\fB\fR
Enable/disable peer exchange for torrents that aren't marked private. Disabled by default.
.TP
\fBschedule = \fIid\fB,\fIstart\fB,\fIinterval\fB,\fIcommand\fB\fR
Call \fBcommand\fR every \fBinterval\fR
seconds, starting from \fBstart\fR\&. An
\fBinterval\fR of zero calls the task once, while a
\fBstart\fR of zero calls it immediately. Currently
\fBcommand\fR is forwarded to the option handler.
\fBstart\fR and \fBinterval\fR may
optionally use a time format, \fBdd:hh:mm:ss\fR\&. F.ex to
start a task every day at \fB18:00\fR, use
\fB18:00:00,24:00:00\fR\&.
.TP
\fBschedule_remove = \fIid\fB\fR
Delete \fBid\fR from the scheduler.
.TP
\fBstart_tied =\fR
Start torrents that are tied to filenames that have been re-added.
.TP
\fBstop_untied =\fR
.TP
\fBclose_untied =\fR
.TP
\fBremove_untied =\fR
Stop, close or remove the torrents that are tied to filenames that
have been deleted. Clear the association with the 'U' key.
.TP
\fBclose_low_diskspace = \fIspace\fB\fR
Close any active torrents on filesystems with less than
\fBspace\fR diskspace left. Use with
the \fBschedule\fR option. A default scheduled event
with id \fBlow_diskspace\fR is set to 500Mb.
.TP
\fBload = \fIfile\fB\fR
.TP
\fBload_verbose = \fIfile\fB\fR
.TP
\fBload_start = \fIfile\fB\fR
.TP
\fBload_start_verbose = \fIfile\fB\fR
Load and possibly start a file, or possibly multiple files by using the
wild-card "*". This is meant for use with
\fBschedule\fR, though ensure that the
\fBstart\fR is non-zero. The loaded file will be tied
to the filename provided.
.TP
\fBimport = \fIfile\fB\fR
.TP
\fBtry_import = \fIfile\fB\fR
Load a resource file. \fBtry_import\fR does not throw
torrent::input_error exception on bad input.
.TP
\fBstop_on_ratio = \fImin_ratio\fB\fR
.TP
\fBstop_on_ratio = \fImin_ratio\fB,\fImin_upload\fB\fR
.TP
\fBstop_on_ratio = \fImin_ratio\fB,\fImin_upload\fB,\fImax_ratio\fB\fR
Stop torrents when they reach the given upload ratio
\fBmin_ratio\fR in percent. If the optional
\fBmin_upload\fR is given, require a total
upload amount of this many bytes as well. If the optional
\fBmax_ratio\fR is given, stop the torrent
when reaching this ratio regardless of the total upload
amount. Exclude certain torrent by pressing
\fBShift+I\fR in the downlist list.
Use with the \fBschedule\fR option.
.TP
\fBon_insert = \fIid\fB,\fIcommand\fB\fR
.TP
\fBon_erase = \fIid\fB,\fIcommand\fB\fR
.TP
\fBon_open = \fIid\fB,\fIcommand\fB\fR
.TP
\fBon_close = \fIid\fB,\fIcommand\fB\fR
.TP
\fBon_start = \fIid\fB,\fIcommand\fB\fR
.TP
\fBon_stop = \fIid\fB,\fIcommand\fB\fR
.TP
\fBon_hash_queued = \fIid\fB,\fIcommand\fB\fR
.TP
\fBon_hash_removed = \fIid\fB,\fIcommand\fB\fR
.TP
\fBon_hash_done = \fIid\fB,\fIcommand\fB\fR
.TP
\fBon_finished = \fIid\fB,\fIcommand\fB\fR
Call a command on a download when its state changes. Only a subset of
commands are available.
.SH "THROTTLE SETTINGS"
.TP
\fBupload_rate = \fIKB\fB\fR
.TP
\fBdownload_rate = \fIKB\fB\fR
Set the maximum global uploand and download rates.
.TP
\fBmin_peers = \fIvalue\fB\fR
.TP
\fBmax_peers = \fIvalue\fB\fR
Set the minimum and maximum number of peers to allow in each download.
.TP
\fBmin_peers_seed = \fIvalue\fB\fR
.TP
\fBmax_peers_seed = \fIvalue\fB\fR
Set the minimum nad maximum number of peers to allow while seeding, or
-1 (default) to use max_peers.
.TP
\fBmax_uploads = \fIvalue\fB\fR
Set the maximum number of simultaneous uploads per download.
.TP
\fBmax_uploads_div = \fIvalue\fB\fR
.TP
\fBmax_downloads_div = \fIvalue\fB\fR
Change the divider used to calculate the max upload and download slots
to use when the throttle is changed. Disable by
setting \fB0\fR\&.
.TP
\fBmax_uploads_global = \fIvalue\fB\fR
.TP
\fBmax_downloads_global = \fIvalue\fB\fR
Max upload and download slots allowed. Disable by
setting \fB0\fR\&.
.TP
\fBthrottle_up = \fIname\fB, \fIupload_rate\fB\fR
.TP
\fBthrottle_down = \fIname\fB, \fIdownload_rate\fB\fR
Define secondary throttle and/or set the given upload or download rate. Attach to a download with the d.set_throttle_name=name command
or switch throttles with Ctrl-T. Download must be stopped when changing throttles. Note that secondary throttles only work if the
global upload/download is throttled. Setting a download to use the \fBNULL\fR throttle makes the download unthrottled
even when there is a global throttle. Note that this special case bypasses the global throttle entirely, and as such its rate and
transfer amounts are not included in the global statistics.
.TP
\fBthrottle_ip = \fIname\fB, \fIhost\fB\fR
.TP
\fBthrottle_ip = \fIname\fB, \fInetwork/prefix\fB\fR
.TP
\fBthrottle_ip = \fIname\fB, \fIstart\fB, \fIend\fB\fR
Use the given secondary throttle for a host, CIDR network or IP range. All peers with a matching IP will use this throttle instead
of the global throttle or a custom download throttle. The name may be \fBNULL\fR to make these peers unthrottled, with
the same caveats as explained above.
.SH "TRACKER RELATED SETTINGS"
.PP
Tracker related settings.
.TP
\fBenable_trackers = \fIyes\fB\fR
Set to \fBno\fR to disable all tracker requests. Useful
for disabling rtorrent with the \fBschedule\fR command.
.TP
\fBtracker_dump = \fIfilename\fB\fR
Dump tracker requests to \fBfilename\fR, disable by
supplying an empty string. Only torrents loaded while
\fBtracker_dump\fR contains a non-empty string will be
logged at the moment, although disabling it will work as expected.
.TP
\fBtracker_numwant = \fInumber\fB\fR
Set the numwant field sent to the tracker, which indicates how many
peers we want. A negative value disables this feature.
.TP
\fBuse_udp_trackers = \fIyes\fB\fR
Use UDP trackers. Disable if you are behind a firewall, etc, that does
not allow connections to UDP trackers.
.TP
\fBdht = \fIdisabled|off|auto|on\fB\fR
Support for querying the distributed hash table (DHT) to find peers for trackerless
torrents or when all trackers are down. Set to \fBdisable\fR to completely
disable DHT, \fBoff\fR (default) to enable DHT but to not start the
DHT server, \fBauto\fR to automatically start and stop the DHT server
as needed or \fBon\fR for permanently keeping the DHT server running.
When set to automatic, the DHT server will start up when the first non-private torrent
is started, and will stop 15-30 minutes after the last non-private torrent is
stopped (or when rTorrent quits). For DHT to work, a session directory must be set (for
saving the DHT cache).
.TP
\fBdht_port = \fInumber\fB\fR
Set the UDP listen port for DHT. Defaults to 6881.
.TP
\fBdht_add_node = \fIhost[:port]\fB\fR
Not intended for use in the configuration file but as one-time option in the
client or on the command line to bootstrap an empty DHT node table. Contacts
the given node and attempts to bootstrap from it if it replies.
The port is optional, with port 6881 being used by default.
.TP
\fBhttp_capath = \fIpath\fB\fR
.TP
\fBhttp_cacert = \fIfilename\fB\fR
Set the certificates to use in http requests. See Curl's
CURLOPT_CAPATH and CURLOPT_CAINFO options for further information.
.SH "USER-INTERFACE SETTINGS"
.PP
Display related settings.
.TP
\fBview_add = \fIname\fB\fR
Create a new view.
.TP
\fBview_sort = \fIname\fB\fR
.TP
\fBview_sort = \fIname\fB,\fIseconds\fB\fR
Sort a view according the the criteria set by
\fBview_sort_current\fR\&. If the optional argument is
supplied, the view is not sorted if a change happened during the last
\fBseconds\fR\&. This command is meant to be used with
\fBschedule\fR\&.
.TP
\fBview_sort_new = \fIname\fB,\fI\&...\fB\fR
.TP
\fBview_sort_current = \fIname\fB,\fI\&...\fB\fR
Set the sorting criteria for when new elements inserted or
\fBview_sort\fR is called. The list can contain any
number of criteria, including zero, from the following:
\fBname\fR, \fBname_reverse\fR,
\fBstopped\fR, \fBstarted\fR,
\fBcomplete\fR, \fBincomplete\fR,
\fBstate_changed\fR,
\fBstate_changed_reverse\fR
.TP
\fBkey_layout = \fIqwerty|azerty|qwertz|dvorak\fB\fR
Change the key-bindings.
.SH "FILE-SYSTEM SETTINGS"
.PP
File-system related settings.
.TP
\fBmax_file_size = \fIsize\fB\fR
Set the maximum size a file can have. Disable by
passing \fB-1\fR\&.
.TP
\fBsplit_file_size = \fIsize\fB\fR
Split files in a torrent larger than \fBsize\fR into
seperate files. Disable by passing \fB-1\fR\&.
.TP
\fBsplit_suffix = \fIstring\fB\fR
Set the suffix used on split files. Defaults
to \fB\&.part\fR\&.
.SH "DOWNLOAD SETTINGS"
.PP
Settings that require a download as a target, the options need to be
called through f.ex \fBon_finished\fR\&.
.TP
\fBcreate_link = \fItype\fB,\fIpath\fB,\fIsuffix\fB\fR
.TP
\fBdelete_link = \fItype\fB,\fIpath\fB,\fIsuffix\fB\fR
Create or delete a symbolic link. The link path is the concatenation
of \fBpath\fR, the result of
the \fBtype\fR on the download,
and \fBsuffix\fR\&.
Available types are; \fBbase_path\fR uses the base path
of the download, \fBbase_filename\fR uses the base
filename of the download, \fBtied\fR uses the path of
the file the download is tied to, see \fBstart_tied\fR\&.
.SH "ADVANCED SETTINGS"
.PP
This list contains settings users shouldn't need to touch, some may
even cause crashes or similar if incorrectly set.
.TP
\fBhash_read_ahead = \fIMB\fB\fR
Configure how far ahead we ask the kernel to read when doing hash
checking. The hash checker uses madvise(..., MADV_WILLNEED) for the
requests.
.TP
\fBhash_interval = \fIms\fB\fR
Interval between attempts to check the hash when the chunk is not in
memory, in milliseconds.
.TP
\fBhash_max_tries = \fItries\fB\fR
Number of attempts to check the hash while using the mincore status,
before forcing. Overworked systems might need lower values to get a
decent hash checking rate.
.TP
\fBsafe_sync = \fIyes|no\fB\fR
Always use MS_SYNC rather than MS_ASYNC when syncing chunks. This may
be nessesary in case of filesystem bugs like NFS in linux ~2.6.13.
.TP
\fBmax_open_files = \fIvalue\fB\fR
Number of files to simultaneously keep open. LibTorrent dynamically
opens and closes files as necessary when mapping files to
memory. Default is based on sysconf(_SC_OPEN_MAX).
You probably only think you know what this option does, so don't touch
it.
.TP
\fBmax_open_sockets = \fIvalue\fB\fR
Number of network sockets to simultaneously keep open. This value is
set to a reasonable value based on \fBsysconf(_SC_OPEN_MAX)\fR\&.
.TP
\fBmax_open_http = \fIvalue\fB\fR
Number of sockets to simultaneously keep open. This value is set
to \fB32\fR by default.
.TP
\fBmax_memory_usage = \fIbytes\fB\fR
Set the max amount of memory space used to mapping file chunks. This
may also be set using \fBulimit -m\fR where 3/4 will be
allocated to file chunks.
.TP
\fBsend_buffer_size = \fIvalue\fB\fR
.TP
\fBreceive_buffer_size = \fIvalue\fB\fR
Adjust the send and receive buffer size for socket.
.TP
\fBumask = \fI0022\fB\fR
Set the umask for this process, which is applied to all files created
by the program.
.TP
\fBcwd = \fIdirectory\fB\fR
Changes the working directory of the process using
\fBchdir\fR\&.
.TP
\fBsession_on_completion = \fIyes\fB\fR
Controls if the session torrent is saved when a torrent finishes. By
default on.
.TP
\fBsession_lock = \fIyes\fB\fR
Controls if a lock file is created in the session directory on startup.
.TP
\fBsession_save = \fR
Save the session files for all downloads.
.TP
\fBtos = \fIdefault|lowdelay|throughput|reliability|mincost\fB\fR
.TP
\fBtos = \fIhex\fB\fR
Change the TOS of peer connections, by default set to
\fBthroughput\fR\&. If the option is set to
\fBdefault\fR then the system default TOS is used. A
hex value may be used for non-standard settings.
.TP
\fBhandshake_log = \fIyes\fB\fR
Enable logging of the peer handshake. This generates a large number of
log messages, but may be useful to debug connection problems.
.SH "AUTHORS"
.PP
Jari "Rakshasa" Sundell <jaris@ifi.uio.no>
File diff suppressed because it is too large Load Diff
-49
View File
@@ -1,49 +0,0 @@
#/bin/bash
gnuplot << EOF
set terminal png size 1024,768 enhanced
set xdata time
set timefmt "%s"
set format x "%H:%M"
set y2tics
set autoscale xfix
set key autotitle columnhead
# set datafile missing '0'
set format y "%.0f"
set format y2 "%.0f"
set yrange [0:]
set y2range [0:]
set output "output_$1_transfer_requests.png"
plot \
"instrumentation_transfers.log.$1" using 1:2 title 'delegated' with lines lw 4 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:3 title 'downloading' with lines lw 4 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:4 title 'finished' with lines lw 4 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:5 title 'skipped' with lines lw 2 axis x1y2,\
"instrumentation_transfers.log.$1" using 1:6 title 'unknown' with lines lw 2 axis x1y2,\
"instrumentation_transfers.log.$1" using 1:7 title 'unordered' with lines lw 2 axis x1y2,\
"instrumentation_transfers.log.$1" using 1:19 title 'unaccounted' with lines lw 2 axis x1y2
set output "output_$1_transfer_queues.png"
plot \
"instrumentation_transfers.log.$1" using 1:8 title 'queue added' with lines lw 2 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:9 title 'queue moved' with lines lw 2 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:10 title 'queue removed' with lines lw 2 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:11 title 'queue total' with lines lw 4 axis x1y2,\
"instrumentation_transfers.log.$1" using 1:12 title 'unordered added' with lines lw 2 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:13 title 'unordered moved' with lines lw 2 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:14 title 'unordered removed' with lines lw 2 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:15 title 'unordered total' with lines lw 4 axis x1y2,\
"instrumentation_transfers.log.$1" using 1:16 title 'stalled added' with lines lw 2 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:17 title 'stalled moved' with lines lw 2 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:18 title 'stalled removed' with lines lw 2 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:19 title 'stalled total' with lines lw 4 axis x1y2,\
"instrumentation_transfers.log.$1" using 1:20 title 'choked added' with lines lw 2 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:21 title 'choked moved' with lines lw 2 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:22 title 'choked removed' with lines lw 2 axis x1y1,\
"instrumentation_transfers.log.$1" using 1:23 title 'choked total' with lines lw 4 axis x1y2
EOF
-30
View File
@@ -1,30 +0,0 @@
#/bin/bash
gnuplot << EOF
set terminal png size 1024,768 enhanced
set xdata time
set timefmt "%s"
set format x "%H:%M"
set y2tics
set autoscale xfix
set key autotitle columnhead
set format y "%.0f"
set format y2 "%.0f"
set output "output_$1_incore_sync.png"
plot \
"instrumentation_mincore.log.$1" using 1:6 title 'success' smooth sbezier with lines lw 4 axis x1y1,\
"instrumentation_mincore.log.$1" using 1:7 title 'failed' smooth sbezier with lines lw 4 axis x1y1,\
"instrumentation_mincore.log.$1" using 1:8 title 'not synced' smooth sbezier with lines lw 4 axis x1y2,\
"instrumentation_mincore.log.$1" using 1:9 title 'not deallocated' smooth sbezier with lines lw 4 axis x1y2
set format y "%.0g"
set output "output_$1_incore_alloc.png"
plot \
"instrumentation_mincore.log.$1" using 1:12 title 'allocations' smooth sbezier with lines lw 2 axis x1y1,\
"instrumentation_mincore.log.$1" using 1:13 title 'deallocations' smooth sbezier with lines lw 4 axis x1y1,\
"instrumentation_mincore.log.$1" using 1:10 title 'alloc failed' smooth sbezier with lines lw 2 axis x1y2
EOF
-84
View File
@@ -1,84 +0,0 @@
# This is an example resource file for rTorrent. Copy to
# ~/.rtorrent.rc and enable/modify the options as needed. Remember to
# uncomment the options you wish to enable.
# Maximum and minimum number of peers to connect to per torrent.
#min_peers = 40
#max_peers = 100
# Same as above but for seeding completed torrents (-1 = same as downloading)
#min_peers_seed = 10
#max_peers_seed = 50
# Maximum number of simultanious uploads per torrent.
#max_uploads = 15
# Global upload and download rate in KiB. "0" for unlimited.
#download_rate = 0
#upload_rate = 0
# Default directory to save the downloaded torrents.
#directory = ./
# Default session directory. Make sure you don't run multiple instance
# of rtorrent using the same session directory. Perhaps using a
# relative path?
#session = ./session
# Watch a directory for new torrents, and stop those that have been
# deleted.
#schedule = watch_directory,5,5,load_start=./watch/*.torrent
#schedule = untied_directory,5,5,stop_untied=
# Close torrents when diskspace is low.
#schedule = low_diskspace,5,60,close_low_diskspace=100M
# The ip address reported to the tracker.
#ip = 127.0.0.1
#ip = rakshasa.no
# The ip address the listening socket and outgoing connections is
# bound to.
#bind = 127.0.0.1
#bind = rakshasa.no
# Port range to use for listening.
#port_range = 6890-6999
# Start opening ports at a random position within the port range.
#port_random = no
# Check hash for finished torrents. Might be usefull until the bug is
# fixed that causes lack of diskspace not to be properly reported.
#check_hash = no
# Set whether the client should try to connect to UDP trackers.
#use_udp_trackers = yes
# Alternative calls to bind and ip that should handle dynamic ip's.
#schedule = ip_tick,0,1800,ip=rakshasa
#schedule = bind_tick,0,1800,bind=rakshasa
# Encryption options, set to none (default) or any combination of the following:
# allow_incoming, try_outgoing, require, require_RC4, enable_retry, prefer_plaintext
#
# The example value allows incoming encrypted connections, starts unencrypted
# outgoing connections but retries with encryption if they fail, preferring
# plaintext to RC4 encryption after the encrypted handshake
#
# encryption = allow_incoming,enable_retry,prefer_plaintext
# Enable DHT support for trackerless torrents or when all trackers are down.
# May be set to "disable" (completely disable DHT), "off" (do not start DHT),
# "auto" (start and stop DHT as needed), or "on" (start DHT immediately).
# The default is "off". For DHT to work, a session directory must be defined.
#
# dht = auto
# UDP port to use for DHT.
#
# dht_port = 6881
# Enable peer exchange (for torrents not marked private)
#
# peer_exchange = yes
-128
View File
@@ -1,128 +0,0 @@
#!/usr/bin/perl
# Perl script to add rTorrent fast resume data to torrent files.
#
# Usage:
# rtorrent_fast_resume.pl [base-directory] < plain.torrent > with_fast_resume.torrent
# -OR-
# rtorrent_fast_resume.pl [base-directory] plain.torrent [with_fast_resume.torrent]
use strict;
use warnings;
use Convert::Bencode_XS qw(bencode bdecode);
use File::Spec; # core module
use POSIX; # core module
$/ = undef;
$| = 1;
# Process ARGV
my $d = $ARGV[0];
if ($d and not -d $d) {
if (-f $d and -s $d and not $ARGV[2]) { # missing directory, but has file
$ARGV[2] = $ARGV[1];
$ARGV[1] = $ARGV[0];
$d = '';
}
else { die "$d is not a directory\n"; }
}
$d ||= ".";
$d .= "/" unless $d =~ m#/$#;
my ($in, $out, $msg);
my ($in_file, $out_file) = ('', '');
if ($ARGV[1]) {
$in_file = $ARGV[1];
open($in, ($ARGV[2] ? '<' : '+<'), $in_file) || die "Cannot open $in_file for input!\n";
unless ($ARGV[2]) {
$out = $in;
$out_file = $in_file;
}
}
else { $in = *STDIN; }
if ($ARGV[2]) {
$out_file = $ARGV[2];
open($out, '>', $out_file) || die "Cannot open $out_file for output!\n";
$msg = *STDOUT;
}
elsif (!$ARGV[1]) { $out = *STDOUT; }
$msg //= *STDERR;
print {$msg} "Total input torrent size: ".sprintf('%.2f', (-s $in_file) / 1024)." KB\n" if $in_file;
print {$msg} "Decoding ".($in_file || 'torrent from standard input')."...";
my $t = bdecode(scalar <$in>);
die "No info key.\n" unless ref $t eq "HASH" and exists $t->{info};
my $psize = $t->{info}{"piece length"} or die "No piece length key.\n";
print {$msg} "done\n\n";
my @files;
my $tsize = 0;
if (exists $t->{info}{files}) {
print {$msg} "Multi file torrent: $t->{info}{name}\n";
for (@{$t->{info}{files}}) {
push @files, join "/", $t->{info}{name},@{$_->{path}};
$tsize += $_->{length};
}
}
else {
print {$msg} "Single file torrent: $t->{info}{name}\n";
@files = ($t->{info}{name});
$tsize = $t->{info}{length};
}
my $chunks = int(($tsize + $psize - 1) / $psize);
print {$msg} "Total size: ".sprintf('%.2f', $tsize / 1024**2)." MB; $chunks chunks; ", scalar @files, " files.\n\n";
die "Inconsistent piece information!\n" if $chunks*20 != length $t->{info}{pieces};
print {$msg} "Adding fast resume information...";
# flags => 1+16+
my $pmod = 0;
$t->{libtorrent_resume}{bitfield} = $chunks;
foreach my $f (0..$#files) {
die "$d$files[$f] not found.\n" unless -e "$d$files[$f]";
my $mtime = (stat "$d$files[$f]")[9];
# Compute number of chunks per file
my $fsize = $t->{info}{files}[$f]{length};
my $fchunks = ($pmod ? 1 : 0);
if ($pmod >= $fsize) { ($fsize, $pmod ) = (0, $pmod-$fsize); }
else { ($pmod, $fsize) = (0, $fsize-$pmod); }
$fchunks += ceil($fsize / $psize);
$pmod ||= $psize - ($fsize % $psize);
$t->{libtorrent_resume}{files}[$f] = {
priority => 0, # Don't download; we already have the file, so don't clobber it!
mtime => $mtime,
completed => $fchunks,
};
};
$t->{libtorrent_resume}{'uncertain_pieces.timestamp'} = time;
# Some extra information to re-enforce the fact that this is a finished torrent
$d .= $t->{info}{name};
$t->{rtorrent} = {
state => 1, # started
state_changed => time,
state_counter => 1,
chunks_wanted => 0,
chunks_done => $chunks,
complete => 1,
hashing => 0, # Not hashing
directory => File::Spec->file_name_is_absolute($d) ? $d : File::Spec->rel2abs($d),
((tied_to_file => File::Spec->file_name_is_absolute($out_file) ? $out_file : File::Spec->rel2abs($out_file)) x!! $out_file),
'timestamp.finished' => 0,
'timestamp.started' => time,
};
print {$msg} "done\n";
print {$msg} "Encoding ".($out_file || 'torrent from standard output')."...";
seek($out, 0, 0); # just in case files are the same
print {$out} bencode($t);
close($in);
close($out);
print {$msg} "done\n";
exit;
-23
View File
@@ -1,23 +0,0 @@
#!/usr/bin/perl
# Perl script to read torrent data
use strict;
use warnings;
use Convert::Bencode_XS qw(bdecode);
use Data::Dumper;
$/ = undef;
$| = 1;
my $in;
my $in_file = $ARGV[0];
if ($in_file) { open($in, '<', $in_file) || die "Cannot open $in_file for input!\n"; }
else { $in = *STDIN; }
print "Total input torrent size: ".sprintf('%.2f', (-s $in_file) / 1024)." KB\n" if $in_file;
print "Decoding ".($in_file || 'torrent from standard input')."...";
my $t = bdecode(scalar <$in>);
print "done\n\n";
print Data::Dumper->new([$t], ['*Torrent'])->Indent(1)->Useqq(1)->Quotekeys(0)->Sortkeys(1)->Dump;
+14
View File
@@ -0,0 +1,14 @@
Donate to rTorrent development
==============================
* [Paypal](https://paypal.me/jarisundellno)
* [Patreon](https://www.patreon.com/rtorrent)
* [SubscribeStar](https://www.subscribestar.com/rtorrent)
* Bitcoin: 1MpmXm5AHtdBoDaLZstJw8nupJJaeKu8V8
* Ethereum: 0x9AB1e3C3d8a875e870f161b3e9287Db0E6DAfF78
* Litecoin: LdyaVR67LBnTf6mAT4QJnjSG2Zk67qxmfQ
* Cardano: addr1qytaslmqmk6dspltw06sp0zf83dh09u79j49ceh5y26zdcccgq4ph7nmx6kgmzeldauj43254ey97f3x4xw49d86aguqwfhlte
Help keep rTorrent development going by donating to its creator.
(Note the old paypal account is defunct, please use the new one when sending donations)
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="96" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="96" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h49v20H0z"/><path fill="#97ca00" d="M49 0h47v20H49z"/><path fill="url(#b)" d="M0 0h96v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"> <text x="255" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="390">Donate</text><text x="255" y="140" transform="scale(.1)" textLength="390">Donate</text><text x="715" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="370">PayPal</text><text x="715" y="140" transform="scale(.1)" textLength="370">PayPal</text></g> </svg>

After

Width:  |  Height:  |  Size: 954 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 943 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

+39
View File
@@ -0,0 +1,39 @@
RTorrent
========
Introduction
------------
To learn how to use rTorrent visit the [Wiki](https://github.com/rakshasa/rtorrent/wiki).
[Donate](https://rakshasa.github.io/rtorrent/donate.html) to help fund the development of this client.
Stable
------
* [libtorrent-0.16.11.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.16.11.tar.gz)
* [rtorrent-0.16.11.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.16.11.tar.gz)
Development
-----------
* [libtorrent-0.16.13.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/libtorrent-0.16.13.tar.gz)
* [rtorrent-0.16.13.tar.gz](https://github.com/rakshasa/rtorrent-archive/raw/master/rtorrent-0.16.13.tar.gz)
Related Projects
----------------
* [https://github.com/rakshasa/rbedit](https://github.com/rakshasa/rbedit): A dependency-free bencode editor.
Donate to rTorrent development
------------------------------
* [Paypal](https://paypal.me/jarisundellno)
* [Patreon](https://www.patreon.com/rtorrent)
* [SubscribeStar](https://www.subscribestar.com/rtorrent)
* Bitcoin: 1MpmXm5AHtdBoDaLZstJw8nupJJaeKu8V8
* Ethereum: 0x9AB1e3C3d8a875e870f161b3e9287Db0E6DAfF78
* Litecoin: LdyaVR67LBnTf6mAT4QJnjSG2Zk67qxmfQ
* Cardano: addr1qytaslmqmk6dspltw06sp0zf83dh09u79j49ceh5y26zdcccgq4ph7nmx6kgmzeldauj43254ey97f3x4xw49d86aguqwfhlte
Help keep rTorrent development going by donating to its creator.
+1
View File
@@ -0,0 +1 @@
console.log('This would be the main JS file.');
+17
View File
@@ -0,0 +1,17 @@
var metas = document.getElementsByTagName('meta');
var i;
if (navigator.userAgent.match(/iPhone/i)) {
for (i=0; i<metas.length; i++) {
if (metas[i].name == "viewport") {
metas[i].content = "width=device-width, minimum-scale=1.0, maximum-scale=1.0";
}
}
document.addEventListener("gesturestart", gestureStart, false);
}
function gestureStart() {
for (i=0; i<metas.length; i++) {
if (metas[i].name == "viewport") {
metas[i].content = "width=device-width, minimum-scale=0.25, maximum-scale=1.6";
}
}
}
-98
View File
@@ -1,98 +0,0 @@
// rak - Rakshasa's toolbox
// Copyright (C) 2005-2007, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Wrapper for addrinfo with focus on zero-copy conversion to and from
// the c-type and wrapper.
//
// Do use the wrapper on a pre-existing struct addrinfo, cast the
// pointer rather than the base type.
#ifndef RAK_ADDRESS_INFO_H
#define RAK_ADDRESS_INFO_H
#include <netdb.h>
#include <rak/socket_address.h>
namespace rak {
class address_info {
public:
void clear() { std::memset(this, 0, sizeof(address_info)); }
int flags() const { return m_addrinfo.ai_flags; }
void set_flags(int f) { m_addrinfo.ai_flags = f; }
int family() const { return m_addrinfo.ai_family; }
void set_family(int f) { m_addrinfo.ai_family = f; }
int socket_type() const { return m_addrinfo.ai_socktype; }
void set_socket_type(int t) { m_addrinfo.ai_socktype = t; }
int protocol() const { return m_addrinfo.ai_protocol; }
void set_protocol(int p) { m_addrinfo.ai_protocol = p; }
size_t length() const { return m_addrinfo.ai_addrlen; }
socket_address* address() { return reinterpret_cast<socket_address*>(m_addrinfo.ai_addr); }
addrinfo* c_addrinfo() { return &m_addrinfo; }
const addrinfo* c_addrinfo() const { return &m_addrinfo; }
address_info* next() { return reinterpret_cast<address_info*>(m_addrinfo.ai_next); }
static int get_address_info(const char* node, int domain, int type, address_info** ai);
static void free_address_info(address_info* ai) { ::freeaddrinfo(ai->c_addrinfo()); }
static const char* strerror(int err) { return gai_strerror(err); }
private:
addrinfo m_addrinfo;
};
inline int
address_info::get_address_info(const char* node, int pfamily, int stype, address_info** ai) {
address_info hints;
hints.clear();
hints.set_family(pfamily);
hints.set_socket_type(stype);
return ::getaddrinfo(node, NULL, hints.c_addrinfo(), reinterpret_cast<addrinfo**>(ai));
}
}
#endif
-181
View File
@@ -1,181 +0,0 @@
// rak - Rakshasa's toolbox
// Copyright (C) 2005-2007, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RAK_ALGORITHM_H
#define RAK_ALGORITHM_H
#include <algorithm>
#include <functional>
#include <limits>
namespace rak {
template <typename _InputIter, typename _Function>
_Function
for_each_pre(_InputIter __first, _InputIter __last, _Function __f) {
_InputIter __tmp;
while (__first != __last) {
__tmp = __first++;
__f(*__tmp);
}
return __f;
}
// Return a range with a distance of no more than __distance and
// between __first and __last, centered on __middle1.
template <typename _InputIter, typename _Distance>
std::pair<_InputIter, _InputIter>
advance_bidirectional(_InputIter __first, _InputIter __middle1, _InputIter __last, _Distance __distance) {
_InputIter __middle2 = __middle1;
do {
if (!__distance)
break;
if (__middle2 != __last) {
++__middle2;
--__distance;
} else if (__middle1 == __first) {
break;
}
if (!__distance)
break;
if (__middle1 != __first) {
--__middle1;
--__distance;
} else if (__middle2 == __last) {
break;
}
} while (true);
return std::make_pair(__middle1, __middle2);
}
template <typename _InputIter, typename _Distance>
_InputIter
advance_forward(_InputIter __first, _InputIter __last, _Distance __distance) {
while (__first != __last && __distance != 0) {
__first++;
__distance--;
}
return __first;
}
template <typename _InputIter, typename _Distance>
_InputIter
advance_backward(_InputIter __first, _InputIter __last, _Distance __distance) {
while (__first != __last && __distance != 0) {
__first--;
__distance--;
}
return __first;
}
template <typename _Value>
struct compare_base : public std::binary_function<_Value, _Value, bool> {
bool operator () (const _Value& complete, const _Value& base) const {
return !complete.compare(0, base.size(), base);
}
};
// Count the number of elements from the start of the containers to
// the first inequal element.
template <typename _InputIter1, typename _InputIter2>
typename std::iterator_traits<_InputIter1>::difference_type
count_base(_InputIter1 __first1, _InputIter1 __last1,
_InputIter2 __first2, _InputIter2 __last2) {
typename std::iterator_traits<_InputIter1>::difference_type __n = 0;
for ( ;__first1 != __last1 && __first2 != __last2; ++__first1, ++__first2, ++__n)
if (*__first1 != *__first2)
return __n;
return __n;
}
template <typename _Return, typename _InputIter, typename _Ftor>
_Return
make_base(_InputIter __first, _InputIter __last, _Ftor __ftor) {
if (__first == __last)
return "";
_Return __base = __ftor(*__first++);
for ( ;__first != __last; ++__first) {
typename std::iterator_traits<_InputIter>::difference_type __pos = count_base(__base.begin(), __base.end(),
__ftor(*__first).begin(), __ftor(*__first).end());
if (__pos < (typename std::iterator_traits<_InputIter>::difference_type)__base.size())
__base.resize(__pos);
}
return __base;
}
template<typename T>
inline int popcount_wrapper(T t) {
#if USE_BUILTIN_POPCOUNT
if (std::numeric_limits<T>::digits <= std::numeric_limits<unsigned int>::digits)
return __builtin_popcount(t);
else
return __builtin_popcountll(t);
#else
#error __builtin_popcount not found.
unsigned int count = 0;
while (t) {
count += t & 0x1;
t >> 1;
}
return count;
#endif
}
}
#endif
-110
View File
@@ -1,110 +0,0 @@
// rak - Rakshasa's toolbox
// Copyright (C) 2005-2007, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Some allocators for cacheline aligned chunks of memory, etc.
#ifndef RAK_ALLOCATORS_H
#define RAK_ALLOCATORS_H
#include <cstddef>
#include <limits>
#include <stdlib.h>
#include <sys/types.h>
namespace rak {
template <class T = void*>
class cacheline_allocator {
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef const void* const_void_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
cacheline_allocator() throw() { }
cacheline_allocator(const cacheline_allocator&) throw() { }
template <class U>
cacheline_allocator(const cacheline_allocator<U>&) throw() { }
~cacheline_allocator() throw() { }
template <class U>
struct rebind { typedef cacheline_allocator<U> other; };
// return address of values
pointer address (reference value) const { return &value; }
const_pointer address (const_reference value) const { return &value; }
size_type max_size () const throw() { return std::numeric_limits<size_t>::max() / sizeof(T); }
pointer allocate(size_type num, const_void_pointer hint = 0) { return alloc_size(num*sizeof(T)); }
static pointer alloc_size(size_type size) {
pointer ptr = NULL;
int __UNUSED result = posix_memalign((void**)&ptr, LT_SMP_CACHE_BYTES, size);
return ptr;
}
void construct (pointer p, const T& value) { new((void*)p)T(value); }
void destroy (pointer p) { p->~T(); }
void deallocate (pointer p, size_type num) { free((void*)p); }
};
template <class T1, class T2>
bool operator== (const cacheline_allocator<T1>&, const cacheline_allocator<T2>&) throw() {
return true;
}
template <class T1, class T2>
bool operator!= (const cacheline_allocator<T1>&, const cacheline_allocator<T2>&) throw() {
return false;
}
}
//
// Operator new with custom allocators:
//
template <typename T>
void* operator new(size_t s, rak::cacheline_allocator<T> a) { return a.alloc_size(s); }
#endif // namespace rak
-88
View File
@@ -1,88 +0,0 @@
// rak - Rakshasa's toolbox
// Copyright (C) 2005-2007, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RAK_ERROR_NUMBER_H
#define RAK_ERROR_NUMBER_H
#include <cerrno>
#include <cstring>
namespace rak {
class error_number {
public:
static const int e_access = EACCES;
static const int e_again = EAGAIN;
static const int e_connreset = ECONNRESET;
static const int e_connaborted = ECONNABORTED;
static const int e_deadlk = EDEADLK;
static const int e_noent = ENOENT;
static const int e_nodev = ENODEV;
static const int e_nomem = ENOMEM;
static const int e_notdir = ENOTDIR;
static const int e_isdir = EISDIR;
static const int e_intr = EINTR;
error_number() : m_errno(0) {}
error_number(int e) : m_errno(e) {}
bool is_valid() const { return m_errno != 0; }
int value() const { return m_errno; }
const char* c_str() const { return std::strerror(m_errno); }
bool is_blocked_momentary() const { return m_errno == e_again || m_errno == e_intr; }
bool is_blocked_prolonged() const { return m_errno == e_deadlk; }
bool is_closed() const { return m_errno == e_connreset || m_errno == e_connaborted; }
bool is_bad_path() const { return m_errno == e_noent || m_errno == e_notdir || m_errno == e_access; }
static error_number current() { return errno; }
static void clear_global() { errno = 0; }
static void set_global(error_number err) { errno = err.m_errno; }
bool operator == (const error_number& e) const { return m_errno == e.m_errno; }
private:
int m_errno;
};
}
#endif
-77
View File
@@ -1,77 +0,0 @@
// rak - Rakshasa's toolbox
// Copyright (C) 2005-2007, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RAK_FILE_STAT_H
#define RAK_FILE_STAT_H
#include <string>
#include <inttypes.h>
#include <sys/stat.h>
namespace rak {
class file_stat {
public:
// Consider storing rak::error_number.
bool update(int fd) { return fstat(fd, &m_stat) == 0; }
bool update(const char* filename) { return stat(filename, &m_stat) == 0; }
bool update(const std::string& filename) { return update(filename.c_str()); }
bool update_link(const char* filename) { return lstat(filename, &m_stat) == 0; }
bool update_link(const std::string& filename) { return update_link(filename.c_str()); }
bool is_regular() const { return S_ISREG(m_stat.st_mode); }
bool is_directory() const { return S_ISDIR(m_stat.st_mode); }
bool is_character() const { return S_ISCHR(m_stat.st_mode); }
bool is_block() const { return S_ISBLK(m_stat.st_mode); }
bool is_fifo() const { return S_ISFIFO(m_stat.st_mode); }
bool is_link() const { return S_ISLNK(m_stat.st_mode); }
bool is_socket() const { return S_ISSOCK(m_stat.st_mode); }
off_t size() const { return m_stat.st_size; }
time_t access_time() const { return m_stat.st_atime; }
time_t change_time() const { return m_stat.st_ctime; }
time_t modified_time() const { return m_stat.st_mtime; }
private:
struct stat m_stat;
};
}
#endif
-84
View File
@@ -1,84 +0,0 @@
// rak - Rakshasa's toolbox
// Copyright (C) 2005-2007, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RAK_FS_STAT_H
#define RAK_FS_STAT_H
#include <string>
#include <inttypes.h>
#include <rak/error_number.h>
#if HAVE_SYS_VFS_H
#include <sys/vfs.h>
#endif
#if HAVE_SYS_STATVFS_H
#include <sys/statvfs.h>
#endif
#if HAVE_SYS_STATFS_H
#include <sys/statfs.h>
#endif
#if HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#if HAVE_SYS_MOUNT_H
#include <sys/mount.h>
#endif
namespace rak {
class fs_stat {
public:
typedef FS_STAT_SIZE_TYPE blocksize_type;
typedef FS_STAT_COUNT_TYPE blockcount_type;
typedef FS_STAT_STRUCT fs_stat_type;
bool update(int fd) { return FS_STAT_FD; }
bool update(const char* fn) { return FS_STAT_FN; }
bool update(const std::string& filename) { return update(filename.c_str()); }
blocksize_type blocksize() { return FS_STAT_BLOCK_SIZE; }
blockcount_type blocks_avail() { return m_stat.f_bavail; }
int64_t bytes_avail() { return (int64_t) blocksize() * m_stat.f_bavail; }
private:
fs_stat_type m_stat;
};
}
#endif
-683
View File
@@ -1,683 +0,0 @@
// rak - Rakshasa's toolbox
// Copyright (C) 2005-2007, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RAK_FUNCTIONAL_H
#define RAK_FUNCTIONAL_H
#include <cstddef>
#include <functional>
namespace rak {
template <typename Type>
struct reference_fix {
typedef Type type;
};
template <typename Type>
struct reference_fix<Type&> {
typedef Type type;
};
template <typename Type>
struct value_t {
value_t(Type v) : m_v(v) {}
Type operator () () const { return m_v; }
Type m_v;
};
template <typename Type>
inline value_t<Type>
value(Type v) {
return value_t<Type>(v);
}
template <typename Type, typename Ftor>
struct accumulate_t {
accumulate_t(Type t, Ftor f) : result(t), m_f(f) {}
template <typename Arg>
void operator () (const Arg& a) { result += m_f(a); }
Type result;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline accumulate_t<Type, Ftor>
accumulate(Type t, Ftor f) {
return accumulate_t<Type, Ftor>(t, f);
}
// Operators:
template <typename Type, typename Ftor>
struct equal_t {
typedef bool result_type;
equal_t(Type t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (Arg& a) {
return m_t == m_f(a);
}
Type m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline equal_t<Type, Ftor>
equal(Type t, Ftor f) {
return equal_t<Type, Ftor>(t, f);
}
template <typename Type, typename Ftor>
struct equal_ptr_t {
typedef bool result_type;
equal_ptr_t(Type* t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (const Arg& a) {
return *m_t == *m_f(a);
}
Type* m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline equal_ptr_t<Type, Ftor>
equal_ptr(Type* t, Ftor f) {
return equal_ptr_t<Type, Ftor>(t, f);
}
template <typename Type, typename Ftor>
struct not_equal_t {
typedef bool result_type;
not_equal_t(Type t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (Arg& a) {
return m_t != m_f(a);
}
Type m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline not_equal_t<Type, Ftor>
not_equal(Type t, Ftor f) {
return not_equal_t<Type, Ftor>(t, f);
}
template <typename Type, typename Ftor>
struct less_t {
typedef bool result_type;
less_t(Type t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (Arg& a) {
return m_t < m_f(a);
}
Type m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline less_t<Type, Ftor>
less(Type t, Ftor f) {
return less_t<Type, Ftor>(t, f);
}
template <typename FtorA, typename FtorB>
struct less2_t : public std::binary_function<typename FtorA::argument_type, typename FtorB::argument_type, bool> {
less2_t(FtorA f_a, FtorB f_b) : m_f_a(f_a), m_f_b(f_b) {}
bool operator () (typename FtorA::argument_type a, typename FtorB::argument_type b) {
return m_f_a(a) < m_f_b(b);
}
FtorA m_f_a;
FtorB m_f_b;
};
template <typename FtorA, typename FtorB>
inline less2_t<FtorA, FtorB>
less2(FtorA f_a, FtorB f_b) {
return less2_t<FtorA,FtorB>(f_a,f_b);
}
template <typename Type, typename Ftor>
struct _greater {
typedef bool result_type;
_greater(Type t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (Arg& a) {
return m_t > m_f(a);
}
Type m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline _greater<Type, Ftor>
greater(Type t, Ftor f) {
return _greater<Type, Ftor>(t, f);
}
template <typename FtorA, typename FtorB>
struct greater2_t : public std::binary_function<typename FtorA::argument_type, typename FtorB::argument_type, bool> {
greater2_t(FtorA f_a, FtorB f_b) : m_f_a(f_a), m_f_b(f_b) {}
bool operator () (typename FtorA::argument_type a, typename FtorB::argument_type b) {
return m_f_a(a) > m_f_b(b);
}
FtorA m_f_a;
FtorB m_f_b;
};
template <typename FtorA, typename FtorB>
inline greater2_t<FtorA, FtorB>
greater2(FtorA f_a, FtorB f_b) {
return greater2_t<FtorA,FtorB>(f_a,f_b);
}
template <typename Type, typename Ftor>
struct less_equal_t {
typedef bool result_type;
less_equal_t(Type t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (Arg& a) {
return m_t <= m_f(a);
}
Type m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline less_equal_t<Type, Ftor>
less_equal(Type t, Ftor f) {
return less_equal_t<Type, Ftor>(t, f);
}
template <typename Type, typename Ftor>
struct greater_equal_t {
typedef bool result_type;
greater_equal_t(Type t, Ftor f) : m_t(t), m_f(f) {}
template <typename Arg>
bool operator () (Arg& a) {
return m_t >= m_f(a);
}
Type m_t;
Ftor m_f;
};
template <typename Type, typename Ftor>
inline greater_equal_t<Type, Ftor>
greater_equal(Type t, Ftor f) {
return greater_equal_t<Type, Ftor>(t, f);
}
template<typename Tp>
struct invert : public std::unary_function<Tp, Tp> {
Tp
operator () (const Tp& x) const { return ~x; }
};
template <typename Src, typename Dest>
struct on_t : public std::unary_function<typename Src::argument_type, typename Dest::result_type> {
typedef typename Dest::result_type result_type;
on_t(Src s, Dest d) : m_dest(d), m_src(s) {}
result_type operator () (typename reference_fix<typename Src::argument_type>::type arg) {
return m_dest(m_src(arg));
}
Dest m_dest;
Src m_src;
};
template <typename Src, typename Dest>
inline on_t<Src, Dest>
on(Src s, Dest d) {
return on_t<Src, Dest>(s, d);
}
template <typename Src, typename Dest>
struct on2_t : public std::binary_function<typename Src::argument_type, typename Dest::second_argument_type, typename Dest::result_type> {
typedef typename Dest::result_type result_type;
on2_t(Src s, Dest d) : m_dest(d), m_src(s) {}
result_type operator () (typename reference_fix<typename Src::argument_type>::type first, typename reference_fix<typename Dest::second_argument_type>::type second) {
return m_dest(m_src(first), second);
}
Dest m_dest;
Src m_src;
};
template <typename Src, typename Dest>
inline on2_t<Src, Dest>
on2(Src s, Dest d) {
return on2_t<Src, Dest>(s, d);
}
// Creates a functor for accessing a member.
template <typename Class, typename Member>
struct mem_ptr_t : public std::unary_function<Class*, Member&> {
mem_ptr_t(Member Class::*m) : m_member(m) {}
Member& operator () (Class* c) {
return c->*m_member;
}
const Member& operator () (const Class* c) {
return c->*m_member;
}
Member Class::*m_member;
};
template <typename Class, typename Member>
inline mem_ptr_t<Class, Member>
mem_ptr(Member Class::*m) {
return mem_ptr_t<Class, Member>(m);
}
template <typename Class, typename Member>
struct mem_ref_t : public std::unary_function<Class&, Member&> {
mem_ref_t(Member Class::*m) : m_member(m) {}
Member& operator () (Class& c) {
return c.*m_member;
}
Member Class::*m_member;
};
template <typename Class, typename Member>
struct const_mem_ref_t : public std::unary_function<const Class&, const Member&> {
const_mem_ref_t(const Member Class::*m) : m_member(m) {}
const Member& operator () (const Class& c) {
return c.*m_member;
}
const Member Class::*m_member;
};
template <typename Class, typename Member>
inline mem_ref_t<Class, Member>
mem_ref(Member Class::*m) {
return mem_ref_t<Class, Member>(m);
}
template <typename Class, typename Member>
inline const_mem_ref_t<Class, Member>
const_mem_ref(const Member Class::*m) {
return const_mem_ref_t<Class, Member>(m);
}
template <typename Cond, typename Then>
struct if_then_t {
if_then_t(Cond c, Then t) : m_cond(c), m_then(t) {}
template <typename Arg>
void operator () (Arg& a) {
if (m_cond(a))
m_then(a);
}
Cond m_cond;
Then m_then;
};
template <typename Cond, typename Then>
inline if_then_t<Cond, Then>
if_then(Cond c, Then t) {
return if_then_t<Cond, Then>(c, t);
}
template <typename T>
struct call_delete : public std::unary_function<T*, void> {
void operator () (T* t) {
delete t;
}
};
template <typename T>
inline void
call_delete_func(T* t) {
delete t;
}
template <typename Operation>
class bind1st_t : public std::unary_function<typename Operation::second_argument_type, typename Operation::result_type> {
public:
typedef typename reference_fix<typename Operation::first_argument_type>::type value_type;
typedef typename reference_fix<typename Operation::second_argument_type>::type argument_type;
bind1st_t(const Operation& op, const value_type v) :
m_op(op), m_value(v) {}
typename Operation::result_type
operator () (const argument_type arg) {
return m_op(m_value, arg);
}
protected:
Operation m_op;
value_type m_value;
};
template <typename Operation, typename Type>
inline bind1st_t<Operation>
bind1st(const Operation& op, const Type& val) {
return bind1st_t<Operation>(op, val);
}
template <typename Operation>
class bind2nd_t : public std::unary_function<typename Operation::first_argument_type, typename Operation::result_type> {
public:
typedef typename reference_fix<typename Operation::first_argument_type>::type argument_type;
typedef typename reference_fix<typename Operation::second_argument_type>::type value_type;
bind2nd_t(const Operation& op, const value_type v) :
m_op(op), m_value(v) {}
typename Operation::result_type
operator () (argument_type arg) {
return m_op(arg, m_value);
}
protected:
Operation m_op;
value_type m_value;
};
template <typename Operation, typename Type>
inline bind2nd_t<Operation>
bind2nd(const Operation& op, const Type& val) {
return bind2nd_t<Operation>(op, val);
}
// Lightweight callback function including pointer to object. Should
// be replaced by TR1 stuff later. Requires an object to bind, instead
// of using a seperate functor for that.
template <typename Ret>
class ptr_fun0 {
public:
typedef Ret result_type;
typedef Ret (*Function)();
ptr_fun0() {}
ptr_fun0(Function f) : m_function(f) {}
bool is_valid() const { return m_function; }
Ret operator () () { return m_function(); }
private:
Function m_function;
};
template <typename Object, typename Ret>
class mem_fun0 {
public:
typedef Ret result_type;
typedef Ret (Object::*Function)();
mem_fun0() : m_object(NULL) {}
mem_fun0(Object* o, Function f) : m_object(o), m_function(f) {}
bool is_valid() const { return m_object; }
Ret operator () () { return (m_object->*m_function)(); }
private:
Object* m_object;
Function m_function;
};
template <typename Object, typename Ret>
class const_mem_fun0 {
public:
typedef Ret result_type;
typedef Ret (Object::*Function)() const;
const_mem_fun0() : m_object(NULL) {}
const_mem_fun0(const Object* o, Function f) : m_object(o), m_function(f) {}
bool is_valid() const { return m_object; }
Ret operator () () const { return (m_object->*m_function)(); }
private:
const Object* m_object;
Function m_function;
};
template <typename Object, typename Ret, typename Arg1>
class mem_fun1 {
public:
typedef Ret result_type;
typedef Ret (Object::*Function)(Arg1);
mem_fun1() : m_object(NULL) {}
mem_fun1(Object* o, Function f) : m_object(o), m_function(f) {}
bool is_valid() const { return m_object; }
Ret operator () (Arg1 a1) { return (m_object->*m_function)(a1); }
private:
Object* m_object;
Function m_function;
};
template <typename Object, typename Ret, typename Arg1>
class const_mem_fun1 {
public:
typedef Ret result_type;
typedef Ret (Object::*Function)(Arg1) const;
const_mem_fun1() : m_object(NULL) {}
const_mem_fun1(const Object* o, Function f) : m_object(o), m_function(f) {}
bool is_valid() const { return m_object; }
Ret operator () (Arg1 a1) const { return (m_object->*m_function)(a1); }
private:
const Object* m_object;
Function m_function;
};
template <typename Object, typename Ret, typename Arg1, typename Arg2>
class mem_fun2 : public std::binary_function<Arg1, Arg2, Ret> {
public:
typedef Ret result_type;
typedef Ret (Object::*Function)(Arg1, Arg2);
typedef Object object_type;
mem_fun2() : m_object(NULL) {}
mem_fun2(Object* o, Function f) : m_object(o), m_function(f) {}
bool is_valid() const { return m_object; }
object_type* object() { return m_object; }
const object_type* object() const { return m_object; }
Ret operator () (Arg1 a1, Arg2 a2) { return (m_object->*m_function)(a1, a2); }
private:
Object* m_object;
Function m_function;
};
template <typename Object, typename Ret, typename Arg1, typename Arg2, typename Arg3>
class mem_fun3 {
public:
typedef Ret result_type;
typedef Ret (Object::*Function)(Arg1, Arg2, Arg3);
mem_fun3() : m_object(NULL) {}
mem_fun3(Object* o, Function f) : m_object(o), m_function(f) {}
bool is_valid() const { return m_object; }
Ret operator () (Arg1 a1, Arg2 a2, Arg3 a3) { return (m_object->*m_function)(a1, a2, a3); }
private:
Object* m_object;
Function m_function;
};
template <typename Ret>
inline ptr_fun0<Ret>
ptr_fun(Ret (*f)()) { return ptr_fun0<Ret>(f); }
template <typename Object, typename Ret>
inline mem_fun0<Object, Ret>
make_mem_fun(Object* o, Ret (Object::*f)()) {
return mem_fun0<Object, Ret>(o, f);
}
template <typename Object, typename Ret>
inline const_mem_fun0<Object, Ret>
make_mem_fun(const Object* o, Ret (Object::*f)() const) {
return const_mem_fun0<Object, Ret>(o, f);
}
template <typename Object, typename Ret, typename Arg1>
inline mem_fun1<Object, Ret, Arg1>
make_mem_fun(Object* o, Ret (Object::*f)(Arg1)) {
return mem_fun1<Object, Ret, Arg1>(o, f);
}
template <typename Object, typename Ret, typename Arg1>
inline const_mem_fun1<Object, Ret, Arg1>
make_mem_fun(const Object* o, Ret (Object::*f)(Arg1) const) {
return const_mem_fun1<Object, Ret, Arg1>(o, f);
}
template <typename Object, typename Ret, typename Arg1, typename Arg2>
inline mem_fun2<Object, Ret, Arg1, Arg2>
make_mem_fun(Object* o, Ret (Object::*f)(Arg1, Arg2)) {
return mem_fun2<Object, Ret, Arg1, Arg2>(o, f);
}
template <typename Object, typename Ret, typename Arg1, typename Arg2, typename Arg3>
inline mem_fun3<Object, Ret, Arg1, Arg2, Arg3>
make_mem_fun(Object* o, Ret (Object::*f)(Arg1, Arg2, Arg3)) {
return mem_fun3<Object, Ret, Arg1, Arg2, Arg3>(o, f);
}
template <typename Container>
inline void
slot_list_call(const Container& slot_list) {
if (slot_list.empty())
return;
typename Container::const_iterator first = slot_list.begin();
typename Container::const_iterator next = slot_list.begin();
while (++next != slot_list.end()) {
(*first)();
first = next;
}
(*first)();
}
template <typename Container, typename Arg1>
inline void
slot_list_call(const Container& slot_list, Arg1 arg1) {
if (slot_list.empty())
return;
typename Container::const_iterator first = slot_list.begin();
typename Container::const_iterator next = slot_list.begin();
while (++next != slot_list.end()) {
(*first)(arg1);
first = next;
}
(*first)(arg1);
}
template <typename Container, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
inline void
slot_list_call(const Container& slot_list, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) {
if (slot_list.empty())
return;
typename Container::const_iterator first = slot_list.begin();
typename Container::const_iterator next = slot_list.begin();
while (++next != slot_list.end()) {
(*first)(arg1, arg2, arg3, arg4);
first = next;
}
(*first)(arg1, arg2, arg3, arg4);
}
}
#endif
-656
View File
@@ -1,656 +0,0 @@
// rak - Rakshasa's toolbox
// Copyright (C) 2005-2007, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// This file contains functors that wrap function pointers and member
// function pointers.
//
// 'fn' functors are polymorphic and derives from 'rak::function' and
// thus is less strict about types, this adds the cost of calling a
// virtual function.
//
// 'fun' functors are non-polymorphic and thus cheaper, but requires
// the target object's type in the functor's template arguments.
//
// This should be replaced with TR1 stuff when it becomes widely
// available. At the moment it behaves like std::auto_ptr, so be
// careful when copying.
#ifndef RAK_FUNCTIONAL_FUN_H
#define RAK_FUNCTIONAL_FUN_H
#include <memory>
#include <functional>
#include <tr1/functional>
#include <tr1/memory>
namespace rak {
template <typename Result>
class function_base0 {
public:
virtual ~function_base0() {}
virtual Result operator () () = 0;
};
template <typename Result, typename Arg1>
class function_base1 : public std::unary_function<Arg1, Result> {
public:
virtual ~function_base1() {}
virtual Result operator () (Arg1 arg1) = 0;
};
template <typename Result, typename Arg1, typename Arg2>
class function_base2 : public std::binary_function<Arg1, Arg2, Result> {
public:
virtual ~function_base2() {}
virtual Result operator () (Arg1 arg1, Arg2 arg2) = 0;
};
template <typename Result, typename Arg1, typename Arg2, typename Arg3>
class function_base3 {
public:
virtual ~function_base3() {}
virtual Result operator () (Arg1 arg1, Arg2 arg2, Arg3 arg3) = 0;
};
template <typename Result>
class function0 {
public:
typedef Result result_type;
typedef function_base0<Result> base_type;
bool is_valid() const { return m_base.get() != NULL; }
void set(base_type* base) { m_base = std::tr1::shared_ptr<base_type>(base); }
base_type* release() { return m_base.release(); }
Result operator () () { return (*m_base)(); }
private:
std::tr1::shared_ptr<base_type> m_base;
};
template <typename Result, typename Arg1>
class function1 {
public:
typedef Result result_type;
typedef function_base1<Result, Arg1> base_type;
bool is_valid() const { return m_base.get() != NULL; }
void set(base_type* base) { m_base = std::tr1::shared_ptr<base_type>(base); }
base_type* release() { return m_base.release(); }
Result operator () (Arg1 arg1) { return (*m_base)(arg1); }
private:
std::tr1::shared_ptr<base_type> m_base;
};
template <typename Result, typename Arg1, typename Arg2>
class function2 {
public:
typedef Result result_type;
typedef function_base2<Result, Arg1, Arg2> base_type;
bool is_valid() const { return m_base.get() != NULL; }
void set(base_type* base) { m_base = std::tr1::shared_ptr<base_type>(base); }
base_type* release() { return m_base.release(); }
Result operator () (Arg1 arg1, Arg2 arg2) { return (*m_base)(arg1, arg2); }
private:
std::tr1::shared_ptr<base_type> m_base;
};
template <typename Result, typename Arg2>
class function2<Result, void, Arg2> {
public:
typedef Result result_type;
typedef function_base1<Result, Arg2> base_type;
bool is_valid() const { return m_base.get() != NULL; }
void set(base_type* base) { m_base = std::tr1::shared_ptr<base_type>(base); }
base_type* release() { return m_base.release(); }
Result operator () (Arg2 arg2) { return (*m_base)(arg2); }
template <typename Discard>
Result operator () (Discard discard, Arg2 arg2) { return (*m_base)(arg2); }
private:
std::tr1::shared_ptr<base_type> m_base;
};
template <typename Result, typename Arg1, typename Arg2, typename Arg3>
class function3 {
public:
typedef Result result_type;
typedef function_base3<Result, Arg1, Arg2, Arg3> base_type;
bool is_valid() const { return m_base.get() != NULL; }
void set(base_type* base) { m_base = std::tr1::shared_ptr<base_type>(base); }
base_type* release() { return m_base.release(); }
Result operator () (Arg1 arg1, Arg2 arg2, Arg3 arg3) { return (*m_base)(arg1, arg2, arg3); }
private:
std::tr1::shared_ptr<base_type> m_base;
};
template <typename Result>
class ptr_fn0_t : public function_base0<Result> {
public:
typedef Result (*Func)();
ptr_fn0_t(Func func) : m_func(func) {}
virtual ~ptr_fn0_t() {}
virtual Result operator () () { return m_func(); }
private:
Func m_func;
};
template <typename Result, typename Arg1>
class ptr_fn1_t : public function_base1<Result, Arg1> {
public:
typedef Result (*Func)(Arg1);
ptr_fn1_t(Func func) : m_func(func) {}
virtual ~ptr_fn1_t() {}
virtual Result operator () (Arg1 arg1) { return m_func(arg1); }
private:
Func m_func;
};
template <typename Result, typename Arg1, typename Arg2>
class ptr_fn2_t : public function_base2<Result, Arg1, Arg2> {
public:
typedef Result (*Func)(Arg1, Arg2);
ptr_fn2_t(Func func) : m_func(func) {}
virtual ~ptr_fn2_t() {}
virtual Result operator () (Arg1 arg1, Arg2 arg2) { return m_func(arg1, arg2); }
private:
Func m_func;
};
template <typename Object, typename Result>
class mem_fn0_t : public function_base0<Result> {
public:
typedef Result (Object::*Func)();
mem_fn0_t(Object* object, Func func) : m_object(object), m_func(func) {}
virtual ~mem_fn0_t() {}
virtual Result operator () () { return (m_object->*m_func)(); }
private:
Object* m_object;
Func m_func;
};
template <typename Object, typename Result, typename Arg1>
class mem_fn1_t : public function_base1<Result, Arg1> {
public:
typedef Result (Object::*Func)(Arg1);
mem_fn1_t(Object* object, Func func) : m_object(object), m_func(func) {}
virtual ~mem_fn1_t() {}
virtual Result operator () (Arg1 arg1) { return (m_object->*m_func)(arg1); }
private:
Object* m_object;
Func m_func;
};
template <typename Object, typename Result, typename Arg1, typename Arg2, typename Arg3>
class mem_fn3_t : public function_base3<Result, Arg1, Arg2, Arg3> {
public:
typedef Result (Object::*Func)(Arg1, Arg2, Arg3);
mem_fn3_t(Object* object, Func func) : m_object(object), m_func(func) {}
virtual ~mem_fn3_t() {}
virtual Result operator () (Arg1 arg1, Arg2 arg2, Arg3 arg3) { return (m_object->*m_func)(arg1, arg2, arg3); }
private:
Object* m_object;
Func m_func;
};
template <typename Object, typename Result, typename Arg1, typename Arg2>
class mem_fn2_t : public function_base2<Result, Arg1, Arg2> {
public:
typedef Result (Object::*Func)(Arg1, Arg2);
mem_fn2_t(Object* object, Func func) : m_object(object), m_func(func) {}
virtual ~mem_fn2_t() {}
virtual Result operator () (Arg1 arg1, Arg2 arg2) { return (m_object->*m_func)(arg1, arg2); }
private:
Object* m_object;
Func m_func;
};
template <typename Object, typename Result>
class const_mem_fn0_t : public function_base0<Result> {
public:
typedef Result (Object::*Func)() const;
const_mem_fn0_t(const Object* object, Func func) : m_object(object), m_func(func) {}
virtual ~const_mem_fn0_t() {}
virtual Result operator () () { return (m_object->*m_func)(); }
private:
const Object* m_object;
Func m_func;
};
template <typename Object, typename Result, typename Arg1>
class const_mem_fn1_t : public function_base1<Result, Arg1> {
public:
typedef Result (Object::*Func)(Arg1) const;
const_mem_fn1_t(const Object* object, Func func) : m_object(object), m_func(func) {}
virtual ~const_mem_fn1_t() {}
virtual Result operator () (Arg1 arg1) { return (m_object->*m_func)(arg1); }
private:
const Object* m_object;
Func m_func;
};
// Unary functor with a bound argument.
template <typename Object, typename Result, typename Arg1>
class mem_fn0_b1_t : public function_base0<Result> {
public:
typedef Result (Object::*Func)(Arg1);
mem_fn0_b1_t(Object* object, Func func, const Arg1 arg1) : m_object(object), m_func(func), m_arg1(arg1) {}
virtual ~mem_fn0_b1_t() {}
virtual Result operator () () { return (m_object->*m_func)(m_arg1); }
private:
Object* m_object;
Func m_func;
const Arg1 m_arg1;
};
template <typename Object, typename Result, typename Arg1, typename Arg2>
class mem_fn1_b1_t : public function_base1<Result, Arg2> {
public:
typedef Result (Object::*Func)(Arg1, Arg2);
mem_fn1_b1_t(Object* object, Func func, const Arg1 arg1) : m_object(object), m_func(func), m_arg1(arg1) {}
virtual ~mem_fn1_b1_t() {}
virtual Result operator () (const Arg2 arg2) { return (m_object->*m_func)(m_arg1, arg2); }
private:
Object* m_object;
Func m_func;
const Arg1 m_arg1;
};
template <typename Object, typename Result, typename Arg1, typename Arg2>
class mem_fn1_b2_t : public function_base1<Result, Arg1> {
public:
typedef Result (Object::*Func)(Arg1, Arg2);
mem_fn1_b2_t(Object* object, Func func, const Arg2 arg2) : m_object(object), m_func(func), m_arg2(arg2) {}
virtual ~mem_fn1_b2_t() {}
virtual Result operator () (const Arg1 arg1) { return (m_object->*m_func)(arg1, m_arg2); }
private:
Object* m_object;
Func m_func;
const Arg2 m_arg2;
};
template <typename Result, typename Arg1>
class ptr_fn0_b1_t : public function_base0<Result> {
public:
typedef Result (*Func)(Arg1);
ptr_fn0_b1_t(Func func, const Arg1 arg1) : m_func(func), m_arg1(arg1) {}
virtual ~ptr_fn0_b1_t() {}
virtual Result operator () () { return m_func(m_arg1); }
private:
Func m_func;
Arg1 m_arg1;
};
template <typename Result, typename Arg1, typename Arg2>
class ptr_fn1_b1_t : public function_base1<Result, Arg2> {
public:
typedef Result (*Func)(Arg1, Arg2);
ptr_fn1_b1_t(Func func, const Arg1 arg1) : m_func(func), m_arg1(arg1) {}
virtual ~ptr_fn1_b1_t() {}
virtual Result operator () (Arg2 arg2) { return m_func(m_arg1, arg2); }
private:
Func m_func;
Arg1 m_arg1;
};
template <typename Result, typename Arg1, typename Arg2, typename Arg3>
class ptr_fn2_b1_t : public function_base2<Result, Arg2, Arg3> {
public:
typedef Result (*Func)(Arg1, Arg2, Arg3);
ptr_fn2_b1_t(Func func, const Arg1 arg1) : m_func(func), m_arg1(arg1) {}
virtual ~ptr_fn2_b1_t() {}
virtual Result operator () (Arg2 arg2, Arg3 arg3) { return m_func(m_arg1, arg2, arg3); }
private:
Func m_func;
Arg1 m_arg1;
};
template <typename Ftor>
class ftor_fn1_t : public function_base1<typename Ftor::result_type, typename Ftor::argument_type> {
public:
typedef typename Ftor::result_type result_type;
typedef typename Ftor::argument_type argument_type;
ftor_fn1_t(Ftor ftor) : m_ftor(ftor) {}
virtual ~ftor_fn1_t() {}
virtual result_type operator () (argument_type arg1) { return m_ftor(arg1); }
private:
Ftor m_ftor;
};
template <typename Ftor>
class ftor_fn2_t : public function_base2<typename Ftor::result_type, typename Ftor::first_argument_type, typename Ftor::second_argument_type> {
public:
typedef typename Ftor::result_type result_type;
typedef typename Ftor::first_argument_type first_argument_type;
typedef typename Ftor::second_argument_type second_argument_type;
ftor_fn2_t(Ftor ftor) : m_ftor(ftor) {}
virtual ~ftor_fn2_t() {}
virtual result_type operator () (first_argument_type arg1, second_argument_type arg2) { return m_ftor(arg1, arg2); }
private:
Ftor m_ftor;
};
template <typename Result>
class value_fn0_t : public function_base0<Result> {
public:
value_fn0_t(const Result& val) : m_value(val) {}
virtual Result operator () () { return m_value; }
private:
Result m_value;
};
template <typename Result, typename SrcResult>
class convert_fn0_t : public function_base0<Result> {
public:
typedef function0<SrcResult> src_type;
convert_fn0_t(typename src_type::base_type* object) { m_object.set(object); }
virtual ~convert_fn0_t() {}
virtual Result operator () () {
return m_object();
}
private:
src_type m_object;
};
template <typename Result, typename Arg1, typename SrcResult, typename SrcArg1>
class convert_fn1_t : public function_base1<Result, Arg1> {
public:
typedef function1<SrcResult, SrcArg1> src_type;
convert_fn1_t(typename src_type::base_type* object) { m_object.set(object); }
virtual ~convert_fn1_t() {}
virtual Result operator () (Arg1 arg1) {
return m_object(arg1);
}
private:
src_type m_object;
};
template <typename Result, typename Arg1, typename Arg2, typename SrcResult, typename SrcArg1, typename SrcArg2>
class convert_fn2_t : public function_base2<Result, Arg1, Arg2> {
public:
typedef function2<SrcResult, SrcArg1, SrcArg2> src_type;
convert_fn2_t(typename src_type::base_type* object) { m_object.set(object); }
virtual ~convert_fn2_t() {}
virtual Result operator () (Arg1 arg1, Arg2 arg2) {
return m_object(arg1, arg2);
}
private:
src_type m_object;
};
template <typename Result>
inline function_base0<Result>*
ptr_fn(Result (*func)()) {
return new ptr_fn0_t<Result>(func);
}
template <typename Arg1, typename Result>
inline function_base1<Result, Arg1>*
ptr_fn(Result (*func)(Arg1)) {
return new ptr_fn1_t<Result, Arg1>(func);
}
template <typename Arg1, typename Arg2, typename Result>
inline function_base2<Result, Arg1, Arg2>*
ptr_fn(Result (*func)(Arg1, Arg2)) {
return new ptr_fn2_t<Result, Arg1, Arg2>(func);
}
template <typename Result, typename Object>
inline function_base0<Result>*
mem_fn(Object* object, Result (Object::*func)()) {
return new mem_fn0_t<Object, Result>(object, func);
}
template <typename Arg1, typename Result, typename Object>
inline function_base1<Result, Arg1>*
mem_fn(Object* object, Result (Object::*func)(Arg1)) {
return new mem_fn1_t<Object, Result, Arg1>(object, func);
}
template <typename Arg1, typename Arg2, typename Result, typename Object>
inline function_base2<Result, Arg1, Arg2>*
mem_fn(Object* object, Result (Object::*func)(Arg1, Arg2)) {
return new mem_fn2_t<Object, Result, Arg1, Arg2>(object, func);
}
template <typename Arg1, typename Arg2, typename Arg3, typename Result, typename Object>
inline function_base3<Result, Arg1, Arg2, Arg3>*
mem_fn(Object* object, Result (Object::*func)(Arg1, Arg2, Arg3)) {
return new mem_fn3_t<Object, Result, Arg1, Arg2, Arg3>(object, func);
}
template <typename Result, typename Object>
inline function_base0<Result>*
mem_fn(const Object* object, Result (Object::*func)() const) {
return new const_mem_fn0_t<Object, Result>(object, func);
}
template <typename Arg1, typename Result, typename Object>
inline function_base1<Result, Arg1>*
mem_fn(const Object* object, Result (Object::*func)(Arg1) const) {
return new const_mem_fn1_t<Object, Result, Arg1>(object, func);
}
template <typename Arg1, typename Result, typename Object>
inline function_base0<Result>*
bind_mem_fn(Object* object, Result (Object::*func)(Arg1), const Arg1 arg1) {
return new mem_fn0_b1_t<Object, Result, Arg1>(object, func, arg1);
}
template <typename Arg1, typename Arg2, typename Result, typename Object>
inline function_base1<Result, Arg2>*
bind_mem_fn(Object* object, Result (Object::*func)(Arg1, Arg2), const Arg1 arg1) {
return new mem_fn1_b1_t<Object, Result, Arg1, Arg2>(object, func, arg1);
}
template <typename Arg1, typename Arg2, typename Result, typename Object>
inline function_base1<Result, Arg1>*
bind2_mem_fn(Object* object, Result (Object::*func)(Arg1, Arg2), const Arg2 arg2) {
return new mem_fn1_b2_t<Object, Result, Arg1, Arg2>(object, func, arg2);
}
template <typename Arg1, typename Result>
inline function_base0<Result>*
bind_ptr_fn(Result (*func)(Arg1), const Arg1 arg1) {
return new ptr_fn0_b1_t<Result, Arg1>(func, arg1);
}
template <typename Arg1, typename Arg2, typename Result>
inline function_base1<Result, Arg2>*
bind_ptr_fn(Result (*func)(Arg1, Arg2), const Arg1 arg1) {
return new ptr_fn1_b1_t<Result, Arg1, Arg2>(func, arg1);
}
template <typename Arg1, typename Arg2, typename Arg3, typename Result>
inline function_base2<Result, Arg2, Arg3>*
bind_ptr_fn(Result (*func)(Arg1, Arg2, Arg3), const Arg1 arg1) {
return new ptr_fn2_b1_t<Result, Arg1, Arg2, Arg3>(func, arg1);
}
template <typename Ftor>
inline function_base1<typename Ftor::result_type, typename Ftor::argument_type>*
ftor_fn1(Ftor ftor) {
return new ftor_fn1_t<Ftor>(ftor);
}
template <typename Ftor>
inline function_base2<typename Ftor::result_type, typename Ftor::first_argument_type, typename Ftor::second_argument_type>*
ftor_fn2(Ftor ftor) {
return new ftor_fn2_t<Ftor>(ftor);
}
template <typename Result>
inline function_base0<Result>*
value_fn(const Result& val) {
return new value_fn0_t<Result>(val);
}
template <typename A, typename B>
struct equal_types_t {
typedef A first_type;
typedef B second_type;
const static int result = 0;
};
template <typename A>
struct equal_types_t<A, A> {
typedef A first_type;
typedef A second_type;
const static int result = 1;
};
template <typename Result, typename SrcResult>
inline function_base0<Result>*
convert_fn(function_base0<SrcResult>* src) {
if (equal_types_t<function_base0<Result>, function_base0<SrcResult> >::result)
// The pointer cast never gets done if the types are different,
// but needs to be here to pleasant the compiler.
return reinterpret_cast<typename equal_types_t<function_base0<Result>, function_base0<SrcResult> >::first_type*>(src);
else
return new convert_fn0_t<Result, SrcResult>(src);
}
template <typename Result, typename Arg1, typename SrcResult, typename SrcArg1>
inline function_base1<Result, Arg1>*
convert_fn(function_base1<SrcResult, SrcArg1>* src) {
if (equal_types_t<function_base1<Result, Arg1>, function_base1<SrcResult, SrcArg1> >::result)
// The pointer cast never gets done if the types are different,
// but needs to be here to pleasant the compiler.
return reinterpret_cast<typename equal_types_t<function_base1<Result, Arg1>, function_base1<SrcResult, SrcArg1> >::first_type*>(src);
else
return new convert_fn1_t<Result, Arg1, SrcResult, SrcArg1>(src);
}
template <typename Result, typename Arg1, typename Arg2, typename SrcResult, typename SrcArg1, typename SrcArg2>
inline function_base2<Result, Arg1, Arg2>*
convert_fn(function_base2<SrcResult, SrcArg1, SrcArg2>* src) {
if (equal_types_t<function_base2<Result, Arg1, Arg2>, function_base2<SrcResult, SrcArg1, SrcArg2> >::result)
// The pointer cast never gets done if the types are different,
// but needs to be here to pleasant the compiler.
return reinterpret_cast<typename equal_types_t<function_base2<Result, Arg1, Arg2>, function_base2<SrcResult, SrcArg1, SrcArg2> >::first_type*>(src);
else
return new convert_fn2_t<Result, Arg1, Arg2, SrcResult, SrcArg1, SrcArg2>(src);
}
}
#endif
-198
View File
@@ -1,198 +0,0 @@
// rak - Rakshasa's toolbox
// Copyright (C) 2005-2007, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RAK_PARTIAL_QUEUE_H
#define RAK_PARTIAL_QUEUE_H
#include <cstring>
#include <stdexcept>
#include <inttypes.h>
namespace rak {
// First step, don't allow overflowing to the next layer. Only disable
// the above layers for now.
// We also include 0 in a single layer as some chunk may be available
// only through seeders.
class partial_queue {
public:
typedef uint8_t key_type;
typedef uint32_t mapped_type;
typedef uint16_t size_type;
typedef std::pair<size_type, size_type> size_pair_type;
static const size_type num_layers = 8;
partial_queue() : m_data(NULL), m_maxLayerSize(0) {}
~partial_queue() { disable(); }
bool is_full() const { return m_ceiling == 0; }
bool is_layer_full(size_type l) const { return m_layers[l].second >= m_maxLayerSize; }
bool is_enabled() const { return m_data != NULL; }
// Add check to see if we can add more. Also make it possible to
// check how full we are in the lower parts so the caller knows when
// he can stop searching.
//
// Though propably not needed, as we must continue til the first
// layer is full.
size_type max_size() const { return m_maxLayerSize * num_layers; }
size_type max_layer_size() const { return m_maxLayerSize; }
// Must be less that or equal to (max size_type) / num_layers.
void enable(size_type ls);
void disable();
void clear();
// Safe to call while pop'ing and it will not reuse pop'ed indices
// so it is guaranteed to reach max_size at some point. This will
// ensure that the user needs to refill with new data at regular
// intervals.
bool insert(key_type key, mapped_type value);
// Only call this when pop'ing as it moves the index.
bool prepare_pop();
mapped_type pop();
private:
partial_queue(const partial_queue&);
void operator = (const partial_queue&);
static size_type ceiling(size_type layer) { return (2 << layer) - 1; }
void find_non_empty();
mapped_type* m_data;
size_type m_maxLayerSize;
size_type m_index;
size_type m_ceiling;
size_pair_type m_layers[num_layers];
};
inline void
partial_queue::enable(size_type ls) {
if (ls == 0)
throw std::logic_error("partial_queue::enable(...) ls == 0.");
delete [] m_data;
m_data = new mapped_type[ls * num_layers];
m_maxLayerSize = ls;
}
inline void
partial_queue::disable() {
delete [] m_data;
m_data = NULL;
m_maxLayerSize = 0;
}
inline void
partial_queue::clear() {
if (m_data == NULL)
return;
m_index = 0;
m_ceiling = ceiling(num_layers - 1);
std::memset(m_layers, 0, num_layers * sizeof(size_pair_type));
}
inline bool
partial_queue::insert(key_type key, mapped_type value) {
if (key >= m_ceiling)
return false;
size_type idx = 0;
// Hmm... since we already check the 'm_ceiling' above, we only need
// to find the target layer. Could this be calculated directly?
while (key >= ceiling(idx))
++idx;
m_index = std::min(m_index, idx);
// Currently don't allow overflow.
if (is_layer_full(idx))
throw std::logic_error("partial_queue::insert(...) layer already full.");
//return false;
m_data[m_maxLayerSize * idx + m_layers[idx].second] = value;
m_layers[idx].second++;
if (is_layer_full(idx))
// Set the ceiling to 0 when layer 0 is full so no more values can
// be inserted.
m_ceiling = idx > 0 ? ceiling(idx - 1) : 0;
return true;
}
// is_empty() will iterate to the first layer with un-popped elements
// and return true, else return false when it reaches a overflowed or
// the last layer.
inline bool
partial_queue::prepare_pop() {
while (m_layers[m_index].first == m_layers[m_index].second) {
if (is_layer_full(m_index) || m_index + 1 == num_layers)
return false;
m_index++;
}
return true;
}
inline partial_queue::mapped_type
partial_queue::pop() {
if (m_index >= num_layers || m_layers[m_index].first >= m_layers[m_index].second)
throw std::logic_error("partial_queue::pop() bad state.");
return m_data[m_index * m_maxLayerSize + m_layers[m_index].first++];
}
}
#endif
-107
View File
@@ -1,107 +0,0 @@
// rak - Rakshasa's toolbox
// Copyright (C) 2005-2007, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Various functions for manipulating file paths. Also consider making
// a directory iterator.
#ifndef RAK_PATH_H
#define RAK_PATH_H
#include <cstdlib>
#include <string>
namespace rak {
inline std::string
path_expand(const std::string& path) {
if (path.empty() || path[0] != '~')
return path;
char* home = std::getenv("HOME");
if (home == NULL)
return path;
return home + path.substr(1);
}
// Don't inline this...
//
// Same strlcpy as found in *bsd.
inline size_t
strlcpy(char *dest, const char *src, size_t size) {
size_t n = size;
const char* first = src;
if (n != 0) {
while (--n != 0)
if ((*dest++ = *src++) == '\0')
break;
}
if (n == 0) {
if (size != 0)
*dest = '\0';
while (*src++)
;
}
return src - first - 1;
}
inline char*
path_expand(const char* src, char* first, char* last) {
if (*src == '~') {
char* home = std::getenv("HOME");
if (home == NULL)
return first;
first += strlcpy(first, home, std::distance(first, last));
if (first > last)
return last;
src++;
}
return std::min(first + strlcpy(first, src, std::distance(first, last)), last);
}
}
#endif
-144
View File
@@ -1,144 +0,0 @@
// rak - Rakshasa's toolbox
// Copyright (C) 2005-2007, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// priority_queue is a priority queue implemented using a binary
// heap. It can contain multiple instances of a value.
#ifndef RAK_PRIORITY_QUEUE_H
#define RAK_PRIORITY_QUEUE_H
#include <algorithm>
#include <functional>
#include <vector>
namespace rak {
template <typename Value, typename Compare, typename Equal, typename Alloc = std::allocator<Value> >
class priority_queue : public std::vector<Value, Alloc> {
public:
typedef std::vector<Value, Alloc> base_type;
typedef typename base_type::reference reference;
typedef typename base_type::const_reference const_reference;
typedef typename base_type::iterator iterator;
typedef typename base_type::const_iterator const_iterator;
typedef typename base_type::value_type value_type;
using base_type::begin;
using base_type::end;
using base_type::size;
using base_type::empty;
priority_queue(Compare l = Compare(), Equal e = Equal())
: m_compare(l), m_equal(e) {}
const_reference top() const {
return base_type::front();
}
void pop() {
std::pop_heap(begin(), end(), m_compare);
base_type::pop_back();
}
void push(const value_type& value) {
base_type::push_back(value);
std::push_heap(begin(), end(), m_compare);
}
template <typename Key>
iterator find(const Key& key) {
return std::find_if(begin(), end(), std::bind2nd(m_equal, key));
}
template <typename Key>
bool erase(const Key& key) {
iterator itr = find(key);
if (itr == end())
return false;
erase(itr);
return true;
}
// Removes 'itr' from the queue. This assumes 'itr' has been
// modified such that it has a higher priority than any other
// element in the queue.
void erase(iterator itr) {
// std::push_heap(begin(), ++itr, m_compare);
// pop();
base_type::erase(itr);
std::make_heap(begin(), end(), m_compare);
}
private:
Compare m_compare;
Equal m_equal;
};
// Iterate while the top node has higher priority, as 'Compare'
// returns false.
template <typename Queue, typename Compare>
class queue_pop_iterator
: public std::iterator<std::forward_iterator_tag, void, void, void, void> {
public:
typedef Queue container_type;
queue_pop_iterator() : m_queue(NULL) {}
queue_pop_iterator(Queue* q, Compare c) : m_queue(q), m_compare(c) {}
queue_pop_iterator& operator ++ () { m_queue->pop(); return *this; }
queue_pop_iterator& operator ++ (int) { m_queue->pop(); return *this; }
typename container_type::const_reference operator * () { return m_queue->top(); }
bool operator != (const queue_pop_iterator& itr) { return !m_queue->empty() && !m_compare(m_queue->top()); }
bool operator == (const queue_pop_iterator& itr) { return m_queue->empty() || m_compare(m_queue->top()); }
private:
Queue* m_queue;
Compare m_compare;
};
template <typename Queue, typename Compare>
inline queue_pop_iterator<Queue, Compare>
queue_popper(Queue& queue, Compare comp) {
return queue_pop_iterator<Queue, Compare>(&queue, comp);
}
}
#endif
-142
View File
@@ -1,142 +0,0 @@
// rak - Rakshasa's toolbox
// Copyright (C) 2005-2007, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RAK_PRIORITY_QUEUE_DEFAULT_H
#define RAK_PRIORITY_QUEUE_DEFAULT_H
#include <tr1/functional>
#include <rak/allocators.h>
#include <rak/priority_queue.h>
#include <rak/timer.h>
#include "torrent/exceptions.h"
namespace rak {
class priority_item {
public:
typedef std::tr1::function<void (void)> slot_void;
priority_item() {}
~priority_item() {
if (is_queued())
throw torrent::internal_error("priority_item::~priority_item() called on a queued item.");
m_time = timer();
m_slot = slot_void();
}
bool is_valid() const { return (bool)m_slot; }
bool is_queued() const { return m_time != timer(); }
slot_void& slot() { return m_slot; }
const timer& time() const { return m_time; }
void clear_time() { m_time = timer(); }
void set_time(const timer& t) { m_time = t; }
bool compare(const timer& t) const { return m_time > t; }
private:
priority_item(const priority_item&);
void operator = (const priority_item&);
timer m_time;
slot_void m_slot;
};
struct priority_compare {
bool operator () (const priority_item* const p1, const priority_item* const p2) const {
return p1->time() > p2->time();
}
};
typedef std::equal_to<priority_item*> priority_equal;
typedef priority_queue<priority_item*, priority_compare, priority_equal,
cacheline_allocator<priority_item*> > priority_queue_default;
inline void
priority_queue_perform(priority_queue_default* queue, timer t) {
while (!queue->empty() && queue->top()->time() <= t) {
priority_item* v = queue->top();
queue->pop();
v->clear_time();
v->slot()();
}
}
inline void
priority_queue_insert(priority_queue_default* queue, priority_item* item, timer t) {
if (t == timer())
throw torrent::internal_error("priority_queue_insert(...) received a bad timer.");
if (!item->is_valid())
throw torrent::internal_error("priority_queue_insert(...) called on an invalid item.");
if (item->is_queued())
throw torrent::internal_error("priority_queue_insert(...) called on an already queued item.");
if (queue->find(item) != queue->end())
throw torrent::internal_error("priority_queue_insert(...) item found in queue.");
item->set_time(t);
queue->push(item);
}
inline void
priority_queue_erase(priority_queue_default* queue, priority_item* item) {
if (!item->is_queued())
return;
// Check is_valid() after is_queued() so that it is safe to call
// erase on untouched instances.
if (!item->is_valid())
throw torrent::internal_error("priority_queue_erase(...) called on an invalid item.");
// Clear time before erasing to force it to the top.
item->clear_time();
if (!queue->erase(item))
throw torrent::internal_error("priority_queue_erase(...) could not find item in queue.");
if (queue->find(item) != queue->end())
throw torrent::internal_error("priority_queue_erase(...) item still in queue.");
}
}
#endif
-111
View File
@@ -1,111 +0,0 @@
// rak - Rakshasa's toolbox
// Copyright (C) 2005-2007, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// This is a hacked up whole string pattern matching. Replace with
// TR1's regex when that becomes widely available. It is intended for
// small strings.
#ifndef RAK_REGEX_H
#define RAK_REGEX_H
#include <sys/types.h>
#include <algorithm>
#include <functional>
#include <string>
#include <list>
namespace rak {
class regex : public std::unary_function<std::string, bool> {
public:
regex() {}
regex(const std::string& p) : m_pattern(p) {}
const std::string& pattern() const { return m_pattern; }
bool operator () (const std::string& p) const;
private:
std::string m_pattern;
};
// This isn't optimized, or very clean. A simple hack that should work.
inline bool
regex::operator () (const std::string& text) const {
if (m_pattern.empty() ||
text.empty() ||
(m_pattern[0] != '*' && m_pattern[0] != text[0]))
return false;
// Replace with unordered_vector?
std::list<unsigned int> paths;
paths.push_front(0);
for (std::string::const_iterator itrText = ++text.begin(), lastText = text.end(); itrText != lastText; ++itrText) {
for (std::list<unsigned int>::iterator itrPaths = paths.begin(), lastPaths = paths.end(); itrPaths != lastPaths; ) {
unsigned int next = *itrPaths + 1;
if (m_pattern[*itrPaths] != '*')
itrPaths = paths.erase(itrPaths);
else
itrPaths++;
// When we reach the end of 'm_pattern', we don't have a whole
// match of 'text'.
if (next == m_pattern.size())
continue;
// Push to the back so that '*' will match zero length strings.
if (m_pattern[next] == '*')
paths.push_back(next);
if (m_pattern[next] == *itrText)
paths.push_front(next);
}
if (paths.empty())
return false;
}
return std::find(paths.begin(), paths.end(), m_pattern.size() - 1) != paths.end();
}
}
#endif
-411
View File
@@ -1,411 +0,0 @@
// rak - Rakshasa's toolbox
// Copyright (C) 2005-2007, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// Wrappers for the various sockaddr types with focus on zero-copy
// casting between the original type and the wrapper class.
//
// The default ctor does not initialize any data.
//
// _n suffixes indicate that the argument or return value is in
// network byte order, _h that they are in hardware byte order.
// Add define for inet6 scope id?
#ifndef RAK_SOCKET_ADDRESS_H
#define RAK_SOCKET_ADDRESS_H
#include <cstring>
#include <string>
#include <stdexcept>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
namespace rak {
class socket_address_inet;
class socket_address_inet6;
class socket_address {
public:
static const sa_family_t af_inet = AF_INET;
static const int pf_inet = PF_INET;
static const sa_family_t af_inet6 = AF_INET6;
static const int pf_inet6 = PF_INET6;
static const sa_family_t af_unspec = AF_UNSPEC;
static const int pf_unspec = PF_UNSPEC;
#ifdef AF_LOCAL
static const sa_family_t af_local = AF_LOCAL;
static const int pf_local = PF_LOCAL;
#else
static const sa_family_t af_local = AF_UNIX;
static const int pf_local = PF_UNIX;
#endif
bool is_valid() const;
bool is_bindable() const;
bool is_address_any() const;
// Should we need to set AF_UNSPEC?
void clear() { std::memset(this, 0, sizeof(socket_address)); set_family(); }
sa_family_t family() const { return m_sockaddr.sa_family; }
void set_family() { m_sockaddr.sa_family = af_unspec; }
uint16_t port() const;
void set_port(uint16_t p);
std::string address_str() const;
bool address_c_str(char* buf, socklen_t size) const;
// Attemts to set it as an inet, then an inet6 address. It will
// never set anything but net addresses, no local/unix.
bool set_address_str(const std::string& a) { return set_address_c_str(a.c_str()); }
bool set_address_c_str(const char* a);
uint32_t length() const;
socket_address_inet* sa_inet() { return reinterpret_cast<socket_address_inet*>(this); }
const socket_address_inet* sa_inet() const { return reinterpret_cast<const socket_address_inet*>(this); }
sockaddr* c_sockaddr() { return &m_sockaddr; }
sockaddr_in* c_sockaddr_inet() { return &m_sockaddrInet; }
const sockaddr* c_sockaddr() const { return &m_sockaddr; }
const sockaddr_in* c_sockaddr_inet() const { return &m_sockaddrInet; }
#ifdef RAK_USE_INET6
socket_address_inet6* sa_inet6() { return reinterpret_cast<socket_address_inet6*>(this); }
const socket_address_inet6* sa_inet6() const { return reinterpret_cast<const socket_address_inet6*>(this); }
sockaddr_in6* c_sockaddr_inet6() { return &m_sockaddrInet6; }
const sockaddr_in6* c_sockaddr_inet6() const { return &m_sockaddrInet6; }
#endif
// Copy a socket address which has the length 'length. Zero out any
// extranous bytes and ensure it does not go beyond the size of this
// struct.
void copy(const socket_address& src, size_t length);
static socket_address* cast_from(sockaddr* sa) { return reinterpret_cast<socket_address*>(sa); }
static const socket_address* cast_from(const sockaddr* sa) { return reinterpret_cast<const socket_address*>(sa); }
// The different families will be sorted according to the
// sa_family_t's numeric value.
bool operator == (const socket_address& rhs) const;
bool operator < (const socket_address& rhs) const;
bool operator == (const sockaddr& rhs) const { return *this == *cast_from(&rhs); }
bool operator == (const sockaddr* rhs) const { return *this == *cast_from(rhs); }
bool operator < (const sockaddr& rhs) const { return *this == *cast_from(&rhs); }
bool operator < (const sockaddr* rhs) const { return *this == *cast_from(rhs); }
private:
union {
sockaddr m_sockaddr;
sockaddr_in m_sockaddrInet;
#ifdef RAK_USE_INET6
sockaddr_in6 m_sockaddrInet6;
#endif
};
};
// Remeber to set the AF_INET.
class socket_address_inet {
public:
bool is_any() const { return is_port_any() && is_address_any(); }
bool is_valid() const { return !is_port_any() && !is_address_any(); }
bool is_port_any() const { return port() == 0; }
bool is_address_any() const { return m_sockaddr.sin_addr.s_addr == htonl(INADDR_ANY); }
void clear() { std::memset(this, 0, sizeof(socket_address_inet)); set_family(); }
uint16_t port() const { return ntohs(m_sockaddr.sin_port); }
uint16_t port_n() const { return m_sockaddr.sin_port; }
void set_port(uint16_t p) { m_sockaddr.sin_port = htons(p); }
void set_port_n(uint16_t p) { m_sockaddr.sin_port = p; }
// Should address() return the uint32_t?
in_addr address() const { return m_sockaddr.sin_addr; }
uint32_t address_h() const { return ntohl(m_sockaddr.sin_addr.s_addr); }
uint32_t address_n() const { return m_sockaddr.sin_addr.s_addr; }
std::string address_str() const;
bool address_c_str(char* buf, socklen_t size) const;
void set_address(in_addr a) { m_sockaddr.sin_addr = a; }
void set_address_h(uint32_t a) { m_sockaddr.sin_addr.s_addr = htonl(a); }
void set_address_n(uint32_t a) { m_sockaddr.sin_addr.s_addr = a; }
bool set_address_str(const std::string& a) { return set_address_c_str(a.c_str()); }
bool set_address_c_str(const char* a);
void set_address_any() { set_port(0); set_address_h(INADDR_ANY); }
sa_family_t family() const { return m_sockaddr.sin_family; }
void set_family() { m_sockaddr.sin_family = AF_INET; }
sockaddr* c_sockaddr() { return reinterpret_cast<sockaddr*>(&m_sockaddr); }
sockaddr_in* c_sockaddr_inet() { return &m_sockaddr; }
const sockaddr* c_sockaddr() const { return reinterpret_cast<const sockaddr*>(&m_sockaddr); }
const sockaddr_in* c_sockaddr_inet() const { return &m_sockaddr; }
bool operator == (const socket_address_inet& rhs) const;
bool operator < (const socket_address_inet& rhs) const;
private:
struct sockaddr_in m_sockaddr;
};
// Unique key for the address, excluding port numbers etc.
class socket_address_key {
public:
// socket_address_host_key() {}
socket_address_key(const socket_address& sa) {
*this = sa;
}
socket_address_key& operator = (const socket_address& sa) {
if (sa.family() == 0) {
std::memset(this, 0, sizeof(socket_address_key));
} else if (sa.family() == socket_address::af_inet) {
// Using hardware order as we use operator < to compare when
// using inet only.
m_addr.s_addr = sa.sa_inet()->address_h();
} else {
// When we implement INET6 handling, embed the ipv4 address in
// the ipv6 address.
throw std::logic_error("socket_address_key(...) received an unsupported protocol family.");
}
return *this;
}
// socket_address_key& operator = (const socket_address_key& sa) {
// }
bool operator < (const socket_address_key& sa) const {
// Compare the memory area instead.
return m_addr.s_addr < sa.m_addr.s_addr;
}
private:
union {
in_addr m_addr;
// #ifdef RAK_USE_INET6
// in_addr6 m_addr6;
// #endif
};
};
inline bool
socket_address::is_valid() const {
switch (family()) {
case af_inet:
return sa_inet()->is_valid();
// case af_inet6:
// return sa_inet6().is_valid();
default:
return false;
}
}
inline bool
socket_address::is_bindable() const {
switch (family()) {
case af_inet:
return !sa_inet()->is_address_any();
default:
return false;
}
}
inline bool
socket_address::is_address_any() const {
switch (family()) {
case af_inet:
return sa_inet()->is_address_any();
default:
return true;
}
}
inline uint16_t
socket_address::port() const {
switch (family()) {
case af_inet:
return sa_inet()->port();
default:
return 0;
}
}
inline void
socket_address::set_port(uint16_t p) {
switch (family()) {
case af_inet:
return sa_inet()->set_port(p);
default:
break;
}
}
inline std::string
socket_address::address_str() const {
switch (family()) {
case af_inet:
return sa_inet()->address_str();
default:
return std::string();
}
}
inline bool
socket_address::address_c_str(char* buf, socklen_t size) const {
switch (family()) {
case af_inet:
return sa_inet()->address_c_str(buf, size);
default:
return false;
}
}
inline bool
socket_address::set_address_c_str(const char* a) {
if (sa_inet()->set_address_c_str(a)) {
sa_inet()->set_family();
return true;
} else {
return false;
}
}
// Is the zero length really needed, should we require some length?
inline uint32_t
socket_address::length() const {
switch(family()) {
case af_inet:
return sizeof(sockaddr_in);
default:
return 0;
}
}
inline void
socket_address::copy(const socket_address& src, size_t length) {
length = std::min(length, sizeof(socket_address));
// Does this get properly optimized?
std::memset(this, 0, sizeof(socket_address));
std::memcpy(this, &src, length);
}
// Should we be able to compare af_unspec?
inline bool
socket_address::operator == (const socket_address& rhs) const {
if (family() != rhs.family())
return false;
switch (family()) {
case af_inet:
return *sa_inet() == *rhs.sa_inet();
// case af_inet6:
// return *sa_inet6() == *rhs.sa_inet6();
default:
throw std::logic_error("socket_address::operator == (rhs) invalid type comparison.");
}
}
inline bool
socket_address::operator < (const socket_address& rhs) const {
if (family() != rhs.family())
return family() < rhs.family();
switch (family()) {
case af_inet:
return *sa_inet() < *rhs.sa_inet();
// case af_inet6:
// return *sa_inet6() < *rhs.sa_inet6();
default:
throw std::logic_error("socket_address::operator < (rhs) invalid type comparison.");
}
}
inline std::string
socket_address_inet::address_str() const {
char buf[INET_ADDRSTRLEN];
if (!address_c_str(buf, INET_ADDRSTRLEN))
return std::string();
return std::string(buf);
}
inline bool
socket_address_inet::address_c_str(char* buf, socklen_t size) const {
return inet_ntop(family(), &m_sockaddr.sin_addr, buf, size);
}
inline bool
socket_address_inet::set_address_c_str(const char* a) {
return inet_pton(AF_INET, a, &m_sockaddr.sin_addr);
}
inline bool
socket_address_inet::operator == (const socket_address_inet& rhs) const {
return
m_sockaddr.sin_addr.s_addr == rhs.m_sockaddr.sin_addr.s_addr &&
m_sockaddr.sin_port == rhs.m_sockaddr.sin_port;
}
inline bool
socket_address_inet::operator < (const socket_address_inet& rhs) const {
return
m_sockaddr.sin_addr.s_addr < rhs.m_sockaddr.sin_addr.s_addr ||
(m_sockaddr.sin_addr.s_addr == rhs.m_sockaddr.sin_addr.s_addr &&
m_sockaddr.sin_port < rhs.m_sockaddr.sin_port);
}
}
#endif
-376
View File
@@ -1,376 +0,0 @@
// rak - Rakshasa's toolbox
// Copyright (C) 2005-2007, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RAK_STRING_MANIP_H
#define RAK_STRING_MANIP_H
#include <algorithm>
#include <cctype>
#include <cstdlib>
#include <iterator>
#include <locale>
namespace rak {
// Use these trim functions until n1872 is widely supported.
template <typename Sequence>
Sequence trim_begin(const Sequence& seq) {
if (seq.empty() || !std::isspace(*seq.begin()))
return seq;
typename Sequence::size_type pos = 0;
while (pos != seq.length() && std::isspace(seq[pos]))
pos++;
return seq.substr(pos, seq.length() - pos);
}
template <typename Sequence>
Sequence trim_end(const Sequence& seq) {
if (seq.empty() || !std::isspace(*(--seq.end())))
return seq;
typename Sequence::size_type pos = seq.size();
while (pos != 0 && std::isspace(seq[pos - 1]))
pos--;
return seq.substr(0, pos);
}
template <typename Sequence>
Sequence trim(const Sequence& seq) {
return trim_begin(trim_end(seq));
}
template <typename Sequence>
Sequence trim_begin_classic(const Sequence& seq) {
if (seq.empty() || !std::isspace(*seq.begin(), std::locale::classic()))
return seq;
typename Sequence::size_type pos = 0;
while (pos != seq.length() && std::isspace(seq[pos], std::locale::classic()))
pos++;
return seq.substr(pos, seq.length() - pos);
}
template <typename Sequence>
Sequence trim_end_classic(const Sequence& seq) {
if (seq.empty() || !std::isspace(*(--seq.end()), std::locale::classic()))
return seq;
typename Sequence::size_type pos = seq.size();
while (pos != 0 && std::isspace(seq[pos - 1], std::locale::classic()))
pos--;
return seq.substr(0, pos);
}
template <typename Sequence>
Sequence trim_classic(const Sequence& seq) {
return trim_begin_classic(trim_end_classic(seq));
}
// Consider rewritting such that m_seq is replaced by first/last.
template <typename Sequence>
class split_iterator_t {
public:
typedef typename Sequence::const_iterator const_iterator;
typedef typename Sequence::value_type value_type;
split_iterator_t() {}
split_iterator_t(const Sequence& seq, value_type delim) :
m_seq(&seq),
m_delim(delim),
m_pos(seq.begin()),
m_next(std::find(seq.begin(), seq.end(), delim)) {
}
Sequence operator * () { return Sequence(m_pos, m_next); }
split_iterator_t& operator ++ () {
m_pos = m_next;
if (m_pos == m_seq->end())
return *this;
m_pos++;
m_next = std::find(m_pos, m_seq->end(), m_delim);
return *this;
}
bool operator == (__UNUSED const split_iterator_t& itr) const { return m_pos == m_seq->end(); }
bool operator != (__UNUSED const split_iterator_t& itr) const { return m_pos != m_seq->end(); }
private:
const Sequence* m_seq;
value_type m_delim;
const_iterator m_pos;
const_iterator m_next;
};
template <typename Sequence>
inline split_iterator_t<Sequence>
split_iterator(const Sequence& seq, typename Sequence::value_type delim) {
return split_iterator_t<Sequence>(seq, delim);
}
template <typename Sequence>
inline split_iterator_t<Sequence>
split_iterator(__UNUSED const Sequence& seq) {
return split_iterator_t<Sequence>();
}
// Could optimize this abit.
inline char
hexchar_to_value(char c) {
if (c >= '0' && c <= '9')
return c - '0';
else if (c >= 'A' && c <= 'F')
return 10 + c - 'A';
else
return 10 + c - 'a';
}
template <int pos, typename Value>
inline char
value_to_hexchar(Value v) {
v >>= pos * 4;
v &= 0xf;
if (v < 0xA)
return '0' + v;
else
return 'A' + v - 0xA;
}
template <typename InputIterator, typename OutputIterator>
OutputIterator
copy_escape_html(InputIterator first, InputIterator last, OutputIterator dest) {
while (first != last) {
if (std::isalpha(*first, std::locale::classic()) ||
std::isdigit(*first, std::locale::classic()) ||
*first == '-') {
*(dest++) = *first;
} else {
*(dest++) = '%';
*(dest++) = value_to_hexchar<1>(*first);
*(dest++) = value_to_hexchar<0>(*first);
}
++first;
}
return dest;
}
template <typename InputIterator, typename OutputIterator>
OutputIterator
copy_escape_html(InputIterator first1, InputIterator last1, OutputIterator first2, OutputIterator last2) {
while (first1 != last1) {
if (std::isalpha(*first1, std::locale::classic()) ||
std::isdigit(*first1, std::locale::classic()) ||
*first1 == '-') {
if (first2 == last2) break; else *(first2++) = *first1;
} else {
if (first2 == last2) break; else *(first2++) = '%';
if (first2 == last2) break; else *(first2++) = value_to_hexchar<1>(*first1);
if (first2 == last2) break; else *(first2++) = value_to_hexchar<0>(*first1);
}
++first1;
}
return first2;
}
template <typename Iterator>
inline std::string
copy_escape_html(Iterator first, Iterator last) {
std::string dest;
copy_escape_html(first, last, std::back_inserter(dest));
return dest;
}
template <typename Sequence>
inline Sequence
copy_escape_html(const Sequence& src) {
Sequence dest;
copy_escape_html(src.begin(), src.end(), std::back_inserter(dest));
return dest;
}
template <typename Sequence>
inline std::string
copy_escape_html_str(const Sequence& src) {
std::string dest;
copy_escape_html(src.begin(), src.end(), std::back_inserter(dest));
return dest;
}
// Consider support for larger than char type.
template <typename InputIterator, typename OutputIterator>
OutputIterator
transform_hex(InputIterator first, InputIterator last, OutputIterator dest) {
while (first != last) {
*(dest++) = value_to_hexchar<1>(*first);
*(dest++) = value_to_hexchar<0>(*first);
++first;
}
return dest;
}
template <typename InputIterator, typename OutputIterator>
OutputIterator
transform_hex(InputIterator first1, InputIterator last1, OutputIterator first2, OutputIterator last2) {
while (first1 != last1) {
if (first2 == last2) break; else *(first2++) = value_to_hexchar<1>(*first1);
if (first2 == last2) break; else *(first2++) = value_to_hexchar<0>(*first1);
++first1;
}
return first2;
}
template <typename Sequence>
inline Sequence
transform_hex(const Sequence& src) {
Sequence dest;
transform_hex(src.begin(), src.end(), std::back_inserter(dest));
return dest;
}
template <typename Iterator>
inline std::string
transform_hex(Iterator first, Iterator last) {
std::string dest;
transform_hex(first, last, std::back_inserter(dest));
return dest;
}
template <typename Sequence>
inline std::string
transform_hex_str(const Sequence& seq) {
std::string dest;
transform_hex(seq.begin(), seq.end(), std::back_inserter(dest));
return dest;
}
template <typename Sequence>
Sequence
generate_random(size_t length) {
Sequence s;
s.reserve(length);
std::generate_n(std::back_inserter(s), length, &::random);
return s;
}
template <typename Iterator>
inline bool
is_all_alpha(Iterator first, Iterator last) {
while (first != last)
if (!std::isalpha(*first++, std::locale::classic()))
return false;
return true;
}
template <typename Sequence>
inline bool
is_all_alpha(const Sequence& src) {
return is_all_alpha(src.begin(), src.end());
}
template <typename Iterator>
inline bool
is_all_alnum(Iterator first, Iterator last) {
while (first != last)
if (!std::isalnum(*first++, std::locale::classic()))
return false;
return true;
}
template <typename Sequence>
inline bool
is_all_alnum(const Sequence& src) {
return is_all_alnum(src.begin(), src.end());
}
template <typename Iterator>
inline bool
is_all_name(Iterator first, Iterator last) {
while (first != last) {
if (!std::isalnum(*first, std::locale::classic()) && *first != '_')
return false;
first++;
}
return true;
}
template <typename Sequence>
inline bool
is_all_name(const Sequence& src) {
return is_all_name(src.begin(), src.end());
}
}
#endif
-110
View File
@@ -1,110 +0,0 @@
// libTorrent - BitTorrent library
// Copyright (C) 2005-2007, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RAK_TIMER_H
#define RAK_TIMER_H
#include <limits>
#include <inttypes.h>
#include <sys/time.h>
namespace rak {
// Don't convert negative Timer to timeval and then back to Timer, that will bork.
class timer {
public:
timer(int64_t usec = 0) : m_time(usec) {}
timer(timeval tv) : m_time((int64_t)(uint32_t)tv.tv_sec * 1000000 + (int64_t)(uint32_t)tv.tv_usec % 1000000) {}
bool is_zero() const { return m_time == 0; }
bool is_not_zero() const { return m_time != 0; }
int32_t seconds() const { return m_time / 1000000; }
int32_t seconds_ceiling() const { return (m_time + 1000000 - 1) / 1000000; }
int64_t usec() const { return m_time; }
timer round_seconds() const { return (m_time / 1000000) * 1000000; }
timer round_seconds_ceiling() const { return ((m_time + 1000000 - 1) / 1000000) * 1000000; }
timeval tval() const {
timeval val;
val.tv_sec = m_time / 1000000;
val.tv_usec = m_time % 1000000;
return val;
}
static timer current();
static int64_t current_seconds() { return current().seconds(); }
static int64_t current_usec() { return current().usec(); }
static timer from_minutes(uint32_t minutes) { return rak::timer((uint64_t)minutes * 60 * 1000000); }
static timer from_seconds(uint32_t seconds) { return rak::timer((uint64_t)seconds * 1000000); }
static timer from_milliseconds(uint32_t msec) { return rak::timer((uint64_t)msec * 1000); }
static timer max() { return std::numeric_limits<int64_t>::max(); }
bool operator < (const timer& t) const { return m_time < t.m_time; }
bool operator > (const timer& t) const { return m_time > t.m_time; }
bool operator <= (const timer& t) const { return m_time <= t.m_time; }
bool operator >= (const timer& t) const { return m_time >= t.m_time; }
bool operator == (const timer& t) const { return m_time == t.m_time; }
bool operator != (const timer& t) const { return m_time != t.m_time; }
timer operator - (const timer& t) const { return timer(m_time - t.m_time); }
timer operator + (const timer& t) const { return timer(m_time + t.m_time); }
timer operator * (int64_t t) const { return timer(m_time * t); }
timer operator / (int64_t t) const { return timer(m_time / t); }
timer operator -= (int64_t t) { m_time -= t; return *this; }
timer operator -= (const timer& t) { m_time -= t.m_time; return *this; }
timer operator += (int64_t t) { m_time += t; return *this; }
timer operator += (const timer& t) { m_time += t.m_time; return *this; }
private:
int64_t m_time;
};
inline timer
timer::current() {
timeval t;
gettimeofday(&t, 0);
return timer(t);
}
}
#endif
-109
View File
@@ -1,109 +0,0 @@
// rak - Rakshasa's toolbox
// Copyright (C) 2005-2007, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RAK_UNORDERED_VECTOR_H
#define RAK_UNORDERED_VECTOR_H
#include <vector>
namespace rak {
template <typename _Tp>
class unordered_vector : private std::vector<_Tp> {
public:
typedef std::vector<_Tp> Base;
typedef typename Base::value_type value_type;
typedef typename Base::pointer pointer;
typedef typename Base::const_pointer const_pointer;
typedef typename Base::reference reference;
typedef typename Base::const_reference const_reference;
typedef typename Base::size_type size_type;
typedef typename Base::difference_type difference_type;
typedef typename Base::allocator_type allocator_type;
typedef typename Base::iterator iterator;
typedef typename Base::reverse_iterator reverse_iterator;
typedef typename Base::const_iterator const_iterator;
typedef typename Base::const_reverse_iterator const_reverse_iterator;
using Base::clear;
using Base::empty;
using Base::size;
using Base::reserve;
using Base::front;
using Base::back;
using Base::begin;
using Base::end;
using Base::rbegin;
using Base::rend;
using Base::push_back;
using Base::pop_back;
// Use the range erase function, the single element erase gets
// overloaded.
using Base::erase;
iterator insert(iterator position, const value_type& x);
iterator erase(iterator position);
private:
};
template <typename _Tp>
typename unordered_vector<_Tp>::iterator
unordered_vector<_Tp>::insert(iterator position, const value_type& x) {
Base::push_back(x);
return --end();
}
template <typename _Tp>
typename unordered_vector<_Tp>::iterator
unordered_vector<_Tp>::erase(iterator position) {
// We don't need to check if position == end - 1 since we then copy
// to the position we pop later.
*position = Base::back();
Base::pop_back();
return position;
}
}
#endif
-150
View File
@@ -1,150 +0,0 @@
# Functions to check for attributes support in compiler
AC_DEFUN([CC_ATTRIBUTE_CONSTRUCTOR], [
AC_CACHE_CHECK([if compiler supports __attribute__((constructor))],
[cc_cv_attribute_constructor],
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([
void ctor() __attribute__((constructor));
void ctor() { };
])],
[cc_cv_attribute_constructor=yes],
[cc_cv_attribute_constructor=no])
])
if test "x$cc_cv_attribute_constructor" = "xyes"; then
AC_DEFINE([SUPPORT_ATTRIBUTE_CONSTRUCTOR], 1, [Define this if the compiler supports the constructor attribute])
$1
else
true
$2
fi
])
AC_DEFUN([CC_ATTRIBUTE_FORMAT], [
AC_CACHE_CHECK([if compiler supports __attribute__((format(printf, n, n)))],
[cc_cv_attribute_format],
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([
void __attribute__((format(printf, 1, 2))) printflike(const char *fmt, ...) { }
])],
[cc_cv_attribute_format=yes],
[cc_cv_attribute_format=no])
])
if test "x$cc_cv_attribute_format" = "xyes"; then
AC_DEFINE([SUPPORT_ATTRIBUTE_FORMAT], 1, [Define this if the compiler supports the format attribute])
$1
else
true
$2
fi
])
AC_DEFUN([CC_ATTRIBUTE_INTERNAL], [
AC_CACHE_CHECK([if compiler supports __attribute__((visibility("internal")))],
[cc_cv_attribute_internal],
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([
void __attribute__((visibility("internal"))) internal_function() { }
])],
[cc_cv_attribute_internal=yes],
[cc_cv_attribute_internal=no])
])
if test "x$cc_cv_attribute_internal" = "xyes"; then
AC_DEFINE([SUPPORT_ATTRIBUTE_INTERNAL], 1, [Define this if the compiler supports the internal visibility attribute])
$1
else
true
$2
fi
])
AC_DEFUN([CC_ATTRIBUTE_VISIBILITY], [
AC_LANG_PUSH(C++)
tmp_CXXFLAGS=$CXXFLAGS
CXXFLAGS="$CXXFLAGS -fvisibility=hidden"
AC_CACHE_CHECK([if compiler supports __attribute__((visibility("default")))],
[cc_cv_attribute_visibility],
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([
void __attribute__((visibility("default"))) visibility_function() { }
])],
[cc_cv_attribute_visibility=yes],
[cc_cv_attribute_visibility=no])
])
CXXFLAGS=$tmp_CXXFLAGS
AC_LANG_POP(C++)
if test "x$cc_cv_attribute_visibility" = "xyes"; then
AC_DEFINE([SUPPORT_ATTRIBUTE_VISIBILITY], 1, [Define this if the compiler supports the visibility attributes.])
CXXFLAGS="$CXXFLAGS -fvisibility=hidden"
$1
else
true
$2
fi
])
AC_DEFUN([CC_ATTRIBUTE_NONNULL], [
AC_CACHE_CHECK([if compiler supports __attribute__((nonnull()))],
[cc_cv_attribute_nonnull],
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([
void some_function(void *foo, void *bar) __attribute__((nonnull()));
void some_function(void *foo, void *bar) { }
])],
[cc_cv_attribute_nonnull=yes],
[cc_cv_attribute_nonnull=no])
])
if test "x$cc_cv_attribute_nonnull" = "xyes"; then
AC_DEFINE([SUPPORT_ATTRIBUTE_NONNULL], 1, [Define this if the compiler supports the nonnull attribute])
$1
else
true
$2
fi
])
AC_DEFUN([CC_ATTRIBUTE_UNUSED], [
AC_CACHE_CHECK([if compiler supports __attribute__((unused))],
[cc_cv_attribute_unused],
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([
void some_function(void *foo, __attribute__((unused)) void *bar);
])],
[cc_cv_attribute_unused=yes],
[cc_cv_attribute_unused=no])
])
if test "x$cc_cv_attribute_unused" = "xyes"; then
AC_DEFINE([SUPPORT_ATTRIBUTE_UNUSED], 1, [Define this if the compiler supports the unused attribute])
$1
else
true
$2
fi
])
AC_DEFUN([CC_FUNC_EXPECT], [
AC_CACHE_CHECK([if compiler has __builtin_expect function],
[cc_cv_func_expect],
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([
int some_function()
{
int a = 3;
return (int)__builtin_expect(a, 3);
}
])],
[cc_cv_func_expect=yes],
[cc_cv_func_expect=no])
])
if test "x$cc_cv_func_expect" = "xyes"; then
AC_DEFINE([SUPPORT__BUILTIN_EXPECT], 1, [Define this if the compiler supports __builtin_expect() function])
$1
else
true
$2
fi
])
-309
View File
@@ -1,309 +0,0 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_pthread.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
#
# DESCRIPTION
#
# This macro figures out how to build C programs using POSIX threads. It
# sets the PTHREAD_LIBS output variable to the threads library and linker
# flags, and the PTHREAD_CFLAGS output variable to any special C compiler
# flags that are needed. (The user can also force certain compiler
# flags/libs to be tested by setting these environment variables.)
#
# Also sets PTHREAD_CC to any special C compiler that is needed for
# multi-threaded programs (defaults to the value of CC otherwise). (This
# is necessary on AIX to use the special cc_r compiler alias.)
#
# NOTE: You are assumed to not only compile your program with these flags,
# but also link it with them as well. e.g. you should link with
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
#
# If you are only building threads programs, you may wish to use these
# variables in your default LIBS, CFLAGS, and CC:
#
# LIBS="$PTHREAD_LIBS $LIBS"
# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# CC="$PTHREAD_CC"
#
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
# (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
#
# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
# PTHREAD_CFLAGS.
#
# ACTION-IF-FOUND is a list of shell commands to run if a threads library
# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
# is not found. If ACTION-IF-FOUND is not specified, the default action
# will define HAVE_PTHREAD.
#
# Please let the authors know if this macro fails on any platform, or if
# you have any other suggestions or comments. This macro was based on work
# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
# Alejandro Forero Cuervo to the autoconf macro repository. We are also
# grateful for the helpful feedback of numerous users.
#
# Updated for Autoconf 2.68 by Daniel Richard G.
#
# LICENSE
#
# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 17
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
AC_DEFUN([AX_PTHREAD], [
AC_REQUIRE([AC_CANONICAL_HOST])
AC_LANG_PUSH([C])
ax_pthread_ok=no
# We used to check for pthread.h first, but this fails if pthread.h
# requires special compiler flags (e.g. on True64 or Sequent).
# It gets checked for in the link test anyway.
# First of all, check if the user has set any of the PTHREAD_LIBS,
# etcetera environment variables, and if threads linking works using
# them:
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes)
AC_MSG_RESULT($ax_pthread_ok)
if test x"$ax_pthread_ok" = xno; then
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
fi
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
fi
# We must check for the threads library under a number of different
# names; the ordering is very important because some systems
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
# libraries is broken (non-POSIX).
# Create a list of thread flags to try. Items starting with a "-" are
# C compiler flags, and other items are library names, except for "none"
# which indicates that we try without any flags at all, and "pthread-config"
# which is a program returning the flags for the Pth emulation library.
ax_pthread_flags="none pthreads -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
# The ordering *is* (sometimes) important. Some notes on the
# individual items follow:
# pthreads: AIX (must check this before -lpthread)
# none: in case threads are in libc; should be tried before -Kthread and
# other compiler flags to prevent continual compiler warnings
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
# -pthreads: Solaris/gcc
# -mthreads: Mingw32/gcc, Lynx/gcc
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
# doesn't hurt to check since this sometimes defines pthreads too;
# also defines -D_REENTRANT)
# ... -mt is also the pthreads flag for HP/aCC
# pthread: Linux, etcetera
# --thread-safe: KAI C++
# pthread-config: use pthread-config program (for GNU Pth library)
case "${host_cpu}-${host_os}" in
*solaris*)
# On Solaris (at least, for some versions), libc contains stubbed
# (non-functional) versions of the pthreads routines, so link-based
# tests will erroneously succeed. (We need to link with -pthreads/-mt/
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
# a function called by this macro, so we could check for that, but
# who knows whether they'll stub that too in a future libc.) So,
# we'll just look for -pthreads and -lpthread first:
ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
;;
*-darwin*)
ax_pthread_flags="none -pthread $ax_pthread_flags"
;;
esac
if test x"$ax_pthread_ok" = xno; then
for flag in $ax_pthread_flags; do
case $flag in
none)
AC_MSG_CHECKING([whether pthreads work without any flags])
;;
-*)
AC_MSG_CHECKING([whether pthreads work with $flag])
PTHREAD_CFLAGS="$flag"
;;
pthread-config)
AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no)
if test x"$ax_pthread_config" = xno; then continue; fi
PTHREAD_CFLAGS="`pthread-config --cflags`"
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
;;
*)
AC_MSG_CHECKING([for the pthreads library -l$flag])
PTHREAD_LIBS="-l$flag"
;;
esac
save_LIBS="$LIBS"
save_CFLAGS="$CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# Check for various functions. We must include pthread.h,
# since some functions may be macros. (On the Sequent, we
# need a special flag -Kthread to make this header compile.)
# We check for pthread_join because it is in -lpthread on IRIX
# while pthread_create is in libc. We check for pthread_attr_init
# due to DEC craziness with -lpthreads. We check for
# pthread_cleanup_push because it is one of the few pthread
# functions on Solaris that doesn't have a non-functional libc stub.
# We try pthread_create on general principles.
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
static void routine(void *a) { a = 0; }
static void *start_routine(void *a) { return a; }],
[pthread_t th; pthread_attr_t attr;
pthread_create(&th, 0, start_routine, 0);
pthread_join(th, 0);
pthread_attr_init(&attr);
pthread_cleanup_push(routine, 0);
pthread_cleanup_pop(0) /* ; */])],
[ax_pthread_ok=yes],
[])
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
AC_MSG_RESULT($ax_pthread_ok)
if test "x$ax_pthread_ok" = xyes; then
break;
fi
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
done
fi
# Various other checks:
if test "x$ax_pthread_ok" = xyes; then
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
AC_MSG_CHECKING([for joinable pthread attribute])
attr_name=unknown
for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
[int attr = $attr; return attr /* ; */])],
[attr_name=$attr; break],
[])
done
AC_MSG_RESULT($attr_name)
if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
[Define to necessary symbol if this constant
uses a non-standard name on your system.])
fi
AC_MSG_CHECKING([if more special flags are required for pthreads])
flag=no
case "${host_cpu}-${host_os}" in
*-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
*-osf* | *-hpux*) flag="-D_REENTRANT";;
*solaris*)
if test "$GCC" = "yes"; then
flag="-D_REENTRANT"
else
flag="-mt -D_REENTRANT"
fi
;;
esac
AC_MSG_RESULT(${flag})
if test "x$flag" != xno; then
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
fi
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
ax_cv_PTHREAD_PRIO_INHERIT, [
AC_LINK_IFELSE([
AC_LANG_PROGRAM([[#include <pthread.h>]], [[int i = PTHREAD_PRIO_INHERIT;]])],
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
[ax_cv_PTHREAD_PRIO_INHERIT=no])
])
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], 1, [Have PTHREAD_PRIO_INHERIT.]))
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
# More AIX lossage: must compile with xlc_r or cc_r
if test x"$GCC" != xyes; then
AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC})
else
PTHREAD_CC=$CC
fi
else
PTHREAD_CC="$CC"
fi
AC_SUBST(PTHREAD_LIBS)
AC_SUBST(PTHREAD_CFLAGS)
AC_SUBST(PTHREAD_CC)
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
if test x"$ax_pthread_ok" = xyes; then
ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
:
else
ax_pthread_ok=no
$2
fi
AC_LANG_POP
])dnl AX_PTHREAD
-546
View File
@@ -1,546 +0,0 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_with_curses.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_WITH_CURSES
#
# DESCRIPTION
#
# This macro checks whether a SysV or X/Open-compatible Curses library is
# present, along with the associated header file. The NcursesW
# (wide-character) library is searched for first, followed by Ncurses,
# then the system-default plain Curses. The first library found is the
# one returned.
#
# The following options are understood: --with-ncursesw, --with-ncurses,
# --without-ncursesw, --without-ncurses. The "--with" options force the
# macro to use that particular library, terminating with an error if not
# found. The "--without" options simply skip the check for that library.
# The effect on the search pattern is:
#
# (no options) - NcursesW, Ncurses, Curses
# --with-ncurses --with-ncursesw - NcursesW only [*]
# --without-ncurses --with-ncursesw - NcursesW only [*]
# --with-ncursesw - NcursesW only [*]
# --with-ncurses --without-ncursesw - Ncurses only [*]
# --with-ncurses - NcursesW, Ncurses [**]
# --without-ncurses --without-ncursesw - Curses only
# --without-ncursesw - Ncurses, Curses
# --without-ncurses - NcursesW, Curses
#
# [*] If the library is not found, abort the configure script.
#
# [**] If the second library (Ncurses) is not found, abort configure.
#
# The following preprocessor symbols may be defined by this macro if the
# appropriate conditions are met:
#
# HAVE_CURSES - if any SysV or X/Open Curses library found
# HAVE_CURSES_ENHANCED - if library supports X/Open Enhanced functions
# HAVE_CURSES_COLOR - if library supports color (enhanced functions)
# HAVE_CURSES_OBSOLETE - if library supports certain obsolete features
# HAVE_NCURSESW - if NcursesW (wide char) library is to be used
# HAVE_NCURSES - if the Ncurses library is to be used
#
# HAVE_CURSES_H - if <curses.h> is present and should be used
# HAVE_NCURSESW_H - if <ncursesw.h> should be used
# HAVE_NCURSES_H - if <ncurses.h> should be used
# HAVE_NCURSESW_CURSES_H - if <ncursesw/curses.h> should be used
# HAVE_NCURSES_CURSES_H - if <ncurses/curses.h> should be used
#
# (These preprocessor symbols are discussed later in this document.)
#
# The following output variable is defined by this macro; it is precious
# and may be overridden on the ./configure command line:
#
# CURSES_LIB - library to add to xxx_LDADD
#
# The library listed in CURSES_LIB is NOT added to LIBS by default. You
# need to add CURSES_LIB to the appropriate xxx_LDADD line in your
# Makefile.am. For example:
#
# prog_LDADD = @CURSES_LIB@
#
# If CURSES_LIB is set on the configure command line (such as by running
# "./configure CURSES_LIB=-lmycurses"), then the only header searched for
# is <curses.h>. The user may use the CPPFLAGS precious variable to
# override the standard #include search path. If the user needs to
# specify an alternative path for a library (such as for a non-standard
# NcurseW), the user should use the LDFLAGS variable.
#
# The following shell variables may be defined by this macro:
#
# ax_cv_curses - set to "yes" if any Curses library found
# ax_cv_curses_enhanced - set to "yes" if Enhanced functions present
# ax_cv_curses_color - set to "yes" if color functions present
# ax_cv_curses_obsolete - set to "yes" if obsolete features present
#
# ax_cv_ncursesw - set to "yes" if NcursesW library found
# ax_cv_ncurses - set to "yes" if Ncurses library found
# ax_cv_plaincurses - set to "yes" if plain Curses library found
# ax_cv_curses_which - set to "ncursesw", "ncurses", "plaincurses" or "no"
#
# These variables can be used in your configure.ac to determine the level
# of support you need from the Curses library. For example, if you must
# have either Ncurses or NcursesW, you could include:
#
# AX_WITH_CURSES
# if test "x$ax_cv_ncursesw" != xyes && test "x$ax_cv_ncurses" != xyes; then
# AX_MSG_ERROR([requires either NcursesW or Ncurses library])
# fi
#
# If any Curses library will do (but one must be present and must support
# color), you could use:
#
# AX_WITH_CURSES
# if test "x$ax_cv_curses" != xyes || test "x$ax_cv_curses_color" != xyes; then
# AC_MSG_ERROR([requires an X/Open-compatible Curses library with color])
# fi
#
# Certain preprocessor symbols and shell variables defined by this macro
# can be used to determine various features of the Curses library. In
# particular, HAVE_CURSES and ax_cv_curses are defined if the Curses
# library found conforms to the traditional SysV and/or X/Open Base Curses
# definition. Any working Curses library conforms to this level.
#
# HAVE_CURSES_ENHANCED and ax_cv_curses_enhanced are defined if the
# library supports the X/Open Enhanced Curses definition. In particular,
# the wide-character types attr_t, cchar_t and wint_t, the functions
# wattr_set() and wget_wch() and the macros WA_NORMAL and _XOPEN_CURSES
# are checked. The Ncurses library does NOT conform to this definition,
# although NcursesW does.
#
# HAVE_CURSES_COLOR and ax_cv_curses_color are defined if the library
# supports color functions and macros such as COLOR_PAIR, A_COLOR,
# COLOR_WHITE, COLOR_RED and init_pair(). These are NOT part of the
# X/Open Base Curses definition, but are part of the Enhanced set of
# functions. The Ncurses library DOES support these functions, as does
# NcursesW.
#
# HAVE_CURSES_OBSOLETE and ax_cv_curses_obsolete are defined if the
# library supports certain features present in SysV and BSD Curses but not
# defined in the X/Open definition. In particular, the functions
# getattrs(), getcurx() and getmaxx() are checked.
#
# To use the HAVE_xxx_H preprocessor symbols, insert the following into
# your system.h (or equivalent) header file:
#
# #if defined HAVE_NCURSESW_CURSES_H
# # include <ncursesw/curses.h>
# #elif defined HAVE_NCURSESW_H
# # include <ncursesw.h>
# #elif defined HAVE_NCURSES_CURSES_H
# # include <ncurses/curses.h>
# #elif defined HAVE_NCURSES_H
# # include <ncurses.h>
# #elif defined HAVE_CURSES_H
# # include <curses.h>
# #else
# # error "SysV or X/Open-compatible Curses header file required"
# #endif
#
# For previous users of this macro: you should not need to change anything
# in your configure.ac or Makefile.am, as the previous (serial 10)
# semantics are still valid. However, you should update your system.h (or
# equivalent) header file to the fragment shown above. You are encouraged
# also to make use of the extended functionality provided by this version
# of AX_WITH_CURSES, as well as in the additional macros
# AX_WITH_CURSES_PANEL, AX_WITH_CURSES_MENU and AX_WITH_CURSES_FORM.
#
# LICENSE
#
# Copyright (c) 2009 Mark Pulford <mark@kyne.com.au>
# Copyright (c) 2009 Damian Pietras <daper@daper.net>
# Copyright (c) 2012 Reuben Thomas <rrt@sc3d.org>
# Copyright (c) 2011 John Zaitseff <J.Zaitseff@zap.org.au>
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 13
AU_ALIAS([MP_WITH_CURSES], [AX_WITH_CURSES])
AC_DEFUN([AX_WITH_CURSES], [
AC_ARG_VAR([CURSES_LIB], [linker library for Curses, e.g. -lcurses])
AC_ARG_WITH([ncurses], [AS_HELP_STRING([--with-ncurses],
[force the use of Ncurses or NcursesW])],
[], [with_ncurses=check])
AC_ARG_WITH([ncursesw], [AS_HELP_STRING([--without-ncursesw],
[do not use NcursesW (wide character support)])],
[], [with_ncursesw=check])
ax_saved_LIBS=$LIBS
AS_IF([test "x$with_ncurses" = xyes || test "x$with_ncursesw" = xyes],
[ax_with_plaincurses=no], [ax_with_plaincurses=check])
ax_cv_curses_which=no
# Test for NcursesW
AS_IF([test "x$CURSES_LIB" = x && test "x$with_ncursesw" != xno], [
LIBS="$ax_saved_LIBS -lncursesw"
AC_CACHE_CHECK([for NcursesW wide-character library], [ax_cv_ncursesw], [
AC_LINK_IFELSE([AC_LANG_CALL([], [initscr])],
[ax_cv_ncursesw=yes], [ax_cv_ncursesw=no])
])
AS_IF([test "x$ax_cv_ncursesw" = xno && test "x$with_ncursesw" = xyes], [
AC_MSG_ERROR([--with-ncursesw specified but could not find NcursesW library])
])
AS_IF([test "x$ax_cv_ncursesw" = xyes], [
ax_cv_curses=yes
ax_cv_curses_which=ncursesw
CURSES_LIB="-lncursesw"
AC_DEFINE([HAVE_NCURSESW], [1], [Define to 1 if the NcursesW library is present])
AC_DEFINE([HAVE_CURSES], [1], [Define to 1 if a SysV or X/Open compatible Curses library is present])
AC_CACHE_CHECK([for working ncursesw/curses.h], [ax_cv_header_ncursesw_curses_h], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
@%:@define _XOPEN_SOURCE_EXTENDED 1
@%:@include <ncursesw/curses.h>
]], [[
chtype a = A_BOLD;
int b = KEY_LEFT;
chtype c = COLOR_PAIR(1) & A_COLOR;
attr_t d = WA_NORMAL;
cchar_t e;
wint_t f;
int g = getattrs(stdscr);
int h = getcurx(stdscr) + getmaxx(stdscr);
initscr();
init_pair(1, COLOR_WHITE, COLOR_RED);
wattr_set(stdscr, d, 0, NULL);
wget_wch(stdscr, &f);
]])],
[ax_cv_header_ncursesw_curses_h=yes],
[ax_cv_header_ncursesw_curses_h=no])
])
AS_IF([test "x$ax_cv_header_ncursesw_curses_h" = xyes], [
ax_cv_curses_enhanced=yes
ax_cv_curses_color=yes
ax_cv_curses_obsolete=yes
AC_DEFINE([HAVE_CURSES_ENHANCED], [1], [Define to 1 if library supports X/Open Enhanced functions])
AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)])
AC_DEFINE([HAVE_CURSES_OBSOLETE], [1], [Define to 1 if library supports certain obsolete features])
AC_DEFINE([HAVE_NCURSESW_CURSES_H], [1], [Define to 1 if <ncursesw/curses.h> is present])
])
AC_CACHE_CHECK([for working ncursesw.h], [ax_cv_header_ncursesw_h], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
@%:@define _XOPEN_SOURCE_EXTENDED 1
@%:@include <ncursesw.h>
]], [[
chtype a = A_BOLD;
int b = KEY_LEFT;
chtype c = COLOR_PAIR(1) & A_COLOR;
attr_t d = WA_NORMAL;
cchar_t e;
wint_t f;
int g = getattrs(stdscr);
int h = getcurx(stdscr) + getmaxx(stdscr);
initscr();
init_pair(1, COLOR_WHITE, COLOR_RED);
wattr_set(stdscr, d, 0, NULL);
wget_wch(stdscr, &f);
]])],
[ax_cv_header_ncursesw_h=yes],
[ax_cv_header_ncursesw_h=no])
])
AS_IF([test "x$ax_cv_header_ncursesw_h" = xyes], [
ax_cv_curses_enhanced=yes
ax_cv_curses_color=yes
ax_cv_curses_obsolete=yes
AC_DEFINE([HAVE_CURSES_ENHANCED], [1], [Define to 1 if library supports X/Open Enhanced functions])
AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)])
AC_DEFINE([HAVE_CURSES_OBSOLETE], [1], [Define to 1 if library supports certain obsolete features])
AC_DEFINE([HAVE_NCURSESW_H], [1], [Define to 1 if <ncursesw.h> is present])
])
AC_CACHE_CHECK([for working ncurses.h], [ax_cv_header_ncurses_h_with_ncursesw], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
@%:@define _XOPEN_SOURCE_EXTENDED 1
@%:@include <ncurses.h>
]], [[
chtype a = A_BOLD;
int b = KEY_LEFT;
chtype c = COLOR_PAIR(1) & A_COLOR;
attr_t d = WA_NORMAL;
cchar_t e;
wint_t f;
int g = getattrs(stdscr);
int h = getcurx(stdscr) + getmaxx(stdscr);
initscr();
init_pair(1, COLOR_WHITE, COLOR_RED);
wattr_set(stdscr, d, 0, NULL);
wget_wch(stdscr, &f);
]])],
[ax_cv_header_ncurses_h_with_ncursesw=yes],
[ax_cv_header_ncurses_h_with_ncursesw=no])
])
AS_IF([test "x$ax_cv_header_ncurses_h_with_ncursesw" = xyes], [
ax_cv_curses_enhanced=yes
ax_cv_curses_color=yes
ax_cv_curses_obsolete=yes
AC_DEFINE([HAVE_CURSES_ENHANCED], [1], [Define to 1 if library supports X/Open Enhanced functions])
AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)])
AC_DEFINE([HAVE_CURSES_OBSOLETE], [1], [Define to 1 if library supports certain obsolete features])
AC_DEFINE([HAVE_NCURSES_H], [1], [Define to 1 if <ncurses.h> is present])
])
AS_IF([test "x$ax_cv_header_ncursesw_curses_h" = xno && test "x$ax_cv_header_ncursesw_h" = xno && test "x$ax_cv_header_ncurses_h_with_ncursesw" = xno], [
AC_MSG_WARN([could not find a working ncursesw/curses.h, ncursesw.h or ncurses.h])
])
dnl Test if we need to explicitly link against -ltinfow.
AC_CACHE_CHECK([if curses tinfo library is linked properly], [ax_cv_ncurses_compiled], [
LIBS="$ax_saved_LIBS $CURSES_LIB"
AC_LINK_IFELSE([AC_LANG_CALL([], [keypad])], [ax_cv_ncurses_compiled=yes], [ax_cv_ncurses_compiled=no])
LIBS="$ax_saved_LIBS $CURSES_LIB -ltinfo"
AC_LINK_IFELSE([AC_LANG_CALL([], [keypad])], [ax_cv_tinfo_compiled=yes], [ax_cv_tinfo_compiled=no])
LIBS="$ax_saved_LIBS $CURSES_LIB -ltinfow"
AC_LINK_IFELSE([AC_LANG_CALL([], [keypad])], [ax_cv_tinfow_compiled=yes], [ax_cv_tinfow_compiled=no])
LIBS=$ax_saved_LIBS
])
AS_IF([test "x$ax_cv_ncurses_compiled" = xno], [
AS_IF(
[test "x$ax_cv_tinfo_compiled" = xyes], [
AC_MSG_RESULT([adding libtinfo])
CURSES_LIB="$CURSES_LIB -ltinfo"
],
[test "x$ax_cv_tinfow_compiled" = xyes], [
AC_MSG_RESULT([adding libtinfow])
CURSES_LIB="$CURSES_LIB -ltinfow"
], [
AC_MSG_ERROR([no])
])
])
])
])
# Test for Ncurses
AS_IF([test "x$CURSES_LIB" = x && test "x$with_ncurses" != xno && test "x$ax_cv_curses_which" = xno], [
LIBS="$ax_saved_LIBS -lncurses"
AC_CACHE_CHECK([for Ncurses library], [ax_cv_ncurses], [
AC_LINK_IFELSE([AC_LANG_CALL([], [initscr])],
[ax_cv_ncurses=yes], [ax_cv_ncurses=no])
])
AS_IF([test "x$ax_cv_ncurses" = xno && test "x$with_ncurses" = xyes], [
AC_MSG_ERROR([--with-ncurses specified but could not find Ncurses library])
])
AS_IF([test "x$ax_cv_ncurses" = xyes], [
ax_cv_curses=yes
ax_cv_curses_which=ncurses
CURSES_LIB="-lncurses"
AC_DEFINE([HAVE_NCURSES], [1], [Define to 1 if the Ncurses library is present])
AC_DEFINE([HAVE_CURSES], [1], [Define to 1 if a SysV or X/Open compatible Curses library is present])
AC_CACHE_CHECK([for working ncurses/curses.h], [ax_cv_header_ncurses_curses_h], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
@%:@include <ncurses/curses.h>
]], [[
chtype a = A_BOLD;
int b = KEY_LEFT;
chtype c = COLOR_PAIR(1) & A_COLOR;
int g = getattrs(stdscr);
int h = getcurx(stdscr) + getmaxx(stdscr);
initscr();
init_pair(1, COLOR_WHITE, COLOR_RED);
]])],
[ax_cv_header_ncurses_curses_h=yes],
[ax_cv_header_ncurses_curses_h=no])
])
AS_IF([test "x$ax_cv_header_ncurses_curses_h" = xyes], [
ax_cv_curses_color=yes
ax_cv_curses_obsolete=yes
AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)])
AC_DEFINE([HAVE_CURSES_OBSOLETE], [1], [Define to 1 if library supports certain obsolete features])
AC_DEFINE([HAVE_NCURSES_CURSES_H], [1], [Define to 1 if <ncurses/curses.h> is present])
])
AC_CACHE_CHECK([for working ncurses.h], [ax_cv_header_ncurses_h], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
@%:@include <ncurses.h>
]], [[
chtype a = A_BOLD;
int b = KEY_LEFT;
chtype c = COLOR_PAIR(1) & A_COLOR;
int g = getattrs(stdscr);
int h = getcurx(stdscr) + getmaxx(stdscr);
initscr();
init_pair(1, COLOR_WHITE, COLOR_RED);
]])],
[ax_cv_header_ncurses_h=yes],
[ax_cv_header_ncurses_h=no])
])
AS_IF([test "x$ax_cv_header_ncurses_h" = xyes], [
ax_cv_curses_color=yes
ax_cv_curses_obsolete=yes
AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)])
AC_DEFINE([HAVE_CURSES_OBSOLETE], [1], [Define to 1 if library supports certain obsolete features])
AC_DEFINE([HAVE_NCURSES_H], [1], [Define to 1 if <ncurses.h> is present])
])
AS_IF([test "x$ax_cv_header_ncurses_curses_h" = xno && test "x$ax_cv_header_ncurses_h" = xno], [
AC_MSG_WARN([could not find a working ncurses/curses.h or ncurses.h])
])
])
])
# Test for plain Curses (or if CURSES_LIB was set by user)
AS_IF([test "x$with_plaincurses" != xno && test "x$ax_cv_curses_which" = xno], [
AS_IF([test "x$CURSES_LIB" != x], [
LIBS="$ax_saved_LIBS $CURSES_LIB"
], [
LIBS="$ax_saved_LIBS -lcurses"
])
AC_CACHE_CHECK([for Curses library], [ax_cv_plaincurses], [
AC_LINK_IFELSE([AC_LANG_CALL([], [initscr])],
[ax_cv_plaincurses=yes], [ax_cv_plaincurses=no])
])
AS_IF([test "x$ax_cv_plaincurses" = xyes], [
ax_cv_curses=yes
ax_cv_curses_which=plaincurses
AS_IF([test "x$CURSES_LIB" = x], [
CURSES_LIB="-lcurses"
])
AC_DEFINE([HAVE_CURSES], [1], [Define to 1 if a SysV or X/Open compatible Curses library is present])
# Check for base conformance (and header file)
AC_CACHE_CHECK([for working curses.h], [ax_cv_header_curses_h], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
@%:@include <curses.h>
]], [[
chtype a = A_BOLD;
int b = KEY_LEFT;
initscr();
]])],
[ax_cv_header_curses_h=yes],
[ax_cv_header_curses_h=no])
])
AS_IF([test "x$ax_cv_header_curses_h" = xyes], [
AC_DEFINE([HAVE_CURSES_H], [1], [Define to 1 if <curses.h> is present])
# Check for X/Open Enhanced conformance
AC_CACHE_CHECK([for X/Open Enhanced Curses conformance], [ax_cv_plaincurses_enhanced], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
@%:@define _XOPEN_SOURCE_EXTENDED 1
@%:@include <curses.h>
@%:@ifndef _XOPEN_CURSES
@%:@error "this Curses library is not enhanced"
"this Curses library is not enhanced"
@%:@endif
]], [[
chtype a = A_BOLD;
int b = KEY_LEFT;
chtype c = COLOR_PAIR(1) & A_COLOR;
attr_t d = WA_NORMAL;
cchar_t e;
wint_t f;
initscr();
init_pair(1, COLOR_WHITE, COLOR_RED);
wattr_set(stdscr, d, 0, NULL);
wget_wch(stdscr, &f);
]])],
[ax_cv_plaincurses_enhanced=yes],
[ax_cv_plaincurses_enhanced=no])
])
AS_IF([test "x$ax_cv_plaincurses_enhanced" = xyes], [
ax_cv_curses_enhanced=yes
ax_cv_curses_color=yes
AC_DEFINE([HAVE_CURSES_ENHANCED], [1], [Define to 1 if library supports X/Open Enhanced functions])
AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)])
])
# Check for color functions
AC_CACHE_CHECK([for Curses color functions], [ax_cv_plaincurses_color], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
@%:@define _XOPEN_SOURCE_EXTENDED 1
@%:@include <curses.h>
]], [[
chtype a = A_BOLD;
int b = KEY_LEFT;
chtype c = COLOR_PAIR(1) & A_COLOR;
initscr();
init_pair(1, COLOR_WHITE, COLOR_RED);
]])],
[ax_cv_plaincurses_color=yes],
[ax_cv_plaincurses_color=no])
])
AS_IF([test "x$ax_cv_plaincurses_color" = xyes], [
ax_cv_curses_color=yes
AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)])
])
# Check for obsolete functions
AC_CACHE_CHECK([for obsolete Curses functions], [ax_cv_plaincurses_obsolete], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
@%:@include <curses.h>
]], [[
chtype a = A_BOLD;
int b = KEY_LEFT;
int g = getattrs(stdscr);
int h = getcurx(stdscr) + getmaxx(stdscr);
initscr();
]])],
[ax_cv_plaincurses_obsolete=yes],
[ax_cv_plaincurses_obsolete=no])
])
AS_IF([test "x$ax_cv_plaincurses_obsolete" = xyes], [
ax_cv_curses_obsolete=yes
AC_DEFINE([HAVE_CURSES_OBSOLETE], [1], [Define to 1 if library supports certain obsolete features])
])
])
AS_IF([test "x$ax_cv_header_curses_h" = xno], [
AC_MSG_WARN([could not find a working curses.h])
])
])
])
AS_IF([test "x$ax_cv_curses" != xyes], [ax_cv_curses=no])
AS_IF([test "x$ax_cv_curses_enhanced" != xyes], [ax_cv_curses_enhanced=no])
AS_IF([test "x$ax_cv_curses_color" != xyes], [ax_cv_curses_color=no])
AS_IF([test "x$ax_cv_curses_obsolete" != xyes], [ax_cv_curses_obsolete=no])
LIBS=$ax_saved_LIBS
])dnl
-539
View File
@@ -1,539 +0,0 @@
AC_DEFUN([TORRENT_CHECK_XFS], [
AC_MSG_CHECKING(for XFS support)
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <xfs/libxfs.h>
#include <sys/ioctl.h>
int main() {
struct xfs_flock64 l;
ioctl(0, XFS_IOC_RESVSP64, &l);
return 0;
}
])],
[
AC_DEFINE(USE_XFS, 1, Use XFS filesystem stuff.)
AC_MSG_RESULT(yes)
], [
AC_MSG_RESULT(no)
])
])
AC_DEFUN([TORRENT_WITHOUT_XFS], [
AC_ARG_WITH(xfs,
AC_HELP_STRING([--without-xfs], [do not check for XFS filesystem support]),
[
if test "$withval" = "yes"; then
TORRENT_CHECK_XFS
fi
], [
TORRENT_CHECK_XFS
])
])
AC_DEFUN([TORRENT_WITH_XFS], [
AC_ARG_WITH(xfs,
AC_HELP_STRING([--with-xfs], [check for XFS filesystem support]),
[
if test "$withval" = "yes"; then
TORRENT_CHECK_XFS
fi
])
])
AC_DEFUN([TORRENT_CHECK_EPOLL], [
AC_MSG_CHECKING(for epoll support)
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <sys/epoll.h>
int main() {
int fd = epoll_create(100);
return 0;
}
])],
[
AC_DEFINE(USE_EPOLL, 1, Use epoll.)
AC_MSG_RESULT(yes)
], [
AC_MSG_RESULT(no)
])
])
AC_DEFUN([TORRENT_WITHOUT_EPOLL], [
AC_ARG_WITH(epoll,
AC_HELP_STRING([--without-epoll], [do not check for epoll support]),
[
if test "$withval" = "yes"; then
TORRENT_CHECK_EPOLL
fi
], [
TORRENT_CHECK_EPOLL
])
])
AC_DEFUN([TORRENT_CHECK_KQUEUE], [
AC_MSG_CHECKING(for kqueue support)
AC_LINK_IFELSE([AC_LANG_SOURCE([
#include <sys/time.h> /* Because OpenBSD's sys/event.h fails to compile otherwise. Yeah... */
#include <sys/event.h>
int main() {
int fd = kqueue();
return 0;
}
])],
[
AC_DEFINE(USE_KQUEUE, 1, Use kqueue.)
AC_MSG_RESULT(yes)
], [
AC_MSG_RESULT(no)
])
])
AC_DEFUN([TORRENT_CHECK_KQUEUE_SOCKET_ONLY], [
AC_MSG_CHECKING(whether kqueue supports pipes and ptys)
AC_RUN_IFELSE([AC_LANG_SOURCE([
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/event.h>
#include <sys/time.h>
int main() {
struct kevent ev@<:@2@:>@, ev_out@<:@2@:>@;
struct timespec ts = { 0, 0 };
int pfd@<:@2@:>@, pty@<:@2@:>@, kfd, n;
char buffer@<:@9001@:>@;
if (pipe(pfd) == -1) return 1;
if (fcntl(pfd@<:@1@:>@, F_SETFL, O_NONBLOCK) == -1) return 2;
while ((n = write(pfd@<:@1@:>@, buffer, sizeof(buffer))) == sizeof(buffer));
if ((pty@<:@0@:>@=posix_openpt(O_RDWR | O_NOCTTY)) == -1) return 3;
if ((pty@<:@1@:>@=grantpt(pty@<:@0@:>@)) == -1) return 4;
EV_SET(ev+0, pfd@<:@1@:>@, EVFILT_WRITE, EV_ADD | EV_ENABLE, 0, 0, NULL);
EV_SET(ev+1, pty@<:@1@:>@, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, NULL);
if ((kfd = kqueue()) == -1) return 5;
if ((n = kevent(kfd, ev, 2, NULL, 0, NULL)) == -1) return 6;
if (ev_out@<:@0@:>@.flags & EV_ERROR) return 7;
if (ev_out@<:@1@:>@.flags & EV_ERROR) return 8;
read(pfd@<:@0@:>@, buffer, sizeof(buffer));
if ((n = kevent(kfd, NULL, 0, ev_out, 2, &ts)) < 1) return 9;
return 0;
}
])],
[
AC_MSG_RESULT(yes)
], [
AC_DEFINE(KQUEUE_SOCKET_ONLY, 1, kqueue only supports sockets.)
AC_MSG_RESULT(no)
])
])
AC_DEFUN([TORRENT_WITH_KQUEUE], [
AC_ARG_WITH(kqueue,
AC_HELP_STRING([--with-kqueue], [enable kqueue [[default=no]]]),
[
if test "$withval" = "yes"; then
TORRENT_CHECK_KQUEUE
TORRENT_CHECK_KQUEUE_SOCKET_ONLY
fi
])
])
AC_DEFUN([TORRENT_WITHOUT_KQUEUE], [
AC_ARG_WITH(kqueue,
AC_HELP_STRING([--without-kqueue], [do not check for kqueue support]),
[
if test "$withval" = "yes"; then
TORRENT_CHECK_KQUEUE
TORRENT_CHECK_KQUEUE_SOCKET_ONLY
fi
], [
TORRENT_CHECK_KQUEUE
TORRENT_CHECK_KQUEUE_SOCKET_ONLY
])
])
AC_DEFUN([TORRENT_WITHOUT_VARIABLE_FDSET], [
AC_ARG_WITH(variable-fdset,
AC_HELP_STRING([--without-variable-fdset], [do not use non-portable variable sized fd_set's]),
[
if test "$withval" = "yes"; then
AC_DEFINE(USE_VARIABLE_FDSET, 1, defined when we allow the use of fd_set's of any size)
fi
], [
AC_DEFINE(USE_VARIABLE_FDSET, 1, defined when we allow the use of fd_set's of any size)
])
])
AC_DEFUN([TORRENT_CHECK_FALLOCATE], [
AC_MSG_CHECKING(for fallocate)
AC_TRY_LINK([#include <fcntl.h>
#include <linux/falloc.h>
],[ fallocate(0, FALLOC_FL_KEEP_SIZE, 0, 0); return 0;
],
[
AC_DEFINE(HAVE_FALLOCATE, 1, Linux's fallocate supported.)
AC_MSG_RESULT(yes)
], [
AC_MSG_RESULT(no)
])
])
AC_DEFUN([TORRENT_CHECK_POSIX_FALLOCATE], [
AC_MSG_CHECKING(for posix_fallocate)
AC_TRY_LINK([#include <fcntl.h>
],[ posix_fallocate(0, 0, 0);
],
[
AC_DEFINE(USE_POSIX_FALLOCATE, 1, posix_fallocate supported.)
AC_MSG_RESULT(yes)
], [
AC_MSG_RESULT(no)
])
])
AC_DEFUN([TORRENT_WITH_POSIX_FALLOCATE], [
AC_ARG_WITH(posix-fallocate,
AC_HELP_STRING([--with-posix-fallocate], [check for and use posix_fallocate to allocate files]),
[
if test "$withval" = "yes"; then
TORRENT_CHECK_POSIX_FALLOCATE
fi
])
])
AC_DEFUN([TORRENT_CHECK_STATVFS], [
AC_CHECK_HEADERS(sys/vfs.h sys/statvfs.h sys/statfs.h)
AC_MSG_CHECKING(for statvfs)
AC_TRY_LINK(
[
#if HAVE_SYS_VFS_H
#include <sys/vfs.h>
#endif
#if HAVE_SYS_STATVFS_H
#include <sys/statvfs.h>
#endif
#if HAVE_SYS_STATFS_H
#include <sys/statfs.h>
#endif
],[
struct statvfs s; fsblkcnt_t c;
statvfs("", &s);
fstatvfs(0, &s);
],
[
AC_DEFINE(FS_STAT_FD, [fstatvfs(fd, &m_stat) == 0], Function to determine filesystem stats from fd)
AC_DEFINE(FS_STAT_FN, [statvfs(fn, &m_stat) == 0], Function to determine filesystem stats from filename)
AC_DEFINE(FS_STAT_STRUCT, [struct statvfs], Type of second argument to statfs function)
AC_DEFINE(FS_STAT_SIZE_TYPE, [unsigned long], Type of block size member in stat struct)
AC_DEFINE(FS_STAT_COUNT_TYPE, [fsblkcnt_t], Type of block count member in stat struct)
AC_DEFINE(FS_STAT_BLOCK_SIZE, [(m_stat.f_frsize)], Determine the block size)
AC_MSG_RESULT(ok)
have_stat_vfs=yes
],
[
AC_MSG_RESULT(no)
have_stat_vfs=no
])
])
AC_DEFUN([TORRENT_CHECK_STATFS], [
AC_CHECK_HEADERS(sys/statfs.h sys/param.h sys/mount.h)
AC_MSG_CHECKING(for statfs)
AC_TRY_LINK(
[
#if HAVE_SYS_STATFS_H
#include <sys/statfs.h>
#endif
#if HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#if HAVE_SYS_MOUNT_H
#include <sys/mount.h>
#endif
],[
struct statfs s;
statfs("", &s);
fstatfs(0, &s);
],
[
AC_DEFINE(FS_STAT_FD, [fstatfs(fd, &m_stat) == 0], Function to determine filesystem stats from fd)
AC_DEFINE(FS_STAT_FN, [statfs(fn, &m_stat) == 0], Function to determine filesystem stats from filename)
AC_DEFINE(FS_STAT_STRUCT, [struct statfs], Type of second argument to statfs function)
AC_DEFINE(FS_STAT_SIZE_TYPE, [long], Type of block size member in stat struct)
AC_DEFINE(FS_STAT_COUNT_TYPE, [long], Type of block count member in stat struct)
AC_DEFINE(FS_STAT_BLOCK_SIZE, [(m_stat.f_bsize)], Determine the block size)
AC_MSG_RESULT(ok)
have_stat_vfs=yes
],
[
AC_MSG_RESULT(no)
have_stat_vfs=no
])
])
AC_DEFUN([TORRENT_DISABLED_STATFS], [
AC_DEFINE(FS_STAT_FD, [(errno = ENOSYS) == 0], Function to determine filesystem stats from fd)
AC_DEFINE(FS_STAT_FN, [(errno = ENOSYS) == 0], Function to determine filesystem stats from filename)
AC_DEFINE(FS_STAT_STRUCT, [struct {blocksize_type f_bsize; blockcount_type f_bavail;}], Type of second argument to statfs function)
AC_DEFINE(FS_STAT_SIZE_TYPE, [int], Type of block size member in stat struct)
AC_DEFINE(FS_STAT_COUNT_TYPE, [int], Type of block count member in stat struct)
AC_DEFINE(FS_STAT_BLOCK_SIZE, [(4096)], Determine the block size)
AC_MSG_RESULT(No filesystem stats available)
])
AC_DEFUN([TORRENT_WITHOUT_STATVFS], [
AC_ARG_WITH(statvfs,
AC_HELP_STRING([--without-statvfs], [don't try to use statvfs to find free diskspace]),
[
if test "$withval" = "yes"; then
TORRENT_CHECK_STATVFS
else
have_stat_vfs=no
fi
],
[
TORRENT_CHECK_STATVFS
])
])
AC_DEFUN([TORRENT_WITHOUT_STATFS], [
AC_ARG_WITH(statfs,
AC_HELP_STRING([--without-statfs], [don't try to use statfs to find free diskspace]),
[
if test "$have_stat_vfs" = "no"; then
if test "$withval" = "yes"; then
TORRENT_CHECK_STATFS
else
TORRENT_DISABLED_STATFS
fi
fi
],
[
if test "$have_stat_vfs" = "no"; then
TORRENT_CHECK_STATFS
if test "$have_stat_vfs" = "no"; then
TORRENT_DISABLED_STATFS
fi
fi
])
])
AC_DEFUN([TORRENT_WITH_ADDRESS_SPACE], [
AC_ARG_WITH(address-space,
AC_HELP_STRING([--with-address-space=MB], [change the default address space size [[default=1024mb]]]),
[
if test ! -z $withval -a "$withval" != "yes" -a "$withval" != "no"; then
AC_DEFINE_UNQUOTED(DEFAULT_ADDRESS_SPACE_SIZE, [$withval])
else
AC_MSG_ERROR(--with-address-space requires a parameter.)
fi
],
[
AC_CHECK_SIZEOF(long)
if test $ac_cv_sizeof_long = 8; then
AC_DEFINE(DEFAULT_ADDRESS_SPACE_SIZE, 4096, Default address space size.)
else
AC_DEFINE(DEFAULT_ADDRESS_SPACE_SIZE, 1024, Default address space size.)
fi
])
])
AC_DEFUN([TORRENT_CHECK_TR1], [
AC_LANG_PUSH(C++)
AC_MSG_CHECKING(for TR1 support)
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <tr1/unordered_map>
class Foo;
typedef std::tr1::unordered_map<Foo*, int> Bar;
])],
[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_TR1, 1, Define to 1 if your C++ library supports the extensions from Technical Report 1)
],
[
AC_MSG_RESULT(no)
]
)
AC_LANG_POP(C++)
])
AC_DEFUN([TORRENT_CHECK_CXX11], [
AC_LANG_PUSH(C++)
AC_MSG_CHECKING(for C++11 support)
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <functional>
#include <unordered_map>
class Foo;
typedef std::unordered_map<Foo*, int> Bar;
union test { Bar b1; };
])],
[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_CXX11, 1, Define to 1 if your C++ compiler has support for C++11.)
],
[
AC_MSG_RESULT(no)
]
)
AC_LANG_POP(C++)
])
AC_DEFUN([TORRENT_WITH_FASTCGI], [
AC_ARG_WITH(fastcgi,
AC_HELP_STRING([--with-fastcgi=PATH], [enable FastCGI RPC support (DO NOT USE)]),
[
AC_MSG_CHECKING([for FastCGI (DO NOT USE)])
if test "$withval" = "no"; then
AC_MSG_RESULT(no)
elif test "$withval" = "yes"; then
CXXFLAGS="$CXXFLAGS"
LIBS="$LIBS -lfcgi"
AC_TRY_LINK(
[ #include <fcgiapp.h>
],[ FCGX_Init(); ],
[
AC_MSG_RESULT(ok)
],
[
AC_MSG_RESULT(not found)
AC_MSG_ERROR(Could not compile FastCGI test.)
])
AC_DEFINE(HAVE_FASTCGI, 1, Support for FastCGI.)
else
CXXFLAGS="$CXXFLAGS -I$withval/include"
LIBS="$LIBS -lfcgi -L$withval/lib"
AC_TRY_LINK(
[ #include <fcgiapp.h>
],[ FCGX_Init(); ],
[
AC_MSG_RESULT(ok)
],
[
AC_MSG_RESULT(not found)
AC_MSG_ERROR(Could not compile FastCGI test.)
])
AC_DEFINE(HAVE_FASTCGI, 1, Support for FastCGI.)
fi
])
])
AC_DEFUN([TORRENT_WITH_XMLRPC_C], [
AC_MSG_CHECKING(for XMLRPC-C)
AC_ARG_WITH(xmlrpc-c,
AC_HELP_STRING([--with-xmlrpc-c=PATH], [enable XMLRPC-C support]),
[
if test "$withval" = "no"; then
AC_MSG_RESULT(no)
else
if test "$withval" = "yes"; then
xmlrpc_cc_prg="xmlrpc-c-config"
else
xmlrpc_cc_prg="$withval"
fi
if eval $xmlrpc_cc_prg --version 2>/dev/null >/dev/null; then
CXXFLAGS="$CXXFLAGS `$xmlrpc_cc_prg --cflags server-util`"
LIBS="$LIBS `$xmlrpc_cc_prg server-util --libs`"
AC_TRY_LINK(
[ #include <xmlrpc-c/server.h>
],[ xmlrpc_registry_new(NULL); ],
[
AC_MSG_RESULT(ok)
], [
AC_MSG_RESULT(failed)
AC_MSG_ERROR(Could not compile XMLRPC-C test.)
])
AC_DEFINE(HAVE_XMLRPC_C, 1, Support for XMLRPC-C.)
else
AC_MSG_RESULT(failed)
AC_MSG_ERROR(Could not compile XMLRPC-C test.)
fi
fi
],[
AC_MSG_RESULT(ignored)
])
])
AC_DEFUN([TORRENT_WITH_INOTIFY], [
AC_LANG_PUSH(C++)
AC_CHECK_HEADERS([sys/inotify.h mcheck.h])
AC_MSG_CHECKING([whether sys/inotify.h actually works])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <sys/inotify.h>
int main(int,const char**) { return (-1 == inotify_init()); }])
],[
AC_DEFINE(HAVE_INOTIFY, 1, [sys/inotify.h exists and works correctly])
AC_MSG_RESULT(yes)],
[AC_MSG_RESULT(failed)]
)
AC_LANG_POP(C++)
])
AC_DEFUN([TORRENT_CHECK_PTHREAD_SETNAME_NP], [
AC_CHECK_HEADERS(pthread.h)
AC_MSG_CHECKING(for pthread_setname_np type)
AC_TRY_LINK([
#include <pthread.h>
#include <sys/types.h>
],[
pthread_t t;
pthread_setname_np(t, "foo");
],[
AC_DEFINE(HAS_PTHREAD_SETNAME_NP_GENERIC, 1, The function to set pthread name has a pthread_t argumet.)
AC_MSG_RESULT(generic)
],[
AC_TRY_LINK([
#include <pthread.h>
#include <sys/types.h>
],[
pthread_t t;
pthread_setname_np("foo");
],[
AC_DEFINE(HAS_PTHREAD_SETNAME_NP_DARWIN, 1, The function to set pthread name has no pthread argument.)
AC_MSG_RESULT(darwin)
],[
AC_MSG_RESULT(no)
])
])
])
-343
View File
@@ -1,343 +0,0 @@
AC_DEFUN([TORRENT_CHECK_CXXFLAGS], [
AC_MSG_CHECKING([for user-defined CXXFLAGS])
if test -n "$CXXFLAGS"; then
AC_MSG_RESULT([user-defined "$CXXFLAGS"])
else
CXXFLAGS="-O2 -Wall"
AC_MSG_RESULT([default "$CXXFLAGS"])
fi
])
AC_DEFUN([TORRENT_ENABLE_DEBUG], [
AC_ARG_ENABLE(debug,
AC_HELP_STRING([--enable-debug], [enable debug information [[default=yes]]]),
[
if test "$enableval" = "yes"; then
CXXFLAGS="$CXXFLAGS -g -DDEBUG"
else
CXXFLAGS="$CXXFLAGS -DNDEBUG"
fi
],[
CXXFLAGS="$CXXFLAGS -g -DDEBUG"
])
])
AC_DEFUN([TORRENT_ENABLE_WERROR], [
AC_ARG_ENABLE(werror,
AC_HELP_STRING([--enable-werror], [enable the -Werror and -Wall flag [[default=no]]]),
[
if test "$enableval" = "yes"; then
CXXFLAGS="$CXXFLAGS -Werror -Wall"
fi
])
])
AC_DEFUN([TORRENT_ENABLE_EXTRA_DEBUG], [
AC_ARG_ENABLE(extra-debug,
AC_HELP_STRING([--enable-extra-debug], [enable extra debugging checks [[default=no]]]),
[
if test "$enableval" = "yes"; then
AC_DEFINE(USE_EXTRA_DEBUG, 1, Enable extra debugging checks.)
fi
])
])
AC_DEFUN([TORRENT_WITH_SYSROOT], [
AC_ARG_WITH(sysroot,
AC_HELP_STRING([--with-sysroot=PATH], [compile and link with a specific sysroot]),
[
AC_MSG_CHECKING(for sysroot)
if test "$withval" = "no"; then
AC_MSG_RESULT(no)
elif test "$withval" = "yes"; then
AC_MSG_RESULT(not a path)
AC_MSG_ERROR(The sysroot option must point to a directory, like f.ex "/Developer/SDKs/MacOSX10.4u.sdk".)
else
AC_MSG_RESULT($withval)
CXXFLAGS="$CXXFLAGS -isysroot $withval"
LDFLAGS="$LDFLAGS -Wl,-syslibroot,$withval"
fi
])
])
AC_DEFUN([TORRENT_ENABLE_ARCH], [
AC_ARG_ENABLE(arch,
AC_HELP_STRING([--enable-arch=ARCH], [comma seprated list of architectures to compile for]),
[
AC_MSG_CHECKING(for target architectures)
if test "$enableval" = "yes"; then
AC_MSG_ERROR(no arch supplied)
elif test "$enableval" = "no"; then
AC_MSG_RESULT(using default)
else
AC_MSG_RESULT($enableval)
for i in `IFS=,; echo $enableval`; do
CFLAGS="$CFLAGS -march=$i"
CXXFLAGS="$CXXFLAGS -march=$i"
LDFLAGS="$LDFLAGS -march=$i"
done
fi
])
])
AC_DEFUN([TORRENT_OTFD], [
AC_LANG_PUSH(C++)
AC_MSG_CHECKING(for proper overloaded template function disambiguation)
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
template <typename T> void f(T&) {}
template <typename T> void f(T*) {}
int main() { int *i = 0; f(*i); f(i); }
])],
[
AC_MSG_RESULT(yes)
], [
AC_MSG_RESULT(no)
AC_MSG_ERROR([your compiler does not properly handle overloaded template function disambiguation])
])
AC_LANG_POP(C++)
])
AC_DEFUN([TORRENT_MINCORE_SIGNEDNESS], [
AC_LANG_PUSH(C++)
AC_MSG_CHECKING(signedness of mincore parameter)
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
void f() { mincore((char*)0, 0, (unsigned char*)0); }
])],
[
AC_DEFINE(USE_MINCORE, 1, Use mincore)
AC_DEFINE(USE_MINCORE_UNSIGNED, 1, use unsigned char* in mincore)
AC_MSG_RESULT(unsigned)
],
[
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
void f() { mincore((char*)0, 0, (char*)0); }
])],
[
AC_DEFINE(USE_MINCORE, 1, Use mincore)
AC_DEFINE(USE_MINCORE_UNSIGNED, 0, use char* in mincore)
AC_MSG_RESULT(signed)
],
[
AC_MSG_ERROR([failed, do *not* attempt fix this with --disable-mincore unless you are running Win32.])
])
])
AC_LANG_POP(C++)
])
AC_DEFUN([TORRENT_MINCORE], [
AC_ARG_ENABLE(mincore,
AC_HELP_STRING([--disable-mincore], [disable mincore check [[default=enable]]]),
[
if test "$enableval" = "yes"; then
TORRENT_MINCORE_SIGNEDNESS()
else
AC_MSG_CHECKING(for mincore)
AC_MSG_RESULT(disabled)
fi
],[
TORRENT_MINCORE_SIGNEDNESS()
])
])
AC_DEFUN([TORRENT_CHECK_MADVISE], [
AC_MSG_CHECKING(for madvise)
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <sys/types.h>
#include <sys/mman.h>
void f() { static char test@<:@1024@:>@; madvise((void *)test, sizeof(test), MADV_NORMAL); }
])],
[
AC_MSG_RESULT(yes)
AC_DEFINE(USE_MADVISE, 1, Use madvise)
], [
AC_MSG_RESULT(no)
])
])
AC_DEFUN([TORRENT_CHECK_POPCOUNT], [
AC_MSG_CHECKING(for __builtin_popcount)
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
int f() { return __builtin_popcount(0); }
])],
[
AC_MSG_RESULT(yes)
AC_DEFINE(USE_BUILTIN_POPCOUNT, 1, Use __builtin_popcount.)
], [
AC_MSG_RESULT(no)
])
])
AC_DEFUN([TORRENT_CHECK_CACHELINE], [
AC_MSG_CHECKING(for cacheline)
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <stdlib.h>
#include <linux/cache.h>
void* vptr __cacheline_aligned;
void f() { posix_memalign(&vptr, SMP_CACHE_BYTES, 42); }
])],
[
AC_MSG_RESULT(found builtin)
dnl AC_DEFINE(LT_SMP_CACHE_BYTES, SMP_CACHE_BYTES, Largest L1 cache size we know of, should work on all archs.)
dnl AC_DEFINE(lt_cacheline_aligned, __cacheline_aligned, LibTorrent defined cacheline aligned.)
dnl Need to fix this so that it uses the stuff defined by the system.
AC_DEFINE(LT_SMP_CACHE_BYTES, 128, Largest L1 cache size we know of should work on all archs.)
AC_DEFINE(lt_cacheline_aligned, __attribute__((__aligned__(LT_SMP_CACHE_BYTES))), LibTorrent defined cacheline aligned.)
], [
AC_MSG_RESULT(using default 128 bytes)
AC_DEFINE(LT_SMP_CACHE_BYTES, 128, Largest L1 cache size we know of should work on all archs.)
AC_DEFINE(lt_cacheline_aligned, __attribute__((__aligned__(LT_SMP_CACHE_BYTES))), LibTorrent defined cacheline aligned.)
])
])
AC_DEFUN([TORRENT_CHECK_EXECINFO], [
AC_MSG_CHECKING(for execinfo.h)
AC_RUN_IFELSE([AC_LANG_SOURCE([
#include <execinfo.h>
int main() { backtrace((void**)0, 0); backtrace_symbols((char**)0, 0); return 0;}
])],
[
AC_MSG_RESULT(yes)
AC_DEFINE(USE_EXECINFO, 1, Use execinfo.h)
], [
AC_MSG_RESULT(no)
])
])
AC_DEFUN([TORRENT_CHECK_ALIGNED], [
AC_MSG_CHECKING(the byte alignment)
AC_RUN_IFELSE([AC_LANG_SOURCE([
#include <inttypes.h>
int main() {
char buf@<:@8@:>@ = { 0, 0, 0, 0, 1, 0, 0, 0 };
int i;
for (i = 1; i < 4; ++i)
if (*(uint32_t*)(buf + i) == 0) return -1;
return 0;
}
])],
[
AC_MSG_RESULT(none needed)
], [
AC_DEFINE(USE_ALIGNED, 1, Require byte alignment)
AC_MSG_RESULT(required)
])
])
AC_DEFUN([TORRENT_ENABLE_ALIGNED], [
AC_ARG_ENABLE(aligned,
AC_HELP_STRING([--enable-aligned], [enable alignment safe code [[default=check]]]),
[
if test "$enableval" = "yes"; then
AC_DEFINE(USE_ALIGNED, 1, Require byte alignment)
fi
],[
TORRENT_CHECK_ALIGNED
])
])
AC_DEFUN([TORRENT_DISABLE_INSTRUMENTATION], [
AC_MSG_CHECKING([if instrumentation should be included])
AC_ARG_ENABLE(instrumentation,
AC_HELP_STRING([--disable-instrumentation], [disable instrumentation [[default=enabled]]]),
[
if test "$enableval" = "yes"; then
AC_DEFINE(LT_INSTRUMENTATION, 1, enable instrumentation)
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
],[
AC_DEFINE(LT_INSTRUMENTATION, 1, enable instrumentation)
AC_MSG_RESULT(yes)
])
])
AC_DEFUN([TORRENT_ENABLE_INTERRUPT_SOCKET], [
AC_ARG_ENABLE(interrupt-socket,
AC_HELP_STRING([--enable-interrupt-socket], [enable interrupt socket [[default=no]]]),
[
if test "$enableval" = "yes"; then
AC_DEFINE(USE_INTERRUPT_SOCKET, 1, Use interrupt socket instead of pthread_kill)
fi
]
)
])
AC_DEFUN([TORRENT_DISABLE_IPV6], [
AC_ARG_ENABLE(ipv6,
AC_HELP_STRING([--enable-ipv6], [enable ipv6 [[default=no]]]),
[
if test "$enableval" = "yes"; then
AC_DEFINE(RAK_USE_INET6, 1, enable ipv6 stuff)
fi
])
])
AC_DEFUN([TORRENT_ENABLE_TR1], [
AC_ARG_ENABLE(std_tr1,
AC_HELP_STRING([--disable-std_tr1], [disable check for support for TR1 [[default=enable]]]),
[
if test "$enableval" = "yes"; then
TORRENT_CHECK_TR1()
else
AC_MSG_CHECKING(for TR1 support)
AC_MSG_RESULT(disabled)
fi
],[
TORRENT_CHECK_TR1()
])
])
AC_DEFUN([TORRENT_ENABLE_CXX11], [
AC_ARG_ENABLE(std_c++11,
AC_HELP_STRING([--disable-std_c++11], [disable check for support for C++11 [[default=enable]]]),
[
if test "$enableval" = "yes"; then
TORRENT_CHECK_CXX11()
else
AC_MSG_CHECKING(for C++11 support)
AC_MSG_RESULT(disabled)
fi
],[
TORRENT_CHECK_CXX11()
]
)
])
-55
View File
@@ -1,55 +0,0 @@
SUBDIRS = \
core \
display \
input \
rpc \
ui \
utils
noinst_LIBRARIES = libsub_root.a
libsub_root_a_SOURCES = \
command_download.cc \
command_dynamic.cc \
command_events.cc \
command_file.cc \
command_ip.cc \
command_helpers.cc \
command_helpers.h \
command_groups.cc \
command_local.cc \
command_network.cc \
command_peer.cc \
command_throttle.cc \
command_tracker.cc \
command_scheduler.cc \
command_ui.cc \
control.cc \
control.h \
globals.cc \
globals.h \
option_parser.cc \
option_parser.h \
signal_handler.cc \
signal_handler.h \
thread_base.cc \
thread_base.h \
thread_worker.cc \
thread_worker.h
bin_PROGRAMS = rtorrent
rtorrent_LDADD = \
libsub_root.a \
ui/libsub_ui.a \
core/libsub_core.a \
display/libsub_display.a \
input/libsub_input.a \
rpc/libsub_rpc.a \
utils/libsub_utils.a \
@PTHREAD_LIBS@
rtorrent_SOURCES = \
main.cc
AM_CPPFLAGS = -I$(srcdir) -I$(top_srcdir)
-871
View File
@@ -1,871 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <functional>
#include <unistd.h>
#include <cstdio>
#include <rak/file_stat.h>
#include <rak/error_number.h>
#include <rak/path.h>
#include <rak/socket_address.h>
#include <rak/string_manip.h>
#include <rak/regex.h>
#include <torrent/rate.h>
#include <torrent/throttle.h>
#include <torrent/tracker.h>
#include <torrent/tracker_controller.h>
#include <torrent/tracker_list.h>
#include <torrent/connection_manager.h>
#include <torrent/data/download_data.h>
#include <torrent/data/file.h>
#include <torrent/data/file_list.h>
#include <torrent/download/resource_manager.h>
#include <torrent/peer/connection_list.h>
#include <torrent/peer/peer_list.h>
#include <torrent/utils/log.h>
#include <torrent/utils/option_strings.h>
#include "core/download.h"
#include "core/download_store.h"
#include "core/manager.h"
#include "rpc/parse.h"
#include "globals.h"
#include "control.h"
#include "command_helpers.h"
std::string
retrieve_d_base_path(core::Download* download) {
if (download->file_list()->is_multi_file())
return download->file_list()->frozen_root_dir();
else
return download->file_list()->empty() ? std::string() : download->file_list()->at(0)->frozen_path();
}
std::string
retrieve_d_base_filename(core::Download* download) {
const std::string* base;
if (download->file_list()->is_multi_file())
base = &download->file_list()->frozen_root_dir();
else
base = &download->file_list()->at(0)->frozen_path();
std::string::size_type split = base->rfind('/');
if (split == std::string::npos)
return *base;
else
return base->substr(split + 1);
}
torrent::Object
apply_d_change_link(core::Download* download, const torrent::Object::list_type& args, int changeType) {
if (args.size() != 3)
throw torrent::input_error("Wrong argument count.");
torrent::Object::list_const_iterator itr = args.begin();
const std::string& type = (itr++)->as_string();
const std::string& prefix = (itr++)->as_string();
const std::string& postfix = (itr++)->as_string();
if (type.empty())
throw torrent::input_error("Invalid arguments.");
std::string target;
std::string link;
if (type == "base_path") {
target = rpc::call_command_string("d.base_path", rpc::make_target(download));
link = rak::path_expand(prefix + rpc::call_command_string("d.base_path", rpc::make_target(download)) + postfix);
} else if (type == "base_filename") {
target = rpc::call_command_string("d.base_path", rpc::make_target(download));
link = rak::path_expand(prefix + rpc::call_command_string("d.base_filename", rpc::make_target(download)) + postfix);
// } else if (type == "directory_path") {
// target = rpc::call_command_string("d.directory", rpc::make_target(download));
// link = rak::path_expand(prefix + rpc::call_command_string("d.base_path", rpc::make_target(download)) + postfix);
} else if (type == "tied") {
link = rak::path_expand(rpc::call_command_string("d.tied_to_file", rpc::make_target(download)));
if (link.empty())
return torrent::Object();
link = rak::path_expand(prefix + link + postfix);
target = rpc::call_command_string("d.base_path", rpc::make_target(download));
} else {
throw torrent::input_error("Unknown type argument.");
}
switch (changeType) {
case 0:
if (symlink(target.c_str(), link.c_str()) == -1){
lt_log_print(torrent::LOG_TORRENT_WARN, "create_link failed: %s",
rak::error_number::current().c_str());
}
break;
case 1:
{
rak::file_stat fileStat;
rak::error_number::clear_global();
if (!fileStat.update_link(link) || !fileStat.is_link() ||
unlink(link.c_str()) == -1){
lt_log_print(torrent::LOG_TORRENT_WARN, "delete_link failed: %s",
rak::error_number::current().c_str());
}
break;
}
default:
break;
}
return torrent::Object();
}
torrent::Object
apply_d_delete_tied(core::Download* download) {
const std::string& tie = rpc::call_command_string("d.tied_to_file", rpc::make_target(download));
if (tie.empty())
return torrent::Object();
if (::unlink(rak::path_expand(tie).c_str()) == -1)
control->core()->push_log_std("Could not unlink tied file: " + std::string(rak::error_number::current().c_str()));
rpc::call_command("d.tied_to_file.set", std::string(), rpc::make_target(download));
return torrent::Object();
}
void
apply_d_directory(core::Download* download, const std::string& name) {
if (!download->file_list()->is_multi_file())
download->set_root_directory(name);
else if (name.empty() || *name.rbegin() == '/')
download->set_root_directory(name + download->info()->name());
else
download->set_root_directory(name + "/" + download->info()->name());
}
torrent::Object
apply_d_connection_type(core::Download* download, const std::string& name) {
torrent::Download::ConnectionType t =
(torrent::Download::ConnectionType)torrent::option_find_string(torrent::OPTION_CONNECTION_TYPE, name.c_str());
download->download()->set_connection_type(t);
return torrent::Object();
}
torrent::Object
apply_d_choke_heuristics(core::Download* download, const std::string& name, bool is_down) {
torrent::Download::HeuristicType t =
(torrent::Download::HeuristicType)torrent::option_find_string(torrent::OPTION_CHOKE_HEURISTICS, name.c_str());
if (is_down)
download->download()->set_download_choke_heuristic(t);
else
download->download()->set_upload_choke_heuristic(t);
return torrent::Object();
}
const char*
retrieve_d_priority_str(core::Download* download) {
switch (download->priority()) {
case 0:
return "off";
case 1:
return "low";
case 2:
return "normal";
case 3:
return "high";
default:
throw torrent::input_error("Priority out of range.");
}
}
torrent::Object
retrieve_d_ratio(core::Download* download) {
if (download->is_hash_checking())
return int64_t();
int64_t bytesDone = download->download()->bytes_done();
int64_t upTotal = download->info()->up_rate()->total();
return bytesDone > 0 ? (1000 * upTotal) / bytesDone : 0;
}
torrent::Object
apply_d_custom(core::Download* download, const torrent::Object::list_type& args) {
torrent::Object::list_const_iterator itr = args.begin();
if (itr == args.end())
throw torrent::bencode_error("Missing key argument.");
const std::string& key = itr->as_string();
if (++itr == args.end())
throw torrent::bencode_error("Missing value argument.");
download->bencode()->get_key("rtorrent").
insert_preserve_copy("custom", torrent::Object::create_map()).first->second.
insert_key(key, itr->as_string());
return torrent::Object();
}
torrent::Object
retrieve_d_custom(core::Download* download, const std::string& key) {
try {
return download->bencode()->get_key("rtorrent").get_key("custom").get_key_string(key);
} catch (torrent::bencode_error& e) {
return std::string();
}
}
torrent::Object
retrieve_d_custom_throw(core::Download* download, const std::string& key) {
try {
return download->bencode()->get_key("rtorrent").get_key("custom").get_key_string(key);
} catch (torrent::bencode_error& e) {
throw torrent::input_error("No such custom value.");
}
}
torrent::Object
retrieve_d_bitfield(core::Download* download) {
const torrent::Bitfield* bitField = download->download()->file_list()->bitfield();
if (bitField->empty())
return torrent::Object("");
return torrent::Object(rak::transform_hex(bitField->begin(), bitField->end()));
}
struct call_add_d_peer_t {
call_add_d_peer_t(core::Download* d, int port) : m_download(d), m_port(port) { }
void operator() (const sockaddr* sa, int err) {
if (sa == NULL) {
lt_log_print(torrent::LOG_CONNECTION_WARN, "Could not resolve hostname for added peer.");
} else {
m_download->download()->add_peer(sa, m_port);
}
}
core::Download* m_download;
int m_port;
};
void
apply_d_add_peer(core::Download* download, const std::string& arg) {
int port, ret;
char dummy;
char host[1024];
if (download->download()->info()->is_private())
throw torrent::input_error("Download is private.");
ret = std::sscanf(arg.c_str(), "%1023[^:]:%i%c", host, &port, &dummy);
if (ret == 1)
port = 6881;
else if (ret != 2)
throw torrent::input_error("Could not parse host.");
if (port < 1 || port > 65535)
throw torrent::input_error("Invalid port number.");
torrent::connection_manager()->resolver()(host, (int)rak::socket_address::pf_inet, SOCK_STREAM, call_add_d_peer_t(download, port));
}
torrent::Object
d_chunks_seen(core::Download* download) {
const uint8_t* seen = download->download()->chunks_seen();
if (seen == NULL)
return std::string();
uint32_t size = download->download()->file_list()->size_chunks();
std::string result;
result.resize(size * 2);
rak::transform_hex((const char*)seen, (const char*)seen + size, result.begin());
return result;
}
torrent::Object
f_multicall(core::Download* download, const torrent::Object::list_type& args) {
if (args.empty())
throw torrent::input_error("Too few arguments.");
// We ignore the first arg for now, but it will be used for
// selecting what files to include.
// Add some pre-parsing of the commands, so we don't spend time
// parsing and searching command map for every single call.
torrent::Object resultRaw = torrent::Object::create_list();
torrent::Object::list_type& result = resultRaw.as_list();
std::vector<rak::regex> regex_list;
bool use_regex = true;
if (args.front().is_list())
std::transform(args.front().as_list().begin(), args.front().as_list().end(),
std::back_inserter(regex_list),
tr1::bind(&torrent::Object::as_string_c, tr1::placeholders::_1));
else if (args.front().is_string() && !args.front().as_string().empty())
regex_list.push_back(args.front().as_string());
else
use_regex = false;
for (torrent::FileList::const_iterator itr = download->file_list()->begin(), last = download->file_list()->end(); itr != last; itr++) {
if (use_regex &&
std::find_if(regex_list.begin(), regex_list.end(),
tr1::bind(&rak::regex::operator(), tr1::placeholders::_1, (*itr)->path()->as_string())) == regex_list.end())
continue;
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
for (torrent::Object::list_const_iterator cItr = ++args.begin(); cItr != args.end(); cItr++) {
const std::string& cmd = cItr->as_string();
row.push_back(rpc::parse_command(rpc::make_target(*itr), cmd.c_str(), cmd.c_str() + cmd.size()).first);
}
}
return resultRaw;
}
torrent::Object
t_multicall(core::Download* download, const torrent::Object::list_type& args) {
if (args.empty())
throw torrent::input_error("Too few arguments.");
// We ignore the first arg for now, but it will be used for
// selecting what files to include.
// Add some pre-parsing of the commands, so we don't spend time
// parsing and searching command map for every single call.
torrent::Object resultRaw = torrent::Object::create_list();
torrent::Object::list_type& result = resultRaw.as_list();
for (int itr = 0, last = download->tracker_list()->size(); itr != last; itr++) {
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
for (torrent::Object::list_const_iterator cItr = ++args.begin(); cItr != args.end(); cItr++) {
const std::string& cmd = cItr->as_string();
torrent::Tracker* t = download->tracker_list()->at(itr);
row.push_back(rpc::parse_command(rpc::make_target(t), cmd.c_str(), cmd.c_str() + cmd.size()).first);
}
}
return resultRaw;
}
torrent::Object
p_multicall(core::Download* download, const torrent::Object::list_type& args) {
if (args.empty())
throw torrent::input_error("Too few arguments.");
// We ignore the first arg for now, but it will be used for
// selecting what files to include.
// Add some pre-parsing of the commands, so we don't spend time
// parsing and searching command map for every single call.
torrent::Object resultRaw = torrent::Object::create_list();
torrent::Object::list_type& result = resultRaw.as_list();
for (torrent::ConnectionList::const_iterator itr = download->connection_list()->begin(), last = download->connection_list()->end();
itr != last; itr++) {
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
for (torrent::Object::list_const_iterator cItr = ++args.begin(); cItr != args.end(); cItr++) {
const std::string& cmd = cItr->as_string();
row.push_back(rpc::parse_command(rpc::make_target(*itr), cmd.c_str(), cmd.c_str() + cmd.size()).first);
}
}
return resultRaw;
}
torrent::Object
p_call_target(const torrent::Object::list_type& args) {
if (args.empty() || args.begin() + 1 == args.end() || args.begin() + 2 == args.end())
throw torrent::input_error("Too few arguments.");
// We ignore the first arg for now, but it will be used for
// selecting what files to include.
// Add some pre-parsing of the commands, so we don't spend time
// parsing and searching command map for every single call.
torrent::Object::list_const_iterator itr = args.begin();
core::Download* download = control->core()->download_list()->find_hex_ptr(itr++->as_string().c_str());
const std::string& peer_id = itr++->as_string();
const std::string& command_key = itr++->as_string();
torrent::HashString hash;
if (peer_id.size() != 40 ||
torrent::hash_string_from_hex_c_str(peer_id.c_str(), hash) == peer_id.c_str())
throw torrent::input_error("Not a hash string.");
torrent::ConnectionList::iterator peerItr = download->connection_list()->find(hash.c_str());
if (peerItr == download->connection_list()->end())
throw torrent::input_error("Could not find peer.");
if (itr == args.end())
return rpc::commands.call(command_key.c_str());
if (itr + 1 == args.end())
return rpc::commands.call(command_key.c_str(), *itr);
return rpc::commands.call(command_key.c_str(), torrent::Object::create_list_range(itr, args.end()));
}
torrent::Object
download_tracker_insert(core::Download* download, const torrent::Object::list_type& args) {
if (args.size() != 2)
throw torrent::input_error("Wrong argument count.");
int64_t group;
if (args.front().is_string())
rpc::parse_whole_value_nothrow(args.front().as_string().c_str(), &group);
else
group = args.front().as_value();
if (group < 0 || group > 32)
throw torrent::input_error("Tracker group number invalid.");
download->download()->tracker_list()->insert_url(group, args.back().as_string(), true);
return torrent::Object();
}
//
// New download commands and macros:
//
torrent::Object&
download_get_variable(core::Download* download, const char* first_key, const char* second_key = NULL) {
if (second_key == NULL)
return download->bencode()->get_key(first_key);
return download->bencode()->get_key(first_key).get_key(second_key);
}
torrent::Object
download_set_variable(core::Download* download, const torrent::Object& rawArgs, const char* first_key, const char* second_key = NULL) {
if (second_key == NULL)
return download->bencode()->get_key(first_key) = torrent::object_create_normal(rawArgs);
return download->bencode()->get_key(first_key).get_key(second_key) = torrent::object_create_normal(rawArgs);
}
torrent::Object
download_set_variable_value(core::Download* download, const torrent::Object::value_type& args,
const char* first_key, const char* second_key = NULL) {
if (second_key == NULL)
return download->bencode()->get_key(first_key) = args;
return download->bencode()->get_key(first_key).get_key(second_key) = args;
}
torrent::Object
download_set_variable_value_ifz(core::Download* download, const torrent::Object::value_type& args,
const char* first_key, const char* second_key = NULL) {
torrent::Object& object = second_key == NULL ?
download->bencode()->get_key(first_key) :
download->bencode()->get_key(first_key).get_key(second_key);
if (object.as_value() == 0)
object = args;
return object;
}
torrent::Object
download_set_variable_string(core::Download* download, const torrent::Object::string_type& args,
const char* first_key, const char* second_key = NULL) {
if (second_key == NULL)
return download->bencode()->get_key(first_key) = args;
return download->bencode()->get_key(first_key).get_key(second_key) = args;
}
//
//
//
torrent::Object
d_list_push_back(core::Download* download, const torrent::Object& rawArgs, const char* first_key, const char* second_key) {
download_get_variable(download, first_key, second_key).as_list().push_back(rawArgs);
return torrent::Object();
}
torrent::Object
d_list_push_back_unique(core::Download* download, const torrent::Object& rawArgs, const char* first_key, const char* second_key) {
const torrent::Object& args = (rawArgs.is_list() && !rawArgs.as_list().empty()) ? rawArgs.as_list().front() : rawArgs;
torrent::Object::list_type& list = download_get_variable(download, first_key, second_key).as_list();
if (std::find_if(list.begin(), list.end(),
rak::bind1st(std::ptr_fun(&torrent::object_equal), args)) == list.end())
list.push_back(rawArgs);
return torrent::Object();
}
torrent::Object
d_list_has(core::Download* download, const torrent::Object& rawArgs, const char* first_key, const char* second_key) {
const torrent::Object& args = (rawArgs.is_list() && !rawArgs.as_list().empty()) ? rawArgs.as_list().front() : rawArgs;
torrent::Object::list_type& list = download_get_variable(download, first_key, second_key).as_list();
return (int64_t)(std::find_if(list.begin(), list.end(),
rak::bind1st(std::ptr_fun(&torrent::object_equal), args)) != list.end());
}
torrent::Object
d_list_remove(core::Download* download, const torrent::Object& rawArgs, const char* first_key, const char* second_key) {
const torrent::Object& args = (rawArgs.is_list() && !rawArgs.as_list().empty()) ? rawArgs.as_list().front() : rawArgs;
torrent::Object::list_type& list = download_get_variable(download, first_key, second_key).as_list();
list.erase(std::remove_if(list.begin(), list.end(), rak::bind1st(std::ptr_fun(&torrent::object_equal), args)), list.end());
return torrent::Object();
}
#define CMD2_ON_INFO(func) tr1::bind(&torrent::DownloadInfo::func, tr1::bind(&core::Download::info, tr1::placeholders::_1))
#define CMD2_ON_DATA(func) tr1::bind(&torrent::download_data::func, tr1::bind(&core::Download::data, tr1::placeholders::_1))
#define CMD2_ON_DL(func) tr1::bind(&torrent::Download::func, tr1::bind(&core::Download::download, tr1::placeholders::_1))
#define CMD2_ON_FL(func) tr1::bind(&torrent::FileList::func, tr1::bind(&core::Download::file_list, tr1::placeholders::_1))
#define CMD2_BIND_DL tr1::bind(&core::Download::download, tr1::placeholders::_1)
#define CMD2_BIND_CL tr1::bind(&core::Download::connection_list, tr1::placeholders::_1)
#define CMD2_BIND_FL tr1::bind(&core::Download::file_list, tr1::placeholders::_1)
#define CMD2_BIND_PL tr1::bind(&core::Download::c_peer_list, tr1::placeholders::_1)
#define CMD2_BIND_TL tr1::bind(&core::Download::tracker_list, tr1::placeholders::_1)
#define CMD2_BIND_TC tr1::bind(&core::Download::tracker_controller, tr1::placeholders::_1)
#define CMD2_BIND_INFO tr1::bind(&core::Download::info, tr1::placeholders::_1)
#define CMD2_BIND_DATA tr1::bind(&core::Download::data, tr1::placeholders::_1)
#define CMD2_DL_VAR_VALUE(key, first_key, second_key) \
CMD2_DL(key, tr1::bind(&download_get_variable, tr1::placeholders::_1, first_key, second_key)); \
CMD2_DL_VALUE_P(key ".set", tr1::bind(&download_set_variable_value, \
tr1::placeholders::_1, tr1::placeholders::_2, \
first_key, second_key));
#define CMD2_DL_VAR_VALUE_PUBLIC(key, first_key, second_key) \
CMD2_DL(key, tr1::bind(&download_get_variable, tr1::placeholders::_1, first_key, second_key)); \
CMD2_DL_VALUE(key ".set", tr1::bind(&download_set_variable_value, \
tr1::placeholders::_1, tr1::placeholders::_2, \
first_key, second_key));
#define CMD2_DL_TIMESTAMP(key, first_key, second_key) \
CMD2_DL(key, tr1::bind(&download_get_variable, tr1::placeholders::_1, first_key, second_key)); \
CMD2_DL_VALUE_P(key ".set", tr1::bind(&download_set_variable_value, \
tr1::placeholders::_1, tr1::placeholders::_2, \
first_key, second_key)); \
CMD2_DL_VALUE_P(key ".set_if_z", tr1::bind(&download_set_variable_value_ifz, \
tr1::placeholders::_1, tr1::placeholders::_2, \
first_key, second_key)); \
#define CMD2_DL_VAR_STRING(key, first_key, second_key) \
CMD2_DL(key, tr1::bind(&download_get_variable, tr1::placeholders::_1, first_key, second_key)); \
CMD2_DL_STRING_P(key ".set", tr1::bind(&download_set_variable_string, \
tr1::placeholders::_1, tr1::placeholders::_2, \
first_key, second_key));
#define CMD2_DL_VAR_STRING_PUBLIC(key, first_key, second_key) \
CMD2_DL(key, tr1::bind(&download_get_variable, tr1::placeholders::_1, first_key, second_key)); \
CMD2_DL_STRING(key ".set", tr1::bind(&download_set_variable_string, \
tr1::placeholders::_1, tr1::placeholders::_2, \
first_key, second_key));
int64_t cg_d_group(core::Download* download);
const std::string& cg_d_group_name(core::Download* download);
void cg_d_group_set(core::Download* download, const torrent::Object& arg);
void
initialize_command_download() {
CMD2_DL("d.hash", tr1::bind(&rak::transform_hex_str<torrent::HashString>, CMD2_ON_INFO(hash)));
CMD2_DL("d.local_id", tr1::bind(&rak::transform_hex_str<torrent::HashString>, CMD2_ON_INFO(local_id)));
CMD2_DL("d.local_id_html", tr1::bind(&rak::copy_escape_html_str<torrent::HashString>, CMD2_ON_INFO(local_id)));
CMD2_DL("d.bitfield", tr1::bind(&retrieve_d_bitfield, tr1::placeholders::_1));
CMD2_DL("d.base_path", tr1::bind(&retrieve_d_base_path, tr1::placeholders::_1));
CMD2_DL("d.base_filename", tr1::bind(&retrieve_d_base_filename, tr1::placeholders::_1));
CMD2_DL("d.name", CMD2_ON_INFO(name));
CMD2_DL("d.creation_date", CMD2_ON_INFO(creation_date));
CMD2_DL("d.load_date", CMD2_ON_INFO(load_date));
//
// Network related:
//
CMD2_DL ("d.up.rate", tr1::bind(&torrent::Rate::rate, CMD2_ON_INFO(up_rate)));
CMD2_DL ("d.up.total", tr1::bind(&torrent::Rate::total, CMD2_ON_INFO(up_rate)));
CMD2_DL ("d.down.rate", tr1::bind(&torrent::Rate::rate, CMD2_ON_INFO(down_rate)));
CMD2_DL ("d.down.total", tr1::bind(&torrent::Rate::total, CMD2_ON_INFO(down_rate)));
CMD2_DL ("d.skip.rate", tr1::bind(&torrent::Rate::rate, CMD2_ON_INFO(skip_rate)));
CMD2_DL ("d.skip.total", tr1::bind(&torrent::Rate::total, CMD2_ON_INFO(skip_rate)));
CMD2_DL ("d.peer_exchange", CMD2_ON_INFO(is_pex_enabled));
CMD2_DL_VALUE_V ("d.peer_exchange.set", tr1::bind(&torrent::Download::set_pex_enabled, CMD2_BIND_DL, tr1::placeholders::_2));
CMD2_DL_LIST ("d.create_link", tr1::bind(&apply_d_change_link, tr1::placeholders::_1, tr1::placeholders::_2, 0));
CMD2_DL_LIST ("d.delete_link", tr1::bind(&apply_d_change_link, tr1::placeholders::_1, tr1::placeholders::_2, 1));
CMD2_DL ("d.delete_tied", tr1::bind(&apply_d_delete_tied, tr1::placeholders::_1));
CMD2_FUNC_SINGLE("d.start", "d.hashing_failed.set=0 ;view.set_visible=started");
CMD2_FUNC_SINGLE("d.stop", "view.set_visible=stopped");
CMD2_FUNC_SINGLE("d.try_start", "branch=\"or={d.hashing_failed=,d.ignore_commands=}\",{},{view.set_visible=started}");
CMD2_FUNC_SINGLE("d.try_stop", "branch=d.ignore_commands=, {}, {view.set_visible=stopped}");
CMD2_FUNC_SINGLE("d.try_close", "branch=d.ignore_commands=, {}, {view.set_visible=stopped, d.close=}");
//
// Control functinos:
//
CMD2_DL ("d.is_open", CMD2_ON_INFO(is_open));
CMD2_DL ("d.is_active", CMD2_ON_INFO(is_active));
CMD2_DL ("d.is_hash_checked", tr1::bind(&torrent::Download::is_hash_checked, CMD2_BIND_DL));
CMD2_DL ("d.is_hash_checking", tr1::bind(&torrent::Download::is_hash_checking, CMD2_BIND_DL));
CMD2_DL ("d.is_multi_file", tr1::bind(&torrent::FileList::is_multi_file, CMD2_BIND_FL));
CMD2_DL ("d.is_private", CMD2_ON_INFO(is_private));
CMD2_DL ("d.is_pex_active", CMD2_ON_INFO(is_pex_active));
CMD2_DL ("d.is_partially_done", CMD2_ON_DATA(is_partially_done));
CMD2_DL ("d.is_not_partially_done", CMD2_ON_DATA(is_not_partially_done));
CMD2_DL_V ("d.resume", tr1::bind(&core::DownloadList::resume_default, control->core()->download_list(), tr1::placeholders::_1));
CMD2_DL_V ("d.pause", tr1::bind(&core::DownloadList::pause_default, control->core()->download_list(), tr1::placeholders::_1));
CMD2_DL_V ("d.open", tr1::bind(&core::DownloadList::open_throw, control->core()->download_list(), tr1::placeholders::_1));
CMD2_DL_V ("d.close", tr1::bind(&core::DownloadList::close_throw, control->core()->download_list(), tr1::placeholders::_1));
CMD2_DL_V ("d.close.directly", tr1::bind(&core::DownloadList::close_directly, control->core()->download_list(), tr1::placeholders::_1));
CMD2_DL_V ("d.erase", tr1::bind(&core::DownloadList::erase_ptr, control->core()->download_list(), tr1::placeholders::_1));
CMD2_DL_V ("d.check_hash", tr1::bind(&core::DownloadList::check_hash, control->core()->download_list(), tr1::placeholders::_1));
CMD2_DL ("d.save_resume", tr1::bind(&core::DownloadStore::save_resume, control->core()->download_store(), tr1::placeholders::_1));
CMD2_DL ("d.save_full_session", tr1::bind(&core::DownloadStore::save_full, control->core()->download_store(), tr1::placeholders::_1));
CMD2_DL_V ("d.update_priorities", CMD2_ON_DL(update_priorities));
CMD2_DL_STRING_V("add_peer", tr1::bind(&apply_d_add_peer, tr1::placeholders::_1, tr1::placeholders::_2));
//
// Custom settings:
//
CMD2_DL_STRING("d.custom", tr1::bind(&retrieve_d_custom, tr1::placeholders::_1, tr1::placeholders::_2));
CMD2_DL_STRING("d.custom_throw", tr1::bind(&retrieve_d_custom_throw, tr1::placeholders::_1, tr1::placeholders::_2));
CMD2_DL_LIST ("d.custom.set", tr1::bind(&apply_d_custom, tr1::placeholders::_1, tr1::placeholders::_2));
CMD2_DL_VAR_STRING_PUBLIC("d.custom1", "rtorrent", "custom1");
CMD2_DL_VAR_STRING_PUBLIC("d.custom2", "rtorrent", "custom2");
CMD2_DL_VAR_STRING_PUBLIC("d.custom3", "rtorrent", "custom3");
CMD2_DL_VAR_STRING_PUBLIC("d.custom4", "rtorrent", "custom4");
CMD2_DL_VAR_STRING_PUBLIC("d.custom5", "rtorrent", "custom5");
// 0 - stopped
// 1 - started
CMD2_DL_VAR_VALUE("d.state", "rtorrent", "state");
CMD2_DL_VAR_VALUE("d.complete", "rtorrent", "complete");
CMD2_FUNC_SINGLE ("d.incomplete", "not=(d.complete)");
// 0 off
// 1 scheduled, being controlled by a download scheduler. Includes a priority.
// 3 forced off
// 2 forced on
CMD2_DL_VAR_VALUE("d.mode", "rtorrent", "mode");
// 0 - Not hashing
// 1 - Normal hashing
// 2 - Download finished, hashing
// 3 - Rehashing
CMD2_DL_VAR_VALUE("d.hashing", "rtorrent", "hashing");
// 'tied_to_file' is the file the download is associated with, and
// can be changed by the user.
//
// 'loaded_file' is the file this instance of the torrent was loaded
// from, and should not be changed.
CMD2_DL_VAR_STRING_PUBLIC("d.tied_to_file", "rtorrent", "tied_to_file");
CMD2_DL_VAR_STRING("d.loaded_file", "rtorrent", "loaded_file");
// The "state_changed" variable is required to be a valid unix time
// value, it indicates the last time the torrent changed its state,
// resume/pause.
CMD2_DL_VAR_VALUE("d.state_changed", "rtorrent", "state_changed");
CMD2_DL_VAR_VALUE("d.state_counter", "rtorrent", "state_counter");
CMD2_DL_VAR_VALUE_PUBLIC("d.ignore_commands", "rtorrent", "ignore_commands");
CMD2_DL_TIMESTAMP("d.timestamp.started", "rtorrent", "timestamp.started");
CMD2_DL_TIMESTAMP("d.timestamp.finished", "rtorrent", "timestamp.finished");
CMD2_DL ("d.connection_current", tr1::bind(&torrent::option_as_string, torrent::OPTION_CONNECTION_TYPE, CMD2_ON_DL(connection_type)));
CMD2_DL_STRING("d.connection_current.set", tr1::bind(&apply_d_connection_type, tr1::placeholders::_1, tr1::placeholders::_2));
CMD2_DL_VAR_STRING("d.connection_leech", "rtorrent", "connection_leech");
CMD2_DL_VAR_STRING("d.connection_seed", "rtorrent", "connection_seed");
CMD2_DL ("d.up.choke_heuristics", tr1::bind(&torrent::option_as_string, torrent::OPTION_CHOKE_HEURISTICS, CMD2_ON_DL(upload_choke_heuristic)));
CMD2_DL_STRING("d.up.choke_heuristics.set", tr1::bind(&apply_d_choke_heuristics, tr1::placeholders::_1, tr1::placeholders::_2, false));
CMD2_DL ("d.down.choke_heuristics", tr1::bind(&torrent::option_as_string, torrent::OPTION_CHOKE_HEURISTICS, CMD2_ON_DL(download_choke_heuristic)));
CMD2_DL_STRING("d.down.choke_heuristics.set", tr1::bind(&apply_d_choke_heuristics, tr1::placeholders::_1, tr1::placeholders::_2, true));
CMD2_DL_VAR_STRING("d.up.choke_heuristics.leech", "rtorrent", "choke_heuristics.up.leech");
CMD2_DL_VAR_STRING("d.up.choke_heuristics.seed", "rtorrent", "choke_heuristics.up.seed");
CMD2_DL_VAR_STRING("d.down.choke_heuristics.leech", "rtorrent", "choke_heuristics.down.leech");
CMD2_DL_VAR_STRING("d.down.choke_heuristics.seed", "rtorrent", "choke_heuristics.down.seed");
CMD2_DL ("d.hashing_failed", tr1::bind(&core::Download::is_hash_failed, tr1::placeholders::_1));
CMD2_DL_VALUE_V ("d.hashing_failed.set", tr1::bind(&core::Download::set_hash_failed, tr1::placeholders::_1, tr1::placeholders::_2));
CMD2_DL ("d.views", tr1::bind(&download_get_variable, tr1::placeholders::_1, "rtorrent", "views"));
CMD2_DL ("d.views.has", tr1::bind(&d_list_has, tr1::placeholders::_1, tr1::placeholders::_2, "rtorrent", "views"));
CMD2_DL ("d.views.remove", tr1::bind(&d_list_remove, tr1::placeholders::_1, tr1::placeholders::_2, "rtorrent", "views"));
CMD2_DL ("d.views.push_back", tr1::bind(&d_list_push_back, tr1::placeholders::_1, tr1::placeholders::_2, "rtorrent", "views"));
CMD2_DL ("d.views.push_back_unique", tr1::bind(&d_list_push_back_unique, tr1::placeholders::_1, tr1::placeholders::_2, "rtorrent", "views"));
// This command really needs to be improved, so we have proper
// logging support.
CMD2_DL ("d.message", tr1::bind(&core::Download::message, tr1::placeholders::_1));
CMD2_DL_STRING_V("d.message.set", tr1::bind(&core::Download::set_message, tr1::placeholders::_1, tr1::placeholders::_2));
CMD2_DL ("d.max_file_size", CMD2_ON_FL(max_file_size));
CMD2_DL_VALUE_V ("d.max_file_size.set", tr1::bind(&torrent::FileList::set_max_file_size, CMD2_BIND_FL, tr1::placeholders::_2));
CMD2_DL ("d.peers_min", tr1::bind(&torrent::ConnectionList::min_size, CMD2_BIND_CL));
CMD2_DL_VALUE_V ("d.peers_min.set", tr1::bind(&torrent::ConnectionList::set_min_size, CMD2_BIND_CL, tr1::placeholders::_2));
CMD2_DL ("d.peers_max", tr1::bind(&torrent::ConnectionList::max_size, CMD2_BIND_CL));
CMD2_DL_VALUE_V ("d.peers_max.set", tr1::bind(&torrent::ConnectionList::set_max_size, CMD2_BIND_CL, tr1::placeholders::_2));
CMD2_DL ("d.uploads_max", tr1::bind(&torrent::Download::uploads_max, CMD2_BIND_DL));
CMD2_DL_VALUE_V ("d.uploads_max.set", tr1::bind(&torrent::Download::set_uploads_max, CMD2_BIND_DL, tr1::placeholders::_2));
CMD2_DL ("d.uploads_min", tr1::bind(&torrent::Download::uploads_min, CMD2_BIND_DL));
CMD2_DL_VALUE_V ("d.uploads_min.set", tr1::bind(&torrent::Download::set_uploads_min, CMD2_BIND_DL, tr1::placeholders::_2));
CMD2_DL ("d.downloads_max", tr1::bind(&torrent::Download::downloads_max, CMD2_BIND_DL));
CMD2_DL_VALUE_V ("d.downloads_max.set", tr1::bind(&torrent::Download::set_downloads_max, CMD2_BIND_DL, tr1::placeholders::_2));
CMD2_DL ("d.downloads_min", tr1::bind(&torrent::Download::downloads_min, CMD2_BIND_DL));
CMD2_DL_VALUE_V ("d.downloads_min.set", tr1::bind(&torrent::Download::set_downloads_min, CMD2_BIND_DL, tr1::placeholders::_2));
CMD2_DL ("d.peers_connected", tr1::bind(&torrent::ConnectionList::size, CMD2_BIND_CL));
CMD2_DL ("d.peers_not_connected", tr1::bind(&torrent::PeerList::available_list_size, CMD2_BIND_PL));
CMD2_DL ("d.peers_complete", CMD2_ON_DL(peers_complete));
CMD2_DL ("d.peers_accounted", CMD2_ON_DL(peers_accounted));
CMD2_DL_V ("d.disconnect.seeders", tr1::bind(&torrent::ConnectionList::erase_seeders, CMD2_BIND_CL));
CMD2_DL ("d.accepting_seeders", CMD2_ON_INFO(is_accepting_seeders));
CMD2_DL_V ("d.accepting_seeders.enable", tr1::bind(&torrent::DownloadInfo::public_set_flags, CMD2_BIND_INFO, torrent::DownloadInfo::flag_accepting_seeders));
CMD2_DL_V ("d.accepting_seeders.disable", tr1::bind(&torrent::DownloadInfo::public_unset_flags, CMD2_BIND_INFO, torrent::DownloadInfo::flag_accepting_seeders));
CMD2_DL ("d.throttle_name", tr1::bind(&download_get_variable, tr1::placeholders::_1, "rtorrent", "throttle_name"));
CMD2_DL_STRING_V("d.throttle_name.set", tr1::bind(&core::Download::set_throttle_name, tr1::placeholders::_1, tr1::placeholders::_2));
CMD2_DL ("d.bytes_done", CMD2_ON_DL(bytes_done));
CMD2_DL ("d.ratio", tr1::bind(&retrieve_d_ratio, tr1::placeholders::_1));
CMD2_DL ("d.chunks_hashed", CMD2_ON_DL(chunks_hashed));
CMD2_DL ("d.free_diskspace", CMD2_ON_FL(free_diskspace));
CMD2_DL ("d.size_files", CMD2_ON_FL(size_files));
CMD2_DL ("d.size_bytes", CMD2_ON_FL(size_bytes));
CMD2_DL ("d.size_chunks", CMD2_ON_FL(size_chunks));
CMD2_DL ("d.chunk_size", CMD2_ON_FL(chunk_size));
CMD2_DL ("d.size_pex", CMD2_ON_DL(size_pex));
CMD2_DL ("d.max_size_pex", CMD2_ON_DL(max_size_pex));
CMD2_DL ("d.chunks_seen", tr1::bind(&d_chunks_seen, tr1::placeholders::_1));
CMD2_DL ("d.completed_bytes", CMD2_ON_FL(completed_bytes));
CMD2_DL ("d.completed_chunks", CMD2_ON_FL(completed_chunks));
CMD2_DL ("d.left_bytes", CMD2_ON_FL(left_bytes));
CMD2_DL ("d.wanted_chunks", CMD2_ON_DATA(wanted_chunks));
CMD2_DL_V ("d.tracker_announce", tr1::bind(&torrent::Download::manual_request, CMD2_BIND_DL, false));
CMD2_DL ("d.tracker_numwant", tr1::bind(&torrent::TrackerList::numwant, CMD2_BIND_TL));
CMD2_DL_VALUE_V ("d.tracker_numwant.set", tr1::bind(&torrent::TrackerList::set_numwant, CMD2_BIND_TL, tr1::placeholders::_2));
// TODO: Deprecate 'd.tracker_focus'.
CMD2_DL ("d.tracker_focus", tr1::bind(&core::Download::tracker_list_size, tr1::placeholders::_1));
CMD2_DL ("d.tracker_size", tr1::bind(&core::Download::tracker_list_size, tr1::placeholders::_1));
CMD2_DL_LIST ("d.tracker.insert", tr1::bind(&download_tracker_insert, tr1::placeholders::_1, tr1::placeholders::_2));
CMD2_DL_VALUE_V ("d.tracker.send_scrape", tr1::bind(&torrent::TrackerController::scrape_request, CMD2_BIND_TC, tr1::placeholders::_2));
CMD2_DL ("d.directory", CMD2_ON_FL(root_dir));
CMD2_DL_STRING_V("d.directory.set", tr1::bind(&apply_d_directory, tr1::placeholders::_1, tr1::placeholders::_2));
CMD2_DL ("d.directory_base", CMD2_ON_FL(root_dir));
CMD2_DL_STRING_V("d.directory_base.set", tr1::bind(&core::Download::set_root_directory, tr1::placeholders::_1, tr1::placeholders::_2));
CMD2_DL ("d.priority", tr1::bind(&core::Download::priority, tr1::placeholders::_1));
CMD2_DL ("d.priority_str", tr1::bind(&retrieve_d_priority_str, tr1::placeholders::_1));
CMD2_DL_VALUE_V ("d.priority.set", tr1::bind(&core::Download::set_priority, tr1::placeholders::_1, tr1::placeholders::_2));
// CMD2_DL ("d.group", tr1::bind(&torrent::resource_manager_entry::group,
// tr1::bind(&torrent::ResourceManager::entry_at, torrent::resource_manager(),
// tr1::bind(&core::Download::main, tr1::placeholders::_1))));
// CMD2_DL_V ("d.group.set", tr1::bind(&torrent::ResourceManager::set_group,
// torrent::resource_manager(),
// tr1::bind(&torrent::ResourceManager::find_throw, torrent::resource_manager(),
// tr1::bind(&core::Download::main, tr1::placeholders::_1)),
// CG_GROUP_INDEX()));
CMD2_DL ("d.group", tr1::bind(&cg_d_group, tr1::placeholders::_1));
CMD2_DL ("d.group.name", tr1::bind(&cg_d_group, tr1::placeholders::_1));
CMD2_DL_V ("d.group.set", tr1::bind(&cg_d_group_set, tr1::placeholders::_1, tr1::placeholders::_2));
CMD2_DL_LIST ("f.multicall", tr1::bind(&f_multicall, tr1::placeholders::_1, tr1::placeholders::_2));
CMD2_DL_LIST ("p.multicall", tr1::bind(&p_multicall, tr1::placeholders::_1, tr1::placeholders::_2));
CMD2_DL_LIST ("t.multicall", tr1::bind(&t_multicall, tr1::placeholders::_1, tr1::placeholders::_2));
CMD2_ANY_LIST ("p.call_target", tr1::bind(&p_call_target, tr1::placeholders::_2));
}
-471
View File
@@ -1,471 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <algorithm>
#include <torrent/utils/log.h>
#include "globals.h"
#include "control.h"
#include "command_helpers.h"
#include "rpc/parse.h"
std::string
system_method_generate_command(torrent::Object::list_const_iterator first, torrent::Object::list_const_iterator last) {
std::string command;
while (first != last) {
if (!command.empty())
command += " ;";
command += (first++)->as_string();
}
return command;
}
void
system_method_generate_command2(torrent::Object* object, torrent::Object::list_const_iterator first, torrent::Object::list_const_iterator last) {
if (first == last) {
// TODO: Use empty object.
*object = "";
return;
}
if (first->is_string()) {
std::string command;
while (first != last) {
if (!command.empty())
command += " ;";
command += (first++)->as_string();
}
*object = command;
return;
}
if (first + 1 == last) {
if (!first->is_dict_key())
throw torrent::input_error("New command of wrong type.");
*object = *first;
uint32_t flags = object->flags() & torrent::Object::mask_function;
object->unset_flags(torrent::Object::mask_function);
object->set_flags((flags >> 1) & torrent::Object::mask_function);
} else {
*object = torrent::Object::create_list();
while (first != last) {
if (!first->is_dict_key())
throw torrent::input_error("New command of wrong type.");
object->as_list().push_back(*first++);
uint32_t flags = object->as_list().back().flags() & torrent::Object::mask_function;
object->as_list().back().unset_flags(torrent::Object::mask_function);
object->as_list().back().set_flags((flags >> 1) & torrent::Object::mask_function);
}
}
}
// torrent::Object
// system_method_insert_function(const torrent::Object::list_type& args, int flags) {
// }
torrent::Object
system_method_insert_object(const torrent::Object::list_type& args, int flags) {
if (args.empty())
throw torrent::input_error("Invalid argument count.");
torrent::Object::list_const_iterator itrArgs = args.begin();
const std::string& rawKey = (itrArgs++)->as_string();
if (rawKey.empty() ||
control->object_storage()->find_local(torrent::raw_string::from_string(rawKey)) != control->object_storage()->end(0) ||
rpc::commands.has(rawKey) || rpc::commands.has(rawKey + ".set"))
throw torrent::input_error("Invalid key.");
torrent::Object value;
switch (flags & rpc::object_storage::mask_type) {
case rpc::object_storage::flag_bool_type:
case rpc::object_storage::flag_value_type:
value = itrArgs != args.end() ? rpc::convert_to_value(*itrArgs) : int64_t();
break;
case rpc::object_storage::flag_string_type:
value = itrArgs != args.end() ? rpc::convert_to_string(*itrArgs) : "";
break;
case rpc::object_storage::flag_function_type:
system_method_generate_command2(&value, itrArgs, args.end());
break;
case rpc::object_storage::flag_multi_type:
break;
default:
throw torrent::input_error("Invalid type.");
}
int cmd_flags = 0;
if (!(flags & rpc::object_storage::flag_static))
cmd_flags |= rpc::CommandMap::flag_modifiable;
if (!(flags & rpc::object_storage::flag_private))
cmd_flags |= rpc::CommandMap::flag_public_xmlrpc;
control->object_storage()->insert_str(rawKey, value, flags);
if ((flags & rpc::object_storage::mask_type) == rpc::object_storage::flag_function_type ||
(flags & rpc::object_storage::mask_type) == rpc::object_storage::flag_multi_type) {
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call<rpc::target_type> >::type>
(create_new_key(rawKey),
tr1::bind(&rpc::object_storage::call_function_str, control->object_storage(),
rawKey, tr1::placeholders::_1, tr1::placeholders::_2),
&rpc::command_base_call<rpc::target_type>,
cmd_flags, NULL, NULL);
} else {
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call<rpc::target_type> >::type>
(create_new_key(rawKey),
tr1::bind(&rpc::object_storage::get_str, control->object_storage(), rawKey),
&rpc::command_base_call<rpc::target_type>,
cmd_flags, NULL, NULL);
}
// Not the right argument.
// if (flags & rpc::object_storage::flag_rlookup) {
// rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_string<rpc::target_type> >::type>
// (create_new_key<9>(rawKey, ".rlookup"),
// tr1::bind(&rpc::object_storage::rlookup_obj_list, control->object_storage(), rawKey),
// &rpc::command_base_call_string<rpc::target_type>,
// cmd_flags, NULL, NULL);
// }
// TODO: Next... Make test class for this.
// // Ehm... no proper handling if these throw.
if (!(flags & rpc::object_storage::flag_constant)) {
switch (flags & rpc::object_storage::mask_type) {
case rpc::object_storage::flag_bool_type:
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_value<rpc::target_type> >::type>
(create_new_key<5>(rawKey, ".set"),
tr1::bind(&rpc::object_storage::set_str_bool, control->object_storage(), rawKey, tr1::placeholders::_2),
&rpc::command_base_call_value<rpc::target_type>,
cmd_flags, NULL, NULL);
break;
case rpc::object_storage::flag_value_type:
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_value<rpc::target_type> >::type>
(create_new_key<5>(rawKey, ".set"),
tr1::bind(&rpc::object_storage::set_str_value, control->object_storage(), rawKey, tr1::placeholders::_2),
&rpc::command_base_call_value<rpc::target_type>,
cmd_flags, NULL, NULL);
break;
case rpc::object_storage::flag_string_type:
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::command_base_call_string<rpc::target_type> >::type>
(create_new_key<5>(rawKey, ".set"),
tr1::bind(&rpc::object_storage::set_str_string, control->object_storage(), rawKey, tr1::placeholders::_2),
&rpc::command_base_call_string<rpc::target_type>,
cmd_flags, NULL, NULL);
break;
case rpc::object_storage::flag_function_type:
case rpc::object_storage::flag_multi_type:
default: break;
}
}
return torrent::Object();
}
// method.insert <generic> {name, "simple|private|const", ...}
// method.insert <generic> {name, "multi|private|const"}
// method.insert <generic> {name, "value|private|const"}
// method.insert <generic> {name, "value|private|const", value}
// method.insert <generic> {name, "bool|private|const"}
// method.insert <generic> {name, "bool|private|const", bool}
// method.insert <generic> {name, "string|private|const"}
// method.insert <generic> {name, "string|private|const", string}
//
// Add a new user-defined method called 'name' and any number of
// lines.
//
// TODO: Make a static version of this that doesn't need to be called
// as a command, and which takes advantage of static const char
// strings, etc.
torrent::Object
system_method_insert(const torrent::Object::list_type& args) {
if (args.empty() || ++args.begin() == args.end())
throw torrent::input_error("Invalid argument count.");
torrent::Object::list_const_iterator itrArgs = args.begin();
const std::string& rawKey = (itrArgs++)->as_string();
if (rawKey.empty() || rpc::commands.has(rawKey))
throw torrent::input_error("Invalid key.");
int flags = rpc::CommandMap::flag_delete_key | rpc::CommandMap::flag_modifiable | rpc::CommandMap::flag_public_xmlrpc;
const std::string& options = itrArgs->as_string();
if (options.find("private") != std::string::npos)
flags &= ~rpc::CommandMap::flag_public_xmlrpc;
if (options.find("const") != std::string::npos)
flags &= ~rpc::CommandMap::flag_modifiable;
if (options.find("multi") != std::string::npos) {
torrent::Object::list_type new_args;
new_args.push_back(rawKey);
new_args.push_back(system_method_generate_command(++itrArgs, args.end()));
int new_flags = rpc::object_storage::flag_multi_type;
if (options.find("static") != std::string::npos)
new_flags |= rpc::object_storage::flag_static;
if (options.find("private") != std::string::npos)
new_flags |= rpc::object_storage::flag_private;
if (options.find("const") != std::string::npos)
new_flags |= rpc::object_storage::flag_constant;
if (options.find("rlookup") != std::string::npos)
new_flags |= rpc::object_storage::flag_rlookup;
return system_method_insert_object(new_args, new_flags);
} else if (options.find("simple") != std::string::npos) {
torrent::Object::list_type new_args;
new_args.push_back(rawKey);
new_args.push_back(system_method_generate_command(++itrArgs, args.end()));
int new_flags = rpc::object_storage::flag_function_type;
if (options.find("static") != std::string::npos)
new_flags |= rpc::object_storage::flag_static;
if (options.find("private") != std::string::npos)
new_flags |= rpc::object_storage::flag_private;
if (options.find("const") != std::string::npos)
new_flags |= rpc::object_storage::flag_constant;
return system_method_insert_object(new_args, new_flags);
} else if (options.find("value") != std::string::npos ||
options.find("bool") != std::string::npos ||
options.find("string") != std::string::npos ||
options.find("list") != std::string::npos ||
options.find("simple") != std::string::npos) {
torrent::Object::list_type new_args;
new_args.push_back(rawKey);
if (++itrArgs != args.end())
new_args.insert(new_args.end(), itrArgs, args.end());
int new_flags;
if (options.find("value") != std::string::npos)
new_flags = rpc::object_storage::flag_value_type;
else if (options.find("bool") != std::string::npos)
new_flags = rpc::object_storage::flag_bool_type;
else if (options.find("string") != std::string::npos)
new_flags = rpc::object_storage::flag_string_type;
else if (options.find("list") != std::string::npos)
new_flags = rpc::object_storage::flag_list_type;
else if (options.find("simple") != std::string::npos)
new_flags = rpc::object_storage::flag_function_type;
else
throw torrent::input_error("No support for 'list' variable type.");
if (options.find("static") != std::string::npos)
new_flags |= rpc::object_storage::flag_static;
if (options.find("private") != std::string::npos)
new_flags |= rpc::object_storage::flag_private;
if (options.find("const") != std::string::npos)
new_flags |= rpc::object_storage::flag_constant;
return system_method_insert_object(new_args, new_flags);
} else {
// THROW.
}
return torrent::Object();
}
// method.erase <> {name}
//
// Erase a modifiable method called 'name. Trying to remove methods
// that aren't modifiable, e.g. defined by rtorrent or set to
// read-only by the user, will result in an error.
torrent::Object
system_method_erase(const torrent::Object::string_type& args) {
rpc::CommandMap::iterator itr = rpc::commands.find(args.c_str());
if (itr == rpc::commands.end())
return torrent::Object();
if (!rpc::commands.is_modifiable(itr))
throw torrent::input_error("Command not modifiable.");
rpc::commands.erase(itr);
return torrent::Object();
}
torrent::Object
system_method_redirect(const torrent::Object::list_type& args) {
if (args.size() != 2)
throw torrent::input_error("Invalid argument count.");
std::string new_key = torrent::object_create_string(args.front());
std::string dest_key = torrent::object_create_string(args.back());
rpc::commands.create_redirect(create_new_key(new_key), create_new_key(dest_key),
rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_delete_key | rpc::CommandMap::flag_modifiable);
return torrent::Object();
}
torrent::Object
system_method_set_function(const torrent::Object::list_type& args) {
if (args.empty())
throw torrent::input_error("Invalid argument count.");
rpc::object_storage::local_iterator itr =
control->object_storage()->find_local(torrent::raw_string::from_string(args.front().as_string()));
if (itr == control->object_storage()->end(0) || itr->second.flags & rpc::object_storage::flag_constant)
throw torrent::input_error("Command is not modifiable.");
return control->object_storage()->set_str_function(args.front().as_string(),
system_method_generate_command(++args.begin(), args.end()));
}
torrent::Object
system_method_has_key(const torrent::Object::list_type& args) {
if (args.empty() || ++args.begin() == args.end())
throw torrent::input_error("Invalid argument count.");
torrent::Object::list_const_iterator itrArgs = args.begin();
const std::string& key = (itrArgs++)->as_string();
const std::string& cmd_key = (itrArgs++)->as_string();
return control->object_storage()->has_str_multi_key(key, cmd_key);
}
torrent::Object
system_method_set_key(const torrent::Object::list_type& args) {
if (args.empty() || ++args.begin() == args.end())
throw torrent::input_error("Invalid argument count.");
torrent::Object::list_const_iterator itrArgs = args.begin();
const std::string& key = (itrArgs++)->as_string();
const std::string& cmd_key = (itrArgs++)->as_string();
if (itrArgs == args.end()) {
control->object_storage()->erase_str_multi_key(key, cmd_key);
return torrent::Object();
}
if (itrArgs->is_dict_key() || itrArgs->is_list())
control->object_storage()->set_str_multi_key_obj(key.c_str(), cmd_key, *itrArgs);
else
control->object_storage()->set_str_multi_key(key, cmd_key, system_method_generate_command(itrArgs, args.end()));
return torrent::Object();
}
torrent::Object
system_method_list_keys(const torrent::Object::string_type& args) {
const torrent::Object::map_type& multi_cmd = control->object_storage()->get_str(args).as_map();
torrent::Object rawResult = torrent::Object::create_list();
torrent::Object::list_type& result = rawResult.as_list();
for (torrent::Object::map_const_iterator itr = multi_cmd.begin(), last = multi_cmd.end(); itr != last; itr++)
result.push_back(itr->first);
return rawResult;
}
torrent::Object
cmd_catch(rpc::target_type target, const torrent::Object& args) {
try {
return rpc::call_object(args, target);
} catch (torrent::input_error& e) {
lt_log_print(torrent::LOG_WARN, "Caught exception: '%s'.", e.what());
return torrent::Object();
}
}
#define CMD2_METHOD_INSERT(key, flags) \
CMD2_ANY_LIST(key, tr1::bind(&system_method_insert_object, tr1::placeholders::_2, flags));
void
initialize_command_dynamic() {
CMD2_VAR_BOOL ("method.use_deprecated", true);
CMD2_VAR_VALUE ("method.use_intermediate", 1);
CMD2_ANY_LIST ("method.insert", tr1::bind(&system_method_insert, tr1::placeholders::_2));
CMD2_ANY_LIST ("method.insert.value", tr1::bind(&system_method_insert_object, tr1::placeholders::_2, rpc::object_storage::flag_value_type));
CMD2_METHOD_INSERT("method.insert.simple", rpc::object_storage::flag_function_type);
CMD2_METHOD_INSERT("method.insert.c_simple", rpc::object_storage::flag_constant | rpc::object_storage::flag_function_type);
CMD2_METHOD_INSERT("method.insert.s_c_simple", rpc::object_storage::flag_static |
rpc::object_storage::flag_constant |rpc::object_storage::flag_function_type);
CMD2_ANY_STRING ("method.erase", tr1::bind(&system_method_erase, tr1::placeholders::_2));
CMD2_ANY_LIST ("method.redirect", tr1::bind(&system_method_redirect, tr1::placeholders::_2));
CMD2_ANY_STRING ("method.get", tr1::bind(&rpc::object_storage::get_str, control->object_storage(),
tr1::placeholders::_2));
CMD2_ANY_LIST ("method.set", tr1::bind(&system_method_set_function, tr1::placeholders::_2));
CMD2_ANY_STRING ("method.const", tr1::bind(&rpc::object_storage::has_flag_str, control->object_storage(),
tr1::placeholders::_2, rpc::object_storage::flag_constant));
CMD2_ANY_STRING_V("method.const.enable", tr1::bind(&rpc::object_storage::enable_flag_str, control->object_storage(),
tr1::placeholders::_2, rpc::object_storage::flag_constant));
CMD2_ANY_LIST ("method.has_key", tr1::bind(&system_method_has_key, tr1::placeholders::_2));
CMD2_ANY_LIST ("method.set_key", tr1::bind(&system_method_set_key, tr1::placeholders::_2));
CMD2_ANY_STRING ("method.list_keys", tr1::bind(&system_method_list_keys, tr1::placeholders::_2));
CMD2_ANY_STRING ("method.rlookup", tr1::bind(&rpc::object_storage::rlookup_obj_list, control->object_storage(), tr1::placeholders::_2));
CMD2_ANY_STRING_V("method.rlookup.clear", tr1::bind(&rpc::object_storage::rlookup_clear, control->object_storage(), tr1::placeholders::_2));
CMD2_ANY ("catch", tr1::bind(&cmd_catch, tr1::placeholders::_1, tr1::placeholders::_2));
}
-337
View File
@@ -1,337 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <functional>
#include <cstdio>
#include <rak/file_stat.h>
#include <rak/path.h>
#include <rak/string_manip.h>
#include <torrent/rate.h>
#include <torrent/hash_string.h>
#include <torrent/utils/log.h>
#include "core/download.h"
#include "core/download_list.h"
#include "core/manager.h"
#include "core/view_manager.h"
#include "rpc/command_scheduler.h"
#include "rpc/parse.h"
#include "rpc/parse_commands.h"
#include "globals.h"
#include "control.h"
#include "command_helpers.h"
#include "thread_worker.h"
torrent::Object
apply_on_ratio(const torrent::Object& rawArgs) {
const std::string& groupName = rawArgs.as_string();
char buffer[32 + groupName.size()];
sprintf(buffer, "group2.%s.view", groupName.c_str());
core::ViewManager::iterator viewItr = control->view_manager()->find(rpc::commands.call(buffer, rpc::make_target()).as_string());
if (viewItr == control->view_manager()->end())
throw torrent::input_error("Could not find view.");
char* bufferStart = buffer + sprintf(buffer, "group2.%s.ratio.", groupName.c_str());
// first argument: minimum ratio to reach
// second argument: minimum upload amount to reach [optional]
// third argument: maximum ratio to reach [optional]
std::strcpy(bufferStart, "min");
int64_t minRatio = rpc::commands.call(buffer, rpc::make_target()).as_value();
std::strcpy(bufferStart, "max");
int64_t maxRatio = rpc::commands.call(buffer, rpc::make_target()).as_value();
std::strcpy(bufferStart, "upload");
int64_t minUpload = rpc::commands.call(buffer, rpc::make_target()).as_value();
std::vector<core::Download*> downloads;
for (core::View::iterator itr = (*viewItr)->begin_visible(), last = (*viewItr)->end_visible(); itr != last; itr++) {
if (!(*itr)->is_seeding() || rpc::call_command_value("d.ignore_commands", rpc::make_target(*itr)) != 0)
continue;
// rpc::parse_command_single(rpc::make_target(*itr), "print={Checked ratio of download.}");
int64_t totalDone = (*itr)->download()->bytes_done();
int64_t totalUpload = (*itr)->info()->up_rate()->total();
if (!(totalUpload >= minUpload && totalUpload * 100 >= totalDone * minRatio) &&
!(maxRatio > 0 && totalUpload * 100 > totalDone * maxRatio))
continue;
downloads.push_back(*itr);
}
sprintf(buffer, "group.%s.ratio.command", groupName.c_str());
for (std::vector<core::Download*>::iterator itr = downloads.begin(), last = downloads.end(); itr != last; itr++) {
// rpc::commands.call("print", rpc::make_target(*itr), "Calling ratio command.");
rpc::commands.call_catch(buffer, rpc::make_target(*itr), torrent::Object(), "Ratio reached, but command failed: ");
}
return torrent::Object();
}
torrent::Object
apply_start_tied() {
for (core::DownloadList::iterator itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ++itr) {
if (rpc::call_command_value("d.state", rpc::make_target(*itr)) == 1)
continue;
rak::file_stat fs;
const std::string& tiedToFile = rpc::call_command_string("d.tied_to_file", rpc::make_target(*itr));
if (!tiedToFile.empty() && fs.update(rak::path_expand(tiedToFile)))
rpc::parse_command_single(rpc::make_target(*itr), "d.try_start=");
}
return torrent::Object();
}
torrent::Object
apply_stop_untied() {
for (core::DownloadList::iterator itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ++itr) {
if (rpc::call_command_value("d.state", rpc::make_target(*itr)) == 0)
continue;
rak::file_stat fs;
const std::string& tiedToFile = rpc::call_command_string("d.tied_to_file", rpc::make_target(*itr));
if (!tiedToFile.empty() && !fs.update(rak::path_expand(tiedToFile)))
rpc::parse_command_single(rpc::make_target(*itr), "d.try_stop=");
}
return torrent::Object();
}
torrent::Object
apply_close_untied() {
for (core::DownloadList::iterator itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ++itr) {
rak::file_stat fs;
const std::string& tiedToFile = rpc::call_command_string("d.tied_to_file", rpc::make_target(*itr));
if (rpc::call_command_value("d.ignore_commands", rpc::make_target(*itr)) == 0 && !tiedToFile.empty() && !fs.update(rak::path_expand(tiedToFile)))
rpc::parse_command_single(rpc::make_target(*itr), "d.try_close=");
}
return torrent::Object();
}
torrent::Object
apply_remove_untied() {
for (core::DownloadList::iterator itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ) {
rak::file_stat fs;
const std::string& tiedToFile = rpc::call_command_string("d.tied_to_file", rpc::make_target(*itr));
if (!tiedToFile.empty() && !fs.update(rak::path_expand(tiedToFile))) {
// Need to clear tied_to_file so it doesn't try to delete it.
rpc::call_command("d.tied_to_file.set", std::string(), rpc::make_target(*itr));
itr = control->core()->download_list()->erase(itr);
} else {
++itr;
}
}
return torrent::Object();
}
torrent::Object
apply_schedule(const torrent::Object::list_type& args) {
if (args.size() != 4)
throw torrent::input_error("Wrong number of arguments.");
torrent::Object::list_const_iterator itr = args.begin();
const std::string& arg1 = (itr++)->as_string();
const std::string& arg2 = (itr++)->as_string();
const std::string& arg3 = (itr++)->as_string();
control->command_scheduler()->parse(arg1, arg2, arg3, *itr);
return torrent::Object();
}
torrent::Object
apply_load(const torrent::Object::list_type& args, int flags) {
torrent::Object::list_const_iterator argsItr = args.begin();
if (argsItr == args.end())
throw torrent::input_error("Too few arguments.");
const std::string& filename = argsItr->as_string();
core::Manager::command_list_type commands;
while (++argsItr != args.end())
commands.push_back(argsItr->as_string());
control->core()->try_create_download_expand(filename, flags, commands);
return torrent::Object();
}
void apply_import(const std::string& path) { if (!rpc::parse_command_file(path)) throw torrent::input_error("Could not open option file: " + path); }
void apply_try_import(const std::string& path) { if (!rpc::parse_command_file(path)) control->core()->push_log_std("Could not read resource file: " + path); }
torrent::Object
apply_close_low_diskspace(int64_t arg) {
core::DownloadList* downloadList = control->core()->download_list();
bool closed = false;
core::Manager::DListItr itr = downloadList->begin();
while ((itr = std::find_if(itr, downloadList->end(), std::mem_fun(&core::Download::is_downloading)))
!= downloadList->end()) {
if ((*itr)->file_list()->free_diskspace() < (uint64_t)arg) {
downloadList->close(*itr);
(*itr)->set_hash_failed(true);
(*itr)->set_message(std::string("Low diskspace."));
closed = true;
}
++itr;
}
if (closed)
lt_log_print(torrent::LOG_TORRENT_ERROR, "Closed torrents due to low diskspace.");
return torrent::Object();
}
torrent::Object
apply_download_list(const torrent::Object::list_type& args) {
torrent::Object::list_const_iterator argsItr = args.begin();
core::ViewManager* viewManager = control->view_manager();
core::ViewManager::iterator viewItr;
if (argsItr != args.end() && !argsItr->as_string().empty())
viewItr = viewManager->find((argsItr++)->as_string());
else
viewItr = viewManager->find("default");
if (viewItr == viewManager->end())
throw torrent::input_error("Could not find view.");
torrent::Object result = torrent::Object::create_list();
torrent::Object::list_type& resultList = result.as_list();
for (core::View::const_iterator itr = (*viewItr)->begin_visible(), last = (*viewItr)->end_visible(); itr != last; itr++) {
const torrent::HashString* hashString = &(*itr)->info()->hash();
resultList.push_back(rak::transform_hex(hashString->begin(), hashString->end()));
}
return result;
}
torrent::Object
d_multicall(const torrent::Object::list_type& args) {
if (args.empty())
throw torrent::input_error("Too few arguments.");
core::ViewManager* viewManager = control->view_manager();
core::ViewManager::iterator viewItr;
if (!args.front().as_string().empty())
viewItr = viewManager->find(args.front().as_string());
else
viewItr = viewManager->find("default");
if (viewItr == viewManager->end())
throw torrent::input_error("Could not find view.");
// Add some pre-parsing of the commands, so we don't spend time
// parsing and searching command map for every single call.
unsigned int dlist_size = (*viewItr)->size_visible();
core::Download* dlist[dlist_size];
std::copy((*viewItr)->begin_visible(), (*viewItr)->end_visible(), dlist);
torrent::Object resultRaw = torrent::Object::create_list();
torrent::Object::list_type& result = resultRaw.as_list();
for (core::Download** vItr = dlist; vItr != dlist + dlist_size; vItr++) {
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
for (torrent::Object::list_const_iterator cItr = ++args.begin(); cItr != args.end(); cItr++) {
const std::string& cmd = cItr->as_string();
row.push_back(rpc::parse_command(rpc::make_target(*vItr), cmd.c_str(), cmd.c_str() + cmd.size()).first);
}
}
return resultRaw;
}
void
initialize_command_events() {
CMD2_ANY_STRING ("on_ratio", tr1::bind(&apply_on_ratio, tr1::placeholders::_2));
CMD2_ANY ("start_tied", tr1::bind(&apply_start_tied));
CMD2_ANY ("stop_untied", tr1::bind(&apply_stop_untied));
CMD2_ANY ("close_untied", tr1::bind(&apply_close_untied));
CMD2_ANY ("remove_untied", tr1::bind(&apply_remove_untied));
CMD2_ANY_LIST ("schedule2", tr1::bind(&apply_schedule, tr1::placeholders::_2));
CMD2_ANY_STRING_V("schedule_remove2", tr1::bind(&rpc::CommandScheduler::erase_str, control->command_scheduler(), tr1::placeholders::_2));
CMD2_ANY_STRING_V("import", tr1::bind(&apply_import, tr1::placeholders::_2));
CMD2_ANY_STRING_V("try_import", tr1::bind(&apply_try_import, tr1::placeholders::_2));
CMD2_ANY_LIST ("load.normal", tr1::bind(&apply_load, tr1::placeholders::_2, core::Manager::create_quiet | core::Manager::create_tied));
CMD2_ANY_LIST ("load.verbose", tr1::bind(&apply_load, tr1::placeholders::_2, core::Manager::create_tied));
CMD2_ANY_LIST ("load.start", tr1::bind(&apply_load, tr1::placeholders::_2,
core::Manager::create_quiet | core::Manager::create_tied | core::Manager::create_start));
CMD2_ANY_LIST ("load.start_verbose", tr1::bind(&apply_load, tr1::placeholders::_2, core::Manager::create_tied | core::Manager::create_start));
CMD2_ANY_LIST ("load.raw", tr1::bind(&apply_load, tr1::placeholders::_2, core::Manager::create_quiet | core::Manager::create_raw_data));
CMD2_ANY_LIST ("load.raw_verbose", tr1::bind(&apply_load, tr1::placeholders::_2, core::Manager::create_raw_data));
CMD2_ANY_LIST ("load.raw_start", tr1::bind(&apply_load, tr1::placeholders::_2,
core::Manager::create_quiet | core::Manager::create_start | core::Manager::create_raw_data));
CMD2_ANY_VALUE ("close_low_diskspace", tr1::bind(&apply_close_low_diskspace, tr1::placeholders::_2));
CMD2_ANY_LIST ("download_list", tr1::bind(&apply_download_list, tr1::placeholders::_2));
CMD2_ANY_LIST ("d.multicall2", tr1::bind(&d_multicall, tr1::placeholders::_2));
}
-144
View File
@@ -1,144 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <rak/error_number.h>
#include <rak/path.h>
#include <torrent/data/file.h>
#include <torrent/data/file_list.h>
#include <torrent/data/file_list_iterator.h>
#include "core/manager.h"
#include "globals.h"
#include "control.h"
#include "command_helpers.h"
void
apply_f_set_priority(torrent::File* file, uint32_t value) {
if (value > torrent::PRIORITY_HIGH)
throw torrent::input_error("Invalid value.");
file->set_priority((torrent::priority_t)value);
}
// TODO: Redundant.
torrent::Object
apply_f_path(torrent::File* file) {
if (file->path()->empty())
return std::string();
torrent::Object resultRaw(*file->path()->begin());
torrent::Object::string_type& result = resultRaw.as_string();
for (torrent::Path::const_iterator itr = ++file->path()->begin(), last = file->path()->end(); itr != last; itr++)
result += '/' + *itr;
return resultRaw;
}
torrent::Object
apply_f_path_components(torrent::File* file) {
torrent::Object resultRaw = torrent::Object::create_list();
torrent::Object::list_type& result = resultRaw.as_list();
for (torrent::Path::const_iterator itr = file->path()->begin(), last = file->path()->end(); itr != last; itr++)
result.push_back(*itr);
return resultRaw;
}
torrent::Object
apply_f_path_depth(torrent::File* file) {
return (int64_t)file->path()->size();
}
torrent::Object
apply_fi_filename_last(torrent::FileListIterator* itr) {
if (itr->file()->path()->empty())
return "EMPTY";
if (itr->depth() >= itr->file()->path()->size())
return "ERROR";
return itr->file()->path()->at(itr->depth());
}
void
initialize_command_file() {
CMD2_FILE("f.is_created", tr1::bind(&torrent::File::is_created, tr1::placeholders::_1));
CMD2_FILE("f.is_open", tr1::bind(&torrent::File::is_open, tr1::placeholders::_1));
CMD2_FILE("f.is_create_queued", tr1::bind(&torrent::File::is_create_queued, tr1::placeholders::_1));
CMD2_FILE("f.is_resize_queued", tr1::bind(&torrent::File::is_resize_queued, tr1::placeholders::_1));
CMD2_FILE_VALUE_V("f.set_create_queued", tr1::bind(&torrent::File::set_flags, tr1::placeholders::_1, torrent::File::flag_create_queued));
CMD2_FILE_VALUE_V("f.set_resize_queued", tr1::bind(&torrent::File::set_flags, tr1::placeholders::_1, torrent::File::flag_resize_queued));
CMD2_FILE_VALUE_V("f.unset_create_queued", tr1::bind(&torrent::File::unset_flags, tr1::placeholders::_1, torrent::File::flag_create_queued));
CMD2_FILE_VALUE_V("f.unset_resize_queued", tr1::bind(&torrent::File::unset_flags, tr1::placeholders::_1, torrent::File::flag_resize_queued));
CMD2_FILE ("f.prioritize_first", tr1::bind(&torrent::File::has_flags, tr1::placeholders::_1, torrent::File::flag_prioritize_first));
CMD2_FILE_V("f.prioritize_first.enable", tr1::bind(&torrent::File::set_flags, tr1::placeholders::_1, torrent::File::flag_prioritize_first));
CMD2_FILE_V("f.prioritize_first.disable", tr1::bind(&torrent::File::unset_flags, tr1::placeholders::_1, torrent::File::flag_prioritize_first));
CMD2_FILE ("f.prioritize_last", tr1::bind(&torrent::File::has_flags, tr1::placeholders::_1, torrent::File::flag_prioritize_last));
CMD2_FILE_V("f.prioritize_last.enable", tr1::bind(&torrent::File::set_flags, tr1::placeholders::_1, torrent::File::flag_prioritize_last));
CMD2_FILE_V("f.prioritize_last.disable", tr1::bind(&torrent::File::unset_flags, tr1::placeholders::_1, torrent::File::flag_prioritize_last));
CMD2_FILE("f.size_bytes", tr1::bind(&torrent::File::size_bytes, tr1::placeholders::_1));
CMD2_FILE("f.size_chunks", tr1::bind(&torrent::File::size_chunks, tr1::placeholders::_1));
CMD2_FILE("f.completed_chunks", tr1::bind(&torrent::File::completed_chunks, tr1::placeholders::_1));
CMD2_FILE("f.offset", tr1::bind(&torrent::File::offset, tr1::placeholders::_1));
CMD2_FILE("f.range_first", tr1::bind(&torrent::File::range_first, tr1::placeholders::_1));
CMD2_FILE("f.range_second", tr1::bind(&torrent::File::range_second, tr1::placeholders::_1));
CMD2_FILE("f.priority", tr1::bind(&torrent::File::priority, tr1::placeholders::_1));
CMD2_FILE_VALUE_V("f.priority.set", tr1::bind(&apply_f_set_priority, tr1::placeholders::_1, tr1::placeholders::_2));
CMD2_FILE("f.path", tr1::bind(&apply_f_path, tr1::placeholders::_1));
CMD2_FILE("f.path_components", tr1::bind(&apply_f_path_components, tr1::placeholders::_1));
CMD2_FILE("f.path_depth", tr1::bind(&apply_f_path_depth, tr1::placeholders::_1));
CMD2_FILE("f.frozen_path", tr1::bind(&torrent::File::frozen_path, tr1::placeholders::_1));
CMD2_FILE("f.match_depth_prev", tr1::bind(&torrent::File::match_depth_prev, tr1::placeholders::_1));
CMD2_FILE("f.match_depth_next", tr1::bind(&torrent::File::match_depth_next, tr1::placeholders::_1));
CMD2_FILE("f.last_touched", tr1::bind(&torrent::File::last_touched, tr1::placeholders::_1));
CMD2_FILEITR("fi.filename_last", tr1::bind(&apply_fi_filename_last, tr1::placeholders::_1));
CMD2_FILEITR("fi.is_file", tr1::bind(&torrent::FileListIterator::is_file, tr1::placeholders::_1));
}
-389
View File
@@ -1,389 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <torrent/download/resource_manager.h>
#include <torrent/download/choke_group.h>
#include <torrent/download/choke_queue.h>
#include <torrent/utils/option_strings.h>
#include "ui/root.h"
#include "rpc/parse.h"
#include "rpc/parse_commands.h"
#include "globals.h"
#include "control.h"
#include "command_helpers.h"
// For cg_d_group.
#include "core/download.h"
// A hack to allow testing of the new choke_group API without the
// working parts present.
#define USE_CHOKE_GROUP 0
#if USE_CHOKE_GROUP
int64_t
cg_get_index(const torrent::Object& raw_args) {
const torrent::Object& arg = (raw_args.is_list() && !raw_args.as_list().empty()) ? raw_args.as_list().front() : raw_args;
int64_t index = 0;
if (arg.is_string()) {
if (!rpc::parse_whole_value_nothrow(arg.as_string().c_str(), &index))
return torrent::resource_manager()->group_index_of(arg.as_string());
} else {
index = arg.as_value();
}
if (index < 0)
index = (int64_t)torrent::resource_manager()->group_size() + index;
return std::min<uint64_t>(index, torrent::resource_manager()->group_size());
}
torrent::choke_group*
cg_get_group(const torrent::Object& raw_args) {
return torrent::resource_manager()->group_at(cg_get_index(raw_args));
}
int64_t
cg_d_group(core::Download* download) {
return torrent::resource_manager()->entry_at(download->main()).group();
}
const std::string&
cg_d_group_name(core::Download* download) {
return torrent::resource_manager()->group_at(torrent::resource_manager()->entry_at(download->main()).group())->name();
}
void
cg_d_group_set(core::Download* download, const torrent::Object& arg) {
torrent::resource_manager()->set_group(torrent::resource_manager()->find_throw(download->main()), cg_get_index(arg));
}
torrent::Object
apply_cg_list() {
torrent::Object::list_type result;
for (torrent::ResourceManager::group_iterator
itr = torrent::resource_manager()->group_begin(),
last = torrent::resource_manager()->group_end(); itr != last; itr++)
result.push_back((*itr)->name());
return torrent::Object::from_list(result);
}
torrent::Object
apply_cg_insert(const std::string& arg) {
int64_t dummy;
if (rpc::parse_whole_value_nothrow(arg.c_str(), &dummy))
throw torrent::input_error("Cannot use a value string as choke group name.");
torrent::resource_manager()->push_group(arg);
return torrent::Object();
}
//
// The hacked version:
//
#else
std::vector<torrent::choke_group*> cg_list_hack;
int64_t
cg_get_index(const torrent::Object& raw_args) {
const torrent::Object& arg = (raw_args.is_list() && !raw_args.as_list().empty()) ? raw_args.as_list().front() : raw_args;
int64_t index = 0;
if (arg.is_string()) {
if (!rpc::parse_whole_value_nothrow(arg.as_string().c_str(), &index)) {
std::vector<torrent::choke_group*>::iterator itr = std::find_if(cg_list_hack.begin(), cg_list_hack.end(),
rak::equal(arg.as_string(), std::mem_fun(&torrent::choke_group::name)));
if (itr == cg_list_hack.end())
throw torrent::input_error("Choke group not found.");
return std::distance(cg_list_hack.begin(), itr);
}
} else {
index = arg.as_value();
}
if (index < 0)
index = (int64_t)cg_list_hack.size() + index;
if ((size_t)index >= cg_list_hack.size())
throw torrent::input_error("Choke group not found.");
return index;
}
torrent::choke_group*
cg_get_group(const torrent::Object& raw_args) {
int64_t index = cg_get_index(raw_args);
if ((size_t)index >= cg_list_hack.size())
throw torrent::input_error("Choke group not found.");
return cg_list_hack.at(index);
}
int64_t cg_d_group(core::Download* download) { return download->group(); }
void cg_d_group_set(core::Download* download, const torrent::Object& arg) { download->set_group(cg_get_index(arg)); }
torrent::Object
apply_cg_list() {
torrent::Object::list_type result;
for (std::vector<torrent::choke_group*>::iterator itr = cg_list_hack.begin(), last = cg_list_hack.end(); itr != last; itr++)
result.push_back((*itr)->name());
return torrent::Object::from_list(result);
}
torrent::Object
apply_cg_insert(const std::string& arg) {
int64_t dummy;
if (rpc::parse_whole_value_nothrow(arg.c_str(), &dummy))
throw torrent::input_error("Cannot use a value string as choke group name.");
if (arg.empty() ||
std::find_if(cg_list_hack.begin(), cg_list_hack.end(),
rak::equal(arg, std::mem_fun(&torrent::choke_group::name))) != cg_list_hack.end())
throw torrent::input_error("Duplicate name for choke group.");
cg_list_hack.push_back(new torrent::choke_group());
cg_list_hack.back()->set_name(arg);
cg_list_hack.back()->up_queue()->set_heuristics(torrent::choke_queue::HEURISTICS_UPLOAD_LEECH);
cg_list_hack.back()->down_queue()->set_heuristics(torrent::choke_queue::HEURISTICS_DOWNLOAD_LEECH);
return torrent::Object();
}
torrent::Object
apply_cg_index_of(const std::string& arg) {
std::vector<torrent::choke_group*>::iterator itr =
std::find_if(cg_list_hack.begin(), cg_list_hack.end(), rak::equal(arg, std::mem_fun(&torrent::choke_group::name)));
if (itr == cg_list_hack.end())
throw torrent::input_error("Choke group not found.");
return std::distance(cg_list_hack.begin(), itr);
}
//
// End of choke group hack.
//
#endif
torrent::Object
apply_cg_max_set(const torrent::Object::list_type& args, bool is_up) {
if (args.size() != 2)
throw torrent::input_error("Incorrect number of arguments.");
int64_t second_arg = 0;
rpc::parse_whole_value(args.back().as_string().c_str(), &second_arg);
if (is_up)
cg_get_group(args.front())->up_queue()->set_max_unchoked(second_arg);
else
cg_get_group(args.front())->down_queue()->set_max_unchoked(second_arg);
return torrent::Object();
}
torrent::Object
apply_cg_heuristics_set(const torrent::Object::list_type& args, bool is_up) {
if (args.size() != 2)
throw torrent::input_error("Incorrect number of arguments.");
int t = torrent::option_find_string(is_up ? torrent::OPTION_CHOKE_HEURISTICS_UPLOAD : torrent::OPTION_CHOKE_HEURISTICS_DOWNLOAD,
args.back().as_string().c_str());
if (is_up)
cg_get_group(args.front())->up_queue()->set_heuristics((torrent::choke_queue::heuristics_enum)t);
else
cg_get_group(args.front())->down_queue()->set_heuristics((torrent::choke_queue::heuristics_enum)t);
return torrent::Object();
}
torrent::Object
apply_cg_tracker_mode_set(const torrent::Object::list_type& args) {
if (args.size() != 2)
throw torrent::input_error("Incorrect number of arguments.");
int t = torrent::option_find_string(torrent::OPTION_TRACKER_MODE, args.back().as_string().c_str());
cg_get_group(args.front())->set_tracker_mode((torrent::choke_group::tracker_mode_enum)t);
return torrent::Object();
}
#define CG_GROUP_AT() tr1::bind(&cg_get_group, tr1::placeholders::_2)
#define CHOKE_GROUP(direction) tr1::bind(direction, CG_GROUP_AT())
/*
<cg_index> -> '0'..'(choke_group.size)'
-> '-1'..'-(choke_group.size)'
-> '<group_name>'
(choke_group.list) -> List of group names.
(choke_group.size) -> Number of groups.
(choke_group.insert,"group_name")
Adds a new group with default settings, use index '-1' to accessing it
immediately afterwards.
(choke_group.index_of,"group_name") -> <group_index>
Throws if the group name was not found.
(choke_group.general.size,<cg_index>) -> <size>
Number of torrents in this group.
(choke_group.tracker.mode,<cg_index>) -> "tracker_mode"
(choke_group.tracker.mode.set,<cg_index>,"tracker_mode")
Decide on how aggressive a tracker should be, see
'strings.tracker_mode' for list of available options
(choke_group.up.rate,<cg_index>) -> <bytes/second>
(choke_group.down.rate,<cg_index>) -> <bytes/second>
Upload / download rate for the aggregate of all torrents in this
particular group.
(choke_group.up.max,<cg_index>) -> <max_upload_slots>
(choke_group.up.max.unlimited,<cg_index>) -> <max_upload_slots>
(choke_group.up.max.set,<cg_index>, <max_upload_slots>)
(choke_group.down.max,<cg_index>) -> <max_download_slots>
(choke_group.down.max.unlimited,<cg_index>) -> <max_download_slots>
(choke_group.down.max.set,<cg_index>, <max_download_slots)
Number of unchoked upload / download peers regulated on a group basis.
(choke_group.up.total,<cg_index>) -> <number of queued and unchoked interested peers>
(choke_group.up.queued,<cg_index>) -> <number of queued interested peers>
(choke_group.up.unchoked,<cg_index>) -> <number of unchoked uploads>
(choke_group.down.total,<cg_index>) -> <number of queued and unchoked interested peers>
(choke_group.down.queued,<cg_index>) -> <number of queued interested peers>
(choke_group.down.unchoked,<cg_index>) -> <number of unchoked uploads>
(choke_group.up.heuristics,<cg_index>) -> "heuristics"
(choke_group.up.heuristics.set,<cg_index>,"heuristics")
(choke_group.down.heuristics,<cg_index>) -> "heuristics"
(choke_group.down.heuristics.set,<cg_index>,"heuristics")
Heuristics are used for deciding what peers to choke and unchoke, see
'strings.choke_heuristics{,_download,_upload}' for a list of available
options.
(d.group) -> <choke_group_index>
(d.group.name) -> "choke_group_name"
(d.group.set,<cg_index>)
*/
void
initialize_command_groups() {
// Move somewhere else?
CMD2_ANY ("strings.choke_heuristics", tr1::bind(&torrent::option_list_strings, torrent::OPTION_CHOKE_HEURISTICS));
CMD2_ANY ("strings.choke_heuristics.upload", tr1::bind(&torrent::option_list_strings, torrent::OPTION_CHOKE_HEURISTICS_UPLOAD));
CMD2_ANY ("strings.choke_heuristics.download", tr1::bind(&torrent::option_list_strings, torrent::OPTION_CHOKE_HEURISTICS_DOWNLOAD));
CMD2_ANY ("strings.tracker_mode", tr1::bind(&torrent::option_list_strings, torrent::OPTION_TRACKER_MODE));
CMD2_ANY ("choke_group.list", tr1::bind(&apply_cg_list));
CMD2_ANY_STRING ("choke_group.insert", tr1::bind(&apply_cg_insert, tr1::placeholders::_2));
#if USE_CHOKE_GROUP
CMD2_ANY ("choke_group.size", tr1::bind(&torrent::ResourceManager::group_size, torrent::resource_manager()));
CMD2_ANY_STRING ("choke_group.index_of", tr1::bind(&torrent::ResourceManager::group_index_of, torrent::resource_manager(), tr1::placeholders::_2));
#else
apply_cg_insert("default");
CMD2_ANY ("choke_group.size", tr1::bind(&std::vector<torrent::choke_group*>::size, cg_list_hack));
CMD2_ANY_STRING ("choke_group.index_of", tr1::bind(&apply_cg_index_of, tr1::placeholders::_2));
#endif
// Commands specific for a group. Supports as the first argument the
// name, the index or a negative index.
CMD2_ANY ("choke_group.general.size", tr1::bind(&torrent::choke_group::size, CG_GROUP_AT()));
CMD2_ANY ("choke_group.tracker.mode", tr1::bind(&torrent::option_as_string, torrent::OPTION_TRACKER_MODE,
tr1::bind(&torrent::choke_group::tracker_mode, CG_GROUP_AT())));
CMD2_ANY_LIST ("choke_group.tracker.mode.set", tr1::bind(&apply_cg_tracker_mode_set, tr1::placeholders::_2));
CMD2_ANY ("choke_group.up.rate", tr1::bind(&torrent::choke_group::up_rate, CG_GROUP_AT()));
CMD2_ANY ("choke_group.down.rate", tr1::bind(&torrent::choke_group::down_rate, CG_GROUP_AT()));
CMD2_ANY ("choke_group.up.max.unlimited", tr1::bind(&torrent::choke_queue::is_unlimited, CHOKE_GROUP(&torrent::choke_group::up_queue)));
CMD2_ANY ("choke_group.up.max", tr1::bind(&torrent::choke_queue::max_unchoked_signed, CHOKE_GROUP(&torrent::choke_group::up_queue)));
CMD2_ANY_LIST ("choke_group.up.max.set", tr1::bind(&apply_cg_max_set, tr1::placeholders::_2, true));
CMD2_ANY ("choke_group.up.total", tr1::bind(&torrent::choke_queue::size_total, CHOKE_GROUP(&torrent::choke_group::up_queue)));
CMD2_ANY ("choke_group.up.queued", tr1::bind(&torrent::choke_queue::size_queued, CHOKE_GROUP(&torrent::choke_group::up_queue)));
CMD2_ANY ("choke_group.up.unchoked", tr1::bind(&torrent::choke_queue::size_unchoked, CHOKE_GROUP(&torrent::choke_group::up_queue)));
CMD2_ANY ("choke_group.up.heuristics", tr1::bind(&torrent::option_as_string, torrent::OPTION_CHOKE_HEURISTICS,
tr1::bind(&torrent::choke_queue::heuristics, CHOKE_GROUP(&torrent::choke_group::up_queue))));
CMD2_ANY_LIST ("choke_group.up.heuristics.set", tr1::bind(&apply_cg_heuristics_set, tr1::placeholders::_2, true));
CMD2_ANY ("choke_group.down.max.unlimited", tr1::bind(&torrent::choke_queue::is_unlimited, CHOKE_GROUP(&torrent::choke_group::down_queue)));
CMD2_ANY ("choke_group.down.max", tr1::bind(&torrent::choke_queue::max_unchoked_signed, CHOKE_GROUP(&torrent::choke_group::down_queue)));
CMD2_ANY_LIST ("choke_group.down.max.set", tr1::bind(&apply_cg_max_set, tr1::placeholders::_2, false));
CMD2_ANY ("choke_group.down.total", tr1::bind(&torrent::choke_queue::size_total, CHOKE_GROUP(&torrent::choke_group::down_queue)));
CMD2_ANY ("choke_group.down.queued", tr1::bind(&torrent::choke_queue::size_queued, CHOKE_GROUP(&torrent::choke_group::down_queue)));
CMD2_ANY ("choke_group.down.unchoked", tr1::bind(&torrent::choke_queue::size_unchoked, CHOKE_GROUP(&torrent::choke_group::down_queue)));
CMD2_ANY ("choke_group.down.heuristics", tr1::bind(&torrent::option_as_string, torrent::OPTION_CHOKE_HEURISTICS,
tr1::bind(&torrent::choke_queue::heuristics, CHOKE_GROUP(&torrent::choke_group::down_queue))));
CMD2_ANY_LIST ("choke_group.down.heuristics.set", tr1::bind(&apply_cg_heuristics_set, tr1::placeholders::_2, false));
}
-74
View File
@@ -1,74 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <torrent/exceptions.h>
#include "globals.h"
#include "control.h"
#include "command_helpers.h"
void initialize_command_dynamic();
void initialize_command_download();
void initialize_command_events();
void initialize_command_file();
void initialize_command_ip();
void initialize_command_peer();
void initialize_command_local();
void initialize_command_network();
void initialize_command_groups();
void initialize_command_throttle();
void initialize_command_tracker();
void initialize_command_scheduler();
void initialize_command_ui();
void
initialize_commands() {
initialize_command_dynamic();
initialize_command_events();
initialize_command_network();
initialize_command_groups();
initialize_command_local();
initialize_command_ui();
initialize_command_download();
initialize_command_file();
initialize_command_ip();
initialize_command_peer();
initialize_command_throttle();
initialize_command_tracker();
initialize_command_scheduler();
}
-213
View File
@@ -1,213 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_UTILS_COMMAND_HELPERS_H
#define RTORRENT_UTILS_COMMAND_HELPERS_H
#include "rpc/command.h"
#include "rpc/parse_commands.h"
#include "rpc/object_storage.h"
namespace tr1 { using namespace std::tr1; }
void initialize_commands();
//
// New std::function based command_base helper functions:
//
#define CMD2_A_FUNCTION(key, function, slot, parm, doc) \
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::function>::type>(key, slot, &rpc::function, \
rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_xmlrpc, NULL, NULL);
#define CMD2_A_FUNCTION_PRIVATE(key, function, slot, parm, doc) \
rpc::commands.insert_slot<rpc::command_base_is_type<rpc::function>::type>(key, slot, &rpc::function, \
rpc::CommandMap::flag_dont_delete, NULL, NULL);
#define CMD2_ANY(key, slot) CMD2_A_FUNCTION(key, command_base_call<rpc::target_type>, slot, "i:", "")
#define CMD2_ANY_P(key, slot) CMD2_A_FUNCTION_PRIVATE(key, command_base_call<rpc::target_type>, slot, "i:", "")
#define CMD2_ANY_VOID(key, slot) CMD2_A_FUNCTION(key, command_base_call<rpc::target_type>, object_convert_void(slot), "i:", "")
#define CMD2_ANY_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_list<rpc::target_type>, object_convert_void(slot), "i:", "")
#define CMD2_ANY_L(key, slot) CMD2_A_FUNCTION(key, command_base_call_list<rpc::target_type>, slot, "A:", "")
#define CMD2_ANY_VALUE(key, slot) CMD2_A_FUNCTION(key, command_base_call_value<rpc::target_type>, slot, "i:i", "")
#define CMD2_ANY_VALUE_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_value<rpc::target_type>, object_convert_void(slot), "i:i", "")
#define CMD2_ANY_VALUE_KB(key, slot) CMD2_A_FUNCTION(key, command_base_call_value_kb<rpc::target_type>, object_convert_void(slot), "i:i", "")
#define CMD2_ANY_STRING(key, slot) CMD2_A_FUNCTION(key, command_base_call_string<rpc::target_type>, slot, "i:s", "")
#define CMD2_ANY_STRING_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_string<rpc::target_type>, object_convert_void(slot), "i:s", "")
#define CMD2_ANY_LIST(key, slot) CMD2_A_FUNCTION(key, command_base_call_list<rpc::target_type>, slot, "i:", "")
#define CMD2_DL(key, slot) CMD2_A_FUNCTION(key, command_base_call<core::Download*>, slot, "i:", "")
#define CMD2_DL_V(key, slot) CMD2_A_FUNCTION(key, command_base_call<core::Download*>, object_convert_void(slot), "i:", "")
#define CMD2_DL_VALUE(key, slot) CMD2_A_FUNCTION(key, command_base_call_value<core::Download*>, slot, "i:", "")
#define CMD2_DL_VALUE_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_value<core::Download*>, object_convert_void(slot), "i:", "")
#define CMD2_DL_STRING(key, slot) CMD2_A_FUNCTION(key, command_base_call_string<core::Download*>, slot, "i:", "")
#define CMD2_DL_STRING_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_string<core::Download*>, object_convert_void(slot), "i:", "")
#define CMD2_DL_LIST(key, slot) CMD2_A_FUNCTION(key, command_base_call_list<core::Download*>, slot, "i:", "")
#define CMD2_DL_VALUE_P(key, slot) CMD2_A_FUNCTION_PRIVATE(key, command_base_call_value<core::Download*>, slot, "i:", "")
#define CMD2_DL_STRING_P(key, slot) CMD2_A_FUNCTION_PRIVATE(key, command_base_call_string<core::Download*>, slot, "i:", "")
#define CMD2_FILE(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::File*>, slot, "i:", "")
#define CMD2_FILE_V(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::File*>, object_convert_void(slot), "i:", "")
#define CMD2_FILE_VALUE_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_value<torrent::File*>, object_convert_void(slot), "i:i", "")
#define CMD2_FILEITR(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::FileListIterator*>, slot, "i:", "")
#define CMD2_PEER(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::Peer*>, slot, "i:", "")
#define CMD2_PEER_V(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::Peer*>, object_convert_void(slot), "i:", "")
#define CMD2_PEER_VALUE_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_value<torrent::Peer*>, object_convert_void(slot), "i:i", "")
#define CMD2_TRACKER(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::Tracker*>, slot, "i:", "")
#define CMD2_TRACKER_V(key, slot) CMD2_A_FUNCTION(key, command_base_call<torrent::Tracker*>, object_convert_void(slot), "i:", "")
#define CMD2_TRACKER_VALUE_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_value<torrent::Tracker*>, object_convert_void(slot), "i:i", "")
#define CMD2_VAR_BOOL(key, value) \
control->object_storage()->insert_c_str(key, int64_t(value), rpc::object_storage::flag_bool_type); \
CMD2_ANY(key, tr1::bind(&rpc::object_storage::get, control->object_storage(), \
torrent::raw_string::from_c_str(key))); \
CMD2_ANY_VALUE(key ".set", tr1::bind(&rpc::object_storage::set_bool, control->object_storage(), \
torrent::raw_string::from_c_str(key), tr1::placeholders::_2));
#define CMD2_VAR_VALUE(key, value) \
control->object_storage()->insert_c_str(key, int64_t(value), rpc::object_storage::flag_value_type); \
CMD2_ANY(key, tr1::bind(&rpc::object_storage::get, control->object_storage(), \
torrent::raw_string::from_c_str(key))); \
CMD2_ANY_VALUE(key ".set", tr1::bind(&rpc::object_storage::set_value, control->object_storage(), \
torrent::raw_string::from_c_str(key), tr1::placeholders::_2));
#define CMD2_VAR_STRING(key, value) \
control->object_storage()->insert_c_str(key, value, rpc::object_storage::flag_string_type); \
CMD2_ANY(key, tr1::bind(&rpc::object_storage::get, control->object_storage(), \
torrent::raw_string::from_c_str(key))); \
CMD2_ANY_STRING(key ".set", tr1::bind(&rpc::object_storage::set_string, control->object_storage(), \
torrent::raw_string::from_c_str(key), tr1::placeholders::_2));
#define CMD2_VAR_C_STRING(key, value) \
control->object_storage()->insert_c_str(key, value, rpc::object_storage::flag_string_type); \
CMD2_ANY(key, tr1::bind(&rpc::object_storage::get, control->object_storage(), \
torrent::raw_string::from_c_str(key)));
#define CMD2_VAR_LIST(key) \
control->object_storage()->insert_c_str(key, torrent::Object::create_list(), rpc::object_storage::flag_list_type); \
CMD2_ANY(key, tr1::bind(&rpc::object_storage::get, control->object_storage(), \
torrent::raw_string::from_c_str(key))); \
CMD2_ANY_LIST(key ".set", tr1::bind(&rpc::object_storage::set_list, control->object_storage(), \
torrent::raw_string::from_c_str(key), tr1::placeholders::_2)); \
CMD2_ANY_VOID(key ".push_back", tr1::bind(&rpc::object_storage::list_push_back, control->object_storage(), \
torrent::raw_string::from_c_str(key), tr1::placeholders::_2));
#define CMD2_FUNC_SINGLE(key, cmds) \
CMD2_ANY(key, tr1::bind(&rpc::command_function_call_object, torrent::Object(torrent::raw_string::from_c_str(cmds)), \
tr1::placeholders::_1, tr1::placeholders::_2));
#define CMD2_REDIRECT(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_dont_delete);
#define CMD2_REDIRECT_GENERIC(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_dont_delete);
#define CMD2_REDIRECT_GENERIC_NO_EXPORT(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_dont_delete);
#define CMD2_REDIRECT_FILE(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_file_target | rpc::CommandMap::flag_dont_delete);
#define CMD2_REDIRECT_TRACKER(from_key, to_key) \
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_tracker_target | rpc::CommandMap::flag_dont_delete);
#define CMD2_REDIRECT_GENERIC_STR(from_key, to_key) \
rpc::commands.create_redirect(create_new_key(from_key), create_new_key(to_key), \
rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_delete_key);
#define CMD2_REDIRECT_GENERIC_STR_NO_EXPORT(from_key, to_key) \
rpc::commands.create_redirect(create_new_key(from_key), create_new_key(to_key), \
rpc::CommandMap::flag_no_target | rpc::CommandMap::flag_delete_key);
//
// Conversion of return types:
//
template <typename Functor, typename Result>
struct object_convert_type;
template <typename Functor>
struct object_convert_type<Functor, void> {
template <typename Signature> struct result {
typedef torrent::Object type;
};
object_convert_type(Functor s) : m_slot(s) {}
torrent::Object operator () () { m_slot(); return torrent::Object(); }
template <typename Arg1>
torrent::Object operator () (Arg1& arg1) { m_slot(arg1); return torrent::Object(); }
template <typename Arg1, typename Arg2>
torrent::Object operator () (const Arg1& arg1) { m_slot(arg1); return torrent::Object(); }
template <typename Arg1, typename Arg2>
torrent::Object operator () (Arg1& arg1, Arg2& arg2) { m_slot(arg1, arg2); return torrent::Object(); }
template <typename Arg1, typename Arg2>
torrent::Object operator () (const Arg1& arg1, const Arg2& arg2) { m_slot(arg1, arg2); return torrent::Object(); }
Functor m_slot;
};
template <typename T>
object_convert_type<T, void>
object_convert_void(T f) { return f; }
//
// Key creation:
//
template <int postfix_size>
inline const char*
create_new_key(const std::string& key, const char postfix[postfix_size]) {
char *buffer = new char[key.size() + std::max(postfix_size, 1)];
std::memcpy(buffer, key.c_str(), key.size() + 1);
std::memcpy(buffer + key.size(), postfix, postfix_size);
return buffer;
}
inline const char*
create_new_key(const std::string& key) {
char *buffer = new char[key.size() + 1];
std::memcpy(buffer, key.c_str(), key.size() + 1);
return buffer;
}
#endif
-297
View File
@@ -1,297 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <fstream>
#include <rak/path.h>
#include <torrent/peer/peer_list.h>
#include <torrent/utils/log.h>
#include <torrent/utils/option_strings.h>
#include "globals.h"
#include "command_helpers.h"
void
ipv4_filter_parse(const char* address, int value) {
uint32_t ip_values[4] = { 0, 0, 0, 0 };
unsigned int block = rpc::ipv4_table::mask_bits;
char ip_dot;
int values_read;
if ((values_read = sscanf(address, "%u%1[.]%u%1[.]%u%1[.]%u/%u",
ip_values + 0, &ip_dot,
ip_values + 1, &ip_dot,
ip_values + 2, &ip_dot,
ip_values + 3,
&block)) < 2 ||
// Make sure the dot is included.
(values_read < 7 && values_read % 2) ||
ip_values[0] >= 256 ||
ip_values[1] >= 256 ||
ip_values[2] >= 256 ||
ip_values[3] >= 256 ||
block > rpc::ipv4_table::mask_bits)
throw torrent::input_error("Invalid address format.");
// E.g. '10.10.' will be '10.10.0.0/16'.
if (values_read < 7)
block = 8 * (values_read / 2);
lt_log_print(torrent::LOG_CONNECTION_DEBUG, "Adding ip filter for %u.%u.%u.%u/%u.",
ip_values[0], ip_values[1], ip_values[2], ip_values[3], block);
torrent::PeerList::ipv4_filter()->insert((ip_values[0] << 24) + (ip_values[1] << 16) + (ip_values[2] << 8) + ip_values[3],
rpc::ipv4_table::mask_bits - block, value);
}
torrent::Object
apply_ip_tables_insert_table(const std::string& args) {
if (ip_tables.find(args) != ip_tables.end())
throw torrent::input_error("IP table already exists.");
ip_tables.insert(args);
return torrent::Object();
}
torrent::Object
apply_ip_tables_size_data(const std::string& args) {
rpc::ip_table_list::const_iterator itr = ip_tables.find(args);
if (itr != ip_tables.end())
throw torrent::input_error("IP table does not exist.");
return itr->table.sizeof_data();
}
torrent::Object
apply_ip_tables_get(const torrent::Object::list_type& args) {
if (args.size() != 2)
throw torrent::input_error("Incorrect number of arguments.");
torrent::Object::list_const_iterator args_itr = args.begin();
const std::string& name = (args_itr++)->as_string();
const std::string& address = (args_itr++)->as_string();
// Move to a helper function, add support for addresses.
uint32_t ip_values[4];
if (sscanf(address.c_str(), "%u.%u.%u.%u",
ip_values + 0, ip_values + 1, ip_values + 2, ip_values + 3) != 4)
throw torrent::input_error("Invalid address format.");
rpc::ip_table_list::iterator table_itr = ip_tables.find(name);
if (table_itr == ip_tables.end())
throw torrent::input_error("Could not find ip table.");
return table_itr->table.at((ip_values[0] << 24) + (ip_values[1] << 16) + (ip_values[2] << 8) + ip_values[3]);
}
torrent::Object
apply_ip_tables_add_address(const torrent::Object::list_type& args) {
if (args.size() != 3)
throw torrent::input_error("Incorrect number of arguments.");
torrent::Object::list_const_iterator args_itr = args.begin();
const std::string& name = (args_itr++)->as_string();
const std::string& address = (args_itr++)->as_string();
const std::string& value_str = (args_itr++)->as_string();
// Move to a helper function, add support for addresses.
uint32_t ip_values[4];
unsigned int block = rpc::ipv4_table::mask_bits;
if (sscanf(address.c_str(), "%u.%u.%u.%u/%u",
ip_values + 0, ip_values + 1, ip_values + 2, ip_values + 3, &block) < 4 ||
block > rpc::ipv4_table::mask_bits)
throw torrent::input_error("Invalid address format.");
int value;
if (value_str == "block")
value = 1;
else
throw torrent::input_error("Invalid value.");
rpc::ip_table_list::iterator table_itr = ip_tables.find(name);
if (table_itr == ip_tables.end())
throw torrent::input_error("Could not find ip table.");
table_itr->table.insert((ip_values[0] << 24) + (ip_values[1] << 16) + (ip_values[2] << 8) + ip_values[3],
rpc::ipv4_table::mask_bits - block, value);
return torrent::Object();
}
//
// IPv4 filter functions:
//
torrent::Object
apply_ipv4_filter_size_data() {
return torrent::PeerList::ipv4_filter()->sizeof_data();
}
torrent::Object
apply_ipv4_filter_get(const std::string& args) {
// Move to a helper function, add support for addresses.
uint32_t ip_values[4];
if (sscanf(args.c_str(), "%u.%u.%u.%u",
ip_values + 0, ip_values + 1, ip_values + 2, ip_values + 3) != 4)
throw torrent::input_error("Invalid address format.");
return torrent::PeerList::ipv4_filter()->at((ip_values[0] << 24) + (ip_values[1] << 16) + (ip_values[2] << 8) + ip_values[3]);
}
torrent::Object
apply_ipv4_filter_add_address(const torrent::Object::list_type& args) {
if (args.size() != 2)
throw torrent::input_error("Incorrect number of arguments.");
ipv4_filter_parse(args.front().as_string().c_str(),
torrent::option_find_string(torrent::OPTION_IP_FILTER, args.back().as_string().c_str()));
return torrent::Object();
}
torrent::Object
apply_ipv4_filter_load(const torrent::Object::list_type& args) {
if (args.size() != 2)
throw torrent::input_error("Incorrect number of arguments.");
std::string filename = args.front().as_string();
std::string value_name = args.back().as_string();
int value = torrent::option_find_string(torrent::OPTION_IP_FILTER, value_name.c_str());
std::fstream file(rak::path_expand(filename).c_str(), std::ios::in);
if (!file.is_open())
throw torrent::input_error("Could not open ip filter file: " + filename);
unsigned int lineNumber = 0;
char buffer[4096];
try {
while (file.good() && !file.getline(buffer, 4096).fail()) {
if (file.gcount() == 0)
throw torrent::internal_error("parse_command_file(...) file.gcount() == 0.");
lineNumber++;
if (buffer[0] == '\0' || buffer[0] == '#')
continue;
ipv4_filter_parse(buffer, value);
}
} catch (torrent::input_error& e) {
snprintf(buffer, 2048, "Error in ip filter file: %s:%u: %s", filename.c_str(), lineNumber, e.what());
throw torrent::input_error(buffer);
}
lt_log_print(torrent::LOG_CONNECTION_INFO, "Loaded %u %s address blocks (%u kb in-memory) from '%s'.",
lineNumber,
value_name.c_str(),
torrent::PeerList::ipv4_filter()->sizeof_data() / 1024,
filename.c_str());
return torrent::Object();
}
static void
append_table(torrent::ipv4_table::base_type* extent, torrent::Object::list_type& result) {
torrent::ipv4_table::table_type::iterator first = extent->table.begin();
torrent::ipv4_table::table_type::iterator last = extent->table.end();
while (first != last) {
if (first->first != NULL) {
// Do something more here?...
append_table(first->first, result);
} else if (first->second != 0) {
uint32_t position = extent->partition_pos(first);
char buffer[256];
snprintf(buffer, 256, "%u.%u.%u.%u/%u %s",
(position >> 24) & 0xff,
(position >> 16) & 0xff,
(position >> 8) & 0xff,
(position >> 0) & 0xff,
extent->mask_bits,
torrent::option_as_string(torrent::OPTION_IP_FILTER, first->second));
result.push_back((std::string)buffer);
}
first++;
}
}
torrent::Object
apply_ipv4_filter_dump() {
torrent::Object raw_result = torrent::Object::create_list();
torrent::Object::list_type& result = raw_result.as_list();
append_table(torrent::PeerList::ipv4_filter()->data(), result);
return raw_result;
}
void
initialize_command_ip() {
CMD2_ANY ("strings.ip_filter", tr1::bind(&torrent::option_list_strings, torrent::OPTION_IP_FILTER));
CMD2_ANY ("strings.ip_tos", tr1::bind(&torrent::option_list_strings, torrent::OPTION_IP_TOS));
CMD2_ANY_STRING ("ip_tables.insert_table", tr1::bind(&apply_ip_tables_insert_table, tr1::placeholders::_2));
CMD2_ANY_STRING ("ip_tables.size_data", tr1::bind(&apply_ip_tables_size_data, tr1::placeholders::_2));
CMD2_ANY_LIST ("ip_tables.get", tr1::bind(&apply_ip_tables_get, tr1::placeholders::_2));
CMD2_ANY_LIST ("ip_tables.add_address", tr1::bind(&apply_ip_tables_add_address, tr1::placeholders::_2));
CMD2_ANY ("ipv4_filter.size_data", tr1::bind(&apply_ipv4_filter_size_data));
CMD2_ANY_STRING ("ipv4_filter.get", tr1::bind(&apply_ipv4_filter_get, tr1::placeholders::_2));
CMD2_ANY_LIST ("ipv4_filter.add_address", tr1::bind(&apply_ipv4_filter_add_address, tr1::placeholders::_2));
CMD2_ANY_LIST ("ipv4_filter.load", tr1::bind(&apply_ipv4_filter_load, tr1::placeholders::_2));
CMD2_ANY_LIST ("ipv4_filter.dump", tr1::bind(&apply_ipv4_filter_dump));
}
-425
View File
@@ -1,425 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <fcntl.h>
#include <functional>
#include <stdio.h>
#include <unistd.h>
#include <rak/path.h>
#include <rak/error_number.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <torrent/torrent.h>
#include <torrent/chunk_manager.h>
#include <torrent/data/file_manager.h>
#include <torrent/data/chunk_utils.h>
#include <torrent/utils/log.h>
#include <torrent/utils/option_strings.h>
#include "core/download.h"
#include "core/download_list.h"
#include "core/download_store.h"
#include "core/manager.h"
#include "rak/string_manip.h"
#include "rpc/parse_commands.h"
#include "rpc/scgi.h"
#include "utils/file_status_cache.h"
#include "globals.h"
#include "control.h"
#include "command_helpers.h"
typedef torrent::ChunkManager CM_t;
typedef torrent::FileManager FM_t;
torrent::Object
apply_pieces_stats_total_size() {
uint64_t size = 0;
core::DownloadList* d_list = control->core()->download_list();
for (core::DownloadList::iterator itr = d_list->begin(), last = d_list->end(); itr != last; itr++)
if ((*itr)->is_active())
size += (*itr)->file_list()->size_bytes();
return size;
}
torrent::Object
apply_log(const torrent::Object::string_type& arg, int logType) {
if (rpc::execFile.log_fd() != -1) {
switch (logType) {
case 0: ::close(rpc::execFile.log_fd()); rpc::execFile.set_log_fd(-1); break;
case 1:
// if (control->scgi()) {
// ::close(control->scgi()->log_fd());
// control->scgi()->set_log_fd(-1);
// }
break;
default: break;
}
}
if (!arg.empty()) {
int logFd = open(rak::path_expand(arg).c_str(), O_WRONLY | O_APPEND | O_CREAT, 0644);
if (logFd < 0)
throw torrent::input_error("Could not open execute log file.");
switch (logType) {
case 0: rpc::execFile.set_log_fd(logFd); break;
// case 1: if (control->scgi()) control->scgi()->set_log_fd(logFd); break;
default: break;
}
control->core()->push_log("Opened log file.");
} else {
control->core()->push_log("Closed log file.");
}
return torrent::Object();
}
torrent::Object
system_hostname() {
char buffer[1024];
if (gethostname(buffer, 1023) == -1)
throw torrent::input_error("Unable to read hostname.");
// if (shorten)
// *std::find(buffer, buffer + 1023, '.') = '\0';
return std::string(buffer);
}
torrent::Object
system_get_cwd() {
char* buffer = getcwd(NULL, 0);
if (buffer == NULL)
throw torrent::input_error("Unable to read cwd.");
torrent::Object result = torrent::Object(std::string(buffer));
free(buffer);
return result;
}
torrent::Object
system_set_cwd(const torrent::Object::string_type& rawArgs) {
if (::chdir(rawArgs.c_str()) != 0)
throw torrent::input_error("Could not change current working directory.");
return torrent::Object();
}
inline torrent::Object::list_const_iterator
post_increment(torrent::Object::list_const_iterator& itr, const torrent::Object::list_const_iterator& last) {
if (itr == last)
throw torrent::input_error("Invalid number of arguments.");
return itr++;
}
inline const std::string&
check_name(const std::string& str) {
if (!rak::is_all_name(str))
throw torrent::input_error("Non-alphanumeric characters found.");
return str;
}
torrent::Object
group_insert(const torrent::Object::list_type& args) {
torrent::Object::list_const_iterator itr = args.begin();
torrent::Object::list_const_iterator last = args.end();
const std::string& name = check_name(post_increment(itr, last)->as_string());
const std::string& view = check_name(post_increment(itr, last)->as_string());
rpc::commands.call("method.insert", rpc::create_object_list("group." + name + ".ratio.enable", "simple",
"schedule2=group." + name + ".ratio,5,60,on_ratio=" + name));
rpc::commands.call("method.insert", rpc::create_object_list("group." + name + ".ratio.disable", "simple",
"schedule_remove2=group." + name + ".ratio"));
rpc::commands.call("method.insert", rpc::create_object_list("group." + name + ".ratio.command", "simple",
"d.try_close= ;d.ignore_commands.set=1"));
rpc::commands.call("method.insert", rpc::create_object_list("group2." + name + ".view", "string", view));
rpc::commands.call("method.insert", rpc::create_object_list("group2." + name + ".ratio.min", "value", (int64_t)200));
rpc::commands.call("method.insert", rpc::create_object_list("group2." + name + ".ratio.max", "value", (int64_t)300));
rpc::commands.call("method.insert", rpc::create_object_list("group2." + name + ".ratio.upload", "value", (int64_t)20 << 20));
if (rpc::call_command_value("method.use_intermediate") == 1) {
// Deprecated in 0.7.0:
CMD2_REDIRECT_GENERIC_STR("group." + name + ".view", "group2." + name + ".view");
CMD2_REDIRECT_GENERIC_STR("group." + name + ".view.set", "group2." + name + ".view.set");
CMD2_REDIRECT_GENERIC_STR("group." + name + ".ratio.min", "group2." + name + ".ratio.min");
CMD2_REDIRECT_GENERIC_STR("group." + name + ".ratio.min.set", "group2." + name + ".ratio.min.set");
CMD2_REDIRECT_GENERIC_STR("group." + name + ".ratio.max", "group2." + name + ".ratio.max");
CMD2_REDIRECT_GENERIC_STR("group." + name + ".ratio.max.set", "group2." + name + ".ratio.max.set");
CMD2_REDIRECT_GENERIC_STR("group." + name + ".ratio.upload", "group2." + name + ".ratio.upload");
CMD2_REDIRECT_GENERIC_STR("group." + name + ".ratio.upload.set", "group2." + name + ".ratio.upload.set");
} if (rpc::call_command_value("method.use_intermediate") == 2) {
// Deprecated in 0.7.0:
CMD2_REDIRECT_GENERIC_STR_NO_EXPORT("group." + name + ".view", "group2." + name + ".view");
CMD2_REDIRECT_GENERIC_STR_NO_EXPORT("group." + name + ".view.set", "group2." + name + ".view.set");
CMD2_REDIRECT_GENERIC_STR_NO_EXPORT("group." + name + ".ratio.min", "group2." + name + ".ratio.min");
CMD2_REDIRECT_GENERIC_STR_NO_EXPORT("group." + name + ".ratio.min.set", "group2." + name + ".ratio.min.set");
CMD2_REDIRECT_GENERIC_STR_NO_EXPORT("group." + name + ".ratio.max", "group2." + name + ".ratio.max");
CMD2_REDIRECT_GENERIC_STR_NO_EXPORT("group." + name + ".ratio.max.set", "group2." + name + ".ratio.max.set");
CMD2_REDIRECT_GENERIC_STR_NO_EXPORT("group." + name + ".ratio.upload", "group2." + name + ".ratio.upload");
CMD2_REDIRECT_GENERIC_STR_NO_EXPORT("group." + name + ".ratio.upload.set", "group2." + name + ".ratio.upload.set");
}
return name;
}
torrent::Object
log_vmmap_dump(const std::string& str) {
core::DownloadList* d_list = control->core()->download_list();
std::vector<torrent::vm_mapping> all_mappings;
for (core::DownloadList::iterator itr = d_list->begin(), last = d_list->end(); itr != last; itr++) {
std::vector<torrent::vm_mapping> tmp_mappings = torrent::chunk_list_mapping((*itr)->download());
all_mappings.insert(all_mappings.end(), tmp_mappings.begin(), tmp_mappings.end());
}
FILE* log_file = fopen(str.c_str(), "w");
for (std::vector<torrent::vm_mapping>::iterator itr = all_mappings.begin(), last = all_mappings.end(); itr != last; itr++) {
fprintf(log_file, "%8p-%8p [%5llxk]\n", itr->ptr, (char*)itr->ptr + itr->length, (long long unsigned int)(itr->length / 1024));
}
fclose(log_file);
return torrent::Object();
}
static const int file_print_use_space = 0x1;
static const int file_print_delim_space = 0x2;
void
file_print_list(torrent::Object::list_const_iterator first, torrent::Object::list_const_iterator last, FILE* output, int flags) {
while (first != last) {
switch (first->type()) {
case torrent::Object::TYPE_STRING:
fprintf(output, (const char*)" %s" + !(flags & file_print_use_space), first->as_string().c_str());
break;
case torrent::Object::TYPE_VALUE:
fprintf(output, (const char*)" %lli" + !(flags & file_print_use_space), first->as_value());
break;
case torrent::Object::TYPE_LIST:
file_print_list(first->as_list().begin(), first->as_list().end(), output, 0);
break;
case torrent::Object::TYPE_NONE:
break;
default:
throw torrent::input_error("Invalid type.");
}
flags |= (flags & file_print_delim_space) >> 1;
first++;
}
}
torrent::Object
cmd_file_append(const torrent::Object::list_type& args) {
if (args.empty())
throw torrent::input_error("Invalid number of arguments.");
FILE* output = fopen(args.front().as_string().c_str(), "a");
if (output == NULL)
throw torrent::input_error("Could not append to file '" + args.front().as_string() + "': " + rak::error_number::current().c_str());
file_print_list(++args.begin(), args.end(), output, file_print_delim_space);
fprintf(output, "\n");
fclose(output);
return torrent::Object();
}
torrent::Object
apply_log_open_file(const torrent::Object::list_type& args) {
if (args.size() != 2)
throw torrent::input_error("Invalid number of arguments.");
torrent::log_open_file_output(args.front().as_string().c_str(),
rak::path_expand(args.back().as_string()).c_str());
return torrent::Object();
}
torrent::Object
apply_log_open_gz_file(const torrent::Object::list_type& args) {
if (args.size() != 2)
throw torrent::input_error("Invalid number of arguments.");
torrent::log_open_gz_file_output(args.front().as_string().c_str(),
rak::path_expand(args.back().as_string()).c_str());
return torrent::Object();
}
torrent::Object
apply_log_add_output(const torrent::Object::list_type& args) {
if (args.size() != 2)
throw torrent::input_error("Invalid number of arguments.");
torrent::log_add_group_output(torrent::option_find_string(torrent::OPTION_LOG_GROUP, args.front().as_string().c_str()),
args.back().as_string().c_str());
return torrent::Object();
}
void
initialize_command_local() {
torrent::ChunkManager* chunkManager = torrent::chunk_manager();
torrent::FileManager* fileManager = torrent::file_manager();
core::DownloadList* dList = control->core()->download_list();
core::DownloadStore* dStore = control->core()->download_store();
CMD2_ANY ("system.hostname", tr1::bind(&system_hostname));
CMD2_ANY ("system.pid", tr1::bind(&getpid));
CMD2_VAR_C_STRING("system.api_version", (int64_t)API_VERSION);
CMD2_VAR_C_STRING("system.client_version", PACKAGE_VERSION);
CMD2_VAR_C_STRING("system.library_version", torrent::version());
CMD2_VAR_VALUE ("system.file.allocate", 0);
CMD2_VAR_VALUE ("system.file.max_size", (int64_t)128 << 30);
CMD2_VAR_VALUE ("system.file.split_size", -1);
CMD2_VAR_STRING ("system.file.split_suffix", ".part");
CMD2_ANY ("system.file_status_cache.size", tr1::bind(&utils::FileStatusCache::size,
(utils::FileStatusCache::base_type*)control->core()->file_status_cache()));
CMD2_ANY_V ("system.file_status_cache.prune", tr1::bind(&utils::FileStatusCache::prune, control->core()->file_status_cache()));
CMD2_VAR_BOOL ("file.prioritize_toc", 0);
CMD2_VAR_LIST ("file.prioritize_toc.first");
CMD2_VAR_LIST ("file.prioritize_toc.last");
CMD2_ANY ("system.files.opened_counter", tr1::bind(&FM_t::files_opened_counter, fileManager));
CMD2_ANY ("system.files.closed_counter", tr1::bind(&FM_t::files_closed_counter, fileManager));
CMD2_ANY ("system.files.failed_counter", tr1::bind(&FM_t::files_failed_counter, fileManager));
CMD2_ANY ("system.time", tr1::bind(&rak::timer::seconds, &cachedTime));
CMD2_ANY ("system.time_seconds", tr1::bind(&rak::timer::current_seconds));
CMD2_ANY ("system.time_usec", tr1::bind(&rak::timer::current_usec));
CMD2_ANY_VALUE_V ("system.umask.set", tr1::bind(&umask, tr1::placeholders::_2));
CMD2_ANY ("system.cwd", tr1::bind(&system_get_cwd));
CMD2_ANY_STRING ("system.cwd.set", tr1::bind(&system_set_cwd, tr1::placeholders::_2));
CMD2_ANY ("pieces.sync.always_safe", tr1::bind(&CM_t::safe_sync, chunkManager));
CMD2_ANY_VALUE_V ("pieces.sync.always_safe.set", tr1::bind(&CM_t::set_safe_sync, chunkManager, tr1::placeholders::_2));
CMD2_ANY ("pieces.sync.safe_free_diskspace", tr1::bind(&CM_t::safe_free_diskspace, chunkManager));
CMD2_ANY ("pieces.sync.timeout", tr1::bind(&CM_t::timeout_sync, chunkManager));
CMD2_ANY_VALUE_V ("pieces.sync.timeout.set", tr1::bind(&CM_t::set_timeout_sync, chunkManager, tr1::placeholders::_2));
CMD2_ANY ("pieces.sync.timeout_safe", tr1::bind(&CM_t::timeout_safe_sync, chunkManager));
CMD2_ANY_VALUE_V ("pieces.sync.timeout_safe.set", tr1::bind(&CM_t::set_timeout_safe_sync, chunkManager, tr1::placeholders::_2));
CMD2_ANY ("pieces.sync.queue_size", tr1::bind(&CM_t::sync_queue_size, chunkManager));
CMD2_ANY ("pieces.preload.type", tr1::bind(&CM_t::preload_type, chunkManager));
CMD2_ANY_VALUE_V ("pieces.preload.type.set", tr1::bind(&CM_t::set_preload_type, chunkManager, tr1::placeholders::_2));
CMD2_ANY ("pieces.preload.min_size", tr1::bind(&CM_t::preload_min_size, chunkManager));
CMD2_ANY_VALUE_V ("pieces.preload.min_size.set", tr1::bind(&CM_t::set_preload_min_size, chunkManager, tr1::placeholders::_2));
CMD2_ANY ("pieces.preload.min_rate", tr1::bind(&CM_t::preload_required_rate, chunkManager));
CMD2_ANY_VALUE_V ("pieces.preload.min_rate.set", tr1::bind(&CM_t::set_preload_required_rate, chunkManager, tr1::placeholders::_2));
CMD2_ANY ("pieces.memory.current", tr1::bind(&CM_t::memory_usage, chunkManager));
CMD2_ANY ("pieces.memory.sync_queue", tr1::bind(&CM_t::sync_queue_memory_usage, chunkManager));
CMD2_ANY ("pieces.memory.block_count", tr1::bind(&CM_t::memory_block_count, chunkManager));
CMD2_ANY ("pieces.memory.max", tr1::bind(&CM_t::max_memory_usage, chunkManager));
CMD2_ANY_VALUE_V ("pieces.memory.max.set", tr1::bind(&CM_t::set_max_memory_usage, chunkManager, tr1::placeholders::_2));
CMD2_ANY ("pieces.stats_preloaded", tr1::bind(&CM_t::stats_preloaded, chunkManager));
CMD2_ANY ("pieces.stats_not_preloaded", tr1::bind(&CM_t::stats_not_preloaded, chunkManager));
CMD2_ANY ("pieces.stats.total_size", tr1::bind(&apply_pieces_stats_total_size));
CMD2_ANY ("pieces.hash.queue_size", tr1::bind(&torrent::hash_queue_size));
CMD2_VAR_BOOL ("pieces.hash.on_completion", true);
CMD2_VAR_STRING ("directory.default", "./");
CMD2_VAR_STRING ("session.name", "");
CMD2_VAR_BOOL ("session.use_lock", true);
CMD2_VAR_BOOL ("session.on_completion", true);
CMD2_ANY ("session.path", tr1::bind(&core::DownloadStore::path, dStore));
CMD2_ANY_STRING_V("session.path.set", tr1::bind(&core::DownloadStore::set_path, dStore, tr1::placeholders::_2));
CMD2_ANY_V ("session.save", tr1::bind(&core::DownloadList::session_save, dList));
#define CMD2_EXECUTE(key, flags) \
CMD2_ANY(key, tr1::bind(&rpc::ExecFile::execute_object, &rpc::execFile, tr1::placeholders::_2, flags));
CMD2_EXECUTE ("execute2", rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_throw);
CMD2_EXECUTE ("execute.throw", rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_throw);
CMD2_EXECUTE ("execute.throw.bg", rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_throw | rpc::ExecFile::flag_background);
CMD2_EXECUTE ("execute.nothrow", rpc::ExecFile::flag_expand_tilde);
CMD2_EXECUTE ("execute.nothrow.bg", rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_background);
CMD2_EXECUTE ("execute.raw", rpc::ExecFile::flag_throw);
CMD2_EXECUTE ("execute.raw.bg", rpc::ExecFile::flag_throw | rpc::ExecFile::flag_background);
CMD2_EXECUTE ("execute.raw_nothrow", 0);
CMD2_EXECUTE ("execute.raw_nothrow.bg", rpc::ExecFile::flag_background);
CMD2_EXECUTE ("execute.capture", rpc::ExecFile::flag_throw | rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_capture);
CMD2_EXECUTE ("execute.capture_nothrow", rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_capture);
CMD2_ANY_LIST ("log.open_file", tr1::bind(&apply_log_open_file, tr1::placeholders::_2));
CMD2_ANY_LIST ("log.open_gz_file", tr1::bind(&apply_log_open_gz_file, tr1::placeholders::_2));
CMD2_ANY_LIST ("log.add_output", tr1::bind(&apply_log_add_output, tr1::placeholders::_2));
CMD2_ANY_STRING ("log.execute", tr1::bind(&apply_log, tr1::placeholders::_2, 0));
CMD2_ANY_STRING ("log.vmmap.dump", tr1::bind(&log_vmmap_dump, tr1::placeholders::_2));
CMD2_ANY_STRING_V("log.xmlrpc", tr1::bind(&ThreadWorker::set_xmlrpc_log, worker_thread, tr1::placeholders::_2));
CMD2_ANY_LIST ("file.append", tr1::bind(&cmd_file_append, tr1::placeholders::_2));
// TODO: Convert to new command types:
*rpc::command_base::argument(0) = "placeholder.0";
*rpc::command_base::argument(1) = "placeholder.1";
*rpc::command_base::argument(2) = "placeholder.2";
*rpc::command_base::argument(3) = "placeholder.3";
CMD2_ANY_P("argument.0", tr1::bind(&rpc::command_base::argument_ref, 0));
CMD2_ANY_P("argument.1", tr1::bind(&rpc::command_base::argument_ref, 1));
CMD2_ANY_P("argument.2", tr1::bind(&rpc::command_base::argument_ref, 2));
CMD2_ANY_P("argument.3", tr1::bind(&rpc::command_base::argument_ref, 3));
CMD2_ANY_LIST ("group.insert", tr1::bind(&group_insert, tr1::placeholders::_2));
}
-306
View File
@@ -1,306 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <functional>
#include <cstdio>
#include <unistd.h>
#include <rak/address_info.h>
#include <rak/path.h>
#include <torrent/connection_manager.h>
#include <torrent/tracker.h>
#include <torrent/tracker_list.h>
#include <torrent/torrent.h>
#include <torrent/rate.h>
#include <torrent/data/file_manager.h>
#include <torrent/download/resource_manager.h>
#include <torrent/utils/log.h>
#include <torrent/utils/option_strings.h>
#include "core/download.h"
#include "core/manager.h"
#include "rpc/scgi.h"
#include "ui/root.h"
#include "rpc/parse.h"
#include "rpc/parse_commands.h"
#include "globals.h"
#include "control.h"
#include "command_helpers.h"
namespace tr1 { using namespace std::tr1; }
torrent::Object
apply_encryption(const torrent::Object::list_type& args) {
uint32_t options_mask = torrent::ConnectionManager::encryption_none;
for (torrent::Object::list_const_iterator itr = args.begin(), last = args.end(); itr != last; itr++) {
uint32_t opt = torrent::option_find_string(torrent::OPTION_ENCRYPTION, itr->as_string().c_str());
if (opt == torrent::ConnectionManager::encryption_none)
options_mask = torrent::ConnectionManager::encryption_none;
else
options_mask |= opt;
}
torrent::connection_manager()->set_encryption_options(options_mask);
return torrent::Object();
}
torrent::Object
apply_tos(const torrent::Object::string_type& arg) {
rpc::command_base::value_type value;
if (!rpc::parse_whole_value_nothrow(arg.c_str(), &value, 16, 1))
value = torrent::option_find_string(torrent::OPTION_IP_TOS, arg.c_str());
torrent::connection_manager()->set_priority(value);
return torrent::Object();
}
torrent::Object apply_encoding_list(const std::string& arg) { torrent::encoding_list()->push_back(arg); return torrent::Object(); }
torrent::File*
xmlrpc_find_file(core::Download* download, uint32_t index) {
if (index >= download->file_list()->size_files())
return NULL;
return (*download->file_list())[index];
}
// Ergh... time to update the Tracker API to allow proper ptrs.
torrent::Tracker*
xmlrpc_find_tracker(core::Download* download, uint32_t index) {
if (index >= download->tracker_list()->size())
return NULL;
return download->tracker_list()->at(index);
}
torrent::Peer*
xmlrpc_find_peer(core::Download* download, const torrent::HashString& hash) {
torrent::ConnectionList::iterator itr = download->connection_list()->find(hash.c_str());
if (itr == download->connection_list()->end())
return NULL;
return *itr;
}
void
initialize_xmlrpc() {
rpc::xmlrpc.initialize();
rpc::xmlrpc.slot_find_download() = tr1::bind(&core::DownloadList::find_hex_ptr, control->core()->download_list(), tr1::placeholders::_1);
rpc::xmlrpc.slot_find_file() = tr1::bind(&xmlrpc_find_file, tr1::placeholders::_1, tr1::placeholders::_2);
rpc::xmlrpc.slot_find_tracker() = tr1::bind(&xmlrpc_find_tracker, tr1::placeholders::_1, tr1::placeholders::_2);
rpc::xmlrpc.slot_find_peer() = tr1::bind(&xmlrpc_find_peer, tr1::placeholders::_1, tr1::placeholders::_2);
unsigned int count = 0;
for (rpc::CommandMap::const_iterator itr = rpc::commands.begin(), last = rpc::commands.end(); itr != last; itr++, count++) {
if (!(itr->second.m_flags & rpc::CommandMap::flag_public_xmlrpc))
continue;
rpc::xmlrpc.insert_command(itr->first, itr->second.m_parm, itr->second.m_doc);
}
lt_log_print(torrent::LOG_RPC_EVENTS, "XMLRPC initialized with %u functions.", count);
}
torrent::Object
apply_scgi(const std::string& arg, int type) {
if (worker_thread->scgi() != NULL)
throw torrent::input_error("SCGI already enabled.");
if (!rpc::xmlrpc.is_valid())
initialize_xmlrpc();
rpc::SCgi* scgi = new rpc::SCgi;
rak::address_info* ai = NULL;
rak::socket_address sa;
rak::socket_address* saPtr;
try {
int port, err;
char dummy;
char address[1024];
std::string path;
switch (type) {
case 1:
if (std::sscanf(arg.c_str(), ":%i%c", &port, &dummy) == 1) {
sa.sa_inet()->clear();
saPtr = &sa;
lt_log_print(torrent::LOG_RPC_EVENTS,
"The SCGI socket has not been bound to any address and likely poses a security risk.");
} else if (std::sscanf(arg.c_str(), "%1023[^:]:%i%c", address, &port, &dummy) == 2) {
if ((err = rak::address_info::get_address_info(address, PF_INET, SOCK_STREAM, &ai)) != 0)
throw torrent::input_error("Could not bind address: " + std::string(rak::address_info::strerror(err)) + ".");
saPtr = ai->address();
lt_log_print(torrent::LOG_RPC_EVENTS,
"The SCGI socket is bound to a specific network device yet may still pose a security risk, consider using 'scgi_local'.");
} else {
throw torrent::input_error("Could not parse address.");
}
if (port <= 0 || port >= (1 << 16))
throw torrent::input_error("Invalid port number.");
saPtr->set_port(port);
scgi->open_port(saPtr, saPtr->length(), rpc::call_command_value("network.scgi.dont_route"));
break;
case 2:
default:
path = rak::path_expand(arg);
unlink(path.c_str());
scgi->open_named(path);
break;
}
if (ai != NULL) rak::address_info::free_address_info(ai);
} catch (torrent::local_error& e) {
if (ai != NULL) rak::address_info::free_address_info(ai);
delete scgi;
throw torrent::input_error(e.what());
}
worker_thread->set_scgi(scgi);
return torrent::Object();
}
torrent::Object
apply_xmlrpc_dialect(const std::string& arg) {
int value;
if (arg == "i8")
value = rpc::XmlRpc::dialect_i8;
else if (arg == "apache")
value = rpc::XmlRpc::dialect_apache;
else if (arg == "generic")
value = rpc::XmlRpc::dialect_generic;
else
value = -1;
rpc::xmlrpc.set_dialect(value);
return torrent::Object();
}
void
initialize_command_network() {
torrent::ConnectionManager* cm = torrent::connection_manager();
torrent::FileManager* fileManager = torrent::file_manager();
core::CurlStack* httpStack = control->core()->http_stack();
CMD2_ANY ("strings.connection_type", tr1::bind(&torrent::option_list_strings, torrent::OPTION_CONNECTION_TYPE));
CMD2_ANY ("strings.encryption", tr1::bind(&torrent::option_list_strings, torrent::OPTION_ENCRYPTION));
// CMD2_ANY_STRING ("encoding_list", tr1::bind(&apply_encoding_list, tr1::placeholders::_2));
CMD2_ANY_STRING ("encoding.add", tr1::bind(&apply_encoding_list, tr1::placeholders::_2));
// Isn't port_open used?
CMD2_VAR_BOOL ("network.port_open", true);
CMD2_VAR_BOOL ("network.port_random", true);
CMD2_VAR_STRING ("network.port_range", "6881-6999");
CMD2_ANY ("network.listen.port", tr1::bind(&torrent::ConnectionManager::listen_port, cm));
CMD2_ANY ("network.listen.backlog", tr1::bind(&torrent::ConnectionManager::listen_backlog, cm));
CMD2_ANY_VALUE_V ("network.listen.backlog.set", tr1::bind(&torrent::ConnectionManager::set_listen_backlog, cm, tr1::placeholders::_2));
CMD2_VAR_BOOL ("protocol.pex", true);
CMD2_ANY_LIST ("protocol.encryption.set", tr1::bind(&apply_encryption, tr1::placeholders::_2));
CMD2_VAR_STRING ("protocol.connection.leech", "leech");
CMD2_VAR_STRING ("protocol.connection.seed", "seed");
CMD2_VAR_STRING ("protocol.choke_heuristics.up.leech", "upload_leech");
CMD2_VAR_STRING ("protocol.choke_heuristics.up.seed", "upload_leech");
CMD2_VAR_STRING ("protocol.choke_heuristics.down.leech", "download_leech");
CMD2_VAR_STRING ("protocol.choke_heuristics.down.seed", "download_leech");
CMD2_ANY ("network.http.capath", tr1::bind(&core::CurlStack::http_capath, httpStack));
CMD2_ANY_STRING_V("network.http.capath.set", tr1::bind(&core::CurlStack::set_http_capath, httpStack, tr1::placeholders::_2));
CMD2_ANY ("network.http.cacert", tr1::bind(&core::CurlStack::http_cacert, httpStack));
CMD2_ANY_STRING_V("network.http.cacert.set", tr1::bind(&core::CurlStack::set_http_cacert, httpStack, tr1::placeholders::_2));
CMD2_ANY ("network.http.proxy_address", tr1::bind(&core::CurlStack::http_proxy, httpStack));
CMD2_ANY_STRING_V("network.http.proxy_address.set", tr1::bind(&core::CurlStack::set_http_proxy, httpStack, tr1::placeholders::_2));
CMD2_ANY ("network.http.max_open", tr1::bind(&core::CurlStack::max_active, httpStack));
CMD2_ANY_VALUE_V ("network.http.max_open.set", tr1::bind(&core::CurlStack::set_max_active, httpStack, tr1::placeholders::_2));
CMD2_ANY ("network.http.ssl_verify_peer", tr1::bind(&core::CurlStack::ssl_verify_peer, httpStack));
CMD2_ANY_VALUE_V ("network.http.ssl_verify_peer.set", tr1::bind(&core::CurlStack::set_ssl_verify_peer, httpStack, tr1::placeholders::_2));
CMD2_ANY ("network.http.dns_cache_timeout", tr1::bind(&core::CurlStack::dns_timeout, httpStack));
CMD2_ANY_VALUE_V ("network.http.dns_cache_timeout.set", tr1::bind(&core::CurlStack::set_dns_timeout, httpStack, tr1::placeholders::_2));
CMD2_ANY ("network.send_buffer.size", tr1::bind(&torrent::ConnectionManager::send_buffer_size, cm));
CMD2_ANY_VALUE_V ("network.send_buffer.size.set", tr1::bind(&torrent::ConnectionManager::set_send_buffer_size, cm, tr1::placeholders::_2));
CMD2_ANY ("network.receive_buffer.size", tr1::bind(&torrent::ConnectionManager::receive_buffer_size, cm));
CMD2_ANY_VALUE_V ("network.receive_buffer.size.set", tr1::bind(&torrent::ConnectionManager::set_receive_buffer_size, cm, tr1::placeholders::_2));
CMD2_ANY_STRING ("network.tos.set", tr1::bind(&apply_tos, tr1::placeholders::_2));
CMD2_ANY ("network.bind_address", tr1::bind(&core::Manager::bind_address, control->core()));
CMD2_ANY_STRING_V("network.bind_address.set", tr1::bind(&core::Manager::set_bind_address, control->core(), tr1::placeholders::_2));
CMD2_ANY ("network.local_address", tr1::bind(&core::Manager::local_address, control->core()));
CMD2_ANY_STRING_V("network.local_address.set", tr1::bind(&core::Manager::set_local_address, control->core(), tr1::placeholders::_2));
CMD2_ANY ("network.proxy_address", tr1::bind(&core::Manager::proxy_address, control->core()));
CMD2_ANY_STRING_V("network.proxy_address.set", tr1::bind(&core::Manager::set_proxy_address, control->core(), tr1::placeholders::_2));
CMD2_ANY ("network.max_open_files", tr1::bind(&torrent::FileManager::max_open_files, fileManager));
CMD2_ANY_VALUE_V ("network.max_open_files.set", tr1::bind(&torrent::FileManager::set_max_open_files, fileManager, tr1::placeholders::_2));
CMD2_ANY ("network.open_sockets", tr1::bind(&torrent::ConnectionManager::size, cm));
CMD2_ANY ("network.max_open_sockets", tr1::bind(&torrent::ConnectionManager::max_size, cm));
CMD2_ANY_VALUE_V ("network.max_open_sockets.set", tr1::bind(&torrent::ConnectionManager::set_max_size, cm, tr1::placeholders::_2));
CMD2_ANY_STRING ("network.scgi.open_port", tr1::bind(&apply_scgi, tr1::placeholders::_2, 1));
CMD2_ANY_STRING ("network.scgi.open_local", tr1::bind(&apply_scgi, tr1::placeholders::_2, 2));
CMD2_VAR_BOOL ("network.scgi.dont_route", false);
CMD2_ANY_STRING ("network.xmlrpc.dialect.set", tr1::bind(&apply_xmlrpc_dialect, tr1::placeholders::_2));
CMD2_ANY ("network.xmlrpc.size_limit", tr1::bind(&rpc::XmlRpc::size_limit));
CMD2_ANY_VALUE_V ("network.xmlrpc.size_limit.set", tr1::bind(&rpc::XmlRpc::set_size_limit, tr1::placeholders::_2));
}
-133
View File
@@ -1,133 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <rak/error_number.h>
#include <rak/path.h>
#include <rak/socket_address.h>
#include <rak/string_manip.h>
#include <torrent/bitfield.h>
#include <torrent/rate.h>
#include <torrent/peer/connection_list.h>
#include <torrent/peer/peer.h>
#include <torrent/peer/peer_info.h>
#include "core/manager.h"
#include "display/utils.h"
#include "globals.h"
#include "control.h"
#include "command_helpers.h"
torrent::Object
retrieve_p_id(torrent::Peer* peer) {
const torrent::HashString* hashString = &peer->id();
return rak::transform_hex(hashString->begin(), hashString->end());
}
torrent::Object
retrieve_p_id_html(torrent::Peer* peer) {
const torrent::HashString* hashString = &peer->id();
return rak::copy_escape_html(hashString->begin(), hashString->end());
}
torrent::Object
retrieve_p_address(torrent::Peer* peer) {
return rak::socket_address::cast_from(peer->peer_info()->socket_address())->address_str();
}
torrent::Object
retrieve_p_port(torrent::Peer* peer) {
return rak::socket_address::cast_from(peer->peer_info()->socket_address())->port();
}
torrent::Object
retrieve_p_client_version(torrent::Peer* peer) {
char buf[128];
display::print_client_version(buf, buf + 128, peer->peer_info()->client_info());
return std::string(buf);
}
torrent::Object
retrieve_p_options_str(torrent::Peer* peer) {
return rak::transform_hex(peer->peer_info()->options(), peer->peer_info()->options() + 8);
}
torrent::Object
retrieve_p_completed_percent(torrent::Peer* peer) {
return (100 * peer->bitfield()->size_set()) / peer->bitfield()->size_bits();
}
void
initialize_command_peer() {
CMD2_PEER("p.id", tr1::bind(&retrieve_p_id, tr1::placeholders::_1));
CMD2_PEER("p.id_html", tr1::bind(&retrieve_p_id_html, tr1::placeholders::_1));
CMD2_PEER("p.client_version", tr1::bind(&retrieve_p_client_version, tr1::placeholders::_1));
CMD2_PEER("p.options_str", tr1::bind(&retrieve_p_options_str, tr1::placeholders::_1));
CMD2_PEER("p.is_encrypted", tr1::bind(&torrent::Peer::is_encrypted, tr1::placeholders::_1));
CMD2_PEER("p.is_incoming", tr1::bind(&torrent::Peer::is_incoming, tr1::placeholders::_1));
CMD2_PEER("p.is_obfuscated", tr1::bind(&torrent::Peer::is_obfuscated, tr1::placeholders::_1));
CMD2_PEER("p.is_snubbed", tr1::bind(&torrent::Peer::is_snubbed, tr1::placeholders::_1));
CMD2_PEER("p.is_unwanted", tr1::bind(&torrent::PeerInfo::is_unwanted, tr1::bind(&torrent::Peer::peer_info, tr1::placeholders::_1)));
CMD2_PEER("p.is_preferred", tr1::bind(&torrent::PeerInfo::is_preferred, tr1::bind(&torrent::Peer::peer_info, tr1::placeholders::_1)));
CMD2_PEER("p.address", tr1::bind(&retrieve_p_address, tr1::placeholders::_1));
CMD2_PEER("p.port", tr1::bind(&retrieve_p_port, tr1::placeholders::_1));
CMD2_PEER("p.completed_percent", tr1::bind(&retrieve_p_completed_percent, tr1::placeholders::_1));
CMD2_PEER("p.up_rate", tr1::bind(&torrent::Rate::rate, tr1::bind(&torrent::Peer::up_rate, tr1::placeholders::_1)));
CMD2_PEER("p.up_total", tr1::bind(&torrent::Rate::total, tr1::bind(&torrent::Peer::up_rate, tr1::placeholders::_1)));
CMD2_PEER("p.down_rate", tr1::bind(&torrent::Rate::rate, tr1::bind(&torrent::Peer::down_rate, tr1::placeholders::_1)));
CMD2_PEER("p.down_total", tr1::bind(&torrent::Rate::total, tr1::bind(&torrent::Peer::down_rate, tr1::placeholders::_1)));
CMD2_PEER("p.peer_rate", tr1::bind(&torrent::Rate::rate, tr1::bind(&torrent::Peer::peer_rate, tr1::placeholders::_1)));
CMD2_PEER("p.peer_total", tr1::bind(&torrent::Rate::total, tr1::bind(&torrent::Peer::peer_rate, tr1::placeholders::_1)));
CMD2_PEER ("p.snubbed", tr1::bind(&torrent::Peer::is_snubbed, tr1::placeholders::_1));
CMD2_PEER_VALUE_V("p.snubbed.set", tr1::bind(&torrent::Peer::set_snubbed, tr1::placeholders::_1, tr1::placeholders::_2));
CMD2_PEER ("p.banned", tr1::bind(&torrent::Peer::is_banned, tr1::placeholders::_1));
CMD2_PEER_VALUE_V("p.banned.set", tr1::bind(&torrent::Peer::set_banned, tr1::placeholders::_1, tr1::placeholders::_2));
CMD2_PEER_V("p.disconnect", tr1::bind(&torrent::Peer::disconnect, tr1::placeholders::_1, 0));
CMD2_PEER_V("p.disconnect_delayed", tr1::bind(&torrent::Peer::disconnect, tr1::placeholders::_1, torrent::ConnectionList::disconnect_delayed));
}
-121
View File
@@ -1,121 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <sys/types.h>
#include "core/manager.h"
#include "core/download.h"
#include "core/download_list.h"
#include "core/view.h"
#include "core/view_manager.h"
#include "globals.h"
#include "control.h"
#include "command_helpers.h"
torrent::Object
cmd_scheduler_simple_added(core::Download* download) {
unsigned int numActive = (*control->view_manager()->find("active"))->size_visible();
int64_t maxActive = rpc::call_command("scheduler.max_active", torrent::Object()).as_value();
if (numActive < (uint64_t)maxActive)
control->core()->download_list()->resume(download);
return torrent::Object();
}
torrent::Object
cmd_scheduler_simple_removed(core::Download* download) {
control->core()->download_list()->pause(download);
core::View* viewActive = *control->view_manager()->find("active");
int64_t maxActive = rpc::call_command("scheduler.max_active", torrent::Object()).as_value();
if ((int64_t)viewActive->size_visible() >= maxActive)
return torrent::Object();
// The 'started' view contains all the views we may choose amongst.
core::View* viewStarted = *control->view_manager()->find("started");
for (core::View::iterator itr = viewStarted->begin_visible(), last = viewStarted->end_visible(); itr != last; itr++) {
if ((*itr)->is_active())
continue;
control->core()->download_list()->resume(*itr);
}
return torrent::Object();
}
torrent::Object
cmd_scheduler_simple_update(core::Download* download) {
core::View* viewActive = *control->view_manager()->find("active");
core::View* viewStarted = *control->view_manager()->find("started");
unsigned int numActive = viewActive->size_visible();
uint64_t maxActive = rpc::call_command("scheduler.max_active", torrent::Object()).as_value();
if (viewActive->size_visible() < maxActive) {
for (core::View::iterator itr = viewStarted->begin_visible(), last = viewStarted->end_visible(); itr != last; itr++) {
if ((*itr)->is_active())
continue;
control->core()->download_list()->resume(*itr);
if (++numActive >= maxActive)
break;
}
} else if (viewActive->size_visible() > maxActive) {
while (viewActive->size_visible() > maxActive)
control->core()->download_list()->pause(*viewActive->begin_visible());
}
return torrent::Object();
}
void
initialize_command_scheduler() {
CMD2_VAR_VALUE("scheduler.max_active", int64_t(-1));
CMD2_DL("scheduler.simple.added", tr1::bind(&cmd_scheduler_simple_added, tr1::placeholders::_1));
CMD2_DL("scheduler.simple.removed", tr1::bind(&cmd_scheduler_simple_removed, tr1::placeholders::_1));
CMD2_DL("scheduler.simple.update", tr1::bind(&cmd_scheduler_simple_update, tr1::placeholders::_1));
}
-226
View File
@@ -1,226 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <cstdio>
#include <rak/address_info.h>
#include <torrent/throttle.h>
#include <torrent/rate.h>
#include <torrent/download/resource_manager.h>
#include "core/manager.h"
#include "ui/root.h"
#include "rpc/parse.h"
#include "rpc/parse_commands.h"
#include "globals.h"
#include "control.h"
#include "command_helpers.h"
std::pair<uint32_t, uint32_t>
parse_address_range(const torrent::Object::list_type& args, torrent::Object::list_type::const_iterator itr) {
unsigned int prefixWidth, ret;
char dummy;
char host[1024];
rak::address_info* ai;
ret = std::sscanf(itr->as_string().c_str(), "%1023[^/]/%d%c", host, &prefixWidth, &dummy);
if (ret < 1 || rak::address_info::get_address_info(host, PF_INET, SOCK_STREAM, &ai) != 0)
throw torrent::input_error("Could not resolve host.");
uint32_t begin, end;
rak::socket_address sa;
sa.copy(*ai->address(), ai->length());
begin = end = sa.sa_inet()->address_h();
rak::address_info::free_address_info(ai);
if (ret == 2) {
if (++itr != args.end())
throw torrent::input_error("Cannot specify both network and range end.");
uint32_t netmask = std::numeric_limits<uint32_t>::max() << (32 - prefixWidth);
if (prefixWidth >= 32 || sa.sa_inet()->address_h() & ~netmask)
throw torrent::input_error("Invalid address/prefix.");
end = sa.sa_inet()->address_h() | ~netmask;
} else if (++itr != args.end()) {
if (rak::address_info::get_address_info(itr->as_string().c_str(), PF_INET, SOCK_STREAM, &ai) != 0)
throw torrent::input_error("Could not resolve host.");
sa.copy(*ai->address(), ai->length());
rak::address_info::free_address_info(ai);
end = sa.sa_inet()->address_h();
}
// convert to [begin, end) making sure the end doesn't overflow
// (this precludes 255.255.255.255 from ever matching, but that's not a real IP anyway)
return std::make_pair((uint32_t)begin, (uint32_t)std::max(end, end + 1));
}
torrent::Object
apply_throttle(const torrent::Object::list_type& args, bool up) {
torrent::Object::list_const_iterator argItr = args.begin();
const std::string& name = argItr->as_string();
if (name.empty() || name == "NULL")
throw torrent::input_error("Invalid throttle name.");
if ((++argItr)->as_string().empty())
return torrent::Object();
int64_t rate;
rpc::parse_whole_value_nothrow(argItr->as_string().c_str(), &rate);
if (rate < 0)
throw torrent::input_error("Throttle rate must be non-negative.");
core::ThrottleMap::iterator itr = control->core()->throttles().find(name);
if (itr == control->core()->throttles().end())
itr = control->core()->throttles().insert(std::make_pair(name, torrent::ThrottlePair(NULL, NULL))).first;
torrent::Throttle*& throttle = up ? itr->second.first : itr->second.second;
if (rate != 0 && throttle == NULL)
throttle = (up ? torrent::up_throttle_global() : torrent::down_throttle_global())->create_slave();
if (throttle != NULL)
throttle->set_max_rate(rate * 1024);
return torrent::Object();
}
static const int throttle_info_up = (1 << 0);
static const int throttle_info_down = (1 << 1);
static const int throttle_info_max = (1 << 2);
static const int throttle_info_rate = (1 << 3);
torrent::Object
retrieve_throttle_info(const torrent::Object::string_type& name, int flags) {
core::ThrottleMap::iterator itr = control->core()->throttles().find(name);
torrent::ThrottlePair throttles = itr == control->core()->throttles().end() ? torrent::ThrottlePair(NULL, NULL) : itr->second;
torrent::Throttle* throttle = flags & throttle_info_down ? throttles.second : throttles.first;
torrent::Throttle* global = flags & throttle_info_down ? torrent::down_throttle_global() : torrent::up_throttle_global();
if (throttle == NULL && name.empty())
throttle = global;
if (throttle == NULL)
return flags & throttle_info_rate ? (int64_t)0 : (int64_t)-1;
else if (!throttle->is_throttled() || !global->is_throttled())
return (int64_t)0;
else if (flags & throttle_info_rate)
return (int64_t)throttle->rate()->rate();
else
return (int64_t)throttle->max_rate();
}
torrent::Object
apply_address_throttle(const torrent::Object::list_type& args) {
if (args.size() < 2 || args.size() > 3)
throw torrent::input_error("Incorrect number of arguments.");
std::pair<uint32_t, uint32_t> range = parse_address_range(args, ++args.begin());
core::ThrottleMap::iterator throttleItr = control->core()->throttles().find(args.begin()->as_string().c_str());
if (throttleItr == control->core()->throttles().end())
throw torrent::input_error("Throttle not found.");
control->core()->set_address_throttle(range.first, range.second, throttleItr->second);
return torrent::Object();
}
torrent::Object
throttle_update(const char* variable, int64_t value) {
rpc::commands.call_command(variable, value);
control->ui()->adjust_up_throttle(0);
control->ui()->adjust_down_throttle(0);
return torrent::Object();
}
void
initialize_command_throttle() {
CMD2_ANY ("throttle.unchoked_uploads", tr1::bind(&torrent::ResourceManager::currently_upload_unchoked, torrent::resource_manager()));
CMD2_ANY ("throttle.unchoked_downloads", tr1::bind(&torrent::ResourceManager::currently_download_unchoked, torrent::resource_manager()));
CMD2_VAR_VALUE ("throttle.min_peers.normal", 100);
CMD2_VAR_VALUE ("throttle.max_peers.normal", 200);
CMD2_VAR_VALUE ("throttle.min_peers.seed", -1);
CMD2_VAR_VALUE ("throttle.max_peers.seed", -1);
CMD2_VAR_VALUE ("throttle.min_uploads", 0);
CMD2_VAR_VALUE ("throttle.max_uploads", 50);
CMD2_VAR_VALUE ("throttle.min_downloads", 0);
CMD2_VAR_VALUE ("throttle.max_downloads", 50);
CMD2_VAR_VALUE ("throttle.max_uploads.div._val", 1);
CMD2_VAR_VALUE ("throttle.max_uploads.global._val", 0);
CMD2_VAR_VALUE ("throttle.max_downloads.div._val", 1);
CMD2_VAR_VALUE ("throttle.max_downloads.global._val", 0);
CMD2_REDIRECT_GENERIC("throttle.max_uploads.div", "throttle.max_uploads.div._val");
CMD2_REDIRECT_GENERIC("throttle.max_uploads.global", "throttle.max_uploads.global._val");
CMD2_REDIRECT_GENERIC("throttle.max_downloads.div", "throttle.max_downloads.div._val");
CMD2_REDIRECT_GENERIC("throttle.max_downloads.global", "throttle.max_downloads.global._val");
CMD2_ANY_VALUE ("throttle.max_uploads.div.set", tr1::bind(&throttle_update, "throttle.max_uploads.div._val.set", tr1::placeholders::_2));
CMD2_ANY_VALUE ("throttle.max_uploads.global.set", tr1::bind(&throttle_update, "throttle.max_uploads.global._val.set", tr1::placeholders::_2));
CMD2_ANY_VALUE ("throttle.max_downloads.div.set", tr1::bind(&throttle_update, "throttle.max_downloads.div._val.set", tr1::placeholders::_2));
CMD2_ANY_VALUE ("throttle.max_downloads.global.set", tr1::bind(&throttle_update, "throttle.max_downloads.global._val.set", tr1::placeholders::_2));
// TODO: Move the logic into some libtorrent function.
CMD2_ANY ("throttle.global_up.rate", tr1::bind(&torrent::Rate::rate, torrent::up_rate()));
CMD2_ANY ("throttle.global_up.total", tr1::bind(&torrent::Rate::total, torrent::up_rate()));
CMD2_ANY ("throttle.global_up.max_rate", tr1::bind(&torrent::Throttle::max_rate, torrent::up_throttle_global()));
CMD2_ANY_VALUE_V ("throttle.global_up.max_rate.set", tr1::bind(&ui::Root::set_up_throttle_i64, control->ui(), tr1::placeholders::_2));
CMD2_ANY_VALUE_KB("throttle.global_up.max_rate.set_kb", tr1::bind(&ui::Root::set_up_throttle_i64, control->ui(), tr1::placeholders::_2));
CMD2_ANY ("throttle.global_down.rate", tr1::bind(&torrent::Rate::rate, torrent::down_rate()));
CMD2_ANY ("throttle.global_down.total", tr1::bind(&torrent::Rate::total, torrent::down_rate()));
CMD2_ANY ("throttle.global_down.max_rate", tr1::bind(&torrent::Throttle::max_rate, torrent::down_throttle_global()));
CMD2_ANY_VALUE_V ("throttle.global_down.max_rate.set", tr1::bind(&ui::Root::set_down_throttle_i64, control->ui(), tr1::placeholders::_2));
CMD2_ANY_VALUE_KB("throttle.global_down.max_rate.set_kb", tr1::bind(&ui::Root::set_down_throttle_i64, control->ui(), tr1::placeholders::_2));
// Temporary names, need to change this to accept real rates rather
// than kB.
CMD2_ANY_LIST ("throttle.up", tr1::bind(&apply_throttle, tr1::placeholders::_2, true));
CMD2_ANY_LIST ("throttle.down", tr1::bind(&apply_throttle, tr1::placeholders::_2, false));
CMD2_ANY_LIST ("throttle.ip", tr1::bind(&apply_address_throttle, tr1::placeholders::_2));
CMD2_ANY_STRING ("throttle.up.max", tr1::bind(&retrieve_throttle_info, tr1::placeholders::_2, throttle_info_up | throttle_info_max));
CMD2_ANY_STRING ("throttle.up.rate", tr1::bind(&retrieve_throttle_info, tr1::placeholders::_2, throttle_info_up | throttle_info_rate));
CMD2_ANY_STRING ("throttle.down.max", tr1::bind(&retrieve_throttle_info, tr1::placeholders::_2, throttle_info_down | throttle_info_max));
CMD2_ANY_STRING ("throttle.down.rate", tr1::bind(&retrieve_throttle_info, tr1::placeholders::_2, throttle_info_down | throttle_info_rate));
}
-169
View File
@@ -1,169 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <cstdio>
#include <rak/address_info.h>
#include <rak/error_number.h>
#include <torrent/dht_manager.h>
#include <torrent/tracker.h>
#include <torrent/utils/log.h>
#include "core/download.h"
#include "core/manager.h"
#include "globals.h"
#include "control.h"
#include "command_helpers.h"
#include "core/dht_manager.h"
void
tracker_set_enabled(torrent::Tracker* tracker, bool state) {
if (state)
tracker->enable();
else
tracker->disable();
}
struct call_add_node_t {
call_add_node_t(int port) : m_port(port) { }
void operator() (const sockaddr* sa, int err) {
if (sa == NULL) {
lt_log_print(torrent::LOG_DHT_WARN, "Could not resolve host.");
} else {
torrent::dht_manager()->add_node(sa, m_port);
}
}
int m_port;
};
torrent::Object
apply_dht_add_node(const std::string& arg) {
if (!torrent::dht_manager()->is_valid())
throw torrent::input_error("DHT not enabled.");
int port, ret;
char dummy;
char host[1024];
ret = std::sscanf(arg.c_str(), "%1023[^:]:%i%c", host, &port, &dummy);
if (ret == 1)
port = 6881;
else if (ret != 2)
throw torrent::input_error("Could not parse host.");
if (port < 1 || port > 65535)
throw torrent::input_error("Invalid port number.");
torrent::connection_manager()->resolver()(host, (int)rak::socket_address::pf_inet, SOCK_DGRAM, call_add_node_t(port));
return torrent::Object();
}
torrent::Object
apply_enable_trackers(int64_t arg) {
for (core::Manager::DListItr itr = control->core()->download_list()->begin(), last = control->core()->download_list()->end(); itr != last; ++itr) {
std::for_each((*itr)->tracker_list()->begin(), (*itr)->tracker_list()->end(),
arg ? std::mem_fun(&torrent::Tracker::enable) : std::mem_fun(&torrent::Tracker::disable));
if (arg && !rpc::call_command_value("trackers.use_udp"))
(*itr)->enable_udp_trackers(false);
}
return torrent::Object();
}
void
initialize_command_tracker() {
CMD2_TRACKER ("t.is_open", tr1::bind(&torrent::Tracker::is_busy, tr1::placeholders::_1));
CMD2_TRACKER ("t.is_enabled", tr1::bind(&torrent::Tracker::is_enabled, tr1::placeholders::_1));
CMD2_TRACKER ("t.is_usable", tr1::bind(&torrent::Tracker::is_usable, tr1::placeholders::_1));
CMD2_TRACKER ("t.is_busy", tr1::bind(&torrent::Tracker::is_busy, tr1::placeholders::_1));
CMD2_TRACKER ("t.is_extra_tracker", tr1::bind(&torrent::Tracker::is_extra_tracker, tr1::placeholders::_1));
CMD2_TRACKER ("t.can_scrape", tr1::bind(&torrent::Tracker::can_scrape, tr1::placeholders::_1));
CMD2_TRACKER_V ("t.enable", tr1::bind(&torrent::Tracker::enable, tr1::placeholders::_1));
CMD2_TRACKER_V ("t.disable", tr1::bind(&torrent::Tracker::disable, tr1::placeholders::_1));
CMD2_TRACKER_VALUE_V("t.is_enabled.set", tr1::bind(&tracker_set_enabled, tr1::placeholders::_1, tr1::placeholders::_2));
CMD2_TRACKER ("t.url", tr1::bind(&torrent::Tracker::url, tr1::placeholders::_1));
CMD2_TRACKER ("t.group", tr1::bind(&torrent::Tracker::group, tr1::placeholders::_1));
CMD2_TRACKER ("t.type", tr1::bind(&torrent::Tracker::type, tr1::placeholders::_1));
CMD2_TRACKER ("t.id", tr1::bind(&torrent::Tracker::tracker_id, tr1::placeholders::_1));
CMD2_TRACKER ("t.latest_event", tr1::bind(&torrent::Tracker::latest_event, tr1::placeholders::_1));
CMD2_TRACKER ("t.latest_new_peers", tr1::bind(&torrent::Tracker::latest_new_peers, tr1::placeholders::_1));
CMD2_TRACKER ("t.latest_sum_peers", tr1::bind(&torrent::Tracker::latest_sum_peers, tr1::placeholders::_1));
// Time since last connection, connection attempt.
CMD2_TRACKER ("t.normal_interval", tr1::bind(&torrent::Tracker::normal_interval, tr1::placeholders::_1));
CMD2_TRACKER ("t.min_interval", tr1::bind(&torrent::Tracker::min_interval, tr1::placeholders::_1));
CMD2_TRACKER ("t.activity_time_next", tr1::bind(&torrent::Tracker::activity_time_next, tr1::placeholders::_1));
CMD2_TRACKER ("t.activity_time_last", tr1::bind(&torrent::Tracker::activity_time_last, tr1::placeholders::_1));
CMD2_TRACKER ("t.success_time_next", tr1::bind(&torrent::Tracker::success_time_next, tr1::placeholders::_1));
CMD2_TRACKER ("t.success_time_last", tr1::bind(&torrent::Tracker::success_time_last, tr1::placeholders::_1));
CMD2_TRACKER ("t.success_counter", tr1::bind(&torrent::Tracker::success_counter, tr1::placeholders::_1));
CMD2_TRACKER ("t.failed_time_next", tr1::bind(&torrent::Tracker::failed_time_next, tr1::placeholders::_1));
CMD2_TRACKER ("t.failed_time_last", tr1::bind(&torrent::Tracker::failed_time_last, tr1::placeholders::_1));
CMD2_TRACKER ("t.failed_counter", tr1::bind(&torrent::Tracker::failed_counter, tr1::placeholders::_1));
CMD2_TRACKER ("t.scrape_time_last", tr1::bind(&torrent::Tracker::scrape_time_last, tr1::placeholders::_1));
CMD2_TRACKER ("t.scrape_counter", tr1::bind(&torrent::Tracker::scrape_counter, tr1::placeholders::_1));
CMD2_TRACKER ("t.scrape_complete", tr1::bind(&torrent::Tracker::scrape_complete, tr1::placeholders::_1));
CMD2_TRACKER ("t.scrape_incomplete", tr1::bind(&torrent::Tracker::scrape_incomplete, tr1::placeholders::_1));
CMD2_TRACKER ("t.scrape_downloaded", tr1::bind(&torrent::Tracker::scrape_downloaded, tr1::placeholders::_1));
CMD2_ANY_VALUE ("trackers.enable", tr1::bind(&apply_enable_trackers, int64_t(1)));
CMD2_ANY_VALUE ("trackers.disable", tr1::bind(&apply_enable_trackers, int64_t(0)));
CMD2_VAR_VALUE ("trackers.numwant", -1);
CMD2_VAR_BOOL ("trackers.use_udp", true);
CMD2_ANY_STRING_V ("dht.mode.set", tr1::bind(&core::DhtManager::set_mode, control->dht_manager(), tr1::placeholders::_2));
CMD2_VAR_VALUE ("dht.port", int64_t(6881));
CMD2_ANY_STRING ("dht.add_node", tr1::bind(&apply_dht_add_node, tr1::placeholders::_2));
CMD2_ANY ("dht.statistics", tr1::bind(&core::DhtManager::dht_statistics, control->dht_manager()));
CMD2_ANY ("dht.throttle.name", tr1::bind(&core::DhtManager::throttle_name, control->dht_manager()));
CMD2_ANY_STRING_V ("dht.throttle.name.set", tr1::bind(&core::DhtManager::set_throttle_name, control->dht_manager(), tr1::placeholders::_2));
}
-581
View File
@@ -1,581 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <sys/types.h>
#include <ctime>
#include <rak/functional.h>
#include <rak/functional_fun.h>
#include "core/manager.h"
#include "core/view_manager.h"
#include "ui/root.h"
#include "ui/download_list.h"
#include "rpc/parse.h"
#include "globals.h"
#include "control.h"
#include "command_helpers.h"
typedef void (core::ViewManager::*view_event_slot)(const std::string&, const torrent::Object&);
torrent::Object
apply_view_filter_on(const torrent::Object::list_type& args) {
if (args.size() < 1)
throw torrent::input_error("Too few arguments.");
const std::string& name = args.front().as_string();
if (name.empty())
throw torrent::input_error("First argument must be a string.");
core::ViewManager::filter_args filterArgs;
for (torrent::Object::list_const_iterator itr = ++args.begin(), last = args.end(); itr != last; itr++)
filterArgs.push_back(itr->as_string());
control->view_manager()->set_filter_on(name, filterArgs);
return torrent::Object();
}
torrent::Object
apply_view_event(view_event_slot viewFilterSlot, const torrent::Object::list_type& args) {
if (args.size() != 2)
throw torrent::input_error("Wrong argument count.");
(control->view_manager()->*viewFilterSlot)(args.front().as_string(), args.back());
return torrent::Object();
}
torrent::Object
apply_view_sort(const torrent::Object::list_type& args) {
if (args.size() <= 0 || args.size() > 2)
throw torrent::input_error("Wrong argument count.");
const std::string& name = args.front().as_string();
if (name.empty())
throw torrent::input_error("First argument must be a string.");
int32_t value = 0;
if (args.size() == 2)
value = rpc::convert_to_value(args.back());
control->view_manager()->sort(name, value);
return torrent::Object();
}
torrent::Object
apply_view_list() {
torrent::Object rawResult = torrent::Object::create_list();
torrent::Object::list_type& result = rawResult.as_list();
for (core::ViewManager::const_iterator itr = control->view_manager()->begin(), last = control->view_manager()->end(); itr != last; itr++)
result.push_back((*itr)->name());
return rawResult;
}
torrent::Object
apply_view_set(const torrent::Object::list_type& args) {
if (args.size() != 2)
throw torrent::input_error("Wrong argument count.");
core::ViewManager::iterator itr = control->view_manager()->find(args.back().as_string());
if (itr == control->view_manager()->end())
throw torrent::input_error("Could not find view \"" + args.back().as_string() + "\".");
// if (args.front().as_string() == "main")
// control->ui()->download_list()->set_view(*itr);
// else
throw torrent::input_error("No such target.");
}
torrent::Object
apply_print(rpc::target_type target, const torrent::Object& rawArgs) {
char buffer[1024];
rpc::print_object(buffer, buffer + 1024, &rawArgs, 0);
control->core()->push_log(buffer);
return torrent::Object();
}
torrent::Object
apply_cat(rpc::target_type target, const torrent::Object& rawArgs) {
std::string result;
rpc::print_object_std(&result, &rawArgs, 0);
return result;
}
// Move these boolean operators to a new file.
inline bool
as_boolean(const torrent::Object& rawArgs) {
switch (rawArgs.type()) {
case torrent::Object::TYPE_VALUE: return rawArgs.as_value();
case torrent::Object::TYPE_STRING: return !rawArgs.as_string().empty();
// We need to properly handle argument lists that are single-object
// at a higher level.
case torrent::Object::TYPE_LIST: return !rawArgs.as_list().empty() && as_boolean(rawArgs.as_list().front());
// case torrent::Object::TYPE_MAP: return !rawArgs.as_map().empty();
default: return false;
}
}
torrent::Object
apply_not(rpc::target_type target, const torrent::Object& rawArgs) {
bool result;
if (rawArgs.is_dict_key())
result = as_boolean(rpc::commands.call_command(rawArgs.as_dict_key().c_str(), rawArgs.as_dict_obj(),
target));
// TODO: Thus we should clean this up...
else if (rawArgs.is_list() && !rawArgs.as_list().empty())
return apply_not(target, rawArgs.as_list().front());
else
result = as_boolean(rawArgs);
return (int64_t)!result;
}
torrent::Object
apply_false(rpc::target_type target, const torrent::Object& rawArgs) {
return (int64_t)0;
}
torrent::Object
apply_and(rpc::target_type target, const torrent::Object& rawArgs) {
if (rawArgs.type() != torrent::Object::TYPE_LIST)
return as_boolean(rawArgs);
for (torrent::Object::list_const_iterator itr = rawArgs.as_list().begin(), last = rawArgs.as_list().end(); itr != last; itr++)
if (itr->is_dict_key()) {
if (!as_boolean(rpc::commands.call_command(itr->as_dict_key().c_str(), itr->as_dict_obj(), target)))
return (int64_t)false;
} else if (itr->is_value()) {
if (!itr->as_value())
return (int64_t)false;
} else {
// TODO: Switch to new versions that only accept the new command syntax.
if (!as_boolean(rpc::parse_command_single(target, itr->as_string())))
return (int64_t)false;
}
return (int64_t)true;
}
torrent::Object
apply_or(rpc::target_type target, const torrent::Object& rawArgs) {
if (rawArgs.type() != torrent::Object::TYPE_LIST)
return as_boolean(rawArgs);
for (torrent::Object::list_const_iterator itr = rawArgs.as_list().begin(), last = rawArgs.as_list().end(); itr != last; itr++)
if (itr->is_dict_key()) {
if (as_boolean(rpc::commands.call_command(itr->as_dict_key().c_str(), itr->as_dict_obj(), target)))
return (int64_t)true;
} else if (itr->is_value()) {
if (itr->as_value())
return (int64_t)true;
} else {
if (as_boolean(rpc::parse_command_single(target, itr->as_string())))
return (int64_t)true;
}
return (int64_t)false;
}
torrent::Object
apply_cmp(rpc::target_type target, const torrent::Object::list_type& args) {
// We only need to check if empty() since if size() == 1 it calls
// the same command for both, or if size() == 2 then each side of
// the comparison has different commands.
if (args.empty())
throw torrent::input_error("Wrong argument count.");
// This really should be converted to using args flagged as
// commands, so that we can compare commands and statics values.
torrent::Object result1;
torrent::Object result2;
rpc::target_type target1 = rpc::is_target_pair(target) ? rpc::get_target_left(target) : target;
rpc::target_type target2 = rpc::is_target_pair(target) ? rpc::get_target_right(target) : target;
if (args.front().is_dict_key())
result1 = rpc::commands.call_command(args.front().as_dict_key().c_str(), args.front().as_dict_obj(), target1);
else
result1 = rpc::parse_command_single(target1, args.front().as_string());
if (args.back().is_dict_key())
result2 = rpc::commands.call_command(args.back().as_dict_key().c_str(), args.back().as_dict_obj(), target2);
else
result2 = rpc::parse_command_single(target2, args.back().as_string());
if (result1.type() != result2.type())
throw torrent::input_error("Type mismatch.");
switch (result1.type()) {
case torrent::Object::TYPE_VALUE: return result1.as_value() - result2.as_value();
case torrent::Object::TYPE_STRING: return result1.as_string().compare(result2.as_string());
default: return torrent::Object();
}
}
torrent::Object apply_less(rpc::target_type target, const torrent::Object::list_type& args) {
torrent::Object result = apply_cmp(target, args);
return result.is_value() ? result.as_value() < 0 : (int64_t)false;
}
torrent::Object apply_greater(rpc::target_type target, const torrent::Object::list_type& args) {
torrent::Object result = apply_cmp(target, args);
return result.is_value() ? result.as_value() > 0 : (int64_t)false;
}
torrent::Object apply_equal(rpc::target_type target, const torrent::Object::list_type& args) {
torrent::Object result = apply_cmp(target, args);
return result.is_value() ? result.as_value() == 0 : (int64_t)false;
}
torrent::Object
apply_to_time(const torrent::Object& rawArgs, int flags) {
std::tm *u;
time_t t = (uint64_t)rawArgs.as_value();
if (flags & 0x1)
u = std::localtime(&t);
else
u = std::gmtime(&t);
if (u == NULL)
return torrent::Object();
char buffer[11];
if (flags & 0x2)
snprintf(buffer, 11, "%02u/%02u/%04u", u->tm_mday, (u->tm_mon + 1), (1900 + u->tm_year));
else
snprintf(buffer, 9, "%2d:%02d:%02d", u->tm_hour, u->tm_min, u->tm_sec);
return std::string(buffer);
}
torrent::Object
apply_to_elapsed_time(const torrent::Object& rawArgs) {
uint64_t arg = cachedTime.seconds() - rawArgs.as_value();
char buffer[48];
snprintf(buffer, 48, "%2d:%02d:%02d", (int)(arg / 3600), (int)((arg / 60) % 60), (int)(arg % 60));
return std::string(buffer);
}
torrent::Object
apply_to_kb(const torrent::Object& rawArgs) {
char buffer[32];
snprintf(buffer, 32, "%5.1f", (double)rawArgs.as_value() / (1 << 10));
return std::string(buffer);
}
torrent::Object
apply_to_mb(const torrent::Object& rawArgs) {
char buffer[32];
snprintf(buffer, 32, "%8.1f", (double)rawArgs.as_value() / (1 << 20));
return std::string(buffer);
}
torrent::Object
apply_to_xb(const torrent::Object& rawArgs) {
char buffer[48];
int64_t arg = rawArgs.as_value();
if (arg < (int64_t(1000) << 10))
snprintf(buffer, 48, "%5.1f KB", (double)arg / (int64_t(1) << 10));
else if (arg < (int64_t(1000) << 20))
snprintf(buffer, 48, "%5.1f MB", (double)arg / (int64_t(1) << 20));
else if (arg < (int64_t(1000) << 30))
snprintf(buffer, 48, "%5.1f GB", (double)arg / (int64_t(1) << 30));
else
snprintf(buffer, 48, "%5.1f TB", (double)arg / (int64_t(1) << 40));
return std::string(buffer);
}
torrent::Object
apply_to_throttle(const torrent::Object& rawArgs) {
int64_t arg = rawArgs.as_value();
if (arg < 0)
return "---";
else if (arg == 0)
return "off";
char buffer[32];
snprintf(buffer, 32, "%3d", (int)(arg / (1 << 10)));
return std::string(buffer);
}
// A series of if/else statements. Every even arguments are
// conditionals and odd arguments are branches to be executed, except
// the last one which is always a branch.
//
// if (cond1) { branch1 }
// <cond1>,<branch1>
//
// if (cond1) { branch1 } else if (cond2) { branch2 } else { branch3 }
// <cond1>,<branch1>,<cond2>,<branch2>,<branch3>
torrent::Object
apply_if(rpc::target_type target, const torrent::Object& rawArgs, int flags) {
const torrent::Object::list_type& args = rawArgs.as_list();
torrent::Object::list_const_iterator itr = args.begin();
while (itr != args.end() && itr != --args.end()) {
torrent::Object tmp;
const torrent::Object* conditional;
if (flags & 0x1 && itr->is_string())
conditional = &(tmp = rpc::parse_command(target, itr->as_string().c_str(), itr->as_string().c_str() + itr->as_string().size()).first);
else if (flags & 0x1 && itr->is_dict_key())
conditional = &(tmp = rpc::commands.call_command(itr->as_dict_key().c_str(), itr->as_dict_obj(), target));
else
conditional = &*itr;
bool result;
switch (conditional->type()) {
case torrent::Object::TYPE_STRING:
result = !conditional->as_string().empty();
break;
case torrent::Object::TYPE_VALUE:
result = conditional->as_value();
break;
case torrent::Object::TYPE_NONE:
result = false;
break;
default:
throw torrent::input_error("Type not supported by 'if'.");
};
itr++;
if (result)
break;
itr++;
}
if (itr == args.end())
return torrent::Object();
if (flags & 0x1 && itr->is_string()) {
return rpc::parse_command(target, itr->as_string().c_str(), itr->as_string().c_str() + itr->as_string().size()).first;
} else if (flags & 0x1 && itr->is_dict_key()) {
return rpc::commands.call_command(itr->as_dict_key().c_str(), itr->as_dict_obj(), target);
} else if (flags & 0x1 && itr->is_list()) {
// Move this into a special function or something. Also, might be
// nice to have a parse_command function that takes list
// iterator...
for (torrent::Object::list_type::const_iterator cmdItr = itr->as_list().begin(), last = itr->as_list().end(); cmdItr != last; cmdItr++)
if (cmdItr->is_string())
rpc::parse_command(target, cmdItr->as_string().c_str(), cmdItr->as_string().c_str() + cmdItr->as_string().size());
return torrent::Object();
} else {
return *itr;
}
}
torrent::Object
cmd_view_size(const torrent::Object::string_type& args) {
return (*control->view_manager()->find_throw(args))->size_visible();
}
torrent::Object
cmd_view_size_not_visible(const torrent::Object::string_type& args) {
return (*control->view_manager()->find_throw(args))->size_not_visible();
}
torrent::Object
cmd_view_persistent(const torrent::Object::string_type& args) {
core::View* view = *control->view_manager()->find_throw(args);
if (!view->get_filter().is_empty() || !view->event_added().is_empty() || !view->event_removed().is_empty())
throw torrent::input_error("Cannot set modified views as persitent.");
view->set_filter("d.views.has=" + args);
view->set_event_added("d.views.push_back_unique=" + args);
view->set_event_removed("d.views.remove=" + args);
return torrent::Object();
}
// TODO: These don't need wrapper functions anymore...
torrent::Object
cmd_ui_set_view(const torrent::Object::string_type& args) {
control->ui()->download_list()->set_current_view(args);
return torrent::Object();
}
torrent::Object
cmd_ui_unfocus_download(core::Download* download) {
control->ui()->download_list()->unfocus_download(download);
return torrent::Object();
}
torrent::Object
cmd_view_filter_download(core::Download* download, const torrent::Object::string_type& args) {
(*control->view_manager()->find_throw(args))->filter_download(download);
return torrent::Object();
}
torrent::Object
cmd_view_set_visible(core::Download* download, const torrent::Object::string_type& args) {
(*control->view_manager()->find_throw(args))->set_visible(download);
return torrent::Object();
}
torrent::Object
cmd_view_set_not_visible(core::Download* download, const torrent::Object::string_type& args) {
(*control->view_manager()->find_throw(args))->set_not_visible(download);
return torrent::Object();
}
torrent::Object
apply_elapsed_less(const torrent::Object::list_type& args) {
if (args.size() != 2)
throw torrent::input_error("Wrong argument count.");
int64_t start_time = rpc::convert_to_value(args.front());
return (int64_t)(start_time != 0 && rak::timer::current_seconds() - start_time < rpc::convert_to_value(args.back()));
}
torrent::Object
apply_elapsed_greater(const torrent::Object::list_type& args) {
if (args.size() != 2)
throw torrent::input_error("Wrong argument count.");
int64_t start_time = rpc::convert_to_value(args.front());
return (int64_t)(start_time != 0 && rak::timer::current_seconds() - start_time > rpc::convert_to_value(args.back()));
}
void
initialize_command_ui() {
CMD2_VAR_STRING("keys.layout", "qwerty");
CMD2_ANY_STRING("view.add", object_convert_void(tr1::bind(&core::ViewManager::insert_throw, control->view_manager(), tr1::placeholders::_2)));
CMD2_ANY_L ("view.list", tr1::bind(&apply_view_list));
CMD2_ANY_LIST("view.set", tr1::bind(&apply_view_set, tr1::placeholders::_2));
CMD2_ANY_LIST("view.filter", tr1::bind(&apply_view_event, &core::ViewManager::set_filter, tr1::placeholders::_2));
CMD2_ANY_LIST("view.filter_on", tr1::bind(&apply_view_filter_on, tr1::placeholders::_2));
CMD2_ANY_LIST("view.sort", tr1::bind(&apply_view_sort, tr1::placeholders::_2));
CMD2_ANY_LIST("view.sort_new", tr1::bind(&apply_view_event, &core::ViewManager::set_sort_new, tr1::placeholders::_2));
CMD2_ANY_LIST("view.sort_current", tr1::bind(&apply_view_event, &core::ViewManager::set_sort_current, tr1::placeholders::_2));
CMD2_ANY_LIST("view.event_added", tr1::bind(&apply_view_event, &core::ViewManager::set_event_added, tr1::placeholders::_2));
CMD2_ANY_LIST("view.event_removed", tr1::bind(&apply_view_event, &core::ViewManager::set_event_removed, tr1::placeholders::_2));
// Cleanup and add . to view.
CMD2_ANY_STRING("view.size", tr1::bind(&cmd_view_size, tr1::placeholders::_2));
CMD2_ANY_STRING("view.size_not_visible", tr1::bind(&cmd_view_size_not_visible, tr1::placeholders::_2));
CMD2_ANY_STRING("view.persistent", tr1::bind(&cmd_view_persistent, tr1::placeholders::_2));
CMD2_ANY_STRING_V("view.filter_all", tr1::bind(&core::View::filter, tr1::bind(&core::ViewManager::find_ptr_throw, control->view_manager(), tr1::placeholders::_2)));
CMD2_DL_STRING ("view.filter_download", tr1::bind(&cmd_view_filter_download, tr1::placeholders::_1, tr1::placeholders::_2));
CMD2_DL_STRING ("view.set_visible", tr1::bind(&cmd_view_set_visible, tr1::placeholders::_1, tr1::placeholders::_2));
CMD2_DL_STRING ("view.set_not_visible", tr1::bind(&cmd_view_set_not_visible, tr1::placeholders::_1, tr1::placeholders::_2));
// Commands that affect the default rtorrent UI.
CMD2_DL ("ui.unfocus_download", tr1::bind(&cmd_ui_unfocus_download, tr1::placeholders::_1));
CMD2_ANY_STRING("ui.current_view.set", tr1::bind(&cmd_ui_set_view, tr1::placeholders::_2));
// Move.
CMD2_ANY("print", &apply_print);
CMD2_ANY("cat", &apply_cat);
CMD2_ANY("if", tr1::bind(&apply_if, tr1::placeholders::_1, tr1::placeholders::_2, 0));
CMD2_ANY("not", &apply_not);
CMD2_ANY("false", &apply_false);
CMD2_ANY("and", &apply_and);
CMD2_ANY("or", &apply_or);
// A temporary command for handling stuff until we get proper
// support for seperation of commands and literals.
CMD2_ANY("branch", tr1::bind(&apply_if, tr1::placeholders::_1, tr1::placeholders::_2, 1));
CMD2_ANY_LIST("less", &apply_less);
CMD2_ANY_LIST("greater", &apply_greater);
CMD2_ANY_LIST("equal", &apply_equal);
CMD2_ANY_VALUE("convert.gm_time", tr1::bind(&apply_to_time, tr1::placeholders::_2, 0));
CMD2_ANY_VALUE("convert.gm_date", tr1::bind(&apply_to_time, tr1::placeholders::_2, 0x2));
CMD2_ANY_VALUE("convert.time", tr1::bind(&apply_to_time, tr1::placeholders::_2, 0x1));
CMD2_ANY_VALUE("convert.date", tr1::bind(&apply_to_time, tr1::placeholders::_2, 0x1 | 0x2));
CMD2_ANY_VALUE("convert.elapsed_time", tr1::bind(&apply_to_elapsed_time, tr1::placeholders::_2));
CMD2_ANY_VALUE("convert.kb", tr1::bind(&apply_to_kb, tr1::placeholders::_2));
CMD2_ANY_VALUE("convert.mb", tr1::bind(&apply_to_mb, tr1::placeholders::_2));
CMD2_ANY_VALUE("convert.xb", tr1::bind(&apply_to_xb, tr1::placeholders::_2));
CMD2_ANY_VALUE("convert.throttle", tr1::bind(&apply_to_throttle, tr1::placeholders::_2));
CMD2_ANY_LIST ("elapsed.less", tr1::bind(&apply_elapsed_less, tr1::placeholders::_2));
CMD2_ANY_LIST ("elapsed.greater", tr1::bind(&apply_elapsed_greater, tr1::placeholders::_2));
}
-186
View File
@@ -1,186 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <unistd.h>
#include <sys/stat.h>
#include <torrent/connection_manager.h>
#include "core/manager.h"
#include "core/download_store.h"
#include "core/view_manager.h"
#include "core/dht_manager.h"
#include "core/http_queue.h"
#include "display/canvas.h"
#include "display/window.h"
#include "display/manager.h"
#include "input/manager.h"
#include "input/input_event.h"
#include "rpc/command_scheduler.h"
#include "rpc/parse_commands.h"
#include "rpc/scgi.h"
#include "rpc/object_storage.h"
#include "ui/root.h"
#include "control.h"
Control::Control() :
m_ui(new ui::Root()),
m_display(new display::Manager()),
m_input(new input::Manager()),
m_inputStdin(new input::InputEvent(STDIN_FILENO)),
m_commandScheduler(new rpc::CommandScheduler()),
m_objectStorage(new rpc::object_storage()),
m_tick(0),
m_shutdownReceived(false),
m_shutdownQuick(false) {
m_core = new core::Manager();
m_viewManager = new core::ViewManager();
m_dhtManager = new core::DhtManager();
m_inputStdin->slot_pressed(std::tr1::bind(&input::Manager::pressed, m_input, std::tr1::placeholders::_1));
m_taskShutdown.slot() = std::tr1::bind(&Control::handle_shutdown, this);
m_commandScheduler->set_slot_error_message(rak::mem_fn(m_core, &core::Manager::push_log_std));
}
Control::~Control() {
delete m_inputStdin;
delete m_input;
delete m_viewManager;
delete m_ui;
delete m_display;
delete m_core;
delete m_dhtManager;
delete m_commandScheduler;
delete m_objectStorage;
}
void
Control::initialize() {
display::Canvas::initialize();
display::Window::slot_schedule(rak::make_mem_fun(m_display, &display::Manager::schedule));
display::Window::slot_unschedule(rak::make_mem_fun(m_display, &display::Manager::unschedule));
display::Window::slot_adjust(rak::make_mem_fun(m_display, &display::Manager::adjust_layout));
m_core->http_stack()->set_user_agent(USER_AGENT);
m_core->initialize_second();
m_core->listen_open();
m_core->download_store()->enable(rpc::call_command_value("session.use_lock"));
m_core->set_hashing_view(*m_viewManager->find_throw("hashing"));
m_ui->init(this);
m_inputStdin->insert(torrent::main_thread()->poll());
}
void
Control::cleanup() {
// delete m_scgi; m_scgi = NULL;
rpc::xmlrpc.cleanup();
priority_queue_erase(&taskScheduler, &m_taskShutdown);
m_inputStdin->remove(torrent::main_thread()->poll());
m_core->download_store()->disable();
m_ui->cleanup();
m_core->cleanup();
display::Canvas::erase_std();
display::Canvas::refresh_std();
display::Canvas::do_update();
display::Canvas::cleanup();
}
void
Control::cleanup_exception() {
// delete m_scgi; m_scgi = NULL;
display::Canvas::cleanup();
}
bool
Control::is_shutdown_completed() {
if (!m_shutdownQuick || worker_thread->is_active())
return false;
// Tracker requests can be disowned, so wait for these to
// finish. The edge case of torrent http downloads may delay
// shutdown.
if (!core()->http_stack()->empty() || !core()->http_queue()->empty())
return false;
return torrent::is_inactive();
}
void
Control::handle_shutdown() {
if (!m_shutdownQuick) {
// Temporary hack:
if (worker_thread->is_active())
worker_thread->queue_item(&ThreadBase::stop_thread);
torrent::connection_manager()->listen_close();
m_core->shutdown(false);
if (!m_taskShutdown.is_queued())
priority_queue_insert(&taskScheduler, &m_taskShutdown, cachedTime + rak::timer::from_seconds(5));
} else {
// Temporary hack:
if (worker_thread->is_active())
worker_thread->queue_item(&ThreadBase::stop_thread);
m_core->shutdown(true);
}
m_shutdownQuick = true;
m_shutdownReceived = false;
}
-134
View File
@@ -1,134 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_CONTROL_H
#define RTORRENT_CONTROL_H
#include <inttypes.h>
#include <sys/types.h>
#include <rak/timer.h>
#include <rak/priority_queue_default.h>
#include <torrent/torrent.h>
namespace ui {
class Root;
}
namespace core {
class Manager;
class ViewManager;
class DhtManager;
}
namespace display {
class Manager;
}
namespace input {
class InputEvent;
class Manager;
}
namespace rpc {
class CommandScheduler;
class XmlRpc;
class object_storage;
}
class Control {
public:
Control();
~Control();
bool is_shutdown_completed();
bool is_shutdown_received() { return m_shutdownReceived; }
bool is_shutdown_started() { return m_shutdownQuick; }
void initialize();
void cleanup();
void cleanup_exception();
void handle_shutdown();
void receive_normal_shutdown() { m_shutdownReceived = true; __sync_synchronize(); }
void receive_quick_shutdown() { m_shutdownReceived = true; m_shutdownQuick = true; __sync_synchronize(); }
core::Manager* core() { return m_core; }
core::ViewManager* view_manager() { return m_viewManager; }
core::DhtManager* dht_manager() { return m_dhtManager; }
ui::Root* ui() { return m_ui; }
display::Manager* display() { return m_display; }
input::Manager* input() { return m_input; }
input::InputEvent* input_stdin() { return m_inputStdin; }
rpc::CommandScheduler* command_scheduler() { return m_commandScheduler; }
rpc::object_storage* object_storage() { return m_objectStorage; }
uint64_t tick() const { return m_tick; }
void inc_tick() { m_tick++; }
const std::string& working_directory() const { return m_workingDirectory; }
void set_working_directory(const std::string& dir);
private:
Control(const Control&);
void operator = (const Control&);
core::Manager* m_core;
core::ViewManager* m_viewManager;
core::DhtManager* m_dhtManager;
ui::Root* m_ui;
display::Manager* m_display;
input::Manager* m_input;
input::InputEvent* m_inputStdin;
rpc::CommandScheduler* m_commandScheduler;
rpc::object_storage* m_objectStorage;
uint64_t m_tick;
mode_t m_umask;
std::string m_workingDirectory;
rak::priority_item m_taskShutdown;
bool m_shutdownReceived lt_cacheline_aligned;
bool m_shutdownQuick lt_cacheline_aligned;
};
#endif
-33
View File
@@ -1,33 +0,0 @@
noinst_LIBRARIES = libsub_core.a
libsub_core_a_SOURCES = \
curl_get.cc \
curl_get.h \
curl_socket.cc \
curl_socket.h \
curl_stack.cc \
curl_stack.h \
dht_manager.cc \
dht_manager.h \
download.cc \
download.h \
download_factory.cc \
download_factory.h \
download_list.cc \
download_list.h \
download_slot_map.h \
download_store.cc \
download_store.h \
http_queue.cc \
http_queue.h \
manager.cc \
manager.h \
poll_manager.cc \
poll_manager.h \
range_map.h \
view.cc \
view.h \
view_manager.cc \
view_manager.h
AM_CPPFLAGS = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir)
-134
View File
@@ -1,134 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <iostream>
#include <curl/curl.h>
#include <curl/easy.h>
#include <torrent/exceptions.h>
#include "globals.h"
#include "curl_get.h"
#include "curl_stack.h"
namespace core {
size_t
curl_get_receive_write(void* data, size_t size, size_t nmemb, void* handle) {
if (!((CurlGet*)handle)->stream()->write((const char*)data, size * nmemb).fail())
return size * nmemb;
else
return 0;
}
CurlGet::~CurlGet() {
close();
}
void
CurlGet::start() {
if (is_busy())
throw torrent::internal_error("Tried to call CurlGet::start on a busy object.");
if (m_stream == NULL)
throw torrent::internal_error("Tried to call CurlGet::start without a valid output stream.");
m_handle = curl_easy_init();
if (m_handle == NULL)
throw torrent::internal_error("Call to curl_easy_init() failed.");
curl_easy_setopt(m_handle, CURLOPT_URL, m_url.c_str());
curl_easy_setopt(m_handle, CURLOPT_WRITEFUNCTION, &curl_get_receive_write);
curl_easy_setopt(m_handle, CURLOPT_WRITEDATA, this);
if (m_timeout != 0) {
curl_easy_setopt(m_handle, CURLOPT_CONNECTTIMEOUT, (long)60);
curl_easy_setopt(m_handle, CURLOPT_TIMEOUT, (long)m_timeout);
// Normally libcurl should handle the timeout. But sometimes that doesn't
// work right so we do a fallback timeout that just aborts the transfer.
m_taskTimeout.slot() = std::tr1::bind(&CurlGet::receive_timeout, this);
priority_queue_erase(&taskScheduler, &m_taskTimeout);
priority_queue_insert(&taskScheduler, &m_taskTimeout, cachedTime + rak::timer::from_seconds(m_timeout + 5));
}
curl_easy_setopt(m_handle, CURLOPT_FORBID_REUSE, (long)1);
curl_easy_setopt(m_handle, CURLOPT_NOSIGNAL, (long)1);
curl_easy_setopt(m_handle, CURLOPT_FOLLOWLOCATION, (long)1);
curl_easy_setopt(m_handle, CURLOPT_MAXREDIRS, (long)5);
curl_easy_setopt(m_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_easy_setopt(m_handle, CURLOPT_ENCODING, "");
m_stack->add_get(this);
}
void
CurlGet::close() {
priority_queue_erase(&taskScheduler, &m_taskTimeout);
if (!is_busy())
return;
m_stack->remove_get(this);
curl_easy_cleanup(m_handle);
m_handle = NULL;
}
void
CurlGet::receive_timeout() {
return m_stack->transfer_done(m_handle, "Timed out");
}
double
CurlGet::size_done() {
double d = 0.0;
curl_easy_getinfo(m_handle, CURLINFO_SIZE_DOWNLOAD, &d);
return d;
}
double
CurlGet::size_total() {
double d = 0.0;
curl_easy_getinfo(m_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d);
return d;
}
}
-87
View File
@@ -1,87 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_CORE_CURL_GET_H
#define RTORRENT_CORE_CURL_GET_H
#include <iosfwd>
#include <string>
#include <curl/curl.h>
#include <torrent/http.h>
#include "rak/priority_queue_default.h"
namespace core {
class CurlStack;
class CurlGet : public torrent::Http {
public:
friend class CurlStack;
CurlGet(CurlStack* s) : m_active(false), m_handle(NULL), m_stack(s) {}
virtual ~CurlGet();
void start();
void close();
bool is_busy() const { return m_handle; }
bool is_active() const { return m_active; }
void set_active(bool a) { m_active = a; }
double size_done();
double size_total();
CURL* handle() { return m_handle; }
private:
CurlGet(const CurlGet&);
void operator = (const CurlGet&);
void receive_timeout();
bool m_active;
rak::priority_item m_taskTimeout;
CURL* m_handle;
CurlStack* m_stack;
};
}
#endif
-134
View File
@@ -1,134 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2008, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <curl/curl.h>
#include <curl/multi.h>
#include <torrent/poll.h>
#include <torrent/exceptions.h>
#include <torrent/utils/thread_base.h>
#include "control.h"
#include "curl_socket.h"
#include "curl_stack.h"
namespace core {
int
CurlSocket::receive_socket(void* easy_handle, curl_socket_t fd, int what, void* userp, void* socketp) {
CurlStack* stack = (CurlStack*)userp;
CurlSocket* socket = (CurlSocket*)socketp;
if (what == CURL_POLL_REMOVE) {
// We also probably need the special code here as we're not
// guaranteed that the fd will be closed, afaik.
if (socket != NULL)
socket->close();
// TODO: Consider the possibility that we'll need to set the
// fd-associated pointer curl holds to NULL.
delete socket;
return 0;
}
if (socket == NULL) {
socket = stack->new_socket(fd);
torrent::main_thread()->poll()->open(socket);
// No interface for libcurl to signal when it's interested in error events.
// Assume that hence it must always be interested in them.
torrent::main_thread()->poll()->insert_error(socket);
}
if (what == CURL_POLL_NONE || what == CURL_POLL_OUT)
torrent::main_thread()->poll()->remove_read(socket);
else
torrent::main_thread()->poll()->insert_read(socket);
if (what == CURL_POLL_NONE || what == CURL_POLL_IN)
torrent::main_thread()->poll()->remove_write(socket);
else
torrent::main_thread()->poll()->insert_write(socket);
return 0;
}
CurlSocket::~CurlSocket() {
if (m_fileDesc != -1)
throw torrent::internal_error("CurlSocket::~CurlSocket() m_fileDesc != -1.");
}
void
CurlSocket::close() {
if (m_fileDesc == -1)
throw torrent::internal_error("CurlSocket::close() m_fileDesc == -1.");
torrent::main_thread()->poll()->closed(this);
m_fileDesc = -1;
}
void
CurlSocket::event_read() {
#if (LIBCURL_VERSION_NUM >= 0x071003)
return m_stack->receive_action(this, CURL_CSELECT_IN);
#else
return m_stack->receive_action(this, 0);
#endif
}
void
CurlSocket::event_write() {
#if (LIBCURL_VERSION_NUM >= 0x071003)
return m_stack->receive_action(this, CURL_CSELECT_OUT);
#else
return m_stack->receive_action(this, 0);
#endif
}
void
CurlSocket::event_error() {
#if (LIBCURL_VERSION_NUM >= 0x071003)
return m_stack->receive_action(this, CURL_CSELECT_ERR);
#else
return m_stack->receive_action(this, 0);
#endif
}
}
-72
View File
@@ -1,72 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2008, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_CORE_CURL_SOCKET_H
#define RTORRENT_CORE_CURL_SOCKET_H
#include <torrent/event.h>
#include "globals.h"
namespace core {
class CurlStack;
class CurlSocket : public torrent::Event {
public:
CurlSocket(int fd, CurlStack* stack) : m_stack(stack) { m_fileDesc = fd; }
~CurlSocket();
const char* type_name() const { return "curl"; }
void close();
static int receive_socket(void* easy_handle, curl_socket_t fd, int what, void* userp, void* socketp);
private:
CurlSocket(const CurlSocket&);
void operator = (const CurlSocket&);
virtual void event_read();
virtual void event_write();
virtual void event_error();
CurlStack* m_stack;
};
}
#endif
-254
View File
@@ -1,254 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <algorithm>
#include <curl/multi.h>
#include <torrent/exceptions.h>
#include "rak/functional.h"
#include "curl_get.h"
#include "curl_socket.h"
#include "curl_stack.h"
namespace core {
CurlStack::CurlStack() :
m_handle((void*)curl_multi_init()),
m_active(0),
m_maxActive(32),
m_ssl_verify_peer(true),
m_dns_timeout(60) {
m_taskTimeout.slot() = std::tr1::bind(&CurlStack::receive_timeout, this);
#if (LIBCURL_VERSION_NUM >= 0x071000)
curl_multi_setopt((CURLM*)m_handle, CURLMOPT_TIMERDATA, this);
curl_multi_setopt((CURLM*)m_handle, CURLMOPT_TIMERFUNCTION, &CurlStack::set_timeout);
#endif
curl_multi_setopt((CURLM*)m_handle, CURLMOPT_SOCKETDATA, this);
curl_multi_setopt((CURLM*)m_handle, CURLMOPT_SOCKETFUNCTION, &CurlSocket::receive_socket);
}
CurlStack::~CurlStack() {
while (!empty())
front()->close();
curl_multi_cleanup((CURLM*)m_handle);
priority_queue_erase(&taskScheduler, &m_taskTimeout);
}
CurlGet*
CurlStack::new_object() {
return new CurlGet(this);
}
CurlSocket*
CurlStack::new_socket(int fd) {
CurlSocket* socket = new CurlSocket(fd, this);
curl_multi_assign((CURLM*)m_handle, fd, socket);
return socket;
}
void
CurlStack::receive_action(CurlSocket* socket, int events) {
CURLMcode code;
do {
int count;
#if (LIBCURL_VERSION_NUM >= 0x071003)
code = curl_multi_socket_action((CURLM*)m_handle,
socket != NULL ? socket->file_descriptor() : CURL_SOCKET_TIMEOUT,
events,
&count);
#else
code = curl_multi_socket((CURLM*)m_handle,
socket != NULL ? socket->file_descriptor() : CURL_SOCKET_TIMEOUT,
&count);
#endif
if (code > 0)
throw torrent::internal_error("Error calling curl_multi_socket_action.");
// Socket might be removed when cleaning handles below, future
// calls should not use it.
socket = NULL;
events = 0;
if ((unsigned int)count != size()) {
while (process_done_handle())
; // Do nothing.
if (empty())
priority_queue_erase(&taskScheduler, &m_taskTimeout);
}
} while (code == CURLM_CALL_MULTI_PERFORM);
}
bool
CurlStack::process_done_handle() {
int remaining_msgs = 0;
CURLMsg* msg = curl_multi_info_read((CURLM*)m_handle, &remaining_msgs);
if (msg == NULL)
return false;
if (msg->msg != CURLMSG_DONE)
throw torrent::internal_error("CurlStack::receive_action() msg->msg != CURLMSG_DONE.");
transfer_done(msg->easy_handle,
msg->data.result == CURLE_OK ? NULL : curl_easy_strerror(msg->data.result));
return remaining_msgs != 0;
}
void
CurlStack::transfer_done(void* handle, const char* msg) {
iterator itr = std::find_if(begin(), end(), rak::equal(handle, std::mem_fun(&CurlGet::handle)));
if (itr == end())
throw torrent::internal_error("Could not find CurlGet with the right easy_handle.");
if (msg == NULL)
(*itr)->trigger_done();
else
(*itr)->trigger_failed(msg);
}
void
CurlStack::receive_timeout() {
receive_action(NULL, 0);
// Sometimes libcurl forgets to reset the timeout. Try to poll the value in that case, or use 10 seconds.
if (!empty() && !m_taskTimeout.is_queued()) {
long timeout;
curl_multi_timeout((CURLM*)m_handle, &timeout);
priority_queue_insert(&taskScheduler, &m_taskTimeout,
cachedTime + rak::timer::from_milliseconds(std::max<unsigned long>(timeout, 10000)));
}
}
void
CurlStack::add_get(CurlGet* get) {
if (!m_userAgent.empty())
curl_easy_setopt(get->handle(), CURLOPT_USERAGENT, m_userAgent.c_str());
if (!m_httpProxy.empty())
curl_easy_setopt(get->handle(), CURLOPT_PROXY, m_httpProxy.c_str());
if (!m_bindAddress.empty())
curl_easy_setopt(get->handle(), CURLOPT_INTERFACE, m_bindAddress.c_str());
if (!m_httpCaPath.empty())
curl_easy_setopt(get->handle(), CURLOPT_CAPATH, m_httpCaPath.c_str());
if (!m_httpCaCert.empty())
curl_easy_setopt(get->handle(), CURLOPT_CAINFO, m_httpCaCert.c_str());
curl_easy_setopt(get->handle(), CURLOPT_SSL_VERIFYPEER, (long)m_ssl_verify_peer);
curl_easy_setopt(get->handle(), CURLOPT_DNS_CACHE_TIMEOUT, m_dns_timeout);
base_type::push_back(get);
if (m_active >= m_maxActive)
return;
m_active++;
get->set_active(true);
if (curl_multi_add_handle((CURLM*)m_handle, get->handle()) > 0)
throw torrent::internal_error("Error calling curl_multi_add_handle.");
#if (LIBCURL_VERSION_NUM < 0x071000)
receive_timeout();
#endif
}
void
CurlStack::remove_get(CurlGet* get) {
iterator itr = std::find(begin(), end(), get);
if (itr == end())
throw torrent::internal_error("Could not find CurlGet when calling CurlStack::remove.");
base_type::erase(itr);
// The CurlGet object was never activated, so we just skip this one.
if (!get->is_active())
return;
get->set_active(false);
if (curl_multi_remove_handle((CURLM*)m_handle, get->handle()) > 0)
throw torrent::internal_error("Error calling curl_multi_remove_handle.");
if (m_active == m_maxActive &&
(itr = std::find_if(begin(), end(), std::not1(std::mem_fun(&CurlGet::is_active)))) != end()) {
(*itr)->set_active(true);
if (curl_multi_add_handle((CURLM*)m_handle, (*itr)->handle()) > 0)
throw torrent::internal_error("Error calling curl_multi_add_handle.");
} else {
m_active--;
}
}
void
CurlStack::global_init() {
curl_global_init(CURL_GLOBAL_ALL);
}
void
CurlStack::global_cleanup() {
curl_global_cleanup();
}
// TODO: Is this function supposed to set a per-handle timeout, or is
// it the shortest timeout amongst all handles?
int
CurlStack::set_timeout(void* handle, long timeout_ms, void* userp) {
CurlStack* stack = (CurlStack*)userp;
priority_queue_erase(&taskScheduler, &stack->m_taskTimeout);
priority_queue_insert(&taskScheduler, &stack->m_taskTimeout, cachedTime + rak::timer::from_milliseconds(timeout_ms));
return 0;
}
}
-149
View File
@@ -1,149 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_CORE_CURL_STACK_H
#define RTORRENT_CORE_CURL_STACK_H
#include <deque>
#include <string>
#include "rak/priority_queue_default.h"
namespace core {
class CurlGet;
class CurlSocket;
// By using a deque instead of vector we allow for cheaper removal of
// the oldest elements, those that will be first in the in the
// deque.
//
// This should fit well with the use-case of a http stack, thus
// we get most of the cache locality benefits of a vector with fast
// removal of elements.
class CurlStack : std::deque<CurlGet*> {
public:
friend class CurlGet;
typedef std::deque<CurlGet*> base_type;
using base_type::value_type;
using base_type::iterator;
using base_type::const_iterator;
using base_type::reverse_iterator;
using base_type::const_reverse_iterator;
using base_type::begin;
using base_type::end;
using base_type::rbegin;
using base_type::rend;
using base_type::back;
using base_type::front;
using base_type::size;
using base_type::empty;
CurlStack();
~CurlStack();
CurlGet* new_object();
CurlSocket* new_socket(int fd);
unsigned int active() const { return m_active; }
unsigned int max_active() const { return m_maxActive; }
void set_max_active(unsigned int a) { m_maxActive = a; }
const std::string& user_agent() const { return m_userAgent; }
const std::string& http_proxy() const { return m_httpProxy; }
const std::string& bind_address() const { return m_bindAddress; }
const std::string& http_capath() const { return m_httpCaPath; }
const std::string& http_cacert() const { return m_httpCaCert; }
void set_user_agent(const std::string& s) { m_userAgent = s; }
void set_http_proxy(const std::string& s) { m_httpProxy = s; }
void set_bind_address(const std::string& s) { m_bindAddress = s; }
void set_http_capath(const std::string& s) { m_httpCaPath = s; }
void set_http_cacert(const std::string& s) { m_httpCaCert = s; }
bool ssl_verify_peer() const { return m_ssl_verify_peer; }
void set_ssl_verify_peer(bool s) { m_ssl_verify_peer = s; }
long dns_timeout() const { return m_dns_timeout; }
void set_dns_timeout(long timeout) { m_dns_timeout = timeout; }
static void global_init();
static void global_cleanup();
void receive_action(CurlSocket* socket, int type);
static int set_timeout(void* handle, long timeout_ms, void* userp);
void transfer_done(void* handle, const char* msg);
protected:
void add_get(CurlGet* get);
void remove_get(CurlGet* get);
private:
CurlStack(const CurlStack&);
void operator = (const CurlStack&);
void receive_timeout();
bool process_done_handle();
void* m_handle;
unsigned int m_active;
unsigned int m_maxActive;
rak::priority_item m_taskTimeout;
std::string m_userAgent;
std::string m_httpProxy;
std::string m_bindAddress;
std::string m_httpCaPath;
std::string m_httpCaCert;
bool m_ssl_verify_peer;
long m_dns_timeout;
};
}
#endif
-324
View File
@@ -1,324 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <fstream>
#include <sstream>
#include <torrent/object.h>
#include <torrent/dht_manager.h>
#include <torrent/object_stream.h>
#include <torrent/rate.h>
#include <torrent/utils/log.h>
#include "rpc/parse_commands.h"
#include "globals.h"
#include "control.h"
#include "dht_manager.h"
#include "download.h"
#include "download_store.h"
#include "manager.h"
namespace core {
const char* DhtManager::dht_settings[dht_settings_num] = { "disable", "off", "auto", "on" };
DhtManager::~DhtManager() {
priority_queue_erase(&taskScheduler, &m_updateTimeout);
priority_queue_erase(&taskScheduler, &m_stopTimeout);
}
void
DhtManager::load_dht_cache() {
if (m_start == dht_disable || !control->core()->download_store()->is_enabled())
return;
torrent::Object cache = torrent::Object::create_map();
std::fstream cache_file((control->core()->download_store()->path() + "rtorrent.dht_cache").c_str(), std::ios::in | std::ios::binary);
if (cache_file.is_open()) {
cache_file >> cache;
// If the cache file is corrupted we will just discard it with an
// error message.
if (cache_file.fail()) {
lt_log_print(torrent::LOG_DHT_WARN, "DHT cache file corrupted, discarding.");
cache = torrent::Object::create_map();
}
}
try {
torrent::dht_manager()->initialize(cache);
if (m_start == dht_on)
start_dht();
} catch (torrent::local_error& e) {
lt_log_print(torrent::LOG_DHT_WARN, "DHT failed: %s", e.what());
}
}
void
DhtManager::start_dht() {
priority_queue_erase(&taskScheduler, &m_stopTimeout);
if (!torrent::dht_manager()->is_valid() || torrent::dht_manager()->is_active())
return;
torrent::ThrottlePair throttles = control->core()->get_throttle(m_throttleName);
torrent::dht_manager()->set_upload_throttle(throttles.first);
torrent::dht_manager()->set_download_throttle(throttles.second);
int port = rpc::call_command_value("dht.port");
if (port <= 0)
return;
lt_log_print(torrent::LOG_DHT_INFO, "Starting DHT server on port %d.", port);
try {
torrent::dht_manager()->start(port);
torrent::dht_manager()->reset_statistics();
m_updateTimeout.slot() = std::tr1::bind(&DhtManager::update, this);
priority_queue_insert(&taskScheduler, &m_updateTimeout, (cachedTime + rak::timer::from_seconds(60)).round_seconds());
m_dhtPrevCycle = 0;
m_dhtPrevQueriesSent = 0;
m_dhtPrevRepliesReceived = 0;
m_dhtPrevQueriesReceived = 0;
m_dhtPrevBytesUp = 0;
m_dhtPrevBytesDown = 0;
} catch (torrent::local_error& e) {
lt_log_print(torrent::LOG_DHT_ERROR, "DHT start failed: %s", e.what());
m_start = dht_off;
}
}
void
DhtManager::stop_dht() {
priority_queue_erase(&taskScheduler, &m_updateTimeout);
priority_queue_erase(&taskScheduler, &m_stopTimeout);
if (torrent::dht_manager()->is_active()) {
log_statistics(true);
lt_log_print(torrent::LOG_DHT_INFO, "Stopping DHT server.");
torrent::dht_manager()->stop();
}
}
void
DhtManager::save_dht_cache() {
if (!control->core()->download_store()->is_enabled() || !torrent::dht_manager()->is_valid())
return;
std::string filename = control->core()->download_store()->path() + "rtorrent.dht_cache";
std::string filename_tmp = filename + ".new";
std::fstream cache_file(filename_tmp.c_str(), std::ios::out | std::ios::trunc);
if (!cache_file.is_open())
return;
torrent::Object cache = torrent::Object::create_map();
cache_file << *torrent::dht_manager()->store_cache(&cache);
if (!cache_file.good())
return;
cache_file.close();
::rename(filename_tmp.c_str(), filename.c_str());
}
void
DhtManager::set_mode(const std::string& arg) {
int i;
for (i = 0; i < dht_settings_num; i++) {
if (arg == dht_settings[i]) {
m_start = i;
break;
}
}
if (i == dht_settings_num)
throw torrent::input_error("Invalid argument.");
if (m_start == dht_off)
stop_dht();
else if (m_start == dht_on)
start_dht();
}
void
DhtManager::update() {
if (!torrent::dht_manager()->is_active())
throw torrent::internal_error("DhtManager::update called with DHT inactive.");
if (m_start == dht_auto && !m_stopTimeout.is_queued()) {
DownloadList::const_iterator itr, end;
for (itr = control->core()->download_list()->begin(), end = control->core()->download_list()->end(); itr != end; ++itr)
if ((*itr)->download()->info()->is_active() && !(*itr)->download()->info()->is_private())
break;
if (itr == end) {
m_stopTimeout.slot() = std::tr1::bind(&DhtManager::stop_dht, this);
priority_queue_insert(&taskScheduler, &m_stopTimeout, (cachedTime + rak::timer::from_seconds(15 * 60)).round_seconds());
}
}
// While bootstrapping (log_statistics returns true), check every minute if it completed, otherwise update every 15 minutes.
if (log_statistics(false))
priority_queue_insert(&taskScheduler, &m_updateTimeout, (cachedTime + rak::timer::from_seconds(60)).round_seconds());
else
priority_queue_insert(&taskScheduler, &m_updateTimeout, (cachedTime + rak::timer::from_seconds(15 * 60)).round_seconds());
}
bool
DhtManager::log_statistics(bool force) {
torrent::DhtManager::statistics_type stats = torrent::dht_manager()->get_statistics();
// Check for firewall problems.
if (stats.cycle > 2 && stats.queries_sent - m_dhtPrevQueriesSent > 100 && stats.queries_received == m_dhtPrevQueriesReceived) {
// We should have had clients ping us at least but have received
// nothing, that means the UDP port is probably unreachable.
if (torrent::dht_manager()->can_receive_queries())
lt_log_print(torrent::LOG_DHT_WARN, "DHT port appears to be unreachable, no queries received.");
torrent::dht_manager()->set_can_receive(false);
}
if (stats.queries_sent - m_dhtPrevQueriesSent > stats.num_nodes * 2 + 20 && stats.replies_received == m_dhtPrevRepliesReceived) {
// No replies to over 20 queries plus two per node we have. Probably firewalled.
if (!m_warned)
lt_log_print(torrent::LOG_DHT_WARN, "DHT port appears to be firewalled, no replies received.");
m_warned = true;
return false;
}
m_warned = false;
if (stats.queries_received > m_dhtPrevQueriesReceived)
torrent::dht_manager()->set_can_receive(true);
// Nothing to log while bootstrapping, but check again every minute.
if (stats.cycle <= 1) {
m_dhtPrevCycle = stats.cycle;
return true;
}
// If bootstrap completed between now and the previous check, notify user.
if (m_dhtPrevCycle == 1) {
char buffer[128];
snprintf(buffer, sizeof(buffer), "DHT bootstrap complete, have %d nodes in %d buckets.", stats.num_nodes, stats.num_buckets);
control->core()->push_log_complete(buffer);
m_dhtPrevCycle = stats.cycle;
return false;
};
// Standard DHT statistics on first real cycle, and every 8th cycle
// afterwards (i.e. every 2 hours), or when forced.
if ((force && stats.cycle != m_dhtPrevCycle) || stats.cycle == 3 || stats.cycle > m_dhtPrevCycle + 7) {
char buffer[256];
snprintf(buffer, sizeof(buffer),
"DHT statistics: %d queries in, %d queries out, %d replies received, %lld bytes read, %lld bytes sent, "
"%d known nodes in %d buckets, %d peers (highest: %d) tracked in %d torrents.",
stats.queries_received - m_dhtPrevQueriesReceived,
stats.queries_sent - m_dhtPrevQueriesSent,
stats.replies_received - m_dhtPrevRepliesReceived,
(long long unsigned int)(stats.down_rate.total() - m_dhtPrevBytesDown),
(long long unsigned int)(stats.up_rate.total() - m_dhtPrevBytesUp),
stats.num_nodes,
stats.num_buckets,
stats.num_peers,
stats.max_peers,
stats.num_trackers);
control->core()->push_log_complete(buffer);
m_dhtPrevCycle = stats.cycle;
m_dhtPrevQueriesSent = stats.queries_sent;
m_dhtPrevRepliesReceived = stats.replies_received;
m_dhtPrevQueriesReceived = stats.queries_received;
m_dhtPrevBytesUp = stats.up_rate.total();
m_dhtPrevBytesDown = stats.down_rate.total();
}
return false;
}
torrent::Object
DhtManager::dht_statistics() {
torrent::Object dhtStats = torrent::Object::create_map();
dhtStats.insert_key("dht", dht_settings[m_start]);
dhtStats.insert_key("active", torrent::dht_manager()->is_active());
dhtStats.insert_key("throttle", m_throttleName);
if (torrent::dht_manager()->is_active()) {
torrent::DhtManager::statistics_type stats = torrent::dht_manager()->get_statistics();
dhtStats.insert_key("cycle", stats.cycle);
dhtStats.insert_key("queries_received", stats.queries_received);
dhtStats.insert_key("queries_sent", stats.queries_sent);
dhtStats.insert_key("replies_received", stats.replies_received);
dhtStats.insert_key("errors_received", stats.errors_received);
dhtStats.insert_key("errors_caught", stats.errors_caught);
dhtStats.insert_key("bytes_read", stats.down_rate.total());
dhtStats.insert_key("bytes_written", stats.up_rate.total());
dhtStats.insert_key("nodes", stats.num_nodes);
dhtStats.insert_key("buckets", stats.num_buckets);
dhtStats.insert_key("peers", stats.num_peers);
dhtStats.insert_key("peers_max", stats.max_peers);
dhtStats.insert_key("torrents", stats.num_trackers);
}
return dhtStats;
}
void
DhtManager::set_throttle_name(const std::string& throttleName) {
if (torrent::dht_manager()->is_active())
throw torrent::input_error("Cannot set DHT throttle while active.");
m_throttleName = throttleName;
}
}
-93
View File
@@ -1,93 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_CORE_DHT_MANAGER_H
#define RTORRENT_CORE_DHT_MANAGER_H
#include <rak/priority_queue_default.h>
#include <torrent/object.h>
namespace core {
class DhtManager {
public:
DhtManager() : m_warned(false), m_start(dht_off) { }
~DhtManager();
void load_dht_cache();
void save_dht_cache();
torrent::Object dht_statistics();
void start_dht();
void stop_dht();
void auto_start() { if (m_start == dht_auto) start_dht(); }
void set_mode(const std::string& arg);
void set_throttle_name(const std::string& throttleName);
const std::string& throttle_name() const { return m_throttleName; }
private:
static const int dht_disable = 0;
static const int dht_off = 1;
static const int dht_auto = 2;
static const int dht_on = 3;
static const int dht_settings_num = 4;
static const char* dht_settings[dht_settings_num];
void update();
bool log_statistics(bool force);
unsigned int m_dhtPrevCycle;
unsigned int m_dhtPrevQueriesSent;
unsigned int m_dhtPrevRepliesReceived;
unsigned int m_dhtPrevQueriesReceived;
uint64_t m_dhtPrevBytesUp;
uint64_t m_dhtPrevBytesDown;
rak::priority_item m_updateTimeout;
rak::priority_item m_stopTimeout;
bool m_warned;
int m_start;
std::string m_throttleName;
};
}
#endif
-185
View File
@@ -1,185 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <list>
#include <rak/file_stat.h>
#include <rak/functional.h>
#include <rak/path.h>
#include <torrent/exceptions.h>
#include <torrent/rate.h>
#include <torrent/torrent.h>
#include <torrent/tracker.h>
#include <torrent/tracker_list.h>
#include <torrent/data/file_list.h>
#include "rpc/parse_commands.h"
#include "control.h"
#include "download.h"
#include "manager.h"
namespace core {
Download::Download(download_type d) :
m_download(d),
m_hashFailed(false),
m_resumeFlags(~uint32_t()),
m_group(0) {
m_download.info()->signal_tracker_success().push_back(tr1::bind(&Download::receive_tracker_msg, this, ""));
m_download.info()->signal_tracker_failed().push_back(tr1::bind(&Download::receive_tracker_msg, this, tr1::placeholders::_1));
}
Download::~Download() {
if (!m_download.is_valid())
return;
m_download = download_type();
}
void
Download::enable_udp_trackers(bool state) {
for (torrent::TrackerList::iterator itr = m_download.tracker_list()->begin(), last = m_download.tracker_list()->end(); itr != last; ++itr)
if ((*itr)->type() == torrent::Tracker::TRACKER_UDP) {
if (state)
(*itr)->enable();
else
(*itr)->disable();
}
}
uint32_t
Download::priority() {
return bencode()->get_key("rtorrent").get_key_value("priority");
}
void
Download::set_priority(uint32_t p) {
p %= 4;
// Seeding torrents get half the priority of unfinished torrents.
if (!is_done())
torrent::download_set_priority(m_download, p * p * 2);
else
torrent::download_set_priority(m_download, p * p);
bencode()->get_key("rtorrent").insert_key("priority", (int64_t)p);
}
uint32_t
Download::connection_list_size() const {
return m_download.connection_list()->size();
}
void
Download::receive_tracker_msg(std::string msg) {
if (msg.empty())
m_message = "";
else
m_message = "Tracker: [" + msg + "]";
}
float
Download::distributed_copies() const {
const uint8_t* avail = m_download.chunks_seen();
const torrent::Bitfield* bitfield = m_download.file_list()->bitfield();
if (avail == NULL)
return 0;
int minAvail = std::numeric_limits<uint8_t>::max();
int num = 0;
for (uint32_t i = m_download.file_list()->size_chunks(); i-- > 0; ) {
int totAvail = (int)avail[i] + bitfield->get(i);
if (totAvail == minAvail) {
num++;
} else if (totAvail < minAvail) {
minAvail = totAvail;
num = 1;
}
}
return minAvail + 1 - bitfield->is_all_set() - (float)num / m_download.file_list()->size_chunks();
}
void
Download::set_throttle_name(const std::string& throttleName) {
if (m_download.info()->is_active())
throw torrent::input_error("Cannot set throttle on active download.");
torrent::ThrottlePair throttles = control->core()->get_throttle(throttleName);
m_download.set_upload_throttle(throttles.first);
m_download.set_download_throttle(throttles.second);
m_download.bencode()->get_key("rtorrent").insert_key("throttle_name", throttleName);
}
void
Download::set_root_directory(const std::string& path) {
// If the download is open, hashed and has completed chunks make
// sure to verify that the download files are still present.
//
// This should ensure that no one tries to set the destination
// directory 'after' moving files. In cases where the user wants to
// override this behavior the download must first be closed or
// 'd.directory_base.set' may be used.
rak::file_stat file_stat;
torrent::FileList* file_list = m_download.file_list();
if (is_hash_checked() && file_list->completed_chunks() != 0 &&
(file_list->is_multi_file() ?
!file_list->is_root_dir_created() :
!file_stat.update(file_list->front()->frozen_path()))) {
set_message("Cannot change the directory of an open download after the files have been moved.");
rpc::call_command("d.state.set", (int64_t)0, rpc::make_target(this));
control->core()->download_list()->close_directly(this);
throw torrent::input_error("Cannot change the directory of an open download atter the files have been moved.");
}
control->core()->download_list()->close_directly(this);
file_list->set_root_dir(rak::path_expand(path));
bencode()->get_key("rtorrent").insert_key("directory", path);
}
}
-159
View File
@@ -1,159 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_CORE_DOWNLOAD_H
#define RTORRENT_CORE_DOWNLOAD_H
#include <torrent/download.h>
#include <torrent/download_info.h>
#include <torrent/hash_string.h>
#include <torrent/tracker_list.h>
#include <torrent/data/file_list.h>
#include <torrent/peer/connection_list.h>
#include "globals.h"
namespace torrent {
class PeerList;
class TrackerList;
}
namespace core {
class Download {
public:
typedef torrent::Download download_type;
typedef torrent::FileList file_list_type;
typedef torrent::PeerList peer_list_type;
typedef torrent::TrackerList tracker_list_type;
typedef torrent::TrackerController tracker_controller_type;
typedef torrent::ConnectionList connection_list_type;
typedef download_type::ConnectionType connection_type;
static const int variable_hashing_stopped = 0;
static const int variable_hashing_initial = 1;
static const int variable_hashing_last = 2;
static const int variable_hashing_rehash = 3;
Download(download_type d);
~Download();
const torrent::DownloadInfo* info() const { return m_download.info(); }
const torrent::download_data* data() const { return m_download.data(); }
torrent::DownloadMain* main() { return m_download.main(); }
bool is_open() const { return m_download.info()->is_open(); }
bool is_active() const { return m_download.info()->is_active(); }
bool is_done() const { return m_download.file_list()->is_done(); }
bool is_downloading() const { return is_active() && !is_done(); }
bool is_seeding() const { return is_active() && is_done(); }
// FIXME: Fixed a bug in libtorrent that caused is_hash_checked to
// return true when the torrent is closed. Remove this redundant
// test in the next milestone.
bool is_hash_checked() const { return is_open() && m_download.is_hash_checked(); }
bool is_hash_checking() const { return m_download.is_hash_checking(); }
bool is_hash_failed() const { return m_hashFailed; }
void set_hash_failed(bool v) { m_hashFailed = v; }
download_type* download() { return &m_download; }
const download_type* c_download() const { return &m_download; }
file_list_type* file_list() { return m_download.file_list(); }
const file_list_type* c_file_list() const { return m_download.file_list(); }
peer_list_type* peer_list() { return m_download.peer_list(); }
const peer_list_type* c_peer_list() const { return m_download.peer_list(); }
torrent::Object* bencode() { return m_download.bencode(); }
tracker_list_type* tracker_list() { return m_download.tracker_list(); }
uint32_t tracker_list_size() const { return m_download.tracker_list()->size(); }
tracker_controller_type* tracker_controller() { return m_download.tracker_controller(); }
connection_list_type* connection_list() { return m_download.connection_list(); }
uint32_t connection_list_size() const;
const std::string& message() const { return m_message; }
void set_message(const std::string& msg) { m_message = msg; }
void enable_udp_trackers(bool state);
uint32_t priority();
void set_priority(uint32_t p);
uint32_t resume_flags() { return m_resumeFlags; }
void set_resume_flags(uint32_t flags) { m_resumeFlags = flags; }
void set_root_directory(const std::string& path);
void set_throttle_name(const std::string& throttleName);
bool operator == (const std::string& str) const;
float distributed_copies() const;
// HACK: Choke group setting.
unsigned int group() const { return m_group; }
void set_group(unsigned int g) { m_group = g; }
private:
Download(const Download&);
void operator () (const Download&);
void receive_tracker_msg(std::string msg);
void receive_chunk_failed(uint32_t idx);
// Store the FileList instance so we can use slots etc on it.
download_type m_download;
bool m_hashFailed;
std::string m_message;
uint32_t m_resumeFlags;
unsigned int m_group;
};
inline bool
Download::operator == (const std::string& str) const {
return str.size() == torrent::HashString::size_data && *torrent::HashString::cast_from(str) == m_download.info()->hash();
}
}
#endif
-440
View File
@@ -1,440 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <cstdlib>
#include <fstream>
#include <sstream>
#include <stdexcept>
#include <rak/path.h>
#include <tr1/functional>
#include <torrent/utils/log.h>
#include <torrent/utils/resume.h>
#include <torrent/object.h>
#include <torrent/object_stream.h>
#include <torrent/exceptions.h>
#include <torrent/rate.h>
#include <torrent/data/file_utils.h>
#include "rpc/parse_commands.h"
#include "curl_get.h"
#include "control.h"
#include "http_queue.h"
#include "globals.h"
#include "manager.h"
#include "download.h"
#include "download_factory.h"
#include "download_store.h"
namespace core {
bool
is_network_uri(const std::string& uri) {
return
std::strncmp(uri.c_str(), "http://", 7) == 0 ||
std::strncmp(uri.c_str(), "https://", 8) == 0 ||
std::strncmp(uri.c_str(), "ftp://", 6) == 0;
}
static bool
download_factory_add_stream(torrent::Object* root, const char* key, const char* filename) {
std::fstream stream(filename, std::ios::in | std::ios::binary);
if (!stream.is_open())
return false;
torrent::Object obj;
stream >> obj;
if (!stream.good())
return false;
root->insert_key_move(key, obj);
return true;
}
bool
is_magnet_uri(const std::string& uri) {
return
std::strncmp(uri.c_str(), "magnet:?", 8) == 0;
}
DownloadFactory::DownloadFactory(Manager* m) :
m_manager(m),
m_stream(NULL),
m_object(NULL),
m_commited(false),
m_loaded(false),
m_session(false),
m_start(false),
m_printLog(true),
m_isFile(false) {
m_taskLoad.slot() = std::tr1::bind(&DownloadFactory::receive_load, this);
m_taskCommit.slot() = std::tr1::bind(&DownloadFactory::receive_commit, this);
// m_variables["connection_leech"] = rpc::call_command("protocol.connection.leech");
// m_variables["connection_seed"] = rpc::call_command("protocol.connection.seed");
m_variables["connection_leech"] = std::string();
m_variables["connection_seed"] = std::string();
m_variables["directory"] = rpc::call_command("directory.default");
m_variables["tied_to_file"] = torrent::Object((int64_t)false);
}
DownloadFactory::~DownloadFactory() {
priority_queue_erase(&taskScheduler, &m_taskLoad);
priority_queue_erase(&taskScheduler, &m_taskCommit);
delete m_stream;
delete m_object;
m_stream = NULL;
}
void
DownloadFactory::load(const std::string& uri) {
m_uri = uri;
priority_queue_insert(&taskScheduler, &m_taskLoad, cachedTime);
}
// This function must be called before DownloadFactory::commit().
void
DownloadFactory::load_raw_data(const std::string& input) {
if (m_stream)
throw torrent::internal_error("DownloadFactory::load*() called on an object with m_stream != NULL");
m_stream = new std::stringstream(input);
m_loaded = true;
}
void
DownloadFactory::commit() {
priority_queue_insert(&taskScheduler, &m_taskCommit, cachedTime);
}
void
DownloadFactory::receive_load() {
if (m_stream)
throw torrent::internal_error("DownloadFactory::load*() called on an object with m_stream != NULL");
if (is_network_uri(m_uri)) {
// Http handling here.
m_stream = new std::stringstream;
HttpQueue::iterator itr = m_manager->http_queue()->insert(m_uri, m_stream);
(*itr)->signal_done().push_front(std::tr1::bind(&DownloadFactory::receive_loaded, this));
(*itr)->signal_failed().push_front(std::tr1::bind(&DownloadFactory::receive_failed, this, std::tr1::placeholders::_1));
m_variables["tied_to_file"] = (int64_t)false;
} else if (is_magnet_uri(m_uri)) {
// DEBUG: Use m_object.
m_stream = new std::stringstream();
*m_stream << "d10:magnet-uri" << m_uri.length() << ":" << m_uri << "e";
m_variables["tied_to_file"] = (int64_t)false;
receive_loaded();
} else {
std::fstream stream(rak::path_expand(m_uri).c_str(), std::ios::in | std::ios::binary);
if (!stream.is_open())
return receive_failed("Could not open file");
m_object = new torrent::Object;
stream >> *m_object;
if (!stream.good())
return receive_failed("Reading torrent file failed");
m_isFile = true;
receive_loaded();
}
}
void
DownloadFactory::receive_loaded() {
m_loaded = true;
if (m_commited)
receive_success();
}
void
DownloadFactory::receive_commit() {
m_commited = true;
if (m_loaded)
receive_success();
}
void
DownloadFactory::receive_success() {
Download* download = m_stream != NULL ?
m_manager->download_list()->create(m_stream, m_printLog) :
m_manager->download_list()->create(m_object, m_printLog);
m_object = NULL;
if (download == NULL) {
// core::Manager should already have added the error message to
// the log.
m_slot_finished();
return;
}
torrent::Object* root = download->bencode();
if (download->download()->info()->is_meta_download()) {
torrent::Object& meta = root->insert_key("rtorrent_meta_download", torrent::Object::create_map());
meta.insert_key("start", m_start);
meta.insert_key("print_log", m_printLog);
torrent::Object::list_type& commands = meta.insert_key("commands", torrent::Object::create_list()).as_list();
for (command_list_type::iterator itr = m_commands.begin(); itr != m_commands.end(); ++itr)
commands.push_back(*itr);
}
if (m_session) {
download_factory_add_stream(root, "rtorrent", (rak::path_expand(m_uri) + ".rtorrent").c_str());
download_factory_add_stream(root, "libtorrent_resume", (rak::path_expand(m_uri) + ".libtorrent_resume").c_str());
} else {
// We only allow session torrents to keep their
// 'rtorrent/libtorrent' sections. The "fast_resume" section
// should be safe to keep.
root->erase_key("rtorrent");
}
torrent::Object* rtorrent = &root->insert_preserve_copy("rtorrent", torrent::Object::create_map()).first->second;
torrent::Object& resumeObject = root->insert_preserve_copy("libtorrent_resume", torrent::Object::create_map()).first->second;
initialize_rtorrent(download, rtorrent);
if (!rtorrent->has_key_string("custom1")) rtorrent->insert_key("custom1", std::string());
if (!rtorrent->has_key_string("custom2")) rtorrent->insert_key("custom2", std::string());
if (!rtorrent->has_key_string("custom3")) rtorrent->insert_key("custom3", std::string());
if (!rtorrent->has_key_string("custom4")) rtorrent->insert_key("custom4", std::string());
if (!rtorrent->has_key_string("custom5")) rtorrent->insert_key("custom5", std::string());
rpc::call_command("d.uploads_min.set", rpc::call_command("throttle.min_uploads"), rpc::make_target(download));
rpc::call_command("d.uploads_max.set", rpc::call_command("throttle.max_uploads"), rpc::make_target(download));
rpc::call_command("d.downloads_min.set", rpc::call_command("throttle.min_downloads"), rpc::make_target(download));
rpc::call_command("d.downloads_max.set", rpc::call_command("throttle.max_downloads"), rpc::make_target(download));
rpc::call_command("d.peers_min.set", rpc::call_command("throttle.min_peers.normal"), rpc::make_target(download));
rpc::call_command("d.peers_max.set", rpc::call_command("throttle.max_peers.normal"), rpc::make_target(download));
rpc::call_command("d.tracker_numwant.set", rpc::call_command("trackers.numwant"), rpc::make_target(download));
rpc::call_command("d.max_file_size.set", rpc::call_command("system.file.max_size"), rpc::make_target(download));
if (rpc::call_command_value("d.complete", rpc::make_target(download)) != 0) {
if (rpc::call_command_value("throttle.min_peers.seed") >= 0)
rpc::call_command("d.peers_min.set", rpc::call_command("throttle.min_peers.seed"), rpc::make_target(download));
if (rpc::call_command_value("throttle.max_peers.seed") >= 0)
rpc::call_command("d.peers_max.set", rpc::call_command("throttle.max_peers.seed"), rpc::make_target(download));
}
if (!rpc::call_command_value("trackers.use_udp"))
download->enable_udp_trackers(false);
// Check first if we already have these values set in the session
// torrent, so that it is safe to change the values.
//
// Need to also catch the exceptions.
if (rpc::call_command_value("system.file.split_size") >= 0)
torrent::file_split_all(download->download()->file_list(),
rpc::call_command_value("system.file.split_size"),
rpc::call_command_string("system.file.split_suffix"));
if (!rtorrent->has_key_string("directory"))
rpc::call_command("d.directory.set", m_variables["directory"], rpc::make_target(download));
else
rpc::call_command("d.directory_base.set", rtorrent->get_key("directory"), rpc::make_target(download));
if (!m_session && m_variables["tied_to_file"].as_value())
rpc::call_command("d.tied_to_file.set", m_uri.empty() ? m_variables["tied_file"] : m_uri, rpc::make_target(download));
rpc::call_command("d.peer_exchange.set", rpc::call_command_value("protocol.pex"), rpc::make_target(download));
torrent::resume_load_addresses(*download->download(), resumeObject);
torrent::resume_load_file_priorities(*download->download(), resumeObject);
torrent::resume_load_tracker_settings(*download->download(), resumeObject);
// The action of inserting might cause the torrent to be
// opened/started or such. Figure out a nicer way of handling this.
if (m_manager->download_list()->insert(download) == m_manager->download_list()->end()) {
// ATM doesn't really ever get here.
delete download;
m_slot_finished();
return;
}
// Save the info-hash just in case the commands decide to delete it.
torrent::HashString infohash = download->info()->hash();
try {
if (torrent::log_groups[torrent::LOG_TORRENT_DEBUG].valid())
log_created(download, rtorrent);
std::for_each(m_commands.begin(), m_commands.end(),
rak::bind2nd(std::ptr_fun(&rpc::parse_command_multiple_std), rpc::make_target(download)));
if (m_manager->download_list()->find(infohash) == m_manager->download_list()->end())
throw torrent::input_error("The newly created download was removed.");
if (!m_session)
rpc::call_command("d.state.set", (int64_t)m_start, rpc::make_target(download));
rpc::commands.call_catch(m_session ? "event.download.inserted_session" : "event.download.inserted_new",
rpc::make_target(download), torrent::Object(), "Download event action failed: ");
} catch (torrent::input_error& e) {
std::string msg = "Command on torrent creation failed: " + std::string(e.what());
if (m_printLog)
m_manager->push_log_std(msg);
if (m_manager->download_list()->find(infohash) != m_manager->download_list()->end()) {
// Should stop it, mark it bad. Perhaps even delete it?
download->set_hash_failed(true);
download->set_message(msg);
// m_manager->download_list()->erase(m_manager->download_list()->find(infohash.data()));
}
}
m_slot_finished();
}
void
DownloadFactory::log_created(Download* download, torrent::Object* rtorrent) {
std::stringstream dump;
dump << "info_hash = " << torrent::hash_string_to_hex_str(download->info()->hash()) << std::endl;
dump << "session = " << (m_session ? "true" : "false") << std::endl;
if (download->download()->info()->is_meta_download())
dump << "magnet = true" << std::endl;
if (!rtorrent->has_key_string("directory"))
dump << "directory = \"" << (m_variables["directory"].is_string() ? m_variables["directory"].as_string() : std::string()) << '"' << std::endl;
else
dump << "directory_base = \"" << (rtorrent->get_key("directory").is_string() ? rtorrent->get_key("directory").as_string() : std::string()) << '"' << std::endl;
dump << "---COMMANDS---" << std::endl;
for (command_list_type::const_iterator itr = m_commands.begin(); itr != m_commands.end(); itr++) {
dump << *itr << std::endl;
}
std::string dump_str = dump.str();
lt_log_print_dump(torrent::LOG_TORRENT_DEBUG, dump_str.c_str(), dump_str.size(), "Creating new download:");
}
void
DownloadFactory::receive_failed(const std::string& msg) {
// Add message to log.
if (m_printLog)
m_manager->push_log_std(msg + ": \"" + m_uri + "\"");
m_slot_finished();
}
void
DownloadFactory::initialize_rtorrent(Download* download, torrent::Object* rtorrent) {
if (!rtorrent->has_key_value("state") || rtorrent->get_key_value("state") > 1) {
rtorrent->insert_key("state", (int64_t)m_start);
rtorrent->insert_key("state_changed", cachedTime.seconds());
rtorrent->insert_key("state_counter", int64_t());
} else if (!rtorrent->has_key_value("state_changed") ||
rtorrent->get_key_value("state_changed") > cachedTime.seconds() || rtorrent->get_key_value("state_changed") == 0 ||
!rtorrent->has_key_value("state_counter") || (uint64_t)rtorrent->get_key_value("state_counter") > (1 << 20)) {
rtorrent->insert_key("state_changed", cachedTime.seconds());
rtorrent->insert_key("state_counter", int64_t());
}
rtorrent->insert_preserve_copy("complete", (int64_t)0);
rtorrent->insert_preserve_copy("hashing", (int64_t)Download::variable_hashing_stopped);
rtorrent->insert_preserve_copy("timestamp.started", (int64_t)0);
rtorrent->insert_preserve_copy("timestamp.finished", (int64_t)0);
rtorrent->insert_preserve_copy("tied_to_file", "");
rtorrent->insert_key("loaded_file", m_isFile ? m_uri : std::string());
if (rtorrent->has_key_value("priority"))
rpc::call_command("d.priority.set", rtorrent->get_key_value("priority") % 4, rpc::make_target(download));
else
rpc::call_command("d.priority.set", (int64_t)2, rpc::make_target(download));
if (rtorrent->has_key_value("key")) {
download->tracker_list()->set_key(rtorrent->get_key_value("key"));
} else {
download->tracker_list()->set_key(random() % (std::numeric_limits<uint32_t>::max() - 1) + 1);
rtorrent->insert_key("key", download->tracker_list()->key());
}
if (rtorrent->has_key_value("total_uploaded"))
download->info()->mutable_up_rate()->set_total(rtorrent->get_key_value("total_uploaded"));
if (rtorrent->has_key_value("chunks_done") && rtorrent->has_key_value("chunks_wanted"))
download->download()->set_chunks_done(rtorrent->get_key_value("chunks_done"), rtorrent->get_key_value("chunks_wanted"));
download->set_throttle_name(rtorrent->has_key_string("throttle_name")
? rtorrent->get_key_string("throttle_name")
: std::string());
rtorrent->insert_preserve_copy("ignore_commands", (int64_t)0);
rtorrent->insert_preserve_copy("views", torrent::Object::create_list());
rtorrent->insert_preserve_type("connection_leech", m_variables["connection_leech"]);
rtorrent->insert_preserve_type("connection_seed", m_variables["connection_seed"]);
rtorrent->insert_preserve_copy("choke_heuristics.up.leech", std::string());
rtorrent->insert_preserve_copy("choke_heuristics.up.seed", std::string());
rtorrent->insert_preserve_copy("choke_heuristics.down.leech", std::string());
rtorrent->insert_preserve_copy("choke_heuristics.down.seed", std::string());
}
}
-122
View File
@@ -1,122 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// The DownloadFactory class assures that loading torrents can be done
// anywhere in the code by queueing the task. The user may change
// settings while, or even after, the torrent is loading.
#ifndef RTORRENT_CORE_DOWNLOAD_FACTORY_H
#define RTORRENT_CORE_DOWNLOAD_FACTORY_H
#include <iosfwd>
#include <rak/priority_queue_default.h>
#include <torrent/object.h>
#include <tr1/functional>
#include "http_queue.h"
namespace core {
class Manager;
class DownloadFactory {
public:
typedef std::tr1::function<void ()> slot_void;
typedef std::vector<std::string> command_list_type;
// Do not destroy this object while it is in a HttpQueue.
DownloadFactory(Manager* m);
~DownloadFactory();
// Calling of receive_load() is delayed so you can change whatever
// you want without fear of the slots being triggered as you call
// load() or commit().
void load(const std::string& uri);
void load_raw_data(const std::string& input);
void commit();
command_list_type& commands() { return m_commands; }
torrent::Object::map_type& variables() { return m_variables; }
bool get_session() const { return m_session; }
void set_session(bool v) { m_session = v; }
bool get_start() const { return m_start; }
void set_start(bool v) { m_start = v; }
bool print_log() const { return m_printLog; }
void set_print_log(bool v) { m_printLog = v; }
void slot_finished(slot_void s) { m_slot_finished = s; }
private:
void receive_load();
void receive_loaded();
void receive_commit();
void receive_success();
void receive_failed(const std::string& msg);
void log_created(Download* download, torrent::Object* rtorrent);
void initialize_rtorrent(Download* download, torrent::Object* rtorrent);
Manager* m_manager;
std::iostream* m_stream;
torrent::Object* m_object;
bool m_commited;
bool m_loaded;
std::string m_uri;
bool m_session;
bool m_start;
bool m_printLog;
bool m_isFile;
command_list_type m_commands;
torrent::Object::map_type m_variables;
slot_void m_slot_finished;
rak::priority_item m_taskLoad;
rak::priority_item m_taskCommit;
};
bool is_network_uri(const std::string& uri);
bool is_magnet_uri(const std::string& uri);
}
#endif
-724
View File
@@ -1,724 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <algorithm>
#include <fstream>
#include <iostream>
#include <rak/functional.h>
#include <rak/string_manip.h>
#include <torrent/data/file.h>
#include <torrent/utils/resume.h>
#include <torrent/exceptions.h>
#include <torrent/download.h>
#include <torrent/hash_string.h>
#include <torrent/object.h>
#include <torrent/object_stream.h>
#include <torrent/torrent.h>
#include <torrent/utils/log.h>
#include "rpc/parse_commands.h"
#include "control.h"
#include "globals.h"
#include "manager.h"
#include "view.h"
#include "view_manager.h"
#include "dht_manager.h"
#include "download.h"
#include "download_list.h"
#include "download_store.h"
#define DL_TRIGGER_EVENT(download, event_name) \
rpc::commands.call_catch(event_name, rpc::make_target(download), torrent::Object(), "Event '" event_name "' failed: ");
namespace core {
inline void
DownloadList::check_contains(Download* d) {
#ifdef USE_EXTRA_DEBUG
if (std::find(begin(), end(), d) == end())
throw torrent::internal_error("DownloadList::check_contains(...) failed.");
#endif
}
void
DownloadList::clear() {
std::for_each(begin(), end(), std::bind1st(std::mem_fun(&DownloadList::close), this));
std::for_each(begin(), end(), rak::call_delete<Download>());
base_type::clear();
}
void
DownloadList::session_save() {
unsigned int c = std::count_if(begin(), end(), std::bind1st(std::mem_fun(&DownloadStore::save_resume), control->core()->download_store()));
if (c != size())
lt_log_print(torrent::LOG_ERROR, "Failed to save session torrents.");
control->dht_manager()->save_dht_cache();
}
DownloadList::iterator
DownloadList::find(const torrent::HashString& hash) {
return std::find_if(begin(), end(), rak::equal(hash, rak::on(std::mem_fun(&Download::info), std::mem_fun(&torrent::DownloadInfo::hash))));
}
DownloadList::iterator
DownloadList::find_hex(const char* hash) {
torrent::HashString key;
for (torrent::HashString::iterator itr = key.begin(), last = key.end(); itr != last; itr++, hash += 2)
*itr = (rak::hexchar_to_value(*hash) << 4) + rak::hexchar_to_value(*(hash + 1));
return std::find_if(begin(), end(), rak::equal(key, rak::on(std::mem_fun(&Download::info), std::mem_fun(&torrent::DownloadInfo::hash))));
}
Download*
DownloadList::find_hex_ptr(const char* hash) {
iterator itr = find_hex(hash);
return itr != end() ? *itr : NULL;
}
Download*
DownloadList::create(torrent::Object* obj, bool printLog) {
torrent::Download download;
try {
download = torrent::download_add(obj);
} catch (torrent::local_error& e) {
delete obj;
if (printLog)
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not create download: %s", e.what());
return NULL;
}
// There's no non-critical exceptions that should be throwable by
// the ctor, so don't catch.
return new Download(download);
}
Download*
DownloadList::create(std::istream* str, bool printLog) {
torrent::Object* object = new torrent::Object;
torrent::Download download;
try {
*str >> *object;
// Don't throw input_error from here as gcc-3.3.5 produces bad
// code.
if (str->fail()) {
delete object;
if (printLog)
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not create download, the input is not a valid torrent.");
return NULL;
}
download = torrent::download_add(object);
} catch (torrent::local_error& e) {
delete object;
if (printLog)
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not create download: %s", e.what());
return NULL;
}
// There's no non-critical exceptions that should be throwable by
// the ctor, so don't catch.
return new Download(download);
}
DownloadList::iterator
DownloadList::insert(Download* download) {
iterator itr = base_type::insert(end(), download);
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Inserting download.");
try {
(*itr)->data()->slot_initial_hash() = tr1::bind(&DownloadList::hash_done, this, download);
(*itr)->data()->slot_download_done() = tr1::bind(&DownloadList::received_finished, this, download);
// This needs to be separated into two different calls to ensure
// the download remains in the view.
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), std::bind2nd(std::mem_fun(&View::insert), download));
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), std::bind2nd(std::mem_fun(&View::filter_download), download));
DL_TRIGGER_EVENT(*itr, "event.download.inserted");
} catch (torrent::local_error& e) {
// Should perhaps relax this, just print an error and remove the
// downloads?
throw torrent::internal_error("Caught during DownloadList::insert(...): " + std::string(e.what()));
}
return itr;
}
void
DownloadList::erase_ptr(Download* download) {
erase(std::find(begin(), end(), download));
}
DownloadList::iterator
DownloadList::erase(iterator itr) {
if (itr == end())
throw torrent::internal_error("DownloadList::erase(...) could not find download.");
lt_log_print_info(torrent::LOG_TORRENT_INFO, (*itr)->info(), "download_list", "Erasing download.");
// Makes sure close doesn't restart hashing of this download.
(*itr)->set_hash_failed(true);
close(*itr);
control->core()->download_store()->remove(*itr);
DL_TRIGGER_EVENT(*itr, "event.download.erased");
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), std::bind2nd(std::mem_fun(&View::erase), *itr));
torrent::download_remove(*(*itr)->download());
delete *itr;
return base_type::erase(itr);
}
bool
DownloadList::open(Download* download) {
try {
open_throw(download);
return true;
} catch (torrent::local_error& e) {
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not open download: %s", e.what());
return false;
}
}
void
DownloadList::open_throw(Download* download) {
check_contains(download);
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Opening download.");
if (download->download()->info()->is_open())
return;
int openFlags = download->resume_flags();
if (rpc::call_command_value("system.file.allocate"))
openFlags |= torrent::Download::open_enable_fallocate;
download->download()->open(openFlags);
DL_TRIGGER_EVENT(download, "event.download.opened");
}
void
DownloadList::close(Download* download) {
try {
close_throw(download);
} catch (torrent::local_error& e) {
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not close download: %s", e.what());
}
}
void
DownloadList::close_directly(Download* download) {
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Closing download directly.");
if (download->download()->info()->is_active()) {
download->download()->stop(torrent::Download::stop_skip_tracker);
if (torrent::resume_check_target_files(*download->download(), download->download()->bencode()->get_key("libtorrent_resume")))
torrent::resume_save_progress(*download->download(), download->download()->bencode()->get_key("libtorrent_resume"));
}
if (download->download()->info()->is_open())
download->download()->close();
}
void
DownloadList::close_quick(Download* download) {
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Closing download quickly.");
close(download);
// Make sure we cancel any tracker requests. This should rather be
// handled by some parameter to the close function, or some other
// way of giving the client more control of when STOPPED requests
// are sent.
download->download()->manual_cancel();
}
void
DownloadList::close_throw(Download* download) {
check_contains(download);
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Closing download with throw.");
// When pause gets called it will clear the initial hash check state
// and set hash failed. This should ensure hashing doesn't restart
// until resume gets called.
pause(download);
// Check for is_open after pause due to hashing.
if (!download->is_open())
return;
// Save the torrent on close, this covers shutdown and if a torrent
// is manually closed which would clear the progress data. For
// better crash protection, save regulary in addition to this.
//
// Used to be in pause, but this was wrong for rehashing etc.
//
// Reconsider this save. Should be done explicitly when shutting down.
//control->core()->download_store()->save(download);
download->download()->close();
if (!download->is_hash_failed() && rpc::call_command_value("d.hashing", rpc::make_target(download)) != Download::variable_hashing_stopped)
throw torrent::internal_error("DownloadList::close_throw(...) called but we're going into a hashing loop.");
DL_TRIGGER_EVENT(download, "event.download.hash_removed");
DL_TRIGGER_EVENT(download, "event.download.closed");
}
void
DownloadList::resume(Download* download, int flags) {
check_contains(download);
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Resuming download: flags:%0x.", flags);
try {
if (download->download()->info()->is_active())
return;
rpc::parse_command_single(rpc::make_target(download), "view.set_visible=active");
// We need to make sure the flags aren't reset if someone decideds
// to call resume() while it is hashing, etc.
if (download->resume_flags() == ~uint32_t())
download->set_resume_flags(flags);
// Manual or end-of-download rehashing clears the resume data so
// we can just start the hashing again without clearing it again.
//
// It is also assumed the is_hash_checked flag gets cleared when
// 'hashing' was set.
if (!download->is_hash_checked()) {
// If the hash failed flag wasn't cleared then hashing won't be
// initiated.
if (download->is_hash_failed())
return;
if (rpc::call_command_value("d.hashing", rpc::make_target(download)) == Download::variable_hashing_stopped)
rpc::call_command("d.hashing.set", Download::variable_hashing_initial, rpc::make_target(download));
DL_TRIGGER_EVENT(download, "event.download.hash_queued");
return;
}
// This will never actually do anything due to the above hash check.
// open_throw(download);
rpc::call_command("d.state_changed.set", cachedTime.seconds(), rpc::make_target(download));
rpc::call_command("d.state_counter.set", rpc::call_command_value("d.state_counter", rpc::make_target(download)) + 1, rpc::make_target(download));
if (download->is_done()) {
torrent::Object conn_current = rpc::call_command("d.connection_seed", torrent::Object(), rpc::make_target(download));
torrent::Object choke_up = rpc::call_command("d.up.choke_heuristics.seed", torrent::Object(), rpc::make_target(download));
torrent::Object choke_down = rpc::call_command("d.down.choke_heuristics.seed", torrent::Object(), rpc::make_target(download));
if (conn_current.is_string_empty()) conn_current = rpc::call_command("protocol.connection.seed", torrent::Object(), rpc::make_target(download));
if (choke_up.is_string_empty()) choke_up = rpc::call_command("protocol.choke_heuristics.up.seed", torrent::Object(), rpc::make_target(download));
if (choke_down.is_string_empty()) choke_down = rpc::call_command("protocol.choke_heuristics.down.seed", torrent::Object(), rpc::make_target(download));
rpc::call_command("d.connection_current.set", conn_current, rpc::make_target(download));
rpc::call_command("d.up.choke_heuristics.set", choke_up, rpc::make_target(download));
rpc::call_command("d.down.choke_heuristics.set", choke_down, rpc::make_target(download));
} else {
torrent::Object conn_current = rpc::call_command("d.connection_leech", torrent::Object(), rpc::make_target(download));
torrent::Object choke_up = rpc::call_command("d.up.choke_heuristics.leech", torrent::Object(), rpc::make_target(download));
torrent::Object choke_down = rpc::call_command("d.down.choke_heuristics.leech", torrent::Object(), rpc::make_target(download));
if (conn_current.is_string_empty()) conn_current = rpc::call_command("protocol.connection.leech", torrent::Object(), rpc::make_target(download));
if (choke_up.is_string_empty()) choke_up = rpc::call_command("protocol.choke_heuristics.up.leech", torrent::Object(), rpc::make_target(download));
if (choke_down.is_string_empty()) choke_down = rpc::call_command("protocol.choke_heuristics.down.leech", torrent::Object(), rpc::make_target(download));
rpc::call_command("d.connection_current.set", conn_current, rpc::make_target(download));
rpc::call_command("d.up.choke_heuristics.set", choke_up, rpc::make_target(download));
rpc::call_command("d.down.choke_heuristics.set", choke_down, rpc::make_target(download));
// For the moment, clear the resume data so we force hash-check
// on non-complete downloads after a crash. This shouldn't be
// needed, but for some reason linux 2.6 is very lazy about
// updating mtime.
//
// Disabling this due to the new resume code.
// torrent::resume_save_progress(*download->download(), download->download()->bencode()->get_key("libtorrent_resume"), true);
}
// If the DHT server is set to auto, start it now.
if (!download->download()->info()->is_private())
control->dht_manager()->auto_start();
// Update the priority to ensure it has the correct
// seeding/unfinished modifiers.
download->set_priority(download->priority());
download->download()->start(download->resume_flags());
download->set_resume_flags(~uint32_t());
DL_TRIGGER_EVENT(download, "event.download.resumed");
} catch (torrent::local_error& e) {
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not resume download: %s", e.what());
}
}
void
DownloadList::pause(Download* download, int flags) {
check_contains(download);
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Pausing download: flags:%0x.", flags);
try {
download->set_resume_flags(~uint32_t());
rpc::parse_command_single(rpc::make_target(download), "view.set_not_visible=active");
// Always clear hashing on pause. When a hashing request is added,
// it should have cleared the hash resume data.
if (rpc::call_command_value("d.hashing", rpc::make_target(download)) != Download::variable_hashing_stopped) {
download->download()->hash_stop();
rpc::call_command_set_value("d.hashing.set", Download::variable_hashing_stopped, rpc::make_target(download));
DL_TRIGGER_EVENT(download, "event.download.hash_removed");
}
if (!download->download()->info()->is_active())
return;
download->download()->stop(flags);
torrent::resume_save_progress(*download->download(), download->download()->bencode()->get_key("libtorrent_resume"));
// TODO: This is actually for pause, not stop... And doesn't get
// called when the download isn't active, but was in the 'started'
// view.
DL_TRIGGER_EVENT(download, "event.download.paused");
rpc::call_command("d.state_changed.set", cachedTime.seconds(), rpc::make_target(download));
rpc::call_command("d.state_counter.set", rpc::call_command_value("d.state_counter", rpc::make_target(download)), rpc::make_target(download));
// If initial seeding is complete, don't try it again when restarting.
if (download->is_done() &&
rpc::call_command("d.connection_current", torrent::Object(), rpc::make_target(download)).as_string() == "initial_seed")
rpc::call_command("d.connection_seed.set", rpc::call_command("d.connection_current", torrent::Object(), rpc::make_target(download)), rpc::make_target(download));
// Save the state after all the slots, etc have been called so we
// include the modifications they may make.
//control->core()->download_store()->save(download);
} catch (torrent::local_error& e) {
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not pause download: %s", e.what());
}
}
void
DownloadList::check_hash(Download* download) {
check_contains(download);
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Checking hash.");
try {
if (rpc::call_command_value("d.hashing", rpc::make_target(download)) != Download::variable_hashing_stopped)
return;
hash_queue(download, Download::variable_hashing_rehash);
} catch (torrent::local_error& e) {
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not check hash: %s", e.what());
}
}
void
DownloadList::hash_done(Download* download) {
check_contains(download);
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Hash done.");
if (download->is_hash_checking() || download->is_active())
throw torrent::internal_error("DownloadList::hash_done(...) download in invalid state.");
if (!download->is_hash_checked()) {
download->set_hash_failed(true);
DL_TRIGGER_EVENT(download, "event.download.hash_failed");
return;
}
// Need to find some sane conditional here. Can we check the total
// downloaded to ensure something was transferred, thus we didn't
// just hash an already completed torrent with lacking session data?
//
// Perhaps we should use a seperate variable or state, and check
// that. Thus we can bork the download if the hash check doesn't
// confirm all the data, avoiding large BW usage on f.ex. the
// ReiserFS bug with >4GB files.
int64_t hashing = rpc::call_command_value("d.hashing", rpc::make_target(download));
rpc::call_command_set_value("d.hashing.set", Download::variable_hashing_stopped, rpc::make_target(download));
if (download->is_done() && download->download()->info()->is_meta_download())
return process_meta_download(download);
switch (hashing) {
case Download::variable_hashing_initial:
case Download::variable_hashing_rehash:
// Normal re/hashing.
// If the download was previously completed but the files were
// f.ex deleted, then we clear the state and complete.
if (rpc::call_command_value("d.complete", rpc::make_target(download)) && !download->is_done()) {
rpc::call_command("d.state.set", (int64_t)0, rpc::make_target(download));
download->set_message("Download registered as completed, but hash check returned unfinished chunks.");
}
// Save resume data so we update time-stamps and priorities if
// they were invalid/changed while loading/hashing.
rpc::call_command("d.complete.set", (int64_t)download->is_done(), rpc::make_target(download));
torrent::resume_save_progress(*download->download(), download->download()->bencode()->get_key("libtorrent_resume"));
if (rpc::call_command_value("d.state", rpc::make_target(download)) == 1)
resume(download, download->resume_flags());
break;
case Download::variable_hashing_last:
if (download->is_done()) {
confirm_finished(download);
} else {
download->set_message("Hash check on download completion found bad chunks, consider using \"safe_sync\".");
lt_log_print(torrent::LOG_TORRENT_ERROR, "Hash check on download completion found bad chunks, consider using \"safe_sync\".");
DL_TRIGGER_EVENT(download, "event.download.hash_final_failed");
}
// TODO: Should we skip the 'hash_done' event here?
return;
case Download::variable_hashing_stopped:
default:
// Either an error or someone wrote to the hashing variable...
download->set_message("Hash check completed but the \"hashing\" variable is in an invalid state.");
return;
}
DL_TRIGGER_EVENT(download, "event.download.hash_done");
}
void
DownloadList::hash_queue(Download* download, int type) {
check_contains(download);
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Hash queue.");
if (rpc::call_command_value("d.hashing", rpc::make_target(download)) != Download::variable_hashing_stopped)
throw torrent::internal_error("DownloadList::hash_queue(...) hashing already queued.");
// HACK
if (download->is_open()) {
pause(download, torrent::Download::stop_skip_tracker);
download->download()->close();
DL_TRIGGER_EVENT(download, "event.download.hash_removed");
DL_TRIGGER_EVENT(download, "event.download.closed");
}
torrent::resume_clear_progress(*download->download(), download->download()->bencode()->get_key("libtorrent_resume"));
download->set_hash_failed(false);
rpc::call_command_set_value("d.hashing.set", type, rpc::make_target(download));
if (download->is_open())
throw torrent::internal_error("DownloadList::hash_clear(...) download still open.");
// If any more stuff is added here, make sure resume etc are still
// correct.
DL_TRIGGER_EVENT(download, "event.download.hash_queued");
}
void
DownloadList::received_finished(Download* download) {
check_contains(download);
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Received finished.");
if (rpc::call_command_value("pieces.hash.on_completion"))
// Set some 'checking_finished_thingie' variable to make hash_done
// trigger correctly, also so it can bork on missing data.
hash_queue(download, Download::variable_hashing_last);
else
confirm_finished(download);
}
// The download must be open when we call this function.
void
DownloadList::confirm_finished(Download* download) {
check_contains(download);
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Confirming finished.");
if (download->download()->info()->is_meta_download())
return process_meta_download(download);
rpc::call_command("d.complete.set", (int64_t)1, rpc::make_target(download));
// Clean up these settings:
torrent::Object conn_current = rpc::call_command("d.connection_seed", torrent::Object(), rpc::make_target(download));
torrent::Object choke_up = rpc::call_command("d.up.choke_heuristics.seed", torrent::Object(), rpc::make_target(download));
torrent::Object choke_down = rpc::call_command("d.down.choke_heuristics.seed", torrent::Object(), rpc::make_target(download));
if (conn_current.is_string_empty()) conn_current = rpc::call_command("protocol.connection.seed", torrent::Object(), rpc::make_target(download));
if (choke_up.is_string_empty()) choke_up = rpc::call_command("protocol.choke_heuristics.up.seed", torrent::Object(), rpc::make_target(download));
if (choke_down.is_string_empty()) choke_down = rpc::call_command("protocol.choke_heuristics.down.seed", torrent::Object(), rpc::make_target(download));
rpc::call_command("d.connection_current.set", conn_current, rpc::make_target(download));
rpc::call_command("d.up.choke_heuristics.set", choke_up, rpc::make_target(download));
rpc::call_command("d.down.choke_heuristics.set", choke_down, rpc::make_target(download));
download->set_priority(download->priority());
if (rpc::call_command_value("d.peers_min", rpc::make_target(download)) == rpc::call_command_value("throttle.min_peers.normal") &&
rpc::call_command_value("throttle.min_peers.seed") >= 0)
rpc::call_command("d.peers_min.set", rpc::call_command("throttle.min_peers.seed"), rpc::make_target(download));
if (rpc::call_command_value("d.peers_max", rpc::make_target(download)) == rpc::call_command_value("throttle.max_peers.normal") &&
rpc::call_command_value("throttle.max_peers.seed") >= 0)
rpc::call_command("d.peers_max.set", rpc::call_command("throttle.max_peers.seed"), rpc::make_target(download));
// Do this before the slots are called in case one of them closes
// the download.
//
// Obsolete.
if (!download->is_active() && rpc::call_command_value("session.on_completion") != 0) {
// torrent::resume_save_progress(*download->download(), download->download()->bencode()->get_key("libtorrent_resume"));
control->core()->download_store()->save_resume(download);
}
// Send the completed request before resuming so we don't reset the
// up/downloaded baseline.
download->download()->send_completed();
// Save the hash in case the finished event erases it.
torrent::HashString infohash = download->info()->hash();
DL_TRIGGER_EVENT(download, "event.download.finished");
if (find(infohash) == end())
return;
// if (download->resume_flags() != ~uint32_t())
// throw torrent::internal_error("DownloadList::confirm_finished(...) download->resume_flags() != ~uint32_t().");
// See #1292.
//
// Just reset the value for the moment. If a torrent finishes while
// others are hashing, or some other situtation that causes resume
// flag to change could cause the state to be invalid.
//
// TODO: Add a check when setting the flags to see if the torrent is
// being hashed.
download->set_resume_flags(~uint32_t());
if (!download->is_active() && rpc::call_command_value("d.state", rpc::make_target(download)) == 1)
resume(download,
torrent::Download::start_no_create |
torrent::Download::start_skip_tracker |
torrent::Download::start_keep_baseline);
}
void
DownloadList::process_meta_download(Download* download) {
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Processing meta download.");
rpc::call_command("d.stop", torrent::Object(), rpc::make_target(download));
rpc::call_command("d.close", torrent::Object(), rpc::make_target(download));
std::string metafile = (*download->file_list()->begin())->frozen_path();
std::fstream file(metafile.c_str(), std::ios::in | std::ios::binary);
if (!file.is_open()) {
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not read download metadata.");
return;
}
torrent::Object* bencode = new torrent::Object(torrent::Object::create_map());
file >> bencode->insert_key("info", torrent::Object());
if (file.fail()) {
delete bencode;
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not create download, the input is not a valid torrent.");
return;
}
file.close();
// Steal the keys we still need. The old download has no use for them.
bencode->insert_key("rtorrent_meta_download", torrent::Object()).swap(download->bencode()->get_key("rtorrent_meta_download"));
if (download->bencode()->has_key("announce"))
bencode->insert_key("announce", torrent::Object()).swap(download->bencode()->get_key("announce"));
if (download->bencode()->has_key("announce-list"))
bencode->insert_key("announce-list", torrent::Object()).swap(download->bencode()->get_key("announce-list"));
erase_ptr(download);
control->core()->try_create_download_from_meta_download(bencode, metafile);
}
}
-171
View File
@@ -1,171 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_CORE_DOWNLOAD_LIST_H
#define RTORRENT_CORE_DOWNLOAD_LIST_H
#include <iosfwd>
#include <list>
#include <string>
namespace torrent {
class HashString;
}
namespace core {
class Download;
// Container for all downloads. Add slots to the slot maps to cause
// some action to be taken when the torrent changes states. Don't
// change the states from outside of core.
//
// Fix apply_on_ratio if the base_type is changed.
class DownloadList : private std::list<Download*> {
public:
typedef std::list<Download*> base_type;
using base_type::iterator;
using base_type::const_iterator;
using base_type::reverse_iterator;
using base_type::const_reverse_iterator;
using base_type::value_type;
using base_type::pointer;
using base_type::begin;
using base_type::end;
using base_type::rbegin;
using base_type::rend;
using base_type::empty;
using base_type::size;
DownloadList() { }
void clear();
void session_save();
iterator find(const torrent::HashString& hash);
iterator find_hex(const char* hash);
Download* find_hex_ptr(const char* hash);
// Might move this to DownloadFactory.
Download* create(std::istream* str, bool printLog);
Download* create(torrent::Object* obj, bool printLog);
iterator insert(Download* d);
void erase_ptr(Download* d);
iterator erase(iterator itr);
//void save(Download* d);
bool open(Download* d);
void open_throw(Download* d);
void close(Download* d);
void close_directly(Download* d);
void close_quick(Download* d);
void close_throw(Download* d);
void resume(Download* d, int flags = 0);
void pause(Download* d, int flags = 0);
void resume_default(Download* d) { resume(d); }
void pause_default(Download* d) { pause(d); }
void check_hash(Download* d);
enum {
D_SLOTS_INSERT,
D_SLOTS_ERASE,
D_SLOTS_OPEN,
D_SLOTS_CLOSE,
D_SLOTS_START,
D_SLOTS_STOP,
D_SLOTS_HASH_QUEUED,
D_SLOTS_HASH_REMOVED,
D_SLOTS_HASH_DONE,
D_SLOTS_FINISHED,
SLOTS_MAX_SIZE
};
static const char* slot_name(int m) {
switch(m) {
case D_SLOTS_INSERT: return "event.download.inserted";
case D_SLOTS_ERASE: return "event.download.erased";
case D_SLOTS_OPEN: return "event.download.opened";
case D_SLOTS_CLOSE: return "event.download.closed";
case D_SLOTS_START: return "event.download.resumed";
case D_SLOTS_STOP: return "event.download.paused";
case D_SLOTS_HASH_QUEUED: return "event.download.hash_queued";
case D_SLOTS_HASH_REMOVED: return "event.download.hash_removed";
case D_SLOTS_HASH_DONE: return "event.download.hash_done";
case D_SLOTS_FINISHED: return "event.download.finished";
default: return "BORK";
}
}
// The finished slots will be called when an active download with
// "finished" == 0 performs a hash check which returns a done
// torrent.
//
// But how to avoid sending 'completed' messages to the tracker?
// Also we need to handle cases when a hashing torrent starts up
// after a shutdown.
private:
DownloadList(const DownloadList&);
void operator = (const DownloadList&);
void hash_done(Download* d);
void hash_queue(Download* d, int type);
inline void check_contains(Download* d);
void received_finished(Download* d);
void confirm_finished(Download* d);
void process_meta_download(Download* d);
};
}
#endif
-67
View File
@@ -1,67 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_CORE_DOWNLOAD_SLOT_MAP_H
#define RTORRENT_CORE_DOWNLOAD_SLOT_MAP_H
#include <map>
#include <string>
#include <tr1/functional>
#include "download.h"
namespace core {
class DownloadSlotMap : public std::map<std::string, std::tr1::function<void (Download*)> > {
public:
typedef std::tr1::function<void (Download*)> slot_download;
typedef std::map<std::string, slot_download> Base;
void insert(const std::string& key, slot_download s) { Base::operator[](key) = s; }
void erase(const std::string& key) { Base::erase(key); }
void for_each(Download* d);
};
inline void
DownloadSlotMap::for_each(Download* d) {
for (iterator itr = begin(), last = end(); itr != last; ++itr)
itr->second(d);
}
}
#endif
-221
View File
@@ -1,221 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// DownloadStore handles the saving and listing of session torrents.
#include "config.h"
#include <fstream>
#include <stdio.h>
#include <unistd.h>
#include <rak/error_number.h>
#include <rak/path.h>
#include <rak/string_manip.h>
#include <torrent/utils/resume.h>
#include <torrent/object.h>
#include <torrent/exceptions.h>
#include <torrent/torrent.h>
#include <torrent/rate.h>
#include <torrent/object_stream.h>
#include "utils/directory.h"
#include "download.h"
#include "download_store.h"
namespace core {
void
DownloadStore::enable(bool lock) {
if (is_enabled())
throw torrent::input_error("Session directory already enabled.");
if (m_path.empty())
return;
if (lock)
m_lockfile.set_path(m_path + "rtorrent.lock");
else
m_lockfile.set_path(std::string());
if (!m_lockfile.try_lock()) {
if (rak::error_number::current().is_bad_path())
throw torrent::input_error("Could not lock session directory: \"" + m_path + "\", " + rak::error_number::current().c_str());
else
throw torrent::input_error("Could not lock session directory: \"" + m_path + "\", held by \"" + m_lockfile.locked_by_as_string() + "\".");
}
}
void
DownloadStore::disable() {
if (!is_enabled())
return;
m_lockfile.unlock();
}
void
DownloadStore::set_path(const std::string& path) {
if (is_enabled())
throw torrent::input_error("Tried to change session directory while it is enabled.");
if (!path.empty() && *path.rbegin() != '/')
m_path = rak::path_expand(path + '/');
else
m_path = rak::path_expand(path);
}
bool
DownloadStore::write_bencode(const std::string& filename, const torrent::Object& obj, uint32_t skip_mask) {
torrent::Object tmp;
std::fstream output(filename.c_str(), std::ios::out | std::ios::trunc);
if (!output.is_open())
goto download_store_save_error;
torrent::object_write_bencode(&output, &obj, skip_mask);
if (!output.good())
goto download_store_save_error;
output.close();
// Test the new file, to ensure it is a valid bencode string.
output.open(filename.c_str(), std::ios::in);
output >> tmp;
if (!output.good())
goto download_store_save_error;
output.close();
return true;
download_store_save_error:
output.close();
return false;
}
bool
DownloadStore::save(Download* d, int flags) {
if (!is_enabled())
return true;
torrent::Object* resume_base = &d->download()->bencode()->get_key("libtorrent_resume");
torrent::Object* rtorrent_base = &d->download()->bencode()->get_key("rtorrent");
// Move this somewhere else?
rtorrent_base->insert_key("chunks_done", d->download()->file_list()->completed_chunks());
rtorrent_base->insert_key("chunks_wanted", d->download()->data()->wanted_chunks());
rtorrent_base->insert_key("total_uploaded", d->info()->up_rate()->total());
// Don't save for completed torrents when we've cleared the uncertain_pieces.
torrent::resume_save_progress(*d->download(), *resume_base);
torrent::resume_save_uncertain_pieces(*d->download(), *resume_base);
torrent::resume_save_addresses(*d->download(), *resume_base);
torrent::resume_save_file_priorities(*d->download(), *resume_base);
torrent::resume_save_tracker_settings(*d->download(), *resume_base);
// Temp fixing of all flags, move to a better place:
resume_base->set_flags(torrent::Object::flag_session_data);
rtorrent_base->set_flags(torrent::Object::flag_session_data);
std::string base_filename = create_filename(d);
if (!write_bencode(base_filename + ".libtorrent_resume.new", *resume_base, 0) ||
!write_bencode(base_filename + ".rtorrent.new", *rtorrent_base, 0))
return false;
::rename((base_filename + ".libtorrent_resume.new").c_str(), (base_filename + ".libtorrent_resume").c_str());
::rename((base_filename + ".rtorrent.new").c_str(), (base_filename + ".rtorrent").c_str());
if (!(flags & flag_skip_static) &&
write_bencode(base_filename + ".new", *d->bencode(), torrent::Object::flag_session_data))
::rename((base_filename + ".new").c_str(), base_filename.c_str());
return true;
}
void
DownloadStore::remove(Download* d) {
if (!is_enabled())
return;
::unlink((create_filename(d) + ".libtorrent_resume").c_str());
::unlink((create_filename(d) + ".rtorrent").c_str());
::unlink(create_filename(d).c_str());
}
// This also needs to check that it isn't a directory.
bool
not_correct_format(const utils::directory_entry& entry) {
return !DownloadStore::is_correct_format(entry.d_name);
}
utils::Directory
DownloadStore::get_formated_entries() {
if (!is_enabled())
return utils::Directory();
utils::Directory d(m_path);
if (!d.update(utils::Directory::update_hide_dot))
throw torrent::storage_error("core::DownloadStore::update() could not open directory \"" + m_path + "\"");
d.erase(std::remove_if(d.begin(), d.end(), std::ptr_fun(&not_correct_format)), d.end());
return d;
}
bool
DownloadStore::is_correct_format(const std::string& f) {
if (f.size() != 48 || f.substr(40) != ".torrent")
return false;
for (std::string::const_iterator itr = f.begin(); itr != f.end() - 8; ++itr)
if (!(*itr >= '0' && *itr <= '9') &&
!(*itr >= 'A' && *itr <= 'F'))
return false;
return true;
}
std::string
DownloadStore::create_filename(Download* d) {
return m_path + rak::transform_hex(d->info()->hash().begin(), d->info()->hash().end()) + ".torrent";
}
}
-85
View File
@@ -1,85 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#ifndef RTORRENT_CORE_DOWNLOAD_STORE_H
#define RTORRENT_CORE_DOWNLOAD_STORE_H
#include <string>
#include "utils/lockfile.h"
namespace utils {
class Directory;
}
namespace core {
class Download;
class DownloadStore {
public:
static const int flag_skip_static = 0x1;
bool is_enabled() { return m_lockfile.is_locked(); }
void enable(bool lock);
void disable();
const std::string& path() const { return m_path; }
void set_path(const std::string& path);
bool save(Download* d, int flags);
bool save_full(Download* d) { return save(d, 0); }
bool save_resume(Download* d) { return save(d, flag_skip_static); }
void remove(Download* d);
// Currently shows all entries in the correct format.
utils::Directory get_formated_entries();
static bool is_correct_format(const std::string& f);
private:
std::string create_filename(Download* d);
bool write_bencode(const std::string& filename, const torrent::Object& obj, uint32_t skip_mask);
std::string m_path;
utils::Lockfile m_lockfile;
};
}
#endif
-89
View File
@@ -1,89 +0,0 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <memory>
#include <sstream>
#include <torrent/http.h>
#include "rak/functional.h"
#include "http_queue.h"
#include "curl_get.h"
namespace core {
HttpQueue::iterator
HttpQueue::insert(const std::string& url, std::iostream* s) {
std::auto_ptr<CurlGet> h(m_slot_factory());
h->set_url(url);
h->set_stream(s);
h->set_timeout(5 * 60);
iterator signal_itr = base_type::insert(end(), h.get());
h->signal_done().push_back(std::tr1::bind(&HttpQueue::erase, this, signal_itr));
h->signal_failed().push_back(std::tr1::bind(&HttpQueue::erase, this, signal_itr));
(*signal_itr)->start();
h.release();
for (signal_curl_get::iterator itr = m_signal_insert.begin(), last = m_signal_insert.end(); itr != last; itr++)
(*itr)(*signal_itr);
return signal_itr;
}
void
HttpQueue::erase(iterator signal_itr) {
for (signal_curl_get::iterator itr = m_signal_erase.begin(), last = m_signal_erase.end(); itr != last; itr++)
(*itr)(*signal_itr);
delete *signal_itr;
base_type::erase(signal_itr);
}
void
HttpQueue::clear() {
while (!empty())
erase(begin());
base_type::clear();
}
}

Some files were not shown because too many files have changed in this diff Show More