pax_global_header00006660000000000000000000000064132450130010014477gustar00rootroot0000000000000052 comment=a8ee6e7f60aa059091ebb45634b7c4a08b850d17 modelrockettier-uhub-a8ee6e7/000077500000000000000000000000001324501300100163425ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/.gitignore000066400000000000000000000005241324501300100203330ustar00rootroot00000000000000*~ *.[oa] *.lib *.exe *.manifest *.gch CMakeFiles/* CMakeCache.txt cmake_install.cmake mod_*.dll mod_*.exp mod_*.so uhub-admin adcrush uhub build-stamp debian/files debian/uhub.debhelper.log debian/uhub.postinst.debhelper debian/uhub.postrm.debhelper debian/uhub.prerm.debhelper debian/uhub.substvars uhub-passwd src/version.h src/system.h modelrockettier-uhub-a8ee6e7/.gitmodules000066400000000000000000000001461324501300100205200ustar00rootroot00000000000000[submodule "thirdparty/sqlite"] path = thirdparty/sqlite url = git://github.com/janvidar/sqlite.git modelrockettier-uhub-a8ee6e7/.travis.yml000066400000000000000000000002661324501300100204570ustar00rootroot00000000000000language: cpp compiler: - gcc - clang env: - CONFIG=minimal - CONFIG=full install: - autotest/travis/install-build-depends.sh script: - autotest/travis/build-and-test.sh modelrockettier-uhub-a8ee6e7/AUTHORS000066400000000000000000000006231324501300100174130ustar00rootroot00000000000000Authors of uhub =============== Jan Vidar Krey, Design and implementation E_zombie, Centos/RedHat customization scripts and heavy load testing FleetCommand, Hub topic plugin code MiMic, Implemented user commands, and plugins Boris Pek (tehnick), Debian/Ubuntu packaging Tillmann Karras (Tilka), Misc. bug fixes Yoran Heling (Yorhel), TLS/SSL handshake detection bugfixes Blair Bonnett, Misc. bug fixes modelrockettier-uhub-a8ee6e7/BUGS000066400000000000000000000000571324501300100170270ustar00rootroot00000000000000Bugs are tracked on: http://bugs.extatic.org/ modelrockettier-uhub-a8ee6e7/CMakeLists.txt000066400000000000000000000201101324501300100210740ustar00rootroot00000000000000 ## ## Makefile for uhub ## Copyright (C) 2007-2013, Jan Vidar Krey # cmake_minimum_required (VERSION 2.8.2) project (uhub NONE) enable_language(C) set (UHUB_VERSION_MAJOR 0) set (UHUB_VERSION_MINOR 5) set (UHUB_VERSION_PATCH 1) set (PROJECT_SOURCE_DIR "${CMAKE_SOURCE_DIR}/src") set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake/Modules) option(RELEASE "Release build, debug build if disabled" ON) option(LOWLEVEL_DEBUG, "Enable low level debug messages." OFF) option(SSL_SUPPORT "Enable SSL support" ON) option(USE_OPENSSL "Use OpenSSL's SSL support" ON ) option(SYSTEMD_SUPPORT "Enable systemd notify and journal logging" OFF) option(ADC_STRESS "Enable the stress tester client" OFF) find_package(Git) find_package(Sqlite3) include(TestBigEndian) include(CheckSymbolExists) include(CheckIncludeFile) include(CheckTypeSize) #Some functions need this to be found add_definitions(-D_GNU_SOURCE) set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_GNU_SOURCE") TEST_BIG_ENDIAN(BIGENDIAN) if (BIGENDIAN) add_definitions(-DARCH_BIGENDIAN) endif() if (NOT RELEASE) add_definitions(-DDEBUG) endif() if (SSL_SUPPORT) if (USE_OPENSSL) find_package(OpenSSL) else() find_package(GnuTLS) endif() if (NOT GNUTLS_FOUND AND NOT OPENSSL_FOUND) message(FATAL_ERROR "Neither OpenSSL nor GnuTLS were found!") endif() endif() if (NOT SQLITE3_FOUND) message(FATAL_ERROR "SQLite3 is not found!") endif() if (SYSTEMD_SUPPORT) INCLUDE(FindPkgConfig) pkg_search_module(SD REQUIRED libsystemd) endif() if (MSVC) add_definitions(-D_CRT_SECURE_NO_WARNINGS) endif() check_include_file(stdint.h HAVE_STDINT_H) check_include_file(sys/types.h HAVE_SYS_TYPES_H) if (HAVE_SYS_TYPES_H) set (CMAKE_EXTRA_INCLUDE_FILES ${CMAKE_EXTRA_INCLUDE_FILES} "sys/types.h") endif() check_type_size( ssize_t SSIZE_T ) check_symbol_exists(memmem string.h HAVE_MEMMEM) check_symbol_exists(strndup string.h HAVE_STRNDUP) include_directories("${PROJECT_SOURCE_DIR}") include_directories(${SQLITE3_INCLUDE_DIRS}) link_directories(${SQLITE3_LIBRARY_DIRS}) file (GLOB uhub_SOURCES ${PROJECT_SOURCE_DIR}/core/*.c) list (REMOVE_ITEM uhub_SOURCES ${PROJECT_SOURCE_DIR}/core/gen_config.c ${PROJECT_SOURCE_DIR}/core/main.c ) file (GLOB adc_SOURCES ${PROJECT_SOURCE_DIR}/adc/*.c) file (GLOB network_SOURCES ${PROJECT_SOURCE_DIR}/network/*.c) file (GLOB utils_SOURCES ${PROJECT_SOURCE_DIR}/util/*.c) set (adcclient_SOURCES ${PROJECT_SOURCE_DIR}/tools/adcclient.c ${PROJECT_SOURCE_DIR}/core/ioqueue.c ) add_library(adc STATIC ${adc_SOURCES}) add_library(network STATIC ${network_SOURCES}) add_library(utils STATIC ${utils_SOURCES}) if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") set_target_properties(utils PROPERTIES COMPILE_FLAGS -fPIC) set_target_properties(network PROPERTIES COMPILE_FLAGS -fPIC) endif() add_dependencies(adc utils) add_dependencies(network utils) add_executable(uhub ${PROJECT_SOURCE_DIR}/core/main.c ${uhub_SOURCES} ) add_executable(autotest-bin ${CMAKE_SOURCE_DIR}/autotest/test.c ${uhub_SOURCES} ) add_executable(uhub-passwd ${PROJECT_SOURCE_DIR}/tools/uhub-passwd.c) add_library(mod_example MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_example.c) add_library(mod_welcome MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_welcome.c) add_library(mod_logging MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_logging.c ${PROJECT_SOURCE_DIR}/adc/sid.c) add_library(mod_auth_simple MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_auth_simple.c ) add_library(mod_chat_history MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_history.c ) add_library(mod_chat_history_sqlite MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_history_sqlite.c ) add_library(mod_chat_only MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_only.c) add_library(mod_topic MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_topic.c) add_library(mod_no_guest_downloads MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_no_guest_downloads.c) add_library(mod_auth_sqlite MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_auth_sqlite.c) if(WIN32) target_link_libraries(uhub ws2_32) target_link_libraries(autotest-bin ws2_32) target_link_libraries(mod_logging ws2_32) target_link_libraries(mod_welcome ws2_32) endif() set_target_properties( mod_example mod_welcome mod_logging mod_auth_simple mod_auth_sqlite mod_chat_history mod_chat_history_sqlite mod_chat_only mod_no_guest_downloads mod_topic PROPERTIES PREFIX "") target_link_libraries(uhub ${CMAKE_DL_LIBS} adc network utils) target_link_libraries(uhub-passwd ${SQLITE3_LIBRARIES} utils) target_link_libraries(autotest-bin ${CMAKE_DL_LIBS} adc network utils) target_link_libraries(mod_example utils) target_link_libraries(mod_welcome utils) target_link_libraries(mod_auth_simple utils) target_link_libraries(mod_auth_sqlite ${SQLITE3_LIBRARIES} utils) target_link_libraries(mod_chat_history utils) target_link_libraries(mod_chat_history_sqlite ${SQLITE3_LIBRARIES} utils) target_link_libraries(mod_no_guest_downloads utils) target_link_libraries(mod_chat_only utils) target_link_libraries(mod_logging utils) target_link_libraries(mod_topic utils) target_link_libraries(utils network) target_link_libraries(mod_welcome network) target_link_libraries(mod_logging network) if(UNIX) add_library(adcclient STATIC ${adcclient_SOURCES}) add_executable(uhub-admin ${PROJECT_SOURCE_DIR}/tools/admin.c) target_link_libraries(uhub-admin adcclient adc network utils pthread) target_link_libraries(uhub pthread) target_link_libraries(autotest-bin pthread) if (ADC_STRESS) add_executable(adcrush ${PROJECT_SOURCE_DIR}/tools/adcrush.c ${adcclient_SOURCES}) target_link_libraries(adcrush adcclient adc network utils pthread) endif() endif() if (NOT UHUB_REVISION AND GIT_FOUND) execute_process(COMMAND ${GIT_EXECUTABLE} show -s --pretty=format:%h WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} OUTPUT_VARIABLE UHUB_REVISION_TEMP OUTPUT_STRIP_TRAILING_WHITESPACE) if (UHUB_REVISION_TEMP) set (UHUB_REVISION "git-${UHUB_REVISION_TEMP}") endif() endif() if (NOT UHUB_REVISION) set (UHUB_REVISION "release") endif() set (UHUB_GIT_VERSION "${UHUB_VERSION_MAJOR}.${UHUB_VERSION_MINOR}.${UHUB_VERSION_PATCH}-${UHUB_REVISION}") message (STATUS "Configuring uhub version: ${UHUB_GIT_VERSION}") if(OPENSSL_FOUND) set(SSL_LIBS ${OPENSSL_LIBRARIES}) add_definitions(-DSSL_SUPPORT=1 -DSSL_USE_OPENSSL=1) include_directories(${OPENSSL_INCLUDE_DIR}) endif() if (GNUTLS_FOUND) set(SSL_LIBS ${GNUTLS_LIBRARIES}) add_definitions(-DSSL_SUPPORT=1 -DSSL_USE_GNUTLS=1 ${GNUTLS_DEFINITIONS}) include_directories(${GNUTLS_INCLUDE_DIR}) endif() if(SSL_SUPPORT) target_link_libraries(uhub ${SSL_LIBS}) target_link_libraries(autotest-bin ${SSL_LIBS}) if(UNIX) target_link_libraries(uhub-admin ${SSL_LIBS}) endif() target_link_libraries(mod_welcome ${SSL_LIBS}) target_link_libraries(mod_logging ${SSL_LIBS}) if (ADC_STRESS) target_link_libraries(adcrush ${SSL_LIBS}) endif() endif() if (SYSTEMD_SUPPORT) target_link_libraries(uhub ${SD_LIBRARIES}) target_link_libraries(autotest-bin ${SD_LIBRARIES}) target_link_libraries(uhub-passwd ${SD_LIBRARIES}) target_link_libraries(uhub-admin ${SD_LIBRARIES}) include_directories(${SD_INCLUDE_DIRS}) add_definitions(-DSYSTEMD) endif() configure_file ("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_SOURCE_DIR}/version.h") configure_file ("${PROJECT_SOURCE_DIR}/system.h.in" "${PROJECT_SOURCE_DIR}/system.h") # mark_as_advanced(FORCE CMAKE_BUILD_TYPE) # if (RELEASE) # set(CMAKE_BUILD_TYPE Release) # add_definitions(-DNDEBUG) #else() # set(CMAKE_BUILD_TYPE Debug) # add_definitions(-DDEBUG) #endif() if (LOWLEVEL_DEBUG) add_definitions(-DLOWLEVEL_DEBUG) endif() if (UNIX) install( TARGETS uhub uhub-passwd RUNTIME DESTINATION bin ) install( TARGETS mod_example mod_welcome mod_logging mod_auth_simple mod_auth_sqlite mod_chat_history mod_chat_history_sqlite mod_chat_only mod_topic mod_no_guest_downloads DESTINATION /usr/lib/uhub/ OPTIONAL ) install( FILES ${CMAKE_SOURCE_DIR}/doc/uhub.conf ${CMAKE_SOURCE_DIR}/doc/plugins.conf ${CMAKE_SOURCE_DIR}/doc/rules.txt ${CMAKE_SOURCE_DIR}/doc/motd.txt DESTINATION /etc/uhub OPTIONAL ) endif() modelrockettier-uhub-a8ee6e7/COPYING000066400000000000000000001045131324501300100174010ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. 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. Copyright (C) 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 . 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: Copyright (C) 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 . 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 . modelrockettier-uhub-a8ee6e7/COPYING.OpenSSL000066400000000000000000000020211324501300100206520ustar00rootroot00000000000000OpenSSL License Exception ------------------------- Copyright (c) 2007-2012, 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 3 (GPL) as published by the Free Software Foundation. The full text the GPL can be found in the COPYING file. In addition this distribution of uhub may be linked against OpenSSL according to the terms described here: You have permission to copy, modify, propagate, and distribute a work formed by combining OpenSSL with uhub, or a work derivative of such a combination, even if such copying, modification, propagation, or distribution would otherwise violate the terms of the GPL. You must comply with the GPL in all respects for all of the code used other than OpenSSL. You may include this OpenSSL exception and its grant of permissions when you distribute uhub. Inclusion of this notice with such a distribution constitutes a grant of such permission. If you do not wish to grant these permissions, delete this file. modelrockettier-uhub-a8ee6e7/ChangeLog000066400000000000000000000245211324501300100201200ustar00rootroot000000000000000.5.0: - Use TLS 1.2 and strong ciphers by default, but made this configurable. - Fix TLS event handling which caused some busy loops - TLS: Support certificate chains - Fix bug #211: Better Hublist pinger support by adding the AP flag of the INF message. - Fix bug #198: Timers could cause infinite loops - Sqlite3 is now mandatory - Added mod_chat_history_sqlite and mod_chat_is_privileged. - Support for systemd notify and journal logging - Improved flood control counting to strictly not allow more than the given amount of messages in the configured interval. - Optimize lookups by CID and nick. - Added an NMDC and ADC hub redirectors written in Python. - Fix all Clang compile warnings. - Install uhub-passwd also. - Add support for detecting HTTP connections to the hub. Enough to tell browsers to stop calling. - Compile fixes for OpenBSD, including warnings about strcat. - Fix crashing autotest due to wrong initialization of the usermanager. - mod_topic: check argument for NULL - rename !cleartopic to !resettopic 0.4.1: - Converted to CMake which replaces Visual Studio project files and GNU makefiles - Fix issues with SSL causing excessive CPU usage. - Fix TLS/SSL handshake detection issues - Fixed crash in mod_chat_only. - Implemented red-black tree for better performance for certain lookups. - Better network statistics using the !stats command. - Improved protocol parsing, especially escape handling. - Fix cbuffer initialization. - Install plugins in /usr/lib/uhub, not /var/lib/uhub. - Improved init scripts and added a upstart script. - Work-around client security bugs by disallowing UCMD messages from being relayed. - Added asynchronous DNS resolver. 0.4.0: - Cleaned up code generator for config file parsing. - Merge pull request #5 from yorhel/master - Print error message in case of shutting down due to errors loading plugins. - Fix Windows file read discrepancy. - convert_to_sqlite.pl: Update to the latest SQL schema + be more Perlish - Fix VS2010 project file - missing .c file. - Merge https://github.com/Tilka/uhub - use "I64u" instead of PRIu64 on Windows - remove obsolete settings in uhub.conf - fix uhub_itoa() and uhub_ulltoa() - marked plugin callbacks that are not called yet - add on_change_nick() to struct plugin_funcs - minimal changes - Updated init script in debian package. - Updated list of man pages in debian package. - Added man page for uhub-passwd. - Merge branch 'master' of https://github.com/Tilka/uhub - Fix issue with QUI messages being allowed through the hub - don't show error on SIGTERM in select() backend - fix dependency of 'install' target - changed all calls to assert() to uhub_assert() - Don't strip the U4/U6 port numbers if updated after login. - Fix compile issue with double typedefs. - Remove list assertion when removing element that is not in the list. Breaks autotest. - Cleaned up command handling code, by splitting into multiple files. - Fix bug #183 - Added proper OpenSSL license exception for the GPL. - OMG OPTIMIZED - use dh_prep instead of dh_clean -k - fix double free - use "0" instead of "false" - fix use of uninitialized struct ip_range - fix random crashes upon !reload - fix command syntax - use arg parser in !broadcast - Fixed tiny memory leak on reload/shutdown. - Merge https://github.com/Tilka/uhub - fix multiple optional arguments - small cleanup - also clean uhub-passwd - ignore files generated by dpkg-buildpackage - automatically clean up plugin commands - minimal documentation fixes - update client software link - update compile howto link - fix debian changelog - Fix bug #158 - Added plugin for setting topic (hub description). - Command arguments handling + cleanups 0.3.2: - Fixed bugs in the kqueue network backend (OSX/BSD) - Rewrote the configuration backend code. - Added support for escaping characters in the configuration files. - Updated the !broadcast command to send private messages instead of main chat messages. - Adding support for redirecting clients to other hubs when they fail to log in. - Fix some out of memory related crashes. - Fixed minor memory leaks. 0.3.1: - Fixed bug where !getip did not work. - Added flood control configuration options. - Added configuration options to disallow old/obsolete ADC clients. - Fixed crash bugs, an freezes. - SSL/TLS fix for tls_require configuration option. - Fixed disconnect messages, so that clients can interpret them. - Fixed bugs where share limits could be circumvented. - Added support for listening to multiple ports. - kqueue backend for Mac OS X, and BSD systems. 0.3.0: - More user commands: ban, broadcast, mute, rules, history, myip, whoip, log - Experimental SSL support - Large rewrite of the network stack in order to support SSL. - Added rule file for defining hub rules. - Many crash fixes and other important bug fixes. - Optimizations: O(1) timeout scheduler - New sid allocation code. - Added configurable server_listen_backlog (default 50). - Added init.d scripts for RedHat/CentOS 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 modelrockettier-uhub-a8ee6e7/README000066400000000000000000000004331324501300100172220ustar00rootroot00000000000000Welcome and thanks for downloading uHub, a high performance ADC p2p hub. For the official documentation, bugs and other information, please visit: http://www.uhub.org/ For a list of compatible ADC clients, see: http://en.wikipedia.org/wiki/Advanced_Direct_Connect#Client_software modelrockettier-uhub-a8ee6e7/TODO000066400000000000000000000000001324501300100170200ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/admin/000077500000000000000000000000001324501300100174325ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/admin/common.sh000066400000000000000000000053071324501300100212630ustar00rootroot00000000000000HOST_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 } modelrockettier-uhub-a8ee6e7/admin/export.sh000077500000000000000000000000661324501300100213140ustar00rootroot00000000000000#!/bin/bash . admin/common.sh export_source_directory modelrockettier-uhub-a8ee6e7/admin/make_pkg_deb.sh000077500000000000000000000045251324501300100223670ustar00rootroot00000000000000#!/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 < 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 < `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 < 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} modelrockettier-uhub-a8ee6e7/admin/release_binaries.sh000077500000000000000000000000561324501300100232660ustar00rootroot00000000000000#!/bin/bash . admin/common.sh export_binaries modelrockettier-uhub-a8ee6e7/admin/release_sources.sh000077500000000000000000000000671324501300100231570ustar00rootroot00000000000000#!/bin/bash . admin/common.sh WANTZIP=1 export_sources modelrockettier-uhub-a8ee6e7/admin/setup_archive.sh000077500000000000000000000007371324501300100226410ustar00rootroot00000000000000#!/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} <> .ssh/authorized_keys" modelrockettier-uhub-a8ee6e7/admin/upload.sh000077500000000000000000000000561324501300100212560ustar00rootroot00000000000000#!/bin/bash . admin/common.sh upload_packages modelrockettier-uhub-a8ee6e7/autotest/000077500000000000000000000000001324501300100202125ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/autotest/exotic000077500000000000000000000176401324501300100214430ustar00rootroot00000000000000#!/usr/bin/perl -w # exotic 0.4 # Copyright (c) 2007-2012, Jan Vidar Krey use strict; my $program = $0; my $file; my $line; my @tests; my $found; my $test; my @files; if ($#ARGV == -1) { die "Usage: $program files\n"; } my $version = "0.4"; foreach my $arg (@ARGV) { push(@files, $arg); } print "/* THIS FILE IS AUTOMATICALLY GENERATED BY EXOTIC - DO NOT EDIT THIS FILE! */\n"; print "/* exotic/$version (Mon Nov 7 11:15:31 CET 2011) */\n\n"; print "#define __EXOTIC__STANDALONE__\n"; standalone_include_exotic_h(); if ($#ARGV >= 0) { foreach $file (@ARGV) { $found = 0; open( FILE, "$file") || next; my @data = ; my $comment = 0; foreach $line (@data) { chomp($line); if ($comment == 1) { if ($line =~ /^(.*\*\/)(.*)/) { $line = $2; $comment = 0; } else { next; # ignore comment data } } if ($line =~ /^(.*)\/\*(.*)\*\/(.*)$/) { $line = $1 . " " . $3; # exclude comment stuff in between "/*" and "*/". } if ($line =~ /^(.*)(\/\/.*)$/) { $line = $1; # exclude stuff after "//" (FIXME: does not work if they are inside a string) } if ($line =~ /\/\*/) { $comment = 1; next; } if ($line =~ /^\s*EXO_TEST\(\s*(\w+)\s*,/) { $found++; push(@tests, $1); } } if ($found > 0) { print "#include \"" . $file . "\"\n"; } close(FILE); } print "\n"; } # Write a main() that will start the test run print "int main(int argc, char** argv)\n{\n"; print "\tstruct exotic_handle handle;\n\n"; print "\tif (exotic_initialize(&handle, argc, argv) == -1)\n\t\treturn -1;\n\n"; if ($#tests > 0) { print "\t/* Register the tests to be run */\n"; foreach $test (@tests) { print "\texotic_add_test(&handle, &exotic_test_" . $test . ", \"" . $test . "\");\n"; } } else { print "\t/* No tests are found! */\n"; } print "\n"; print "\treturn exotic_run(&handle);\n"; print "}\n\n"; standalone_include_exotic_c(); sub standalone_include_exotic_h { print ' /* * Exotic (EXtatic.Org Test InfrastuCture) * Copyright (c) 2007, Jan Vidar Krey */ #ifndef EXO_TEST #define EXO_TEST(NAME, block) int exotic_test_ ## NAME (void) block #endif #ifndef HAVE_EXOTIC_AUTOTEST_H #define HAVE_EXOTIC_AUTOTEST_H #ifdef __cplusplus extern "C" { #endif typedef int(*exo_test_t)(); enum exo_toggle { cfg_default, cfg_off, cfg_on }; struct exotic_handle { enum exo_toggle config_show_summary; enum exo_toggle config_show_pass; enum exo_toggle config_show_fail; unsigned int fail; unsigned int pass; struct exo_test_data* first; struct exo_test_data* current; }; extern int exotic_initialize(struct exotic_handle* handle, int argc, char** argv); extern void exotic_add_test(struct exotic_handle* handle, exo_test_t, const char* name); extern int exotic_run(struct exotic_handle* handle); #ifdef __cplusplus } #endif #endif /* HAVE_EXOTIC_AUTOTEST_H */ '; } sub standalone_include_exotic_c { print ' /* * Exotic - C/C++ source code testing * Copyright (c) 2007, Jan Vidar Krey */ #include #include #include #include static void exotic_version(); #ifndef __EXOTIC__STANDALONE__ #include "autotest.h" static void exotic_version() { printf("Extatic.org Test Infrastructure: exotic " "${version}" "\n\n"); printf("Copyright (C) 2007 Jan Vidar Krey, janvidar@extatic.org\n"); printf("This is free software with ABSOLUTELY NO WARRANTY.\n\n"); } #endif struct exo_test_data { exo_test_t test; char* name; struct exo_test_data* next; }; static void exotic_summary(struct exotic_handle* handle) { int total = handle->pass + handle->fail; int pass_rate = total ? (100*handle->pass / total) : 0; int fail_rate = total ? (100*handle->fail / total) : 0; printf("\n"); printf("--------------------------------------------\n"); printf("Results:\n"); printf(" * Total tests run: %8d\n", total); printf(" * Tests passed: %8d (~%d%%)\n", (int) handle->pass, pass_rate); printf(" * Tests failed: %8d (~%d%%)\n", (int) handle->fail, fail_rate); printf("--------------------------------------------\n"); } static void exotic_help(const char* program) { printf("Usage: %s [OPTIONS]\n\n", program); printf("Options:\n"); printf(" --help -h Show this message\n"); printf(" --version -v Show version\n"); printf(" --summary -s show only summary)\n"); printf(" --fail -f show only test failures\n"); printf(" --pass -p show only test passes\n"); printf("\nExamples:\n"); printf(" %s -s -f\n\n", program); } int exotic_initialize(struct exotic_handle* handle, int argc, char** argv) { int n; if (!handle || !argv) return -1; memset(handle, 0, sizeof(struct exotic_handle)); for (n = 1; n < argc; n++) { if (!strcmp(argv[n], "-h") || !strcmp(argv[n], "--help")) { exotic_help(argv[0]); exit(0); } if (!strcmp(argv[n], "-v") || !strcmp(argv[n], "--version")) { exotic_version(); exit(0); } if (!strcmp(argv[n], "-s") || !strcmp(argv[n], "--summary")) { handle->config_show_summary = cfg_on; continue; } if (!strcmp(argv[n], "-f") || !strcmp(argv[n], "--fail")) { handle->config_show_fail = cfg_on; continue; } if (!strcmp(argv[n], "-p") || !strcmp(argv[n], "--pass")) { handle->config_show_pass = cfg_on; continue; } fprintf(stderr, "Unknown argument: %s\n\n", argv[n]); exotic_help(argv[0]); exit(0); } if (handle->config_show_summary == cfg_on) { if (handle->config_show_pass == cfg_default) handle->config_show_pass = cfg_off; if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off; } else if (handle->config_show_pass == cfg_on) { if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_off; if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off; } else if (handle->config_show_fail == cfg_on) { if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_off; if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off; } else { if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_on; if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_on; if (handle->config_show_pass == cfg_default) handle->config_show_pass = cfg_on; } return 0; } void exotic_add_test(struct exotic_handle* handle, exo_test_t func, const char* name) { struct exo_test_data* test; if (!handle) { fprintf(stderr, "exotic_add_test: failed, no handle!\n"); exit(-1); } test = (struct exo_test_data*) malloc(sizeof(struct exo_test_data)); if (!test) { fprintf(stderr, "exotic_add_test: out of memory!\n"); exit(-1); } /* Create the test */ memset(test, 0, sizeof(struct exo_test_data)); test->test = func; test->name = strdup(name); /* Register the test in the handle */ if (!handle->first) { handle->first = test; handle->current = test; } else { handle->current->next = test; handle->current = test; } } int exotic_run(struct exotic_handle* handle) { struct exo_test_data* tmp = NULL; if (!handle) { fprintf(stderr, "Error: exotic is not initialized\n"); return -1; } handle->current = handle->first; while (handle->current) { tmp = handle->current; if (handle->current->test()) { if (handle->config_show_pass == cfg_on) printf("* PASS test \'%s\'\n", tmp->name); handle->pass++; } else { if (handle->config_show_fail == cfg_on) printf("* FAIL test \'%s\'\n", tmp->name); handle->fail++; } handle->current = handle->current->next; free(tmp->name); free(tmp); } if (!handle->first) { printf("(No tests added)\n"); } if (handle->config_show_summary == cfg_on) exotic_summary(handle); return (handle->fail) ? handle->fail : 0; } static void exotic_version() { printf("exotic 0.4-standalone\n\n"); printf("Copyright (C) 2007 Jan Vidar Krey, janvidar@extatic.org\n"); printf("This is free software with ABSOLUTELY NO WARRANTY.\n\n"); } '; } modelrockettier-uhub-a8ee6e7/autotest/test.c000066400000000000000000002074771324501300100213560ustar00rootroot00000000000000/* THIS FILE IS AUTOMATICALLY GENERATED BY EXOTIC - DO NOT EDIT THIS FILE! */ /* exotic/0.4 (Mon Nov 7 11:15:31 CET 2011) */ #define __EXOTIC__STANDALONE__ /* * Exotic (EXtatic.Org Test InfrastuCture) * Copyright (c) 2007, Jan Vidar Krey */ #ifndef EXO_TEST #define EXO_TEST(NAME, block) int exotic_test_ ## NAME (void) block #endif #ifndef HAVE_EXOTIC_AUTOTEST_H #define HAVE_EXOTIC_AUTOTEST_H #ifdef __cplusplus extern "C" { #endif typedef int(*exo_test_t)(); enum exo_toggle { cfg_default, cfg_off, cfg_on }; struct exotic_handle { enum exo_toggle config_show_summary; enum exo_toggle config_show_pass; enum exo_toggle config_show_fail; unsigned int fail; unsigned int pass; struct exo_test_data* first; struct exo_test_data* current; }; extern int exotic_initialize(struct exotic_handle* handle, int argc, char** argv); extern void exotic_add_test(struct exotic_handle* handle, exo_test_t, const char* name); extern int exotic_run(struct exotic_handle* handle); #ifdef __cplusplus } #endif #endif /* HAVE_EXOTIC_AUTOTEST_H */ #include "test_commands.tcc" #include "test_credentials.tcc" #include "test_eventqueue.tcc" #include "test_hub.tcc" #include "test_inf.tcc" #include "test_ipfilter.tcc" #include "test_list.tcc" #include "test_memory.tcc" #include "test_message.tcc" #include "test_misc.tcc" #include "test_rbtree.tcc" #include "test_sid.tcc" #include "test_tiger.tcc" #include "test_timer.tcc" #include "test_tokenizer.tcc" #include "test_usermanager.tcc" int main(int argc, char** argv) { struct exotic_handle handle; if (exotic_initialize(&handle, argc, argv) == -1) return -1; /* Register the tests to be run */ exotic_add_test(&handle, &exotic_test_setup, "setup"); exotic_add_test(&handle, &exotic_test_command_setup_user, "command_setup_user"); exotic_add_test(&handle, &exotic_test_command_create, "command_create"); exotic_add_test(&handle, &exotic_test_command_access_1, "command_access_1"); exotic_add_test(&handle, &exotic_test_command_access_2, "command_access_2"); exotic_add_test(&handle, &exotic_test_command_access_3, "command_access_3"); exotic_add_test(&handle, &exotic_test_command_syntax_1, "command_syntax_1"); exotic_add_test(&handle, &exotic_test_command_syntax_2, "command_syntax_2"); exotic_add_test(&handle, &exotic_test_command_missing_args_1, "command_missing_args_1"); exotic_add_test(&handle, &exotic_test_command_missing_args_2, "command_missing_args_2"); exotic_add_test(&handle, &exotic_test_command_missing_args_3, "command_missing_args_3"); exotic_add_test(&handle, &exotic_test_command_number_1, "command_number_1"); exotic_add_test(&handle, &exotic_test_command_number_2, "command_number_2"); exotic_add_test(&handle, &exotic_test_command_number_3, "command_number_3"); exotic_add_test(&handle, &exotic_test_command_user_1, "command_user_1"); exotic_add_test(&handle, &exotic_test_command_user_2, "command_user_2"); exotic_add_test(&handle, &exotic_test_command_user_3, "command_user_3"); exotic_add_test(&handle, &exotic_test_command_user_4, "command_user_4"); exotic_add_test(&handle, &exotic_test_command_user_5, "command_user_5"); exotic_add_test(&handle, &exotic_test_command_command_1, "command_command_1"); exotic_add_test(&handle, &exotic_test_command_command_2, "command_command_2"); exotic_add_test(&handle, &exotic_test_command_command_3, "command_command_3"); exotic_add_test(&handle, &exotic_test_command_command_4, "command_command_4"); exotic_add_test(&handle, &exotic_test_command_command_5, "command_command_5"); exotic_add_test(&handle, &exotic_test_command_command_6, "command_command_6"); exotic_add_test(&handle, &exotic_test_command_command_7, "command_command_7"); exotic_add_test(&handle, &exotic_test_command_command_8, "command_command_8"); exotic_add_test(&handle, &exotic_test_command_cred_1, "command_cred_1"); exotic_add_test(&handle, &exotic_test_command_cred_2, "command_cred_2"); exotic_add_test(&handle, &exotic_test_command_cred_3, "command_cred_3"); exotic_add_test(&handle, &exotic_test_command_cred_4, "command_cred_4"); exotic_add_test(&handle, &exotic_test_command_cred_5, "command_cred_5"); exotic_add_test(&handle, &exotic_test_command_cred_6, "command_cred_6"); exotic_add_test(&handle, &exotic_test_command_cred_7, "command_cred_7"); exotic_add_test(&handle, &exotic_test_command_cred_8, "command_cred_8"); exotic_add_test(&handle, &exotic_test_command_parse_3, "command_parse_3"); exotic_add_test(&handle, &exotic_test_command_parse_4, "command_parse_4"); exotic_add_test(&handle, &exotic_test_command_argument_integer_1, "command_argument_integer_1"); exotic_add_test(&handle, &exotic_test_command_argument_integer_2, "command_argument_integer_2"); exotic_add_test(&handle, &exotic_test_command_argument_integer_3, "command_argument_integer_3"); exotic_add_test(&handle, &exotic_test_command_argument_user_1, "command_argument_user_1"); exotic_add_test(&handle, &exotic_test_command_argument_cid_1, "command_argument_cid_1"); exotic_add_test(&handle, &exotic_test_command_argument_cred_1, "command_argument_cred_1"); exotic_add_test(&handle, &exotic_test_command_argument_cred_2, "command_argument_cred_2"); exotic_add_test(&handle, &exotic_test_command_argument_cred_3, "command_argument_cred_3"); exotic_add_test(&handle, &exotic_test_command_argument_cred_4, "command_argument_cred_4"); exotic_add_test(&handle, &exotic_test_command_argument_cred_5, "command_argument_cred_5"); exotic_add_test(&handle, &exotic_test_command_argument_cred_6, "command_argument_cred_6"); exotic_add_test(&handle, &exotic_test_command_user_destroy, "command_user_destroy"); exotic_add_test(&handle, &exotic_test_command_destroy, "command_destroy"); exotic_add_test(&handle, &exotic_test_cleanup, "cleanup"); exotic_add_test(&handle, &exotic_test_cred_to_string_1, "cred_to_string_1"); exotic_add_test(&handle, &exotic_test_cred_to_string_2, "cred_to_string_2"); exotic_add_test(&handle, &exotic_test_cred_to_string_3, "cred_to_string_3"); exotic_add_test(&handle, &exotic_test_cred_to_string_4, "cred_to_string_4"); exotic_add_test(&handle, &exotic_test_cred_to_string_5, "cred_to_string_5"); exotic_add_test(&handle, &exotic_test_cred_to_string_6, "cred_to_string_6"); exotic_add_test(&handle, &exotic_test_cred_to_string_7, "cred_to_string_7"); exotic_add_test(&handle, &exotic_test_cred_to_string_8, "cred_to_string_8"); exotic_add_test(&handle, &exotic_test_cred_from_string_1, "cred_from_string_1"); exotic_add_test(&handle, &exotic_test_cred_from_string_2, "cred_from_string_2"); exotic_add_test(&handle, &exotic_test_cred_from_string_3, "cred_from_string_3"); exotic_add_test(&handle, &exotic_test_cred_from_string_4, "cred_from_string_4"); exotic_add_test(&handle, &exotic_test_cred_from_string_5, "cred_from_string_5"); exotic_add_test(&handle, &exotic_test_cred_from_string_6, "cred_from_string_6"); exotic_add_test(&handle, &exotic_test_cred_from_string_7, "cred_from_string_7"); exotic_add_test(&handle, &exotic_test_cred_from_string_8, "cred_from_string_8"); exotic_add_test(&handle, &exotic_test_cred_from_string_9, "cred_from_string_9"); exotic_add_test(&handle, &exotic_test_cred_from_string_10, "cred_from_string_10"); exotic_add_test(&handle, &exotic_test_eventqueue_init_1, "eventqueue_init_1"); exotic_add_test(&handle, &exotic_test_eventqueue_init_2, "eventqueue_init_2"); exotic_add_test(&handle, &exotic_test_eventqueue_post_1, "eventqueue_post_1"); exotic_add_test(&handle, &exotic_test_eventqueue_process_1, "eventqueue_process_1"); exotic_add_test(&handle, &exotic_test_eventqueue_size_1, "eventqueue_size_1"); exotic_add_test(&handle, &exotic_test_eventqueue_post_2, "eventqueue_post_2"); exotic_add_test(&handle, &exotic_test_eventqueue_size_2, "eventqueue_size_2"); exotic_add_test(&handle, &exotic_test_eventqueue_post_3, "eventqueue_post_3"); exotic_add_test(&handle, &exotic_test_eventqueue_size_3, "eventqueue_size_3"); exotic_add_test(&handle, &exotic_test_eventqueue_process_2, "eventqueue_process_2"); exotic_add_test(&handle, &exotic_test_eventqueue_size_4, "eventqueue_size_4"); exotic_add_test(&handle, &exotic_test_eventqueue_shutdown_1, "eventqueue_shutdown_1"); exotic_add_test(&handle, &exotic_test_hub_net_startup, "hub_net_startup"); exotic_add_test(&handle, &exotic_test_hub_config_initialize, "hub_config_initialize"); exotic_add_test(&handle, &exotic_test_hub_acl_initialize, "hub_acl_initialize"); exotic_add_test(&handle, &exotic_test_hub_service_initialize, "hub_service_initialize"); exotic_add_test(&handle, &exotic_test_hub_variables_startup, "hub_variables_startup"); exotic_add_test(&handle, &exotic_test_hub_variables_shutdown, "hub_variables_shutdown"); exotic_add_test(&handle, &exotic_test_hub_acl_shutdown, "hub_acl_shutdown"); exotic_add_test(&handle, &exotic_test_hub_config_shutdown, "hub_config_shutdown"); exotic_add_test(&handle, &exotic_test_hub_service_shutdown, "hub_service_shutdown"); exotic_add_test(&handle, &exotic_test_hub_net_shutdown, "hub_net_shutdown"); exotic_add_test(&handle, &exotic_test_inf_create_setup, "inf_create_setup"); exotic_add_test(&handle, &exotic_test_inf_ok_1, "inf_ok_1"); exotic_add_test(&handle, &exotic_test_inf_cid_1, "inf_cid_1"); exotic_add_test(&handle, &exotic_test_inf_cid_2, "inf_cid_2"); exotic_add_test(&handle, &exotic_test_inf_cid_3, "inf_cid_3"); exotic_add_test(&handle, &exotic_test_inf_cid_4, "inf_cid_4"); exotic_add_test(&handle, &exotic_test_inf_cid_5, "inf_cid_5"); exotic_add_test(&handle, &exotic_test_inf_cid_6, "inf_cid_6"); exotic_add_test(&handle, &exotic_test_inf_cid_7, "inf_cid_7"); exotic_add_test(&handle, &exotic_test_inf_cid_8, "inf_cid_8"); exotic_add_test(&handle, &exotic_test_inf_cid_9, "inf_cid_9"); exotic_add_test(&handle, &exotic_test_inf_pid_1, "inf_pid_1"); exotic_add_test(&handle, &exotic_test_inf_pid_2, "inf_pid_2"); exotic_add_test(&handle, &exotic_test_inf_pid_3, "inf_pid_3"); exotic_add_test(&handle, &exotic_test_inf_pid_4, "inf_pid_4"); exotic_add_test(&handle, &exotic_test_inf_pid_5, "inf_pid_5"); exotic_add_test(&handle, &exotic_test_inf_pid_6, "inf_pid_6"); exotic_add_test(&handle, &exotic_test_inf_pid_7, "inf_pid_7"); exotic_add_test(&handle, &exotic_test_inf_pid_8, "inf_pid_8"); exotic_add_test(&handle, &exotic_test_inf_pid_9, "inf_pid_9"); exotic_add_test(&handle, &exotic_test_inf_nick_01, "inf_nick_01"); exotic_add_test(&handle, &exotic_test_inf_nick_02, "inf_nick_02"); exotic_add_test(&handle, &exotic_test_inf_nick_03, "inf_nick_03"); exotic_add_test(&handle, &exotic_test_inf_nick_04, "inf_nick_04"); exotic_add_test(&handle, &exotic_test_inf_nick_05, "inf_nick_05"); exotic_add_test(&handle, &exotic_test_inf_nick_06, "inf_nick_06"); exotic_add_test(&handle, &exotic_test_inf_nick_07, "inf_nick_07"); exotic_add_test(&handle, &exotic_test_inf_nick_08, "inf_nick_08"); exotic_add_test(&handle, &exotic_test_inf_nick_09, "inf_nick_09"); exotic_add_test(&handle, &exotic_test_inf_nick_10, "inf_nick_10"); exotic_add_test(&handle, &exotic_test_inf_limits_1, "inf_limits_1"); exotic_add_test(&handle, &exotic_test_inf_limits_2, "inf_limits_2"); exotic_add_test(&handle, &exotic_test_inf_limits_3, "inf_limits_3"); exotic_add_test(&handle, &exotic_test_inf_limits_4, "inf_limits_4"); exotic_add_test(&handle, &exotic_test_inf_limit_hubs_setup, "inf_limit_hubs_setup"); exotic_add_test(&handle, &exotic_test_inf_limit_hubs_1, "inf_limit_hubs_1"); exotic_add_test(&handle, &exotic_test_inf_limit_hubs_2, "inf_limit_hubs_2"); exotic_add_test(&handle, &exotic_test_inf_limit_hubs_3, "inf_limit_hubs_3"); exotic_add_test(&handle, &exotic_test_inf_limit_hubs_4, "inf_limit_hubs_4"); exotic_add_test(&handle, &exotic_test_inf_limit_hubs_5, "inf_limit_hubs_5"); exotic_add_test(&handle, &exotic_test_inf_limit_hubs_6, "inf_limit_hubs_6"); exotic_add_test(&handle, &exotic_test_inf_limit_hubs_7, "inf_limit_hubs_7"); exotic_add_test(&handle, &exotic_test_inf_destroy_setup, "inf_destroy_setup"); exotic_add_test(&handle, &exotic_test_prepare_network, "prepare_network"); exotic_add_test(&handle, &exotic_test_check_ipv6, "check_ipv6"); exotic_add_test(&handle, &exotic_test_create_addresses_1, "create_addresses_1"); exotic_add_test(&handle, &exotic_test_create_addresses_2, "create_addresses_2"); exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_1, "ip_is_valid_ipv4_1"); exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_2, "ip_is_valid_ipv4_2"); exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_3, "ip_is_valid_ipv4_3"); exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_4, "ip_is_valid_ipv4_4"); exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_5, "ip_is_valid_ipv4_5"); exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_6, "ip_is_valid_ipv4_6"); exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_7, "ip_is_valid_ipv4_7"); exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_8, "ip_is_valid_ipv4_8"); exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_9, "ip_is_valid_ipv4_9"); exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv6_1, "ip_is_valid_ipv6_1"); exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv6_2, "ip_is_valid_ipv6_2"); exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv6_3, "ip_is_valid_ipv6_3"); exotic_add_test(&handle, &exotic_test_ip4_compare_1, "ip4_compare_1"); exotic_add_test(&handle, &exotic_test_ip4_compare_2, "ip4_compare_2"); exotic_add_test(&handle, &exotic_test_ip4_compare_3, "ip4_compare_3"); exotic_add_test(&handle, &exotic_test_ip4_compare_4, "ip4_compare_4"); exotic_add_test(&handle, &exotic_test_ip4_compare_5, "ip4_compare_5"); exotic_add_test(&handle, &exotic_test_ip4_compare_6, "ip4_compare_6"); exotic_add_test(&handle, &exotic_test_ip6_compare_1, "ip6_compare_1"); exotic_add_test(&handle, &exotic_test_ip6_compare_2, "ip6_compare_2"); exotic_add_test(&handle, &exotic_test_ip6_compare_3, "ip6_compare_3"); exotic_add_test(&handle, &exotic_test_ip6_compare_4, "ip6_compare_4"); exotic_add_test(&handle, &exotic_test_ip6_compare_5, "ip6_compare_5"); exotic_add_test(&handle, &exotic_test_ip6_compare_6, "ip6_compare_6"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_0, "ipv4_lmask_create_0"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_1, "ipv4_lmask_create_1"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_2, "ipv4_lmask_create_2"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_3, "ipv4_lmask_create_3"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_4, "ipv4_lmask_create_4"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_5, "ipv4_lmask_create_5"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_6, "ipv4_lmask_create_6"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_7, "ipv4_lmask_create_7"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_8, "ipv4_lmask_create_8"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_9, "ipv4_lmask_create_9"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_10, "ipv4_lmask_create_10"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_11, "ipv4_lmask_create_11"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_12, "ipv4_lmask_create_12"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_13, "ipv4_lmask_create_13"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_14, "ipv4_lmask_create_14"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_15, "ipv4_lmask_create_15"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_16, "ipv4_lmask_create_16"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_17, "ipv4_lmask_create_17"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_18, "ipv4_lmask_create_18"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_19, "ipv4_lmask_create_19"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_20, "ipv4_lmask_create_20"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_21, "ipv4_lmask_create_21"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_22, "ipv4_lmask_create_22"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_23, "ipv4_lmask_create_23"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_24, "ipv4_lmask_create_24"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_25, "ipv4_lmask_create_25"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_26, "ipv4_lmask_create_26"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_27, "ipv4_lmask_create_27"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_28, "ipv4_lmask_create_28"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_29, "ipv4_lmask_create_29"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_30, "ipv4_lmask_create_30"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_31, "ipv4_lmask_create_31"); exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_32, "ipv4_lmask_create_32"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_0, "ipv4_rmask_create_0"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_1, "ipv4_rmask_create_1"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_2, "ipv4_rmask_create_2"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_3, "ipv4_rmask_create_3"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_4, "ipv4_rmask_create_4"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_5, "ipv4_rmask_create_5"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_6, "ipv4_rmask_create_6"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_7, "ipv4_rmask_create_7"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_8, "ipv4_rmask_create_8"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_9, "ipv4_rmask_create_9"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_10, "ipv4_rmask_create_10"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_11, "ipv4_rmask_create_11"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_12, "ipv4_rmask_create_12"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_13, "ipv4_rmask_create_13"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_14, "ipv4_rmask_create_14"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_15, "ipv4_rmask_create_15"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_16, "ipv4_rmask_create_16"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_17, "ipv4_rmask_create_17"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_18, "ipv4_rmask_create_18"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_19, "ipv4_rmask_create_19"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_20, "ipv4_rmask_create_20"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_21, "ipv4_rmask_create_21"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_22, "ipv4_rmask_create_22"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_23, "ipv4_rmask_create_23"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_24, "ipv4_rmask_create_24"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_25, "ipv4_rmask_create_25"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_26, "ipv4_rmask_create_26"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_27, "ipv4_rmask_create_27"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_28, "ipv4_rmask_create_28"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_29, "ipv4_rmask_create_29"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_30, "ipv4_rmask_create_30"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_31, "ipv4_rmask_create_31"); exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_32, "ipv4_rmask_create_32"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_0, "ip6_lmask_create_0"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_1, "ip6_lmask_create_1"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_2, "ip6_lmask_create_2"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_3, "ip6_lmask_create_3"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_4, "ip6_lmask_create_4"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_5, "ip6_lmask_create_5"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_6, "ip6_lmask_create_6"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_7, "ip6_lmask_create_7"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_8, "ip6_lmask_create_8"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_9, "ip6_lmask_create_9"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_10, "ip6_lmask_create_10"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_11, "ip6_lmask_create_11"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_12, "ip6_lmask_create_12"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_13, "ip6_lmask_create_13"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_14, "ip6_lmask_create_14"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_15, "ip6_lmask_create_15"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_16, "ip6_lmask_create_16"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_17, "ip6_lmask_create_17"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_18, "ip6_lmask_create_18"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_19, "ip6_lmask_create_19"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_20, "ip6_lmask_create_20"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_21, "ip6_lmask_create_21"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_22, "ip6_lmask_create_22"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_23, "ip6_lmask_create_23"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_24, "ip6_lmask_create_24"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_25, "ip6_lmask_create_25"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_26, "ip6_lmask_create_26"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_27, "ip6_lmask_create_27"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_28, "ip6_lmask_create_28"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_29, "ip6_lmask_create_29"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_30, "ip6_lmask_create_30"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_31, "ip6_lmask_create_31"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_32, "ip6_lmask_create_32"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_33, "ip6_lmask_create_33"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_34, "ip6_lmask_create_34"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_35, "ip6_lmask_create_35"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_36, "ip6_lmask_create_36"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_37, "ip6_lmask_create_37"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_38, "ip6_lmask_create_38"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_39, "ip6_lmask_create_39"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_40, "ip6_lmask_create_40"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_41, "ip6_lmask_create_41"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_42, "ip6_lmask_create_42"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_43, "ip6_lmask_create_43"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_44, "ip6_lmask_create_44"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_45, "ip6_lmask_create_45"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_46, "ip6_lmask_create_46"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_47, "ip6_lmask_create_47"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_48, "ip6_lmask_create_48"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_49, "ip6_lmask_create_49"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_50, "ip6_lmask_create_50"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_51, "ip6_lmask_create_51"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_52, "ip6_lmask_create_52"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_53, "ip6_lmask_create_53"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_54, "ip6_lmask_create_54"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_55, "ip6_lmask_create_55"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_56, "ip6_lmask_create_56"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_57, "ip6_lmask_create_57"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_58, "ip6_lmask_create_58"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_59, "ip6_lmask_create_59"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_60, "ip6_lmask_create_60"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_61, "ip6_lmask_create_61"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_62, "ip6_lmask_create_62"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_63, "ip6_lmask_create_63"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_64, "ip6_lmask_create_64"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_65, "ip6_lmask_create_65"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_66, "ip6_lmask_create_66"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_67, "ip6_lmask_create_67"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_68, "ip6_lmask_create_68"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_69, "ip6_lmask_create_69"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_70, "ip6_lmask_create_70"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_71, "ip6_lmask_create_71"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_72, "ip6_lmask_create_72"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_73, "ip6_lmask_create_73"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_74, "ip6_lmask_create_74"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_75, "ip6_lmask_create_75"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_76, "ip6_lmask_create_76"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_77, "ip6_lmask_create_77"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_78, "ip6_lmask_create_78"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_79, "ip6_lmask_create_79"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_80, "ip6_lmask_create_80"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_81, "ip6_lmask_create_81"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_82, "ip6_lmask_create_82"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_83, "ip6_lmask_create_83"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_84, "ip6_lmask_create_84"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_85, "ip6_lmask_create_85"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_86, "ip6_lmask_create_86"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_87, "ip6_lmask_create_87"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_88, "ip6_lmask_create_88"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_89, "ip6_lmask_create_89"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_90, "ip6_lmask_create_90"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_91, "ip6_lmask_create_91"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_92, "ip6_lmask_create_92"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_93, "ip6_lmask_create_93"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_94, "ip6_lmask_create_94"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_95, "ip6_lmask_create_95"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_96, "ip6_lmask_create_96"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_97, "ip6_lmask_create_97"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_98, "ip6_lmask_create_98"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_99, "ip6_lmask_create_99"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_100, "ip6_lmask_create_100"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_101, "ip6_lmask_create_101"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_102, "ip6_lmask_create_102"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_103, "ip6_lmask_create_103"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_104, "ip6_lmask_create_104"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_105, "ip6_lmask_create_105"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_106, "ip6_lmask_create_106"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_107, "ip6_lmask_create_107"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_108, "ip6_lmask_create_108"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_109, "ip6_lmask_create_109"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_110, "ip6_lmask_create_110"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_111, "ip6_lmask_create_111"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_112, "ip6_lmask_create_112"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_113, "ip6_lmask_create_113"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_114, "ip6_lmask_create_114"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_115, "ip6_lmask_create_115"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_116, "ip6_lmask_create_116"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_117, "ip6_lmask_create_117"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_118, "ip6_lmask_create_118"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_119, "ip6_lmask_create_119"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_120, "ip6_lmask_create_120"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_121, "ip6_lmask_create_121"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_122, "ip6_lmask_create_122"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_123, "ip6_lmask_create_123"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_124, "ip6_lmask_create_124"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_125, "ip6_lmask_create_125"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_126, "ip6_lmask_create_126"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_127, "ip6_lmask_create_127"); exotic_add_test(&handle, &exotic_test_ip6_lmask_create_128, "ip6_lmask_create_128"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_0, "ip6_rmask_create_0"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_1, "ip6_rmask_create_1"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_2, "ip6_rmask_create_2"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_3, "ip6_rmask_create_3"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_4, "ip6_rmask_create_4"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_5, "ip6_rmask_create_5"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_6, "ip6_rmask_create_6"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_7, "ip6_rmask_create_7"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_8, "ip6_rmask_create_8"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_9, "ip6_rmask_create_9"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_10, "ip6_rmask_create_10"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_11, "ip6_rmask_create_11"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_12, "ip6_rmask_create_12"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_13, "ip6_rmask_create_13"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_14, "ip6_rmask_create_14"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_15, "ip6_rmask_create_15"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_16, "ip6_rmask_create_16"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_17, "ip6_rmask_create_17"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_18, "ip6_rmask_create_18"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_19, "ip6_rmask_create_19"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_20, "ip6_rmask_create_20"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_21, "ip6_rmask_create_21"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_22, "ip6_rmask_create_22"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_23, "ip6_rmask_create_23"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_24, "ip6_rmask_create_24"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_25, "ip6_rmask_create_25"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_26, "ip6_rmask_create_26"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_27, "ip6_rmask_create_27"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_28, "ip6_rmask_create_28"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_29, "ip6_rmask_create_29"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_30, "ip6_rmask_create_30"); exotic_add_test(&handle, &exotic_test_ip6_rmask_create_31, "ip6_rmask_create_31"); exotic_add_test(&handle, &exotic_test_check_ban_setup_1, "check_ban_setup_1"); exotic_add_test(&handle, &exotic_test_check_ban_ipv4_1, "check_ban_ipv4_1"); exotic_add_test(&handle, &exotic_test_check_ban_ipv4_2, "check_ban_ipv4_2"); exotic_add_test(&handle, &exotic_test_check_ban_ipv4_3, "check_ban_ipv4_3"); exotic_add_test(&handle, &exotic_test_check_ban_ipv4_4, "check_ban_ipv4_4"); exotic_add_test(&handle, &exotic_test_check_ban_ipv4_5, "check_ban_ipv4_5"); exotic_add_test(&handle, &exotic_test_check_ban_ipv6_1, "check_ban_ipv6_1"); exotic_add_test(&handle, &exotic_test_check_ban_ipv6_2, "check_ban_ipv6_2"); exotic_add_test(&handle, &exotic_test_check_ban_ipv6_3, "check_ban_ipv6_3"); exotic_add_test(&handle, &exotic_test_check_ban_ipv6_4, "check_ban_ipv6_4"); exotic_add_test(&handle, &exotic_test_check_ban_ipv6_5, "check_ban_ipv6_5"); exotic_add_test(&handle, &exotic_test_check_ban_ipv6_6, "check_ban_ipv6_6"); exotic_add_test(&handle, &exotic_test_check_ban_afmix_1, "check_ban_afmix_1"); exotic_add_test(&handle, &exotic_test_check_ban_afmix_2, "check_ban_afmix_2"); exotic_add_test(&handle, &exotic_test_ip4_bitwise_AND_1, "ip4_bitwise_AND_1"); exotic_add_test(&handle, &exotic_test_ip4_bitwise_AND_2, "ip4_bitwise_AND_2"); exotic_add_test(&handle, &exotic_test_ip4_bitwise_AND_3, "ip4_bitwise_AND_3"); exotic_add_test(&handle, &exotic_test_ip4_bitwise_AND_4, "ip4_bitwise_AND_4"); exotic_add_test(&handle, &exotic_test_ip4_bitwise_AND_5, "ip4_bitwise_AND_5"); exotic_add_test(&handle, &exotic_test_ip4_bitwise_OR_1, "ip4_bitwise_OR_1"); exotic_add_test(&handle, &exotic_test_ip4_bitwise_OR_2, "ip4_bitwise_OR_2"); exotic_add_test(&handle, &exotic_test_ip4_bitwise_OR_3, "ip4_bitwise_OR_3"); exotic_add_test(&handle, &exotic_test_ip4_bitwise_OR_4, "ip4_bitwise_OR_4"); exotic_add_test(&handle, &exotic_test_ip4_bitwise_OR_5, "ip4_bitwise_OR_5"); exotic_add_test(&handle, &exotic_test_ip6_bitwise_AND_1, "ip6_bitwise_AND_1"); exotic_add_test(&handle, &exotic_test_ip6_bitwise_AND_2, "ip6_bitwise_AND_2"); exotic_add_test(&handle, &exotic_test_ip6_bitwise_AND_3, "ip6_bitwise_AND_3"); exotic_add_test(&handle, &exotic_test_ip6_bitwise_OR_1, "ip6_bitwise_OR_1"); exotic_add_test(&handle, &exotic_test_ip6_bitwise_OR_2, "ip6_bitwise_OR_2"); exotic_add_test(&handle, &exotic_test_ip6_bitwise_OR_3, "ip6_bitwise_OR_3"); exotic_add_test(&handle, &exotic_test_ip_range_1, "ip_range_1"); exotic_add_test(&handle, &exotic_test_ip_range_2, "ip_range_2"); exotic_add_test(&handle, &exotic_test_ip_range_3, "ip_range_3"); exotic_add_test(&handle, &exotic_test_ip_range_4, "ip_range_4"); exotic_add_test(&handle, &exotic_test_shutdown_network, "shutdown_network"); exotic_add_test(&handle, &exotic_test_list_create_destroy, "list_create_destroy"); exotic_add_test(&handle, &exotic_test_list_create, "list_create"); exotic_add_test(&handle, &exotic_test_list_append_1, "list_append_1"); exotic_add_test(&handle, &exotic_test_list_remove_1, "list_remove_1"); exotic_add_test(&handle, &exotic_test_list_append_2, "list_append_2"); exotic_add_test(&handle, &exotic_test_list_remove_2, "list_remove_2"); exotic_add_test(&handle, &exotic_test_list_remove_3, "list_remove_3"); exotic_add_test(&handle, &exotic_test_list_remove_4, "list_remove_4"); exotic_add_test(&handle, &exotic_test_list_append_3, "list_append_3"); exotic_add_test(&handle, &exotic_test_list_append_4, "list_append_4"); exotic_add_test(&handle, &exotic_test_list_remove_5, "list_remove_5"); exotic_add_test(&handle, &exotic_test_list_get_index_1, "list_get_index_1"); exotic_add_test(&handle, &exotic_test_list_get_index_2, "list_get_index_2"); exotic_add_test(&handle, &exotic_test_list_get_index_3, "list_get_index_3"); exotic_add_test(&handle, &exotic_test_list_get_index_4, "list_get_index_4"); exotic_add_test(&handle, &exotic_test_list_get_first_1, "list_get_first_1"); exotic_add_test(&handle, &exotic_test_list_get_first_next_1, "list_get_first_next_1"); exotic_add_test(&handle, &exotic_test_list_get_first_next_2, "list_get_first_next_2"); exotic_add_test(&handle, &exotic_test_list_get_last_1, "list_get_last_1"); exotic_add_test(&handle, &exotic_test_list_get_last_prev_1, "list_get_last_prev_1"); exotic_add_test(&handle, &exotic_test_list_get_last_prev_2, "list_get_last_prev_2"); exotic_add_test(&handle, &exotic_test_list_get_last_prev_next_1, "list_get_last_prev_next_1"); exotic_add_test(&handle, &exotic_test_list_clear, "list_clear"); exotic_add_test(&handle, &exotic_test_list_remove_first_1_1, "list_remove_first_1_1"); exotic_add_test(&handle, &exotic_test_list_remove_first_1_2, "list_remove_first_1_2"); exotic_add_test(&handle, &exotic_test_list_remove_first_1_3, "list_remove_first_1_3"); exotic_add_test(&handle, &exotic_test_list_remove_first_1_4, "list_remove_first_1_4"); exotic_add_test(&handle, &exotic_test_list_remove_first_1_5, "list_remove_first_1_5"); exotic_add_test(&handle, &exotic_test_list_append_list_1, "list_append_list_1"); exotic_add_test(&handle, &exotic_test_list_append_list_2, "list_append_list_2"); exotic_add_test(&handle, &exotic_test_list_append_list_3, "list_append_list_3"); exotic_add_test(&handle, &exotic_test_list_clear_list_last, "list_clear_list_last"); exotic_add_test(&handle, &exotic_test_list_destroy_1, "list_destroy_1"); exotic_add_test(&handle, &exotic_test_list_destroy_2, "list_destroy_2"); exotic_add_test(&handle, &exotic_test_test_message_refc_1, "test_message_refc_1"); exotic_add_test(&handle, &exotic_test_test_message_refc_2, "test_message_refc_2"); exotic_add_test(&handle, &exotic_test_test_message_refc_3, "test_message_refc_3"); exotic_add_test(&handle, &exotic_test_test_message_refc_4, "test_message_refc_4"); exotic_add_test(&handle, &exotic_test_test_message_refc_5, "test_message_refc_5"); exotic_add_test(&handle, &exotic_test_test_message_refc_6, "test_message_refc_6"); exotic_add_test(&handle, &exotic_test_test_message_refc_7, "test_message_refc_7"); exotic_add_test(&handle, &exotic_test_adc_message_first, "adc_message_first"); exotic_add_test(&handle, &exotic_test_adc_message_parse_1, "adc_message_parse_1"); exotic_add_test(&handle, &exotic_test_adc_message_parse_2, "adc_message_parse_2"); exotic_add_test(&handle, &exotic_test_adc_message_parse_3, "adc_message_parse_3"); exotic_add_test(&handle, &exotic_test_adc_message_parse_4, "adc_message_parse_4"); exotic_add_test(&handle, &exotic_test_adc_message_parse_5, "adc_message_parse_5"); exotic_add_test(&handle, &exotic_test_adc_message_parse_6, "adc_message_parse_6"); exotic_add_test(&handle, &exotic_test_adc_message_parse_7, "adc_message_parse_7"); exotic_add_test(&handle, &exotic_test_adc_message_parse_8, "adc_message_parse_8"); exotic_add_test(&handle, &exotic_test_adc_message_parse_9, "adc_message_parse_9"); exotic_add_test(&handle, &exotic_test_adc_message_parse_10, "adc_message_parse_10"); exotic_add_test(&handle, &exotic_test_adc_message_parse_11, "adc_message_parse_11"); exotic_add_test(&handle, &exotic_test_adc_message_parse_12, "adc_message_parse_12"); exotic_add_test(&handle, &exotic_test_adc_message_parse_13, "adc_message_parse_13"); exotic_add_test(&handle, &exotic_test_adc_message_parse_14, "adc_message_parse_14"); exotic_add_test(&handle, &exotic_test_adc_message_parse_15, "adc_message_parse_15"); exotic_add_test(&handle, &exotic_test_adc_message_parse_16, "adc_message_parse_16"); exotic_add_test(&handle, &exotic_test_adc_message_parse_17, "adc_message_parse_17"); exotic_add_test(&handle, &exotic_test_adc_message_parse_18, "adc_message_parse_18"); exotic_add_test(&handle, &exotic_test_adc_message_parse_19, "adc_message_parse_19"); exotic_add_test(&handle, &exotic_test_adc_message_parse_20, "adc_message_parse_20"); exotic_add_test(&handle, &exotic_test_adc_message_parse_21, "adc_message_parse_21"); exotic_add_test(&handle, &exotic_test_adc_message_parse_22, "adc_message_parse_22"); exotic_add_test(&handle, &exotic_test_adc_message_parse_23, "adc_message_parse_23"); exotic_add_test(&handle, &exotic_test_adc_message_parse_24, "adc_message_parse_24"); exotic_add_test(&handle, &exotic_test_adc_message_add_arg_1, "adc_message_add_arg_1"); exotic_add_test(&handle, &exotic_test_adc_message_add_arg_2, "adc_message_add_arg_2"); exotic_add_test(&handle, &exotic_test_adc_message_remove_arg_1, "adc_message_remove_arg_1"); exotic_add_test(&handle, &exotic_test_adc_message_remove_arg_2, "adc_message_remove_arg_2"); exotic_add_test(&handle, &exotic_test_adc_message_remove_arg_3, "adc_message_remove_arg_3"); exotic_add_test(&handle, &exotic_test_adc_message_remove_arg_4, "adc_message_remove_arg_4"); exotic_add_test(&handle, &exotic_test_adc_message_replace_arg_1, "adc_message_replace_arg_1"); exotic_add_test(&handle, &exotic_test_adc_message_replace_arg_2, "adc_message_replace_arg_2"); exotic_add_test(&handle, &exotic_test_adc_message_replace_arg_3, "adc_message_replace_arg_3"); exotic_add_test(&handle, &exotic_test_adc_message_get_arg_1, "adc_message_get_arg_1"); exotic_add_test(&handle, &exotic_test_adc_message_get_arg_2, "adc_message_get_arg_2"); exotic_add_test(&handle, &exotic_test_adc_message_get_arg_3, "adc_message_get_arg_3"); exotic_add_test(&handle, &exotic_test_adc_message_get_arg_4, "adc_message_get_arg_4"); exotic_add_test(&handle, &exotic_test_adc_message_get_named_arg_1, "adc_message_get_named_arg_1"); exotic_add_test(&handle, &exotic_test_adc_message_get_named_arg_2, "adc_message_get_named_arg_2"); exotic_add_test(&handle, &exotic_test_adc_message_get_named_arg_3, "adc_message_get_named_arg_3"); exotic_add_test(&handle, &exotic_test_adc_message_get_named_arg_4, "adc_message_get_named_arg_4"); exotic_add_test(&handle, &exotic_test_adc_message_has_named_arg_1, "adc_message_has_named_arg_1"); exotic_add_test(&handle, &exotic_test_adc_message_has_named_arg_2, "adc_message_has_named_arg_2"); exotic_add_test(&handle, &exotic_test_adc_message_has_named_arg_3, "adc_message_has_named_arg_3"); exotic_add_test(&handle, &exotic_test_adc_message_has_named_arg_4, "adc_message_has_named_arg_4"); exotic_add_test(&handle, &exotic_test_adc_message_has_named_arg_5, "adc_message_has_named_arg_5"); exotic_add_test(&handle, &exotic_test_adc_message_has_named_arg_6, "adc_message_has_named_arg_6"); exotic_add_test(&handle, &exotic_test_adc_message_has_named_arg_7, "adc_message_has_named_arg_7"); exotic_add_test(&handle, &exotic_test_adc_message_terminate_1, "adc_message_terminate_1"); exotic_add_test(&handle, &exotic_test_adc_message_terminate_2, "adc_message_terminate_2"); exotic_add_test(&handle, &exotic_test_adc_message_terminate_3, "adc_message_terminate_3"); exotic_add_test(&handle, &exotic_test_adc_message_terminate_4, "adc_message_terminate_4"); exotic_add_test(&handle, &exotic_test_adc_message_terminate_5, "adc_message_terminate_5"); exotic_add_test(&handle, &exotic_test_adc_message_terminate_6, "adc_message_terminate_6"); exotic_add_test(&handle, &exotic_test_adc_message_escape_1, "adc_message_escape_1"); exotic_add_test(&handle, &exotic_test_adc_message_escape_2, "adc_message_escape_2"); exotic_add_test(&handle, &exotic_test_adc_message_escape_3, "adc_message_escape_3"); exotic_add_test(&handle, &exotic_test_adc_message_copy_1, "adc_message_copy_1"); exotic_add_test(&handle, &exotic_test_adc_message_copy_2, "adc_message_copy_2"); exotic_add_test(&handle, &exotic_test_adc_message_copy_3, "adc_message_copy_3"); exotic_add_test(&handle, &exotic_test_adc_message_copy_4, "adc_message_copy_4"); exotic_add_test(&handle, &exotic_test_adc_message_update_1, "adc_message_update_1"); exotic_add_test(&handle, &exotic_test_adc_message_update_2, "adc_message_update_2"); exotic_add_test(&handle, &exotic_test_adc_message_update_3, "adc_message_update_3"); exotic_add_test(&handle, &exotic_test_adc_message_update_4, "adc_message_update_4"); exotic_add_test(&handle, &exotic_test_adc_message_update_4_cleanup, "adc_message_update_4_cleanup"); exotic_add_test(&handle, &exotic_test_adc_message_empty_1, "adc_message_empty_1"); exotic_add_test(&handle, &exotic_test_adc_message_empty_2, "adc_message_empty_2"); exotic_add_test(&handle, &exotic_test_adc_message_empty_3, "adc_message_empty_3"); exotic_add_test(&handle, &exotic_test_adc_message_last, "adc_message_last"); exotic_add_test(&handle, &exotic_test_is_num_0, "is_num_0"); exotic_add_test(&handle, &exotic_test_is_num_1, "is_num_1"); exotic_add_test(&handle, &exotic_test_is_num_2, "is_num_2"); exotic_add_test(&handle, &exotic_test_is_num_3, "is_num_3"); exotic_add_test(&handle, &exotic_test_is_num_4, "is_num_4"); exotic_add_test(&handle, &exotic_test_is_num_5, "is_num_5"); exotic_add_test(&handle, &exotic_test_is_num_6, "is_num_6"); exotic_add_test(&handle, &exotic_test_is_num_7, "is_num_7"); exotic_add_test(&handle, &exotic_test_is_num_8, "is_num_8"); exotic_add_test(&handle, &exotic_test_is_num_9, "is_num_9"); exotic_add_test(&handle, &exotic_test_is_num_10, "is_num_10"); exotic_add_test(&handle, &exotic_test_is_num_11, "is_num_11"); exotic_add_test(&handle, &exotic_test_is_space_1, "is_space_1"); exotic_add_test(&handle, &exotic_test_is_space_2, "is_space_2"); exotic_add_test(&handle, &exotic_test_is_white_space_1, "is_white_space_1"); exotic_add_test(&handle, &exotic_test_is_white_space_2, "is_white_space_2"); exotic_add_test(&handle, &exotic_test_is_white_space_3, "is_white_space_3"); exotic_add_test(&handle, &exotic_test_is_white_space_4, "is_white_space_4"); exotic_add_test(&handle, &exotic_test_itoa_1, "itoa_1"); exotic_add_test(&handle, &exotic_test_itoa_2, "itoa_2"); exotic_add_test(&handle, &exotic_test_itoa_3, "itoa_3"); exotic_add_test(&handle, &exotic_test_itoa_4, "itoa_4"); exotic_add_test(&handle, &exotic_test_itoa_5, "itoa_5"); exotic_add_test(&handle, &exotic_test_itoa_6, "itoa_6"); exotic_add_test(&handle, &exotic_test_itoa_7, "itoa_7"); exotic_add_test(&handle, &exotic_test_itoa_8, "itoa_8"); exotic_add_test(&handle, &exotic_test_base32_valid_1, "base32_valid_1"); exotic_add_test(&handle, &exotic_test_base32_valid_2, "base32_valid_2"); exotic_add_test(&handle, &exotic_test_base32_valid_3, "base32_valid_3"); exotic_add_test(&handle, &exotic_test_base32_valid_4, "base32_valid_4"); exotic_add_test(&handle, &exotic_test_base32_valid_5, "base32_valid_5"); exotic_add_test(&handle, &exotic_test_base32_valid_6, "base32_valid_6"); exotic_add_test(&handle, &exotic_test_base32_valid_7, "base32_valid_7"); exotic_add_test(&handle, &exotic_test_base32_valid_8, "base32_valid_8"); exotic_add_test(&handle, &exotic_test_base32_valid_9, "base32_valid_9"); exotic_add_test(&handle, &exotic_test_base32_valid_10, "base32_valid_10"); exotic_add_test(&handle, &exotic_test_base32_valid_11, "base32_valid_11"); exotic_add_test(&handle, &exotic_test_base32_valid_12, "base32_valid_12"); exotic_add_test(&handle, &exotic_test_base32_valid_13, "base32_valid_13"); exotic_add_test(&handle, &exotic_test_base32_valid_14, "base32_valid_14"); exotic_add_test(&handle, &exotic_test_base32_valid_15, "base32_valid_15"); exotic_add_test(&handle, &exotic_test_base32_valid_16, "base32_valid_16"); exotic_add_test(&handle, &exotic_test_base32_valid_17, "base32_valid_17"); exotic_add_test(&handle, &exotic_test_base32_valid_18, "base32_valid_18"); exotic_add_test(&handle, &exotic_test_base32_valid_19, "base32_valid_19"); exotic_add_test(&handle, &exotic_test_base32_valid_20, "base32_valid_20"); exotic_add_test(&handle, &exotic_test_base32_valid_21, "base32_valid_21"); exotic_add_test(&handle, &exotic_test_base32_valid_22, "base32_valid_22"); exotic_add_test(&handle, &exotic_test_base32_valid_23, "base32_valid_23"); exotic_add_test(&handle, &exotic_test_base32_valid_24, "base32_valid_24"); exotic_add_test(&handle, &exotic_test_base32_valid_25, "base32_valid_25"); exotic_add_test(&handle, &exotic_test_base32_valid_26, "base32_valid_26"); exotic_add_test(&handle, &exotic_test_base32_valid_27, "base32_valid_27"); exotic_add_test(&handle, &exotic_test_base32_valid_28, "base32_valid_28"); exotic_add_test(&handle, &exotic_test_base32_valid_29, "base32_valid_29"); exotic_add_test(&handle, &exotic_test_base32_valid_30, "base32_valid_30"); exotic_add_test(&handle, &exotic_test_base32_valid_31, "base32_valid_31"); exotic_add_test(&handle, &exotic_test_base32_valid_32, "base32_valid_32"); exotic_add_test(&handle, &exotic_test_base32_invalid_1, "base32_invalid_1"); exotic_add_test(&handle, &exotic_test_base32_invalid_2, "base32_invalid_2"); exotic_add_test(&handle, &exotic_test_base32_invalid_3, "base32_invalid_3"); exotic_add_test(&handle, &exotic_test_base32_invalid_4, "base32_invalid_4"); exotic_add_test(&handle, &exotic_test_base32_invalid_5, "base32_invalid_5"); exotic_add_test(&handle, &exotic_test_base32_invalid_6, "base32_invalid_6"); exotic_add_test(&handle, &exotic_test_base32_invalid_7, "base32_invalid_7"); exotic_add_test(&handle, &exotic_test_base32_invalid_8, "base32_invalid_8"); exotic_add_test(&handle, &exotic_test_base32_invalid_9, "base32_invalid_9"); exotic_add_test(&handle, &exotic_test_base32_invalid_10, "base32_invalid_10"); exotic_add_test(&handle, &exotic_test_base32_invalid_11, "base32_invalid_11"); exotic_add_test(&handle, &exotic_test_base32_invalid_12, "base32_invalid_12"); exotic_add_test(&handle, &exotic_test_base32_invalid_13, "base32_invalid_13"); exotic_add_test(&handle, &exotic_test_base32_invalid_14, "base32_invalid_14"); exotic_add_test(&handle, &exotic_test_base32_invalid_15, "base32_invalid_15"); exotic_add_test(&handle, &exotic_test_base32_invalid_16, "base32_invalid_16"); exotic_add_test(&handle, &exotic_test_base32_invalid_17, "base32_invalid_17"); exotic_add_test(&handle, &exotic_test_base32_invalid_18, "base32_invalid_18"); exotic_add_test(&handle, &exotic_test_base32_invalid_19, "base32_invalid_19"); exotic_add_test(&handle, &exotic_test_base32_invalid_20, "base32_invalid_20"); exotic_add_test(&handle, &exotic_test_base32_invalid_21, "base32_invalid_21"); exotic_add_test(&handle, &exotic_test_base32_invalid_22, "base32_invalid_22"); exotic_add_test(&handle, &exotic_test_base32_invalid_23, "base32_invalid_23"); exotic_add_test(&handle, &exotic_test_base32_invalid_24, "base32_invalid_24"); exotic_add_test(&handle, &exotic_test_base32_invalid_25, "base32_invalid_25"); exotic_add_test(&handle, &exotic_test_base32_invalid_26, "base32_invalid_26"); exotic_add_test(&handle, &exotic_test_base32_invalid_27, "base32_invalid_27"); exotic_add_test(&handle, &exotic_test_base32_invalid_28, "base32_invalid_28"); exotic_add_test(&handle, &exotic_test_base32_invalid_29, "base32_invalid_29"); exotic_add_test(&handle, &exotic_test_base32_invalid_30, "base32_invalid_30"); exotic_add_test(&handle, &exotic_test_base32_invalid_31, "base32_invalid_31"); exotic_add_test(&handle, &exotic_test_utf8_valid_1, "utf8_valid_1"); exotic_add_test(&handle, &exotic_test_utf8_valid_2, "utf8_valid_2"); exotic_add_test(&handle, &exotic_test_utf8_valid_3, "utf8_valid_3"); exotic_add_test(&handle, &exotic_test_utf8_valid_4, "utf8_valid_4"); exotic_add_test(&handle, &exotic_test_utf8_valid_5, "utf8_valid_5"); exotic_add_test(&handle, &exotic_test_utf8_valid_6, "utf8_valid_6"); exotic_add_test(&handle, &exotic_test_utf8_valid_7, "utf8_valid_7"); exotic_add_test(&handle, &exotic_test_utf8_valid_8, "utf8_valid_8"); exotic_add_test(&handle, &exotic_test_utf8_valid_9, "utf8_valid_9"); exotic_add_test(&handle, &exotic_test_utf8_valid_10, "utf8_valid_10"); exotic_add_test(&handle, &exotic_test_utf8_valid_11, "utf8_valid_11"); exotic_add_test(&handle, &exotic_test_utf8_valid_12, "utf8_valid_12"); exotic_add_test(&handle, &exotic_test_utf8_valid_13, "utf8_valid_13"); exotic_add_test(&handle, &exotic_test_utf8_valid_14, "utf8_valid_14"); exotic_add_test(&handle, &exotic_test_utf8_valid_15, "utf8_valid_15"); exotic_add_test(&handle, &exotic_test_utf8_valid_16, "utf8_valid_16"); exotic_add_test(&handle, &exotic_test_utf8_valid_17, "utf8_valid_17"); exotic_add_test(&handle, &exotic_test_utf8_valid_18, "utf8_valid_18"); exotic_add_test(&handle, &exotic_test_utf8_valid_19, "utf8_valid_19"); exotic_add_test(&handle, &exotic_test_utf8_valid_20, "utf8_valid_20"); exotic_add_test(&handle, &exotic_test_utf8_valid_21, "utf8_valid_21"); exotic_add_test(&handle, &exotic_test_utf8_valid_22, "utf8_valid_22"); exotic_add_test(&handle, &exotic_test_utf8_valid_23, "utf8_valid_23"); exotic_add_test(&handle, &exotic_test_utf8_valid_24, "utf8_valid_24"); exotic_add_test(&handle, &exotic_test_utf8_valid_25, "utf8_valid_25"); exotic_add_test(&handle, &exotic_test_utf8_valid_26, "utf8_valid_26"); exotic_add_test(&handle, &exotic_test_utf8_valid_27, "utf8_valid_27"); exotic_add_test(&handle, &exotic_test_utf8_valid_28, "utf8_valid_28"); exotic_add_test(&handle, &exotic_test_utf8_valid_29, "utf8_valid_29"); exotic_add_test(&handle, &exotic_test_utf8_valid_30, "utf8_valid_30"); exotic_add_test(&handle, &exotic_test_utf8_valid_31, "utf8_valid_31"); exotic_add_test(&handle, &exotic_test_utf8_valid_32, "utf8_valid_32"); exotic_add_test(&handle, &exotic_test_utf8_valid_33, "utf8_valid_33"); exotic_add_test(&handle, &exotic_test_utf8_valid_34, "utf8_valid_34"); exotic_add_test(&handle, &exotic_test_utf8_valid_35, "utf8_valid_35"); exotic_add_test(&handle, &exotic_test_utf8_valid_36, "utf8_valid_36"); exotic_add_test(&handle, &exotic_test_utf8_valid_37, "utf8_valid_37"); exotic_add_test(&handle, &exotic_test_utf8_valid_38, "utf8_valid_38"); exotic_add_test(&handle, &exotic_test_utf8_valid_39, "utf8_valid_39"); exotic_add_test(&handle, &exotic_test_utf8_valid_40, "utf8_valid_40"); exotic_add_test(&handle, &exotic_test_rbtree_create_destroy, "rbtree_create_destroy"); exotic_add_test(&handle, &exotic_test_rbtree_create_1, "rbtree_create_1"); exotic_add_test(&handle, &exotic_test_rbtree_size_0, "rbtree_size_0"); exotic_add_test(&handle, &exotic_test_rbtree_insert_1, "rbtree_insert_1"); exotic_add_test(&handle, &exotic_test_rbtree_insert_2, "rbtree_insert_2"); exotic_add_test(&handle, &exotic_test_rbtree_insert_3, "rbtree_insert_3"); exotic_add_test(&handle, &exotic_test_rbtree_insert_3_again, "rbtree_insert_3_again"); exotic_add_test(&handle, &exotic_test_rbtree_size_1, "rbtree_size_1"); exotic_add_test(&handle, &exotic_test_rbtree_search_1, "rbtree_search_1"); exotic_add_test(&handle, &exotic_test_rbtree_search_2, "rbtree_search_2"); exotic_add_test(&handle, &exotic_test_rbtree_search_3, "rbtree_search_3"); exotic_add_test(&handle, &exotic_test_rbtree_search_4, "rbtree_search_4"); exotic_add_test(&handle, &exotic_test_rbtree_remove_1, "rbtree_remove_1"); exotic_add_test(&handle, &exotic_test_rbtree_size_2, "rbtree_size_2"); exotic_add_test(&handle, &exotic_test_rbtree_remove_2, "rbtree_remove_2"); exotic_add_test(&handle, &exotic_test_rbtree_remove_3, "rbtree_remove_3"); exotic_add_test(&handle, &exotic_test_rbtree_remove_3_again, "rbtree_remove_3_again"); exotic_add_test(&handle, &exotic_test_rbtree_search_5, "rbtree_search_5"); exotic_add_test(&handle, &exotic_test_rbtree_search_6, "rbtree_search_6"); exotic_add_test(&handle, &exotic_test_rbtree_search_7, "rbtree_search_7"); exotic_add_test(&handle, &exotic_test_rbtree_search_8, "rbtree_search_8"); exotic_add_test(&handle, &exotic_test_rbtree_size_3, "rbtree_size_3"); exotic_add_test(&handle, &exotic_test_rbtree_insert_10000, "rbtree_insert_10000"); exotic_add_test(&handle, &exotic_test_rbtree_size_4, "rbtree_size_4"); exotic_add_test(&handle, &exotic_test_rbtree_check_10000, "rbtree_check_10000"); exotic_add_test(&handle, &exotic_test_rbtree_iterate_10000, "rbtree_iterate_10000"); exotic_add_test(&handle, &exotic_test_rbtree_remove_10000, "rbtree_remove_10000"); exotic_add_test(&handle, &exotic_test_rbtree_destroy_1, "rbtree_destroy_1"); exotic_add_test(&handle, &exotic_test_sid_create_pool, "sid_create_pool"); exotic_add_test(&handle, &exotic_test_sid_check_0a, "sid_check_0a"); exotic_add_test(&handle, &exotic_test_sid_check_0b, "sid_check_0b"); exotic_add_test(&handle, &exotic_test_sid_alloc_1, "sid_alloc_1"); exotic_add_test(&handle, &exotic_test_sid_check_1a, "sid_check_1a"); exotic_add_test(&handle, &exotic_test_sid_check_1b, "sid_check_1b"); exotic_add_test(&handle, &exotic_test_sid_alloc_2, "sid_alloc_2"); exotic_add_test(&handle, &exotic_test_sid_check_2, "sid_check_2"); exotic_add_test(&handle, &exotic_test_sid_alloc_3, "sid_alloc_3"); exotic_add_test(&handle, &exotic_test_sid_check_3, "sid_check_3"); exotic_add_test(&handle, &exotic_test_sid_alloc_4, "sid_alloc_4"); exotic_add_test(&handle, &exotic_test_sid_check_4, "sid_check_4"); exotic_add_test(&handle, &exotic_test_sid_alloc_5, "sid_alloc_5"); exotic_add_test(&handle, &exotic_test_sid_check_6, "sid_check_6"); exotic_add_test(&handle, &exotic_test_sid_list_all_1, "sid_list_all_1"); exotic_add_test(&handle, &exotic_test_sid_remove_1, "sid_remove_1"); exotic_add_test(&handle, &exotic_test_sid_remove_2, "sid_remove_2"); exotic_add_test(&handle, &exotic_test_sid_remove_3, "sid_remove_3"); exotic_add_test(&handle, &exotic_test_sid_remove_4, "sid_remove_4"); exotic_add_test(&handle, &exotic_test_sid_destroy_pool, "sid_destroy_pool"); exotic_add_test(&handle, &exotic_test_hash_tiger_1, "hash_tiger_1"); exotic_add_test(&handle, &exotic_test_hash_tiger_2, "hash_tiger_2"); exotic_add_test(&handle, &exotic_test_hash_tiger_3, "hash_tiger_3"); exotic_add_test(&handle, &exotic_test_hash_tiger_4, "hash_tiger_4"); exotic_add_test(&handle, &exotic_test_hash_tiger_5, "hash_tiger_5"); exotic_add_test(&handle, &exotic_test_hash_tiger_6, "hash_tiger_6"); exotic_add_test(&handle, &exotic_test_hash_tiger_7, "hash_tiger_7"); exotic_add_test(&handle, &exotic_test_timer_setup, "timer_setup"); exotic_add_test(&handle, &exotic_test_timer_check_timeout_0, "timer_check_timeout_0"); exotic_add_test(&handle, &exotic_test_timer_add_event_1, "timer_add_event_1"); exotic_add_test(&handle, &exotic_test_timer_check_timeout_1, "timer_check_timeout_1"); exotic_add_test(&handle, &exotic_test_timer_remove_event_1, "timer_remove_event_1"); exotic_add_test(&handle, &exotic_test_timer_check_timeout_2, "timer_check_timeout_2"); exotic_add_test(&handle, &exotic_test_timer_remove_event_1_no_crash, "timer_remove_event_1_no_crash"); exotic_add_test(&handle, &exotic_test_timer_add_5_events_1, "timer_add_5_events_1"); exotic_add_test(&handle, &exotic_test_timer_check_5_events_1, "timer_check_5_events_1"); exotic_add_test(&handle, &exotic_test_timer_process_5_events_1, "timer_process_5_events_1"); exotic_add_test(&handle, &exotic_test_timer_shutdown, "timer_shutdown"); exotic_add_test(&handle, &exotic_test_tokenizer_basic_0, "tokenizer_basic_0"); exotic_add_test(&handle, &exotic_test_tokenizer_basic_1, "tokenizer_basic_1"); exotic_add_test(&handle, &exotic_test_tokenizer_basic_1a, "tokenizer_basic_1a"); exotic_add_test(&handle, &exotic_test_tokenizer_basic_1b, "tokenizer_basic_1b"); exotic_add_test(&handle, &exotic_test_tokenizer_basic_1c, "tokenizer_basic_1c"); exotic_add_test(&handle, &exotic_test_tokenizer_basic_1d, "tokenizer_basic_1d"); exotic_add_test(&handle, &exotic_test_tokenizer_basic_1e, "tokenizer_basic_1e"); exotic_add_test(&handle, &exotic_test_tokenizer_basic_2, "tokenizer_basic_2"); exotic_add_test(&handle, &exotic_test_tokenizer_basic_2a, "tokenizer_basic_2a"); exotic_add_test(&handle, &exotic_test_tokenizer_basic_3, "tokenizer_basic_3"); exotic_add_test(&handle, &exotic_test_tokenizer_basic_3a, "tokenizer_basic_3a"); exotic_add_test(&handle, &exotic_test_tokenizer_basic_3b, "tokenizer_basic_3b"); exotic_add_test(&handle, &exotic_test_tokenizer_basic_3c, "tokenizer_basic_3c"); exotic_add_test(&handle, &exotic_test_tokenizer_basic_3d, "tokenizer_basic_3d"); exotic_add_test(&handle, &exotic_test_tokenizer_basic_compare_0, "tokenizer_basic_compare_0"); exotic_add_test(&handle, &exotic_test_tokenizer_basic_compare_1, "tokenizer_basic_compare_1"); exotic_add_test(&handle, &exotic_test_tokenizer_basic_compare_2, "tokenizer_basic_compare_2"); exotic_add_test(&handle, &exotic_test_tokenizer_basic_compare_3, "tokenizer_basic_compare_3"); exotic_add_test(&handle, &exotic_test_tokenizer_basic_compare_4, "tokenizer_basic_compare_4"); exotic_add_test(&handle, &exotic_test_tokenizer_basic_compare_5, "tokenizer_basic_compare_5"); exotic_add_test(&handle, &exotic_test_tokenizer_basic_compare_6, "tokenizer_basic_compare_6"); exotic_add_test(&handle, &exotic_test_tokenizer_comment_1, "tokenizer_comment_1"); exotic_add_test(&handle, &exotic_test_tokenizer_comment_2, "tokenizer_comment_2"); exotic_add_test(&handle, &exotic_test_tokenizer_comment_3, "tokenizer_comment_3"); exotic_add_test(&handle, &exotic_test_tokenizer_escape_1, "tokenizer_escape_1"); exotic_add_test(&handle, &exotic_test_tokenizer_escape_2, "tokenizer_escape_2"); exotic_add_test(&handle, &exotic_test_tokenizer_escape_3, "tokenizer_escape_3"); exotic_add_test(&handle, &exotic_test_tokenizer_escape_4, "tokenizer_escape_4"); exotic_add_test(&handle, &exotic_test_tokenizer_escape_5, "tokenizer_escape_5"); exotic_add_test(&handle, &exotic_test_tokenizer_escape_6, "tokenizer_escape_6"); exotic_add_test(&handle, &exotic_test_tokenizer_escape_7, "tokenizer_escape_7"); exotic_add_test(&handle, &exotic_test_tokenizer_settings_1, "tokenizer_settings_1"); exotic_add_test(&handle, &exotic_test_tokenizer_settings_2, "tokenizer_settings_2"); exotic_add_test(&handle, &exotic_test_tokenizer_settings_3, "tokenizer_settings_3"); exotic_add_test(&handle, &exotic_test_tokenizer_settings_4, "tokenizer_settings_4"); exotic_add_test(&handle, &exotic_test_tokenizer_settings_5, "tokenizer_settings_5"); exotic_add_test(&handle, &exotic_test_tokenizer_settings_6, "tokenizer_settings_6"); exotic_add_test(&handle, &exotic_test_tokenizer_settings_7, "tokenizer_settings_7"); exotic_add_test(&handle, &exotic_test_tokenizer_settings_8, "tokenizer_settings_8"); exotic_add_test(&handle, &exotic_test_tokenizer_settings_9, "tokenizer_settings_9"); exotic_add_test(&handle, &exotic_test_um_init_1, "um_init_1"); exotic_add_test(&handle, &exotic_test_um_shutdown_1, "um_shutdown_1"); exotic_add_test(&handle, &exotic_test_um_shutdown_2, "um_shutdown_2"); exotic_add_test(&handle, &exotic_test_um_init_2, "um_init_2"); exotic_add_test(&handle, &exotic_test_um_add_1, "um_add_1"); exotic_add_test(&handle, &exotic_test_um_size_1, "um_size_1"); exotic_add_test(&handle, &exotic_test_um_remove_1, "um_remove_1"); exotic_add_test(&handle, &exotic_test_um_size_2, "um_size_2"); exotic_add_test(&handle, &exotic_test_um_add_2, "um_add_2"); exotic_add_test(&handle, &exotic_test_um_size_3, "um_size_3"); exotic_add_test(&handle, &exotic_test_um_remove_2, "um_remove_2"); exotic_add_test(&handle, &exotic_test_um_shutdown_4, "um_shutdown_4"); return exotic_run(&handle); } /* * Exotic - C/C++ source code testing * Copyright (c) 2007, Jan Vidar Krey */ #include #include #include #include static void exotic_version(); #ifndef __EXOTIC__STANDALONE__ #include "autotest.h" static void exotic_version() { printf("Extatic.org Test Infrastructure: exotic " "${version}" "\n\n"); printf("Copyright (C) 2007 Jan Vidar Krey, janvidar@extatic.org\n"); printf("This is free software with ABSOLUTELY NO WARRANTY.\n\n"); } #endif struct exo_test_data { exo_test_t test; char* name; struct exo_test_data* next; }; static void exotic_summary(struct exotic_handle* handle) { int total = handle->pass + handle->fail; int pass_rate = total ? (100*handle->pass / total) : 0; int fail_rate = total ? (100*handle->fail / total) : 0; printf("\n"); printf("--------------------------------------------\n"); printf("Results:\n"); printf(" * Total tests run: %8d\n", total); printf(" * Tests passed: %8d (~%d%%)\n", (int) handle->pass, pass_rate); printf(" * Tests failed: %8d (~%d%%)\n", (int) handle->fail, fail_rate); printf("--------------------------------------------\n"); } static void exotic_help(const char* program) { printf("Usage: %s [OPTIONS]\n\n", program); printf("Options:\n"); printf(" --help -h Show this message\n"); printf(" --version -v Show version\n"); printf(" --summary -s show only summary)\n"); printf(" --fail -f show only test failures\n"); printf(" --pass -p show only test passes\n"); printf("\nExamples:\n"); printf(" %s -s -f\n\n", program); } int exotic_initialize(struct exotic_handle* handle, int argc, char** argv) { int n; if (!handle || !argv) return -1; memset(handle, 0, sizeof(struct exotic_handle)); for (n = 1; n < argc; n++) { if (!strcmp(argv[n], "-h") || !strcmp(argv[n], "--help")) { exotic_help(argv[0]); exit(0); } if (!strcmp(argv[n], "-v") || !strcmp(argv[n], "--version")) { exotic_version(); exit(0); } if (!strcmp(argv[n], "-s") || !strcmp(argv[n], "--summary")) { handle->config_show_summary = cfg_on; continue; } if (!strcmp(argv[n], "-f") || !strcmp(argv[n], "--fail")) { handle->config_show_fail = cfg_on; continue; } if (!strcmp(argv[n], "-p") || !strcmp(argv[n], "--pass")) { handle->config_show_pass = cfg_on; continue; } fprintf(stderr, "Unknown argument: %s\n\n", argv[n]); exotic_help(argv[0]); exit(0); } if (handle->config_show_summary == cfg_on) { if (handle->config_show_pass == cfg_default) handle->config_show_pass = cfg_off; if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off; } else if (handle->config_show_pass == cfg_on) { if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_off; if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off; } else if (handle->config_show_fail == cfg_on) { if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_off; if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off; } else { if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_on; if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_on; if (handle->config_show_pass == cfg_default) handle->config_show_pass = cfg_on; } return 0; } void exotic_add_test(struct exotic_handle* handle, exo_test_t func, const char* name) { struct exo_test_data* test; if (!handle) { fprintf(stderr, "exotic_add_test: failed, no handle!\n"); exit(-1); } test = (struct exo_test_data*) malloc(sizeof(struct exo_test_data)); if (!test) { fprintf(stderr, "exotic_add_test: out of memory!\n"); exit(-1); } /* Create the test */ memset(test, 0, sizeof(struct exo_test_data)); test->test = func; test->name = strdup(name); /* Register the test in the handle */ if (!handle->first) { handle->first = test; handle->current = test; } else { handle->current->next = test; handle->current = test; } } int exotic_run(struct exotic_handle* handle) { struct exo_test_data* tmp = NULL; if (!handle) { fprintf(stderr, "Error: exotic is not initialized\n"); return -1; } handle->current = handle->first; while (handle->current) { tmp = handle->current; if (handle->current->test()) { if (handle->config_show_pass == cfg_on) printf("* PASS test '%s'\n", tmp->name); handle->pass++; } else { if (handle->config_show_fail == cfg_on) printf("* FAIL test '%s'\n", tmp->name); handle->fail++; } handle->current = handle->current->next; free(tmp->name); free(tmp); } if (!handle->first) { printf("(No tests added)\n"); } if (handle->config_show_summary == cfg_on) exotic_summary(handle); return (handle->fail) ? handle->fail : 0; } static void exotic_version() { printf("exotic 0.4-standalone\n\n"); printf("Copyright (C) 2007 Jan Vidar Krey, janvidar@extatic.org\n"); printf("This is free software with ABSOLUTELY NO WARRANTY.\n\n"); } modelrockettier-uhub-a8ee6e7/autotest/test_commands.tcc000066400000000000000000000200601324501300100235430ustar00rootroot00000000000000#include static struct hub_info* hub = NULL; static struct hub_command* cmd = NULL; static struct hub_user user; static struct command_base* cbase = NULL; static struct command_handle* c_test1 = NULL; static struct command_handle* c_test2 = NULL; static struct command_handle* c_test3 = NULL; static struct command_handle* c_test4 = NULL; static struct command_handle* c_test5 = NULL; static struct command_handle* c_test6 = NULL; static struct command_handle* c_test7 = NULL; // for results: static int result = 0; EXO_TEST(setup, { hub = hub_malloc_zero(sizeof(struct hub_info)); cbase = command_initialize(hub); hub->commands = cbase; hub->users = uman_init(); return cbase && hub && hub->users; }); static int test_handler(struct command_base* cbase, struct hub_user* user, struct hub_command* hcmd) { printf("test_handler\n"); result = 1; return 0; } static struct command_handle* create_handler(const char* prefix, const char* args, enum auth_credentials cred) { struct command_handle* c = hub_malloc_zero(sizeof(struct command_handle)); c->prefix = prefix; c->length = strlen(prefix); c->args = args; c->cred = cred; c->handler = test_handler; c->description = "A handler added by autotest."; c->origin = "exotic test"; c->ptr = &c->ptr; return c; } EXO_TEST(command_setup_user, { memset(&user, 0, sizeof(user)); user.id.sid = 1; strcpy(user.id.nick, "tester"); strcpy(user.id.cid, "3AGHMAASJA2RFNM22AA6753V7B7DYEPNTIWHBAY"); user.credentials = auth_cred_guest; return 1; }); #define ADD_TEST(var, prefix, args, cred) \ var = create_handler(prefix, args, cred); \ if (!command_add(cbase, var, NULL)) \ return 0; #define DEL_TEST(var) \ if (var) \ { \ if (!command_del(cbase, var)) \ return 0; \ hub_free(var); \ var = NULL; \ } EXO_TEST(command_create, { ADD_TEST(c_test1, "test1", "", auth_cred_guest); ADD_TEST(c_test2, "test2", "", auth_cred_operator); ADD_TEST(c_test3, "test3", "N?N?N", auth_cred_guest); ADD_TEST(c_test4, "test4", "u", auth_cred_guest); ADD_TEST(c_test5, "test5", "i", auth_cred_guest); ADD_TEST(c_test6, "test6", "?c", auth_cred_guest); ADD_TEST(c_test6, "test7", "C", auth_cred_guest); return 1; }); extern void command_destroy(struct hub_command* cmd); static int verify(const char* str, enum command_parse_status expected) { struct hub_command* cmd = command_parse(cbase, hub, &user, str); enum command_parse_status status = cmd->status; command_free(cmd); return status == expected; } static struct hub_command_arg_data* verify_argument(struct hub_command* cmd, enum hub_command_arg_type type) { return hub_command_arg_next(cmd, type); } static int verify_arg_integer(struct hub_command* cmd, int expected) { struct hub_command_arg_data* data = verify_argument(cmd, type_integer); return data->data.integer == expected; } static int verify_arg_user(struct hub_command* cmd, struct hub_user* expected) { struct hub_command_arg_data* data = verify_argument(cmd, type_user); return data->data.user == expected; } static int verify_arg_cred(struct hub_command* cmd, enum auth_credentials cred) { struct hub_command_arg_data* data = verify_argument(cmd, type_credentials); return data->data.credentials == cred; } EXO_TEST(command_access_1, { return verify("!test1", cmd_status_ok); }); EXO_TEST(command_access_2, { return verify("!test2", cmd_status_access_error); }); EXO_TEST(command_access_3, { user.credentials = auth_cred_operator; return verify("!test2", cmd_status_ok); }); EXO_TEST(command_syntax_1, { return verify("", cmd_status_syntax_error); }); EXO_TEST(command_syntax_2, { return verify("!", cmd_status_syntax_error); }); EXO_TEST(command_missing_args_1, { return verify("!test3", cmd_status_missing_args); }); EXO_TEST(command_missing_args_2, { return verify("!test3 12345", cmd_status_ok); }); EXO_TEST(command_missing_args_3, { return verify("!test3 1 2 345", cmd_status_ok); }); EXO_TEST(command_number_1, { return verify("!test3 abc", cmd_status_arg_number); }); EXO_TEST(command_number_2, { return verify("!test3 -", cmd_status_arg_number); }); EXO_TEST(command_number_3, { return verify("!test3 -12", cmd_status_ok); }); EXO_TEST(command_user_1, { return verify("!test4 tester", cmd_status_arg_nick); }); EXO_TEST(command_user_2, { return verify("!test5 3AGHMAASJA2RFNM22AA6753V7B7DYEPNTIWHBAY", cmd_status_arg_cid); }); EXO_TEST(command_user_3, { return uman_add(hub->users, &user) == 0; }); EXO_TEST(command_user_4, { return verify("!test4 tester", cmd_status_ok); }); EXO_TEST(command_user_5, { return verify("!test5 3AGHMAASJA2RFNM22AA6753V7B7DYEPNTIWHBAY", cmd_status_ok); }); EXO_TEST(command_command_1, { return verify("!test6 test1", cmd_status_ok); }); EXO_TEST(command_command_2, { return verify("!test6 test2", cmd_status_ok); }); EXO_TEST(command_command_3, { return verify("!test6 test3", cmd_status_ok); }); EXO_TEST(command_command_4, { return verify("!test6 test4", cmd_status_ok); }); EXO_TEST(command_command_5, { return verify("!test6 test5", cmd_status_ok); }); EXO_TEST(command_command_6, { return verify("!test6 test6", cmd_status_ok); }); EXO_TEST(command_command_7, { return verify("!test6 fail", cmd_status_arg_command); }); EXO_TEST(command_command_8, { return verify("!test6", cmd_status_ok); }); EXO_TEST(command_cred_1, { return verify("!test7 guest", cmd_status_ok); }); EXO_TEST(command_cred_2, { return verify("!test7 user", cmd_status_ok); }); EXO_TEST(command_cred_3, { return verify("!test7 operator", cmd_status_ok); }); EXO_TEST(command_cred_4, { return verify("!test7 super", cmd_status_ok); }); EXO_TEST(command_cred_5, { return verify("!test7 admin", cmd_status_ok); }); EXO_TEST(command_cred_6, { return verify("!test7 nobody", cmd_status_arg_cred); }); EXO_TEST(command_cred_7, { return verify("!test7 bot", cmd_status_ok); }); EXO_TEST(command_cred_8, { return verify("!test7 link", cmd_status_ok); }); #if 0 cmd_status_arg_cred, /** <<< "A credentials argument is not valid ('C')" */ }; #endif // command not found EXO_TEST(command_parse_3, { return verify("!fail", cmd_status_not_found); }); // built-in command EXO_TEST(command_parse_4, { return verify("!help", cmd_status_ok); }); #define SETUP_COMMAND(string) \ do { \ if (cmd) command_free(cmd); \ cmd = command_parse(cbase, hub, &user, string); \ } while(0) EXO_TEST(command_argument_integer_1, { SETUP_COMMAND("!test3"); return verify_argument(cmd, type_integer) == NULL; }); EXO_TEST(command_argument_integer_2, { SETUP_COMMAND("!test3 10 42"); return verify_arg_integer(cmd, 10) && verify_arg_integer(cmd, 42) && verify_argument(cmd, type_integer) == NULL; }); EXO_TEST(command_argument_integer_3, { SETUP_COMMAND("!test3 10 42 6784"); return verify_arg_integer(cmd, 10) && verify_arg_integer(cmd, 42) && verify_arg_integer(cmd, 6784); }); EXO_TEST(command_argument_user_1, { SETUP_COMMAND("!test4 tester"); return verify_arg_user(cmd, &user) ; }); EXO_TEST(command_argument_cid_1, { SETUP_COMMAND("!test5 3AGHMAASJA2RFNM22AA6753V7B7DYEPNTIWHBAY"); return verify_arg_user(cmd, &user) ; }); EXO_TEST(command_argument_cred_1, { SETUP_COMMAND("!test7 admin"); return verify_arg_cred(cmd, auth_cred_admin);; }); EXO_TEST(command_argument_cred_2, { SETUP_COMMAND("!test7 op"); return verify_arg_cred(cmd, auth_cred_operator);; }); EXO_TEST(command_argument_cred_3, { SETUP_COMMAND("!test7 operator"); return verify_arg_cred(cmd, auth_cred_operator); }); EXO_TEST(command_argument_cred_4, { SETUP_COMMAND("!test7 super"); return verify_arg_cred(cmd, auth_cred_super); }); EXO_TEST(command_argument_cred_5, { SETUP_COMMAND("!test7 guest"); return verify_arg_cred(cmd, auth_cred_guest); }); EXO_TEST(command_argument_cred_6, { SETUP_COMMAND("!test7 user"); return verify_arg_cred(cmd, auth_cred_user); }); #undef SETUP_COMMAND EXO_TEST(command_user_destroy, { return uman_remove(hub->users, &user) == 0; }); EXO_TEST(command_destroy, { command_free(cmd); cmd = NULL; DEL_TEST(c_test1); DEL_TEST(c_test2); DEL_TEST(c_test3); DEL_TEST(c_test4); DEL_TEST(c_test5); DEL_TEST(c_test6); DEL_TEST(c_test7); return 1; }); EXO_TEST(cleanup, { uman_shutdown(hub->users); command_shutdown(hub->commands); hub_free(hub); return 1; }); modelrockettier-uhub-a8ee6e7/autotest/test_credentials.tcc000066400000000000000000000034361324501300100242470ustar00rootroot00000000000000#include EXO_TEST(cred_to_string_1, { return !strcmp(auth_cred_to_string(auth_cred_none), "none"); }); EXO_TEST(cred_to_string_2, { return !strcmp(auth_cred_to_string(auth_cred_bot), "bot"); }); EXO_TEST(cred_to_string_3, { return !strcmp(auth_cred_to_string(auth_cred_guest), "guest"); }); EXO_TEST(cred_to_string_4, { return !strcmp(auth_cred_to_string(auth_cred_user), "user"); }); EXO_TEST(cred_to_string_5, { return !strcmp(auth_cred_to_string(auth_cred_operator), "operator"); }); EXO_TEST(cred_to_string_6, { return !strcmp(auth_cred_to_string(auth_cred_super), "super"); }); EXO_TEST(cred_to_string_7, { return !strcmp(auth_cred_to_string(auth_cred_link), "link"); }); EXO_TEST(cred_to_string_8, { return !strcmp(auth_cred_to_string(auth_cred_admin), "admin"); }); #define CRED_FROM_STRING(STR, EXPECT) enum auth_credentials cred; return auth_string_to_cred(STR, &cred) && cred == EXPECT; EXO_TEST(cred_from_string_1, { CRED_FROM_STRING("none", auth_cred_none); }); EXO_TEST(cred_from_string_2, { CRED_FROM_STRING("bot", auth_cred_bot); }); EXO_TEST(cred_from_string_3, { CRED_FROM_STRING("guest", auth_cred_guest); }); EXO_TEST(cred_from_string_4, { CRED_FROM_STRING("user", auth_cred_user); }); EXO_TEST(cred_from_string_5, { CRED_FROM_STRING("reg", auth_cred_user); }); EXO_TEST(cred_from_string_6, { CRED_FROM_STRING("operator", auth_cred_operator); }); EXO_TEST(cred_from_string_7, { CRED_FROM_STRING("op", auth_cred_operator); }); EXO_TEST(cred_from_string_8, { CRED_FROM_STRING("super", auth_cred_super); }); EXO_TEST(cred_from_string_9, { CRED_FROM_STRING("link", auth_cred_link); }); EXO_TEST(cred_from_string_10, { CRED_FROM_STRING("admin", auth_cred_admin); }); modelrockettier-uhub-a8ee6e7/autotest/test_eventqueue.tcc000066400000000000000000000032521324501300100241340ustar00rootroot00000000000000#include 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; }); modelrockettier-uhub-a8ee6e7/autotest/test_hub.tcc000066400000000000000000000023251324501300100225240ustar00rootroot00000000000000#include 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); g_config.server_port = 65111; 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); }); modelrockettier-uhub-a8ee6e7/autotest/test_inf.tcc000066400000000000000000000247511324501300100225310ustar00rootroot00000000000000#include #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() { net_initialize(); inf_hub = (struct hub_info*) hub_malloc_zero(sizeof(struct hub_info)); inf_hub->users = uman_init(); 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() { uman_shutdown(inf_hub->users); acl_shutdown(inf_hub->acl); free_config(inf_hub->config); hub_free(inf_hub->acl); hub_free(inf_hub->config); hub_free(inf_hub); net_destroy(); } static void inf_create_user() { if (inf_user) return; inf_user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user)); 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) \ do { \ 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; \ } while(0) 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"; int ok; char nick[10]; struct adc_message* msg; nick[0] = 0xf7; nick[1] = 0x80; nick[2] = 0x7f; nick[3] = 0x81; nick[4] = 0x98; nick[5] = 0x00; msg = adc_msg_parse_verify(inf_user, line, strlen(line)); adc_msg_add_named_argument(msg, "NI", nick); 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; }); modelrockettier-uhub-a8ee6e7/autotest/test_ipfilter.tcc000066400000000000000000001026721324501300100235720ustar00rootroot00000000000000#include 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, { struct ip_addr_encap addr; if (!ipv6) return 1; ip_convert_to_binary("2001::201:2ff:fefa:0", &addr); return ip_in_range(&addr, &ban6); }); EXO_TEST(check_ban_ipv6_2, { struct ip_addr_encap addr; if (!ipv6) return 1; ip_convert_to_binary("2001::201:2ff:fefa:1", &addr); return ip_in_range(&addr, &ban6); }); EXO_TEST(check_ban_ipv6_3, { struct ip_addr_encap addr; if (!ipv6) return 1; ip_convert_to_binary("2001::201:2ff:fefa:fffe", &addr); return ip_in_range(&addr, &ban6); }); EXO_TEST(check_ban_ipv6_4, { struct ip_addr_encap addr; if (!ipv6) return 1; ip_convert_to_binary("2001::201:2ff:fefa:ffff", &addr); return ip_in_range(&addr, &ban6); }); EXO_TEST(check_ban_ipv6_5, { struct ip_addr_encap addr; if (!ipv6) return 1; ip_convert_to_binary("2001::201:2ff:fefb:0", &addr); return !ip_in_range(&addr, &ban6); }); EXO_TEST(check_ban_ipv6_6, { struct ip_addr_encap addr; if (!ipv6) return 1; ip_convert_to_binary("2001::201:2ff:fef9:ffff", &addr); return !ip_in_range(&addr, &ban6); }); EXO_TEST(check_ban_afmix_1, { struct ip_addr_encap addr; if (!ipv6) return 1; 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; struct ip_range range2; memset(&range1, 0, sizeof(range1)); 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; }); modelrockettier-uhub-a8ee6e7/autotest/test_list.tcc000066400000000000000000000076741324501300100227350ustar00rootroot00000000000000#include static struct linked_list* list = NULL; static struct linked_list* list2 = NULL; static char A[2] = { 'A', 0 }; static char B[2] = { 'B', 0 }; static char C[2] = { 'C', 0 }; static char A2[2] = { 'a', 0 }; static char B2[2] = { 'b', 0 }; static char C2[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; }); static int g_remove_flag = 0; static void null_free_inc_flag(void* ptr) { (void) ptr; g_remove_flag++; } EXO_TEST(list_remove_first_1_1, { list_append(list, A); list_append(list, B); list_append(list, C); return list->size == 3; }); EXO_TEST(list_remove_first_1_2, { g_remove_flag = 0; list_remove_first(list, null_free_inc_flag); return list->size == 2 && g_remove_flag == 1; }); EXO_TEST(list_remove_first_1_3, { list_remove_first(list, NULL); return list->size == 1; }); EXO_TEST(list_remove_first_1_4, { list_remove_first(list, NULL); return list->size == 0; }); EXO_TEST(list_remove_first_1_5, { list_remove_first(list, NULL); return list->size == 0; }); EXO_TEST(list_append_list_1, { list_append(list, A); list_append(list, B); list_append(list, C); list2 = list_create(); list_append(list2, A2); list_append(list2, B2); list_append(list2, C2); return list->size == 3 && list2->size == 3; }); EXO_TEST(list_append_list_2, { list_append_list(list, list2); return list->size == 6 && list2->size == 0; }); EXO_TEST(list_append_list_3, { list_destroy(list2); return list_get_index(list, 0) == A && list_get_index(list, 1) == B && list_get_index(list, 2) == C && list_get_index(list, 3) == A2 && list_get_index(list, 4) == B2 && list_get_index(list, 5) == C2; }); EXO_TEST(list_clear_list_last, { list_clear(list, &null_free); return 1; }); EXO_TEST(list_destroy_1, { list_destroy(list); return 1; }); EXO_TEST(list_destroy_2, { list_destroy(0); return 1; }); modelrockettier-uhub-a8ee6e7/autotest/test_memory.tcc000066400000000000000000000012251324501300100232540ustar00rootroot00000000000000#include 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 == 1; }); EXO_TEST(test_message_refc_3, { adc_msg_incref(g_msg); return g_msg->references == 2; }); EXO_TEST(test_message_refc_4, { adc_msg_incref(g_msg); return g_msg->references == 3; }); EXO_TEST(test_message_refc_5, { adc_msg_free(g_msg); return g_msg->references == 2; }); EXO_TEST(test_message_refc_6, { adc_msg_free(g_msg); return g_msg->references == 1; }); EXO_TEST(test_message_refc_7, { adc_msg_free(g_msg); return 1; }); modelrockettier-uhub-a8ee6e7/autotest/test_message.tcc000066400000000000000000000366401324501300100234010ustar00rootroot00000000000000#include 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, { int ok; struct adc_message* msg = adc_msg_create(test_string1); adc_msg_add_argument(msg, "XXwtf?"); ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat XXwtf?\n") == 0; adc_msg_free(msg); return ok; }); EXO_TEST(adc_message_add_arg_2, { int ok; struct adc_message* msg = adc_msg_create(test_string1); adc_msg_add_named_argument(msg, "XX", "wtf?"); ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat XXwtf?\n") == 0; adc_msg_free(msg); return ok; }); EXO_TEST(adc_message_remove_arg_1, { int ok; struct adc_message* msg = adc_msg_create(test_string1); adc_msg_remove_named_argument(msg, "AA"); ok = strcmp(msg->cache, "IINF BBbar CCwhat\n") == 0; adc_msg_free(msg); return ok; }); EXO_TEST(adc_message_remove_arg_2, { int ok; struct adc_message* msg = adc_msg_create(test_string1); adc_msg_remove_named_argument(msg, "BB"); ok = strcmp(msg->cache, "IINF AAfoo CCwhat\n") == 0; adc_msg_free(msg); return ok; }); EXO_TEST(adc_message_remove_arg_3, { int ok; struct adc_message* msg = adc_msg_create(test_string1); adc_msg_remove_named_argument(msg, "CC"); 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 */ int ok; struct adc_message* msg = adc_msg_parse_verify(g_user, test_string3, strlen(test_string3)); adc_msg_remove_named_argument(msg, "AW"); 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, { int ok; struct adc_message* msg = adc_msg_create(test_string1); adc_msg_remove_named_argument(msg, "AA"); ok = strcmp(msg->cache, "IINF BBbar CCwhat\n") == 0; adc_msg_free(msg); return ok; }); EXO_TEST(adc_message_replace_arg_2, { int ok; struct adc_message* msg = adc_msg_create(test_string1); adc_msg_remove_named_argument(msg, "BB"); ok = strcmp(msg->cache, "IINF AAfoo CCwhat\n") == 0; adc_msg_free(msg); return ok; }); EXO_TEST(adc_message_replace_arg_3, { int ok; struct adc_message* msg = adc_msg_create(test_string1); adc_msg_remove_named_argument(msg, "CC"); ok = strcmp(msg->cache, "IINF AAfoo BBbar\n") == 0; adc_msg_free(msg); return ok; }); EXO_TEST(adc_message_get_arg_1, { int ok; struct adc_message* msg = adc_msg_create(test_string1); char* c = adc_msg_get_argument(msg, 0); ok = strcmp(c, "AAfoo") == 0; adc_msg_free(msg); hub_free(c); return ok; }); EXO_TEST(adc_message_get_arg_2, { int ok; struct adc_message* msg = adc_msg_create(test_string1); char* c = adc_msg_get_argument(msg, 1); 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, { int n; struct adc_message* msg = adc_msg_create(test_string1); adc_msg_add_argument(msg, "XXwtf?"); n = adc_msg_has_named_argument(msg, "XX"); adc_msg_free(msg); return n == 1; }); EXO_TEST(adc_message_has_named_arg_5, { int n; struct adc_message* msg = adc_msg_create(test_string1); adc_msg_add_argument(msg, "XXone"); adc_msg_add_argument(msg, "XXtwo"); n = adc_msg_has_named_argument(msg, "XX"); adc_msg_free(msg); return n == 2; }); EXO_TEST(adc_message_has_named_arg_6, { int n; 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"); 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, { int ok; struct adc_message* msg = adc_msg_create("IINF AAfoo BBbar CCwhat"); adc_msg_unterminate(msg); ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat") == 0; adc_msg_free(msg); return ok; }); EXO_TEST(adc_message_terminate_2, { int ok; struct adc_message* msg = adc_msg_create(test_string1); adc_msg_unterminate(msg); adc_msg_terminate(msg); ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat\n") == 0; adc_msg_free(msg); return ok; }); EXO_TEST(adc_message_terminate_3, { int ok; struct adc_message* msg = adc_msg_create(test_string1); adc_msg_unterminate(msg); adc_msg_terminate(msg); adc_msg_unterminate(msg); ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat") == 0; adc_msg_free(msg); return ok; }); EXO_TEST(adc_message_terminate_4, { int ok; struct adc_message* msg = adc_msg_create(test_string1); adc_msg_unterminate(msg); adc_msg_terminate(msg); adc_msg_terminate(msg); ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat\n") == 0; adc_msg_free(msg); return ok; }); EXO_TEST(adc_message_terminate_5, { int ok; struct adc_message* msg = adc_msg_create(test_string1); adc_msg_terminate(msg); adc_msg_terminate(msg); ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat\n") == 0; adc_msg_free(msg); return ok; }); EXO_TEST(adc_message_terminate_6, { int ok; struct adc_message* msg = adc_msg_create(test_string1); adc_msg_unterminate(msg); adc_msg_unterminate(msg); ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat") == 0; adc_msg_free(msg); return ok; }); EXO_TEST(adc_message_escape_1, { int ok; char* s = adc_msg_escape(test_string1); 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; }); modelrockettier-uhub-a8ee6e7/autotest/test_misc.tcc000066400000000000000000000264611324501300100227100ustar00rootroot00000000000000#include 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"); }); static const char test_utf_seq_1[] = { 0x65, 0x00 }; // valid static const char test_utf_seq_2[] = { 0xD8, 0x00 }; // invalid static const char test_utf_seq_3[] = { 0x24, 0x00 }; // valid static const char test_utf_seq_4[] = { 0xC2, 0x24, 0x00}; // invalid static const char test_utf_seq_5[] = { 0xC2, 0xA2, 0x00}; // valid static const char test_utf_seq_6[] = { 0xE2, 0x82, 0xAC, 0x00}; // valid static const char test_utf_seq_7[] = { 0xC2, 0x32, 0x00}; // invalid static const char test_utf_seq_8[] = { 0xE2, 0x82, 0x32, 0x00}; // invalid static const char test_utf_seq_9[] = { 0xE2, 0x32, 0x82, 0x00}; // invalid static const char test_utf_seq_10[] = { 0xF0, 0x9F, 0x98, 0x81, 0x00}; // valid EXO_TEST(utf8_valid_4, { return is_valid_utf8(test_utf_seq_1); }); EXO_TEST(utf8_valid_5, { return !is_valid_utf8(test_utf_seq_2); }); EXO_TEST(utf8_valid_6, { return is_valid_utf8(test_utf_seq_3); }); EXO_TEST(utf8_valid_7, { return !is_valid_utf8(test_utf_seq_4); }); EXO_TEST(utf8_valid_8, { return is_valid_utf8(test_utf_seq_5); }); EXO_TEST(utf8_valid_9, { return is_valid_utf8(test_utf_seq_6); }); EXO_TEST(utf8_valid_10, { return !is_valid_utf8(test_utf_seq_7); }); EXO_TEST(utf8_valid_11, { return !is_valid_utf8(test_utf_seq_8); }); EXO_TEST(utf8_valid_12, { return !is_valid_utf8(test_utf_seq_9); }); EXO_TEST(utf8_valid_13, { return is_valid_utf8(test_utf_seq_10); }); // Limits of utf-8 static const char test_utf_seq_11[] = { 0x7F, 0x00 }; // valid last 7-bit character static const char test_utf_seq_12[] = { 0x80, 0x00 }; // invalid truncated string static const char test_utf_seq_13[] = { 0xBF, 0x00 }; // invalid truncated string static const char test_utf_seq_14[] = { 0xC0, 0x80, 0x00 }; // invalid out of 2 bytes range static const char test_utf_seq_15[] = { 0xC1, 0x7F, 0x00 }; // invalid out of 2 bytes range static const char test_utf_seq_16[] = { 0xC2, 0x00 }; // invalid truncated string static const char test_utf_seq_17[] = { 0xC2, 0x80, 0x00 }; // valid static const char test_utf_seq_18[] = { 0xDF, 0xBF, 0x00 }; // valid static const char test_utf_seq_19[] = { 0xE0, 0x80, 0x80, 0x00 }; // invalid out of 3 bytes range static const char test_utf_seq_20[] = { 0xE0, 0x9F, 0xBF, 0x00 }; // invalid out of 3 bytes range static const char test_utf_seq_21[] = { 0xE0, 0x00 }; // invalid truncated string static const char test_utf_seq_22[] = { 0xE0, 0xA0, 0x00 }; // invalid truncated string static const char test_utf_seq_23[] = { 0xE0, 0xA0, 0x80, 0x00 }; // valid static const char test_utf_seq_24[] = { 0xEC, 0x9F, 0xBF, 0x00 }; // valid static const char test_utf_seq_25[] = { 0xED, 0xA0, 0x80, 0x00 }; // invalid surrogate static const char test_utf_seq_26[] = { 0xED, 0xBF, 0xBF, 0x00 }; // invalid surrogate static const char test_utf_seq_27[] = { 0xEF, 0x80, 0x80, 0x00 }; // valid static const char test_utf_seq_28[] = { 0xEF, 0xBF, 0xBF, 0x00 }; // valid static const char test_utf_seq_29[] = { 0xF0, 0x80, 0x80, 0x80, 0x00 }; // invalid out of 4 bytes range static const char test_utf_seq_30[] = { 0xF0, 0x8F, 0xBF, 0xBF, 0x00 }; // invalid out of 4 bytes range static const char test_utf_seq_31[] = { 0xF0, 0x00 }; // invalid truncated string static const char test_utf_seq_32[] = { 0xF0, 0x90, 0x00 }; // invalid truncated string static const char test_utf_seq_33[] = { 0xF0, 0x90, 0x80, 0x00 }; // invalid truncated string static const char test_utf_seq_34[] = { 0xF0, 0x90, 0x80, 0x80, 0x00 }; // valid static const char test_utf_seq_35[] = { 0xF4, 0x8F, 0xBF, 0xBF, 0x00 }; // valid static const char test_utf_seq_36[] = { 0xF4, 0x90, 0x80, 0x80, 0x00 }; // invalid out of 4 bytes range static const char test_utf_seq_37[] = { 0xFF, 0xBF, 0xBF, 0xBF, 0x00 }; // invalid out of 4 bytes range EXO_TEST(utf8_valid_14, { return is_valid_utf8(test_utf_seq_11); }); EXO_TEST(utf8_valid_15, { return !is_valid_utf8(test_utf_seq_12); }); EXO_TEST(utf8_valid_16, { return !is_valid_utf8(test_utf_seq_13); }); EXO_TEST(utf8_valid_17, { return !is_valid_utf8(test_utf_seq_14); }); EXO_TEST(utf8_valid_18, { return !is_valid_utf8(test_utf_seq_15); }); EXO_TEST(utf8_valid_19, { return !is_valid_utf8(test_utf_seq_16); }); EXO_TEST(utf8_valid_20, { return is_valid_utf8(test_utf_seq_17); }); EXO_TEST(utf8_valid_21, { return is_valid_utf8(test_utf_seq_18); }); EXO_TEST(utf8_valid_22, { return !is_valid_utf8(test_utf_seq_19); }); EXO_TEST(utf8_valid_23, { return !is_valid_utf8(test_utf_seq_20); }); EXO_TEST(utf8_valid_24, { return !is_valid_utf8(test_utf_seq_21); }); EXO_TEST(utf8_valid_25, { return !is_valid_utf8(test_utf_seq_22); }); EXO_TEST(utf8_valid_26, { return is_valid_utf8(test_utf_seq_23); }); EXO_TEST(utf8_valid_27, { return is_valid_utf8(test_utf_seq_24); }); EXO_TEST(utf8_valid_28, { return !is_valid_utf8(test_utf_seq_25); }); EXO_TEST(utf8_valid_29, { return !is_valid_utf8(test_utf_seq_26); }); EXO_TEST(utf8_valid_30, { return is_valid_utf8(test_utf_seq_27); }); EXO_TEST(utf8_valid_31, { return is_valid_utf8(test_utf_seq_28); }); EXO_TEST(utf8_valid_32, { return !is_valid_utf8(test_utf_seq_29); }); EXO_TEST(utf8_valid_33, { return !is_valid_utf8(test_utf_seq_30); }); EXO_TEST(utf8_valid_34, { return !is_valid_utf8(test_utf_seq_31); }); EXO_TEST(utf8_valid_35, { return !is_valid_utf8(test_utf_seq_32); }); EXO_TEST(utf8_valid_36, { return !is_valid_utf8(test_utf_seq_33); }); EXO_TEST(utf8_valid_37, { return is_valid_utf8(test_utf_seq_34); }); EXO_TEST(utf8_valid_38, { return is_valid_utf8(test_utf_seq_35); }); EXO_TEST(utf8_valid_39, { return !is_valid_utf8(test_utf_seq_36); }); EXO_TEST(utf8_valid_40, { return !is_valid_utf8(test_utf_seq_37); }); modelrockettier-uhub-a8ee6e7/autotest/test_rbtree.tcc000066400000000000000000000065201324501300100232320ustar00rootroot00000000000000#include #include #define MAX_NODES 10000 static struct rb_tree* tree = NULL; int test_tree_compare(const void* a, const void* b) { return strcmp((const char*) a, (const char*) b); } EXO_TEST(rbtree_create_destroy, { int ok = 0; struct rb_tree* atree; atree = rb_tree_create(test_tree_compare, &hub_malloc, &hub_free); if (atree) ok = 1; rb_tree_destroy(atree); return ok; }); EXO_TEST(rbtree_create_1, { tree = rb_tree_create(test_tree_compare, &hub_malloc, &hub_free); return tree != NULL; }); EXO_TEST(rbtree_size_0, { return rb_tree_size(tree) == 0; }); EXO_TEST(rbtree_insert_1, { return rb_tree_insert(tree, "one", "1"); }); EXO_TEST(rbtree_insert_2, { return rb_tree_insert(tree, "two", "2"); }); EXO_TEST(rbtree_insert_3, { return rb_tree_insert(tree, "three", "3"); }); EXO_TEST(rbtree_insert_3_again, { return !rb_tree_insert(tree, "three", "3-again"); }); EXO_TEST(rbtree_size_1, { return rb_tree_size(tree) == 3; }); static int test_check_search(const char* key, const char* expect) { const char* value = (const char*) rb_tree_get(tree, key); if (!value) return !expect; if (!expect) return 0; return strcmp(value, expect) == 0; } EXO_TEST(rbtree_search_1, { return test_check_search("one", "1"); }); EXO_TEST(rbtree_search_2, { return test_check_search("two", "2"); }); EXO_TEST(rbtree_search_3, { return test_check_search("three", "3"); }); EXO_TEST(rbtree_search_4, { return test_check_search("four", NULL); }); EXO_TEST(rbtree_remove_1, { return rb_tree_remove(tree, "one"); }); EXO_TEST(rbtree_size_2, { return rb_tree_size(tree) == 2; }); EXO_TEST(rbtree_remove_2, { return rb_tree_remove(tree, "two"); }); EXO_TEST(rbtree_remove_3, { return rb_tree_remove(tree, "three"); }); EXO_TEST(rbtree_remove_3_again, { return !rb_tree_remove(tree, "three"); }); EXO_TEST(rbtree_search_5, { return test_check_search("one", NULL); }); EXO_TEST(rbtree_search_6, { return test_check_search("two", NULL); }); EXO_TEST(rbtree_search_7, { return test_check_search("three", NULL); }); EXO_TEST(rbtree_search_8, { return test_check_search("four", NULL); }); EXO_TEST(rbtree_size_3, { return rb_tree_size(tree) == 0; }); EXO_TEST(rbtree_insert_10000, { int i; for (i = 0; i < MAX_NODES; i++) { const char* key = strdup(uhub_itoa(i)); const char* val = strdup(uhub_itoa(i + 16384)); if (!rb_tree_insert(tree, key, val)) return 0; } return 1; }); EXO_TEST(rbtree_size_4, { return rb_tree_size(tree) == MAX_NODES; }); EXO_TEST(rbtree_check_10000, { int i; for (i = 0; i < MAX_NODES; i++) { char* key = strdup(uhub_itoa(i)); const char* expect = uhub_itoa(i + 16384); if (!test_check_search(key, expect)) return 0; hub_free(key); } return 1; }); EXO_TEST(rbtree_iterate_10000, { int i = 0; struct rb_node* n = (struct rb_node*) rb_tree_first(tree); while (n) { n = (struct rb_node*) rb_tree_next(tree); i++; } return i == MAX_NODES; }); static int freed_nodes = 0; static void free_node(struct rb_node* n) { hub_free((void*) n->key); hub_free((void*) n->value); freed_nodes += 1; } EXO_TEST(rbtree_remove_10000, { int i; int j; for (j = 0; j < 2; j++) { for (i = j; i < MAX_NODES; i += 2) { const char* key = uhub_itoa(i); rb_tree_remove_node(tree, key, &free_node); } } return freed_nodes == MAX_NODES; }); EXO_TEST(rbtree_destroy_1, { rb_tree_destroy(tree); return 1; }); modelrockettier-uhub-a8ee6e7/autotest/test_sid.tcc000066400000000000000000000060061324501300100225250ustar00rootroot00000000000000#include static struct sid_pool* sid_pool = 0; struct dummy_user { sid_t sid; }; static struct dummy_user* last = 0; sid_t last_sid = 0; EXO_TEST(sid_create_pool, { sid_pool = sid_pool_create(4); return sid_pool != 0; }); EXO_TEST(sid_check_0a, { struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, 0); return user == 0; }); EXO_TEST(sid_check_0b, { struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, 5); return user == 0; }); EXO_TEST(sid_alloc_1, { struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user)); user->sid = sid_alloc(sid_pool, (struct hub_user*) user); last = user; last_sid = user->sid; return (user->sid > 0 && user->sid < 1048576); }); EXO_TEST(sid_check_1a, { struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid); return last == user; }); EXO_TEST(sid_check_1b, { struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid+1); return user == 0; }); EXO_TEST(sid_alloc_2, { struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user)); user->sid = sid_alloc(sid_pool, (struct hub_user*) user); last_sid = user->sid; return (user->sid > 0 && user->sid < 1048576); }); EXO_TEST(sid_check_2, { struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid); return last != user; }); EXO_TEST(sid_alloc_3, { struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user)); user->sid = sid_alloc(sid_pool, (struct hub_user*) user); last_sid = user->sid; return (user->sid > 0 && user->sid < 1048576); }); EXO_TEST(sid_check_3, { struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid); return last != user; }); EXO_TEST(sid_alloc_4, { struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user)); user->sid = sid_alloc(sid_pool, (struct hub_user*) user); last_sid = user->sid; return (user->sid > 0 && user->sid < 1048576); }); EXO_TEST(sid_check_4, { struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid); return last != user; }); EXO_TEST(sid_alloc_5, { struct dummy_user user; sid_t sid; sid = sid_alloc(sid_pool, (struct hub_user*) &user); return sid == 0; }); EXO_TEST(sid_check_6, { struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, 0); return user == 0; }); EXO_TEST(sid_list_all_1, { sid_t s; size_t n = 0; int ok = 1; for (s = last->sid; s <= last_sid; s++) { struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, s); if (s != (user ? user->sid : -1)) { ok = 0; break; } n++; } return ok && n == 4; }); #define FREE_SID(N) \ struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, N); \ sid_free(sid_pool, N); \ hub_free(user); \ return sid_lookup(sid_pool, N) == NULL; EXO_TEST(sid_remove_1, { FREE_SID(2); }); EXO_TEST(sid_remove_2, { FREE_SID(1); }); EXO_TEST(sid_remove_3, { FREE_SID(4); }); EXO_TEST(sid_remove_4, { FREE_SID(3); }); EXO_TEST(sid_destroy_pool, { sid_pool_destroy(sid_pool); sid_pool = 0; return sid_pool == 0; }); modelrockettier-uhub-a8ee6e7/autotest/test_tiger.tcc000066400000000000000000000033721324501300100230630ustar00rootroot00000000000000#include #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"); }); modelrockettier-uhub-a8ee6e7/autotest/test_timer.tcc000066400000000000000000000060051324501300100230650ustar00rootroot00000000000000#include #define MAX_EVENTS 15 static struct timeout_queue* g_queue; static time_t g_now; static size_t g_max; static struct timeout_evt g_events[MAX_EVENTS]; static size_t g_triggered; static void timeout_cb(struct timeout_evt* t) { g_triggered++; } /* typedef void (*timeout_evt_cb)(struct timeout_evt*); struct timeout_evt { time_t timestamp; timeout_evt_cb callback; void* ptr; struct timeout_evt* prev; struct timeout_evt* next; }; 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*); struct timeout_queue { time_t last; size_t max; struct timeout_evt** events; }; void timeout_queue_initialize(struct timeout_queue*, time_t now, size_t max); void timeout_queue_shutdown(struct timeout_queue*); size_t timeout_queue_process(struct timeout_queue*, time_t now); void timeout_queue_insert(struct timeout_queue*, struct timeout_evt*, size_t seconds); void timeout_queue_remove(struct timeout_queue*, struct timeout_evt*); void timeout_queue_reschedule(struct timeout_queue*, struct timeout_evt*, size_t seconds); size_t timeout_queue_get_next_timeout(struct timeout_queue*, time_t now); */ EXO_TEST(timer_setup,{ size_t n; g_queue = hub_malloc_zero(sizeof(struct timeout_queue)); g_now = 0; g_max = 5; g_triggered = 0; timeout_queue_initialize(g_queue, g_now, g_max); memset(g_events, 0, sizeof(g_events)); for (n = 0; n < MAX_EVENTS; n++) { timeout_evt_initialize(&g_events[n], timeout_cb, &g_events[n]); } return g_queue != NULL; }); EXO_TEST(timer_check_timeout_0,{ return timeout_queue_get_next_timeout(g_queue, g_now) == g_max; }); EXO_TEST(timer_add_event_1,{ timeout_queue_insert(g_queue, &g_events[0], 2); return g_events[0].prev != NULL; }); EXO_TEST(timer_check_timeout_1,{ return timeout_queue_get_next_timeout(g_queue, g_now) == 2; }); EXO_TEST(timer_remove_event_1,{ timeout_queue_remove(g_queue, &g_events[0]); return g_events[0].prev == NULL; }); EXO_TEST(timer_check_timeout_2,{ return timeout_queue_get_next_timeout(g_queue, g_now) == g_max; }); /* test re-removing an event - should not crash! */ EXO_TEST(timer_remove_event_1_no_crash,{ timeout_queue_remove(g_queue, &g_events[0]); return g_events[0].prev == NULL; }); EXO_TEST(timer_add_5_events_1,{ timeout_queue_insert(g_queue, &g_events[0], 0); timeout_queue_insert(g_queue, &g_events[1], 1); timeout_queue_insert(g_queue, &g_events[2], 2); timeout_queue_insert(g_queue, &g_events[3], 3); timeout_queue_insert(g_queue, &g_events[4], 4); return (g_events[0].prev != NULL && g_events[1].prev != NULL && g_events[2].prev != NULL && g_events[3].prev != NULL && g_events[4].prev != NULL); }); EXO_TEST(timer_check_5_events_1,{ return timeout_queue_get_next_timeout(g_queue, g_now) == 1; }); EXO_TEST(timer_process_5_events_1,{ g_now = 4; return timeout_queue_process(g_queue, g_now) == g_triggered; }); EXO_TEST(timer_shutdown,{ timeout_queue_shutdown(g_queue); hub_free(g_queue); return 1; }); modelrockettier-uhub-a8ee6e7/autotest/test_tokenizer.tcc000066400000000000000000000113221324501300100237550ustar00rootroot00000000000000#include #define SETUP(X, STR) struct cfg_tokens* tokens = cfg_tokenize(STR) #define CLEANUP_LIST(X) do { list_clear(X, hub_free); list_destroy(X); } while(0) #define CLEANUP_TOKENS(X) do { cfg_tokens_free(X); } while(0) static int match_str(const char* str1, char* str2) { size_t i; int ret; for (i = 0; i < strlen(str2); i++) if (str2[i] == '_') str2[i] = ' '; else if (str2[i] == '|') str2[i] = '\t'; ret = strcmp(str1, str2); if (ret) { fprintf(stderr, "\n Mismatch: \"%s\" != \"%s\"\n", str1, str2); } return ret; } static int count(const char* STR, size_t EXPECT) { SETUP(tokens, STR); int pass = cfg_token_count(tokens) == EXPECT; CLEANUP_TOKENS(tokens); return pass; } static int compare(const char* str, const char* ref) { size_t i, max; int pass; struct linked_list* compare = list_create(); SETUP(tokens, str); split_string(ref, " ", compare, 0); pass = cfg_token_count(tokens) == list_size(compare); if (pass) { max = cfg_token_count(tokens); for (i = 0; i < max; i++) { char* token = (char*) cfg_token_get(tokens, i); char* refer = (char*) list_get_index(compare, i); if (match_str(token, refer)) { pass = 0; break; } } } CLEANUP_TOKENS(tokens); CLEANUP_LIST(compare); return pass; } EXO_TEST(tokenizer_basic_0, { return count("", 0); }); EXO_TEST(tokenizer_basic_1, { return count("a", 1); }); EXO_TEST(tokenizer_basic_1a, { return count(" a", 1); }) EXO_TEST(tokenizer_basic_1b, { return count("\ta", 1); }) EXO_TEST(tokenizer_basic_1c, { return count(" a", 1); }) EXO_TEST(tokenizer_basic_1d, { return count(" a ", 1); }) EXO_TEST(tokenizer_basic_1e, { return count(" a ", 1); }) EXO_TEST(tokenizer_basic_2, { return count("a b", 2); }); EXO_TEST(tokenizer_basic_2a, { return count(" a b ", 2); }); EXO_TEST(tokenizer_basic_3, { return count("a b c", 3); }); EXO_TEST(tokenizer_basic_3a, { return count("a b c", 3); }); EXO_TEST(tokenizer_basic_3b, { return count("a b\tc", 3); }); EXO_TEST(tokenizer_basic_3c, { return count("a b c ", 3); }); EXO_TEST(tokenizer_basic_3d, { return count("a b c ", 3); }); EXO_TEST(tokenizer_basic_compare_0, { return compare("value1 value2 value3", "value1 value2 value3"); }); EXO_TEST(tokenizer_basic_compare_1, { return compare("a b c", "a b c"); }); EXO_TEST(tokenizer_basic_compare_2, { return compare("a b c", "a b c"); }); EXO_TEST(tokenizer_basic_compare_3, { return compare(" a b c", "a b c"); }); EXO_TEST(tokenizer_basic_compare_4, { return compare(" a b c ", "a b c"); }); EXO_TEST(tokenizer_basic_compare_5, { return compare("a b c ", "a b c"); }); EXO_TEST(tokenizer_basic_compare_6, { return compare("a b c ", "a b c"); }); EXO_TEST(tokenizer_comment_1, { return compare("value1 value2 # value3", "value1 value2"); }); EXO_TEST(tokenizer_comment_2, { return compare("value1 value2\\# value3", "value1 value2# value3"); }); EXO_TEST(tokenizer_comment_3, { return compare("value1 \"value2#\" value3", "value1 value2# value3"); }); EXO_TEST(tokenizer_escape_1, { return compare("\"value1\" value2", "value1 value2"); }); EXO_TEST(tokenizer_escape_2, { return compare("\"value1\\\"\" value2", "value1\" value2"); }); EXO_TEST(tokenizer_escape_3, { return compare("\"value1\" \"value 2\"", "value1 value_2"); }); EXO_TEST(tokenizer_escape_4, { return compare("\"value1\" value\\ 2", "value1 value_2"); }); EXO_TEST(tokenizer_escape_5, { return compare("\"value1\" value\\\\2", "value1 value\\2"); }); EXO_TEST(tokenizer_escape_6, { return compare("\"value1\" value\\\t2", "value1 value|2"); }); EXO_TEST(tokenizer_escape_7, { return compare("\"value1\" \"value\t2\"", "value1 value|2"); }); static int test_setting(const char* str, const char* expected_key, const char* expected_value) { int success = 0; struct cfg_settings* setting = cfg_settings_split(str); if (!setting) return expected_key == NULL; success = (!strcmp(cfg_settings_get_key(setting), expected_key) && !strcmp(cfg_settings_get_value(setting), expected_value)); cfg_settings_free(setting); return success; } EXO_TEST(tokenizer_settings_1, { return test_setting("foo=bar", "foo", "bar"); }); EXO_TEST(tokenizer_settings_2, { return test_setting("foo =bar", "foo", "bar"); }); EXO_TEST(tokenizer_settings_3, { return test_setting("foo= bar", "foo", "bar"); }); EXO_TEST(tokenizer_settings_4, { return test_setting("\tfoo=bar", "foo", "bar"); }); EXO_TEST(tokenizer_settings_5, { return test_setting("foo=bar\t", "foo", "bar"); }); EXO_TEST(tokenizer_settings_6, { return test_setting("\tfoo=bar\t", "foo", "bar"); }); EXO_TEST(tokenizer_settings_7, { return test_setting("\tfoo\t=\tbar\t", "foo", "bar"); }); EXO_TEST(tokenizer_settings_8, { return test_setting("foo=", "foo", ""); }); EXO_TEST(tokenizer_settings_9, { return test_setting("=bar", NULL, ""); }); modelrockettier-uhub-a8ee6e7/autotest/test_usermanager.tcc000066400000000000000000000022501324501300100242540ustar00rootroot00000000000000#include #define MAX_USERS 64 static struct hub_user_manager* uman = 0; static struct hub_user um_user[MAX_USERS]; EXO_TEST(um_init_1, { sid_t s; uman = uman_init(); for (s = 0; s < MAX_USERS; s++) { memset(&um_user[s], 0, sizeof(struct hub_user)); um_user[s].id.sid = s; } return !!uman; }); EXO_TEST(um_shutdown_1, { return uman_shutdown(0) == -1; }); EXO_TEST(um_shutdown_2, { return uman_shutdown(uman) == 0; }); EXO_TEST(um_init_2, { uman = uman_init(); return !!uman; }); EXO_TEST(um_add_1, { return uman_add(uman, &um_user[0]) == 0; }); EXO_TEST(um_size_1, { return uman->count == 1; }); EXO_TEST(um_remove_1, { return uman_remove(uman, &um_user[0]) == 0; }); EXO_TEST(um_size_2, { return uman->count == 0; }); EXO_TEST(um_add_2, { int i; for (i = 0; i < MAX_USERS; i++) { if (uman_add(uman, &um_user[i]) != 0) return 0; } return 1; }); EXO_TEST(um_size_3, { return uman->count == MAX_USERS; }); EXO_TEST(um_remove_2, { int i; for (i = 0; i < MAX_USERS; i++) { if (uman_remove(uman, &um_user[i]) != 0) return 0; } return 1; }); /* Last test */ EXO_TEST(um_shutdown_4, { return uman_shutdown(uman) == 0; }); modelrockettier-uhub-a8ee6e7/autotest/travis/000077500000000000000000000000001324501300100215225ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/autotest/travis/build-and-test.sh000077500000000000000000000015621324501300100247010ustar00rootroot00000000000000#!/bin/sh set -x set -e export CFLAGS="$(dpkg-buildflags --get CFLAGS) $(dpkg-buildflags --get CPPFLAGS)" export LDFLAGS="$(dpkg-buildflags --get LDFLAGS) -Wl,--as-needed" mkdir -p builddir cd builddir CMAKEOPTS=".. -DCMAKE_INSTALL_PREFIX=/usr" if [ "${CONFIG}" = "full" ]; then CMAKEOPTS="${CMAKEOPTS} -DRELEASE=OFF -DLOWLEVEL_DEBUG=ON -DSSL_SUPPORT=ON -DUSE_OPENSSL=ON -DADC_STRESS=ON" else CMAKEOPTS="${CMAKEOPTS} -DRELEASE=ON -DLOWLEVEL_DEBUG=OFF -DSSL_SUPPORT=OFF -DADC_STRESS=OFF" fi cmake ${CMAKEOPTS} \ -DCMAKE_C_FLAGS="${CFLAGS}" \ -DCMAKE_EXE_LINKER_FLAGS="${LDFLAGS}" make VERBOSE=1 make VERBOSE=1 autotest-bin ./autotest-bin sudo make install du -shc /etc/uhub/ /usr/bin/uhub* /usr/lib/uhub/ modelrockettier-uhub-a8ee6e7/autotest/travis/install-build-depends.sh000077500000000000000000000002411324501300100262410ustar00rootroot00000000000000#!/bin/sh sudo apt-get update -qq sudo apt-get install -qq cmake if [ "${CONFIG}" = "full" ]; then sudo apt-get install -qq libsqlite3-dev libssl-dev fi modelrockettier-uhub-a8ee6e7/autotest/update.sh000077500000000000000000000000441324501300100220310ustar00rootroot00000000000000#!/bin/sh ./exotic *.tcc > test.c modelrockettier-uhub-a8ee6e7/cmake/000077500000000000000000000000001324501300100174225ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/cmake/Modules/000077500000000000000000000000001324501300100210325ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/cmake/Modules/FindSqlite3.cmake000066400000000000000000000047371324501300100241740ustar00rootroot00000000000000# - Try to find sqlite3 # Find sqlite3 headers, libraries and the answer to all questions. # # SQLITE3_FOUND True if sqlite3 got found # SQLITE3_INCLUDEDIR Location of sqlite3 headers # SQLITE3_LIBRARIES List of libaries to use sqlite3 # SQLITE3_DEFINITIONS Definitions to compile sqlite3 # # Copyright (c) 2007 Juha Tuomala # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007 Alban Browaeys # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about sqlite3.pc settings IF ( Sqlite3_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( Sqlite3_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( Sqlite3_FIND_REQUIRED ) IF ( SQLITE3_MIN_VERSION ) PKG_SEARCH_MODULE( SQLITE3 ${_pkgconfig_REQUIRED} sqlite3>=${SQLITE3_MIN_VERSION} ) ELSE ( SQLITE3_MIN_VERSION ) pkg_search_module( SQLITE3 ${_pkgconfig_REQUIRED} sqlite3 ) ENDIF ( SQLITE3_MIN_VERSION ) # Look for sqlite3 include dir and libraries w/o pkgconfig IF ( NOT SQLITE3_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( _sqlite3_include_DIR sqlite3.h PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) FIND_LIBRARY( _sqlite3_link_DIR sqlite3 PATHS /opt/local/lib /sw/lib /usr/lib /usr/lib/${CMAKE_LIBRARY_ARCHITECTURE} /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) IF ( _sqlite3_include_DIR AND _sqlite3_link_DIR ) SET ( _sqlite3_FOUND TRUE ) ENDIF ( _sqlite3_include_DIR AND _sqlite3_link_DIR ) IF ( _sqlite3_FOUND ) SET ( SQLITE3_INCLUDE_DIRS ${_sqlite3_include_DIR} ) SET ( SQLITE3_LIBRARIES ${_sqlite3_link_DIR} ) ENDIF ( _sqlite3_FOUND ) # Report results IF ( SQLITE3_LIBRARIES AND SQLITE3_INCLUDE_DIRS AND _sqlite3_FOUND ) SET( SQLITE3_FOUND 1 ) MESSAGE( STATUS "Found sqlite3: ${SQLITE3_LIBRARIES} ${SQLITE3_INCLUDE_DIRS}" ) ELSE ( SQLITE3_LIBRARIES AND SQLITE3_INCLUDE_DIRS AND _sqlite3_FOUND ) IF ( Sqlite3_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find sqlite3" ) ELSE ( Sqlite3_FIND_REQUIRED ) MESSAGE( STATUS "Could NOT find sqlite3" ) ENDIF ( Sqlite3_FIND_REQUIRED ) ENDIF ( SQLITE3_LIBRARIES AND SQLITE3_INCLUDE_DIRS AND _sqlite3_FOUND ) ENDIF ( NOT SQLITE3_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( SQLITE3_LIBRARIES SQLITE3_INCLUDE_DIRS ) modelrockettier-uhub-a8ee6e7/debian/000077500000000000000000000000001324501300100175645ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/debian/changelog000066400000000000000000000011211324501300100214310ustar00rootroot00000000000000uhub (0.3.2-1) unstable; urgency=low * Updated upstream version. -- Jan Vidar Krey Mon, 30 May 2010 18:00:00 +0200 uhub (0.3.1-1) unstable; urgency=low * Updated version number. -- Jan Vidar Krey Mon, 04 Apr 2010 16:44:21 +0200 uhub (0.3.0-2) unstable; urgency=low * Fixed init.d scripts. * Fixed lintian warnings. -- Jan Vidar Krey Tue, 26 Jan 2010 19:02:02 +0100 uhub (0.3.0-1) unstable; urgency=low * Initial Release. -- Jan Vidar Krey Tue, 26 Jan 2010 18:59:02 +0100 modelrockettier-uhub-a8ee6e7/debian/compat000066400000000000000000000000021324501300100207620ustar00rootroot000000000000007 modelrockettier-uhub-a8ee6e7/debian/control000066400000000000000000000012521324501300100211670ustar00rootroot00000000000000Source: uhub Section: net Priority: optional Maintainer: Jan Vidar Krey Build-Depends: debhelper (>= 7.0.0) Standards-Version: 3.8.3.0 Package: uhub Architecture: any Depends: ${shlibs:Depends} Description: High performance ADC p2p hub 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. . Key features: - High performance and low memory usage - IPv4 and IPv6 support - Experimental SSL support (optional) - Advanced access control support - Easy configuration . Homepage: http://www.uhub.org/ modelrockettier-uhub-a8ee6e7/debian/copyright000066400000000000000000000015101324501300100215140ustar00rootroot00000000000000uhub - High performance ADC p2p hub. Copyright (C) 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 . On Debian GNU/Linux systems, the complete text of the GNU General Public License can be found in `/usr/share/common-licenses/GPL'. modelrockettier-uhub-a8ee6e7/debian/rules000077500000000000000000000013151324501300100206440ustar00rootroot00000000000000#!/usr/bin/make -f # export DH_VERBOSE=1 makeopts := DESTDIR=$(shell pwd)/debian/uhub/ \ UHUB_PREFIX=$(shell pwd)/debian/uhub/usr \ RELEASE=YES SILENT=YES build: build-stamp build-stamp: dh_testdir make $(makeopts) touch build-stamp clean: dh_testdir dh_testroot rm -f build-stamp make clean dh_clean binary-indep: build binary-arch: build dh_testdir dh_testroot dh_prep dh_installdirs $(MAKE) install $(makeopts) dh_installdocs dh_installinit dh_installlogrotate dh_installman -A dh_installchangelogs ChangeLog dh_strip dh_compress dh_installdeb dh_shlibdeps dh_gencontrol dh_md5sums dh_builddeb binary: binary-indep binary-arch .PHONY: build clean binary-indep binary-arch binary modelrockettier-uhub-a8ee6e7/debian/uhub.default000066400000000000000000000000631324501300100220740ustar00rootroot00000000000000# uhub - high performance adc hub. UHUB_ENABLE=0 modelrockettier-uhub-a8ee6e7/debian/uhub.dirs000066400000000000000000000001051324501300100214060ustar00rootroot00000000000000etc/default etc/init.d etc/logrotate.d etc/uhub usr/bin var/log/uhub modelrockettier-uhub-a8ee6e7/debian/uhub.docs000066400000000000000000000000541324501300100214000ustar00rootroot00000000000000AUTHORS README BUGS TODO doc/getstarted.txt modelrockettier-uhub-a8ee6e7/debian/uhub.init000066400000000000000000000035721324501300100214230ustar00rootroot00000000000000#!/bin/sh ### BEGIN INIT INFO # Provides: uhub # Required-Start: $remote_fs $network # Required-Stop: $remote_fs $network # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Start daemon at boot time # Description: Enable service provided by daemon. ### END INIT INFO PATH=/sbin:/bin:/usr/sbin:/usr/bin NAME=uhub DESC="ADC hub" DAEMON=/usr/bin/uhub PIDFILE=/var/run/uhub/uhub.pid LOGFILE=/var/log/uhub/uhub.log SCRIPTNAME=/etc/init.d/uhub DEFAULTFILE=/etc/default/uhub [ -r $DEFAULTFILE ] && . $DEFAULTFILE DAEMON_ENABLE="${UHUB_ENABLE}" DAEMON_OPTS="-l ${LOGFILE} -f -p ${PIDFILE}" test -x $DAEMON || exit 0 . /lib/lsb/init-functions ulimit -n 65536 mkdir -p /var/run/uhub/ set -e case "$1" in start) if [ "$DAEMON_ENABLE" != "true" ]; then log_daemon_msg "Disabled $DESC" $NAME log_end_msg 0 exit 0 fi log_daemon_msg "Starting $DESC" $NAME if ! start-stop-daemon --start --quiet --oknodo \ --pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS then log_end_msg 1 else log_end_msg 0 fi ;; stop) log_daemon_msg "Stopping $DESC" $NAME if start-stop-daemon --quiet --stop --oknodo --retry 30 --oknodo \ --pidfile $PIDFILE --exec $DAEMON then rm -f $PIDFILE log_end_msg 0 else log_end_msg 1 fi ;; reload) log_daemon_msg "Reloading $DESC configuration" $NAME if start-stop-daemon --stop --signal 2 --oknodo --retry 30 --oknodo \ --quiet --pidfile $PIDFILE --exec $DAEMON then if start-stop-daemon --start --quiet \ --pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS ; then log_end_msg 0 else log_end_msg 1 fi else log_end_msg 1 fi ;; restart|force-reload) $0 stop $0 start ;; status) status_of_proc $DAEMON $NAME && exit 0 || exit $? ;; *) echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload|status}" >&2 exit 1 ;; esac exit 0 modelrockettier-uhub-a8ee6e7/debian/uhub.logrotate000066400000000000000000000001621324501300100224500ustar00rootroot00000000000000/var/log/uhub/*.log { compress size 10M rotate 10 missingok notifempty } modelrockettier-uhub-a8ee6e7/debian/uhub.manpages000066400000000000000000000000351324501300100222420ustar00rootroot00000000000000doc/uhub.1 doc/uhub-passwd.1 modelrockettier-uhub-a8ee6e7/debian/uhub.postinst000066400000000000000000000007361324501300100223420ustar00rootroot00000000000000#!/bin/sh set -e case "$1" in configure) chmod 0750 /var/log/uhub if [ -x /etc/init.d/uhub ]; then update-rc.d uhub defaults >/dev/null if [ -x /usr/sbin/invoke-rc.d ]; then invoke-rc.d uhub restart else /etc/init.d/uhub restart fi fi ;; abort-upgrade|abort-remove|abort-deconfigure) ;; *) echo "postinst: error: unknown argument: $1" >&2 exit 1 ;; esac modelrockettier-uhub-a8ee6e7/debian/uhub.postrm000066400000000000000000000001271324501300100217750ustar00rootroot00000000000000#!/bin/sh -e if [ "$1" = purge ]; then update-rc.d uhub remove >/dev/null fi modelrockettier-uhub-a8ee6e7/debian/uhub.prerm000066400000000000000000000003211324501300100215720ustar00rootroot00000000000000#!/bin/sh -e if [ "$1" = remove ]; then if command -v invoke-rc.d >/dev/null 2>&1; then invoke-rc.d uhub stop || true else /etc/init.d/uhub stop fi fi modelrockettier-uhub-a8ee6e7/doc/000077500000000000000000000000001324501300100171075ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/doc/Doxyfile000066400000000000000000000223711324501300100206220ustar00rootroot00000000000000# 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 modelrockettier-uhub-a8ee6e7/doc/architecture.txt000066400000000000000000000061601324501300100223350ustar00rootroot00000000000000= 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 "speaks" 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. | ------------------------ modelrockettier-uhub-a8ee6e7/doc/compile.txt000066400000000000000000000011241324501300100212760ustar00rootroot00000000000000How to compile: --------------- See the official compiling howto: http://www.uhub.org/compile.php Prerequisites Before you try to compile µHub, please make sure the following prerequisites are met. * GNU make * gcc > 3.0 (or MinGW on Windows) * Perl 5 * openssl > 0.9.8 (or use "make USE_SSL=NO") * sqlite > 3.x or read http://www.uhub.org/compile.php for more info. Linux, Mac OSX, FreeBSD, NetBSD and OpenBSD ------------------------------------------- Simply, run: % make If you have an old gcc compiler, try disabling pre-compiled headers like this: gmake USE_PCH=NO modelrockettier-uhub-a8ee6e7/doc/extensions.txt000066400000000000000000000055171324501300100220570ustar00rootroot00000000000000ADC 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 incomming 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. modelrockettier-uhub-a8ee6e7/doc/getstarted.txt000066400000000000000000000037401324501300100220220ustar00rootroot00000000000000Getting 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 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 If you are planning to more than 1024 users on hub, you must increase the max number of file descriptors allowed. This limit needs to be higher than the configured max_users in uhub.conf. In linux can add the following lines to /etc/security/limits.conf (allows for ~4000 users) * soft nofile 4096 * hard nofile 4096 Or, you can use (as root): % ulimit -n 4096 Your mileage may vary -- Good luck! modelrockettier-uhub-a8ee6e7/doc/init.d.RedHat/000077500000000000000000000000001324501300100214425ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/doc/init.d.RedHat/etc/000077500000000000000000000000001324501300100222155ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/doc/init.d.RedHat/etc/init.d/000077500000000000000000000000001324501300100234025ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/doc/init.d.RedHat/etc/init.d/uhub000077500000000000000000000032661324501300100243020ustar00rootroot00000000000000#!/bin/sh # # chkconfig: - 91 35 # description: Starts and stops the Uhub ( http://www.uhub.org ) 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 bin and uhub.conf exists. [ -f $UHUBBINFILE ] || exit 6 [ -f /etc/uhub/uhub.conf ] || exit 6 RETVAL=0 start() { KIND="Uhub" echo -n $"Starting $KIND services: " daemon $UHUBBINFILE $UHUBOPTIONS RETVAL=$? echo "" return $RETVAL } stop() { KIND="Uhub" echo -n $"Shutting down $KIND services: " killproc $UHUBBINFILE RETVAL=$? echo "" return $RETVAL } restart() { stop start } reload() { echo -n $"Reloading uhub.conf / user.conf file: " killproc uhub -HUP RETVAL=$? echo "" return $RETVAL } relog() { echo -n $"Reopen main log file: " killproc uhub -SIGHUP RETVAL=$? echo "" return $RETVAL } rhstatus() { status $UHUBBINFILE RETVAL=$? if [ $RETVAL -ne 0 ] ; then return $RETVAL fi } case "$1" in start) start ;; stop) stop ;; restart) restart ;; reload) reload ;; relog) relog ;; status) rhstatus ;; *) echo $"Usage: $0 {start|stop|restart|reload|relog|status}" exit 2 esac exit $? modelrockettier-uhub-a8ee6e7/doc/init.d.RedHat/etc/logrotate.d/000077500000000000000000000000001324501300100244375ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/doc/init.d.RedHat/etc/logrotate.d/uhub000066400000000000000000000002401324501300100253210ustar00rootroot00000000000000# Log rotate for Uhub # see man logrotate # # /var/log/uhub.log { compress size 10M rotate 10 missingok notifempty } modelrockettier-uhub-a8ee6e7/doc/init.d.RedHat/etc/sysconfig/000077500000000000000000000000001324501300100242215ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/doc/init.d.RedHat/etc/sysconfig/uhub000066400000000000000000000011711324501300100251070ustar00rootroot00000000000000# locate bin file UHUBBINFILE=/usr/bin/uhub # Options to UHUB # -v Verbose mode. Add more -v's for higher verbosity. # -q Quiet mode - no output # -f Fork to background # -l Log messages to given file (default: stderr) # -L Log messages to syslog # -c Specify configuration file (default: /etc/uhub/uhub.conf) # -S Show configuration parameters, but ignore defaults # -u Run as given user # -g Run with given group permissions # -p Store pid in file (process id) UHUBOPTIONS=" -u uhub -f -p /var/run/uhub.pid -l /var/log/uhub.log" modelrockettier-uhub-a8ee6e7/doc/plugins.conf000066400000000000000000000050241324501300100214400ustar00rootroot00000000000000# ATTENTION! # Plugins are invoked in the order of listing in the plugin config file. # Sqlite based user authentication. # # This plugin provides a Sqlite based authentication database for # registered users. # Use the uhub-passwd utility to create the database and add/remove users. # # Parameters: # file: path/filename for database. # plugin /usr/lib/uhub/mod_auth_sqlite.so "file=/etc/uhub/users.db" # Topic commands. # Note: "topic" == "hub description" (as configured in uhub.conf) # # !topic - change the topic (op required) # !showtopic - show the topic # !resettopic - reset the topic to the default (op required) # # This plugins takes no parameters. #plugin /usr/lib/uhub/mod_topic.so # Log file writer # # Parameters: # file: path/filename for log file. # syslog: if true then syslog is used instead of writing to a file (Unix only) plugin /usr/lib/uhub/mod_logging.so "file=/var/log/uhub.log" # A simple example plugin #plugin /usr/lib/uhub/mod_example.so # A plugin sending a welcome message. # # This plugin provides the following commands: # !motd - Message of the day # !rules - Show hub rules. # # Parameters: # motd: path/filename for the welcome message (message of the day) # rules: path/filenam for the rules file # # NOTE: The files MUST exist, however if you do not wish to provide one then these parameters can be omitted. # # The motd/rules files can do the following substitutions: # %n - Nickname of the user who entered the hub or issued the command. # %a - IP address of the user # %c - The credentials of the user (guest, user, op, super, admin). # %% - Becomes '%' # %H - Hour 24-hour format (00-23) (Hub local time) # %I - Hour 12-hour format (01-12) (Hub local time) # %P - 'AM' or 'PM' # %p - 'am' or 'pm' # %M - Minutes (00-59) (Hub local time) # %S - Seconds (00-60) (Hub local time) plugin /usr/lib/uhub/mod_welcome.so "motd=/etc/uhub/motd.txt rules=/etc/uhub/rules.txt" # Load the chat history plugin. # # This plugin provides chat history when users are connecting, or # when users invoke the !history command. # The history command can optionally take a parameter to indicate how many lines of history is requested. # # Parameters: # history_max: the maximum number of messages to keep in history # history_default: when !history is provided without arguments, then this default number of messages are returned. # history_connect: the number of chat history messages to send when users connect (0 = do not send any history) plugin /usr/lib/uhub/mod_chat_history.so "history_max=200 history_default=10 history_connect=5" modelrockettier-uhub-a8ee6e7/doc/rules.txt000066400000000000000000000000641324501300100210020ustar00rootroot000000000000001. rule #1 2. rule #2 3. rule #3 ...... 34. Rule #34modelrockettier-uhub-a8ee6e7/doc/uhub-passwd.1000066400000000000000000000017471324501300100214440ustar00rootroot00000000000000.TH UHUB-PASSWD "1" "May 2012" .SH NAME uhub-passwd \- small utility for manipulating passwords which are used by uhub daemon .SH SYNOPSIS .B uhub-passwd \fIfilename command \fR[...] .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 \^create .TP .BI \^add " username password [credentials = user]" .TP .BI \^del " username" .TP .BI \^mod " username credentials" .TP .BI \^pass " username password" .TP .BI \^list .SH "PARAMETERS" .TP .B 'filename' is a database file .TP .B 'username' is a nickname (UTF\-8, up to 64 bytes) .TP .B 'password' is a password (UTF\-8, up to 64 bytes) .TP .B 'credentials' is one of 'admin', 'super', 'op', 'user' .SH AUTHOR This program was written by Jan Vidar Krey .SH "BUG REPORTS" If you find a bug in uhub please report it to .B http://bugs.extatic.org/ modelrockettier-uhub-a8ee6e7/doc/uhub.1000066400000000000000000000036231324501300100201400ustar00rootroot00000000000000.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 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 .SH "BUG REPORTS" If you find a bug in uhub please report it to .B http://bugs.extatic.org/ modelrockettier-uhub-a8ee6e7/doc/uhub.conf000066400000000000000000000110151324501300100207170ustar00rootroot00000000000000# uhub.conf - A example configuration file. # You should normally place this file in /etc/uhub/uhub.conf # and customize some of the settings 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 # Alternative server ports # server_alt_ports = 1512, 1513 # The maximum amount of users allowed on the hub. max_users=500 # If 1, will show a "Powered by uHub/{VERSION}". show_banner=1 # If enabled then operating system and cpu architecture is part of the banner. show_banner_sys_info=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 conf for plugin subsystem file_plugins = /etc/uhub/plugins.conf # 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 # Flood control support: # set the interval to 5 seconds flood_ctl_interval = 5 # Then the maximum chat, connect, search, updates etc will be measured over 5 seconds. # So, 3 chat messages per 5 seconds allowed. flood_ctl_chat=3 flood_ctl_connect=20 flood_ctl_search=1 flood_ctl_update=2 flood_ctl_extras=5 # chat control # if chat_is_privileged=yes only registered users may write in main chat chat_is_privileged = no # if obsolete_clients=1 allows old clients to enter , 0 gives an error message (msg_proto_obsolete_adc0) if they try connect # defaults obsolete_clients=1 obsolete_clients=1 # 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 has too few upload slots msg_user_slots_high = User has 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 = Out of memory msg_user_flood_chat = Chat flood detected, messages are dropped. msg_user_flood_connect = Connect flood detected, connection refused. msg_user_flood_search = Search flood detected, search is stopped. msg_user_flood_update = Update flood detected. msg_user_flood_extras = Flood detected. # If a client that supports ADC but not a compatible hash algorithm (tiger), # then the hub cannot accept the client: msg_proto_no_common_hash = No common hash algorithm. # Message to be shown to old clients using an older version of ADC than ADC/1.0 msg_proto_obsolete_adc0 = Client is using an obsolete ADC protocol version. modelrockettier-uhub-a8ee6e7/doc/uhub.dot000066400000000000000000000033761324501300100205730ustar00rootroot00000000000000/** * 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()" } modelrockettier-uhub-a8ee6e7/doc/uhub.ebuild000066400000000000000000000017051324501300100212430ustar00rootroot00000000000000# Copyright 1999-2010 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: $ inherit eutils if [ "$PV" != "9999" ]; then SRC_URI="http://www.extatic.org/downloads/uhub/${P}-src.tar.bz2" KEYWORDS="~amd64 ~x86" else inherit git SRC_URI="" EGIT_REPO_URI="git://github.com/janvidar/uhub.git" KEYWORDS="" fi EAPI="2" DESCRIPTION="High performance ADC hub" HOMEPAGE="http://www.uhub.org/" LICENSE="GPL-3" SLOT="0" IUSE="+ssl" DEPEND="=dev-lang/perl-5* ssl? ( >=dev-libs/openssl-0.9.8 ) " RDEPEND="${DEPEND}" src_compile() { $opts="" use ssl && opts="USE_SSL=YES $opts" emake $opts } src_install() { dodir /usr/bin dodir /etc/uhub emake DESTDIR="${D}" UHUB_PREFIX="${D}/usr" install || die "install failed" newinitd doc/uhub.gentoo.rc uhub || newinitd ${FILESDIR}/uhub.rc uhub } pkg_postinst() { enewuser uhub } modelrockettier-uhub-a8ee6e7/doc/uhub.spec000066400000000000000000000060761324501300100207370ustar00rootroot00000000000000Summary: High performance ADC p2p hub. Name: uhub Version: 0.4.0 Release: 2 License: GPLv3 Group: Networking/File transfer Source: uhub-%{version}.tar.gz URL: http://www.uhub.org BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root BuildRequires: sqlite-devel BuildRequires: openssl-devel %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. Key features: - High performance and low memory usage - IPv4 and IPv6 support - Experimental SSL support (optional) - Advanced access control support - Easy configuration - plugin support - mod_welcome - MOTD\RULES messages - mod_auth_sipmle - auth with sqlite DB - mod_logging - log hub activity %prep %setup -q -n %{name}-%{version} %build echo RPM_BUILD_ROOT = $RPM_BUILD_ROOT make %install mkdir -p $RPM_BUILD_ROOT/usr/bin mkdir -p $RPM_BUILD_ROOT/etc/uhub mkdir -p $RPM_BUILD_ROOT/etc/init.d mkdir -p $RPM_BUILD_ROOT/etc/logrotate.d mkdir -p $RPM_BUILD_ROOT/etc/sysconfig mkdir -p $RPM_BUILD_ROOT/usr/share/man/man1 mkdir -p $RPM_BUILD_ROOT/usr/lib/uhub install uhub $RPM_BUILD_ROOT/usr/bin/ install uhub-passwd $RPM_BUILD_ROOT/usr/bin/ > doc/motd.txt install -m644 doc/uhub.conf doc/users.conf doc/rules.txt doc/motd.txt doc/plugins.conf doc/users.db $RPM_BUILD_ROOT/etc/uhub install doc/init.d.RedHat/etc/init.d/uhub $RPM_BUILD_ROOT/etc/init.d install -m644 doc/init.d.RedHat/etc/sysconfig/uhub $RPM_BUILD_ROOT/etc/sysconfig/ install -m644 doc/init.d.RedHat/etc/logrotate.d/uhub $RPM_BUILD_ROOT/etc/logrotate.d/ /bin/gzip -9c doc/uhub.1 > doc/uhub.1.gz && install -m644 doc/uhub.1.gz $RPM_BUILD_ROOT/usr/share/man/man1 install -m644 mod_*.so $RPM_BUILD_ROOT/usr/lib/uhub %files %defattr(-,root,root) %doc AUTHORS BUGS COPYING ChangeLog README TODO doc/Doxyfile doc/architecture.txt doc/compile.txt doc/extensions.txt doc/getstarted.txt doc/uhub.dot %config(noreplace) /etc/uhub/uhub.conf #%{_sysconfdir}/uhub/uhub.conf %config(noreplace) %{_sysconfdir}/uhub/users.conf %config(noreplace) %{_sysconfdir}/uhub/motd.txt %config(noreplace) %{_sysconfdir}/uhub/rules.txt %config(noreplace) %{_sysconfdir}/uhub/plugins.conf %config(noreplace) %{_sysconfdir}/uhub/users.db %{_sysconfdir}/init.d/uhub %config(noreplace) %{_sysconfdir}/logrotate.d/uhub %config(noreplace) %{_sysconfdir}/sysconfig/uhub /usr/share/man/man1/uhub.1.gz %{_bindir}/uhub %{_libdir}/uhub/mod_*.so %clean rm -rf $RPM_BUILD_ROOT %post /sbin/chkconfig --add uhub if [ $1 -gt 1 ] ; then /etc/rc.d/init.d/uhub restart >/dev/null || : fi # need more informations about add services and users in system /usr/sbin/adduser -M -d /tmp -G nobody -s /sbin/nologin -c 'The Uhub ADC p2p hub Daemon' uhub >/dev/null 2>&1 ||: # write SSL create echo "PLS see /usr/share/doc/uhub/" %changelog * Fri Dec 30 2011 E_zombie - add users.db - add new doc * Tue Jun 26 2010 E_zombie - add plugins.conf * Tue Jan 31 2010 E_zombie - change GROUP - chmod for files - add postinstall scripts - fix "License" * Tue Jan 26 2010 E_zombie - first .spec release modelrockettier-uhub-a8ee6e7/doc/upstart/000077500000000000000000000000001324501300100206115ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/doc/upstart/etc/000077500000000000000000000000001324501300100213645ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/doc/upstart/etc/init/000077500000000000000000000000001324501300100223275ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/doc/upstart/etc/init/uhub.conf000066400000000000000000000014251324501300100241430ustar00rootroot00000000000000# uHub - a lightweight but high-performance hub for the ADC # peer-to-peer protocol. description "uHub - High performance ADC peer-to-peer hub" # Start and stop conditions. start on filesystem or runlevel [2345] stop on runlevel [!2345] # Allow the service to respawn, but if its happening too often # (10 times in 5 seconds) theres a problem and we should stop trying. respawn respawn limit 10 5 # The program is going to fork, and upstart needs to know this # so it can track the change in PID. expect fork # Set the mode the process should create files in. umask 022 # Make sure the log folder exists. pre-start script mkdir -p -m0755 /var/log/uhub end script # Command to run it. exec /usr/bin/uhub -f -u uhub -g uhub -l /var/log/uhub/uhub.log -c /etc/uhub/uhub.conf modelrockettier-uhub-a8ee6e7/doc/users.conf000066400000000000000000000025631324501300100211250ustar00rootroot00000000000000# uHub access control lists. # # Syntax: [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' modelrockettier-uhub-a8ee6e7/src/000077500000000000000000000000001324501300100171315ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/src/adc/000077500000000000000000000000001324501300100176605ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/src/adc/adcconst.h000066400000000000000000000170251324501300100216340ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_ADC_CONSTANTS_H #define HAVE_UHUB_ADC_CONSTANTS_H #ifndef SID_T_DEFINED typedef uint32_t sid_t; #define SID_T_DEFINED #endif 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 ADUCMD" /* 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') /* invalid search results (spam) */ #define ADC_CMD_BRES FOURCC('B','R','E','S') #define ADC_CMD_ERES FOURCC('E','R','E','S') #define ADC_CMD_FRES FOURCC('F','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') #define ADC_CMD_BQUI FOURCC('B','Q','U','I') #define ADC_CMD_DQUI FOURCC('D','Q','U','I') #define ADC_CMD_EQUI FOURCC('E','Q','U','I') #define ADC_CMD_FQUI FOURCC('F','Q','U','I') /* Extension messages */ #define ADC_CMD_HCHK FOURCC('H','C','H','K') /* UCMD Extension */ #define ADC_CMD_BCMD FOURCC('B','C','M','D') #define ADC_CMD_DCMD FOURCC('D','C','M','D') #define ADC_CMD_ECMD FOURCC('E','C','M','D') #define ADC_CMD_FCMD FOURCC('F','C','M','D') #define ADC_CMD_HCMD FOURCC('H','C','M','D') #define ADC_CMD_ICMD FOURCC('I','C','M','D') #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_PRODUCT "AP" /* software name */ #define ADC_INF_FLAG_USER_AGENT_VERSION "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_HUBBOT "5" /* 1 + 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 */ modelrockettier-uhub-a8ee6e7/src/adc/message.c000066400000000000000000000500111324501300100214450ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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 <= X->capacity); \ uhub_assert(X->references > 0); \ uhub_assert(X->length == strlen(X->cache)); #define ADC_MSG_NULL_ON_FREE #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); } #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 */ static int msg_check_escapes(const char* string, size_t len) { char* start = (char*) string; while ((start = memchr(start, '\\', len - (start - string)))) { if (start+1 == (string + len)) return 0; switch (*(++start)) { case '\\': case 'n': case 's': /* Increment so we don't check the escaped * character next time around. Not doing so * leads to messages with escaped backslashes * being incorrectly reported as having invalid * escapes. */ ++start; break; default: return 0; } } return 1; } struct adc_message* adc_msg_incref(struct adc_message* msg) { #ifndef ADC_MESSAGE_INCREF 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) return 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); uhub_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); msg->references--; if (msg->references == 0) { #ifdef ADC_MSG_NULL_ON_FREE if (msg->cache) { *msg->cache = 0; } #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 = 1; copy->feature_cast_include = 0; copy->feature_cast_exclude = 0; if (!adc_msg_grow(copy, copy->length)) { adc_msg_free(copy); return NULL; /* OOM */ } if (!copy->cache) { adc_msg_free(copy); return NULL; } memcpy(copy->cache, cmd->cache, cmd->length); copy->cache[copy->length] = 0; if (cmd->feature_cast_include) { copy->feature_cast_include = list_create(); LIST_FOREACH(char*, tmp, cmd->feature_cast_include, { list_append(copy->feature_cast_include, hub_strdup(tmp)); }); } if (cmd->feature_cast_exclude) { copy->feature_cast_exclude = list_create(); LIST_FOREACH(char*, tmp, cmd->feature_cast_exclude, { list_append(copy->feature_cast_exclude, hub_strdup(tmp)); }); } ADC_MSG_ASSERT(copy); 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 && !auth_cred_is_unrestricted(u->credentials)))) { 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 (!msg_check_escapes(line, length)) { LOG_DEBUG("Dropped message with invalid ADC escape."); 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; command->references = 1; 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); return command; } struct adc_message* adc_msg_create(const char* line) { return adc_msg_parse(line, strlen(line)); } struct adc_message* adc_msg_construct_source(fourcc_t fourcc, sid_t source, size_t size) { struct adc_message* msg = adc_msg_construct(fourcc, size + 4 + 1); if (!msg) return NULL; adc_msg_add_argument(msg, sid_to_string(source)); msg->source = source; return msg; } struct adc_message* adc_msg_construct_source_dest(fourcc_t fourcc, sid_t source, sid_t dest, size_t size) { struct adc_message* msg = adc_msg_construct(fourcc, size + 4 + 4 + 1); if (!msg) return NULL; adc_msg_add_argument(msg, sid_to_string(source)); adc_msg_add_argument(msg, sid_to_string(dest)); msg->source = source; msg->target = dest; return msg; } 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 (!adc_msg_grow(msg, sizeof(fourcc) + 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; msg->references = 1; 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 ((size_t) (&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); } /* FIXME: this looks bogus */ void adc_msg_unterminate(struct adc_message* cmd) { ADC_MSG_ASSERT(cmd); 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 && 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; } int adc_msg_unescape_to_target(const char* string, char* target, size_t target_size) { size_t w = 0; char* ptr = (char*) target; char* str = (char*) string; int escaped = 0; while (*str && w < (target_size-1)) { if (escaped) { if (*str == 's') *ptr++ = ' '; else if (*str == '\\') *ptr++ = '\\'; else if (*str == 'n') *ptr++ = '\n'; else *ptr++ = *str; w++; escaped = 0; } else { if (*str == '\\') escaped = 1; else { *ptr++ = *str; w++; } } str++; } *ptr = 0; w++; return w; } char* adc_msg_escape(const char* string) { char* str = hub_malloc(adc_msg_escape_length(string)+1); size_t n = 0; size_t 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; } modelrockettier-uhub-a8ee6e7/src/adc/message.h000066400000000000000000000174301324501300100214620ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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); /** * Construct a message for the given 'fourcc' and add a source SID to it, * in addition pre-allocate 'size' bytes at the end of the message. */ extern struct adc_message* adc_msg_construct_source(fourcc_t fourcc, sid_t source, size_t size); extern struct adc_message* adc_msg_construct_source_dest(fourcc_t fourcc, sid_t source, sid_t dest, 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 ADC command escaped string to a regular string. * @return The number of bytes written to target. If the target is not large enough then * the -1 is returned, but the string is guaranteed to always be \0 terminated. */ extern int adc_msg_unescape_to_target(const char* string, char* target, size_t target_size); /** * 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 */ modelrockettier-uhub-a8ee6e7/src/adc/sid.c000066400000000000000000000071501324501300100206060ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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; if (pool->count >= (pool->max - pool->min)) { #ifdef DEBUG_SID LOG_DUMP("SID_POOL: alloc, sid pool is full."); #endif return 0; } 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]; } modelrockettier-uhub-a8ee6e7/src/adc/sid.h000066400000000000000000000023301324501300100206060ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_SID_H #define HAVE_UHUB_SID_H #define SID_MAX 1048576 struct sid_pool; struct hub_user; 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 */ modelrockettier-uhub-a8ee6e7/src/core/000077500000000000000000000000001324501300100200615ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/src/core/auth.c000066400000000000000000000264661324501300100212040ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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) static int check_cmd_bool(const char* cmd, struct linked_list* list, char* line, int line_count) { char* data; 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; } 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 auth_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 auth_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++; } } strncpy(info->nickname, data, MAX_NICK_LEN); if (data_extra) strncpy(info->password, data_extra, MAX_PASS_LEN); info->credentials = status; list_append(list, info); LOG_DEBUG("ACL: Added user '%s' (%s)", info->nickname, auth_cred_to_string(info->credentials)); 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: Added ip range: %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) { struct acl_handle* handle = (struct acl_handle*) ptr_data; int ret; strip_off_ini_line_comments(line, line_count); line = strip_white_space(line); if (!*line) return 0; LOG_DEBUG("acl_parse_line: '%s'", line); ACL_ADD_USER("bot", handle->users, auth_cred_bot); ACL_ADD_USER("ubot", handle->users, auth_cred_ubot); ACL_ADD_USER("opbot", handle->users, auth_cred_opbot); ACL_ADD_USER("opubot", handle->users, auth_cred_opubot); ACL_ADD_USER("user_admin", handle->users, auth_cred_admin); ACL_ADD_USER("user_super", handle->users, auth_cred_super); ACL_ADD_USER("user_op", handle->users, auth_cred_operator); ACL_ADD_USER("user_reg", handle->users, auth_cred_user); ACL_ADD_USER("link", handle->users, auth_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 auth_info* info = (struct auth_info*) ptr; if (info) { 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; } extern int acl_register_user(struct hub_info* hub, struct auth_info* info) { if (plugin_auth_register_user(hub, info) != st_allow) { return 0; } return 1; } extern int acl_update_user(struct hub_info* hub, struct auth_info* info) { if (plugin_auth_update_user(hub, info) != st_allow) { return 0; } return 1; } extern int acl_delete_user(struct hub_info* hub, const char* name) { struct auth_info data; strncpy(data.nickname, name, MAX_NICK_LEN); data.nickname[MAX_NICK_LEN] = '\0'; data.password[0] = '\0'; data.credentials = auth_cred_none; if (plugin_auth_delete_user(hub, &data) != st_allow) { return 0; } return 1; } struct auth_info* acl_get_access_info(struct hub_info* hub, const char* name) { struct auth_info* info = 0; info = (struct auth_info*) hub_malloc(sizeof(struct auth_info)); if (plugin_auth_get_user(hub, name, info) != st_allow) { hub_free(info); return NULL; } return info; } #define STR_LIST_CONTAINS(LIST, STR) \ LIST_FOREACH(char*, str, LIST, \ { \ if (strcasecmp(str, STR) == 0) \ return 1; \ }); \ return 0 int acl_is_cid_banned(struct acl_handle* handle, const char* data) { char* str; if (!handle) return 0; STR_LIST_CONTAINS(handle->cids, data); } int acl_is_user_banned(struct acl_handle* handle, const char* data) { char* str; if (!handle) return 0; STR_LIST_CONTAINS(handle->users_banned, data); } int acl_is_user_denied(struct acl_handle* handle, const char* data) { char* str; 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 = hub_strdup(nick); if (!data) { LOG_ERROR("ACL error: Out of memory!"); return -1; } list_append(handle->users_banned, data); return 0; } int acl_user_ban_cid(struct acl_handle* handle, const char* cid) { char* data = hub_strdup(cid); if (!data) { LOG_ERROR("ACL error: Out of memory!"); 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; ip_convert_to_binary(ip_address, &raw); LIST_FOREACH(struct ip_range*, info, handle->networks, { if (ip_in_range(&raw, info)) return 1; }); 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; ip_convert_to_binary(ip_address, &raw); LIST_FOREACH(struct ip_range*, info, handle->nat_override, { if (ip_in_range(&raw, info)) return 1; }); 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 hub_info* hub, 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 hub_info* hub, struct hub_user* user, const char* password) { char buf[1024]; struct auth_info* access; const char* challenge; char raw_challenge[64]; char password_calc[64]; uint64_t tiger_res[3]; size_t password_len; if (!password || !user || strlen(password) != MAX_CID_LEN) return 0; access = acl_get_access_info(hub, user->id.nick); if (!access) return 0; challenge = acl_password_generate_challenge(hub, user); base32_decode(challenge, (unsigned char*) raw_challenge, MAX_CID_LEN); password_len = strlen(access->password); memcpy(&buf[0], access->password, password_len); memcpy(&buf[password_len], raw_challenge, TIGERSIZE); tiger((uint64_t*) buf, TIGERSIZE+password_len, (uint64_t*) tiger_res); base32_encode((unsigned char*) tiger_res, TIGERSIZE, password_calc); password_calc[MAX_CID_LEN] = 0; hub_free(access); if (strcasecmp(password, password_calc) == 0) { return 1; } return 0; } modelrockettier-uhub-a8ee6e7/src/core/auth.h000066400000000000000000000054521324501300100212010ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_ACL_H #define HAVE_UHUB_ACL_H struct hub_config; struct hub_info; struct hub_user; struct ip_addr_encap; 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 auth_info* acl_get_access_info(struct hub_info* hub, const char* name); extern int acl_register_user(struct hub_info* hub, struct auth_info* info); extern int acl_update_user(struct hub_info* hub, struct auth_info* info); extern int acl_delete_user(struct hub_info* hub, 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); /** * 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 hub_info* hub, struct hub_user* user, const char* password); extern const char* acl_password_generate_challenge(struct hub_info* hub, struct hub_user* user); #endif /* HAVE_UHUB_ACL_H */ modelrockettier-uhub-a8ee6e7/src/core/command_parser.c000066400000000000000000000151521324501300100232230ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" static void hub_command_args_free(struct hub_command* cmd) { struct hub_command_arg_data* data = NULL; if (!cmd->args) return; LIST_FOREACH(struct hub_command_arg_data*, data, cmd->args, { switch (data->type) { case type_string: hub_free(data->data.string); break; case type_range: hub_free(data->data.range); break; default: break; } }); list_clear(cmd->args, hub_free); list_destroy(cmd->args); cmd->args = NULL; } void command_free(struct hub_command* cmd) { if (!cmd) return; hub_free(cmd->prefix); hub_command_args_free(cmd); hub_free(cmd); } static enum command_parse_status command_extract_arguments(struct hub_info* hub, const struct hub_user* user, struct command_handle* command, struct linked_list* tokens, struct linked_list* args) { int arg = 0; int opt = 0; int greedy = 0; char arg_code; char* token = NULL; char* tmp = NULL; size_t size = 0; size_t offset = 0; struct hub_command_arg_data* data = NULL; enum command_parse_status status = cmd_status_ok; // Ignore the first token since it is the prefix. token = list_get_first(tokens); list_remove(tokens, token); hub_free(token); while (status == cmd_status_ok && (arg_code = command->args[arg++])) { if (greedy) { size = 1; LIST_FOREACH(char*, tmp, tokens, { size += (strlen(tmp) + 1); }); token = hub_malloc_zero(size); while ((tmp = list_get_first(tokens))) { if (offset > 0) token[offset++] = ' '; memcpy(token + offset, tmp, strlen(tmp)); offset += strlen(tmp); list_remove(tokens, tmp); hub_free(tmp); } } else { token = list_get_first(tokens); } if (!token || !*token) { if (arg_code == '?' || opt == 1) status = cmd_status_ok; else status = cmd_status_missing_args; break; } switch (arg_code) { case '?': opt = 1; continue; case '+': greedy = 1; continue; case 'u': data = hub_malloc(sizeof(*data)); data->type = type_user; data->data.user = uman_get_user_by_nick(hub->users, token); if (!data->data.user) { hub_free(data); data = NULL; status = cmd_status_arg_nick; } break; case 'i': data = hub_malloc(sizeof(*data)); data->type = type_user; data->data.user = uman_get_user_by_cid(hub->users, token); if (!data->data.user) { hub_free(data); data = NULL; status = cmd_status_arg_cid; } break; case 'a': data = hub_malloc(sizeof(*data)); data->type = type_address; if (ip_convert_to_binary(token, data->data.address) == -1) { hub_free(data); data = NULL; status = cmd_status_arg_address; } break; case 'r': data = hub_malloc(sizeof(*data)); data->type = type_range; data->data.range = hub_malloc_zero(sizeof(struct ip_range)); if (!ip_convert_address_to_range(token, data->data.range)) { hub_free(data->data.range); hub_free(data); data = NULL; status = cmd_status_arg_address; } break; case 'n': case 'm': case 'p': data = hub_malloc(sizeof(*data)); data->type = type_string; data->data.string = strdup(token); break; case 'c': data = hub_malloc(sizeof(*data)); data->type = type_command; data->data.command = command_handler_lookup(hub->commands, token); if (!data->data.command) { hub_free(data); data = NULL; status = cmd_status_arg_command; } break; case 'C': data = hub_malloc(sizeof(*data)); data->type = type_credentials; if (!auth_string_to_cred(token, &data->data.credentials)) { hub_free(data); data = NULL; status = cmd_status_arg_cred; } break; case 'N': data = hub_malloc(sizeof(*data)); data->type = type_integer; if (!is_number(token, &data->data.integer)) { hub_free(data); data = NULL; status = cmd_status_arg_number; } break; case '\0': if (!opt) { status = cmd_status_missing_args; } else { status = cmd_status_ok; } } if (data) { list_append(args, data); data = NULL; } list_remove(tokens, token); hub_free(token); } hub_free(data); return status; } static struct command_handle* command_get_handler(struct command_base* cbase, const char* prefix, const struct hub_user* user, struct hub_command* cmd) { struct command_handle* handler = NULL; uhub_assert(cmd != NULL); if (prefix && prefix[0] && prefix[1]) { handler = command_handler_lookup(cbase, prefix + 1); if (handler) { cmd->ptr = handler->ptr; cmd->handler = handler->handler; cmd->status = command_is_available(handler, user->credentials) ? cmd_status_ok : cmd_status_access_error; } else { cmd->status = cmd_status_not_found; } } else { cmd->status = cmd_status_syntax_error; } return handler; } /** * Parse a command and break it down into a struct hub_command. */ struct hub_command* command_parse(struct command_base* cbase, struct hub_info* hub, const struct hub_user* user, const char* message) { struct linked_list* tokens = list_create(); struct hub_command* cmd = NULL; struct command_handle* handle = NULL; cmd = hub_malloc_zero(sizeof(struct hub_command)); cmd->status = cmd_status_ok; cmd->message = message; cmd->prefix = NULL; cmd->args = list_create(); cmd->user = user; if (split_string(message, " ", tokens, 0) <= 0) { cmd->status = cmd_status_syntax_error; goto command_parse_cleanup; } // Setup hub command. cmd->prefix = strdup(((char*) list_get_first(tokens)) + 1); // Find a matching command handler handle = command_get_handler(cbase, list_get_first(tokens), user, cmd); if (cmd->status != cmd_status_ok) goto command_parse_cleanup; // Parse arguments cmd->status = command_extract_arguments(hub, user, handle, tokens, cmd->args); goto command_parse_cleanup; command_parse_cleanup: list_clear(tokens, &hub_free); list_destroy(tokens); return cmd; } modelrockettier-uhub-a8ee6e7/src/core/command_parser.h000066400000000000000000000123161324501300100232270ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_COMMAND_PARSER_H #define HAVE_UHUB_COMMAND_PARSER_H struct hub_command; struct hub_user; struct command_base; /** * Parse a message as a command and return a status indicating if the command * is valid and that the arguments are sane. * * @param cbase Command base pointer. * @param user User who invoked the command. * @param message The message that is to be interpreted as a command (including the invokation prefix '!' or '+') * * @return a hub_command that must be freed with command_free(). @See struct hub_command. */ extern struct hub_command* command_parse(struct command_base* cbase, struct hub_info* hub, const struct hub_user* user, const char* message); /** * Free a hub_command that was created in command_parse(). */ extern void command_free(struct hub_command* command); enum command_parse_status { cmd_status_ok, /** <<< "Everything seems to OK" */ cmd_status_not_found, /** <<< "Command was not found" */ cmd_status_access_error, /** <<< "You don't have access to this command" */ cmd_status_syntax_error, /** <<< "Not a valid command." */ cmd_status_missing_args, /** <<< "Missing some or all required arguments." */ cmd_status_arg_nick, /** <<< "A nick argument does not match an online user. ('n')" */ cmd_status_arg_cid, /** <<< "A cid argument does not match an online user. ('i')." */ cmd_status_arg_address, /** <<< "A address range argument is not valid ('a')." */ cmd_status_arg_number, /** <<< "A number argument is not valid ('N')" */ cmd_status_arg_cred, /** <<< "A credentials argument is not valid ('C')" */ cmd_status_arg_command, /** <<< "A command argument is not valid ('c')" */ }; enum hub_command_arg_type { type_integer, type_string, type_user, type_address, type_range, type_credentials, type_command }; struct hub_command_arg_data { enum hub_command_arg_type type; union { int integer; char* string; struct hub_user* user; struct ip_addr_encap* address; struct ip_range* range; enum auth_credentials credentials; struct command_handle* command; } data; }; typedef int (*command_handler)(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd); /** * This struct contains all information needed to invoke * a command, which includes the whole message, the prefix, * the decoded arguments (according to parameter list), and * the user pointer (ptr) which comes from the command it was matched to. * * The message and prefix is generally always available, but args only * if status == cmd_status_ok. * Handler and ptr are NULL if status == cmd_status_not_found, or status == cmd_status_access_error. * Ptr might also be NULL if cmd_status_ok because the command that handles it was added with a NULL ptr. */ struct hub_command { const char* message; /**<<< "The complete message." */ char* prefix; /**<<< "The prefix extracted from the message." */ struct linked_list* args; /**<<< "List of arguments of type struct hub_command_arg_data. Parsed from message." */ enum command_parse_status status; /**<<< "Status of the parsed hub_command." */ command_handler handler; /**<<< "The function handler to call in order to invoke this command." */ const struct hub_user* user; /**<<< "The user who invoked this command." */ void* ptr; /**<<< "A pointer of data which came from struct command_handler" */ }; /** * Reset the command argument iterator and return the number of arguments * that can be extracted from a parsed command. * * @param cmd the command to start iterating arguments * @return returns the number of arguments provided for the command */ extern size_t hub_command_arg_reset(struct hub_command* cmd); /** * Obtain the current argument and place it in data and increments the iterator. * If no argument exists, or the argument is of a different type than \param type, then 0 is returned. * * NOTE: when calling hub_command_arg_next the first time during a command callback it is safe to assume * that the first argument will be extracted. Thus you don't need to call hub_command_arg_reset(). * * @param cmd the command used for iterating arguments. * @param type the expected type of this argument * @return NULL if no argument is found or if the argument found does not match the expected type. */ extern struct hub_command_arg_data* hub_command_arg_next(struct hub_command* cmd, enum hub_command_arg_type type); #endif /* HAVE_UHUB_COMMAND_PARSER_H */ modelrockettier-uhub-a8ee6e7/src/core/commands.c000066400000000000000000000461611324501300100220360ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" #ifdef DEBUG // #define DEBUG_UNLOAD_PLUGINS #endif #define MAX_HELP_MSG 16384 #define MAX_HELP_LINE 512 static int send_command_access_denied(struct command_base* cbase, struct hub_user* user, const char* prefix); static int send_command_not_found(struct command_base* cbase, struct hub_user* user, const char* prefix); static int send_command_syntax_error(struct command_base* cbase, struct hub_user* user); static int send_command_missing_arguments(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd); struct command_base { struct hub_info* hub; struct linked_list* handlers; size_t prefix_length_max; }; struct command_base* command_initialize(struct hub_info* hub) { struct command_base* cbase = (struct command_base*) hub_malloc(sizeof(struct command_base)); uhub_assert(cbase != NULL); // uhub_assert(hub != NULL); cbase->hub = hub; cbase->handlers = (struct linked_list*) list_create(); cbase->prefix_length_max = 0; uhub_assert(cbase->handlers != NULL); commands_builtin_add(cbase); return cbase; } void command_shutdown(struct command_base* cbase) { commands_builtin_remove(cbase); uhub_assert(list_size(cbase->handlers) == 0); list_destroy(cbase->handlers); hub_free(cbase); } int command_add(struct command_base* cbase, struct command_handle* cmd, void* ptr) { uhub_assert(cbase != NULL); uhub_assert(cmd != NULL); uhub_assert(cmd->length == strlen(cmd->prefix)); uhub_assert(cmd->handler != NULL); uhub_assert(cmd->description && *cmd->description); list_append(cbase->handlers, cmd); cbase->prefix_length_max = MAX(cmd->length, cbase->prefix_length_max); cmd->ptr = ptr; return 1; } int command_del(struct command_base* cbase, struct command_handle* cmd) { uhub_assert(cbase != NULL); uhub_assert(cmd != NULL); list_remove(cbase->handlers, cmd); return 1; } int command_is_available(struct command_handle* handle, enum auth_credentials credentials) { uhub_assert(handle != NULL); return handle->cred <= credentials; } struct command_handle* command_handler_lookup(struct command_base* cbase, const char* prefix) { struct command_handle* handler = NULL; size_t prefix_len = strlen(prefix); LIST_FOREACH(struct command_handle*, handler, cbase->handlers, { if (prefix_len != handler->length) continue; if (!memcmp(prefix, handler->prefix, handler->length)) return handler; }); return NULL; } void command_get_syntax(struct command_handle* handler, struct cbuffer* buf) { size_t n, arg_count; int opt = 0; char arg_code, last_arg = -1; cbuf_append_format(buf, "!%s", handler->prefix); if (handler->args) { arg_count = strlen(handler->args); for (n = 0; n < arg_count; n++) { if (!strchr("?+", last_arg)) cbuf_append(buf, " "); arg_code = handler->args[n]; switch (arg_code) { case '?': cbuf_append(buf, "["); opt++; break; case '+': /* ignore */ break; case 'n': cbuf_append(buf, ""); break; case 'u': cbuf_append(buf, ""); break; case 'i': cbuf_append(buf, ""); break; case 'a': cbuf_append(buf, ""); break; case 'r': cbuf_append(buf, ""); break; case 'm': cbuf_append(buf, ""); break; case 'p': cbuf_append(buf, ""); break; case 'C': cbuf_append(buf, ""); break; case 'c': cbuf_append(buf, ""); break; case 'N': cbuf_append(buf, ""); break; default: LOG_ERROR("unknown argument code '%c'", arg_code); } last_arg = arg_code; } while (opt--) cbuf_append(buf, "]"); } } void send_message(struct command_base* cbase, struct hub_user* user, struct cbuffer* buf) { char* buffer = adc_msg_escape(cbuf_get(buf)); struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6); adc_msg_add_argument(command, buffer); route_to_user(cbase->hub, user, command); adc_msg_free(command); hub_free(buffer); cbuf_destroy(buf); } static int send_command_access_denied(struct command_base* cbase, struct hub_user* user, const char* prefix) { struct cbuffer* buf = cbuf_create(128); cbuf_append_format(buf, "*** %s: Access denied.", prefix); send_message(cbase, user, buf); return 0; } static int send_command_not_found(struct command_base* cbase, struct hub_user* user, const char* prefix) { struct cbuffer* buf = cbuf_create(128); cbuf_append_format(buf, "*** %s: Command not found.", prefix); send_message(cbase, user, buf); return 0; } static int send_command_syntax_error(struct command_base* cbase, struct hub_user* user) { struct cbuffer* buf = cbuf_create(128); cbuf_append(buf, "*** Syntax error."); send_message(cbase, user, buf); return 0; } static int send_command_missing_arguments(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) { struct cbuffer* buf = cbuf_create(512); cbuf_append_format(buf, "*** Missing argument: See !help %s\n", cmd->prefix); send_message(cbase, user, buf); return 0; } static size_t command_count_required_args(struct command_handle* handler) { size_t n = 0; for (n = 0; n < strlen(handler->args); n++) { if (handler->args[n] == '?') break; } return n; } int command_check_args(struct hub_command* cmd, struct command_handle* handler) { if (!handler->args) return 1; if (list_size(cmd->args) >= command_count_required_args(handler)) return 1; return 0; } int command_invoke(struct command_base* cbase, struct hub_user* user, const char* message) { int ret = 0; struct hub_command* cmd = command_parse(cbase, cbase->hub, user, message); switch (cmd->status) { case cmd_status_ok: ret = cmd->handler(cbase, user, cmd); break; case cmd_status_not_found: ret = send_command_not_found(cbase, user, cmd->prefix); break; case cmd_status_access_error: ret = send_command_access_denied(cbase, user, cmd->prefix); break; case cmd_status_missing_args: ret = send_command_missing_arguments(cbase, user, cmd); break; case cmd_status_syntax_error: case cmd_status_arg_nick: case cmd_status_arg_cid: case cmd_status_arg_address: case cmd_status_arg_number: case cmd_status_arg_cred: case cmd_status_arg_command: ret = send_command_syntax_error(cbase, user); break; } command_free(cmd); return ret; } size_t hub_command_arg_reset(struct hub_command* cmd) { cmd->args->iterator = NULL; return list_size(cmd->args); } struct hub_command_arg_data* hub_command_arg_next(struct hub_command* cmd, enum hub_command_arg_type type) { struct hub_command_arg_data* ptr = (struct hub_command_arg_data*) list_get_next(cmd->args); if (!ptr) return NULL; uhub_assert(ptr->type == type); if (ptr->type != type) return NULL; return ptr; } static int command_status(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd, struct cbuffer* msg) { struct cbuffer* buf = cbuf_create(cbuf_size(msg) + strlen(cmd->prefix) + 7); cbuf_append_format(buf, "*** %s: %s", cmd->prefix, cbuf_get(msg)); send_message(cbase, user, buf); cbuf_destroy(msg); return 0; } static int command_help(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) { size_t n; struct cbuffer* buf = cbuf_create(MAX_HELP_LINE); struct hub_command_arg_data* data = hub_command_arg_next(cmd, type_command); struct command_handle* command; if (!data) { cbuf_append(buf, "Available commands:\n"); LIST_FOREACH(struct command_handle*, command, cbase->handlers, { if (command_is_available(command, user->credentials)) { cbuf_append_format(buf, "!%s", command->prefix); for (n = strlen(command->prefix); n < cbase->prefix_length_max; n++) cbuf_append(buf, " "); cbuf_append_format(buf, " - %s\n", command->description); } }); } else { command = data->data.command; if (command_is_available(command, user->credentials)) { cbuf_append_format(buf, "Usage: "); command_get_syntax(command, buf); cbuf_append_format(buf, "\n%s\n", command->description); } else { cbuf_append(buf, "This command is not available to you.\n"); } } return command_status(cbase, user, cmd, buf); } static int command_uptime(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) { struct cbuffer* buf = cbuf_create(128); size_t d; size_t h; size_t m; size_t D = (size_t) difftime(time(0), cbase->hub->tm_started); d = D / (24 * 3600); D = D % (24 * 3600); h = D / 3600; D = D % 3600; m = D / 60; if (d) cbuf_append_format(buf, "%d day%s, ", (int) d, d != 1 ? "s" : ""); cbuf_append_format(buf, "%02d:%02d", (int) h, (int) m); return command_status(cbase, user, cmd, buf); } static int command_kick(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) { struct cbuffer* buf; struct hub_command_arg_data* arg = hub_command_arg_next(cmd, type_user); struct hub_user* target = arg->data.user; buf = cbuf_create(128); if (target == user) { cbuf_append(buf, "Cannot kick yourself."); } else { cbuf_append_format(buf, "Kicking user \"%s\".", target->id.nick); hub_disconnect_user(cbase->hub, target, quit_kicked); } return command_status(cbase, user, cmd, buf); } static int command_reload(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) { cbase->hub->status = hub_status_restart; return command_status(cbase, user, cmd, cbuf_create_const("Reloading configuration...")); } #ifdef DEBUG_UNLOAD_PLUGINS int hub_plugins_load(struct hub_info* hub); int hub_plugins_unload(struct hub_info* hub); static int command_load(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) { hub_plugins_load(cbase->hub); return command_status(cbase, user, cmd, cbuf_create_const("Loading plugins...")); } static int command_unload(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) { hub_plugins_unload(cbase->hub); return command_status(cbase, user, cmd, cbuf_create_const("Unloading plugins...")); } #endif /* DEBUG_UNLOAD_PLUGINS */ static int command_shutdown_hub(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) { cbase->hub->status = hub_status_shutdown; return command_status(cbase, user, cmd, cbuf_create_const("Hub shutting down...")); } static int command_version(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) { struct cbuffer* buf; if (cbase->hub->config->show_banner_sys_info) buf = cbuf_create_const("Powered by " PRODUCT_STRING " on " OPSYS "/" CPUINFO); else buf = cbuf_create_const("Powered by " PRODUCT_STRING); return command_status(cbase, user, cmd, buf); } static int command_myip(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) { struct cbuffer* buf = cbuf_create(128); cbuf_append_format(buf, "Your address is \"%s\"", user_get_address(user)); return command_status(cbase, user, cmd, buf); } static int command_getip(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) { struct cbuffer* buf = cbuf_create(128); struct hub_command_arg_data* arg = hub_command_arg_next(cmd, type_user); cbuf_append_format(buf, "\"%s\" has address \"%s\"", arg->data.user->id.nick, user_get_address(arg->data.user)); return command_status(cbase, user, cmd, buf); } static int command_whoip(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) { struct cbuffer* buf; struct hub_command_arg_data* arg = hub_command_arg_next(cmd, type_range); struct linked_list* users = (struct linked_list*) list_create(); struct hub_user* u; int ret = 0; ret = uman_get_user_by_addr(cbase->hub->users, users, arg->data.range); if (!ret) { list_clear(users, NULL); list_destroy(users); return command_status(cbase, user, cmd, cbuf_create_const("No users found.")); } buf = cbuf_create(128 + ((MAX_NICK_LEN + INET6_ADDRSTRLEN + 5) * ret)); cbuf_append_format(buf, "*** %s: Found %d match%s:\n", cmd->prefix, ret, ((ret != 1) ? "es" : "")); LIST_FOREACH(struct hub_user*, u, users, { cbuf_append_format(buf, "%s (%s)\n", u->id.nick, user_get_address(u)); }); cbuf_append(buf, "\n"); send_message(cbase, user, buf); list_clear(users, NULL); list_destroy(users); return 0; } static int command_broadcast(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) { struct hub_command_arg_data* arg = hub_command_arg_next(cmd, type_string); char* message = arg->data.string; size_t message_len = strlen(message); char pm_flag[7] = "PM"; char from_sid[5]; size_t recipients = 0; struct hub_user* target; struct cbuffer* buf = cbuf_create(128); struct adc_message* command = NULL; memcpy(from_sid, sid_to_string(user->id.sid), sizeof(from_sid)); memcpy(pm_flag + 2, from_sid, sizeof(from_sid)); LIST_FOREACH(struct hub_user*, target, cbase->hub->users->list, { if (target != user) { recipients++; command = adc_msg_construct(ADC_CMD_DMSG, message_len + 23); if (!command) break; adc_msg_add_argument(command, from_sid); adc_msg_add_argument(command, sid_to_string(target->id.sid)); adc_msg_add_argument(command, message); adc_msg_add_argument(command, pm_flag); route_to_user(cbase->hub, target, command); adc_msg_free(command); } }); cbuf_append_format(buf, "*** %s: Delivered to " PRINTF_SIZE_T " user%s", cmd->prefix, recipients, (recipients != 1 ? "s" : "")); send_message(cbase, user, buf); return 0; } static int command_log(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) { struct cbuffer* buf; struct hub_command_arg_data* arg = hub_command_arg_next(cmd, type_string); struct linked_list* messages = cbase->hub->logout_info; struct hub_logout_info* log; char* search = arg ? arg->data.string : ""; size_t search_len = strlen(search); size_t search_hits = 0; if (!list_size(messages)) { return command_status(cbase, user, cmd, cbuf_create_const("No entries logged.")); } buf = cbuf_create(128); cbuf_append_format(buf, "Logged entries: " PRINTF_SIZE_T, list_size(messages)); if (search_len) { cbuf_append_format(buf, ", searching for \"%s\"", search); } command_status(cbase, user, cmd, buf); buf = cbuf_create(MAX_HELP_LINE); LIST_FOREACH(struct hub_logout_info*, log, messages, { 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) { cbuf_append_format(buf, "* %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(cbase, user, buf); buf = cbuf_create(MAX_HELP_LINE); } }); if (search_len) { cbuf_append_format(buf, PRINTF_SIZE_T " entries shown.", search_hits); command_status(cbase, user, cmd, buf); buf = NULL; } if (buf) cbuf_destroy(buf); return 0; } static int command_stats(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) { struct cbuffer* buf = cbuf_create(128); struct hub_info* hub = cbase->hub; static char rxbuf[64] = { "0 B" }; static char txbuf[64] = { "0 B" }; cbuf_append(buf, "Hub statistics: "); cbuf_append_format(buf, PRINTF_SIZE_T "/" PRINTF_SIZE_T " users (peak %d). ", hub->users->count, hub->config->max_users, hub->users->count_peak); format_size(hub->stats.net_rx, rxbuf, sizeof(rxbuf)); format_size(hub->stats.net_tx, txbuf, sizeof(txbuf)); cbuf_append_format(buf, "Network: tx=%s/s, rx=%s/s", txbuf, rxbuf); #ifdef SHOW_PEAK_NET_STATS /* currently disabled */ format_size(hub->stats.net_rx_peak, rxbuf, sizeof(rxbuf)); format_size(hub->stats.net_tx_peak, txbuf, sizeof(txbuf)); cbuf_append_format(buf, ", peak_tx=%s/s, peak_rx=%s/s", txbuf, rxbuf); #endif format_size(hub->stats.net_rx_total, rxbuf, sizeof(rxbuf)); format_size(hub->stats.net_tx_total, txbuf, sizeof(txbuf)); cbuf_append_format(buf, ", total_tx=%s", txbuf); cbuf_append_format(buf, ", total_rx=%s", rxbuf); return command_status(cbase, user, cmd, buf); } static struct command_handle* add_builtin(struct command_base* cbase, const char* prefix, const char* args, enum auth_credentials cred, command_handler handler, const char* description) { struct command_handle* handle = (struct command_handle*) hub_malloc_zero(sizeof(struct command_handle)); handle->prefix = prefix; handle->length = strlen(prefix); handle->args = args; handle->cred = cred; handle->handler = handler; handle->description = description; handle->origin = "built-in"; handle->ptr = cbase; return handle; } #define ADD_COMMAND(PREFIX, LENGTH, ARGS, CREDENTIALS, FUNCTION, DESCRIPTION) \ command_add(cbase, add_builtin(cbase, PREFIX, ARGS, CREDENTIALS, FUNCTION, DESCRIPTION), NULL) void commands_builtin_add(struct command_base* cbase) { ADD_COMMAND("broadcast", 9, "+m",auth_cred_operator, command_broadcast,"Send a message to all users" ); ADD_COMMAND("getip", 5, "u", auth_cred_operator, command_getip, "Show IP address for a user" ); ADD_COMMAND("help", 4, "?c",auth_cred_guest, command_help, "Show this help message." ); ADD_COMMAND("kick", 4, "u", auth_cred_operator, command_kick, "Kick a user" ); ADD_COMMAND("log", 3, "?m",auth_cred_operator, command_log, "Display log" ); // fail ADD_COMMAND("myip", 4, "", auth_cred_guest, command_myip, "Show your own IP." ); ADD_COMMAND("reload", 6, "", auth_cred_admin, command_reload, "Reload configuration files." ); ADD_COMMAND("shutdown", 8, "", auth_cred_admin, command_shutdown_hub, "Shutdown hub." ); ADD_COMMAND("stats", 5, "", auth_cred_super, command_stats, "Show hub statistics." ); ADD_COMMAND("uptime", 6, "", auth_cred_guest, command_uptime, "Display hub uptime info." ); ADD_COMMAND("version", 7, "", auth_cred_guest, command_version, "Show hub version info." ); ADD_COMMAND("whoip", 5, "r", auth_cred_operator, command_whoip, "Show users matching IP range" ); #ifdef DEBUG_UNLOAD_PLUGINS ADD_COMMAND("load", 4, "", auth_cred_admin, command_load, "Load plugins." ); ADD_COMMAND("unload", 6, "", auth_cred_admin, command_unload, "Unload plugins." ); #endif /* DEBUG_UNLOAD_PLUGINS */ } void commands_builtin_remove(struct command_base* cbase) { struct command_handle* command; while ((command = list_get_first(cbase->handlers))) { command_del(cbase, command); hub_free(command); } } modelrockettier-uhub-a8ee6e7/src/core/commands.h000066400000000000000000000103161324501300100220340ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_COMMANDS_H #define HAVE_UHUB_COMMANDS_H struct command_base; struct command_handle; struct hub_command; /** * Argument codes are used to automatically parse arguments * for a a hub command. * * u = user (must exist in hub session, or will cause error) * n = nick name (string) * i = CID (must exist in hub) * a = (IP) address (must be a valid IPv4 or IPv6 address) * r = (IP) address range (either: IP-IP or IP/mask, both IPv4 or IPv6 work) * m = message (string) * p = password (string) * C = credentials (see auth_string_to_cred). * c = command (name of command) * N = number (integer) * * Prefix an argument with ? to make it optional. * Prefix with + to make the argument greedy, which causes it to grab the rest of the line ignoring boundaries (only supported for string types). * * NOTE: if an argument is optional then all following arguments must also be optional. * NOTE: You can combine optional and greedy, example: "?+m" would match "", "a", "a b c", etc. * * Example: * "nia" means "nick cid ip" * "n?p" means "nick [password]" where password is optional. * "?N?N" means zero, one, or two integers. * "?NN" means zero or two integers. * "?+m" means an optional string which may contain spaces that would otherwise be split into separate arguments. */ struct command_handle { const char* prefix; /**<<< "Command prefix, for instance 'help' would be the prefix for the !help command." */ size_t length; /**<<< "Length of the prefix" */ const char* args; /**<<< "Argument codes (see above)" */ enum auth_credentials cred; /**<<< "Minimum access level for the command" */ command_handler handler; /**<<< "Function pointer for the command" */ const char* description; /**<<< "Description for the command" */ const char* origin; /**<<< "Name of module where the command is implemented." */ void* ptr; /**<<< "A pointer which will be passed along to the handler. @See hub_command::ptr" */ }; /** * Returns NULL on error, or handle */ extern struct command_base* command_initialize(struct hub_info* hub); extern void command_shutdown(struct command_base* cbase); /** * Add a new command to the command base. * Returns 1 on success, or 0 on error. */ extern int command_add(struct command_base*, struct command_handle*, void* ptr); /** * Remove a command from the command base. * Returns 1 on success, or 0 on error. */ extern int command_del(struct command_base*, struct command_handle*); /** * Dispatch a message and forward it as a command. * Returns 1 if the message should be forwarded as a chat message, or 0 if * it is supposed to be handled internally in the dispatcher. * * This will break the message down into a struct hub_command and invoke the command handler * for that command if the sufficient access credentials are met. */ extern int command_invoke(struct command_base*, struct hub_user* user, const char* message); /** * Returns 1 if the command handle can be used with the given credentials, 0 otherwise. */ int command_is_available(struct command_handle* handle, enum auth_credentials credentials); /** * Lookup a command handle based on prefix. * If no matching command handle is found then NULL is returned. */ struct command_handle* command_handler_lookup(struct command_base* cbase, const char* prefix); extern void commands_builtin_add(struct command_base*); extern void commands_builtin_remove(struct command_base*); #endif /* HAVE_UHUB_COMMANDS_H */ modelrockettier-uhub-a8ee6e7/src/core/config.c000066400000000000000000000054361324501300100215020ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" #ifndef INT_MAX #define INT_MAX 0x7fffffff #endif #ifndef INT_MIN #define INT_MIN (-0x7fffffff - 1) #endif static int apply_boolean(const char* key, const char* data, int* target) { return string_to_boolean(data, target); } static int apply_string(const char* key, const char* data, char** target, char* regexp) { (void) regexp; // FIXME: Add regexp checks for correct data if (*target) hub_free(*target); *target = hub_strdup(data); return 1; } static int apply_integer(const char* key, const char* data, int* target, int* min, int* max) { 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) return 0; if (min && val < *min) return 0; if (max && val > *max) return 0; *target = val; return 1; } #include "gen_config.c" 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; strip_off_ini_line_comments(line, line_count); 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); data = strip_off_quotes(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)); config_defaults(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; } } return 0; } modelrockettier-uhub-a8ee6e7/src/core/config.h000066400000000000000000000032221324501300100214760ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_CONFIG_H #define HAVE_UHUB_CONFIG_H #include "gen_config.h" /** * 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 */ modelrockettier-uhub-a8ee6e7/src/core/config.py000077500000000000000000000210201324501300100216760ustar00rootroot00000000000000#!/usr/bin/env python """ uhub - A tiny ADC p2p connection hub Copyright (C) 2007-2013, Jan Vidar Krey """ from xml.dom import minidom, Node from datetime import datetime import argparse class OptionParseError(Exception): pass class Option(object): def _get(self, node, name): self.__dict__[name] = None if (node.getElementsByTagName(name)): self.__dict__[name] = node.getElementsByTagName(name)[0].firstChild.nodeValue def _attr(self, node, name, required = False): try: return node.attributes[name].value except Exception: pass if (required): raise OptionParseError("Option %s is required but not found!" % name) return None def __init__(self, node): self.otype = self._attr(node, 'type', True) # Verify that the type is known if not self.otype in ["int", "boolean", "string", "message", "file"]: raise OptionParseError("Option %s has unknown type" % self.name) self.name = self._attr(node, 'name', True) self.default = self._attr(node, 'default', True) self.advanced = self._attr(node, 'advanced', False) self.is_string = self.otype in ["string", "message", "file"] self._get(node, "short"); self._get(node, "description"); self._get(node, "syntax"); self._get(node, "since"); self._get(node, "example"); check = node.getElementsByTagName("check") if (check): check = node.getElementsByTagName("check")[0] self.check_min = self._attr(check, 'min', False) self.check_max = self._attr(check, 'max', False) self.check_regexp = self._attr(check, 'regexp', False) else: self.check_min = None self.check_max = None self.check_regexp = None def c_type(self): if self.otype == "boolean": return "int" elif self.is_string: return "char*" else: return self.otype def sql_type(self): if self.otype == "int": return "integer" return self.otype def c_comment(self): comment = "" if (self.otype == "message"): comment = self.formatted_default() elif len(self.short): comment = "%s (default: %s)" % (self.short, self.formatted_default()) return comment def formatted_default(self): if self.is_string: return "\"%s\"" % self.default return self.default class SourceGenerator(object): def __init__(self, filename, cppStyle = True): print ("Generating %s..." % filename) self.f = open(filename, 'w'); def write_header(self, Comment = True): if Comment: s = "/*\n * uhub - A tiny ADC p2p connection hub\n" s += " * Copyright (C) 2007-%s, Jan Vidar Krey\n *\n" % datetime.now().strftime("%Y") s += " * THIS FILE IS AUTOGENERATED - DO NOT MODIFY\n" s += " * Created %s, by config.py\n */\n\n" % datetime.now().strftime("%Y-%m-%d %H:%M") self.f.write(s) class CHeaderGenerator(SourceGenerator): def __init__(self, filename): super(CHeaderGenerator, self).__init__(filename) def _write_declaration(self, option): comment = ' ' * (32 - len(option.name)) + "/*<<< %s */" % option.c_comment() ptype = option.c_type() + (5 - len(option.c_type())) * ' ' self.f.write("\t%(type)s %(name)s;%(comment)s\n" % { "type": ptype, "name": option.name, "comment": comment}) def write(self, options): self.write_header() self.f.write("struct hub_config\n{\n") for option in options: self._write_declaration(option) self.f.write("};\n\n") class CSourceGenerator(SourceGenerator): def __init__(self, filename): super(CSourceGenerator, self).__init__(filename) def _write_default_impl(self, option): s = "\tconfig->%s = " % option.name if option.is_string: s += "hub_strdup(%s);\n" % option.formatted_default() else: s += option.formatted_default() + ";\n" self.f.write(s) def _write_apply_impl(self, option): s = "\tif (!strcmp(key, \"%s\"))\n\t{\n" % option.name if option.otype == "int": s_min = "0" s_max = "0" if (option.check_min): s += "\t\tmin = %s;\n" % option.check_min s_min = "&min" if (option.check_max): s += "\t\tmax = %s;\n" % option.check_max s_max = "&max" s+= "\t\tif (!apply_integer(key, data, &config->%s, %s, %s))\n" % (option.name, s_min, s_max) elif option.otype == "boolean": s += "\t\tif (!apply_boolean(key, data, &config->%s))\n" % option.name elif option.is_string: s += "\t\tif (!apply_string(key, data, &config->%s, (char*) \"\"))\n" % option.name s += "\t\t{\n\t\t\tLOG_ERROR(\"Configuration parse error on line %d\", line_count);\n\t\t\treturn -1;\n\t\t}\n\t\treturn 0;\n\t}\n\n" self.f.write(s) def _write_free_impl(self, option): if option.is_string: self.f.write("\thub_free(config->%s);\n\n" % option.name) def _write_dump_impl(self, option): s = "" fmt = "%s" val = "config->%s" % option.name test = "config->%s != %s" % (option.name, option.default) if (option.otype == "int"): fmt = "%d" elif (option.otype == "boolean"): val = "config->%s ? \"yes\" : \"no\"" % option.name elif (option.is_string): fmt = "\\\"%s\\\""; test = "strcmp(config->%s, %s) != 0" % (option.name, option.formatted_default()) s += "\tif (!ignore_defaults || %s)\n" % test; s += "\t\tfprintf(stdout, \"%s = %s\\n\", %s);\n\n" % (option.name, fmt, val) self.f.write(s) def write(self, options): self.write_header() self.f.write("void config_defaults(struct hub_config* config)\n{\n") for option in options: self._write_default_impl(option) self.f.write("}\n\n") self.f.write("static int apply_config(struct hub_config* config, char* key, char* data, int line_count)\n{\n\tint max = 0;\n\tint min = 0;\n\n") for option in options: self._write_apply_impl(option) self.f.write("\t/* Still here -- unknown directive */\n\tLOG_ERROR(\"Unknown configuration directive: '%s'\", key);\n\treturn -1;\n}\n\n") self.f.write("void free_config(struct hub_config* config)\n{\n") for option in options: self._write_free_impl(option) self.f.write("}\n\n") self.f.write("void dump_config(struct hub_config* config, int ignore_defaults)\n{\n") for option in options: self._write_dump_impl(option) self.f.write("}\n\n") class SqlWebsiteDocsGenerator(SourceGenerator): def __init__(self, filename, sqlite_support = False): self.sqlite_support = sqlite_support super(SqlWebsiteDocsGenerator, self).__init__(filename) def _sql_escape(self, s): if self.sqlite_support: return s.replace("\"", "\"\"") return s.replace("\"", "\\\"") def _write_or_null(self, s): if (not s or len(s) == 0): return "NULL" return "\"%s\"" % self._sql_escape(s) def write(self, options): self.write_header(False) table = "uhub_config" s = "" if not self.sqlite_support: s += "START TRANSACTION;\n\nDROP TABLE %(table)s IF EXISTS;" % { "table": table } s += "\n\nCREATE TABLE %(table)s (\n\tname VARCHAR(32) UNIQUE NOT NULL,\n\tdefaultValue TINYTEXT NOT NULL,\n\tdescription LONGTEXT NOT NULL,\n\ttype TINYTEXT NOT NULL,\n\tadvanced BOOLEAN,\n\texample LONGTEXT,\n\tsince TINYTEXT\n);\n\n" % { "table": table } self.f.write(s) for option in options: s = "INSERT INTO %(table)s VALUES(\"%(name)s\", \"%(default)s\", \"%(description)s\", \"%(type)s\", %(example)s, %(since)s, %(advanced)s);\n" % { "table": table, "name": self._sql_escape(option.name), "default": self._sql_escape(option.formatted_default()), "description": self._sql_escape(option.description), "type": option.sql_type(), "example": self._write_or_null(option.example), "since": self._write_or_null(option.since), "advanced": self._write_or_null(option.example), } self.f.write(s) if not self.sqlite_support: self.f.write("\n\nCOMMIT;\n\n") if __name__ == "__main__": # parser = argparse.ArgumentParser(description = "Configuration file parser and source generator") # parser.add_argument("--in", nargs=1, type=argparse.FileType('r'), default="config.xml", help="Input file (config.xml)", required = True) # parser.add_argument("--c-decl", nargs=1, type=argparse.FileType('w'), default="gen_config.h", help="Output file for C declarations (gen_config.h)") # parser.add_argument("--c-impl", nargs=1, type=argparse.FileType('w'), default="gen_config.c", help="Output file for C implementation (gen_config.c)") # parser.add_argument("--doc-sql", nargs=1, type=argparse.FileType('w'), help="Output file for SQL documentation") # args = parser.parse_args() xmldoc = minidom.parse("./config.xml") opt_tags = xmldoc.getElementsByTagName('option') options = [] for option in opt_tags: opt = Option(option) options.append(opt) header = CHeaderGenerator("./gen_config.h"); header.write(options); source = CSourceGenerator("./gen_config.c"); source.write(options); #sql = SqlWebsiteDocsGenerator("./gen_config.sql", True); #sql.write(options); modelrockettier-uhub-a8ee6e7/src/core/config.xml000066400000000000000000000667561324501300100220740ustar00rootroot00000000000000 modelrockettier-uhub-a8ee6e7/src/core/eventid.h000066400000000000000000000024401324501300100216700ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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 */ modelrockettier-uhub-a8ee6e7/src/core/eventqueue.c000066400000000000000000000057631324501300100224260ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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; LIST_FOREACH(struct event_data*, data, queue->q1, { #ifdef EQ_DEBUG eq_debug("EXEC", data); #endif queue->callback(queue->callback_data, data); }); list_clear(queue->q1, event_queue_cleanup_callback); uhub_assert(list_size(queue->q1) == 0); /* unlock queue */ queue->locked = 0; /* transfer from secondary queue to the primary queue. */ list_append_list(queue->q1, 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); } modelrockettier-uhub-a8ee6e7/src/core/eventqueue.h000066400000000000000000000030301324501300100224140ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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 */ modelrockettier-uhub-a8ee6e7/src/core/gen_config.c000066400000000000000000001141731324501300100223320ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, Jan Vidar Krey * * THIS FILE IS AUTOGENERATED - DO NOT MODIFY * Created 2014-07-29 12:22, by config.py */ void config_defaults(struct hub_config* config) { config->hub_enabled = 1; config->server_port = 1511; config->server_bind_addr = hub_strdup("any"); config->server_listen_backlog = 50; config->server_alt_ports = hub_strdup(""); config->show_banner = 1; config->show_banner_sys_info = 1; config->max_users = 500; config->registered_users_only = 0; config->register_self = 0; config->obsolete_clients = 0; config->chat_is_privileged = 0; config->hub_name = hub_strdup("uhub"); config->hub_description = hub_strdup("no description"); config->redirect_addr = hub_strdup(""); config->max_recv_buffer = 4096; config->max_send_buffer = 131072; config->max_send_buffer_soft = 98304; config->low_bandwidth_mode = 0; config->max_chat_history = 20; config->max_logout_log = 20; config->limit_max_hubs_user = 10; config->limit_max_hubs_reg = 10; config->limit_max_hubs_op = 10; config->limit_max_hubs = 25; config->limit_min_hubs_user = 0; config->limit_min_hubs_reg = 0; config->limit_min_hubs_op = 0; config->limit_min_share = 0; config->limit_max_share = 0; config->limit_min_slots = 0; config->limit_max_slots = 0; config->flood_ctl_interval = 0; config->flood_ctl_chat = 0; config->flood_ctl_connect = 0; config->flood_ctl_search = 0; config->flood_ctl_update = 0; config->flood_ctl_extras = 0; config->tls_enable = 0; config->tls_require = 0; config->tls_require_redirect_addr = hub_strdup(""); config->tls_certificate = hub_strdup(""); config->tls_private_key = hub_strdup(""); config->tls_ciphersuite = hub_strdup("ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS"); config->tls_version = hub_strdup("1.2"); config->file_acl = hub_strdup(""); config->file_plugins = hub_strdup(""); config->msg_hub_full = hub_strdup("Hub is full"); config->msg_hub_disabled = hub_strdup("Hub is disabled"); config->msg_hub_registered_users_only = hub_strdup("Hub is for registered users only"); config->msg_inf_error_nick_missing = hub_strdup("No nickname given"); config->msg_inf_error_nick_multiple = hub_strdup("Multiple nicknames given"); config->msg_inf_error_nick_invalid = hub_strdup("Nickname is invalid"); config->msg_inf_error_nick_long = hub_strdup("Nickname too long"); config->msg_inf_error_nick_short = hub_strdup("Nickname too short"); config->msg_inf_error_nick_spaces = hub_strdup("Nickname cannot start with spaces"); config->msg_inf_error_nick_bad_chars = hub_strdup("Nickname contains invalid characters"); config->msg_inf_error_nick_not_utf8 = hub_strdup("Nickname is not valid UTF-8"); config->msg_inf_error_nick_taken = hub_strdup("Nickname is already in use"); config->msg_inf_error_nick_restricted = hub_strdup("Nickname cannot be used on this hub"); config->msg_inf_error_cid_invalid = hub_strdup("CID is not valid"); config->msg_inf_error_cid_missing = hub_strdup("CID is not specified"); config->msg_inf_error_cid_taken = hub_strdup("CID is taken"); config->msg_inf_error_pid_missing = hub_strdup("PID is not specified"); config->msg_inf_error_pid_invalid = hub_strdup("PID is invalid"); config->msg_ban_permanently = hub_strdup("Banned permanently"); config->msg_ban_temporarily = hub_strdup("Banned temporarily"); config->msg_auth_invalid_password = hub_strdup("Password is wrong"); config->msg_auth_user_not_found = hub_strdup("User not found in password database"); config->msg_error_no_memory = hub_strdup("No memory"); config->msg_user_share_size_low = hub_strdup("User is not sharing enough"); config->msg_user_share_size_high = hub_strdup("User is sharing too much"); config->msg_user_slots_low = hub_strdup("User have too few upload slots."); config->msg_user_slots_high = hub_strdup("User have too many upload slots."); config->msg_user_hub_limit_low = hub_strdup("User is on too few hubs."); config->msg_user_hub_limit_high = hub_strdup("User is on too many hubs."); config->msg_user_flood_chat = hub_strdup("Chat flood detected, messages are dropped."); config->msg_user_flood_connect = hub_strdup("Connect flood detected, connection refused."); config->msg_user_flood_search = hub_strdup("Search flood detected, search is stopped."); config->msg_user_flood_update = hub_strdup("Update flood detected."); config->msg_user_flood_extras = hub_strdup("Flood detected."); config->msg_proto_no_common_hash = hub_strdup("No common hash algorithm."); config->msg_proto_obsolete_adc0 = hub_strdup("Client is using an obsolete ADC protocol version."); } static int apply_config(struct hub_config* config, char* key, char* data, int line_count) { int max = 0; int min = 0; if (!strcmp(key, "hub_enabled")) { if (!apply_boolean(key, data, &config->hub_enabled)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "server_port")) { min = 1; max = 65535; if (!apply_integer(key, data, &config->server_port, &min, &max)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "server_bind_addr")) { if (!apply_string(key, data, &config->server_bind_addr, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "server_listen_backlog")) { min = 5; if (!apply_integer(key, data, &config->server_listen_backlog, &min, 0)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "server_alt_ports")) { if (!apply_string(key, data, &config->server_alt_ports, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "show_banner")) { if (!apply_boolean(key, data, &config->show_banner)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "show_banner_sys_info")) { if (!apply_boolean(key, data, &config->show_banner_sys_info)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "max_users")) { min = 1; max = 1048576; if (!apply_integer(key, data, &config->max_users, &min, &max)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "registered_users_only")) { if (!apply_boolean(key, data, &config->registered_users_only)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "register_self")) { if (!apply_boolean(key, data, &config->register_self)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "obsolete_clients")) { if (!apply_boolean(key, data, &config->obsolete_clients)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "chat_is_privileged")) { if (!apply_boolean(key, data, &config->chat_is_privileged)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "hub_name")) { if (!apply_string(key, data, &config->hub_name, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "hub_description")) { if (!apply_string(key, data, &config->hub_description, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "redirect_addr")) { if (!apply_string(key, data, &config->redirect_addr, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "max_recv_buffer")) { min = 1024; max = 1048576; if (!apply_integer(key, data, &config->max_recv_buffer, &min, &max)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "max_send_buffer")) { min = 2048; if (!apply_integer(key, data, &config->max_send_buffer, &min, 0)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "max_send_buffer_soft")) { min = 1024; if (!apply_integer(key, data, &config->max_send_buffer_soft, &min, 0)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "low_bandwidth_mode")) { if (!apply_boolean(key, data, &config->low_bandwidth_mode)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "max_chat_history")) { min = 0; max = 250; if (!apply_integer(key, data, &config->max_chat_history, &min, &max)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "max_logout_log")) { min = 0; max = 2000; if (!apply_integer(key, data, &config->max_logout_log, &min, &max)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "limit_max_hubs_user")) { min = 0; if (!apply_integer(key, data, &config->limit_max_hubs_user, &min, 0)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "limit_max_hubs_reg")) { min = 0; if (!apply_integer(key, data, &config->limit_max_hubs_reg, &min, 0)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "limit_max_hubs_op")) { min = 0; if (!apply_integer(key, data, &config->limit_max_hubs_op, &min, 0)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "limit_max_hubs")) { min = 0; if (!apply_integer(key, data, &config->limit_max_hubs, &min, 0)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "limit_min_hubs_user")) { min = 0; if (!apply_integer(key, data, &config->limit_min_hubs_user, &min, 0)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "limit_min_hubs_reg")) { min = 0; if (!apply_integer(key, data, &config->limit_min_hubs_reg, &min, 0)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "limit_min_hubs_op")) { min = 0; if (!apply_integer(key, data, &config->limit_min_hubs_op, &min, 0)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "limit_min_share")) { min = 0; if (!apply_integer(key, data, &config->limit_min_share, &min, 0)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "limit_max_share")) { min = 0; if (!apply_integer(key, data, &config->limit_max_share, &min, 0)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "limit_min_slots")) { min = 0; if (!apply_integer(key, data, &config->limit_min_slots, &min, 0)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "limit_max_slots")) { min = 0; if (!apply_integer(key, data, &config->limit_max_slots, &min, 0)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "flood_ctl_interval")) { min = 1; max = 60; if (!apply_integer(key, data, &config->flood_ctl_interval, &min, &max)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "flood_ctl_chat")) { if (!apply_integer(key, data, &config->flood_ctl_chat, 0, 0)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "flood_ctl_connect")) { if (!apply_integer(key, data, &config->flood_ctl_connect, 0, 0)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "flood_ctl_search")) { if (!apply_integer(key, data, &config->flood_ctl_search, 0, 0)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "flood_ctl_update")) { if (!apply_integer(key, data, &config->flood_ctl_update, 0, 0)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "flood_ctl_extras")) { if (!apply_integer(key, data, &config->flood_ctl_extras, 0, 0)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "tls_enable")) { if (!apply_boolean(key, data, &config->tls_enable)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "tls_require")) { if (!apply_boolean(key, data, &config->tls_require)) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "tls_require_redirect_addr")) { if (!apply_string(key, data, &config->tls_require_redirect_addr, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "tls_certificate")) { if (!apply_string(key, data, &config->tls_certificate, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "tls_private_key")) { if (!apply_string(key, data, &config->tls_private_key, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "tls_ciphersuite")) { if (!apply_string(key, data, &config->tls_ciphersuite, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "tls_version")) { if (!apply_string(key, data, &config->tls_version, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "file_acl")) { if (!apply_string(key, data, &config->file_acl, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "file_plugins")) { if (!apply_string(key, data, &config->file_plugins, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_hub_full")) { if (!apply_string(key, data, &config->msg_hub_full, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_hub_disabled")) { if (!apply_string(key, data, &config->msg_hub_disabled, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_hub_registered_users_only")) { if (!apply_string(key, data, &config->msg_hub_registered_users_only, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_inf_error_nick_missing")) { if (!apply_string(key, data, &config->msg_inf_error_nick_missing, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_inf_error_nick_multiple")) { if (!apply_string(key, data, &config->msg_inf_error_nick_multiple, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_inf_error_nick_invalid")) { if (!apply_string(key, data, &config->msg_inf_error_nick_invalid, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_inf_error_nick_long")) { if (!apply_string(key, data, &config->msg_inf_error_nick_long, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_inf_error_nick_short")) { if (!apply_string(key, data, &config->msg_inf_error_nick_short, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_inf_error_nick_spaces")) { if (!apply_string(key, data, &config->msg_inf_error_nick_spaces, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_inf_error_nick_bad_chars")) { if (!apply_string(key, data, &config->msg_inf_error_nick_bad_chars, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_inf_error_nick_not_utf8")) { if (!apply_string(key, data, &config->msg_inf_error_nick_not_utf8, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_inf_error_nick_taken")) { if (!apply_string(key, data, &config->msg_inf_error_nick_taken, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_inf_error_nick_restricted")) { if (!apply_string(key, data, &config->msg_inf_error_nick_restricted, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_inf_error_cid_invalid")) { if (!apply_string(key, data, &config->msg_inf_error_cid_invalid, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_inf_error_cid_missing")) { if (!apply_string(key, data, &config->msg_inf_error_cid_missing, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_inf_error_cid_taken")) { if (!apply_string(key, data, &config->msg_inf_error_cid_taken, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_inf_error_pid_missing")) { if (!apply_string(key, data, &config->msg_inf_error_pid_missing, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_inf_error_pid_invalid")) { if (!apply_string(key, data, &config->msg_inf_error_pid_invalid, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_ban_permanently")) { if (!apply_string(key, data, &config->msg_ban_permanently, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_ban_temporarily")) { if (!apply_string(key, data, &config->msg_ban_temporarily, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_auth_invalid_password")) { if (!apply_string(key, data, &config->msg_auth_invalid_password, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_auth_user_not_found")) { if (!apply_string(key, data, &config->msg_auth_user_not_found, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_error_no_memory")) { if (!apply_string(key, data, &config->msg_error_no_memory, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_user_share_size_low")) { if (!apply_string(key, data, &config->msg_user_share_size_low, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_user_share_size_high")) { if (!apply_string(key, data, &config->msg_user_share_size_high, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_user_slots_low")) { if (!apply_string(key, data, &config->msg_user_slots_low, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_user_slots_high")) { if (!apply_string(key, data, &config->msg_user_slots_high, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_user_hub_limit_low")) { if (!apply_string(key, data, &config->msg_user_hub_limit_low, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_user_hub_limit_high")) { if (!apply_string(key, data, &config->msg_user_hub_limit_high, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_user_flood_chat")) { if (!apply_string(key, data, &config->msg_user_flood_chat, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_user_flood_connect")) { if (!apply_string(key, data, &config->msg_user_flood_connect, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_user_flood_search")) { if (!apply_string(key, data, &config->msg_user_flood_search, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_user_flood_update")) { if (!apply_string(key, data, &config->msg_user_flood_update, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_user_flood_extras")) { if (!apply_string(key, data, &config->msg_user_flood_extras, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_proto_no_common_hash")) { if (!apply_string(key, data, &config->msg_proto_no_common_hash, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } if (!strcmp(key, "msg_proto_obsolete_adc0")) { if (!apply_string(key, data, &config->msg_proto_obsolete_adc0, (char*) "")) { LOG_ERROR("Configuration parse error on line %d", line_count); return -1; } return 0; } /* 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->server_alt_ports); hub_free(config->hub_name); hub_free(config->hub_description); hub_free(config->redirect_addr); hub_free(config->tls_require_redirect_addr); hub_free(config->tls_certificate); hub_free(config->tls_private_key); hub_free(config->tls_ciphersuite); hub_free(config->tls_version); hub_free(config->file_acl); hub_free(config->file_plugins); 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->msg_user_flood_chat); hub_free(config->msg_user_flood_connect); hub_free(config->msg_user_flood_search); hub_free(config->msg_user_flood_update); hub_free(config->msg_user_flood_extras); hub_free(config->msg_proto_no_common_hash); hub_free(config->msg_proto_obsolete_adc0); } void dump_config(struct hub_config* config, int ignore_defaults) { if (!ignore_defaults || config->hub_enabled != 1) fprintf(stdout, "hub_enabled = %s\n", config->hub_enabled ? "yes" : "no"); if (!ignore_defaults || config->server_port != 1511) fprintf(stdout, "server_port = %d\n", config->server_port); if (!ignore_defaults || strcmp(config->server_bind_addr, "any") != 0) fprintf(stdout, "server_bind_addr = \"%s\"\n", config->server_bind_addr); if (!ignore_defaults || config->server_listen_backlog != 50) fprintf(stdout, "server_listen_backlog = %d\n", config->server_listen_backlog); if (!ignore_defaults || strcmp(config->server_alt_ports, "") != 0) fprintf(stdout, "server_alt_ports = \"%s\"\n", config->server_alt_ports); if (!ignore_defaults || config->show_banner != 1) fprintf(stdout, "show_banner = %s\n", config->show_banner ? "yes" : "no"); if (!ignore_defaults || config->show_banner_sys_info != 1) fprintf(stdout, "show_banner_sys_info = %s\n", config->show_banner_sys_info ? "yes" : "no"); if (!ignore_defaults || config->max_users != 500) fprintf(stdout, "max_users = %d\n", config->max_users); if (!ignore_defaults || config->registered_users_only != 0) fprintf(stdout, "registered_users_only = %s\n", config->registered_users_only ? "yes" : "no"); if (!ignore_defaults || config->register_self != 0) fprintf(stdout, "register_self = %s\n", config->register_self ? "yes" : "no"); if (!ignore_defaults || config->obsolete_clients != 0) fprintf(stdout, "obsolete_clients = %s\n", config->obsolete_clients ? "yes" : "no"); if (!ignore_defaults || config->chat_is_privileged != 0) fprintf(stdout, "chat_is_privileged = %s\n", config->chat_is_privileged ? "yes" : "no"); if (!ignore_defaults || strcmp(config->hub_name, "uhub") != 0) fprintf(stdout, "hub_name = \"%s\"\n", config->hub_name); if (!ignore_defaults || strcmp(config->hub_description, "no description") != 0) fprintf(stdout, "hub_description = \"%s\"\n", config->hub_description); if (!ignore_defaults || strcmp(config->redirect_addr, "") != 0) fprintf(stdout, "redirect_addr = \"%s\"\n", config->redirect_addr); if (!ignore_defaults || config->max_recv_buffer != 4096) fprintf(stdout, "max_recv_buffer = %d\n", config->max_recv_buffer); if (!ignore_defaults || config->max_send_buffer != 131072) fprintf(stdout, "max_send_buffer = %d\n", config->max_send_buffer); if (!ignore_defaults || config->max_send_buffer_soft != 98304) fprintf(stdout, "max_send_buffer_soft = %d\n", config->max_send_buffer_soft); if (!ignore_defaults || config->low_bandwidth_mode != 0) fprintf(stdout, "low_bandwidth_mode = %s\n", config->low_bandwidth_mode ? "yes" : "no"); if (!ignore_defaults || config->max_chat_history != 20) fprintf(stdout, "max_chat_history = %d\n", config->max_chat_history); if (!ignore_defaults || config->max_logout_log != 20) fprintf(stdout, "max_logout_log = %d\n", config->max_logout_log); if (!ignore_defaults || config->limit_max_hubs_user != 10) fprintf(stdout, "limit_max_hubs_user = %d\n", config->limit_max_hubs_user); if (!ignore_defaults || config->limit_max_hubs_reg != 10) fprintf(stdout, "limit_max_hubs_reg = %d\n", config->limit_max_hubs_reg); if (!ignore_defaults || config->limit_max_hubs_op != 10) fprintf(stdout, "limit_max_hubs_op = %d\n", config->limit_max_hubs_op); if (!ignore_defaults || config->limit_max_hubs != 25) fprintf(stdout, "limit_max_hubs = %d\n", config->limit_max_hubs); if (!ignore_defaults || config->limit_min_hubs_user != 0) fprintf(stdout, "limit_min_hubs_user = %d\n", config->limit_min_hubs_user); if (!ignore_defaults || config->limit_min_hubs_reg != 0) fprintf(stdout, "limit_min_hubs_reg = %d\n", config->limit_min_hubs_reg); if (!ignore_defaults || config->limit_min_hubs_op != 0) fprintf(stdout, "limit_min_hubs_op = %d\n", config->limit_min_hubs_op); if (!ignore_defaults || config->limit_min_share != 0) fprintf(stdout, "limit_min_share = %d\n", config->limit_min_share); if (!ignore_defaults || config->limit_max_share != 0) fprintf(stdout, "limit_max_share = %d\n", config->limit_max_share); if (!ignore_defaults || config->limit_min_slots != 0) fprintf(stdout, "limit_min_slots = %d\n", config->limit_min_slots); if (!ignore_defaults || config->limit_max_slots != 0) fprintf(stdout, "limit_max_slots = %d\n", config->limit_max_slots); if (!ignore_defaults || config->flood_ctl_interval != 0) fprintf(stdout, "flood_ctl_interval = %d\n", config->flood_ctl_interval); if (!ignore_defaults || config->flood_ctl_chat != 0) fprintf(stdout, "flood_ctl_chat = %d\n", config->flood_ctl_chat); if (!ignore_defaults || config->flood_ctl_connect != 0) fprintf(stdout, "flood_ctl_connect = %d\n", config->flood_ctl_connect); if (!ignore_defaults || config->flood_ctl_search != 0) fprintf(stdout, "flood_ctl_search = %d\n", config->flood_ctl_search); if (!ignore_defaults || config->flood_ctl_update != 0) fprintf(stdout, "flood_ctl_update = %d\n", config->flood_ctl_update); if (!ignore_defaults || config->flood_ctl_extras != 0) fprintf(stdout, "flood_ctl_extras = %d\n", config->flood_ctl_extras); if (!ignore_defaults || config->tls_enable != 0) fprintf(stdout, "tls_enable = %s\n", config->tls_enable ? "yes" : "no"); if (!ignore_defaults || config->tls_require != 0) fprintf(stdout, "tls_require = %s\n", config->tls_require ? "yes" : "no"); if (!ignore_defaults || strcmp(config->tls_require_redirect_addr, "") != 0) fprintf(stdout, "tls_require_redirect_addr = \"%s\"\n", config->tls_require_redirect_addr); if (!ignore_defaults || strcmp(config->tls_certificate, "") != 0) fprintf(stdout, "tls_certificate = \"%s\"\n", config->tls_certificate); if (!ignore_defaults || strcmp(config->tls_private_key, "") != 0) fprintf(stdout, "tls_private_key = \"%s\"\n", config->tls_private_key); if (!ignore_defaults || strcmp(config->tls_ciphersuite, "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS") != 0) fprintf(stdout, "tls_ciphersuite = \"%s\"\n", config->tls_ciphersuite); if (!ignore_defaults || strcmp(config->tls_version, "1.2") != 0) fprintf(stdout, "tls_version = \"%s\"\n", config->tls_version); if (!ignore_defaults || strcmp(config->file_acl, "") != 0) fprintf(stdout, "file_acl = \"%s\"\n", config->file_acl); if (!ignore_defaults || strcmp(config->file_plugins, "") != 0) fprintf(stdout, "file_plugins = \"%s\"\n", config->file_plugins); if (!ignore_defaults || strcmp(config->msg_hub_full, "Hub is full") != 0) fprintf(stdout, "msg_hub_full = \"%s\"\n", config->msg_hub_full); if (!ignore_defaults || strcmp(config->msg_hub_disabled, "Hub is disabled") != 0) fprintf(stdout, "msg_hub_disabled = \"%s\"\n", config->msg_hub_disabled); if (!ignore_defaults || strcmp(config->msg_hub_registered_users_only, "Hub is for registered users only") != 0) fprintf(stdout, "msg_hub_registered_users_only = \"%s\"\n", config->msg_hub_registered_users_only); if (!ignore_defaults || strcmp(config->msg_inf_error_nick_missing, "No nickname given") != 0) fprintf(stdout, "msg_inf_error_nick_missing = \"%s\"\n", config->msg_inf_error_nick_missing); if (!ignore_defaults || strcmp(config->msg_inf_error_nick_multiple, "Multiple nicknames given") != 0) fprintf(stdout, "msg_inf_error_nick_multiple = \"%s\"\n", config->msg_inf_error_nick_multiple); if (!ignore_defaults || strcmp(config->msg_inf_error_nick_invalid, "Nickname is invalid") != 0) fprintf(stdout, "msg_inf_error_nick_invalid = \"%s\"\n", config->msg_inf_error_nick_invalid); if (!ignore_defaults || strcmp(config->msg_inf_error_nick_long, "Nickname too long") != 0) fprintf(stdout, "msg_inf_error_nick_long = \"%s\"\n", config->msg_inf_error_nick_long); if (!ignore_defaults || strcmp(config->msg_inf_error_nick_short, "Nickname too short") != 0) fprintf(stdout, "msg_inf_error_nick_short = \"%s\"\n", config->msg_inf_error_nick_short); if (!ignore_defaults || strcmp(config->msg_inf_error_nick_spaces, "Nickname cannot start with spaces") != 0) fprintf(stdout, "msg_inf_error_nick_spaces = \"%s\"\n", config->msg_inf_error_nick_spaces); if (!ignore_defaults || strcmp(config->msg_inf_error_nick_bad_chars, "Nickname contains invalid characters") != 0) fprintf(stdout, "msg_inf_error_nick_bad_chars = \"%s\"\n", config->msg_inf_error_nick_bad_chars); if (!ignore_defaults || strcmp(config->msg_inf_error_nick_not_utf8, "Nickname is not valid UTF-8") != 0) fprintf(stdout, "msg_inf_error_nick_not_utf8 = \"%s\"\n", config->msg_inf_error_nick_not_utf8); if (!ignore_defaults || strcmp(config->msg_inf_error_nick_taken, "Nickname is already in use") != 0) fprintf(stdout, "msg_inf_error_nick_taken = \"%s\"\n", config->msg_inf_error_nick_taken); if (!ignore_defaults || strcmp(config->msg_inf_error_nick_restricted, "Nickname cannot be used on this hub") != 0) fprintf(stdout, "msg_inf_error_nick_restricted = \"%s\"\n", config->msg_inf_error_nick_restricted); if (!ignore_defaults || strcmp(config->msg_inf_error_cid_invalid, "CID is not valid") != 0) fprintf(stdout, "msg_inf_error_cid_invalid = \"%s\"\n", config->msg_inf_error_cid_invalid); if (!ignore_defaults || strcmp(config->msg_inf_error_cid_missing, "CID is not specified") != 0) fprintf(stdout, "msg_inf_error_cid_missing = \"%s\"\n", config->msg_inf_error_cid_missing); if (!ignore_defaults || strcmp(config->msg_inf_error_cid_taken, "CID is taken") != 0) fprintf(stdout, "msg_inf_error_cid_taken = \"%s\"\n", config->msg_inf_error_cid_taken); if (!ignore_defaults || strcmp(config->msg_inf_error_pid_missing, "PID is not specified") != 0) fprintf(stdout, "msg_inf_error_pid_missing = \"%s\"\n", config->msg_inf_error_pid_missing); if (!ignore_defaults || strcmp(config->msg_inf_error_pid_invalid, "PID is invalid") != 0) fprintf(stdout, "msg_inf_error_pid_invalid = \"%s\"\n", config->msg_inf_error_pid_invalid); if (!ignore_defaults || strcmp(config->msg_ban_permanently, "Banned permanently") != 0) fprintf(stdout, "msg_ban_permanently = \"%s\"\n", config->msg_ban_permanently); if (!ignore_defaults || strcmp(config->msg_ban_temporarily, "Banned temporarily") != 0) fprintf(stdout, "msg_ban_temporarily = \"%s\"\n", config->msg_ban_temporarily); if (!ignore_defaults || strcmp(config->msg_auth_invalid_password, "Password is wrong") != 0) fprintf(stdout, "msg_auth_invalid_password = \"%s\"\n", config->msg_auth_invalid_password); if (!ignore_defaults || strcmp(config->msg_auth_user_not_found, "User not found in password database") != 0) fprintf(stdout, "msg_auth_user_not_found = \"%s\"\n", config->msg_auth_user_not_found); if (!ignore_defaults || strcmp(config->msg_error_no_memory, "No memory") != 0) fprintf(stdout, "msg_error_no_memory = \"%s\"\n", config->msg_error_no_memory); if (!ignore_defaults || strcmp(config->msg_user_share_size_low, "User is not sharing enough") != 0) fprintf(stdout, "msg_user_share_size_low = \"%s\"\n", config->msg_user_share_size_low); if (!ignore_defaults || strcmp(config->msg_user_share_size_high, "User is sharing too much") != 0) fprintf(stdout, "msg_user_share_size_high = \"%s\"\n", config->msg_user_share_size_high); if (!ignore_defaults || strcmp(config->msg_user_slots_low, "User have too few upload slots.") != 0) fprintf(stdout, "msg_user_slots_low = \"%s\"\n", config->msg_user_slots_low); if (!ignore_defaults || strcmp(config->msg_user_slots_high, "User have too many upload slots.") != 0) fprintf(stdout, "msg_user_slots_high = \"%s\"\n", config->msg_user_slots_high); if (!ignore_defaults || strcmp(config->msg_user_hub_limit_low, "User is on too few hubs.") != 0) fprintf(stdout, "msg_user_hub_limit_low = \"%s\"\n", config->msg_user_hub_limit_low); if (!ignore_defaults || strcmp(config->msg_user_hub_limit_high, "User is on too many hubs.") != 0) fprintf(stdout, "msg_user_hub_limit_high = \"%s\"\n", config->msg_user_hub_limit_high); if (!ignore_defaults || strcmp(config->msg_user_flood_chat, "Chat flood detected, messages are dropped.") != 0) fprintf(stdout, "msg_user_flood_chat = \"%s\"\n", config->msg_user_flood_chat); if (!ignore_defaults || strcmp(config->msg_user_flood_connect, "Connect flood detected, connection refused.") != 0) fprintf(stdout, "msg_user_flood_connect = \"%s\"\n", config->msg_user_flood_connect); if (!ignore_defaults || strcmp(config->msg_user_flood_search, "Search flood detected, search is stopped.") != 0) fprintf(stdout, "msg_user_flood_search = \"%s\"\n", config->msg_user_flood_search); if (!ignore_defaults || strcmp(config->msg_user_flood_update, "Update flood detected.") != 0) fprintf(stdout, "msg_user_flood_update = \"%s\"\n", config->msg_user_flood_update); if (!ignore_defaults || strcmp(config->msg_user_flood_extras, "Flood detected.") != 0) fprintf(stdout, "msg_user_flood_extras = \"%s\"\n", config->msg_user_flood_extras); if (!ignore_defaults || strcmp(config->msg_proto_no_common_hash, "No common hash algorithm.") != 0) fprintf(stdout, "msg_proto_no_common_hash = \"%s\"\n", config->msg_proto_no_common_hash); if (!ignore_defaults || strcmp(config->msg_proto_obsolete_adc0, "Client is using an obsolete ADC protocol version.") != 0) fprintf(stdout, "msg_proto_obsolete_adc0 = \"%s\"\n", config->msg_proto_obsolete_adc0); } modelrockettier-uhub-a8ee6e7/src/core/gen_config.h000066400000000000000000000173061324501300100223370ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, Jan Vidar Krey * * THIS FILE IS AUTOGENERATED - DO NOT MODIFY * Created 2014-07-29 12:22, by config.py */ struct hub_config { int hub_enabled; /*<<< Is server enabled (default: 1) */ int server_port; /*<<< Server port to bind to (default: 1511) */ char* server_bind_addr; /*<<< Server bind address (default: "any") */ int server_listen_backlog; /*<<< Server listen backlog (default: 50) */ char* server_alt_ports; /*<<< Comma separated list of alternative ports to listen to (default: "") */ int show_banner; /*<<< Show banner on connect (default: 1) */ int show_banner_sys_info; /*<<< 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 register_self; /*<<< Allow users to register themselves on the hub. (default: 0) */ int obsolete_clients; /*<<< Support obsolete clients using a ADC protocol prior to 1.0 (default: 0) */ int chat_is_privileged; /*<<< Allow chat for operators and above only (default: 0) */ char* hub_name; /*<<< Name of hub (default: "uhub") */ char* hub_description; /*<<< Short hub description, topic or subject. (default: "no description") */ char* redirect_addr; /*<<< A common hub redirect address. (default: "") */ 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: 131072) */ int max_send_buffer_soft; /*<<< Max send buffer before message drops, per user (default: 98304) */ int low_bandwidth_mode; /*<<< Enable bandwidth saving measures (default: 0) */ 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: 20) */ int limit_max_hubs_user; /*<<< Max concurrent hubs as a guest user (default: 10) */ int limit_max_hubs_reg; /*<<< Max concurrent hubs as a registered user (default: 10) */ int limit_max_hubs_op; /*<<< Max concurrent hubs as a operator (or admin) (default: 10) */ int limit_max_hubs; /*<<< Max total hub connections allowed, user/reg/op combined. (default: 25) */ int limit_min_hubs_user; /*<<< Minimum concurrent hubs as a guest user (default: 0) */ int limit_min_hubs_reg; /*<<< Minimum concurrent hubs as a registered user (default: 0) */ int limit_min_hubs_op; /*<<< Minimum concurrent hubs as a operator (or admin) (default: 0) */ int limit_min_share; /*<<< Limit minimum share size in megabytes (default: 0) */ int limit_max_share; /*<<< Limit maximum share size in megabytes (default: 0) */ int limit_min_slots; /*<<< Limit minimum number of upload slots open per user (default: 0) */ int limit_max_slots; /*<<< Limit minimum number of upload slots open per user (default: 0) */ int flood_ctl_interval; /*<<< Time interval in seconds for flood control check. (default: 0) */ int flood_ctl_chat; /*<<< Max chat messages allowed in time interval (default: 0) */ int flood_ctl_connect; /*<<< Max connections requests allowed in time interval (default: 0) */ int flood_ctl_search; /*<<< Max search requests allowed in time interval (default: 0) */ int flood_ctl_update; /*<<< Max updates allowed in time interval (default: 0) */ int flood_ctl_extras; /*<<< Max extra messages allowed in time interval (default: 0) */ int tls_enable; /*<<< Enable SSL/TLS support (default: 0) */ int tls_require; /*<<< If SSL/TLS enabled, should it be required (default: 0) */ char* tls_require_redirect_addr; /*<<< A redirect address in case a client connects using "adc://" when "adcs://" is required. (default: "") */ char* tls_certificate; /*<<< Certificate file (default: "") */ char* tls_private_key; /*<<< Private key file (default: "") */ char* tls_ciphersuite; /*<<< List of TLS ciphers to use (default: "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS") */ char* tls_version; /*<<< Specify minimum TLS version supported. (default: "1.2") */ char* file_acl; /*<<< File containing access control lists (default: "") */ char* file_plugins; /*<<< Plugin configuration file (default: "") */ 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; /*<<< "Nickname is invalid" */ 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 invalid characters" */ char* msg_inf_error_nick_not_utf8; /*<<< "Nickname is not valid UTF-8" */ char* msg_inf_error_nick_taken; /*<<< "Nickname is already 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." */ char* msg_user_flood_chat; /*<<< "Chat flood detected, messages are dropped." */ char* msg_user_flood_connect; /*<<< "Connect flood detected, connection refused." */ char* msg_user_flood_search; /*<<< "Search flood detected, search is stopped." */ char* msg_user_flood_update; /*<<< "Update flood detected." */ char* msg_user_flood_extras; /*<<< "Flood detected." */ char* msg_proto_no_common_hash; /*<<< "No common hash algorithm." */ char* msg_proto_obsolete_adc0; /*<<< "Client is using an obsolete ADC protocol version." */ }; modelrockettier-uhub-a8ee6e7/src/core/hub.c000066400000000000000000001010351324501300100210030ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" struct hub_info* g_hub = 0; /* FIXME: Flood control should be done in a plugin! */ #define CHECK_FLOOD(TYPE, WARN) \ if (flood_control_check(&u->flood_ ## TYPE , hub->config->flood_ctl_ ## TYPE, hub->config->flood_ctl_interval, net_get_time()) && !auth_cred_is_unrestricted(u->credentials)) \ { \ if (WARN) \ { \ hub_send_flood_warning(hub, u, hub->config->msg_user_flood_ ## TYPE); \ } \ break; \ } #define ROUTE_MSG \ if (user_is_logged_in(u)) \ { \ ret = route_message(hub, u, cmd); \ } \ else \ { \ ret = -1; \ } \ break; int hub_handle_message(struct hub_info* hub, struct hub_user* u, const char* line, size_t length) { int ret = 0; struct adc_message* cmd = 0; LOG_PROTO("recv %s: %s", sid_to_string(u->id.sid), line); if (user_is_disconnecting(u)) return -1; cmd = adc_msg_parse_verify(u, line, length); if (cmd) { switch (cmd->cmd) { case ADC_CMD_HSUP: CHECK_FLOOD(extras, 0); ret = hub_handle_support(hub, u, cmd); break; case ADC_CMD_HPAS: CHECK_FLOOD(extras, 0); ret = hub_handle_password(hub, u, cmd); break; case ADC_CMD_BINF: CHECK_FLOOD(update, 1); ret = hub_handle_info(hub, u, cmd); break; case ADC_CMD_DINF: case ADC_CMD_EINF: case ADC_CMD_FINF: case ADC_CMD_BQUI: case ADC_CMD_DQUI: case ADC_CMD_EQUI: case ADC_CMD_FQUI: /* these must never be allowed for security reasons, so we ignore them. */ CHECK_FLOOD(extras, 1); break; case ADC_CMD_EMSG: case ADC_CMD_DMSG: case ADC_CMD_BMSG: case ADC_CMD_FMSG: CHECK_FLOOD(chat, 1); ret = hub_handle_chat_message(hub, u, cmd); break; case ADC_CMD_BSCH: case ADC_CMD_DSCH: case ADC_CMD_ESCH: case ADC_CMD_FSCH: cmd->priority = -1; if (plugin_handle_search(hub, u, cmd->cache) == st_deny) break; CHECK_FLOOD(search, 1); ROUTE_MSG; case ADC_CMD_FRES: // spam case ADC_CMD_BRES: // spam case ADC_CMD_ERES: // pointless. CHECK_FLOOD(extras, 1); break; case ADC_CMD_DRES: cmd->priority = -1; if (plugin_handle_search_result(hub, u, uman_get_user_by_sid(hub->users, cmd->target), cmd->cache) == st_deny) break; /* CHECK_FLOOD(search, 0); */ ROUTE_MSG; case ADC_CMD_DRCM: cmd->priority = -1; if (plugin_handle_revconnect(hub, u, uman_get_user_by_sid(hub->users, cmd->target)) == st_deny) break; CHECK_FLOOD(connect, 1); ROUTE_MSG; case ADC_CMD_DCTM: cmd->priority = -1; if (plugin_handle_connect(hub, u, uman_get_user_by_sid(hub->users, cmd->target)) == st_deny) break; CHECK_FLOOD(connect, 1); ROUTE_MSG; case ADC_CMD_BCMD: case ADC_CMD_DCMD: case ADC_CMD_ECMD: case ADC_CMD_FCMD: case ADC_CMD_HCMD: CHECK_FLOOD(extras, 1); break; default: CHECK_FLOOD(extras, 1); ROUTE_MSG; } adc_msg_free(cmd); } else { if (!user_is_logged_in(u)) { ret = -1; } } return ret; } int hub_handle_support(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd) { int ret = 0; int index = 0; int ok = 1; char* arg = adc_msg_get_argument(cmd, index); if (hub->status == hub_status_disabled && u->state == state_protocol) { on_login_failure(hub, u, status_msg_hub_disabled); hub_free(arg); return -1; } while (arg) { if (strlen(arg) == 6) { fourcc_t fourcc = FOURCC(arg[2], arg[3], arg[4], arg[5]); if (strncmp(arg, ADC_SUP_FLAG_ADD, 2) == 0) { user_support_add(u, fourcc); } else if (strncmp(arg, ADC_SUP_FLAG_REMOVE, 2) == 0) { user_support_remove(u, fourcc); } else { ok = 0; } } else { ok = 0; } index++; hub_free(arg); arg = adc_msg_get_argument(cmd, index); } if (u->state == state_protocol) { if (index == 0) ok = 0; /* Need to support *SOMETHING*, at least BASE */ if (!ok) { /* disconnect user. Do not send crap during initial handshake! */ hub_disconnect_user(hub, u, quit_logon_error); return -1; } if (user_flag_get(u, feature_base)) { /* User supports ADC/1.0 and a hash we know */ if (user_flag_get(u, feature_tiger)) { hub_send_handshake(hub, u); net_con_set_timeout(u->connection, TIMEOUT_HANDSHAKE); } else { // no common hash algorithm. hub_send_status(hub, u, status_msg_proto_no_common_hash, status_level_fatal); hub_disconnect_user(hub, u, quit_protocol_error); } } else if (user_flag_get(u, feature_bas0)) { if (hub->config->obsolete_clients) { hub_send_handshake(hub, u); net_con_set_timeout(u->connection, TIMEOUT_HANDSHAKE); } else { /* disconnect user for using an obsolete client. */ char* tmp = adc_msg_escape(hub->config->msg_proto_obsolete_adc0); struct adc_message* message = adc_msg_construct(ADC_CMD_IMSG, 6 + strlen(tmp)); adc_msg_add_argument(message, tmp); hub_free(tmp); route_to_user(hub, u, message); adc_msg_free(message); hub_disconnect_user(hub, u, quit_protocol_error); } } else { /* Not speaking a compatible protocol - just disconnect. */ hub_disconnect_user(hub, u, quit_logon_error); } } return ret; } int hub_handle_password(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd) { char* password = adc_msg_get_argument(cmd, 0); int ret = 0; if (u->state == state_verify) { if (acl_password_verify(hub, u, password)) { on_login_success(hub, u); } else { on_login_failure(hub, u, status_msg_auth_invalid_password); ret = -1; } } hub_free(password); return ret; } int hub_handle_chat_message(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd) { char* message = adc_msg_get_argument(cmd, 0); char* message_decoded = NULL; int ret = 0; int relay = 1; int broadcast; int private_msg; int command; int offset; if (!message) return 0; message_decoded = adc_msg_unescape(message); if (!message_decoded) { hub_free(message); return 0; } if (!user_is_logged_in(u)) { hub_free(message); return 0; } broadcast = (cmd->cache[0] == 'B'); private_msg = (cmd->cache[0] == 'D' || cmd->cache[0] == 'E'); command = (message[0] == '!' || message[0] == '+'); if (broadcast && command) { /* * A message such as "++message" is handled as "+message", by removing the first character. * The first character is removed by memmoving the string one byte to the left. */ if (message[1] == message[0]) { relay = 1; offset = adc_msg_get_arg_offset(cmd); memmove(cmd->cache+offset+1, cmd->cache+offset+2, cmd->length - offset); cmd->length--; } else { relay = command_invoke(hub->commands, u, message_decoded); } } /* FIXME: Plugin should do this! */ if (relay && (((hub->config->chat_is_privileged && !user_is_protected(u)) || (user_flag_get(u, flag_muted))) && broadcast)) { relay = 0; } if (relay) { plugin_st status = st_default; if (broadcast) { status = plugin_handle_chat_message(hub, u, message_decoded, 0); } else if (private_msg) { struct hub_user* target = uman_get_user_by_sid(hub->users, cmd->target); if (target) status = plugin_handle_private_message(hub, u, target, message_decoded, 0); else relay = 0; } if (status == st_deny) relay = 0; } if (relay) { /* adc_msg_remove_named_argument(cmd, "PM"); */ if (broadcast) { plugin_log_chat_message(hub, u, message_decoded, 0); } ret = route_message(hub, u, cmd); } hub_free(message); hub_free(message_decoded); return ret; } void hub_send_support(struct hub_info* hub, struct hub_user* u) { if (user_is_connecting(u) || user_is_logged_in(u)) { route_to_user(hub, u, hub->command_support); } } void hub_send_sid(struct hub_info* hub, struct hub_user* u) { sid_t sid; struct adc_message* command; if (user_is_connecting(u)) { command = adc_msg_construct(ADC_CMD_ISID, 10); sid = uman_get_free_sid(hub->users, u); adc_msg_add_argument(command, (const char*) sid_to_string(sid)); route_to_user(hub, u, command); adc_msg_free(command); } } void hub_send_ping(struct hub_info* hub, struct hub_user* user) { /* This will just send a newline, despite appearing to do more below. */ struct adc_message* ping = adc_msg_construct(0, 0); ping->cache[0] = '\n'; ping->cache[1] = 0; ping->length = 1; ping->priority = 1; route_to_user(hub, user, ping); adc_msg_free(ping); } void hub_send_hubinfo(struct hub_info* hub, struct hub_user* u) { struct adc_message* info = adc_msg_copy(hub->command_info); int value = 0; uint64_t size = 0; if (user_flag_get(u, feature_ping)) { /* FIXME: These are missing: HH - Hub Host address ( DNS or IP ) WS - Hub Website NE - Hub Network OW - Hub Owner name */ adc_msg_add_named_argument(info, "UC", uhub_itoa(hub_get_user_count(hub))); adc_msg_add_named_argument(info, "MC", uhub_itoa(hub_get_max_user_count(hub))); adc_msg_add_named_argument(info, "SS", uhub_ulltoa(hub_get_shared_size(hub))); adc_msg_add_named_argument(info, "SF", uhub_ulltoa(hub_get_shared_files(hub))); /* Maximum/minimum share size */ size = hub_get_max_share(hub); if (size) adc_msg_add_named_argument(info, "XS", uhub_ulltoa(size)); size = hub_get_min_share(hub); if (size) adc_msg_add_named_argument(info, "MS", uhub_ulltoa(size)); /* Maximum/minimum upload slots allowed per user */ value = hub_get_max_slots(hub); if (value) adc_msg_add_named_argument(info, "XL", uhub_itoa(value)); value = hub_get_min_slots(hub); if (value) adc_msg_add_named_argument(info, "ML", uhub_itoa(value)); /* guest users must be on min/max hubs */ value = hub_get_max_hubs_user(hub); if (value) adc_msg_add_named_argument(info, "XU", uhub_itoa(value)); value = hub_get_min_hubs_user(hub); if (value) adc_msg_add_named_argument(info, "MU", uhub_itoa(value)); /* registered users must be on min/max hubs */ value = hub_get_max_hubs_reg(hub); if (value) adc_msg_add_named_argument(info, "XR", uhub_itoa(value)); value = hub_get_min_hubs_reg(hub); if (value) adc_msg_add_named_argument(info, "MR", uhub_itoa(value)); /* operators must be on min/max hubs */ value = hub_get_max_hubs_op(hub); if (value) adc_msg_add_named_argument(info, "XO", uhub_itoa(value)); value = hub_get_min_hubs_op(hub); if (value) adc_msg_add_named_argument(info, "MO", uhub_itoa(value)); /* uptime in seconds */ adc_msg_add_named_argument(info, "UP", uhub_itoa((int) difftime(time(0), hub->tm_started))); } if (user_is_connecting(u) || user_is_logged_in(u)) { route_to_user(hub, u, info); } adc_msg_free(info); /* Only send banner when connecting */ if (hub->config->show_banner && user_is_connecting(u)) { route_to_user(hub, u, hub->command_banner); } } void hub_send_handshake(struct hub_info* hub, struct hub_user* u) { user_flag_set(u, flag_pipeline); hub_send_support(hub, u); hub_send_sid(hub, u); hub_send_hubinfo(hub, u); route_flush_pipeline(hub, u); if (!user_is_disconnecting(u)) { user_set_state(u, state_identify); } } void hub_send_password_challenge(struct hub_info* hub, struct hub_user* u) { struct adc_message* igpa; igpa = adc_msg_construct(ADC_CMD_IGPA, 38); adc_msg_add_argument(igpa, acl_password_generate_challenge(hub, u)); user_set_state(u, state_verify); route_to_user(hub, u, igpa); adc_msg_free(igpa); } void hub_send_flood_warning(struct hub_info* hub, struct hub_user* u, const char* message) { struct adc_message* msg; char* tmp; if (user_flag_get(u, flag_flood)) return; msg = adc_msg_construct(ADC_CMD_ISTA, 128); if (msg) { tmp = adc_msg_escape(message); adc_msg_add_argument(msg, "110"); adc_msg_add_argument(msg, tmp); hub_free(tmp); route_to_user(hub, u, msg); user_flag_set(u, flag_flood); adc_msg_free(msg); } } static int check_duplicate_logins_ok(struct hub_info* hub, struct hub_user* user) { struct hub_user* lookup1; struct hub_user* lookup2; lookup1 = uman_get_user_by_nick(hub->users, user->id.nick); if (lookup1) return status_msg_inf_error_nick_taken; lookup2 = uman_get_user_by_cid(hub->users, user->id.cid); if (lookup2) return status_msg_inf_error_cid_taken; return 0; } static void hub_event_dispatcher(void* callback_data, struct event_data* message) { int status; struct hub_info* hub = (struct hub_info*) callback_data; struct hub_user* user = (struct hub_user*) message->ptr; uhub_assert(hub != NULL); switch (message->id) { case UHUB_EVENT_USER_JOIN: { if (user_is_disconnecting(user)) break; if (message->flags) { hub_send_password_challenge(hub, user); } else { /* Race condition, we could have two messages for two logins queued up. So make sure we don't let the second client in. */ status = check_duplicate_logins_ok(hub, user); if (!status) { on_login_success(hub, user); } else { on_login_failure(hub, user, (enum status_message) status); } } break; } case UHUB_EVENT_USER_QUIT: { uman_remove(hub->users, user); uman_send_quit_message(hub, hub->users, user); on_logout_user(hub, user); hub_schedule_destroy_user(hub, user); break; } case UHUB_EVENT_USER_DESTROY: { user_destroy(user); break; } case UHUB_EVENT_HUB_SHUTDOWN: { struct hub_user* u = (struct hub_user*) list_get_first(hub->users->list); while (u) { uman_remove(hub->users, u); user_destroy(u); u = (struct hub_user*) list_get_first(hub->users->list); } break; } default: /* FIXME: ignored */ break; } } static void hub_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(); } static void hub_timer_statistics(struct timeout_evt* t) { struct hub_info* hub = (struct hub_info*) t->ptr; hub_update_stats(hub); timeout_queue_reschedule(net_backend_get_timeout_queue(), hub->stats.timeout, TIMEOUT_STATS); } static struct net_connection* start_listening_socket(const char* bind_addr, uint16_t port, int backlog, struct hub_info* hub) { struct net_connection* server; struct sockaddr_storage addr; socklen_t sockaddr_size; int sd, ret; if (ip_convert_address(bind_addr, port, (struct sockaddr*) &addr, &sockaddr_size) == -1) { return 0; } sd = net_socket_create(addr.ss_family, SOCK_STREAM, IPPROTO_TCP); if (sd == -1) { return 0; } if ((net_set_reuseaddress(sd, 1) == -1) || (net_set_nonblocking(sd, 1) == -1)) { net_close(sd); return 0; } ret = net_bind(sd, (struct sockaddr*) &addr, sockaddr_size); if (ret == -1) { LOG_ERROR("hub_start_service(): Unable to bind to TCP local address. errno=%d, str=%s", net_error(), net_error_string(net_error())); net_close(sd); return 0; } ret = net_listen(sd, backlog); if (ret == -1) { LOG_ERROR("hub_start_service(): Unable to listen to socket"); net_close(sd); return 0; } server = net_con_create(); net_con_initialize(server, sd, net_on_accept, hub, NET_EVENT_READ); return server; } struct server_alt_port_data { struct hub_info* hub; struct hub_config* config; }; static int server_alt_port_start_one(char* line, int count, void* ptr) { struct server_alt_port_data* data = (struct server_alt_port_data*) ptr; int port = uhub_atoi(line); struct net_connection* con = start_listening_socket(data->config->server_bind_addr, port, data->config->server_listen_backlog, data->hub); if (con) { list_append(data->hub->server_alt_ports, con); LOG_INFO("Listening on alternate port %d...", port); return 0; } return -1; } static void server_alt_port_start(struct hub_info* hub, struct hub_config* config) { struct server_alt_port_data data; if (!config->server_alt_ports || !*config->server_alt_ports) return; hub->server_alt_ports = (struct linked_list*) list_create(); data.hub = hub; data.config = config; string_split(config->server_alt_ports, ",", &data, server_alt_port_start_one); } static void server_alt_port_clear(void* ptr) { struct net_connection* con = (struct net_connection*) ptr; if (con) { net_con_close(con); hub_free(con); } } static void server_alt_port_stop(struct hub_info* hub) { if (hub->server_alt_ports) { list_clear(hub->server_alt_ports, &server_alt_port_clear); list_destroy(hub->server_alt_ports); } } #ifdef SSL_SUPPORT static int load_ssl_certificates(struct hub_info* hub, struct hub_config* config) { if (config->tls_enable) { hub->ctx = net_ssl_context_create(config->tls_version, config->tls_ciphersuite); if (!hub->ctx) return 0; if (ssl_load_certificate(hub->ctx, config->tls_certificate) && ssl_load_private_key(hub->ctx, config->tls_private_key) && ssl_check_private_key(hub->ctx)) { LOG_INFO("Enabling TLS (%s), using certificate: %s, private key: %s", net_ssl_get_provider(), config->tls_certificate, config->tls_private_key); return 1; } return 0; } return 1; } static void unload_ssl_certificates(struct hub_info* hub) { if (hub->ctx) net_ssl_context_destroy(hub->ctx); } #endif /* SSL_SUPPORT */ struct hub_info* hub_start_service(struct hub_config* config) { struct hub_info* hub = 0; int ipv6_supported; hub = hub_malloc_zero(sizeof(struct hub_info)); if (!hub) { LOG_FATAL("Unable to allocate memory for hub"); return 0; } hub->tm_started = time(0); ipv6_supported = net_is_ipv6_supported(); if (ipv6_supported) LOG_DEBUG("IPv6 supported."); else LOG_DEBUG("IPv6 not supported."); hub->server = start_listening_socket(config->server_bind_addr, config->server_port, config->server_listen_backlog, hub); if (!hub->server) { hub_free(hub); LOG_FATAL("Unable to start hub service"); return 0; } LOG_INFO("Starting " PRODUCT "/" VERSION ", listening on %s:%d...", net_get_local_address(hub->server->sd), config->server_port); #ifdef SSL_SUPPORT if (!load_ssl_certificates(hub, config)) { hub_free(hub); return 0; } #endif hub->config = config; hub->users = NULL; hub->users = uman_init(); if (!hub->users) { net_con_close(hub->server); hub_free(hub); return 0; } if (event_queue_initialize(&hub->queue, hub_event_dispatcher, (void*) hub) == -1) { net_con_close(hub->server); uman_shutdown(hub->users); hub_free(hub); return 0; } hub->recvbuf = hub_malloc(MAX_RECV_BUF); hub->sendbuf = hub_malloc(MAX_SEND_BUF); if (!hub->recvbuf || !hub->sendbuf) { net_con_close(hub->server); hub_free(hub->recvbuf); hub_free(hub->sendbuf); uman_shutdown(hub->users); hub_free(hub); return 0; } hub->logout_info = (struct linked_list*) list_create(); server_alt_port_start(hub, config); hub->status = hub_status_running; g_hub = hub; if (net_backend_get_timeout_queue()) { hub->stats.timeout = hub_malloc_zero(sizeof(struct timeout_evt)); timeout_evt_initialize(hub->stats.timeout, hub_timer_statistics, hub); timeout_queue_insert(net_backend_get_timeout_queue(), hub->stats.timeout, TIMEOUT_STATS); } // Start the hub command sub-system hub->commands = command_initialize(hub); return hub; } void hub_shutdown_service(struct hub_info* hub) { LOG_DEBUG("hub_shutdown_service()"); if (net_backend_get_timeout_queue()) { timeout_queue_remove(net_backend_get_timeout_queue(), hub->stats.timeout); hub_free(hub->stats.timeout); } #ifdef SSL_SUPPORT unload_ssl_certificates(hub); #endif event_queue_shutdown(hub->queue); net_con_close(hub->server); server_alt_port_stop(hub); uman_shutdown(hub->users); hub->status = hub_status_stopped; hub_free(hub->sendbuf); hub_free(hub->recvbuf); list_clear(hub->logout_info, &hub_free); list_destroy(hub->logout_info); command_shutdown(hub->commands); hub_free(hub); hub = 0; g_hub = 0; } int hub_plugins_load(struct hub_info* hub) { if (!hub->config->file_plugins || !*hub->config->file_plugins) return 0; hub->plugins = hub_malloc_zero(sizeof(struct uhub_plugins)); if (!hub->plugins) return -1; if (plugin_initialize(hub->config, hub) < 0) { hub_free(hub->plugins); hub->plugins = 0; return -1; } return 0; } void hub_plugins_unload(struct hub_info* hub) { if (hub->plugins) { plugin_shutdown(hub->plugins); hub_free(hub->plugins); hub->plugins = 0; } } void hub_set_variables(struct hub_info* hub, struct acl_handle* acl) { char* tmp; char* server = adc_msg_escape(PRODUCT_STRING); /* FIXME: OOM */ hub->acl = acl; hub->command_info = adc_msg_construct(ADC_CMD_IINF, 15); if (hub->command_info) { adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_CLIENT_TYPE, ADC_CLIENT_TYPE_HUB); adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_USER_AGENT_PRODUCT, PRODUCT); adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_USER_AGENT_VERSION, GIT_VERSION); tmp = adc_msg_escape(hub->config->hub_name); adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_NICK, tmp); hub_free(tmp); tmp = adc_msg_escape(hub->config->hub_description); adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_DESCRIPTION, tmp); hub_free(tmp); } hub->command_support = adc_msg_construct(ADC_CMD_ISUP, 6 + strlen(ADC_PROTO_SUPPORT)); if (hub->command_support) { adc_msg_add_argument(hub->command_support, ADC_PROTO_SUPPORT); } hub->command_banner = adc_msg_construct(ADC_CMD_ISTA, 100 + strlen(server)); if (hub->command_banner) { if (hub->config->show_banner_sys_info) tmp = adc_msg_escape("Powered by " PRODUCT_STRING " on " OPSYS "/" CPUINFO); else tmp = adc_msg_escape("Powered by " PRODUCT_STRING); adc_msg_add_argument(hub->command_banner, "000"); adc_msg_add_argument(hub->command_banner, tmp); hub_free(tmp); } if (hub_plugins_load(hub) < 0) { LOG_FATAL("Unable to load plugins."); hub->status = hub_status_shutdown; } else hub->status = (hub->config->hub_enabled ? hub_status_running : hub_status_disabled); hub_free(server); } void hub_free_variables(struct hub_info* hub) { hub_plugins_unload(hub); adc_msg_free(hub->command_info); adc_msg_free(hub->command_banner); adc_msg_free(hub->command_support); } static void set_status_code(enum msg_status_level level, int code, char buffer[4]) { buffer[0] = ('0' + (int) level); buffer[1] = ('0' + (code / 10)); buffer[2] = ('0' + (code % 10)); buffer[3] = 0; } /** * @param hub The hub instance this message is sent from. * @param user The user this message is sent to. * @param msg See enum status_message * @param level See enum status_level */ void hub_send_status(struct hub_info* hub, struct hub_user* user, enum status_message msg, enum msg_status_level level) { struct hub_config* cfg = hub->config; struct adc_message* cmd = adc_msg_construct(ADC_CMD_ISTA, 6); struct adc_message* qui = adc_msg_construct(ADC_CMD_IQUI, 512); char code[4]; char buf[256]; const char* text = 0; const char* flag = 0; char* escaped_text = 0; int reconnect_time = 0; int redirect = 0; if (!cmd || !qui) { adc_msg_free(cmd); adc_msg_free(qui); return; } #define STATUS(CODE, MSG, FLAG, RCONTIME, REDIRECT) case status_ ## MSG : set_status_code(level, CODE, code); text = cfg->MSG; flag = FLAG; reconnect_time = RCONTIME; redirect = REDIRECT; break switch (msg) { STATUS(11, msg_hub_full, 0, 600, 1); /* FIXME: Proper timeout? */ STATUS(12, msg_hub_disabled, 0, -1, 1); STATUS(26, msg_hub_registered_users_only, 0, 0, 1); STATUS(43, msg_inf_error_nick_missing, 0, 0, 0); STATUS(43, msg_inf_error_nick_multiple, 0, 0, 0); STATUS(21, msg_inf_error_nick_invalid, 0, 0, 0); STATUS(21, msg_inf_error_nick_long, 0, 0, 0); STATUS(21, msg_inf_error_nick_short, 0, 0, 0); STATUS(21, msg_inf_error_nick_spaces, 0, 0, 0); STATUS(21, msg_inf_error_nick_bad_chars, 0, 0, 0); STATUS(21, msg_inf_error_nick_not_utf8, 0, 0, 0); STATUS(22, msg_inf_error_nick_taken, 0, 0, 0); STATUS(21, msg_inf_error_nick_restricted, 0, 0, 0); STATUS(43, msg_inf_error_cid_invalid, "FBID", 0, 0); STATUS(43, msg_inf_error_cid_missing, "FMID", 0, 0); STATUS(24, msg_inf_error_cid_taken, 0, 0, 0); STATUS(43, msg_inf_error_pid_missing, "FMPD", 0, 0); STATUS(27, msg_inf_error_pid_invalid, "FBPD", 0, 0); STATUS(31, msg_ban_permanently, 0, 0, 0); STATUS(32, msg_ban_temporarily, "TL600", 600, 0); /* FIXME: Proper timeout? */ STATUS(23, msg_auth_invalid_password, 0, 0, 0); STATUS(20, msg_auth_user_not_found, 0, 0, 0); STATUS(30, msg_error_no_memory, 0, 0, 0); STATUS(43, msg_user_share_size_low, "FB" ADC_INF_FLAG_SHARED_SIZE, 0, 1); STATUS(43, msg_user_share_size_high, "FB" ADC_INF_FLAG_SHARED_SIZE, 0, 1); STATUS(43, msg_user_slots_low, "FB" ADC_INF_FLAG_UPLOAD_SLOTS, 0, 1); STATUS(43, msg_user_slots_high, "FB" ADC_INF_FLAG_UPLOAD_SLOTS, 0, 1); STATUS(43, msg_user_hub_limit_low, 0, 0, 1); STATUS(43, msg_user_hub_limit_high, 0, 0, 1); STATUS(47, msg_proto_no_common_hash, 0, -1, 1); STATUS(40, msg_proto_obsolete_adc0, 0, -1, 1); } #undef STATUS escaped_text = adc_msg_escape(text); adc_msg_add_argument(cmd, code); adc_msg_add_argument(cmd, escaped_text); if (flag) { adc_msg_add_argument(cmd, flag); } route_to_user(hub, user, cmd); if (level >= status_level_fatal) { adc_msg_add_argument(qui, sid_to_string(user->id.sid)); snprintf(buf, 230, "MS%s", escaped_text); adc_msg_add_argument(qui, buf); if (reconnect_time != 0) { snprintf(buf, 10, "TL%d", reconnect_time); adc_msg_add_argument(qui, buf); } if (redirect && *hub->config->redirect_addr) { snprintf(buf, 255, "RD%s", hub->config->redirect_addr); adc_msg_add_argument(qui, buf); } route_to_user(hub, user, qui); } hub_free(escaped_text); adc_msg_free(cmd); adc_msg_free(qui); } const char* hub_get_status_message(struct hub_info* hub, enum status_message msg) { #define STATUS(MSG) case status_ ## MSG : return cfg->MSG; break struct hub_config* cfg = hub->config; switch (msg) { STATUS(msg_hub_full); STATUS(msg_hub_disabled); STATUS(msg_hub_registered_users_only); STATUS(msg_inf_error_nick_missing); STATUS(msg_inf_error_nick_multiple); STATUS(msg_inf_error_nick_invalid); STATUS(msg_inf_error_nick_long); STATUS(msg_inf_error_nick_short); STATUS(msg_inf_error_nick_spaces); STATUS(msg_inf_error_nick_bad_chars); STATUS(msg_inf_error_nick_not_utf8); STATUS(msg_inf_error_nick_taken); STATUS(msg_inf_error_nick_restricted); STATUS(msg_inf_error_cid_invalid); STATUS(msg_inf_error_cid_missing); STATUS(msg_inf_error_cid_taken); STATUS(msg_inf_error_pid_missing); STATUS(msg_inf_error_pid_invalid); STATUS(msg_ban_permanently); STATUS(msg_ban_temporarily); STATUS(msg_auth_invalid_password); STATUS(msg_auth_user_not_found); STATUS(msg_error_no_memory); STATUS(msg_user_share_size_low); STATUS(msg_user_share_size_high); STATUS(msg_user_slots_low); STATUS(msg_user_slots_high); STATUS(msg_user_hub_limit_low); STATUS(msg_user_hub_limit_high); STATUS(msg_proto_no_common_hash); STATUS(msg_proto_obsolete_adc0); } #undef STATUS return "Unknown"; } const char* hub_get_status_message_log(struct hub_info* hub, enum status_message msg) { #define STATUS(MSG) case status_ ## MSG : return #MSG; break switch (msg) { STATUS(msg_hub_full); STATUS(msg_hub_disabled); STATUS(msg_hub_registered_users_only); STATUS(msg_inf_error_nick_missing); STATUS(msg_inf_error_nick_multiple); STATUS(msg_inf_error_nick_invalid); STATUS(msg_inf_error_nick_long); STATUS(msg_inf_error_nick_short); STATUS(msg_inf_error_nick_spaces); STATUS(msg_inf_error_nick_bad_chars); STATUS(msg_inf_error_nick_not_utf8); STATUS(msg_inf_error_nick_taken); STATUS(msg_inf_error_nick_restricted); STATUS(msg_inf_error_cid_invalid); STATUS(msg_inf_error_cid_missing); STATUS(msg_inf_error_cid_taken); STATUS(msg_inf_error_pid_missing); STATUS(msg_inf_error_pid_invalid); STATUS(msg_ban_permanently); STATUS(msg_ban_temporarily); STATUS(msg_auth_invalid_password); STATUS(msg_auth_user_not_found); STATUS(msg_error_no_memory); STATUS(msg_user_share_size_low); STATUS(msg_user_share_size_high); STATUS(msg_user_slots_low); STATUS(msg_user_slots_high); STATUS(msg_user_hub_limit_low); STATUS(msg_user_hub_limit_high); STATUS(msg_proto_no_common_hash); STATUS(msg_proto_obsolete_adc0); } #undef STATUS return "unknown"; } size_t hub_get_user_count(struct hub_info* hub) { return hub->users->count; } size_t hub_get_max_user_count(struct hub_info* hub) { return hub->config->max_users; } uint64_t hub_get_shared_size(struct hub_info* hub) { return hub->users->shared_size; } uint64_t hub_get_shared_files(struct hub_info* hub) { return hub->users->shared_files; } uint64_t hub_get_min_share(struct hub_info* hub) { uint64_t size = hub->config->limit_min_share; size *= (1024 * 1024); return size; } uint64_t hub_get_max_share(struct hub_info* hub) { uint64_t size = hub->config->limit_max_share; size *= (1024 * 1024); return size; } size_t hub_get_min_slots(struct hub_info* hub) { return hub->config->limit_min_slots; } size_t hub_get_max_slots(struct hub_info* hub) { return hub->config->limit_max_slots; } size_t hub_get_max_hubs_total(struct hub_info* hub) { return hub->config->limit_max_hubs; } size_t hub_get_max_hubs_user(struct hub_info* hub) { return hub->config->limit_max_hubs_user; } size_t hub_get_min_hubs_user(struct hub_info* hub) { return hub->config->limit_min_hubs_user; } size_t hub_get_max_hubs_reg(struct hub_info* hub) { return hub->config->limit_max_hubs_reg; } size_t hub_get_min_hubs_reg(struct hub_info* hub) { return hub->config->limit_min_hubs_reg; } size_t hub_get_max_hubs_op(struct hub_info* hub) { return hub->config->limit_max_hubs_op; } size_t hub_get_min_hubs_op(struct hub_info* hub) { return hub->config->limit_min_hubs_op; } void hub_schedule_destroy_user(struct hub_info* hub, struct hub_user* user) { struct event_data post; memset(&post, 0, sizeof(post)); post.id = UHUB_EVENT_USER_DESTROY; post.ptr = user; event_queue_post(hub->queue, &post); if (user->id.sid) { sid_free(hub->users->sids, user->id.sid); } } void hub_disconnect_all(struct hub_info* hub) { struct event_data post; memset(&post, 0, sizeof(post)); post.id = UHUB_EVENT_HUB_SHUTDOWN; post.ptr = 0; event_queue_post(hub->queue, &post); } void hub_event_loop(struct hub_info* hub) { do { net_backend_process(); event_queue_process(hub->queue); } while (hub->status == hub_status_running || hub->status == hub_status_disabled); if (hub->status == hub_status_shutdown) { LOG_DEBUG("Removing all users..."); event_queue_process(hub->queue); event_queue_process(hub->queue); hub_disconnect_all(hub); event_queue_process(hub->queue); hub->status = hub_status_stopped; } } void hub_disconnect_user(struct hub_info* hub, struct hub_user* user, int reason) { struct event_data post; int need_notify = 0; /* is user already being disconnected ? */ if (user_is_disconnecting(user)) { return; } /* stop reading from user */ net_shutdown_r(net_con_get_sd(user->connection)); net_con_close(user->connection); user->connection = 0; LOG_TRACE("hub_disconnect_user(), user=%p, reason=%d, state=%d", user, reason, user->state); need_notify = user_is_logged_in(user) && hub->status == hub_status_running; user->quit_reason = reason; user_set_state(user, state_cleanup); if (need_notify) { memset(&post, 0, sizeof(post)); post.id = UHUB_EVENT_USER_QUIT; post.ptr = user; event_queue_post(hub->queue, &post); } else { hub_schedule_destroy_user(hub, user); } } void hub_logout_log(struct hub_info* hub, struct hub_user* user) { struct hub_logout_info* loginfo = hub_malloc_zero(sizeof(struct hub_logout_info)); if (!loginfo) return; loginfo->time = time(NULL); memcpy(loginfo->cid, user->id.cid, sizeof(loginfo->cid)); memcpy(loginfo->nick, user->id.nick, sizeof(loginfo->nick)); memcpy(&loginfo->addr, &user->id.addr, sizeof(struct ip_addr_encap)); loginfo->reason = user->quit_reason; list_append(hub->logout_info, loginfo); while (list_size(hub->logout_info) > (size_t) hub->config->max_logout_log) { list_remove_first(hub->logout_info, hub_free); } } modelrockettier-uhub-a8ee6e7/src/core/hub.h000066400000000000000000000270251324501300100210160ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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/unknown */ 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, /* User is on too few hubs. */ status_msg_user_hub_limit_high = -45, /* User is on too many hubs. */ status_msg_proto_no_common_hash = -50, /* No common hash algorithms */ status_msg_proto_obsolete_adc0 = -51, /* Client is using an obsolete protocol version */ }; 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 timeout_evt* timeout; /**<< "Timeout handler for statistics" */ }; 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; struct linked_list* server_alt_ports; 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_banner; /* The default welcome message */ time_t tm_started; int status; char* recvbuf; /* Global receive buffer */ char* sendbuf; /* Global send buffer */ struct linked_list* logout_info; /* Log of people logging out. */ struct command_base* commands; /* Hub command handler */ struct uhub_plugins* plugins; /* Plug-ins loaded for this hub instance. */ #ifdef SSL_SUPPORT struct ssl_context_handle* 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); /** * 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 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); /** * Warn user about flooding. */ extern void hub_send_flood_warning(struct hub_info*, struct hub_user* user, const char* message); /** * 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 */ modelrockettier-uhub-a8ee6e7/src/core/hubevent.c000066400000000000000000000043071324501300100220510ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" #include "plugin_api/handle.h" /* Notify plugins, 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, hub->users, 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->users, u); /* Announce new user to all connected users */ if (user_is_logged_in(u)) route_info_message(hub, u); plugin_log_user_login_success(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) { plugin_log_user_login_error(hub, u, hub_get_status_message_log(hub, msg)); hub_send_status(hub, u, msg, status_level_fatal); hub_disconnect_user(hub, u, quit_logon_error); } void on_update_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg) { plugin_log_user_update_error(hub, u, hub_get_status_message_log(hub, msg)); hub_send_status(hub, u, msg, status_level_fatal); hub_disconnect_user(hub, u, quit_update_error); } void on_nick_change(struct hub_info* hub, struct hub_user* u, const char* nick) { if (user_is_logged_in(u)) { plugin_log_user_nick_change(hub, 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); plugin_log_user_logout(hub, user, reason); hub_logout_log(hub, user); } modelrockettier-uhub-a8ee6e7/src/core/hubevent.h000066400000000000000000000030771324501300100220610ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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); extern void on_update_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 */ modelrockettier-uhub-a8ee6e7/src/core/inf.c000066400000000000000000000510371324501300100210070ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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. */ static 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; } static 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_IPV4_ADDR); } 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->users, user->id.nick); struct hub_user* lookup2 = uman_get_user_by_cid(hub->users, 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_name_encoded = 0; char* ua_version_encoded = 0; char* str = 0; size_t offset = 0; /* Get client user agent version */ ua_name_encoded = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_USER_AGENT_PRODUCT); ua_version_encoded = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_USER_AGENT_VERSION); if (ua_name_encoded) { str = adc_msg_unescape(ua_name_encoded); if (str) { offset = strlen(str); memcpy(user->id.user_agent, str, MIN(offset, MAX_UA_LEN)); hub_free(str); } } if (ua_version_encoded) { str = adc_msg_unescape(ua_version_encoded); if (str) { memcpy(user->id.user_agent + offset, str, MIN(strlen(str), MAX_UA_LEN - offset)); hub_free(str); } } hub_free(ua_name_encoded); hub_free(ua_version_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) { int shared_files = atoi(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) { int num = atoi(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) { int num = atoi(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) { int num = atoi(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) { int num = atoi(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 auth_info* info = acl_get_access_info(hub, user->id.nick); if (info) { user->credentials = info->credentials; ret = 1; } else { user->credentials = auth_cred_guest; } hub_free(info); switch (user->credentials) { case auth_cred_none: break; case auth_cred_bot: adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_BOT); break; case auth_cred_ubot: adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_BOT); break; case auth_cred_guest: /* Nothing to be added to the info message */ break; case auth_cred_user: adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_REGISTERED_USER); break; case auth_cred_operator: adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_OPERATOR); break; case auth_cred_opbot: adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_HUBBOT); break; case auth_cred_opubot: adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_HUBBOT); break; case auth_cred_super: adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_SUPER_USER); break; case auth_cred_admin: adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_ADMIN); break; case auth_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 >= (size_t) 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_VERSION); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_USER_AGENT_PRODUCT); 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) static 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) { int ret; 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; } 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); } ret = check_limits(hub, user, cmd); if (ret < 0) { on_update_failure(hub, user, ret); adc_msg_free(cmd); return -1; } 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; } modelrockettier-uhub-a8ee6e7/src/core/inf.h000066400000000000000000000034061324501300100210110ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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 */ modelrockettier-uhub-a8ee6e7/src/core/ioqueue.c000066400000000000000000000064661324501300100217150ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.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 ioq_recv* ioq_recv_create() { struct ioq_recv* q = hub_malloc_zero(sizeof(struct ioq_recv)); return q; } void ioq_recv_destroy(struct ioq_recv* q) { if (q) { hub_free(q->buf); hub_free(q); } } size_t ioq_recv_get(struct ioq_recv* q, void* buf, size_t bufsize) { uhub_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 ioq_recv_set(struct ioq_recv* 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 ioq_send* ioq_send_create() { struct ioq_send* q = hub_malloc_zero(sizeof(struct ioq_send)); 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 ioq_send_destroy(struct ioq_send* q) { if (q) { list_clear(q->queue, &clear_send_queue_callback); list_destroy(q->queue); hub_free(q); } } void ioq_send_add(struct ioq_send* q, struct adc_message* msg_) { struct adc_message* msg = adc_msg_incref(msg_); #ifdef DEBUG_SENDQ debug_msg("ioq_send_add", msg); #endif uhub_assert(msg->cache && *msg->cache); list_append(q->queue, msg); q->size += msg->length; } static void ioq_send_remove(struct ioq_send* q, struct adc_message* msg) { #ifdef DEBUG_SENDQ debug_msg("ioq_send_remove", msg); #endif list_remove(q->queue, msg); q->size -= msg->length; adc_msg_free(msg); q->offset = 0; } int ioq_send_send(struct ioq_send* q, struct net_connection* con) { int ret; struct adc_message* msg = list_get_first(q->queue); if (!msg) return 0; uhub_assert(msg->cache && *msg->cache); ret = net_con_send(con, msg->cache + q->offset, msg->length - q->offset); if (ret > 0) { q->offset += ret; if (msg->length - q->offset > 0) return 0; ioq_send_remove(q, msg); return 1; } return ret; } int ioq_send_is_empty(struct ioq_send* q) { return (q->size - q->offset) == 0; } size_t ioq_send_get_bytes(struct ioq_send* q) { return q->size - q->offset; } modelrockettier-uhub-a8ee6e7/src/core/ioqueue.h000066400000000000000000000055431324501300100217150ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_IO_QUEUE_H #define HAVE_UHUB_IO_QUEUE_H struct adc_message; struct linked_list; typedef int (*ioq_write)(void* desc, const void* buf, size_t len); typedef int (*ioq_read)(void* desc, void* buf, size_t len); struct ioq_send { 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 adc_message) */ }; struct ioq_recv { char* buf; size_t size; }; /** * Create a send queue */ extern struct ioq_send* ioq_send_create(); /** * Destroy a send queue, and delete any queued messages. */ extern void ioq_send_destroy(struct ioq_send*); /** * Add a message to the send queue. */ extern void ioq_send_add(struct ioq_send*, 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 ioq_send_send(struct ioq_send*, struct net_connection* con); /** * @returns 1 if send queue is empty, 0 otherwise. */ extern int ioq_send_is_empty(struct ioq_send*); /** * @returns the number of bytes remaining to be sent in the queue. */ extern size_t ioq_send_get_bytes(struct ioq_send*); /** * Create a receive queue. */ extern struct ioq_recv* ioq_recv_create(); /** * Destroy a receive queue. */ extern void ioq_recv_destroy(struct ioq_recv*); /** * 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 ioq_recv_get(struct ioq_recv*, void* buf, size_t bufsize); /** * Sets the buffer */ extern size_t ioq_recv_set(struct ioq_recv*, void* buf, size_t bufsize); /** * @return 1 if size is zero, 0 otherwise. */ extern int ioq_recv_is_empty(struct ioq_recv* buf); #endif /* HAVE_UHUB_IO_QUEUE_H */ modelrockettier-uhub-a8ee6e7/src/core/main.c000066400000000000000000000222141324501300100211520ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" #ifdef SYSTEMD #include #endif 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) extern struct hub_info* g_hub; void hub_handle_signal(int sig) { struct hub_info* hub = g_hub; switch (sig) { 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 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) { sigset_t sig_set; struct sigaction act; int i; sigemptyset(&sig_set); act.sa_mask = sig_set; act.sa_flags = SA_ONSTACK | SA_RESTART; act.sa_handler = hub_handle_signal; for (i = 0; signals[i]; i++) { if (sigaction(signals[i], &act, 0) != 0) { LOG_ERROR("Error setting signal handler %d", signals[i]); } } } void shutdown_signal_handlers(struct hub_info* hub) { } #endif /* !WIN32 */ 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); /* Reinitialize logs */ hub_log_shutdown(); hub_log_initialize(arg_log, arg_log_syslog); hub_set_log_verbosity(arg_verbose); } 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) { acl_shutdown(&acl); free_config(&configuration); net_destroy(); hub_log_shutdown(); return -1; } #if !defined(WIN32) setup_signal_handlers(hub); #ifdef SYSTEMD /* Notify the service manager that this daemon has * been successfully initalized and shall enter the * main loop. */ sd_notifyf(0, "READY=1\n" "MAINPID=%lu", (unsigned long) getpid()); #endif /* SYSTEMD */ #endif /* ! WIN32 */ } 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) 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_STRING "\n"); fprintf(stdout, COPYRIGHT "\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 Log messages to given file (default: stderr)\n" " -c 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 #ifdef SYSTEMD " -L Log messages to journal\n" #else " -L Log messages to syslog\n" #endif " -u Run as given user\n" " -g Run with given group permissions\n" " -p 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; } modelrockettier-uhub-a8ee6e7/src/core/netevent.c000066400000000000000000000105161324501300100220600ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include #include "ioqueue.h" #include "probe.h" int handle_net_read(struct hub_user* user) { static char buf[MAX_RECV_BUF]; struct ioq_recv* q = user->recv_queue; size_t buf_size = ioq_recv_get(q, buf, MAX_RECV_BUF); ssize_t size; if (user_flag_get(user, flag_maxbuf)) buf_size = 0; size = net_con_recv(user->connection, buf + buf_size, MAX_RECV_BUF - buf_size); 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+1; 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) && user->hub->config->max_recv_buffer > (pos - start)) { if (hub_handle_message(user->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 < (size_t) user->hub->config->max_recv_buffer) { ioq_recv_set(q, lastPos ? lastPos : buf, remaining); } else { ioq_recv_set(q, 0, 0); user_flag_set(user, flag_maxbuf); LOG_WARN("Received message past max_recv_buffer, dropping message."); } } else { ioq_recv_set(q, 0, 0); } } return 0; } int handle_net_write(struct hub_user* user) { int ret = 0; while (ioq_send_get_bytes(user->send_queue)) { ret = ioq_send_send(user->send_queue, user->connection); if (ret <= 0) break; } if (ret < 0) return quit_socket_error; if (ioq_send_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", con->sd, (int) event, arg); #endif if (event == NET_EVENT_TIMEOUT) { if (user_is_connecting(user)) { hub_disconnect_user(user->hub, user, quit_timeout); } return; } if (event & NET_EVENT_READ) { flag_close = handle_net_read(user); if (flag_close) { hub_disconnect_user(user->hub, user, flag_close); return; } } if (event & NET_EVENT_WRITE) { flag_close = handle_net_write(user); if (flag_close) { hub_disconnect_user(user->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; int server_fd = net_con_get_sd(con); plugin_st status; for (;;) { int fd = net_accept(server_fd, &ipaddr); if (fd == -1) { #ifdef WINSOCK if (net_error() == WSAEWOULDBLOCK) #else if (net_error() == EWOULDBLOCK) #endif { break; } else { LOG_ERROR("Accept error: %d %s", net_error(), strerror(net_error())); break; } } status = plugin_check_ip_early(hub, &ipaddr); if (status == st_deny) { plugin_log_connection_denied(hub, &ipaddr); net_close(fd); continue; } plugin_log_connection_accepted(hub, &ipaddr); probe = probe_create(hub, fd, &ipaddr); if (!probe) { LOG_ERROR("Unable to create probe after socket accepted. Out of memory?"); net_close(fd); break; } } } modelrockettier-uhub-a8ee6e7/src/core/netevent.h000066400000000000000000000022041324501300100220600ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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 */ modelrockettier-uhub-a8ee6e7/src/core/plugincallback.c000066400000000000000000000203231324501300100232000ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" #include "plugin_api/command_api.h" struct plugin_callback_data { struct linked_list* commands; }; static struct plugin_callback_data* get_callback_data(struct plugin_handle* plugin) { return get_internals(plugin)->callback_data; } static int plugin_command_dispatch(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) { struct plugin_handle* plugin = (struct plugin_handle*) cmd->ptr; struct plugin_callback_data* data = get_callback_data(plugin); struct plugin_command_handle* cmdh; struct plugin_user* puser = (struct plugin_user*) user; // FIXME: Use a proper conversion function instead. struct plugin_command* pcommand = (struct plugin_command*) cmd; // FIXME: Use a proper conversion function instead. LOG_PLUGIN("plugin_command_dispatch: cmd=%s", cmd->prefix); LIST_FOREACH(struct plugin_command_handle*, cmdh, data->commands, { if (strcmp(cmdh->prefix, cmd->prefix) == 0) return cmdh->handler(plugin, puser, pcommand); }); return 0; } static struct hub_user* convert_user_type(struct plugin_user* user) { struct hub_user* huser = (struct hub_user*) user; return huser; } static int cbfunc_send_message(struct plugin_handle* plugin, struct plugin_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(plugin_get_hub(plugin), convert_user_type(user), command); adc_msg_free(command); hub_free(buffer); return 1; } static int cbfunc_send_broadcast(struct plugin_handle* plugin, 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_all(plugin_get_hub(plugin), command); adc_msg_free(command); hub_free(buffer); return 1; } static int cbfunc_send_status(struct plugin_handle* plugin, struct plugin_user* user, int code, const char* message) { char code_str[4]; char* buffer = adc_msg_escape(message); struct adc_message* command = adc_msg_construct(ADC_CMD_ISTA, strlen(buffer) + 10); snprintf(code_str, sizeof(code_str), "%03d", code); adc_msg_add_argument(command, code_str); adc_msg_add_argument(command, buffer); route_to_user(plugin_get_hub(plugin), convert_user_type(user), command); adc_msg_free(command); hub_free(buffer); return 1; } static int cbfunc_user_disconnect(struct plugin_handle* plugin, struct plugin_user* user) { hub_disconnect_user(plugin_get_hub(plugin), convert_user_type(user), quit_kicked); return 0; } static int cbfunc_command_add(struct plugin_handle* plugin, struct plugin_command_handle* cmdh) { struct plugin_callback_data* data = get_callback_data(plugin); struct command_handle* command = (struct command_handle*) hub_malloc_zero(sizeof(struct command_handle)); command->prefix = cmdh->prefix; command->length = cmdh->length; command->args = cmdh->args; command->cred = cmdh->cred; command->description = cmdh->description; command->origin = cmdh->origin; command->handler = plugin_command_dispatch; cmdh->internal_handle = command; list_append(data->commands, cmdh); command_add(plugin_get_hub(plugin)->commands, command, (void*) plugin); return 0; } static int cbfunc_command_del(struct plugin_handle* plugin, struct plugin_command_handle* cmdh) { struct plugin_callback_data* data = get_callback_data(plugin); struct command_handle* command = (struct command_handle*) cmdh->internal_handle; list_remove(data->commands, cmdh); command_del(plugin_get_hub(plugin)->commands, command); hub_free(command); cmdh->internal_handle = NULL; return 0; } size_t cbfunc_command_arg_reset(struct plugin_handle* plugin, struct plugin_command* cmd) { // TODO: Use proper function for rewriting for plugin_command -> hub_command return hub_command_arg_reset((struct hub_command*) cmd); } struct plugin_command_arg_data* cbfunc_command_arg_next(struct plugin_handle* plugin, struct plugin_command* cmd, enum plugin_command_arg_type t) { // TODO: Use proper function for rewriting for plugin_command -> hub_command return (struct plugin_command_arg_data*) hub_command_arg_next((struct hub_command*) cmd, (enum hub_command_arg_type) t); } static size_t cbfunc_get_usercount(struct plugin_handle* plugin) { struct hub_info* hub = plugin_get_hub(plugin); return hub->users->count; } static char* cbfunc_get_hub_name(struct plugin_handle* plugin) { struct hub_info* hub = plugin_get_hub(plugin); char* str_encoded = adc_msg_get_named_argument(hub->command_info, ADC_INF_FLAG_NICK); char* str = adc_msg_unescape(str_encoded); hub_free(str_encoded); return str; } static char* cbfunc_get_hub_description(struct plugin_handle* plugin) { struct hub_info* hub = plugin_get_hub(plugin); char* str_encoded = adc_msg_get_named_argument(hub->command_info, ADC_INF_FLAG_DESCRIPTION); char* str = adc_msg_unescape(str_encoded); hub_free(str_encoded); return str; } static void cbfunc_set_hub_name(struct plugin_handle* plugin, const char* str) { struct hub_info* hub = plugin_get_hub(plugin); struct adc_message* command; char* new_str = adc_msg_escape(str ? str : hub->config->hub_name); adc_msg_replace_named_argument(hub->command_info, ADC_INF_FLAG_NICK, new_str); // Broadcast hub name command = adc_msg_construct(ADC_CMD_IINF, (strlen(new_str) + 8)); adc_msg_add_named_argument(command, ADC_INF_FLAG_NICK, new_str); route_to_all(hub, command); adc_msg_free(command); hub_free(new_str); } static void cbfunc_set_hub_description(struct plugin_handle* plugin, const char* str) { struct hub_info* hub = plugin_get_hub(plugin); struct adc_message* command; char* new_str = adc_msg_escape(str ? str : hub->config->hub_description); adc_msg_replace_named_argument(hub->command_info, ADC_INF_FLAG_DESCRIPTION, new_str); // Broadcast hub description command = adc_msg_construct(ADC_CMD_IINF, (strlen(new_str) + 8)); adc_msg_add_named_argument(command, ADC_INF_FLAG_DESCRIPTION, new_str); route_to_all(hub, command); adc_msg_free(command); hub_free(new_str); } void plugin_register_callback_functions(struct plugin_handle* handle) { handle->hub.send_message = cbfunc_send_message; handle->hub.send_broadcast_message = cbfunc_send_broadcast; handle->hub.send_status_message = cbfunc_send_status; handle->hub.user_disconnect = cbfunc_user_disconnect; handle->hub.command_add = cbfunc_command_add; handle->hub.command_del = cbfunc_command_del; handle->hub.command_arg_reset = cbfunc_command_arg_reset; handle->hub.command_arg_next = cbfunc_command_arg_next; handle->hub.get_usercount = cbfunc_get_usercount; handle->hub.get_name = cbfunc_get_hub_name; handle->hub.set_name = cbfunc_set_hub_name; handle->hub.get_description = cbfunc_get_hub_description; handle->hub.set_description = cbfunc_set_hub_description; } void plugin_unregister_callback_functions(struct plugin_handle* handle) { } struct plugin_callback_data* plugin_callback_data_create() { struct plugin_callback_data* data = (struct plugin_callback_data*) hub_malloc_zero(sizeof(struct plugin_callback_data)); LOG_PLUGIN("plugin_callback_data_create()"); data->commands = list_create(); return data; } void plugin_callback_data_destroy(struct plugin_handle* plugin, struct plugin_callback_data* data) { LOG_PLUGIN("plugin_callback_data_destroy()"); if (data->commands) { // delete commands not deleted by the plugin itself: struct plugin_command_handle* cmd; while ( (cmd = list_get_first(data->commands)) ) cbfunc_command_del(plugin, cmd); list_destroy(data->commands); } hub_free(data); } modelrockettier-uhub-a8ee6e7/src/core/plugincallback.h000066400000000000000000000023221324501300100232040ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_PLUGIN_CALLBACK_H #define HAVE_UHUB_PLUGIN_CALLBACK_H struct plugin_handle; struct uhub_plugin; extern struct plugin_callback_data* plugin_callback_data_create(); extern void plugin_callback_data_destroy(struct plugin_handle* plugin, struct plugin_callback_data* data); extern void plugin_register_callback_functions(struct plugin_handle* plugin); extern void plugin_unregister_callback_functions(struct plugin_handle* plugin); #endif /* HAVE_UHUB_PLUGIN_CALLBACK_H */ modelrockettier-uhub-a8ee6e7/src/core/plugininvoke.c000066400000000000000000000147621324501300100227510ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" #include "plugin_api/handle.h" #define PLUGIN_DEBUG(hub, name) LOG_PLUGIN("Invoke %s on %d plugins", name, (int) (hub->plugins ? list_size(hub->plugins->loaded) : -1)); #define INVOKE(HUB, FUNCNAME, CODE) \ PLUGIN_DEBUG(HUB, # FUNCNAME) \ if (HUB->plugins && HUB->plugins->loaded) \ { \ struct plugin_handle* plugin;\ LIST_FOREACH(struct plugin_handle*, plugin, HUB->plugins->loaded, \ { \ if (plugin->funcs.FUNCNAME) \ CODE \ }); \ } #define PLUGIN_INVOKE_STATUS_1(HUB, FUNCNAME, ARG1) \ do { \ plugin_st status = st_default; \ INVOKE(HUB, FUNCNAME, { \ status = plugin->funcs.FUNCNAME(plugin, ARG1); \ if (status != st_default) \ break; \ }); \ return status; \ } while(0) #define PLUGIN_INVOKE_STATUS_2(HUB, FUNCNAME, ARG1, ARG2) \ do { \ plugin_st status = st_default; \ INVOKE(HUB, FUNCNAME, { \ status = plugin->funcs.FUNCNAME(plugin, ARG1, ARG2); \ if (status != st_default) \ break; \ }); \ return status; \ } while(0) #define PLUGIN_INVOKE_STATUS_3(HUB, FUNCNAME, ARG1, ARG2, ARG3) \ do { \ plugin_st status = st_default; \ INVOKE(HUB, FUNCNAME, { \ status = plugin->funcs.FUNCNAME(plugin, ARG1, ARG2, ARG3); \ if (status != st_default) \ break; \ }); \ return status; \ } while(0) #define PLUGIN_INVOKE_1(HUB, FUNCNAME, ARG1) INVOKE(HUB, FUNCNAME, { plugin->funcs.FUNCNAME(plugin, ARG1); }) #define PLUGIN_INVOKE_2(HUB, FUNCNAME, ARG1, ARG2) INVOKE(HUB, FUNCNAME, { plugin->funcs.FUNCNAME(plugin, ARG1, ARG2); }) #define PLUGIN_INVOKE_3(HUB, FUNCNAME, ARG1, ARG2, ARG3) INVOKE(HUB, FUNCNAME, { plugin->funcs.FUNCNAME(plugin, ARG1, ARG2, ARG3); }) static struct plugin_user* convert_user_type(struct hub_user* user) { struct plugin_user* puser = (struct plugin_user*) user; return puser; } plugin_st plugin_check_ip_early(struct hub_info* hub, struct ip_addr_encap* addr) { PLUGIN_INVOKE_STATUS_1(hub, on_check_ip_early, addr); } plugin_st plugin_check_ip_late(struct hub_info* hub, struct hub_user* who, struct ip_addr_encap* addr) { struct plugin_user* user = convert_user_type(who); PLUGIN_INVOKE_STATUS_2(hub, on_check_ip_late, user, addr); } void plugin_log_connection_accepted(struct hub_info* hub, struct ip_addr_encap* ipaddr) { PLUGIN_INVOKE_1(hub, on_connection_accepted, ipaddr); } void plugin_log_connection_denied(struct hub_info* hub, struct ip_addr_encap* ipaddr) { PLUGIN_INVOKE_1(hub, on_connection_refused, ipaddr); } void plugin_log_user_login_success(struct hub_info* hub, struct hub_user* who) { struct plugin_user* user = convert_user_type(who); PLUGIN_INVOKE_1(hub, on_user_login, user); } void plugin_log_user_login_error(struct hub_info* hub, struct hub_user* who, const char* reason) { struct plugin_user* user = convert_user_type(who); PLUGIN_INVOKE_2(hub, on_user_login_error, user, reason); } void plugin_log_user_logout(struct hub_info* hub, struct hub_user* who, const char* reason) { struct plugin_user* user = convert_user_type(who); PLUGIN_INVOKE_2(hub, on_user_logout, user, reason); } void plugin_log_user_nick_change(struct hub_info* hub, struct hub_user* who, const char* new_nick) { struct plugin_user* user = convert_user_type(who); PLUGIN_INVOKE_2(hub, on_user_nick_change, user, new_nick); } void plugin_log_user_update_error(struct hub_info* hub, struct hub_user* who, const char* reason) { struct plugin_user* user = convert_user_type(who); PLUGIN_INVOKE_2(hub, on_user_update_error, user, reason); } void plugin_log_chat_message(struct hub_info* hub, struct hub_user* who, const char* message, int flags) { struct plugin_user* user = convert_user_type(who); PLUGIN_INVOKE_3(hub, on_user_chat_message, user, message, flags); } plugin_st plugin_handle_chat_message(struct hub_info* hub, struct hub_user* from, const char* message, int flags) { struct plugin_user* user = convert_user_type(from); PLUGIN_INVOKE_STATUS_2(hub, on_chat_msg, user, message); } plugin_st plugin_handle_private_message(struct hub_info* hub, struct hub_user* from, struct hub_user* to, const char* message, int flags) { struct plugin_user* user1 = convert_user_type(from); struct plugin_user* user2 = convert_user_type(to); PLUGIN_INVOKE_STATUS_3(hub, on_private_msg, user1, user2, message); } plugin_st plugin_handle_search(struct hub_info* hub, struct hub_user* from, const char* data) { struct plugin_user* user = convert_user_type(from); PLUGIN_INVOKE_STATUS_2(hub, on_search, user, data); } plugin_st plugin_handle_search_result(struct hub_info* hub, struct hub_user* from, struct hub_user* to, const char* data) { struct plugin_user* user1 = convert_user_type(from); struct plugin_user* user2 = convert_user_type(to); PLUGIN_INVOKE_STATUS_3(hub, on_search_result, user1, user2, data); } plugin_st plugin_handle_connect(struct hub_info* hub, struct hub_user* from, struct hub_user* to) { struct plugin_user* user1 = convert_user_type(from); struct plugin_user* user2 = convert_user_type(to); PLUGIN_INVOKE_STATUS_2(hub, on_p2p_connect, user1, user2); } plugin_st plugin_handle_revconnect(struct hub_info* hub, struct hub_user* from, struct hub_user* to) { struct plugin_user* user1 = convert_user_type(from); struct plugin_user* user2 = convert_user_type(to); PLUGIN_INVOKE_STATUS_2(hub, on_p2p_revconnect, user1, user2); } plugin_st plugin_auth_get_user(struct hub_info* hub, const char* nickname, struct auth_info* info) { PLUGIN_INVOKE_STATUS_2(hub, auth_get_user, nickname, info); } plugin_st plugin_auth_register_user(struct hub_info* hub, struct auth_info* info) { PLUGIN_INVOKE_STATUS_1(hub, auth_register_user, info); } plugin_st plugin_auth_update_user(struct hub_info* hub, struct auth_info* info) { PLUGIN_INVOKE_STATUS_1(hub, auth_update_user, info); } plugin_st plugin_auth_delete_user(struct hub_info* hub, struct auth_info* info) { PLUGIN_INVOKE_STATUS_1(hub, auth_delete_user, info); } modelrockettier-uhub-a8ee6e7/src/core/plugininvoke.h000066400000000000000000000062761324501300100227570ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_PLUGIN_INVOKE_H #define HAVE_UHUB_PLUGIN_INVOKE_H #include "uhub.h" #include "plugin_api/handle.h" struct hub_info; struct ip_addr_encap; /* All log related functions */ void plugin_log_connection_accepted(struct hub_info* hub, struct ip_addr_encap* addr); void plugin_log_connection_denied(struct hub_info* hub, struct ip_addr_encap* addr); void plugin_log_user_login_success(struct hub_info* hub, struct hub_user* user); void plugin_log_user_login_error(struct hub_info* hub, struct hub_user* user, const char* reason); void plugin_log_user_logout(struct hub_info* hub, struct hub_user* user, const char* reason); void plugin_log_user_nick_change(struct hub_info* hub, struct hub_user* user, const char* new_nick); void plugin_log_user_update_error(struct hub_info* hub, struct hub_user* user, const char* reason); void plugin_log_chat_message(struct hub_info* hub, struct hub_user* from, const char* message, int flags); /* IP ban related */ plugin_st plugin_check_ip_early(struct hub_info* hub, struct ip_addr_encap* addr); plugin_st plugin_check_ip_late(struct hub_info* hub, struct hub_user* user, struct ip_addr_encap* addr); /* Nickname allow/deny handling */ plugin_st plugin_check_nickname_valid(struct hub_info* hub, const char* nick); plugin_st plugin_check_nickname_reserved(struct hub_info* hub, const char* nick); /* Handle chat messages */ plugin_st plugin_handle_chat_message(struct hub_info* hub, struct hub_user* from, const char* message, int flags); plugin_st plugin_handle_private_message(struct hub_info* hub, struct hub_user* from, struct hub_user* to, const char* message, int flags); /* Handle searches */ plugin_st plugin_handle_search(struct hub_info* hub, struct hub_user* user, const char* data); plugin_st plugin_handle_search_result(struct hub_info* hub, struct hub_user* from, struct hub_user* to, const char* data); /* Handle p2p connections */ plugin_st plugin_handle_connect(struct hub_info* hub, struct hub_user* from, struct hub_user* to); plugin_st plugin_handle_revconnect(struct hub_info* hub, struct hub_user* from, struct hub_user* to); /* Authentication related */ plugin_st plugin_auth_get_user(struct hub_info* hub, const char* nickname, struct auth_info* info); plugin_st plugin_auth_register_user(struct hub_info* hub, struct auth_info* user); plugin_st plugin_auth_update_user(struct hub_info* hub, struct auth_info* user); plugin_st plugin_auth_delete_user(struct hub_info* hub, struct auth_info* user); #endif // HAVE_UHUB_PLUGIN_INVOKE_H modelrockettier-uhub-a8ee6e7/src/core/pluginloader.c000066400000000000000000000142721324501300100227200ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" #include "plugin_api/handle.h" struct plugin_callback_data; struct plugin_hub_internals* get_internals(struct plugin_handle* handle) { struct plugin_hub_internals* internals; uhub_assert(handle && handle->handle && handle->handle->internals); internals = (struct plugin_hub_internals*) handle->handle->internals; return internals; } struct uhub_plugin* plugin_open(const char* filename) { struct uhub_plugin* plugin; LOG_PLUGIN("plugin_open: \"%s\"", filename); plugin = (struct uhub_plugin*) hub_malloc_zero(sizeof(struct uhub_plugin)); if (!plugin) { return 0; } #ifdef HAVE_DLOPEN plugin->handle = dlopen(filename, RTLD_LAZY); #else plugin->handle = LoadLibraryExA(filename, NULL, 0); #endif if (!plugin->handle) { #ifdef HAVE_DLOPEN LOG_ERROR("Unable to open plugin %s: %s", filename, dlerror()); #else LOG_ERROR("Unable to open plugin %s: %d", filename, GetLastError()); #endif hub_free(plugin); return 0; } plugin->filename = strdup(filename); plugin->internals = hub_malloc_zero(sizeof(struct plugin_hub_internals)); return plugin; } void plugin_close(struct uhub_plugin* plugin) { struct plugin_hub_internals* internals = (struct plugin_hub_internals*) plugin->internals; LOG_PLUGIN("plugin_close: \"%s\"", plugin->filename); plugin_callback_data_destroy(plugin->handle, internals->callback_data); hub_free(internals); plugin->internals = NULL; #ifdef HAVE_DLOPEN dlclose(plugin->handle); #else FreeLibrary((HMODULE) plugin->handle); #endif hub_free(plugin->filename); hub_free(plugin); } void* plugin_lookup_symbol(struct uhub_plugin* plugin, const char* symbol) { #ifdef HAVE_DLOPEN void* addr = dlsym(plugin->handle, symbol); return addr; #else FARPROC addr = GetProcAddress((HMODULE) plugin->handle, symbol); return (void*) addr; #endif } struct plugin_handle* plugin_load(const char* filename, const char* config, struct hub_info* hub) { plugin_register_f register_f; plugin_unregister_f unregister_f; int ret; struct plugin_handle* handle = (struct plugin_handle*) hub_malloc_zero(sizeof(struct plugin_handle)); struct uhub_plugin* plugin = plugin_open(filename); struct plugin_hub_internals* internals = (struct plugin_hub_internals*) plugin->internals; if (!plugin) return NULL; if (!handle) { plugin_close(plugin); return NULL; } handle->handle = plugin; register_f = plugin_lookup_symbol(plugin, "plugin_register"); unregister_f = plugin_lookup_symbol(plugin, "plugin_unregister"); // register hub internals internals->unregister = unregister_f; internals->hub = hub; internals->callback_data = plugin_callback_data_create(); // setup callback functions, where the plugin can contact the hub. plugin_register_callback_functions(handle); if (register_f && unregister_f) { ret = register_f(handle, config); if (ret == 0) { if (handle->plugin_api_version == PLUGIN_API_VERSION && handle->plugin_funcs_size == sizeof(struct plugin_funcs)) { LOG_INFO("Loaded plugin: %s: %s, version %s.", filename, handle->name, handle->version); LOG_PLUGIN("Plugin API version: %d (func table size: " PRINTF_SIZE_T ")", handle->plugin_api_version, handle->plugin_funcs_size); return handle; } else { LOG_ERROR("Unable to load plugin: %s - API version mistmatch", filename); } } else { LOG_ERROR("Unable to load plugin: %s - Failed to initialize: %s", filename, handle->error_msg); } } plugin_close(plugin); hub_free(handle); return NULL; } void plugin_unload(struct plugin_handle* plugin) { struct plugin_hub_internals* internals = get_internals(plugin); internals->unregister(plugin); plugin_unregister_callback_functions(plugin); plugin_close(plugin->handle); hub_free(plugin); } static int plugin_parse_line(char* line, int line_count, void* ptr_data) { struct hub_info* hub = (struct hub_info*) ptr_data; struct uhub_plugins* handle = hub->plugins; struct cfg_tokens* tokens = cfg_tokenize(line); struct plugin_handle* plugin; char *directive, *soname, *params; if (cfg_token_count(tokens) == 0) { cfg_tokens_free(tokens); return 0; } if (cfg_token_count(tokens) < 2) { cfg_tokens_free(tokens); return -1; } directive = cfg_token_get_first(tokens); soname = cfg_token_get_next(tokens); params = cfg_token_get_next(tokens); if (strcmp(directive, "plugin") == 0 && soname && *soname) { if (!params) params = ""; LOG_PLUGIN("Load plugin: \"%s\", params=\"%s\"", soname, params); plugin = plugin_load(soname, params, hub); if (plugin) { list_append(handle->loaded, plugin); cfg_tokens_free(tokens); return 0; } } cfg_tokens_free(tokens); return -1; } int plugin_initialize(struct hub_config* config, struct hub_info* hub) { int ret; hub->plugins->loaded = list_create(); if (!hub->plugins->loaded) return -1; if (config) { if (!*config->file_plugins) return 0; ret = file_read_lines(config->file_plugins, hub, &plugin_parse_line); if (ret == -1) { list_clear(hub->plugins->loaded, hub_free); list_destroy(hub->plugins->loaded); hub->plugins->loaded = 0; return -1; } } return 0; } static void plugin_unload_ptr(void* ptr) { struct plugin_handle* plugin = (struct plugin_handle*) ptr; plugin_unload(plugin); } void plugin_shutdown(struct uhub_plugins* handle) { list_clear(handle->loaded, plugin_unload_ptr); list_destroy(handle->loaded); } // Used internally only struct hub_info* plugin_get_hub(struct plugin_handle* plugin) { struct plugin_hub_internals* data = get_internals(plugin); return data->hub; } modelrockettier-uhub-a8ee6e7/src/core/pluginloader.h000066400000000000000000000042241324501300100227210ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_PLUGIN_LOADER_H #define HAVE_UHUB_PLUGIN_LOADER_H #include "plugin_api/handle.h" struct hub_config; struct hub_info; struct linked_list; struct plugin_handle; struct uhub_plugin { void* handle; plugin_unregister_f unregister; char* filename; void* internals; // Hub-internal stuff (struct plugin_hub_internals) }; struct uhub_plugins { struct linked_list* loaded; }; // High level plugin loader code extern struct plugin_handle* plugin_load(const char* filename, const char* config, struct hub_info* hub); extern void plugin_unload(struct plugin_handle* plugin); // extern void plugin_unload(struct plugin_handle*); extern int plugin_initialize(struct hub_config* config, struct hub_info* hub); extern void plugin_shutdown(struct uhub_plugins* handle); // Low level plugin loader code (used internally) extern struct uhub_plugin* plugin_open(const char* filename); extern void plugin_close(struct uhub_plugin*); extern void* plugin_lookup_symbol(struct uhub_plugin*, const char* symbol); // Used internally only struct plugin_hub_internals { struct hub_info* hub; plugin_unregister_f unregister; /* The unregister function. */ struct plugin_callback_data* callback_data; /* callback data that is unique for the plugin */ }; extern struct plugin_hub_internals* get_internals(struct plugin_handle*); extern struct hub_info* plugin_get_hub(struct plugin_handle*); #endif /* HAVE_UHUB_PLUGIN_LOADER_H */ modelrockettier-uhub-a8ee6e7/src/core/probe.c000066400000000000000000000103351324501300100213360ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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_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"); #ifdef SSL_SUPPORT if (probe->hub->config->tls_enable && probe->hub->config->tls_require) { LOG_TRACE("Not TLS connection - closing connection."); if (*probe->hub->config->tls_require_redirect_addr) { char buf[512]; ssize_t len = snprintf(buf, sizeof(buf), "ISUP " ADC_PROTO_SUPPORT "\nISID AAAB\nIINF NIRedirecting...\nIQUI AAAB RD%s\n", probe->hub->config->tls_require_redirect_addr); net_con_send(con, buf, (size_t) len); LOG_TRACE("Not TLS connection - Redirecting to %s.", probe->hub->config->tls_require_redirect_addr); } else { LOG_TRACE("Not TLS connection - closing connection."); } } else #endif if (user_create(probe->hub, probe->connection, &probe->addr)) { probe->connection = 0; } probe_destroy(probe); return; } else if ((memcmp(probe_recvbuf, "GET ", 4) == 0) || (memcmp(probe_recvbuf, "POST", 4) == 0) || (memcmp(probe_recvbuf, "HEAD", 4) == 0)) { /* Looks like HTTP - Not supported, but we log it. */ LOG_TRACE("Probed HTTP connection. Not supported closing connection (%s)", ip_convert_to_string(&probe->addr)); const char* buf = "501 Not implemented\r\n\r\n"; net_con_send(con, buf, strlen(buf)); } #ifdef SSL_SUPPORT else 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]) { if (probe->hub->config->tls_enable) { LOG_TRACE("Probed TLS %d.%d connection", (int) probe_recvbuf[9], (int) probe_recvbuf[10]); if (user_create(probe->hub, probe->connection, &probe->addr)) { probe->connection = 0; } net_con_ssl_handshake(con, net_con_ssl_mode_server, probe->hub->ctx); } else { LOG_TRACE("Probed TLS %d.%d connection. TLS disabled in hub.", (int) probe_recvbuf[9], (int) probe_recvbuf[10]); } } else { LOG_TRACE("Probed unsupported protocol: %x%x%x%x.", (int) probe_recvbuf[0], (int) probe_recvbuf[1], (int) probe_recvbuf[2], (int) probe_recvbuf[3]); } #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 */ LOG_TRACE("probe_create(): %p", probe); 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) { LOG_TRACE("probe_destroy(): %p (connection=%p)", probe, probe->connection); if (probe->connection) { net_con_close(probe->connection); probe->connection = 0; } hub_free(probe); } modelrockettier-uhub-a8ee6e7/src/core/probe.h000066400000000000000000000023301324501300100213370ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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 */ modelrockettier-uhub-a8ee6e7/src/core/route.c000066400000000000000000000114111324501300100213610ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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->users, msg->target); if (target) { route_to_user(hub, target, msg); } break; case 'E': target = uman_get_user_by_sid(hub->users, 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 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 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 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; uhub_assert(msg->cache && *msg->cache); if (ioq_send_is_empty(user->send_queue) && !user_flag_get(user, flag_pipeline)) { /* Perform oportunistic write */ ioq_send_add(user->send_queue, msg); handle_net_write(user); } else { if (check_send_queue(hub, user, msg) >= 0) { ioq_send_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 (ioq_send_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; LIST_FOREACH(struct hub_user*, user, hub->users->list, { route_to_user(hub, user, command); }); 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; LIST_FOREACH(struct hub_user*, user, hub->users->list, { if (user->feature_cast) { do_send = 1; LIST_FOREACH(char*, tmp, command->feature_cast_include, { if (!user_have_feature_cast_support(user, tmp)) { do_send = 0; break; } }); if (!do_send) continue; LIST_FOREACH(char*, tmp, command->feature_cast_exclude, { if (user_have_feature_cast_support(user, tmp)) { do_send = 0; break; } }); if (do_send) route_to_user(hub, user, command); } }); 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); LIST_FOREACH(struct hub_user*, user, hub->users->list, { if (user_is_nat_override(user)) route_to_user(hub, user, cmd); else route_to_user(hub, user, u->info); }); adc_msg_free(cmd); } return 0; } modelrockettier-uhub-a8ee6e7/src/core/route.h000066400000000000000000000033321324501300100213710ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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 */ modelrockettier-uhub-a8ee6e7/src/core/user.c000066400000000000000000000175551324501300100212200ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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 = ioq_send_create(); user->recv_queue = ioq_recv_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); flood_control_reset(&user->flood_chat); flood_control_reset(&user->flood_connect); flood_control_reset(&user->flood_search); flood_control_reset(&user->flood_update); flood_control_reset(&user->flood_extras); user->hub = hub; return user; } void user_destroy(struct hub_user* user) { LOG_TRACE("user_destroy(), user=%p", user); ioq_recv_destroy(user->recv_queue); ioq_send_destroy(user->send_queue); if (user->connection) { LOG_TRACE("user_destory() -> net_con_close(%p)", user->connection); net_con_close(user->connection); } 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); if (cmd) { user->info = adc_msg_incref(cmd); } else { user->info = 0; } } 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'): return feature_bas0; 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; // ignore these extensions, they are not useful for the hub. case FOURCC('D','H','T','0'): return 0; 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_FOREACH(char*, tmp, user->feature_cast, { if (strncmp(tmp, feature, 4) == 0) return 1; }); 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) { return auth_cred_is_protected(user->credentials); } /** * 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) { return auth_cred_is_registered(user->credentials); } 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_update_error: return "update 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); } modelrockettier-uhub-a8ee6e7/src/core/user.h000066400000000000000000000245551324501300100212230ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_USER_H #define HAVE_UHUB_USER_H struct hub_info; struct hub_iobuf; struct flood_control; 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 */ feature_bas0 = 0x00000400, /** BAS0: Obsolete pre-ADC/1.0 protocol version */ flag_flood = 0x00400000, /** User has been notified about flooding. */ flag_muted = 0x00800000, /** User is muted (cannot chat) */ 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_update_error = 10, /** Update error. INF update changed share/slot info and no longer satisfies the hub limits. */ quit_hub_disabled = 11, /** Hub is disabled. No new connections allowed */ quit_ghost_timeout = 12, /** 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 nick[MAX_NICK_LEN+1]; /** User's nick name */ char cid[MAX_CID_LEN+1]; /** global client ID */ char user_agent[MAX_UA_LEN+1];/** User agent string */ 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 { struct hub_user_info id; /** Contains nick name and CID */ enum auth_credentials credentials; /** see enum user_credentials */ enum user_state state; /** see enum user_state */ uint32_t flags; /** see enum user_flags */ 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 ioq_recv* recv_queue; struct ioq_send* 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) */ struct flood_control flood_chat; struct flood_control flood_connect; struct flood_control flood_search; struct flood_control flood_update; struct flood_control flood_extras; }; /** * 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 */ modelrockettier-uhub-a8ee6e7/src/core/usermanager.c000066400000000000000000000115061324501300100225410ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" /* * 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 = auth_cred_none; user_destroy(u); } } static int uman_map_compare(const void* a, const void* b) { return strcmp((const char*) a, (const char*) b); } struct hub_user_manager* uman_init() { struct hub_user_manager* users = (struct hub_user_manager*) hub_malloc_zero(sizeof(struct hub_user_manager)); if (!users) return NULL; users->list = list_create(); users->nickmap = rb_tree_create(uman_map_compare, NULL, NULL); users->cidmap = rb_tree_create(uman_map_compare, NULL, NULL); users->sids = sid_pool_create(net_get_max_sockets()); return users; } int uman_shutdown(struct hub_user_manager* users) { if (!users) return -1; if (users->nickmap) rb_tree_destroy(users->nickmap); if (users->cidmap) rb_tree_destroy(users->cidmap); if (users->list) { list_clear(users->list, &clear_user_list_callback); list_destroy(users->list); } sid_pool_destroy(users->sids); hub_free(users); return 0; } int uman_add(struct hub_user_manager* users, struct hub_user* user) { if (!users || !user) return -1; rb_tree_insert(users->nickmap, user->id.nick, user); rb_tree_insert(users->cidmap, user->id.cid, user); list_append(users->list, user); users->count++; users->count_peak = MAX(users->count, users->count_peak); users->shared_size += user->limits.shared_size; users->shared_files += user->limits.shared_files; return 0; } int uman_remove(struct hub_user_manager* users, struct hub_user* user) { if (!users || !user) return -1; list_remove(users->list, user); rb_tree_remove(users->nickmap, user->id.nick); rb_tree_remove(users->cidmap, user->id.cid); if (users->count > 0) { users->count--; } else { uhub_assert(!"negative count!"); } users->shared_size -= user->limits.shared_size; users->shared_files -= user->limits.shared_files; return 0; } struct hub_user* uman_get_user_by_sid(struct hub_user_manager* users, sid_t sid) { return sid_lookup(users->sids, sid); } struct hub_user* uman_get_user_by_cid(struct hub_user_manager* users, const char* cid) { struct hub_user* user = (struct hub_user*) rb_tree_get(users->cidmap, (const void*) cid); return user; } struct hub_user* uman_get_user_by_nick(struct hub_user_manager* users, const char* nick) { struct hub_user* user = (struct hub_user*) rb_tree_get(users->nickmap, nick); return user; } size_t uman_get_user_by_addr(struct hub_user_manager* users, struct linked_list* target, struct ip_range* range) { size_t num = 0; struct hub_user* user; LIST_FOREACH(struct hub_user*, user, users->list, { if (ip_in_range(&user->id.addr, range)) { list_append(target, user); num++; } }); return num; } int uman_send_user_list(struct hub_info* hub, struct hub_user_manager* users, struct hub_user* target) { int ret = 1; struct hub_user* user; user_flag_set(target, flag_user_list); LIST_FOREACH(struct hub_user*, user, users->list, { if (user_is_logged_in(user)) { ret = route_to_user(hub, target, user->info); if (!ret) break; } }); #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_manager* users, 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_user_manager* users, struct hub_user* user) { sid_t sid = sid_alloc(users->sids, user); user->id.sid = sid; return sid; } modelrockettier-uhub-a8ee6e7/src/core/usermanager.h000066400000000000000000000110571324501300100225470ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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" */ 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 sid_pool* sids; /**<< "Maps SIDs to users (constant time)" */ struct linked_list* list; /**<< "Contains all logged in users" */ struct rb_tree* nickmap; /**<< "Maps nicknames to users (red black tree)" */ struct rb_tree* cidmap; /**<< "Maps CIDs to users (red black tree)" */ }; /** * Initializes the user manager. * @return 0 on success, or -1 if error (out of memory). */ extern struct hub_user_manager* uman_init(); /** * 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 (invalid pointer). */ extern int uman_shutdown(struct hub_user_manager* users); /** * Generate statistics for logfiles. */ extern void uman_update_stats(struct hub_user_manager* users); extern void uman_print_stats(struct hub_user_manager* users); /** * Add a user to the user manager. * * @param users The usermanager to add the user to * @param user The user to be added to the hub. */ extern int uman_add(struct hub_user_manager* users, 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_user_manager* users, struct hub_user* user); /** * Returns and allocates an unused session ID (SID). */ extern sid_t uman_get_free_sid(struct hub_user_manager* users, 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_user_manager* users, 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_user_manager* users, 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_user_manager* users, const char* nick); /** * Lookup users based on an ip address range. * * @param[out] target the list of users matching the address * @param range the IP range of users to match * @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_user_manager* users, struct linked_list* target, 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_manager* users, 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_manager* users, struct hub_user* user); #endif /* HAVE_UHUB_USER_MANAGER_H */ modelrockettier-uhub-a8ee6e7/src/network/000077500000000000000000000000001324501300100206225ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/src/network/backend.c000066400000000000000000000127211324501300100223600ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" #include "network/connection.h" struct net_backend; struct net_connection; struct net_cleanup_handler { size_t num; size_t max; struct net_connection** queue; }; struct net_backend { struct net_backend_common common; time_t now; /* the time now (used for timeout handling) */ struct timeout_queue timeout_queue; /* used for timeout handling */ struct net_cleanup_handler* cleaner; /* handler to cleanup connections at a safe point */ struct net_backend_handler handler; /* backend event handler */ struct net_backend* data; /* backend specific data */ }; static struct net_backend* g_backend; #ifdef USE_EPOLL extern struct net_backend* net_backend_init_epoll(struct net_backend_handler*, struct net_backend_common*); #endif #ifdef USE_KQUEUE extern struct net_backend* net_backend_init_kqueue(struct net_backend_handler*, struct net_backend_common*); #endif #ifdef USE_SELECT extern struct net_backend* net_backend_init_select(struct net_backend_handler*, struct net_backend_common*); #endif static net_backend_init_t net_backend_init_funcs[] = { #ifdef USE_EPOLL net_backend_init_epoll, #endif #ifdef USE_KQUEUE net_backend_init_kqueue, #endif #ifdef USE_SELECT net_backend_init_select, #endif 0 }; int net_backend_init() { size_t n; g_backend = (struct net_backend*) hub_malloc_zero(sizeof(struct net_backend)); g_backend->common.num = 0; g_backend->common.max = net_get_max_sockets(); g_backend->now = time(0); timeout_queue_initialize(&g_backend->timeout_queue, g_backend->now, 120); /* FIXME: max 120 secs! */ g_backend->cleaner = net_cleanup_initialize(g_backend->common.max); for (n = 0; net_backend_init_funcs[n]; n++) { g_backend->data = net_backend_init_funcs[n](&g_backend->handler, &g_backend->common); if (g_backend->data) { LOG_DEBUG("Initialized %s network backend.", g_backend->handler.backend_name()); return 1; } } LOG_FATAL("Unable to find a suitable network backend"); return 0; } void net_backend_shutdown() { g_backend->handler.backend_shutdown(g_backend->data); timeout_queue_shutdown(&g_backend->timeout_queue); net_cleanup_shutdown(g_backend->cleaner); hub_free(g_backend); g_backend = 0; } void net_backend_update(struct net_connection* con, int events) { g_backend->handler.con_mod(g_backend->data, con, events); } struct net_connection* net_con_create() { return g_backend->handler.con_create(g_backend->data); } struct timeout_queue* net_backend_get_timeout_queue() { if (!g_backend) return 0; return &g_backend->timeout_queue; } /** * Process the network backend. */ int net_backend_process() { int res = 0; size_t secs = timeout_queue_get_next_timeout(&g_backend->timeout_queue, g_backend->now); if (g_backend->common.num) res = g_backend->handler.backend_poll(g_backend->data, secs * 1000); g_backend->now = time(0); timeout_queue_process(&g_backend->timeout_queue, g_backend->now); if (res == -1) { LOG_WARN("backend error."); return 0; } // Process pending DNS results // net_dns_process(); g_backend->handler.backend_process(g_backend->data, res); net_cleanup_process(g_backend->cleaner); return 1; } time_t net_get_time() { return g_backend->now; } void net_con_initialize(struct net_connection* con, int sd, net_connection_cb callback, const void* ptr, int events) { g_backend->handler.con_init(g_backend->data, con, sd, callback, ptr); net_set_nonblocking(net_con_get_sd(con), 1); net_set_nosigpipe(net_con_get_sd(con), 1); g_backend->handler.con_add(g_backend->data, con, events); g_backend->common.num++; } void net_con_close(struct net_connection* con) { if (con->flags & NET_CLEANUP) return; g_backend->common.num--; net_con_clear_timeout(con); g_backend->handler.con_del(g_backend->data, con); #ifdef SSL_SUPPORT if (con->ssl) net_ssl_shutdown(con); #endif /* SSL_SUPPORT */ net_close(con->sd); con->sd = -1; net_cleanup_delayed_free(g_backend->cleaner, con); } struct net_cleanup_handler* net_cleanup_initialize(size_t max) { struct net_cleanup_handler* handler = (struct net_cleanup_handler*) hub_malloc(sizeof(struct net_cleanup_handler)); handler->num = 0; handler->max = max; handler->queue = hub_malloc_zero(sizeof(struct net_connection*) * max); return handler; } void net_cleanup_shutdown(struct net_cleanup_handler* handler) { net_cleanup_process(handler); hub_free(handler->queue); hub_free(handler); } void net_cleanup_delayed_free(struct net_cleanup_handler* handler, struct net_connection* con) { handler->queue[handler->num++] = con; con->flags |= NET_CLEANUP; } void net_cleanup_process(struct net_cleanup_handler* handler) { size_t n; for (n = 0; n < handler->num; n++) { struct net_connection* con = handler->queue[n]; LOG_TRACE("net_cleanup_process: free: %p", con); net_con_destroy(con); } handler->num = 0; } modelrockettier-uhub-a8ee6e7/src/network/backend.h000066400000000000000000000063161324501300100223700ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_NETWORK_BACKEND_H #define HAVE_UHUB_NETWORK_BACKEND_H struct net_backend; struct net_backend_common; struct net_backend_handler; struct net_cleanup_handler; struct net_connection; typedef void (*net_connection_cb)(struct net_connection*, int event, void* ptr); typedef struct net_backend* (*net_backend_init_t)(struct net_backend_handler* handler, struct net_backend_common* common); typedef int (*net_backend_poll)(struct net_backend*, int ms); typedef void (*net_backend_proc)(struct net_backend*, int res); typedef void (*net_backend_destroy)(struct net_backend*); typedef struct net_connection* (*net_con_backend_create)(struct net_backend*); typedef void (*net_con_backend_init)(struct net_backend*, struct net_connection*, int sd, net_connection_cb callback, const void* ptr); typedef void (*net_con_backend_add)(struct net_backend*, struct net_connection*, int mask); typedef void (*net_con_backend_mod)(struct net_backend*, struct net_connection*, int mask); typedef void (*net_con_backend_del)(struct net_backend*,struct net_connection*); typedef const char* (*net_con_backend_name)(); struct net_backend_handler { net_con_backend_name backend_name; net_backend_poll backend_poll; net_backend_proc backend_process; net_backend_destroy backend_shutdown; net_con_backend_create con_create; net_con_backend_init con_init; net_con_backend_add con_add; net_con_backend_mod con_mod; net_con_backend_del con_del; }; struct net_backend_common { size_t num; /* number of connections monitored by the backend */ size_t max; /* max number of connections that can be monitored */ }; /** * Initialize the network backend. * Returns 1 on success, or 0 on failure. */ extern int net_backend_init(); /** * Shutdown the network connection backend. */ extern void net_backend_shutdown(); /** * Process the network backend. */ extern int net_backend_process(); /** * Update the event mask. * * @param con Connection handle. * @param events Event mask (NET_EVENT_*) */ extern void net_backend_update(struct net_connection* con, int events); /** * Get the current time. */ time_t net_get_time(); extern struct timeout_queue* net_backend_get_timeout_queue(); struct net_cleanup_handler* net_cleanup_initialize(size_t max); void net_cleanup_shutdown(struct net_cleanup_handler* handler); void net_cleanup_delayed_free(struct net_cleanup_handler* handler, struct net_connection* con); void net_cleanup_process(struct net_cleanup_handler* handler); #endif /* HAVE_UHUB_NETWORK_BACKEND_H */ modelrockettier-uhub-a8ee6e7/src/network/common.h000066400000000000000000000032401324501300100222620ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #define NET_WANT_READ NET_EVENT_READ #define NET_WANT_WRITE NET_EVENT_WRITE #define NET_WANT_ACCEPT NET_EVENT_READ #define NET_SSL_ANY NET_WANT_SSL_READ | NET_WANT_SSL_WRITE | NET_WANT_SSL_ACCEPT | NET_WANT_SSL_CONNECT | NET_WANT_SSL_X509_LOOKUP struct ssl_handle; /* abstract type */ #define NET_CLEANUP 0x8000 #define NET_CON_STRUCT_BASIC \ int sd; /** socket descriptor */ \ uint32_t flags; /** Connection flags */ \ void* ptr; /** data pointer */ \ net_connection_cb callback; /** Callback function */ \ struct timeout_evt* timeout; /** timeout event handler */ #define NET_CON_STRUCT_SSL \ struct ssl_handle* ssl; /** SSL handle */ #ifdef SSL_SUPPORT #define NET_CON_STRUCT_COMMON \ NET_CON_STRUCT_BASIC \ NET_CON_STRUCT_SSL #else #define NET_CON_STRUCT_COMMON \ NET_CON_STRUCT_BASIC #endif /* SSL_SUPPORT */ modelrockettier-uhub-a8ee6e7/src/network/connection.c000066400000000000000000000305311324501300100231270ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" #include "network/common.h" #include "network/backend.h" static int is_blocked_or_interrupted() { int err = net_error(); return #ifdef WINSOCK err == WSAEWOULDBLOCK #else err == EWOULDBLOCK #endif || err == EINTR; } ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len) { int ret; #ifdef SSL_SUPPORT if (!con->ssl) { #endif ret = net_send(con->sd, buf, len, UHUB_SEND_SIGNAL); if (ret == -1) { if (is_blocked_or_interrupted()) return 0; return -1; } #ifdef SSL_SUPPORT } else { ret = net_ssl_send(con, buf, len); } #endif /* SSL_SUPPORT */ return ret; } ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len) { int ret; #ifdef SSL_SUPPORT if (!con->ssl) { #endif ret = net_recv(con->sd, buf, len, 0); if (ret == -1) { if (is_blocked_or_interrupted()) return 0; return -net_error(); } else if (ret == 0) { return -1; } #ifdef SSL_SUPPORT } else { ret = net_ssl_recv(con, buf, len); } #endif /* SSL_SUPPORT */ return ret; } ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len) { int ret = net_recv(con->sd, buf, len, MSG_PEEK); if (ret == -1) { if (is_blocked_or_interrupted()) return 0; return -net_error(); } else if (ret == 0) return -1; return ret; } #ifdef SSL_SUPPORT int net_con_is_ssl(struct net_connection* con) { return !!con->ssl; } #endif /* SSL_SUPPORT */ 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 net_con_update(struct net_connection* con, int events) { #ifdef SSL_SUPPORT if (con->ssl) net_ssl_update(con, events); else #endif net_backend_update(con, events); } 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_destroy(struct net_connection* con) { #ifdef SSL_SUPPORT if (con && con->ssl) net_ssl_destroy(con); #endif hub_free(con); } void net_con_callback(struct net_connection* con, int events) { if (con->flags & NET_CLEANUP) return; if (events == NET_EVENT_TIMEOUT) { LOG_TRACE("net_con_callback(%p, TIMEOUT)", con); con->callback(con, events, con->ptr); return; } #ifdef SSL_SUPPORT if (con->ssl) net_ssl_callback(con, events); else #endif con->callback(con, events, con->ptr); } struct net_connect_job { struct net_connection* con; struct net_connect_handle* handle; struct sockaddr_storage addr; struct net_connect_job* next; }; struct net_connect_handle { const char* address; uint16_t port; void* ptr; net_connect_cb callback; struct net_dns_job* dns; const struct net_dns_result* result; struct net_connect_job* job4; struct net_connect_job* job6; }; static void net_connect_callback(struct net_connect_handle* handle, enum net_connect_status status, struct net_connection* con); static void net_connect_job_internal_cb(struct net_connection* con, int event, void* ptr); /** * Check if a connection job is completed. * @return -1 on completed with an error, 0 on not yet completed, or 1 if completed successfully (connected). */ static int net_connect_job_check(struct net_connect_job* job) { struct net_connection* con = job->con; int af = job->addr.ss_family; enum net_connect_status status; int ret = net_connect(net_con_get_sd(con), (struct sockaddr*) &job->addr, af == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)); if (ret == 0 || (ret == -1 && net_error() == EISCONN)) { LOG_TRACE("net_connect_job_check(): Socket connected!"); job->con = NULL; net_con_clear_timeout(con); net_connect_callback(job->handle, net_connect_status_ok, con); return 1; } else if (ret == -1 && (net_error() == EALREADY || net_error() == EINPROGRESS || net_error() == EWOULDBLOCK || net_error() == EINTR)) { return 0; } LOG_TRACE("net_connect_job_check(): Socket error!"); switch (net_error()) { case ECONNREFUSED: status = net_connect_status_refused; break; case ENETUNREACH: status = net_connect_status_unreachable; break; default: status = net_connect_status_socket_error; } net_connect_callback(job->handle, status, NULL); return -1; } static void net_connect_job_free(struct net_connect_job* job) { if (job->con) net_con_close(job->con); job->handle = NULL; job->next = NULL; hub_free(job); } static void net_connect_job_stop(struct net_connect_job* job) { if (job->addr.ss_family == AF_INET6) { job->handle->job6 = job->next; } else { job->handle->job4 = job->next; } net_connect_job_free(job); } static int net_connect_depleted(struct net_connect_handle* handle) { return (!handle->job6 && !handle->job4); } static int net_connect_job_process(struct net_connect_job* job) { int sd; if (!job->con) { sd = net_socket_create(job->addr.ss_family, SOCK_STREAM, IPPROTO_TCP); if (sd == -1) { LOG_DEBUG("net_connect_job_process: Unable to create socket!"); net_connect_callback(job->handle, net_connect_status_socket_error, NULL); return -1; // FIXME } job->con = net_con_create(); net_con_initialize(job->con, sd, net_connect_job_internal_cb, job, NET_EVENT_WRITE); net_con_set_timeout(job->con, TIMEOUT_CONNECTED); // FIXME: Use a proper timeout value! } return net_connect_job_check(job); } /* * Internal callback used to establish an outbound connection. */ static void net_connect_job_internal_cb(struct net_connection* con, int event, void* ptr) { struct net_connect_job* job = net_con_get_ptr(con); struct net_connect_job* next_job = job->next; struct net_connect_handle* handle = job->handle; if (event == NET_EVENT_TIMEOUT) { // FIXME: Try next address, or if no more addresses left declare failure to connect. if (job->addr.ss_family == AF_INET6) { net_connect_job_stop(job); if (!next_job) { LOG_TRACE("No more IPv6 addresses to try!"); } } else { net_connect_job_stop(job); if (!next_job) { LOG_TRACE("No more IPv4 addresses to try!"); } } if (net_connect_depleted(handle)) { LOG_TRACE("No more addresses left. Unable to connect!"); net_connect_callback(handle, net_connect_status_timeout, NULL); } return; } if (event == NET_EVENT_WRITE) { net_connect_job_process(job); } } static void net_connect_cancel(struct net_connect_handle* handle) { struct net_connect_job* job; job = handle->job6; while (job) { job = job->next; net_connect_job_free(handle->job6); handle->job6 = job; } job = handle->job4; while (job) { job = job->next; net_connect_job_free(handle->job4); handle->job4 = job; } } static int net_connect_process_queue(struct net_connect_handle* handle, struct net_connect_job* job) { int ret; while (job) { ret = net_connect_job_process(job); if (ret < 0) { net_connect_job_stop(job); continue; } else if (ret == 0) { // Need to process again return 0; } else { // FIXME: Success! return 1; } } return -1; } static int net_connect_process(struct net_connect_handle* handle) { int ret4, ret6; ret6 = net_connect_process_queue(handle, handle->job6); if (ret6 == 1) return 1; // Connected - cool! net_connect_process_queue(handle, handle->job4); return 0; } static int net_connect_job_schedule(struct net_connect_handle* handle, struct ip_addr_encap* addr) { struct net_connect_job* job; struct sockaddr_in* addr4; struct sockaddr_in6* addr6; if (addr->af == AF_INET6 && !net_is_ipv6_supported()) { LOG_TRACE("net_connect_job_schedule(): Skipping IPv6 support since IPv6 is not supported."); return 0; } else { job = hub_malloc_zero(sizeof(struct net_connect_job)); job->handle = handle; if (addr->af == AF_INET6) { addr6 = (struct sockaddr_in6*) &job->addr; LOG_TRACE("net_connect_job_schedule(): Scheduling IPv6 connect job."); addr6->sin6_family = AF_INET6; addr6->sin6_port = htons(handle->port); memcpy(&addr6->sin6_addr, &addr->internal_ip_data.in6, sizeof(struct in6_addr)); // prepend job->next = handle->job6; handle->job6 = job; } else { addr4 = (struct sockaddr_in*) &job->addr; LOG_TRACE("net_connect_job_schedule(): Scheduling IPv4 connect job."); addr4->sin_family = AF_INET; addr4->sin_port = htons(handle->port); memcpy(&addr4->sin_addr, &addr->internal_ip_data.in, sizeof(struct in_addr)); // prepend job->next = handle->job4; handle->job4 = job; } } return 1; } /* * Callback when the DNS results are ready. * Create a list of IPv6 and IPv4 addresses, then * start connecting to them one by one until one succeeds. */ static int net_con_connect_dns_callback(struct net_dns_job* job, const struct net_dns_result* result) { struct ip_addr_encap* addr; struct net_connect_handle* handle = (struct net_connect_handle*) net_dns_job_get_ptr(job); handle->dns = NULL; size_t usable = 0; LOG_TRACE("net_con_connect(): async - Got DNS results"); if (!result) { LOG_DEBUG("net_con_connect() - Unable to lookup host!"); net_connect_callback(handle, net_connect_status_dns_error, NULL); return 1; } if (!net_dns_result_size(result)) { LOG_DEBUG("net_con_connect() - Host not found!"); net_connect_callback(handle, net_connect_status_host_not_found, NULL); return 1; } handle->result = result; // Extract results into a separate list of IPv4 and IPv6 addresses. addr = net_dns_result_first(result); while (addr) { if (net_connect_job_schedule(handle, addr)) usable++; addr = net_dns_result_next(result); } net_connect_process(handle); return 0; } // typedef void (*net_connect_cb)(struct net_connect_handle*, enum net_connect_handle_code, struct net_connection* con); struct net_connect_handle* net_con_connect(const char* address, uint16_t port, net_connect_cb callback, void* ptr) { struct net_connect_handle* handle = hub_malloc_zero(sizeof(struct net_connect_handle)); handle->address = hub_strdup(address); handle->port = port; handle->ptr = ptr; handle->callback = callback; // FIXME: Check if DNS resolving is necessary ? handle->dns = net_dns_gethostbyname(address, AF_UNSPEC, net_con_connect_dns_callback, handle); if (!handle->dns) { LOG_TRACE("net_con_connect(): Unable to create DNS lookup job."); hub_free((char*) handle->address); hub_free(handle); return NULL; } return handle; } void net_connect_destroy(struct net_connect_handle* handle) { hub_free((char*) handle->address); // cancel DNS job if pending if (handle->dns) net_dns_job_cancel(handle->dns); // Stop any connect jobs. net_connect_cancel(handle); // free any DNS results net_dns_result_free(handle->result); hub_free(handle); } static void net_connect_callback(struct net_connect_handle* handle, enum net_connect_status status, struct net_connection* con) { uhub_assert(handle->callback != NULL); // Call the callback handle->callback(handle, status, con, handle->ptr); handle->callback = NULL; // Cleanup net_connect_destroy(handle); } static void timeout_callback(struct timeout_evt* evt) { net_con_callback((struct net_connection*) evt->ptr, NET_EVENT_TIMEOUT); } 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(net_backend_get_timeout_queue(), con->timeout, seconds); } else { timeout_queue_reschedule(net_backend_get_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(net_backend_get_timeout_queue(), con->timeout); hub_free(con->timeout); con->timeout = 0; } } modelrockettier-uhub-a8ee6e7/src/network/connection.h000066400000000000000000000103541324501300100231350ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_NETWORK_CONNECTION_H #define HAVE_UHUB_NETWORK_CONNECTION_H #include "uhub.h" #include "network/common.h" #include "network/backend.h" #include "network/tls.h" #define NET_EVENT_TIMEOUT 0x0001 #define NET_EVENT_READ 0x0002 #define NET_EVENT_WRITE 0x0004 #define NET_EVENT_ERROR 0x1000 struct net_connection { NET_CON_STRUCT_COMMON }; struct net_connect_handle; enum net_connect_status { net_connect_status_ok = 0, net_connect_status_host_not_found = -1, net_connect_status_no_address = -2, net_connect_status_dns_error = -3, net_connect_status_refused = -4, net_connect_status_unreachable = -5, net_connect_status_timeout = -6, net_connect_status_socket_error = -7, }; typedef void (*net_connect_cb)(struct net_connect_handle*, enum net_connect_status status, struct net_connection* con, 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(); /** * Establish an outbound TCP connection. * This will resolve the IP-addresses, and connect to * either an IPv4 or IPv6 address depending if it is supported, * and using the happy eyeballs algorithm. * * @param address Hostname, IPv4 or IPv6 address * @param port TCP port number * @param callback A callback to be called once the connection is established, or failed. * @returns a handle to the connection establishment job, or NULL if an immediate error. */ extern struct net_connect_handle* net_con_connect(const char* address, uint16_t port, net_connect_cb callback, void* ptr); extern void net_connect_destroy(struct net_connect_handle* handle); 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); extern void net_con_callback(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). */ extern void 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); #endif /* HAVE_UHUB_NETWORK_CONNECTION_H */ modelrockettier-uhub-a8ee6e7/src/network/dnsresolver.c000066400000000000000000000242221324501300100233360ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" static struct net_dns_job* find_and_remove_job(struct net_dns_job* job); static struct net_dns_result* find_and_remove_result(struct net_dns_job* job); struct net_dns_job { net_dns_job_cb callback; void* ptr; char* host; int af; #ifdef DEBUG_LOOKUP_TIME struct timeval time_start; struct timeval time_finish; #endif uhub_thread_t* thread_handle; }; struct net_dns_result { struct linked_list* addr_list; struct net_dns_job* job; }; static void free_job(struct net_dns_job* job) { if (job) { hub_free(job->host); hub_free(job); } } static void shutdown_free_jobs(void* ptr) { struct net_dns_job* job = (struct net_dns_job*) ptr; uhub_thread_cancel(job->thread_handle); uhub_thread_join(job->thread_handle); free_job(job); } static void shutdown_free_results(void* ptr) { struct net_dns_result* result = (struct net_dns_result*) ptr; uhub_thread_join(result->job->thread_handle); net_dns_result_free(result); } static void notify_callback(struct uhub_notify_handle* handle, void* ptr) { net_dns_process(); } // NOTE: Any job manipulating the members of this // struct must lock the mutex! struct net_dns_subsystem { struct linked_list* jobs; // currently running jobs struct linked_list* results; // queue of results that are awaiting being delivered to callback. uhub_mutex_t mutex; struct uhub_notify_handle* notify_handle; // used to signal back to the event loop that there is something to process. }; static struct net_dns_subsystem* g_dns = NULL; void net_dns_initialize() { LOG_TRACE("net_dns_initialize()"); g_dns = (struct net_dns_subsystem*) hub_malloc_zero(sizeof(struct net_dns_subsystem)); g_dns->jobs = list_create(); g_dns->results = list_create(); uhub_mutex_init(&g_dns->mutex); g_dns->notify_handle = net_notify_create(notify_callback, g_dns); } void net_dns_destroy() { uhub_mutex_lock(&g_dns->mutex); LOG_TRACE("net_dns_destroy(): jobs=%d", (int) list_size(g_dns->jobs)); list_clear(g_dns->jobs, &shutdown_free_jobs); LOG_TRACE("net_dns_destroy(): results=%d", (int) list_size(g_dns->results)); list_clear(g_dns->results, &shutdown_free_results); uhub_mutex_unlock(&g_dns->mutex); list_destroy(g_dns->jobs); list_destroy(g_dns->results); uhub_mutex_destroy(&g_dns->mutex); net_notify_destroy(g_dns->notify_handle); hub_free(g_dns); g_dns = NULL; } void net_dns_process() { struct net_dns_result* result; uhub_mutex_lock(&g_dns->mutex); LOG_TRACE("net_dns_process(): jobs=%d, results=%d", (int) list_size(g_dns->jobs), (int) list_size(g_dns->results)); LIST_FOREACH(struct net_dns_result*, result, g_dns->results, { struct net_dns_job* job = result->job; #ifdef DEBUG_LOOKUP_TIME struct timeval time_result; timersub(&result->job->time_finish, &result->job->time_start, &time_result); LOG_TRACE("DNS lookup took %d ms", (time_result.tv_sec * 1000) + (time_result.tv_usec / 1000)); #endif // wait for the work thread to finish uhub_thread_join(job->thread_handle); // callback - should we delete the data immediately? if (job->callback(job, result)) { net_dns_result_free(result); } else { /* Caller wants to keep the result data, and * thus needs to call net_dns_result_free() to release it later. * We only clean up the job data here and keep the results intact. */ result->job = NULL; free_job(job); } }); list_clear(g_dns->results, NULL); uhub_mutex_unlock(&g_dns->mutex); } static void* job_thread_resolve_name(void* ptr) { struct net_dns_job* job = (struct net_dns_job*) ptr; struct addrinfo hints, *result, *it; struct net_dns_result* dns_results; int ret; memset(&hints, 0, sizeof(hints)); hints.ai_family = job->af; hints.ai_protocol = IPPROTO_TCP; ret = getaddrinfo(job->host, NULL, &hints, &result); if (ret != 0 && ret != EAI_NONAME) { LOG_TRACE("getaddrinfo() failed: %s", gai_strerror(ret)); return NULL; } dns_results = (struct net_dns_result*) hub_malloc(sizeof(struct net_dns_result)); dns_results->addr_list = list_create(); dns_results->job = job; if (ret != EAI_NONAME) { for (it = result; it; it = it->ai_next) { struct ip_addr_encap* ipaddr = hub_malloc_zero(sizeof(struct ip_addr_encap)); ipaddr->af = it->ai_family; if (it->ai_family == AF_INET) { struct sockaddr_in* addr4 = (struct sockaddr_in*) it->ai_addr; memcpy(&ipaddr->internal_ip_data.in, &addr4->sin_addr, sizeof(struct in_addr)); } else if (it->ai_family == AF_INET6) { struct sockaddr_in6* addr6 = (struct sockaddr_in6*) it->ai_addr; memcpy(&ipaddr->internal_ip_data.in6, &addr6->sin6_addr, sizeof(struct in6_addr)); } else { LOG_TRACE("getaddrinfo() returned result with unknown address family: %d", it->ai_family); hub_free(ipaddr); continue; } LOG_DUMP("getaddrinfo() - Address (%d) %s for \"%s\"", ret++, ip_convert_to_string(ipaddr), job->host); list_append(dns_results->addr_list, ipaddr); } freeaddrinfo(result); } else { /* hm */ } #ifdef DEBUG_LOOKUP_TIME gettimeofday(&job->time_finish, NULL); #endif uhub_mutex_lock(&g_dns->mutex); list_remove(g_dns->jobs, job); list_append(g_dns->results, dns_results); net_notify_signal(g_dns->notify_handle, 1); uhub_mutex_unlock(&g_dns->mutex); return dns_results; } extern struct net_dns_job* net_dns_gethostbyname(const char* host, int af, net_dns_job_cb callback, void* ptr) { struct net_dns_job* job = (struct net_dns_job*) hub_malloc_zero(sizeof(struct net_dns_job)); job->host = strdup(host); job->af = af; job->callback = callback; job->ptr = ptr; #ifdef DEBUG_LOOKUP_TIME gettimeofday(&job->time_start, NULL); #endif // FIXME - scheduling - what about a max number of threads? uhub_mutex_lock(&g_dns->mutex); job->thread_handle = uhub_thread_create(job_thread_resolve_name, job); if (!job->thread_handle) { LOG_WARN("Unable to create thread"); free_job(job); job = NULL; } else { list_append(g_dns->jobs, job); } uhub_mutex_unlock(&g_dns->mutex); return job; } extern struct net_dns_job* net_dns_gethostbyaddr(struct ip_addr_encap* ipaddr, net_dns_job_cb callback, void* ptr) { struct net_dns_job* job = (struct net_dns_job*) hub_malloc_zero(sizeof(struct net_dns_job)); // job->host = strdup(addr); job->af = ipaddr->af; job->callback = callback; job->ptr = ptr; // if (pthread_create(&job->thread_handle, NULL, start_job, job)) // { // free_job(job); // return NULL; // } return job; } // NOTE: mutex must be locked first! static struct net_dns_job* find_and_remove_job(struct net_dns_job* job) { struct net_dns_job* it; LIST_FOREACH(struct net_dns_job*, it, g_dns->jobs, { if (it == job) { list_remove(g_dns->jobs, it); return job; } }); return NULL; } // NOTE: mutex must be locked first! static struct net_dns_result* find_and_remove_result(struct net_dns_job* job) { struct net_dns_result* it; LIST_FOREACH(struct net_dns_result*, it, g_dns->results, { if (it->job == job) { list_remove(g_dns->results, it); return it; } }); return NULL; } extern int net_dns_job_cancel(struct net_dns_job* job) { int retval = 0; struct net_dns_result* res; LOG_TRACE("net_dns_job_cancel(): job=%p, name=%s", job, job->host); /* * This function looks up the job in the jobs queue (which contains only active jobs) * If that is found then the thread is cancelled, and the object is deleted. * If the job was not found, that is either because it was an invalid job, or because * it was already finished. At which point it was not deleted. * If the job is already finished, but the result has not been delivered, then this * deletes the result and the job. */ uhub_mutex_lock(&g_dns->mutex); if (find_and_remove_job(job)) { // job still active - cancel it, then close it. uhub_thread_cancel(job->thread_handle); uhub_thread_join(job->thread_handle); free_job(job); retval = 1; } else if ((res = find_and_remove_result(job))) { // job already finished - close it. uhub_thread_join(job->thread_handle); net_dns_result_free(res); } uhub_mutex_unlock(&g_dns->mutex); return retval; } extern struct net_dns_result* net_dns_job_sync_wait(struct net_dns_job* job) { struct net_dns_result* res = NULL; // Wait for job to finish (if not already) // This should make sure the job is removed from jobs and a result is // present in results. uhub_thread_join(job->thread_handle); // Remove the result in order to prevent the callback from being called. uhub_mutex_lock(&g_dns->mutex); res = find_and_remove_result(job); uhub_assert(res != NULL); res->job = NULL; free_job(job); uhub_mutex_unlock(&g_dns->mutex); return res; } void* net_dns_job_get_ptr(const struct net_dns_job* job) { return job->ptr; } extern size_t net_dns_result_size(const struct net_dns_result* res) { return list_size(res->addr_list); } extern struct ip_addr_encap* net_dns_result_first(const struct net_dns_result* res) { struct ip_addr_encap* ipaddr = list_get_first(res->addr_list); LOG_TRACE("net_dns_result_first() - Address: %s", ipaddr ? ip_convert_to_string(ipaddr) : "(no address)"); return ipaddr; } extern struct ip_addr_encap* net_dns_result_next(const struct net_dns_result* res) { struct ip_addr_encap* ipaddr = list_get_next(res->addr_list); LOG_TRACE("net_dns_result_next() - Address: %s", ipaddr ? ip_convert_to_string(ipaddr) : "(no more addresses)"); return ipaddr; } extern void net_dns_result_free(const struct net_dns_result* res) { if (!res) return; list_clear(res->addr_list, &hub_free); list_destroy(res->addr_list); free_job(res->job); hub_free((struct net_dns_result*) res); } modelrockettier-uhub-a8ee6e7/src/network/dnsresolver.h000066400000000000000000000114271324501300100233460ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_NETWORK_DNS_RESOLVER_H #define HAVE_UHUB_NETWORK_DNS_RESOLVER_H struct net_dns_job; struct net_dns_result; // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- /// Initialize the DNS subsystem void net_dns_initialize(); /// Shutdown and destroy the DNS subsystem. This will cancel any pending DNS jobs. void net_dns_destroy(); /// Process finished DNS lookups. void net_dns_process(); // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- /** * Callback to be called when the DNS job has finished. * If the name or address could not be resolved to an IP address (host not found, or found but has no address) * then 'result' contains an empty list (@see net_dns_result_size()). * If resolving caused an error then result is NULL. * * After this callback is called the job is considered done, and is freed. * * @param If 1 is returned then result is deleted immediately after the callback, * otherwise the callback becomes owner of the result data which must be freed with net_dns_result_free(). */ typedef int (*net_dns_job_cb)(struct net_dns_job*, const struct net_dns_result* result); /** * Resolve a hostname. * * @param host the hostname to be resolved. * @param af the indicated address family. Should be AF_INET, AF_INET6 (or AF_UNSPEC - which means both AF_INET and AF_INET6. * @param callback the callback to be called when the hostname has been resolved. * @param ptr A user-defined pointer value. * * @return A resolve job handle if the job has successfully started or NULL if unable to start resolving. */ extern struct net_dns_job* net_dns_gethostbyname(const char* host, int af, net_dns_job_cb callback, void* ptr); /** * Perform a reverse DNS lookup for a given IP address. * * @see net_dns_gethostbyname() * @return A resolve job handle if the job has successfully started or NULL if unable to start resolving. */ extern struct net_dns_job* net_dns_gethostbyaddr(struct ip_addr_encap* ipaddr, net_dns_job_cb callback, void* ptr); /** * Cancel a DNS lookup job. * * It is only allowed to call this once after a job has been started (@see net_dns_gethostbyname(), @see net_dns_gethostbyaddr()) * but before it has finished and delivered a to the callback address (@see net_dns_job_cb). * * @returns 1 if cancelled, or 0 if not cancelled (because the job was not found!) */ extern int net_dns_job_cancel(struct net_dns_job* job); /** * Wait in a synchronous manner for a running DNS job to finished and * return the result here. * The job must be started with net_dns_gethostbyaddr/net_dns_gethostbyname * and not finished or cancelled. * * If this function is invoked then the callback function will not be called and * can therefore be NULL. * * * struct net_dns_job* job = net_dns_gethostbyname("www.example.com", AF_INET, NULL, NULL); * struct net_dns_result* net_dns_job_sync_wait(job); * */ extern struct net_dns_result* net_dns_job_sync_wait(struct net_dns_job* job); /** * Returns the user specified pointer assigned to the resolving job */ extern void* net_dns_job_get_ptr(const struct net_dns_job* job); /// Returns the number of results provided. This is 0 if the host could not be found (or has no matching IP address). extern size_t net_dns_result_size(const struct net_dns_result*); /// Returns the first result (if net_dns_result_size > 0), or NULL if not first result exists. extern struct ip_addr_encap* net_dns_result_first(const struct net_dns_result*); /// Returns the next result or NULL if no next result exists. extern struct ip_addr_encap* net_dns_result_next(const struct net_dns_result*); /// When finished with the results extern void net_dns_result_free(const struct net_dns_result*); #endif /* HAVE_UHUB_NETWORK_DNS_RESOLVER_H */ modelrockettier-uhub-a8ee6e7/src/network/epoll.c000066400000000000000000000124611324501300100221050ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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_epoll { NET_CON_STRUCT_COMMON struct epoll_event ev; }; struct net_backend_epoll { int epfd; struct net_connection_epoll** conns; struct epoll_event events[EPOLL_EVBUFFER]; struct net_backend_common* common; }; static void net_backend_set_handlers(struct net_backend_handler* handler); const char* net_backend_name_epoll() { return "epoll"; } int net_backend_poll_epoll(struct net_backend* data, int ms) { struct net_backend_epoll* backend = (struct net_backend_epoll*) data; int res = epoll_wait(backend->epfd, backend->events, MIN(backend->common->num, EPOLL_EVBUFFER), ms); if (res == -1 && errno == EINTR) return 0; return res; } void net_backend_process_epoll(struct net_backend* data, int res) { int n, ev; struct net_backend_epoll* backend = (struct net_backend_epoll*) data; for (n = 0; n < res; n++) { struct net_connection_epoll* con = backend->conns[backend->events[n].data.fd]; if (con) { ev = 0; if (backend->events[n].events & EPOLLIN) ev |= NET_EVENT_READ; if (backend->events[n].events & EPOLLOUT) ev |= NET_EVENT_WRITE; net_con_callback((struct net_connection*) con, ev); } } } struct net_connection* net_con_create_epoll(struct net_backend* data) { struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection_epoll)); con->sd = -1; return con; } void net_con_initialize_epoll(struct net_backend* data, struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr) { struct net_connection_epoll* con = (struct net_connection_epoll*) con_; con->sd = sd; con->flags = 0; con->callback = callback; con->ev.events = 0; con->ptr = (void*) ptr; con->ev.data.fd = sd; } void net_con_backend_add_epoll(struct net_backend* data, struct net_connection* con_, int events) { struct net_backend_epoll* backend = (struct net_backend_epoll*) data; struct net_connection_epoll* con = (struct net_connection_epoll*) con_; backend->conns[con->sd] = con; if (events & NET_EVENT_READ) con->ev.events |= EPOLLIN; if (events & NET_EVENT_WRITE) con->ev.events |= EPOLLOUT; if (epoll_ctl(backend->epfd, EPOLL_CTL_ADD, con->sd, &con->ev) == -1) { LOG_TRACE("epoll_ctl() add failed."); } } void net_con_backend_mod_epoll(struct net_backend* data, struct net_connection* con_, int events) { struct net_backend_epoll* backend = (struct net_backend_epoll*) data; struct net_connection_epoll* con = (struct net_connection_epoll*) con_; int newev = 0; if (events & NET_EVENT_READ) newev |= EPOLLIN; if (events & NET_EVENT_WRITE) newev |= EPOLLOUT; if (newev == con->ev.events) return; con->ev.events = newev; if (epoll_ctl(backend->epfd, EPOLL_CTL_MOD, con->sd, &con->ev) == -1) { LOG_TRACE("epoll_ctl() modify failed."); } } void net_con_backend_del_epoll(struct net_backend* data, struct net_connection* con_) { struct net_backend_epoll* backend = (struct net_backend_epoll*) data; struct net_connection_epoll* con = (struct net_connection_epoll*) con_; backend->conns[con->sd] = 0; if (epoll_ctl(backend->epfd, EPOLL_CTL_DEL, con->sd, &con->ev) == -1) { LOG_WARN("epoll_ctl() delete failed."); } } void net_backend_shutdown_epoll(struct net_backend* data) { struct net_backend_epoll* backend = (struct net_backend_epoll*) data; close(backend->epfd); hub_free(backend->conns); hub_free(backend); } struct net_backend* net_backend_init_epoll(struct net_backend_handler* handler, struct net_backend_common* common) { struct net_backend_epoll* backend; if (getenv("EVENT_NOEPOLL")) return 0; backend = hub_malloc_zero(sizeof(struct net_backend_epoll)); backend->epfd = epoll_create(common->max); if (backend->epfd == -1) { LOG_WARN("Unable to create epoll socket."); hub_free(backend); return 0; } backend->conns = hub_malloc_zero(sizeof(struct net_connection_epoll*) * common->max); backend->common = common; net_backend_set_handlers(handler); return (struct net_backend*) backend; } static void net_backend_set_handlers(struct net_backend_handler* handler) { handler->backend_name = net_backend_name_epoll; handler->backend_poll = net_backend_poll_epoll; handler->backend_process = net_backend_process_epoll; handler->backend_shutdown = net_backend_shutdown_epoll; handler->con_create = net_con_create_epoll; handler->con_init = net_con_initialize_epoll; handler->con_add = net_con_backend_add_epoll; handler->con_mod = net_con_backend_mod_epoll; handler->con_del = net_con_backend_del_epoll; } #endif /* USE_EPOLL */ modelrockettier-uhub-a8ee6e7/src/network/ipcalc.c000066400000000000000000000273571324501300100222370ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" int ip_is_valid_ipv4(const char* address) { size_t 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)); 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)); 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; const char* split; if (!address || !range) return 0; 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); } modelrockettier-uhub-a8ee6e7/src/network/ipcalc.h000066400000000000000000000066601324501300100222360ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ /* * 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 */ modelrockettier-uhub-a8ee6e7/src/network/kqueue.c000066400000000000000000000172421324501300100222730ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" #ifdef USE_KQUEUE #include "network/connection.h" #include "network/common.h" #include "network/backend.h" #define KQUEUE_EVBUFFER 512 struct net_connection_kqueue { NET_CON_STRUCT_COMMON struct kevent ev_r; struct kevent ev_w; int change; }; struct net_backend_kqueue { int kqfd; struct net_connection_kqueue** conns; struct kevent* changes; int* change_list; size_t change_list_len; struct kevent events[KQUEUE_EVBUFFER]; struct net_backend_common* common; }; #define CHANGE_ACTION_ADD 0x0001 #define CHANGE_ACTION_MOD 0x0002 #define CHANGE_ACTION_DEL 0x0004 #define CHANGE_OP_WANT_READ 0x0100 #define CHANGE_OP_WANT_WRITE 0x0200 static void net_backend_set_handlers(struct net_backend_handler* handler); static void add_change(struct net_backend_kqueue* backend, struct net_connection_kqueue* con, int actions); static size_t create_change_list(struct net_backend_kqueue* backend); const char* net_backend_name_kqueue() { return "kqueue"; } int net_backend_poll_kqueue(struct net_backend* data, int ms) { int res; struct timespec tspec = { 0, }; struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data; size_t changes; tspec.tv_sec = (ms / 1000); tspec.tv_nsec = ((ms % 1000) * 1000000); changes = create_change_list(backend); res = kevent(backend->kqfd, backend->changes, changes, backend->events, KQUEUE_EVBUFFER, &tspec); if (res == -1 && errno == EINTR) return 0; return res; } void net_backend_process_kqueue(struct net_backend* data, int res) { int n; struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data; for (n = 0; n < res; n++) { struct net_connection_kqueue* con = (struct net_connection_kqueue*) backend->events[n].udata; if (con && con->sd >= 0 && backend->conns[con->sd]) { int ev = 0; if (backend->events[n].filter == EVFILT_READ) ev = NET_EVENT_READ; else if (backend->events[n].filter == EVFILT_WRITE) ev = NET_EVENT_WRITE; net_con_callback((struct net_connection*) con, ev); } } } struct net_connection* net_con_create_kqueue(struct net_backend* data) { struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection_kqueue)); con->sd = -1; return con; } void net_con_initialize_kqueue(struct net_backend* data, struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr) { struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_; con->sd = sd; con->flags = 0; con->callback = callback; con->ptr = (void*) ptr; } void net_con_backend_add_kqueue(struct net_backend* data, struct net_connection* con_, int events) { struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data; struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_; int operation; backend->conns[con->sd] = con; operation = CHANGE_ACTION_ADD; if (events & NET_EVENT_READ) operation |= CHANGE_OP_WANT_READ; if (events & NET_EVENT_WRITE) operation |= CHANGE_OP_WANT_WRITE; add_change(backend, con, operation); } void net_con_backend_mod_kqueue(struct net_backend* data, struct net_connection* con_, int events) { struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data; struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_; int operation = CHANGE_ACTION_ADD; if (events & NET_EVENT_READ) operation |= CHANGE_OP_WANT_READ; if (events & NET_EVENT_WRITE) operation |= CHANGE_OP_WANT_WRITE; add_change(backend, con, operation); } void net_con_backend_del_kqueue(struct net_backend* data, struct net_connection* con_) { struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data; struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_; /* No need to remove it from the kqueue filter, the kqueue man page says it is automatically removed when the descriptor is closed... */ add_change(backend, con, CHANGE_ACTION_DEL); // Unmap the socket descriptor. backend->conns[con->sd] = 0; } void net_backend_shutdown_kqueue(struct net_backend* data) { struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data; close(backend->kqfd); hub_free(backend->conns); hub_free(backend->changes); hub_free(backend->change_list); hub_free(backend); } struct net_backend* net_backend_init_kqueue(struct net_backend_handler* handler, struct net_backend_common* common) { struct net_backend_kqueue* backend; if (getenv("EVENT_NOKQUEUE")) return 0; backend = hub_malloc_zero(sizeof(struct net_backend_kqueue)); backend->kqfd = kqueue(); if (backend->kqfd == -1) { LOG_WARN("Unable to create kqueue socket."); return 0; } backend->conns = hub_malloc_zero(sizeof(struct net_connection_kqueue*) * common->max); backend->changes = hub_malloc_zero(sizeof(struct kevent) * common->max * 2); backend->change_list = hub_malloc_zero(sizeof(int) * common->max); backend->common = common; net_backend_set_handlers(handler); return (struct net_backend*) backend; } static void net_backend_set_handlers(struct net_backend_handler* handler) { handler->backend_name = net_backend_name_kqueue; handler->backend_poll = net_backend_poll_kqueue; handler->backend_process = net_backend_process_kqueue; handler->backend_shutdown = net_backend_shutdown_kqueue; handler->con_create = net_con_create_kqueue; handler->con_init = net_con_initialize_kqueue; handler->con_add = net_con_backend_add_kqueue; handler->con_mod = net_con_backend_mod_kqueue; handler->con_del = net_con_backend_del_kqueue; } static void add_change(struct net_backend_kqueue* backend, struct net_connection_kqueue* con, int actions) { if (actions && !con->change) { backend->change_list[backend->change_list_len++] = con->sd; con->change = actions; } } static size_t create_change_list(struct net_backend_kqueue* backend) { size_t n = 0; size_t changes = 0; int sd; struct net_connection_kqueue* con; unsigned short flags_r = 0; unsigned short flags_w = 0; for (; n < backend->change_list_len; n++) { sd = backend->change_list[n]; con = backend->conns[sd]; if (con) { flags_r = 0; flags_w = 0; if (con->change & CHANGE_ACTION_ADD) { flags_r |= EV_ADD; flags_w |= EV_ADD; } if (con->change & CHANGE_OP_WANT_READ) flags_r |= EV_ENABLE; else flags_r |= EV_DISABLE; if (con->change & CHANGE_OP_WANT_WRITE) flags_w |= EV_ENABLE; else flags_w |= EV_DISABLE; if (con->ev_r.flags != flags_r) { EV_SET(&con->ev_r, sd, EVFILT_READ, flags_r, 0, 0, con); memcpy(&backend->changes[changes++], &con->ev_r, sizeof(struct kevent)); } if (con->ev_w.flags != flags_w) { EV_SET(&con->ev_w, sd, EVFILT_WRITE, flags_w, 0, 0, con); memcpy(&backend->changes[changes++], &con->ev_w, sizeof(struct kevent)); } con->change = 0; } else { EV_SET(&backend->changes[changes++], sd, EVFILT_READ, EV_DELETE, 0, 0, 0); EV_SET(&backend->changes[changes++], sd, EVFILT_READ, EV_DELETE, 0, 0, 0); } } backend->change_list_len = 0; return changes; } #endif /* USE_KQUEUE */ modelrockettier-uhub-a8ee6e7/src/network/network.c000066400000000000000000000356521324501300100224720ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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() { #ifdef WINSOCK struct WSAData wsa; #endif if (!net_initialized) { LOG_TRACE("Initializing network monitor."); #ifdef WINSOCK if (WSAStartup(MAKEWORD(2, 2), &wsa) != NO_ERROR) { LOG_ERROR("Unable to initialize winsock."); return -1; } #endif /* WINSOCK */ if (!net_backend_init() #ifdef SSL_SUPPORT || !net_ssl_library_init() #endif ) { #ifdef WINSOCK WSACleanup(); #endif return -1; } net_dns_initialize(); net_stats_initialize(); 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 MIN(limits.rlim_max, 65536); } LOG_ERROR("getrlimit() failed"); return 1024; #else #ifdef WIN32 return FD_SETSIZE; #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_dns_destroy(); net_backend_shutdown(); #ifdef SSL_SUPPORT net_ssl_library_shutdown(); #endif /* SSL_SUPPORT */ #ifdef WINSOCK WSACleanup(); #endif net_initialized = 0; return 0; } return -1; } 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(__HAIKU__) case ETIMEDOUT: #endif #if defined(__linux__) case ENETDOWN: case EPROTO: case ENOPROTOOPT: case EHOSTDOWN: case ENONET: case EHOSTUNREACH: case EOPNOTSUPP: errno = EWOULDBLOCK; #endif #ifdef WINSOCK case WSAEWOULDBLOCK: break; #else case EWOULDBLOCK: break; #endif 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 = addr.ss_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 (strchr(address, '.')) { /* Hack to convert IPv6 mapped IPv4 addresses to true IPv4 addresses */ ipaddr->af = AF_INET; net_string_to_address(AF_INET, address, (void*) &ipaddr->internal_ip_data.in); } 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) { #ifdef WINSOCK if (net_error() != WSAEINPROGRESS) #else if (net_error() != EINPROGRESS) #endif { 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; sin6.sin6_scope_id = 0; size = sizeof(sin6); addr = (LPSOCKADDR) &sin6; break; default: return NULL; } if (WSAAddressToStringA(addr, size, NULL, dst, &len) == 0) { return dst; } return NULL; #else if (inet_ntop(af, src, dst, cnt)) { if (af == AF_INET6 && strncmp(dst, "::ffff:", 7) == 0) /* IPv6 mapped IPv4 address. */ { memmove(dst, dst + 7, cnt - 7); } return dst; } return NULL; #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; socklen_t namelen; memset(address, 0, INET6_ADDRSTRLEN); 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 = storage.ss_family; if (af == AF_INET6) { net_address_to_string(af, (void*) &name6->sin6_addr, address, INET6_ADDRSTRLEN); } 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"; } const char* net_get_local_address(int fd) { static char address[INET6_ADDRSTRLEN+1]; struct sockaddr_storage storage; struct sockaddr_in6* name6; struct sockaddr_in* name4; struct sockaddr* name; socklen_t namelen; memset(address, 0, INET6_ADDRSTRLEN); namelen = sizeof(struct sockaddr_storage); memset(&storage, 0, namelen); name6 = (struct sockaddr_in6*) &storage; name4 = (struct sockaddr_in*) &storage; name = (struct sockaddr*) &storage; if (getsockname(fd, (struct sockaddr*) name, &namelen) != -1) { #ifndef WINSOCK int af = storage.ss_family; if (af == AF_INET6) { net_address_to_string(af, (void*) &name6->sin6_addr, address, INET6_ADDRSTRLEN); } else #else int af = AF_INET; #endif { net_address_to_string(af, (void*) &name4->sin_addr, address, INET6_ADDRSTRLEN); } return address; } else { net_error_out(fd, "net_get_local_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 { #ifdef WINSOCK if (net_error() != WSAEWOULDBLOCK) #else if (net_error() != EWOULDBLOCK) #endif { /* 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 { #ifdef WINSOCK if (net_error() != WSAEWOULDBLOCK) #else if (net_error() != EWOULDBLOCK) #endif { /* 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++; } modelrockettier-uhub-a8ee6e7/src/network/network.h000066400000000000000000000160701324501300100224700ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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; struct ip_addr_encap; /** * 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(); /** * @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); extern const char* net_get_local_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); #endif /* HAVE_UHUB_NETWORK_H */ modelrockettier-uhub-a8ee6e7/src/network/notify.c000066400000000000000000000051351324501300100223020ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" struct uhub_notify_handle { net_notify_callback callback; void* ptr; #ifndef WIN32 int pipe_fd[2]; struct net_connection* con; #endif }; /* * This contains a mechanism to wake up the main thread * in a thread safe manner while it would be blocking * in select() or something equivalent typically invoked from * net_backend_process(). * * The main usage is for the DNS resolver to notify the * main thread that there are DNS results to be * processed. */ /** * Create a notification handle. */ #ifndef WIN32 static void notify_callback(struct net_connection* con, int event, void* ptr) { LOG_TRACE("notify_callback()"); struct uhub_notify_handle* handle = (struct uhub_notify_handle*) ptr; char buf; int ret = read(handle->pipe_fd[0], &buf, 1); if (ret == 1) { if (handle->callback) handle->callback(handle, handle->ptr); } } #endif struct uhub_notify_handle* net_notify_create(net_notify_callback cb, void* ptr) { LOG_TRACE("net_notify_create()"); struct uhub_notify_handle* handle = (struct uhub_notify_handle*) hub_malloc(sizeof(struct uhub_notify_handle)); handle->callback = cb; handle->ptr = ptr; #ifndef WIN32 int ret = pipe(handle->pipe_fd); if (ret == -1) { LOG_ERROR("Unable to setup notification pipes."); hub_free(handle); return 0; } handle->con = net_con_create(); net_con_initialize(handle->con, handle->pipe_fd[0], notify_callback, handle, NET_EVENT_READ); #endif return handle; } void net_notify_destroy(struct uhub_notify_handle* handle) { LOG_TRACE("net_notify_destroy()"); #ifndef WIN32 net_con_destroy(handle->con); close(handle->pipe_fd[0]); close(handle->pipe_fd[1]); handle->pipe_fd[0] = -1; handle->pipe_fd[0] = -1; #endif hub_free(handle); } void net_notify_signal(struct uhub_notify_handle* handle, char data) { LOG_TRACE("net_notify_signal()"); #ifndef WIN32 write(handle->pipe_fd[1], &data, 1); #endif }modelrockettier-uhub-a8ee6e7/src/network/notify.h000066400000000000000000000032761324501300100223130ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_NETWORK_NOTIFY_API_H #define HAVE_UHUB_NETWORK_NOTIFY_API_H struct uhub_notify_handle; typedef void (*net_notify_callback)(struct uhub_notify_handle* handle, void* ptr); /* * This contains a mechanism to wake up the main thread * in a thread safe manner while it would be blocking * in select() or something equivalent typically invoked from * net_backend_process(). * * The main usage is for the DNS resolver to notify the * main thread that there are DNS results to be * processed. */ /** * Create a notification handle. */ struct uhub_notify_handle* net_notify_create(net_notify_callback cb, void* ptr); /** * Destroy a notification handle. */ void net_notify_destroy(struct uhub_notify_handle*); /** * Signal the notification handle, this will surely * interrupt the net_backend_process(), and force it to * process messages. */ void net_notify_signal(struct uhub_notify_handle*, char data); #endif /* HAVE_UHUB_NETWORK_NOTIFY_API_H */ modelrockettier-uhub-a8ee6e7/src/network/openssl.c000066400000000000000000000274011324501300100224550ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" #include "network/common.h" #include "network/tls.h" #include "network/backend.h" #ifdef SSL_SUPPORT #ifdef SSL_USE_OPENSSL void net_stats_add_tx(size_t bytes); void net_stats_add_rx(size_t bytes); struct net_ssl_openssl { SSL* ssl; BIO* bio; enum ssl_state state; int events; int ssl_read_events; int ssl_write_events; uint32_t flags; size_t bytes_rx; size_t bytes_tx; }; struct net_context_openssl { SSL_CTX* ssl; }; static struct net_ssl_openssl* get_handle(struct net_connection* con) { uhub_assert(con); return (struct net_ssl_openssl*) con->ssl; } #ifdef DEBUG static const char* get_state_str(enum ssl_state state) { switch (state) { case tls_st_none: return "tls_st_none"; case tls_st_error: return "tls_st_error"; case tls_st_accepting: return "tls_st_accepting"; case tls_st_connecting: return "tls_st_connecting"; case tls_st_connected: return "tls_st_connected"; case tls_st_disconnecting: return "tls_st_disconnecting"; } uhub_assert(!"This should not happen - invalid state!"); return "(UNKNOWN STATE)"; } #endif static void net_ssl_set_state(struct net_ssl_openssl* handle, enum ssl_state new_state) { LOG_DEBUG("net_ssl_set_state(): prev_state=%s, new_state=%s", get_state_str(handle->state), get_state_str(new_state)); handle->state = new_state; } const char* net_ssl_get_provider() { return OPENSSL_VERSION_TEXT; } int net_ssl_library_init() { LOG_TRACE("Initializing OpenSSL..."); SSL_library_init(); SSL_load_error_strings(); return 1; } int net_ssl_library_shutdown() { ERR_clear_error(); #if OPENSSL_VERSION_NUMBER < 0x10100000L ERR_remove_state(0); #endif ENGINE_cleanup(); CONF_modules_unload(1); ERR_free_strings(); EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); // sk_SSL_COMP_free(SSL_COMP_get_compression_methods()); return 1; } static void add_io_stats(struct net_ssl_openssl* handle) { #if OPENSSL_VERSION_NUMBER < 0x10100000L unsigned long num_read = handle->bio->num_read; unsigned long num_write = handle->bio->num_write; #else unsigned long num_read = BIO_number_read(handle->bio); unsigned long num_write = BIO_number_written(handle->bio); #endif if (num_read > handle->bytes_rx) { net_stats_add_rx(num_read - handle->bytes_rx); handle->bytes_rx = num_read; } if (num_write > handle->bytes_tx) { net_stats_add_tx(num_write - handle->bytes_tx); handle->bytes_tx = num_write; } } static const SSL_METHOD* get_ssl_method(const char* tls_version) { if (!tls_version || !*tls_version) { LOG_ERROR("tls_version is not set."); return 0; } #if OPENSSL_VERSION_NUMBER < 0x10100000L if (!strcmp(tls_version, "1.0")) return TLSv1_method(); if (!strcmp(tls_version, "1.1")) return TLSv1_1_method(); if (!strcmp(tls_version, "1.2")) return TLSv1_2_method(); LOG_ERROR("Unable to recognize tls_version."); return 0; #else LOG_WARN("tls_version is obsolete, and should not be used."); return TLS_method(); #endif } /** * Create a new SSL context. */ struct ssl_context_handle* net_ssl_context_create(const char* tls_version, const char* tls_ciphersuite) { struct net_context_openssl* ctx = (struct net_context_openssl*) hub_malloc_zero(sizeof(struct net_context_openssl)); const SSL_METHOD* ssl_method = get_ssl_method(tls_version); if (!ssl_method) { hub_free(ctx); return 0; } ctx->ssl = SSL_CTX_new(ssl_method); /* Disable SSLv2 */ SSL_CTX_set_options(ctx->ssl, SSL_OP_NO_SSLv2); // #ifdef SSL_OP_NO_SSLv3 /* Disable SSLv3 */ SSL_CTX_set_options(ctx->ssl, SSL_OP_NO_SSLv3); // #endif // FIXME: Why did we need this again? SSL_CTX_set_quiet_shutdown(ctx->ssl, 1); #ifdef SSL_OP_NO_COMPRESSION /* Disable compression */ LOG_TRACE("Disabling SSL compression."); /* "CRIME" attack */ SSL_CTX_set_options(ctx->ssl, SSL_OP_NO_COMPRESSION); #endif /* Set preferred cipher suite */ if (SSL_CTX_set_cipher_list(ctx->ssl, tls_ciphersuite) != 1) { LOG_ERROR("Unable to set cipher suite."); SSL_CTX_free(ctx->ssl); hub_free(ctx); return 0; } return (struct ssl_context_handle*) ctx; } void net_ssl_context_destroy(struct ssl_context_handle* ctx_) { struct net_context_openssl* ctx = (struct net_context_openssl*) ctx_; SSL_CTX_free(ctx->ssl); hub_free(ctx); } int ssl_load_certificate(struct ssl_context_handle* ctx_, const char* pem_file) { struct net_context_openssl* ctx = (struct net_context_openssl*) ctx_; if (SSL_CTX_use_certificate_chain_file(ctx->ssl, pem_file) < 0) { LOG_ERROR("SSL_CTX_use_certificate_chain_file: %s", ERR_error_string(ERR_get_error(), NULL)); return 0; } return 1; } int ssl_load_private_key(struct ssl_context_handle* ctx_, const char* pem_file) { struct net_context_openssl* ctx = (struct net_context_openssl*) ctx_; if (SSL_CTX_use_PrivateKey_file(ctx->ssl, pem_file, SSL_FILETYPE_PEM) < 0) { LOG_ERROR("SSL_CTX_use_PrivateKey_file: %s", ERR_error_string(ERR_get_error(), NULL)); return 0; } return 1; } int ssl_check_private_key(struct ssl_context_handle* ctx_) { struct net_context_openssl* ctx = (struct net_context_openssl*) ctx_; if (SSL_CTX_check_private_key(ctx->ssl) != 1) { LOG_FATAL("SSL_CTX_check_private_key: Private key does not match the certificate public key: %s", ERR_error_string(ERR_get_error(), NULL)); return 0; } return 1; } static int handle_openssl_error(struct net_connection* con, int ret, int read) { struct net_ssl_openssl* handle = get_handle(con); int err = SSL_get_error(handle->ssl, ret); switch (err) { case SSL_ERROR_ZERO_RETURN: // Not really an error, but SSL was shut down. return -1; case SSL_ERROR_WANT_READ: if (read) handle->ssl_read_events = NET_EVENT_READ; else handle->ssl_write_events = NET_EVENT_READ; return 0; case SSL_ERROR_WANT_WRITE: if (read) handle->ssl_read_events = NET_EVENT_WRITE; else handle->ssl_write_events = NET_EVENT_WRITE; return 0; case SSL_ERROR_SSL: net_ssl_set_state(handle, tls_st_error); return -2; case SSL_ERROR_SYSCALL: net_ssl_set_state(handle, tls_st_error); return -2; } return -2; } ssize_t net_con_ssl_accept(struct net_connection* con) { struct net_ssl_openssl* handle = get_handle(con); ssize_t ret; net_ssl_set_state(handle, tls_st_accepting); ret = SSL_accept(handle->ssl); LOG_PROTO("SSL_accept() ret=%d", ret); if (ret > 0) { net_con_update(con, NET_EVENT_READ); net_ssl_set_state(handle, tls_st_connected); return ret; } return handle_openssl_error(con, ret, tls_st_accepting); } ssize_t net_con_ssl_connect(struct net_connection* con) { struct net_ssl_openssl* handle = get_handle(con); ssize_t ret; net_ssl_set_state(handle, tls_st_connecting); ret = SSL_connect(handle->ssl); LOG_PROTO("SSL_connect() ret=%d", ret); if (ret > 0) { net_con_update(con, NET_EVENT_READ); net_ssl_set_state(handle, tls_st_connected); return ret; } ret = handle_openssl_error(con, ret, tls_st_connecting); LOG_ERROR("net_con_ssl_connect: ret=%d", ret); return ret; } ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode ssl_mode, struct ssl_context_handle* ssl_ctx) { uhub_assert(con); uhub_assert(ssl_ctx); struct net_context_openssl* ctx = (struct net_context_openssl*) ssl_ctx; struct net_ssl_openssl* handle = (struct net_ssl_openssl*) hub_malloc_zero(sizeof(struct net_ssl_openssl)); if (ssl_mode == net_con_ssl_mode_server) { handle->ssl = SSL_new(ctx->ssl); if (!handle->ssl) { LOG_ERROR("Unable to create new SSL stream\n"); return -1; } SSL_set_fd(handle->ssl, con->sd); handle->bio = SSL_get_rbio(handle->ssl); con->ssl = (struct ssl_handle*) handle; return net_con_ssl_accept(con); } else { handle->ssl = SSL_new(ctx->ssl); SSL_set_fd(handle->ssl, con->sd); handle->bio = SSL_get_rbio(handle->ssl); con->ssl = (struct ssl_handle*) handle; return net_con_ssl_connect(con); } } ssize_t net_ssl_send(struct net_connection* con, const void* buf, size_t len) { struct net_ssl_openssl* handle = get_handle(con); LOG_TRACE("net_ssl_send(), state=%d", (int) handle->state); if (handle->state == tls_st_error) return -2; uhub_assert(handle->state == tls_st_connected); ERR_clear_error(); ssize_t ret = SSL_write(handle->ssl, buf, len); add_io_stats(handle); LOG_PROTO("SSL_write(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret); if (ret > 0) handle->ssl_write_events = 0; else ret = handle_openssl_error(con, ret, 0); net_ssl_update(con, handle->events); // Update backend only return ret; } ssize_t net_ssl_recv(struct net_connection* con, void* buf, size_t len) { struct net_ssl_openssl* handle = get_handle(con); ssize_t ret; if (handle->state == tls_st_error) return -2; if (handle->state == tls_st_accepting || handle->state == tls_st_connecting) return -1; uhub_assert(handle->state == tls_st_connected); ERR_clear_error(); ret = SSL_read(handle->ssl, buf, len); add_io_stats(handle); LOG_PROTO("SSL_read(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret); if (ret > 0) handle->ssl_read_events = 0; else ret = handle_openssl_error(con, ret, 1); net_ssl_update(con, handle->events); // Update backend only return ret; } void net_ssl_update(struct net_connection* con, int events) { struct net_ssl_openssl* handle = get_handle(con); handle->events = events; net_backend_update(con, handle->events | handle->ssl_read_events | handle->ssl_write_events); } void net_ssl_shutdown(struct net_connection* con) { struct net_ssl_openssl* handle = get_handle(con); if (handle) { SSL_shutdown(handle->ssl); SSL_clear(handle->ssl); } } void net_ssl_destroy(struct net_connection* con) { struct net_ssl_openssl* handle = get_handle(con); LOG_TRACE("net_ssl_destroy: %p", con); SSL_free(handle->ssl); hub_free(handle); } void net_ssl_callback(struct net_connection* con, int events) { struct net_ssl_openssl* handle = get_handle(con); int ret; switch (handle->state) { case tls_st_none: con->callback(con, events, con->ptr); break; case tls_st_error: con->callback(con, NET_EVENT_ERROR, con->ptr); break; case tls_st_accepting: if (net_con_ssl_accept(con) != 0) con->callback(con, NET_EVENT_READ, con->ptr); break; case tls_st_connecting: ret = net_con_ssl_connect(con); if (ret == 0) return; if (ret > 0) { LOG_DEBUG("%p SSL connected!", con); con->callback(con, NET_EVENT_READ, con->ptr); } else { LOG_DEBUG("%p SSL handshake failed!", con); con->callback(con, NET_EVENT_ERROR, con->ptr); } break; case tls_st_connected: if (handle->ssl_read_events & events) events |= NET_EVENT_READ; if (handle->ssl_write_events & events) events |= NET_EVENT_WRITE; con->callback(con, events, con->ptr); break; case tls_st_disconnecting: return; } } const char* net_ssl_get_tls_version(struct net_connection* con) { struct net_ssl_openssl* handle = get_handle(con); return SSL_get_version(handle->ssl); } const char* net_ssl_get_tls_cipher(struct net_connection* con) { struct net_ssl_openssl* handle = get_handle(con); const SSL_CIPHER *cipher = SSL_get_current_cipher(handle->ssl); return SSL_CIPHER_get_name(cipher); } #endif /* SSL_USE_OPENSSL */ #endif /* SSL_SUPPORT */ modelrockettier-uhub-a8ee6e7/src/network/select.c000066400000000000000000000120011324501300100222370ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" #ifdef USE_SELECT #include "network/connection.h" #include "network/common.h" #include "network/backend.h" struct net_connection_select { NET_CON_STRUCT_COMMON }; struct net_backend_select { struct net_connection_select** conns; fd_set rfds; fd_set wfds; fd_set xfds; int maxfd; struct net_backend_common* common; }; static void net_backend_set_handlers(struct net_backend_handler* handler); const char* net_backend_name_select() { return "select"; } int net_backend_poll_select(struct net_backend* data, int ms) { int res; size_t n, found; struct timeval tval; struct net_backend_select* backend = (struct net_backend_select*) data; tval.tv_sec = ms / 1000; tval.tv_usec = (ms % 1000) * 1000; FD_ZERO(&backend->rfds); FD_ZERO(&backend->wfds); FD_ZERO(&backend->xfds); backend->maxfd = -1; for (n = 0, found = 0; found < backend->common->num && n < backend->common->max; n++) { struct net_connection_select* con = backend->conns[n]; if (con) { if (con->flags & NET_EVENT_READ) FD_SET(con->sd, &backend->rfds); if (con->flags & NET_EVENT_WRITE) FD_SET(con->sd, &backend->wfds); found++; backend->maxfd = con->sd; } } backend->maxfd++; res = select(backend->maxfd, &backend->rfds, &backend->wfds, &backend->xfds, &tval); if (res == -1) { if (net_error() == EINTR) return 0; printf("Error: %d\n", net_error()); } return res; } void net_backend_process_select(struct net_backend* data, int res) { int n, found; struct net_backend_select* backend = (struct net_backend_select*) data; for (n = 0, found = 0; found < res && n < backend->maxfd; n++) { struct net_connection_select* con = backend->conns[n]; if (con) { int ev = 0; if (FD_ISSET(con->sd, &backend->rfds)) ev |= NET_EVENT_READ; if (FD_ISSET(con->sd, &backend->wfds)) ev |= NET_EVENT_WRITE; if (ev) { net_con_callback((struct net_connection*) con, ev); found++; } } } } struct net_connection* net_con_create_select(struct net_backend* data) { struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection_select)); con->sd = -1; return con; } void net_con_initialize_select(struct net_backend* data, struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr) { struct net_connection_select* con = (struct net_connection_select*) con_; con->sd = sd; con->flags = 0; con->callback = callback; con->ptr = (void*) ptr; } void net_con_backend_add_select(struct net_backend* data, struct net_connection* con, int events) { struct net_backend_select* backend = (struct net_backend_select*) data; backend->conns[con->sd] = (struct net_connection_select*) con; con->flags |= (events & (NET_EVENT_READ | NET_EVENT_WRITE)); } void net_con_backend_mod_select(struct net_backend* data, struct net_connection* con, int events) { con->flags |= (events & (NET_EVENT_READ | NET_EVENT_WRITE)); } void net_con_backend_del_select(struct net_backend* data, struct net_connection* con) { struct net_backend_select* backend = (struct net_backend_select*) data; backend->conns[con->sd] = 0; } void net_backend_shutdown_select(struct net_backend* data) { struct net_backend_select* backend = (struct net_backend_select*) data; hub_free(backend->conns); hub_free(backend); } struct net_backend* net_backend_init_select(struct net_backend_handler* handler, struct net_backend_common* common) { struct net_backend_select* backend; if (getenv("EVENT_NOSELECT")) return 0; backend = hub_malloc_zero(sizeof(struct net_backend_select)); FD_ZERO(&backend->rfds); FD_ZERO(&backend->wfds); backend->conns = hub_malloc_zero(sizeof(struct net_connection_select*) * common->max); backend->common = common; net_backend_set_handlers(handler); return (struct net_backend*) backend; } static void net_backend_set_handlers(struct net_backend_handler* handler) { handler->backend_name = net_backend_name_select; handler->backend_poll = net_backend_poll_select; handler->backend_process = net_backend_process_select; handler->backend_shutdown = net_backend_shutdown_select; handler->con_create = net_con_create_select; handler->con_init = net_con_initialize_select; handler->con_add = net_con_backend_add_select; handler->con_mod = net_con_backend_mod_select; handler->con_del = net_con_backend_del_select; } #endif /* USE_SELECT */ modelrockettier-uhub-a8ee6e7/src/network/timeout.c000066400000000000000000000123741324501300100224630ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 wtimeout_evtith this program. If not, see . * */ #include "uhub.h" void timeout_evt_initialize(struct timeout_evt* t, timeout_evt_cb cb, void* ptr) { t->callback = cb; t->ptr = ptr; t->prev = 0; t->next = 0; } void timeout_evt_reset(struct timeout_evt* t) { t->prev = 0; t->next = 0; } int timeout_evt_is_scheduled(struct timeout_evt* t) { return t->prev != NULL; } void timeout_queue_initialize(struct timeout_queue* t, time_t now, size_t max) { t->last = now; t->max = max; memset(&t->lock, 0, sizeof(t->lock)); t->events = hub_malloc_zero(max * sizeof(struct timeout_evt*)); } void timeout_queue_shutdown(struct timeout_queue* t) { hub_free(t->events); t->events = 0; t->max = 0; } static int timeout_queue_locked(struct timeout_queue* t) { return t->lock.ptr != NULL; } static void timeout_queue_lock(struct timeout_queue* t) { t->lock.ptr = t; } // unlock and flush the locked events to the main timeout queue. static void timeout_queue_unlock(struct timeout_queue* t) { struct timeout_evt* evt, *tmp, *first; size_t pos; t->lock.ptr = NULL; evt = t->lock.next; while (evt) { tmp = evt->next; pos = evt->timestamp % t->max; first = t->events[pos]; if (first) { first->prev->next = evt; evt->prev = first->prev; first->prev = evt; } else { t->events[pos] = evt; evt->prev = evt; } evt->next = 0; evt = tmp; } t->lock.next = 0; t->lock.prev = 0; } size_t timeout_queue_process(struct timeout_queue* t, time_t now) { size_t pos = (size_t) t->last; size_t events = 0; struct timeout_evt* evt = 0; t->last = now; timeout_queue_lock(t); for (; pos <= now; pos++) { while ((evt = t->events[pos % t->max])) { timeout_queue_remove(t, evt); evt->callback(evt); events++; } } timeout_queue_unlock(t); return events; } size_t timeout_queue_get_next_timeout(struct timeout_queue* t, time_t now) { size_t seconds = 0; while (t->events[(now + seconds) % t->max] == NULL && seconds < t->max) { seconds++; } if (seconds == 0) return 1; return seconds; } static void timeout_queue_insert_locked(struct timeout_queue* t, struct timeout_evt* evt) { /* All events point back to the sentinel. * this means the event is considered schedule (see timeout_evt_is_scheduled), * and it is easy to tell if the event is in the wait queue or not. */ evt->prev = &t->lock; evt->next = NULL; // The sentinel next points to the first event in the locked queue // The sentinel prev points to the last evetnt in the locked queue. // NOTE: if prev is != NULL then next also must be != NULL. if (t->lock.prev) { t->lock.prev->next = evt; t->lock.prev = evt; } else { t->lock.next = evt; t->lock.prev = evt; } return; } static void timeout_queue_remove_locked(struct timeout_queue* t, struct timeout_evt* evt) { uhub_assert(evt->prev == &t->lock); if (t->lock.next == evt) { t->lock.next = evt->next; if (t->lock.prev == evt) t->lock.prev = evt->next; } else { struct timeout_evt *prev, *it; prev = 0; it = t->lock.next; while (it) { prev = it; it = it->next; if (it == evt) { prev->next = it->next; if (!prev->next) t->lock.prev = prev; } } } timeout_evt_reset(evt); } void timeout_queue_insert(struct timeout_queue* t, struct timeout_evt* evt, size_t seconds) { struct timeout_evt* first; size_t pos = ((t->last + seconds) % t->max); evt->timestamp = t->last + seconds; evt->next = 0; if (timeout_queue_locked(t)) { timeout_queue_insert_locked(t, evt); return; } first = t->events[pos]; if (first) { uhub_assert(first->timestamp == evt->timestamp); first->prev->next = evt; evt->prev = first->prev; first->prev = evt; } else { t->events[pos] = evt; evt->prev = evt; } evt->next = 0; } void timeout_queue_remove(struct timeout_queue* t, struct timeout_evt* evt) { size_t pos = (evt->timestamp % t->max); struct timeout_evt* first = t->events[pos]; // Removing a locked event if (evt->prev == &t->lock) { timeout_queue_remove_locked(t, evt); return; } if (!first || !evt->prev) return; if (first == evt) { if (first->prev != first) { t->events[pos] = first->next; t->events[pos]->prev = evt->prev; } else { t->events[pos] = 0; } } else if (evt == first->prev) { first->prev = evt->prev; evt->prev->next = 0; } else { evt->prev->next = evt->next; evt->next->prev = evt->prev; } timeout_evt_reset(evt); } void timeout_queue_reschedule(struct timeout_queue* t, struct timeout_evt* evt, size_t seconds) { if (timeout_evt_is_scheduled(evt)) timeout_queue_remove(t, evt); timeout_queue_insert(t, evt, seconds); } modelrockettier-uhub-a8ee6e7/src/network/timeout.h000066400000000000000000000035501324501300100224640ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_TIMEOUT_HANDLER_H #define HAVE_UHUB_TIMEOUT_HANDLER_H struct timeout_evt; struct timeout_queue; typedef void (*timeout_evt_cb)(struct timeout_evt*); struct timeout_evt { time_t timestamp; timeout_evt_cb callback; void* ptr; struct timeout_evt* prev; struct timeout_evt* next; }; 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*); struct timeout_queue { time_t last; size_t max; struct timeout_evt lock; struct timeout_evt** events; }; void timeout_queue_initialize(struct timeout_queue*, time_t now, size_t max); void timeout_queue_shutdown(struct timeout_queue*); size_t timeout_queue_process(struct timeout_queue*, time_t now); void timeout_queue_insert(struct timeout_queue*, struct timeout_evt*, size_t seconds); void timeout_queue_remove(struct timeout_queue*, struct timeout_evt*); void timeout_queue_reschedule(struct timeout_queue*, struct timeout_evt*, size_t seconds); size_t timeout_queue_get_next_timeout(struct timeout_queue*, time_t now); #endif /* HAVE_UHUB_TIMEOUT_HANDLER_H */ modelrockettier-uhub-a8ee6e7/src/network/timer.c000066400000000000000000000014331324501300100221070ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" #include "network/connection.h" modelrockettier-uhub-a8ee6e7/src/network/tls.h000066400000000000000000000061771324501300100216100ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_NETWORK_TLS_H #define HAVE_UHUB_NETWORK_TLS_H #include "uhub.h" #ifdef SSL_SUPPORT enum ssl_state { tls_st_none, tls_st_error, tls_st_accepting, tls_st_connecting, tls_st_connected, tls_st_disconnecting, }; enum net_con_ssl_mode { net_con_ssl_mode_server, net_con_ssl_mode_client, }; struct ssl_context_handle; /** * Returns a string describing the TLS/SSL provider information */ extern const char* net_ssl_get_provider(); /** * return 0 if error, 1 on success. */ extern int net_ssl_library_init(); extern int net_ssl_library_shutdown(); /** * Create a new SSL context. * Specify a TLS version as a string: "1.2" for TLS 1.2. */ extern struct ssl_context_handle* net_ssl_context_create(const char* tls_version, const char* tls_ciphersuite); extern void net_ssl_context_destroy(struct ssl_context_handle* ctx); /** * Return 0 on error, 1 otherwise. */ extern int ssl_load_certificate(struct ssl_context_handle* ctx, const char* pem_file); /** * Return 0 on error, 1 otherwise. */ extern int ssl_load_private_key(struct ssl_context_handle* ctx, const char* pem_file); /** * Return 0 if private key does not match certificate, 1 if everything is OK. */ extern int ssl_check_private_key(struct ssl_context_handle* ctx); /** * 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*); extern ssize_t net_ssl_send(struct net_connection* con, const void* buf, size_t len); extern ssize_t net_ssl_recv(struct net_connection* con, void* buf, size_t len); /** * Update the event mask. Additional events may be requested depending on the * needs of the TLS layer. * * @param con Connection handle. * @param events Event mask (NET_EVENT_*) */ extern void net_ssl_update(struct net_connection* con, int events); extern void net_ssl_shutdown(struct net_connection* con); extern void net_ssl_destroy(struct net_connection* con); extern void net_ssl_callback(struct net_connection* con, int events); extern ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode, struct ssl_context_handle* ssl_ctx); extern int net_con_is_ssl(struct net_connection* con); extern const char* net_ssl_get_tls_version(struct net_connection* con); extern const char* net_ssl_get_tls_cipher(struct net_connection* con); #endif /* SSL_SUPPORT */ #endif /* HAVE_UHUB_NETWORK_TLS_H */ modelrockettier-uhub-a8ee6e7/src/plugin_api/000077500000000000000000000000001324501300100212605ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/src/plugin_api/command_api.h000066400000000000000000000047501324501300100237060ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_PLUGIN_API_H #define HAVE_UHUB_PLUGIN_API_H /** * This file describes the interface a plugin implementation may use from * uhub. */ #include "system.h" #include "plugin_api/types.h" struct plugin_command { const char* message; const char* prefix; struct linked_list* args; }; struct plugin_command_arg_data { enum plugin_command_arg_type type; union { int integer; char* string; struct plugin_user* user; struct ip_addr_encap* address; struct ip_range* range; enum auth_credentials credentials; } data; }; typedef int (*plugin_command_handler)(struct plugin_handle*, struct plugin_user* to, struct plugin_command*); struct plugin_command_handle { void* internal_handle; /**<<< "Internal used by the hub only" */ struct plugin_handle* handle; /**<<< "The plugin handle this is associated with" */ const char* prefix; /**<<< "Command prefix, for instance 'help' would be the prefix for the !help command." */ size_t length; /**<<< "Length of the prefix" */ const char* args; /**<<< "Argument codes" */ enum auth_credentials cred; /**<<< "Minimum access level for the command" */ plugin_command_handler handler; /**<<< "Function pointer for the command" */ const char* description; /**<<< "Description for the command" */ const char* origin; /**<<< "Name of plugin where the command originated." */ }; #define PLUGIN_COMMAND_INITIALIZE(PTR, HANDLE, PREFIX, ARGS, CRED, CALLBACK, DESC) \ do { \ PTR->internal_handle = 0; \ PTR->handle = HANDLE; \ PTR->prefix = PREFIX; \ PTR->length = strlen(PREFIX); \ PTR->args = ARGS; \ PTR->cred = CRED; \ PTR->handler = CALLBACK; \ PTR->description = DESC; \ } while (0) #endif /* HAVE_UHUB_PLUGIN_API_H */ modelrockettier-uhub-a8ee6e7/src/plugin_api/handle.h000066400000000000000000000235661324501300100227000ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_PLUGIN_HANDLE_H #define HAVE_UHUB_PLUGIN_HANDLE_H /** * This file describes the interface a uhub uses to interact with plugins. */ #include "system.h" #include "util/credentials.h" #include "network/ipcalc.h" #include "plugin_api/types.h" typedef void (*on_connection_accepted_t)(struct plugin_handle*, struct ip_addr_encap*); typedef void (*on_connection_refused_t)(struct plugin_handle*, struct ip_addr_encap*); typedef void (*on_user_login_t)(struct plugin_handle*, struct plugin_user*); typedef void (*on_user_login_error_t)(struct plugin_handle*, struct plugin_user*, const char* reason); typedef void (*on_user_logout_t)(struct plugin_handle*, struct plugin_user*, const char* reason); typedef void (*on_user_nick_change_t)(struct plugin_handle*, struct plugin_user*, const char* new_nick); typedef void (*on_user_update_error_t)(struct plugin_handle*, struct plugin_user*, const char* reason); typedef void (*on_user_chat_msg_t)(struct plugin_handle*, struct plugin_user*, const char* message, int flags); typedef void (*on_hub_started_t)(struct plugin_handle*, struct plugin_hub_info*); typedef void (*on_hub_reloaded_t)(struct plugin_handle*, struct plugin_hub_info*); typedef void (*on_hub_shutdown_t)(struct plugin_handle*, struct plugin_hub_info*); typedef void (*on_hub_error_t)(struct plugin_handle*, struct plugin_hub_info*, const char* message); typedef plugin_st (*on_check_ip_early_t)(struct plugin_handle*, struct ip_addr_encap*); typedef plugin_st (*on_check_ip_late_t)(struct plugin_handle*, struct plugin_user*, struct ip_addr_encap*); typedef plugin_st (*on_validate_nick_t)(struct plugin_handle*, const char* nick); typedef plugin_st (*on_validate_cid_t)(struct plugin_handle*, const char* cid); typedef plugin_st (*on_change_nick_t)(struct plugin_handle*, struct plugin_user*, const char* new_nick); typedef plugin_st (*on_chat_msg_t)(struct plugin_handle*, struct plugin_user* from, const char* message); typedef plugin_st (*on_private_msg_t)(struct plugin_handle*, struct plugin_user* from, struct plugin_user* to, const char* message); typedef plugin_st (*on_search_t)(struct plugin_handle*, struct plugin_user* from, const char* data); typedef plugin_st (*on_search_result_t)(struct plugin_handle*, struct plugin_user* from, struct plugin_user* to, const char* data); typedef plugin_st (*on_p2p_connect_t)(struct plugin_handle*, struct plugin_user* from, struct plugin_user* to); typedef plugin_st (*on_p2p_revconnect_t)(struct plugin_handle*, struct plugin_user* from, struct plugin_user* to); typedef plugin_st (*auth_get_user_t)(struct plugin_handle*, const char* nickname, struct auth_info* info); typedef plugin_st (*auth_register_user_t)(struct plugin_handle*, struct auth_info* user); typedef plugin_st (*auth_update_user_t)(struct plugin_handle*, struct auth_info* user); typedef plugin_st (*auth_delete_user_t)(struct plugin_handle*, struct auth_info* user); /** * These are callbacks used for the hub to invoke functions in plugins. * The marked ones are not being called yet. */ struct plugin_funcs { // Log events for connections on_connection_accepted_t on_connection_accepted; /* Someone successfully connected to the hub */ on_connection_refused_t on_connection_refused; /* Someone was refused connection to the hub */ // Log events for users on_user_login_t on_user_login; /* A user has successfully logged in to the hub */ on_user_login_error_t on_user_login_error; /* A user has failed to log in to the hub */ on_user_logout_t on_user_logout; /* A user has logged out of the hub (was previously logged in) */ /* ! */ on_user_nick_change_t on_user_nick_change; /* A user has changed nickname */ on_user_update_error_t on_user_update_error;/* A user has failed to update - nickname, etc. */ on_user_chat_msg_t on_user_chat_message;/* A user has sent a public chat message */ // Log hub events /* ! */ on_hub_started_t on_hub_started; /* Triggered just after plugins are loaded and the hub is started. */ /* ! */ on_hub_reloaded_t on_hub_reloaded; /* Triggered immediately after hub configuration is reloaded. */ /* ! */ on_hub_shutdown_t on_hub_shutdown; /* Triggered just before the hub is being shut down and before plugins are unloaded. */ /* ! */ on_hub_error_t on_hub_error; /* Triggered for log-worthy error messages */ // Activity events (can be intercepted and refused/accepted by a plugin) on_check_ip_early_t on_check_ip_early; /* A user has just connected (can be intercepted) */ /* ! */ on_check_ip_late_t on_check_ip_late; /* A user has logged in (can be intercepted) */ /* ! */ on_change_nick_t on_change_nick; /* A user wants to change his nick (can be intercepted) */ on_chat_msg_t on_chat_msg; /* A public chat message is about to be sent (can be intercepted) */ on_private_msg_t on_private_msg; /* A public chat message is about to be sent (can be intercepted) */ on_search_t on_search; /* A search is about to be sent (can be intercepted) */ on_search_result_t on_search_result; /* A search result is about to be sent (can be intercepted) */ on_p2p_connect_t on_p2p_connect; /* A user is about to connect to another user (can be intercepted) */ on_p2p_revconnect_t on_p2p_revconnect; /* A user is about to connect to another user (can be intercepted) */ // Authentication actions. auth_get_user_t auth_get_user; /* Get authentication info from plugin */ auth_register_user_t auth_register_user; /* Register user */ auth_update_user_t auth_update_user; /* Update a registered user */ auth_delete_user_t auth_delete_user; /* Delete a registered user */ }; struct plugin_command_handle; struct plugin_command; struct plugin_command_arg_data; typedef int (*hfunc_send_message)(struct plugin_handle*, struct plugin_user* user, const char* message); typedef int (*hfunc_send_broadcast_message)(struct plugin_handle*, const char* message); typedef int (*hfunc_send_status)(struct plugin_handle*, struct plugin_user* to, int code, const char* message); typedef int (*hfunc_user_disconnect)(struct plugin_handle*, struct plugin_user* user); typedef int (*hfunc_command_add)(struct plugin_handle*, struct plugin_command_handle*); typedef int (*hfunc_command_del)(struct plugin_handle*, struct plugin_command_handle*); typedef size_t (*hfunc_command_arg_reset)(struct plugin_handle*, struct plugin_command*); typedef struct plugin_command_arg_data* (*hfunc_command_arg_next)(struct plugin_handle*, struct plugin_command*, enum plugin_command_arg_type); typedef size_t (*hfunc_get_usercount)(struct plugin_handle*); typedef char* (*hfunc_get_hub_name)(struct plugin_handle*); typedef void (*hfunc_set_hub_name)(struct plugin_handle*, const char*); typedef char* (*hfunc_get_hub_description)(struct plugin_handle*); typedef void (*hfunc_set_hub_description)(struct plugin_handle*, const char*); /** * These are functions created and initialized by the hub and which can be used * by plugins to access functionality internal to the hub. */ struct plugin_hub_funcs { hfunc_send_message send_message; hfunc_send_broadcast_message send_broadcast_message; hfunc_send_status send_status_message; hfunc_user_disconnect user_disconnect; hfunc_command_add command_add; hfunc_command_del command_del; hfunc_command_arg_reset command_arg_reset; hfunc_command_arg_next command_arg_next; hfunc_get_usercount get_usercount; hfunc_get_hub_name get_name; hfunc_set_hub_name set_name; hfunc_get_hub_description get_description; hfunc_set_hub_description set_description; }; struct plugin_handle { struct uhub_plugin* handle; /* Must NOT be modified by the plugin */ const char* name; /* plugin name */ const char* version; /* plugin version */ const char* description; /* plugin description */ void* ptr; /* Plugin specific data */ const char* error_msg; /* Error message for registration error. */ size_t plugin_api_version; /* Plugin API version */ size_t plugin_funcs_size; /* Size of the plugin funcs */ struct plugin_funcs funcs; /* Table of functions that can be implemented by a plugin */ struct plugin_hub_funcs hub; /* Table of core hub functions that can be used by a plugin */ }; #define PLUGIN_INITIALIZE(PTR, NAME, VERSION, DESCRIPTION) \ do { \ PTR->name = NAME; \ PTR->version = VERSION; \ PTR->description = DESCRIPTION; \ PTR->ptr = NULL; \ PTR->error_msg = NULL; \ PTR->plugin_api_version = PLUGIN_API_VERSION; \ PTR->plugin_funcs_size = sizeof(struct plugin_funcs); \ memset(&PTR->funcs, 0, sizeof(struct plugin_funcs)); \ } while (0) /** * Implemented by the plugin. * * @param handle[out] Sets all information by the plugin * @param config A configuration string * @return 0 on success, -1 on error. */ PLUGIN_API int plugin_register(struct plugin_handle* handle, const char* config); /** * @return 0 on success, -1 on error. */ PLUGIN_API int plugin_unregister(struct plugin_handle*); typedef int (*plugin_register_f)(struct plugin_handle* handle, const char* config); typedef int (*plugin_unregister_f)(struct plugin_handle*); #endif /* HAVE_UHUB_PLUGIN_HANDLE_H */ modelrockettier-uhub-a8ee6e7/src/plugin_api/message_api.h000066400000000000000000000022771324501300100237160ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_PLUGIN_MESSAGE_API_H #define HAVE_UHUB_PLUGIN_MESSAGE_API_H /** * Send an informal message to a user. * The user will see the message as if the hub sent it. */ extern int plugin_send_message(struct plugin_handle*, struct plugin_user* to, const char* message); /** * Send a status message to a user. */ extern int plugin_send_status(struct plugin_handle* struct plugin_user* to, int code, const char* message); #endif /* HAVE_UHUB_PLUGIN_API_H */ modelrockettier-uhub-a8ee6e7/src/plugin_api/types.h000066400000000000000000000050441324501300100226000ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_PLUGIN_TYPES_H #define HAVE_UHUB_PLUGIN_TYPES_H #define PLUGIN_API_VERSION 1 #ifndef MAX_NICK_LEN #define MAX_NICK_LEN 64 #endif #ifndef MAX_PASS_LEN #define MAX_PASS_LEN 64 #endif #ifndef MAX_CID_LEN #define MAX_CID_LEN 39 #endif #ifndef MAX_UA_LEN #define MAX_UA_LEN 32 #endif #ifndef SID_T_DEFINED typedef uint32_t sid_t; #define SID_T_DEFINED #endif struct plugin_handle; struct plugin_user { sid_t sid; char nick[MAX_NICK_LEN+1]; char cid[MAX_CID_LEN+1]; char user_agent[MAX_UA_LEN+1]; struct ip_addr_encap addr; enum auth_credentials credentials; }; struct plugin_hub_info { const char* description; }; enum plugin_status { st_default = 0, /* Use default */ st_allow = 1, /* Allow action */ st_deny = -1, /* Deny action */ }; typedef enum plugin_status plugin_st; struct auth_info { char nickname[MAX_NICK_LEN+1]; char password[MAX_PASS_LEN+1]; enum auth_credentials credentials; }; enum ban_flags { ban_nickname = 0x01, /* Nickname is banned */ ban_cid = 0x02, /* CID is banned */ ban_ip = 0x04, /* IP address (range) is banned */ }; struct ban_info { unsigned int flags; /* See enum ban_flags. */ char nickname[MAX_NICK_LEN+1]; /* Nickname - only defined if (ban_nickname & flags). */ char cid[MAX_CID_LEN+1]; /* CID - only defined if (ban_cid & flags). */ struct ip_addr_encap ip_addr_lo; /* Low IP address of an IP range */ struct ip_addr_encap ip_addr_hi; /* High IP address of an IP range */ time_t expiry; /* Time when the ban record expires */ }; enum plugin_command_arg_type { plugin_cmd_arg_type_integer, plugin_cmd_arg_type_string, plugin_cmd_arg_type_user, plugin_cmd_arg_type_address, plugin_cmd_arg_type_range, plugin_cmd_arg_type_credentials, }; #endif /* HAVE_UHUB_PLUGIN_TYPES_H */ modelrockettier-uhub-a8ee6e7/src/plugins/000077500000000000000000000000001324501300100206125ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/src/plugins/mod_auth_simple.c000066400000000000000000000132131324501300100241270ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "plugin_api/handle.h" #include "util/memory.h" #include "util/list.h" #include "util/misc.h" #include "util/log.h" #include "util/config_token.h" static void set_error_message(struct plugin_handle* plugin, const char* msg) { plugin->error_msg = msg; } struct acl_data { struct linked_list* users; char* file; int readonly; int exclusive; }; static void insert_user(struct linked_list* users, const char* nick, const char* pass, enum auth_credentials cred) { struct auth_info* data = (struct auth_info*) hub_malloc_zero(sizeof(struct auth_info)); strncpy(data->nickname, nick, MAX_NICK_LEN); strncpy(data->password, pass, MAX_PASS_LEN); data->credentials = cred; list_append(users, data); } static void free_acl(struct acl_data* data) { if (!data) return; if (data->users) { list_clear(data->users, hub_free); list_destroy(data->users); } hub_free(data->file); hub_free(data); } static struct acl_data* parse_config(const char* line) { struct acl_data* data = (struct acl_data*) hub_malloc_zero(sizeof(struct acl_data)); struct cfg_tokens* tokens = cfg_tokenize(line); char* token = cfg_token_get_first(tokens); if (!data) return 0; // set defaults data->readonly = 1; data->exclusive = 0; data->users = list_create(); while (token) { char* split = strchr(token, '='); size_t len = strlen(token); size_t key = split ? (split - token) : len; if (key == 4 && strncmp(token, "file", 4) == 0) { if (data->file) hub_free(data->file); data->file = strdup(split + 1); } else if (key == 8 && strncmp(token, "readonly", 8) == 0) { if (!string_to_boolean(split + 1, &data->readonly)) data->readonly = 1; } else if (key == 9 && strncmp(token, "exclusive", 9) == 0) { if (!string_to_boolean(split + 1, &data->exclusive)) data->exclusive = 1; } else { cfg_tokens_free(tokens); free_acl(data); return 0; } token = cfg_token_get_next(tokens); } cfg_tokens_free(tokens); return data; } static int parse_line(char* line, int line_count, void* ptr_data) { struct linked_list* users = (struct linked_list*) ptr_data; struct cfg_tokens* tokens = cfg_tokenize(line); enum auth_credentials cred; char* credential; char* username; char* password; if (cfg_token_count(tokens) == 0) { cfg_tokens_free(tokens); return 0; } if (cfg_token_count(tokens) < 2) { cfg_tokens_free(tokens); return -1; } credential = cfg_token_get_first(tokens); username = cfg_token_get_next(tokens); password = cfg_token_get_next(tokens); if (!auth_string_to_cred(credential, &cred)) { cfg_tokens_free(tokens); return -1; } insert_user(users, username, password, cred); cfg_tokens_free(tokens); return 0; } static struct acl_data* load_acl(const char* config, struct plugin_handle* handle) { struct acl_data* data = parse_config(config); if (!data) return 0; if (!data->file || !*data->file) { free_acl(data); data = 0; set_error_message(handle, "No configuration file given, missing \"file=\" configuration option."); return 0; } if (file_read_lines(data->file, data->users, &parse_line) == -1) { fprintf(stderr, "Unable to load %s\n", data->file); set_error_message(handle, "Unable to load file"); } return data; } static void unload_acl(struct acl_data* data) { free_acl(data); } static plugin_st get_user(struct plugin_handle* plugin, const char* nickname, struct auth_info* data) { struct acl_data* acl = (struct acl_data*) plugin->ptr; struct auth_info* info; LIST_FOREACH(struct auth_info*, info, acl->users, { if (strcasecmp((char*)info->nickname, nickname) == 0) { memcpy(data, info, sizeof(struct auth_info)); return st_allow; } }); if (acl->exclusive) return st_deny; return st_default; } static plugin_st register_user(struct plugin_handle* plugin, struct auth_info* user) { struct acl_data* acl = (struct acl_data*) plugin->ptr; if (acl->exclusive) return st_deny; return st_default; } static plugin_st update_user(struct plugin_handle* plugin, struct auth_info* user) { struct acl_data* acl = (struct acl_data*) plugin->ptr; if (acl->exclusive) return st_deny; return st_default; } static plugin_st delete_user(struct plugin_handle* plugin, struct auth_info* user) { struct acl_data* acl = (struct acl_data*) plugin->ptr; if (acl->exclusive) return st_deny; return st_default; } PLUGIN_API int plugin_register(struct plugin_handle* plugin, const char* config) { PLUGIN_INITIALIZE(plugin, "File authentication plugin", "0.1", "Authenticate users based on a read-only text file."); // Authentication actions. plugin->funcs.auth_get_user = get_user; plugin->funcs.auth_register_user = register_user; plugin->funcs.auth_update_user = update_user; plugin->funcs.auth_delete_user = delete_user; plugin->ptr = load_acl(config, plugin); if (plugin->ptr) return 0; return -1; } PLUGIN_API int plugin_unregister(struct plugin_handle* plugin) { set_error_message(plugin, 0); unload_acl(plugin->ptr); return 0; } modelrockettier-uhub-a8ee6e7/src/plugins/mod_auth_sqlite.c000066400000000000000000000157571324501300100241560ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "plugin_api/handle.h" #include #include "util/memory.h" #include "util/list.h" #include "util/misc.h" #include "util/log.h" #include "util/config_token.h" // #define DEBUG_SQL static void set_error_message(struct plugin_handle* plugin, const char* msg) { plugin->error_msg = msg; } struct sql_data { int exclusive; sqlite3* db; }; static int null_callback(void* ptr, int argc, char **argv, char **colName) { return 0; } static int sql_execute(struct sql_data* sql, int (*callback)(void* ptr, int argc, char **argv, char **colName), void* ptr, const char* sql_fmt, ...) { va_list args; char query[1024]; char* errMsg; int rc; va_start(args, sql_fmt); vsnprintf(query, sizeof(query), sql_fmt, args); #ifdef DEBUG_SQL printf("SQL: %s\n", query); #endif rc = sqlite3_exec(sql->db, query, callback, ptr, &errMsg); if (rc != SQLITE_OK) { #ifdef DEBUG_SQL fprintf(stderr, "ERROR: %s\n", errMsg); #endif sqlite3_free(errMsg); return -rc; } rc = sqlite3_changes(sql->db); return rc; } static struct sql_data* parse_config(const char* line, struct plugin_handle* plugin) { struct sql_data* data = (struct sql_data*) hub_malloc_zero(sizeof(struct sql_data)); struct cfg_tokens* tokens = cfg_tokenize(line); char* token = cfg_token_get_first(tokens); if (!data) return 0; while (token) { struct cfg_settings* setting = cfg_settings_split(token); if (!setting) { set_error_message(plugin, "Unable to parse startup parameters"); cfg_tokens_free(tokens); hub_free(data); return 0; } if (strcmp(cfg_settings_get_key(setting), "file") == 0) { if (!data->db) { if (sqlite3_open(cfg_settings_get_value(setting), &data->db)) { cfg_tokens_free(tokens); cfg_settings_free(setting); hub_free(data); set_error_message(plugin, "Unable to open database file"); return 0; } } } else if (strcmp(cfg_settings_get_key(setting), "exclusive") == 0) { if (!string_to_boolean(cfg_settings_get_value(setting), &data->exclusive)) data->exclusive = 1; } else { set_error_message(plugin, "Unknown startup parameters given"); cfg_tokens_free(tokens); cfg_settings_free(setting); hub_free(data); return 0; } cfg_settings_free(setting); token = cfg_token_get_next(tokens); } cfg_tokens_free(tokens); if (!data->db) { set_error_message(plugin, "No database file is given, use file="); hub_free(data); return 0; } return data; } static const char* sql_escape_string(const char* str) { static char out[1024]; size_t i = 0; size_t n = 0; for (; n < strlen(str); n++) { if (str[n] == '\'') out[i++] = '\''; out[i++] = str[n]; } out[i++] = '\0'; return out; } struct data_record { struct auth_info* data; int found; }; static int get_user_callback(void* ptr, int argc, char **argv, char **colName){ struct data_record* data = (struct data_record*) ptr; int i = 0; for (; i < argc; i++) { if (strcmp(colName[i], "nickname") == 0) strncpy(data->data->nickname, argv[i], MAX_NICK_LEN); else if (strcmp(colName[i], "password") == 0) strncpy(data->data->password, argv[i], MAX_PASS_LEN); else if (strcmp(colName[i], "credentials") == 0) { auth_string_to_cred(argv[i], &data->data->credentials); data->found = 1; } } #ifdef DEBUG_SQL printf("SQL: nickname=%s, password=%s, credentials=%s\n", data->data->nickname, data->data->password, auth_cred_to_string(data->data->credentials)); #endif return 0; } static plugin_st get_user(struct plugin_handle* plugin, const char* nickname, struct auth_info* data) { struct sql_data* sql = (struct sql_data*) plugin->ptr; struct data_record result; char query[1024]; char* errMsg; int rc; snprintf(query, sizeof(query), "SELECT * FROM users WHERE nickname='%s';", sql_escape_string(nickname)); memset(data, 0, sizeof(struct auth_info)); result.data = data; result.found = 0; #ifdef DEBUG_SQL printf("SQL: %s\n", query); #endif rc = sqlite3_exec(sql->db, query , get_user_callback, &result, &errMsg); if (rc != SQLITE_OK) { #ifdef DEBUG_SQL fprintf(stderr, "SQL: ERROR: %s\n", errMsg); #endif sqlite3_free(errMsg); return st_default; } if (result.found) return st_allow; return st_default; } static plugin_st register_user(struct plugin_handle* plugin, struct auth_info* user) { struct sql_data* sql = (struct sql_data*) plugin->ptr; char* nick = strdup(sql_escape_string(user->nickname)); char* pass = strdup(sql_escape_string(user->password)); const char* cred = auth_cred_to_string(user->credentials); int rc = sql_execute(sql, null_callback, NULL, "INSERT INTO users (nickname, password, credentials) VALUES('%s', '%s', '%s');", nick, pass, cred); free(nick); free(pass); if (rc <= 0) { fprintf(stderr, "Unable to add user \"%s\"\n", user->nickname); return st_deny; } return st_allow; } static plugin_st update_user(struct plugin_handle* plugin, struct auth_info* user) { struct sql_data* sql = (struct sql_data*) plugin->ptr; char* nick = strdup(sql_escape_string(user->nickname)); char* pass = strdup(sql_escape_string(user->password)); const char* cred = auth_cred_to_string(user->credentials); int rc = sql_execute(sql, null_callback, NULL, "INSERT INTO users (nickname, password, credentials) VALUES('%s', '%s', '%s');", nick, pass, cred); free(nick); free(pass); if (rc <= 0) { fprintf(stderr, "Unable to add user \"%s\"\n", user->nickname); return st_deny; } return st_allow; } static plugin_st delete_user(struct plugin_handle* plugin, struct auth_info* user) { struct sql_data* sql = (struct sql_data*) plugin->ptr; if (sql->exclusive) return st_deny; return st_default; } int plugin_register(struct plugin_handle* plugin, const char* config) { PLUGIN_INITIALIZE(plugin, "SQLite authentication plugin", "1.0", "Authenticate users based on a SQLite database."); // Authentication actions. plugin->funcs.auth_get_user = get_user; plugin->funcs.auth_register_user = register_user; plugin->funcs.auth_update_user = update_user; plugin->funcs.auth_delete_user = delete_user; plugin->ptr = parse_config(config, plugin); if (plugin->ptr) return 0; return -1; } int plugin_unregister(struct plugin_handle* plugin) { struct sql_data* sql; set_error_message(plugin, 0); sql = (struct sql_data*) plugin->ptr; sqlite3_close(sql->db); hub_free(sql); return 0; } modelrockettier-uhub-a8ee6e7/src/plugins/mod_chat_history.c000066400000000000000000000160501324501300100243170ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "plugin_api/handle.h" #include "plugin_api/command_api.h" #include "util/config_token.h" #include "util/memory.h" #include "util/misc.h" #include "util/list.h" #include "util/cbuffer.h" #define MAX_HISTORY_SIZE 16384 struct chat_history_data { size_t history_max; ///<<< "the maximum number of chat messages kept in history." size_t history_default; ///<<< "the default number of chat messages returned if no limit was provided" size_t history_connect; ///<<< "the number of chat messages provided when users connect to the hub." struct linked_list* chat_history; ///<<< "The chat history storage." struct plugin_command_handle* command_history_handle; ///<<< "A handle to the !history command." }; /** * Add a chat message to history. */ static void history_add(struct plugin_handle* plugin, struct plugin_user* from, const char* message, int flags) { size_t loglen = strlen(message) + strlen(from->nick) + 13; struct chat_history_data* data = (struct chat_history_data*) plugin->ptr; char* log = hub_malloc(loglen + 1); snprintf(log, loglen, "%s <%s> %s\n", get_timestamp(time(NULL)), from->nick, message); log[loglen] = '\0'; list_append(data->chat_history, log); while (list_size(data->chat_history) > data->history_max) { list_remove_first(data->chat_history, hub_free); } } /** * Obtain 'num' messages from the chat history and append them to outbuf. * * @return the number of messages added to the buffer. */ static size_t get_messages(struct chat_history_data* data, size_t num, struct cbuffer* outbuf) { struct linked_list* messages = data->chat_history; char* message; int skiplines = 0; size_t lines = 0; size_t total = list_size(messages); if (total == 0) return 0; if (num <= 0 || num > total) num = total; if (num != total) skiplines = total - num; cbuf_append(outbuf, "\n"); LIST_FOREACH(char*, message, messages, { if (--skiplines < 0) { cbuf_append(outbuf, message); lines++; } }); cbuf_append(outbuf, "\n"); return lines; } void user_login(struct plugin_handle* plugin, struct plugin_user* user) { struct chat_history_data* data = (struct chat_history_data*) plugin->ptr; struct cbuffer* buf = NULL; // size_t messages = 0; if (data->history_connect > 0 && list_size(data->chat_history) > 0) { buf = cbuf_create(MAX_HISTORY_SIZE); cbuf_append(buf, "Chat history:\n"); get_messages(data, data->history_connect, buf); plugin->hub.send_message(plugin, user, cbuf_get(buf)); cbuf_destroy(buf); } } /** * Send a status message back to the user who issued the !history command. */ static int command_status(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd, struct cbuffer* buf) { struct cbuffer* msg = cbuf_create(cbuf_size(buf) + strlen(cmd->prefix) + 8); cbuf_append_format(msg, "*** %s: %s", cmd->prefix, cbuf_get(buf)); plugin->hub.send_message(plugin, user, cbuf_get(msg)); cbuf_destroy(msg); cbuf_destroy(buf); return 0; } /** * The callback function for handling the !history command. */ static int command_history(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd) { struct cbuffer* buf; struct chat_history_data* data = (struct chat_history_data*) plugin->ptr; struct plugin_command_arg_data* arg = plugin->hub.command_arg_next(plugin, cmd, plugin_cmd_arg_type_integer); int maxlines; if (!list_size(data->chat_history)) return command_status(plugin, user, cmd, cbuf_create_const("No messages.")); if (arg) maxlines = arg->data.integer; else maxlines = data->history_default; buf = cbuf_create(MAX_HISTORY_SIZE); cbuf_append_format(buf, "*** %s: Chat History:\n", cmd->prefix); get_messages(data, maxlines, buf); plugin->hub.send_message(plugin, user, cbuf_get(buf)); cbuf_destroy(buf); return 0; } static void set_error_message(struct plugin_handle* plugin, const char* msg) { plugin->error_msg = msg; } static struct chat_history_data* parse_config(const char* line, struct plugin_handle* plugin) { struct chat_history_data* data = (struct chat_history_data*) hub_malloc_zero(sizeof(struct chat_history_data)); struct cfg_tokens* tokens = cfg_tokenize(line); char* token = cfg_token_get_first(tokens); uhub_assert(data != NULL); data->history_max = 200; data->history_default = 25; data->history_connect = 5; data->chat_history = list_create(); while (token) { struct cfg_settings* setting = cfg_settings_split(token); if (!setting) { set_error_message(plugin, "Unable to parse startup parameters"); cfg_tokens_free(tokens); hub_free(data); return 0; } if (strcmp(cfg_settings_get_key(setting), "history_max") == 0) { data->history_max = (size_t) uhub_atoi(cfg_settings_get_value(setting)); } else if (strcmp(cfg_settings_get_key(setting), "history_default") == 0) { data->history_default = (size_t) uhub_atoi(cfg_settings_get_value(setting)); } else if (strcmp(cfg_settings_get_key(setting), "history_connect") == 0) { data->history_connect = (size_t) uhub_atoi(cfg_settings_get_value(setting)); } else { set_error_message(plugin, "Unknown startup parameters given"); cfg_tokens_free(tokens); cfg_settings_free(setting); hub_free(data); return 0; } cfg_settings_free(setting); token = cfg_token_get_next(tokens); } cfg_tokens_free(tokens); return data; } int plugin_register(struct plugin_handle* plugin, const char* config) { struct chat_history_data* data; PLUGIN_INITIALIZE(plugin, "Chat history plugin", "1.0", "Provide a global chat history log."); plugin->funcs.on_user_chat_message = history_add; plugin->funcs.on_user_login = user_login; data = parse_config(config, plugin); if (!data) return -1; plugin->ptr = data; data->command_history_handle = (struct plugin_command_handle*) hub_malloc(sizeof(struct plugin_command_handle)); PLUGIN_COMMAND_INITIALIZE(data->command_history_handle, plugin, "history", "?N", auth_cred_guest, &command_history, "Show chat message history."); plugin->hub.command_add(plugin, data->command_history_handle); return 0; } int plugin_unregister(struct plugin_handle* plugin) { struct chat_history_data* data = (struct chat_history_data*) plugin->ptr; if (data) { list_clear(data->chat_history, &hub_free); list_destroy(data->chat_history); plugin->hub.command_del(plugin, data->command_history_handle); hub_free(data->command_history_handle); hub_free(data); } return 0; } modelrockettier-uhub-a8ee6e7/src/plugins/mod_chat_history_sqlite.c000066400000000000000000000250661324501300100257070ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "plugin_api/handle.h" #include "plugin_api/command_api.h" #include "util/config_token.h" #include #include "util/memory.h" #include "util/misc.h" #include "util/list.h" #include "util/cbuffer.h" #define MAX_HISTORY_SIZE 16384 struct chat_history_data { size_t history_max; ///<<< "the maximum number of chat messages kept in history." size_t history_default; ///<<< "the default number of chat messages returned if no limit was provided" size_t history_connect; ///<<< "the number of chat messages provided when users connect to the hub." sqlite3* db; ///<<< "The chat history storage database." struct plugin_command_handle* command_history_handle; ///<<< "A handle to the !history command." struct plugin_command_handle* command_historycleanup_handle; ///<<< "A handle to the !historycleanup command." }; struct chat_history_line { char message[MAX_HISTORY_SIZE]; char from[MAX_NICK_LEN]; char time[20]; }; static int null_callback(void* ptr, int argc, char **argv, char **colName) { return 0; } static const char* sql_escape_string(const char* str) { static char out[MAX_HISTORY_SIZE]; size_t i = 0; size_t n = 0; for (; n < strlen(str); n++) { if (str[n] == '\'') out[i++] = '\''; out[i++] = str[n]; } out[i++] = '\0'; return out; } static int sql_execute(struct chat_history_data* sql, int (*callback)(void* ptr, int argc, char **argv, char **colName), void* ptr, const char* sql_fmt, ...) { va_list args; char query[MAX_HISTORY_SIZE]; char* errMsg; int rc; va_start(args, sql_fmt); vsnprintf(query, sizeof(query), sql_fmt, args); rc = sqlite3_exec(sql->db, query, callback, ptr, &errMsg); if (rc != SQLITE_OK) { sqlite3_free(errMsg); return -rc; } rc = sqlite3_changes(sql->db); return rc; } static void create_tables(struct plugin_handle* plugin) { const char* table_create = "CREATE TABLE IF NOT EXISTS chat_history" "(" "from_nick CHAR," "message TEXT," "time TIMESTAMP DEFAULT (DATETIME('NOW'))" ");"; struct chat_history_data* data = (struct chat_history_data*) plugin->ptr; sql_execute(data, null_callback, NULL, table_create); } /** * Add a chat message to history. */ static void history_add(struct plugin_handle* plugin, struct plugin_user* from, const char* message, int flags) { struct chat_history_data* data = (struct chat_history_data*) plugin->ptr; char* history_line = strdup(sql_escape_string(message)); char* history_nick = strdup(sql_escape_string(from->nick)); sql_execute(data, null_callback, NULL, "INSERT INTO chat_history (from_nick, message) VALUES('%s', '%s');DELETE FROM chat_history WHERE time <= (SELECT time FROM chat_history ORDER BY time DESC LIMIT %d,1);", history_nick, history_line, data->history_max); hub_free(history_line); hub_free(history_nick); } /** * Obtain messages from the chat history as a linked list */ static int get_messages_callback(void* ptr, int argc, char **argv, char **colName) { struct linked_list* messages = (struct linked_list*) ptr; struct chat_history_line* line = hub_malloc(sizeof(struct chat_history_line)); int i = 0; memset(line, 0, sizeof(struct chat_history_line)); for (; i < argc; i++) { if (strcmp(colName[i], "from_nick") == 0) strncpy(line->from, argv[i], MAX_NICK_LEN); else if (strcmp(colName[i], "message") == 0) strncpy(line->message, argv[i], MAX_HISTORY_SIZE); else if (strcmp(colName[i], "time") == 0) strncpy(line->time, argv[i], 20); } list_append(messages, line); return 0; } void user_login(struct plugin_handle* plugin, struct plugin_user* user) { struct chat_history_data* data = (struct chat_history_data*) plugin->ptr; struct cbuffer* buf = NULL; struct linked_list* found = (struct linked_list*) list_create(); sql_execute(data, get_messages_callback, found, "SELECT * FROM chat_history ORDER BY time DESC LIMIT 0,%d;", (int) data->history_connect); if (data->history_connect > 0 && list_size(found) > 0) { buf = cbuf_create(MAX_HISTORY_SIZE); cbuf_append(buf, "Chat history:\n\n"); struct chat_history_line* history_line; history_line = (struct chat_history_line*) list_get_last(found); while (history_line) { cbuf_append_format(buf, "[%s] <%s> %s\n", history_line->time, history_line->from, history_line->message); list_remove(found, history_line); hub_free(history_line); history_line = (struct chat_history_line*) list_get_last(found); } plugin->hub.send_message(plugin, user, cbuf_get(buf)); cbuf_destroy(buf); } list_clear(found, &hub_free); list_destroy(found); } /** * The callback function for handling the !history command. */ static int command_history(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd) { struct chat_history_data* data = (struct chat_history_data*) plugin->ptr; struct cbuffer* buf = cbuf_create(MAX_HISTORY_SIZE); struct linked_list* found = (struct linked_list*) list_create(); struct plugin_command_arg_data* arg = plugin->hub.command_arg_next(plugin, cmd, plugin_cmd_arg_type_integer); int maxlines; if (arg) maxlines = arg->data.integer; else maxlines = data->history_default; sql_execute(data, get_messages_callback, found, "SELECT * FROM chat_history ORDER BY time DESC LIMIT 0,%d;", maxlines); size_t linecount = list_size(found); if (linecount > 0) { cbuf_append_format(buf, "*** %s: Chat History:\n\n", cmd->prefix); struct chat_history_line* history_line; history_line = (struct chat_history_line*) list_get_last(found); while (history_line) { cbuf_append_format(buf, "[%s] <%s> %s\n", history_line->time, history_line->from, history_line->message); list_remove(found, history_line); hub_free(history_line); history_line = (struct chat_history_line*) list_get_last(found); } } else { cbuf_append_format(buf, "*** %s: No messages found.", cmd->prefix); } plugin->hub.send_message(plugin, user, cbuf_get(buf)); cbuf_destroy(buf); list_clear(found, &hub_free); list_destroy(found); return 0; } static int command_historycleanup(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd) { struct chat_history_data* data = (struct chat_history_data*) plugin->ptr; struct cbuffer* buf = cbuf_create(128); int rc = 0; rc = sql_execute(data, null_callback, NULL, "DELETE FROM chat_history;"); if (!rc) cbuf_append_format(buf, "*** %s: Unable to clean chat history table.", cmd->prefix); else cbuf_append_format(buf, "*** %s: Cleaned chat history table.", cmd->prefix); plugin->hub.send_message(plugin, user, cbuf_get(buf)); cbuf_destroy(buf); sql_execute(data, null_callback, NULL, "VACUUM;"); return 0; } static void set_error_message(struct plugin_handle* plugin, const char* msg) { plugin->error_msg = msg; } static struct chat_history_data* parse_config(const char* line, struct plugin_handle* plugin) { struct chat_history_data* data = (struct chat_history_data*) hub_malloc_zero(sizeof(struct chat_history_data)); struct cfg_tokens* tokens = cfg_tokenize(line); char* token = cfg_token_get_first(tokens); uhub_assert(data != NULL); data->history_max = 200; data->history_default = 25; data->history_connect = 5; while (token) { struct cfg_settings* setting = cfg_settings_split(token); if (!setting) { set_error_message(plugin, "Unable to parse startup parameters"); cfg_tokens_free(tokens); hub_free(data); return 0; } if (strcmp(cfg_settings_get_key(setting), "file") == 0) { if (!data->db) { if (sqlite3_open(cfg_settings_get_value(setting), &data->db)) { cfg_tokens_free(tokens); cfg_settings_free(setting); hub_free(data); set_error_message(plugin, "Unable to open database file"); return 0; } } } else if (strcmp(cfg_settings_get_key(setting), "history_max") == 0) { data->history_max = (size_t) uhub_atoi(cfg_settings_get_value(setting)); } else if (strcmp(cfg_settings_get_key(setting), "history_default") == 0) { data->history_default = (size_t) uhub_atoi(cfg_settings_get_value(setting)); } else if (strcmp(cfg_settings_get_key(setting), "history_connect") == 0) { data->history_connect = (size_t) uhub_atoi(cfg_settings_get_value(setting)); } else { set_error_message(plugin, "Unknown startup parameters given"); cfg_tokens_free(tokens); cfg_settings_free(setting); hub_free(data); return 0; } cfg_settings_free(setting); token = cfg_token_get_next(tokens); } cfg_tokens_free(tokens); return data; } int plugin_register(struct plugin_handle* plugin, const char* config) { struct chat_history_data* data; PLUGIN_INITIALIZE(plugin, "SQLite chat history plugin", "1.0", "Provide a global chat history log."); plugin->funcs.on_user_chat_message = history_add; plugin->funcs.on_user_login = user_login; data = parse_config(config, plugin); if (!data) return -1; plugin->ptr = data; create_tables(plugin); data->command_history_handle = (struct plugin_command_handle*) hub_malloc(sizeof(struct plugin_command_handle)); PLUGIN_COMMAND_INITIALIZE(data->command_history_handle, plugin, "history", "?N", auth_cred_guest, &command_history, "Show chat message history."); plugin->hub.command_add(plugin, data->command_history_handle); data->command_historycleanup_handle = (struct plugin_command_handle*) hub_malloc(sizeof(struct plugin_command_handle)); PLUGIN_COMMAND_INITIALIZE(data->command_historycleanup_handle, plugin, "historycleanup", "", auth_cred_admin, &command_historycleanup, "Clean chat message history."); plugin->hub.command_add(plugin, data->command_historycleanup_handle); return 0; } int plugin_unregister(struct plugin_handle* plugin) { struct chat_history_data* data = (struct chat_history_data*) plugin->ptr; if (data) { sqlite3_close(data->db); plugin->hub.command_del(plugin, data->command_history_handle); plugin->hub.command_del(plugin, data->command_historycleanup_handle); hub_free(data->command_history_handle); hub_free(data->command_historycleanup_handle); hub_free(data); } return 0; } modelrockettier-uhub-a8ee6e7/src/plugins/mod_chat_is_privileged.c000066400000000000000000000111641324501300100254440ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "plugin_api/handle.h" #include "util/memory.h" struct user_info { sid_t sid; int warnings; }; struct chat_restrictions_data { size_t num_users; // number of users tracked. size_t max_users; // max users (hard limit max 1M users due to limitations in the SID (20 bits)). struct user_info* users; // array of max_users enum auth_credentials allow_privchat; // minimum credentials to allow using private chat enum auth_credentials allow_op_contact; // minimum credentials to allow private chat to operators (including super and admins). enum auth_credentials allow_mainchat; // minimum credentials to allow using main chat }; static struct chat_data* parse_config(struct plugin_handle* plugin, const char* line) { struct chat_data* data = (struct chat_data*) hub_malloc(sizeof(struct chat_data)); struct cfg_tokens* tokens = cfg_tokenize(line); char* token = cfg_token_get_first(tokens); // defaults data->num_users = 0; data->max_users = 512; data->users = hub_malloc_zero(sizeof(struct user_info) * data->max_users); data->allow_mainchat = auth_cred_guest; data->allow_op_contact = auth_cred_guest; data->allow_privchat = auth_cred_guest; while (token) { struct cfg_settings* setting = cfg_settings_split(token); if (!setting) { set_error_message(plugin, "Unable to parse startup parameters"); cfg_tokens_free(tokens); hub_free(data); return 0; } if (strcmp(cfg_settings_get_key(setting), "allow_privchat") == 0) { if (!string_to_boolean(cfg_settings_get_value(setting), &data->allow_privchat)) data->allow_privchat = 0; } else if (strcmp(cfg_settings_get_key(setting), "minimum_access") == 0) { } else { set_error_message(plugin, "Unknown startup parameters given"); cfg_tokens_free(tokens); cfg_settings_free(setting); hub_free(data); return 0; } cfg_settings_free(setting); token = cfg_token_get_next(tokens); } cfg_tokens_free(tokens); return data; } static struct user_info* get_user_info(struct chat_data* data, sid_t sid) { struct user_info* u; // resize buffer if needed. if (sid >= data->max_users) { u = hub_malloc_zero(sizeof(struct user_info) * (sid + 1)); memcpy(u, data->users, data->max_users); hub_free(data->users); data->users = u; data->max_users = sid; u = NULL; } u = &data->users[sid]; // reset counters if the user was not previously known. if (!u->sid) { u->sid = sid; u->warnings = 0; data->num_users++; } return u; } static void on_user_login(struct plugin_handle* plugin, struct plugin_user* user) { struct chat_data* data = (struct chat_data*) plugin->ptr; /*struct user_info* info = */ get_user_info(data, user->sid); } static void on_user_logout(struct plugin_handle* plugin, struct plugin_user* user, const char* reason) { struct chat_data* data = (struct chat_data*) plugin->ptr; struct user_info* info = get_user_info(data, user->sid); if (info->sid) data->num_users--; info->warnings = 0; info->sid = 0; } plugin_st on_chat_msg(struct plugin_handle* plugin, struct plugin_user* from, const char* message) { struct chat_data* data = (struct chat_data*) plugin->ptr; if (from->credentials >= return st_default; } plugin_st on_private_msg(struct plugin_handle* plugin, struct plugin_user* from, struct plugin_user* to, const char* message) { return st_default; } int plugin_register(struct plugin_handle* plugin, const char* config) { PLUGIN_INITIALIZE(plugin, "Privileged chat hub", "1.0", "Only registered users can send messages on the main chat."); plugin->ptr = cip_initialize(); plugin->funcs.on_user_login = on_user_login; plugin->funcs.on_user_logout = on_user_logout; plugin->funcs.on_chat_msg = on_chat_msg; plugin->funcs.on_private_msg = on_private_msg; return 0; } int plugin_unregister(struct plugin_handle* plugin) { struct chat_data* data = (struct chat_data*) plugin->ptr; if (data) { hub_free(data->users); hub_free(data); } return 0; } modelrockettier-uhub-a8ee6e7/src/plugins/mod_chat_only.c000066400000000000000000000113531324501300100236000ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "plugin_api/handle.h" #include "util/memory.h" enum Warnings { WARN_SEARCH = 0x01, ///<<< "Warn about searching." WARN_CONNECT = 0x02, ///<<< "Warn about connecting to a user" WARN_EXTRA = 0x08, ///<<< "Warn about unknown protocol data." }; struct user_info { sid_t sid; // The SID of the user int warnings; // The number of denies (used to track wether or not a warning should be sent). @see enum Warnings. }; struct chat_only_data { size_t num_users; // number of users tracked. size_t max_users; // max users (hard limit max 1M users due to limitations in the SID (20 bits)). struct user_info* users; // array of max_users int operator_override; // operators are allowed to override these limitations. }; static struct chat_only_data* co_initialize() { struct chat_only_data* data = (struct chat_only_data*) hub_malloc(sizeof(struct chat_only_data)); data->num_users = 0; data->max_users = 512; data->users = hub_malloc_zero(sizeof(struct user_info) * data->max_users); return data; } static void co_shutdown(struct chat_only_data* data) { if (data) { hub_free(data->users); hub_free(data); } } static struct user_info* get_user_info(struct chat_only_data* data, sid_t sid) { struct user_info* u; // resize buffer if needed. if (sid >= data->max_users) { u = hub_malloc_zero(sizeof(struct user_info) * (sid + 1)); memcpy(u, data->users, data->max_users); hub_free(data->users); data->users = u; data->max_users = sid + 1; u = NULL; } u = &data->users[sid]; // reset counters if the user was not previously known. if (!u->sid) { u->sid = sid; u->warnings = 0; data->num_users++; } return u; } static plugin_st on_search_result(struct plugin_handle* plugin, struct plugin_user* from, struct plugin_user* to, const char* search_data) { return st_deny; } static plugin_st on_search(struct plugin_handle* plugin, struct plugin_user* user, const char* search_data) { struct chat_only_data* data = (struct chat_only_data*) plugin->ptr; struct user_info* info = get_user_info(data, user->sid); if (user->credentials >= auth_cred_operator && data->operator_override) return st_allow; if (!(info->warnings & WARN_SEARCH)) { plugin->hub.send_status_message(plugin, user, 000, "Searching is disabled. This is a chat only hub."); info->warnings |= WARN_SEARCH; } return st_deny; } static plugin_st on_p2p_connect(struct plugin_handle* plugin, struct plugin_user* from, struct plugin_user* to) { struct chat_only_data* data = (struct chat_only_data*) plugin->ptr; struct user_info* info = get_user_info(data, from->sid); if (from->credentials >= auth_cred_operator && data->operator_override) return st_allow; if (!(info->warnings & WARN_CONNECT)) { plugin->hub.send_status_message(plugin, from, 000, "Connection setup denied. This is a chat only hub."); info->warnings |= WARN_CONNECT; } return st_deny; } static void on_user_login(struct plugin_handle* plugin, struct plugin_user* user) { struct chat_only_data* data = (struct chat_only_data*) plugin->ptr; /*struct user_info* info = */ get_user_info(data, user->sid); } static void on_user_logout(struct plugin_handle* plugin, struct plugin_user* user, const char* reason) { struct chat_only_data* data = (struct chat_only_data*) plugin->ptr; struct user_info* info = get_user_info(data, user->sid); if (info->sid) data->num_users--; info->warnings = 0; info->sid = 0; } int plugin_register(struct plugin_handle* plugin, const char* config) { PLUGIN_INITIALIZE(plugin, "Chat only hub", "1.0", "Disables connection setup, search and results."); plugin->ptr = co_initialize(); plugin->funcs.on_search = on_search; plugin->funcs.on_search_result = on_search_result; plugin->funcs.on_p2p_connect = on_p2p_connect; plugin->funcs.on_p2p_revconnect = on_p2p_connect; plugin->funcs.on_user_login = on_user_login; plugin->funcs.on_user_logout = on_user_logout; return 0; } int plugin_unregister(struct plugin_handle* plugin) { co_shutdown((struct chat_only_data*) plugin->ptr); return 0; } modelrockettier-uhub-a8ee6e7/src/plugins/mod_example.c000066400000000000000000000042141324501300100232510ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "plugin_api/handle.h" #include "plugin_api/command_api.h" #include "util/memory.h" struct example_plugin_data { struct plugin_command_handle* example; }; static int example_command_handler(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd) { plugin->hub.send_message(plugin, user, "Hello from mod_example."); return 0; } static void command_register(struct plugin_handle* plugin) { struct example_plugin_data* data = (struct example_plugin_data*) hub_malloc(sizeof(struct example_plugin_data)); data->example = hub_malloc_zero(sizeof(struct plugin_command_handle)); PLUGIN_COMMAND_INITIALIZE(data->example, (void*) data, "example", "", auth_cred_guest, example_command_handler, "This is an example command that is added dynamically by loading the mod_example plug-in."); plugin->hub.command_add(plugin, data->example); plugin->ptr = data; } static void command_unregister(struct plugin_handle* plugin) { struct example_plugin_data* data = (struct example_plugin_data*) plugin->ptr; plugin->hub.command_del(plugin, data->example); hub_free(data->example); hub_free(data); plugin->ptr = NULL; } int plugin_register(struct plugin_handle* plugin, const char* config) { PLUGIN_INITIALIZE(plugin, "Example plugin", "1.0", "A simple example plugin"); command_register(plugin); return 0; } int plugin_unregister(struct plugin_handle* plugin) { command_unregister(plugin); return 0; } modelrockettier-uhub-a8ee6e7/src/plugins/mod_logging.c000066400000000000000000000143721324501300100232520ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "system.h" #include "adc/adcconst.h" #include "adc/sid.h" #include "util/memory.h" #include "network/ipcalc.h" #include "plugin_api/handle.h" #include "util/misc.h" #include "util/config_token.h" #ifndef WIN32 #include #endif struct ip_addr_encap; struct log_data { enum { mode_file, mode_syslog } logmode; char* logfile; int fd; }; static void reset(struct log_data* data) { /* set defaults */ data->logmode = mode_file; data->logfile = NULL; data->fd = -1; } static void set_error_message(struct plugin_handle* plugin, const char* msg) { plugin->error_msg = msg; } static int log_open_file(struct plugin_handle* plugin, struct log_data* data) { int flags = O_CREAT | O_APPEND | O_WRONLY; data->fd = open(data->logfile, flags, 0664); return (data->fd != -1); } #ifndef WIN32 static int log_open_syslog(struct plugin_handle* plugin) { openlog("uhub", 0, LOG_USER); return 1; } #endif static struct log_data* parse_config(const char* line, struct plugin_handle* plugin) { struct log_data* data = (struct log_data*) hub_malloc(sizeof(struct log_data)); struct cfg_tokens* tokens = cfg_tokenize(line); char* token = cfg_token_get_first(tokens); if (!data) return 0; reset(data); while (token) { struct cfg_settings* setting = cfg_settings_split(token); if (!setting) { set_error_message(plugin, "Unable to parse startup parameters"); cfg_tokens_free(tokens); hub_free(data); return 0; } if (strcmp(cfg_settings_get_key(setting), "file") == 0) { data->logfile = strdup(cfg_settings_get_value(setting)); data->logmode = mode_file; } #ifndef WIN32 else if (strcmp(cfg_settings_get_key(setting), "syslog") == 0) { int use_syslog = 0; if (string_to_boolean(cfg_settings_get_value(setting), &use_syslog)) { data->logmode = (use_syslog) ? mode_syslog : mode_file; } } #endif else { set_error_message(plugin, "Unknown startup parameters given"); cfg_tokens_free(tokens); cfg_settings_free(setting); hub_free(data); return 0; } cfg_settings_free(setting); token = cfg_token_get_next(tokens); } cfg_tokens_free(tokens); if (data->logmode == mode_file) { if ((data->logmode == mode_file && !data->logfile)) { set_error_message(plugin, "No log file is given, use file="); hub_free(data); return 0; } if (!log_open_file(plugin, data)) { hub_free(data->logfile); hub_free(data); set_error_message(plugin, "Unable to open log file"); return 0; } } #ifndef WIN32 else { if (!log_open_syslog(plugin)) { hub_free(data->logfile); hub_free(data); set_error_message(plugin, "Unable to open syslog"); return 0; } } #endif return data; } static void log_close(struct log_data* data) { if (data->logmode == mode_file) { hub_free(data->logfile); close(data->fd); } #ifndef WIN32 else { closelog(); } #endif hub_free(data); } static void log_message(struct log_data* data, const char *format, ...) { static char logmsg[1024]; struct tm *tmp; time_t t; va_list args; ssize_t size = 0; if (data->logmode == mode_file) { t = time(NULL); tmp = localtime(&t); strftime(logmsg, 32, "%Y-%m-%d %H:%M:%S ", tmp); va_start(args, format); size = vsnprintf(logmsg + 20, 1004, format, args); va_end(args); if (write(data->fd, logmsg, size + 20) < (size+20)) { fprintf(stderr, "Unable to write full log. Error=%d: %s\n", errno, strerror(errno)); } else { #ifdef WIN32 _commit(data->fd); #else #if defined _POSIX_SYNCHRONIZED_IO && _POSIX_SYNCHRONIZED_IO > 0 fdatasync(data->fd); #else fsync(data->fd); #endif #endif } } #ifndef WIN32 else { va_start(args, format); vsyslog(LOG_INFO, format, args); va_end(args); } #endif } static void log_user_login(struct plugin_handle* plugin, struct plugin_user* user) { const char* cred = auth_cred_to_string(user->credentials); const char* addr = ip_convert_to_string(&user->addr); log_message(plugin->ptr, "LoginOK %s/%s %s \"%s\" (%s) \"%s\"\n", sid_to_string(user->sid), user->cid, addr, user->nick, cred, user->user_agent); } static void log_user_login_error(struct plugin_handle* plugin, struct plugin_user* user, const char* reason) { const char* addr = ip_convert_to_string(&user->addr); log_message(plugin->ptr, "LoginError %s/%s %s \"%s\" (%s) \"%s\"\n", sid_to_string(user->sid), user->cid, addr, user->nick, reason, user->user_agent); } static void log_user_logout(struct plugin_handle* plugin, struct plugin_user* user, const char* reason) { const char* addr = ip_convert_to_string(&user->addr); log_message(plugin->ptr, "Logout %s/%s %s \"%s\" (%s) \"%s\"\n", sid_to_string(user->sid), user->cid, addr, user->nick, reason, user->user_agent); } static void log_change_nick(struct plugin_handle* plugin, struct plugin_user* user, const char* new_nick) { const char* addr = ip_convert_to_string(&user->addr); log_message(plugin->ptr, "NickChange %s/%s %s \"%s\" -> \"%s\"\n", sid_to_string(user->sid), user->cid, addr, user->nick, new_nick); } int plugin_register(struct plugin_handle* plugin, const char* config) { PLUGIN_INITIALIZE(plugin, "Logging plugin", "1.0", "Logs users entering and leaving the hub."); plugin->funcs.on_user_login = log_user_login; plugin->funcs.on_user_login_error = log_user_login_error; plugin->funcs.on_user_logout = log_user_logout; plugin->funcs.on_user_nick_change = log_change_nick; plugin->ptr = parse_config(config, plugin); if (!plugin->ptr) return -1; return 0; } int plugin_unregister(struct plugin_handle* plugin) { /* No need to do anything! */ log_close(plugin->ptr); return 0; } modelrockettier-uhub-a8ee6e7/src/plugins/mod_no_guest_downloads.c000066400000000000000000000036511324501300100255170ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "plugin_api/handle.h" #include "util/memory.h" static plugin_st on_search_result(struct plugin_handle* plugin, struct plugin_user* from, struct plugin_user* to, const char* search_data) { if (to->credentials >= auth_cred_user) return st_default; return st_deny; } static plugin_st on_search(struct plugin_handle* plugin, struct plugin_user* user, const char* search_data) { // Registered users are allowed to search. if (user->credentials >= auth_cred_user) return st_default; return st_deny; } static plugin_st on_p2p_connect(struct plugin_handle* plugin, struct plugin_user* from, struct plugin_user* to) { if (from->credentials >= auth_cred_user) return st_default; return st_deny; } int plugin_register(struct plugin_handle* plugin, const char* config) { PLUGIN_INITIALIZE(plugin, "No guest downloading", "0.1", "This plug-in only allows registered users to search and initiate transfers."); plugin->ptr = NULL; plugin->funcs.on_search = on_search; plugin->funcs.on_search_result = on_search_result; plugin->funcs.on_p2p_connect = on_p2p_connect; // plugin->funcs.on_p2p_revconnect = on_p2p_connect; return 0; } int plugin_unregister(struct plugin_handle* plugin) { return 0; } modelrockettier-uhub-a8ee6e7/src/plugins/mod_topic.c000066400000000000000000000075511324501300100227430ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "plugin_api/handle.h" #include "plugin_api/command_api.h" #include "util/memory.h" #include "util/cbuffer.h" struct topic_plugin_data { struct plugin_command_handle* topic; struct plugin_command_handle* resettopic; struct plugin_command_handle* showtopic; }; static int command_topic_handler(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd) { struct cbuffer* buf = cbuf_create(128); struct plugin_command_arg_data* arg = plugin->hub.command_arg_next(plugin, cmd, plugin_cmd_arg_type_string); char* topic = arg ? arg->data.string : ""; plugin->hub.set_description(plugin, topic); cbuf_append_format(buf, "*** %s: Topic set to \"%s\"", cmd->prefix, topic); plugin->hub.send_message(plugin, user, cbuf_get(buf)); cbuf_destroy(buf); return 0; } static int command_resettopic_handler(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd) { struct cbuffer* buf = cbuf_create(128); plugin->hub.set_description(plugin, NULL); cbuf_append_format(buf, "*** %s: Topic reset.", cmd->prefix); plugin->hub.send_message(plugin, user, cbuf_get(buf)); cbuf_destroy(buf); return 0; } static int command_showtopic_handler(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd) { struct cbuffer* buf = cbuf_create(128); char* topic = plugin->hub.get_description(plugin); cbuf_append_format(buf, "*** %s: Current topic is: \"%s\"", cmd->prefix, topic); plugin->hub.send_message(plugin, user, cbuf_get(buf)); cbuf_destroy(buf); hub_free(topic); return 0; } int plugin_register(struct plugin_handle* plugin, const char* config) { struct topic_plugin_data* data = (struct topic_plugin_data*) hub_malloc(sizeof(struct topic_plugin_data)); data->topic = (struct plugin_command_handle*) hub_malloc_zero(sizeof(struct plugin_command_handle)); data->resettopic = (struct plugin_command_handle*) hub_malloc_zero(sizeof(struct plugin_command_handle)); data->showtopic = (struct plugin_command_handle*) hub_malloc_zero(sizeof(struct plugin_command_handle)); PLUGIN_INITIALIZE(plugin, "Topic plugin", "1.0", "Add commands for changing the hub topic (description)"); PLUGIN_COMMAND_INITIALIZE(data->topic, (void*) data, "topic", "+m", auth_cred_operator, command_topic_handler, "Set new topic"); PLUGIN_COMMAND_INITIALIZE(data->resettopic, (void*) data, "resettopic", "", auth_cred_operator, command_resettopic_handler, "Set topic to default"); PLUGIN_COMMAND_INITIALIZE(data->showtopic, (void*) data, "showtopic", "", auth_cred_guest, command_showtopic_handler, "Shows the current topic"); plugin->hub.command_add(plugin, data->topic); plugin->hub.command_add(plugin, data->resettopic); plugin->hub.command_add(plugin, data->showtopic); plugin->ptr = data; return 0; } int plugin_unregister(struct plugin_handle* plugin) { struct topic_plugin_data* data = (struct topic_plugin_data*) plugin->ptr; plugin->hub.command_del(plugin, data->topic); plugin->hub.command_del(plugin, data->resettopic); plugin->hub.command_del(plugin, data->showtopic); hub_free(data->topic); hub_free(data->resettopic); hub_free(data->showtopic); hub_free(data); plugin->ptr = NULL; return 0; } modelrockettier-uhub-a8ee6e7/src/plugins/mod_welcome.c000066400000000000000000000161161324501300100232550ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "system.h" #include "adc/adcconst.h" #include "adc/sid.h" #include "util/cbuffer.h" #include "util/memory.h" #include "network/ipcalc.h" #include "plugin_api/handle.h" #include "plugin_api/command_api.h" #include "util/misc.h" #include "util/config_token.h" #define MAX_WELCOME_SIZE 16384 struct welcome_data { char* motd_file; char* motd; char* rules_file; char* rules; struct plugin_command_handle* cmd_motd; struct plugin_command_handle* cmd_rules; }; static int command_handler_motd(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd); static int command_handler_rules(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd); static char* read_file(const char* filename) { char* str; char buf[MAX_WELCOME_SIZE]; int fd = open(filename, O_RDONLY); int ret; if (fd == -1) return NULL; ret = read(fd, buf, MAX_WELCOME_SIZE); close(fd); buf[ret > 0 ? ret : 0] = 0; str = strdup(buf); return str; } int read_motd(struct welcome_data* data) { data->motd = read_file(data->motd_file); return !!data->motd; } int read_rules(struct welcome_data* data) { data->rules = read_file(data->rules_file); return !!data->rules; } static void free_welcome_data(struct welcome_data* data) { if (!data) return; hub_free(data->cmd_motd); hub_free(data->motd_file); hub_free(data->motd); hub_free(data->cmd_rules); hub_free(data->rules_file); hub_free(data->rules); hub_free(data); } static void set_error_message(struct plugin_handle* plugin, const char* msg) { plugin->error_msg = msg; } static struct welcome_data* parse_config(const char* line, struct plugin_handle* plugin) { struct welcome_data* data = (struct welcome_data*) hub_malloc_zero(sizeof(struct welcome_data)); struct cfg_tokens* tokens = cfg_tokenize(line); char* token = cfg_token_get_first(tokens); if (!data) return 0; while (token) { struct cfg_settings* setting = cfg_settings_split(token); if (!setting) { set_error_message(plugin, "Unable to parse startup parameters"); goto cleanup_parse_error; } if (strcmp(cfg_settings_get_key(setting), "motd") == 0) { data->motd_file = strdup(cfg_settings_get_value(setting)); if (!read_motd(data)) { set_error_message(plugin, "Unable to read motd file."); cfg_settings_free(setting); goto cleanup_parse_error; } data->cmd_motd = hub_malloc_zero(sizeof(struct plugin_command_handle)); PLUGIN_COMMAND_INITIALIZE(data->cmd_motd, (void*) data, "motd", "", auth_cred_guest, command_handler_motd, "Show the message of the day."); } else if (strcmp(cfg_settings_get_key(setting), "rules") == 0) { data->rules_file = strdup(cfg_settings_get_value(setting)); if (!read_rules(data)) { set_error_message(plugin, "Unable to read rules file."); cfg_settings_free(setting); goto cleanup_parse_error; } data->cmd_rules = hub_malloc_zero(sizeof(struct plugin_command_handle)); PLUGIN_COMMAND_INITIALIZE(data->cmd_rules, (void*) data, "rules", "", auth_cred_guest, command_handler_rules, "Show the hub rules."); } else { set_error_message(plugin, "Unknown startup parameters given"); cfg_settings_free(setting); goto cleanup_parse_error; } cfg_settings_free(setting); token = cfg_token_get_next(tokens); } cfg_tokens_free(tokens); return data; cleanup_parse_error: cfg_tokens_free(tokens); free_welcome_data(data); return 0; } static struct cbuffer* parse_message(struct plugin_user* user, const char* msg) { struct cbuffer* buf = cbuf_create(strlen(msg)); const char* start = msg; const char* offset = NULL; time_t timestamp = time(NULL); struct tm* now = localtime(×tamp); while ((offset = strchr(start, '%'))) { cbuf_append_bytes(buf, start, (offset - start)); offset++; switch (offset[0]) { case 'n': cbuf_append(buf, user->nick); break; case 'a': cbuf_append(buf, ip_convert_to_string(&user->addr)); break; case 'c': cbuf_append(buf, auth_cred_to_string(user->credentials)); break; case '%': cbuf_append(buf, "%"); break; case 'H': cbuf_append_strftime(buf, "%H", now); break; case 'I': cbuf_append_strftime(buf, "%I", now); break; case 'P': cbuf_append_strftime(buf, "%P", now); break; case 'p': cbuf_append_strftime(buf, "%p", now); break; case 'M': cbuf_append_strftime(buf, "%M", now); break; case 'S': cbuf_append_strftime(buf, "%S", now); break; } start = offset + 1; } if (*start) cbuf_append(buf, start); return buf; } static void send_motd(struct plugin_handle* plugin, struct plugin_user* user) { struct welcome_data* data = (struct welcome_data*) plugin->ptr; struct cbuffer* buf = NULL; if (data->motd) { buf = parse_message(user, data->motd); plugin->hub.send_message(plugin, user, cbuf_get(buf)); cbuf_destroy(buf); } } static void send_rules(struct plugin_handle* plugin, struct plugin_user* user) { struct welcome_data* data = (struct welcome_data*) plugin->ptr; struct cbuffer* buf = NULL; if (data->rules) { buf = parse_message(user, data->rules); plugin->hub.send_message(plugin, user, cbuf_get(buf)); cbuf_destroy(buf); } } static void on_user_login(struct plugin_handle* plugin, struct plugin_user* user) { send_motd(plugin, user); } static int command_handler_motd(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd) { send_motd(plugin, user); return 0; } static int command_handler_rules(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd) { send_rules(plugin, user); return 0; } int plugin_register(struct plugin_handle* plugin, const char* config) { struct welcome_data* data; PLUGIN_INITIALIZE(plugin, "Welcome plugin", "0.1", "Sends a welcome message to users when they log into the hub."); data = parse_config(config, plugin); if (!data) return -1; plugin->ptr = data; plugin->funcs.on_user_login = on_user_login; if (data->cmd_motd) plugin->hub.command_add(plugin, data->cmd_motd); if (data->cmd_rules) plugin->hub.command_add(plugin, data->cmd_rules); return 0; } int plugin_unregister(struct plugin_handle* plugin) { struct welcome_data* data = (struct welcome_data*) plugin->ptr; if (data->cmd_motd) plugin->hub.command_del(plugin, data->cmd_motd); if (data->cmd_rules) plugin->hub.command_del(plugin, data->cmd_rules); free_welcome_data(data); return 0; } modelrockettier-uhub-a8ee6e7/src/system.h.in000066400000000000000000000137741324501300100212470ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_SYSTEM_H #define HAVE_UHUB_SYSTEM_H #define _FILE_OFFSET_BITS 64 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD_kernel__) #define BSD_LIKE #endif #if defined(__CYGWIN__) || defined(__MINGW32__) || defined(_MSC_VER) #ifndef WINSOCK #define WINSOCK #endif #define WINTHREAD_SUPPORT 1 #endif #if defined(__CYGWIN__) || defined(__MINGW32__) #define NEED_GETOPT #endif #cmakedefine HAVE_SYS_TYPES_H #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef WINSOCK #ifndef FD_SETSIZE #define FD_SETSIZE 4096 #endif #include #include #else #include #include #include #include #include #include #endif #include #include #include #cmakedefine HAVE_STDINT_H #ifdef HAVE_STDINT_H #include #endif #include #include #include #include #include #include #if !defined(WIN32) #include #include #include #include #include #define HAVE_DLOPEN #define HAVE_GETOPT #include #define HAVE_GETRLIMIT #endif #cmakedefine HAVE_SSIZE_T #cmakedefine HAVE_STRNDUP #cmakedefine HAVE_MEMMEM /* printf support for size_t and uint64_t */ #if defined(WIN32) #define PRINTF_SIZE_T "%Iu" #define PRINTF_UINT64_T "%I64u" #else #define PRINTF_SIZE_T "%zu" #define PRINTF_UINT64_T ("%" PRIu64) #endif #ifdef SSL_SUPPORT #ifdef SSL_USE_OPENSSL #include #include #include #include #endif /* SSL_USE_OPENSSL */ #ifdef SSL_USE_GNUTLS #include #endif /* SSL_USE_GNUTLS */ #endif #include "version.h" #define uhub_assert assert #ifdef __linux__ #define POSIX_THREAD_SUPPORT #define USE_EPOLL #include #endif #ifdef BSD_LIKE #define POSIX_THREAD_SUPPORT /* #define USE_KQUEUE #include */ #endif #ifdef __GNU__ #define POSIX_THREAD_SUPPORT #endif #define USE_SELECT #ifndef WINSOCK #include #endif #ifdef HAVE_GETOPT #include #endif /* * Detect operating system info. * See: http://predef.sourceforge.net/ */ #if defined(__linux__) #define OPSYS "Linux" #endif #if defined(_WIN32) || defined(__MINGW32__) || defined(_WIN64) || defined(__WIN32__) || defined(__WINDOWS__) #define OPSYS "Windows" #endif #if defined(__APPLE__) && defined(__MACH__) #define OPSYS "MacOSX" #endif #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #define OPSYS "FreeBSD" #endif #if defined(__OpenBSD__) #define OPSYS "OpenBSD" #endif #if defined(__NetBSD__) #define OPSYS "NetBSD" #endif #if defined(__sun__) #if defined(__SVR4) || defined(__svr4__) #define OPSYS "Solaris" #else #define OPSYS "SunOS" #endif #endif #if defined(__HAIKU__) #define OPSYS "Haiku" #endif #if defined(__GNU__) #define OPSYS "Hurd" #endif /* Detect CPUs */ #if defined(__alpha__) || defined(__alpha) #define CPUINFO "Alpha" #endif #if defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || defined(__amd64) || defined(_M_X64) #define CPUINFO "AMD64" #endif #if defined(__arm__) || defined(__thumb__) || defined(_ARM) || defined(__TARGET_ARCH_ARM) #define CPUINFO "ARM" #endif #if defined(__i386__) || defined(__i386) || defined(i386) || defined(_M_IX86) || defined(__X86__) || defined(_X86_) || defined(__I86__) || defined(__INTEL__) || defined(__THW_INTEL__) #define CPUINFO "i386" #endif #if defined(__ia64__) || defined(_IA64) || defined(__IA64__) || defined(__ia64) || defined(_M_IA64) #define CPUINFO "IA64" #endif #if defined(__hppa__) || defined(__hppa) #define CPUINFO "PARISC" #endif #if defined(__m68k__) || defined(M68000) #define CPUINFO "M68K" #endif #if defined(__mips__) || defined(mips) || defined(__mips) || defined(__MIPS__) #define CPUINFO "MIPS" #endif #if defined(__POWERPC__) || defined(__ppc__) || defined(_ARCH_PPC) || defined(__powerpc) || defined(__powerpc__) #define CPUINFO "PowerPC" #endif #if defined(__sparc__) || defined(__sparc) #define CPUINFO "SPARC" #endif #if defined(__sh__) #define CPUINFO "SuperH" #endif #if defined(__s390__) || defined(__s390x__) #define CPUINFO "s390" #endif /* Misc */ #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 #ifndef MIN #define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif #ifndef MAX #define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif #ifndef HAVE_SSIZE_T typedef int ssize_t; #define HAVE_SSIZE_T #endif #ifdef _MSC_VER typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; #endif #ifdef _MSC_VER #define strdup _strdup #define snprintf _snprintf #define strcasecmp _stricmp #define strncasecmp _strnicmp #define atoll _atoi64 #include #define open _open #define close _close #define read _read #define write _write #define NEED_GETOPT #endif #ifdef POSIX_THREAD_SUPPORT #include #endif #if defined(__CYGWIN__) || defined(__MINGW32__) || defined(_MSC_VER) #define PLUGIN_API __declspec(dllexport) #else #define PLUGIN_API #endif #endif /* HAVE_UHUB_SYSTEM_H */ modelrockettier-uhub-a8ee6e7/src/tools/000077500000000000000000000000001324501300100202715ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/src/tools/adcclient.c000066400000000000000000000443521324501300100223730ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "tools/adcclient.h" #define ADC_HANDSHAKE "HSUP ADBASE ADTIGR ADPING\n" #define ADC_CID_SIZE 39 #define BIG_BUFSIZE 32768 #define TIGERSIZE 24 #define MAX_RECV_BUFFER 65536 // #define ADCC_DEBUG // #define ADC_CLIENT_DEBUG_PROTO struct ADC_client_global { size_t references; #ifdef SSL_SUPPORT struct ssl_context_handle* ctx; #endif }; static struct ADC_client_global* g_adc_client = NULL; enum ADC_client_state { ps_none, /* Not connected */ ps_conn, /* Connecting... */ ps_conn_ssl, /* SSL handshake */ ps_protocol, /* Have sent HSUP */ ps_identify, /* Have sent BINF */ ps_verify, /* Have sent HPAS */ ps_normal, /* Are fully logged in */ }; enum ADC_client_flags { cflag_none = 0, cflag_ssl = 1, cflag_choke = 2, cflag_pipe = 4, }; struct ADC_client_address { enum Protocol { ADC, ADCS } protocol; char* hostname; uint16_t port; }; struct ADC_client { sid_t sid; enum ADC_client_state state; struct adc_message* info; struct ioq_recv* recv_queue; struct ioq_send* send_queue; 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_storage addr; struct net_connect_handle* connect_job; struct ADC_client_address address; char* nick; char* desc; int flags; void* ptr; }; 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); #ifdef SSL_SUPPORT static void ADC_client_on_connected_ssl(struct ADC_client* client); #endif 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 int ADC_client_on_recv_line(struct ADC_client* client, const char* line, size_t length); static int ADC_client_send_queue(struct ADC_client* client); 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); } #ifdef ADCC_DEBUG #define ADC_TRACE fprintf(stderr, "TRACE: %s\n", __PRETTY_FUNCTION__) #else #define ADC_TRACE do { } while(0) #endif #ifdef ADCC_DEBUG static const char* ADC_client_state_string[] = { "ps_none", "ps_conn", "ps_conn_ssl", "ps_protocol", "ps_identify", "ps_verify", "ps_normal", 0 }; #endif static void ADC_client_set_state(struct ADC_client* client, enum ADC_client_state state) { ADC_TRACE; if (client->state != state) { #ifdef ADCC_DEBUG ADC_client_debug(client, "Set state %s (was %s)", ADC_client_state_string[(int) state], ADC_client_state_string[(int) client->state]); #endif client->state = state; } } static void adc_cid_pid(struct ADC_client* client) { ADC_TRACE; 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) { ADC_TRACE; struct ADC_client* client = (struct ADC_client*) net_con_get_ptr(con); switch (client->state) { case ps_conn: if (events == NET_EVENT_TIMEOUT) { client->callback(client, ADC_CLIENT_DISCONNECTED, 0); return; } break; #ifdef SSL_SUPPORT case ps_conn_ssl: if (events == NET_EVENT_TIMEOUT) { client->callback(client, ADC_CLIENT_DISCONNECTED, 0); return; } if (events == NET_EVENT_ERROR) { ADC_client_on_disconnected(client); client->callback(client, ADC_CLIENT_DISCONNECTED, 0); return; } else { ADC_client_on_connected_ssl(client); } break; #endif default: if (events & NET_EVENT_READ) { if (ADC_client_recv(client) == -1) { ADC_client_on_disconnected(client); } } if (events & NET_EVENT_WRITE) { ADC_client_send_queue(client); } } } #define UNESCAPE_ARG(TMP, TARGET) \ if (TMP) \ TARGET = adc_msg_unescape(TMP); \ else \ TARGET = NULL; \ hub_free(TMP); #define UNESCAPE_ARG_X(TMP, TARGET, SIZE) \ if (TMP) \ adc_msg_unescape_to_target(TMP, TARGET, SIZE); \ else \ TARGET[0] = '\0'; \ 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_NAMED_ARG_X(MSG, NAME, TARGET, SIZE) \ do { \ char* tmp = adc_msg_get_named_argument(MSG, NAME); \ UNESCAPE_ARG_X(tmp, TARGET, SIZE); \ } 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 int ADC_client_on_recv_line(struct ADC_client* client, const char* line, size_t length) { struct ADC_chat_message chat; struct ADC_client_callback_data data; ADC_TRACE; #ifdef ADC_CLIENT_DEBUG_PROTO ADC_client_debug(client, "- LINE: '%s'", line); #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 -1; } if (length < 4) { ADC_client_debug(client, "Unexpected response from hub: '%s'", line); return -1; } 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: { chat.from_sid = msg->source; chat.to_sid = msg->target; data.chat = &chat; EXTRACT_POS_ARG(msg, 0, chat.message); chat.flags = 0; if (adc_msg_has_named_argument(msg, ADC_MSG_FLAG_ACTION)) chat.flags |= chat_flags_action; if (adc_msg_has_named_argument(msg, ADC_MSG_FLAG_PRIVATE)) chat.flags |= chat_flags_private; 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; user.sid = msg->source; EXTRACT_NAMED_ARG_X(msg, "NI", user.name, sizeof(user.name)); EXTRACT_NAMED_ARG_X(msg, "DE", user.description, sizeof(user.description)); EXTRACT_NAMED_ARG_X(msg, "VE", user.version, sizeof(user.version)); EXTRACT_NAMED_ARG_X(msg, "ID", user.cid, sizeof(user.cid)); EXTRACT_NAMED_ARG_X(msg, "I4", user.address, sizeof(user.address)); struct ADC_client_callback_data data; data.user = &user; client->callback(client, ADC_CLIENT_USER_JOIN, &data); } } } break; case ADC_CMD_IQUI: { struct ADC_client_quit_reason reason; memset(&reason, 0, sizeof(reason)); reason.sid = string_to_sid(&line[5]); if (adc_msg_has_named_argument(msg, ADC_QUI_FLAG_DISCONNECT)) reason.flags |= 1; data.quit = &reason; client->callback(client, ADC_CLIENT_USER_QUIT, &data); break; } 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); return 0; } static ssize_t ADC_client_recv(struct ADC_client* client) { static char buf[BIG_BUFSIZE]; struct ioq_recv* q = client->recv_queue; size_t buf_size = ioq_recv_get(q, buf, BIG_BUFSIZE); ssize_t size; ADC_TRACE; if (client->flags & cflag_choke) buf_size = 0; size = net_con_recv(client->con, buf + buf_size, BIG_BUFSIZE - buf_size); if (size > 0) buf_size += size; if (size < 0) return -1; 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+1; pos[0] = '\0'; #ifdef DEBUG_SENDQ LOG_DUMP("PROC: \"%s\" (%d)\n", start, (int) (pos - start)); #endif if (client->flags & cflag_choke) client->flags &= ~cflag_choke; else { if (((pos - start) > 0) && MAX_RECV_BUFFER > (pos - start)) { if (ADC_client_on_recv_line(client, start, pos - start) == -1) return -1; } } pos[0] = '\n'; /* FIXME: not needed */ pos ++; remaining -= (pos - start); start = pos; } if (lastPos || remaining) { if (remaining < (size_t) MAX_RECV_BUFFER) { ioq_recv_set(q, lastPos ? lastPos : buf, remaining); } else { ioq_recv_set(q, 0, 0); client->flags |= cflag_choke; LOG_WARN("Received message past MAX_RECV_BUFFER (%d), dropping message.", MAX_RECV_BUFFER); } } else { ioq_recv_set(q, 0, 0); } } return 0; } static int ADC_client_send_queue(struct ADC_client* client) { int ret = 0; while (ioq_send_get_bytes(client->send_queue)) { ret = ioq_send_send(client->send_queue, client->con); if (ret <= 0) break; } if (ret < 0) return quit_socket_error; if (ioq_send_get_bytes(client->send_queue)) { net_con_update(client->con, NET_EVENT_READ | NET_EVENT_WRITE); } else { net_con_update(client->con, NET_EVENT_READ); } return 0; } void ADC_client_send(struct ADC_client* client, struct adc_message* msg) { ADC_TRACE; uhub_assert(client->con != NULL); uhub_assert(msg->cache && *msg->cache); if (ioq_send_is_empty(client->send_queue) && !(client->flags & cflag_pipe)) { /* Perform oportunistic write */ ioq_send_add(client->send_queue, msg); ADC_client_send_queue(client); } else { ioq_send_add(client->send_queue, msg); if (!(client->flags & cflag_pipe)) net_con_update(client->con, NET_EVENT_READ | NET_EVENT_WRITE); } } void ADC_client_send_info(struct ADC_client* client) { ADC_TRACE; client->info = adc_msg_construct_source(ADC_CMD_BINF, client->sid, 96); 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, PRODUCT); adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_USER_AGENT_VERSION, VERSION); adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_UPLOAD_SLOTS, 0); adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_SHARED_SIZE, 0); adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_SHARED_FILES, 0); adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_COUNT_HUB_NORMAL, 1); adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_COUNT_HUB_REGISTER, 0); adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_COUNT_HUB_OPERATOR, 0); adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_DOWNLOAD_SPEED, 5 * 1024 * 1024); adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_UPLOAD_SPEED, 10 * 1024 * 1024); adc_cid_pid(client); ADC_client_send(client, client->info); } struct ADC_client* ADC_client_create(const char* nickname, const char* description, void* ptr) { ADC_TRACE; struct ADC_client* client = (struct ADC_client*) hub_malloc_zero(sizeof(struct ADC_client)); ADC_client_set_state(client, ps_none); client->nick = hub_strdup(nickname); client->desc = hub_strdup(description); client->send_queue = ioq_send_create(); client->recv_queue = ioq_recv_create(); client->ptr = ptr; if (!g_adc_client) { g_adc_client = (struct ADC_client_global*) hub_malloc_zero(sizeof(struct ADC_client_global)); #ifdef SSL_SUPPORT g_adc_client->ctx = net_ssl_context_create("1.2", "HIGH"); #endif } g_adc_client->references++; return client; } void ADC_client_destroy(struct ADC_client* client) { ADC_TRACE; ADC_client_disconnect(client); ioq_send_destroy(client->send_queue); ioq_recv_destroy(client->recv_queue); hub_free(client->timer); adc_msg_free(client->info); hub_free(client->nick); hub_free(client->desc); hub_free(client->address.hostname); hub_free(client); if (g_adc_client && g_adc_client->references > 0) { g_adc_client->references--; if (!g_adc_client->references) { #ifdef SSL_SUPPORT net_ssl_context_destroy(g_adc_client->ctx); g_adc_client->ctx = NULL; #endif hub_free(g_adc_client); g_adc_client = NULL; } } } static void connect_callback(struct net_connect_handle* handle, enum net_connect_status status, struct net_connection* con, void* ptr) { struct ADC_client* client = (struct ADC_client*) ptr; client->connect_job = NULL; switch (status) { case net_connect_status_ok: client->con = con; net_con_reinitialize(client->con, event_callback, client, 0); ADC_client_on_connected(client); break; case net_connect_status_host_not_found: case net_connect_status_no_address: case net_connect_status_dns_error: case net_connect_status_refused: case net_connect_status_unreachable: case net_connect_status_timeout: case net_connect_status_socket_error: ADC_client_disconnect(client); break; } } int ADC_client_connect(struct ADC_client* client, const char* address) { ADC_TRACE; if (client->state == ps_none) { if (!ADC_client_parse_address(client, address)) return 0; } ADC_client_set_state(client, ps_conn); client->connect_job = net_con_connect(client->address.hostname, client->address.port, connect_callback, client); if (!client->connect_job) { ADC_client_on_disconnected(client); return 0; } return 1; } static void ADC_client_send_handshake(struct ADC_client* client) { ADC_TRACE; struct adc_message* handshake = adc_msg_create(ADC_HANDSHAKE); client->callback(client, ADC_CLIENT_CONNECTED, 0); net_con_update(client->con, NET_EVENT_READ); ADC_client_send(client, handshake); ADC_client_set_state(client, ps_protocol); adc_msg_free(handshake); } static void ADC_client_on_connected(struct ADC_client* client) { ADC_TRACE; #ifdef SSL_SUPPORT if (client->flags & cflag_ssl) { net_con_update(client->con, NET_EVENT_READ | NET_EVENT_WRITE); client->callback(client, ADC_CLIENT_SSL_HANDSHAKE, 0); ADC_client_set_state(client, ps_conn_ssl); net_con_ssl_handshake(client->con, net_con_ssl_mode_client, g_adc_client->ctx); } else #endif ADC_client_send_handshake(client); } #ifdef SSL_SUPPORT static void ADC_client_on_connected_ssl(struct ADC_client* client) { ADC_TRACE; struct ADC_client_callback_data data; struct ADC_client_tls_info tls_info; data.tls_info = &tls_info; tls_info.version = net_ssl_get_tls_version(client->con); tls_info.cipher = net_ssl_get_tls_cipher(client->con); client->callback(client, ADC_CLIENT_SSL_OK, &data); ADC_client_send_handshake(client); } #endif static void ADC_client_on_disconnected(struct ADC_client* client) { ADC_TRACE; 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_TRACE; ADC_client_set_state(client, ps_normal); client->callback(client, ADC_CLIENT_LOGGED_IN, 0); } void ADC_client_disconnect(struct ADC_client* client) { ADC_TRACE; 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) { ADC_TRACE; const char* hub_address = arg; char* split; int ssl = 0; if (!arg) return 0; /* Minimum length of a valid address */ if (strlen(arg) < 9) return 0; /* Check for ADC or ADCS */ if (!strncmp(arg, "adc://", 6)) { client->flags &= ~cflag_ssl; client->address.protocol = ADC; } else if (!strncmp(arg, "adcs://", 7)) { client->flags |= cflag_ssl; ssl = 1; client->address.protocol = ADCS; } else return 0; /* Split hostname and port (if possible) */ hub_address = arg + 6 + ssl; split = strrchr(hub_address, ':'); if (split == 0 || strlen(split) < 2 || strlen(split) > 6) return 0; /* Ensure port number is valid */ client->address.port = strtol(split+1, NULL, 10); if (client->address.port <= 0 || client->address.port > 65535) return 0; client->address.hostname = strndup(hub_address, &split[0] - &hub_address[0]); return 1; } void ADC_client_set_callback(struct ADC_client* client, adc_client_cb cb) { ADC_TRACE; client->callback = cb; } sid_t ADC_client_get_sid(const struct ADC_client* client) { return client->sid; } const char* ADC_client_get_nick(const struct ADC_client* client) { return client->nick; } const char* ADC_client_get_description(const struct ADC_client* client) { return client->desc; } void* ADC_client_get_ptr(const struct ADC_client* client) { return client->ptr; } modelrockettier-uhub-a8ee6e7/src/tools/adcclient.h000066400000000000000000000065051324501300100223760ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_ADC_CLIENT_H #define HAVE_UHUB_ADC_CLIENT_H #include "uhub.h" #define ADC_BUFSIZE 16384 struct ADC_client; enum ADC_client_callback_type { ADC_CLIENT_NAME_LOOKUP = 1000, ADC_CLIENT_CONNECTING = 1001, ADC_CLIENT_CONNECTED = 1002, ADC_CLIENT_DISCONNECTED = 1003, ADC_CLIENT_SSL_HANDSHAKE = 1101, ADC_CLIENT_SSL_OK = 1102, 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; }; enum ADC_chat_message_flags { chat_flags_none = 0, chat_flags_action = 1, chat_flags_private = 2 }; struct ADC_chat_message { sid_t from_sid; sid_t to_sid; char* message; int flags; }; #define MAX_DESC_LEN 128 struct ADC_user { sid_t sid; char cid[MAX_CID_LEN+1]; char name[MAX_NICK_LEN+1]; char description[MAX_DESC_LEN+1]; char address[INET6_ADDRSTRLEN+1]; char version[MAX_UA_LEN+1]; }; struct ADC_client_quit_reason { sid_t sid; sid_t initator; // 0 = default/hub. char message[128]; // optional int flags; }; struct ADC_client_tls_info { const char* cipher; const char* version; }; struct ADC_client_callback_data { union { struct ADC_hub_info* hubinfo; struct ADC_chat_message* chat; struct ADC_user* user; struct ADC_client_quit_reason* quit; struct ADC_client_tls_info* tls_info; }; }; sid_t ADC_client_get_sid(const struct ADC_client* client); const char* ADC_client_get_nick(const struct ADC_client* client); const char* ADC_client_get_description(const struct ADC_client* client); void* ADC_client_get_ptr(const struct ADC_client* client); typedef int (*adc_client_cb)(struct ADC_client*, enum ADC_client_callback_type, struct ADC_client_callback_data* data); struct ADC_client* ADC_client_create(const char* nickname, const char* description, void* ptr); 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, struct adc_message* msg); #endif /* HAVE_UHUB_ADC_CLIENT_H */ modelrockettier-uhub-a8ee6e7/src/tools/adcrush.c000066400000000000000000000330401324501300100220660ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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 STATS_INTERVAL 3 #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 cfg_netstats_interval = STATS_INTERVAL; static int running = 1; static int logged_in = 0; static int blank = 0; static struct net_statistics* stats_intermediate; static struct net_statistics* stats_total; static int handle(struct ADC_client* client, enum ADC_client_callback_type type, struct ADC_client_callback_data* data); static void timer_callback(struct timeout_evt* t); static void do_blank(int n) { n++; while (n > 0) { fprintf(stdout, " "); n--; } } struct AdcFuzzUser { struct ADC_client* client; struct timeout_evt* timer; int logged_in; }; #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) { int num = fprintf(stdout, "* [%p] %s", client, logmsg); do_blank(blank - num); fprintf(stdout, "\n"); } } 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 size_t get_next_timeout_evt() { switch (cfg_level) { case 0: return get_wait_rand(120); case 1: return get_wait_rand(60); case 2: return get_wait_rand(15); case 3: return get_wait_rand(5); } return 0; } 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) { size_t r = get_wait_rand(MAX_CHAT_MSGS-1); char* msg = adc_msg_escape(chat_messages[r]); struct adc_message* cmd = NULL; if (priv) cmd = adc_msg_construct_source_dest(ADC_CMD_DMSG, ADC_client_get_sid(client), ADC_client_get_sid(client), strlen(msg)); else cmd = adc_msg_construct_source(ADC_CMD_BMSG, ADC_client_get_sid(client), strlen(msg)); hub_free(msg); ADC_client_send(client, cmd); } static void perf_search(struct ADC_client* client) { size_t r = get_wait_rand(MAX_SEARCH_MSGS-1); size_t pst = get_wait_rand(100); struct adc_message* cmd = NULL; if (pst > 80) { cmd = adc_msg_construct_source(ADC_CMD_FSCH, ADC_client_get_sid(client), strlen(search_messages[r]) + 6); adc_msg_add_argument(cmd, "+TCP4"); } else { cmd = adc_msg_construct_source(ADC_CMD_BSCH, ADC_client_get_sid(client), strlen(search_messages[r]) + 6); adc_msg_add_argument(cmd, "+TCP4"); } ADC_client_send(client, cmd); } static void perf_result(struct ADC_client* client, sid_t target, const char* what, const char* token) { char tmp[256]; struct adc_message* cmd = adc_msg_construct_source_dest(ADC_CMD_DRES, ADC_client_get_sid(client), target, strlen(what) + strlen(token) + 64); snprintf(tmp, sizeof(tmp), "FNtest/%s.dat", what); adc_msg_add_argument(cmd, tmp); adc_msg_add_argument(cmd, "SL0"); adc_msg_add_argument(cmd, "SI1209818412"); adc_msg_add_argument(cmd, "TR5T6YJYKO3WECS52BKWVSOP5VUG4IKNSZBZ5YHBA"); snprintf(tmp, sizeof(tmp), "TO%s", token); adc_msg_add_argument(cmd, tmp); ADC_client_send(client, cmd); } static void perf_ctm(struct ADC_client* client) { char buf[1024] = { 0, }; struct adc_message* cmd = adc_msg_construct_source_dest(ADC_CMD_DCTM, ADC_client_get_sid(client), ADC_client_get_sid(client), 32); adc_msg_add_argument(cmd, "ADC/1.0"); adc_msg_add_argument(cmd, "TOKEN123456"); adc_msg_add_argument(cmd, sid_to_string(ADC_client_get_sid(client))); ADC_client_send(client, cmd); } static void perf_update(struct ADC_client* client) { char buf[16] = { 0, }; int n = (int) get_wait_rand(10)+1; struct adc_message* cmd = adc_msg_construct_source(ADC_CMD_BINF, ADC_client_get_sid(client), 32); snprintf(buf, sizeof(buf), "HN%d", n); adc_msg_add_argument(cmd, buf); ADC_client_send(client, cmd); } static void client_disconnect(struct AdcFuzzUser* c) { ADC_client_destroy(c->client); c->client = 0; timeout_queue_remove(net_backend_get_timeout_queue(), c->timer); hub_free(c->timer); c->timer = 0; c->logged_in = 0; } static void client_connect(struct AdcFuzzUser* c, const char* nick, const char* description) { size_t timeout = get_next_timeout_evt(); struct ADC_client* client = ADC_client_create(nick, description, c); c->client = client; c->timer = (struct timeout_evt*) hub_malloc(sizeof(struct timeout_evt)); timeout_evt_initialize(c->timer, timer_callback, c); timeout_queue_insert(net_backend_get_timeout_queue(), c->timer, timeout); bot_output(client, LVL_VERBOSE, "Initial timeout: %d seconds", timeout); c->logged_in = 0; ADC_client_set_callback(client, handle); ADC_client_connect(client, cfg_uri); } static void perf_normal_action(struct ADC_client* client) { struct AdcFuzzUser* user = (struct AdcFuzzUser*) ADC_client_get_ptr(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))) { struct ADC_client* c; char* nick = hub_strdup(ADC_client_get_nick(client)); char* desc = hub_strdup(ADC_client_get_description(client)); bot_output(client, LVL_VERBOSE, "timeout -> disconnect"); client_disconnect(user); client_connect(user, nick, desc); hub_free(nick); hub_free(desc); } break; case 1: if (cfg_chat) { bot_output(client, LVL_VERBOSE, "timeout -> chat"); if (user->logged_in) perf_chat(client, 0); } break; case 2: bot_output(client, LVL_VERBOSE, "timeout -> search"); if (user->logged_in) perf_search(client); break; case 3: bot_output(client, LVL_VERBOSE, "timeout -> update"); if (user->logged_in) perf_update(client); break; case 4: bot_output(client, LVL_VERBOSE, "timeout -> privmsg"); if (user->logged_in) perf_chat(client, 1); break; case 5: bot_output(client, LVL_VERBOSE, "timeout -> ctm/rcm"); if (user->logged_in) perf_ctm(client); break; } } static int handle(struct ADC_client* client, enum ADC_client_callback_type type, struct ADC_client_callback_data* data) { struct AdcFuzzUser* user = (struct AdcFuzzUser*) ADC_client_get_ptr(client); 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."); break; case ADC_CLIENT_LOGGED_IN: bot_output(client, LVL_DEBUG, "*** Logged in."); user->logged_in = 1; break; case ADC_CLIENT_LOGIN_ERROR: bot_output(client, LVL_DEBUG, "*** Login error"); break; case ADC_CLIENT_SSL_HANDSHAKE: case ADC_CLIENT_SSL_OK: 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: break; case ADC_CLIENT_USER_QUIT: break; case ADC_CLIENT_SEARCH_REQ: break; case ADC_CLIENT_HUB_INFO: break; default: bot_output(client, LVL_DEBUG, "Not handled event=%d\n", (int) type); return 0; break; } return 1; } static void timer_callback(struct timeout_evt* t) { size_t timeout = get_next_timeout_evt(); struct AdcFuzzUser* client = (struct AdcFuzzUser*) t->ptr; if (client->logged_in) { perf_normal_action(client->client); bot_output(client->client, LVL_VERBOSE, "Next timeout: %d seconds", (int) timeout); } timeout_queue_reschedule(net_backend_get_timeout_queue(), client->timer, timeout); } static struct AdcFuzzUser client[ADC_MAX_CLIENTS]; void p_status() { static char rxbuf[64] = { "0 B" }; static char txbuf[64] = { "0 B" }; int logged_in = 0; size_t n; static size_t rx = 0, tx = 0; for (n = 0; n < cfg_clients; n++) { if (client[n].logged_in) logged_in++; } if (difftime(time(NULL), stats_intermediate->timestamp) >= cfg_netstats_interval) { net_stats_get(&stats_intermediate, &stats_total); rx = stats_intermediate->rx / cfg_netstats_interval; tx = stats_intermediate->tx / cfg_netstats_interval; net_stats_reset(); format_size(rx, rxbuf, sizeof(rxbuf)); format_size(tx, txbuf, sizeof(txbuf)); } n = blank; blank = printf("Connected bots: %d/%d, network: rx=%s/s, tx=%s/s", logged_in, cfg_clients, rxbuf, txbuf); if (n > blank) do_blank(n-blank); printf("\r"); } void runloop(size_t clients) { size_t n = 0; blank = 0; for (n = 0; n < clients; n++) { char nick[20]; snprintf(nick, 20, "adcrush_%d", (int) n); client_connect(&client[n], nick, "stresstester"); } while (running && net_backend_process()) { p_status(); } for (n = 0; n < clients; n++) { struct AdcFuzzUser* c = &client[n]; client_disconnect(c); } } static void print_version() { printf(ADCRUSH "\n"); printf("Copyright (C) 2008-2012, Jan Vidar Krey\n"); printf("\n"); } static void print_usage(const char* program) { print_version(); printf("Usage: %s [adc[s]://:] [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 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(" -i Average network statistics for given interval (default: 3)\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], "-i") && (++opt) < argc) { cfg_netstats_interval = MAX(uhub_atoi(argv[opt]), 1); } 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]); } } int main(int argc, char** argv) { parse_command_line(argc, argv); net_initialize(); net_stats_get(&stats_intermediate, &stats_total); hub_log_initialize(NULL, 0); hub_set_log_verbosity(1000); setvbuf(stdout, NULL, _IONBF, 0); runloop(cfg_clients); net_destroy(); return 0; } modelrockettier-uhub-a8ee6e7/src/tools/admin.c000066400000000000000000000126111324501300100215260ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "adcclient.h" static struct ADC_user g_usermap[SID_MAX]; static void user_add(const struct ADC_user* user) { printf(" >> JOIN: %s (%s)\n", user->name, user->address); memcpy(&g_usermap[user->sid], user, sizeof(struct ADC_user)); } static struct ADC_user* user_get(sid_t sid) { struct ADC_user* user = &g_usermap[sid]; uhub_assert(user->sid != 0); return user; } static void user_remove(const struct ADC_client_quit_reason* quit) { struct ADC_user* user = user_get(quit->sid); printf(" << QUIT: %s (%s)\n", user->name, quit->message); memset(&g_usermap[quit->sid], 0, sizeof(struct ADC_user)); } static void on_message(struct ADC_chat_message* chat) { struct ADC_user* user; const char* pm = (chat->flags & chat_flags_private) ? "PM" : " "; const char* brack1 = (chat->flags & chat_flags_action) ? "*" : "<"; const char* brack2 = (chat->flags & chat_flags_action) ? "" : ">"; struct linked_list* lines; int ret; char* line; if (!chat->from_sid) { printf("HUB "); } else { user = user_get(chat->from_sid); printf(" %s %s%s%s ", pm, brack1, user->name, brack2); } lines = list_create(); ret = split_string(chat->message, "\n", lines, 1); ret = 0; LIST_FOREACH(char*, line, lines, { if (ret > 0) printf(" "); printf("%s\n", line); ret++; }); list_clear(lines, &hub_free); list_destroy(lines); } static void status(const char* msg) { printf("*** %s\n", msg); } static int handle(struct ADC_client* client, enum ADC_client_callback_type type, struct ADC_client_callback_data* data) { switch (type) { case ADC_CLIENT_NAME_LOOKUP: status("Looking up hostname..."); break; case ADC_CLIENT_CONNECTING: status("Connecting..."); break; case ADC_CLIENT_CONNECTED: status("Connected."); break; case ADC_CLIENT_DISCONNECTED: status("Disconnected."); break; case ADC_CLIENT_SSL_HANDSHAKE: status("SSL handshake."); break; case ADC_CLIENT_SSL_OK: printf("*** SSL connected (%s/%s).\n", data->tls_info->version, data->tls_info->cipher); break; case ADC_CLIENT_LOGGING_IN: status("Logging in..."); break; case ADC_CLIENT_PASSWORD_REQ: status("Requesting password."); break; case ADC_CLIENT_LOGGED_IN: status("Logged in."); break; case ADC_CLIENT_LOGIN_ERROR: status("Login error"); break; case ADC_CLIENT_MESSAGE: on_message(data->chat); break; case ADC_CLIENT_USER_JOIN: user_add(data->user); break; case ADC_CLIENT_USER_QUIT: user_remove(data->quit); 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; } static int running = 1; #if !defined(WIN32) static struct uhub_notify_handle* notify_handle; void adm_handle_signal(int sig) { switch (sig) { case SIGINT: LOG_INFO("Interrupted. Shutting down..."); running = 0; break; case SIGTERM: LOG_INFO("Terminated. Shutting down..."); running = 0; break; case SIGPIPE: break; case SIGHUP: break; default: LOG_TRACE("hub_handle_signal(): caught unknown signal: %d", signal); running = 0; break; } } static int signals[] = { SIGINT, /* Interrupt the application */ SIGTERM, /* Terminate the application */ SIGPIPE, /* prevent sigpipe from kills the application */ SIGHUP, /* reload configuration */ 0 }; void adm_setup_signal_handlers() { sigset_t sig_set; struct sigaction act; int i; sigemptyset(&sig_set); act.sa_mask = sig_set; act.sa_flags = SA_ONSTACK | SA_RESTART; act.sa_handler = adm_handle_signal; for (i = 0; signals[i]; i++) { if (sigaction(signals[i], &act, 0) != 0) { LOG_ERROR("Error setting signal handler %d", signals[i]); } } } void adm_setup_control_pipe() { notify_handle = net_notify_create(NULL, NULL); } void adm_shutdown_control_pipe() { net_notify_destroy(notify_handle); notify_handle = NULL; } void adm_shutdown_signal_handlers() { } #endif /* !WIN32 */ int main(int argc, char** argv) { if (argc < 2) { printf("Usage: %s adc[s]://host:port\n", argv[0]); return 1; } hub_set_log_verbosity(5); adm_setup_signal_handlers(); struct ADC_client* client; net_initialize(); adm_setup_control_pipe(); memset(g_usermap, 0, sizeof(g_usermap)); client = ADC_client_create("uhub-admin", "stresstester", NULL); ADC_client_set_callback(client, handle); ADC_client_connect(client, argv[1]); while (running && net_backend_process()) { } adm_shutdown_control_pipe(); ADC_client_destroy(client); net_destroy(); adm_shutdown_signal_handlers(); return 0; } modelrockettier-uhub-a8ee6e7/src/tools/fuzzer.h000066400000000000000000000045621324501300100217760ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ 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 */ }; modelrockettier-uhub-a8ee6e7/src/tools/uhub-passwd.c000066400000000000000000000205251324501300100227030ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" #include "util/misc.h" #include // #define DEBUG_SQL static sqlite3* db = NULL; static const char* command = NULL; static const char* filename = NULL; static const char* binary = NULL; typedef int (*command_func_t)(size_t, const char**); static int create(size_t argc, const char** argv); static int list(size_t argc, const char** argv); static int pass(size_t argc, const char** argv); static int add(size_t argc, const char** argv); static int del(size_t argc, const char** argv); static int mod(size_t argc, const char** argv); static struct commands { command_func_t handle; const char* command; const char* usage; } COMMANDS[6] = { { &create, "create", "" }, { &list, "list", "" }, { &add, "add", "username password [credentials = user]" }, { &del, "del", "username" }, { &mod, "mod", "username credentials" }, { &pass, "pass", "username password" }, }; static void print_usage(const char* str) { fprintf(stderr, "Usage: %s filename %s %s\n", binary, command, str); exit(1); } /** * Escape an SQL statement and return a pointer to the string. * NOTE: The returned value needs to be free'd. * * @return an escaped string. */ static char* sql_escape_string(const char* str) { size_t i, n, size; char* buf; for (n = 0, size = strlen(str); n < strlen(str); n++) if (str[n] == '\'') size++; buf = malloc(size+1); for (n = 0, i = 0; n < strlen(str); n++) { if (str[n] == '\'') buf[i++] = '\''; buf[i++] = str[n]; } buf[i++] = '\0'; return buf; } /** * Validate credentials. */ static const char* validate_cred(const char* cred_str) { if (!strcmp(cred_str, "admin")) return "admin"; if (!strcmp(cred_str, "super")) return "super"; if (!strcmp(cred_str, "op")) return "op"; if (!strcmp(cred_str, "user")) return "user"; if (!strcmp(cred_str, "bot")) return "bot"; if (!strcmp(cred_str, "ubot")) return "ubot"; if (!strcmp(cred_str, "opbot")) return "opbot"; if (!strcmp(cred_str, "opubot")) return "opubot"; fprintf(stderr, "Invalid user credentials. Must be one of: 'bot', 'ubot', 'opbot', 'opubot', 'admin', 'super', 'op' or 'user'\n"); exit(1); } static const char* validate_username(const char* username) { const char* tmp; // verify length if (strlen(username) > MAX_NICK_LEN) { fprintf(stderr, "User name is too long.\n"); exit(1); } /* Nick must not start with a space */ if (is_white_space(username[0])) { fprintf(stderr, "User name cannot start with white space.\n"); exit(1); } /* Check for ASCII values below 32 */ for (tmp = username; *tmp; tmp++) if ((*tmp < 32) && (*tmp > 0)) { fprintf(stderr, "User name contains illegal characters.\n"); exit(1); } if (!is_valid_utf8(username)) { fprintf(stderr, "User name must be utf-8 encoded.\n"); exit(1); } return username; } static const char* validate_password(const char* password) { // verify length if (strlen(password) > MAX_PASS_LEN) { fprintf(stderr, "Password is too long.\n"); exit(1); } if (!is_valid_utf8(password)) { fprintf(stderr, "Password must be utf-8 encoded.\n"); exit(1); } return password; } static void open_database() { int res = sqlite3_open(filename, &db); if (res) { fprintf(stderr, "Unable to open database: %s (result=%d)\n", filename, res); exit(1); } } static int sql_callback(void* ptr, int argc, char **argv, char **colName) { return 0; } static int sql_execute(const char* sql, ...) { va_list args; char query[1024]; char* errMsg; int rc; va_start(args, sql); vsnprintf(query, sizeof(query), sql, args); #ifdef DEBUG_SQL printf("SQL: %s\n", query); #endif open_database(); rc = sqlite3_exec(db, query, sql_callback, NULL, &errMsg); if (rc != SQLITE_OK) { fprintf(stderr, "ERROR: %s\n", errMsg); sqlite3_free(errMsg); } rc = sqlite3_changes(db); sqlite3_close(db); return rc; } static int create(size_t argc, const char** argv) { const char* sql = "CREATE TABLE users" "(" "nickname CHAR NOT NULL UNIQUE," "password CHAR NOT NULL," "credentials CHAR NOT NULL DEFAULT 'user'," "created TIMESTAMP DEFAULT (DATETIME('NOW'))," "activity TIMESTAMP DEFAULT (DATETIME('NOW'))" ");"; sql_execute(sql); return 0; } static int sql_callback_list(void* ptr, int argc, char **argv, char **colName) { int* found = (int*) ptr; uhub_assert(strcmp(colName[0], "nickname") == 0 && strcmp(colName[2], "credentials") == 0); printf("%s\t%s\n", argv[2], argv[0]); (*found)++; return 0; } static int list(size_t argc, const char** argv) { char* errMsg; int found = 0; int rc; open_database(); rc = sqlite3_exec(db, "SELECT * FROM users;", sql_callback_list, &found, &errMsg); if (rc != SQLITE_OK) { #ifdef DEBUG_SQL fprintf(stderr, "SQL: ERROR: %s (%d)\n", errMsg, rc); #endif sqlite3_free(errMsg); exit(1); } sqlite3_close(db); return 0; } static int add(size_t argc, const char** argv) { char* user = NULL; char* pass = NULL; const char* cred = NULL; int rc; if (argc < 2) print_usage("username password [credentials = user]"); user = sql_escape_string(validate_username(argv[0])); pass = sql_escape_string(validate_password(argv[1])); cred = validate_cred(argv[2] ? argv[2] : "user"); rc = sql_execute("INSERT INTO users (nickname, password, credentials) VALUES('%s', '%s', '%s');", user, pass, cred); free(user); free(pass); if (rc != 1) { fprintf(stderr, "Unable to add user \"%s\"\n", argv[0]); return 1; } return 0; } static int mod(size_t argc, const char** argv) { char* user = NULL; const char* cred = NULL; int rc; if (argc < 2) print_usage("username credentials"); user = sql_escape_string(argv[0]); cred = validate_cred(argv[1]); rc = sql_execute("UPDATE users SET credentials = '%s' WHERE nickname = '%s';", cred, user); free(user); if (rc != 1) { fprintf(stderr, "Unable to set credentials for user \"%s\"\n", argv[0]); return 1; } return 0; } static int pass(size_t argc, const char** argv) { char* user = NULL; char* pass = NULL; int rc; if (argc < 2) print_usage("username password"); user = sql_escape_string(argv[0]); pass = sql_escape_string(validate_password(argv[1])); rc = sql_execute("UPDATE users SET password = '%s' WHERE nickname = '%s';", pass, user); free(user); free(pass); if (rc != 1) { fprintf(stderr, "Unable to change password for user \"%s\"\n", argv[0]); return 1; } return 0; } static int del(size_t argc, const char** argv) { char* user = NULL; int rc; if (argc < 1) print_usage("username"); user = sql_escape_string(argv[0]); rc = sql_execute("DELETE FROM users WHERE nickname = '%s';", user); free(user); if (rc != 1) { fprintf(stderr, "Unable to delete user \"%s\".\n", argv[0]); return 1; } return 0; } void main_usage(const char* binary) { printf( "Usage: %s filename command [...]\n" "\n" "Command syntax:\n" " create\n" " add username password [credentials = user]\n" " del username\n" " mod username credentials\n" " pass username password\n" " list\n" "\n" "Parameters:\n" " 'filename' is a database file\n" " 'username' is a nickname (UTF-8, up to %i bytes)\n" " 'password' is a password (UTF-8, up to %i bytes)\n" " 'credentials' is one of 'admin', 'super', 'op', 'user'\n" "\n" , binary, MAX_NICK_LEN, MAX_PASS_LEN); } int main(int argc, char** argv) { size_t n = 0; binary = argv[0]; filename = argv[1]; command = argv[2]; if (argc < 3) { main_usage(argv[0]); return 1; } for (; n < sizeof(COMMANDS) / sizeof(COMMANDS[0]); n++) { if (!strcmp(command, COMMANDS[n].command)) return COMMANDS[n].handle(argc - 3, (const char**) &argv[3]); } // Unknown command! main_usage(argv[0]); return 1; } modelrockettier-uhub-a8ee6e7/src/uhub.h000066400000000000000000000050731324501300100202520ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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 10 #define MAX_CID_LEN 39 #define MAX_NICK_LEN 64 #define MAX_PASS_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/cbuffer.h" #include "util/config_token.h" #include "util/credentials.h" #include "util/floodctl.h" #include "util/getopt.h" #include "util/list.h" #include "util/log.h" #include "util/memory.h" #include "util/misc.h" #include "util/tiger.h" #include "util/threads.h" #include "util/rbtree.h" #include "adc/sid.h" #include "adc/message.h" #include "network/network.h" #include "network/notify.h" #include "network/connection.h" #include "network/dnsresolver.h" #include "network/ipcalc.h" #include "network/timeout.h" #include "core/auth.h" #include "core/config.h" #include "core/eventid.h" #include "core/eventqueue.h" #include "core/netevent.h" #include "core/ioqueue.h" #include "core/user.h" #include "core/usermanager.h" #include "core/route.h" #include "core/pluginloader.h" #include "core/hub.h" #include "core/command_parser.h" #include "core/commands.h" #include "core/inf.h" #include "core/hubevent.h" #include "core/plugincallback.h" #include "core/plugininvoke.h" #include "core/pluginloader.h" #ifdef __cplusplus } #endif #endif /* HAVE_UHUB_COMMON_H */ modelrockettier-uhub-a8ee6e7/src/util/000077500000000000000000000000001324501300100201065ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/src/util/cbuffer.c000066400000000000000000000053001324501300100216640ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" #define CBUF_FLAG_CONST_BUFFER 0x01 struct cbuffer { size_t capacity; size_t size; size_t flags; char* buf; }; extern struct cbuffer* cbuf_create(size_t capacity) { struct cbuffer* buf = hub_malloc(sizeof(struct cbuffer)); buf->capacity = capacity; buf->size = 0; buf->flags = 0; buf->buf = hub_malloc(capacity + 1); buf->buf[0] = '\0'; return buf; } struct cbuffer* cbuf_create_const(const char* buffer) { struct cbuffer* buf = hub_malloc(sizeof(struct cbuffer)); buf->capacity = 0; buf->size = strlen(buffer); buf->flags = CBUF_FLAG_CONST_BUFFER; buf->buf = (char*) buffer; return buf; } void cbuf_destroy(struct cbuffer* buf) { if (!(buf->flags & CBUF_FLAG_CONST_BUFFER)) { hub_free(buf->buf); } hub_free(buf); } void cbuf_resize(struct cbuffer* buf, size_t capacity) { uhub_assert(buf->flags == 0); buf->capacity = capacity; buf->buf = hub_realloc(buf->buf, capacity + 1); } void cbuf_append_bytes(struct cbuffer* buf, const char* msg, size_t len) { uhub_assert(buf->flags == 0); if (buf->size + len >= buf->capacity) cbuf_resize(buf, buf->size + len); memcpy(buf->buf + buf->size, msg, len); buf->size += len; buf->buf[buf->size] = '\0'; } void cbuf_append(struct cbuffer* buf, const char* msg) { size_t len = strlen(msg); uhub_assert(buf->flags == 0); cbuf_append_bytes(buf, msg, len); } void cbuf_append_format(struct cbuffer* buf, const char* format, ...) { static char tmp[1024]; va_list args; int bytes; uhub_assert(buf->flags == 0); va_start(args, format); bytes = vsnprintf(tmp, 1024, format, args); va_end(args); cbuf_append_bytes(buf, tmp, bytes); } void cbuf_append_strftime(struct cbuffer* buf, const char* format, const struct tm* tm) { static char tmp[1024]; int bytes; uhub_assert(buf->flags == 0); bytes = strftime(tmp, sizeof(tmp), format, tm); cbuf_append_bytes(buf, tmp, bytes); } const char* cbuf_get(struct cbuffer* buf) { return buf->buf; } size_t cbuf_size(struct cbuffer* buf) { return buf->size; } modelrockettier-uhub-a8ee6e7/src/util/cbuffer.h000066400000000000000000000027241324501300100217000ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UTIL_CBUFFER_H #define HAVE_UTIL_CBUFFER_H struct cbuffer; extern struct cbuffer* cbuf_create(size_t capacity); extern struct cbuffer* cbuf_create_const(const char* buffer); extern void cbuf_destroy(struct cbuffer* buf); extern void cbuf_resize(struct cbuffer* buf, size_t capacity); extern void cbuf_append_bytes(struct cbuffer* buf, const char* msg, size_t len); extern void cbuf_append(struct cbuffer* buf, const char* msg); extern void cbuf_append_format(struct cbuffer* buf, const char* format, ...); extern void cbuf_append_strftime(struct cbuffer* buf, const char* format, const struct tm* tm); extern const char* cbuf_get(struct cbuffer* buf); extern size_t cbuf_size(struct cbuffer* buf); #endif /* HAVE_UTIL_CBUFFER_H */ modelrockettier-uhub-a8ee6e7/src/util/config_token.c000066400000000000000000000116351324501300100227250ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" #define ADD_CHAR(X) do { *out = X; out++; token_size++; } while(0) #define RESET_TOKEN do { ADD_CHAR('\0'); out = buffer; if (cfg_token_add(tokens, out)) token_count++; token_size = 0; buffer[0] = '\0'; } while (0) struct cfg_tokens { struct linked_list* list; }; struct cfg_tokens* cfg_tokenize(const char* line) { struct cfg_tokens* tokens = (struct cfg_tokens*) hub_malloc_zero(sizeof(struct cfg_tokens)); char* buffer = (char*) hub_malloc_zero(strlen(line) + 1); char* out = buffer; const char* p = line; int backslash = 0; char quote = 0; size_t token_count = 0; size_t token_size = 0; tokens->list = list_create(); for (; *p; p++) { switch (*p) { case '\\': if (backslash) { ADD_CHAR('\\'); backslash = 0; } else { backslash = 1; } break; case '#': if (backslash) { ADD_CHAR('#'); backslash = 0; } else if (quote) { ADD_CHAR('#'); } else { RESET_TOKEN; hub_free(buffer); return tokens; } break; case '"': if (backslash) { ADD_CHAR('"'); backslash = 0; } else if (quote) { quote = 0; } else { quote = 1; } break; case '\r': /* Pretend it does not exist! */ break; case ' ': case '\t': if (quote) { ADD_CHAR(*p); } else if (backslash) { ADD_CHAR(*p); backslash = 0; } else { RESET_TOKEN; } break; default: ADD_CHAR(*p); } } RESET_TOKEN; hub_free(buffer); return tokens; } void cfg_tokens_free(struct cfg_tokens* tokens) { if (tokens) { list_clear(tokens->list, hub_free); list_destroy(tokens->list); hub_free(tokens); } } int cfg_token_add(struct cfg_tokens* tokens, char* new_token) { if (*new_token) { list_append(tokens->list, hub_strdup(new_token)); return 1; } return 0; } size_t cfg_token_count(struct cfg_tokens* tokens) { return list_size(tokens->list); } char* cfg_token_get(struct cfg_tokens* tokens, size_t offset) { return list_get_index(tokens->list, offset); } char* cfg_token_get_first(struct cfg_tokens* tokens) { return list_get_first(tokens->list); } char* cfg_token_get_next(struct cfg_tokens* tokens) { return list_get_next(tokens->list); } struct cfg_settings { char* key; char* value; }; struct cfg_settings* cfg_settings_split(const char* line) { struct cfg_settings* s = NULL; struct cfg_tokens* tok = NULL; char* pos = NULL; if ( !line || !*line || ((pos = (char*) strchr(line, '=')) == NULL) || ((s = hub_malloc_zero(sizeof(struct cfg_settings))) == NULL) || ((tok = cfg_tokenize(line)) == NULL) || (cfg_token_count(tok) < 1) || (cfg_token_count(tok) > 3) || (cfg_token_count(tok) == 3 && strcmp(cfg_token_get(tok, 1), "=")) ) { cfg_tokens_free(tok); cfg_settings_free(s); return NULL; } if (cfg_token_count(tok) == 1) { char* key = cfg_token_get_first(tok); pos = strchr(key, '='); if (!pos) { cfg_tokens_free(tok); cfg_settings_free(s); return NULL; } pos[0] = 0; key = strip_white_space(key); if (!*key) { cfg_tokens_free(tok); cfg_settings_free(s); return NULL; } s->key = strdup(key); s->value = strdup(strip_white_space(pos+1)); } else if (cfg_token_count(tok) == 2) { char* key = cfg_token_get_first(tok); char* val = cfg_token_get_next(tok); if ((pos = strchr(key, '='))) { pos[0] = 0; key = strip_white_space(key); } else if ((pos = strchr(val, '='))) { val = strip_white_space(pos+1); } else { cfg_tokens_free(tok); cfg_settings_free(s); return NULL; } if (!*key) { cfg_tokens_free(tok); cfg_settings_free(s); return NULL; } s->key = strdup(key); s->value = strdup(val); } else { s->key = strdup(strip_white_space(cfg_token_get(tok, 0))); s->value = strdup(strip_white_space(cfg_token_get(tok, 2))); } cfg_tokens_free(tok); return s; } const char* cfg_settings_get_key(struct cfg_settings* s) { return s->key; } const char* cfg_settings_get_value(struct cfg_settings* s) { return s->value; } void cfg_settings_free(struct cfg_settings* s) { if (s) { hub_free(s->key); hub_free(s->value); hub_free(s); } } modelrockettier-uhub-a8ee6e7/src/util/config_token.h000066400000000000000000000026611324501300100227310ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_CONFIG_TOKEN_H #define HAVE_UHUB_CONFIG_TOKEN_H struct cfg_tokens; struct cfg_tokens* cfg_tokenize(const char* line); void cfg_tokens_free(struct cfg_tokens*); int cfg_token_add(struct cfg_tokens*, char* new_token); size_t cfg_token_count(struct cfg_tokens*); char* cfg_token_get(struct cfg_tokens*, size_t offset); char* cfg_token_get_first(struct cfg_tokens*); char* cfg_token_get_next(struct cfg_tokens*); struct cfg_settings; struct cfg_settings* cfg_settings_split(const char* line); const char* cfg_settings_get_key(struct cfg_settings*); const char* cfg_settings_get_value(struct cfg_settings*); void cfg_settings_free(struct cfg_settings*); #endif /* HAVE_UHUB_CONFIG_TOKEN_H */ modelrockettier-uhub-a8ee6e7/src/util/credentials.c000066400000000000000000000073331324501300100225550ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" /** * Returns 1 if a user is unrestricted. * Unrestricted users override the limits of flood and can send messages in * the name of other users. * This is useful for amongst other external chatrooms. */ int auth_cred_is_unrestricted(enum auth_credentials cred) { switch (cred) { case auth_cred_ubot: case auth_cred_opubot: return 1; default: break; } return 0; } int auth_cred_is_protected(enum auth_credentials cred) { switch (cred) { case auth_cred_bot: case auth_cred_ubot: case auth_cred_opbot: case auth_cred_opubot: case auth_cred_operator: case auth_cred_super: case auth_cred_admin: case auth_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 auth_cred_is_registered(enum auth_credentials cred) { switch (cred) { case auth_cred_bot: case auth_cred_ubot: case auth_cred_opbot: case auth_cred_opubot: case auth_cred_user: case auth_cred_operator: case auth_cred_super: case auth_cred_admin: case auth_cred_link: return 1; default: break; } return 0; } const char* auth_cred_to_string(enum auth_credentials cred) { switch (cred) { case auth_cred_none: return "none"; case auth_cred_bot: return "bot"; case auth_cred_ubot: return "ubot"; case auth_cred_opbot: return "opbot"; case auth_cred_opubot: return "opubot"; case auth_cred_guest: return "guest"; case auth_cred_user: return "user"; case auth_cred_operator: return "operator"; case auth_cred_super: return "super"; case auth_cred_link: return "link"; case auth_cred_admin: return "admin"; } return ""; }; int auth_string_to_cred(const char* str, enum auth_credentials* out) { if (!str || !*str || !out) return 0; switch (strlen(str)) { case 2: if (!strcasecmp(str, "op")) { *out = auth_cred_operator; return 1; } return 0; case 3: if (!strcasecmp(str, "bot")) { *out = auth_cred_bot; return 1; } if (!strcasecmp(str, "reg")) { *out = auth_cred_user; return 1; } return 0; case 4: if (!strcasecmp(str, "none")) { *out = auth_cred_none; return 1; } if (!strcasecmp(str, "user")) { *out = auth_cred_user; return 1; } if (!strcasecmp(str, "link")) { *out = auth_cred_link; return 1; } if (!strcasecmp(str, "ubot")) { *out = auth_cred_ubot; return 1; } return 0; case 5: if (!strcasecmp(str, "admin")) { *out = auth_cred_admin; return 1; } if (!strcasecmp(str, "super")) { *out = auth_cred_super; return 1; } if (!strcasecmp(str, "opbot")) { *out = auth_cred_opbot; return 1; } if (!strcasecmp(str, "guest")) { *out = auth_cred_guest; return 1; } return 0; case 6: if (!strcasecmp(str, "opubot")) { *out = auth_cred_opubot; return 1; } return 0; case 8: if (!strcasecmp(str, "operator")) { *out = auth_cred_operator; return 1; } return 0; default: return 0; } } modelrockettier-uhub-a8ee6e7/src/util/credentials.h000066400000000000000000000046701324501300100225630ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_CREDENTIALS_H #define HAVE_UHUB_CREDENTIALS_H enum auth_credentials { auth_cred_none, /**<<< "User has no credentials (not yet logged in)" */ auth_cred_guest, /**<<< "User is a guest (unregistered user)" */ auth_cred_user, /**<<< "User is identified as a registered user" */ auth_cred_bot, /**<<< "User is a robot" */ auth_cred_ubot, /**<<< "User is an unrestricted robot" */ auth_cred_operator, /**<<< "User is identified as a hub operator" */ auth_cred_opbot, /**<<< "User is a operator robot" */ auth_cred_opubot, /**<<< "User is an unrestricted operator robot" */ auth_cred_super, /**<<< "User is a super user" (not used) */ auth_cred_link, /**<<< "User is a link (not used currently)" */ auth_cred_admin, /**<<< "User is identified as a hub administrator/owner" */ }; /** * Returns 1 if the credentials means that a user is unrestricted. * Returns 0 otherwise. */ int auth_cred_is_unrestricted(enum auth_credentials cred); /** * Returns 1 if the credentials means that a user is protected. * Returns 0 otherwise. */ int auth_cred_is_protected(enum auth_credentials cred); /** * Returns 1 if a user is registered. * Returns 0 otherwise. * Only registered users will be let in if the hub is configured for registered * users only. */ int auth_cred_is_registered(enum auth_credentials cred); /** * Returns a string representation of the credentials enum. */ const char* auth_cred_to_string(enum auth_credentials cred); int auth_string_to_cred(const char* str, enum auth_credentials* out); #endif /* HAVE_UHUB_CREDENTIALS_H */ modelrockettier-uhub-a8ee6e7/src/util/floodctl.c000066400000000000000000000027401324501300100220630ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" void flood_control_reset(struct flood_control* data) { memset(data, 0, sizeof(struct flood_control)); } int flood_control_check(struct flood_control* data, size_t max_count, size_t time_delay, time_t now) { // Is flood control disabled? if (!time_delay || !max_count) return 0; // No previous message, or a long time since // the last message. We allow the message. if (!data->time || ((now - data->time) > time_delay)) { data->time = now; data->count = 1; return 0; } // increase hit count data->count++; // did we overflow the limits yet? if (data->count < max_count) return 0; // if we continue sending spam messages we extend the flood interval // based on the last message. data->time = now; return 1; } modelrockettier-uhub-a8ee6e7/src/util/floodctl.h000066400000000000000000000025051324501300100220670ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_FLOOD_CTL_H #define HAVE_UHUB_FLOOD_CTL_H struct flood_control { time_t time; size_t count; }; /** * Reset flood control statistics */ void flood_control_reset(struct flood_control*); /** * @param ctl Flood control data structure * @param max_count Max count for flood control * @param window Time window for max_count to appear. * @param now The current time. * * @return 0 if flood no flood detected. * 1 if flood detected. */ int flood_control_check(struct flood_control* ctl, size_t max_count, size_t window, time_t now); #endif /* HAVE_UHUB_FLOOD_CTL_H */ modelrockettier-uhub-a8ee6e7/src/util/getopt.c000066400000000000000000000023561324501300100215620ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" #ifdef NEED_GETOPT char *optarg = NULL; int optind = 1; /* * This is a very simple subset of the real getopt(). */ int getopt(int argc, char* const argv[], const char *optstring) { int ret; char* pos; char* arg = argv[optind++]; optarg = NULL; if (optind > argc) return -1; if (*arg != '-') return -1; arg++; if (*arg == '-') arg++; ret = *arg; pos = strchr(optstring, ret); if (!pos) return ret; if (*(pos+1) == ':') optarg = argv[optind++]; return ret; } #endif modelrockettier-uhub-a8ee6e7/src/util/getopt.h000066400000000000000000000016321324501300100215630ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" #ifdef NEED_GETOPT extern char* optarg; extern int optind; extern int getopt(int argc, char* const argv[], const char *optstring); #endif /* NEED_GETOPT */ modelrockettier-uhub-a8ee6e7/src/util/list.c000066400000000000000000000113041324501300100212240ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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) { uhub_assert(list->size == 0); uhub_assert(list->first == NULL); uhub_assert(list->last == NULL); hub_free(list); } } static void dummy_free(void* ptr) { } void list_clear(struct linked_list* list, void (*free_handle)(void* ptr)) { struct node* node = list->first; struct node* tmp = NULL; if (free_handle == NULL) free_handle = &dummy_free; 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_append_list(struct linked_list* list, struct linked_list* other) { /* Anything to move? */ if (!other->size) return; if (!list->size) { /* If the list is empty, just move the pointers */ list->size = other->size; list->first = other->first; list->last = other->last; list->iterator = other->iterator; } else { other->first->prev = list->last; list->last->next = other->first; list->last = other->last; list->size += other->size; } /* Make sure the original list appears empty */ other->size = 0; other->first = NULL; other->last = NULL; other->iterator = NULL; } void list_remove(struct linked_list* list, void* data_ptr) { struct node* node = list->first; uhub_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--; return; } node = node->next; } } void list_remove_first(struct linked_list* list, void (*free_handle)(void* ptr)) { struct node* node = list->first; list->iterator = NULL; if (!node) return; list->first = node->next; if (list->first) list->first->prev = NULL; if (list->last == node) list->last = NULL; list->size--; if (free_handle) free_handle(node->ptr); hub_free(node); } 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; } modelrockettier-uhub-a8ee6e7/src/util/list.h000066400000000000000000000045611324501300100212400ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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); /** * A special list append that moves all nodes from other_list to list. * The other list will be empty. */ extern void list_append_list(struct linked_list* list, struct linked_list* other); /** * 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*); /** * Remove the first element, and call the free_handle function (if not NULL) * to ensure the data is freed also. */ extern void list_remove_first(struct linked_list* list, void (*free_handle)(void* ptr)); #define LIST_FOREACH(TYPE, ITEM, LIST, BLOCK) \ for (ITEM = (TYPE) list_get_first(LIST); ITEM; ITEM = (TYPE) list_get_next(LIST)) \ BLOCK #endif /* HAVE_UHUB_LINKED_LIST_H */ modelrockettier-uhub-a8ee6e7/src/util/log.c000066400000000000000000000110051324501300100210300ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" #include #ifndef WIN32 #ifdef SYSTEMD #define SD_JOURNAL_SUPPRESS_LOCATION #include #else #include #endif 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", "PLUGIN", 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; #ifndef SYSTEMD openlog("uhub", LOG_PID, LOG_USER); #endif } #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; #ifndef SYSTEMD closelog(); #endif } #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 %6s: %s\n", timestamp, prefixes[log_verbosity], logmsg); fflush(logfile); } else { fprintf(stderr, "%s %6s: %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; #ifdef SYSTEMD case log_user: level = LOG_INFO; break; #else case log_user: level = LOG_INFO | LOG_AUTH; break; #endif case log_info: level = LOG_INFO; break; case log_debug: level = LOG_DEBUG; break; default: level = 0; break; } if (level == 0) return; #ifdef SYSTEMD sd_journal_print(level, "%s", logmsg); #else level |= (LOG_USER | LOG_DAEMON); syslog(level, "%s", logmsg); #endif } #endif } modelrockettier-uhub-a8ee6e7/src/util/log.h000066400000000000000000000054471324501300100210520ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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, log_plugin = 10, }; #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__) # define LOG_PLUGIN(format, ...) hub_log(log_plugin, format, ## __VA_ARGS__) #else # define LOG_DEBUG(format, ...) do { } while(0) # define LOG_TRACE(format, ...) do { } while(0) # define LOG_PLUGIN(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 */ modelrockettier-uhub-a8ee6e7/src/util/memory.c000066400000000000000000000132371324501300100215700ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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 */ modelrockettier-uhub-a8ee6e7/src/util/memory.h000066400000000000000000000026311324501300100215710ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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_realloc realloc #define hub_strdup strdup #define hub_strndup strndup #endif extern void* hub_malloc_zero(size_t size); #endif /* HAVE_UHUB_MEMORY_HANDLER_H */ modelrockettier-uhub-a8ee6e7/src/util/misc.c000066400000000000000000000244761324501300100212220ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" static const char* BASE32_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 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 unsigned 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 > 0x08; div /= 2) { if (string[pos] & div) expect++; else break; } if ((string[pos] & div) || (pos+expect >= length)) return 0; switch (expect) { case 0: return 0; case 1: /* Out of range */ if (string[pos] < 0xC2) return 0; break; case 2: /* Out of range */ if ((string[pos] == 0xE0) && (string[pos+1] < 0xA0 )) return 0; /* Surrogates */ if ((string[pos] == 0xED) && (string[pos+1] > 0x9F )) return 0; break; case 3: /* Out of range */ if ((string[pos] == 0xF0) && (string[pos+1] < 0x90 )) return 0; if (string[pos] > 0xF4) return 0; if ((string[pos] == 0xF4) && (string[pos+1] > 0x8F )) return 0; break; } } } } 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 string_split(const char* string, const char* split, void* data, string_split_handler_t handler) { char* buf = strdup(string); char* start; char* pos; int count = 0; start = buf; while ((pos = strstr(start, split))) { pos[0] = '\0'; start = strip_white_space(start); if (*start) { if (handler(start, count, data) < 0) { hub_free(buf); return -1; } } start = &pos[1]; count++; } start = strip_white_space(start); if (*start) { if (handler(start, count, data) < 0) { hub_free(buf); return -1; } } hub_free(buf); return count+1; } struct file_read_line_data { file_line_handler_t handler; void* data; }; static int file_read_line_handler(char* line, int count, void* ptr) { struct file_read_line_data* data = (struct file_read_line_data*) ptr; LOG_DUMP("Line: %s", line); if (data->handler(line, count+1, data->data) < 0) return -1; return 0; } int file_read_lines(const char* file, void* data, file_line_handler_t handler) { int fd; ssize_t ret; char buf[MAX_RECV_BUF]; struct file_read_line_data split_data; 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-1); close(fd); if (ret < 0) { LOG_ERROR("Unable to read from file %s: %s", file, strerror(errno)); return -1; } else if (ret == 0) { LOG_WARN("File is empty."); return 0; } buf[ret] = 0; /* Parse configuration */ split_data.handler = handler; split_data.data = data; return string_split(buf, "\n", &split_data, file_read_line_handler); } 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; } int is_number(const char* value, int* num) { int len = strlen(value); int offset = (value[0] == '-') ? 1 : 0; int val = 0; int i = offset; if (!*(value + offset)) return 0; for (; i < len; i++) if (value[i] > '9' || value[i] < '0') return 0; for (i = offset; i< len; i++) val = val*10 + (value[i] - '0'); *num = value[0] == '-' ? -val : val; return 1; } const char* format_size(size_t bytes, char* buf, size_t bufsize) { static const char* quant[] = { "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB" }; size_t b = bytes; size_t factor = 0; size_t divisor = 1; while (b > 1024) { factor++; b = (b >> 10); divisor = (divisor << 10); } uhub_assert(factor < (sizeof(quant) / sizeof(const char*))); if (factor >= 2) snprintf(buf, bufsize, "%.1f %s", (double) bytes / (double) divisor, quant[factor]); else snprintf(buf, bufsize, PRINTF_SIZE_T " %s", bytes / divisor, quant[factor]); return buf; } const char* uhub_itoa(int val) { static char buf[22]; return snprintf(buf, sizeof(buf), "%d", val) < 0 ? NULL : buf; } const char* uhub_ulltoa(uint64_t val) { static char buf[22]; return snprintf(buf, sizeof(buf), PRINTF_UINT64_T, val) < 0 ? NULL : buf; } #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 && ((size_t) (&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); snprintf(ts, sizeof(ts), "[%02d:%02d]", t->tm_hour, t->tm_min); return ts; } void strip_off_ini_line_comments(char* line, int line_count) { char* p = line; char* out = line; int backslash = 0; if (!*line) return; for (; *p; p++) { if (!backslash) { if (*p == '\\') { backslash = 1; } else if (*p == '#') { *out = '\0'; out++; break; } else { *out = *p; out++; } } else { if (*p == '\\' || *p == '#' || *p == '\"') { *out = *p; out++; } else { LOG_WARN("Invalid backslash escape on line %d", line_count); *out = *p; out++; } backslash = 0; } } *out = '\0'; } int string_to_boolean(const char* str, int* boolean) { if (!str || !*str || !boolean) return 0; switch (strlen(str)) { case 1: if (str[0] == '1') { *boolean = 1; return 1; } else if (str[0] == '0') { *boolean = 0; return 1; } return 0; case 2: if (!strcasecmp(str, "on")) { *boolean = 1; return 1; } if (!strcasecmp(str, "no")) { *boolean = 0; return 1; } return 0; case 3: if (!strcasecmp(str, "yes")) { *boolean = 1; return 1; } if (!strcasecmp(str, "off")) { *boolean = 0; return 1; } return 0; case 4: if (!strcasecmp(str, "true")) { *boolean = 1; return 1; } return 0; case 5: if (!strcasecmp(str, "false")) { *boolean = 0; return 1; } return 0; default: return 0; } } char* strip_off_quotes(char* line) { size_t len; if (!*line) return line; len = strlen(line); if (len < 2) return line; if ((line[0] == '"' && line[len - 1] == '"') || (line[0] == '\'' && line[len - 1] == '\'')) { line[len-1] = '\0'; return line + 1; } return line; } modelrockettier-uhub-a8ee6e7/src/util/misc.h000066400000000000000000000067151324501300100212230ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #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 void strip_off_ini_line_comments(char* line, int line_count); extern char* strip_off_quotes(char* line); /** * Convert number in str to integer and store it in num. * @return 1 on success, or 0 on error. */ extern int is_number(const char* str, int* num); /** * Convert the 'bytes' number into a formatted byte size string. * E.g. "129012" becomes "125.99 KB". * Note, if the output buffer is not large enough then the output * will be truncated. The buffer will always be \0 terminated. * * @param bytes the number that should be formatted. * @param[out] buf the buffer the string should be formatted into * @param bufsize the size of 'buf' * @return A pointer to buf. */ extern const char* format_size(size_t bytes, char* buf, size_t bufsize); extern int file_read_lines(const char* file, void* data, file_line_handler_t handler); /** * Convert a string to a boolean (0 or 1). * Example: * "yes", "true", "1", "on" sets 1 in boolean, and returns 1. * "no", "false", "0", "off" sets 0 in boolean, and returns 1. * All other values return 0, and boolean is unchanged. */ extern int string_to_boolean(const char* str, int* boolean); /** * Convert number to string. * Note: these functions are neither thread-safe nor reentrant. * @return pointer to the resulting string, NULL on error */ extern const char* uhub_itoa(int val); extern const char* uhub_ulltoa(uint64_t val); extern int uhub_atoi(const char* value); #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); typedef int (*string_split_handler_t)(char* string, int count, void* data); extern int string_split(const char* string, const char* split, void* data, string_split_handler_t handler); #endif /* HAVE_UHUB_MISC_H */ modelrockettier-uhub-a8ee6e7/src/util/rbtree.c000066400000000000000000000176561324501300100215540ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" #include "rbtree.h" // #define RB_TREE_CHECKS 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(node->key, key); if (!res) break; node = node->link[res < 0]; } return node; } static struct rb_node* create_node(struct rb_tree* tree, const void* key, const void* value) { struct rb_node* node = tree->alloc(sizeof(struct rb_node)); node->key = key; node->value = value; node->red = 1; node->link[0] = 0; node->link[1] = 0; return node; } static int is_red(struct rb_node* node) { return node && node->red; } #ifdef RB_TREE_CHECKS int rb_tree_check(struct rb_tree* tree, struct rb_node* node) { int lh, rh; if (node == NULL) return 1; else { struct rb_node *ln = node->link[0]; struct rb_node *rn = node->link[1]; /* Consecutive red links */ if (is_red(node)) { if (is_red(ln) || is_red(rn)) { puts("Red violation"); return 0; } } lh = rb_tree_check(tree, ln); rh = rb_tree_check(tree, rn); /* Invalid binary search tree - not sorted correctly */ if ((ln && tree->compare(ln->key, node->key) >= 0) || (rn && tree->compare(rn->key, node->key) <= 0)) { puts("Binary tree violation"); return 0; } /* Black height mismatch */ if ( lh != 0 && rh != 0 && lh != rh ) { puts ( "Black violation" ); return 0; } /* Only count black links */ if (lh != 0 && rh != 0) return is_red(node) ? lh : lh + 1; else return 0; } } #endif // RB_TREE_CHECKS static struct rb_node* rb_tree_rotate_single(struct rb_node* node, int dir) { struct rb_node* other = node->link[!dir]; node->link[!dir] = other->link[dir]; other->link[dir] = node; node->red = 1; other->red = 0; return other; } static struct rb_node* rb_tree_rotate_double(struct rb_node* node, int dir) { node->link[!dir] = rb_tree_rotate_single(node->link[!dir], !dir); return rb_tree_rotate_single(node, dir); } static struct rb_node* rb_tree_insert_r(struct rb_tree* tree, struct rb_node* node, const void* key, const void* value) { int res; if (!node) return create_node(tree, key, value); res = tree->compare(node->key, key); if (!res) { puts("Node already exists!"); return NULL; } else { int dir = res < 0; node->link[dir] = rb_tree_insert_r(tree, node->link[dir], key, value); if (is_red(node->link[dir])) { if (is_red(node->link[!dir])) { /* Case 1 */ node->red = 1; node->link[0]->red = 0; node->link[1]->red = 0; } else { /* Cases 2 & 3 */ if (is_red(node->link[dir]->link[dir])) node = rb_tree_rotate_single(node, !dir); else if (is_red(node->link[dir]->link[!dir])) node = rb_tree_rotate_double(node, !dir); } } } return node; } struct rb_tree* rb_tree_create(rb_tree_compare compare, rb_tree_alloc a, rb_tree_free f) { struct rb_tree* tree = a ? a(sizeof(struct rb_tree)) : hub_malloc(sizeof(struct rb_tree)); tree->compare = compare; tree->alloc = a ? a : hub_malloc; tree->free = f ? f : hub_free; tree->root = NULL; tree->elements = 0; tree->iterator.node = NULL; tree->iterator.stack = list_create(); return tree; } void rb_tree_destroy(struct rb_tree* tree) { list_destroy(tree->iterator.stack); tree->free(tree); } int rb_tree_insert(struct rb_tree* tree, const void* key, const void* value) { struct rb_node* node; if (tree_search(tree, key)) return 0; node = rb_tree_insert_r(tree, tree->root, key, value); tree->root = node; tree->root->red = 0; tree->elements++; #ifdef RB_TREE_CHECKS rb_tree_check(tree, node); #endif return 1; } void null_node_free(struct rb_node* n) { } int rb_tree_remove(struct rb_tree* tree, const void* key) { return rb_tree_remove_node(tree, key, &null_node_free); } int rb_tree_remove_node(struct rb_tree* tree, const void* key, rb_tree_free_node freecb) { struct rb_node head = {0}; /* False tree root */ struct rb_node *q, *p, *g; /* Helpers */ struct rb_node *f = NULL; /* Found item */ int dir = 1; if (!tree->root) return 0; /* Set up helpers */ q = &head; g = p = NULL; q->link[1] = tree->root; /* Search and push a red down */ while (q->link[dir]) { int last = dir; int res; /* Update helpers */ g = p, p = q; q = q->link[dir]; res = tree->compare(q->key, key); dir = res < 0; /* Save found node */ if (!res) f = q; /* Push the red node down */ if (!is_red(q) && !is_red(q->link[dir])) { if (is_red(q->link[!dir])) p = p->link[last] = rb_tree_rotate_single(q, dir); else if (!is_red(q->link[!dir])) { struct rb_node* s = p->link[!last]; if (s) { if (!is_red(s->link[!last]) && !is_red (s->link[last])) { /* Color flip */ p->red = 0; s->red = 1; q->red = 1; } else { int dir2 = g->link[1] == p; if (is_red(s->link[last])) g->link[dir2] = rb_tree_rotate_double(p, last); else if (is_red(s->link[!last])) g->link[dir2] = rb_tree_rotate_single(p, last); /* Ensure correct coloring */ q->red = g->link[dir2]->red = 1; g->link[dir2]->link[0]->red = 0; g->link[dir2]->link[1]->red = 0; } } } } } /* Replace and remove if found */ if (f) { freecb(f); f->key = q->key; f->value = q->value; p->link[p->link[1] == q] = q->link[q->link[0] == NULL]; tree->free(q); tree->elements--; } /* Update root and make it black */ tree->root = head.link[1]; if (tree->root != NULL) tree->root->red = 0; #ifdef RB_TREE_CHECKS rb_tree_check(tree, tree->root); #endif return f != NULL; } void* rb_tree_get(struct rb_tree* tree, const void* key) { struct rb_node* node = tree_search(tree, key); if (node) return (void*) node->value; return 0; } size_t rb_tree_size(struct rb_tree* tree) { return tree->elements; } static void push(struct rb_tree* tree, struct rb_node* n) { list_append(tree->iterator.stack, n); } static struct rb_node* pop(struct rb_tree* tree) { struct rb_node* n = list_get_last(tree->iterator.stack); if (n) list_remove(tree->iterator.stack, n); return n; } static struct rb_node* rb_it_set(struct rb_tree* tree, struct rb_node* n) { tree->iterator.node = n; return n; } struct rb_node* rb_tree_first(struct rb_tree* tree) { struct rb_node* n = tree->root; list_clear(tree->iterator.stack, NULL); while (n->link[0]) { push(tree, n); n = n->link[0]; } return rb_it_set(tree, n); }; static struct rb_node* rb_tree_traverse(struct rb_tree* tree, int dir) { struct rb_node* n = tree->iterator.node; struct rb_node* p; /* parent */ if (n->link[dir]) { push(tree, n); n = n->link[dir]; while (n->link[!dir]) { list_append(tree->iterator.stack, n); n = n->link[!dir]; } return rb_it_set(tree, n); } // Need to walk upwards to the parent node. p = pop(tree); if (p) { // walk up in opposite direction if (p->link[!dir] == n) return rb_it_set(tree, p); // walk up in hte current direction while (p->link[dir] == n) { n = p; p = pop(tree); if (!p) return rb_it_set(tree, NULL); } return rb_it_set(tree, p); } return rb_it_set(tree, NULL); } struct rb_node* rb_tree_next(struct rb_tree* tree) { return rb_tree_traverse(tree, 1); } struct rb_node* rb_tree_prev(struct rb_tree* tree) { return rb_tree_traverse(tree, 0); } modelrockettier-uhub-a8ee6e7/src/util/rbtree.h000066400000000000000000000076521324501300100215540ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_RED_BLACK_TREE_H #define HAVE_UHUB_RED_BLACK_TREE_H struct rb_node { const void* key; const void* value; /* data */ int red; struct rb_node* link[2]; }; typedef int (*rb_tree_compare)(const void* a, const void* b); typedef void* (*rb_tree_alloc)(size_t); typedef void (*rb_tree_free)(void*); typedef void (*rb_tree_free_node)(struct rb_node*); struct rb_iterator { struct rb_node* node; // current node. struct linked_list* stack; // stack from the top -- needed since we don't have parent pointers. }; struct rb_tree { struct rb_node* root; size_t elements; rb_tree_alloc alloc; rb_tree_free free; rb_tree_compare compare; struct rb_iterator iterator; }; /** * Create a tree. * * @param compare Comparison function * @param alloc Allocator (if NULL then hub_malloc() is used) * @param dealloc Deallocator (if NULL then hub_free() is used) * @return a tree handle. */ extern struct rb_tree* rb_tree_create(rb_tree_compare compare, rb_tree_alloc alloc, rb_tree_free dealloc); /** * Delete the tree. * Assumes that the tree is empty. */ extern void rb_tree_destroy(struct rb_tree*); /** * Insert a key into the tree, returns 1 if successful, * or 0 if the key already existed. */ extern int rb_tree_insert(struct rb_tree* tree, const void* key, const void* data); /** * Remove a key from the tree. * Returns 1 if the node was removed, or 0 if it was not removed (i.e. not found!) * * NOTE: the content of the node is not freed if it needs to be then use rb_tree_remove_node * where you can specify a callback cleanup function. */ extern int rb_tree_remove(struct rb_tree* tree, const void* key); /** * Remove the node, but call the free callback before the node is removed. * This is useful in cases where you need to deallocate the key and/or value from the node. * Returns 1 if the node was removed, or 0 if not found. */ extern int rb_tree_remove_node(struct rb_tree* tree, const void* key, rb_tree_free_node free); /** * Returns NULL if the key was not found in the tree. */ extern void* rb_tree_get(struct rb_tree* tree, const void* key); /** * Returns the number of elements inside the tree. */ extern size_t rb_tree_size(struct rb_tree* tree); /** * Returns the first node in the tree. * (leftmost, or lowest value in sorted order). * * Example: * * * struct rb_node* it; * for (it = rb_tree_first(tree); it; it = rb_tree_next()) * { * void* key = rb_iterator_key(it); * void* value = rb_iterator_value(it); * } * */ extern struct rb_node* rb_tree_first(struct rb_tree* tree); /** * Points the iterator at the next node. * If the next node is NULL then the iterator becomes NULL too. */ extern struct rb_node* rb_tree_next(struct rb_tree* tree); extern struct rb_node* rb_tree_prev(struct rb_tree* tree); /** * Returnst the key of the node pointed to by the iterator. * If this iterator is the same as rb_tree_end() then NULL is returned. */ extern void* rb_iterator_key(struct rb_iterator* it); /** * Returnst the value of the node pointed to by the iterator. * If this iterator is the same as rb_tree_end() then the behavior is undefined. */ extern void* rb_iterator_value(struct rb_iterator* it); #endif /* HAVE_UHUB_RED_BLACK_TREE_H */ modelrockettier-uhub-a8ee6e7/src/util/threads.c000066400000000000000000000062401324501300100217060ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" #ifdef POSIX_THREAD_SUPPORT struct pthread_data { pthread_t handle; }; void uhub_mutex_init(uhub_mutex_t* mutex) { pthread_mutex_init(mutex, NULL); } void uhub_mutex_destroy(uhub_mutex_t* mutex) { pthread_mutex_destroy(mutex); } void uhub_mutex_lock(uhub_mutex_t* mutex) { pthread_mutex_lock(mutex); } void uhub_mutex_unlock(uhub_mutex_t* mutex) { pthread_mutex_unlock(mutex); } int uhub_mutex_trylock(uhub_mutex_t* mutex) { int ret = pthread_mutex_trylock(mutex); return (ret == 0); } uhub_thread_t* uhub_thread_create(uhub_thread_start start, void* arg) { struct pthread_data* thread = (struct pthread_data*) hub_malloc_zero(sizeof(struct pthread_data)); int ret = pthread_create(&thread->handle, NULL, start, arg); if (ret != 0) { hub_free(thread); thread = NULL; } return thread; } void uhub_thread_cancel(uhub_thread_t* thread) { pthread_cancel(thread->handle); } void* uhub_thread_join(uhub_thread_t* thread) { void* ret = NULL; pthread_join(thread->handle, &ret); hub_free(thread); return ret; } #endif /* POSIX_THREAD_SUPPORT */ #ifdef WINTHREAD_SUPPORT struct winthread_data { uhub_thread_t* handle; uhub_thread_start start; void* arg; }; static DWORD WINAPI uhub_winthread_start(void* ptr) { struct winthread_data* data = (struct winthread_data*) ptr; DWORD ret = (DWORD) data->start(data->arg); return ret; } void uhub_mutex_init(uhub_mutex_t* mutex) { InitializeCriticalSection(mutex); } void uhub_mutex_destroy(uhub_mutex_t* mutex) { DeleteCriticalSection(mutex); } void uhub_mutex_lock(uhub_mutex_t* mutex) { EnterCriticalSection(mutex); } void uhub_mutex_unlock(uhub_mutex_t* mutex) { LeaveCriticalSection(mutex); } int uhub_mutex_trylock(uhub_mutex_t* mutex) { return TryEnterCriticalSection(mutex); } uhub_thread_t* uhub_thread_create(uhub_thread_start start, void* arg) { struct winthread_data* thread = (struct winthread_data*) hub_malloc_zero(sizeof(struct winthread_data)); thread->start = start; thread->arg = arg; thread->handle = CreateThread(NULL, 0, uhub_winthread_start, thread, 0, 0); return thread; } void uhub_thread_cancel(uhub_thread_t* thread) { TerminateThread(thread->handle, 0); } void* uhub_thread_join(uhub_thread_t* thread) { void* ret = NULL; DWORD exitCode; WaitForSingleObject(thread->handle, INFINITE); GetExitCodeThread(thread->handle, &exitCode); ret = &exitCode; CloseHandle(thread->handle); hub_free(thread); return ret; } #endif /* WINTHREAD_SUPPORT */ modelrockettier-uhub-a8ee6e7/src/util/threads.h000066400000000000000000000030751324501300100217160ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_UTIL_THREADS_H #define HAVE_UHUB_UTIL_THREADS_H typedef void*(*uhub_thread_start)(void*) ; #ifdef POSIX_THREAD_SUPPORT typedef struct pthread_data uhub_thread_t; typedef pthread_mutex_t uhub_mutex_t; #endif #ifdef WINTHREAD_SUPPORT struct winthread_data; typedef struct winthread_data uhub_thread_t; typedef CRITICAL_SECTION uhub_mutex_t; #endif // Mutexes extern void uhub_mutex_init(uhub_mutex_t* mutex); extern void uhub_mutex_destroy(uhub_mutex_t* mutex); extern void uhub_mutex_lock(uhub_mutex_t* mutex); extern void uhub_mutex_unlock(uhub_mutex_t* mutex); extern int uhub_mutex_trylock(uhub_mutex_t* mutex); // Threads uhub_thread_t* uhub_thread_create(uhub_thread_start start, void* arg); void uhub_thread_cancel(uhub_thread_t* thread); void* uhub_thread_join(uhub_thread_t* thread); #endif /* HAVE_UHUB_UTIL_THREADS_H */ modelrockettier-uhub-a8ee6e7/src/util/tiger.c000066400000000000000000000706761324501300100214040ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #include "uhub.h" #define PASSES 3 extern uint64_t tiger_sboxes[4*256]; #define t1 (tiger_sboxes) #define t2 (tiger_sboxes + 256) #define t3 (tiger_sboxes + 512) #define t4 (tiger_sboxes + 768) #define ROUND(a, b, c, x, mul) \ c ^= x; \ a -= t1[c & 0xFF] ^ t2[(c >> 0x10) & 0xFF] ^ \ t3[(c >> 0x20) & 0xFF] ^ t4[(c >> 0x30) & 0xFF] ; \ b += t4[(c >> 0x08) & 0xFF] ^ t3[(c >> 0x18) & 0xFF] ^ \ t2[(c >> 0x28) & 0xFF] ^ t1[(c >> 0x38) & 0xFF] ; \ b *= mul; #define PASS(a, b, c, mul) \ ROUND(a, b, c, x0, mul) \ ROUND(b, c, a, x1, mul) \ ROUND(c, a, b, x2, mul) \ ROUND(a, b, c, x3, mul) \ ROUND(b, c, a, x4, mul) \ ROUND(c, a, b, x5, mul) \ ROUND(a, b, c, x6, mul) \ ROUND(b, c, a, x7, mul) void tiger_compress(uint64_t* str, uint64_t state[3]) { uint64_t a, b, c; uint64_t x0, x1, x2, x3, x4, x5, x6, x7; uint64_t aa, bb, cc; #if PASSES > 3 uint64_t swap; size_t pass_no; #endif a = state[0]; b = state[1]; c = state[2]; x0 = str[0]; x1 = str[1]; x2 = str[2]; x3 = str[3]; x4 = str[4]; x5 = str[5]; x6 = str[6]; x7 = str[7]; aa = a; bb = b; cc = c; PASS(a, b, c, 5); x0 -= x7 ^ 0xA5A5A5A5A5A5A5A5ULL; x1 ^= x0; x2 += x1; x3 -= x2 ^ ((~x1) << 19); x4 ^= x3; x5 += x4; x6 -= x5 ^ ((~x4) >> 23); x7 ^= x6; x0 += x7; x1 -= x0 ^ ((~x7) << 19); x2 ^= x1; x3 += x2; x4 -= x3 ^ ((~x2) >> 23); x5 ^= x4; x6 += x5; x7 -= x6 ^ 0x0123456789ABCDEFULL; PASS(c, a, b, 7); x0 -= x7 ^ 0xA5A5A5A5A5A5A5A5ULL; x1 ^= x0; x2 += x1; x3 -= x2 ^ ((~x1) << 19); x4 ^= x3; x5 += x4; x6 -= x5 ^ ((~x4) >> 23); x7 ^= x6; x0 += x7; x1 -= x0 ^ ((~x7) << 19); x2 ^= x1; x3 += x2; x4 -= x3 ^ ((~x2) >> 23); x5 ^= x4; x6 += x5; x7 -= x6 ^ 0x0123456789ABCDEFULL; PASS(b, c, a, 9); #if PASSES > 3 for (pass_no = 3; pass_no < PASSES; pass_no++) { x0 -= x7 ^ 0xA5A5A5A5A5A5A5A5ULL; x1 ^= x0; x2 += x1; x3 -= x2 ^ ((~x1) << 19); x4 ^= x3; x5 += x4; x6 -= x5 ^ ((~x4) >> 23); x7 ^= x6; x0 += x7; x1 -= x0 ^ ((~x7) << 19); x2 ^= x1; x3 += x2; x4 -= x3 ^ ((~x2) >> 23); x5 ^= x4; x6 += x5; x7 -= x6 ^ 0x0123456789ABCDEFULL; PASS(a, b, c, 9); swap = a; a = c; c = b; b = swap; } #endif a ^= aa; b -= bb; c += cc; state[0] = a; state[1] = b; state[2] = c; } #ifdef ARCH_BIGENDIAN void tiger_fix_endian(uint8_t *s) { uint64_t *i; uint8_t *b, btemp; uint16_t *w, wtemp; for(w = (uint16_t *)s; w < ((uint16_t *)s) + 12; w++) { b = (uint8_t *)w; btemp = *b; *b = *(b + 1); *(b + 1) = btemp; } for(i = (uint64_t *)s; i < ((uint64_t *)s) + 3; i++) { w = (uint16_t *)i; wtemp = *w; *w = *(w + 3); *(w + 3) = wtemp; wtemp = *(w + 1); *(w + 1) = *(w + 2); *(w + 2) = wtemp; } } #endif void tiger(uint64_t* str, uint64_t length, uint64_t res[3]) { uint64_t i, j; uint8_t temp[64]; res[0]= 0x0123456789ABCDEFULL; res[1]= 0xFEDCBA9876543210ULL; res[2]= 0xF096A5B4C3B2E187ULL; for (i = length; i >= 64; i -= 64) { #ifdef ARCH_BIGENDIAN for(j = 0; j < 64; j++) temp[j ^ 7] = ((uint8_t*) str)[j]; tiger_compress(((uint64_t*) temp), res); #else tiger_compress(str, res); #endif str += 8; } #ifdef ARCH_BIGENDIAN for (j = 0; j < i; j++) temp[j ^ 7] = ((uint8_t*) str)[j]; temp[j++ ^ 7] = 0x01; for (; j & 7; j++) temp[j ^ 7] = 0; #else for (j = 0; j < i; j++) temp[j] = ((uint8_t*) str)[j]; temp[j++] = 0x01; for (; j & 7; j++) temp[j] = 0; #endif if (j > 56) { for(; j < 64; j++) temp[j] = 0; tiger_compress(((uint64_t*) temp), res); j = 0; } for (; j < 56; j++) temp[j] = 0; ((uint64_t*) (&(temp[56])))[0] = ((uint64_t) length) << 3; tiger_compress(((uint64_t*) temp), res); #ifdef ARCH_BIGENDIAN tiger_fix_endian((uint8_t*) res); #endif } uint64_t tiger_sboxes[1024] = { 0x02AAB17CF7E90C5EULL, 0xAC424B03E243A8ECULL, 0x72CD5BE30DD5FCD3ULL, 0x6D019B93F6F97F3AULL, 0xCD9978FFD21F9193ULL, 0x7573A1C9708029E2ULL, 0xB164326B922A83C3ULL, 0x46883EEE04915870ULL, 0xEAACE3057103ECE6ULL, 0xC54169B808A3535CULL, 0x4CE754918DDEC47CULL, 0x0AA2F4DFDC0DF40CULL, 0x10B76F18A74DBEFAULL, 0xC6CCB6235AD1AB6AULL, 0x13726121572FE2FFULL, 0x1A488C6F199D921EULL, 0x4BC9F9F4DA0007CAULL, 0x26F5E6F6E85241C7ULL, 0x859079DBEA5947B6ULL, 0x4F1885C5C99E8C92ULL, 0xD78E761EA96F864BULL, 0x8E36428C52B5C17DULL, 0x69CF6827373063C1ULL, 0xB607C93D9BB4C56EULL, 0x7D820E760E76B5EAULL, 0x645C9CC6F07FDC42ULL, 0xBF38A078243342E0ULL, 0x5F6B343C9D2E7D04ULL, 0xF2C28AEB600B0EC6ULL, 0x6C0ED85F7254BCACULL, 0x71592281A4DB4FE5ULL, 0x1967FA69CE0FED9FULL, 0xFD5293F8B96545DBULL, 0xC879E9D7F2A7600BULL, 0x860248920193194EULL, 0xA4F9533B2D9CC0B3ULL, 0x9053836C15957613ULL, 0xDB6DCF8AFC357BF1ULL, 0x18BEEA7A7A370F57ULL, 0x037117CA50B99066ULL, 0x6AB30A9774424A35ULL, 0xF4E92F02E325249BULL, 0x7739DB07061CCAE1ULL, 0xD8F3B49CECA42A05ULL, 0xBD56BE3F51382F73ULL, 0x45FAED5843B0BB28ULL, 0x1C813D5C11BF1F83ULL, 0x8AF0E4B6D75FA169ULL, 0x33EE18A487AD9999ULL, 0x3C26E8EAB1C94410ULL, 0xB510102BC0A822F9ULL, 0x141EEF310CE6123BULL, 0xFC65B90059DDB154ULL, 0xE0158640C5E0E607ULL, 0x884E079826C3A3CFULL, 0x930D0D9523C535FDULL, 0x35638D754E9A2B00ULL, 0x4085FCCF40469DD5ULL, 0xC4B17AD28BE23A4CULL, 0xCAB2F0FC6A3E6A2EULL, 0x2860971A6B943FCDULL, 0x3DDE6EE212E30446ULL, 0x6222F32AE01765AEULL, 0x5D550BB5478308FEULL, 0xA9EFA98DA0EDA22AULL, 0xC351A71686C40DA7ULL, 0x1105586D9C867C84ULL, 0xDCFFEE85FDA22853ULL, 0xCCFBD0262C5EEF76ULL, 0xBAF294CB8990D201ULL, 0xE69464F52AFAD975ULL, 0x94B013AFDF133E14ULL, 0x06A7D1A32823C958ULL, 0x6F95FE5130F61119ULL, 0xD92AB34E462C06C0ULL, 0xED7BDE33887C71D2ULL, 0x79746D6E6518393EULL, 0x5BA419385D713329ULL, 0x7C1BA6B948A97564ULL, 0x31987C197BFDAC67ULL, 0xDE6C23C44B053D02ULL, 0x581C49FED002D64DULL, 0xDD474D6338261571ULL, 0xAA4546C3E473D062ULL, 0x928FCE349455F860ULL, 0x48161BBACAAB94D9ULL, 0x63912430770E6F68ULL, 0x6EC8A5E602C6641CULL, 0x87282515337DDD2BULL, 0x2CDA6B42034B701BULL, 0xB03D37C181CB096DULL, 0xE108438266C71C6FULL, 0x2B3180C7EB51B255ULL, 0xDF92B82F96C08BBCULL, 0x5C68C8C0A632F3BAULL, 0x5504CC861C3D0556ULL, 0xABBFA4E55FB26B8FULL, 0x41848B0AB3BACEB4ULL, 0xB334A273AA445D32ULL, 0xBCA696F0A85AD881ULL, 0x24F6EC65B528D56CULL, 0x0CE1512E90F4524AULL, 0x4E9DD79D5506D35AULL, 0x258905FAC6CE9779ULL, 0x2019295B3E109B33ULL, 0xF8A9478B73A054CCULL, 0x2924F2F934417EB0ULL, 0x3993357D536D1BC4ULL, 0x38A81AC21DB6FF8BULL, 0x47C4FBF17D6016BFULL, 0x1E0FAADD7667E3F5ULL, 0x7ABCFF62938BEB96ULL, 0xA78DAD948FC179C9ULL, 0x8F1F98B72911E50DULL, 0x61E48EAE27121A91ULL, 0x4D62F7AD31859808ULL, 0xECEBA345EF5CEAEBULL, 0xF5CEB25EBC9684CEULL, 0xF633E20CB7F76221ULL, 0xA32CDF06AB8293E4ULL, 0x985A202CA5EE2CA4ULL, 0xCF0B8447CC8A8FB1ULL, 0x9F765244979859A3ULL, 0xA8D516B1A1240017ULL, 0x0BD7BA3EBB5DC726ULL, 0xE54BCA55B86ADB39ULL, 0x1D7A3AFD6C478063ULL, 0x519EC608E7669EDDULL, 0x0E5715A2D149AA23ULL, 0x177D4571848FF194ULL, 0xEEB55F3241014C22ULL, 0x0F5E5CA13A6E2EC2ULL, 0x8029927B75F5C361ULL, 0xAD139FABC3D6E436ULL, 0x0D5DF1A94CCF402FULL, 0x3E8BD948BEA5DFC8ULL, 0xA5A0D357BD3FF77EULL, 0xA2D12E251F74F645ULL, 0x66FD9E525E81A082ULL, 0x2E0C90CE7F687A49ULL, 0xC2E8BCBEBA973BC5ULL, 0x000001BCE509745FULL, 0x423777BBE6DAB3D6ULL, 0xD1661C7EAEF06EB5ULL, 0xA1781F354DAACFD8ULL, 0x2D11284A2B16AFFCULL, 0xF1FC4F67FA891D1FULL, 0x73ECC25DCB920ADAULL, 0xAE610C22C2A12651ULL, 0x96E0A810D356B78AULL, 0x5A9A381F2FE7870FULL, 0xD5AD62EDE94E5530ULL, 0xD225E5E8368D1427ULL, 0x65977B70C7AF4631ULL, 0x99F889B2DE39D74FULL, 0x233F30BF54E1D143ULL, 0x9A9675D3D9A63C97ULL, 0x5470554FF334F9A8ULL, 0x166ACB744A4F5688ULL, 0x70C74CAAB2E4AEADULL, 0xF0D091646F294D12ULL, 0x57B82A89684031D1ULL, 0xEFD95A5A61BE0B6BULL, 0x2FBD12E969F2F29AULL, 0x9BD37013FEFF9FE8ULL, 0x3F9B0404D6085A06ULL, 0x4940C1F3166CFE15ULL, 0x09542C4DCDF3DEFBULL, 0xB4C5218385CD5CE3ULL, 0xC935B7DC4462A641ULL, 0x3417F8A68ED3B63FULL, 0xB80959295B215B40ULL, 0xF99CDAEF3B8C8572ULL, 0x018C0614F8FCB95DULL, 0x1B14ACCD1A3ACDF3ULL, 0x84D471F200BB732DULL, 0xC1A3110E95E8DA16ULL, 0x430A7220BF1A82B8ULL, 0xB77E090D39DF210EULL, 0x5EF4BD9F3CD05E9DULL, 0x9D4FF6DA7E57A444ULL, 0xDA1D60E183D4A5F8ULL, 0xB287C38417998E47ULL, 0xFE3EDC121BB31886ULL, 0xC7FE3CCC980CCBEFULL, 0xE46FB590189BFD03ULL, 0x3732FD469A4C57DCULL, 0x7EF700A07CF1AD65ULL, 0x59C64468A31D8859ULL, 0x762FB0B4D45B61F6ULL, 0x155BAED099047718ULL, 0x68755E4C3D50BAA6ULL, 0xE9214E7F22D8B4DFULL, 0x2ADDBF532EAC95F4ULL, 0x32AE3909B4BD0109ULL, 0x834DF537B08E3450ULL, 0xFA209DA84220728DULL, 0x9E691D9B9EFE23F7ULL, 0x0446D288C4AE8D7FULL, 0x7B4CC524E169785BULL, 0x21D87F0135CA1385ULL, 0xCEBB400F137B8AA5ULL, 0x272E2B66580796BEULL, 0x3612264125C2B0DEULL, 0x057702BDAD1EFBB2ULL, 0xD4BABB8EACF84BE9ULL, 0x91583139641BC67BULL, 0x8BDC2DE08036E024ULL, 0x603C8156F49F68EDULL, 0xF7D236F7DBEF5111ULL, 0x9727C4598AD21E80ULL, 0xA08A0896670A5FD7ULL, 0xCB4A8F4309EBA9CBULL, 0x81AF564B0F7036A1ULL, 0xC0B99AA778199ABDULL, 0x959F1EC83FC8E952ULL, 0x8C505077794A81B9ULL, 0x3ACAAF8F056338F0ULL, 0x07B43F50627A6778ULL, 0x4A44AB49F5ECCC77ULL, 0x3BC3D6E4B679EE98ULL, 0x9CC0D4D1CF14108CULL, 0x4406C00B206BC8A0ULL, 0x82A18854C8D72D89ULL, 0x67E366B35C3C432CULL, 0xB923DD61102B37F2ULL, 0x56AB2779D884271DULL, 0xBE83E1B0FF1525AFULL, 0xFB7C65D4217E49A9ULL, 0x6BDBE0E76D48E7D4ULL, 0x08DF828745D9179EULL, 0x22EA6A9ADD53BD34ULL, 0xE36E141C5622200AULL, 0x7F805D1B8CB750EEULL, 0xAFE5C7A59F58E837ULL, 0xE27F996A4FB1C23CULL, 0xD3867DFB0775F0D0ULL, 0xD0E673DE6E88891AULL, 0x123AEB9EAFB86C25ULL, 0x30F1D5D5C145B895ULL, 0xBB434A2DEE7269E7ULL, 0x78CB67ECF931FA38ULL, 0xF33B0372323BBF9CULL, 0x52D66336FB279C74ULL, 0x505F33AC0AFB4EAAULL, 0xE8A5CD99A2CCE187ULL, 0x534974801E2D30BBULL, 0x8D2D5711D5876D90ULL, 0x1F1A412891BC038EULL, 0xD6E2E71D82E56648ULL, 0x74036C3A497732B7ULL, 0x89B67ED96361F5ABULL, 0xFFED95D8F1EA02A2ULL, 0xE72B3BD61464D43DULL, 0xA6300F170BDC4820ULL, 0xEBC18760ED78A77AULL, 0xE6A6BE5A05A12138ULL, 0xB5A122A5B4F87C98ULL, 0x563C6089140B6990ULL, 0x4C46CB2E391F5DD5ULL, 0xD932ADDBC9B79434ULL, 0x08EA70E42015AFF5ULL, 0xD765A6673E478CF1ULL, 0xC4FB757EAB278D99ULL, 0xDF11C6862D6E0692ULL, 0xDDEB84F10D7F3B16ULL, 0x6F2EF604A665EA04ULL, 0x4A8E0F0FF0E0DFB3ULL, 0xA5EDEEF83DBCBA51ULL, 0xFC4F0A2A0EA4371EULL, 0xE83E1DA85CB38429ULL, 0xDC8FF882BA1B1CE2ULL, 0xCD45505E8353E80DULL, 0x18D19A00D4DB0717ULL, 0x34A0CFEDA5F38101ULL, 0x0BE77E518887CAF2ULL, 0x1E341438B3C45136ULL, 0xE05797F49089CCF9ULL, 0xFFD23F9DF2591D14ULL, 0x543DDA228595C5CDULL, 0x661F81FD99052A33ULL, 0x8736E641DB0F7B76ULL, 0x15227725418E5307ULL, 0xE25F7F46162EB2FAULL, 0x48A8B2126C13D9FEULL, 0xAFDC541792E76EEAULL, 0x03D912BFC6D1898FULL, 0x31B1AAFA1B83F51BULL, 0xF1AC2796E42AB7D9ULL, 0x40A3A7D7FCD2EBACULL, 0x1056136D0AFBBCC5ULL, 0x7889E1DD9A6D0C85ULL, 0xD33525782A7974AAULL, 0xA7E25D09078AC09BULL, 0xBD4138B3EAC6EDD0ULL, 0x920ABFBE71EB9E70ULL, 0xA2A5D0F54FC2625CULL, 0xC054E36B0B1290A3ULL, 0xF6DD59FF62FE932BULL, 0x3537354511A8AC7DULL, 0xCA845E9172FADCD4ULL, 0x84F82B60329D20DCULL, 0x79C62CE1CD672F18ULL, 0x8B09A2ADD124642CULL, 0xD0C1E96A19D9E726ULL, 0x5A786A9B4BA9500CULL, 0x0E020336634C43F3ULL, 0xC17B474AEB66D822ULL, 0x6A731AE3EC9BAAC2ULL, 0x8226667AE0840258ULL, 0x67D4567691CAECA5ULL, 0x1D94155C4875ADB5ULL, 0x6D00FD985B813FDFULL, 0x51286EFCB774CD06ULL, 0x5E8834471FA744AFULL, 0xF72CA0AEE761AE2EULL, 0xBE40E4CDAEE8E09AULL, 0xE9970BBB5118F665ULL, 0x726E4BEB33DF1964ULL, 0x703B000729199762ULL, 0x4631D816F5EF30A7ULL, 0xB880B5B51504A6BEULL, 0x641793C37ED84B6CULL, 0x7B21ED77F6E97D96ULL, 0x776306312EF96B73ULL, 0xAE528948E86FF3F4ULL, 0x53DBD7F286A3F8F8ULL, 0x16CADCE74CFC1063ULL, 0x005C19BDFA52C6DDULL, 0x68868F5D64D46AD3ULL, 0x3A9D512CCF1E186AULL, 0x367E62C2385660AEULL, 0xE359E7EA77DCB1D7ULL, 0x526C0773749ABE6EULL, 0x735AE5F9D09F734BULL, 0x493FC7CC8A558BA8ULL, 0xB0B9C1533041AB45ULL, 0x321958BA470A59BDULL, 0x852DB00B5F46C393ULL, 0x91209B2BD336B0E5ULL, 0x6E604F7D659EF19FULL, 0xB99A8AE2782CCB24ULL, 0xCCF52AB6C814C4C7ULL, 0x4727D9AFBE11727BULL, 0x7E950D0C0121B34DULL, 0x756F435670AD471FULL, 0xF5ADD442615A6849ULL, 0x4E87E09980B9957AULL, 0x2ACFA1DF50AEE355ULL, 0xD898263AFD2FD556ULL, 0xC8F4924DD80C8FD6ULL, 0xCF99CA3D754A173AULL, 0xFE477BACAF91BF3CULL, 0xED5371F6D690C12DULL, 0x831A5C285E687094ULL, 0xC5D3C90A3708A0A4ULL, 0x0F7F903717D06580ULL, 0x19F9BB13B8FDF27FULL, 0xB1BD6F1B4D502843ULL, 0x1C761BA38FFF4012ULL, 0x0D1530C4E2E21F3BULL, 0x8943CE69A7372C8AULL, 0xE5184E11FEB5CE66ULL, 0x618BDB80BD736621ULL, 0x7D29BAD68B574D0BULL, 0x81BB613E25E6FE5BULL, 0x071C9C10BC07913FULL, 0xC7BEEB7909AC2D97ULL, 0xC3E58D353BC5D757ULL, 0xEB017892F38F61E8ULL, 0xD4EFFB9C9B1CC21AULL, 0x99727D26F494F7ABULL, 0xA3E063A2956B3E03ULL, 0x9D4A8B9A4AA09C30ULL, 0x3F6AB7D500090FB4ULL, 0x9CC0F2A057268AC0ULL, 0x3DEE9D2DEDBF42D1ULL, 0x330F49C87960A972ULL, 0xC6B2720287421B41ULL, 0x0AC59EC07C00369CULL, 0xEF4EAC49CB353425ULL, 0xF450244EEF0129D8ULL, 0x8ACC46E5CAF4DEB6ULL, 0x2FFEAB63989263F7ULL, 0x8F7CB9FE5D7A4578ULL, 0x5BD8F7644E634635ULL, 0x427A7315BF2DC900ULL, 0x17D0C4AA2125261CULL, 0x3992486C93518E50ULL, 0xB4CBFEE0A2D7D4C3ULL, 0x7C75D6202C5DDD8DULL, 0xDBC295D8E35B6C61ULL, 0x60B369D302032B19ULL, 0xCE42685FDCE44132ULL, 0x06F3DDB9DDF65610ULL, 0x8EA4D21DB5E148F0ULL, 0x20B0FCE62FCD496FULL, 0x2C1B912358B0EE31ULL, 0xB28317B818F5A308ULL, 0xA89C1E189CA6D2CFULL, 0x0C6B18576AAADBC8ULL, 0xB65DEAA91299FAE3ULL, 0xFB2B794B7F1027E7ULL, 0x04E4317F443B5BEBULL, 0x4B852D325939D0A6ULL, 0xD5AE6BEEFB207FFCULL, 0x309682B281C7D374ULL, 0xBAE309A194C3B475ULL, 0x8CC3F97B13B49F05ULL, 0x98A9422FF8293967ULL, 0x244B16B01076FF7CULL, 0xF8BF571C663D67EEULL, 0x1F0D6758EEE30DA1ULL, 0xC9B611D97ADEB9B7ULL, 0xB7AFD5887B6C57A2ULL, 0x6290AE846B984FE1ULL, 0x94DF4CDEACC1A5FDULL, 0x058A5BD1C5483AFFULL, 0x63166CC142BA3C37ULL, 0x8DB8526EB2F76F40ULL, 0xE10880036F0D6D4EULL, 0x9E0523C9971D311DULL, 0x45EC2824CC7CD691ULL, 0x575B8359E62382C9ULL, 0xFA9E400DC4889995ULL, 0xD1823ECB45721568ULL, 0xDAFD983B8206082FULL, 0xAA7D29082386A8CBULL, 0x269FCD4403B87588ULL, 0x1B91F5F728BDD1E0ULL, 0xE4669F39040201F6ULL, 0x7A1D7C218CF04ADEULL, 0x65623C29D79CE5CEULL, 0x2368449096C00BB1ULL, 0xAB9BF1879DA503BAULL, 0xBC23ECB1A458058EULL, 0x9A58DF01BB401ECCULL, 0xA070E868A85F143DULL, 0x4FF188307DF2239EULL, 0x14D565B41A641183ULL, 0xEE13337452701602ULL, 0x950E3DCF3F285E09ULL, 0x59930254B9C80953ULL, 0x3BF299408930DA6DULL, 0xA955943F53691387ULL, 0xA15EDECAA9CB8784ULL, 0x29142127352BE9A0ULL, 0x76F0371FFF4E7AFBULL, 0x0239F450274F2228ULL, 0xBB073AF01D5E868BULL, 0xBFC80571C10E96C1ULL, 0xD267088568222E23ULL, 0x9671A3D48E80B5B0ULL, 0x55B5D38AE193BB81ULL, 0x693AE2D0A18B04B8ULL, 0x5C48B4ECADD5335FULL, 0xFD743B194916A1CAULL, 0x2577018134BE98C4ULL, 0xE77987E83C54A4ADULL, 0x28E11014DA33E1B9ULL, 0x270CC59E226AA213ULL, 0x71495F756D1A5F60ULL, 0x9BE853FB60AFEF77ULL, 0xADC786A7F7443DBFULL, 0x0904456173B29A82ULL, 0x58BC7A66C232BD5EULL, 0xF306558C673AC8B2ULL, 0x41F639C6B6C9772AULL, 0x216DEFE99FDA35DAULL, 0x11640CC71C7BE615ULL, 0x93C43694565C5527ULL, 0xEA038E6246777839ULL, 0xF9ABF3CE5A3E2469ULL, 0x741E768D0FD312D2ULL, 0x0144B883CED652C6ULL, 0xC20B5A5BA33F8552ULL, 0x1AE69633C3435A9DULL, 0x97A28CA4088CFDECULL, 0x8824A43C1E96F420ULL, 0x37612FA66EEEA746ULL, 0x6B4CB165F9CF0E5AULL, 0x43AA1C06A0ABFB4AULL, 0x7F4DC26FF162796BULL, 0x6CBACC8E54ED9B0FULL, 0xA6B7FFEFD2BB253EULL, 0x2E25BC95B0A29D4FULL, 0x86D6A58BDEF1388CULL, 0xDED74AC576B6F054ULL, 0x8030BDBC2B45805DULL, 0x3C81AF70E94D9289ULL, 0x3EFF6DDA9E3100DBULL, 0xB38DC39FDFCC8847ULL, 0x123885528D17B87EULL, 0xF2DA0ED240B1B642ULL, 0x44CEFADCD54BF9A9ULL, 0x1312200E433C7EE6ULL, 0x9FFCC84F3A78C748ULL, 0xF0CD1F72248576BBULL, 0xEC6974053638CFE4ULL, 0x2BA7B67C0CEC4E4CULL, 0xAC2F4DF3E5CE32EDULL, 0xCB33D14326EA4C11ULL, 0xA4E9044CC77E58BCULL, 0x5F513293D934FCEFULL, 0x5DC9645506E55444ULL, 0x50DE418F317DE40AULL, 0x388CB31A69DDE259ULL, 0x2DB4A83455820A86ULL, 0x9010A91E84711AE9ULL, 0x4DF7F0B7B1498371ULL, 0xD62A2EABC0977179ULL, 0x22FAC097AA8D5C0EULL, 0xF49FCC2FF1DAF39BULL, 0x487FD5C66FF29281ULL, 0xE8A30667FCDCA83FULL, 0x2C9B4BE3D2FCCE63ULL, 0xDA3FF74B93FBBBC2ULL, 0x2FA165D2FE70BA66ULL, 0xA103E279970E93D4ULL, 0xBECDEC77B0E45E71ULL, 0xCFB41E723985E497ULL, 0xB70AAA025EF75017ULL, 0xD42309F03840B8E0ULL, 0x8EFC1AD035898579ULL, 0x96C6920BE2B2ABC5ULL, 0x66AF4163375A9172ULL, 0x2174ABDCCA7127FBULL, 0xB33CCEA64A72FF41ULL, 0xF04A4933083066A5ULL, 0x8D970ACDD7289AF5ULL, 0x8F96E8E031C8C25EULL, 0xF3FEC02276875D47ULL, 0xEC7BF310056190DDULL, 0xF5ADB0AEBB0F1491ULL, 0x9B50F8850FD58892ULL, 0x4975488358B74DE8ULL, 0xA3354FF691531C61ULL, 0x0702BBE481D2C6EEULL, 0x89FB24057DEDED98ULL, 0xAC3075138596E902ULL, 0x1D2D3580172772EDULL, 0xEB738FC28E6BC30DULL, 0x5854EF8F63044326ULL, 0x9E5C52325ADD3BBEULL, 0x90AA53CF325C4623ULL, 0xC1D24D51349DD067ULL, 0x2051CFEEA69EA624ULL, 0x13220F0A862E7E4FULL, 0xCE39399404E04864ULL, 0xD9C42CA47086FCB7ULL, 0x685AD2238A03E7CCULL, 0x066484B2AB2FF1DBULL, 0xFE9D5D70EFBF79ECULL, 0x5B13B9DD9C481854ULL, 0x15F0D475ED1509ADULL, 0x0BEBCD060EC79851ULL, 0xD58C6791183AB7F8ULL, 0xD1187C5052F3EEE4ULL, 0xC95D1192E54E82FFULL, 0x86EEA14CB9AC6CA2ULL, 0x3485BEB153677D5DULL, 0xDD191D781F8C492AULL, 0xF60866BAA784EBF9ULL, 0x518F643BA2D08C74ULL, 0x8852E956E1087C22ULL, 0xA768CB8DC410AE8DULL, 0x38047726BFEC8E1AULL, 0xA67738B4CD3B45AAULL, 0xAD16691CEC0DDE19ULL, 0xC6D4319380462E07ULL, 0xC5A5876D0BA61938ULL, 0x16B9FA1FA58FD840ULL, 0x188AB1173CA74F18ULL, 0xABDA2F98C99C021FULL, 0x3E0580AB134AE816ULL, 0x5F3B05B773645ABBULL, 0x2501A2BE5575F2F6ULL, 0x1B2F74004E7E8BA9ULL, 0x1CD7580371E8D953ULL, 0x7F6ED89562764E30ULL, 0xB15926FF596F003DULL, 0x9F65293DA8C5D6B9ULL, 0x6ECEF04DD690F84CULL, 0x4782275FFF33AF88ULL, 0xE41433083F820801ULL, 0xFD0DFE409A1AF9B5ULL, 0x4325A3342CDB396BULL, 0x8AE77E62B301B252ULL, 0xC36F9E9F6655615AULL, 0x85455A2D92D32C09ULL, 0xF2C7DEA949477485ULL, 0x63CFB4C133A39EBAULL, 0x83B040CC6EBC5462ULL, 0x3B9454C8FDB326B0ULL, 0x56F56A9E87FFD78CULL, 0x2DC2940D99F42BC6ULL, 0x98F7DF096B096E2DULL, 0x19A6E01E3AD852BFULL, 0x42A99CCBDBD4B40BULL, 0xA59998AF45E9C559ULL, 0x366295E807D93186ULL, 0x6B48181BFAA1F773ULL, 0x1FEC57E2157A0A1DULL, 0x4667446AF6201AD5ULL, 0xE615EBCACFB0F075ULL, 0xB8F31F4F68290778ULL, 0x22713ED6CE22D11EULL, 0x3057C1A72EC3C93BULL, 0xCB46ACC37C3F1F2FULL, 0xDBB893FD02AAF50EULL, 0x331FD92E600B9FCFULL, 0xA498F96148EA3AD6ULL, 0xA8D8426E8B6A83EAULL, 0xA089B274B7735CDCULL, 0x87F6B3731E524A11ULL, 0x118808E5CBC96749ULL, 0x9906E4C7B19BD394ULL, 0xAFED7F7E9B24A20CULL, 0x6509EADEEB3644A7ULL, 0x6C1EF1D3E8EF0EDEULL, 0xB9C97D43E9798FB4ULL, 0xA2F2D784740C28A3ULL, 0x7B8496476197566FULL, 0x7A5BE3E6B65F069DULL, 0xF96330ED78BE6F10ULL, 0xEEE60DE77A076A15ULL, 0x2B4BEE4AA08B9BD0ULL, 0x6A56A63EC7B8894EULL, 0x02121359BA34FEF4ULL, 0x4CBF99F8283703FCULL, 0x398071350CAF30C8ULL, 0xD0A77A89F017687AULL, 0xF1C1A9EB9E423569ULL, 0x8C7976282DEE8199ULL, 0x5D1737A5DD1F7ABDULL, 0x4F53433C09A9FA80ULL, 0xFA8B0C53DF7CA1D9ULL, 0x3FD9DCBC886CCB77ULL, 0xC040917CA91B4720ULL, 0x7DD00142F9D1DCDFULL, 0x8476FC1D4F387B58ULL, 0x23F8E7C5F3316503ULL, 0x032A2244E7E37339ULL, 0x5C87A5D750F5A74BULL, 0x082B4CC43698992EULL, 0xDF917BECB858F63CULL, 0x3270B8FC5BF86DDAULL, 0x10AE72BB29B5DD76ULL, 0x576AC94E7700362BULL, 0x1AD112DAC61EFB8FULL, 0x691BC30EC5FAA427ULL, 0xFF246311CC327143ULL, 0x3142368E30E53206ULL, 0x71380E31E02CA396ULL, 0x958D5C960AAD76F1ULL, 0xF8D6F430C16DA536ULL, 0xC8FFD13F1BE7E1D2ULL, 0x7578AE66004DDBE1ULL, 0x05833F01067BE646ULL, 0xBB34B5AD3BFE586DULL, 0x095F34C9A12B97F0ULL, 0x247AB64525D60CA8ULL, 0xDCDBC6F3017477D1ULL, 0x4A2E14D4DECAD24DULL, 0xBDB5E6D9BE0A1EEBULL, 0x2A7E70F7794301ABULL, 0xDEF42D8A270540FDULL, 0x01078EC0A34C22C1ULL, 0xE5DE511AF4C16387ULL, 0x7EBB3A52BD9A330AULL, 0x77697857AA7D6435ULL, 0x004E831603AE4C32ULL, 0xE7A21020AD78E312ULL, 0x9D41A70C6AB420F2ULL, 0x28E06C18EA1141E6ULL, 0xD2B28CBD984F6B28ULL, 0x26B75F6C446E9D83ULL, 0xBA47568C4D418D7FULL, 0xD80BADBFE6183D8EULL, 0x0E206D7F5F166044ULL, 0xE258A43911CBCA3EULL, 0x723A1746B21DC0BCULL, 0xC7CAA854F5D7CDD3ULL, 0x7CAC32883D261D9CULL, 0x7690C26423BA942CULL, 0x17E55524478042B8ULL, 0xE0BE477656A2389FULL, 0x4D289B5E67AB2DA0ULL, 0x44862B9C8FBBFD31ULL, 0xB47CC8049D141365ULL, 0x822C1B362B91C793ULL, 0x4EB14655FB13DFD8ULL, 0x1ECBBA0714E2A97BULL, 0x6143459D5CDE5F14ULL, 0x53A8FBF1D5F0AC89ULL, 0x97EA04D81C5E5B00ULL, 0x622181A8D4FDB3F3ULL, 0xE9BCD341572A1208ULL, 0x1411258643CCE58AULL, 0x9144C5FEA4C6E0A4ULL, 0x0D33D06565CF620FULL, 0x54A48D489F219CA1ULL, 0xC43E5EAC6D63C821ULL, 0xA9728B3A72770DAFULL, 0xD7934E7B20DF87EFULL, 0xE35503B61A3E86E5ULL, 0xCAE321FBC819D504ULL, 0x129A50B3AC60BFA6ULL, 0xCD5E68EA7E9FB6C3ULL, 0xB01C90199483B1C7ULL, 0x3DE93CD5C295376CULL, 0xAED52EDF2AB9AD13ULL, 0x2E60F512C0A07884ULL, 0xBC3D86A3E36210C9ULL, 0x35269D9B163951CEULL, 0x0C7D6E2AD0CDB5FAULL, 0x59E86297D87F5733ULL, 0x298EF221898DB0E7ULL, 0x55000029D1A5AA7EULL, 0x8BC08AE1B5061B45ULL, 0xC2C31C2B6C92703AULL, 0x94CC596BAF25EF42ULL, 0x0A1D73DB22540456ULL, 0x04B6A0F9D9C4179AULL, 0xEFFDAFA2AE3D3C60ULL, 0xF7C8075BB49496C4ULL, 0x9CC5C7141D1CD4E3ULL, 0x78BD1638218E5534ULL, 0xB2F11568F850246AULL, 0xEDFABCFA9502BC29ULL, 0x796CE5F2DA23051BULL, 0xAAE128B0DC93537CULL, 0x3A493DA0EE4B29AEULL, 0xB5DF6B2C416895D7ULL, 0xFCABBD25122D7F37ULL, 0x70810B58105DC4B1ULL, 0xE10FDD37F7882A90ULL, 0x524DCAB5518A3F5CULL, 0x3C9E85878451255BULL, 0x4029828119BD34E2ULL, 0x74A05B6F5D3CECCBULL, 0xB610021542E13ECAULL, 0x0FF979D12F59E2ACULL, 0x6037DA27E4F9CC50ULL, 0x5E92975A0DF1847DULL, 0xD66DE190D3E623FEULL, 0x5032D6B87B568048ULL, 0x9A36B7CE8235216EULL, 0x80272A7A24F64B4AULL, 0x93EFED8B8C6916F7ULL, 0x37DDBFF44CCE1555ULL, 0x4B95DB5D4B99BD25ULL, 0x92D3FDA169812FC0ULL, 0xFB1A4A9A90660BB6ULL, 0x730C196946A4B9B2ULL, 0x81E289AA7F49DA68ULL, 0x64669A0F83B1A05FULL, 0x27B3FF7D9644F48BULL, 0xCC6B615C8DB675B3ULL, 0x674F20B9BCEBBE95ULL, 0x6F31238275655982ULL, 0x5AE488713E45CF05ULL, 0xBF619F9954C21157ULL, 0xEABAC46040A8EAE9ULL, 0x454C6FE9F2C0C1CDULL, 0x419CF6496412691CULL, 0xD3DC3BEF265B0F70ULL, 0x6D0E60F5C3578A9EULL, 0x5B0E608526323C55ULL, 0x1A46C1A9FA1B59F5ULL, 0xA9E245A17C4C8FFAULL, 0x65CA5159DB2955D7ULL, 0x05DB0A76CE35AFC2ULL, 0x81EAC77EA9113D45ULL, 0x528EF88AB6AC0A0DULL, 0xA09EA253597BE3FFULL, 0x430DDFB3AC48CD56ULL, 0xC4B3A67AF45CE46FULL, 0x4ECECFD8FBE2D05EULL, 0x3EF56F10B39935F0ULL, 0x0B22D6829CD619C6ULL, 0x17FD460A74DF2069ULL, 0x6CF8CC8E8510ED40ULL, 0xD6C824BF3A6ECAA7ULL, 0x61243D581A817049ULL, 0x048BACB6BBC163A2ULL, 0xD9A38AC27D44CC32ULL, 0x7FDDFF5BAAF410ABULL, 0xAD6D495AA804824BULL, 0xE1A6A74F2D8C9F94ULL, 0xD4F7851235DEE8E3ULL, 0xFD4B7F886540D893ULL, 0x247C20042AA4BFDAULL, 0x096EA1C517D1327CULL, 0xD56966B4361A6685ULL, 0x277DA5C31221057DULL, 0x94D59893A43ACFF7ULL, 0x64F0C51CCDC02281ULL, 0x3D33BCC4FF6189DBULL, 0xE005CB184CE66AF1ULL, 0xFF5CCD1D1DB99BEAULL, 0xB0B854A7FE42980FULL, 0x7BD46A6A718D4B9FULL, 0xD10FA8CC22A5FD8CULL, 0xD31484952BE4BD31ULL, 0xC7FA975FCB243847ULL, 0x4886ED1E5846C407ULL, 0x28CDDB791EB70B04ULL, 0xC2B00BE2F573417FULL, 0x5C9590452180F877ULL, 0x7A6BDDFFF370EB00ULL, 0xCE509E38D6D9D6A4ULL, 0xEBEB0F00647FA702ULL, 0x1DCC06CF76606F06ULL, 0xE4D9F28BA286FF0AULL, 0xD85A305DC918C262ULL, 0x475B1D8732225F54ULL, 0x2D4FB51668CCB5FEULL, 0xA679B9D9D72BBA20ULL, 0x53841C0D912D43A5ULL, 0x3B7EAA48BF12A4E8ULL, 0x781E0E47F22F1DDFULL, 0xEFF20CE60AB50973ULL, 0x20D261D19DFFB742ULL, 0x16A12B03062A2E39ULL, 0x1960EB2239650495ULL, 0x251C16FED50EB8B8ULL, 0x9AC0C330F826016EULL, 0xED152665953E7671ULL, 0x02D63194A6369570ULL, 0x5074F08394B1C987ULL, 0x70BA598C90B25CE1ULL, 0x794A15810B9742F6ULL, 0x0D5925E9FCAF8C6CULL, 0x3067716CD868744EULL, 0x910AB077E8D7731BULL, 0x6A61BBDB5AC42F61ULL, 0x93513EFBF0851567ULL, 0xF494724B9E83E9D5ULL, 0xE887E1985C09648DULL, 0x34B1D3C675370CFDULL, 0xDC35E433BC0D255DULL, 0xD0AAB84234131BE0ULL, 0x08042A50B48B7EAFULL, 0x9997C4EE44A3AB35ULL, 0x829A7B49201799D0ULL, 0x263B8307B7C54441ULL, 0x752F95F4FD6A6CA6ULL, 0x927217402C08C6E5ULL, 0x2A8AB754A795D9EEULL, 0xA442F7552F72943DULL, 0x2C31334E19781208ULL, 0x4FA98D7CEAEE6291ULL, 0x55C3862F665DB309ULL, 0xBD0610175D53B1F3ULL, 0x46FE6CB840413F27ULL, 0x3FE03792DF0CFA59ULL, 0xCFE700372EB85E8FULL, 0xA7BE29E7ADBCE118ULL, 0xE544EE5CDE8431DDULL, 0x8A781B1B41F1873EULL, 0xA5C94C78A0D2F0E7ULL, 0x39412E2877B60728ULL, 0xA1265EF3AFC9A62CULL, 0xBCC2770C6A2506C5ULL, 0x3AB66DD5DCE1CE12ULL, 0xE65499D04A675B37ULL, 0x7D8F523481BFD216ULL, 0x0F6F64FCEC15F389ULL, 0x74EFBE618B5B13C8ULL, 0xACDC82B714273E1DULL, 0xDD40BFE003199D17ULL, 0x37E99257E7E061F8ULL, 0xFA52626904775AAAULL, 0x8BBBF63A463D56F9ULL, 0xF0013F1543A26E64ULL, 0xA8307E9F879EC898ULL, 0xCC4C27A4150177CCULL, 0x1B432F2CCA1D3348ULL, 0xDE1D1F8F9F6FA013ULL, 0x606602A047A7DDD6ULL, 0xD237AB64CC1CB2C7ULL, 0x9B938E7225FCD1D3ULL, 0xEC4E03708E0FF476ULL, 0xFEB2FBDA3D03C12DULL, 0xAE0BCED2EE43889AULL, 0x22CB8923EBFB4F43ULL, 0x69360D013CF7396DULL, 0x855E3602D2D4E022ULL, 0x073805BAD01F784CULL, 0x33E17A133852F546ULL, 0xDF4874058AC7B638ULL, 0xBA92B29C678AA14AULL, 0x0CE89FC76CFAADCDULL, 0x5F9D4E0908339E34ULL, 0xF1AFE9291F5923B9ULL, 0x6E3480F60F4A265FULL, 0xEEBF3A2AB29B841CULL, 0xE21938A88F91B4ADULL, 0x57DFEFF845C6D3C3ULL, 0x2F006B0BF62CAAF2ULL, 0x62F479EF6F75EE78ULL, 0x11A55AD41C8916A9ULL, 0xF229D29084FED453ULL, 0x42F1C27B16B000E6ULL, 0x2B1F76749823C074ULL, 0x4B76ECA3C2745360ULL, 0x8C98F463B91691BDULL, 0x14BCC93CF1ADE66AULL, 0x8885213E6D458397ULL, 0x8E177DF0274D4711ULL, 0xB49B73B5503F2951ULL, 0x10168168C3F96B6BULL, 0x0E3D963B63CAB0AEULL, 0x8DFC4B5655A1DB14ULL, 0xF789F1356E14DE5CULL, 0x683E68AF4E51DAC1ULL, 0xC9A84F9D8D4B0FD9ULL, 0x3691E03F52A0F9D1ULL, 0x5ED86E46E1878E80ULL, 0x3C711A0E99D07150ULL, 0x5A0865B20C4E9310ULL, 0x56FBFC1FE4F0682EULL, 0xEA8D5DE3105EDF9BULL, 0x71ABFDB12379187AULL, 0x2EB99DE1BEE77B9CULL, 0x21ECC0EA33CF4523ULL, 0x59A4D7521805C7A1ULL, 0x3896F5EB56AE7C72ULL, 0xAA638F3DB18F75DCULL, 0x9F39358DABE9808EULL, 0xB7DEFA91C00B72ACULL, 0x6B5541FD62492D92ULL, 0x6DC6DEE8F92E4D5BULL, 0x353F57ABC4BEEA7EULL, 0x735769D6DA5690CEULL, 0x0A234AA642391484ULL, 0xF6F9508028F80D9DULL, 0xB8E319A27AB3F215ULL, 0x31AD9C1151341A4DULL, 0x773C22A57BEF5805ULL, 0x45C7561A07968633ULL, 0xF913DA9E249DBE36ULL, 0xDA652D9B78A64C68ULL, 0x4C27A97F3BC334EFULL, 0x76621220E66B17F4ULL, 0x967743899ACD7D0BULL, 0xF3EE5BCAE0ED6782ULL, 0x409F753600C879FCULL, 0x06D09A39B5926DB6ULL, 0x6F83AEB0317AC588ULL, 0x01E6CA4A86381F21ULL, 0x66FF3462D19F3025ULL, 0x72207C24DDFD3BFBULL, 0x4AF6B6D3E2ECE2EBULL, 0x9C994DBEC7EA08DEULL, 0x49ACE597B09A8BC4ULL, 0xB38C4766CF0797BAULL, 0x131B9373C57C2A75ULL, 0xB1822CCE61931E58ULL, 0x9D7555B909BA1C0CULL, 0x127FAFDD937D11D2ULL, 0x29DA3BADC66D92E4ULL, 0xA2C1D57154C2ECBCULL, 0x58C5134D82F6FE24ULL, 0x1C3AE3515B62274FULL, 0xE907C82E01CB8126ULL, 0xF8ED091913E37FCBULL, 0x3249D8F9C80046C9ULL, 0x80CF9BEDE388FB63ULL, 0x1881539A116CF19EULL, 0x5103F3F76BD52457ULL, 0x15B7E6F5AE47F7A8ULL, 0xDBD7C6DED47E9CCFULL, 0x44E55C410228BB1AULL, 0xB647D4255EDB4E99ULL, 0x5D11882BB8AAFC30ULL, 0xF5098BBB29D3212AULL, 0x8FB5EA14E90296B3ULL, 0x677B942157DD025AULL, 0xFB58E7C0A390ACB5ULL, 0x89D3674C83BD4A01ULL, 0x9E2DA4DF4BF3B93BULL, 0xFCC41E328CAB4829ULL, 0x03F38C96BA582C52ULL, 0xCAD1BDBD7FD85DB2ULL, 0xBBB442C16082AE83ULL, 0xB95FE86BA5DA9AB0ULL, 0xB22E04673771A93FULL, 0x845358C9493152D8ULL, 0xBE2A488697B4541EULL, 0x95A2DC2DD38E6966ULL, 0xC02C11AC923C852BULL, 0x2388B1990DF2A87BULL, 0x7C8008FA1B4F37BEULL, 0x1F70D0C84D54E503ULL, 0x5490ADEC7ECE57D4ULL, 0x002B3C27D9063A3AULL, 0x7EAEA3848030A2BFULL, 0xC602326DED2003C0ULL, 0x83A7287D69A94086ULL, 0xC57A5FCB30F57A8AULL, 0xB56844E479EBE779ULL, 0xA373B40F05DCBCE9ULL, 0xD71A786E88570EE2ULL, 0x879CBACDBDE8F6A0ULL, 0x976AD1BCC164A32FULL, 0xAB21E25E9666D78BULL, 0x901063AAE5E5C33CULL, 0x9818B34448698D90ULL, 0xE36487AE3E1E8ABBULL, 0xAFBDF931893BDCB4ULL, 0x6345A0DC5FBBD519ULL, 0x8628FE269B9465CAULL, 0x1E5D01603F9C51ECULL, 0x4DE44006A15049B7ULL, 0xBF6C70E5F776CBB1ULL, 0x411218F2EF552BEDULL, 0xCB0C0708705A36A3ULL, 0xE74D14754F986044ULL, 0xCD56D9430EA8280EULL, 0xC12591D7535F5065ULL, 0xC83223F1720AEF96ULL, 0xC3A0396F7363A51FULL }; modelrockettier-uhub-a8ee6e7/src/util/tiger.h000066400000000000000000000016161324501300100213750ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2014, 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 . * */ #ifndef HAVE_UHUB_HASH_TIGER_H #define HAVE_UHUB_HASH_TIGER_H extern void tiger(uint64_t* str, uint64_t length, uint64_t* res); #endif /* HAVE_UHUB_HASH_TIGER_H */ modelrockettier-uhub-a8ee6e7/src/version.h.in000066400000000000000000000022111324501300100213700ustar00rootroot00000000000000/* * uhub - A tiny ADC p2p connection hub * Copyright (C) 2007-2013, 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 . * */ /* THIS FILE IS AUTO-GENERATED BY CMAKE - DO NOT EDIT MANUALLY! */ #ifndef VERSION #define VERSION "@UHUB_VERSION_MAJOR@.@UHUB_VERSION_MINOR@.@UHUB_VERSION_PATCH@" #endif #define GIT_VERSION "@UHUB_GIT_VERSION@" #ifndef PRODUCT #define PRODUCT "uhub" #endif #define PRODUCT_STRING PRODUCT "/" GIT_VERSION #ifndef COPYRIGHT #define COPYRIGHT "Copyright (c) 2007-2014, Jan Vidar Krey " #endif modelrockettier-uhub-a8ee6e7/thirdparty/000077500000000000000000000000001324501300100205345ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/thirdparty/sqlite/000077500000000000000000000000001324501300100220355ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/tools/000077500000000000000000000000001324501300100175025ustar00rootroot00000000000000modelrockettier-uhub-a8ee6e7/tools/adc-redirector000077500000000000000000000015671324501300100223300ustar00rootroot00000000000000#!/usr/bin/perl -w # Setup using inetd/xinetd or similar. # In /etc/inetd.conf add: # 1511 stream tcp nowait nobody /usr/bin/adc-redirector adc://target:port # # Change port to whatever you want. # Make sure the path and the target:port is correct, then you should be good # to go! use strict; use IO::Handle; autoflush STDIN; autoflush STDOUT; my $target = $ARGV[0]; eval { local %SIG; $SIG{ALRM}= sub { exit 0; }; alarm 30; }; while (my $line = ) { chomp($line); if ($line =~ /^HSUP /) { print "ISUP ADBASE ADPING ADTIGR\n"; print "ISID AAAX\n"; print "IINF CT32 NIRedirector VEadc-redirector/0.1\n"; next; } if ($line =~ /^BINF /) { print "$line\n"; print "IMSG This\\sserver\\shas\\smoved\\sto:\\s" . $target . "\n"; print "IMSG You\\sare\\sbeing\\sredirected...\n"; print "IQUI AAAX RD" . $target . "\n"; alarm 5; } } alarm 0; modelrockettier-uhub-a8ee6e7/tools/convert_to_sqlite.pl000077500000000000000000000010121324501300100235770ustar00rootroot00000000000000#!/usr/bin/perl # Usage: # cat /etc/uhub/users.conf | tools/convert_to_sqlite.pl | sqlite3 users.db print <<_; CREATE TABLE users( nickname CHAR(64) UNIQUE, password CHAR(64), credentials CHAR(5), created TIMESTAMP DEFAULT (DATETIME('NOW')), activity TIMESTAMP DEFAULT (DATETIME('NOW')) ); _ sub e($) { (my $v = shift) =~ s/'/\\'/g; $v } s{^\s*user_(op|admin|super|reg)\s+([^#\s]+):([^#\s]+)}{ printf "INSERT INTO users (nickname, password, credentials) VALUES('%s','%s','%s');\n", e $2, e $3, $1 }eg while(<>); modelrockettier-uhub-a8ee6e7/tools/create_certificate.sh000077500000000000000000000006071324501300100236510ustar00rootroot00000000000000#!/bin/sh OPENSSL=/usr/bin/openssl NAME=certificate if [ ! -x ${OPENSSL} ]; then echo "Cannot locate the openssl utility: ${OPENSSL}" exit 1 fi ${OPENSSL} genrsa -out ${NAME}.key 1024 && ${OPENSSL} req -new -x509 -nodes -sha1 -days 365 -key ${NAME}.key > ${NAME}.crt && cat ${NAME}.key ${NAME}.crt > ${NAME}.pem && rm -f ${NAME}.key ${NAME}.crt echo "Created certificate ${NAME}.pem" modelrockettier-uhub-a8ee6e7/tools/fh2uh_regimport.pl000066400000000000000000000046271324501300100231540ustar00rootroot00000000000000#!/usr/bin/perl # A simple tool for importing FlexHub users to uhub sqlite database # # Usage: ./fh2uh_regimport.pl # # Note: uhub database has to be created before running this script. use File::Slurp; use Data::Dumper; use DBI; my @uhubaccounts; my $text = read_file $ARGV[0]; my $dbfile = $ARGV[1]; sub convertprofile { $flexprofile = $_[0]; if($flexprofile >= 0 && $flexprofile <= 3) { return 'user'; } elsif($flexprofile >= 4 && $flexprofile <= 6) { return 'operator'; } elsif($flexprofile >= 7 && $flexprofile <= 8) { return 'super'; } elsif($flexprofile >= 9 && $flexprofile <= 10) { return 'admin'; } return 'unknown'; } sub parseinfo { my @info = split('\n', $_[0]); for my $line (@info) { chop $line; my %reginfo; if ($line =~ /\["sNick"\]\s*=\s*\S+/) { my @nick = split(/\["sNick"\]\s*=\s*"(\S+)"/, $line); $reginfo->{'nickname'} = $nick[1]; } elsif ($line =~ /\["sPassword"\]\s*=\s*\S+/) { my @password = split(/\["sPassword"\]\s*=\s*"(\S+)"/, $line); $reginfo->{'password'} = $password[1]; } elsif ($line =~ /\["iLevel"\]\s*=\s*\S+/) { my @level = split(/\["iLevel"\]\s*=\s*(\d+)/, $line); $reginfo->{'credentials'} = convertprofile $level[1]; } elsif ($line =~ /\["iRegDate"\]\s*=\s*\S+/) { my @created = split(/\["iRegDate"\]\s*=\s*(\d+)/, $line); $reginfo->{'created'} = $created[1]; } elsif ($line =~ /\["iLastLogin"\]\s*=\s*\S+/) { my @activity = split(/\["iLastLogin"\]\s*=\s*(\d+)/, $line); $reginfo->{'activity'} = $activity[1]; } } return %{$reginfo}; } sub dbimport { my @arr = @_; my $db = DBI->connect("dbi:SQLite:dbname=$dbfile", "", "", {RaiseError => 1, AutoCommit => 1}); for my $import (@arr) { if ($import->{'credentials'} ne 'unknown') { $db->do("INSERT OR IGNORE INTO users (nickname,password,credentials,created,activity) VALUES('$import->{'nickname'}','$import->{'password'}','$import->{'credentials'}',datetime($import->{'created'}, 'unixepoch'),datetime($import->{'activity'}, 'unixepoch'));"); } } $db->disconnect(); } if ($text =~ /tAccounts = {/) { $text =~ s/^(?:.*\n){1}/},\n/; my @flexaccounts = split('},.*\n.*\[".+"\] = {', $text); shift(@flexaccounts); for my $account (@flexaccounts) { my %info = parseinfo $account; push(@uhubaccounts, \%info); } dbimport @uhubaccounts; } else { print "Provided file is not valid FlexHub userlist.\n"; }modelrockettier-uhub-a8ee6e7/tools/nmdc-redirector000077500000000000000000000007431324501300100225150ustar00rootroot00000000000000#!/usr/bin/perl -w # Setup using inetd/xinetd or similar. # In /etc/inetd.conf add: # 1511 stream tcp nowait nobody /usr/bin/nmdc-redirector adc://target:port # # Change port to whatever you want. # Make sure the path and the target:port is correct, then you should be good # to go! use strict; use IO::Handle; autoflush STDIN; autoflush STDOUT; my $target = $ARGV[0]; print " You are being redirected to " . $target . "|"; print "\$ForceMove " . $target . "|"; modelrockettier-uhub-a8ee6e7/tools/px2uh_regimport.pl000066400000000000000000000023471324501300100232030ustar00rootroot00000000000000#!/usr/bin/perl # A simple tool for importing PtokaX (< 0.5.0.0) users to uhub sqlite database. # Userlist MUST be in xml format. # # Usage: ./px2uh_regimport.pl # # Note: uhub database has to be created before running this script. use XML::Simple; use DBI; # create xml object my $xml = new XML::Simple; # read XML file my $regdata = $xml->XMLin($ARGV[0], ForceArray => [ 'RegisteredUser' ]); my $dbfile = $ARGV[1]; my @pxaccounts = @{$regdata->{'RegisteredUser'}}; sub convertprofile { $pxprofile = $_[0]; if($pxprofile == 2 || $pxprofile == 3) { return 'user'; } elsif($pxprofile == 1) { return 'operator'; } elsif($pxprofile == 0) { return 'admin'; } return 'unknown'; } sub dbimport { my @arr = @_; my $db = DBI->connect("dbi:SQLite:dbname=$dbfile", "", "", {RaiseError => 1, AutoCommit => 1}); for my $import (@arr) { if ($import->{'credentials'} ne 'unknown') { $db->do("INSERT OR IGNORE INTO users (nickname,password,credentials) VALUES('$import->{'Nick'}','$import->{'Password'}','$import->{'credentials'}');"); } } $db->disconnect(); } for my $account (@pxaccounts) { $account->{'credentials'} = convertprofile $account->{'Profile'}; } dbimport @pxaccounts; modelrockettier-uhub-a8ee6e7/tools/uhub-adc-redirector.py000077500000000000000000000025171324501300100237140ustar00rootroot00000000000000#!/usr/bin/env python """ A simple ADC redirector service. """ import SocketServer # The target hub we want to redirect clients to redirect_uri = "adcs://adcs.uhub.org:1511" # A message to be sent to users while they are being redirected. message = "This hub has been permanently moved." # The chat name of the message. bot_name = "Redirector" # The local address and port to bind the redirector to. bind_addr = "0.0.0.0" bind_port = 1411 class AdcRedirector(SocketServer.BaseRequestHandler): def escape(self, str): modified = str.replace("\\", "\\\\").replace(" ", "\\s").replace("\n", "\\n") return modified; def handle(self): supports = False; while True: data = self.request.recv(1024) if (data.startswith("HSUP") and not supports): self.request.sendall("ISUP ADBASE ADTIGR\nISID AAAX\nIINF CT32 NI%(botname)s VEuhub-adc-redirector/0.1\n" % { "address": redirect_uri, "botname": self.escape(bot_name), "message": self.escape(message) }) supports = True elif (data.startswith("BINF") and supports): self.request.sendall("IMSG %(message)s\nIQUI AAAX RD%(address)s\n" % {"message": self.escape(message), "address": redirect_uri }) break else: break if __name__ == "__main__": server = SocketServer.TCPServer((bind_addr, bind_port), AdcRedirector) server.allow_reuse_address = True server.serve_forever() modelrockettier-uhub-a8ee6e7/tools/uhub-nmdc-redirector.py000077500000000000000000000015211324501300100241000ustar00rootroot00000000000000#!/usr/bin/env python """ A simple NMDC to ADC redirector service. """ import SocketServer # The target hub we want to redirect clients to redirect_uri = "adcs://adcs.uhub.org:1511" # A message to be sent to users while they are being redirected. message = "This hub has been permanently moved." # The chat name of the message. bot_name = "Redirector" # The local address and port to bind the redirector to. bind_addr = "0.0.0.0" bind_port = 1411 class NmdcRedirector(SocketServer.BaseRequestHandler): def setup(self): self.request.sendall("<%(botname)s> %(message)s|$ForceMove %(address)s|" % { "address": redirect_uri, "botname": bot_name, "message": message }) return False if __name__ == "__main__": server = SocketServer.TCPServer((bind_addr, bind_port), NmdcRedirector) server.allow_reuse_address = True server.serve_forever()