Compare commits

..
Author SHA1 Message Date
Jan Vidar Krey cfa38fa5ed Created gh-pages branch via GitHub 2012-04-24 01:34:49 -07:00
107 changed files with 405 additions and 19933 deletions
-8
View File
@@ -1,8 +0,0 @@
*~
*.[oa]
*.exe
*.gch
uhub-admin
adcrush
uhub
-6
View File
@@ -1,6 +0,0 @@
Authors of uHub
===============
Jan Vidar Krey, Design and implementation
-2
View File
@@ -1,2 +0,0 @@
Bugs are tracked on: http://bugs.extatic.org/
-674
View File
@@ -1,674 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. 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
them 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 prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. 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.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey 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;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If 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 convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU 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 that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
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.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
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.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
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
state 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 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/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program 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, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU 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 Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
-151
View File
@@ -1,151 +0,0 @@
0.2.8:
- Fix bug #13: getsockname() failure, use sockaddr from accept() instead.
- Fix bug #10: Improve logging, ensure logs are machine readable.
- Fix bug #12: asserts in adc_msg_parse -> enabled strict utf8 parsing.
0.2.7:
- Fixed a nasty crash (bug #11), Thanks Toast for finding it.
- Fix bug #9 - net_get_peer_address() failure on CentOS/Xen configurations.
- Write a log message if an operator reloads the config file.
- Don't print OK or ERROR when using '-s' or '-S' show the configuration.
- Cleanup credential string handling
- Made sure "!help" only display accessible commands.
- Cleanup in-hub command parsing
- Fix a possible crash if multiple INF messages are sent during login.
- Rewrote the mainloop to not use a timer.
0.2.6:
- Better "!uptime" command formatting.
- Better "!stats"; can display peak and current bandwidth usage.
- Added "+myip" command.
- Ensure super users and hub owners also have the operator flag set.
- Bug #1: Disconnecting users due to excessive "send queue".
- Bug #5: Always provide IP-address for all users, not just for active clients.
- Better send queue priorities.
- Dump configuration does not quote integer and boolean settings.
- Sources hosted by GitHub.com, and bug tracker on bugs.extatic.org
- Minor optimizations.
0.2.5-3487:
- Fixed out of memory situations, used when uhub operates on a limited heap.
- Code cleanups, reduced heap memory footprint.
- Fixed bug throwing users out due to exessive send queue when logging into a large hub.
- Added some simple hub commands (!stats, !uptime, !version, !help, etc).
0.2.4-3470:
- Added option chat_is_privileged, which makes chat for privileged users only.
- Started working on hub commands.
- Fixed a double free() related crash / abort.
- Fixed several send() -> EPIPE related crashes.
0.2.3-3429:
- Fixed one crash bug (jump to NULL).
- Fixed IPv6 dual stack issues on Winsock, but needs Vista or later to compile.
- Disable IPv6 if dual stack is not supported (WinXP with IPv6).
- Fixed bind issue for IPv4 addresses.
- Made sure no chat message could have PM context flag, unless set by the hub.
- Ignore empty INF update messages.
0.2.2-3393:
- Fixed a crash related to hub login.
- Added some fixes for older versions of libevent
- Added option to log messages through syslog.
- Added low bandwidth mode for really big hubs.
- Started writing a benchmark tool for the hub.
- Fix bug: reload configuration reset uptime.
- Experimental support for NetBSD 3.1.
0.2.1-3321:
- Added more robust configuration file parsing.
- Use defaults if config file is not found, unless a file is specified.
- Added user class super user (above operator, below admin).
- Added NAT override for clients behind the same NAT as the hub.
- Fixed a bug summarizing shared size and files for the PING extension.
- Fixed bugs related to hub limits.
0.2.0-3293:
- Fixed multiple crash bugs.
- Fully compatible with ADC/1.0.
- Protocol extensions: 'TIGR' and 'PING'
- Added support for configuring min/max share size, slots, concurrent hubs, not very well tested.
- Made all status message strings configurable.
- Various BSD issues fixed. Should perform equally well as Linux.
- Allow ignored configuration options (used when deprecating configuration options).
- Added command line options for checking configuration.
- A windows port is more or less done (MinGW)
- Lots of new auto tests added.
0.1.6-2608:
- Changes required for the ADC/0.14 specification.
- Stability fixes.
- Win32 fixes, it compiles and runs, but not quite ported yet.
- Added CMAKE files, which can be used instead of GNU make.
- Made sure all messages are terminated when created.
- Use length of messages, instead of strlen() to determine them.
- Added more asserts for messages. Spotted a few errors as a result of that.
- Added support for more sophisticated memory allocation debugging.
0.1.5-2462
- Fixed double free (crash).
- Fixed password challenge/response coding error (crash).
- Changes required for the new ADC/0.13 specification.
- Fixed IPv6 netmask matching (banning)
- Added UDP server, needed for auto-configure extension (AUT0)
- Send 'ping' messages periodically if nothing heard from clients.
- Print IP when client disconnects.
- Lots of automatic testcases added, fix many bugs in the process.
- GCC 2.95 compile fixes.
0.1.4-2301:
- uHub now requires and utilizes libevent. This allows for greater code
portability, and less code complexity.
- Various FreeBSD/OpenBSD/NetBSD fixes have been applied.
- Can now log files other than stderr.
- Added several automatic testcases.
- The application should now be much more stable, and never consume much CPU.
- Fixed several small annoying bugs.
0.1.3-2147:
- Changed license to GPL3
- Fixed several crashes
- Major code cleanups
- Refactored event handling
- Log file format change (minor)
- Automatic regression testing of code base (via exotic).
- Memory handling debug infrastructure.
0.1.2-2020:
- Fix infinite loops
- Don't log users leaving unless they are logged in.
- Fix private messages in chat only hubs.
- Operators/admins override chat only hub settings.
- Fix client/server protocol support negotiation handling
- IP banning should now work (IPv6 is not tested yet).
0.1.1-1956:
- Fixed memory leaks in ACL handling
- Prevent unneeded malloc's in command handling when buffers are big enough.
- Code cleanups and more doxygen style comments added.
- Fixed crashes and infinite loops
- FreeBSD compile fixes
- Timestamp log messages.
- Log network/bandwidth statistics
0.1.0-1840:
- First public release
-250
View File
@@ -1,250 +0,0 @@
##
## Makefile for uhub (Use GNU make)
## Copyright (C) 2007-2010, Jan Vidar Krey <janvidar@extatic.org>
#
CC = gcc
LD := $(CC)
MV := mv
RANLIB := ranlib
CFLAGS += -pipe -Wall
USE_SSL ?= NO
USE_LIBEVENT ?= NO
USE_BIGENDIAN ?= AUTO
BITS ?= AUTO
SILENT ?= YES
TERSE ?= NO
STACK_PROTECT ?= NO
ifeq ($(OS), Windows_NT)
WINDOWS ?= YES
endif
ifeq (SOLARIS,YES)
LDLIBS += -lsocket -lnsl
endif
CFLAGS += -I./src/
ifeq ($(WINDOWS),YES)
USE_BIGENDIAN := NO
LDLIBS += -lws2_32
UHUB_CONF_DIR ?= c:/uhub/
UHUB_PREFIX ?= c:/uhub/
CFLAGS += -mno-cygwin
LDFLAGS += -mno-cygwin
BIN_EXT ?= .exe
GIT_REVISION ?= NO
else
DESTDIR ?= /
UHUB_CONF_DIR ?= $(DESTDIR)/etc/uhub
UHUB_PREFIX ?= $(DESTDIR)/usr/local
CFLAGS += -I/usr/local/include
LDFLAGS += -L/usr/local/lib
BIN_EXT ?=
endif
ifeq ($(SILENT),YES)
MSG_CC=@echo " CC:" $(notdir $^) &&
MSG_LD=@echo " LD:" $(notdir $@) &&
MSG_AR=@echo " AR:" $(notdir $@) &&
else
MSG_CC=
MSG_LD=
MSG_AR=
endif
ifeq ($(TERSE), YES)
MSG_CC=@
MSG_LD=@
MSG_AR=@
MSG_CLEAN=-n ""
else
MSG_CLEAN="Clean as a whistle"
endif
# CFLAGS += -I/source/libevent
# LDFLAGS += -L/source/libevent
ifeq ($(RELEASE),YES)
CFLAGS += -O3 -DNDEBUG
GIT_REVISION ?= NO
else
CFLAGS += -ggdb -DDEBUG
GIT_REVISION ?= YES
endif
ifeq ($(STACK_PROTECT),YES)
CFLAGS += -fstack-protector-all
endif
ifeq ($(PROFILING),YES)
CFLAGS += -pg
LDFLAGS += -pg
endif
ifeq ($(FUNCTRACE),YES)
CFLAGS += -finstrument-functions
CFLAGS += -DDEBUG_FUNCTION_TRACE
endif
ifneq ($(BITS), AUTO)
ifeq ($(BITS), 64)
CFLAGS += -m64
LDFLAGS += -m64
else
ifeq ($(BITS), 32)
CFLAGS += -m32
LDFLAGS += -m32
endif
endif
endif
ifeq ($(USE_BIGENDIAN),AUTO)
ifeq ($(shell perl -e 'print pack("L", 0x554E4958)'),UNIX)
CFLAGS += -DARCH_BIGENDIAN
endif
else
ifeq ($(USE_BIGENDIAN),YES)
CFLAGS += -DARCH_BIGENDIAN
endif
endif
ifeq ($(USE_SSL),YES)
CFLAGS += -DSSL_SUPPORT
LDLIBS += -lssl
endif
ifeq ($(USE_LIBEVENT),YES)
CFLAGS += -DUSE_LIBEVENT
LDLIBS += -levent
ifneq ($(LIBEVENT_PATH),)
CFLAGS += -I$(LIBEVENT_PATH)
LDFLAGS += -L$(LIBEVENT_PATH)
endif
endif
ifeq ($(GIT_REVISION),YES)
CFLAGS += -DGIT_REVISION=\"$(shell git show --abbrev-commit | head -n 1 | cut -f 2 -d " ")\"
endif
# Sources
libuhub_SOURCES := \
src/core/auth.c \
src/core/commands.c \
src/core/config.c \
src/core/eventqueue.c \
src/core/hub.c \
src/core/hubevent.c \
src/core/hubio.c \
src/core/inf.c \
src/core/netevent.c \
src/core/probe.c \
src/core/route.c \
src/core/user.c \
src/core/usermanager.c \
src/network/connection.c \
src/network/epoll.c \
src/network/libevent.c \
src/network/network.c \
src/util/ipcalc.c \
src/util/list.c \
src/util/log.c \
src/util/memory.c \
src/util/misc.c \
src/util/rbtree.c \
src/util/timeout.c \
src/util/tiger.c
libadc_common_SOURCES := \
src/adc/message.c \
src/adc/sid.c
libadc_client_SOURCES := \
src/tools/adcclient.c
uhub_SOURCES := src/core/main.c
adcrush_SOURCES := src/tools/adcrush.c
admin_SOURCES := src/tools/admin.c
autotest_SOURCES := \
autotest/test_message.tcc \
autotest/test_list.tcc \
autotest/test_memory.tcc \
autotest/test_ipfilter.tcc \
autotest/test_inf.tcc \
autotest/test_hub.tcc \
autotest/test_misc.tcc \
autotest/test_tiger.tcc \
autotest/test_usermanager.tcc \
autotest/test_eventqueue.tcc
autotest_OBJECTS = autotest.o
# Source to objects
libuhub_OBJECTS := $(libuhub_SOURCES:.c=.o)
libadc_client_OBJECTS := $(libadc_client_SOURCES:.c=.o)
libadc_common_OBJECTS := $(libadc_common_SOURCES:.c=.o)
uhub_OBJECTS := $(uhub_SOURCES:.c=.o)
adcrush_OBJECTS := $(adcrush_SOURCES:.c=.o)
admin_OBJECTS := $(admin_SOURCES:.c=.o)
all_OBJECTS := $(libuhub_OBJECTS) $(uhub_OBJECTS) $(adcrush_OBJECTS) $(autotest_OBJECTS) $(admin_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
uhub_BINARY=uhub$(BIN_EXT)
adcrush_BINARY=adcrush$(BIN_EXT)
admin_BINARY=uhub-admin$(BIN_EXT)
autotest_BINARY=autotest/test$(BIN_EXT)
%.o: %.c
$(MSG_CC) $(CC) -c $(CFLAGS) -o $@ $^
all: $(uhub_BINARY)
$(adcrush_BINARY): $(adcrush_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
$(admin_BINARY): $(admin_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
$(uhub_BINARY): $(uhub_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS)
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
autotest.c: $(autotest_SOURCES)
$(shell exotic --standalone $(autotest_SOURCES) > $@)
$(autotest_OBJECTS): autotest.c
$(MSG_CC) $(CC) -c $(CFLAGS) -Isrc -o $@ $<
$(autotest_BINARY): $(autotest_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
autotest: $(autotest_BINARY)
@./$(autotest_BINARY) -s -f
ifeq ($(WINDOWS),YES)
install:
@echo "Cannot install automatically on windows."
else
install: $(uhub_BINARY)
@echo Copying $(uhub_BINARY) to $(UHUB_PREFIX)/bin/
@cp $(uhub_BINARY) $(UHUB_PREFIX)/bin/
@if [ ! -d $(UHUB_CONF_DIR) ]; then echo Creating $(UHUB_CONF_DIR); mkdir -p $(UHUB_CONF_DIR); fi
@if [ ! -f $(UHUB_CONF_DIR)/uhub.conf ]; then cp doc/uhub.conf $(UHUB_CONF_DIR); fi
@if [ ! -f $(UHUB_CONF_DIR)/users.conf ]; then cp doc/users.conf $(UHUB_CONF_DIR); fi
@touch $(UHUB_CONF_DIR)/motd.txt
@echo done.
endif
dist-clean:
@rm -rf $(all_OBJECTS) *~ core
clean:
@rm -rf $(libuhub_OBJECTS) *~ core $(uhub_BINARY) $(admin_BINARY) $(autotest_BINARY) $(adcrush_BINARY) $(all_OBJECTS) autotest.c && \
echo $(MSG_CLEAN)
-5
View File
@@ -1,5 +0,0 @@
Welcome and thanks for downloading uHub, a high performance ADC p2p hub.
For the official documentation, bugs and other information, please visit:
http://www.extatic.org/uhub/
View File
-140
View File
@@ -1,140 +0,0 @@
HOST_SYSTEM=`uname -s | tr [:upper:] [:lower:] | sed s/darwin/macosx/`
if [ "${HOST_SYSTEM}" = "macosx" ]; then
HOST_MACHINE=`uname -p | tr [:upper:] [:lower:]`
else
HOST_MACHINE=`uname -m | tr [:upper:] [:lower:] | sed s/i686/i386/ | sed s/x86_64/amd64/ | sed s/ppc64/powerpc/`
fi
BINSUFFIX=
MAKEARGS=
MAKE=make
WANTZIP=0
if [ "${HOST_SYSTEM}" = "mingw32_nt-5.1" ]; then
HOST_SYSTEM=win32
BINSUFFIX=.exe
WANTZIP=1
MAKEARGS="USE_BIGENDIAN=NO"
fi
BINARY=uhub${BINSUFFIX}
if [ "${HOST_SYSTEM}" = "freebsd" ]; then
MAKE=gmake
fi
VERSION=`grep define\ VERSION version.h | cut -f 3 -d " " | tr -d [=\"=]`
SNAPSHOT=`date '+%Y%m%d'`
PACKAGE=uhub-${VERSION}
PACKAGE_SRC=${PACKAGE}-src
PACKAGE_BIN=${PACKAGE}-${HOST_SYSTEM}-${HOST_MACHINE}
ARCHIVE='build-archive:~/www/downloads/uhub/'
function export_source_directory
{
if [ -d ${PACKAGE} ]; then
rm -Rf ${PACKAGE};
fi
if [ ! -d .git ]; then
echo "No git repo found in `dirname $0`"
exit 1
fi
git archive --format=tar --prefix=${PACKAGE}/ HEAD > tmp.tar && tar -xf tmp.tar && rm tmp.tar
if [ ! -d ${PACKAGE} ]; then
echo "Something went wrong while exporting the repo."
exit 1
fi
}
function package_zips
{
tar cf $1.tar $2
gzip -c -9 $1.tar > $1.tar.gz
bzip2 -c -9 $1.tar > $1.tar.bz2
rm -f $1.tar
if [ $WANTZIP -eq 1 ]; then
zip -q -9 -r $1.zip $2
fi
}
function export_sources
{
if [ ! -d ${PACKAGE} ]; then
export_source_directory
fi
cd ${PACKAGE}
${MAKE} ${MAKEARGS} autotest.c
cd ..
if [ ! -f ${PACKAGE}/autotest.c ]; then
echo "Unable to create autotest.c, aborting..."
exit 1
fi
rm -Rf ${PACKAGE}/admin
package_zips ${PACKAGE_SRC} ${PACKAGE}
rm -Rf ${PACKAGE};
cp ChangeLog ChangeLog-${VERSION}
}
function build_binaries
{
if [ ! -d ${PACKAGE} ]; then
export_source_directory
fi
cd ${PACKAGE}
${MAKE} ${MAKEARGS} RELEASE=YES
cd ..
if [ ! -x ${PACKAGE}/${BINARY} ]; then
echo "Build failed, no binary found..."
exit 1
fi
}
function export_binaries
{
build_binaries
rm -Rf ${PACKAGE}/admin
rm -Rf ${PACKAGE}/autotest
rm -Rf ${PACKAGE}/src
rm -Rf ${PACKAGE}/debian
rm -f ${PACKAGE}/autotest.c
rm -f ${PACKAGE}/*akefile
rm -f ${PACKAGE}/version.h
rm -f ${PACKAGE}/doc/Doxyfile
rm -f ${PACKAGE}/doc/uhub.dot
rm -f ${PACKAGE}/libuhub*
package_zips ${PACKAGE_BIN} ${PACKAGE}
rm -Rf ${PACKAGE}
}
function upload_pkg
{
if [ -f $1 ]; then
scp $1 ${ARCHIVE}
fi
}
function upload_packages
{
upload_pkg ${PACKAGE_SRC}.tar.gz
upload_pkg ${PACKAGE_SRC}.tar.bz2
upload_pkg ${PACKAGE_SRC}.zip
upload_pkg ChangeLog-${VERSION}
upload_pkg ${PACKAGE_BIN}.tar.gz
upload_pkg ${PACKAGE_BIN}.tar.bz2
upload_pkg ${PACKAGE_BIN}.zip
}
-3
View File
@@ -1,3 +0,0 @@
#!/bin/bash
. admin/common.sh
export_source_directory
-95
View File
@@ -1,95 +0,0 @@
#!/bin/sh
. admin/common.sh
export_source_directory
build_binaries
DEB_REVISION=1
if [ -d deb ]; then
rm -Rf deb
fi
mkdir -p \
deb/DEBIAN \
deb/usr/bin \
deb/usr/share/man/man1/ \
deb/usr/share/doc/uhub \
deb/etc/uhub \
|| exit 1
find deb -type d | xargs chmod 755
# Copy binaries...
cp ${PACKAGE}/${BINARY} deb/usr/bin
strip deb/usr/bin/${BINARY}
# Copy configuration files...
cp ${PACKAGE}/doc/uhub.conf deb/etc/uhub
cp ${PACKAGE}/doc/users.conf deb/etc/uhub
echo "Welcome to uHub" > deb/etc/uhub/motd.txt
# Copy other files
cp ${PACKAGE}/README deb/usr/share/doc/uhub
cp ${PACKAGE}/AUTHORS deb/usr/share/doc/uhub
gzip -c --best < ${PACKAGE}/ChangeLog > deb/usr/share/doc/uhub/changelog.gz
gzip -c --best < ${PACKAGE}/doc/uhub.1 > deb/usr/share/man/man1/uhub.1.gz
cat > deb/usr/share/doc/uhub/copyright <<EOF
uHub - a high performance hub for the ADC peer-to-peer network
Copyright (C) 2007-2009 Jan Vidar Krey <janvidar@extatic.org>
uHub is free and open source software, licensed under the
GNU General Public License version 3.
For details, see /usr/share/common-licenses/GPL-3
EOF
gzip -c --best > deb/usr/share/doc/uhub/changelog.Debian.gz <<EOF
uhub (${VERSION}) stable; urgency=low
* See changelog.gz for details.
-- Jan Vidar Krey <janvidar@extatic.org> `date -R`
EOF
### Write control files
cd deb
echo "/etc/uhub/uhub.conf" > DEBIAN/conffiles
echo "/etc/uhub/users.conf" >> DEBIAN/conffiles
echo "/etc/uhub/motd.txt" >> DEBIAN/conffiles
md5sum `find usr -type f` > DEBIAN/md5sums
INSTALL_SIZE=`du -s | cut -f 1`
cat > DEBIAN/control <<EOF
Package: uhub
Version: ${VERSION}-${DEB_REVISION}
Architecture: ${HOST_MACHINE}
Maintainer: Jan Vidar Krey <janvidar@extatic.org>
Installed-Size: ${INSTALL_SIZE}
Depends: libc6 (>= 2.7-1), libevent1 (>= 1.3e-1)
Section: net
Priority: optional
Description: a high performance hub for the ADC peer-to-peer network
uHub is a high performance peer-to-peer hub for the ADC network.
Its low memory footprint allows it to handle several thousand users
on high-end servers, or a small private hub on embedded hardware.
.
Homepage: http://www.extatic.org/uhub/
EOF
cd ..
### Create deb file
fakeroot dpkg-deb --build deb
mv deb.deb uhub_${VERSION}-${DEB_REVISION}_${HOST_MACHINE}.deb
### Check for errors
lintian uhub_${VERSION}-${DEB_REVISION}_${HOST_MACHINE}.deb
### Cleanup
rm -Rf deb
rm -Rf ${PACKAGE}
-3
View File
@@ -1,3 +0,0 @@
#!/bin/bash
. admin/common.sh
export_binaries
-4
View File
@@ -1,4 +0,0 @@
#!/bin/bash
. admin/common.sh
WANTZIP=1
export_sources
-26
View File
@@ -1,26 +0,0 @@
#!/bin/bash
PUB="${HOME}/.ssh/id_rsa.pub"
CFG="${HOME}/.ssh/config"
if [ ! "`grep build-archive ${CFG}`" ]; then
echo "Updating ssh config (${CFG})..."
cat >> ${CFG} <<EOF
Host build-archive
ForwardX11 no
HostName login.domeneshop.no
User extatic
EOF
else
echo "ssh config seems OK (${CFG})"
fi
if [ ! -f ${PUB} ]; then
echo "No id_rsa.pub - run ssh-keygen"
exit 1
fi
echo "Copying public key (${PUB})..."
cat ${PUB} | ssh build-archive "cat >> .ssh/authorized_keys"
-3
View File
@@ -1,3 +0,0 @@
#!/bin/bash
. admin/common.sh
upload_packages
-85
View File
@@ -1,85 +0,0 @@
#include <uhub.h>
static struct event_queue* eq;
static int eq_val;
static void eq_callback(void* callback_data, struct event_data* event_data)
{
eq_val += event_data->id;
}
EXO_TEST(eventqueue_init_1, {
eq = 0;
eq_val = 0;
return event_queue_initialize(&eq, eq_callback, &eq_val) == 0 && event_queue_size(eq) == 0;
});
EXO_TEST(eventqueue_init_2, {
/* hack */
return eq->callback_data == &eq_val && eq->callback == eq_callback && eq->q1 && eq->q2 && !eq->locked;
});
EXO_TEST(eventqueue_post_1, {
struct event_data message;
message.id = 0x1001;
message.ptr = &message;
message.flags = message.id * 2;
event_queue_post(eq, &message);
return event_queue_size(eq) == 1;
});
EXO_TEST(eventqueue_process_1, {
event_queue_process(eq);
return eq_val == 0x1001;
});
EXO_TEST(eventqueue_size_1, {
eq_val = 0;
return event_queue_size(eq) == 0;
});
EXO_TEST(eventqueue_post_2, {
struct event_data message;
message.id = 0x1002;
message.ptr = &message;
message.flags = message.id * 2;
event_queue_post(eq, &message);
return event_queue_size(eq) == 1;
});
EXO_TEST(eventqueue_size_2, {
eq_val = 0;
return event_queue_size(eq) == 1;
});
EXO_TEST(eventqueue_post_3, {
struct event_data message;
message.id = 0x1003;
message.ptr = &message;
message.flags = message.id * 2;
event_queue_post(eq, &message);
return event_queue_size(eq) == 2;
});
EXO_TEST(eventqueue_size_3, {
eq_val = 0;
return event_queue_size(eq) == 2;
});
EXO_TEST(eventqueue_process_2, {
event_queue_process(eq);
return eq_val == 0x2005;
});
EXO_TEST(eventqueue_size_4, {
eq_val = 0;
return event_queue_size(eq) == 0;
});
EXO_TEST(eventqueue_shutdown_1, {
event_queue_shutdown(eq);
return 1;
});
-71
View File
@@ -1,71 +0,0 @@
#include <uhub.h>
static struct hub_config g_config;
static struct acl_handle g_acl;
static struct hub_info* g_hub;
/*
static void create_test_user()
{
if (g_user)
return;
g_user = (struct hub_user*) malloc(sizeof(struct hub_user));
memset(g_user, 0, sizeof(struct hub_user));
memcpy(g_user->id.nick, "exotic-tester", 13);
g_user->sid = 1;
}
*/
EXO_TEST(hub_net_startup, {
return (net_initialize() != -1);
});
EXO_TEST(hub_config_initialize, {
config_defaults(&g_config);
return 1;
});
EXO_TEST(hub_acl_initialize, {
return (acl_initialize(&g_config, &g_acl) != -1);
});
EXO_TEST(hub_service_initialize, {
g_hub = hub_start_service(&g_config);
return g_hub ? 1 : 0;
});
EXO_TEST(hub_variables_startup, {
hub_set_variables(g_hub, &g_acl);
return 1;
});
/*** HUB IS OPERATIONAL HERE! ***/
EXO_TEST(hub_variables_shutdown, {
hub_free_variables(g_hub);
return 1;
});
EXO_TEST(hub_acl_shutdown, {
acl_shutdown(&g_acl);
return 1;
});
EXO_TEST(hub_config_shutdown, {
free_config(&g_config);
return 1;
});
EXO_TEST(hub_service_shutdown, {
if (g_hub)
{
hub_shutdown_service(g_hub);
return 1;
}
return 0;
});
EXO_TEST(hub_net_shutdown, {
return (net_destroy() != -1);
});
-162
View File
@@ -1,162 +0,0 @@
#include <uhub.h>
#define USER_CID "GNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI"
#define USER_PID "3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y"
#define USER_NICK "Friend"
#define USER_SID "AAAB"
static struct hub_user* inf_user = 0;
static struct hub_info* inf_hub = 0;
extern int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd);
static void inf_create_hub()
{
inf_hub = (struct hub_info*) hub_malloc_zero(sizeof(struct hub_info));
inf_hub->users = (struct hub_user_manager*) hub_malloc_zero(sizeof(struct hub_user_manager));
inf_hub->users->list = list_create();
inf_hub->users->sids = sid_pool_create(500);
inf_hub->acl = (struct acl_handle*) hub_malloc_zero(sizeof(struct acl_handle));
inf_hub->config = (struct hub_config*) hub_malloc_zero(sizeof(struct hub_config));
config_defaults(inf_hub->config);
acl_initialize(inf_hub->config, inf_hub->acl);
}
static void inf_destroy_hub()
{
/* FIXME */
list_destroy(inf_hub->users->list);
sid_pool_destroy(inf_hub->users->sids);
acl_shutdown(inf_hub->acl);
free_config(inf_hub->config);
hub_free(inf_hub->users);
hub_free(inf_hub->acl);
hub_free(inf_hub->config);
hub_free(inf_hub);
}
static void inf_create_user()
{
if (inf_user) return;
inf_user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
inf_user->connection = net_con_create();
inf_user->id.sid = 1;
inf_user->limits.upload_slots = 1;
}
static void inf_destroy_user()
{
if (!inf_user) return;
hub_free(inf_user);
inf_user = 0;
}
EXO_TEST(inf_create_setup,
{
inf_create_hub();
inf_create_user();
return (inf_user && inf_hub);
});
/* FIXME: MEMORY LEAK - Need to fix hub_handle_info_login */
#define CHECK_INF(MSG, EXPECT) \
struct adc_message* msg = adc_msg_parse_verify(inf_user, MSG, strlen(MSG)); \
int ok = hub_handle_info_login(inf_hub, inf_user, msg); /* FIXME: MEMORY LEAK */ \
adc_msg_free(msg); \
if (ok == EXPECT) \
user_set_info(inf_user, 0); \
return ok == EXPECT;
EXO_TEST(inf_ok_1, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", 0); });
/* check CID abuse */
EXO_TEST(inf_cid_1, { CHECK_INF("BINF AAAB NIFriend PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", status_msg_inf_error_cid_missing); });
EXO_TEST(inf_cid_2, { CHECK_INF("BINF AAAB NIFriend IDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", status_msg_inf_error_cid_invalid); });
EXO_TEST(inf_cid_3, { CHECK_INF("BINF AAAB NIFriend IDaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", status_msg_inf_error_cid_invalid); });
EXO_TEST(inf_cid_4, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2R PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", status_msg_inf_error_cid_invalid); }); /* cid 1 byte short */
EXO_TEST(inf_cid_5, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RX PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", status_msg_inf_error_cid_invalid); }); /* cid 1 byte longer */
EXO_TEST(inf_cid_6, { CHECK_INF("BINF AAAB NIFriend IDA PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", status_msg_inf_error_cid_invalid); });
EXO_TEST(inf_cid_7, { CHECK_INF("BINF AAAB NIFriend IDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", status_msg_inf_error_cid_invalid); }); /* multi */
EXO_TEST(inf_cid_8, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y IDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n", status_msg_inf_error_cid_invalid); });
EXO_TEST(inf_cid_9, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI\n", status_msg_inf_error_cid_invalid); });
/* equivalent to the pid versions */
EXO_TEST(inf_pid_1, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI\n", status_msg_inf_error_pid_missing); }); /* pid missing */
EXO_TEST(inf_pid_2, { CHECK_INF("BINF AAAB NIFriend ID3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y PDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n", status_msg_inf_error_cid_invalid); }); /* variant of inf_cid_2 */
EXO_TEST(inf_pid_3, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PDaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n", status_msg_inf_error_pid_invalid); }); /* pid invalid */
EXO_TEST(inf_pid_4, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7\n", status_msg_inf_error_pid_invalid); }); /* pid 1 byte short */
EXO_TEST(inf_pid_5, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7YX\n", status_msg_inf_error_pid_invalid); }); /* pid 1 byte longer */
EXO_TEST(inf_pid_6, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PDA\n", status_msg_inf_error_pid_invalid); }); /* very short pid */
EXO_TEST(inf_pid_7, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y PDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n", status_msg_inf_error_pid_invalid); });
EXO_TEST(inf_pid_8, { CHECK_INF("BINF AAAB NIFriend PDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", status_msg_inf_error_pid_invalid); });
EXO_TEST(inf_pid_9, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", status_msg_inf_error_pid_invalid); });
/* check nickname abuse */
EXO_TEST(inf_nick_01, { CHECK_INF("BINF AAAB IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", status_msg_inf_error_nick_missing); });
EXO_TEST(inf_nick_02, { CHECK_INF("BINF AAAB NI IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", status_msg_inf_error_nick_short); });
EXO_TEST(inf_nick_03, { CHECK_INF("BINF AAAB NIa IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", status_msg_inf_error_nick_short); });
EXO_TEST(inf_nick_04, { CHECK_INF("BINF AAAB NIabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", status_msg_inf_error_nick_long); });
EXO_TEST(inf_nick_05, { CHECK_INF("BINF AAAB NI\\sabc IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", status_msg_inf_error_nick_spaces); });
EXO_TEST(inf_nick_06, { CHECK_INF("BINF AAAB NIa\\sc IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", 0); });
EXO_TEST(inf_nick_07, { CHECK_INF("BINF AAAB NIa\tc IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", status_msg_inf_error_nick_bad_chars); });
EXO_TEST(inf_nick_08, { CHECK_INF("BINF AAAB NIa\\nc IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", status_msg_inf_error_nick_bad_chars); });
EXO_TEST(inf_nick_09, { CHECK_INF("BINF AAAB NIabc NIdef IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", status_msg_inf_error_nick_multiple); });
EXO_TEST(inf_nick_10, {
const char* line = "BINF AAAB IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n";
char nick[10];
nick[0] = 0xf7; nick[1] = 0x80; nick[2] = 0x7f; nick[3] = 0x81; nick[4] = 0x98; nick[5] = 0x00;
struct adc_message* msg = adc_msg_parse_verify(inf_user, line, strlen(line));
adc_msg_add_named_argument(msg, "NI", nick);
int ok = hub_handle_info_login(inf_hub, inf_user, msg);
adc_msg_free(msg);
if (ok != status_msg_inf_error_nick_not_utf8)
printf("Expected %d, got %d\n", status_msg_inf_error_nick_not_utf8, ok);
return ok == status_msg_inf_error_nick_not_utf8;
});
/* check limits for slots and share */
EXO_TEST(inf_limits_1, { inf_hub->config->limit_min_slots = 1; CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y SL0\n", status_msg_user_slots_low); });
EXO_TEST(inf_limits_2, { inf_hub->config->limit_max_slots = 5; CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y SL99\n", status_msg_user_slots_high); });
EXO_TEST(inf_limits_3, { inf_hub->config->limit_min_share = 100; CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y SS104857599\n", status_msg_user_share_size_low); });
EXO_TEST(inf_limits_4, { inf_hub->config->limit_max_share = 500; CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y SS524288001\n", status_msg_user_share_size_high); });
/* setup for check limits for hubs */
EXO_TEST(inf_limit_hubs_setup,
{
inf_hub->config->limit_min_slots = 0;
inf_hub->config->limit_max_slots = 0;
inf_hub->config->limit_max_share = 0;
inf_hub->config->limit_min_share = 0;
inf_hub->config->limit_max_hubs_user = 10;
inf_hub->config->limit_max_hubs_reg = 10;
inf_hub->config->limit_max_hubs_op = 10;
inf_hub->config->limit_min_hubs_user = 2;
inf_hub->config->limit_min_hubs_reg = 2;
inf_hub->config->limit_min_hubs_op = 2;
inf_hub->config->limit_max_hubs = 25;
return 1;
} );
EXO_TEST(inf_limit_hubs_1, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y HN15\n", status_msg_user_hub_limit_high); });
EXO_TEST(inf_limit_hubs_2, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y HN1\n", status_msg_user_hub_limit_low); });
EXO_TEST(inf_limit_hubs_3, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y HO15\n", status_msg_user_hub_limit_high); });
EXO_TEST(inf_limit_hubs_4, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y HO1\n", status_msg_user_hub_limit_low); });
EXO_TEST(inf_limit_hubs_5, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y HR15\n", status_msg_user_hub_limit_high); });
EXO_TEST(inf_limit_hubs_6, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y HR1\n", status_msg_user_hub_limit_low); });
EXO_TEST(inf_limit_hubs_7, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y HN15 HR15 HO15\n", status_msg_user_hub_limit_high); });
EXO_TEST(inf_destroy_setup,
{
inf_destroy_user();
inf_destroy_hub();
return 1;
});
-621
View File
@@ -1,621 +0,0 @@
#include <uhub.h>
static int ipv6 = 0;
static struct ip_addr_encap ip4_a;
static struct ip_addr_encap ip4_b;
static struct ip_addr_encap ip4_c;
static struct ip_addr_encap ip6_a;
static struct ip_addr_encap ip6_b;
static struct ip_addr_encap ip6_c;
static struct ip_addr_encap mask;
static struct ip_range ban6;
static struct ip_range ban4;
EXO_TEST(prepare_network, {
return net_initialize() == 0;
});
EXO_TEST(check_ipv6, {
ipv6 = net_is_ipv6_supported();
return ipv6 != -1;
});
EXO_TEST(create_addresses_1, {
return
ip_convert_to_binary("192.168.0.0", &ip4_a) &&
ip_convert_to_binary("192.168.255.255", &ip4_b) &&
ip_convert_to_binary("192.168.0.1", &ip4_c);
});
EXO_TEST(create_addresses_2, {
return
ip_convert_to_binary("2001::201:2ff:fefa:0", &ip6_a) &&
ip_convert_to_binary("2001::201:2ff:fefa:ffff", &ip6_b) &&
ip_convert_to_binary("2001::201:2ff:fefa:fffe", &ip6_c);
});
EXO_TEST(ip_is_valid_ipv4_1, {
return ip_is_valid_ipv4("127.0.0.1");
});
EXO_TEST(ip_is_valid_ipv4_2, {
return ip_is_valid_ipv4("10.18.1.178");
});
EXO_TEST(ip_is_valid_ipv4_3, {
return ip_is_valid_ipv4("10.18.1.178");
});
EXO_TEST(ip_is_valid_ipv4_4, {
return ip_is_valid_ipv4("224.0.0.1");
});
EXO_TEST(ip_is_valid_ipv4_5, {
return !ip_is_valid_ipv4("224.0.0.");
});
EXO_TEST(ip_is_valid_ipv4_6, {
return !ip_is_valid_ipv4("invalid");
});
EXO_TEST(ip_is_valid_ipv4_7, {
return !ip_is_valid_ipv4("localhost");
});
EXO_TEST(ip_is_valid_ipv4_8, {
return !ip_is_valid_ipv4("123.45.67.890");
});
EXO_TEST(ip_is_valid_ipv4_9, {
return !ip_is_valid_ipv4("777.777.777.777");
});
EXO_TEST(ip_is_valid_ipv6_1, {
if (!ipv6) return 1;
return ip_is_valid_ipv6("::");
});
EXO_TEST(ip_is_valid_ipv6_2, {
if (!ipv6) return 1;
return ip_is_valid_ipv6("::1");
});
EXO_TEST(ip_is_valid_ipv6_3, {
if (!ipv6) return 1;
return ip_is_valid_ipv6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
});
EXO_TEST(ip4_compare_1, {
return ip_compare(&ip4_a, &ip4_b) < 0;
});
EXO_TEST(ip4_compare_2, {
return ip_compare(&ip4_a, &ip4_c) < 0;
});
EXO_TEST(ip4_compare_3, {
return ip_compare(&ip4_b, &ip4_c) > 0;
});
EXO_TEST(ip4_compare_4, {
return ip_compare(&ip4_b, &ip4_a) > 0;
});
EXO_TEST(ip4_compare_5, {
return ip_compare(&ip4_c, &ip4_a) > 0;
});
EXO_TEST(ip4_compare_6, {
if (!ipv6) return 1;
return ip_compare(&ip4_c, &ip4_c) == 0;
});
EXO_TEST(ip6_compare_1, {
if (!ipv6) return 1;
return ip_compare(&ip6_a, &ip6_b) < 0;
});
EXO_TEST(ip6_compare_2, {
if (!ipv6) return 1;
return ip_compare(&ip6_a, &ip6_c) < 0;
});
EXO_TEST(ip6_compare_3, {
if (!ipv6) return 1;
return ip_compare(&ip6_b, &ip6_c) > 0;
});
EXO_TEST(ip6_compare_4, {
if (!ipv6) return 1;
return ip_compare(&ip6_b, &ip6_a) > 0;
});
EXO_TEST(ip6_compare_5, {
if (!ipv6) return 1;
return ip_compare(&ip6_c, &ip6_a) > 0;
});
EXO_TEST(ip6_compare_6, {
if (!ipv6) return 1;
return ip_compare(&ip6_c, &ip6_c) == 0;
});
static int compare_str(const char* s1, const char* s2)
{
int ok = strcmp(s1, s2);
#ifdef DEBUG_TESTS
if (ok)
{
printf("compare_str fail: s1='%s', s2='%s'\n", s1, s2);
}
#endif
return ok;
}
#define LMASK4(bits) !ip_mask_create_left (AF_INET, bits, &mask)
#define LMASK6(bits) (ipv6 ? !ip_mask_create_left (AF_INET6, bits, &mask) : 1)
#define RMASK4(bits) !ip_mask_create_right(AF_INET, bits, &mask)
#define RMASK6(bits) (ipv6 ? !ip_mask_create_right(AF_INET6, bits, &mask) : 1)
#define CHECK4(expect) !compare_str(ip_convert_to_string(&mask), expect)
#define CHECK6(expect) (ipv6 ? !compare_str(ip_convert_to_string(&mask), expect) : 1)
/* Check IPv4 masks */
EXO_TEST(ipv4_lmask_create_0, { return LMASK4( 0) && CHECK4("0.0.0.0"); });
EXO_TEST(ipv4_lmask_create_1, { return LMASK4( 1) && CHECK4("128.0.0.0"); });
EXO_TEST(ipv4_lmask_create_2, { return LMASK4( 2) && CHECK4("192.0.0.0"); });
EXO_TEST(ipv4_lmask_create_3, { return LMASK4( 3) && CHECK4("224.0.0.0"); });
EXO_TEST(ipv4_lmask_create_4, { return LMASK4( 4) && CHECK4("240.0.0.0"); });
EXO_TEST(ipv4_lmask_create_5, { return LMASK4( 5) && CHECK4("248.0.0.0"); });
EXO_TEST(ipv4_lmask_create_6, { return LMASK4( 6) && CHECK4("252.0.0.0"); });
EXO_TEST(ipv4_lmask_create_7, { return LMASK4( 7) && CHECK4("254.0.0.0"); });
EXO_TEST(ipv4_lmask_create_8, { return LMASK4( 8) && CHECK4("255.0.0.0"); });
EXO_TEST(ipv4_lmask_create_9, { return LMASK4( 9) && CHECK4("255.128.0.0"); });
EXO_TEST(ipv4_lmask_create_10, { return LMASK4(10) && CHECK4("255.192.0.0"); });
EXO_TEST(ipv4_lmask_create_11, { return LMASK4(11) && CHECK4("255.224.0.0"); });
EXO_TEST(ipv4_lmask_create_12, { return LMASK4(12) && CHECK4("255.240.0.0"); });
EXO_TEST(ipv4_lmask_create_13, { return LMASK4(13) && CHECK4("255.248.0.0"); });
EXO_TEST(ipv4_lmask_create_14, { return LMASK4(14) && CHECK4("255.252.0.0"); });
EXO_TEST(ipv4_lmask_create_15, { return LMASK4(15) && CHECK4("255.254.0.0"); });
EXO_TEST(ipv4_lmask_create_16, { return LMASK4(16) && CHECK4("255.255.0.0"); });
EXO_TEST(ipv4_lmask_create_17, { return LMASK4(17) && CHECK4("255.255.128.0"); });
EXO_TEST(ipv4_lmask_create_18, { return LMASK4(18) && CHECK4("255.255.192.0"); });
EXO_TEST(ipv4_lmask_create_19, { return LMASK4(19) && CHECK4("255.255.224.0"); });
EXO_TEST(ipv4_lmask_create_20, { return LMASK4(20) && CHECK4("255.255.240.0"); });
EXO_TEST(ipv4_lmask_create_21, { return LMASK4(21) && CHECK4("255.255.248.0"); });
EXO_TEST(ipv4_lmask_create_22, { return LMASK4(22) && CHECK4("255.255.252.0"); });
EXO_TEST(ipv4_lmask_create_23, { return LMASK4(23) && CHECK4("255.255.254.0"); });
EXO_TEST(ipv4_lmask_create_24, { return LMASK4(24) && CHECK4("255.255.255.0"); });
EXO_TEST(ipv4_lmask_create_25, { return LMASK4(25) && CHECK4("255.255.255.128"); });
EXO_TEST(ipv4_lmask_create_26, { return LMASK4(26) && CHECK4("255.255.255.192"); });
EXO_TEST(ipv4_lmask_create_27, { return LMASK4(27) && CHECK4("255.255.255.224"); });
EXO_TEST(ipv4_lmask_create_28, { return LMASK4(28) && CHECK4("255.255.255.240"); });
EXO_TEST(ipv4_lmask_create_29, { return LMASK4(29) && CHECK4("255.255.255.248"); });
EXO_TEST(ipv4_lmask_create_30, { return LMASK4(30) && CHECK4("255.255.255.252"); });
EXO_TEST(ipv4_lmask_create_31, { return LMASK4(31) && CHECK4("255.255.255.254"); });
EXO_TEST(ipv4_lmask_create_32, { return LMASK4(32) && CHECK4("255.255.255.255"); });
/* Check IPv4 right to left mask */
EXO_TEST(ipv4_rmask_create_0, { return RMASK4( 0) && CHECK4("0.0.0.0"); });
EXO_TEST(ipv4_rmask_create_1, { return RMASK4( 1) && CHECK4("0.0.0.1"); });
EXO_TEST(ipv4_rmask_create_2, { return RMASK4( 2) && CHECK4("0.0.0.3"); });
EXO_TEST(ipv4_rmask_create_3, { return RMASK4( 3) && CHECK4("0.0.0.7"); });
EXO_TEST(ipv4_rmask_create_4, { return RMASK4( 4) && CHECK4("0.0.0.15"); });
EXO_TEST(ipv4_rmask_create_5, { return RMASK4( 5) && CHECK4("0.0.0.31"); });
EXO_TEST(ipv4_rmask_create_6, { return RMASK4( 6) && CHECK4("0.0.0.63"); });
EXO_TEST(ipv4_rmask_create_7, { return RMASK4( 7) && CHECK4("0.0.0.127"); });
EXO_TEST(ipv4_rmask_create_8, { return RMASK4( 8) && CHECK4("0.0.0.255"); });
EXO_TEST(ipv4_rmask_create_9, { return RMASK4( 9) && CHECK4("0.0.1.255"); });
EXO_TEST(ipv4_rmask_create_10, { return RMASK4(10) && CHECK4("0.0.3.255"); });
EXO_TEST(ipv4_rmask_create_11, { return RMASK4(11) && CHECK4("0.0.7.255"); });
EXO_TEST(ipv4_rmask_create_12, { return RMASK4(12) && CHECK4("0.0.15.255"); });
EXO_TEST(ipv4_rmask_create_13, { return RMASK4(13) && CHECK4("0.0.31.255"); });
EXO_TEST(ipv4_rmask_create_14, { return RMASK4(14) && CHECK4("0.0.63.255"); });
EXO_TEST(ipv4_rmask_create_15, { return RMASK4(15) && CHECK4("0.0.127.255"); });
EXO_TEST(ipv4_rmask_create_16, { return RMASK4(16) && CHECK4("0.0.255.255"); });
EXO_TEST(ipv4_rmask_create_17, { return RMASK4(17) && CHECK4("0.1.255.255"); });
EXO_TEST(ipv4_rmask_create_18, { return RMASK4(18) && CHECK4("0.3.255.255"); });
EXO_TEST(ipv4_rmask_create_19, { return RMASK4(19) && CHECK4("0.7.255.255"); });
EXO_TEST(ipv4_rmask_create_20, { return RMASK4(20) && CHECK4("0.15.255.255"); });
EXO_TEST(ipv4_rmask_create_21, { return RMASK4(21) && CHECK4("0.31.255.255"); });
EXO_TEST(ipv4_rmask_create_22, { return RMASK4(22) && CHECK4("0.63.255.255"); });
EXO_TEST(ipv4_rmask_create_23, { return RMASK4(23) && CHECK4("0.127.255.255"); });
EXO_TEST(ipv4_rmask_create_24, { return RMASK4(24) && CHECK4("0.255.255.255"); });
EXO_TEST(ipv4_rmask_create_25, { return RMASK4(25) && CHECK4("1.255.255.255"); });
EXO_TEST(ipv4_rmask_create_26, { return RMASK4(26) && CHECK4("3.255.255.255"); });
EXO_TEST(ipv4_rmask_create_27, { return RMASK4(27) && CHECK4("7.255.255.255"); });
EXO_TEST(ipv4_rmask_create_28, { return RMASK4(28) && CHECK4("15.255.255.255"); });
EXO_TEST(ipv4_rmask_create_29, { return RMASK4(29) && CHECK4("31.255.255.255"); });
EXO_TEST(ipv4_rmask_create_30, { return RMASK4(30) && CHECK4("63.255.255.255"); });
EXO_TEST(ipv4_rmask_create_31, { return RMASK4(31) && CHECK4("127.255.255.255"); });
EXO_TEST(ipv4_rmask_create_32, { return RMASK4(32) && CHECK4("255.255.255.255"); });
/* Check IPv6 masks */
EXO_TEST(ip6_lmask_create_0, { return LMASK6( 0) && CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); });
EXO_TEST(ip6_lmask_create_1, { return LMASK6( 1) && CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe"); });
EXO_TEST(ip6_lmask_create_2, { return LMASK6( 2) && CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc"); });
EXO_TEST(ip6_lmask_create_3, { return LMASK6( 3) && CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff8"); });
EXO_TEST(ip6_lmask_create_4, { return LMASK6( 4) && CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff0"); });
EXO_TEST(ip6_lmask_create_5, { return LMASK6( 5) && CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffe0"); });
EXO_TEST(ip6_lmask_create_6, { return LMASK6( 6) && CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffc0"); });
EXO_TEST(ip6_lmask_create_7, { return LMASK6( 7) && CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff80"); });
EXO_TEST(ip6_lmask_create_8, { return LMASK6( 8) && CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00"); });
EXO_TEST(ip6_lmask_create_9, { return LMASK6( 9) && CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fe00"); });
EXO_TEST(ip6_lmask_create_10, { return LMASK6( 10) && CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fc00"); });
EXO_TEST(ip6_lmask_create_11, { return LMASK6( 11) && CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:f800"); });
EXO_TEST(ip6_lmask_create_12, { return LMASK6( 12) && CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:f000"); });
EXO_TEST(ip6_lmask_create_13, { return LMASK6( 13) && CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:e000"); });
EXO_TEST(ip6_lmask_create_14, { return LMASK6( 14) && CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:c000"); });
EXO_TEST(ip6_lmask_create_15, { return LMASK6( 15) && CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:8000"); });
EXO_TEST(ip6_lmask_create_16, { return LMASK6( 16) && (CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0") || CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ffff::")); });
EXO_TEST(ip6_lmask_create_17, { return LMASK6( 17) && (CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:fffe:0") || CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:fffe::")); });
EXO_TEST(ip6_lmask_create_18, { return LMASK6( 18) && (CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:fffc:0") || CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:fffc::")); });
EXO_TEST(ip6_lmask_create_19, { return LMASK6( 19) && (CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:fff8:0") || CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:fff8::")); });
EXO_TEST(ip6_lmask_create_20, { return LMASK6( 20) && (CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:fff0:0") || CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:fff0::")); });
EXO_TEST(ip6_lmask_create_21, { return LMASK6( 21) && (CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ffe0:0") || CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ffe0::")); });
EXO_TEST(ip6_lmask_create_22, { return LMASK6( 22) && (CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ffc0:0") || CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ffc0::")); });
EXO_TEST(ip6_lmask_create_23, { return LMASK6( 23) && (CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ff80:0") || CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ff80::")); });
EXO_TEST(ip6_lmask_create_24, { return LMASK6( 24) && (CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ff00:0") || CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ff00::")); });
EXO_TEST(ip6_lmask_create_25, { return LMASK6( 25) && (CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:fe00:0") || CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:fe00::")); });
EXO_TEST(ip6_lmask_create_26, { return LMASK6( 26) && (CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:fc00:0") || CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:fc00::")); });
EXO_TEST(ip6_lmask_create_27, { return LMASK6( 27) && (CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:f800:0") || CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:f800::")); });
EXO_TEST(ip6_lmask_create_28, { return LMASK6( 28) && (CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:f000:0") || CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:f000::")); });
EXO_TEST(ip6_lmask_create_29, { return LMASK6( 29) && (CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:e000:0") || CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:e000::")); });
EXO_TEST(ip6_lmask_create_30, { return LMASK6( 30) && (CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:c000:0") || CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:c000::")); });
EXO_TEST(ip6_lmask_create_31, { return LMASK6( 31) && (CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:8000:0") || CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:8000::")); });
EXO_TEST(ip6_lmask_create_32, { return LMASK6( 32) && CHECK6("ffff:ffff:ffff:ffff:ffff:ffff::"); });
EXO_TEST(ip6_lmask_create_33, { return LMASK6( 33) && CHECK6("ffff:ffff:ffff:ffff:ffff:fffe::"); });
EXO_TEST(ip6_lmask_create_34, { return LMASK6( 34) && CHECK6("ffff:ffff:ffff:ffff:ffff:fffc::"); });
EXO_TEST(ip6_lmask_create_35, { return LMASK6( 35) && CHECK6("ffff:ffff:ffff:ffff:ffff:fff8::"); });
EXO_TEST(ip6_lmask_create_36, { return LMASK6( 36) && CHECK6("ffff:ffff:ffff:ffff:ffff:fff0::"); });
EXO_TEST(ip6_lmask_create_37, { return LMASK6( 37) && CHECK6("ffff:ffff:ffff:ffff:ffff:ffe0::"); });
EXO_TEST(ip6_lmask_create_38, { return LMASK6( 38) && CHECK6("ffff:ffff:ffff:ffff:ffff:ffc0::"); });
EXO_TEST(ip6_lmask_create_39, { return LMASK6( 39) && CHECK6("ffff:ffff:ffff:ffff:ffff:ff80::"); });
EXO_TEST(ip6_lmask_create_40, { return LMASK6( 40) && CHECK6("ffff:ffff:ffff:ffff:ffff:ff00::"); });
EXO_TEST(ip6_lmask_create_41, { return LMASK6( 41) && CHECK6("ffff:ffff:ffff:ffff:ffff:fe00::"); });
EXO_TEST(ip6_lmask_create_42, { return LMASK6( 42) && CHECK6("ffff:ffff:ffff:ffff:ffff:fc00::"); });
EXO_TEST(ip6_lmask_create_43, { return LMASK6( 43) && CHECK6("ffff:ffff:ffff:ffff:ffff:f800::"); });
EXO_TEST(ip6_lmask_create_44, { return LMASK6( 44) && CHECK6("ffff:ffff:ffff:ffff:ffff:f000::"); });
EXO_TEST(ip6_lmask_create_45, { return LMASK6( 45) && CHECK6("ffff:ffff:ffff:ffff:ffff:e000::"); });
EXO_TEST(ip6_lmask_create_46, { return LMASK6( 46) && CHECK6("ffff:ffff:ffff:ffff:ffff:c000::"); });
EXO_TEST(ip6_lmask_create_47, { return LMASK6( 47) && CHECK6("ffff:ffff:ffff:ffff:ffff:8000::"); });
EXO_TEST(ip6_lmask_create_48, { return LMASK6( 48) && CHECK6("ffff:ffff:ffff:ffff:ffff::"); });
EXO_TEST(ip6_lmask_create_49, { return LMASK6( 49) && CHECK6("ffff:ffff:ffff:ffff:fffe::"); });
EXO_TEST(ip6_lmask_create_50, { return LMASK6( 50) && CHECK6("ffff:ffff:ffff:ffff:fffc::"); });
EXO_TEST(ip6_lmask_create_51, { return LMASK6( 51) && CHECK6("ffff:ffff:ffff:ffff:fff8::"); });
EXO_TEST(ip6_lmask_create_52, { return LMASK6( 52) && CHECK6("ffff:ffff:ffff:ffff:fff0::"); });
EXO_TEST(ip6_lmask_create_53, { return LMASK6( 53) && CHECK6("ffff:ffff:ffff:ffff:ffe0::"); });
EXO_TEST(ip6_lmask_create_54, { return LMASK6( 54) && CHECK6("ffff:ffff:ffff:ffff:ffc0::"); });
EXO_TEST(ip6_lmask_create_55, { return LMASK6( 55) && CHECK6("ffff:ffff:ffff:ffff:ff80::"); });
EXO_TEST(ip6_lmask_create_56, { return LMASK6( 56) && CHECK6("ffff:ffff:ffff:ffff:ff00::"); });
EXO_TEST(ip6_lmask_create_57, { return LMASK6( 57) && CHECK6("ffff:ffff:ffff:ffff:fe00::"); });
EXO_TEST(ip6_lmask_create_58, { return LMASK6( 58) && CHECK6("ffff:ffff:ffff:ffff:fc00::"); });
EXO_TEST(ip6_lmask_create_59, { return LMASK6( 59) && CHECK6("ffff:ffff:ffff:ffff:f800::"); });
EXO_TEST(ip6_lmask_create_60, { return LMASK6( 60) && CHECK6("ffff:ffff:ffff:ffff:f000::"); });
EXO_TEST(ip6_lmask_create_61, { return LMASK6( 61) && CHECK6("ffff:ffff:ffff:ffff:e000::"); });
EXO_TEST(ip6_lmask_create_62, { return LMASK6( 62) && CHECK6("ffff:ffff:ffff:ffff:c000::"); });
EXO_TEST(ip6_lmask_create_63, { return LMASK6( 63) && CHECK6("ffff:ffff:ffff:ffff:8000::"); });
EXO_TEST(ip6_lmask_create_64, { return LMASK6( 64) && CHECK6("ffff:ffff:ffff:ffff::"); });
EXO_TEST(ip6_lmask_create_65, { return LMASK6( 65) && CHECK6("ffff:ffff:ffff:fffe::"); });
EXO_TEST(ip6_lmask_create_66, { return LMASK6( 66) && CHECK6("ffff:ffff:ffff:fffc::"); });
EXO_TEST(ip6_lmask_create_67, { return LMASK6( 67) && CHECK6("ffff:ffff:ffff:fff8::"); });
EXO_TEST(ip6_lmask_create_68, { return LMASK6( 68) && CHECK6("ffff:ffff:ffff:fff0::"); });
EXO_TEST(ip6_lmask_create_69, { return LMASK6( 69) && CHECK6("ffff:ffff:ffff:ffe0::"); });
EXO_TEST(ip6_lmask_create_70, { return LMASK6( 70) && CHECK6("ffff:ffff:ffff:ffc0::"); });
EXO_TEST(ip6_lmask_create_71, { return LMASK6( 71) && CHECK6("ffff:ffff:ffff:ff80::"); });
EXO_TEST(ip6_lmask_create_72, { return LMASK6( 72) && CHECK6("ffff:ffff:ffff:ff00::"); });
EXO_TEST(ip6_lmask_create_73, { return LMASK6( 73) && CHECK6("ffff:ffff:ffff:fe00::"); });
EXO_TEST(ip6_lmask_create_74, { return LMASK6( 74) && CHECK6("ffff:ffff:ffff:fc00::"); });
EXO_TEST(ip6_lmask_create_75, { return LMASK6( 75) && CHECK6("ffff:ffff:ffff:f800::"); });
EXO_TEST(ip6_lmask_create_76, { return LMASK6( 76) && CHECK6("ffff:ffff:ffff:f000::"); });
EXO_TEST(ip6_lmask_create_77, { return LMASK6( 77) && CHECK6("ffff:ffff:ffff:e000::"); });
EXO_TEST(ip6_lmask_create_78, { return LMASK6( 78) && CHECK6("ffff:ffff:ffff:c000::"); });
EXO_TEST(ip6_lmask_create_79, { return LMASK6( 79) && CHECK6("ffff:ffff:ffff:8000::"); });
EXO_TEST(ip6_lmask_create_80, { return LMASK6( 80) && CHECK6("ffff:ffff:ffff::"); });
EXO_TEST(ip6_lmask_create_81, { return LMASK6( 81) && CHECK6("ffff:ffff:fffe::"); });
EXO_TEST(ip6_lmask_create_82, { return LMASK6( 82) && CHECK6("ffff:ffff:fffc::"); });
EXO_TEST(ip6_lmask_create_83, { return LMASK6( 83) && CHECK6("ffff:ffff:fff8::"); });
EXO_TEST(ip6_lmask_create_84, { return LMASK6( 84) && CHECK6("ffff:ffff:fff0::"); });
EXO_TEST(ip6_lmask_create_85, { return LMASK6( 85) && CHECK6("ffff:ffff:ffe0::"); });
EXO_TEST(ip6_lmask_create_86, { return LMASK6( 86) && CHECK6("ffff:ffff:ffc0::"); });
EXO_TEST(ip6_lmask_create_87, { return LMASK6( 87) && CHECK6("ffff:ffff:ff80::"); });
EXO_TEST(ip6_lmask_create_88, { return LMASK6( 88) && CHECK6("ffff:ffff:ff00::"); });
EXO_TEST(ip6_lmask_create_89, { return LMASK6( 89) && CHECK6("ffff:ffff:fe00::"); });
EXO_TEST(ip6_lmask_create_90, { return LMASK6( 90) && CHECK6("ffff:ffff:fc00::"); });
EXO_TEST(ip6_lmask_create_91, { return LMASK6( 91) && CHECK6("ffff:ffff:f800::"); });
EXO_TEST(ip6_lmask_create_92, { return LMASK6( 92) && CHECK6("ffff:ffff:f000::"); });
EXO_TEST(ip6_lmask_create_93, { return LMASK6( 93) && CHECK6("ffff:ffff:e000::"); });
EXO_TEST(ip6_lmask_create_94, { return LMASK6( 94) && CHECK6("ffff:ffff:c000::"); });
EXO_TEST(ip6_lmask_create_95, { return LMASK6( 95) && CHECK6("ffff:ffff:8000::"); });
EXO_TEST(ip6_lmask_create_96, { return LMASK6( 96) && CHECK6("ffff:ffff::"); });
EXO_TEST(ip6_lmask_create_97, { return LMASK6( 97) && CHECK6("ffff:fffe::"); });
EXO_TEST(ip6_lmask_create_98, { return LMASK6( 98) && CHECK6("ffff:fffc::"); });
EXO_TEST(ip6_lmask_create_99, { return LMASK6( 99) && CHECK6("ffff:fff8::"); });
EXO_TEST(ip6_lmask_create_100, { return LMASK6(100) && CHECK6("ffff:fff0::"); });
EXO_TEST(ip6_lmask_create_101, { return LMASK6(101) && CHECK6("ffff:ffe0::"); });
EXO_TEST(ip6_lmask_create_102, { return LMASK6(102) && CHECK6("ffff:ffc0::"); });
EXO_TEST(ip6_lmask_create_103, { return LMASK6(103) && CHECK6("ffff:ff80::"); });
EXO_TEST(ip6_lmask_create_104, { return LMASK6(104) && CHECK6("ffff:ff00::"); });
EXO_TEST(ip6_lmask_create_105, { return LMASK6(105) && CHECK6("ffff:fe00::"); });
EXO_TEST(ip6_lmask_create_106, { return LMASK6(106) && CHECK6("ffff:fc00::"); });
EXO_TEST(ip6_lmask_create_107, { return LMASK6(107) && CHECK6("ffff:f800::"); });
EXO_TEST(ip6_lmask_create_108, { return LMASK6(108) && CHECK6("ffff:f000::"); });
EXO_TEST(ip6_lmask_create_109, { return LMASK6(109) && CHECK6("ffff:e000::"); });
EXO_TEST(ip6_lmask_create_110, { return LMASK6(110) && CHECK6("ffff:c000::"); });
EXO_TEST(ip6_lmask_create_111, { return LMASK6(111) && CHECK6("ffff:8000::"); });
EXO_TEST(ip6_lmask_create_112, { return LMASK6(112) && CHECK6("ffff::"); });
EXO_TEST(ip6_lmask_create_113, { return LMASK6(113) && CHECK6("fffe::"); });
EXO_TEST(ip6_lmask_create_114, { return LMASK6(114) && CHECK6("fffc::"); });
EXO_TEST(ip6_lmask_create_115, { return LMASK6(115) && CHECK6("fff8::"); });
EXO_TEST(ip6_lmask_create_116, { return LMASK6(116) && CHECK6("fff0::"); });
EXO_TEST(ip6_lmask_create_117, { return LMASK6(117) && CHECK6("ffe0::"); });
EXO_TEST(ip6_lmask_create_118, { return LMASK6(118) && CHECK6("ffc0::"); });
EXO_TEST(ip6_lmask_create_119, { return LMASK6(119) && CHECK6("ff80::"); });
EXO_TEST(ip6_lmask_create_120, { return LMASK6(120) && CHECK6("ff00::"); });
EXO_TEST(ip6_lmask_create_121, { return LMASK6(121) && CHECK6("fe00::"); });
EXO_TEST(ip6_lmask_create_122, { return LMASK6(122) && CHECK6("fc00::"); });
EXO_TEST(ip6_lmask_create_123, { return LMASK6(123) && CHECK6("f800::"); });
EXO_TEST(ip6_lmask_create_124, { return LMASK6(124) && CHECK6("f000::"); });
EXO_TEST(ip6_lmask_create_125, { return LMASK6(125) && CHECK6("e000::"); });
EXO_TEST(ip6_lmask_create_126, { return LMASK6(126) && CHECK6("c000::"); });
EXO_TEST(ip6_lmask_create_127, { return LMASK6(127) && CHECK6("8000::"); });
EXO_TEST(ip6_lmask_create_128, { return LMASK6(128) && CHECK6("::"); });
/* Check IPv6 right to left masks */
EXO_TEST(ip6_rmask_create_0, { return RMASK6( 0) && CHECK6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); });
EXO_TEST(ip6_rmask_create_1, { return RMASK6( 1) && CHECK6("7fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); });
EXO_TEST(ip6_rmask_create_2, { return RMASK6( 2) && CHECK6("3fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); });
EXO_TEST(ip6_rmask_create_3, { return RMASK6( 3) && CHECK6("1fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); });
EXO_TEST(ip6_rmask_create_4, { return RMASK6( 4) && CHECK6("fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); });
EXO_TEST(ip6_rmask_create_5, { return RMASK6( 5) && CHECK6("7ff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); });
EXO_TEST(ip6_rmask_create_6, { return RMASK6( 6) && CHECK6("3ff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); });
EXO_TEST(ip6_rmask_create_7, { return RMASK6( 7) && CHECK6("1ff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); });
EXO_TEST(ip6_rmask_create_8, { return RMASK6( 8) && CHECK6("ff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); });
EXO_TEST(ip6_rmask_create_9, { return RMASK6( 9) && CHECK6("7f:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); });
EXO_TEST(ip6_rmask_create_10, { return RMASK6( 10) && CHECK6("3f:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); });
EXO_TEST(ip6_rmask_create_11, { return RMASK6( 11) && CHECK6("1f:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); });
EXO_TEST(ip6_rmask_create_12, { return RMASK6( 12) && CHECK6("f:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); });
EXO_TEST(ip6_rmask_create_13, { return RMASK6( 13) && CHECK6("7:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); });
EXO_TEST(ip6_rmask_create_14, { return RMASK6( 14) && CHECK6("3:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); });
EXO_TEST(ip6_rmask_create_15, { return RMASK6( 15) && CHECK6("1:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); });
EXO_TEST(ip6_rmask_create_16, { return RMASK6( 16) && (CHECK6("0:ffff:ffff:ffff:ffff:ffff:ffff:ffff") || CHECK6("::ffff:ffff:ffff:ffff:ffff:ffff:ffff") || CHECK6("ffff:ffff:ffff:ffff:ffff:ffff")); });
EXO_TEST(ip6_rmask_create_17, { return RMASK6( 17) && (CHECK6("0:7fff:ffff:ffff:ffff:ffff:ffff:ffff") || CHECK6("::7fff:ffff:ffff:ffff:ffff:ffff:ffff")); });
EXO_TEST(ip6_rmask_create_18, { return RMASK6( 18) && (CHECK6("0:3fff:ffff:ffff:ffff:ffff:ffff:ffff") || CHECK6("::3fff:ffff:ffff:ffff:ffff:ffff:ffff")); });
EXO_TEST(ip6_rmask_create_19, { return RMASK6( 19) && (CHECK6("0:1fff:ffff:ffff:ffff:ffff:ffff:ffff") || CHECK6("::1fff:ffff:ffff:ffff:ffff:ffff:ffff")); });
EXO_TEST(ip6_rmask_create_20, { return RMASK6( 20) && (CHECK6("0:fff:ffff:ffff:ffff:ffff:ffff:ffff") || CHECK6("::fff:ffff:ffff:ffff:ffff:ffff:ffff")); });
EXO_TEST(ip6_rmask_create_21, { return RMASK6( 21) && (CHECK6("0:7ff:ffff:ffff:ffff:ffff:ffff:ffff") || CHECK6("::7ff:ffff:ffff:ffff:ffff:ffff:ffff")); });
EXO_TEST(ip6_rmask_create_22, { return RMASK6( 22) && (CHECK6("0:3ff:ffff:ffff:ffff:ffff:ffff:ffff") || CHECK6("::3ff:ffff:ffff:ffff:ffff:ffff:ffff")); });
EXO_TEST(ip6_rmask_create_23, { return RMASK6( 23) && (CHECK6("0:1ff:ffff:ffff:ffff:ffff:ffff:ffff") || CHECK6("::1ff:ffff:ffff:ffff:ffff:ffff:ffff")); });
EXO_TEST(ip6_rmask_create_24, { return RMASK6( 24) && (CHECK6("0:ff:ffff:ffff:ffff:ffff:ffff:ffff") || CHECK6("::ff:ffff:ffff:ffff:ffff:ffff:ffff")); });
EXO_TEST(ip6_rmask_create_25, { return RMASK6( 25) && (CHECK6("0:7f:ffff:ffff:ffff:ffff:ffff:ffff") || CHECK6("::7f:ffff:ffff:ffff:ffff:ffff:ffff")); });
EXO_TEST(ip6_rmask_create_26, { return RMASK6( 26) && (CHECK6("0:3f:ffff:ffff:ffff:ffff:ffff:ffff") || CHECK6("::3f:ffff:ffff:ffff:ffff:ffff:ffff")); });
EXO_TEST(ip6_rmask_create_27, { return RMASK6( 27) && (CHECK6("0:1f:ffff:ffff:ffff:ffff:ffff:ffff") || CHECK6("::1f:ffff:ffff:ffff:ffff:ffff:ffff")); });
EXO_TEST(ip6_rmask_create_28, { return RMASK6( 28) && (CHECK6("0:f:ffff:ffff:ffff:ffff:ffff:ffff") || CHECK6("::f:ffff:ffff:ffff:ffff:ffff:ffff")); });
EXO_TEST(ip6_rmask_create_29, { return RMASK6( 29) && (CHECK6("0:7:ffff:ffff:ffff:ffff:ffff:ffff") || CHECK6("::7:ffff:ffff:ffff:ffff:ffff:ffff")); });
EXO_TEST(ip6_rmask_create_30, { return RMASK6( 30) && (CHECK6("0:3:ffff:ffff:ffff:ffff:ffff:ffff") || CHECK6("::3:ffff:ffff:ffff:ffff:ffff:ffff")); });
EXO_TEST(ip6_rmask_create_31, { return RMASK6( 31) && (CHECK6("0:1:ffff:ffff:ffff:ffff:ffff:ffff") || CHECK6("::1:ffff:ffff:ffff:ffff:ffff:ffff")); });
EXO_TEST(check_ban_setup_1, {
return ip_convert_to_binary("2001::201:2ff:fefa:0", &ban6.lo) &&
ip_convert_to_binary("2001::201:2ff:fefa:ffff", &ban6.hi) &&
ip_convert_to_binary("192.168.0.0", &ban4.lo) &&
ip_convert_to_binary("192.168.0.255", &ban4.hi);
});
EXO_TEST(check_ban_ipv4_1, {
struct ip_addr_encap addr; ip_convert_to_binary("192.168.0.0", &addr);
return ip_in_range(&addr, &ban4);
});
EXO_TEST(check_ban_ipv4_2, {
struct ip_addr_encap addr; ip_convert_to_binary("192.168.0.1", &addr);
return ip_in_range(&addr, &ban4);
});
EXO_TEST(check_ban_ipv4_3, {
struct ip_addr_encap addr; ip_convert_to_binary("192.168.0.255", &addr);
return ip_in_range(&addr, &ban4);
});
EXO_TEST(check_ban_ipv4_4, {
struct ip_addr_encap addr; ip_convert_to_binary("192.168.1.0", &addr);
return !ip_in_range(&addr, &ban4);
});
EXO_TEST(check_ban_ipv4_5, {
struct ip_addr_encap addr; ip_convert_to_binary("192.167.255.255", &addr);
return !ip_in_range(&addr, &ban4);
});
EXO_TEST(check_ban_ipv6_1, {
if (!ipv6) return 1;
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:0", &addr);
return ip_in_range(&addr, &ban6);
});
EXO_TEST(check_ban_ipv6_2, {
if (!ipv6) return 1;
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:1", &addr);
return ip_in_range(&addr, &ban6);
});
EXO_TEST(check_ban_ipv6_3, {
if (!ipv6) return 1;
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:fffe", &addr);
return ip_in_range(&addr, &ban6);
});
EXO_TEST(check_ban_ipv6_4, {
if (!ipv6) return 1;
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:ffff", &addr);
return ip_in_range(&addr, &ban6);
});
EXO_TEST(check_ban_ipv6_5, {
if (!ipv6) return 1;
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefb:0", &addr);
return !ip_in_range(&addr, &ban6);
});
EXO_TEST(check_ban_ipv6_6, {
if (!ipv6) return 1;
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fef9:ffff", &addr);
return !ip_in_range(&addr, &ban6);
});
EXO_TEST(check_ban_afmix_1, {
if (!ipv6) return 1;
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fef9:ffff", &addr);
return !ip_in_range(&addr, &ban4);
});
EXO_TEST(check_ban_afmix_2, {
struct ip_addr_encap addr; ip_convert_to_binary("10.20.30.40", &addr);
return !ip_in_range(&addr, &ban6);
});
EXO_TEST(ip4_bitwise_AND_1, {
ip_convert_to_binary("255.255.255.255", &ip4_a);
ip_convert_to_binary("255.255.255.0", &ip4_b);
ip_mask_apply_AND(&ip4_a, &ip4_b, &ip4_c);
return !strcmp(ip_convert_to_string(&ip4_c), "255.255.255.0");
});
EXO_TEST(ip4_bitwise_AND_2, {
ip_convert_to_binary("192.168.217.113", &ip4_a);
ip_convert_to_binary("255.255.255.0", &ip4_b);
ip_mask_apply_AND(&ip4_a, &ip4_b, &ip4_c);
return !strcmp(ip_convert_to_string(&ip4_c), "192.168.217.0");
});
EXO_TEST(ip4_bitwise_AND_3, {
ip_convert_to_binary("192.168.217.113", &ip4_a);
ip_convert_to_binary("255.255.0.0", &ip4_b);
ip_mask_apply_AND(&ip4_a, &ip4_b, &ip4_c);
return !strcmp(ip_convert_to_string(&ip4_c), "192.168.0.0");
});
EXO_TEST(ip4_bitwise_AND_4, {
ip_convert_to_binary("192.168.217.113", &ip4_a);
ip_convert_to_binary("255.0.0.0", &ip4_b);
ip_mask_apply_AND(&ip4_a, &ip4_b, &ip4_c);
return !strcmp(ip_convert_to_string(&ip4_c), "192.0.0.0");
});
EXO_TEST(ip4_bitwise_AND_5, {
ip_convert_to_binary("192.168.217.113", &ip4_a);
ip_convert_to_binary("0.0.0.0", &ip4_b);
ip_mask_apply_AND(&ip4_a, &ip4_b, &ip4_c);
return !strcmp(ip_convert_to_string(&ip4_c), "0.0.0.0");
});
EXO_TEST(ip4_bitwise_OR_1, {
ip_convert_to_binary("255.255.255.255", &ip4_a);
ip_convert_to_binary("255.255.255.0", &ip4_b);
ip_mask_apply_OR(&ip4_a, &ip4_b, &ip4_c);
return !strcmp(ip_convert_to_string(&ip4_c), "255.255.255.255");
});
EXO_TEST(ip4_bitwise_OR_2, {
ip_convert_to_binary("192.168.217.113", &ip4_a);
ip_convert_to_binary("255.255.255.0", &ip4_b);
ip_mask_apply_OR(&ip4_a, &ip4_b, &ip4_c);
return !strcmp(ip_convert_to_string(&ip4_c), "255.255.255.113");
});
EXO_TEST(ip4_bitwise_OR_3, {
ip_convert_to_binary("192.168.217.113", &ip4_a);
ip_convert_to_binary("255.255.0.0", &ip4_b);
ip_mask_apply_OR(&ip4_a, &ip4_b, &ip4_c);
return !strcmp(ip_convert_to_string(&ip4_c), "255.255.217.113");
});
EXO_TEST(ip4_bitwise_OR_4, {
ip_convert_to_binary("192.168.217.113", &ip4_a);
ip_convert_to_binary("255.0.0.0", &ip4_b);
ip_mask_apply_OR(&ip4_a, &ip4_b, &ip4_c);
return !strcmp(ip_convert_to_string(&ip4_c), "255.168.217.113");
});
EXO_TEST(ip4_bitwise_OR_5, {
ip_convert_to_binary("192.168.217.113", &ip4_a);
ip_convert_to_binary("0.0.0.0", &ip4_b);
ip_mask_apply_OR(&ip4_a, &ip4_b, &ip4_c);
return !strcmp(ip_convert_to_string(&ip4_c), "192.168.217.113");
});
EXO_TEST(ip6_bitwise_AND_1, {
if (!ipv6) return 1;
ip_convert_to_binary("7f7f:ffff:ffff:3f3f:ffff:ffff:ffff:ffff", &ip6_a);
ip_convert_to_binary("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0", &ip6_b);
ip_mask_apply_AND(&ip6_a, &ip6_b, &ip6_c);
return !strcmp(ip_convert_to_string(&ip6_c), "7f7f:ffff:ffff:3f3f:ffff:ffff:ffff:0") ||
!strcmp(ip_convert_to_string(&ip6_c), "7f7f:ffff:ffff:3f3f:ffff:ffff:ffff::");
});
EXO_TEST(ip6_bitwise_AND_2, {
if (!ipv6) return 1;
ip_convert_to_binary("7777:cccc:3333:1111:ffff:ffff:ffff:ffff", &ip6_a);
ip_convert_to_binary("ffff:ffff:ffff:ffff::", &ip6_b);
ip_mask_apply_AND(&ip6_a, &ip6_b, &ip6_c);
return !strcmp(ip_convert_to_string(&ip6_c), "7777:cccc:3333:1111::");
});
EXO_TEST(ip6_bitwise_AND_3, {
if (!ipv6) return 1;
ip_convert_to_binary("7777:cccc:3333:1111:ffff:ffff:ffff:ffff", &ip6_a);
ip_convert_to_binary("::", &ip6_b);
ip_mask_apply_AND(&ip6_a, &ip6_b, &ip6_c);
return !strcmp(ip_convert_to_string(&ip6_c), "::");
});
EXO_TEST(ip6_bitwise_OR_1, {
if (!ipv6) return 1;
ip_convert_to_binary("7f7f:ffff:ffff:3f3f:ffff:ffff:ffff:ffff", &ip6_a);
ip_convert_to_binary("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0", &ip6_b);
ip_mask_apply_OR(&ip6_a, &ip6_b, &ip6_c);
return !strcmp(ip_convert_to_string(&ip6_c), "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
});
EXO_TEST(ip6_bitwise_OR_2, {
if (!ipv6) return 1;
ip_convert_to_binary("7777:cccc:3333:1111:ffff:ffff:ffff:ffff", &ip6_a);
ip_convert_to_binary("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0", &ip6_b);
ip_mask_apply_OR(&ip6_a, &ip6_b, &ip6_c);
return !strcmp(ip_convert_to_string(&ip6_c), "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
});
EXO_TEST(ip6_bitwise_OR_3, {
if (!ipv6) return 1;
ip_convert_to_binary("7777:cccc:3333:1111:ffff:ffff:ffff:1c1c", &ip6_a);
ip_convert_to_binary("::", &ip6_b);
ip_mask_apply_OR(&ip6_a, &ip6_b, &ip6_c);
return !strcmp(ip_convert_to_string(&ip6_c), "7777:cccc:3333:1111:ffff:ffff:ffff:1c1c");
});
EXO_TEST(ip_range_1, {
struct ip_range range; memset(&range, 0, sizeof(range));
return ip_convert_address_to_range("192.168.0.1", &range) && memcmp(&range.lo, &range.hi, sizeof(struct ip_addr_encap)) == 0;
});
EXO_TEST(ip_range_2, {
struct ip_range range; memset(&range, 0, sizeof(range));
return ip_convert_address_to_range("192.168.0.0-192.168.255.255", &range) && range.lo.af == range.hi.af && memcmp(&range.lo, &range.hi, sizeof(struct ip_addr_encap)) != 0;
});
EXO_TEST(ip_range_3, {
struct ip_range range; memset(&range, 0, sizeof(range));
return ip_convert_address_to_range("192.168.0.0/16", &range) && range.lo.af == range.hi.af && memcmp(&range.lo, &range.hi, sizeof(struct ip_addr_encap)) != 0;
});
EXO_TEST(ip_range_4, {
struct ip_range range1; memset(&range1, 0, sizeof(range1));
struct ip_range range2; memset(&range2, 0, sizeof(range2));
return ip_convert_address_to_range("192.168.0.0/16", &range1) && ip_convert_address_to_range("192.168.0.0-192.168.255.255", &range2) && memcmp(&range1, &range2, sizeof(struct ip_range)) == 0;
});
EXO_TEST(shutdown_network, {
return net_destroy() == 0;
});
-137
View File
@@ -1,137 +0,0 @@
#include <uhub.h>
static struct linked_list* list = NULL;
static char A[2] = { 'A', 0 };
static char B[2] = { 'B', 0 };
static char C[2] = { 'C', 0 };
static void null_free(void* ptr)
{
(void) ptr;
}
EXO_TEST(list_create_destroy, {
int ok = 0;
struct linked_list* alist;
alist = list_create();
if (alist) ok = 1;
list_destroy(alist);
return ok;
});
EXO_TEST(list_create, {
list = list_create();
return list->size == 0;
});
EXO_TEST(list_append_1, {
list_append(list, (char*) A);
return list->size == 1;
});
EXO_TEST(list_remove_1, {
list_remove(list, (char*) A);
return list->size == 0;
});
EXO_TEST(list_append_2, {
list_append(list, A);
list_append(list, B);
return list->size == 2;
});
EXO_TEST(list_remove_2, {
list_remove(list, (char*) A);
return list->size == 1;
});
EXO_TEST(list_remove_3, {
list_remove(list, (char*) A); /* already removed, so should have no effect */
return list->size == 1;
});
EXO_TEST(list_remove_4, {
list_remove(list, (char*) B); /* already removed, so should have no effect */
return list->size == 0;
});
EXO_TEST(list_append_3, {
list_append(list, A);
list_append(list, B);
list_append(list, C);
return list->size == 3;
});
EXO_TEST(list_append_4, {
list_append(list, A); /* OK. adding the same one *AGAIN* */
return list->size == 4;
});
EXO_TEST(list_remove_5, {
list_remove(list, A); /* removing the first one. */
return list->size == 3;
});
EXO_TEST(list_get_index_1, {
return list_get_index(list, 0) == B;
});
EXO_TEST(list_get_index_2, {
return list_get_index(list, 1) == C;
});
EXO_TEST(list_get_index_3, {
return list_get_index(list, 2) == A;
});
EXO_TEST(list_get_index_4, {
return list_get_index(list, 3) == NULL;
});
EXO_TEST(list_get_first_1, {
return list_get_first(list) == B;
});
EXO_TEST(list_get_first_next_1, {
return list_get_next(list) == C;
});
EXO_TEST(list_get_first_next_2, {
return list_get_next(list) == A;
});
EXO_TEST(list_get_last_1, {
return list_get_last(list) == A;
});
EXO_TEST(list_get_last_prev_1, {
return list_get_prev(list) == C;
});
EXO_TEST(list_get_last_prev_2, {
return list_get_prev(list) == B;
});
EXO_TEST(list_get_last_prev_next_1, {
return list_get_next(list) == C;
});
EXO_TEST(list_clear, {
list_clear(list, &null_free);
return list->size == 0 && list->first == 0 && list->last == 0 && list->iterator == 0;
});
EXO_TEST(list_destroy_1, {
list_destroy(list);
return 1;
});
EXO_TEST(list_destroy_2, {
list_destroy(0);
return 1;
});
-37
View File
@@ -1,37 +0,0 @@
#include <uhub.h>
struct adc_message* g_msg;
EXO_TEST(test_message_refc_1, {
g_msg = adc_msg_create("IMSG Hello\\sWorld!");
return g_msg != NULL;
});
EXO_TEST(test_message_refc_2, {
return g_msg->references == 0; // 0
});
EXO_TEST(test_message_refc_3, {
adc_msg_incref(g_msg);
return g_msg->references == 1; // 1
});
EXO_TEST(test_message_refc_4, {
adc_msg_incref(g_msg);
return g_msg->references == 2; // 2
});
EXO_TEST(test_message_refc_5, {
adc_msg_free(g_msg);
return g_msg->references == 1; // 1
});
EXO_TEST(test_message_refc_6, {
adc_msg_free(g_msg);
return g_msg->references == 0; // 0
});
EXO_TEST(test_message_refc_7, {
adc_msg_free(g_msg);
return 1;
});
-560
View File
@@ -1,560 +0,0 @@
#include <uhub.h>
static struct hub_user* g_user = 0;
static const char* test_string1 = "IINF AAfoo BBbar CCwhat\n";
static const char* test_string2 = "BMSG AAAB Hello\\sWorld!\n";
static const char* test_string3 = "BINF AAAB IDAN7ZMSLIEBL53OPTM7WXGSTXUS3XOY6KQS5LBGX NIFriend DEstuff SL3 SS0 SF0 VEQuickDC/0.4.17 US6430 SUADC0,TCP4,UDP4 I4127.0.0.1 HO5 HN1 AW\n";
static const char* test_string4 = "BMSG AAAB\n";
static const char* test_string5 = "BMSG AAAB \n";
static void create_test_user()
{
if (g_user)
return;
g_user = (struct hub_user*) malloc(sizeof(struct hub_user));
memset(g_user, 0, sizeof(struct hub_user));
memcpy(g_user->id.nick, "exotic-tester", 13);
g_user->id.sid = 1;
}
EXO_TEST(adc_message_first, {
create_test_user();
return g_user != 0;
});
EXO_TEST(adc_message_parse_1, {
struct adc_message* msg = adc_msg_create("IMSG Hello\\sWorld!");
int ok = msg != NULL;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_parse_2, {
struct adc_message* msg = adc_msg_create(test_string2);
int ok = (msg != NULL);
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_parse_3, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "BMSG AAAB Hello\\sWorld!", 23);
int ok = msg != NULL;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_parse_4, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "BMSG AAAC Hello\\sWorld!", 23);
return msg == NULL;
});
EXO_TEST(adc_message_parse_5, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "BMSG AAAB Hello\\sWorld!\n", 24);
int ok = msg != NULL;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_parse_6, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "FMSG AAAB +TCP4 Hello\\sWorld!\n", 30);
int ok = msg != NULL;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_parse_7, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "FMSG AAAB -TCP4 Hello\\sWorld!\n", 30);
int ok = msg != NULL;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_parse_8, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "FMSG AAAB +TCP4+UDP4 Hello\\sWorld!\n", 35);
int ok = msg != NULL;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_parse_9, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "FMSG AAAB +TCP4-UDP4 Hello\\sWorld!\n", 35);
int ok = msg != NULL;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_parse_10, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "FMSG AAAB -TCP4-UDP4 Hello\\sWorld!\n", 35);
int ok = msg != NULL;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_parse_11, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "FMSG AAAB Hello\\sWorld!\n", 24);
return msg == NULL;
});
EXO_TEST(adc_message_parse_12, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "FMSG AAAB Hello\\sWorld!\n", 25);
return msg == NULL;
});
EXO_TEST(adc_message_parse_13, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "FMSG AAAB +jalla Hello\\sWorld!\n", 31);
return msg == NULL;
});
EXO_TEST(adc_message_parse_14, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "FMSG AAAB +jall Hello\\sWorld!\n", 30);
int ok = msg != NULL;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_parse_15, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "FMSG AAAB +TCP4 Hello\\sWorld!\n", 30);
int ok = msg != NULL;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_parse_16, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "BMSG AAAB Hello\\sWorld!\n", 24);
int ok = msg != NULL;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_parse_17, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "BMSG aaab Hello\\sWorld!\n", 24);
return msg == NULL;
});
EXO_TEST(adc_message_parse_18, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "DMSG AAAB AAAC Hello\\sthere!\n", 29);
int ok = msg != NULL;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_parse_19, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "DMSG AAAC AAAB Hello\\sthere!\n", 29);
return msg == NULL;
});
EXO_TEST(adc_message_parse_20, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "EMSG AAAB AAAC Hello\\sthere!\n", 29);
int ok = msg != NULL;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_parse_21, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "EMSG AAAC AAAB Hello\\sthere!\n", 29);
return msg == NULL;
});
EXO_TEST(adc_message_parse_22, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "\n", 0);
return msg == NULL;
});
EXO_TEST(adc_message_parse_23, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "\r\n", 1);
return msg == NULL;
});
EXO_TEST(adc_message_parse_24, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "EMSG AAAC\0AAAB Hello\\sthere!\n", 29);
return msg == NULL;
});
EXO_TEST(adc_message_add_arg_1, {
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_add_argument(msg, "XXwtf?");
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat XXwtf?\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_add_arg_2, {
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_add_named_argument(msg, "XX", "wtf?");
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat XXwtf?\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_remove_arg_1, {
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_remove_named_argument(msg, "AA");
int ok = strcmp(msg->cache, "IINF BBbar CCwhat\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_remove_arg_2, {
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_remove_named_argument(msg, "BB");
int ok = strcmp(msg->cache, "IINF AAfoo CCwhat\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_remove_arg_3, {
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_remove_named_argument(msg, "CC");
int ok = strcmp(msg->cache, "IINF AAfoo BBbar\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_remove_arg_4, {
/* this ensures we can remove the last element also */
struct adc_message* msg = adc_msg_parse_verify(g_user, test_string3, strlen(test_string3));
adc_msg_remove_named_argument(msg, "AW");
int ok = strcmp(msg->cache, "BINF AAAB IDAN7ZMSLIEBL53OPTM7WXGSTXUS3XOY6KQS5LBGX NIFriend DEstuff SL3 SS0 SF0 VEQuickDC/0.4.17 US6430 SUADC0,TCP4,UDP4 I4127.0.0.1 HO5 HN1\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_replace_arg_1, {
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_remove_named_argument(msg, "AA");
int ok = strcmp(msg->cache, "IINF BBbar CCwhat\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_replace_arg_2, {
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_remove_named_argument(msg, "BB");
int ok = strcmp(msg->cache, "IINF AAfoo CCwhat\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_replace_arg_3, {
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_remove_named_argument(msg, "CC");
int ok = strcmp(msg->cache, "IINF AAfoo BBbar\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_get_arg_1, {
struct adc_message* msg = adc_msg_create(test_string1);
char* c = adc_msg_get_argument(msg, 0);
int ok = strcmp(c, "AAfoo") == 0;
adc_msg_free(msg);
hub_free(c);
return ok;
});
EXO_TEST(adc_message_get_arg_2, {
struct adc_message* msg = adc_msg_create(test_string1);
char* c = adc_msg_get_argument(msg, 1);
int ok = strcmp(c, "BBbar") == 0;
adc_msg_free(msg);
hub_free(c);
return ok;
});
EXO_TEST(adc_message_get_arg_3, {
struct adc_message* msg = adc_msg_create(test_string1);
char* c = adc_msg_get_argument(msg, 2);
int ok = strcmp(c, "CCwhat") == 0;
adc_msg_free(msg);
hub_free(c);
return ok;
});
EXO_TEST(adc_message_get_arg_4, {
struct adc_message* msg = adc_msg_create(test_string1);
char* c = adc_msg_get_argument(msg, 3);
int ok = c == 0;
adc_msg_free(msg);
hub_free(c);
return ok;
});
EXO_TEST(adc_message_get_named_arg_1, {
struct adc_message* msg = adc_msg_create(test_string1);
char* c = adc_msg_get_named_argument(msg, "AA");
int ok = strcmp(c, "foo") == 0;
adc_msg_free(msg);
hub_free(c);
return ok;
});
EXO_TEST(adc_message_get_named_arg_2, {
struct adc_message* msg = adc_msg_create(test_string1);
char* c = adc_msg_get_named_argument(msg, "BB");
int ok = strcmp(c, "bar") == 0;
adc_msg_free(msg);
hub_free(c);
return ok;
});
EXO_TEST(adc_message_get_named_arg_3, {
struct adc_message* msg = adc_msg_create(test_string1);
char* c = adc_msg_get_named_argument(msg, "CC");
int ok = strcmp(c, "what") == 0;
adc_msg_free(msg);
hub_free(c);
return ok;
});
EXO_TEST(adc_message_get_named_arg_4, {
struct adc_message* msg = adc_msg_create(test_string1);
char* c = adc_msg_get_named_argument(msg, "XX");
int ok = c == 0;
adc_msg_free(msg);
hub_free(c);
return ok;
});
EXO_TEST(adc_message_has_named_arg_1, {
struct adc_message* msg = adc_msg_create(test_string1);
int n = adc_msg_has_named_argument(msg, "XX");
adc_msg_free(msg);
return n == 0;
});
EXO_TEST(adc_message_has_named_arg_2, {
struct adc_message* msg = adc_msg_create(test_string1);
int n = adc_msg_has_named_argument(msg, "BB");
adc_msg_free(msg);
return n == 1;
});
EXO_TEST(adc_message_has_named_arg_3, {
struct adc_message* msg = adc_msg_create(test_string1);
int n = adc_msg_has_named_argument(msg, "CC");
adc_msg_free(msg);
return n == 1;
});
EXO_TEST(adc_message_has_named_arg_4, {
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_add_argument(msg, "XXwtf?");
int n = adc_msg_has_named_argument(msg, "XX");
adc_msg_free(msg);
return n == 1;
});
EXO_TEST(adc_message_has_named_arg_5, {
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_add_argument(msg, "XXone");
adc_msg_add_argument(msg, "XXtwo");
int n = adc_msg_has_named_argument(msg, "XX");
adc_msg_free(msg);
return n == 2;
});
EXO_TEST(adc_message_has_named_arg_6, {
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_add_argument(msg, "XXone");
adc_msg_add_argument(msg, "XXtwo");
adc_msg_add_argument(msg, "XXthree");
int n = adc_msg_has_named_argument(msg, "XX");
adc_msg_free(msg);
return n == 3;
});
EXO_TEST(adc_message_has_named_arg_7, {
struct adc_message* msg = adc_msg_create(test_string1);
int n = adc_msg_has_named_argument(msg, "AA");
adc_msg_free(msg);
return n == 1;
});
EXO_TEST(adc_message_terminate_1, {
struct adc_message* msg = adc_msg_create("IINF AAfoo BBbar CCwhat");
adc_msg_unterminate(msg);
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_terminate_2, {
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_unterminate(msg);
adc_msg_terminate(msg);
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_terminate_3, {
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_unterminate(msg);
adc_msg_terminate(msg);
adc_msg_unterminate(msg);
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_terminate_4, {
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_unterminate(msg);
adc_msg_terminate(msg);
adc_msg_terminate(msg);
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_terminate_5, {
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_terminate(msg);
adc_msg_terminate(msg);
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_terminate_6, {
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_unterminate(msg);
adc_msg_unterminate(msg);
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_escape_1, {
char* s = adc_msg_escape(test_string1);
int ok = strcmp(s, "IINF\\sAAfoo\\sBBbar\\sCCwhat\\n") == 0;
hub_free(s);
return ok;
});
EXO_TEST(adc_message_escape_2, {
char* s = adc_msg_escape(test_string1);
char* s2 = adc_msg_unescape(s);
int ok = strcmp(s2, test_string1) == 0;
hub_free(s);
hub_free(s2);
return ok;
});
EXO_TEST(adc_message_escape_3, {
char* s = adc_msg_unescape(test_string1);
int ok = strcmp(s, test_string1) == 0;
hub_free(s);
return ok;
});
EXO_TEST(adc_message_copy_1, {
struct adc_message* msg1 = adc_msg_create(test_string1);
struct adc_message* msg2 = adc_msg_copy(msg1);
int ok = strncmp(msg1->cache, msg2->cache, msg1->length) == 0;
adc_msg_free(msg1);
adc_msg_free(msg2);
return ok;
});
EXO_TEST(adc_message_copy_2, {
struct adc_message* msg1 = adc_msg_parse_verify(g_user, test_string2, strlen(test_string2));
struct adc_message* msg2 = adc_msg_copy(msg1);
int ok = msg1->source == msg2->source;
adc_msg_free(msg1);
adc_msg_free(msg2);
return ok;
});
EXO_TEST(adc_message_copy_3, {
struct adc_message* msg1 = adc_msg_parse_verify(g_user, test_string2, strlen(test_string2));
struct adc_message* msg2 = adc_msg_copy(msg1);
int ok = ( msg1->cmd == msg2->cmd &&
msg1->source == msg2->source &&
msg1->target == msg2->target &&
msg1->length == msg2->length &&
msg1->priority == msg2->priority &&
msg1->capacity == msg2->capacity && /* might not be true! */
strcmp(msg1->cache, msg2->cache) == 0);
adc_msg_free(msg1);
adc_msg_free(msg2);
return ok;
});
EXO_TEST(adc_message_copy_4, {
struct adc_message* msg1 = adc_msg_parse_verify(g_user, test_string2, strlen(test_string2));
struct adc_message* msg2 = adc_msg_copy(msg1);
int ok = msg2->target == 0;
adc_msg_free(msg1);
adc_msg_free(msg2);
return ok;
});
static struct adc_message* updater1 = NULL;
static struct adc_message* updater2 = NULL;
static const char* update_info1 = "BINF AAAB IDABCDEFGHIJKLMNOPQRSTUVWXYZ1234567ABCDEF NItester SL10 SS12817126127 SF4125 HN3 HR0 HO0 VE++\\s0.698 US104857600 DS81911808 SUTCP4,UDP4 I4127.0.0.1\n";
static const char* update_info2 = "BINF AAAB HN34 SF4126 SS12817526127\n";
EXO_TEST(adc_message_update_1, {
updater1 = adc_msg_parse_verify(g_user, update_info1, strlen(update_info1));
return updater1 != NULL;
});
EXO_TEST(adc_message_update_2, {
user_set_info(g_user, updater1);
return strcmp(g_user->info->cache, updater1->cache) == 0 && g_user->info == updater1;
});
EXO_TEST(adc_message_update_3, {
updater2 = adc_msg_parse_verify(g_user, update_info2, strlen(update_info2));
return updater2 != NULL;
});
EXO_TEST(adc_message_update_4, {
user_update_info(g_user, updater2);
return strlen(g_user->info->cache) == 159;
});
EXO_TEST(adc_message_update_4_cleanup, {
adc_msg_free(updater1);
updater1 = 0;
adc_msg_free(updater2);
updater2 = 0;
adc_msg_free(g_user->info);
g_user->info = 0;
return 1;
});
EXO_TEST(adc_message_empty_1, {
struct adc_message* msg = adc_msg_parse_verify(g_user, test_string2, strlen(test_string2));
int ok = adc_msg_is_empty(msg) == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_empty_2, {
struct adc_message* msg = adc_msg_parse_verify(g_user, test_string4, strlen(test_string4));
int ok = adc_msg_is_empty(msg);
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_empty_3, {
struct adc_message* msg = adc_msg_parse_verify(g_user, test_string5, strlen(test_string5));
int ok = adc_msg_is_empty(msg) == 0; /* arguably not empty, contains a space */
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_last, {
hub_free(g_user);
g_user = 0;
return g_user == 0;
});
-111
View File
@@ -1,111 +0,0 @@
#include <uhub.h>
EXO_TEST(is_num_0, { return is_num('0'); });
EXO_TEST(is_num_1, { return is_num('1'); });
EXO_TEST(is_num_2, { return is_num('2'); });
EXO_TEST(is_num_3, { return is_num('3'); });
EXO_TEST(is_num_4, { return is_num('4'); });
EXO_TEST(is_num_5, { return is_num('5'); });
EXO_TEST(is_num_6, { return is_num('6'); });
EXO_TEST(is_num_7, { return is_num('7'); });
EXO_TEST(is_num_8, { return is_num('8'); });
EXO_TEST(is_num_9, { return is_num('9'); });
EXO_TEST(is_num_10, { return !is_num('/'); });
EXO_TEST(is_num_11, { return !is_num(':'); });
EXO_TEST(is_space_1, { return is_space(' '); });
EXO_TEST(is_space_2, { return !is_space('\t'); });
EXO_TEST(is_white_space_1, { return is_white_space(' '); });
EXO_TEST(is_white_space_2, { return is_white_space('\t'); });
EXO_TEST(is_white_space_3, { return !is_white_space('A'); });
EXO_TEST(is_white_space_4, { return !is_white_space('!'); });
EXO_TEST(itoa_1, { return strcmp(uhub_itoa(0), "0") == 0; });
EXO_TEST(itoa_2, { return strcmp(uhub_itoa(1), "1") == 0; });
EXO_TEST(itoa_3, { return strcmp(uhub_itoa(-1), "-1") == 0; });
EXO_TEST(itoa_4, { return strcmp(uhub_itoa(255), "255") == 0; });
EXO_TEST(itoa_5, { return strcmp(uhub_itoa(-3), "-3") == 0; });
EXO_TEST(itoa_6, { return strcmp(uhub_itoa(-2147483647), "-2147483647") == 0; });
EXO_TEST(itoa_7, { return strcmp(uhub_itoa(2147483647), "2147483647") == 0; });
EXO_TEST(itoa_8, { return strcmp(uhub_itoa(-65536), "-65536") == 0; });
EXO_TEST(base32_valid_1, { return is_valid_base32_char('A'); });
EXO_TEST(base32_valid_2, { return is_valid_base32_char('B'); });
EXO_TEST(base32_valid_3, { return is_valid_base32_char('C'); });
EXO_TEST(base32_valid_4, { return is_valid_base32_char('D'); });
EXO_TEST(base32_valid_5, { return is_valid_base32_char('E'); });
EXO_TEST(base32_valid_6, { return is_valid_base32_char('F'); });
EXO_TEST(base32_valid_7, { return is_valid_base32_char('G'); });
EXO_TEST(base32_valid_8, { return is_valid_base32_char('H'); });
EXO_TEST(base32_valid_9, { return is_valid_base32_char('I'); });
EXO_TEST(base32_valid_10, { return is_valid_base32_char('J'); });
EXO_TEST(base32_valid_11, { return is_valid_base32_char('K'); });
EXO_TEST(base32_valid_12, { return is_valid_base32_char('L'); });
EXO_TEST(base32_valid_13, { return is_valid_base32_char('M'); });
EXO_TEST(base32_valid_14, { return is_valid_base32_char('N'); });
EXO_TEST(base32_valid_15, { return is_valid_base32_char('O'); });
EXO_TEST(base32_valid_16, { return is_valid_base32_char('P'); });
EXO_TEST(base32_valid_17, { return is_valid_base32_char('Q'); });
EXO_TEST(base32_valid_18, { return is_valid_base32_char('R'); });
EXO_TEST(base32_valid_19, { return is_valid_base32_char('S'); });
EXO_TEST(base32_valid_20, { return is_valid_base32_char('T'); });
EXO_TEST(base32_valid_21, { return is_valid_base32_char('U'); });
EXO_TEST(base32_valid_22, { return is_valid_base32_char('V'); });
EXO_TEST(base32_valid_23, { return is_valid_base32_char('W'); });
EXO_TEST(base32_valid_24, { return is_valid_base32_char('X'); });
EXO_TEST(base32_valid_25, { return is_valid_base32_char('Y'); });
EXO_TEST(base32_valid_26, { return is_valid_base32_char('Z'); });
EXO_TEST(base32_valid_27, { return is_valid_base32_char('2'); });
EXO_TEST(base32_valid_28, { return is_valid_base32_char('3'); });
EXO_TEST(base32_valid_29, { return is_valid_base32_char('4'); });
EXO_TEST(base32_valid_30, { return is_valid_base32_char('5'); });
EXO_TEST(base32_valid_31, { return is_valid_base32_char('6'); });
EXO_TEST(base32_valid_32, { return is_valid_base32_char('7'); });
EXO_TEST(base32_invalid_1, { return !is_valid_base32_char('a'); });
EXO_TEST(base32_invalid_2, { return !is_valid_base32_char('b'); });
EXO_TEST(base32_invalid_3, { return !is_valid_base32_char('c'); });
EXO_TEST(base32_invalid_4, { return !is_valid_base32_char('d'); });
EXO_TEST(base32_invalid_5, { return !is_valid_base32_char('e'); });
EXO_TEST(base32_invalid_6, { return !is_valid_base32_char('f'); });
EXO_TEST(base32_invalid_7, { return !is_valid_base32_char('g'); });
EXO_TEST(base32_invalid_8, { return !is_valid_base32_char('h'); });
EXO_TEST(base32_invalid_9, { return !is_valid_base32_char('i'); });
EXO_TEST(base32_invalid_10, { return !is_valid_base32_char('j'); });
EXO_TEST(base32_invalid_11, { return !is_valid_base32_char('k'); });
EXO_TEST(base32_invalid_12, { return !is_valid_base32_char('l'); });
EXO_TEST(base32_invalid_13, { return !is_valid_base32_char('m'); });
EXO_TEST(base32_invalid_14, { return !is_valid_base32_char('n'); });
EXO_TEST(base32_invalid_15, { return !is_valid_base32_char('o'); });
EXO_TEST(base32_invalid_16, { return !is_valid_base32_char('p'); });
EXO_TEST(base32_invalid_17, { return !is_valid_base32_char('q'); });
EXO_TEST(base32_invalid_18, { return !is_valid_base32_char('r'); });
EXO_TEST(base32_invalid_19, { return !is_valid_base32_char('s'); });
EXO_TEST(base32_invalid_20, { return !is_valid_base32_char('t'); });
EXO_TEST(base32_invalid_21, { return !is_valid_base32_char('u'); });
EXO_TEST(base32_invalid_22, { return !is_valid_base32_char('v'); });
EXO_TEST(base32_invalid_23, { return !is_valid_base32_char('w'); });
EXO_TEST(base32_invalid_24, { return !is_valid_base32_char('x'); });
EXO_TEST(base32_invalid_25, { return !is_valid_base32_char('y'); });
EXO_TEST(base32_invalid_26, { return !is_valid_base32_char('z'); });
EXO_TEST(base32_invalid_27, { return !is_valid_base32_char('0'); });
EXO_TEST(base32_invalid_28, { return !is_valid_base32_char('1'); });
EXO_TEST(base32_invalid_29, { return !is_valid_base32_char('8'); });
EXO_TEST(base32_invalid_30, { return !is_valid_base32_char('9'); });
EXO_TEST(base32_invalid_31, { return !is_valid_base32_char('@'); });
EXO_TEST(utf8_valid_1, { return is_valid_utf8("abcdefghijklmnopqrstuvwxyz"); });
EXO_TEST(utf8_valid_2, { return is_valid_utf8("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); });
EXO_TEST(utf8_valid_3, { return is_valid_utf8("0123456789"); });
EXO_TEST(utf8_valid_4, { return is_valid_utf8( (char[]) { 0x65, 0x00} ); });
EXO_TEST(utf8_valid_5, { return !is_valid_utf8( (char[]) { 0xD8, 0x00} ); });
EXO_TEST(utf8_valid_6, { return is_valid_utf8( (char[]) { 0x24, 0x00} ); });
EXO_TEST(utf8_valid_7, { return !is_valid_utf8( (char[]) { 0xC2, 0x24, 0x00} ); });
EXO_TEST(utf8_valid_8, { return is_valid_utf8( (char[]) { 0xC2, 0xA2, 0x00} ); });
EXO_TEST(utf8_valid_9, { return is_valid_utf8( (char[]) { 0xE2, 0x82, 0xAC, 0x00} ); });
EXO_TEST(utf8_valid_10, { return !is_valid_utf8( (char[]) { 0xC2, 0x32, 0x00} ); });
EXO_TEST(utf8_valid_11, { return !is_valid_utf8( (char[]) { 0xE2, 0x82, 0x32, 0x00} ); });
EXO_TEST(utf8_valid_12, { return !is_valid_utf8( (char[]) { 0xE2, 0x32, 0x82, 0x00} ); });
-69
View File
@@ -1,69 +0,0 @@
#include <uhub.h>
#define DEBUG_HASH
static char* byte_to_hex(char* dest, uint8_t c)
{
static const char* hexchars = "0123456789abcdef";
*dest = hexchars[c / 16]; dest++;
*dest = hexchars[c % 16]; dest++;
return dest;
}
static int test_tiger_hex(char* input, char* expected) {
char buf[TIGERSIZE*2+1];
uint64_t tiger_res[3];
int i = 0;
#ifdef DEBUG_HASH
int res = 0;
#endif
char* ptr = buf;
buf[TIGERSIZE*2] = 0;
tiger((uint64_t*) input, strlen(input), (uint64_t*) tiger_res);
for (i = 0; i < TIGERSIZE; i++)
ptr = byte_to_hex(ptr, (char) (((uint8_t*) tiger_res)[i]) );
#ifdef DEBUG_HASH
res = strcasecmp(buf, expected) == 0 ? 1 : 0;
if (!res)
{
printf("Expected: '%s', Got: '%s'\n", expected, buf);
}
return res;
#else
return strcasecmp(buf, expected) == 0;
#endif
}
EXO_TEST(hash_tiger_1, {
return test_tiger_hex("", "3293AC630C13F0245F92BBB1766E16167A4E58492DDE73F3");
});
EXO_TEST(hash_tiger_2, {
return test_tiger_hex("a", "77BEFBEF2E7EF8AB2EC8F93BF587A7FC613E247F5F247809");
});
EXO_TEST(hash_tiger_3, {
return test_tiger_hex("abc", "2AAB1484E8C158F2BFB8C5FF41B57A525129131C957B5F93");
});
EXO_TEST(hash_tiger_4, {
return test_tiger_hex("message digest", "D981F8CB78201A950DCF3048751E441C517FCA1AA55A29F6");
});
EXO_TEST(hash_tiger_5, {
return test_tiger_hex("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "0F7BF9A19B9C58F2B7610DF7E84F0AC3A71C631E7B53F78E");
});
EXO_TEST(hash_tiger_6, {
return test_tiger_hex("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "8DCEA680A17583EE502BA38A3C368651890FFBCCDC49A8CC");
});
EXO_TEST(hash_tiger_7, {
return test_tiger_hex("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "1C14795529FD9F207A958F84C52F11E887FA0CABDFD91BFD");
});
-109
View File
@@ -1,109 +0,0 @@
#include <uhub.h>
#define MAX_USERS 64
static struct hub_info um_hub;
static struct hub_user um_user[MAX_USERS];
// static struct net_connection um_cons[MAX_USERS];
EXO_TEST(um_test_setup, {
int i = 0;
memset(&um_hub, 0, sizeof(um_hub));
for (i = 0; i < MAX_USERS; i++)
{
/* memset(&um_cons[i], 0, sizeof(struct net_connection));
um_cons[i].sd = -1;
memset(&um_user[i], 0, sizeof(struct hub_user));
um_user[i].id.sid = i+1;
um_user[i].connection = &um_cons[i];*/
}
return 1;
});
EXO_TEST(um_init_1, {
return uman_init(0) != 0;
});
EXO_TEST(um_init_2, {
return uman_init(&um_hub) == 0;
});
EXO_TEST(um_shutdown_1, {
return uman_shutdown(0) == -1;
});
EXO_TEST(um_shutdown_2, {
return uman_shutdown(&um_hub) == 0;
});
EXO_TEST(um_shutdown_3, {
return uman_shutdown(&um_hub) == -1;
});
EXO_TEST(um_init_3, {
return uman_init(&um_hub) == 0;
});
EXO_TEST(um_add_1, {
return uman_add(&um_hub, &um_user[0]) == 0;
});
EXO_TEST(um_size_1, {
return hub_get_user_count(&um_hub) == 1;
});
EXO_TEST(um_remove_1, {
return uman_remove(&um_hub, &um_user[0]) == 0;
});
EXO_TEST(um_size_2, {
return hub_get_user_count(&um_hub) == 0;
});
EXO_TEST(um_add_2, {
int i;
for (i = 0; i < MAX_USERS; i++)
{
if (uman_add(&um_hub, &um_user[i]) != 0)
return 0;
}
return 1;
});
EXO_TEST(um_size_3, {
return hub_get_user_count(&um_hub) == MAX_USERS;
});
EXO_TEST(um_add_3, {
return uman_add(&um_hub, &um_user[5]) != 0;
});
EXO_TEST(um_remove_2, {
int i;
for (i = 0; i < MAX_USERS; i++)
{
if (uman_remove(&um_hub, &um_user[i]) != 0)
return 0;
}
return 1;
});
/* Last test */
EXO_TEST(um_shutdown_4, {
return uman_shutdown(&um_hub) == 0;
});
-256
View File
@@ -1,256 +0,0 @@
# Doxyfile 1.5.5-KDevelop
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = uHub
PROJECT_NUMBER = 0.2.0-alpha
OUTPUT_DIRECTORY =
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF = "The $name class" \
"The $name widget" \
"The $name file" \
is \
provides \
specifies \
contains \
represents \
a \
an \
the
ALWAYS_DETAILED_SEC = YES
INLINE_INHERITED_MEMB = YES
FULL_PATH_NAMES = NO
STRIP_FROM_PATH =
STRIP_FROM_INC_PATH =
SHORT_NAMES = YES
JAVADOC_AUTOBRIEF = NO
QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
DETAILS_AT_TOP = YES
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 8
ALIASES =
OPTIMIZE_OUTPUT_FOR_C = YES
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = NO
SUBGROUPING = YES
TYPEDEF_HIDES_STRUCT = NO
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = YES
EXTRACT_PRIVATE = YES
EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = YES
EXTRACT_ANON_NSPACES = NO
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = YES
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = NO
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = YES
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_DIRECTORIES = NO
SHOW_FILES = YES
SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = YES
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = .
INPUT_ENCODING = UTF-8
FILE_PATTERNS = *.c \
*.h
RECURSIVE = YES
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS = autotest/*
EXCLUDE_SYMBOLS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS = *
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = YES
INLINE_SOURCES = YES
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
REFERENCES_LINK_SOURCE = YES
USE_HTAGS = NO
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
GENERATE_HTMLHELP = YES
GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = org.doxygen.Project
HTML_DYNAMIC_SECTIONS = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
BINARY_TOC = NO
TOC_EXPAND = YES
DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = NONE
TREEVIEW_WIDTH = 250
FORMULA_FONTSIZE = 10
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = NO
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4wide
EXTRA_PACKAGES =
LATEX_HEADER =
PDF_HYPERLINKS = YES
USE_PDFLATEX = YES
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_LINKS = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
XML_OUTPUT = xml
XML_SCHEMA =
XML_DTD =
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::additions related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE = uhub.tag
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
MSCGEN_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = YES
DOT_FONTNAME = FreeSans
DOT_FONTPATH =
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = NO
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
DOT_PATH =
DOTFILE_DIRS =
DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 1000
DOT_TRANSPARENT = YES
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# Configuration::additions related to the search engine
#---------------------------------------------------------------------------
SEARCHENGINE = NO
-91
View File
@@ -1,91 +0,0 @@
= Architecture of uHub =
uHub is single threaded and handles network and timer events using the
libevent library.
For each state there is a read event (and sometimes a write event) and timeout
event in case an expected read (or write) event does not occur.
== Protocol overview ==
uHub use "speak" the ADC protocol, which works in short as follows:
(C = client, S = server aka uHub).
C: HSUP ADBASE
Client connects to hub and supplies a list of supported features to the hub.
S: ISUP ADBASE { }
Server responds with a list of supported features.
S: ISID xxxx
Server assigns a session-ID to the client (4 bytes, BASE32 encoded).
C: BINF xxxx (...)
Client sends information about itself, such as nick name, etc.
The hub will relay this information to all users, including the client.
S: BINF xxx1 NInick1 (...)
S: BINF xxx2 NInick2
S: (...)
S: BINF xxxx (client's own nick)
Client gets list of other clients, which ends with the client's own user info.
At this point the client is successfully logged into the hub.
== The hub architecture ==
Accepting new users
--------------------- -----------------
| Accept connection | <---------- | libevent loop |
--------------------- -----------------
|
V
--------------------- ------------
| Setup login timer | --+----> | Timeout? | <----+
--------------------- | ------------ |
| | | |
V | V |
--------------------- | --------------- |
| Receive 'HSUP' | --+----> | DISCONNECT! | |
--------------------- --------------- |
| ^ |
V | |
--------------------- | |
| Send 'ISUP', and | | |
| assign Session ID | | |
--------------------- | |
| | |
V | |
--------------------- | |
| Receive 'BINF' |-----------------+------------
+--| Validate message | ^
| --------------------- |
| | |
| V |
| --------------------- ---------------------
| | Send password | ------> | Reveive and check |
| | request, if needed| | password. |
| --------------------- ---------------------
| |
| |
| ------------------------ |
+->| Send welcome message |<--------------+
------------------------
|
V
------------------------
| Send user list to |
| newly accepted user. |
------------------------
|
V
------------------------
| User is logged in. |
| Announce to all. |
------------------------
-27
View File
@@ -1,27 +0,0 @@
How to compile:
---------------
See the official compiling howto: http://www.extatic.org/uhub/compile.html
Prerequisites
Before you try to compile µHub, please make sure the following prerequisites are met.
* GNU make
* gcc > 3.0 (or MinGW on Windows)
* libevent >= 1.3
* Perl 5
Linux and Mac OSX
-----------------
Simply, run:
% make
FreeBSD, NetBSD and OpenBSD
---------------------------
Use GNU make, not BSD make:
% gmake
If you have an old gcc compiler, try disabling pre-compiled headers like this:
gmake USE_PCH=NO
-76
View File
@@ -1,76 +0,0 @@
ADC protocol extensions supported:
STATUS: **** Not yet implemented.
the 'AUT0' extension (network connection auto detection extension).
Rationale: Detect if client is capable of initiating active connections.
After logging in:
Client -> 'HCHK 12345 ABCD'.
Server sends a UDP packet containing token to the client's IP address at the given port as shown in the INF message.
Server -> 'ICHK ABCD'
The server should send it from a UDP socket bound to the same port as the TCP server, which means the server will
have to listen to both TCP and UDP.
If client receives the packet, it knows it can receive UDP connections, and will advertise it in the INF message as
a supported feature.
If the client does not receive any UDP packets within a few seconds, it MAY try to reconfigure the router using
UPnP/ZeroConf, and issue a HCHK command to the server again.
If the client still doesn't receive any UDP packets, hole punching can be tried.
The server will send a UDP packet to the hub (using the port of the TCP server), and reissue the HCHK command.
The UDP packet SHOULD be echoed by the hub.
This UDP packet should contain simply 'HECH {cid} {token}' (Hub echo).
The hub should send a packet containing the token back:
'IECH {token} {host:port}', aswell as the same message via TCP.
If the client receives the message via UDP, it should now be able to determine the type of NAT.
If the client receives the message via TCP only it knows it has a firewall blocking icomming communication.
If the client does not receive the message, it should assume a firewall is blocking all UDP communication,
and resume in passive mode.
Requirements:
'AUT0' in the extensions message (SUP) for client and hub.
Server will also listen to UDP messages on the same port as the TCP port.
The server MUST now respond to the 'HCHK' command via TCP
The server MUST now respond to the 'HECH' command via UDP.
The client will always initiate communication.
-------------------------------------------------------------------------------
Syntax: HCHK {port} {token}
- port is a 16-bit port number where the client is listening for packets.
- token is 4 bytes base32 encoded data specified by the client.
Example:
Client: 'HCHK 1511 BACD' (tcp)
Server: 'ICHK BACD' (udp)
-------------------------------------------------------------------------------
Syntax: HECH {cid} {token}
- cid is the client ID.
- token is 4 bytes base32 encoded data specified by the client.
Example:
Client: 'HECH 3NGFVJUDBRHX2CYRJGQ5HACRDM5CTNLGZ36M64I BACD' (udp)
Server: 'IECH BACD 192.168.0.1:1512' (udp)
Server: 'IECH BACD 192.168.0.1:1512' (tcp)
Security considerations:
The hub must verify that IP address where the HECH command originated from
matches the IP address where the user with the given CID is connected from.
If the CID and IP does not match, or the CID is not used the hub MUST ignore
the request.
-46
View File
@@ -1,46 +0,0 @@
Getting started guide
---------------------
(This document is maintained at http://www.extatic.org/uhub/getstarted.html )
Unpack your binaries
Example:
% tar xzf uhub-0.2.6-linux-i386.tar.gz
% cd uhub-0.2.6
Copy the binary to /usr/local/bin
% sudo cp uhub /usr/local/bin
Create configuration files.
If no configuration files are created, uhub will use the default parameters, so you can skip this step if you are in a hurry to see it run.
As root, or use sudo.
% mkdir /etc/uhub
% cp doc/uhub.conf /etc/uhub
% cp doc/users.conf /etc/uhub
% echo "welcome to uhub" > /etc/uhub/motd.txt
Start the hub in the foreground for the first time. Shut it down, by pressing CTRL+C.
% uhub
Thu, 05 Feb 2009 00:48:04 +0000 INFO: Starting server, listening on :::1511...
Connect to the hub using an ADC client, use the address adc://localhost:1511, or replace localhost with the correct hostname or IP address.
NOTE: It is important to use the "adc://" prefix, and the port number when using DC++ and other ADC clients.
If you modify the configuration files in /etc/uhub you will have to notify uhub by sending a HUP signal.
% kill -HUP <pid of uhub>
Or, for the lazy people
% killall -HUP uhub
In order to run uhub as a daemon, start it with the -f switch which will make it fork into the background.
In addition, use the -l to specify a log file instead of stdout. One can also specify a specific user and/or group,
if one wishes to run uhub as a specific user using the -u and -g switches.
Example:
% uhub -f -l mylog.txt -u nobody -g nogroup
Your mileage may vary -- Good luck!
-101
View File
@@ -1,101 +0,0 @@
#!/bin/sh
#
# chkconfig: - 91 35
# description: Starts and stops the Uhub ( http://www.extatic.org/uhub ) daemons on RHEL\CentOS \
# used to provide p2p network services.
#
# pidfile: /var/run/uhub.pid
# config: /etc/uhub/uhub.conf
# Source function library.
if [ -f /etc/init.d/functions ] ; then
. /etc/init.d/functions
elif [ -f /etc/rc.d/init.d/functions ] ; then
. /etc/rc.d/init.d/functions
else
exit 1
fi
# Avoid using root's TMPDIR
unset TMPDIR
# Source networking configuration.
. /etc/sysconfig/network
if [ -f /etc/sysconfig/uhub ]; then
. /etc/sysconfig/uhub
fi
# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 1
# Check that uhub.conf exists.
[ -f /etc/uhub/uhub.conf ] || exit 6
RETVAL=0
start() {
KIND="UHUB"
echo -n $"Starting $KIND services: "
daemon uhub $UHUBOPTIONS
RETVAL=$?
echo ""
return $RETVAL
}
stop() {
KIND="UHUB"
echo -n $"Shutting down $KIND services: "
killproc uhub
RETVAL=$?
echo ""
return $RETVAL
}
restart() {
stop
start
}
reload() {
echo -n $"Reloading uhub.conf / user.conf file: "
killproc uhub -HUP
RETVAL=$?
echo ""
return $RETVAL
}
rhstatus() {
status uhub
RETVAL=$?
if [ $RETVAL -ne 0 ] ; then
return $RETVAL
fi
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
reload)
reload
;;
status)
rhstatus
;;
*)
echo $"Usage: $0 {start|stop|restart|reload|status}"
exit 2
esac
exit $?
-15
View File
@@ -1,15 +0,0 @@
# Options to UHUB
# -v Verbose mode. Add more -v's for higher verbosity.
# -q Quiet mode - no output
# -f Fork to background
# -l <file> Log messages to given file (default: stderr)
# -L Log messages to syslog
# -c <file> Specify configuration file (default: /etc/uhub/uhub.conf)
# -S Show configuration parameters, but ignore defaults
# -u <user> Run as given user
# -g <group> Run with given group permissions
# -p <file> Store pid in file (process id)
UHUBOPTIONS=" -u uhub -f -p /var/run/uhub.pid -l /var/log/uhub.log"
-72
View File
@@ -1,72 +0,0 @@
.TH UHUB 1 "March 2009"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
.\" .nh disable hyphenation
.\" .hy enable hyphenation
.\" .ad l left justify
.\" .ad b justify to both left and right margins
.\" .nf disable filling
.\" .fi enable filling
.\" .br insert line break
.\" .sp <n> insert n+1 empty lines
.\" for manpage-specific macros, see man(7)
.SH NAME
uhub \- a high performance ADC peer-to-peer hub
.SH SYNOPSIS
.B uhub
.RI [ options ]
.SH DESCRIPTION
uHub is a high performance peer-to-peer hub for the ADC network.
Its low memory footprint allows it to handle several thousand users
on high-end servers, or a small private hub on embedded hardware.
.SH "OPTIONS"
.TP
.BI \^\-v
Verbose mode, add more -v's for higher verbosity.
.TP
.BI \^\-q
Quiet mode, if quiet mode is enabled no output or logs are made.
.TP
.BI \^\-f
Fork uhub to background in order to run it as a daemon.
.TP
.BI \^\-l " logfile"
Log messages to the given logfile (default: stderr)
.TP
.BI \^\-L
Log messages to syslog.
.TP
.BI \^\-c " config"
Specify configuration file (default: /etc/uhub/uhub.conf)
.TP
.BI \^\-C
Check configuration files and return. Will print either \"OK\" or \"ERROR\".
.TP
.BI \^\-s
Show all configuration parameters. In a format that is compatible with
the configuration files.
.TP
.BI \^\-S
Show all non-default configuration parameters.
.TP
.BI \^\-h
Show the help message.
.TP
.BI \^\-u " user"
Drop privileges and run as the given user.
.TP
.BI \^\-g " group"
Drop privileges and run with the given group permissions.
.TP
.BI \^\-V
Show the version number
.SH EXAMPLES
To run uhub as a daemon, and log to a file:
.TP
.B uhub " -f -l /var/log/uhub/uhub.log"
.SH AUTHOR
This program was written by Jan Vidar Krey <janvidar@extatic.org>
.SH "BUG REPORTS"
If you find a bug in uhub please report it to
.B http://bugs.extatic.org/
-90
View File
@@ -1,90 +0,0 @@
# uhub.conf - A example configuration file.
# You should normally place this file in /etc/uhub/uhub.conf
# And change the file_acl and file_motd below.
#
# This file is read only to the uhub deamon, and if you
# make changes to it while uhub is running you can send a
# HUP signal to it ( $ killall -HUP uhub ), to reparse configuration (only on UNIX).
# All configuration directives: http://www.uhub.org/config.php
# Bind to this port and address
# server_bind_addr=any means listen to "::" if IPv6 is supported
# by the host OS, otherwise 0.0.0.0.
server_port=1511
server_bind_addr=any
# The maximum amount of users allowed on the hub.
max_users=500
# If 1, will show a "This hub is running uhub/version".
show_banner=1
# Allow only registered users on the hub if set to 1.
registered_users_only=0
# A server name and description.
hub_name=my hub
hub_description=Powered by uHub
# Set this to 0, and the hub will disconnect everyone
hub_enabled=1
# Access control list (user database)
file_acl=/etc/uhub/users.conf
# This file can contain a message of the day. A welcome
# message send to any client when connecting.
# If the file does not exist, is empty, or cannot be opened
# the motd will not be sent to the clients.
# Normally this message is sent to clients when connecting.
file_motd=/etc/uhub/motd.txt
# Slots\share\hubs limits
limit_max_hubs_user = 0
limit_max_hubs_reg = 0
limit_max_hubs_op = 0
limit_max_hubs = 0
limit_min_hubs_user = 0
limit_min_hubs_reg = 0
limit_min_hubs_op = 0
limit_min_share = 0
# Example:
# To require users to share at least 1 GB in order to enter the hub:
# limit_min_share = 1024
limit_max_share = 0
limit_min_slots = 0
limit_max_slots = 0
# Configure status message as sent to clients in different circumstances.
msg_hub_full = Hub is full
msg_hub_disabled = Hub is disabled
msg_hub_registered_users_only = Hub is for registered users only
msg_inf_error_nick_missing = No nickname given
msg_inf_error_nick_multiple = Multiple nicknames given
msg_inf_error_nick_invalid = Nickname is invalid
msg_inf_error_nick_long = Nickname too long
msg_inf_error_nick_short = Nickname too short
msg_inf_error_nick_spaces = Nickname cannot start with spaces
msg_inf_error_nick_bad_chars = Nickname contains invalid characters
msg_inf_error_nick_not_utf8 = Nickname is not valid utf8
msg_inf_error_nick_taken = Nickname is already in use
msg_inf_error_nick_restricted = Nickname cannot be used on this hub
msg_inf_error_cid_invalid = CID is not valid
msg_inf_error_cid_missing = CID is not specified
msg_inf_error_cid_taken = CID is taken
msg_inf_error_pid_missing = PID is not specified
msg_inf_error_pid_invalid = PID is invalid
msg_ban_permanently = Banned permanently
msg_ban_temporarily = Banned temporarily
msg_auth_invalid_password = Password is wrong
msg_auth_user_not_found = User not found in password database
msg_user_share_size_low = User is not sharing enough
msg_user_share_size_high = User is sharing too much
msg_user_slots_low = User have too few upload slots
msg_user_slots_high = User have too many upload slots
msg_user_hub_limit_low = User is on too few hubs
msg_user_hub_limit_high = User is on too many hubs
msg_error_no_memory = No memory
-59
View File
@@ -1,59 +0,0 @@
/**
* Overview of uHub
*/
digraph G
{
"main()" -> "event_dispatch()"
"event_dispatch()" -> "net_on_accept()"
"event_dispatch()" -> "net_on_read()"
"event_dispatch()" -> "net_on_write()"
"event_dispatch()" -> "event_queue_process()"
/* net events */
"net_on_write()" -> "net_send()"
"net_on_write()" -> "user_disconnect()"
"net_on_accept()" -> "user_create()"
"net_on_read()" -> "net_recv()"
"net_on_read()" -> "user_disconnect()"
"net_recv()" -> "hub_handle_message()"
/* adc message handling */
"hub_handle_message()" -> "hub_handle_password()"
"hub_handle_message()" -> "hub_handle_support()"
"hub_handle_password()" -> "user_disconnect()"
"hub_handle_support()" -> "user_disconnect()"
"hub_handle_password()" -> "route_to_user()"
"hub_handle_support()" -> "route_to_user()"
"hub_handle_message()" -> "hub_handle_info()"
"hub_handle_message()" -> "route_message()"
"hub_handle_info()" -> "route_to_user()"
"hub_handle_info()" -> "route_to_all()"
/* message routing, depending on message type */
"route_message()" -> "route_to_user()"
"route_message()" -> "route_to_all()" -> "route_to_user()"
"route_message()" -> "route_to_subscribers()" -> "route_to_user()"
"route_to_user()" -> "net_send()"
"route_to_user()" -> "queue_command()"
"route_to_user()" -> "user_disconnect()"
/* Message dispatcher */
"event_queue_process()" -> "hub_event_dispatcher()"
"hub_event_dispatcher()" -> "EVENT_USER_JOIN"
"hub_event_dispatcher()" -> "EVENT_USER_QUIT"
"EVENT_USER_QUIT" -> "route_to_all()"
"EVENT_USER_QUIT" -> "user_destroy()"
"EVENT_USER_JOIN" -> "route_to_all()"
/* user_disconnect() -- critical part */
"user_disconnect()" -> "user_set_state(state_cleanup)" -> "post: EVENT_USER_QUIT"
"user_disconnect()" -> "user_destroy()"
}
-51
View File
@@ -1,51 +0,0 @@
# uHub access control lists.
#
# Syntax: <command> [data]
#
# commands:
# 'user_reg' - registered user with no particular privileges (data=nick:password)
# 'user_op' - operator, can kick or ban people (data=nick:password)
# 'user_admin' - administrator, can do everything operators can, and reconfigure the hub (data=nick:password)
# 'deny_nick' - nick name that is not accepted (example; Administrator)
# 'deny_ip' - Unacceptable IP (masks can be specified as CIDR: 0.0.0.0/32 will block all IPv4)
# 'ban_nick' - banned user by nick
# 'ban_cid' - banned user by cid
# Administrator
# user_admin userA:password1
# user_op userB:password2
# We don't want users with these names
deny_nick Hub-Security
deny_nick Administrator
deny_nick root
deny_nick admin
deny_nick username
deny_nick user
deny_nick guest
deny_nick operator
# Banned users
# ban_nick H4X0R
# ban_cid FOIL5EK2UDZYAXT7UIUFEKL4SEBEAJE3INJDKAY
# ban by ip
#
# to ban by CIDR
# deny_ip 10.21.44.0/24
#
# to ban by IP-range.
# deny_ip 10.21.44.7-10.21.44.9
#
# to ban a single IP address
# deny_ip 10.21.44.7
# (which is equivalent to using):
# deny_ip 10.21.44.7/32
# Will not work, yet
# nat_ip 10.0.0.0/8
# nat_ip 127.0.0.0/8
# If you have made changes to this file, you must send a HANGUP signal
# to uHub so that it will re-read the configuration files.
# For example by invoking: 'killall -HUP uhub'
+63
View File
@@ -0,0 +1,63 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<title>uhub by janvidar</title>
<link rel="stylesheet" href="stylesheets/styles.css">
<link rel="stylesheet" href="stylesheets/pygment_trac.css">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
<div class="wrapper">
<header>
<h1>uhub</h1>
<p>A high performance ADC peer to peer message hub.</p>
<p class="view"><a href="https://github.com/janvidar/uhub">View the Project on GitHub <small>janvidar/uhub</small></a></p>
<ul>
<li><a href="https://github.com/janvidar/uhub/zipball/master">Download <strong>ZIP File</strong></a></li>
<li><a href="https://github.com/janvidar/uhub/tarball/master">Download <strong>TAR Ball</strong></a></li>
<li><a href="https://github.com/janvidar/uhub">Fork On <strong>GitHub</strong></a></li>
</ul>
</header>
<section>
<h3>Welcome to GitHub Pages.</h3>
<p>This automatic page generator is the easiest way to create beautiful pages for all of your projects. Author your page content here using GitHub Flavored Markdown, select a template crafted by a designer, and publish. After your page is generated, you can check out the new branch:</p>
<pre><code>$ cd your_repo_root/repo_name
$ git fetch origin
$ git checkout gh-pages
</code></pre>
<p>If you're using the GitHub for Mac, simply sync your repository and you'll see the new branch.</p>
<h3>Designer Templates</h3>
<p>We've crafted some handsome templates for you to use. Go ahead and continue to layouts to browse through them. You can easily go back to edit your page before publishing. After publishing your page, you can revisit the page generator and switch to another theme. Your Page content will be preserved if it remained markdown format.</p>
<h3>Rather Drive Stick?</h3>
<p>If you prefer to not use the automatic generator, push a branch named <code>gh-pages</code> to your repository to create a page manually. In addition to supporting regular HTML content, GitHub Pages support Jekyll, a simple, blog aware static site generator written by our own Tom Preston-Werner. Jekyll makes it easy to create site-wide headers and footers without having to copy them across every page. It also offers intelligent blog support and other advanced templating features.</p>
<h3>Authors and Contributors</h3>
<p>You can <a href="https://github.com/blog/821" class="user-mention">@mention</a> a GitHub username to generate a link to their profile. The resulting <code>&lt;a&gt;</code> element will link to the contributor's GitHub Profile. For example: In 2007, Chris Wanstrath (<a href="https://github.com/defunkt" class="user-mention">@defunkt</a>), PJ Hyett (<a href="https://github.com/pjhyett" class="user-mention">@pjhyett</a>), and Tom Preston-Werner (<a href="https://github.com/mojombo" class="user-mention">@mojombo</a>) founded GitHub.</p>
<h3>Support or Contact</h3>
<p>Having trouble with Pages? Check out the documentation at <a href="http://help.github.com/pages">http://help.github.com/pages</a> or contact <a href="mailto:support@github.com">support@github.com</a> and we’ll help you sort it out.</p>
</section>
<footer>
<p>This project is maintained by <a href="https://github.com/janvidar">janvidar</a></p>
<p><small>Hosted on GitHub Pages &mdash; Theme by <a href="https://github.com/orderedlist">orderedlist</a></small></p>
</footer>
</div>
<script src="javascripts/scale.fix.js"></script>
</body>
</html>
+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";
}
}
}
+1
View File
@@ -0,0 +1 @@
{"name":"uhub","body":"### Welcome to GitHub Pages.\r\nThis automatic page generator is the easiest way to create beautiful pages for all of your projects. Author your page content here using GitHub Flavored Markdown, select a template crafted by a designer, and publish. After your page is generated, you can check out the new branch:\r\n\r\n```\r\n$ cd your_repo_root/repo_name\r\n$ git fetch origin\r\n$ git checkout gh-pages\r\n```\r\n\r\nIf you're using the GitHub for Mac, simply sync your repository and you'll see the new branch.\r\n\r\n### Designer Templates\r\nWe've crafted some handsome templates for you to use. Go ahead and continue to layouts to browse through them. You can easily go back to edit your page before publishing. After publishing your page, you can revisit the page generator and switch to another theme. Your Page content will be preserved if it remained markdown format.\r\n\r\n### Rather Drive Stick?\r\nIf you prefer to not use the automatic generator, push a branch named `gh-pages` to your repository to create a page manually. In addition to supporting regular HTML content, GitHub Pages support Jekyll, a simple, blog aware static site generator written by our own Tom Preston-Werner. Jekyll makes it easy to create site-wide headers and footers without having to copy them across every page. It also offers intelligent blog support and other advanced templating features.\r\n\r\n### Authors and Contributors\r\nYou can @mention a GitHub username to generate a link to their profile. The resulting `<a>` element will link to the contributor's GitHub Profile. For example: In 2007, Chris Wanstrath (@defunkt), PJ Hyett (@pjhyett), and Tom Preston-Werner (@mojombo) founded GitHub.\r\n\r\n### Support or Contact\r\nHaving trouble with Pages? Check out the documentation at http://help.github.com/pages or contact support@github.com and we’ll help you sort it out.","tagline":"A high performance ADC peer to peer message hub.","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."}
-142
View File
@@ -1,142 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_ADC_CONSTANTS_H
#define HAVE_UHUB_ADC_CONSTANTS_H
typedef uint32_t sid_t;
typedef uint32_t fourcc_t;
/* Internal uhub limit */
#define MAX_ADC_CMD_LEN 4096
#define FOURCC(a,b,c,d) (fourcc_t) ((a << 24) | (b << 16) | (c << 8) | d)
/* default welcome protocol support message, as sent by this server */
#define ADC_PROTO_SUPPORT "ADBASE ADTIGR ADPING"
/* Server sent commands */
#define ADC_CMD_ISID FOURCC('I','S','I','D')
#define ADC_CMD_ISUP FOURCC('I','S','U','P')
#define ADC_CMD_IGPA FOURCC('I','G','P','A')
#define ADC_CMD_ISTA FOURCC('I','S','T','A')
#define ADC_CMD_IINF FOURCC('I','I','N','F')
#define ADC_CMD_IMSG FOURCC('I','M','S','G')
#define ADC_CMD_IQUI FOURCC('I','Q','U','I')
/* Handshake and login/passwordstuff */
#define ADC_CMD_HSUP FOURCC('H','S','U','P')
#define ADC_CMD_HPAS FOURCC('H','P','A','S')
#define ADC_CMD_HINF FOURCC('H','I','N','F')
#define ADC_CMD_BINF FOURCC('B','I','N','F')
/* This is a Admin extension */
#define ADC_CMD_HDSC FOURCC('H','D','S','C')
/* Status/error messages */
#define ADC_CMD_HSTA FOURCC('H','S','T','A')
#define ADC_CMD_DSTA FOURCC('D','S','T','A')
/* searches */
#define ADC_CMD_BSCH FOURCC('B','S','C','H')
#define ADC_CMD_DSCH FOURCC('D','S','C','H')
#define ADC_CMD_ESCH FOURCC('E','S','C','H')
#define ADC_CMD_FSCH FOURCC('F','S','C','H')
#define ADC_CMD_DRES FOURCC('D','R','E','S')
/* connection setup */
#define ADC_CMD_DCTM FOURCC('D','C','T','M')
#define ADC_CMD_DRCM FOURCC('D','R','C','M')
#define ADC_CMD_ECTM FOURCC('E','C','T','M')
#define ADC_CMD_ERCM FOURCC('E','R','C','M')
/* chat messages */
#define ADC_CMD_BMSG FOURCC('B','M','S','G')
#define ADC_CMD_DMSG FOURCC('D','M','S','G')
#define ADC_CMD_EMSG FOURCC('E','M','S','G')
#define ADC_CMD_FMSG FOURCC('F','M','S','G')
/* disallowed messages */
#define ADC_CMD_DINF FOURCC('D','I','N','F')
#define ADC_CMD_EINF FOURCC('E','I','N','F')
#define ADC_CMD_FINF FOURCC('F','I','N','F')
/* Extension messages */
#define ADC_CMD_HCHK FOURCC('H','C','H','K')
#define ADC_INF_FLAG_IPV4_ADDR "I4" /* ipv4 address */
#define ADC_INF_FLAG_IPV6_ADDR "I6" /* ipv6 address */
#define ADC_INF_FLAG_IPV4_UDP_PORT "U4" /* port number */
#define ADC_INF_FLAG_IPV6_UDP_PORT "U6" /* port number */
#define ADC_INF_FLAG_CLIENT_TYPE "CT" /* client type */
#define ADC_INF_FLAG_PRIVATE_ID "PD" /* private id, aka PID */
#define ADC_INF_FLAG_CLIENT_ID "ID" /* client id, aka CID */
#define ADC_INF_FLAG_NICK "NI" /* nick name */
#define ADC_INF_FLAG_DESCRIPTION "DE" /* user description */
#define ADC_INF_FLAG_USER_AGENT "VE" /* software version */
#define ADC_INF_FLAG_SUPPORT "SU" /* support (extensions, feature cast) */
#define ADC_INF_FLAG_SHARED_SIZE "SS" /* size of total files shared in bytes */
#define ADC_INF_FLAG_SHARED_FILES "SF" /* number of files shared */
#define ADC_INF_FLAG_UPLOAD_SPEED "US" /* maximum upload speed acheived in bytes/sec */
#define ADC_INF_FLAG_DOWNLOAD_SPEED "DS" /* maximum download speed acheived in bytes/sec */
#define ADC_INF_FLAG_UPLOAD_SLOTS "SL" /* maximum upload slots (concurrent uploads) */
#define ADC_INF_FLAG_AUTO_SLOTS "AS" /* automatic slot if upload speed is less than this in bytes/sec */
#define ADC_INF_FLAG_AUTO_SLOTS_MAX "AM" /* maximum number of automatic slots */
#define ADC_INF_FLAG_COUNT_HUB_NORMAL "HN" /* user is logged into this amount of hubs as a normal user (guest) */
#define ADC_INF_FLAG_COUNT_HUB_REGISTER "HR" /* user is logged into this amount of hubs as a registered user (password) */
#define ADC_INF_FLAG_COUNT_HUB_OPERATOR "HO" /* user is logged into this amount of hubs as an operator */
#define ADC_INF_FLAG_AWAY "AW" /* away flag, 1=away, 2=extended away */
#define ADC_INF_FLAG_REFERER "RF" /* URL to referer in case of hub redirect */
#define ADC_INF_FLAG_EMAIL "EM" /* E-mail address */
#define ADC_MSG_FLAG_ACTION "ME" /* message is an *action* message */
#define ADC_MSG_FLAG_PRIVATE "PM" /* message is a private message */
#define ADC_SCH_FLAG_INCLUDE "AN" /* include given search term */
#define ADC_SCH_FLAG_EXCLUDE "NO" /* exclude given serach term */
#define ADC_SCH_FLAG_FILE_EXTENSION "EX" /* search only for files with the given file extension */
#define ADC_SCH_FLAG_FILE_TYPE "TY" /* search only for files with this file type (separate type) */
#define ADC_SCH_FLAG_LESS_THAN "LE" /* search for files with this size or less */
#define ADC_SCH_FLAG_GREATER_THAN "GE" /* search for files with this size or greater */
#define ADC_SCH_FLAG_EQUAL "EQ" /* search only for files with this exact size */
#define ADC_SCH_FLAG_TOKEN "TO" /* use this token for search replies */
#define ADC_RES_FLAG_FILE_NAME "FN" /* file name */
#define ADC_RES_FLAG_FILE_SIZE "SI" /* file size */
#define ADC_RES_FLAG_UPLOAD_SLOTS "SL" /* number of upload slots available (if > 0, download is possible) */
#define ADC_RES_FLAG_TOKEN "TO" /* token, same as the token in the search request */
#define ADC_QUI_FLAG_TIME_LEFT "TL" /* time in seconds before reconnect is allowed, or -1 forever */
#define ADC_QUI_FLAG_MESSAGE "MS" /* kick/leave message */
#define ADC_QUI_FLAG_DISCONNECT "DI" /* all further transfers with this user should be disconnected */
#define ADC_QUI_FLAG_REDIRECT "RD" /* redirect to URL */
#define ADC_QUI_FLAG_KICK_OPERATOR "ID" /* SID of operator who disconnected the user */
#define ADC_SUP_FLAG_ADD "AD"
#define ADC_SUP_FLAG_REMOVE "RM"
#define ADC_CLIENT_TYPE_BOT "1"
#define ADC_CLIENT_TYPE_REGISTERED_USER "2"
#define ADC_CLIENT_TYPE_OPERATOR "4"
#define ADC_CLIENT_TYPE_SUPER_USER "12" /* 8 + 4 */
#define ADC_CLIENT_TYPE_ADMIN "20" /* 16 + 4 = hub owner */
#define ADC_CLIENT_TYPE_HUB "32" /* the hub itself */
#endif /* HAVE_UHUB_ADC_CONSTANTS_H */
-952
View File
@@ -1,952 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#include "uhub.h"
#ifdef DEBUG
#define ADC_MSG_ASSERT(X) \
uhub_assert(X); \
uhub_assert(X->cache); \
uhub_assert(X->capacity); \
uhub_assert(X->length); \
uhub_assert(X->length <= X->capacity); \
uhub_assert(X->length == strlen(X->cache));
#else
#define ADC_MSG_ASSERT(X) do { } while(0)
#endif /* DEBUG */
#ifdef MSG_MEMORY_DEBUG
#undef msg_malloc
#undef msg_malloc_zero
#undef msg_free
static void* msg_malloc(size_t size)
{
void* ptr = valloc(size);
LOG_MEMORY("msg_malloc: %p %d", ptr, (int) size);
return ptr;
}
static void* msg_malloc_zero(size_t size)
{
void* ptr = msg_malloc(size);
memset(ptr, 0, size);
return ptr;
}
static void msg_free(void* ptr)
{
LOG_MEMORY("msg_free: %p", ptr);
// hub_free(ptr);
}
#include <sys/mman.h>
static void adc_msg_protect(struct adc_message* cmd)
{
LOG_MEMORY("msg_prot: %p %d", cmd, cmd->capacity);
mprotect(cmd, sizeof(cmd), PROT_READ);
mprotect(cmd->cache, sizeof(cmd->capacity), PROT_READ);
}
static void adc_msg_unprotect(struct adc_message* cmd)
{
LOG_MEMORY("msg_unprot: %p %d", cmd, cmd->capacity);
mprotect(cmd, sizeof(cmd), PROT_READ | PROT_WRITE);
mprotect(cmd->cache, sizeof(cmd->capacity), PROT_READ | PROT_WRITE);
}
#else
#define msg_malloc(X) hub_malloc(X)
#define msg_malloc_zero(X) hub_malloc_zero(X)
#define msg_free(X) hub_free(X)
#endif /* MSG_MEMORY_DEBUG */
struct adc_message* adc_msg_incref(struct adc_message* msg)
{
if (!msg) return 0;
#ifndef ADC_MESSAGE_INCREF
#ifdef MSG_MEMORY_DEBUG
adc_msg_unprotect(msg);
#endif
msg->references++;
#ifdef MSG_MEMORY_DEBUG
adc_msg_protect(msg);
#endif
return msg;
#else
struct adc_message* copy = adc_msg_copy(msg);
return copy;
#endif
}
static void adc_msg_set_length(struct adc_message* msg, size_t len)
{
msg->length = len;
}
static int adc_msg_grow(struct adc_message* msg, size_t size)
{
char* buf;
size_t newsize = 0;
if (msg->capacity > size)
return 1;
/* Make sure we align our data */
newsize = size;
newsize += 2; /* termination */
newsize += (newsize % sizeof(size_t)); /* alignment padding */
buf = msg_malloc_zero(newsize);
if (!buf)
return 0;
if (msg->cache)
{
memcpy(buf, msg->cache, msg->length);
msg_free(msg->cache);
}
msg->cache = buf;
msg->capacity = newsize;
return 1;
}
/* NOTE: msg must be unterminated here */
static int adc_msg_cache_append(struct adc_message* msg, const char* string, size_t len)
{
if (!adc_msg_grow(msg, msg->length + len))
{
/* FIXME: OOM! */
return 0;
}
memcpy(&msg->cache[msg->length], string, len);
adc_msg_set_length(msg, msg->length + len);
assert(msg->capacity > msg->length);
msg->cache[msg->length] = 0;
return 1;
}
/**
* Returns position of the first argument of the message.
* Excludes mandatory arguments for the given type of message
* like source and target.
*/
int adc_msg_get_arg_offset(struct adc_message* msg)
{
if (!msg || !msg->cache)
return -1;
switch (msg->cache[0])
{
/* These *SHOULD* never be seen on a hub */
case 'U':
case 'C':
return 4; /* Actually: 4 + strlen(cid). */
case 'I':
case 'H':
return 4;
case 'B':
return 9;
case 'F':
return (10 + (list_size(msg->feature_cast_include)*5) + (list_size(msg->feature_cast_exclude)*5));
case 'D':
case 'E':
return 14;
}
return -1;
}
int adc_msg_is_empty(struct adc_message* msg)
{
int offset = adc_msg_get_arg_offset(msg);
if (offset == -1)
return -1;
if ((msg->length - 1) == (size_t) offset)
return 1;
return 0;
}
void adc_msg_free(struct adc_message* msg)
{
if (!msg) return;
ADC_MSG_ASSERT(msg);
if (msg->references > 0)
{
#ifdef MSG_MEMORY_DEBUG
adc_msg_unprotect(msg);
#endif
msg->references--;
#ifdef MSG_MEMORY_DEBUG
adc_msg_protect(msg);
#endif
}
else
{
#ifdef MSG_MEMORY_DEBUG
adc_msg_unprotect(msg);
#endif
msg_free(msg->cache);
if (msg->feature_cast_include)
{
list_clear(msg->feature_cast_include, &hub_free);
list_destroy(msg->feature_cast_include);
msg->feature_cast_include = 0;
}
if (msg->feature_cast_exclude)
{
list_clear(msg->feature_cast_exclude, &hub_free);
list_destroy(msg->feature_cast_exclude);
msg->feature_cast_exclude = 0;
}
msg_free(msg);
}
}
struct adc_message* adc_msg_copy(const struct adc_message* cmd)
{
char* tmp = 0;
struct adc_message* copy = (struct adc_message*) msg_malloc_zero(sizeof(struct adc_message));
if (!copy) return NULL; /* OOM */
ADC_MSG_ASSERT(cmd);
/* deep copy */
copy->cmd = cmd->cmd;
copy->source = cmd->source;
copy->target = cmd->target;
copy->cache = 0;
copy->length = cmd->length;
copy->capacity = 0;
copy->priority = cmd->priority;
copy->references = 0;
copy->feature_cast_include = 0;
copy->feature_cast_exclude = 0;
if (cmd->cache)
{
if (!adc_msg_grow(copy, copy->length))
{
adc_msg_free(copy);
return NULL; /* OOM */
}
memcpy(copy->cache, cmd->cache, cmd->length);
copy->cache[copy->length] = 0;
}
if (cmd->feature_cast_include)
{
copy->feature_cast_include = list_create();
tmp = list_get_first(cmd->feature_cast_include);
while (tmp)
{
list_append(copy->feature_cast_include, hub_strdup(tmp));
tmp = list_get_next(cmd->feature_cast_include);
}
}
if (cmd->feature_cast_exclude)
{
copy->feature_cast_exclude = list_create();
tmp = list_get_first(cmd->feature_cast_exclude);
while (tmp)
{
list_append(copy->feature_cast_exclude, hub_strdup(tmp));
tmp = list_get_next(cmd->feature_cast_exclude);
}
}
ADC_MSG_ASSERT(copy);
#ifdef MSG_MEMORY_DEBUG
adc_msg_protect(copy);
#endif
return copy;
}
struct adc_message* adc_msg_parse_verify(struct hub_user* u, const char* line, size_t length)
{
struct adc_message* command = adc_msg_parse(line, length);
if (!command)
return 0;
if (command->source && (!u || command->source != u->id.sid))
{
LOG_DEBUG("Command does not match user's SID (command->source=%d, user->id.sid=%d)", command->source, (u ? u->id.sid : 0));
adc_msg_free(command);
return 0;
}
return command;
}
struct adc_message* adc_msg_parse(const char* line, size_t length)
{
struct adc_message* command = (struct adc_message*) msg_malloc_zero(sizeof(struct adc_message));
char prefix = line[0];
size_t n = 0;
char temp_sid[5];
int ok = 1;
int need_terminate = 0;
struct linked_list* feature_cast_list;
if (command == NULL)
return NULL; /* OOM */
if (!is_printable_utf8(line, length))
{
LOG_DEBUG("Dropped message with non-printable UTF-8 characters.");
msg_free(command);
return NULL;
}
if (line[length-1] != '\n')
{
need_terminate = 1;
}
if (!adc_msg_grow(command, length + need_terminate))
{
msg_free(command);
return NULL; /* OOM */
}
adc_msg_set_length(command, length + need_terminate);
memcpy(command->cache, line, length);
/* Ensure we are zero terminated */
command->cache[length] = 0;
command->cache[length+need_terminate] = 0;
command->cmd = FOURCC(line[0], line[1], line[2], line[3]);
command->priority = 0;
switch (prefix)
{
case 'U':
case 'C':
/* these should never be seen on a hub */
ok = 0;
break;
case 'I':
case 'H':
ok = (length > 3);
break;
case 'B':
ok = (length > 8 &&
is_space(line[4]) &&
is_valid_base32_char(line[5]) &&
is_valid_base32_char(line[6]) &&
is_valid_base32_char(line[7]) &&
is_valid_base32_char(line[8]));
if (!ok) break;
temp_sid[0] = line[5];
temp_sid[1] = line[6];
temp_sid[2] = line[7];
temp_sid[3] = line[8];
temp_sid[4] = '\0';
command->source = string_to_sid(temp_sid);
break;
case 'F':
ok = (length > 8 &&
is_space(line[4]) &&
is_valid_base32_char(line[5]) &&
is_valid_base32_char(line[6]) &&
is_valid_base32_char(line[7]) &&
is_valid_base32_char(line[8]));
if (!ok) break;
temp_sid[0] = line[5];
temp_sid[1] = line[6];
temp_sid[2] = line[7];
temp_sid[3] = line[8];
temp_sid[4] = '\0';
command->source = string_to_sid(temp_sid);
/* Create feature cast lists */
command->feature_cast_include = list_create();
command->feature_cast_exclude = list_create();
if (!command->feature_cast_include || !command->feature_cast_exclude)
{
list_destroy(command->feature_cast_include);
list_destroy(command->feature_cast_exclude);
msg_free(command->cache);
msg_free(command);
return NULL; /* OOM */
}
n = 10;
while (line[n] == '+' || line[n] == '-')
{
if (line[n++] == '+')
feature_cast_list = command->feature_cast_include;
else
feature_cast_list = command->feature_cast_exclude;
temp_sid[0] = line[n++];
temp_sid[1] = line[n++];
temp_sid[2] = line[n++];
temp_sid[3] = line[n++];
temp_sid[4] = '\0';
list_append(feature_cast_list, hub_strdup(temp_sid));
}
if (n == 10)
ok = 0;
break;
case 'D':
case 'E':
ok = (length > 13 &&
is_space(line[4]) &&
is_valid_base32_char(line[5]) &&
is_valid_base32_char(line[6]) &&
is_valid_base32_char(line[7]) &&
is_valid_base32_char(line[8]) &&
is_space(line[9]) &&
is_valid_base32_char(line[10]) &&
is_valid_base32_char(line[11]) &&
is_valid_base32_char(line[12]) &&
is_valid_base32_char(line[13]));
if (!ok) break;
temp_sid[0] = line[5];
temp_sid[1] = line[6];
temp_sid[2] = line[7];
temp_sid[3] = line[8];
temp_sid[4] = '\0';
command->source = string_to_sid(temp_sid);
temp_sid[0] = line[10];
temp_sid[1] = line[11];
temp_sid[2] = line[12];
temp_sid[3] = line[13];
temp_sid[4] = '\0';
command->target = string_to_sid(temp_sid);
break;
default:
ok = 0;
}
if (need_terminate)
{
command->cache[length] = '\n';
}
if (!ok)
{
adc_msg_free(command);
return NULL;
}
/* At this point the arg_offset should point to a space, or the end of message */
n = adc_msg_get_arg_offset(command);
if (command->cache[n] == ' ')
{
if (command->cache[n+1] == ' ') ok = 0;
}
else if (command->cache[n] == '\n') ok = 1;
else ok = 0;
if (!ok)
{
adc_msg_free(command);
return NULL;
}
ADC_MSG_ASSERT(command);
#ifdef MSG_MEMORY_DEBUG
adc_msg_protect(command);
#endif
return command;
}
struct adc_message* adc_msg_create(const char* line)
{
return adc_msg_parse(line, strlen(line));
}
struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
{
struct adc_message* msg = (struct adc_message*) msg_malloc_zero(sizeof(struct adc_message));
if (!msg)
return NULL; /* OOM */
if (size < sizeof(fourcc)) size = sizeof(fourcc);
if (!adc_msg_grow(msg, size+1))
{
msg_free(msg);
return NULL; /* OOM */
}
if (fourcc)
{
msg->cache[0] = (char) ((fourcc >> 24) & 0xff);
msg->cache[1] = (char) ((fourcc >> 16) & 0xff);
msg->cache[2] = (char) ((fourcc >> 8) & 0xff);
msg->cache[3] = (char) ((fourcc ) & 0xff);
msg->cache[4] = '\n';
/* Ensure we are zero terminated */
adc_msg_set_length(msg, 5);
msg->cache[msg->length] = 0;
}
msg->cmd = fourcc;
msg->priority = 0;
#ifdef MSG_MEMORY_DEBUG
adc_msg_protect(msg);
#endif
return msg;
}
int adc_msg_remove_named_argument(struct adc_message* cmd, const char prefix_[2])
{
char* start;
char* end;
char* endInfo;
size_t endlen;
char prefix[4] = { ' ', prefix_[0], prefix_[1], '\0' };
int found = 0;
int arg_offset = adc_msg_get_arg_offset(cmd);
size_t temp_len = 0;
adc_msg_unterminate(cmd);
start = memmem(&cmd->cache[arg_offset], (cmd->length - arg_offset), prefix, 3);
while (start)
{
endInfo = &cmd->cache[cmd->length];
if (&start[0] < &endInfo[0])
{
end = memchr(&start[1], ' ', &endInfo[0]-&start[1]);
}
else
{
end = NULL;
}
if (end)
{
temp_len = &end[0] - &start[0]; // strlen(start);
endlen = strlen(end);
memmove(start, end, endlen);
start[endlen] = '\0';
found++;
adc_msg_set_length(cmd, cmd->length - temp_len);
}
else
{
found++;
adc_msg_set_length(cmd, cmd->length - strlen(start));
start[0] = '\0';
break;
}
start = memmem(&cmd->cache[arg_offset], (cmd->length - arg_offset), prefix, 3);
}
adc_msg_terminate(cmd);
return found;
}
int adc_msg_has_named_argument(struct adc_message* cmd, const char prefix_[2])
{
int count = 0;
char* start;
char prefix[4] = { ' ', prefix_[0], prefix_[1], '\0' };
int arg_offset = adc_msg_get_arg_offset(cmd);
ADC_MSG_ASSERT(cmd);
start = memmem(&cmd->cache[arg_offset], (cmd->length - arg_offset), prefix, 3);
while (start)
{
count++;
if ((&start[0] - &cmd->cache[0]) < 1+cmd->length)
start = memmem(&start[1], (&cmd->cache[cmd->length] - &start[0]), prefix, 3);
else
start = NULL;
}
return count;
}
char* adc_msg_get_named_argument(struct adc_message* cmd, const char prefix_[2])
{
char* start;
char* end;
char* argument;
size_t length;
char prefix[4] = { ' ', prefix_[0], prefix_[1], '\0' };
int arg_offset = adc_msg_get_arg_offset(cmd);
ADC_MSG_ASSERT(cmd);
start = memmem(&cmd->cache[arg_offset], cmd->length - arg_offset, prefix, 3);
if (!start)
return NULL;
start = &start[3];
end = strchr(start, ' ');
if (!end) end = &cmd->cache[cmd->length];
length = &end[0] - &start[0];
argument = hub_strndup(start, length);
if (length > 0 && argument[length-1] == '\n')
{
argument[length-1] = 0;
}
return argument;
}
int adc_msg_replace_named_argument(struct adc_message* cmd, const char prefix[2], const char* string)
{
ADC_MSG_ASSERT(cmd);
while (adc_msg_has_named_argument(cmd, prefix))
{
adc_msg_remove_named_argument(cmd, prefix);
}
if (adc_msg_add_named_argument(cmd, prefix, string) == -1)
{
return -1;
}
ADC_MSG_ASSERT(cmd);
return 0;
}
void adc_msg_terminate(struct adc_message* cmd)
{
if (cmd->cache[cmd->length - 1] != '\n')
{
adc_msg_cache_append(cmd, "\n", 1);
}
ADC_MSG_ASSERT(cmd);
#ifdef MSG_MEMORY_DEBUG
adc_msg_protect(cmd);
#endif
}
/* FIXME: this looks bogus */
void adc_msg_unterminate(struct adc_message* cmd)
{
ADC_MSG_ASSERT(cmd);
#ifdef MSG_MEMORY_DEBUG
adc_msg_unprotect(cmd);
#endif
if (cmd->length > 0 && cmd->cache[cmd->length-1] == '\n')
{
cmd->length--;
cmd->cache[cmd->length] = 0;
}
}
int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix[2], const char* string)
{
int ret = 0;
if (!string)
return -1;
ADC_MSG_ASSERT(cmd);
adc_msg_unterminate(cmd);
adc_msg_cache_append(cmd, " ", 1);
adc_msg_cache_append(cmd, prefix, 2);
adc_msg_cache_append(cmd, string, strlen(string));
adc_msg_terminate(cmd);
return ret;
}
int adc_msg_add_named_argument_string(struct adc_message* cmd, const char prefix[2], const char* string)
{
char* escaped = adc_msg_escape(string);
int ret = adc_msg_add_named_argument(cmd, prefix, escaped);
hub_free(escaped);
return ret;
}
int adc_msg_add_named_argument_int(struct adc_message* cmd, const char prefix[2], int num)
{
const char* s = uhub_itoa(num);
int ret = adc_msg_add_named_argument(cmd, prefix, s);
return ret;
}
int adc_msg_add_named_argument_uint64(struct adc_message* cmd, const char prefix[2], uint64_t num)
{
const char* s = uhub_ulltoa(num);
int ret = adc_msg_add_named_argument(cmd, prefix, s);
return ret;
}
int adc_msg_add_argument(struct adc_message* cmd, const char* string)
{
ADC_MSG_ASSERT(cmd);
adc_msg_unterminate(cmd);
adc_msg_cache_append(cmd, " ", 1);
adc_msg_cache_append(cmd, string, strlen(string));
adc_msg_terminate(cmd);
return 0;
}
char* adc_msg_get_argument(struct adc_message* cmd, int offset)
{
char* start;
char* end;
char* argument;
int count = 0;
ADC_MSG_ASSERT(cmd);
adc_msg_unterminate(cmd);
start = strchr(&cmd->cache[adc_msg_get_arg_offset(cmd)-1], ' ');
while (start)
{
end = strchr(&start[1], ' ');
if (count == offset)
{
if (end)
{
argument = hub_strndup(&start[1], (&end[0] - &start[1]));
}
else
{
argument = hub_strdup(&start[1]);
if (argument && argument[strlen(argument)-1] == '\n')
argument[strlen(argument)-1] = 0;
}
if (!argument)
return 0; // FIXME: OOM
if (*argument)
{
adc_msg_terminate(cmd);
return argument;
}
else
{
hub_free(argument);
}
}
count++;
start = end;
}
adc_msg_terminate(cmd);
return 0;
}
/**
* NOTE: Untested code.
*/
int adc_msg_get_argument_index(struct adc_message* cmd, const char prefix[2])
{
char* start;
char* end;
int count = 0;
ADC_MSG_ASSERT(cmd);
adc_msg_unterminate(cmd);
start = strchr(&cmd->cache[adc_msg_get_arg_offset(cmd)-1], ' ');
while (start)
{
end = strchr(&start[1], ' ');
if (((&end[0] - &start[1]) > 2) && ((start[1] == prefix[0]) && (start[2] == prefix[1])))
{
adc_msg_terminate(cmd);
return count;
}
count++;
start = end;
}
adc_msg_terminate(cmd);
return -1;
}
int adc_msg_escape_length(const char* str)
{
int add = 0;
int n = 0;
for (; str[n]; n++)
if (str[n] == ' ' || str[n] == '\n' || str[n] == '\\') add++;
return n + add;
}
int adc_msg_unescape_length(const char* str)
{
int add = 0;
int n = 0;
int escape = 0;
for (; str[n]; n++)
{
if (escape)
{
escape = 0;
}
else
{
if (str[n] == '\\')
{
escape = 1;
add++;
}
}
}
return n - add;
}
char* adc_msg_unescape(const char* string)
{
char* new_string = msg_malloc(adc_msg_unescape_length(string)+1);
char* ptr = (char*) new_string;
char* str = (char*) string;
int escaped = 0;
while (*str)
{
if (escaped) {
if (*str == 's')
*ptr++ = ' ';
else if (*str == '\\')
*ptr++ = '\\';
else if (*str == 'n')
*ptr++ = '\n';
else
*ptr++ = *str;
escaped = 0;
} else {
if (*str == '\\')
escaped = 1;
else
*ptr++ = *str;
}
str++;
}
*ptr = 0;
return new_string;
}
char* adc_msg_escape(const char* string)
{
char* str = hub_malloc(adc_msg_escape_length(string)+1);
int n = 0;
int i = 0;
for (i = 0; i < strlen(string); i++)
{
switch (string[i]) {
case '\\': /* fall through */
str[n++] = '\\';
str[n++] = '\\';
break;
case '\n':
str[n++] = '\\';
str[n++] = 'n';
break;
case ' ':
str[n++] = '\\';
str[n++] = 's';
break;
default:
str[n++] = string[i];
break;
}
}
str[n] = '\0';
return str;
}
-222
View File
@@ -1,222 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_COMMAND_H
#define HAVE_UHUB_COMMAND_H
struct hub_user;
struct adc_message
{
fourcc_t cmd;
sid_t source;
sid_t target;
char* cache;
size_t length;
size_t capacity;
size_t priority;
size_t references;
struct linked_list* feature_cast_include;
struct linked_list* feature_cast_exclude;
};
enum msg_status_level
{
status_level_info = 0, /* Success/informative status message */
status_level_error = 1, /* Recoverable error */
status_level_fatal = 2, /* Fatal error (disconnect) */
};
/**
* Increase the reference counter for an ADC message struct.
* NOTE: Always use the returned value, and not the passed value, as
* it ensures we can actually copy the value if needed.
*/
extern struct adc_message* adc_msg_incref(struct adc_message* msg);
/**
* Decrease the reference counter, and free the memory when apropriate.
*/
extern void adc_msg_free(struct adc_message* msg);
/**
* Perform deep copy a command.
* NOTE: 'references' will be zero for the copied command.
* @return a copy of cmd or NULL if not able to allocate memory.
*/
extern struct adc_message* adc_msg_copy(const struct adc_message* cmd);
/**
* This will parse 'string' and return it as a adc_message struct, or
* NULL if not able to allocate memory or 'string' does not contain
* a valid ADC command.
*
* The message is only considered valid if the user who sent it
* is the rightful origin of the message.
*/
extern struct adc_message* adc_msg_parse_verify(struct hub_user* u, const char* string, size_t length);
/**
* This will parse 'string' and return it as a adc_message struct, or
* NULL if not able to allocate memory or 'string' does not contain
* a valid ADC command.
*/
extern struct adc_message* adc_msg_parse(const char* string, size_t length);
/**
* This will construct a adc_message based on 'string'.
* Only to be used for server generated commands.
*/
extern struct adc_message* adc_msg_create(const char* string);
/**
* Construct a message with the given 'fourcc' and allocate
* 'size' bytes for later use.
*/
extern struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size);
/**
* Remove a named argument from the command.
*
* @arg prefix a 2 character argument prefix
* @return the number of named arguments removed.
*/
extern int adc_msg_remove_named_argument(struct adc_message* cmd, const char prefix[2]);
/**
* Count the number of arguments matching the given 2 character prefix.
*
* @arg prefix a 2 character argument prefix
* @return the number of matching arguments
*/
extern int adc_msg_has_named_argument(struct adc_message* cmd, const char prefix[2]);
/**
* Returns a named arguments based on the 2 character prefix.
* If multiple matching arguments exists, only the first one will be returned
* by this function.
*
* NOTE: Returned memory must be free'd with hub_free().
*
* @arg prefix a 2 character argument prefix
* @return the argument or NULL if OOM/not found.
*/
extern char* adc_msg_get_named_argument(struct adc_message* cmd, const char prefix[2]);
/**
* Returns a offset of an argument based on the 2 character prefix.
* If multiple matching arguments exists, only the first one will be returned
* by this function.
*
* @arg prefix a 2 character argument prefix
* @return the offset or -1 if the argument is not found.
*/
extern int adc_msg_get_named_argument_index(struct adc_message* cmd, const char prefix[2]);
/**
* @param cmd command to be checked
* @return 1 if the command does not have any arguments (parameters), 0 otherwise, -1 if cmd is invalid.
*/
extern int adc_msg_is_empty(struct adc_message* cmd);
/**
* Returns the argument on the offset position in the command.
* If offset is invalid NULL is returned.
*
* NOTE: Returned memory must be free'd with hub_free().
*
* @return the argument or NULL if OOM/not found.
*/
extern char* adc_msg_get_argument(struct adc_message* cmd, int offset);
/**
* Replace a named argument in the command.
* This will remove any matching arguments (multiple, or none),
* then add 'string' as an argument using the given prefix.
*
* @arg prefix a 2 character argument prefix
* @arg string must be escaped (see adc_msg_escape).
* @return 0 if successful, or -1 if an error occured.
*/
extern int adc_msg_replace_named_argument(struct adc_message* cmd, const char prefix[2], const char* string);
/**
* Append an argument
*
* @arg string must be escaped (see adc_msg_escape).
* @return 0 if successful, or -1 if an error occured (out of memory).
*/
extern int adc_msg_add_argument(struct adc_message* cmd, const char* string);
/**
* Append a named argument
*
* @arg prefix a 2 character argument prefix
* @arg string must be escaped (see adc_msg_escape).
* @return 0 if successful, or -1 if an error occured (out of memory).
*/
extern int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix[2], const char* string);
/**
* Append a string as a named argument.
* The string will automatcally be escaped, if you do not wish to escape th string use adc_msg_add_named_argument() instead.
*
* @arg prefix a 2 character argument prefix
* @arg string must NOT be escaped
* @return 0 if successful, or -1 if an error occured (out of memory).
*/
extern int adc_msg_add_named_argument_string(struct adc_message* cmd, const char prefix[2], const char* string);
/**
* Append an integer as a named argument.
*/
extern int adc_msg_add_named_argument_int(struct adc_message* cmd, const char prefix[2], int integer);
extern int adc_msg_add_named_argument_uint64(struct adc_message* cmd, const char prefix[2], uint64_t num);
/**
* Convert a ADC command escaped string to a regular string.
* @return string or NULL if out of memory
*/
extern char* adc_msg_unescape(const char* string);
/**
* Convert a string to a ADC command escaped string.
* @return adc command escaped string or NULL if out of memory.
*/
extern char* adc_msg_escape(const char* string);
/**
* This will ensure a newline is at the end of the command.
*/
void adc_msg_terminate(struct adc_message* cmd);
/**
* This will remove any newline from the end of the command
*/
void adc_msg_unterminate(struct adc_message* cmd);
/**
* @return the offset for the first command argument in msg->cache.
* or -1 if the command is not understood.
* NOTE: for 'U' and 'C' commands (normally not seen by hubs),
* this returns 4. Should be 4 + lengthOf(cid).
*/
int adc_msg_get_arg_offset(struct adc_message* msg);
#endif /* HAVE_UHUB_COMMAND_H */
-146
View File
@@ -1,146 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#include "uhub.h"
const char* BASE32_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
char* sid_to_string(sid_t sid_)
{
static char t_sid[5];
sid_t sid = (sid_ & 0xFFFFF); /* 20 bits only */
sid_t A, B, C, D = 0;
D = (sid % 32);
sid = (sid - D) / 32;
C = (sid % 32);
sid = (sid - C) / 32;
B = (sid % 32);
sid = (sid - B) / 32;
A = (sid % 32);
t_sid[0] = BASE32_ALPHABET[A];
t_sid[1] = BASE32_ALPHABET[B];
t_sid[2] = BASE32_ALPHABET[C];
t_sid[3] = BASE32_ALPHABET[D];
t_sid[4] = 0;
return t_sid;
}
sid_t string_to_sid(const char* sid)
{
sid_t nsid = 0;
sid_t n, x;
sid_t factors[] = { 32768, 1024, 32, 1};
if (!sid || strlen(sid) != 4) return 0;
for (n = 0; n < 4; n++) {
for (x = 0; x < strlen(BASE32_ALPHABET); x++)
if (sid[n] == BASE32_ALPHABET[x]) break;
if (x == 32) return 0;
nsid += x * factors[n];
}
return nsid;
}
/*
* Session IDs are heavily reused, since they are a fairly scarce
* resource. Only one (2^10)-1 exist, since it is a four byte base32-encoded
* value and 'AAAA' (0) is reserved for the hub.
*
* Initialize with sid_initialize(), which sets min and max to one, and count to 0.
*
* When allocating a session ID:
* - If 'count' is less than the pool size (max-min), then allocate within the pool
* - Increase the pool size (see below)
* - If unable to do that, hub is really full - don't let anyone in!
*
* When freeing a session ID:
* - If the session ID being freed is 'max', then decrease the pool size by one.
*
*/
struct sid_pool
{
sid_t min;
sid_t max;
sid_t count;
struct hub_user** map;
};
struct sid_pool* sid_pool_create(sid_t max)
{
struct sid_pool* pool = hub_malloc(sizeof(struct sid_pool));
if (!pool)
return 0;
pool->min = 1;
pool->max = max + 1;
pool->count = 0;
pool->map = hub_malloc_zero(sizeof(struct hub_user*) * pool->max);
if (!pool->map)
{
hub_free(pool);
return 0;
}
pool->map[0] = (struct hub_user*) pool; /* hack to reserve the first sid. */
#ifdef DEBUG_SID
LOG_DUMP("SID_POOL: max=%d", (int) pool->max);
#endif
return pool;
}
void sid_pool_destroy(struct sid_pool* pool)
{
#ifdef DEBUG_SID
LOG_DUMP("SID_POOL: destroying, current allocs=%d", (int) pool->count);
#endif
hub_free(pool->map);
hub_free(pool);
}
sid_t sid_alloc(struct sid_pool* pool, struct hub_user* user)
{
sid_t n = (++pool->count);
for (; (pool->map[n % pool->max]); n++) ;
#ifdef DEBUG_SID
LOG_DUMP("SID_ALLOC: %d, user=%p", (int) n, user);
#endif
pool->map[n] = user;
return n;
}
void sid_free(struct sid_pool* pool, sid_t sid)
{
#ifdef DEBUG_SID
LOG_DUMP("SID_FREE: %d", (int) sid);
#endif
pool->map[sid] = 0;
pool->count--;
}
struct hub_user* sid_lookup(struct sid_pool* pool, sid_t sid)
{
if (!sid || (sid > pool->max))
return 0;
return pool->map[sid];
}
-42
View File
@@ -1,42 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_SID_H
#define HAVE_UHUB_SID_H
#define SID_MAX 1048576
struct sid_pool;
struct hub_user;
extern const char* BASE32_ALPHABET;
extern char* sid_to_string(sid_t sid_);
extern sid_t string_to_sid(const char* sid);
extern struct sid_pool* sid_pool_create(sid_t max);
extern void sid_pool_destroy(struct sid_pool*);
extern sid_t sid_alloc(struct sid_pool*, struct hub_user*);
extern void sid_free(struct sid_pool*, sid_t);
extern struct hub_user* sid_lookup(struct sid_pool*, sid_t);
#endif /* HAVE_UHUB_SID_H */
-507
View File
@@ -1,507 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#include "uhub.h"
#define ACL_ADD_USER(S, L, V) do { ret = check_cmd_user(S, V, L, line, line_count); if (ret != 0) return ret; } while(0)
#define ACL_ADD_BOOL(S, L) do { ret = check_cmd_bool(S, L, line, line_count); if (ret != 0) return ret; } while(0)
#define ACL_ADD_ADDR(S, L) do { ret = check_cmd_addr(S, L, line, line_count); if (ret != 0) return ret; } while(0)
const char* get_user_credential_string(enum user_credentials cred)
{
switch (cred)
{
case cred_none: return "none";
case cred_bot: return "bot";
case cred_guest: return "guest";
case cred_user: return "user";
case cred_operator: return "operator";
case cred_super: return "super";
case cred_admin: return "admin";
case cred_link: return "link";
}
return "";
};
static int check_cmd_bool(const char* cmd, struct linked_list* list, char* line, int line_count)
{
char* data;
char* data_extra;
if (!strncmp(line, cmd, strlen(cmd)))
{
data = &line[strlen(cmd)];
data_extra = 0;
data[0] = '\0';
data++;
data = strip_white_space(data);
if (!*data)
{
LOG_FATAL("ACL parse error on line %d", line_count);
return -1;
}
list_append(list, hub_strdup(data));
LOG_DEBUG("ACL: Deny access for: '%s' (%s)", data, cmd);
return 1;
}
return 0;
}
static int check_cmd_user(const char* cmd, int status, struct linked_list* list, char* line, int line_count)
{
char* data;
char* data_extra;
struct hub_user_access_info* info = 0;
if (!strncmp(line, cmd, strlen(cmd)))
{
data = &line[strlen(cmd)];
data_extra = 0;
data[0] = '\0';
data++;
data = strip_white_space(data);
if (!*data)
{
LOG_FATAL("ACL parse error on line %d", line_count);
return -1;
}
info = hub_malloc_zero(sizeof(struct hub_user_access_info));
if (!info)
{
LOG_ERROR("ACL parse error. Out of memory!");
return -1;
}
if (strncmp(cmd, "user_", 5) == 0)
{
data_extra = strrchr(data, ':');
if (data_extra)
{
data_extra[0] = 0;
data_extra++;
}
}
info->username = hub_strdup(data);
info->password = data_extra ? hub_strdup(data_extra) : 0;
info->status = status;
list_append(list, info);
LOG_DEBUG("ACL: Added user '%s' (%s)", info->username, get_user_credential_string(info->status));
return 1;
}
return 0;
}
static void add_ip_range(struct linked_list* list, struct ip_range* info)
{
char buf1[INET6_ADDRSTRLEN+1];
char buf2[INET6_ADDRSTRLEN+1];
if (info->lo.af == AF_INET)
{
net_address_to_string(AF_INET, &info->lo.internal_ip_data.in.s_addr, buf1, INET6_ADDRSTRLEN);
net_address_to_string(AF_INET, &info->hi.internal_ip_data.in.s_addr, buf2, INET6_ADDRSTRLEN);
}
else if (info->lo.af == AF_INET6)
{
net_address_to_string(AF_INET6, &info->lo.internal_ip_data.in6, buf1, INET6_ADDRSTRLEN);
net_address_to_string(AF_INET6, &info->hi.internal_ip_data.in6, buf2, INET6_ADDRSTRLEN);
}
LOG_DEBUG("ACL: Deny access for: %s-%s", buf1, buf2);
list_append(list, info);
}
static int check_cmd_addr(const char* cmd, struct linked_list* list, char* line, int line_count)
{
char* data;
struct ip_range* range = 0;
if (!strncmp(line, cmd, strlen(cmd)))
{
data = &line[strlen(cmd)];
data[0] = '\0';
data++;
data = strip_white_space(data);
if (!*data)
{
LOG_FATAL("ACL parse error on line %d", line_count);
return -1;
}
range = hub_malloc_zero(sizeof(struct ip_range));
if (!range)
{
LOG_ERROR("ACL parse error. Out of memory!");
return -1;
}
if (ip_convert_address_to_range(data, range))
{
add_ip_range(list, range);
return 1;
}
hub_free(range);
}
return 0;
}
static int acl_parse_line(char* line, int line_count, void* ptr_data)
{
char* pos;
struct acl_handle* handle = (struct acl_handle*) ptr_data;
int ret;
if ((pos = strchr(line, '#')) != NULL)
{
pos[0] = 0;
}
line = strip_white_space(line);
if (!*line)
return 0;
LOG_DEBUG("acl_parse_line: '%s'", line);
ACL_ADD_USER("bot", handle->users, cred_bot);
ACL_ADD_USER("user_admin", handle->users, cred_admin);
ACL_ADD_USER("user_super", handle->users, cred_super);
ACL_ADD_USER("user_op", handle->users, cred_operator);
ACL_ADD_USER("user_reg", handle->users, cred_user);
ACL_ADD_USER("link", handle->users, cred_link);
ACL_ADD_BOOL("deny_nick", handle->users_denied);
ACL_ADD_BOOL("ban_nick", handle->users_banned);
ACL_ADD_BOOL("ban_cid", handle->cids);
ACL_ADD_ADDR("deny_ip", handle->networks);
ACL_ADD_ADDR("nat_ip", handle->nat_override);
LOG_ERROR("Unknown ACL command on line %d: '%s'", line_count, line);
return -1;
}
int acl_initialize(struct hub_config* config, struct acl_handle* handle)
{
int ret;
memset(handle, 0, sizeof(struct acl_handle));
handle->users = list_create();
handle->users_denied = list_create();
handle->users_banned = list_create();
handle->cids = list_create();
handle->networks = list_create();
handle->nat_override = list_create();
if (!handle->users || !handle->cids || !handle->networks || !handle->users_denied || !handle->users_banned || !handle->nat_override)
{
LOG_FATAL("acl_initialize: Out of memory");
list_destroy(handle->users);
list_destroy(handle->users_denied);
list_destroy(handle->users_banned);
list_destroy(handle->cids);
list_destroy(handle->networks);
list_destroy(handle->nat_override);
return -1;
}
if (config)
{
if (!*config->file_acl) return 0;
ret = file_read_lines(config->file_acl, handle, &acl_parse_line);
if (ret == -1)
return -1;
}
return 0;
}
static void acl_free_access_info(void* ptr)
{
struct hub_user_access_info* info = (struct hub_user_access_info*) ptr;
if (info)
{
hub_free(info->username);
hub_free(info->password);
hub_free(info);
}
}
static void acl_free_ip_info(void* ptr)
{
struct access_info* info = (struct access_info*) ptr;
if (info)
{
hub_free(info);
}
}
int acl_shutdown(struct acl_handle* handle)
{
if (handle->users)
{
list_clear(handle->users, &acl_free_access_info);
list_destroy(handle->users);
}
if (handle->users_denied)
{
list_clear(handle->users_denied, &hub_free);
list_destroy(handle->users_denied);
}
if (handle->users_banned)
{
list_clear(handle->users_banned, &hub_free);
list_destroy(handle->users_banned);
}
if (handle->cids)
{
list_clear(handle->cids, &hub_free);
list_destroy(handle->cids);
}
if (handle->networks)
{
list_clear(handle->networks, &acl_free_ip_info);
list_destroy(handle->networks);
}
if (handle->nat_override)
{
list_clear(handle->nat_override, &acl_free_ip_info);
list_destroy(handle->nat_override);
}
memset(handle, 0, sizeof(struct acl_handle));
return 0;
}
struct hub_user_access_info* acl_get_access_info(struct acl_handle* handle, const char* name)
{
struct hub_user_access_info* info = (struct hub_user_access_info*) list_get_first(handle->users);
while (info)
{
if (strcasecmp(info->username, name) == 0)
{
return info;
}
info = (struct hub_user_access_info*) list_get_next(handle->users);
}
return NULL;
}
#define STR_LIST_CONTAINS(LIST, STR) \
char* str = (char*) list_get_first(LIST); \
while (str) \
{ \
if (strcasecmp(str, STR) == 0) \
return 1; \
str = (char*) list_get_next(LIST); \
} \
return 0
int acl_is_cid_banned(struct acl_handle* handle, const char* data)
{
if (!handle) return 0;
STR_LIST_CONTAINS(handle->cids, data);
}
int acl_is_user_banned(struct acl_handle* handle, const char* data)
{
if (!handle) return 0;
STR_LIST_CONTAINS(handle->users_banned, data);
}
int acl_is_user_denied(struct acl_handle* handle, const char* data)
{
if (!handle) return 0;
STR_LIST_CONTAINS(handle->users_denied, data);
}
int acl_user_ban_nick(struct acl_handle* handle, const char* nick)
{
char* data = 0;
struct hub_user_access_info* info = hub_malloc_zero(sizeof(struct hub_user_access_info));
if (!info)
{
LOG_ERROR("ACL error: Out of memory!");
return -1;
}
data = hub_strdup(nick);
if (!data)
{
LOG_ERROR("ACL error: Out of memory!");
hub_free(info);
return -1;
}
list_append(handle->users_banned, data);
return 0;
}
int acl_user_ban_cid(struct acl_handle* handle, const char* cid)
{
char* data;
struct hub_user_access_info* info = hub_malloc_zero(sizeof(struct hub_user_access_info));
if (!info)
{
LOG_ERROR("ACL error: Out of memory!");
return -1;
}
data = hub_strdup(cid);
if (!data)
{
LOG_ERROR("ACL error: Out of memory!");
hub_free(info);
return -1;
}
list_append(handle->cids, data);
return 0;
}
int acl_user_unban_nick(struct acl_handle* handle, const char* nick)
{
return -1;
}
int acl_user_unban_cid(struct acl_handle* handle, const char* cid)
{
return -1;
}
int acl_is_ip_banned(struct acl_handle* handle, const char* ip_address)
{
struct ip_addr_encap raw;
struct ip_range* info = (struct ip_range*) list_get_first(handle->networks);
ip_convert_to_binary(ip_address, &raw);
while (info)
{
if (ip_in_range(&raw, info))
{
return 1;
}
info = (struct ip_range*) list_get_next(handle->networks);
}
return 0;
}
int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_address)
{
struct ip_addr_encap raw;
struct ip_range* info = (struct ip_range*) list_get_first(handle->nat_override);
ip_convert_to_binary(ip_address, &raw);
while (info)
{
if (ip_in_range(&raw, info))
{
return 1;
}
info = (struct ip_range*) list_get_next(handle->nat_override);
}
return 0;
}
/*
* This will generate the same challenge to the same user, always.
* The challenge is made up of the time of the user connected
* seconds since the unix epoch (modulus 1 million)
* and the SID of the user (0-1 million).
*/
const char* acl_password_generate_challenge(struct acl_handle* acl, struct hub_user* user)
{
char buf[64];
uint64_t tiger_res[3];
static char tiger_buf[MAX_CID_LEN+1];
// FIXME: Generate a better nonce scheme.
snprintf(buf, 64, "%p%d%d", user, (int) user->id.sid, (int) net_con_get_sd(user->connection));
tiger((uint64_t*) buf, strlen(buf), (uint64_t*) tiger_res);
base32_encode((unsigned char*) tiger_res, TIGERSIZE, tiger_buf);
tiger_buf[MAX_CID_LEN] = 0;
return (const char*) tiger_buf;
}
int acl_password_verify(struct acl_handle* acl, struct hub_user* user, const char* password)
{
char buf[1024];
struct hub_user_access_info* access;
const char* challenge;
char raw_challenge[64];
char password_calc[64];
uint64_t tiger_res[3];
if (!password || !user || strlen(password) != MAX_CID_LEN)
return 0;
access = acl_get_access_info(acl, user->id.nick);
if (!access || !access->password)
return 0;
if (TIGERSIZE+strlen(access->password) >= 1024)
return 0;
challenge = acl_password_generate_challenge(acl, user);
base32_decode(challenge, (unsigned char*) raw_challenge, MAX_CID_LEN);
memcpy(&buf[0], (char*) access->password, strlen(access->password));
memcpy(&buf[strlen(access->password)], raw_challenge, TIGERSIZE);
tiger((uint64_t*) buf, TIGERSIZE+strlen(access->password), (uint64_t*) tiger_res);
base32_encode((unsigned char*) tiger_res, TIGERSIZE, password_calc);
password_calc[MAX_CID_LEN] = 0;
if (strcasecmp(password, password_calc) == 0)
{
return 1;
}
return 0;
}
-85
View File
@@ -1,85 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_ACL_H
#define HAVE_UHUB_ACL_H
struct hub_config;
struct hub_user;
struct ip_addr_encap;
enum user_credentials
{
cred_none, /**<<< "User has no credentials (not yet logged in)" */
cred_bot, /**<<< "User is a robot" */
cred_guest, /**<<< "User is a guest (unregistered user)" */
cred_user, /**<<< "User is identified as a registered user" */
cred_operator, /**<<< "User is identified as a hub operator" */
cred_super, /**<<< "User is a super user" (not used) */
cred_admin, /**<<< "User is identified as a hub administrator/owner" */
cred_link, /**<<< "User is a link (not used currently)" */
};
const char* get_user_credential_string(enum user_credentials cred);
struct hub_user_access_info
{
char* username; /* name of user, cid or IP range */
char* password; /* password */
enum user_credentials status;
};
struct acl_handle
{
struct linked_list* users; /* Known users. See enum user_status */
struct linked_list* cids; /* Known CIDs */
struct linked_list* networks; /* IP ranges, used for banning */
struct linked_list* nat_override; /* IPs inside these ranges can provide their false IP. Use with care! */
struct linked_list* users_banned; /* Users permanently banned */
struct linked_list* users_denied; /* bad nickname */
};
extern int acl_initialize(struct hub_config* config, struct acl_handle* handle);
extern int acl_shutdown(struct acl_handle* handle);
extern struct hub_user_access_info* acl_get_access_info(struct acl_handle* handle, const char* name);
extern int acl_is_cid_banned(struct acl_handle* handle, const char* cid);
extern int acl_is_ip_banned(struct acl_handle* handle, const char* ip_address);
extern int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_address);
extern int acl_is_user_banned(struct acl_handle* handle, const char* name);
extern int acl_is_user_denied(struct acl_handle* handle, const char* name);
extern int acl_user_ban_nick(struct acl_handle* handle, const char* nick);
extern int acl_user_ban_cid(struct acl_handle* handle, const char* cid);
extern int acl_user_unban_nick(struct acl_handle* handle, const char* nick);
extern int acl_user_unban_cid(struct acl_handle* handle, const char* cid);
extern const char* acl_password_generate_challenge(struct acl_handle* acl, struct hub_user* user);
/**
* Verify a password.
*
* @param password the hashed password (based on the nonce).
* @return 1 if the password matches, or 0 if the password is incorrect.
*/
extern int acl_password_verify(struct acl_handle* acl, struct hub_user* user, const char* password);
#endif /* HAVE_UHUB_ACL_H */
-573
View File
@@ -1,573 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#include "uhub.h"
#ifdef DEBUG
#define CRASH_DEBUG
#endif
#define MAX_HELP_MSG 1024
struct hub_command
{
const char* message;
char* prefix;
size_t prefix_len;
struct linked_list* args;
};
typedef int (*command_handler)(struct hub_info* hub, struct hub_user* user, struct hub_command*);
struct commands_handler
{
const char* prefix;
size_t length;
const char* args;
enum user_credentials cred;
command_handler handler;
const char* description;
};
static struct commands_handler command_handlers[];
static void command_destroy(struct hub_command* cmd)
{
if (!cmd) return;
hub_free(cmd->prefix);
if (cmd->args)
{
list_clear(cmd->args, &hub_free);
list_destroy(cmd->args);
}
hub_free(cmd);
}
static struct hub_command* command_create(const char* message)
{
struct hub_command* cmd = hub_malloc_zero(sizeof(struct hub_command));
if (!cmd) return 0;
cmd->message = message;
cmd->args = list_create();
int n = split_string(message, "\\s", cmd->args, 0);
if (n <= 0)
{
command_destroy(cmd);
return 0;
}
char* prefix = list_get_first(cmd->args);
if (prefix && prefix[0] && prefix[1])
{
cmd->prefix = hub_strdup(&prefix[1]);
cmd->prefix_len = strlen(cmd->prefix);
}
else
{
command_destroy(cmd);
return 0;
}
list_remove(cmd->args, prefix);
hub_free(prefix);
return cmd;
}
static void send_message(struct hub_info* hub, struct hub_user* user, const char* message)
{
char* buffer = adc_msg_escape(message);
struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
adc_msg_add_argument(command, buffer);
route_to_user(hub, user, command);
adc_msg_free(command);
hub_free(buffer);
}
static int command_access_denied(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
char temp[128];
snprintf(temp, 128, "*** %s: Access denied.", cmd->prefix);
send_message(hub, user, temp);
return 0;
}
static int command_not_found(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
char temp[128];
snprintf(temp, 128, "*** %s: Command not found", cmd->prefix);
send_message(hub, user, temp);
return 0;
}
static int command_status_user_not_found(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd, const char* nick)
{
char temp[128];
snprintf(temp, 128, "*** %s: No user \"%s\"", cmd->prefix, nick);
send_message(hub, user, temp);
return 0;
}
const char* command_get_syntax(struct commands_handler* handler)
{
static char args[128];
args[0] = 0;
size_t n = 0;
if (handler->args)
{
for (n = 0; n < strlen(handler->args); n++)
{
if (n > 0) strcat(args, " ");
switch (handler->args[n])
{
case 'n': strcat(args, "<nick>"); break;
case 'c': strcat(args, "<cid>"); break;
case 'a': strcat(args, "<addr>"); break;
case 'm': strcat(args, "<message>"); break;
}
}
}
return args;
}
static int command_arg_mismatch(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd, struct commands_handler* handler)
{
char temp[256];
const char* args = command_get_syntax(handler);
if (args) snprintf(temp, 256, "*** %s: Use: !%s %s", cmd->prefix, cmd->prefix, args);
else snprintf(temp, 256, "*** %s: Use: !%s", cmd->prefix, cmd->prefix);
send_message(hub, user, temp);
return 0;
}
static int command_status(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd, const char* message)
{
char temp[1024];
snprintf(temp, 1024, "*** %s: %s", cmd->prefix, message);
send_message(hub, user, temp);
return 0;
}
static int command_stats(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
char temp[128];
snprintf(temp, 128, PRINTF_SIZE_T " users, peak: " PRINTF_SIZE_T ". Network (up/down): %d/%d KB/s, peak: %d/%d KB/s",
hub->users->count,
hub->users->count_peak,
(int) hub->stats.net_tx / 1024,
(int) hub->stats.net_rx / 1024,
(int) hub->stats.net_tx_peak / 1024,
(int) hub->stats.net_rx_peak / 1024);
return command_status(hub, user, cmd, temp);
}
static int command_help(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
size_t n;
char msg[MAX_HELP_MSG];
msg[0] = 0;
strcat(msg, "Available commands:\n");
for (n = 0; command_handlers[n].prefix; n++)
{
if (command_handlers[n].cred <= user->credentials)
{
strcat(msg, "!");
strcat(msg, command_handlers[n].prefix);
strcat(msg, " - ");
strcat(msg, command_handlers[n].description);
strcat(msg, "\n");
}
}
return command_status(hub, user, cmd, msg);
}
static int command_uptime(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
char tmp[128];
size_t d;
size_t h;
size_t m;
size_t D = (size_t) difftime(time(0), hub->tm_started);
d = D / (24 * 3600);
D = D % (24 * 3600);
h = D / 3600;
D = D % 3600;
m = D / 60;
tmp[0] = 0;
if (d)
{
strcat(tmp, uhub_itoa((int) d));
strcat(tmp, " day");
if (d != 1) strcat(tmp, "s");
strcat(tmp, ", ");
}
if (h < 10) strcat(tmp, "0");
strcat(tmp, uhub_itoa((int) h));
strcat(tmp, ":");
if (m < 10) strcat(tmp, "0");
strcat(tmp, uhub_itoa((int) m));
return command_status(hub, user, cmd, tmp);
}
static int command_kick(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
char* nick = list_get_first(cmd->args);
if (!nick)
return -1; // FIXME: bad syntax.
struct hub_user* target = uman_get_user_by_nick(hub, nick);
if (!target)
return command_status_user_not_found(hub, user, cmd, nick);
if (target == user)
return command_status(hub, user, cmd, "Cannot kick yourself");
hub_disconnect_user(hub, target, quit_kicked);
return command_status(hub, user, cmd, nick);
}
static int command_ban(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
char* nick = list_get_first(cmd->args);
if (!nick)
return -1; // FIXME: bad syntax.
struct hub_user* target = uman_get_user_by_nick(hub, nick);
if (!target)
return command_status_user_not_found(hub, user, cmd, nick);
if (target == user)
return command_status(hub, user, cmd, "Cannot kick/ban yourself");
hub_disconnect_user(hub, target, quit_kicked);
acl_user_ban_nick(hub->acl, target->id.nick);
acl_user_ban_cid(hub->acl, target->id.cid);
return command_status(hub, user, cmd, nick);
}
static int command_unban(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
return command_status(hub, user, cmd, "Not implemented");
}
static int command_reload(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
hub->status = hub_status_restart;
return command_status(hub, user, cmd, "Reloading configuration...");
}
static int command_shutdown(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
hub->status = hub_status_shutdown;
return command_status(hub, user, cmd, "Hub shutting down...");
}
static int command_version(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
return command_status(hub, user, cmd, "Powered by " PRODUCT "/" VERSION);
}
static int command_myip(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
char tmp[128];
snprintf(tmp, 128, "Your address is \"%s\"", user_get_address(user));
return command_status(hub, user, cmd, tmp);
}
static int command_getip(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
char tmp[128];
char* nick = list_get_first(cmd->args);
if (!nick);
return -1; // FIXME: bad syntax/OOM
struct hub_user* target = uman_get_user_by_nick(hub, nick);
if (!target)
return command_status_user_not_found(hub, user, cmd, nick);
snprintf(tmp, 128, "%s has address \"%s\"", nick, user_get_address(user));
return command_status(hub, user, cmd, tmp);
}
static int command_whoip(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
char* address = list_get_first(cmd->args);
struct ip_range range;
struct linked_list* users;
struct hub_user* u;
int ret = 0;
if (!address)
return -1; // FIXME: bad syntax.
ret = ip_convert_address_to_range(address, &range);
if (!ret)
return command_status(hub, user, cmd, "Invalid IP address/range/mask");
users = (struct linked_list*) list_create();
if (!users)
return -1; // FIXME: OOM
ret = uman_get_user_by_addr(hub, users, &range);
if (!ret)
{
list_destroy(users);
return command_status(hub, user, cmd, "No users found.");
}
char tmp[128];
snprintf(tmp, 128, "*** %s: Found %d match%s:", cmd->prefix, ret, ((ret != 1) ? "es" : ""));
char* buffer = hub_malloc(((MAX_NICK_LEN + INET6_ADDRSTRLEN + 5) * ret) + strlen(tmp) + 3);
if (!buffer)
{
list_destroy(users);
return -1; // FIXME: OOM
}
buffer[0] = 0;
strcat(buffer, tmp);
strcat(buffer, "\n");
u = (struct hub_user*) list_get_first(users);
while (u)
{
strcat(buffer, u->id.nick);
strcat(buffer, " (");
strcat(buffer, user_get_address(u));
strcat(buffer, ")\n");
u = (struct hub_user*) list_get_next(users);
}
strcat(buffer, "\n");
send_message(hub, user, buffer);
hub_free(buffer);
list_destroy(users);
return 0;
}
static int command_broadcast(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen((cmd->message + 10)) + 6);
adc_msg_add_argument(command, (cmd->message + 10));
route_to_all(hub, command);
adc_msg_free(command);
return 0;
}
static int command_history(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
char* buffer;
struct linked_list* messages = hub->chat_history;
char* message = 0;
int ret = (int) list_size(messages);
size_t bufsize;
if (!ret)
{
return command_status(hub, user, cmd, "No messages.");
}
char tmp[128];
snprintf(tmp, 128, "*** %s: Found %d message%s:", cmd->prefix, ret, ((ret != 1) ? "s" : ""));
bufsize = strlen(tmp);
message = (char*) list_get_first(messages);
while (message)
{
bufsize += strlen(message);
message = (char*) list_get_next(messages);
}
buffer = hub_malloc(bufsize+4);
if (!buffer)
{
return command_status(hub, user, cmd, "Not enough memory.");
}
buffer[0] = 0;
strcat(buffer, tmp);
strcat(buffer, "\n");
message = (char*) list_get_first(messages);
while (message)
{
strcat(buffer, message);
message = (char*) list_get_next(messages);
}
strcat(buffer, "\n");
send_message(hub, user, buffer);
hub_free(buffer);
return 0;
}
static int command_log(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
struct linked_list* messages = hub->logout_info;
struct hub_logout_info* log;
char tmp[1024];
char* search = 0;
size_t search_len = 0;
size_t search_hits = 0;
if (!list_size(messages))
{
return command_status(hub, user, cmd, "No entries logged.");
}
search = list_get_first(cmd->args);
if (search)
{
search_len = strlen(search);
}
if (search_len)
{
sprintf(tmp, "Logged entries: " PRINTF_SIZE_T ", searching for \"%s\"", list_size(messages), search);
}
else
{
sprintf(tmp, "Logged entries: " PRINTF_SIZE_T, list_size(messages));
}
command_status(hub, user, cmd, tmp);
log = (struct hub_logout_info*) list_get_first(messages);
while (log)
{
const char* address = ip_convert_to_string(&log->addr);
int show = 0;
if (search_len)
{
if (memmem(log->cid, MAX_CID_LEN, search, search_len) || memmem(log->nick, MAX_NICK_LEN, search, search_len) || memmem(address, strlen(address), search, search_len))
{
search_hits++;
show = 1;
}
}
else
{
show = 1;
}
if (show)
{
sprintf(tmp, "* %s %s, %s [%s] - %s", get_timestamp(log->time), log->cid, log->nick, ip_convert_to_string(&log->addr), user_get_quit_reason_string(log->reason));
send_message(hub, user, tmp);
}
log = (struct hub_logout_info*) list_get_next(messages);
}
if (search_len)
{
sprintf(tmp, PRINTF_SIZE_T " entries shown.", search_hits);
command_status(hub, user, cmd, tmp);
}
return 0;
}
#ifdef CRASH_DEBUG
static int command_crash(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
void (*crash)(void) = NULL;
crash();
return 0;
}
#endif
int command_dipatcher(struct hub_info* hub, struct hub_user* user, const char* message)
{
size_t n = 0;
int rc;
/* Parse and validate the command */
struct hub_command* cmd = command_create(message);
if (!cmd) return 0;
for (n = 0; command_handlers[n].prefix; n++)
{
struct commands_handler* handler = &command_handlers[n];
if (cmd->prefix_len != handler->length)
continue;
if (!strncmp(cmd->prefix, handler->prefix, handler->length))
{
if (handler->cred <= user->credentials)
{
if (!handler->args || (handler->args && list_size(cmd->args) >= strlen(handler->args)))
{
rc = handler->handler(hub, user, cmd);
}
else
{
rc = command_arg_mismatch(hub, user, cmd, handler);
}
command_destroy(cmd);
return rc;
}
else
{
rc = command_access_denied(hub, user, cmd);
command_destroy(cmd);
return rc;
}
}
}
command_not_found(hub, user, cmd);
command_destroy(cmd);
return 0;
}
static struct commands_handler command_handlers[] = {
{ "help", 4, 0, cred_guest, command_help, "Show this help message." },
{ "stats", 5, 0, cred_super, command_stats, "Show hub statistics." },
{ "version", 7, 0, cred_guest, command_version, "Show hub version info." },
{ "history", 7, 0, cred_guest, command_history, "Show the last chat messages." },
{ "uptime", 6, 0, cred_guest, command_uptime, "Display hub uptime info." },
{ "kick", 4, "n", cred_operator, command_kick, "Kick a user" },
{ "ban", 3, "n", cred_operator, command_ban, "Ban a user" },
{ "unban", 5, "n", cred_operator, command_unban, "Lift ban on a user" },
{ "reload", 6, 0, cred_admin, command_reload, "Reload configuration files." },
{ "shutdown", 8, 0, cred_admin, command_shutdown, "Shutdown hub." },
{ "myip", 4, 0, cred_guest, command_myip, "Show your own IP." },
{ "getip", 5, "n", cred_operator, command_getip, "Show IP address for a user" },
{ "whoip", 5, "a", cred_operator, command_whoip, "Show users matching IP range" },
{ "broadcast", 9, "m", cred_operator, command_broadcast,"Send a message to all users" },
{ "log", 3, 0, cred_operator, command_log, "Display log" },
#ifdef CRASH_DEBUG
{ "crash", 5, 0, cred_admin, command_crash, "Crash the hub (DEBUG)." },
#endif
{ 0, 0, 0, cred_none, command_help, "" }
};
-22
View File
@@ -1,22 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#include "uhub.h"
extern int command_dipatcher(struct hub_info* hub, struct hub_user* user, const char* message);
-543
View File
@@ -1,543 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* 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/>.
*
*/
#include "uhub.h"
#ifndef INT_MAX
#define INT_MAX 0x7fffffff
#endif
#ifndef INT_MIN
#define INT_MIN (-0x7fffffff - 1)
#endif
#define CFG_APPLY_BOOLEAN(KEY, TARGET) \
if (strcmp(KEY, key) == 0) \
{ \
if (strlen(data) == 1 && (data[0] == '1')) TARGET = 1; \
else if (strlen(data) == 1 && (data[0] == '0')) TARGET = 0; \
else if (strncasecmp(data, "true", 4) == 0) TARGET = 1; \
else if (strncasecmp(data, "false", 5) == 0) TARGET = 0; \
else if (strncasecmp(data, "yes", 3) == 0) TARGET = 1; \
else if (strncasecmp(data, "no", 2) == 0) TARGET = 0; \
else if (strncasecmp(data, "on", 2) == 0) TARGET = 1; \
else if (strncasecmp(data, "off", 3) == 0) TARGET = 0; \
else\
{ \
LOG_FATAL("Configuration error on line %d: '%s' must be either '1' or '0'", line_count, key); \
return -1; \
} \
TARGET |= 0x80000000; \
return 0; \
}
#define CFG_APPLY_STRING(KEY, TARGET) \
if (strcmp(KEY, key) == 0) \
{ \
TARGET = hub_strdup(data); \
return 0; \
}
#define CFG_APPLY_INTEGER(KEY, TARGET) \
if (strcmp(KEY, key) == 0) \
{ \
char* endptr; \
int val; \
errno = 0; \
val = strtol(data, &endptr, 10); \
if (((errno == ERANGE && (val == INT_MAX || val == INT_MIN)) || (errno != 0 && val == 0)) || endptr == data) { \
LOG_FATAL("Configuration error on line %d: '%s' must be a number", line_count, key); \
return -1; \
} \
TARGET = val; \
return 0; \
}
#define DEFAULT_STRING(KEY, VALUE) \
{ \
if (config->KEY == 0) \
config->KEY = hub_strdup(VALUE); \
}
#define DEFAULT_INTEGER(KEY, VALUE) \
{ \
if (config->KEY == 0) \
config->KEY = VALUE; \
}
#define DEFAULT_BOOLEAN(KEY, VALUE) \
{ \
if (config->KEY & 0x80000000) \
{ \
config->KEY = config->KEY & 0x000000ff; \
} \
else \
{ \
config->KEY = VALUE; \
} \
}
#define GET_STR(NAME) CFG_APPLY_STRING ( #NAME , config->NAME )
#define GET_INT(NAME) CFG_APPLY_INTEGER( #NAME , config->NAME )
#define GET_BOOL(NAME) CFG_APPLY_BOOLEAN( #NAME , config->NAME )
#define IGNORED(NAME) \
if (strcmp(#NAME, key) == 0) \
{ \
LOG_WARN("Configuration option %s deprecated and ingnored.", key); \
return 0; \
} \
/* default configuration values */
#define DEF_SERVER_BIND_ADDR "any"
#define DEF_SERVER_PORT 1511
#define DEF_SERVER_BACKLOG 50
#define DEF_HUB_NAME "uhub"
#define DEF_HUB_DESCRIPTION ""
#define DEF_HUB_ENABLED 1
#define DEF_FILE_ACL ""
#define DEF_FILE_MOTD ""
#define DEF_MAX_USERS 500
#define DEF_MAX_CHAT_HISTORY 20
#define DEF_MAX_LOGOUT_LOG 100
#define DEF_MAX_RECV_BUFFER 4096
#define DEF_MAX_SEND_BUFFER 131072
#define DEF_MAX_SEND_BUFFER_SOFT 98304
#define DEF_SHOW_BANNER 1
#define DEF_REGISTERED_USERS_ONLY 0
#define DEF_CHAT_ONLY 0
#define DEF_CHAT_IS_PRIVILEGED 0
#define DEF_LOW_BANDWIDTH_MODE 0
#define DEF_LIMIT_MAX_HUBS_USER 0
#define DEF_LIMIT_MAX_HUBS_REG 0
#define DEF_LIMIT_MAX_HUBS_OP 0
#define DEF_LIMIT_MAX_HUBS 0
#define DEF_LIMIT_MIN_HUBS_USER 0
#define DEF_LIMIT_MIN_HUBS_REG 0
#define DEF_LIMIT_MIN_HUBS_OP 0
#define DEF_LIMIT_MIN_SHARE 0
#define DEF_LIMIT_MAX_SHARE 0
#define DEF_LIMIT_MIN_SLOTS 0
#define DEF_LIMIT_MAX_SLOTS 0
#define DEF_TLS_ENABLE 0
#define DEF_TLS_REQUIRE 1
#define DEF_TLS_PRIVATE_KEY ""
#define DEF_TLS_CERTIFICATE ""
#define DEF_MSG_HUB_FULL "Hub is full"
#define DEF_MSG_HUB_DISABLED "Hub is disabled"
#define DEF_MSG_HUB_REGISTERED_USERS_ONLY "Hub is for registered users only"
#define DEF_MSG_INF_ERROR_NICK_MISSING "No nickname given"
#define DEF_MSG_INF_ERROR_NICK_MULTIPLE "Multiple nicknames given"
#define DEF_MSG_INF_ERROR_NICK_INVALID "Nickname is invalid"
#define DEF_MSG_INF_ERROR_NICK_LONG "Nickname too long"
#define DEF_MSG_INF_ERROR_NICK_SHORT "Nickname too short"
#define DEF_MSG_INF_ERROR_NICK_SPACES "Nickname cannot start with spaces"
#define DEF_MSG_INF_ERROR_NICK_BAD_CHARS "Nickname contains invalid characters"
#define DEF_MSG_INF_ERROR_NICK_NOT_UTF8 "Nickname is not valid utf8"
#define DEF_MSG_INF_ERROR_NICK_TAKEN "Nickname is already in use"
#define DEF_MSG_INF_ERROR_NICK_RESTRICTED "Nickname cannot be used on this hub"
#define DEF_MSG_INF_ERROR_CID_INVALID "CID is not valid"
#define DEF_MSG_INF_ERROR_CID_MISSING "CID is not specified"
#define DEF_MSG_INF_ERROR_CID_TAKEN "CID is taken"
#define DEF_MSG_INF_ERROR_PID_MISSING "PID is not specified"
#define DEF_MSG_INF_ERROR_PID_INVALID "PID is invalid"
#define DEF_MSG_BAN_PERMANENTLY "Banned permanently"
#define DEF_MSG_BAN_TEMPORARILY "Banned temporarily"
#define DEF_MSG_AUTH_INVALID_PASSWORD "Password is wrong"
#define DEF_MSG_AUTH_USER_NOT_FOUND "User not found in password database"
#define DEF_MSG_ERROR_NO_MEMORY "No memory"
#define DEF_MSG_USER_SHARE_SIZE_LOW "User is not sharing enough"
#define DEF_MSG_USER_SHARE_SIZE_HIGH "User is sharing too much"
#define DEF_MSG_USER_SLOTS_LOW "User have too few upload slots."
#define DEF_MSG_USER_SLOTS_HIGH "User have too many upload slots."
#define DEF_MSG_USER_HUB_LIMIT_LOW "User is on too few hubs."
#define DEF_MSG_USER_HUB_LIMIT_HIGH "User is on too many hubs."
void config_defaults(struct hub_config* config)
{
DEFAULT_STRING (server_bind_addr, DEF_SERVER_BIND_ADDR);
DEFAULT_STRING (hub_name, DEF_HUB_NAME);
DEFAULT_STRING (hub_description, DEF_HUB_DESCRIPTION);
DEFAULT_BOOLEAN(hub_enabled, DEF_HUB_ENABLED);
DEFAULT_STRING (file_acl, DEF_FILE_ACL);
DEFAULT_STRING (file_motd, DEF_FILE_MOTD);
DEFAULT_INTEGER(server_port, DEF_SERVER_PORT);
DEFAULT_INTEGER(server_listen_backlog, DEF_SERVER_BACKLOG);
DEFAULT_INTEGER(max_users, DEF_MAX_USERS);
DEFAULT_INTEGER(max_chat_history, DEF_MAX_CHAT_HISTORY);
DEFAULT_INTEGER(max_logout_log, DEF_MAX_LOGOUT_LOG);
DEFAULT_INTEGER(max_recv_buffer, DEF_MAX_RECV_BUFFER);
DEFAULT_INTEGER(max_send_buffer, DEF_MAX_SEND_BUFFER);
DEFAULT_INTEGER(max_send_buffer_soft, DEF_MAX_SEND_BUFFER_SOFT);
DEFAULT_BOOLEAN(show_banner, DEF_SHOW_BANNER);
DEFAULT_BOOLEAN(chat_only, DEF_CHAT_ONLY);
DEFAULT_BOOLEAN(chat_is_privileged, DEF_CHAT_IS_PRIVILEGED);
DEFAULT_BOOLEAN(low_bandwidth_mode, DEF_LOW_BANDWIDTH_MODE);
DEFAULT_BOOLEAN(registered_users_only, DEF_REGISTERED_USERS_ONLY);
/* Limits enforced on users */
DEFAULT_INTEGER(limit_max_hubs_user, DEF_LIMIT_MAX_HUBS_USER);
DEFAULT_INTEGER(limit_max_hubs_reg, DEF_LIMIT_MAX_HUBS_REG);
DEFAULT_INTEGER(limit_max_hubs_op, DEF_LIMIT_MAX_HUBS_OP);
DEFAULT_INTEGER(limit_min_hubs_user, DEF_LIMIT_MIN_HUBS_USER);
DEFAULT_INTEGER(limit_min_hubs_reg, DEF_LIMIT_MIN_HUBS_REG);
DEFAULT_INTEGER(limit_min_hubs_op, DEF_LIMIT_MIN_HUBS_OP);
DEFAULT_INTEGER(limit_max_hubs, DEF_LIMIT_MAX_HUBS);
DEFAULT_INTEGER(limit_min_share, DEF_LIMIT_MIN_SHARE);
DEFAULT_INTEGER(limit_max_share, DEF_LIMIT_MAX_SHARE);
DEFAULT_INTEGER(limit_min_slots, DEF_LIMIT_MIN_SLOTS);
DEFAULT_INTEGER(limit_max_slots, DEF_LIMIT_MAX_SLOTS);
/* Status/error strings */
DEFAULT_STRING (msg_hub_full, DEF_MSG_HUB_FULL);
DEFAULT_STRING (msg_hub_disabled, DEF_MSG_HUB_DISABLED)
DEFAULT_STRING (msg_hub_registered_users_only, DEF_MSG_HUB_REGISTERED_USERS_ONLY);
DEFAULT_STRING (msg_inf_error_nick_missing, DEF_MSG_INF_ERROR_NICK_MISSING);
DEFAULT_STRING (msg_inf_error_nick_multiple, DEF_MSG_INF_ERROR_NICK_MULTIPLE);
DEFAULT_STRING (msg_inf_error_nick_invalid, DEF_MSG_INF_ERROR_NICK_INVALID);
DEFAULT_STRING (msg_inf_error_nick_long, DEF_MSG_INF_ERROR_NICK_LONG);
DEFAULT_STRING (msg_inf_error_nick_short, DEF_MSG_INF_ERROR_NICK_SHORT);
DEFAULT_STRING (msg_inf_error_nick_spaces, DEF_MSG_INF_ERROR_NICK_SPACES);
DEFAULT_STRING (msg_inf_error_nick_bad_chars, DEF_MSG_INF_ERROR_NICK_BAD_CHARS);
DEFAULT_STRING (msg_inf_error_nick_not_utf8, DEF_MSG_INF_ERROR_NICK_NOT_UTF8);
DEFAULT_STRING (msg_inf_error_nick_taken, DEF_MSG_INF_ERROR_NICK_TAKEN);
DEFAULT_STRING (msg_inf_error_nick_restricted, DEF_MSG_INF_ERROR_NICK_RESTRICTED);
DEFAULT_STRING (msg_inf_error_cid_invalid, DEF_MSG_INF_ERROR_CID_INVALID);
DEFAULT_STRING (msg_inf_error_cid_missing, DEF_MSG_INF_ERROR_CID_MISSING);
DEFAULT_STRING (msg_inf_error_cid_taken, DEF_MSG_INF_ERROR_CID_TAKEN);
DEFAULT_STRING (msg_inf_error_pid_missing, DEF_MSG_INF_ERROR_PID_MISSING);
DEFAULT_STRING (msg_inf_error_pid_invalid, DEF_MSG_INF_ERROR_PID_INVALID);
DEFAULT_STRING (msg_ban_permanently, DEF_MSG_BAN_PERMANENTLY);
DEFAULT_STRING (msg_ban_temporarily, DEF_MSG_BAN_TEMPORARILY);
DEFAULT_STRING (msg_auth_invalid_password, DEF_MSG_AUTH_INVALID_PASSWORD);
DEFAULT_STRING (msg_auth_user_not_found, DEF_MSG_AUTH_USER_NOT_FOUND);
DEFAULT_STRING (msg_error_no_memory, DEF_MSG_ERROR_NO_MEMORY);
DEFAULT_STRING (msg_user_share_size_low, DEF_MSG_USER_SHARE_SIZE_LOW);
DEFAULT_STRING (msg_user_share_size_high, DEF_MSG_USER_SHARE_SIZE_HIGH);
DEFAULT_STRING (msg_user_slots_low, DEF_MSG_USER_SLOTS_LOW);
DEFAULT_STRING (msg_user_slots_high, DEF_MSG_USER_SLOTS_HIGH);
DEFAULT_STRING (msg_user_hub_limit_low, DEF_MSG_USER_HUB_LIMIT_LOW);
DEFAULT_STRING (msg_user_hub_limit_high, DEF_MSG_USER_HUB_LIMIT_HIGH);
DEFAULT_INTEGER(tls_enable, DEF_TLS_ENABLE);
DEFAULT_INTEGER(tls_require, DEF_TLS_REQUIRE);
DEFAULT_STRING (tls_certificate, DEF_TLS_CERTIFICATE);
DEFAULT_STRING (tls_private_key, DEF_TLS_PRIVATE_KEY);
}
static int apply_config(struct hub_config* config, char* key, char* data, int line_count)
{
GET_STR (file_acl);
GET_STR (file_motd);
GET_STR (server_bind_addr);
GET_INT (server_port);
GET_INT (server_listen_backlog);
GET_STR (hub_name);
GET_STR (hub_description);
GET_BOOL(hub_enabled);
GET_INT (max_users);
GET_INT (max_chat_history);
GET_INT (max_logout_log);
GET_INT (max_recv_buffer);
GET_INT (max_send_buffer);
GET_INT (max_send_buffer_soft);
GET_BOOL(show_banner);
GET_BOOL(chat_only);
GET_BOOL(chat_is_privileged);
GET_BOOL(low_bandwidth_mode);
GET_BOOL(registered_users_only);
/* Limits enforced on users */
GET_INT(limit_max_hubs_user);
GET_INT(limit_max_hubs_reg);
GET_INT(limit_max_hubs_op);
GET_INT(limit_min_hubs_user);
GET_INT(limit_min_hubs_reg);
GET_INT(limit_min_hubs_op);
GET_INT(limit_max_hubs);
GET_INT(limit_min_share);
GET_INT(limit_max_share);
GET_INT(limit_min_slots);
GET_INT(limit_max_slots);
/* Status/error strings */
GET_STR (msg_hub_full);
GET_STR (msg_hub_disabled);
GET_STR (msg_hub_registered_users_only);
GET_STR (msg_inf_error_nick_missing);
GET_STR (msg_inf_error_nick_multiple);
GET_STR (msg_inf_error_nick_invalid);
GET_STR (msg_inf_error_nick_long);
GET_STR (msg_inf_error_nick_short);
GET_STR (msg_inf_error_nick_spaces);
GET_STR (msg_inf_error_nick_bad_chars);
GET_STR (msg_inf_error_nick_not_utf8);
GET_STR (msg_inf_error_nick_taken);
GET_STR (msg_inf_error_nick_restricted);
GET_STR (msg_inf_error_cid_invalid);
GET_STR (msg_inf_error_cid_missing);
GET_STR (msg_inf_error_cid_taken);
GET_STR (msg_inf_error_pid_missing);
GET_STR (msg_inf_error_pid_invalid);
GET_STR (msg_ban_permanently);
GET_STR (msg_ban_temporarily);
GET_STR (msg_auth_invalid_password);
GET_STR (msg_auth_user_not_found);
GET_STR (msg_error_no_memory);
GET_STR (msg_user_share_size_low);
GET_STR (msg_user_share_size_high);
GET_STR (msg_user_slots_low);
GET_STR (msg_user_slots_high);
GET_STR (msg_user_hub_limit_low);
GET_STR (msg_user_hub_limit_high);
GET_BOOL(tls_enable);
GET_BOOL(tls_require);
GET_STR (tls_certificate);
GET_STR (tls_private_key);
/* Still here -- unknown directive */
LOG_ERROR("Unknown configuration directive: '%s'", key);
return -1;
}
void free_config(struct hub_config* config)
{
hub_free(config->server_bind_addr);
hub_free(config->file_motd);
hub_free(config->file_acl);
hub_free(config->hub_name);
hub_free(config->hub_description);
hub_free(config->msg_hub_full);
hub_free(config->msg_hub_disabled);
hub_free(config->msg_hub_registered_users_only);
hub_free(config->msg_inf_error_nick_missing);
hub_free(config->msg_inf_error_nick_multiple);
hub_free(config->msg_inf_error_nick_invalid);
hub_free(config->msg_inf_error_nick_long);
hub_free(config->msg_inf_error_nick_short);
hub_free(config->msg_inf_error_nick_spaces);
hub_free(config->msg_inf_error_nick_bad_chars);
hub_free(config->msg_inf_error_nick_not_utf8);
hub_free(config->msg_inf_error_nick_taken);
hub_free(config->msg_inf_error_nick_restricted);
hub_free(config->msg_inf_error_cid_invalid);
hub_free(config->msg_inf_error_cid_missing);
hub_free(config->msg_inf_error_cid_taken);
hub_free(config->msg_inf_error_pid_missing);
hub_free(config->msg_inf_error_pid_invalid);
hub_free(config->msg_ban_permanently);
hub_free(config->msg_ban_temporarily);
hub_free(config->msg_auth_invalid_password);
hub_free(config->msg_auth_user_not_found);
hub_free(config->msg_error_no_memory);
hub_free(config->msg_user_share_size_low);
hub_free(config->msg_user_share_size_high);
hub_free(config->msg_user_slots_low);
hub_free(config->msg_user_slots_high);
hub_free(config->msg_user_hub_limit_low);
hub_free(config->msg_user_hub_limit_high);
hub_free(config->tls_certificate);
hub_free(config->tls_private_key);
memset(config, 0, sizeof(struct hub_config));
}
#define DUMP_STR(NAME, DEFAULT) \
if (ignore_defaults) \
{ \
if (strcmp(config->NAME, DEFAULT) != 0) \
fprintf(stdout, "%s = \"%s\"\n", #NAME , config->NAME); \
} \
else \
fprintf(stdout, "%s = \"%s\"\n", #NAME , config->NAME); \
#define DUMP_INT(NAME, DEFAULT) \
if (ignore_defaults) \
{ \
if (config->NAME != DEFAULT) \
fprintf(stdout, "%s = %d\n", #NAME , config->NAME); \
} \
else \
fprintf(stdout, "%s = %d\n", #NAME , config->NAME); \
#define DUMP_BOOL(NAME, DEFAULT) \
if (ignore_defaults) \
{ \
if (config->NAME != DEFAULT) \
fprintf(stdout, "%s = %s\n", #NAME , (config->NAME ? "yes" : "no")); \
} \
else \
fprintf(stdout, "%s = %s\n", #NAME , (config->NAME ? "yes" : "no"));
void dump_config(struct hub_config* config, int ignore_defaults)
{
DUMP_STR (file_acl, DEF_FILE_ACL);
DUMP_STR (file_motd, DEF_FILE_MOTD);
DUMP_STR (server_bind_addr, DEF_SERVER_BIND_ADDR);
DUMP_INT (server_port, DEF_SERVER_PORT);
DUMP_INT (server_listen_backlog, DEF_SERVER_BACKLOG);
DUMP_STR (hub_name, DEF_HUB_NAME);
DUMP_STR (hub_description, DEF_HUB_DESCRIPTION);
DUMP_BOOL(hub_enabled, DEF_HUB_ENABLED);
DUMP_INT (max_users, DEF_MAX_USERS);
DUMP_INT (max_chat_history, DEF_MAX_CHAT_HISTORY);
DUMP_INT (max_logout_log, DEF_MAX_LOGOUT_LOG);
DUMP_INT (max_recv_buffer, DEF_MAX_RECV_BUFFER);
DUMP_INT (max_send_buffer, DEF_MAX_SEND_BUFFER);
DUMP_INT (max_send_buffer_soft, DEF_MAX_SEND_BUFFER_SOFT);
DUMP_BOOL(show_banner, DEF_SHOW_BANNER);
DUMP_BOOL(chat_only, DEF_CHAT_ONLY);
DUMP_BOOL(chat_is_privileged, DEF_CHAT_IS_PRIVILEGED);
DUMP_BOOL(low_bandwidth_mode, DEF_LOW_BANDWIDTH_MODE);
DUMP_BOOL(registered_users_only, DEF_REGISTERED_USERS_ONLY);
#ifdef SSL_SUPPORT
DUMP_BOOL(tls_enable, DEF_TLS_ENABLE);
DUMP_BOOL(tls_require, DEF_TLS_REQUIRE);
DUMP_STR (tls_certificate, DEF_TLS_CERTIFICATE);
DUMP_STR (tls_private_key, DEF_TLS_PRIVATE_KEY);
#endif
/* Limits enforced on users */
DUMP_INT(limit_max_hubs_user, DEF_LIMIT_MAX_HUBS_USER);
DUMP_INT(limit_max_hubs_reg, DEF_LIMIT_MAX_HUBS_REG);
DUMP_INT(limit_max_hubs_op, DEF_LIMIT_MAX_HUBS_OP);
DUMP_INT(limit_min_hubs_user, DEF_LIMIT_MIN_HUBS_USER);
DUMP_INT(limit_min_hubs_reg, DEF_LIMIT_MIN_HUBS_REG);
DUMP_INT(limit_min_hubs_op, DEF_LIMIT_MIN_HUBS_OP);
DUMP_INT(limit_max_hubs, DEF_LIMIT_MAX_HUBS);
DUMP_INT(limit_min_share, DEF_LIMIT_MIN_SHARE);
DUMP_INT(limit_max_share, DEF_LIMIT_MAX_SHARE);
DUMP_INT(limit_min_slots, DEF_LIMIT_MIN_SLOTS);
DUMP_INT(limit_max_slots, DEF_LIMIT_MAX_SLOTS);
/* Status/error strings */
DUMP_STR (msg_hub_full, DEF_MSG_HUB_FULL);
DUMP_STR (msg_hub_disabled, DEF_MSG_HUB_DISABLED);
DUMP_STR (msg_hub_registered_users_only, DEF_MSG_HUB_REGISTERED_USERS_ONLY);
DUMP_STR (msg_inf_error_nick_missing, DEF_MSG_INF_ERROR_NICK_MISSING);
DUMP_STR (msg_inf_error_nick_multiple, DEF_MSG_INF_ERROR_NICK_MULTIPLE);
DUMP_STR (msg_inf_error_nick_invalid, DEF_MSG_INF_ERROR_NICK_INVALID);
DUMP_STR (msg_inf_error_nick_long, DEF_MSG_INF_ERROR_NICK_LONG);
DUMP_STR (msg_inf_error_nick_short, DEF_MSG_INF_ERROR_NICK_SHORT);
DUMP_STR (msg_inf_error_nick_spaces, DEF_MSG_INF_ERROR_NICK_SPACES);
DUMP_STR (msg_inf_error_nick_bad_chars, DEF_MSG_INF_ERROR_NICK_BAD_CHARS);
DUMP_STR (msg_inf_error_nick_not_utf8, DEF_MSG_INF_ERROR_NICK_NOT_UTF8);
DUMP_STR (msg_inf_error_nick_taken, DEF_MSG_INF_ERROR_NICK_TAKEN);
DUMP_STR (msg_inf_error_nick_restricted, DEF_MSG_INF_ERROR_NICK_RESTRICTED);
DUMP_STR (msg_inf_error_cid_invalid, DEF_MSG_INF_ERROR_CID_INVALID);
DUMP_STR (msg_inf_error_cid_missing, DEF_MSG_INF_ERROR_CID_MISSING);
DUMP_STR (msg_inf_error_cid_taken, DEF_MSG_INF_ERROR_CID_TAKEN);
DUMP_STR (msg_inf_error_pid_missing, DEF_MSG_INF_ERROR_PID_MISSING);
DUMP_STR (msg_inf_error_pid_invalid, DEF_MSG_INF_ERROR_PID_INVALID);
DUMP_STR (msg_ban_permanently, DEF_MSG_BAN_PERMANENTLY);
DUMP_STR (msg_ban_temporarily, DEF_MSG_BAN_TEMPORARILY);
DUMP_STR (msg_auth_invalid_password, DEF_MSG_AUTH_INVALID_PASSWORD);
DUMP_STR (msg_auth_user_not_found, DEF_MSG_AUTH_USER_NOT_FOUND);
DUMP_STR (msg_error_no_memory, DEF_MSG_ERROR_NO_MEMORY);
DUMP_STR (msg_user_share_size_low, DEF_MSG_USER_SHARE_SIZE_LOW);
DUMP_STR (msg_user_share_size_high, DEF_MSG_USER_SHARE_SIZE_HIGH);
DUMP_STR (msg_user_slots_low, DEF_MSG_USER_SLOTS_LOW);
DUMP_STR (msg_user_slots_high, DEF_MSG_USER_SLOTS_HIGH);
DUMP_STR (msg_user_hub_limit_low, DEF_MSG_USER_HUB_LIMIT_LOW);
DUMP_STR (msg_user_hub_limit_high, DEF_MSG_USER_HUB_LIMIT_HIGH);
}
static int config_parse_line(char* line, int line_count, void* ptr_data)
{
char* pos;
char* key;
char* data;
struct hub_config* config = (struct hub_config*) ptr_data;
if ((pos = strchr(line, '#')) != NULL)
{
pos[0] = 0;
}
if (!*line) return 0;
LOG_DUMP("config_parse_line(): '%s'", line);
if (!is_valid_utf8(line))
{
LOG_WARN("Invalid utf-8 characters on line %d", line_count);
}
if ((pos = strchr(line, '=')) != NULL)
{
pos[0] = 0;
}
else
{
return 0;
}
key = line;
data = &pos[1];
key = strip_white_space(key);
data = strip_white_space(data);
if (!*key || !*data)
{
LOG_FATAL("Configuration parse error on line %d", line_count);
return -1;
}
LOG_DUMP("config_parse_line: '%s' => '%s'", key, data);
return apply_config(config, key, data, line_count);
}
int read_config(const char* file, struct hub_config* config, int allow_missing)
{
int ret;
memset(config, 0, sizeof(struct hub_config));
ret = file_read_lines(file, config, &config_parse_line);
if (ret < 0)
{
if (allow_missing && ret == -2)
{
LOG_DUMP("Using default configuration.");
}
else
{
return -1;
}
}
config_defaults(config);
return 0;
}
-126
View File
@@ -1,126 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_CONFIG_H
#define HAVE_UHUB_CONFIG_H
struct hub_config
{
int server_port; /**<<< "Server port to bind to (default: 1511)" */
char* server_bind_addr; /**<<< "Server bind address (default: '0.0.0.0' or '::')" */
int server_listen_backlog; /**<<< "Server listen backlog (default: 50)" */
int hub_enabled; /**<<< "Is server enabled (default: 1)" */
int show_banner; /**<<< "Show banner on connect (default: 1)" */
int max_users; /**<<< "Maximum number of users allowed on the hub (default: 500)" */
int registered_users_only; /**<<< "Allow registered users only (default: 0)" */
int chat_only; /**<<< "Allow chat only operation on hub (default: 0)" */
int chat_is_privileged; /**<<< "Allow chat for operators and above only (default: 0) */
char* file_motd; /**<<< "File containing the 'message of the day' (default: '' - no motd)" */
char* file_acl; /**<<< "File containing user database (default: '' - no known users)" */
char* hub_name; /**<<< "Name of hub (default: 'My uhub hub')" */
char* hub_description; /**<<< "Name of hub (default: 'no description')" */
int max_recv_buffer; /**<<< "Max read buffer before parse, per user (default: 4096)" */
int max_send_buffer; /**<<< "Max send buffer before disconnect, per user (default: 128K)" */
int max_send_buffer_soft; /**<<< "Max send buffer before message drops, per user (default: 96K)" */
int low_bandwidth_mode; /**<<< "If this is enabled, the hub will strip off elements from each user's info message to reduce bandwidth usage" */
int max_chat_history; /**<<< "Number of chat messages kept in history (default: 20)" */
int max_logout_log; /**<<< "Number of log entries for people leaving the hub. (default: 100) */
/* Limits enforced on users */
int limit_max_hubs_user; /**<<< "Max concurrent hubs as a user. (0=off, default: 10)" */
int limit_max_hubs_reg; /**<<< "Max concurrent hubs as registered user. (0=off, default: 10)" */
int limit_max_hubs_op; /**<<< "Max concurrent hubs as operator. (0=off, default: 10)" */
int limit_min_hubs_user; /**<<< "Min concurrent hubs as a user. (0=off, default: 0)" */
int limit_min_hubs_reg; /**<<< "Min concurrent hubs as registered user. (0=off, default: 0)" */
int limit_min_hubs_op; /**<<< "Min concurrent hubs as operator. (0=off, default: 0)" */
int limit_max_hubs; /**<<< "Max total hub connections allowed, user/reg/op combined. (0=off, default: 25)" */
int limit_min_share; /**<<< "Limit minimum share size in megabytes (MiB) (0=off, default: 0)" */
int limit_max_share; /**<<< "Limit maximum share size in megabytes (MiB) (0=off, default: 0)" */
int limit_min_slots; /**<<< "Limit minimum number of slots open per user (0=off, default: 0)" */
int limit_max_slots; /**<<< "Limit maximum number of slots open per user (0=off, default: 0)" */
/* Messages that can be sent to a user */
char* msg_hub_full; /**<<< "hub is full" */
char* msg_hub_disabled; /**<<< "hub is disabled" */
char* msg_hub_registered_users_only; /**<<< "hub is for registered users only" */
char* msg_inf_error_nick_missing; /**<<< "no nickname given" */
char* msg_inf_error_nick_multiple; /**<<< "multiple nicknames given" */
char* msg_inf_error_nick_invalid; /**<<< "generic/unkown" */
char* msg_inf_error_nick_long; /**<<< "nickname too long" */
char* msg_inf_error_nick_short; /**<<< "nickname too short" */
char* msg_inf_error_nick_spaces; /**<<< "nickname cannot start with spaces" */
char* msg_inf_error_nick_bad_chars; /**<<< "nickname contains chars below ascii 32" */
char* msg_inf_error_nick_not_utf8; /**<<< "nickname is not valid utf8" */
char* msg_inf_error_nick_taken; /**<<< "nickname is in use" */
char* msg_inf_error_nick_restricted; /**<<< "nickname cannot be used on this hub" */
char* msg_inf_error_cid_invalid; /**<<< "CID is not valid" */
char* msg_inf_error_cid_missing; /**<<< "CID is not specified" */
char* msg_inf_error_cid_taken; /**<<< "CID is taken" */
char* msg_inf_error_pid_missing; /**<<< "PID is not specified" */
char* msg_inf_error_pid_invalid; /**<<< "PID is invalid" */
char* msg_ban_permanently; /**<<< "Banned permanently" */
char* msg_ban_temporarily; /**<<< "Banned temporarily" */
char* msg_auth_invalid_password; /**<<< "Password is wrong" */
char* msg_auth_user_not_found; /**<<< "User not found in password database" */
char* msg_error_no_memory; /**<<< "No memory" */
char* msg_user_share_size_low; /**<<< "User is not sharing enough" */
char* msg_user_share_size_high; /**<<< "User is sharing too much" */
char* msg_user_slots_low; /**<<< "User have too few upload slots." */
char* msg_user_slots_high; /**<<< "User have too many upload slots." */
char* msg_user_hub_limit_low; /**<<< "User is on too few hubs." */
char* msg_user_hub_limit_high; /**<<< "User is on too many hubs." */
int tls_enable; /**<<< "Enable SSL/TLS support (default: 0)" */
int tls_require; /**<<< "If SSL/TLS enabled, should it be required (default: 0) */
char* tls_certificate; /**<<< "Certificate file (PEM)" */
char* tls_private_key; /**<<< "Private key" */
};
/**
* This initializes the configuration variables, and sets the default
* variables.
*
* NOTE: Any variable is set to it's default variable if zero.
* This function is automatically called in read_config to set any
* configuration that was missing there.
*/
extern void config_defaults(struct hub_config* config);
/**
* Read configuration from file, and use the default variables for
* the missing variables.
*
* @return -1 on error, 0 on success.
*/
extern int read_config(const char* file, struct hub_config* config, int allow_missing);
/**
* Free the configuration data (allocated by read_config, or config_defaults).
*/
extern void free_config(struct hub_config* config);
/**
* Print all configuration data to standard out.
*/
extern void dump_config(struct hub_config* config, int ignore_defaults);
#endif /* HAVE_UHUB_CONFIG_H */
-41
View File
@@ -1,41 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_EVENT_ID_H
#define HAVE_UHUB_EVENT_ID_H
/* User join or quit messages */
#define UHUB_EVENT_USER_JOIN 0x1001
#define UHUB_EVENT_USER_QUIT 0x1002
#define UHUB_EVENT_USER_DESTROY 0x1003
/* Send a broadcast message */
#define UHUB_EVENT_BROADCAST 0x2000
/* Shutdown hub */
#define UHUB_EVENT_HUB_SHUTDOWN 0x3001
/* Statistics, OOM, reconfigure */
#define UHUB_EVENT_STATISTICS 0x4000
#define UHUB_EVENT_OUT_OF_MEMORY 0x4001
#define UHUB_EVENT_RECONFIGURE 0x4002
#endif /* HAVE_UHUB_EVENT_ID_H */
-144
View File
@@ -1,144 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#include "uhub.h"
#ifdef EQ_DEBUG
static void eq_debug(const char* prefix, struct event_data* data)
{
LOG_DUMP(">>> %s: %p, id: %x, flags=%d\n", prefix, data, data->id, data->flags);
}
#endif
int event_queue_initialize(struct event_queue** queue, event_queue_callback callback, void* ptr)
{
*queue = (struct event_queue*) hub_malloc_zero(sizeof(struct event_queue));
if (!(*queue))
return -1;
(*queue)->q1 = list_create();
(*queue)->q2 = list_create();
if (!(*queue)->q1 || !(*queue)->q2)
{
list_destroy((*queue)->q1);
list_destroy((*queue)->q2);
return -1;
}
(*queue)->callback = callback;
(*queue)->callback_data = ptr;
return 0;
}
void event_queue_shutdown(struct event_queue* queue)
{
/* Should be empty at this point! */
list_destroy(queue->q1);
list_destroy(queue->q2);
hub_free(queue);
}
static void event_queue_cleanup_callback(void* ptr)
{
#ifdef EQ_DEBUG
struct event_data* data = (struct event_data*) ptr;
eq_debug("NUKE", data);
#endif
hub_free((struct event_data*) ptr);
}
int event_queue_process(struct event_queue* queue)
{
struct event_data* data;
if (queue->locked)
return 0;
/* lock primary queue, and handle the primary queue messages. */
queue->locked = 1;
data = (struct event_data*) list_get_first(queue->q1);
while (data)
{
#ifdef EQ_DEBUG
eq_debug("EXEC", data);
#endif
queue->callback(queue->callback_data, data);
data = (struct event_data*) list_get_next(queue->q1);
}
list_clear(queue->q1, event_queue_cleanup_callback);
assert(list_size(queue->q1) == 0);
/* unlock queue */
queue->locked = 0;
/* transfer from secondary queue to the primary queue. */
data = (struct event_data*) list_get_first(queue->q2);
while (data)
{
list_remove(queue->q2, data);
list_append(queue->q1, data);
data = (struct event_data*) list_get_first(queue->q2);
}
/* if more events exist, schedule it */
if (list_size(queue->q1))
{
return 1;
}
return 0;
}
void event_queue_post(struct event_queue* queue, struct event_data* message)
{
struct linked_list* q = (!queue->locked) ? queue->q1 : queue->q2;
struct event_data* data;
data = (struct event_data*) hub_malloc(sizeof(struct event_data));
if (data)
{
data->id = message->id;
data->ptr = message->ptr;
data->flags = message->flags;
#ifdef EQ_DEBUG
eq_debug("POST", data);
#endif
list_append(q, data);
}
else
{
LOG_ERROR("event_queue_post: OUT OF MEMORY");
}
}
size_t event_queue_size(struct event_queue* queue)
{
return list_size(queue->q1) + list_size(queue->q2);
}
-48
View File
@@ -1,48 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_EVENT_QUEUE_H
#define HAVE_UHUB_EVENT_QUEUE_H
struct event_data
{
int id;
void* ptr;
int flags;
};
typedef void (*event_queue_callback)(void* callback_data, struct event_data* event_data);
struct event_queue
{
int locked;
struct linked_list* q1; /* primary */
struct linked_list* q2; /* secondary, when primary is locked */
event_queue_callback callback;
void* callback_data;
};
extern int event_queue_initialize(struct event_queue** queue, event_queue_callback callback, void* ptr);
extern int event_queue_process(struct event_queue* queue);
extern void event_queue_shutdown(struct event_queue* queue);
extern void event_queue_post(struct event_queue* queue, struct event_data* message);
extern size_t event_queue_size(struct event_queue* queue);
#endif /* HAVE_UHUB_EVENT_QUEUE_H */
-1063
View File
File diff suppressed because it is too large Load Diff
-364
View File
@@ -1,364 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_HUB_H
#define HAVE_UHUB_HUB_H
enum status_message
{
status_msg_hub_full = -1, /* hub is full */
status_msg_hub_disabled = -2, /* hub is disabled */
status_msg_hub_registered_users_only = -3, /* hub is for registered users only */
status_msg_inf_error_nick_missing = -4, /* no nickname given */
status_msg_inf_error_nick_multiple = -5, /* multiple nicknames given */
status_msg_inf_error_nick_invalid = -6, /* generic/unkown */
status_msg_inf_error_nick_long = -7, /* nickname too long */
status_msg_inf_error_nick_short = -8, /* nickname too short */
status_msg_inf_error_nick_spaces = -9, /* nickname cannot start with spaces */
status_msg_inf_error_nick_bad_chars = -10, /* nickname contains chars below ascii 32 */
status_msg_inf_error_nick_not_utf8 = -11, /* nickname is not valid utf8 */
status_msg_inf_error_nick_taken = -12, /* nickname is in use */
status_msg_inf_error_nick_restricted = -13, /* nickname cannot be used on this hub */
status_msg_inf_error_cid_invalid = -14, /* CID is not valid (generic error) */
status_msg_inf_error_cid_missing = -15, /* CID is not specified */
status_msg_inf_error_cid_taken = -16, /* CID is taken (already logged in?). */
status_msg_inf_error_pid_missing = -17, /* PID is not specified */
status_msg_inf_error_pid_invalid = -18, /* PID is invalid */
status_msg_ban_permanently = -19, /* Banned permanently */
status_msg_ban_temporarily = -20, /* Banned temporarily */
status_msg_auth_invalid_password = -21, /* Password is wrong */
status_msg_auth_user_not_found = -22, /* User not found in password database */
status_msg_error_no_memory = -23, /* Hub is out of memory */
status_msg_user_share_size_low = -40, /* User is not sharing enough. */
status_msg_user_share_size_high = -41, /* User is sharing too much. */
status_msg_user_slots_low = -42, /* User has too few slots open. */
status_msg_user_slots_high = -43, /* User has too many slots open. */
status_msg_user_hub_limit_low = -44, /* Use is on too few hubs. */
status_msg_user_hub_limit_high = -45, /* Use is on too many hubs. */
};
enum hub_state
{
hub_status_uninitialized = 0, /**<<<"Hub is uninitialized" */
hub_status_running = 1, /**<<<"Hub is running (normal operation)" */
hub_status_restart = 2, /**<<<"Hub is restarting (re-reading configuration, etc)" */
hub_status_shutdown = 3, /**<<<"Hub is shutting down, but not yet stopped. */
hub_status_stopped = 4, /**<<<"Hub is stopped (Pretty much the same as initialized) */
hub_status_disabled = 5, /**<<<"Hub is disabled (Running, but not accepting users) */
};
/**
* Always updated each minute.
*/
struct hub_stats
{
size_t net_tx;
size_t net_rx;
size_t net_tx_peak;
size_t net_rx_peak;
size_t net_tx_total;
size_t net_rx_total;
};
struct hub_logout_info
{
time_t time;
char cid[MAX_CID_LEN+1];
char nick[MAX_NICK_LEN+1];
struct ip_addr_encap addr;
enum user_quit_reason reason;
};
struct hub_info
{
struct net_connection* server;
#ifdef USE_LIBEVENT
struct event ev_accept;
struct event ev_timer;
#endif
struct hub_stats stats;
struct event_queue* queue;
struct hub_config* config;
struct hub_user_manager* users;
struct acl_handle* acl;
struct adc_message* command_info; /* The hub's INF command */
struct adc_message* command_support; /* The hub's SUP command */
struct adc_message* command_motd; /* The message of the day */
struct adc_message* command_banner; /* The default welcome message */
time_t tm_started;
int status;
char* recvbuf; /* Global receive buffer */
char* sendbuf; /* Global send buffer */
struct linked_list* chat_history; /* Chat history */
struct linked_list* logout_info; /* Log of people logging out. */
#ifdef SSL_SUPPORT
SSL_METHOD* ssl_method;
SSL_CTX* ssl_ctx;
#endif /* SSL_SUPPORT */
};
/**
* This is the message pre-routing centre.
*
* Any message coming in to the hub comes through here first,
* and will be routed further if valid.
*
* @return 0 on success, -1 on error
*/
extern int hub_handle_message(struct hub_info* hub, struct hub_user* u, const char* message, size_t length);
/**
* Handle protocol support/subscription messages received clients.
*
* @return 0 on success, -1 on error
*/
extern int hub_handle_support(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd);
/**
* Handle password messages received from clients.
*
* @return 0 on success, -1 on error
*/
extern int hub_handle_password(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd);
/**
* Handle chat messages received from clients.
* @return 0 on success, -1 on error.
*/
extern int hub_handle_chat_message(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd);
/**
* Add a chat message to the chat history
*/
extern void hub_chat_history_add(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd);
/**
* Clear the chat history.
*/
extern void hub_chat_history_clear(struct hub_info* hub);
/**
* Used internally by hub_handle_info
* @return 1 if nickname is OK, or 0 if nickname is not accepted.
*/
extern int hub_handle_info_check_nick(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd);
/**
* Used internally by hub_handle_info
* @return 1 if CID/PID is OK, or 0 if not valid.
*/
extern int hub_handle_info_check_cid(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd);
/**
* Send the support line for the hub to a particular user.
* Only used during the initial handshake.
*/
extern void hub_send_support(struct hub_info* hub, struct hub_user* u);
/**
* Send a message assigning a SID for a user.
* This is only sent after hub_send_support() during initial handshake.
*/
extern void hub_send_sid(struct hub_info* hub, struct hub_user* u);
/**
* Send a 'ping' message to user.
*/
extern void hub_send_ping(struct hub_info* hub, struct hub_user* user);
/**
* Send a message containing hub information to a particular user.
* This is sent during user connection, but can safely be sent at any
* point later.
*/
extern void hub_send_hubinfo(struct hub_info* hub, struct hub_user* u);
/**
* Send handshake. This basically calls
* hub_send_support() and hub_send_sid()
*/
extern void hub_send_handshake(struct hub_info* hub, struct hub_user* u);
/**
* Send a welcome message containing the message of the day to
* one particular user. This can be sent in any point in time.
*/
extern void hub_send_motd(struct hub_info* hub, struct hub_user* u);
/**
* Send a password challenge to a user.
* This is only used if the user tries to access the hub using a
* password protected nick name.
*/
extern void hub_send_password_challenge(struct hub_info* hub, struct hub_user* u);
/**
* Sends a status_message to a user.
*/
extern void hub_send_status(struct hub_info*, struct hub_user* user, enum status_message msg, enum msg_status_level level);
/**
* Allocates memory, initializes the hub based on the configuration,
* and returns a hub handle.
* This hub handle must be passed to hub_shutdown_service() in order to cleanup before exiting.
*
* @return a pointer to the hub info.
*/
extern struct hub_info* hub_start_service(struct hub_config* config);
/**
* This shuts down the hub.
*/
extern void hub_shutdown_service(struct hub_info* hub);
/**
* This configures the hub.
*/
extern void hub_set_variables(struct hub_info* hub, struct acl_handle* acl);
/**
* This frees the configuration of the hub.
*/
extern void hub_free_variables(struct hub_info* hub);
/**
* Returns a string for the given status_message (See enum status_message).
*/
extern const char* hub_get_status_message(struct hub_info* hub, enum status_message msg);
extern const char* hub_get_status_message_log(struct hub_info* hub, enum status_message msg);
/**
* Returns the number of logged in users on the hub.
*/
extern size_t hub_get_user_count(struct hub_info* hub);
/**
* Returns the maximum number of allowed users on the hub.
*/
extern size_t hub_get_max_user_count(struct hub_info* hub);
/**
* Returns the accumulated shared size for all logged in
* users on the hub.
*/
extern uint64_t hub_get_shared_size(struct hub_info* hub);
/**
* Returns the accumulated number of files for all logged
* in users on the hub.
*/
extern uint64_t hub_get_shared_files(struct hub_info* hub);
/**
* Returns the minimal share size limit as enforced by
* this hub's configuration.
*/
extern uint64_t hub_get_min_share(struct hub_info* hub);
/**
* Returns the minimal share size limit as enforced by
* this hub's configuration.
*/
extern uint64_t hub_get_max_share(struct hub_info* hub);
/**
* Returns the minimum upload slot limit as enforced by
* this hub's configuration.
* Users with fewer slots in total will not be allowed
* to enter the hub.
* @return limit or 0 if no limit.
*/
extern size_t hub_get_min_slots(struct hub_info* hub);
/**
* Returns the maximum upload slot limit as enforced by
* this hub's configuration.
* Users with more allowed upload slots will not be
* allowed to enter the hub.
* @return limit or 0 if no limit.
*/
extern size_t hub_get_max_slots(struct hub_info* hub);
/**
* Returns the maximum number of hubs a user can
* be logged in to simultaneously as a regular user (guest).
* Users on more hubs will not be allowed to stay on this hub.
* @return limit or 0 if no limit.
*/
extern size_t hub_get_max_hubs_user(struct hub_info* hub);
extern size_t hub_get_min_hubs_user(struct hub_info* hub);
/**
* Returns the maximum number of hubs a user can
* be logged in to simultaneously as a registered user (password required).
* Users on more hubs will not be allowed to stay on this hub.
* @return limit or 0 if no limit.
*/
extern size_t hub_get_max_hubs_reg(struct hub_info* hub);
extern size_t hub_get_min_hubs_reg(struct hub_info* hub);
/**
* Returns the maximum number of hubs a user can
* be logged in to simultaneously as an operator.
* Users who are operator on more than this amount of hubs
* will not be allowed to stay on this hub.
* @return limit or 0 if no limit.
*/
extern size_t hub_get_max_hubs_op(struct hub_info* hub);
extern size_t hub_get_min_hubs_op(struct hub_info* hub);
/**
* Returns the maximum number of hubs a user can
* be logged in to simultaneously regardless of the type of user.
*/
extern size_t hub_get_max_hubs_total(struct hub_info* hub);
/**
* Schedule runslice.
*/
extern void hub_schedule_runslice(struct hub_info* hub);
/**
* Run event loop.
*/
extern void hub_event_loop(struct hub_info* hub);
/**
* Schedule destroying a user.
*/
extern void hub_schedule_destroy_user(struct hub_info* hub, struct hub_user* user);
/**
* Disconnect a user from the hub.
*/
extern void hub_disconnect_user(struct hub_info* hub, struct hub_user* user, int reason);
/**
* Log a user logging out.
*/
extern void hub_logout_log(struct hub_info* hub, struct hub_user* user);
#endif /* HAVE_UHUB_HUB_H */
-96
View File
@@ -1,96 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* 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/>.
*
*/
#include "uhub.h"
static void log_user_login(struct hub_user* u)
{
const char* cred = get_user_credential_string(u->credentials);
const char* addr = user_get_address(u);
LOG_USER("LoginOK %s/%s %s \"%s\" (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, cred, u->user_agent);
}
static void log_user_login_error(struct hub_user* u, enum status_message msg)
{
const char* addr = user_get_address(u);
const char* message = hub_get_status_message_log(u->hub, msg);
LOG_USER("LoginError %s/%s %s \"%s\" (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, message, u->user_agent);
}
static void log_user_logout(struct hub_user* u, const char* message)
{
const char* addr = user_get_address(u);
LOG_USER("Logout %s/%s %s \"%s\" (%s)", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, message);
}
static void log_user_nick_change(struct hub_user* u, const char* nick)
{
const char* addr = user_get_address(u);
LOG_USER("NickChange %s/%s %s \"%s\" -> \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, nick);
}
/* Send MOTD, do logging etc */
void on_login_success(struct hub_info* hub, struct hub_user* u)
{
/* Send user list of all existing users */
if (!uman_send_user_list(hub, u))
return;
/* Mark as being in the normal state, and add user to the user list */
user_set_state(u, state_normal);
uman_add(hub, u);
/* Print log message */
log_user_login(u);
/* Announce new user to all connected users */
if (user_is_logged_in(u))
route_info_message(hub, u);
/* Send message of the day (if any) */
if (user_is_logged_in(u)) /* Previous send() can fail! */
hub_send_motd(hub, u);
/* reset timeout */
net_con_clear_timeout(u->connection);
}
void on_login_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg)
{
log_user_login_error(u, msg);
hub_send_status(hub, u, msg, status_level_fatal);
hub_disconnect_user(hub, u, quit_logon_error);
}
void on_nick_change(struct hub_info* hub, struct hub_user* u, const char* nick)
{
if (user_is_logged_in(u))
{
log_user_nick_change(u, nick);
}
}
void on_logout_user(struct hub_info* hub, struct hub_user* user)
{
const char* reason = user_get_quit_reason_string(user->quit_reason);
log_user_logout(user, reason);
hub_logout_log(hub, user);
}
-45
View File
@@ -1,45 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_HUB_EVENT_H
#define HAVE_UHUB_HUB_EVENT_H
/**
* This event is triggered whenever a user successfully logs in to the hub.
*/
extern void on_login_success(struct hub_info* hub, struct hub_user* u);
/**
* This event is triggered whenever a user failed to log in to the hub.
*/
extern void on_login_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg);
/**
* This event is triggered whenever a previously logged in user leaves the hub.
*/
extern void on_logout_user(struct hub_info* hub, struct hub_user* u);
/**
* This event is triggered whenever a user changes his/her nickname.
*/
extern void on_nick_change(struct hub_info* hub, struct hub_user* u, const char* nick);
#endif /* HAVE_UHUB_HUB_EVENT_H */
-171
View File
@@ -1,171 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* 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/>.
*
*/
#include "uhub.h"
#include "hubio.h"
#ifdef DEBUG_SENDQ
static void debug_msg(const char* prefix, struct adc_message* msg)
{
size_t n;
char* buf = strdup(msg->cache);
for (n = 0; n < msg->length; n++)
{
if (buf[n] == '\r' || buf[n] == '\n')
buf[n] = '_';
}
LOG_TRACE("%s: [%s] (%d bytes)", prefix, buf, (int) msg->length);
free(buf);
}
#endif
struct hub_recvq* hub_recvq_create()
{
struct hub_recvq* q = hub_malloc_zero(sizeof(struct hub_recvq));
return q;
}
void hub_recvq_destroy(struct hub_recvq* q)
{
if (q)
{
hub_free(q->buf);
hub_free(q);
}
}
size_t hub_recvq_get(struct hub_recvq* q, void* buf, size_t bufsize)
{
assert(bufsize >= q->size);
if (q->size)
{
size_t n = q->size;
memcpy(buf, q->buf, n);
hub_free(q->buf);
q->buf = 0;
q->size = 0;
return n;
}
return 0;
}
size_t hub_recvq_set(struct hub_recvq* q, void* buf, size_t bufsize)
{
if (q->buf)
{
hub_free(q->buf);
q->buf = 0;
q->size = 0;
}
if (!bufsize)
{
return 0;
}
q->buf = hub_malloc(bufsize);
if (!q->buf)
return 0;
q->size = bufsize;
memcpy(q->buf, buf, bufsize);
return bufsize;
}
struct hub_sendq* hub_sendq_create()
{
struct hub_sendq* q = hub_malloc_zero(sizeof(struct hub_sendq));
if (!q)
return 0;
q->queue = list_create();
if (!q->queue)
{
hub_free(q);
return 0;
}
return q;
}
static void clear_send_queue_callback(void* ptr)
{
adc_msg_free((struct adc_message*) ptr);
}
void hub_sendq_destroy(struct hub_sendq* q)
{
if (q)
{
list_clear(q->queue, &clear_send_queue_callback);
list_destroy(q->queue);
hub_free(q);
}
}
void hub_sendq_add(struct hub_sendq* q, struct adc_message* msg_)
{
struct adc_message* msg = adc_msg_incref(msg_);
#ifdef DEBUG_SENDQ
debug_msg("hub_sendq_add", msg);
#endif
list_append(q->queue, msg);
q->size += msg->length;
}
void hub_sendq_remove(struct hub_sendq* q, struct adc_message* msg)
{
#ifdef DEBUG_SENDQ
debug_msg("hub_sendq_remove", msg);
#endif
list_remove(q->queue, msg);
q->size -= msg->length;
adc_msg_free(msg);
q->offset = 0;
}
int hub_sendq_send(struct hub_sendq* q, struct hub_user* user)
{
struct adc_message* msg = list_get_first(q->queue);
if (!msg) return 0;
int ret = net_con_send(user->connection, msg->cache + q->offset, msg->length - q->offset);
if (ret > 0)
{
q->offset += ret;
if (msg->length - q->offset > 0)
return 0;
hub_sendq_remove(q, msg);
return 1;
}
return ret;
}
int hub_sendq_is_empty(struct hub_sendq* q)
{
return (q->size - q->offset) == 0;
}
size_t hub_sendq_get_bytes(struct hub_sendq* q)
{
return q->size - q->offset;
}
-106
View File
@@ -1,106 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_HUB_IO_H
#define HAVE_UHUB_HUB_IO_H
struct adc_message;
struct linked_list;
typedef int (*hub_recvq_write)(void* desc, const void* buf, size_t len);
typedef int (*hub_recvq_read)(void* desc, void* buf, size_t len);
struct hub_sendq
{
size_t size; /** Size of send queue (in bytes, not messages) */
size_t offset; /** Queue byte offset in the first message. Should be 0 unless a partial write. */
#ifdef SSL_SUPPORT
size_t last_send; /** When using SSL, one have to send the exact same buffer and length if a write cannot complete. */
#endif
struct linked_list* queue; /** List of queued messages */
};
struct hub_recvq
{
char* buf;
size_t size;
};
/**
* Create a send queue
*/
extern struct hub_sendq* hub_sendq_create();
/**
* Destroy a send queue, and delete any queued messages.
*/
extern void hub_sendq_destroy(struct hub_sendq*);
/**
* Add a message to the send queue.
*/
extern void hub_sendq_add(struct hub_sendq*, struct adc_message* msg);
/**
* Process the send queue, and send as many messages as possible.
* @returns -1 on error, 0 if unable to send more, 1 if more can be sent.
*/
extern int hub_sendq_send(struct hub_sendq*, struct hub_user*);
/**
* @returns 1 if send queue is empty, 0 otherwise.
*/
extern int hub_sendq_is_empty(struct hub_sendq*);
/**
* @returns the number of bytes remaining to be sent in the queue.
*/
extern size_t hub_sendq_get_bytes(struct hub_sendq*);
/**
* Create a receive queue.
*/
extern struct hub_recvq* hub_recvq_create();
/**
* Destroy a receive queue.
*/
extern void hub_recvq_destroy(struct hub_recvq*);
/**
* Gets the buffer, copies it into buf and deallocates it.
* NOTE: bufsize *MUST* be larger than the buffer, otherwise it asserts.
* @return the number of bytes copied into buf.
*/
extern size_t hub_recvq_get(struct hub_recvq*, void* buf, size_t bufsize);
/**
* Sets the buffer
*/
extern size_t hub_recvq_set(struct hub_recvq*, void* buf, size_t bufsize);
/**
* @return 1 if size is zero, 0 otherwise.
*/
extern int hub_recvq_is_empty(struct hub_recvq* buf);
#endif /* HAVE_UHUB_HUB_IO_H */
-794
View File
@@ -1,794 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#include "uhub.h"
/*
* These flags can only be set by the hub.
* Make sure we don't allow clients to specify these themselves.
*
* NOTE: Some of them are legacy ADC flags and no longer used, these
* should be removed at some point in the future when functionality no
* longer depend on them.
*/
static void remove_server_restricted_flags(struct adc_message* cmd)
{
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE); /* Client type flag (CT, obsoletes BO, RG, OP, HU) */
adc_msg_remove_named_argument(cmd, "BO"); /* Obsolete: bot flag (CT) */
adc_msg_remove_named_argument(cmd, "RG"); /* Obsolete: registered user flag (CT) */
adc_msg_remove_named_argument(cmd, "OP"); /* Obsolete: operator flag (CT) */
adc_msg_remove_named_argument(cmd, "HU"); /* Obsolete: hub flag (CT) */
adc_msg_remove_named_argument(cmd, "HI"); /* Obsolete: hidden user flag */
adc_msg_remove_named_argument(cmd, "TO"); /* Client to client token - should not be seen here */
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_REFERER);
}
static int set_feature_cast_supports(struct hub_user* u, struct adc_message* cmd)
{
char *it, *tmp;
if (adc_msg_has_named_argument(cmd, ADC_INF_FLAG_SUPPORT))
{
tmp = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SUPPORT);
if (!tmp)
return -1; // FIXME: OOM
user_clear_feature_cast_support(u);
it = tmp;
while (strlen(it) > 4)
{
it[4] = 0; /* FIXME: Not really needed */
user_set_feature_cast_support(u, it);
it = &it[5];
}
if (*it)
{
user_set_feature_cast_support(u, it);
}
hub_free(tmp);
}
return 0;
}
static int check_hash_tiger(const char* cid, const char* pid)
{
char x_pid[64];
char raw_pid[64];
uint64_t tiger_res[3];
memset(x_pid, 0, MAX_CID_LEN+1);
base32_decode(pid, (unsigned char*) raw_pid, MAX_CID_LEN);
tiger((uint64_t*) raw_pid, TIGERSIZE, (uint64_t*) tiger_res);
base32_encode((unsigned char*) tiger_res, TIGERSIZE, x_pid);
x_pid[MAX_CID_LEN] = 0;
if (strncasecmp(x_pid, cid, MAX_CID_LEN) == 0)
return 1;
return 0;
}
/*
* FIXME: Only works for tiger hash. If a client doesnt support tiger we cannot let it in!
*/
static int check_cid(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
size_t pos;
char* cid = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_CLIENT_ID);
char* pid = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID);
if (!cid || !pid)
{
hub_free(cid);
hub_free(pid);
return status_msg_error_no_memory;
}
if (strlen(cid) != MAX_CID_LEN)
{
hub_free(cid);
hub_free(pid);
return status_msg_inf_error_cid_invalid;
}
if (strlen(pid) != MAX_CID_LEN)
{
hub_free(cid);
hub_free(pid);
return status_msg_inf_error_pid_invalid;
}
for (pos = 0; pos < MAX_CID_LEN; pos++)
{
if (!is_valid_base32_char(cid[pos]))
{
hub_free(cid);
hub_free(pid);
return status_msg_inf_error_cid_invalid;
}
if (!is_valid_base32_char(pid[pos]))
{
hub_free(cid);
hub_free(pid);
return status_msg_inf_error_pid_invalid;
}
}
if (!check_hash_tiger(cid, pid))
{
hub_free(cid);
hub_free(pid);
return status_msg_inf_error_cid_invalid;
}
/* Set the cid in the user object */
memcpy(user->id.cid, cid, MAX_CID_LEN);
user->id.cid[MAX_CID_LEN] = 0;
hub_free(cid);
hub_free(pid);
return 0;
}
static int check_required_login_flags(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
int num = 0;
num = adc_msg_has_named_argument(cmd, ADC_INF_FLAG_CLIENT_ID);
if (num != 1)
{
if (!num)
return status_msg_inf_error_cid_missing;
return status_msg_inf_error_cid_invalid;
}
num = adc_msg_has_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID);
if (num != 1)
{
if (!num)
return status_msg_inf_error_pid_missing;
return status_msg_inf_error_pid_invalid;
}
num = adc_msg_has_named_argument(cmd, ADC_INF_FLAG_NICK);
if (num != 1)
{
if (!num)
return status_msg_inf_error_nick_missing;
return status_msg_inf_error_nick_multiple;
}
return 0;
}
/**
* This will check the ip address of the user, and
* remove any wrong address, and replace it with the correct one
* as seen by the hub.
*/
int check_network(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
const char* address = user_get_address(user);
/* Check for NAT override address */
if (acl_is_ip_nat_override(hub->acl, address))
{
char* client_given_ip = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
if (client_given_ip && strcmp(client_given_ip, "0.0.0.0") != 0)
{
user_set_nat_override(user);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_UDP_PORT);
hub_free(client_given_ip);
return 0;
}
hub_free(client_given_ip);
}
if (strchr(address, '.'))
{
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_UDP_PORT);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
adc_msg_add_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR, address);
}
else if (strchr(address, ':'))
{
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_UDP_PORT);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR);
adc_msg_add_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR, address);
}
return 0;
}
void strip_network(struct hub_user* user, struct adc_message* cmd)
{
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_UDP_PORT);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_UDP_PORT);
}
static int nick_length_ok(const char* nick)
{
size_t length = strlen(nick);
if (length <= 1)
{
return nick_invalid_short;
}
if (length > MAX_NICK_LEN)
{
return nick_invalid_long;
}
return nick_ok;
}
static int nick_bad_characters(const char* nick)
{
const char* tmp;
/* Nick must not start with a space */
if (nick[0] == ' ')
return nick_invalid_spaces;
/* Check for ASCII values below 32 */
for (tmp = nick; *tmp; tmp++)
if ((*tmp < 32) && (*tmp > 0))
return nick_invalid_bad_ascii;
return nick_ok;
}
static int nick_is_utf8(const char* nick)
{
/*
* Nick should be valid utf-8, but
* perhaps we should check if the nick is unicode normalized?
*/
if (!is_valid_utf8(nick))
return nick_invalid_bad_utf8;
return nick_ok;
}
static int check_nick(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
char* nick;
char* tmp;
enum nick_status status;
tmp = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_NICK);
if (!tmp) return 0;
nick = adc_msg_unescape(tmp);
free(tmp); tmp = 0;
if (!nick) return 0;
status = nick_length_ok(nick);
if (status != nick_ok)
{
hub_free(nick);
if (status == nick_invalid_short)
return status_msg_inf_error_nick_short;
return status_msg_inf_error_nick_long;
}
status = nick_bad_characters(nick);
if (status != nick_ok)
{
hub_free(nick);
if (status == nick_invalid_spaces)
return status_msg_inf_error_nick_spaces;
return status_msg_inf_error_nick_bad_chars;
}
status = nick_is_utf8(nick);
if (status != nick_ok)
{
hub_free(nick);
return status_msg_inf_error_nick_not_utf8;
}
if (user_is_connecting(user))
{
memcpy(user->id.nick, nick, strlen(nick));
user->id.nick[strlen(nick)] = 0;
}
hub_free(nick);
return 0;
}
static int check_logged_in(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
struct hub_user* lookup1 = uman_get_user_by_nick(hub, user->id.nick);
struct hub_user* lookup2 = uman_get_user_by_cid(hub, user->id.cid);
if (lookup1 == user)
{
return 0;
}
if (lookup1 || lookup2)
{
if (lookup1 == lookup2)
{
LOG_DEBUG("check_logged_in: exact same user is logged in: %s", user->id.nick);
hub_disconnect_user(hub, lookup1, quit_ghost_timeout);
return 0;
}
else
{
if (lookup1)
{
LOG_DEBUG("check_logged_in: nickname is in use: %s", user->id.nick);
return status_msg_inf_error_nick_taken;
}
else
{
LOG_DEBUG("check_logged_in: CID is in use: %s", user->id.cid);
return status_msg_inf_error_cid_taken;
}
}
}
return 0;
}
/*
* It is possible to do user-agent checking here.
* But this is not something we want to do, and is deprecated in the ADC specification.
* One should rather look at capabilities/features.
*/
static int check_user_agent(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
char* ua_encoded = 0;
char* ua = 0;
/* Get client user agent version */
ua_encoded = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_USER_AGENT);
if (ua_encoded)
{
ua = adc_msg_unescape(ua_encoded);
if (ua)
{
memcpy(user->user_agent, ua, MIN(strlen(ua), MAX_UA_LEN));
hub_free(ua);
}
}
hub_free(ua_encoded);
return 0;
}
static int check_acl(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
if (acl_is_cid_banned(hub->acl, user->id.cid))
{
return status_msg_ban_permanently;
}
if (acl_is_user_banned(hub->acl, user->id.nick))
{
return status_msg_ban_permanently;
}
if (acl_is_user_denied(hub->acl, user->id.nick))
{
return status_msg_inf_error_nick_restricted;
}
return 0;
}
static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
char* arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SHARED_SIZE);
if (arg)
{
int64_t shared_size = atoll(arg);
if (shared_size < 0)
shared_size = 0;
if (user_is_logged_in(user))
{
hub->users->shared_size -= user->limits.shared_size;
hub->users->shared_size += shared_size;
}
user->limits.shared_size = shared_size;
hub_free(arg);
arg = 0;
}
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SHARED_FILES);
if (arg)
{
ssize_t shared_files = atoll(arg);
if (shared_files < 0)
shared_files = 0;
if (user_is_logged_in(user))
{
hub->users->shared_files -= user->limits.shared_files;
hub->users->shared_files += shared_files;
}
user->limits.shared_files = shared_files;
hub_free(arg);
arg = 0;
}
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_NORMAL);
if (arg)
{
ssize_t num = atoll(arg);
if (num < 0) num = 0;
user->limits.hub_count_user = num;
hub_free(arg);
arg = 0;
}
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_REGISTER);
if (arg)
{
ssize_t num = atoll(arg);
if (num < 0) num = 0;
user->limits.hub_count_registered = num;
hub_free(arg);
arg = 0;
}
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_OPERATOR);
if (arg)
{
ssize_t num = atoll(arg);
if (num < 0) num = 0;
user->limits.hub_count_operator = num;
hub_free(arg);
arg = 0;
}
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_UPLOAD_SLOTS);
if (arg)
{
ssize_t num = atoll(arg);
if (num < 0) num = 0;
user->limits.upload_slots = num;
hub_free(arg);
arg = 0;
}
/* summarize total slots */
user->limits.hub_count_total = user->limits.hub_count_user + user->limits.hub_count_registered + user->limits.hub_count_operator;
if (!user_is_protected(user))
{
if (user->limits.shared_size < hub_get_min_share(hub) && hub_get_min_share(hub))
{
return status_msg_user_share_size_low;
}
if (user->limits.shared_size > hub_get_max_share(hub) && hub_get_max_share(hub))
{
return status_msg_user_share_size_high;
}
if ((user->limits.hub_count_user > hub_get_max_hubs_user(hub) && hub_get_max_hubs_user(hub)) ||
(user->limits.hub_count_registered > hub_get_max_hubs_reg(hub) && hub_get_max_hubs_reg(hub)) ||
(user->limits.hub_count_operator > hub_get_max_hubs_op(hub) && hub_get_max_hubs_op(hub)) ||
(user->limits.hub_count_total > hub_get_max_hubs_total(hub) && hub_get_max_hubs_total(hub)))
{
return status_msg_user_hub_limit_high;
}
if ((user->limits.hub_count_user < hub_get_min_hubs_user(hub) && hub_get_min_hubs_user(hub)) ||
(user->limits.hub_count_registered < hub_get_min_hubs_reg(hub) && hub_get_min_hubs_reg(hub)) ||
(user->limits.hub_count_operator < hub_get_min_hubs_op(hub) && hub_get_min_hubs_op(hub)))
{
return status_msg_user_hub_limit_low;
}
if (user->limits.upload_slots < hub_get_min_slots(hub) && hub_get_min_slots(hub))
{
return status_msg_user_slots_low;
}
if (user->limits.upload_slots > hub_get_max_slots(hub) && hub_get_max_slots(hub))
{
return status_msg_user_slots_high;
}
}
return 0;
}
/*
* Set the expected credentials, and returns 1 if authentication is needed,
* or 0 if not.
* If the hub is configured to allow only registered users and the user
* is not recognized this will return 1.
*/
static int set_credentials(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
int ret = 0;
struct hub_user_access_info* info = acl_get_access_info(hub->acl, user->id.nick);
if (info)
{
user->credentials = info->status;
ret = 1;
}
else
{
user->credentials = cred_guest;
}
switch (user->credentials)
{
case cred_none:
break;
case cred_bot:
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_BOT);
break;
case cred_guest:
/* Nothing to be added to the info message */
break;
case cred_user:
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_REGISTERED_USER);
break;
case cred_operator:
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_OPERATOR);
break;
case cred_super:
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_SUPER_USER);
break;
case cred_admin:
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_ADMIN);
break;
case cred_link:
break;
}
return ret;
}
static int check_is_hub_full(struct hub_info* hub, struct hub_user* user)
{
/*
* If hub is full, don't let users in, but we still want to allow
* operators and admins to enter the hub.
*/
if (hub->config->max_users && hub->users->count >= hub->config->max_users && !user_is_protected(user))
{
return 1;
}
return 0;
}
static int check_registered_users_only(struct hub_info* hub, struct hub_user* user)
{
if (hub->config->registered_users_only && !user_is_registered(user))
{
return 1;
}
return 0;
}
static int hub_handle_info_common(struct hub_user* user, struct adc_message* cmd)
{
/* Remove server restricted flags */
remove_server_restricted_flags(cmd);
/* Update/set the feature cast flags. */
set_feature_cast_supports(user, cmd);
return 0;
}
static int hub_handle_info_low_bandwidth(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
if (hub->config->low_bandwidth_mode)
{
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_USER_AGENT);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_SHARED_FILES);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_NORMAL);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_REGISTER);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_OPERATOR);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_UPLOAD_SPEED);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_DOWNLOAD_SPEED);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_AUTO_SLOTS);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_AUTO_SLOTS_MAX);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_AWAY);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_DESCRIPTION);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_EMAIL);
}
return 0;
}
#define INF_CHECK(FUNC, HUB, USER, CMD) \
do { \
int ret = FUNC(HUB, USER, CMD); \
if (ret < 0) \
return ret; \
} while(0)
int hub_perform_login_checks(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
/* Make syntax checks. */
INF_CHECK(check_required_login_flags, hub, user, cmd);
INF_CHECK(check_cid, hub, user, cmd);
INF_CHECK(check_nick, hub, user, cmd);
INF_CHECK(check_network, hub, user, cmd);
INF_CHECK(check_user_agent, hub, user, cmd);
INF_CHECK(check_acl, hub, user, cmd);
INF_CHECK(check_logged_in, hub, user, cmd);
return 0;
}
/**
* Perform additional INF checks used at time of login.
*
* @return 0 if success, <0 if error, >0 if authentication needed.
*/
int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
int code = 0;
INF_CHECK(hub_perform_login_checks, hub, user, cmd);
/* Private ID must never be broadcasted - drop it! */
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID);
code = set_credentials(hub, user, cmd);
/* Note: this must be done *after* set_credentials. */
if (check_is_hub_full(hub, user))
{
return status_msg_hub_full;
}
if (check_registered_users_only(hub, user))
{
return status_msg_hub_registered_users_only;
}
INF_CHECK(check_limits, hub, user, cmd);
/* strip off stuff if low_bandwidth_mode is enabled */
hub_handle_info_low_bandwidth(hub, user, cmd);
/* Set initial user info */
user_set_info(user, cmd);
return code;
}
/*
* If user is in the connecting state, we need to do fairly
* strict checking of all arguments.
* This means we disconnect users when they provide invalid data
* during the login sequence.
* When users are merely updating their data after successful login
* we can just ignore any invalid data and not broadcast it.
*
* The data we need to check is:
* - nick name (valid, not taken, etc)
* - CID/PID (valid, not taken, etc).
* - IP addresses (IPv4 and IPv6)
*/
int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct adc_message* cmd_unmodified)
{
struct adc_message* cmd = adc_msg_copy(cmd_unmodified);
if (!cmd) return -1; /* OOM */
cmd->priority = 1;
hub_handle_info_common(user, cmd);
/* If user is logging in, perform more checks,
otherwise only a few things need to be checked.
*/
if (user_is_connecting(user))
{
/*
* Don't allow the user to send multiple INF messages in this stage!
* Since that can have serious side-effects.
*/
if (user->info)
{
adc_msg_free(cmd);
return 0;
}
int ret = hub_handle_info_login(hub, user, cmd);
if (ret < 0)
{
on_login_failure(hub, user, ret);
adc_msg_free(cmd);
return -1;
}
else
{
/* Post a message, the user has joined */
struct event_data post;
memset(&post, 0, sizeof(post));
post.id = UHUB_EVENT_USER_JOIN;
post.ptr = user;
post.flags = ret; /* 0 - all OK, 1 - need authentication */
event_queue_post(hub->queue, &post);
adc_msg_free(cmd);
return 0;
}
}
else
{
/* These must not be allowed updated, let's remove them! */
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_CLIENT_ID);
/*
* If the nick is not accepted, do not relay it.
* Otherwise, the nickname will be updated.
*/
if (adc_msg_has_named_argument(cmd, ADC_INF_FLAG_NICK))
{
#ifdef ALLOW_CHANGE_NICK
if (!check_nick(hub, user, cmd))
#endif
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_NICK);
}
/* FIXME - What if limits are not met ? */
check_limits(hub, user, cmd);
strip_network(user, cmd);
hub_handle_info_low_bandwidth(hub, user, cmd);
user_update_info(user, cmd);
if (!adc_msg_is_empty(cmd))
{
route_message(hub, user, cmd);
}
adc_msg_free(cmd);
}
return 0;
}
-54
View File
@@ -1,54 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_INF_PARSER_H
#define HAVE_UHUB_INF_PARSER_H
enum nick_status
{
nick_ok = 0,
nick_invalid_short = -1,
nick_invalid_long = -2,
nick_invalid_spaces = -3,
nick_invalid_bad_ascii = -4,
nick_invalid_bad_utf8 = -5,
nick_invalid = -6, /* some unknown reason */
nick_not_allowed = -7, /* Not allowed according to configuration */
nick_banned = -8, /* Nickname is banned */
};
/**
* Handle info messages as received from clients.
* This can be an initial info message, which might end up requiring password
* authentication, etc.
* All sorts of validation is performed here.
* - Nickname valid?
* - CID/PID valid?
* - Network IP address valid?
*
* This can be triggered multiple times, as users can update their information,
* in such case nickname and CID/PID changes are not allowed.
*
* @return 0 on success, -1 on error
*/
extern int hub_handle_info(struct hub_info* hub, struct hub_user* u, const struct adc_message* cmd);
#endif /* HAVE_UHUB_INF_PARSER_H */
-478
View File
@@ -1,478 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#include "uhub.h"
static int arg_verbose = 5;
static int arg_fork = 0;
static int arg_check_config = 0;
static int arg_dump_config = 0;
static int arg_have_config = 0;
static const char* arg_uid = 0;
static const char* arg_gid = 0;
static const char* arg_config = 0;
static const char* arg_log = 0;
static const char* arg_pid = 0;
static int arg_log_syslog = 0;
#if !defined(WIN32) && defined(USE_LIBEVENT)
void hub_handle_signal(int fd, short events, void* arg)
{
struct hub_info* hub = (struct hub_info*) arg;
int signal = fd;
switch (signal)
{
case SIGINT:
LOG_INFO("Interrupted. Shutting down...");
hub->status = hub_status_shutdown;
break;
case SIGTERM:
LOG_INFO("Terminated. Shutting down...");
hub->status = hub_status_shutdown;
break;
case SIGPIPE:
break;
case SIGHUP:
hub->status = hub_status_restart;
break;
default:
LOG_TRACE("hub_handle_signal(): caught unknown signal: %d", signal);
hub->status = hub_status_shutdown;
break;
}
}
static struct event signal_events[10];
static int signals[] =
{
SIGINT, /* Interrupt the application */
SIGTERM, /* Terminate the application */
SIGPIPE, /* prevent sigpipe from kills the application */
SIGHUP, /* reload configuration */
0
};
void setup_signal_handlers(struct hub_info* hub)
{
int i = 0;
for (i = 0; signals[i]; i++)
{
signal_set(&signal_events[i], signals[i], hub_handle_signal, hub);
if (signal_add(&signal_events[i], NULL))
{
LOG_ERROR("Error setting signal handler %d", signals[i]);
}
}
}
void shutdown_signal_handlers(struct hub_info* hub)
{
int i = 0;
for (i = 0; signals[i]; i++)
{
signal_del(&signal_events[i]);
}
}
#endif /* !WIN32 && USE_LIBEVENT*/
int main_loop()
{
struct hub_config configuration;
struct acl_handle acl;
struct hub_info* hub = 0;
if (net_initialize() == -1)
return -1;
do
{
if (hub)
{
LOG_INFO("Reloading configuration files...");
LOG_DEBUG("Hub status: %d", (int) hub->status);
}
if (read_config(arg_config, &configuration, !arg_have_config) == -1)
return -1;
if (acl_initialize(&configuration, &acl) == -1)
return -1;
/*
* Don't restart networking when re-reading configuration.
* This might not be possible either, since we might have
* dropped our privileges to do so.
*/
if (!hub)
{
hub = hub_start_service(&configuration);
if (!hub)
return -1;
#if !defined(WIN32) && defined(USE_LIBEVENT)
setup_signal_handlers(hub);
#endif
}
hub_set_variables(hub, &acl);
hub_event_loop(hub);
hub_free_variables(hub);
acl_shutdown(&acl);
free_config(&configuration);
} while (hub->status == hub_status_restart);
#if !defined(WIN32) && defined(USE_LIBEVENT)
shutdown_signal_handlers(hub);
#endif
if (hub)
{
hub_shutdown_service(hub);
}
net_destroy();
hub_log_shutdown();
return 0;
}
int check_configuration(int dump)
{
struct hub_config configuration;
int ret = read_config(arg_config, &configuration, 0);
if (dump)
{
if (ret != -1)
{
dump_config(&configuration, dump > 1);
}
return 0;
}
if (ret == -1)
{
fprintf(stderr, "ERROR\n");
return 1;
}
fprintf(stdout, "OK\n");
return 0;
}
void print_version()
{
fprintf(stdout, "" PRODUCT " " VERSION "\n");
fprintf(stdout, "Copyright (C) 2007-2009, Jan Vidar Krey <janvidar@extatic.org>\n"
"This is free software with ABSOLUTELY NO WARRANTY.\n\n");
exit(0);
}
void print_usage(char* program)
{
fprintf(stderr, "Usage: %s [options]\n\n", program);
fprintf(stderr,
"Options:\n"
" -v Verbose mode. Add more -v's for higher verbosity.\n"
" -q Quiet mode - no output\n"
" -f Fork to background\n"
" -l <file> Log messages to given file (default: stderr)\n"
" -L Log messages to syslog\n"
" -c <file> Specify configuration file (default: " SERVER_CONFIG ")\n"
" -C Check configuration and return\n"
" -s Show configuration parameters\n"
" -S Show configuration parameters, but ignore defaults\n"
" -h This message\n"
#ifndef WIN32
" -u <user> Run as given user\n"
" -g <group> Run with given group permissions\n"
" -p <file> Store pid in file (process id)\n"
#endif
" -V Show version number.\n"
);
exit(0);
}
void parse_command_line(int argc, char** argv)
{
int opt;
while ((opt = getopt(argc, argv, "vqfc:l:hu:g:VCsSLp:")) != -1)
{
switch (opt)
{
case 'V':
print_version();
break;
case 'v':
arg_verbose++;
break;
case 'q':
arg_verbose -= 99;
break;
case 'f':
arg_fork = 1;
break;
case 'c':
arg_config = optarg;
arg_have_config = 1;
break;
case 'C':
arg_check_config = 1;
arg_have_config = 1;
break;
case 's':
arg_dump_config = 1;
arg_check_config = 1;
break;
case 'S':
arg_dump_config = 2;
arg_check_config = 1;
break;
case 'l':
arg_log = optarg;
break;
case 'L':
arg_log_syslog = 1;
break;
case 'h':
print_usage(argv[0]);
break;
case 'u':
arg_uid = optarg;
break;
case 'g':
arg_gid = optarg;
break;
case 'p':
arg_pid = optarg;
break;
default:
print_usage(argv[0]);
break;
}
}
if (arg_config == NULL)
{
arg_config = SERVER_CONFIG;
}
hub_log_initialize(arg_log, arg_log_syslog);
hub_set_log_verbosity(arg_verbose);
}
#ifndef WIN32
int drop_privileges()
{
struct group* perm_group = 0;
struct passwd* perm_user = 0;
gid_t perm_gid = 0;
uid_t perm_uid = 0;
int gid_ok = 0;
int ret = 0;
if (arg_gid)
{
ret = 0;
while ((perm_group = getgrent()) != NULL)
{
if (strcmp(perm_group->gr_name, arg_gid) == 0)
{
perm_gid = perm_group->gr_gid;
ret = 1;
break;
}
}
endgrent();
if (!ret)
{
LOG_FATAL("Unable to determine group id, check group name.");
return -1;
}
LOG_TRACE("Setting group id %d (%s)", (int) perm_gid, arg_gid);
ret = setgid(perm_gid);
if (ret == -1)
{
LOG_FATAL("Unable to change group id, permission denied.");
return -1;
}
gid_ok = 1;
}
if (arg_uid)
{
ret = 0;
while ((perm_user = getpwent()) != NULL)
{
if (strcmp(perm_user->pw_name, arg_uid) == 0)
{
perm_uid = perm_user->pw_uid;
if (!gid_ok)
perm_gid = perm_user->pw_gid;
ret = 1;
break;
}
}
endpwent();
if (!ret)
{
LOG_FATAL("Unable to determine user id, check user name.");
return -1;
}
if (!gid_ok) {
LOG_TRACE("Setting group id %d (%s)", (int) perm_gid, arg_gid);
ret = setgid(perm_gid);
if (ret == -1)
{
LOG_FATAL("Unable to change group id, permission denied.");
return -1;
}
}
LOG_TRACE("Setting user id %d (%s)", (int) perm_uid, arg_uid);
ret = setuid(perm_uid);
if (ret == -1)
{
LOG_FATAL("Unable to change user id, permission denied.");
return -1;
}
}
return 0;
}
int pidfile_create()
{
if (arg_pid)
{
FILE* pidfile = fopen(arg_pid, "w");
if (!pidfile)
{
LOG_FATAL("Unable to write pid file: %s\n", arg_pid);
return -1;
}
fprintf(pidfile, "%d", (int) getpid());
fclose(pidfile);
}
return 0;
}
int pidfile_destroy()
{
if (arg_pid)
{
return unlink(arg_pid);
}
return 0;
}
#endif /* WIN32 */
int main(int argc, char** argv)
{
int ret = 0;
parse_command_line(argc, argv);
if (arg_check_config)
{
return check_configuration(arg_dump_config);
}
#ifndef WIN32
if (arg_fork)
{
ret = fork();
if (ret == -1)
{
LOG_FATAL("Unable to fork to background!");
return -1;
}
else if (ret == 0)
{
/* child process - detatch from TTY */
fclose(stdin);
fclose(stdout);
fclose(stderr);
close(0);
close(1);
close(2);
}
else
{
/* parent process */
LOG_DEBUG("Forked to background\n");
return 0;
}
}
if (pidfile_create() == -1)
return -1;
if (drop_privileges() == -1)
return -1;
#endif /* WIN32 */
ret = main_loop();
#ifndef WIN32
pidfile_destroy();
#endif
return ret;
}
-254
View File
@@ -1,254 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* 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/>.
*
*/
#include <uhub.h>
#include "hubio.h"
#include "probe.h"
/* FIXME: This should not be needed! */
extern struct hub_info* g_hub;
#ifdef DEBUG_SENDQ
void debug_sendq_send(struct hub_user* user, int sent, int total)
{
LOG_DUMP("SEND: sd=%d, %d/%d bytes\n", user->net.connection.sd, sent, total);
if (sent == -1)
{
int err = net_error();
LOG_DUMP(" errno: %d - %s\n", err, net_error_string(err));
}
}
void debug_sendq_recv(struct hub_user* user, int received, int max, const char* buffer)
{
LOG_DUMP("RECV: %d/%d bytes\n", received, (int) max);
if (received == -1)
{
int err = net_error();
LOG_DUMP(" errno: %d - %s\n", err, net_error_string(err));
}
else if (received > 0)
{
char* data = hub_malloc_zero(received + 1);
memcpy(data, buffer, received);
LOG_DUMP("RECV: \"%s\"\n", data);
hub_free(data);
}
}
#endif
int handle_net_read(struct hub_user* user)
{
static char buf[MAX_RECV_BUF];
struct hub_recvq* q = user->recv_queue;
size_t buf_size = hub_recvq_get(q, buf, MAX_RECV_BUF);
ssize_t size = net_con_recv(user->connection, buf, MAX_RECV_BUF);
if (size > 0)
buf_size += size;
if (size < 0)
{
if (size == -1)
return quit_disconnected;
else
return quit_socket_error;
}
else if (size == 0)
{
return 0;
}
else
{
char* lastPos = 0;
char* start = buf;
char* pos = 0;
size_t remaining = buf_size;
while ((pos = memchr(start, '\n', remaining)))
{
lastPos = pos;
pos[0] = '\0';
#ifdef DEBUG_SENDQ
LOG_DUMP("PROC: \"%s\" (%d)\n", start, (int) (pos - start));
#endif
if (user_flag_get(user, flag_maxbuf))
{
user_flag_unset(user, flag_maxbuf);
}
else
{
if (((pos - start) > 0) && g_hub->config->max_recv_buffer > (pos - start))
{
if (hub_handle_message(g_hub, user, start, (pos - start)) == -1)
{
return quit_protocol_error;
}
}
}
pos[0] = '\n'; /* FIXME: not needed */
pos ++;
remaining -= (pos - start);
start = pos;
}
if (lastPos || remaining)
{
if (remaining < g_hub->config->max_recv_buffer)
{
hub_recvq_set(q, lastPos ? lastPos : buf, remaining);
}
else
{
hub_recvq_set(q, 0, 0);
user_flag_set(user, flag_maxbuf);
LOG_WARN("Received message past max_recv_buffer, dropping message.");
}
}
else
{
hub_recvq_set(q, 0, 0);
}
}
return 0;
}
int handle_net_write(struct hub_user* user)
{
int ret = 0;
while (hub_sendq_get_bytes(user->send_queue))
{
ret = hub_sendq_send(user->send_queue, user);
if (ret <= 0)
break;
}
if (ret < 0)
return quit_socket_error;
if (hub_sendq_get_bytes(user->send_queue))
{
user_net_io_want_write(user);
}
else
{
user_net_io_want_read(user);
}
return 0;
}
void net_event(struct net_connection* con, int event, void *arg)
{
struct hub_user* user = (struct hub_user*) arg;
int flag_close = 0;
#ifdef DEBUG_SENDQ
LOG_TRACE("net_event() : fd=%d, ev=%d, arg=%p", fd, (int) event, arg);
#endif
if (event == NET_EVENT_SOCKERROR)
{
hub_disconnect_user(g_hub, user, quit_socket_error);
return;
}
else if (event == NET_EVENT_CLOSED)
{
hub_disconnect_user(g_hub, user, quit_disconnected);
return;
}
else if (event == NET_EVENT_TIMEOUT)
{
if (user_is_connecting(user))
{
hub_disconnect_user(g_hub, user, quit_timeout);
return;
}
}
if (event & NET_EVENT_READ)
{
flag_close = handle_net_read(user);
if (flag_close)
{
hub_disconnect_user(g_hub, user, flag_close);
return;
}
}
if (event & NET_EVENT_WRITE)
{
flag_close = handle_net_write(user);
if (flag_close)
{
hub_disconnect_user(g_hub, user, flag_close);
return;
}
}
}
void net_on_accept(struct net_connection* con, int event, void *arg)
{
struct hub_info* hub = (struct hub_info*) arg;
struct hub_probe* probe = 0;
struct ip_addr_encap ipaddr;
const char* addr;
int server_fd = net_con_get_sd(con);
for (;;)
{
int fd = net_accept(server_fd, &ipaddr);
if (fd == -1)
{
if (net_error() == EWOULDBLOCK)
{
break;
}
else
{
LOG_ERROR("Accept error: %d %s", net_error(), strerror(net_error()));
break;
}
}
addr = ip_convert_to_string(&ipaddr);
/* FIXME: Should have a plugin log this */
LOG_TRACE("Got connection from %s", addr);
/* FIXME: A plugin should perform this check: is IP banned? */
if (acl_is_ip_banned(hub->acl, addr))
{
LOG_INFO("Denied [%s] (IP banned)", addr);
net_close(fd);
continue;
}
probe = probe_create(hub, fd, &ipaddr);
if (!probe)
{
LOG_ERROR("Unable to create probe after socket accepted. Out of memory?");
net_close(fd);
break;
}
}
}
-34
View File
@@ -1,34 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_NET_EVENT_H
#define HAVE_UHUB_NET_EVENT_H
/**
* Network callback to accept incoming connections.
*/
extern void net_on_accept(struct net_connection* con, int event, void *arg);
extern void net_event(struct net_connection* con, int event, void *arg);
extern int handle_net_read(struct hub_user* user);
extern int handle_net_write(struct hub_user* user);
#endif /* HAVE_UHUB_NET_EVENT_H */
-120
View File
@@ -1,120 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* 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/>.
*
*/
#include "uhub.h"
#include "probe.h"
#define PROBE_RECV_SIZE 12
static char probe_recvbuf[PROBE_RECV_SIZE];
static void probe_net_event(struct net_connection* con, int events, void *arg)
{
struct hub_probe* probe = (struct hub_probe*) net_con_get_ptr(con);
if (events == NET_EVENT_SOCKERROR || events == NET_EVENT_CLOSED || events == NET_EVENT_TIMEOUT)
{
probe_destroy(probe);
return;
}
if (events & NET_EVENT_READ)
{
int bytes = net_con_peek(con, probe_recvbuf, PROBE_RECV_SIZE);
if (bytes < 0)
{
probe_destroy(probe);
return;
}
if (bytes >= 4)
{
if (memcmp(probe_recvbuf, "HSUP", 4) == 0)
{
LOG_TRACE("Probed ADC");
if (user_create(probe->hub, probe->connection, &probe->addr))
{
probe->connection = 0;
}
probe_destroy(probe);
return;
}
#ifdef SSL_SUPPORT
if (bytes >= 11 &&
probe_recvbuf[0] == 22 &&
probe_recvbuf[1] == 3 && /* protocol major version */
probe_recvbuf[5] == 1 && /* message type */
probe_recvbuf[9] == probe_recvbuf[1] &&
probe_recvbuf[10] == probe_recvbuf[2])
{
if (probe->hub->config->tls_enable)
{
LOG_TRACE("Probed TLS %d.%d connection", (int) probe_recvbuf[1], (int) probe_recvbuf[2]);
if (user_create(probe->hub, probe->connection, &probe->addr))
{
probe->connection = 0;
}
net_con_ssl_handshake(con, net_con_ssl_mode_server, probe->hub->ssl_ctx);
}
else
{
LOG_TRACE("Probed TLS %d.%d connection. TLS disabled in hub.", (int) probe_recvbuf[1], (int) probe_recvbuf[2]);
}
probe_destroy(probe);
return;
}
else
{
LOG_TRACE("Probed TLS %d.%d connection", (int) probe_recvbuf[1], (int) probe_recvbuf[2]);
net_con_ssl_handshake(con, net_con_ssl_mode_server, probe->hub->ssl_ctx);
return;
}
#endif
probe_destroy(probe);
return;
}
}
}
struct hub_probe* probe_create(struct hub_info* hub, int sd, struct ip_addr_encap* addr)
{
struct hub_probe* probe = (struct hub_probe*) hub_malloc_zero(sizeof(struct hub_probe));
if (probe == NULL)
return NULL; /* OOM */
probe->hub = hub;
probe->connection = net_con_create();
net_con_initialize(probe->connection, sd, probe_net_event, probe, NET_EVENT_READ);
net_con_set_timeout(probe->connection, TIMEOUT_CONNECTED);
memcpy(&probe->addr, addr, sizeof(struct ip_addr_encap));
return probe;
}
void probe_destroy(struct hub_probe* probe)
{
if (probe->connection)
{
net_con_close(probe->connection);
probe->connection = 0;
}
hub_free(probe);
}
-35
View File
@@ -1,35 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_PROBE_H
#define HAVE_UHUB_PROBE_H
#include "uhub.h"
struct hub_probe
{
struct hub_info* hub; /** The hub instance this probe belong to */
struct net_connection* connection; /** Connection data */
struct ip_addr_encap addr; /** IP address */
};
extern struct hub_probe* probe_create(struct hub_info* hub, int sd, struct ip_addr_encap* addr);
extern void probe_destroy(struct hub_probe* probe);
#endif /* HAVE_UHUB_PROBE_H */
-228
View File
@@ -1,228 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#include "uhub.h"
int route_message(struct hub_info* hub, struct hub_user* u, struct adc_message* msg)
{
struct hub_user* target = NULL;
switch (msg->cache[0])
{
case 'B': /* Broadcast to all logged in clients */
route_to_all(hub, msg);
break;
case 'D':
target = uman_get_user_by_sid(hub, msg->target);
if (target)
{
route_to_user(hub, target, msg);
}
break;
case 'E':
target = uman_get_user_by_sid(hub, msg->target);
if (target)
{
route_to_user(hub, target, msg);
route_to_user(hub, u, msg);
}
break;
case 'F':
route_to_subscribers(hub, msg);
break;
default:
/* Ignore the message */
break;
}
return 0;
}
static inline size_t get_max_send_queue(struct hub_info* hub)
{
/* TODO: More dynamic send queue limit, for instance:
* return MAX(hub->config->max_send_buffer, (hub->config->max_recv_buffer * hub_get_user_count(hub)));
*/
return hub->config->max_send_buffer;
}
static inline size_t get_max_send_queue_soft(struct hub_info* hub)
{
return hub->config->max_send_buffer_soft;
}
/*
* @return 1 if send queue is OK.
* -1 if send queue is overflowed
* 0 if soft send queue is overflowed (not implemented at the moment)
*/
static inline int check_send_queue(struct hub_info* hub, struct hub_user* user, struct adc_message* msg)
{
if (user_flag_get(user, flag_user_list))
return 1;
if ((user->send_queue->size + msg->length) > get_max_send_queue(hub))
{
LOG_WARN("send queue overflowed, message discarded.");
return -1;
}
if (user->send_queue->size > get_max_send_queue_soft(hub))
{
LOG_WARN("send queue soft overflowed.");
return 0;
}
return 1;
}
int route_to_user(struct hub_info* hub, struct hub_user* user, struct adc_message* msg)
{
#ifdef DEBUG_SENDQ
char* data = strndup(msg->cache, msg->length-1);
LOG_PROTO("send %s: \"%s\"", sid_to_string(user->id.sid), data);
free(data);
#endif
if (!user->connection)
return 0;
if (hub_sendq_is_empty(user->send_queue) && !user_flag_get(user, flag_pipeline))
{
/* Perform oportunistic write */
hub_sendq_add(user->send_queue, msg);
handle_net_write(user);
}
else
{
if (check_send_queue(hub, user, msg) >= 0)
{
hub_sendq_add(user->send_queue, msg);
if (!user_flag_get(user, flag_pipeline))
user_net_io_want_write(user);
}
}
return 1;
}
int route_flush_pipeline(struct hub_info* hub, struct hub_user* u)
{
if (hub_sendq_is_empty(u->send_queue))
return 0;
handle_net_write(u);
user_flag_unset(u, flag_pipeline);
return 1;
}
int route_to_all(struct hub_info* hub, struct adc_message* command) /* iterate users */
{
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list);
while (user)
{
route_to_user(hub, user, command);
user = (struct hub_user*) list_get_next(hub->users->list);
}
return 0;
}
int route_to_subscribers(struct hub_info* hub, struct adc_message* command) /* iterate users */
{
int do_send;
char* tmp;
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list);
while (user)
{
if (user->feature_cast)
{
do_send = 1;
tmp = list_get_first(command->feature_cast_include);
while (tmp)
{
if (!user_have_feature_cast_support(user, tmp))
{
do_send = 0;
break;
}
tmp = list_get_next(command->feature_cast_include);;
}
if (!do_send) {
user = (struct hub_user*) list_get_next(hub->users->list);
continue;
}
tmp = list_get_first(command->feature_cast_exclude);
while (tmp)
{
if (user_have_feature_cast_support(user, tmp))
{
do_send = 0;
break;
}
tmp = list_get_next(command->feature_cast_exclude);
}
if (do_send)
{
route_to_user(hub, user, command);
}
}
user = (struct hub_user*) list_get_next(hub->users->list);
}
return 0;
}
int route_info_message(struct hub_info* hub, struct hub_user* u)
{
if (!user_is_nat_override(u))
{
return route_to_all(hub, u->info);
}
else
{
struct adc_message* cmd = adc_msg_copy(u->info);
const char* address = user_get_address(u);
struct hub_user* user = 0;
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
adc_msg_add_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR, address);
user = (struct hub_user*) list_get_first(hub->users->list);
while (user)
{
if (user_is_nat_override(user))
route_to_user(hub, user, cmd);
else
route_to_user(hub, user, u->info);
user = (struct hub_user*) list_get_next(hub->users->list);
}
adc_msg_free(cmd);
}
return 0;
}
-56
View File
@@ -1,56 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_ROUTE_H
#define HAVE_UHUB_ROUTE_H
/**
* Route a message by sending it to it's final destination.
*/
extern int route_message(struct hub_info* hub, struct hub_user* u, struct adc_message* msg);
/**
* Send queued messages.
*/
extern int route_flush_pipeline(struct hub_info* hub, struct hub_user* u);
/**
* Transmit message directly to one user.
*/
extern int route_to_user(struct hub_info* hub, struct hub_user*, struct adc_message* command);
/**
* Broadcast message to all users.
*/
extern int route_to_all(struct hub_info* hub, struct adc_message* command);
/**
* Broadcast message to all users subscribing to the type of message.
*/
extern int route_to_subscribers(struct hub_info* hub, struct adc_message* command);
/**
* Broadcast initial info message to all users.
* This will ensure the correct IP is seen by other users
* in case nat override is in use.
*/
extern int route_info_message(struct hub_info* hub, struct hub_user* user);
#endif /* HAVE_UHUB_ROUTE_H */
-349
View File
@@ -1,349 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#include "uhub.h"
#ifdef DEBUG_SENDQ
static const char* user_log_str(struct hub_user* user)
{
static char buf[128];
if (user)
{
snprintf(buf, 128, "user={ %p, \"%s\", %s/%s}", user, user->id.nick, sid_to_string(user->id.sid), user->id.cid);
}
else
{
snprintf(buf, 128, "user={ %p }", user);
}
return buf;
}
#endif
struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, struct ip_addr_encap* addr)
{
struct hub_user* user = NULL;
LOG_TRACE("user_create(), hub=%p, con[sd=%d]", hub, net_con_get_sd(con));
user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
if (user == NULL)
return NULL; /* OOM */
user->send_queue = hub_sendq_create();
user->recv_queue = hub_recvq_create();
user->connection = con;
net_con_reinitialize(user->connection, net_event, user, NET_EVENT_READ);
memcpy(&user->id.addr, addr, sizeof(struct ip_addr_encap));
user_set_state(user, state_protocol);
return user;
}
void user_destroy(struct hub_user* user)
{
LOG_TRACE("user_destroy(), user=%p", user);
hub_recvq_destroy(user->recv_queue);
hub_sendq_destroy(user->send_queue);
adc_msg_free(user->info);
user_clear_feature_cast_support(user);
hub_free(user);
}
void user_set_state(struct hub_user* user, enum user_state state)
{
if ((user->state == state_cleanup && state != state_disconnected) || (user->state == state_disconnected))
{
return;
}
user->state = state;
}
void user_set_info(struct hub_user* user, struct adc_message* cmd)
{
adc_msg_free(user->info);
user->info = adc_msg_incref(cmd);
}
void user_update_info(struct hub_user* u, struct adc_message* cmd)
{
char prefix[2];
char* argument;
size_t n = 0;
struct adc_message* cmd_new = adc_msg_copy(u->info);
if (!cmd_new)
{
/* FIXME: OOM! */
return;
}
/*
* FIXME: Optimization potential:
*
* remove parts of cmd that do not really change anything in cmd_new.
* this can save bandwidth if clients send multiple updates for information
* that does not really change anything.
*/
argument = adc_msg_get_argument(cmd, n++);
while (argument)
{
if (strlen(argument) >= 2)
{
prefix[0] = argument[0];
prefix[1] = argument[1];
adc_msg_replace_named_argument(cmd_new, prefix, argument+2);
}
hub_free(argument);
argument = adc_msg_get_argument(cmd, n++);
}
user_set_info(u, cmd_new);
adc_msg_free(cmd_new);
}
static int convert_support_fourcc(int fourcc)
{
switch (fourcc)
{
case FOURCC('B','A','S','0'): /* Obsolete */
#ifndef OLD_ADC_SUPPORT
return 0;
#endif
case FOURCC('B','A','S','E'):
return feature_base;
case FOURCC('A','U','T','0'):
return feature_auto;
case FOURCC('U','C','M','0'):
case FOURCC('U','C','M','D'):
return feature_ucmd;
case FOURCC('Z','L','I','F'):
return feature_zlif;
case FOURCC('B','B','S','0'):
return feature_bbs;
case FOURCC('T','I','G','R'):
return feature_tiger;
case FOURCC('B','L','O','M'):
case FOURCC('B','L','O','0'):
return feature_bloom;
case FOURCC('P','I','N','G'):
return feature_ping;
case FOURCC('L','I','N','K'):
return feature_link;
case FOURCC('A','D','C','S'):
return feature_adcs;
default:
LOG_DEBUG("Unknown extension: %x", fourcc);
return 0;
}
}
void user_support_add(struct hub_user* user, int fourcc)
{
int feature_mask = convert_support_fourcc(fourcc);
user->flags |= feature_mask;
}
int user_flag_get(struct hub_user* user, enum user_flags flag)
{
return user->flags & flag;
}
void user_flag_set(struct hub_user* user, enum user_flags flag)
{
user->flags |= flag;
}
void user_flag_unset(struct hub_user* user, enum user_flags flag)
{
user->flags &= ~flag;
}
void user_set_nat_override(struct hub_user* user)
{
user_flag_set(user, flag_nat);
}
int user_is_nat_override(struct hub_user* user)
{
return user_flag_get(user, flag_nat);
}
void user_support_remove(struct hub_user* user, int fourcc)
{
int feature_mask = convert_support_fourcc(fourcc);
user->flags &= ~feature_mask;
}
int user_have_feature_cast_support(struct hub_user* user, char feature[4])
{
char* tmp = list_get_first(user->feature_cast);
while (tmp)
{
if (strncmp(tmp, feature, 4) == 0)
return 1;
tmp = list_get_next(user->feature_cast);
}
return 0;
}
int user_set_feature_cast_support(struct hub_user* u, char feature[4])
{
if (!u->feature_cast)
{
u->feature_cast = list_create();
}
if (!u->feature_cast)
{
return 0; /* OOM! */
}
list_append(u->feature_cast, hub_strndup(feature, 4));
return 1;
}
void user_clear_feature_cast_support(struct hub_user* u)
{
if (u->feature_cast)
{
list_clear(u->feature_cast, &hub_free);
list_destroy(u->feature_cast);
u->feature_cast = 0;
}
}
int user_is_logged_in(struct hub_user* user)
{
if (user->state == state_normal)
return 1;
return 0;
}
int user_is_connecting(struct hub_user* user)
{
if (user->state == state_protocol || user->state == state_identify || user->state == state_verify)
return 1;
return 0;
}
int user_is_protocol_negotiating(struct hub_user* user)
{
if (user->state == state_protocol)
return 1;
return 0;
}
int user_is_disconnecting(struct hub_user* user)
{
if (user->state == state_cleanup || user->state == state_disconnected)
return 1;
return 0;
}
int user_is_protected(struct hub_user* user)
{
switch (user->credentials)
{
case cred_bot:
case cred_operator:
case cred_super:
case cred_admin:
case cred_link:
return 1;
default:
break;
}
return 0;
}
/**
* Returns 1 if a user is registered.
* Only registered users will be let in if the hub is configured for registered
* users only.
*/
int user_is_registered(struct hub_user* user)
{
switch (user->credentials)
{
case cred_bot:
case cred_user:
case cred_operator:
case cred_super:
case cred_admin:
case cred_link:
return 1;
default:
break;
}
return 0;
}
void user_net_io_want_write(struct hub_user* user)
{
net_con_update(user->connection, NET_EVENT_READ | NET_EVENT_WRITE);
}
void user_net_io_want_read(struct hub_user* user)
{
net_con_update(user->connection, NET_EVENT_READ);
}
const char* user_get_quit_reason_string(enum user_quit_reason reason)
{
switch (reason)
{
case quit_unknown: return "unknown"; break;
case quit_disconnected: return "disconnected"; break;
case quit_kicked: return "kicked"; break;
case quit_banned: return "banned"; break;
case quit_timeout: return "timeout"; break;
case quit_send_queue: return "send queue"; break;
case quit_memory_error: return "out of memory"; break;
case quit_socket_error: return "socket error"; break;
case quit_protocol_error: return "protocol error"; break;
case quit_logon_error: return "login error"; break;
case quit_hub_disabled: return "hub disabled"; break;
case quit_ghost_timeout: return "ghost"; break;
}
return "unknown";
}
const char* user_get_address(struct hub_user* user)
{
return ip_convert_to_string(&user->id.addr);
}
-268
View File
@@ -1,268 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_USER_H
#define HAVE_UHUB_USER_H
struct hub_info;
struct hub_iobuf;
enum user_state
{
state_protocol = 0, /**<< "User must send a valid protocol handshake" */
state_identify = 1, /**<< "User must send identification message (INF) " */
state_verify = 2, /**<< "User must send password to verify identification" */
state_normal = 3, /**<< "User is logged in." */
state_cleanup = 4, /**<< "User is disconnected, but other users need to be notified." */
state_disconnected = 5, /**<< "User is disconnected" */
};
enum user_flags
{
feature_base = 0x00000001, /** BASE: Basic configuration (required by all clients) */
feature_auto = 0x00000002, /** AUT0: Automatic nat detection traversal */
feature_bbs = 0x00000004, /** BBS0: Bulletin board system (not supported) */
feature_ucmd = 0x00000008, /** UCMD: User commands (not supported by this software) */
feature_zlif = 0x00000010, /** ZLIF: gzip stream compression (not supported) */
feature_tiger = 0x00000020, /** TIGR: Client supports the tiger hash algorithm */
feature_bloom = 0x00000040, /** BLO0: Bloom filter (not supported) */
feature_ping = 0x00000080, /** PING: Hub pinger information extension */
feature_link = 0x00000100, /** LINK: Hub link (not supported) */
feature_adcs = 0x00000200, /** ADCS: ADC over TLS/SSL */
flag_ignore = 0x01000000, /** Ignore further reads */
flag_maxbuf = 0x02000000, /** Hit max buf read, ignore msg */
flag_choke = 0x04000000, /** Choked: Cannot send, waiting for write event */
flag_want_read = 0x08000000, /** Need to read (SSL) */
flag_want_write = 0x10000000, /** Need to write (SSL) */
flag_user_list = 0x20000000, /** Send queue bypass (when receiving the send queue) */
flag_pipeline = 0x40000000, /** Hub message pipelining */
flag_nat = 0x80000000, /** nat override enabled */
};
enum user_quit_reason
{
quit_unknown = 0,
quit_disconnected = 1, /** User disconnected */
quit_kicked = 2, /** User was kicked */
quit_banned = 3, /** User was banned */
quit_timeout = 4, /** User timed out (no data for a while) */
quit_send_queue = 5, /** User's send queue was overflowed */
quit_memory_error = 6, /** Not enough memory available */
quit_socket_error = 7, /** A socket error occured */
quit_protocol_error = 8, /** Fatal protocol error */
quit_logon_error = 9, /** Unable to login (wrong password, CID/PID, etc) */
quit_hub_disabled = 10, /** Hub is disabled. No new connections allowed */
quit_ghost_timeout = 11, /** The user is a ghost, and trying to login from another connection */
};
/** Returns an apropriate string for the given quit reason */
extern const char* user_get_quit_reason_string(enum user_quit_reason);
struct hub_user_info
{
sid_t sid; /** session ID */
char cid[MAX_CID_LEN+1]; /** global client ID */
char nick[MAX_NICK_LEN+1]; /** User's nick name */
struct ip_addr_encap addr; /** User's IP address */
};
/**
* This struct contains additional information about the user, such
* as the number of bytes and files shared, and the number of hubs the
* user is connected to, etc.
*/
struct hub_user_limits
{
uint64_t shared_size; /** Shared size in bytes */
size_t shared_files; /** The number of shared files */
size_t upload_slots; /** The number of upload slots */
size_t hub_count_user; /** The number of hubs connected as user */
size_t hub_count_registered; /** The number of hubs connected as registered user */
size_t hub_count_operator; /** The number of hubs connected as operator */
size_t hub_count_total; /** The number of hubs connected to in total */
};
struct hub_user
{
enum user_state state; /** see enum user_state */
enum user_credentials credentials; /** see enum user_credentials */
struct hub_user_info id; /** Contains nick name and CID */
uint32_t flags; /** see enum user_features */
char user_agent[MAX_UA_LEN+1];/** User agent string */
struct linked_list* feature_cast; /** Features supported by feature cast */
struct adc_message* info; /** ADC 'INF' message (broadcasted to everyone joining the hub) */
struct hub_info* hub; /** The hub instance this user belong to */
struct hub_recvq* recv_queue;
struct hub_sendq* send_queue;
struct net_connection* connection; /** Connection data */
struct hub_user_limits limits; /** Data used for limitation */
enum user_quit_reason quit_reason; /** Quit reason (see user_quit_reason) */
};
/**
* Create a user with the given socket descriptor.
* This basically only allocates memory and initializes all variables
* to an initial state.
*
* state is set to state_protocol.
*
* @param sd socket descriptor associated with the user
* @return User object or NULL if not enough memory is available.
*/
extern struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, struct ip_addr_encap* addr);
/**
* Delete a user.
*
* !WRONG! If the user is logged in a quit message is issued.
*/
extern void user_destroy(struct hub_user* user);
/**
* This associates a INF message to the user.
* If the user already has a INF message associated, then this is
* released before setting the new one.
*
* @param info new inf message (can be NULL)
*/
extern void user_set_info(struct hub_user* user, struct adc_message* info);
/**
* Update a user's INF message.
* Will parse replace all ellements in the user's inf message with
* the parameters from the cmd (merge operation).
*/
extern void user_update_info(struct hub_user* user, struct adc_message* cmd);
/**
* Specify a user's state.
* NOTE: DON'T, unless you know what you are doing.
*/
extern void user_set_state(struct hub_user* user, enum user_state);
/**
* Returns 1 if the user is in state state_normal, or 0 otherwise.
*/
extern int user_is_logged_in(struct hub_user* user);
/**
* Returns 1 if the user is in state_protocol.
* Returns 0 otherwise.
*/
extern int user_is_protocol_negotiating(struct hub_user* user);
/**
* Returns 1 if the user is in state_protocol, state_identify or state_verify.
* Returns 0 otherwise.
*/
extern int user_is_connecting(struct hub_user* user);
/**
* Returns 1 only if the user is in state_cleanup or state_disconnected.
*/
extern int user_is_disconnecting(struct hub_user* user);
/**
* Returns 1 if a user is protected, which includes users
* having any form of elevated privileges.
*/
extern int user_is_protected(struct hub_user* user);
/**
* Returns 1 if a user is registered, with or without privileges.
*/
extern int user_is_registered(struct hub_user* user);
/**
* User supports the protocol extension as given in fourcc.
* This is usually set while the user is connecting, but can
* also be used to subscribe to a new class of messages from the
* hub.
*
* @see enum user_flags
*/
extern void user_support_add(struct hub_user* user, int fourcc);
/**
* User no longer supports the protocol extension as given in fourcc.
* This can be used to unsubscribe to certain messages generated by
* the hub.
* @see enum user_flags
*/
extern void user_support_remove(struct hub_user* user, int fourcc);
extern const char* user_get_address(struct hub_user* user);
/**
* Sets the nat override flag for a user, this allows users on the same
* subnet as a natted hub to spoof their IP in order to use active mode
* on a natted hub.
*/
extern void user_set_nat_override(struct hub_user* user);
extern int user_is_nat_override(struct hub_user* user);
/**
* Set a flag. @see enum user_flags
*/
extern void user_flag_set(struct hub_user* user, enum user_flags flag);
extern void user_flag_unset(struct hub_user* user, enum user_flags flag);
/**
* Get a flag. @see enum user_flags
*/
extern int user_flag_get(struct hub_user* user, enum user_flags flag);
/**
* Check if a user supports 'feature' for feature casting (basis for 'Fxxx' messages)
* The feature cast is specified as the 'SU' argument to the user's
* INF-message.
*
* @param feature a feature to lookup (example: 'TCP4' or 'UDP4')
* @return 1 if 'feature' supported, or 0 otherwise
*/
extern int user_have_feature_cast_support(struct hub_user* user, char feature[4]);
/**
* Set feature cast support for feature.
*
* @param feature a feature to lookup (example: 'TCP4' or 'UDP4')
* @return 1 if 'feature' supported, or 0 otherwise
*/
extern int user_set_feature_cast_support(struct hub_user* u, char feature[4]);
/**
* Remove all feature cast support features.
*/
extern void user_clear_feature_cast_support(struct hub_user* u);
/**
* Mark the user with a want-write flag, meaning it should poll for writability.
*/
extern void user_net_io_want_write(struct hub_user* user);
/**
* Mark the user with a want read flag, meaning it should poll for readability.
*/
extern void user_net_io_want_read(struct hub_user* user);
#endif /* HAVE_UHUB_USER_H */
-290
View File
@@ -1,290 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#include "uhub.h"
#define USERMANAGER_TIMER
/*
* This callback function is used to clear user objects from the userlist.
* Should only be used in uman_shutdown().
*/
static void clear_user_list_callback(void* ptr)
{
if (ptr)
{
struct hub_user* u = (struct hub_user*) ptr;
/* Mark the user as already being disconnected.
* This prevents the hub from trying to send
* quit messages to other users.
*/
u->credentials = cred_none;
user_destroy(u);
}
}
void uman_update_stats(struct hub_info* hub)
{
const int factor = TIMEOUT_STATS;
struct net_statistics* total;
struct net_statistics* intermediate;
net_stats_get(&intermediate, &total);
hub->stats.net_tx = (intermediate->tx / factor);
hub->stats.net_rx = (intermediate->rx / factor);
hub->stats.net_tx_peak = MAX(hub->stats.net_tx, hub->stats.net_tx_peak);
hub->stats.net_rx_peak = MAX(hub->stats.net_rx, hub->stats.net_rx_peak);
hub->stats.net_tx_total = total->tx;
hub->stats.net_rx_total = total->rx;
net_stats_reset();
}
void uman_print_stats(struct hub_info* hub)
{
LOG_INFO("Statistics users=" PRINTF_SIZE_T " (peak_users=" PRINTF_SIZE_T "), net_tx=%d KB/s, net_rx=%d KB/s (peak_tx=%d KB/s, peak_rx=%d KB/s)",
hub->users->count,
hub->users->count_peak,
(int) hub->stats.net_tx / 1024,
(int) hub->stats.net_rx / 1024,
(int) hub->stats.net_tx_peak / 1024,
(int) hub->stats.net_rx_peak / 1024);
}
#ifdef USERMANAGER_TIMER
#ifdef USE_LIBEVENT
static void timer_statistics(int fd, short ev, void *arg)
{
struct hub_info* hub = (struct hub_info*) arg;
struct timeval timeout = { TIMEOUT_STATS, 0 };
uman_update_stats(hub);
evtimer_set(&hub->ev_timer, timer_statistics, hub);
evtimer_add(&hub->ev_timer, &timeout);
}
#endif
#endif
int uman_init(struct hub_info* hub)
{
struct hub_user_manager* users = NULL;
#ifdef USERMANAGER_TIMER
#ifdef USE_LIBEVENT
struct timeval timeout = { TIMEOUT_STATS, 0 };
#endif
#endif
if (!hub)
return -1;
users = (struct hub_user_manager*) hub_malloc_zero(sizeof(struct hub_user_manager));
if (!users)
return -1;
users->list = list_create();
users->sids = sid_pool_create(net_get_max_sockets());
if (!users->list)
{
list_destroy(users->list);
hub_free(users);
return -1;
}
hub->users = users;
#ifdef USERMANAGER_TIMER
#ifdef USE_LIBEVENT
if (net_get_evbase())
{
evtimer_set(&hub->ev_timer, timer_statistics, hub);
evtimer_add(&hub->ev_timer, &timeout);
}
#endif
#endif // 0
return 0;
}
int uman_shutdown(struct hub_info* hub)
{
if (!hub || !hub->users)
return -1;
#ifdef USERMANAGER_TIMER
#ifdef USE_LIBEVENT
if (evtimer_pending(&hub->ev_timer, 0))
evtimer_del(&hub->ev_timer);
#endif
#endif
if (hub->users->list)
{
list_clear(hub->users->list, &clear_user_list_callback);
list_destroy(hub->users->list);
}
sid_pool_destroy(hub->users->sids);
hub_free(hub->users);
hub->users = 0;
return 0;
}
int uman_add(struct hub_info* hub, struct hub_user* user)
{
if (!hub || !user)
return -1;
if (user->hub)
return -1;
list_append(hub->users->list, user);
hub->users->count++;
hub->users->count_peak = MAX(hub->users->count, hub->users->count_peak);
hub->users->shared_size += user->limits.shared_size;
hub->users->shared_files += user->limits.shared_files;
user->hub = hub;
return 0;
}
int uman_remove(struct hub_info* hub, struct hub_user* user)
{
if (!hub || !user)
return -1;
list_remove(hub->users->list, user);
if (hub->users->count > 0)
{
hub->users->count--;
}
else
{
assert(!"negative count!");
}
hub->users->shared_size -= user->limits.shared_size;
hub->users->shared_files -= user->limits.shared_files;
user->hub = 0;
return 0;
}
struct hub_user* uman_get_user_by_sid(struct hub_info* hub, sid_t sid)
{
return sid_lookup(hub->users->sids, sid);
}
struct hub_user* uman_get_user_by_cid(struct hub_info* hub, const char* cid)
{
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list); /* iterate users - only on incoming INF msg */
while (user)
{
if (strcmp(user->id.cid, cid) == 0)
return user;
user = (struct hub_user*) list_get_next(hub->users->list);
}
return NULL;
}
struct hub_user* uman_get_user_by_nick(struct hub_info* hub, const char* nick)
{
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list); /* iterate users - only on incoming INF msg */
while (user)
{
if (strcmp(user->id.nick, nick) == 0)
return user;
user = (struct hub_user*) list_get_next(hub->users->list);
}
return NULL;
}
size_t uman_get_user_by_addr(struct hub_info* hub, struct linked_list* users, struct ip_range* range)
{
size_t num = 0;
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list); /* iterate users - only on incoming INF msg */
while (user)
{
if (ip_in_range(&user->id.addr, range))
{
list_append(users, user);
num++;
}
user = (struct hub_user*) list_get_next(hub->users->list);
}
return num;
}
int uman_send_user_list(struct hub_info* hub, struct hub_user* target)
{
int ret = 1;
user_flag_set(target, flag_user_list);
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list); /* iterate users - only on INF or PAS msg */
while (user)
{
if (user_is_logged_in(user))
{
ret = route_to_user(hub, target, user->info);
if (!ret)
break;
}
user = (struct hub_user*) list_get_next(hub->users->list);
}
#if 0
FIXME: FIXME FIXME handle send queue excess
if (!target->send_queue_size)
{
user_flag_unset(target, flag_user_list);
}
#endif
return ret;
}
void uman_send_quit_message(struct hub_info* hub, struct hub_user* leaving)
{
struct adc_message* command = adc_msg_construct(ADC_CMD_IQUI, 6);
adc_msg_add_argument(command, (const char*) sid_to_string(leaving->id.sid));
if (leaving->quit_reason == quit_banned || leaving->quit_reason == quit_kicked)
{
adc_msg_add_argument(command, ADC_QUI_FLAG_DISCONNECT);
}
route_to_all(hub, command);
adc_msg_free(command);
}
sid_t uman_get_free_sid(struct hub_info* hub, struct hub_user* user)
{
sid_t sid = sid_alloc(hub->users->sids, user);
user->id.sid = sid;
return sid;
}
-124
View File
@@ -1,124 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_USER_MANAGER_H
#define HAVE_UHUB_USER_MANAGER_H
struct hub_user_manager
{
size_t count; /**<< "Number of all fully connected and logged in users" */
size_t count_peak; /**<< "Peak number of users" */
struct sid_pool* sids;
uint64_t shared_size; /**<< "The total number of shared bytes among fully connected users." */
uint64_t shared_files; /**<< "The total number of shared files among fully connected users." */
struct linked_list* list; /**<< "Contains all logged in users" */
};
/**
* Initializes the user manager.
* @return 0 on success, or -1 if error (out of memory).
*/
extern int uman_init(struct hub_info* hub);
/**
* Shuts down the user manager.
* All users will be disconnected and deleted as part of this.
*
* @return 0 on success, or -1 in an error occured (hub is invalid).
*/
extern int uman_shutdown(struct hub_info* hub);
/**
* Generate statistics for logfiles.
*/
extern void uman_update_stats(struct hub_info* hub);
extern void uman_print_stats(struct hub_info* hub);
/**
* Add a user to the user manager.
*
* @param hub The hub to add the user to
* @param user The user to be added to the hub.
*/
extern int uman_add(struct hub_info* hub, struct hub_user* user);
/**
* Remove a user from the user manager.
* This user is connected, and will be moved to the leaving queue, pending
* all messages in the message queue, and resource cleanup.
*
* @return 0 if successfully removed, -1 if error.
*/
extern int uman_remove(struct hub_info* hub, struct hub_user* user);
/**
* Returns and allocates an unused session ID (SID).
*/
extern sid_t uman_get_free_sid(struct hub_info* hub, struct hub_user* user);
/**
* Lookup a user based on the session ID (SID).
*
* NOTE: This function will only search connected users, which means
* that SIDs assigned to users who are not yet completely logged in,
* or are in the process of being disconnected will result in this
* function returning NULL even though the sid is not freely available.
*
* FIXME: Is that really safe / sensible ?
* - Makes sense from a message routing point of view.
*
* @return a user if found, or NULL if not found
*/
extern struct hub_user* uman_get_user_by_sid(struct hub_info* hub, sid_t sid);
/**
* Lookup a user based on the client ID (CID).
* @return a user if found, or NULL if not found
*/
extern struct hub_user* uman_get_user_by_cid(struct hub_info* hub, const char* cid);
/**
* Lookup a user based on the nick name.
* @return a user if found, or NULL if not found
*/
extern struct hub_user* uman_get_user_by_nick(struct hub_info* hub, const char* nick);
/**
* Lookup users based on an ip address range.
*
* @return The number of users matching the addressess, or -1 on error (mask is wrong).
*/
extern size_t uman_get_user_by_addr(struct hub_info* hub, struct linked_list* users, struct ip_range* range);
/**
* Send the user list of connected clients to 'user'.
* Usually part of the login process.
*
* @return 1 if sending the user list succeeded, 0 otherwise.
*/
extern int uman_send_user_list(struct hub_info* hub, struct hub_user* user);
/**
* Send a quit message to all connected users when 'user' is
* leaving the hub (for whatever reason).
*/
extern void uman_send_quit_message(struct hub_info* hub, struct hub_user* user);
#endif /* HAVE_UHUB_USER_MANAGER_H */
-39
View File
@@ -1,39 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_NETWORK_BACKEND_H
#define HAVE_UHUB_NETWORK_BACKEND_H
/**
* Initialize the network backend.
* Returns 1 on success, or 0 on failure.
*/
extern int net_backend_initialize();
/**
* Shutdown the network connection backend.
*/
extern void net_backend_shutdown();
/**
* Process the network backend.
*/
extern int net_backend_process();
#endif /* HAVE_UHUB_NETWORK_BACKEND_H */
-37
View File
@@ -1,37 +0,0 @@
#define NET_WANT_READ NET_EVENT_READ
#define NET_WANT_WRITE NET_EVENT_WRITE
#define NET_WANT_ACCEPT 0x0008
#define NET_WANT_SSL_READ 0x0010
#define NET_WANT_SSL_WRITE 0x0020
#define NET_WANT_SSL_ACCEPT 0x0040
#define NET_WANT_SSL_CONNECT 0x0080
#define NET_WANT_SSL_X509_LOOKUP 0x0100
#define NET_PROCESSING_BUSY 0x8000
#define NET_CLEANUP 0x4000
#define NET_INITIALIZED 0x2000
#define NET_TIMER_ENABLED 0x1000
/* FIXME: Meant for debugging */
#define NET_EVENT_SET 0x0800
#define NET_CON_STRUCT_BASIC \
int sd; /** socket descriptor */ \
uint32_t flags; /** Connection flags */ \
void* ptr; /** data pointer */ \
net_connection_cb callback; /** Callback function */ \
#define NET_CON_STRUCT_SSL \
SSL* ssl; /** SSL handle */ \
size_t write_len; /** Length of last SSL_write(), only used if flags is NET_WANT_SSL_READ. */ \
#ifdef USE_SSL
#define NET_CON_STRUCT_COMMON \
NET_CON_STRUCT_BASIC \
NET_CON_STRUCT_SSL
#else
#define NET_CON_STRUCT_COMMON \
NET_CON_STRUCT_BASIC
#endif
-210
View File
@@ -1,210 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* 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/>.
*
*/
#include "uhub.h"
#include "network/common.h"
#ifdef SSL_SUPPORT
static int handle_openssl_error(struct net_connection* con, int ret)
{
uhub_assert(con);
int error = SSL_get_error(net_con_get_ssl(con), ret);
switch (error)
{
case SSL_ERROR_ZERO_RETURN:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_ZERO_RETURN", ret, error);
return -1;
case SSL_ERROR_WANT_READ:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_READ", ret, error);
net_con_update(con, NET_EVENT_READ | NET_WANT_SSL_READ);
return 0;
case SSL_ERROR_WANT_WRITE:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_WRITE", ret, error);
net_con_update(con, NET_EVENT_READ | NET_EVENT_WRITE | NET_WANT_SSL_WRITE);
return 0;
case SSL_ERROR_WANT_CONNECT:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_CONNECT", ret, error);
net_con_update(con, NET_EVENT_READ | NET_EVENT_WRITE | NET_WANT_SSL_CONNECT);
return 0;
case SSL_ERROR_WANT_ACCEPT:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_ACCEPT", ret, error);
net_con_update(con, NET_EVENT_READ | NET_EVENT_WRITE | NET_WANT_SSL_ACCEPT);
return 0;
case SSL_ERROR_WANT_X509_LOOKUP:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_X509_LOOKUP", ret, error);
return 0;
case SSL_ERROR_SYSCALL:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SYSCALL", ret, error);
/* if ret == 0, connection closed, if ret == -1, check with errno */
if (ret == 0)
return -1;
else
return -net_error();
case SSL_ERROR_SSL:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SSL", ret, error);
/* internal openssl error */
return -1;
}
return -1;
}
ssize_t net_con_ssl_accept(struct net_connection* con)
{
uhub_assert(con);
ssize_t ret = SSL_accept(net_con_get_ssl(con));
#ifdef NETWORK_DUMP_DEBUG
LOG_PROTO("SSL_accept() ret=%d", ret);
#endif
if (ret > 0)
{
net_con_update(con, NET_EVENT_READ);
}
else
{
return handle_openssl_error(con, ret);
}
return ret;
}
ssize_t net_con_ssl_connect(struct net_connection* con)
{
uhub_assert(con);
ssize_t ret = SSL_connect(net_con_get_ssl(con));
#ifdef NETWORK_DUMP_DEBUG
LOG_PROTO("SSL_connect() ret=%d", ret);
#endif
if (ret > 0)
{
net_con_update(con, NET_EVENT_READ);
}
else
{
return handle_openssl_error(con, ret);
}
return ret;
}
ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode ssl_mode, SSL_CTX* ssl_ctx)
{
uhub_assert(con);
SSL* ssl = 0;
if (ssl_mode == net_con_ssl_mode_server)
{
ssl = SSL_new(ssl_ctx);
SSL_set_fd(ssl, net_con_get_sd(con));
net_con_set_ssl(con, ssl);
return net_con_ssl_accept(con);
}
else
{
ssl = SSL_new(SSL_CTX_new(TLSv1_method()));
SSL_set_fd(ssl, net_con_get_sd(con));
net_con_set_ssl(con, ssl);
return net_con_ssl_connect(con);
}
}
#endif /* SSL_SUPPORT */
ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
{
int ret = net_send(net_con_get_sd(con), buf, len, UHUB_SEND_SIGNAL);
if (ret == -1)
{
if (net_error() == EWOULDBLOCK || net_error() == EINTR)
return 0;
return -1;
}
return ret;
}
ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
{
uhub_assert(con);
#ifdef SSL_SUPPORT
if (!net_con_is_ssl(con))
{
#endif
int ret = net_recv(net_con_get_sd(con), buf, len, 0);
#ifdef NETWORK_DUMP_DEBUG
LOG_PROTO("net_recv: ret=%d", ret);
#endif
if (ret == -1)
{
if (net_error() == EWOULDBLOCK || net_error() == EINTR)
return 0;
return -net_error();
}
else if (ret == 0)
{
return -1;
}
return ret;
#ifdef SSL_SUPPORT
}
else
{
int ret = SSL_read(net_con_get_ssl(con), buf, len);
#ifdef NETWORK_DUMP_DEBUG
LOG_PROTO("net_recv: ret=%d", ret);
#endif
if (ret > 0)
{
net_con_update(con, NET_EVENT_READ);
}
else
{
return -handle_openssl_error(con, ret);
}
return ret;
}
#endif
}
ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len)
{
int ret = net_recv(net_con_get_sd(con), buf, len, MSG_PEEK);
if (ret == -1)
{
if (net_error() == EWOULDBLOCK || net_error() == EINTR)
return 0;
return -net_error();
}
else if (ret == 0)
return -1;
return ret;
}
-110
View File
@@ -1,110 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_NETWORK_CONNECTION_H
#define HAVE_UHUB_NETWORK_CONNECTION_H
#include "uhub.h"
#include "network/backend.h"
#define NET_EVENT_TIMEOUT 0x0001
#define NET_EVENT_READ 0x0002
#define NET_EVENT_WRITE 0x0004
#define NET_EVENT_SOCKERROR 0x1000 /* Socket error, closed */
#define NET_EVENT_CLOSED 0x2000 /* Socket closed */
struct net_connection;
typedef void (*net_connection_cb)(struct net_connection*, int event, void* ptr);
extern int net_con_get_sd(struct net_connection* con);
extern void* net_con_get_ptr(struct net_connection* con);
extern struct net_connection* net_con_create();
extern void net_con_destroy(struct net_connection*);
extern void net_con_initialize(struct net_connection* con, int sd, net_connection_cb callback, const void* ptr, int events);
extern void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events);
extern void net_con_update(struct net_connection* con, int events);
/**
* Close the connection.
* This will ensure a connection is closed properly and will generate a NET_EVENT_DESTROYED event which indicates
* that the con can safely be deleted (or set to NULL).
* @returns 1 if the memory pointed to by con can be freed immediately, or 0 if it needs to go through the NET_EVENT_DESTROYED event.
*/
extern int net_con_close(struct net_connection* con);
/**
* Send data
*
* @return returns the number of bytes sent.
* 0 if no data is sent, and this function should be called again (EWOULDBLOCK/EINTR)
* <0 if an error occured, the negative number contains the error code.
*/
extern ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len);
/**
* Receive data
*
* @return returns the number of bytes sent.
* 0 if no data is sent, and this function should be called again (EWOULDBLOCK/EINTR)
* <0 if an error occured, the negative number contains the error code.
*/
extern ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len);
/**
* Receive data without removing them from the recv() buffer.
* NOTE: This does not currently work for SSL connections after the SSL handshake has been
* performed.
*/
extern ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len);
/**
* Set timeout for connetion.
*
* @param seconds the number of seconds into the future.
*/
extern void net_con_set_timeout(struct net_connection* con, int seconds);
extern void net_con_clear_timeout(struct net_connection* con);
#ifdef SSL_SUPPORT
/**
* Start SSL_accept()
*/
extern ssize_t net_con_ssl_accept(struct net_connection*);
/**
* Start SSL_connect()
*/
extern ssize_t net_con_ssl_connect(struct net_connection*);
enum net_con_ssl_mode
{
net_con_ssl_mode_server,
net_con_ssl_mode_client,
};
extern ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode, SSL_CTX* ssl_ctx);
extern int net_con_is_ssl(struct net_connection* con);
extern SSL* net_con_get_ssl(struct net_connection* con);
extern void net_con_set_ssl(struct net_connection* con, SSL*);
#endif /* SSL_SUPPORT */
#endif /* HAVE_UHUB_NETWORK_CONNECTION_H */
-306
View File
@@ -1,306 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* 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/>.
*
*/
#include "uhub.h"
#ifdef USE_EPOLL
#include "network/connection.h"
#include "network/common.h"
#include "network/backend.h"
#define EPOLL_EVBUFFER 512
struct net_connection
{
int sd;
uint32_t flags;
net_connection_cb callback;
void* ptr;
struct epoll_event ev;
struct timeout_evt* timeout;
#ifdef SSL_SUPPORT
SSL* ssl;
size_t write_len; /** Length of last SSL_write(), only used if flags is NET_WANT_SSL_READ. */
#endif
};
struct net_backend
{
int epfd;
size_t num;
size_t max;
struct net_connection** conns;
struct epoll_event events[EPOLL_EVBUFFER];
time_t now;
struct timeout_queue timeout_queue;
};
static struct net_backend* g_backend = 0;
static void net_con_print(const char* prefix, struct net_connection* con)
{
char buf[512];
int off = snprintf(buf, 512, "%s: net_connection={ sd=%d, flags=%u, callback=%p, ptr=%p, ev={ events=%s%s, data.ptr=%p }",
prefix, con->sd, con->flags, con->callback, con->ptr, (con->ev.events & EPOLLIN ? "R" : ""),(con->ev.events & EPOLLOUT ? "W" : "") , con->ev.data.ptr);
if (con->timeout)
{
sprintf(buf + off, ", timeout={ %d seconds left }", (int) (con->timeout->timestamp - g_backend->now));
}
else
{
sprintf(buf + off, ", timeout=NULL");
}
LOG_TRACE(buf);
}
/**
* Initialize the network backend.
* Returns 1 on success, or 0 on failure.
*/
int net_backend_initialize()
{
size_t max = net_get_max_sockets();
g_backend = hub_malloc(sizeof(struct net_backend));
g_backend->epfd = epoll_create(max);
if (g_backend->epfd == -1)
{
LOG_WARN("Unable to create epoll socket.");
return 0;
}
g_backend->num = 0;
g_backend->max = max;
g_backend->conns = hub_malloc_zero(sizeof(struct net_connection*) * max);
memset(g_backend->events, 0, sizeof(g_backend->events));
g_backend->now = time(0);
timeout_queue_initialize(&g_backend->timeout_queue, g_backend->now, 600); /* look max 10 minutes into the future. */
return 1;
}
/**
* Shutdown the network connection backend.
*/
void net_backend_shutdown()
{
close(g_backend->epfd);
hub_free(g_backend->conns);
hub_free(g_backend);
}
/**
* Process the network backend.
*/
int net_backend_process()
{
int n;
LOG_TRACE("epoll_wait: fd=%d, events=%x, max=%zu", g_backend->epfd, g_backend->events, MIN(g_backend->num, EPOLL_EVBUFFER));
int res = epoll_wait(g_backend->epfd, g_backend->events, MIN(g_backend->num, EPOLL_EVBUFFER), 1000);
if (res == -1)
{
LOG_WARN("epoll_wait returned -1");
return 0;
}
for (n = 0; n < res; n++)
{
struct net_connection* con = (struct net_connection*) g_backend->events[n].data.ptr;
int ev = 0;
if (g_backend->events[n].events & EPOLLIN) ev |= NET_EVENT_READ;
if (g_backend->events[n].events & EPOLLOUT) ev |= NET_EVENT_WRITE;
con->callback(con, ev, con->ptr);
}
return 1;
}
struct net_connection* net_con_create()
{
struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection));
con->sd = -1;
return con;
}
void net_con_destroy(struct net_connection* con)
{
hub_free(con);
}
void net_con_initialize(struct net_connection* con, int sd, net_connection_cb callback, const void* ptr, int events)
{
con->sd = sd;
con->flags = NET_INITIALIZED;
con->callback = callback;
con->ev.events = 0;
con->ptr = (void*) ptr;
con->ev.data.ptr = (void*) con;
net_set_nonblocking(con->sd, 1);
net_set_nosigpipe(con->sd, 1);
if (events & NET_EVENT_READ) con->ev.events |= EPOLLIN;
if (events & NET_EVENT_WRITE) con->ev.events |= EPOLLOUT;
g_backend->conns[sd] = con;
g_backend->num++;
if (epoll_ctl(g_backend->epfd, EPOLL_CTL_ADD, con->sd, &con->ev) == -1)
{
LOG_TRACE("epoll_ctl() add failed.");
}
net_con_print("ADD", con);
}
void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events)
{
con->callback = callback;
con->ptr = (void*) ptr;
net_con_update(con, events);
}
void net_con_update(struct net_connection* con, int events)
{
con->ev.events = 0;
if (events & NET_EVENT_READ) con->ev.events |= EPOLLIN;
if (events & NET_EVENT_WRITE) con->ev.events |= EPOLLOUT;
#ifdef SSL_SUPPORT
if (events & NET_WANT_SSL_WRITE)
con->flags |= NET_WANT_SSL_WRITE;
else
con->flags &= ~NET_WANT_SSL_WRITE;
if (events & NET_WANT_SSL_READ)
con->flags |= NET_WANT_SSL_READ;
else
con->flags &= ~NET_WANT_SSL_READ;
if (events & NET_WANT_SSL_ACCEPT)
con->flags |= NET_WANT_SSL_ACCEPT;
else
con->flags &= ~NET_WANT_SSL_ACCEPT;
if (events & NET_WANT_SSL_CONNECT)
con->flags |= NET_WANT_SSL_CONNECT;
else
con->flags &= ~NET_WANT_SSL_CONNECT;
#endif /* SSL_SUPPORT */
if (epoll_ctl(g_backend->epfd, EPOLL_CTL_MOD, con->sd, &con->ev) == -1)
{
LOG_TRACE("epoll_ctl() modify failed.");
}
net_con_print("MOD", con);
}
int net_con_close(struct net_connection* con)
{
if (!(con->flags & NET_INITIALIZED))
return 0;
con->flags &= ~NET_INITIALIZED;
if (con->sd != -1)
{
g_backend->conns[con->sd] = 0;
g_backend->num--;
}
if (timeout_evt_is_scheduled(con->timeout))
{
timeout_queue_remove(&g_backend->timeout_queue, con->timeout);
hub_free(con->timeout);
con->timeout = 0;
}
if (epoll_ctl(g_backend->epfd, EPOLL_CTL_DEL, con->sd, &con->ev) == -1)
{
LOG_WARN("epoll_ctl() delete failed.");
}
net_con_print("DEL", con);
return 0;
}
#ifdef SSL_SUPPORT
int net_con_is_ssl(struct net_connection* con)
{
return con->ssl != 0;
}
SSL* net_con_get_ssl(struct net_connection* con)
{
return con->ssl;
}
void net_con_set_ssl(struct net_connection* con, SSL* ssl)
{
con->ssl = ssl;
}
#endif
int net_con_get_sd(struct net_connection* con)
{
return con->sd;
}
void* net_con_get_ptr(struct net_connection* con)
{
return con->ptr;
}
void timeout_evt_initialize(struct timeout_evt*, timeout_evt_cb, void* ptr);
void timeout_evt_reset(struct timeout_evt*);
int timeout_evt_is_scheduled(struct timeout_evt*);
static void timeout_callback(struct timeout_evt* evt)
{
struct net_connection* con = (struct net_connection*) evt->ptr;
con->callback(con, NET_EVENT_TIMEOUT, con->ptr);
}
void net_con_set_timeout(struct net_connection* con, int seconds)
{
if (!con->timeout)
{
con->timeout = hub_malloc_zero(sizeof(struct timeout_evt));
timeout_evt_initialize(con->timeout, timeout_callback, con);
timeout_queue_insert(&g_backend->timeout_queue, con->timeout, seconds);
}
else
{
timeout_queue_reschedule(&g_backend->timeout_queue, con->timeout, seconds);
}
}
void net_con_clear_timeout(struct net_connection* con)
{
if (con->timeout && timeout_evt_is_scheduled(con->timeout))
{
timeout_queue_remove(&g_backend->timeout_queue, con->timeout);
hub_free(con->timeout);
con->timeout = 0;
}
}
#endif /* USE_EPOLL */
-399
View File
@@ -1,399 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#ifdef USE_LIBEVENT
struct net_connection
{
NET_CON_STRUCT_COMMON
struct event event; /** libevent struct for read/write events */
struct event timeout; /** Used for internal timeout handling */
};
struct net_timer
{
unsigned int initialized;
struct event timeout;
net_timeout_cb callback;
void* ptr;
};
int net_con_get_sd(struct net_connection* con)
{
return con->sd;
}
void* net_con_get_ptr(struct net_connection* con)
{
return con->ptr;
}
struct net_connection* net_con_create()
{
struct net_connection* con = (struct net_connection*) hub_malloc(sizeof(struct net_connection));
return con;
}
static inline int net_con_flag_get(struct net_connection* con, unsigned int flag)
{
return con->flags & flag;
}
static inline void net_con_flag_set(struct net_connection* con, unsigned int flag)
{
con->flags |= flag;
}
static inline void net_con_flag_unset(struct net_connection* con, unsigned int flag)
{
con->flags &= ~flag;
}
void net_con_destroy(struct net_connection* con)
{
hub_free(con);
}
static inline int net_con_convert_to_libevent_mask(int ev)
{
int events = 0;
if (ev & NET_EVENT_READ) events |= EV_READ;
if (ev & NET_EVENT_WRITE) events |= EV_WRITE;
return events;
}
static inline int net_con_convert_from_libevent_mask(int ev)
{
int events = 0;
if (ev & EV_TIMEOUT) events |= NET_EVENT_TIMEOUT;
if (ev & EV_READ) events |= NET_EVENT_READ;
if (ev & EV_WRITE) events |= NET_EVENT_WRITE;
return events;
}
static void net_con_event(int fd, short ev, void *arg);
int net_con_close(struct net_connection* con)
{
uhub_assert(con);
con->ptr = 0;
if (net_con_flag_get(con, NET_CLEANUP))
return 0;
if (net_con_flag_get(con, NET_PROCESSING_BUSY))
{
net_con_flag_set(con, NET_CLEANUP);
return 0;
}
net_con_after_close(con);
return 1;
}
static void net_con_set(struct net_connection* con)
{
uhub_assert(con);
int ev = 0;
if (net_con_flag_get(con, NET_WANT_READ | NET_WANT_SSL_READ)) ev |= EV_READ;
if (net_con_flag_get(con, NET_WANT_WRITE | NET_WANT_SSL_WRITE)) ev |= EV_WRITE;
if (net_con_flag_get(con, NET_EVENT_SET) != 0)
{
event_del(&con->event);
}
net_con_flag_set(con, NET_EVENT_SET);
LOG_MEMORY("SET: set+add: CON={ %p, %p, %d, %d}", con, &con->event, con->sd, ev);
event_set(&con->event, con->sd, ev, net_con_event, con);
event_add(&con->event, 0);
net_con_flag_set(con, NET_INITIALIZED);
}
static void net_con_after_close(struct net_connection* con)
{
if (net_con_flag_get(con, NET_INITIALIZED))
{
LOG_MEMORY("DEL: close: CON={ %p, %p, %d, %d}", con, &con->event, con->sd, -1);
net_con_flag_unset(con, NET_EVENT_SET);
event_del(&con->event);
net_con_flag_unset(con, NET_INITIALIZED);
}
net_con_clear_timeout(con);
net_close(con->sd);
con->sd = -1;
hub_free(con);
}
void net_con_initialize(struct net_connection* con, int sd, net_connection_cb callback, const void* ptr, int ev)
{
uhub_assert(con);
int events = net_con_convert_to_libevent_mask(ev);
if (ev & NET_EVENT_READ) net_con_flag_set(con, NET_WANT_READ);
if (ev & NET_EVENT_WRITE) net_con_flag_set(con, NET_WANT_WRITE);
con->sd = sd;
con->flags = 0;
con->ptr = (void*) ptr;
con->callback = callback;
con->last_send = time(0);
con->last_recv = con->last_send;
if (ev)
{
uhub_assert(net_con_flag_get(con, NET_EVENT_SET) == 0);
net_con_flag_set(con, NET_EVENT_SET);
LOG_MEMORY("SET: init: CON={ %p, %p, %d, %d}", con, &con->event, con->sd, ev);
event_set(&con->event, con->sd, events, net_con_event, con);
event_add(&con->event, 0);
net_con_flag_set(con, NET_INITIALIZED);
}
net_set_nonblocking(sd, 1);
net_set_nosigpipe(sd, 1);
#ifdef SSL_SUPPORT
con->ssl = NULL;
con->write_len = 0;
#endif
}
void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events)
{
uhub_assert(con);
con->callback = callback;
con->ptr = (void*) ptr;
net_con_update(con, events);
}
void net_con_update(struct net_connection* con, int ev)
{
uhub_assert(con);
if (ev & NET_EVENT_READ)
net_con_flag_set(con, NET_EVENT_READ);
else
net_con_flag_unset(con, NET_EVENT_READ);
if (ev & NET_EVENT_WRITE)
net_con_flag_set(con, NET_EVENT_WRITE);
else
net_con_flag_unset(con, NET_EVENT_WRITE);
if (!net_con_flag_get(con, NET_PROCESSING_BUSY))
{
net_con_set(con);
}
}
#define CALLBACK(CON, EVENTS) \
if (CON->callback) \
CON->callback(con, EVENTS, CON->ptr);
static void net_con_event(int fd, short ev, void *arg)
{
struct net_connection* con = (struct net_connection*) arg;
int events = net_con_convert_from_libevent_mask(ev);
if (!net_con_flag_get(con, NET_INITIALIZED))
{
return;
}
if (net_con_flag_get(con, NET_CLEANUP))
{
net_con_after_close(con);
return;
}
net_con_flag_set(con, NET_PROCESSING_BUSY);
// uhub_assert(net_con_flag_get(con, NET_EVENT_SET) != 0);
net_con_flag_unset(con, NET_EVENT_SET);
LOG_MEMORY("EVT: process: CON={ %p, %p, %d, %d}", con, &con->event, con->sd, (int) ev);
#ifdef SSL_SUPPORT
if (!con->ssl)
{
#endif
CALLBACK(con, events);
#ifdef SSL_SUPPORT
}
else
{
#ifdef NETWORK_DUMP_DEBUG
LOG_PROTO("net_con_event: events=%d, con=%p", ev, con);
#endif
if (ev & (EV_READ | EV_WRITE))
{
if (net_con_flag_get(con, NET_WANT_SSL_ACCEPT))
{
if (net_con_ssl_accept(con) < 0)
CALLBACK(con, NET_EVENT_SOCKERROR);
}
else if (net_con_flag_get(con, NET_WANT_SSL_CONNECT))
{
if (net_con_ssl_connect(con) < 0)
CALLBACK(con, NET_EVENT_SOCKERROR);
}
else if (ev == EV_READ && net_con_flag_get(con, NET_WANT_SSL_READ))
{
CALLBACK(con, NET_EVENT_WRITE);
}
else if (ev == EV_WRITE && net_con_flag_get(con, NET_WANT_SSL_WRITE))
{
CALLBACK(con, events & NET_EVENT_READ);
}
else
{
CALLBACK(con, events);
}
}
else
{
CALLBACK(con, events);
}
}
#endif
net_con_flag_unset(con, NET_PROCESSING_BUSY);
if (net_con_flag_get(con, NET_CLEANUP))
{
net_con_after_close(con);
}
else
{
net_con_set(con);
}
}
static void net_timer_event(int fd, short ev, void *arg)
{
struct net_timer* timer = (struct net_timer*) arg;
timer->callback(timer, timer->ptr);
}
void net_timer_initialize(struct net_timer* timer, net_timeout_cb callback, void* ptr)
{
timer->initialized = 0;
timer->callback = callback;
timer->ptr = ptr;
}
void net_timer_reset(struct net_timer* timer, int seconds)
{
struct timeval timeout = { seconds, 0 };
if (timer->initialized)
{
evtimer_del(&timer->timeout);
timer->initialized = 0;
}
evtimer_set(&timer->timeout, net_timer_event, timer);
evtimer_add(&timer->timeout, &timeout);
}
void net_timer_shutdown(struct net_timer* timer)
{
if (timer->initialized)
{
evtimer_del(&timer->timeout);
timer->initialized = 0;
}
timer->callback = 0;
timer->ptr = 0;
}
void net_con_set_timeout(struct net_connection* con, int seconds)
{
uhub_assert(con);
struct timeval timeout = { seconds, 0 };
net_con_clear_timeout(con);
evtimer_set(&con->timeout, net_con_event, con);
evtimer_add(&con->timeout, &timeout);
net_con_flag_set(con, NET_TIMER_ENABLED);
}
void net_con_clear_timeout(struct net_connection* con)
{
uhub_assert(con);
if (net_con_flag_get(con, NET_TIMER_ENABLED))
{
evtimer_del(&con->timeout);
net_con_flag_unset(con, NET_TIMER_ENABLED);
}
}
static struct event_base g_evbase = 0;
/**
* Initialize the network backend.
* Returns 1 on success, or 0 on failure.
*/
int net_backend_initialize()
{
g_evbase = event_init();
if (!g_evbase)
{
LOG_ERROR("Unable to initialize libevent.");
return 0;
}
LOG_DEBUG("Using libevent %s, backend: %s", event_get_version(), event_get_method());
return 1;
}
/**
* Shutdown the network connection backend.
*/
void net_backend_shutdown()
{
event_base_free(g_evbase);
}
/**
* Process the network backend.
*/
int net_backend_process()
{
int ret = event_base_loop(g_evbase, EVLOOP_ONCE);
if (ret != 0)
{
LOG_DEBUG("event_base_loop returned: %d", (int) ret);
}
if (ret < 0)
return 0;
return 1;
}
#endif /* USE_LIBEVENT */
-742
View File
@@ -1,742 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* 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/>.
*
*/
#include "uhub.h"
static int is_ipv6_supported = -1; /* -1 = CHECK, 0 = NO, 1 = YES */
static int net_initialized = 0;
static struct net_statistics stats;
static struct net_statistics stats_total;
#if defined(IPV6_BINDV6ONLY)
#define SOCK_DUAL_STACK_OPT IPV6_BINDV6ONLY
#elif defined(IPV6_V6ONLY)
#define SOCK_DUAL_STACK_OPT IPV6_V6ONLY
#endif
int net_initialize()
{
if (!net_initialized)
{
LOG_TRACE("Initializing network monitor.");
#ifdef WINSOCK
struct WSAData wsa;
if (WSAStartup(MAKEWORD(2, 2), &wsa) != NO_ERROR)
{
LOG_ERROR("Unable to initialize winsock.");
return -1;
}
#endif /* WINSOCK */
net_backend_initialize();
net_stats_initialize();
#ifdef SSL_SUPPORT
LOG_TRACE("Initializing OpenSSL...");
SSL_library_init();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
#endif /* SSL_SUPPORT */
net_initialized = 1;
return 0;
}
return -1;
}
size_t net_get_max_sockets()
{
#ifdef HAVE_GETRLIMIT
struct rlimit limits;
if (getrlimit(RLIMIT_NOFILE, &limits) == 0)
{
return limits.rlim_max;
}
LOG_ERROR("getrlimit() failed");
return 1024;
#else
#ifdef WIN32
LOG_WARN("Windows system, limited to 4096 connections.");
return 4096;
#else
LOG_WARN("System does not have getrlimit(): constrained to 1024 sockets");
return 1024;
#endif
#endif /* HAVE_GETRLIMIT */
}
int net_destroy()
{
if (net_initialized)
{
LOG_TRACE("Shutting down network monitor");
net_backend_shutdown();
#ifdef SSL_SUPPORT
/* FIXME: Shutdown OpenSSL here. */
#endif
#ifdef WINSOCK
WSACleanup();
#endif
net_initialized = 0;
return 0;
}
return -1;
}
#ifdef USE_LIBEVENT
struct event_base* net_get_evbase()
{
return net_evbase;
}
#endif
static void net_error_out(int fd, const char* func)
{
int err = net_error();
LOG_ERROR("%s, fd=%d: %s (%d)", func, fd, net_error_string(err), err);
}
int net_error()
{
#ifdef WINSOCK
return WSAGetLastError();
#else
return errno;
#endif
}
const char* net_error_string(int code)
{
#ifdef WINSOCK
static char string[32];
snprintf(string, 32, "error code: %d", code);
return string;
#else
return strerror(code);
#endif
}
static int net_setsockopt(int fd, int level, int opt, const void* optval, socklen_t optlen)
{
int ret = -1;
#ifdef WINSOCK
ret = setsockopt(fd, level, opt, (const char*) optval, optlen);
#else
ret = setsockopt(fd, level, opt, optval, optlen);
#endif
if (ret == -1)
{
net_error_out(fd, "net_setsockopt");
}
return ret;
}
static int net_getsockopt(int fd, int level, int opt, void* optval, socklen_t* optlen)
{
int ret = -1;
#ifdef WINSOCK
ret = getsockopt(fd, level, opt, (char*) optval, optlen);
#else
ret = getsockopt(fd, level, opt, optval, optlen);
#endif
if (ret == -1)
{
net_error_out(fd, "net_getsockopt");
}
return ret;
}
int net_set_nonblocking(int fd, int toggle)
{
int ret = -1;
#ifdef WINSOCK
u_long on = toggle ? 1 : 0;
ret = ioctlsocket(fd, FIONBIO, &on);
#else
#ifdef __sun__
int flags = fcntl(fd, F_GETFL, 0);
if (flags != -1)
{
if (toggle) flags |= O_NONBLOCK;
else flags &= ~O_NONBLOCK;
ret = fcntl(fd, F_SETFL, flags);
}
#else
ret = ioctl(fd, FIONBIO, &toggle);
#endif
#endif
if (ret == -1)
{
net_error_out(fd, "net_set_nonblocking");
}
return ret;
}
/* NOTE: Possibly only supported on BSD and OSX? */
int net_set_nosigpipe(int fd, int toggle)
{
int ret = -1;
#ifdef SO_NOSIGPIPE
ret = net_setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &toggle, sizeof(toggle));
if (ret == -1)
{
net_error_out(fd, "net_set_nosigpipe");
}
#endif
return ret;
}
int net_set_close_on_exec(int fd, int toggle)
{
#ifdef WINSOCK
return -1; /* FIXME: How is this done on Windows? */
#else
return fcntl(fd, F_SETFD, toggle);
#endif
}
int net_set_linger(int fd, int toggle)
{
int ret;
ret = net_setsockopt(fd, SOL_SOCKET, SO_LINGER, &toggle, sizeof(toggle));
if (ret == -1)
{
net_error_out(fd, "net_set_linger");
}
return ret;
}
int net_set_keepalive(int fd, int toggle)
{
int ret;
ret = net_setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &toggle, sizeof(toggle));
if (ret == -1)
{
net_error_out(fd, "net_set_keepalive");
}
return ret;
}
int net_set_reuseaddress(int fd, int toggle)
{
int ret;
ret = net_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &toggle, sizeof(toggle));
if (ret == -1)
{
net_error_out(fd, "net_set_reuseaddress");
}
return ret;
}
int net_set_sendbuf_size(int fd, size_t size)
{
return net_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
}
int net_get_sendbuf_size(int fd, size_t* size)
{
socklen_t sz = sizeof(*size);
return net_getsockopt(fd, SOL_SOCKET, SO_SNDBUF, size, &sz);
}
int net_set_recvbuf_size(int fd, size_t size)
{
return net_setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
}
int net_get_recvbuf_size(int fd, size_t* size)
{
socklen_t sz = sizeof(*size);
return net_getsockopt(fd, SOL_SOCKET, SO_RCVBUF, size, &sz);
}
int net_close(int fd)
{
#ifdef WINSOCK
int ret = closesocket(fd);
#else
int ret = close(fd);
#endif
if (ret == 0)
{
net_stats_add_close();
}
else
{
if (ret != -1)
{
net_stats_add_error();
}
}
return ret;
}
int net_shutdown_r(int fd)
{
#ifdef WINSOCK
return shutdown(fd, SD_RECEIVE);
#else
return shutdown(fd, SHUT_RD);
#endif
}
int net_shutdown_w(int fd)
{
#ifdef WINSOCK
return shutdown(fd, SD_SEND);
#else
return shutdown(fd, SHUT_WR);
#endif
}
int net_shutdown_rw(int fd)
{
#ifdef WINSOCK
return shutdown(fd, SD_BOTH);
#else
return shutdown(fd, SHUT_RDWR);
#endif
}
int net_accept(int fd, struct ip_addr_encap* ipaddr)
{
struct sockaddr_storage addr;
struct sockaddr_in* addr4;
struct sockaddr_in6* addr6;
socklen_t addr_size;
int ret = 0;
addr_size = sizeof(struct sockaddr_storage);
memset(&addr, 0, addr_size);
addr4 = (struct sockaddr_in*) &addr;
addr6 = (struct sockaddr_in6*) &addr;
ret = accept(fd, (struct sockaddr*) &addr, &addr_size);
if (ret == -1)
{
switch (net_error())
{
#if defined(__linux__)
case ENETDOWN:
case EPROTO:
case ENOPROTOOPT:
case EHOSTDOWN:
case ENONET:
case EHOSTUNREACH:
case EOPNOTSUPP:
errno = EWOULDBLOCK;
#endif
case EWOULDBLOCK:
break;
default:
net_error_out(fd, "net_accept");
net_stats_add_error();
return -1;
}
}
else
{
net_stats_add_accept();
if (ipaddr)
{
memset(ipaddr, 0, sizeof(struct ip_addr_encap));
ipaddr->af = addr4->sin_family;
if (ipaddr->af == AF_INET6)
{
char address[INET6_ADDRSTRLEN+1] = { 0, };
net_address_to_string(AF_INET6, (void*) &addr6->sin6_addr, address, INET6_ADDRSTRLEN+1);
if (!strncmp(address, "::ffff:", 7))
{
/* Hack to convert IPv6 mapped IPv4 addresses to true IPv4 addresses */
net_string_to_address(AF_INET, address + 7, (void*) &ipaddr->internal_ip_data.in);
ipaddr->af = AF_INET;
}
else
{
memcpy(&ipaddr->internal_ip_data.in6, &addr6->sin6_addr, sizeof(struct in6_addr));
}
}
else
{
memcpy(&ipaddr->internal_ip_data.in, &addr4->sin_addr, sizeof(struct in_addr));
}
}
}
return ret;
}
int net_connect(int fd, const struct sockaddr *serv_addr, socklen_t addrlen)
{
int ret = connect(fd, serv_addr, addrlen);
if (ret == -1)
{
if (net_error() != EINPROGRESS)
{
net_error_out(fd, "net_connect");
net_stats_add_error();
}
}
return ret;
}
int net_is_ipv6_supported()
{
if (is_ipv6_supported == -1)
{
int ret = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
if (ret == -1)
{
#ifdef WINSOCK
if (net_error() == WSAEAFNOSUPPORT)
#else
if (net_error() == EAFNOSUPPORT)
#endif
{
LOG_TRACE("net_is_ipv6_supported(): IPv6 is not supported on this system.");
is_ipv6_supported = 0;
return 0;
}
net_error_out(ret, "net_is_ipv6_supported");
}
else
{
#ifdef SOCK_DUAL_STACK_OPT
int off = 0;
if (net_setsockopt(ret, IPPROTO_IPV6, SOCK_DUAL_STACK_OPT, (char*) &off, sizeof(off)) < 0)
{
LOG_ERROR("net_socket_create(): Dual stack IPv6/IPv4 is not supported.");
is_ipv6_supported = 0;
}
else
{
is_ipv6_supported = 1;
}
#else
is_ipv6_supported = 0;
#endif
net_close(ret);
}
}
return is_ipv6_supported;
}
int net_socket_create(int af, int type, int protocol)
{
int sd = socket(af, type, protocol);
if (sd == -1)
{
net_error_out(sd, "net_socket_create");
return -1;
}
#ifdef SOCK_DUAL_STACK_OPT
/* BSD style */
if (af == AF_INET6)
{
int off = 0;
if (net_setsockopt(sd, IPPROTO_IPV6, SOCK_DUAL_STACK_OPT, (char*) &off, sizeof(off)) < 0)
{
LOG_ERROR("net_socket_create(): Cannot set socket to dual stack mode IPv6/IPv4 (%d - %s).", net_error(), net_error_string(net_error()));
}
}
#endif
return sd;
}
const char* net_address_to_string(int af, const void* src, char* dst, socklen_t cnt)
{
#ifdef WINSOCK
struct sockaddr_in sin4;
struct sockaddr_in6 sin6;
struct in_addr* addr4 = (struct in_addr*) src;
struct in6_addr* addr6 = (struct in6_addr*) src;
size_t size;
LPSOCKADDR addr;
DWORD len = cnt;
switch (af)
{
case AF_INET:
sin4.sin_family = AF_INET;
sin4.sin_port = 0;
sin4.sin_addr = *addr4;
size = sizeof(sin4);
addr = (LPSOCKADDR) &sin4;
break;
case AF_INET6:
sin6.sin6_family = AF_INET6;
sin6.sin6_port = 0;
sin6.sin6_addr = *addr6;
size = sizeof(sin6);
addr = (LPSOCKADDR) &sin6;
break;
default:
return NULL;
}
if (WSAAddressToString(addr, size, NULL, dst, &len) == 0)
{
return dst;
}
return NULL;
#else
return inet_ntop(af, src, dst, cnt);
#endif
}
int net_string_to_address(int af, const char* src, void* dst)
{
#ifdef WINSOCK
int ret, size;
struct sockaddr_in addr4;
struct sockaddr_in6 addr6;
struct sockaddr* addr = 0;
if (af == AF_INET6)
{
if (net_is_ipv6_supported() != 1) return -1;
size = sizeof(struct sockaddr_in6);
addr = (struct sockaddr*) &addr6;
}
else
{
size = sizeof(struct sockaddr_in);
addr = (struct sockaddr*) &addr4;
}
if (!net_initialized)
net_initialize();
ret = WSAStringToAddressA((char*) src, af, NULL, addr, &size);
if (ret == -1)
{
return -1;
}
if (af == AF_INET6)
{
memcpy(dst, &addr6.sin6_addr, sizeof(addr6.sin6_addr));
}
else
{
memcpy(dst, &addr4.sin_addr, sizeof(addr4.sin_addr));
}
return 1;
#else
return inet_pton(af, src, dst);
#endif
}
const char* net_get_peer_address(int fd)
{
static char address[INET6_ADDRSTRLEN+1];
struct sockaddr_storage storage;
struct sockaddr_in6* name6;
struct sockaddr_in* name4;
struct sockaddr* name;
memset(address, 0, INET6_ADDRSTRLEN);
socklen_t namelen = sizeof(struct sockaddr_storage);
memset(&storage, 0, namelen);
name6 = (struct sockaddr_in6*) &storage;
name4 = (struct sockaddr_in*) &storage;
name = (struct sockaddr*) &storage;
if (getpeername(fd, (struct sockaddr*) name, &namelen) != -1)
{
int af = name4->sin_family;
if (af == AF_INET6)
{
net_address_to_string(af, (void*) &name6->sin6_addr, address, INET6_ADDRSTRLEN);
if (strncmp(address, "::ffff:", 7) == 0) /* IPv6 mapped IPv4 address. */
{
return &address[7];
}
return address;
}
else
{
net_address_to_string(af, (void*) &name4->sin_addr, address, INET6_ADDRSTRLEN);
return address;
}
}
else
{
net_error_out(fd, "net_get_peer_address");
net_stats_add_error();
}
return "0.0.0.0";
}
ssize_t net_recv(int fd, void* buf, size_t len, int flags)
{
ssize_t ret = recv(fd, buf, len, flags);
if (ret >= 0)
{
net_stats_add_rx(ret);
}
else
{
if (net_error() != EWOULDBLOCK)
{
/* net_error_out(fd, "net_recv"); */
net_stats_add_error();
}
}
return ret;
}
ssize_t net_send(int fd, const void* buf, size_t len, int flags)
{
ssize_t ret = send(fd, buf, len, flags);
if (ret >= 0)
{
net_stats_add_tx(ret);
}
else
{
if (net_error() != EWOULDBLOCK)
{
/* net_error_out(fd, "net_send"); */
net_stats_add_error();
}
}
return ret;
}
int net_bind(int fd, const struct sockaddr *my_addr, socklen_t addrlen)
{
int ret = bind(fd, my_addr, addrlen);
if (ret == -1)
{
net_error_out(fd, "net_bind");
net_stats_add_error();
}
return ret;
}
int net_listen(int fd, int backlog)
{
int ret = listen(fd, backlog);
if (ret == -1)
{
net_error_out(fd, "net_listen");
net_stats_add_error();
}
return ret;
}
void net_stats_initialize()
{
memset(&stats_total, 0, sizeof(struct net_statistics));
stats_total.timestamp = time(NULL);
memset(&stats, 0, sizeof(struct net_statistics));
stats.timestamp = time(NULL);
}
void net_stats_get(struct net_statistics** intermediate, struct net_statistics** total)
{
*intermediate = &stats;
*total = &stats_total;
}
void net_stats_reset()
{
stats_total.tx += stats.tx;
stats_total.rx += stats.rx;
stats_total.accept += stats.accept;
stats_total.errors += stats.errors;
stats_total.closed += stats.closed;
memset(&stats, 0, sizeof(struct net_statistics));
stats.timestamp = time(NULL);
}
int net_stats_timeout()
{
return (difftime(time(NULL), stats.timestamp) > TIMEOUT_STATS) ? 1 : 0;
}
void net_stats_add_tx(size_t bytes)
{
stats.tx += bytes;
}
void net_stats_add_rx(size_t bytes)
{
stats.rx += bytes;
}
void net_stats_add_accept()
{
stats.accept++;
}
void net_stats_add_error()
{
stats.errors++;
}
void net_stats_add_close()
{
stats.closed++;
}
-297
View File
@@ -1,297 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_NETWORK_H
#define HAVE_UHUB_NETWORK_H
struct net_statistics
{
time_t timestamp;
size_t tx;
size_t rx;
size_t accept;
size_t closed;
size_t errors;
};
struct net_socket_t;
/**
* Initialize the socket monitor subsystem.
* On some operating systems this will also involve loading the TCP/IP stack
* (needed on Windows at least).
*
* @param max_connections The maximum number of sockets the monitor can handle.
* @return -1 on error, 0 on success
*/
extern int net_initialize();
/**
* Shutdown the socket monitor.
* On some operating systems this will also ensure the TCP/IP stack
* is loaded.
*
* @return -1 on error, 0 on success
*/
extern int net_destroy();
extern struct event_base* net_get_evbase();
/**
* @return the number of sockets currrently being monitored.
*/
extern int net_monitor_count();
/**
* @return the monitor's socket capacity.
*/
extern int net_monitor_capacity();
/**
* @return the last error code occured.
*
* NOTE: On Windows this is the last error code from the socket library, but
* on UNIX this is the errno variable that can be overwritten by any
* libc function.
* For this reason, only rely on net_error() immediately after a
* socket function call.
*/
extern int net_error();
extern const char* net_error_string(int code);
/**
* A wrapper for the socket() function call.
*/
extern int net_socket_create(int af, int type, int protocol);
/**
* Returns the maximum number of file/socket descriptors.
*/
extern size_t net_get_max_sockets();
/**
* A wrapper for the close() function call.
*/
extern int net_close(int fd);
extern int net_shutdown_r(int fd);
extern int net_shutdown_w(int fd);
extern int net_shutdown_rw(int fd);
/**
* A wrapper for the accept() function call.
* @param fd socket descriptor
* @param ipaddr (in/out) if non-NULL the ip address of the
* accepted peer is filled in.
*/
extern int net_accept(int fd, struct ip_addr_encap* ipaddr);
/**
* A wrapper for the connect() call.
*/
extern int net_connect(int fd, const struct sockaddr *serv_addr, socklen_t addrlen);
/**
* A wrapper for the bind() function call.
*/
extern int net_bind(int fd, const struct sockaddr *my_addr, socklen_t addrlen);
/**
* A wrapper for the listen() function call.
*/
extern int net_listen(int sockfd, int backlog);
/**
* This will set the socket to blocking or nonblocking mode.
* @param fd socket descriptor
* @param toggle if non-zero nonblocking mode, otherwise blocking mode is assumed
* @return -1 on error, 0 on success
*/
extern int net_set_nonblocking(int fd, int toggle);
/**
* This will prevent the socket to generate a SIGPIPE in case the socket goes down.
* NOTE: Not all operating systems support this feature. In that case this will return success value.
*
* @param fd socket descriptor
* @param toggle if non-zero ignore sigpipe, otherwise disable it.
* @return -1 on error, 0 on success
*/
extern int net_set_nosigpipe(int fd, int toggle);
/**
* This will set the close-on-exec flag. This means if any subprocess is
* started any open file descriptors or sockets will not be inherited if this
* is turned on. Otherwise, subprocesses invoked via exec() can read/write
* to these sockets.
*
* @param fd socket descriptor
* @param toggle if non-zero close-on-exec is enabled, otherwise disabled.
* @return -1 on error, 0 on success.
*/
extern int net_set_close_on_exec(int fd, int toggle);
/**
* Enable/disable linger on close if data is present.
*
* @param fd socket descriptor
* @param toggle enable if non-zero
* @return -1 on error, 0 on success.
*/
extern int net_set_linger(int fd, int toggle);
/**
* This will set or unset the SO_REUSEADDR flag.
* @param fd socket descriptor
* @param toggle Set SO_REUSEADDR if non-zero, otherwise unset it.
* @return -1 on error, 0 on success
*/
extern int net_set_reuseaddress(int fd, int toggle);
/**
* Set the send buffer size for the socket.
* @param fd socket descriptor
* @param size size to set
* @return -1 on error, 0 on success.
*/
extern int net_set_sendbuf_size(int fd, size_t size);
/**
* Get the send buffer size for the socket.
* @param fd socket descriptor
* @param[out] size existing size, cannot be NULL.
* @return -1 on error, 0 on success.
*/
extern int net_get_sendbuf_size(int fd, size_t* size);
/**
* Set the receive buffer size for the socket.
* @param fd socket descriptor
* @param size size to set
* @return -1 on error, 0 on success.
*/
extern int net_set_recvbuf_size(int fd, size_t size);
/**
* Get the receive buffer size for the socket.
* @param fd socket descriptor
* @param[out] size existing size, cannot be NULL.
* @return -1 on error, 0 on success.
*/
extern int net_get_recvbuf_size(int fd, size_t* size);
/**
* A wrapper for the recv() function call.
*/
extern ssize_t net_recv(int fd, void* buf, size_t len, int flags);
/**
* A wrapper for the send() function call.
*/
extern ssize_t net_send(int fd, const void* buf, size_t len, int flags);
/**
* This tries to create a AF_INET6 socket.
* If it succeeds it concludes IPv6 is supported on the host operating
* system. If the call fails with EAFNOSUPPORT the host system
* does not support IPv6.
* The result is cached so further calls to this function are cheap.
*/
extern int net_is_ipv6_supported();
/**
* This will return a string containing the peer IP-address of
* the connected peer associated with the given socket.
*
* @param fd socket descriptor
* @return IP address (IPv6 or IPv4), or "0.0.0.0" if unable to determine the address.
*/
extern const char* net_get_peer_address(int fd);
/**
* See man(3) inet_ntop.
*/
extern const char* net_address_to_string(int af, const void *src, char *dst, socklen_t cnt);
/**
* See man(3) inet_pton.
*/
extern int net_string_to_address(int af, const char *src, void *dst);
/**
* Network statistics monitor.
*
* Keeps track of bandwidth usage, sockets accepted, closed,
* errors etc.
*/
extern void net_stats_initialize();
extern void net_stats_report();
extern void net_stats_reset();
extern void net_stats_add_tx(size_t bytes);
extern void net_stats_add_rx(size_t bytes);
extern void net_stats_add_accept();
extern void net_stats_add_error();
extern void net_stats_add_close();
extern int net_stats_timeout();
extern void net_stats_get(struct net_statistics** intermediate, struct net_statistics** total);
#if defined(WINSOCK) && !defined(__CYGWIN__)
#define EWOULDBLOCK WSAEWOULDBLOCK
#define EINPROGRESS WSAEINPROGRESS
#define EALREADY WSAEALREADY
#define ENOTSOCK WSAENOTSOCK
#define EDESTADDRREQ WSAEDESTADDRREQ
#define EMSGSIZE WSAEMSGSIZE
#define EPROTOTYPE WSAEPROTOTYPE
#define ENOPROTOOPT WSAENOPROTOOPT
#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
#define EOPNOTSUPP WSAEOPNOTSUPP
#define EPFNOSUPPORT WSAEPFNOSUPPORT
#define EAFNOSUPPORT WSAEAFNOSUPPORT
#define EADDRINUSE WSAEADDRINUSE
#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
#define ENETDOWN WSAENETDOWN
#define ENETUNREACH WSAENETUNREACH
#define ENETRESET WSAENETRESET
#define ECONNABORTED WSAECONNABORTED
#define ECONNRESET WSAECONNRESET
#define ENOBUFS WSAENOBUFS
#define EISCONN WSAEISCONN
#define ENOTCONN WSAENOTCONN
#define ESHUTDOWN WSAESHUTDOWN
#define ETOOMANYREFS WSAETOOMANYREFS
#define ETIMEDOUT WSAETIMEDOUT
#define ECONNREFUSED WSAECONNREFUSED
#define ELOOP WSAELOOP
#define EHOSTDOWN WSAEHOSTDOWN
#define EHOSTUNREACH WSAEHOSTUNREACH
#define EPROCLIM WSAEPROCLIM
#define EUSERS WSAEUSERS
#define EDQUOT WSAEDQUOT
#define ESTALE WSAESTALE
#define EREMOTE WSAEREMOTE
#endif /* WINSOCK && !__CYGWIN__ */
#endif /* HAVE_UHUB_NETWORK_H */
-137
View File
@@ -1,137 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_SYSTEM_H
#define HAVE_UHUB_SYSTEM_H
#define _FILE_OFFSET_BITS 64
#if USE_REGPARM && __GNUC__ >= 3
#define REGPRM1 __attribute__((regparm(1)))
#define REGPRM2 __attribute__((regparm(2)))
#define REGPRM3 __attribute__((regparm(3)))
#else
#define REGPRM1
#define REGPRM2
#define REGPRM3
#endif
#ifndef FORCEINLINE
#if __GNUC__ < 3
#define FORCEINLINE inline
#else
#define FORCEINLINE inline __attribute__((always_inline))
#endif
#endif
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#if defined(__CYGWIN__) || defined(__MINGW32__)
#ifndef WINSOCK
#define WINSOCK
#endif
#endif
#ifdef WINSOCK
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <sys/types.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#endif
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#if !defined(WIN32)
#include <grp.h>
#include <pwd.h>
#include <sys/resource.h>
#define HAVE_STRNDUP
#define HAVE_MEMMEM
#define HAVE_GETRLIMIT
#endif
/* printf and size_t support */
#if defined(WIN32)
/* Windows uses %Iu for size_t */
#define PRINTF_SIZE_T "%Iu"
#else
#define PRINTF_SIZE_T "%zu"
#endif
#ifdef SSL_SUPPORT
#include <openssl/ssl.h>
#include <openssl/err.h>
#endif
#include "../version.h"
#define uhub_assert assert
#ifdef USE_LIBEVENT
#include <event.h>
#else
#ifdef __linux__
#define USE_EPOLL
#include <sys/epoll.h>
#endif
#endif
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__sun__)
#undef HAVE_STRNDUP
#undef HAVE_MEMMEM
#endif
#ifdef MSG_NOSIGNAL
#define UHUB_SEND_SIGNAL MSG_NOSIGNAL
#else
#ifdef MSG_NOPIPE
#define UHUB_SEND_SIGNAL MSG_NOPIPE
#else
#define UHUB_SEND_SIGNAL 0
#endif
#endif
#ifndef INET6_ADDRSTRLEN
#define INET6_ADDRSTRLEN 46
#endif
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif /* HAVE_UHUB_SYSTEM_H */
-491
View File
@@ -1,491 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#include "tools/adcclient.h"
#define ADC_HANDSHAKE "HSUP ADBASE ADTIGR ADPING\n"
#define ADC_CID_SIZE 39
#define BIG_BUFSIZE 32768
#define TIGERSIZE 24
static ssize_t ADC_client_recv(struct ADC_client* client);
static void ADC_client_send_info(struct ADC_client* client);
static void ADC_client_on_connected(struct ADC_client* client);
static void ADC_client_on_disconnected(struct ADC_client* client);
static void ADC_client_on_login(struct ADC_client* client);
static int ADC_client_parse_address(struct ADC_client* client, const char* arg);
static void ADC_client_on_recv_line(struct ADC_client* client, const char* line, size_t length);
static void ADC_client_debug(struct ADC_client* client, const char* format, ...)
{
char logmsg[1024];
va_list args;
va_start(args, format);
vsnprintf(logmsg, 1024, format, args);
va_end(args);
fprintf(stdout, "* [%p] %s\n", client, logmsg);
}
static void ADC_client_set_state(struct ADC_client* client, enum ADC_client_state state)
{
client->state = state;
}
static void adc_cid_pid(struct ADC_client* client)
{
char seed[64];
char pid[64];
char cid[64];
uint64_t tiger_res1[3];
uint64_t tiger_res2[3];
/* create cid+pid pair */
memset(seed, 0, 64);
snprintf(seed, 64, VERSION "%p", client);
tiger((uint64_t*) seed, strlen(seed), tiger_res1);
base32_encode((unsigned char*) tiger_res1, TIGERSIZE, pid);
tiger((uint64_t*) tiger_res1, TIGERSIZE, tiger_res2);
base32_encode((unsigned char*) tiger_res2, TIGERSIZE, cid);
cid[ADC_CID_SIZE] = 0;
pid[ADC_CID_SIZE] = 0;
adc_msg_add_named_argument(client->info, ADC_INF_FLAG_PRIVATE_ID, pid);
adc_msg_add_named_argument(client->info, ADC_INF_FLAG_CLIENT_ID, cid);
}
static void event_callback(struct net_connection* con, int events, void *arg)
{
struct ADC_client* client = (struct ADC_client*) net_con_get_ptr(con);
if (events == NET_EVENT_SOCKERROR || events == NET_EVENT_CLOSED)
{
printf("NET_EVENT_SOCKERROR || NET_EVENT_CLOSED\n");
client->callback(client, ADC_CLIENT_DISCONNECTED, 0);
return;
}
if (events == NET_EVENT_TIMEOUT)
{
if (client->state == ps_conn)
{
client->callback(client, ADC_CLIENT_DISCONNECTED, 0);
}
}
if (events & NET_EVENT_READ)
{
if (ADC_client_recv(client) == -1)
{
ADC_client_on_disconnected(client);
}
}
if (events & NET_EVENT_WRITE)
{
if (client->state == ps_conn)
{
ADC_client_connect(client, 0);
}
else
{
/* FIXME: Call send again */
}
}
}
#define UNESCAPE_ARG(TMP, TARGET) \
if (TMP) \
TARGET = adc_msg_unescape(TMP); \
else \
TARGET = NULL; \
hub_free(TMP);
#define EXTRACT_NAMED_ARG(MSG, NAME, TARGET) \
do { \
char* tmp = adc_msg_get_named_argument(MSG, NAME); \
UNESCAPE_ARG(tmp, TARGET); \
} while (0)
#define EXTRACT_POS_ARG(MSG, POS, TARGET) \
do { \
char* tmp = adc_msg_get_argument(MSG, POS); \
UNESCAPE_ARG(tmp, TARGET); \
} while (0)
static void ADC_client_on_recv_line(struct ADC_client* client, const char* line, size_t length)
{
#ifdef ADC_CLIENT_DEBUG_PROTO
ADC_client_debug(client, "- LINE: '%s'", start);
#endif
/* Parse message */
struct adc_message* msg = adc_msg_parse(line, length);
if (!msg)
{
ADC_client_debug(client, "WARNING: Message cannot be decoded: \"%s\"", line);
return;
}
if (length < 4)
{
ADC_client_debug(client, "Unexpected response from hub: '%s'", line);
return;
}
switch (msg->cmd)
{
case ADC_CMD_ISUP:
break;
case ADC_CMD_ISID:
if (client->state == ps_protocol)
{
client->sid = string_to_sid(&line[5]);
client->callback(client, ADC_CLIENT_LOGGING_IN, 0);
ADC_client_set_state(client, ps_identify);
ADC_client_send_info(client);
}
break;
case ADC_CMD_BMSG:
case ADC_CMD_EMSG:
case ADC_CMD_DMSG:
case ADC_CMD_IMSG:
{
struct ADC_chat_message chat;
struct ADC_client_callback_data data;
chat.from_sid = msg->source;
chat.to_sid = msg->target;
data.chat = &chat;
EXTRACT_POS_ARG(msg, 0, chat.message);
client->callback(client, ADC_CLIENT_MESSAGE, &data);
hub_free(chat.message);
break;
}
case ADC_CMD_IINF:
{
struct ADC_hub_info hubinfo;
EXTRACT_NAMED_ARG(msg, "NI", hubinfo.name);
EXTRACT_NAMED_ARG(msg, "DE", hubinfo.description);
EXTRACT_NAMED_ARG(msg, "VE", hubinfo.version);
struct ADC_client_callback_data data;
data.hubinfo = &hubinfo;
client->callback(client, ADC_CLIENT_HUB_INFO, &data);
hub_free(hubinfo.name);
hub_free(hubinfo.description);
hub_free(hubinfo.version);
break;
}
case ADC_CMD_BSCH:
case ADC_CMD_FSCH:
{
client->callback(client, ADC_CLIENT_SEARCH_REQ, 0);
break;
}
case ADC_CMD_BINF:
{
if (msg->source == client->sid)
{
if (client->state == ps_verify || client->state == ps_identify)
{
ADC_client_on_login(client);
}
}
else
{
if (adc_msg_has_named_argument(msg, "ID"))
{
struct ADC_user user;
EXTRACT_NAMED_ARG(msg, "NI", user.name);
EXTRACT_NAMED_ARG(msg, "DE", user.description);
EXTRACT_NAMED_ARG(msg, "VE", user.version);
EXTRACT_NAMED_ARG(msg, "ID", user.cid);
EXTRACT_NAMED_ARG(msg, "I4", user.address);
struct ADC_client_callback_data data;
data.user = &user;
client->callback(client, ADC_CLIENT_USER_JOIN, &data);
hub_free(user.name);
hub_free(user.description);
hub_free(user.version);
hub_free(user.cid);
hub_free(user.address);
}
}
}
case ADC_CMD_ISTA:
/*
if (strncmp(line, "ISTA 000", 8))
{
ADC_client_debug(client, "status: '%s'\n", (start + 9));
}
*/
break;
default:
break;
}
adc_msg_free(msg);
}
static ssize_t ADC_client_recv(struct ADC_client* client)
{
ssize_t size = net_con_recv(client->con, &client->recvbuf[client->r_offset], ADC_BUFSIZE - client->r_offset);
if (size <= 0)
return size;
client->r_offset += size;
client->recvbuf[client->r_offset] = 0;
char* start = client->recvbuf;
char* pos;
char* lastPos = 0;
size_t remaining = client->r_offset;
while ((pos = memchr(start, '\n', remaining)))
{
pos[0] = 0;
ADC_client_on_recv_line(client, start, pos - start);
pos++;
remaining -= (pos - start);
start = pos;
lastPos = pos;
}
if (lastPos)
{
memmove(client->recvbuf, lastPos, remaining);
client->r_offset = remaining;
}
return 0;
}
void ADC_client_send(struct ADC_client* client, char* msg)
{
int ret = net_con_send(client->con, msg, strlen(msg));
#ifdef ADC_CLIENT_DEBUG_PROTO
char* dump = strdup(msg);
dump[strlen(msg) - 1] = 0;
ADC_client_debug(client, "- SEND: '%s'", dump);
free(dump);
#endif
if (ret != strlen(msg))
{
if (ret == -1)
{
if (net_error() != EWOULDBLOCK)
ADC_client_on_disconnected(client);
}
else
{
/* FIXME: Not all data sent! */
printf("ret (%d) != msg->length (%d)\n", ret, (int) strlen(msg));
}
}
}
void ADC_client_send_info(struct ADC_client* client)
{
char binf[11];
snprintf(binf, 11, "BINF %s\n", sid_to_string(client->sid));
client->info = adc_msg_create(binf);
adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_NICK, client->nick);
if (client->desc)
{
adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_DESCRIPTION, client->desc);
}
adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_USER_AGENT, PRODUCT "/" VERSION);
adc_cid_pid(client);
ADC_client_send(client, client->info->cache);
}
int ADC_client_create(struct ADC_client* client, const char* nickname, const char* description)
{
memset(client, 0, sizeof(struct ADC_client));
int sd = net_socket_create(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sd == -1) return -1;
client->con = net_con_create();
#if 0
/* FIXME */
client->timer = 0; /* FIXME: hub_malloc(sizeof(struct net_timer)); */
#endif
net_con_initialize(client->con, sd, event_callback, client, 0);
#if 0
/* FIXME */
net_timer_initialize(client->timer, timer_callback, client);
#endif
ADC_client_set_state(client, ps_none);
client->nick = hub_strdup(nickname);
client->desc = hub_strdup(description);
return 0;
}
void ADC_client_destroy(struct ADC_client* client)
{
ADC_client_disconnect(client);
#if 0
/* FIXME */
net_timer_shutdown(client->timer);
#endif
hub_free(client->timer);
adc_msg_free(client->info);
hub_free(client->nick);
hub_free(client->desc);
hub_free(client->hub_address);
}
int ADC_client_connect(struct ADC_client* client, const char* address)
{
if (!client->hub_address)
{
if (!ADC_client_parse_address(client, address))
return 0;
client->callback(client, ADC_CLIENT_CONNECTING, 0);
}
int ret = net_connect(net_con_get_sd(client->con), (struct sockaddr*) &client->addr, sizeof(struct sockaddr_in));
if (ret == 0 || (ret == -1 && net_error() == EISCONN))
{
ADC_client_on_connected(client);
}
else if (ret == -1 && (net_error() == EALREADY || net_error() == EINPROGRESS || net_error() == EWOULDBLOCK || net_error() == EINTR))
{
if (client->state != ps_conn)
{
net_con_update(client->con, NET_EVENT_READ | NET_EVENT_WRITE);
ADC_client_set_state(client, ps_conn);
}
}
else
{
ADC_client_on_disconnected(client);
return 0;
}
return 1;
}
static void ADC_client_on_connected(struct ADC_client* client)
{
net_con_update(client->con, NET_EVENT_READ);
client->callback(client, ADC_CLIENT_CONNECTED, 0);
ADC_client_send(client, ADC_HANDSHAKE);
ADC_client_set_state(client, ps_protocol);
}
static void ADC_client_on_disconnected(struct ADC_client* client)
{
net_con_close(client->con);
client->con = 0;
ADC_client_set_state(client, ps_none);
}
static void ADC_client_on_login(struct ADC_client* client)
{
ADC_client_set_state(client, ps_normal);
client->callback(client, ADC_CLIENT_LOGGED_IN, 0);
}
void ADC_client_disconnect(struct ADC_client* client)
{
if (client->con && net_con_get_sd(client->con) != -1)
{
net_con_close(client->con);
client->con = 0;
}
}
static int ADC_client_parse_address(struct ADC_client* client, const char* arg)
{
char* split;
int ssl = 0;
struct hostent* dns;
struct in_addr* addr;
if (!arg)
return 0;
client->hub_address = hub_strdup(arg);
/* Minimum length of a valid address */
if (strlen(arg) < 9)
return 0;
/* Check for ADC or ADCS */
if (!strncmp(arg, "adc://", 6))
ssl = 0;
else if (!strncmp(arg, "adcs://", 7))
ssl = 1;
else
return 0;
/* Split hostname and port (if possible) */
split = strrchr(client->hub_address + 6 + ssl, ':');
if (split == 0 || strlen(split) < 2 || strlen(split) > 6)
return 0;
/* Ensure port number is valid */
int port = strtol(split+1, NULL, 10);
if (port <= 0 || port > 65535)
return 0;
split[0] = 0;
/* Resolve IP address (FIXME: blocking call) */
dns = gethostbyname(client->hub_address + 6 + ssl);
if (dns)
{
addr = (struct in_addr*) dns->h_addr_list[0];
}
// Initialize the sockaddr struct.
memset(&client->addr, 0, sizeof(client->addr));
client->addr.sin_family = AF_INET;
client->addr.sin_port = htons(port);
memcpy(&client->addr.sin_addr, addr, sizeof(struct in_addr));
return 1;
}
void ADC_client_set_callback(struct ADC_client* client, adc_client_cb cb)
{
client->callback = cb;
}
-129
View File
@@ -1,129 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_ADC_CLIENT_H
#define HAVE_UHUB_ADC_CLIENT_H
#include "uhub.h"
#define ADC_BUFSIZE 16384
enum ADC_client_state
{
ps_none = 0x00, /* Not connected */
ps_conn = 0x01, /* Connecting... */
ps_protocol = 0x02, /* Have sent HSUP */
ps_identify = 0x04, /* Have sent BINF */
ps_verify = 0x08, /* Have sent HPAS */
ps_normal = 0x10, /* Are fully logged in */
};
struct ADC_client;
enum ADC_client_callback_type
{
ADC_CLIENT_CONNECTING = 1001,
ADC_CLIENT_CONNECTED = 1002,
ADC_CLIENT_DISCONNECTED = 1003,
ADC_CLIENT_LOGGING_IN = 2001,
ADC_CLIENT_PASSWORD_REQ = 2002,
ADC_CLIENT_LOGGED_IN = 2003,
ADC_CLIENT_LOGIN_ERROR = 2004,
ADC_CLIENT_PROTOCOL_STATUS = 3001,
ADC_CLIENT_MESSAGE = 3002,
ADC_CLIENT_CONNECT_REQ = 3003,
ADC_CLIENT_REVCONNECT_REQ = 3004,
ADC_CLIENT_SEARCH_REQ = 3005,
ADC_CLIENT_SEARCH_REP = 3006,
ADC_CLIENT_USER_JOIN = 4001,
ADC_CLIENT_USER_QUIT = 4002,
ADC_CLIENT_USER_UPDATE = 4003,
ADC_CLIENT_HUB_INFO = 5001,
};
struct ADC_hub_info
{
char* name;
char* description;
char* version;
};
struct ADC_chat_message
{
sid_t from_sid;
sid_t to_sid;
char* message;
int flags;
};
struct ADC_user
{
sid_t sid;
char* cid;
char* name;
char* description;
char* address;
char* version;
};
struct ADC_client_callback_data
{
union {
struct ADC_hub_info* hubinfo;
struct ADC_chat_message* chat;
struct ADC_user* user;
};
};
typedef int (*adc_client_cb)(struct ADC_client*, enum ADC_client_callback_type, struct ADC_client_callback_data* data);
struct ADC_client
{
sid_t sid;
enum ADC_client_state state;
struct adc_message* info;
char recvbuf[ADC_BUFSIZE];
char sendbuf[ADC_BUFSIZE];
adc_client_cb callback;
size_t s_offset;
size_t r_offset;
size_t timeout;
struct net_connection* con;
struct net_timer* timer;
struct sockaddr_in addr;
char* hub_address;
char* nick;
char* desc;
};
int ADC_client_create(struct ADC_client* client, const char* nickname, const char* description);
void ADC_client_set_callback(struct ADC_client* client, adc_client_cb);
void ADC_client_destroy(struct ADC_client* client);
int ADC_client_connect(struct ADC_client* client, const char* address);
void ADC_client_disconnect(struct ADC_client* client);
void ADC_client_send(struct ADC_client* client, char* msg);
#endif /* HAVE_UHUB_ADC_CLIENT_H */
-475
View File
@@ -1,475 +0,0 @@
/**
* An ADC client emulator.
*/
#include "adcclient.h"
#define ADC_CLIENTS_DEFAULT 100
#define ADC_MAX_CLIENTS 25000
#define ADC_CID_SIZE 39
#define BIG_BUFSIZE 32768
#define TIGERSIZE 24
#define ADCRUSH "adcrush/0.3"
#define ADC_NICK "[BOT]adcrush"
#define ADC_DESC "crash\\stest\\sdummy"
#define LVL_INFO 1
#define LVL_DEBUG 2
#define LVL_VERBOSE 3
static const char* cfg_uri = 0; /* address */
static int cfg_debug = 0; /* debug level */
static int cfg_level = 1; /* activity level (0..3) */
static int cfg_chat = 0; /* chat mode, allow sending chat messages */
static int cfg_quiet = 0; /* quiet mode (no output) */
static int cfg_clients = ADC_CLIENTS_DEFAULT; /* number of clients */
static int running = 1;
#define MAX_CHAT_MSGS 35
const char* chat_messages[MAX_CHAT_MSGS] = {
"hello",
"I'm an annoying robot, configured to chat in order to measure performance of the hub.",
"I apologize for the inconvenience.",
".",
":)",
"can anyone help me, pls?",
"wtf?",
"bullshit",
"resistance is futile.",
"You crossed the line first, sir. You squeezed them, you hammered them to the point of desperation. And in their desperation they turned to a man they didn't fully understand.",
"beam me up, scotty",
"morning",
"You know where Harvey is? You know who he is?",
"gtg",
"thanks",
"*punt*",
"*nudge*",
"that's ok",
"...anyway",
"hola",
"hey",
"hi",
"nevermind",
"i think so",
"dunno",
"debian ftw",
"oops",
"how do I search?",
"how do I enable active mode?",
"home, sweet home...",
"later",
"Good evening, ladies and gentlemen. We are tonight's entertainment! I only have one question. Where is Harvey Dent?",
"You know where I can find Harvey? I need to talk to him about something. Just something, a little.",
"We really should stop fighting, we'll miss the fireworks!",
"Wanna know how I got these scars?",
};
#define MAX_SEARCH_MSGS 10
const char* search_messages[MAX_SEARCH_MSGS] = {
"ANmp3 TOauto",
"ANxxx TOauto",
"ANdivx TOauto",
"ANtest ANfoo TOauto",
"ANwmv TO1289718",
"ANbabe TO8981884",
"ANpr0n TOauto",
"ANmusic TOauto",
"ANvideo TOauto",
"ANburnout ANps3 TOauto",
};
static void bot_output(struct ADC_client* client, int level, const char* format, ...)
{
char logmsg[1024];
va_list args;
va_start(args, format);
vsnprintf(logmsg, 1024, format, args);
va_end(args);
if (cfg_debug >= level)
fprintf(stdout, "* [%p] %s\n", client, logmsg);
}
#if 0
static size_t get_wait_rand(size_t max)
{
static size_t next = 0;
if (next == 0) next = (size_t) time(0);
next = (next * 1103515245) + 12345;
return ((size_t )(next / 65536) % max);
}
static void perf_result(struct ADC_client* client, sid_t target, const char* what, const char* token);
static void perf_chat(struct ADC_client* client, int priv)
{
char buf[1024] = { 0, };
size_t r = get_wait_rand(MAX_CHAT_MSGS-1);
char* msg = adc_msg_escape(chat_messages[r]);
if (priv)
{
strcat(buf, "EMSG ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " ");
strcat(buf, sid_to_string(client->sid));
}
else
{
strcat(buf, "BMSG ");
strcat(buf, sid_to_string(client->sid));
}
strcat(buf, " ");
strcat(buf, msg);
hub_free(msg);
strcat(buf, "\n");
ADC_client_send(client, buf);
}
static void perf_search(struct ADC_client* client)
{
char buf[1024] = { 0, };
size_t r = get_wait_rand(MAX_SEARCH_MSGS-1);
size_t pst = get_wait_rand(100);
if (pst > 80)
{
strcat(buf, "FSCH ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " +TCP4 ");
}
else
{
strcat(buf, "BSCH ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " ");
}
strcat(buf, search_messages[r]);
strcat(buf, "\n");
ADC_client_send(client, buf);
}
static void perf_result(struct ADC_client* client, sid_t target, const char* what, const char* token)
{
char buf[1024] = { 0, };
strcat(buf, "DRES ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " ");
strcat(buf, sid_to_string(target));
strcat(buf, " FN" "test/");
strcat(buf, what);
strcat(buf, ".dat");
strcat(buf, " SL" "0");
strcat(buf, " SI" "908987128912");
strcat(buf, " TR" "5T6YJYKO3WECS52BKWVSOP5VUG4IKNSZBZ5YHBA");
strcat(buf, " TO");
strcat(buf, token);
strcat(buf, "\n");
ADC_client_send(client, buf);
}
static void perf_ctm(struct ADC_client* client)
{
char buf[1024] = { 0, };
strcat(buf, "DCTM ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " ");
strcat(buf, "ADC/1.0");
strcat(buf, " TOKEN111");
strcat(buf, sid_to_string(client->sid));
strcat(buf, "\n");
ADC_client_send(client, buf);
}
static void perf_update(struct ADC_client* client)
{
char buf[1024] = { 0, };
int n = (int) get_wait_rand(10)+1;
strcat(buf, "BINF ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " HN");
strcat(buf, uhub_itoa(n));
strcat(buf, "\n");
ADC_client_send(client, buf);
}
static void perf_normal_action(struct ADC_client* client)
{
size_t r = get_wait_rand(5);
size_t p = get_wait_rand(100);
switch (r)
{
case 0:
if (p > (90 - (10 * cfg_level)))
{
bot_output(client, LVL_VERBOSE, "timeout -> disconnect");
ADC_client_disconnect(client);
}
break;
case 1:
if (cfg_chat)
{
bot_output(client, LVL_VERBOSE, "timeout -> chat");
perf_chat(client, 0);
}
break;
case 2:
bot_output(client, LVL_VERBOSE, "timeout -> search");
perf_search(client);
break;
case 3:
bot_output(client, LVL_VERBOSE, "timeout -> update");
perf_update(client);
break;
case 4:
bot_output(client, LVL_VERBOSE, "timeout -> privmsg");
perf_chat(client, 1);
break;
case 5:
bot_output(client, LVL_VERBOSE, "timeout -> ctm/rcm");
perf_ctm(client);
break;
}
}
#endif
static int handle(struct ADC_client* client, enum ADC_client_callback_type type, struct ADC_client_callback_data* data)
{
switch (type)
{
case ADC_CLIENT_CONNECTING:
bot_output(client, LVL_DEBUG, "*** Connecting...");
break;
case ADC_CLIENT_CONNECTED:
bot_output(client, LVL_DEBUG, "*** Connected.");
break;
case ADC_CLIENT_DISCONNECTED:
bot_output(client, LVL_DEBUG, "*** Disconnected.");
break;
case ADC_CLIENT_LOGGING_IN:
bot_output(client, LVL_DEBUG, "*** Logging in...");
break;
case ADC_CLIENT_PASSWORD_REQ:
bot_output(client, LVL_DEBUG, "*** Requesting password.");
case ADC_CLIENT_LOGGED_IN:
bot_output(client, LVL_DEBUG, "*** Logged in.");
break;
case ADC_CLIENT_LOGIN_ERROR:
bot_output(client, LVL_DEBUG, "*** Login error");
break;
case ADC_CLIENT_MESSAGE:
bot_output(client, LVL_DEBUG, " <%s> %s", sid_to_string(data->chat->from_sid), data->chat->message);
break;
case ADC_CLIENT_USER_JOIN:
bot_output(client, LVL_VERBOSE, " JOIN: %s", data->user->name);
break;
case ADC_CLIENT_USER_QUIT:
bot_output(client, LVL_VERBOSE, " QUIT");
break;
case ADC_CLIENT_SEARCH_REQ:
break;
case ADC_CLIENT_HUB_INFO:
bot_output(client, LVL_DEBUG, " Hub: \"%s\" [%s]\n"
" \"%s\"\n", data->hubinfo->name, data->hubinfo->version, data->hubinfo->description);
break;
default:
bot_output(client, LVL_DEBUG, "Not handled event=%d\n", (int) type);
return 0;
break;
}
return 1;
}
void runloop(size_t clients)
{
size_t n = 0;
struct ADC_client* client[ADC_MAX_CLIENTS];
for (n = 0; n < clients; n++)
{
struct ADC_client* c = malloc(sizeof(struct ADC_client));
client[n] = c;
char nick[20];
snprintf(nick, 20, "adcrush_%d", (int) n);
ADC_client_create(c, nick, "stresstester");
ADC_client_set_callback(c, handle);
ADC_client_connect(c, cfg_uri);
}
while (running)
{
event_base_loop(net_get_evbase(), EVLOOP_ONCE);
}
for (n = 0; n < clients; n++)
{
ADC_client_destroy(client[n]);
free(client[n]);
client[n] = 0;
}
}
static void print_version()
{
printf(ADCRUSH "\n");
printf("Copyright (C) 2008-2009, Jan Vidar Krey\n");
printf("\n");
}
static void print_usage(const char* program)
{
print_version();
printf("Usage: %s [adc[s]://<host>:<port>] [options]\n", program);
printf("\n");
printf(" OPTIONS\n");
printf(" -l <0-3> Level: 0=polite, 1=normal (default), 2=aggressive, 3=excessive.\n");
printf(" -n <num> Number of concurrent connections\n");
printf(" -c Allow broadcasting chat messages.\n");
printf(" -d Enable debug output.\n");
printf(" -q Quiet mode (no output).\n");
printf("\n");
exit(0);
}
int parse_address(const char* arg)
{
if (!arg || strlen(arg) < 9)
return 0;
if (strncmp(arg, "adc://", 6) && strncmp(arg, "adcs://", 7))
return 0;
cfg_uri = arg;
return 1;
}
int parse_arguments(int argc, char** argv)
{
int ok = 1;
int opt;
for (opt = 2; opt < argc; opt++)
{
if (!strcmp(argv[opt], "-c"))
cfg_chat = 1;
else if (!strncmp(argv[opt], "-d", 2))
cfg_debug += strlen(argv[opt]) - 1;
else if (!strcmp(argv[opt], "-q"))
cfg_quiet = 1;
else if (!strcmp(argv[opt], "-l") && (++opt) < argc)
{
cfg_level = MIN(MAX(uhub_atoi(argv[opt]), 0), 3);
}
else if (!strcmp(argv[opt], "-n") && (++opt) < argc)
{
cfg_clients = MIN(MAX(uhub_atoi(argv[opt]), 1), ADC_MAX_CLIENTS);
}
}
return ok;
}
void parse_command_line(int argc, char** argv)
{
if (argc < 2 ||
!parse_address(argv[1]) ||
!parse_arguments(argc, argv))
{
print_usage(argv[0]);
}
}
#ifndef WIN32
static void handle_signal(int signal, short events, void* arg)
{
switch (signal)
{
case SIGINT:
case SIGTERM:
running = 0;
break;
default:
break;
}
}
static struct event signal_events[10];
static int signals[] =
{
SIGINT, /* Interrupt the application */
SIGTERM, /* Terminate the application */
0
};
void setup_signal_handlers()
{
int i = 0;
for (i = 0; signals[i]; i++)
{
signal_set(&signal_events[i], signals[i], handle_signal, NULL);
signal_add(&signal_events[i], NULL);
}
}
void shutdown_signal_handlers()
{
int i = 0;
for (i = 0; signals[i]; i++)
{
signal_del(&signal_events[i]);
}
}
#endif /* WIN32 */
int main(int argc, char** argv)
{
parse_command_line(argc, argv);
net_initialize();
setup_signal_handlers();
hub_log_initialize(NULL, 0);
hub_set_log_verbosity(1000);
runloop(cfg_clients);
shutdown_signal_handlers();
net_destroy();
return 0;
}
-89
View File
@@ -1,89 +0,0 @@
/**
* A remote uhub admin client.
*/
#include "adcclient.h"
static int handle(struct ADC_client* client, enum ADC_client_callback_type type, struct ADC_client_callback_data* data)
{
switch (type)
{
case ADC_CLIENT_CONNECTING:
puts("*** Connecting...");
break;
case ADC_CLIENT_CONNECTED:
puts("*** Connected.");
break;
case ADC_CLIENT_DISCONNECTED:
puts("*** Disconnected.");
break;
case ADC_CLIENT_LOGGING_IN:
puts("*** Logging in...");
break;
case ADC_CLIENT_PASSWORD_REQ:
puts("*** Requesting password.");
case ADC_CLIENT_LOGGED_IN:
puts("*** Logged in.");
break;
case ADC_CLIENT_LOGIN_ERROR:
puts("*** Login error");
break;
case ADC_CLIENT_MESSAGE:
printf(" <%s> %s\n", sid_to_string(data->chat->from_sid), data->chat->message);
break;
case ADC_CLIENT_USER_JOIN:
printf(" JOIN: %s\n", data->user->name);
break;
case ADC_CLIENT_USER_QUIT:
printf(" QUIT\n");
break;
case ADC_CLIENT_SEARCH_REQ:
break;
case ADC_CLIENT_HUB_INFO:
printf(" Hub: \"%s\" [%s]\n"
" \"%s\"\n", data->hubinfo->name, data->hubinfo->version, data->hubinfo->description);
break;
default:
printf("Not handled event=%d\n", (int) type);
return 0;
break;
}
return 1;
}
int main(int argc, char** argv)
{
if (argc < 2)
{
printf("Usage: %s adc[s]://host:port\n", argv[0]);
return 1;
}
struct ADC_client client;
net_initialize();
ADC_client_create(&client, "uhub-admin", "stresstester");
ADC_client_set_callback(&client, handle);
ADC_client_connect(&client, argv[1]);
event_dispatch();
ADC_client_destroy(&client);
net_destroy();
return 0;
}
-35
View File
@@ -1,35 +0,0 @@
enum commandMode
{
cm_bcast = 0x01, /* B - broadcast */
cm_dir = 0x02, /* D - direct message */
cm_echo = 0x04, /* E - echo message */
cm_fcast = 0x08, /* F - feature cast message */
cm_c2h = 0x10, /* H - client to hub message */
cm_h2c = 0x20, /* I - hub to client message */
cm_c2c = 0x40, /* C - client to client message */
cm_udp = 0x80, /* U - udp message (client to client) */
};
enum commandValidity
{
cv_protocol = 0x01,
cv_identify = 0x02,
cv_verify = 0x04,
cv_normal = 0x08,
};
const struct commandPattern patterns[] =
{
{ cm_c2h | cm_c2c | cm_h2c, "SUP", cv_protocol | cv_normal }, /* protocol support */
{ cm_bcast | cm_h2c | cm_c2c, "INF", cv_identify | cv_verify | cv_normal }, /* info message */
{ cm_bcast | cm_h2c | cm_c2c | cm_c2h | cm_udp, "STA", cv_protocol | cv_identify | cv_verify | cv_normal }, /* status message */
{ cm_bcast | cm_dir | cm_echo | cm_h2c, "MSG", cv_normal }, /* chat message */
{ cm_bcast | cm_dir | cm_echo | cm_fcast, "SCH", cv_normal }, /* search */
{ cm_dir | cm_udp, "RES", cv_normal }, /* search result */
{ cm_dir | cm_echo, "CTM", cv_normal }, /* connect to me */
{ cm_dir | cm_echo, "RCM", cv_normal }, /* reversed, connect to me */
{ cm_h2c, "QUI", cv_normal }, /* quit message */
{ cm_h2c, "GPA", cv_identify }, /* password request */
{ cm_c2h, "PAS", cv_verify } /* password response */
};
-94
View File
@@ -1,94 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_COMMON_H
#define HAVE_UHUB_COMMON_H
/* Debugging */
/* #define NETWORK_DUMP_DEBUG */
/* #define MEMORY_DEBUG */
/* #define DEBUG_SENDQ 1 */
#include "system.h"
#ifndef WIN32
#define SERVER_CONFIG "/etc/uhub/uhub.conf"
#define SERVER_ACL_FILE "/etc/uhub/users.conf"
#else
#define SERVER_CONFIG "uhub.conf"
#define SERVER_ACL_FILE "users.conf"
#ifndef stderr
#define stderr stdout
#endif
#endif
#define TIMEOUT_CONNECTED 15
#define TIMEOUT_HANDSHAKE 30
#define TIMEOUT_SENDQ 120
#define TIMEOUT_STATS 60
#define MAX_CID_LEN 39
#define MAX_NICK_LEN 64
#define MAX_UA_LEN 32
#define TIGERSIZE 24
#define MAX_RECV_BUF 65535
#define MAX_SEND_BUF 65535
#ifdef __cplusplus
extern "C" {
#endif
#include "adc/adcconst.h"
#include "util/ipcalc.h"
#include "util/list.h"
#include "util/log.h"
#include "util/memory.h"
#include "util/misc.h"
#include "util/timeout.h"
#include "util/tiger.h"
#include "adc/sid.h"
#include "adc/message.h"
#include "network/network.h"
#include "network/connection.h"
#include "core/auth.h"
#include "core/config.h"
#include "core/eventid.h"
#include "core/eventqueue.h"
#include "core/netevent.h"
#include "core/hubio.h"
#include "core/user.h"
#include "core/usermanager.h"
#include "core/route.h"
#include "core/hub.h"
#include "core/commands.h"
#include "core/inf.h"
#include "core/hubevent.h"
#ifdef __cplusplus
}
#endif
#endif /* HAVE_UHUB_COMMON_H */
-491
View File
@@ -1,491 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#include "uhub.h"
int ip_is_valid_ipv4(const char* address)
{
int i = 0; /* address index */
int o = 0; /* octet number */
int n = 0; /* numbers after each dot */
int d = 0; /* dots */
if (!address || strlen(address) > 15 || strlen(address) < 7)
return 0;
for (; i < strlen(address); i++)
{
if (is_num(address[i]))
{
n++;
o *= 10;
o += (address[i] - '0');
}
else if (address[i] == '.')
{
if (n == 0 || n > 3 || o > 255) return 0;
n = 0;
o = 0;
d++;
}
else
{
return 0;
}
}
if (n == 0 || n > 3 || o > 255 || d != 3) return 0;
return 1;
}
int ip_is_valid_ipv6(const char* address)
{
unsigned char buf[16];
int ret = net_string_to_address(AF_INET6, address, buf);
if (ret <= 0) return 0;
return 1;
}
int ip_convert_to_binary(const char* taddr, struct ip_addr_encap* raw)
{
if (ip_is_valid_ipv6(taddr))
{
if (net_string_to_address(AF_INET6, taddr, &raw->internal_ip_data.in6) <= 0)
{
return -1;
}
raw->af = AF_INET6;
return AF_INET6;
}
else if (ip_is_valid_ipv4(taddr))
{
if (net_string_to_address(AF_INET, taddr, &raw->internal_ip_data.in) <= 0)
{
return -1;
}
raw->af = AF_INET;
return AF_INET;
}
return -1;
}
const char* ip_convert_to_string(struct ip_addr_encap* raw)
{
static char address[INET6_ADDRSTRLEN+1];
memset(address, 0, INET6_ADDRSTRLEN);
net_address_to_string(raw->af, (void*) &raw->internal_ip_data, address, INET6_ADDRSTRLEN+1);
if (strncmp(address, "::ffff:", 7) == 0) /* IPv6 mapped IPv4 address. */
{
return &address[7];
}
return address;
}
int ip_convert_address(const char* text_address, int port, struct sockaddr* addr, socklen_t* addr_len)
{
struct sockaddr_in6 addr6;
struct sockaddr_in addr4;
size_t sockaddr_size;
const char* taddr = 0;
int ipv6sup = net_is_ipv6_supported();
if (strcmp(text_address, "any") == 0)
{
if (ipv6sup)
{
taddr = "::";
}
else
{
taddr = "0.0.0.0";
}
}
else if (strcmp(text_address, "loopback") == 0)
{
if (ipv6sup)
{
taddr = "::1";
}
else
{
taddr = "127.0.0.1";
}
}
else
{
taddr = text_address;
}
if (ip_is_valid_ipv6(taddr) && ipv6sup)
{
sockaddr_size = sizeof(struct sockaddr_in6);
memset(&addr6, 0, sockaddr_size);
addr6.sin6_family = AF_INET6;
addr6.sin6_port = htons(port);
if (net_string_to_address(AF_INET6, taddr, &addr6.sin6_addr) <= 0)
{
LOG_ERROR("Unable to convert socket address (ipv6)");
return 0;
}
memcpy(addr, &addr6, sockaddr_size);
*addr_len = sockaddr_size;
}
else if (ip_is_valid_ipv4(taddr))
{
sockaddr_size = sizeof(struct sockaddr_in);
memset(&addr4, 0, sockaddr_size);
addr4.sin_family = AF_INET;
addr4.sin_port = htons(port);
if (net_string_to_address(AF_INET, taddr, &addr4.sin_addr) <= 0)
{
LOG_ERROR("Unable to convert socket address (ipv4)");
return 0;
}
memcpy(addr, &addr4, sockaddr_size);
*addr_len = sockaddr_size;
}
else
{
addr = 0;
*addr_len = 0;
return -1;
}
return 0;
}
int ip_mask_create_left(int af, int bits, struct ip_addr_encap* result)
{
uint32_t mask;
int fill, remain_bits, n;
memset(result, 0, sizeof(struct ip_addr_encap));
result->af = af;
if (bits < 0) bits = 0;
if (af == AF_INET)
{
if (bits > 32) bits = 32;
mask = (0xffffffff << (32 - bits));
if (bits == 0) mask = 0;
result->internal_ip_data.in.s_addr = (((uint8_t*) &mask)[0] << 24) | (((uint8_t*) &mask)[1] << 16) | (((uint8_t*) &mask)[2] << 8) | (((uint8_t*) &mask)[3] << 0);
}
else if (af == AF_INET6)
{
if (bits > 128) bits = 128;
fill = (128-bits) / 8;
remain_bits = (128-bits) % 8;
mask = (0xff << (8 - remain_bits));
n = 0;
for (n = 0; n < fill; n++)
((uint8_t*) &result->internal_ip_data.in6)[n] = (uint8_t) 0xff;
if (fill < 16)
((uint8_t*) &result->internal_ip_data.in6)[fill] = (uint8_t) mask;
}
else
{
return -1;
}
#ifdef IP_CALC_DEBUG
char* r_str = hub_strdup(ip_convert_to_string(result));
LOG_DUMP("Created left mask: %s", r_str);
hub_free(r_str);
#endif
return 0;
}
int ip_mask_create_right(int af, int bits, struct ip_addr_encap* result)
{
uint32_t mask;
int fill, remain_bits, n, start;
uint8_t mask8;
memset(result, 0, sizeof(struct ip_addr_encap));
result->af = af;
if (bits < 0) bits = 0;
if (af == AF_INET)
{
if (bits > 32) bits = 32;
mask = (0xffffffff >> (32-bits));
if (bits == 0) mask = 0;
result->internal_ip_data.in.s_addr = (((uint8_t*) &mask)[0] << 24) | (((uint8_t*) &mask)[1] << 16) | (((uint8_t*) &mask)[2] << 8) | (((uint8_t*) &mask)[3] << 0);
}
else if (af == AF_INET6)
{
if (bits > 128) bits = 128;
fill = (128-bits) / 8;
remain_bits = (128-bits) % 8;
mask8 = (0xff >> (8 - remain_bits));
n = 0;
start = 16-fill;
for (n = 0; n < start; n++)
((uint8_t*) &result->internal_ip_data.in6)[n] = (uint8_t) 0x00;
for (n = start; n < 16; n++)
((uint8_t*) &result->internal_ip_data.in6)[n] = (uint8_t) 0xff;
if (start > 0)
((uint8_t*) &result->internal_ip_data.in6)[start-1] = (uint8_t) mask8;
}
else
{
return -1;
}
#ifdef IP_CALC_DEBUG
char* r_str = hub_strdup(ip_convert_to_string(result));
LOG_DUMP("Created right mask: %s", r_str);
hub_free(r_str);
#endif
return 0;
}
void ip_mask_apply_AND(struct ip_addr_encap* addr, struct ip_addr_encap* mask, struct ip_addr_encap* result)
{
memset(result, 0, sizeof(struct ip_addr_encap));
result->af = addr->af;
if (addr->af == AF_INET)
{
result->internal_ip_data.in.s_addr = addr->internal_ip_data.in.s_addr & mask->internal_ip_data.in.s_addr;
}
else if (addr->af == AF_INET6)
{
uint32_t A, B, C, D;
int n = 0;
int offset = 0;
for (n = 0; n < 4; n++)
{
offset = n * 4;
A = (((uint8_t*) &addr->internal_ip_data.in6)[offset+0] << 24) |
(((uint8_t*) &addr->internal_ip_data.in6)[offset+1] << 16) |
(((uint8_t*) &addr->internal_ip_data.in6)[offset+2] << 8) |
(((uint8_t*) &addr->internal_ip_data.in6)[offset+3] << 0);
B = (((uint8_t*) &mask->internal_ip_data.in6)[offset+0] << 24) |
(((uint8_t*) &mask->internal_ip_data.in6)[offset+1] << 16) |
(((uint8_t*) &mask->internal_ip_data.in6)[offset+2] << 8) |
(((uint8_t*) &mask->internal_ip_data.in6)[offset+3] << 0);
C = A & B;
D = (((uint8_t*) &C)[0] << 24) |
(((uint8_t*) &C)[1] << 16) |
(((uint8_t*) &C)[2] << 8) |
(((uint8_t*) &C)[3] << 0);
((uint32_t*) &result->internal_ip_data.in6)[n] = D;
}
}
}
void ip_mask_apply_OR(struct ip_addr_encap* addr, struct ip_addr_encap* mask, struct ip_addr_encap* result)
{
memset(result, 0, sizeof(struct ip_addr_encap));
result->af = addr->af;
if (addr->af == AF_INET)
{
result->internal_ip_data.in.s_addr = addr->internal_ip_data.in.s_addr | mask->internal_ip_data.in.s_addr;
}
else if (addr->af == AF_INET6)
{
uint32_t A, B, C, D;
int n = 0;
int offset = 0;
for (n = 0; n < 4; n++)
{
offset = n * 4;
A = (((uint8_t*) &addr->internal_ip_data.in6)[offset+0] << 24) |
(((uint8_t*) &addr->internal_ip_data.in6)[offset+1] << 16) |
(((uint8_t*) &addr->internal_ip_data.in6)[offset+2] << 8) |
(((uint8_t*) &addr->internal_ip_data.in6)[offset+3] << 0);
B = (((uint8_t*) &mask->internal_ip_data.in6)[offset+0] << 24) |
(((uint8_t*) &mask->internal_ip_data.in6)[offset+1] << 16) |
(((uint8_t*) &mask->internal_ip_data.in6)[offset+2] << 8) |
(((uint8_t*) &mask->internal_ip_data.in6)[offset+3] << 0);
C = A | B;
D = (((uint8_t*) &C)[0] << 24) |
(((uint8_t*) &C)[1] << 16) |
(((uint8_t*) &C)[2] << 8) |
(((uint8_t*) &C)[3] << 0);
((uint32_t*) &result->internal_ip_data.in6)[n] = D;
}
}
}
int ip_compare(struct ip_addr_encap* a, struct ip_addr_encap* b)
{
int ret = 0;
uint32_t A, B;
if (a->af == AF_INET)
{
A = (((uint8_t*) &a->internal_ip_data.in.s_addr)[0] << 24) |
(((uint8_t*) &a->internal_ip_data.in.s_addr)[1] << 16) |
(((uint8_t*) &a->internal_ip_data.in.s_addr)[2] << 8) |
(((uint8_t*) &a->internal_ip_data.in.s_addr)[3] << 0);
B = (((uint8_t*) &b->internal_ip_data.in.s_addr)[0] << 24) |
(((uint8_t*) &b->internal_ip_data.in.s_addr)[1] << 16) |
(((uint8_t*) &b->internal_ip_data.in.s_addr)[2] << 8) |
(((uint8_t*) &b->internal_ip_data.in.s_addr)[3] << 0);
ret = A - B;
}
else if (a->af == AF_INET6)
{
int n = 0;
int offset = 0;
for (n = 0; n < 4; n++)
{
offset = n * 4;
A = (((uint8_t*) &a->internal_ip_data.in6)[offset+0] << 24) |
(((uint8_t*) &a->internal_ip_data.in6)[offset+1] << 16) |
(((uint8_t*) &a->internal_ip_data.in6)[offset+2] << 8) |
(((uint8_t*) &a->internal_ip_data.in6)[offset+3] << 0);
B = (((uint8_t*) &b->internal_ip_data.in6)[offset+0] << 24) |
(((uint8_t*) &b->internal_ip_data.in6)[offset+1] << 16) |
(((uint8_t*) &b->internal_ip_data.in6)[offset+2] << 8) |
(((uint8_t*) &b->internal_ip_data.in6)[offset+3] << 0);
if (A == B) continue;
return A - B;
}
return 0;
}
#ifdef IP_CALC_DEBUG
char* a_str = hub_strdup(ip_convert_to_string(a));
char* b_str = hub_strdup(ip_convert_to_string(b));
LOG_DUMP("Comparing IPs '%s' AND '%s' => %d", a_str, b_str, ret);
hub_free(a_str);
hub_free(b_str);
#endif
return ret;
}
static int check_ip_mask(const char* text_addr, int bits, struct ip_range* range)
{
if (ip_is_valid_ipv4(text_addr) || ip_is_valid_ipv6(text_addr))
{
struct ip_addr_encap addr;
struct ip_addr_encap mask1;
struct ip_addr_encap mask2;
int af = ip_convert_to_binary(text_addr, &addr); /* 192.168.1.2 */
int maxbits = (af == AF_INET6 ? 128 : 32);
bits = MIN(MAX(bits, 0), maxbits);
ip_mask_create_left(af, bits, &mask1); /* 255.255.255.0 */
ip_mask_create_right(af, maxbits - bits, &mask2); /* 0.0.0.255 */
ip_mask_apply_AND(&addr, &mask1, &range->lo); /* 192.168.1.0 */
ip_mask_apply_OR(&range->lo, &mask2, &range->hi); /* 192.168.1.255 */
return 1;
}
return 0;
}
static int check_ip_range(const char* lo, const char* hi, struct ip_range* range)
{
int ret1, ret2;
if ((ip_is_valid_ipv4(lo) && ip_is_valid_ipv4(hi)) || (ip_is_valid_ipv6(lo) && ip_is_valid_ipv6(hi)))
{
ret1 = ip_convert_to_binary(lo, &range->lo);
ret2 = ip_convert_to_binary(hi, &range->hi);
if (ret1 == -1 || ret2 == -1 || ret1 != ret2)
{
return 0;
}
return 1;
}
return 0;
}
int ip_convert_address_to_range(const char* address, struct ip_range* range)
{
int ret = 0;
char* addr = 0;
if (!address || !range)
return 0;
const char* split = strrchr(address, '/');
if (split)
{
int mask = uhub_atoi(split+1);
if (mask == 0 && split[1] != '0') return 0;
addr = hub_strndup(address, split - address);
ret = check_ip_mask(addr, mask, range);
hub_free(addr);
return ret;
}
split = strrchr(address, '-');
if (split)
{
addr = hub_strndup(address, split - address);
ret = check_ip_range(addr, split+1, range);
hub_free(addr);
return ret;
}
if (ip_is_valid_ipv4(address) || ip_is_valid_ipv6(address))
{
if (ip_convert_to_binary(address, &range->lo) == -1)
return 0;
memcpy(&range->hi, &range->lo, sizeof(struct ip_addr_encap));
return 1;
}
return 0;
}
int ip_in_range(struct ip_addr_encap* addr, struct ip_range* range)
{
return (addr->af == range->lo.af && ip_compare(&range->lo, addr) <= 0 && ip_compare(addr, &range->hi) <= 0);
}
-114
View File
@@ -1,114 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
/*
* This file is used for fiddling with IP-addresses,
* primarily used for IP-banning in uhub.
*/
#ifndef HAVE_UHUB_IPCALC_H
#define HAVE_UHUB_IPCALC_H
struct ip_addr_encap {
int af;
union {
struct in_addr in;
struct in6_addr in6;
} internal_ip_data;
};
struct ip_range
{
struct ip_addr_encap lo;
struct ip_addr_encap hi;
};
extern int ip_convert_to_binary(const char* text_addr, struct ip_addr_encap* raw);
extern const char* ip_convert_to_string(struct ip_addr_encap* raw);
/**
* Convert a string on the form:
* ip-ip or ip/mask to an iprange.
*
* Note: both IPv4 and IPv6 addresses are valid, but if a range is given
* both addresses must be of the same address family.
*
* Valid examples of address
* IPv4:
* 192.168.2.1
* 192.168.0.0/16
* 192.168.0.0-192.168.255.255
*
* IPv6:
* 2001:4860:A005::68
* 2001:4860:A005::0/80
* 2001:4860:A005::0-2001:4860:A005:ffff:ffff:ffff:ffff:ffff
*
* @return 0 if invalid, 1 if OK
*/
extern int ip_convert_address_to_range(const char* address, struct ip_range* range);
/**
* @return 1 if addr is inside range, 0 otherwise
*/
extern int ip_in_range(struct ip_addr_encap* addr, struct ip_range* range);
/**
* @return 1 if address is a valid IPv4 address in text notation
* 0 if invalid
*/
extern int ip_is_valid_ipv4(const char* address);
/**
* @return 1 if address is a valid IPv6 address in text notation
* 0 if invalid
*/
extern int ip_is_valid_ipv6(const char* address);
/**
* This function converts an IP address in text_address to a binary
* struct sockaddr.
* This will auto-detect if the IP-address is IPv6 (and that is supported),
* or if IPv4 should be used.
* NOTE: Use sockaddr_storage to allocate enough memory for IPv6.
*
* @param text_addr is an ipaddress either ipv6 or ipv4.
* Special magic addresses called "any" and "loopback" exist,
* and will work accross IPv6/IPv4.
* @param port Fill the struct sockaddr* with the given port, can safely be ignored.
*/
extern int ip_convert_address(const char* text_address, int port, struct sockaddr* addr, socklen_t* addr_len);
extern int ip_mask_create_left(int af, int bits, struct ip_addr_encap* result);
extern int ip_mask_create_right(int af, int bits, struct ip_addr_encap* result);
extern void ip_mask_apply_AND(struct ip_addr_encap* address, struct ip_addr_encap* mask, struct ip_addr_encap* result);
extern void ip_mask_apply_OR(struct ip_addr_encap* address, struct ip_addr_encap* mask, struct ip_addr_encap* result);
/**
* @return <0 if a is less than b
* @return >0 if a is greater than b
* @return 0 if they are equal
*/
extern int ip_compare(struct ip_addr_encap* a, struct ip_addr_encap* b);
#endif /* HAVE_UHUB_IPCALC_H */
-197
View File
@@ -1,197 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#include "uhub.h"
struct linked_list* list_create()
{
struct linked_list* list = NULL;
list = (struct linked_list*) hub_malloc_zero(sizeof(struct linked_list));
if (list == NULL)
return NULL;
return list;
}
void list_destroy(struct linked_list* list)
{
if (list)
hub_free(list);
}
void list_clear(struct linked_list* list, void (*free_handle)(void* ptr))
{
struct node* node = list->first;
struct node* tmp = NULL;
while (node)
{
tmp = node->next;
free_handle(node->ptr);
hub_free(node);
node = tmp;
}
memset(list, 0, sizeof(struct linked_list));
}
void list_append(struct linked_list* list, void* data_ptr)
{
struct node* new_node = (struct node*) hub_malloc_zero(sizeof(struct node));
if (!new_node)
{
LOG_FATAL("Unable to allocate memory");
return;
}
new_node->ptr = data_ptr;
if (list->last)
{
list->last->next = new_node;
new_node->prev = list->last;
}
else
{
list->first = new_node;
}
list->last = new_node;
list->size++;
}
void list_remove(struct linked_list* list, void* data_ptr)
{
struct node* node = list->first;
assert(data_ptr);
list->iterator = NULL;
while (node)
{
if (node->ptr == data_ptr)
{
if (node->next)
node->next->prev = node->prev;
if (node->prev)
node->prev->next = node->next;
if (node == list->last)
list->last = node->prev;
if (node == list->first)
list->first = node->next;
hub_free(node);
list->size--;
break;
}
node = node->next;
}
}
size_t list_size(struct linked_list* list)
{
return list->size;
}
void* list_get_index(struct linked_list* list, size_t offset)
{
struct node* node = list->first;
size_t n = 0;
for (n = 0; n < list->size; n++)
{
if (n == offset)
{
return node->ptr;
}
node = node->next;
}
return NULL;
}
void* list_get_first(struct linked_list* list)
{
list->iterator = list->first;
if (list->iterator == NULL)
return NULL;
return list->iterator->ptr;
}
struct node* list_get_first_node(struct linked_list* list)
{
list->iterator = list->first;
if (list->iterator == NULL)
return NULL;
return list->iterator;
}
void* list_get_last(struct linked_list* list)
{
list->iterator = list->last;
if (list->iterator == NULL)
return NULL;
return list->iterator->ptr;
}
struct node* list_get_last_node(struct linked_list* list)
{
list->iterator = list->last;
if (list->iterator == NULL)
return NULL;
return list->iterator;
}
void* list_get_next(struct linked_list* list)
{
if (list->iterator == NULL)
list->iterator = list->first;
else
list->iterator = list->iterator->next;
if (list->iterator == NULL)
return NULL;
return list->iterator->ptr;
}
void* list_get_prev(struct linked_list* list)
{
if (list->iterator == NULL)
return NULL;
list->iterator = list->iterator->prev;
if (list->iterator == NULL)
return NULL;
return list->iterator->ptr;
}
-61
View File
@@ -1,61 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_LINKED_LIST_H
#define HAVE_UHUB_LINKED_LIST_H
struct linked_list
{
size_t size;
struct node* first;
struct node* last;
struct node* iterator;
};
struct node
{
void* ptr;
struct node* next;
struct node* prev;
};
extern struct linked_list* list_create();
extern void list_destroy(struct linked_list*);
extern void list_clear(struct linked_list*, void (*free_handle)(void* ptr) );
extern void list_append(struct linked_list* list, void* data_ptr);
/**
* Remove data_ptr from the list. If multiple versions occur, only the first one is removed.
*/
extern void list_remove(struct linked_list* list, void* data_ptr);
extern size_t list_size(struct linked_list* list);
extern void* list_get_index(struct linked_list*, size_t offset);
extern void* list_get_first(struct linked_list*);
extern void* list_get_last(struct linked_list*);
extern void* list_get_next(struct linked_list*);
extern void* list_get_prev(struct linked_list*);
extern struct node* list_get_first_node(struct linked_list*);
extern struct node* list_get_last_node(struct linked_list*);
#endif /* HAVE_UHUB_LINKED_LIST_H */
-231
View File
@@ -1,231 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#include "uhub.h"
#include <locale.h>
#ifndef WIN32
#include <syslog.h>
static int use_syslog = 0;
#endif
static int verbosity = 4;
static FILE* logfile = NULL;
#ifdef MEMORY_DEBUG
static FILE* memfile = NULL;
#define MEMORY_DEBUG_FILE "memlog.txt"
#endif
#ifdef NETWORK_DUMP_DEBUG
#define NETWORK_DUMP_FILE "netdump.log"
static FILE* netdump = NULL;
#endif
static const char* prefixes[] =
{
"FATAL",
"ERROR",
"WARN",
"USER",
"INFO",
"DEBUG",
"TRACE",
"DUMP",
"MEM",
"PROTO",
0
};
void hub_log_initialize(const char* file, int syslog)
{
setlocale(LC_ALL, "C");
#ifdef MEMORY_DEBUG
memfile = fopen(MEMORY_DEBUG_FILE, "w");
if (!memfile)
{
fprintf(stderr, "Unable to create " MEMORY_DEBUG_FILE " for logging memory allocations\n");
return;
}
#endif
#ifdef NETWORK_DUMP_DEBUG
netdump = fopen(NETWORK_DUMP_FILE, "w");
if (!netdump)
{
fprintf(stderr, "Unable to create " NETWORK_DUMP_FILE " for logging network traffic\n");
return;
}
#endif
#ifndef WIN32
if (syslog)
{
use_syslog = 1;
openlog("uhub", LOG_PID, LOG_USER);
}
#endif
if (!file)
{
logfile = stderr;
return;
}
logfile = fopen(file, "a");
if (!logfile)
{
logfile = stderr;
return;
}
}
void hub_log_shutdown()
{
if (logfile && logfile != stderr)
{
fclose(logfile);
logfile = NULL;
}
#ifdef MEMORY_DEBUG
if (memfile)
{
fclose(memfile);
memfile = NULL;
}
#endif
#ifdef NETWORK_DUMP_DEBUG
if (netdump)
{
fclose(netdump);
netdump = NULL;
}
#endif
#ifndef WIN32
if (use_syslog)
{
use_syslog = 0;
closelog();
}
#endif
}
void hub_set_log_verbosity(int verb)
{
verbosity = verb;
}
void hub_log(int log_verbosity, const char *format, ...)
{
static char logmsg[1024];
static char timestamp[32];
struct tm *tmp;
time_t t;
va_list args;
#ifdef MEMORY_DEBUG
if (memfile && log_verbosity == log_memory)
{
va_start(args, format);
vsnprintf(logmsg, 1024, format, args);
va_end(args);
fprintf(memfile, "%s\n", logmsg);
fflush(memfile);
return;
}
#endif
#ifdef NETWORK_DUMP_DEBUG
if (netdump && log_verbosity == log_protocol)
{
va_start(args, format);
vsnprintf(logmsg, 1024, format, args);
va_end(args);
fprintf(netdump, "%s\n", logmsg);
fflush(netdump);
return;
}
#endif
if (log_verbosity < verbosity)
{
t = time(NULL);
tmp = localtime(&t);
strftime(timestamp, 32, "%Y-%m-%d %H:%M:%S", tmp);
va_start(args, format);
vsnprintf(logmsg, 1024, format, args);
va_end(args);
if (logfile)
{
fprintf(logfile, "%s %5s: %s\n", timestamp, prefixes[log_verbosity], logmsg);
fflush(logfile);
}
else
{
fprintf(stderr, "%s %5s: %s\n", timestamp, prefixes[log_verbosity], logmsg);
}
}
#ifndef WIN32
if (use_syslog)
{
int level = 0;
if (verbosity < log_info)
return;
va_start(args, format);
vsnprintf(logmsg, 1024, format, args);
va_end(args);
switch (log_verbosity)
{
case log_fatal: level = LOG_CRIT; break;
case log_error: level = LOG_ERR; break;
case log_warning: level = LOG_WARNING; break;
case log_user: level = LOG_INFO | LOG_AUTH; break;
case log_info: level = LOG_INFO; break;
case log_debug: level = LOG_DEBUG; break;
default:
level = 0;
break;
}
if (level == 0)
return;
level |= (LOG_USER | LOG_DAEMON);
syslog(level, "%s", logmsg);
}
#endif
}
-84
View File
@@ -1,84 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_LOG_H
#define HAVE_UHUB_LOG_H
enum log_verbosity {
log_fatal = 0,
log_error = 1,
log_warning = 2,
log_user = 3,
log_info = 4,
log_debug = 5,
log_trace = 6,
log_dump = 7,
log_memory = 8,
log_protocol = 9,
};
#define LOG_FATAL(format, ...) hub_log(log_fatal, format, ## __VA_ARGS__)
#define LOG_ERROR(format, ...) hub_log(log_error, format, ## __VA_ARGS__)
#define LOG_WARN(format, ...) hub_log(log_warning, format, ## __VA_ARGS__)
#define LOG_USER(format, ...) hub_log(log_user, format, ## __VA_ARGS__)
#define LOG_INFO(format, ...) hub_log(log_info, format, ## __VA_ARGS__)
#ifdef DEBUG
# define LOG_DEBUG(format, ...) hub_log(log_debug, format, ## __VA_ARGS__)
# define LOG_TRACE(format, ...) hub_log(log_trace, format, ## __VA_ARGS__)
#else
# define LOG_DEBUG(format, ...) do { } while(0)
# define LOG_TRACE(format, ...) do { } while(0)
#endif
#ifdef LOWLEVEL_DEBUG
# define LOG_DUMP(format, ...) hub_log(log_dump, format, ## __VA_ARGS__)
# define LOG_MEMORY(format, ...) hub_log(log_memory, format, ## __VA_ARGS__)
# define LOG_PROTO(format, ...) hub_log(log_protocol, format, ## __VA_ARGS__)
#else
# define LOG_DUMP(format, ...) do { } while(0)
# define LOG_MEMORY(format, ...) do { } while(0)
# define LOG_PROTO(format, ...) do { } while(0)
#endif
/**
* Specify a minimum log verbosity for what messages should
* be printed in the log.
*/
extern void hub_set_log_verbosity(int log_verbosity);
/**
* Print a message in the log.
*/
extern void hub_log(int log_verbosity, const char *format, ...);
/**
* Initialize the log subsystem, if no output file is given (file is null)
* stderr is assumed by default.
* If the file cannot be opened for writing, stdout is also used.
*/
extern void hub_log_initialize(const char* file, int syslog);
/**
* Shut down and close the logfile.
*/
extern void hub_log_shutdown();
#endif /* HAVE_UHUB_LOG_H */
-248
View File
@@ -1,248 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#include "uhub.h"
#ifdef MEMORY_DEBUG
#define REALTIME_MALLOC_TRACKING
#ifdef REALTIME_MALLOC_TRACKING
#define UHUB_MAX_ALLOCS 50000
struct malloc_info
{
void* ptr;
size_t size;
void* stack1;
void* stack2;
};
static int hub_alloc_count = 0;
static size_t hub_alloc_size = 0;
static int hub_alloc_peak_count = 0;
static size_t hub_alloc_peak_size = 0;
static size_t hub_alloc_oom = 0;
static struct malloc_info hub_allocs[UHUB_MAX_ALLOCS] = { { 0, }, };
static int malloc_slot = -1; /* free slot (-1, no slot) */
void internal_debug_print_leaks()
{
size_t n = 0;
size_t leak = 0;
size_t count = 0;
LOG_MEMORY("--- exit (allocs: %d, size: " PRINTF_SIZE_T ") ---", hub_alloc_count, hub_alloc_size);
for (; n < UHUB_MAX_ALLOCS; n++)
{
if (hub_allocs[n].ptr)
{
leak += hub_allocs[n].size;
count++;
LOG_MEMORY("leak %p size: " PRINTF_SIZE_T " (bt: %p %p)", hub_allocs[n].ptr, hub_allocs[n].size, hub_allocs[n].stack1, hub_allocs[n].stack2);
}
}
LOG_MEMORY("--- done (allocs: %d, size: " PRINTF_SIZE_T ", peak: %d/" PRINTF_SIZE_T ", oom: " PRINTF_SIZE_T ") ---", count, leak, hub_alloc_peak_count, hub_alloc_peak_size, hub_alloc_oom);
}
#endif /* REALTIME_MALLOC_TRACKING */
void* internal_debug_mem_malloc(size_t size, const char* where)
{
size_t n = 0;
char* ptr = malloc(size);
#ifdef REALTIME_MALLOC_TRACKING
/* Make sure the malloc info struct is initialized */
if (!hub_alloc_count)
{
LOG_MEMORY("--- start ---");
for (n = 0; n < UHUB_MAX_ALLOCS; n++)
{
hub_allocs[n].ptr = 0;
hub_allocs[n].size = 0;
hub_allocs[n].stack1 = 0;
hub_allocs[n].stack2 = 0;
}
atexit(&internal_debug_print_leaks);
}
if (ptr)
{
if (malloc_slot != -1)
n = (size_t) malloc_slot;
else
n = 0;
for (; n < UHUB_MAX_ALLOCS; n++)
{
if (!hub_allocs[n].ptr)
{
hub_allocs[n].ptr = ptr;
hub_allocs[n].size = size;
hub_allocs[n].stack1 = __builtin_return_address(1);
hub_allocs[n].stack2 = __builtin_return_address(2);
hub_alloc_size += size;
hub_alloc_count++;
hub_alloc_peak_count = MAX(hub_alloc_count, hub_alloc_peak_count);
hub_alloc_peak_size = MAX(hub_alloc_size, hub_alloc_peak_size);
LOG_MEMORY("%s %p (%d bytes) (bt: %p %p) {allocs: %d, size: " PRINTF_SIZE_T "}", where, ptr, (int) size, hub_allocs[n].stack1, hub_allocs[n].stack2, hub_alloc_count, hub_alloc_size);
break;
}
}
}
else
{
LOG_MEMORY("%s *** OOM for %d bytes", where, size);
hub_alloc_oom++;
return 0;
}
#endif /* REALTIME_MALLOC_TRACKING */
return ptr;
}
void internal_debug_mem_free(void* ptr)
{
#ifdef REALTIME_MALLOC_TRACKING
size_t n = 0;
void* stack1 = __builtin_return_address(1);
void* stack2 = __builtin_return_address(2);
if (!ptr) return;
for (; n < UHUB_MAX_ALLOCS; n++)
{
if (hub_allocs[n].ptr == ptr)
{
hub_alloc_size -= hub_allocs[n].size;
hub_alloc_count--;
hub_allocs[n].ptr = 0;
hub_allocs[n].size = 0;
hub_allocs[n].stack1 = 0;
hub_allocs[n].stack2 = 0;
LOG_MEMORY("free %p (bt: %p %p) {allocs: %d, size: " PRINTF_SIZE_T "}", ptr, stack1, stack2, hub_alloc_count, hub_alloc_size);
malloc_slot = n;
free(ptr);
return;
}
}
malloc_slot = -1;
abort();
LOG_MEMORY("free %p *** NOT ALLOCATED *** (bt: %p %p)", ptr, stack1, stack2);
#else
free(ptr);
#endif /* REALTIME_MALLOC_TRACKING */
}
char* debug_mem_strdup(const char* s)
{
size_t size = strlen(s);
char* ptr = internal_debug_mem_malloc(size+1, "strdup");
if (ptr)
{
memcpy(ptr, s, size);
ptr[size] = 0;
}
return ptr;
}
char* debug_mem_strndup(const char* s, size_t n)
{
size_t size = MIN(strlen(s), n);
char* ptr = internal_debug_mem_malloc(size+1, "strndup");
if (ptr)
{
memcpy(ptr, s, size);
ptr[size] = 0;
}
return ptr;
}
void* debug_mem_malloc(size_t size)
{
void* ptr = internal_debug_mem_malloc(size, "malloc");
return ptr;
}
void debug_mem_free(void *ptr)
{
internal_debug_mem_free(ptr);
}
#endif
void* hub_malloc_zero(size_t size)
{
void* data = hub_malloc(size);
if (data)
{
memset(data, 0, size);
}
return data;
}
#ifdef DEBUG_FUNCTION_TRACE
#define FTRACE_LOG "ftrace.log"
static FILE* functrace = 0;
void main_constructor() __attribute__ ((no_instrument_function, constructor));
void main_deconstructor() __attribute__ ((no_instrument_function, destructor));
void __cyg_profile_func_enter(void* frame, void* callsite) __attribute__ ((no_instrument_function));
void __cyg_profile_func_exit(void* frame, void* callsite) __attribute__ ((no_instrument_function));
void main_constructor()
{
functrace = fopen(FTRACE_LOG, "w");
if (functrace == NULL)
{
fprintf(stderr, "Cannot create function trace file: " FTRACE_LOG "\n");
exit(-1);
}
}
void main_deconstructor()
{
fclose(functrace);
}
void __cyg_profile_func_enter(void* frame, void* callsite)
{
if (functrace)
fprintf(functrace, "E%p\n", frame);
}
void __cyg_profile_func_exit(void* frame, void* callsite)
{
if (functrace)
fprintf(functrace, "X%p\n", frame);
}
#endif /* DEBUG_FUNCTION_TRACE */
-45
View File
@@ -1,45 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_MEMORY_HANDLER_H
#define HAVE_UHUB_MEMORY_HANDLER_H
#ifdef MEMORY_DEBUG
#define hub_malloc debug_mem_malloc
#define hub_free debug_mem_free
#define hub_strdup debug_mem_strdup
#define hub_strndup debug_mem_strndup
extern void* debug_mem_malloc(size_t size);
extern void debug_mem_free(void* ptr);
extern char* debug_mem_strdup(const char* s);
extern char* debug_mem_strndup(const char* s, size_t n);
#else
#define hub_malloc malloc
#define hub_free free
#define hub_strdup strdup
#define hub_strndup strndup
#endif
extern void* hub_malloc_zero(size_t size);
#endif /* HAVE_UHUB_MEMORY_HANDLER_H */
-373
View File
@@ -1,373 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#include "uhub.h"
int is_space(char c)
{
if (c == ' ') return 1;
return 0;
}
int is_white_space(char c)
{
if (c == ' ' || c == '\t' || c == '\r') return 1;
return 0;
}
static int is_printable(unsigned char c)
{
if (c >= 32)
return 1;
if (c == '\t' || c == '\r' || c == '\n')
return 1;
return 0;
}
char* strip_white_space(char* string)
{
char* pos;
if (!string)
return "";
while (string[0] && is_white_space(string[0])) string++;
if (!*string)
return string;
/* Strip appending whitespace */
pos = &string[strlen(string)-1];
while (&string[0] < &pos[0] && is_white_space(pos[0])) { pos[0] = 0; pos--; }
return string;
}
static int is_valid_utf8_str(const char* string, size_t length)
{
int expect = 0;
char div = 0;
size_t pos = 0;
if (length == 0) return 1;
for (pos = 0; pos < length; pos++)
{
if (expect)
{
if ((string[pos] & 0xC0) == 0x80) expect--;
else return 0;
}
else
{
if (string[pos] & 0x80)
{
for (div = 0x40; div > 0x10; div /= 2)
{
if (string[pos] & div) expect++;
else break;
}
if ((string[pos] & div) || (pos+expect >= length)) return 0;
}
}
}
return 1;
}
int is_valid_utf8(const char* string)
{
return is_valid_utf8_str(string, strlen(string));
}
int is_printable_utf8(const char* string, size_t length)
{
size_t pos = 0;
for (pos = 0; pos < length; pos++)
{
if (!is_printable(string[pos]))
return 0;
}
return is_valid_utf8_str(string, length);
}
int is_valid_base32_char(char c)
{
if ((c >= 'A' && c <= 'Z') || (c >= '2' && c <= '7')) return 1;
return 0;
}
int is_num(char c)
{
if (c >= '0' && c <= '9') return 1;
return 0;
}
void base32_encode(const unsigned char* buffer, size_t len, char* result) {
unsigned char word = 0;
size_t n = 0;
size_t i = 0;
size_t index = 0;
for (; i < len;) {
if (index > 3) {
word = (buffer[i] & (0xFF >> index));
index = (index + 5) % 8;
word <<= index;
if (i < len - 1)
word |= buffer[i + 1] >> (8 - index);
i++;
} else {
word = (buffer[i] >> (8 - (index + 5))) & 0x1F;
index = (index + 5) % 8;
if (index == 0) i++;
}
result[n++] = BASE32_ALPHABET[word];
}
result[n] = '\0';
}
void base32_decode(const char* src, unsigned char* dst, size_t len) {
size_t index = 0;
size_t offset = 0;
size_t i = 0;
memset(dst, 0, len);
for (i = 0; src[i]; i++) {
unsigned char n = 0;
for (; n < 32; n++) if (src[i] == BASE32_ALPHABET[n]) break;
if (n == 32) continue;
if (index <= 3) {
index = (index + 5) % 8;
if (index == 0) {
dst[offset++] |= n;
if (offset == len) break;
} else {
dst[offset] |= n << (8 - index);
}
} else {
index = (index + 5) % 8;
dst[offset++] |= (n >> index);
if (offset == len) break;
dst[offset] |= n << (8 - index);
}
}
}
int file_read_lines(const char* file, void* data, file_line_handler_t handler)
{
int fd;
ssize_t ret;
char buf[MAX_RECV_BUF];
char *pos, *start;
size_t line_count = 0;
memset(buf, 0, MAX_RECV_BUF);
LOG_TRACE("Opening file %s for line reading.", file);
fd = open(file, 0);
if (fd == -1)
{
LOG_ERROR("Unable to open file %s: %s", file, strerror(errno));
return -2;
}
ret = read(fd, buf, MAX_RECV_BUF);
if (ret < 0)
{
LOG_ERROR("Unable to read from file %s: %s", file, strerror(errno));
close(fd);
return -1;
}
else if (ret == 0)
{
close(fd);
LOG_WARN("File is empty.");
return 0;
}
else
{
close(fd);
/* Parse configuaration */
start = buf;
while ((pos = strchr(start, '\n')))
{
pos[0] = '\0';
if (*start)
{
LOG_DUMP("Line: %s", start);
if (handler(start, line_count+1, data) < 0)
return -1;
}
start = &pos[1];
line_count++;
}
if (*start)
{
buf[strlen(start)] = 0;
LOG_DUMP("Line: %s", start);
if (handler(start, line_count+1, data) < 0)
return -1;
}
}
return line_count+1;
}
int uhub_atoi(const char* value) {
int len = strlen(value);
int offset = 0;
int val = 0;
int i = 0;
for (; i < len; i++)
if (value[i] > '9' || value[i] < '0')
offset++;
for (i = offset; i< len; i++)
val = val*10 + (value[i] - '0');
return value[0] == '-' ? -val : val;
}
/*
* FIXME: -INTMIN is wrong!
*/
const char* uhub_itoa(int val)
{
size_t i;
int value;
static char buf[22];
memset(buf, 0, sizeof(buf));
if (!val)
{
strcat(buf, "0");
return buf;
}
i = sizeof(buf) - 1;
for (value = abs(val); value && i > 0; value /= 10)
buf[--i] = "0123456789"[value % 10];
if (val < 0 && i > 0)
buf[--i] = '-';
return buf+i;
}
const char* uhub_ulltoa(uint64_t val)
{
size_t i;
static char buf[22] = { 0, };
memset(buf, 0, sizeof(buf));
if (!val)
{
strcat(buf, "0");
return buf;
}
i = sizeof(buf) - 1;
for (; val && i > 0; val /= 10)
buf[--i] = "0123456789"[val % 10];
return buf+i;
}
#ifndef HAVE_STRNDUP
char* strndup(const char* string, size_t n)
{
size_t max = MIN(strlen(string), n);
char* tmp = hub_malloc(max+1);
memcpy(tmp, string, max);
tmp[max] = 0;
return tmp;
}
#endif
#ifndef HAVE_MEMMEM
void* memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen)
{
char* c_buf = (char*) haystack;
char* c_pat = (char*) needle;
char* ptr = memchr(c_buf, c_pat[0], haystacklen);
while (ptr && (&ptr[0] - &c_buf[0] < haystacklen))
{
if (!memcmp(ptr, c_pat, needlelen))
return ptr;
ptr = memchr(&ptr[1], c_pat[0], &c_buf[haystacklen] - &ptr[0]);
}
return 0;
}
#endif
int split_string(const char* string, const char* split, struct linked_list* list, int allow_empty)
{
char* tmp1, *tmp2;
int n = 0;
if (!string || !*string || !split || !*split || !list)
return -1;
for (;;)
{
tmp1 = strstr(string, split);
if (tmp1) tmp2 = hub_strndup(string, tmp1 - string);
else tmp2 = hub_strdup(string);
if (!tmp2)
{
list_clear(list, &hub_free);
return -1;
}
if (*tmp2 || allow_empty)
{
/* store in list */
list_append(list, tmp2);
n++;
}
else
{
/* ignore element */
hub_free(tmp2);
}
if (!tmp1) break; /* last element found */
string = tmp1;
string += strlen(split);
}
return n;
}
const char* get_timestamp(time_t now)
{
static char ts[32] = {0, };
struct tm* t = localtime(&now);
sprintf(ts, "[%02d:%02d]", t->tm_hour, t->tm_min);
return ts;
}
-67
View File
@@ -1,67 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_MISC_H
#define HAVE_UHUB_MISC_H
typedef int (*file_line_handler_t)(char* line, int line_number, void* data);
extern const char* get_timestamp(time_t time);
extern int is_num(char c);
extern int is_space(char c);
extern int is_white_space(char c);
extern int is_valid_utf8(const char* string);
extern int is_printable_utf8(const char* string, size_t length);
extern int is_valid_base32_char(char c);
extern void base32_encode(const unsigned char* buffer, size_t len, char* result);
extern void base32_decode(const char* src, unsigned char* dst, size_t len);
extern char* strip_white_space(char* string);
extern int file_read_lines(const char* file, void* data, file_line_handler_t handler);
extern const char* uhub_itoa(int val);
extern const char* uhub_ulltoa(uint64_t val);
extern int uhub_atoi(const char* value);
#ifdef NEED_ATOLL
extern int atoll(const char* value);
#endif
#ifndef HAVE_STRNDUP
extern char* strndup(const char* string, size_t n);
#endif
#ifndef HAVE_MEMMEM
void* memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen);
#endif
/**
* Split the string based on split, and place the different parts into list.
* @return the number of items in the list after split, or -1 if an error occured.
*/
struct linked_list;
extern int split_string(const char* string, const char* split, struct linked_list* list, int allow_empty);
#endif /* HAVE_UHUB_MISC_H */
-137
View File
@@ -1,137 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#if 0
#include <sys/types.h>
#include "rbtree.h"
#define RED 0
#define BLACK 1
struct rb_node
{
const void* key;
const void* value; /* data */
int color;
struct rb_node* parent;
struct rb_node* left;
struct rb_node* right;
};
struct rb_tree
{
struct rb_node* root;
size_t elements;
rb_tree_alloc alloc;
rb_tree_free free;
rb_tree_compare compare;
};
/* returns the grandparent of a node, if it exits */
static inline struct rb_node* get_grandparent(struct rb_node* n)
{
if (n->parent)
return n->parent->parent;
return 0;
}
static struct rb_node* get_uncle(struct rb_node* n)
{
struct rb_node* gparent = n->parent ? n->parent->parent : 0;
if (gparent)
return (n->parent == gparent->left) ? gparent->right : gparent->left;
return 0;
}
static struct rb_node* tree_search(struct rb_tree* tree, const void* key)
{
struct rb_node* node = tree->root;
while (node)
{
int res = tree->compare(key, node->key);
if (res < 0) node = node->left;
else if (res > 0) node = node->right;
else return node;
}
return 0;
}
static struct rb_node* tree_insert(struct rb_tree* tree, const void* key, const void* value)
{
struct rb_node* node = tree->root;
struct rb_node* newnode = tree->alloc(sizeof(struct rb_node));
newnode->key = key;
newnode->value = value;
newnode->color = RED;
while (node)
{
int res = tree->compare(key, node->key);
if (res < 0) node = node->left;
else if (res > 0) node = node->right;
else
{
/* key already exists in tree */
return node;
}
}
return newnode;
}
struct rb_tree* rb_tree_create(rb_tree_compare compare, rb_tree_alloc a, rb_tree_free f)
{
struct rb_tree* tree = a(sizeof(struct rb_tree));
tree->compare = compare;
tree->alloc = a;
tree->free = f;
return tree;
}
void rb_tree_destroy(struct rb_tree* tree)
{
rb_tree_free f = tree->free;
f(tree);
}
void* rb_tree_insert(struct rb_tree* tree, const void* key, const void* value)
{
struct rb_node* node = tree_insert(tree, key, value);
if (node)
return (void*) node->value;
return 0;
}
void* rb_tree_remove(struct rb_tree* tree, const void* key)
{
}
void* rb_tree_get(struct rb_tree* tree, const void* key)
{
struct rb_node* node = tree_search(tree, key);
if (node)
return node->value;
return 0;
}
#endif
-38
View File
@@ -1,38 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* 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/>.
*
*/
#ifndef HAVE_UHUB_RED_BLACK_TREE_H
#define HAVE_UHUB_RED_BLACK_TREE_H
struct rb_tree;
typedef int (*rb_tree_compare)(const void* a, const void* b);
typedef void* (*rb_tree_alloc)(size_t);
typedef void (*rb_tree_free)(void*);
extern struct rb_tree* rb_tree_create(rb_tree_compare, rb_tree_alloc, rb_tree_free);
extern void rb_tree_destroy(struct rb_tree*);
extern void* rb_tree_insert(struct rb_tree* tree, const void* key, const void* data);
extern void* rb_tree_remove(struct rb_tree* tree, const void* key);
extern void* rb_tree_get(struct rb_tree* tree, const void* key);
#endif /* HAVE_UHUB_RED_BLACK_TREE_H */
-1246
View File
File diff suppressed because it is too large Load Diff

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