Compare commits

...

25 Commits

Author SHA1 Message Date
Jan Vidar Krey
d98f013a51 Attempt to send messages via the Operations bot as private messages. 2013-02-14 02:36:37 +01:00
Jan Vidar Krey
2be48a13f7 Made sure we now have an 'Operations' user logged in.
This is still pretty much work in progress.
2013-02-14 00:16:18 +01:00
Jan Vidar Krey
70ba9d5831 Create a bot user system. 2013-02-13 21:10:13 +01:00
Jan Vidar Krey
f91f3ea68c Added funcions for sending notifications to operators.
Notifications could be compared to some sort of a log message,
but since it is broadcasted to operators live in the hub
it draws attention to them.
2013-02-13 21:10:30 +01:00
Jan Vidar Krey
5b78c0826d Added functions to route messages to operators only.
Technially the messages are routed to users with the
flag_opnotify set, but this is intended to be set only for
operators (and above) - and it allows operators to opt out
of these messages if they wish to.
2013-02-13 21:10:48 +01:00
Jan Vidar Krey
5c31f47bea Added methods for adding a string to be escaped automatically.
Previously only existed for named parameters.
2013-02-13 21:11:05 +01:00
Jan Vidar Krey
51a8e785c0 Attempt to address issues with timers overflowing (bug #198) 2013-02-13 21:11:22 +01:00
Jan Vidar Krey
8899e49f73 Added some auto-tests for bulk timeouts. 2013-02-13 21:11:39 +01:00
Jan Vidar Krey
d48ef710d8 Added an ADC hub redirector written in python. 2013-02-10 22:56:36 +01:00
Jan Vidar Krey
cfa210b3f3 Added a python version of the NMDC redirector. 2013-02-10 21:25:34 +01:00
Jan Vidar Krey
f6f7c7a3a4 Make sure we compile release builds with NDEBUG defined (to disable asserts). 2013-02-05 22:44:31 +01:00
Jan Vidar Krey
1fbde2b0fd Re-factored the ADC client code to use the new connection establishment API. 2013-02-05 22:43:59 +01:00
Jan Vidar Krey
92b65a0e14 Created a connection establishment API.
This API provides transparent asynchronous DNS lookups
with both IPv4 and IPv6 support, and in addition will try
to connect to all addresses until one of them work.

This implements the "happy eyeballs" algorithm provided that the client supports IPv6
and that the DNS records provides both IPv6 and IPv4 addresses.
2013-02-05 22:40:20 +01:00
Jan Vidar Krey
4d438e1e90 Don't poll the connection monitor if there are no connections added.
This caused the backends to return an error code, which
in turn ended the mainloop. However, several other things
also might occur in the main loop, such as DNS lookups which
come prior to creating any connections that in turn would be monitored.
2013-02-05 22:38:13 +01:00
Jan Vidar Krey
4f3c71234b Merge branch 'master' of https://github.com/3M3RY/uhub 2012-11-22 22:26:46 +01:00
Jan Vidar Krey
fdaadccb99 Merge pull request #18 from tehnick/fix-build-on-hurd-i386
(tehnick) Fix build in Debian GNU/Hurd.
2012-11-23 02:25:36 -08:00
Jan Vidar Krey
41251f8d32 Install uhub-passwd also. 2012-11-20 22:53:27 +01:00
Jan Vidar Krey
3b18ae251e Automatically find Sqlite3 - removed option to disable it.
This means Sqlite3 is now mandatory.
2012-11-20 22:53:27 +01:00
Boris Pek
b452488431 Fix build in Debian GNU/Hurd. 2012-11-20 22:41:38 +02:00
Emery
143b68588a Systemd notify support 2012-11-17 09:57:14 -06:00
Jan Vidar Krey
5f2b7bc069 Merge pull request #16 from 3M3RY/master
Systemd journaling support
2012-11-11 23:56:51 -08:00
Emery
ce68c446d1 Optional systemd journal logging 2012-11-11 15:21:00 -06:00
Jan Vidar Krey
6af0f293a6 Updated changelog for 0.4.1 release. 2012-11-07 20:24:06 +01:00
Jan Vidar Krey
a492f30950 Update authors file. 2012-11-07 20:08:28 +01:00
Jan Vidar Krey
a43953bc0d Added simple plugin that blocks downloads for non-registered users (guests). 2012-11-01 22:07:55 +01:00
31 changed files with 1053 additions and 138 deletions

View File

@@ -3,7 +3,9 @@ Authors of uhub
Jan Vidar Krey, Design and implementation Jan Vidar Krey, Design and implementation
E_zombie, Centos/RedHat customization scripts and heavy load testing E_zombie, Centos/RedHat customization scripts and heavy load testing
FleetCommand, Hub topic FleetCommand, Hub topic plugin code
MiMic, Implemented user commands MiMic, Implemented user commands
tehnick, Debian and Ubuntu packaging. 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

View File

@@ -3,7 +3,7 @@
## Copyright (C) 2007-2012, Jan Vidar Krey <janvidar@extatic.org> ## Copyright (C) 2007-2012, Jan Vidar Krey <janvidar@extatic.org>
# #
cmake_minimum_required (VERSION 2.8.3) cmake_minimum_required (VERSION 2.8.2)
project (uhub NONE) project (uhub NONE)
enable_language(C) enable_language(C)
@@ -13,15 +13,17 @@ set (UHUB_VERSION_MINOR 4)
set (UHUB_VERSION_PATCH 1) set (UHUB_VERSION_PATCH 1)
set (PROJECT_SOURCE_DIR "${CMAKE_SOURCE_DIR}/src") 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(RELEASE "Release build, debug build if disabled" ON)
option(LINK_SUPPORT "Allow hub linking" OFF) option(LINK_SUPPORT "Allow hub linking" OFF)
option(SSL_SUPPORT "Enable SSL support" ON) option(SSL_SUPPORT "Enable SSL support" ON)
option(USE_OPENSSL "Use OpenSSL's SSL support" ON ) option(USE_OPENSSL "Use OpenSSL's SSL support" ON )
option(SQLITE_SUPPORT "Enable SQLite support" ON) option(SYSTEMD_SUPPORT "Enable systemd notify and journal logging" OFF)
option(ADC_STRESS "Enable the stress tester client" OFF) option(ADC_STRESS "Enable the stress tester client" OFF)
find_package(Git) find_package(Git)
find_package(Sqlite3)
if (SSL_SUPPORT) if (SSL_SUPPORT)
if (USE_OPENSSL) if (USE_OPENSSL)
@@ -34,11 +36,18 @@ if (SSL_SUPPORT)
endif() endif()
endif() endif()
if (SYSTEMD_SUPPORT)
INCLUDE(FindPkgConfig)
pkg_search_module(SD_DAEMON REQUIRED libsystemd-daemon)
pkg_search_module(SD_JOURNAL REQUIRED libsystemd-journal)
endif()
if (MSVC) if (MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS) add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif() endif()
include_directories("${PROJECT_SOURCE_DIR}") include_directories("${PROJECT_SOURCE_DIR}")
include_directories(${SQLITE3_INCLUDE_DIRS})
file (GLOB uhub_SOURCES ${PROJECT_SOURCE_DIR}/core/*.c) file (GLOB uhub_SOURCES ${PROJECT_SOURCE_DIR}/core/*.c)
list (REMOVE_ITEM uhub_SOURCES list (REMOVE_ITEM uhub_SOURCES
@@ -68,6 +77,7 @@ add_dependencies(network utils)
add_executable(uhub ${PROJECT_SOURCE_DIR}/core/main.c ${uhub_SOURCES} ) add_executable(uhub ${PROJECT_SOURCE_DIR}/core/main.c ${uhub_SOURCES} )
add_executable(test ${CMAKE_SOURCE_DIR}/autotest/test.c ${uhub_SOURCES} ) add_executable(test ${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_example MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_example.c)
add_library(mod_welcome MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_welcome.c) add_library(mod_welcome MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_welcome.c)
@@ -76,16 +86,8 @@ add_library(mod_auth_simple MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_auth_simple
add_library(mod_chat_history MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_history.c ) add_library(mod_chat_history MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_history.c )
add_library(mod_chat_only MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_only.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_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)
if (SQLITE_SUPPORT) add_library(mod_auth_sqlite MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_auth_sqlite.c)
add_library(mod_auth_sqlite MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_auth_sqlite.c)
add_executable(uhub-passwd ${PROJECT_SOURCE_DIR}/tools/uhub-passwd.c)
target_link_libraries(mod_auth_sqlite sqlite3 utils)
target_link_libraries(uhub-passwd sqlite3 utils)
set_target_properties(mod_auth_sqlite PROPERTIES PREFIX "")
endif()
if(WIN32) if(WIN32)
target_link_libraries(uhub ws2_32) target_link_libraries(uhub ws2_32)
@@ -99,17 +101,22 @@ set_target_properties(
mod_welcome mod_welcome
mod_logging mod_logging
mod_auth_simple mod_auth_simple
mod_auth_sqlite
mod_chat_history mod_chat_history
mod_chat_only mod_chat_only
mod_no_guest_downloads
mod_topic mod_topic
PROPERTIES PREFIX "") PROPERTIES PREFIX "")
target_link_libraries(uhub ${CMAKE_DL_LIBS} adc network utils) target_link_libraries(uhub ${CMAKE_DL_LIBS} adc network utils)
target_link_libraries(uhub-passwd ${SQLITE3_LIBRARIES} utils)
target_link_libraries(test ${CMAKE_DL_LIBS} adc network utils) target_link_libraries(test ${CMAKE_DL_LIBS} adc network utils)
target_link_libraries(mod_example utils) target_link_libraries(mod_example utils)
target_link_libraries(mod_welcome utils) target_link_libraries(mod_welcome utils)
target_link_libraries(mod_auth_simple 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 utils)
target_link_libraries(mod_no_guest_downloads utils)
target_link_libraries(mod_chat_only utils) target_link_libraries(mod_chat_only utils)
target_link_libraries(mod_logging utils) target_link_libraries(mod_logging utils)
target_link_libraries(mod_topic utils) target_link_libraries(mod_topic utils)
@@ -117,6 +124,7 @@ target_link_libraries(utils network)
target_link_libraries(mod_welcome network) target_link_libraries(mod_welcome network)
target_link_libraries(mod_logging network) target_link_libraries(mod_logging network)
if(UNIX) if(UNIX)
add_library(adcclient STATIC ${adcclient_SOURCES}) add_library(adcclient STATIC ${adcclient_SOURCES})
add_executable(uhub-admin ${PROJECT_SOURCE_DIR}/tools/admin.c) add_executable(uhub-admin ${PROJECT_SOURCE_DIR}/tools/admin.c)
@@ -172,24 +180,33 @@ if(SSL_SUPPORT)
endif() endif()
endif() endif()
if (SYSTEMD_SUPPORT)
target_link_libraries(uhub ${SD_DAEMON_LIBRARIES})
target_link_libraries(uhub ${SD_JOURNAL_LIBRARIES})
target_link_libraries(test ${SD_DAEMON_LIBRARIES})
target_link_libraries(test ${SD_JOURNAL_LIBRARIES})
target_link_libraries(uhub-passwd ${SD_JOURNAL_LIBRARIES})
target_link_libraries(uhub-admin ${SD_JOURNAL_LIBRARIES})
include_directories(${SD_DAEMON_INCLUDE_DIRS})
include_directories(${SD_JOURNAL_INCLUDE_DIRS})
add_definitions(-DSYSTEMD)
endif()
configure_file ("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_SOURCE_DIR}/version.h") configure_file ("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_SOURCE_DIR}/version.h")
mark_as_advanced(FORCE CMAKE_BUILD_TYPE) mark_as_advanced(FORCE CMAKE_BUILD_TYPE)
if (RELEASE) if (RELEASE)
set(CMAKE_BUILD_TYPE Release) set(CMAKE_BUILD_TYPE Release)
add_definitions(-DNDEBUG)
else() else()
set(CMAKE_BUILD_TYPE Debug) set(CMAKE_BUILD_TYPE Debug)
# add_definitions(-DDEBUG) # add_definitions(-DDEBUG)
endif() endif()
if (UNIX) if (UNIX)
install( TARGETS uhub RUNTIME DESTINATION bin ) 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_only mod_topic DESTINATION /usr/lib/uhub/ OPTIONAL ) install( TARGETS mod_example mod_welcome mod_logging mod_auth_simple mod_auth_sqlite mod_chat_history 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 ) 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 )
if (SQLITE_SUPPORT)
install( TARGETS uhub-passwd RUNTIME DESTINATION bin )
endif()
endif() endif()

View File

@@ -1,3 +1,18 @@
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: 0.4.0:
- Cleaned up code generator for config file parsing. - Cleaned up code generator for config file parsing.
- Merge pull request #5 from yorhel/master - Merge pull request #5 from yorhel/master

View File

@@ -761,6 +761,9 @@ int main(int argc, char** argv)
exotic_add_test(&handle, &exotic_test_timer_add_5_events_1, "timer_add_5_events_1"); 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_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_process_5_events_1, "timer_process_5_events_1");
exotic_add_test(&handle, &exotic_test_timer_clear_1, "timer_clear_1");
exotic_add_test(&handle, &exotic_test_timer_bulk_1, "timer_bulk_1");
exotic_add_test(&handle, &exotic_test_timer_bulk_2, "timer_bulk_2");
exotic_add_test(&handle, &exotic_test_tokenizer_basic_0, "tokenizer_basic_0"); 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_1, "tokenizer_basic_1");
exotic_add_test(&handle, &exotic_test_tokenizer_basic_1a, "tokenizer_basic_1a"); exotic_add_test(&handle, &exotic_test_tokenizer_basic_1a, "tokenizer_basic_1a");
@@ -951,7 +954,6 @@ int exotic_initialize(struct exotic_handle* handle, int argc, char** argv)
void exotic_add_test(struct exotic_handle* handle, exo_test_t func, const char* name) void exotic_add_test(struct exotic_handle* handle, exo_test_t func, const char* name)
{ {
struct exo_test_data* test; struct exo_test_data* test;
if (!handle) if (!handle)
{ {
fprintf(stderr, "exotic_add_test: failed, no handle!\n"); fprintf(stderr, "exotic_add_test: failed, no handle!\n");

View File

@@ -1,6 +1,6 @@
#include <uhub.h> #include <uhub.h>
#define MAX_EVENTS 15 #define MAX_EVENTS 100
static struct timeout_queue* g_queue; static struct timeout_queue* g_queue;
static time_t g_now; static time_t g_now;
static size_t g_max; static size_t g_max;
@@ -117,3 +117,28 @@ EXO_TEST(timer_process_5_events_1,{
g_now = 4; g_now = 4;
return timeout_queue_process(g_queue, g_now) == g_triggered; return timeout_queue_process(g_queue, g_now) == g_triggered;
}); });
EXO_TEST(timer_clear_1,{
size_t n;
for (n = 0; n < MAX_EVENTS; n++)
timeout_queue_remove(g_queue, &g_events[n]);
return timeout_queue_get_next_timeout(g_queue, g_now) == g_max;
});
EXO_TEST(timer_bulk_1,{
size_t n;
g_now = 10;
for (n = 0; n < MAX_EVENTS; n++)
{
timeout_queue_insert(g_queue, &g_events[0], 0);
}
return timeout_queue_process(g_queue, g_now) == 10;
});
EXO_TEST(timer_bulk_2,{
g_now = 110;
return timeout_queue_process(g_queue, g_now) == 90;
});

View File

@@ -0,0 +1,77 @@
# - 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 <tuju@iki.fi>
# Copyright (c) 2007 Daniel Gollub <gollub@b1-systems.de>
# Copyright (c) 2007 Alban Browaeys <prahal@yahoo.com>
#
# 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/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 )

View File

@@ -787,6 +787,13 @@ int adc_msg_add_argument(struct adc_message* cmd, const char* string)
return 0; return 0;
} }
int adc_msg_add_argument_string(struct adc_message* cmd, const char* string)
{
char* escaped = adc_msg_escape(string);
int ret = adc_msg_add_argument(cmd, escaped);
hub_free(escaped);
return ret;
}
char* adc_msg_get_argument(struct adc_message* cmd, int offset) char* adc_msg_get_argument(struct adc_message* cmd, int offset)
{ {
@@ -866,8 +873,6 @@ int adc_msg_get_argument_index(struct adc_message* cmd, const char prefix[2])
return -1; return -1;
} }
int adc_msg_escape_length(const char* str) int adc_msg_escape_length(const char* str)
{ {
int add = 0; int add = 0;

View File

@@ -171,6 +171,12 @@ extern int adc_msg_replace_named_argument(struct adc_message* cmd, const char pr
*/ */
extern int adc_msg_add_argument(struct adc_message* cmd, const char* string); extern int adc_msg_add_argument(struct adc_message* cmd, const char* string);
/**
* Add an argument string, the string will be automatcally escaped.
* @return 0 if successful, or -1 if an error occured (out of memory).
*/
extern int adc_msg_add_argument_string(struct adc_message* cmd, const char* string);
/** /**
* Append a named argument * Append a named argument
* *
@@ -209,6 +215,13 @@ extern char* adc_msg_unescape(const char* string);
*/ */
extern int adc_msg_unescape_to_target(const char* string, char* target, size_t target_size); extern int adc_msg_unescape_to_target(const char* string, char* target, size_t target_size);
/**
* Returns the length of the string once escaped with
* adc_msg_escape().
*
* The string must be NULL terminated.
*/
extern int adc_msg_escape_length(const char* str);
/** /**
* Convert a string to a ADC command escaped string. * Convert a string to a ADC command escaped string.
@@ -234,4 +247,5 @@ void adc_msg_unterminate(struct adc_message* cmd);
*/ */
int adc_msg_get_arg_offset(struct adc_message* msg); int adc_msg_get_arg_offset(struct adc_message* msg);
#endif /* HAVE_UHUB_COMMAND_H */ #endif /* HAVE_UHUB_COMMAND_H */

View File

@@ -353,6 +353,7 @@ static int command_kick(struct command_base* cbase, struct hub_user* user, struc
} }
else else
{ {
hub_notify(cbase->hub, notify_info, "Kicking user \"%s\" (%s)", target->id.nick, user->id.nick);
cbuf_append_format(buf, "Kicking user \"%s\".", target->id.nick); cbuf_append_format(buf, "Kicking user \"%s\".", target->id.nick);
hub_disconnect_user(cbase->hub, target, quit_kicked); hub_disconnect_user(cbase->hub, target, quit_kicked);
} }
@@ -362,6 +363,7 @@ static int command_kick(struct command_base* cbase, struct hub_user* user, struc
static int command_reload(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) static int command_reload(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{ {
cbase->hub->status = hub_status_restart; cbase->hub->status = hub_status_restart;
hub_notify(cbase->hub, notify_info, "Reloading configuration (%s)", user->id.nick);
return command_status(cbase, user, cmd, cbuf_create_const("Reloading configuration...")); return command_status(cbase, user, cmd, cbuf_create_const("Reloading configuration..."));
} }
@@ -384,6 +386,7 @@ static int command_unload(struct command_base* cbase, struct hub_user* user, str
static int command_shutdown_hub(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) static int command_shutdown_hub(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{ {
hub_notify(cbase->hub, notify_warn, "Shutting down hub (%s)", user->id.nick);
cbase->hub->status = hub_status_shutdown; cbase->hub->status = hub_status_shutdown;
return command_status(cbase, user, cmd, cbuf_create_const("Hub shutting down...")); return command_status(cbase, user, cmd, cbuf_create_const("Hub shutting down..."));
} }

View File

@@ -653,6 +653,7 @@ static struct net_connection* start_listening_socket(const char* bind_addr, uint
if (ret == -1) 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())); LOG_ERROR("hub_start_service(): Unable to bind to TCP local address. errno=%d, str=%s", net_error(), net_error_string(net_error()));
hub_notify(hub, notify_error, "Unable to bind to network address %s on port %d: %s (%d)", bind_addr, port, net_error_string(net_error()), net_error());
net_close(sd); net_close(sd);
return 0; return 0;
} }
@@ -671,6 +672,60 @@ static struct net_connection* start_listening_socket(const char* bind_addr, uint
return server; return server;
} }
int hub_is_running(struct hub_info* hub)
{
return hub->status == hub_status_running || hub->status == hub_status_restart;
}
void hub_notify(struct hub_info* hub, enum notify_verbosity verbosity, const char* fmt, ...)
{
struct cbuffer* buf;
struct adc_message* msg;
va_list args;
char temp[1024];
va_start(args, fmt);
vsnprintf(temp, sizeof(temp), fmt, args);
va_end(args);
buf = cbuf_create(strlen(temp) + 8);
switch (verbosity)
{
case notify_error:
cbuf_append(buf, "ERROR: ");
LOG_ERROR(temp);
break;
case notify_warn:
cbuf_append(buf, "WARN: ");
LOG_WARN(temp);
break;
case notify_info:
cbuf_append(buf, "INFO: ");
LOG_INFO(temp);
break;
case notify_debug:
cbuf_append(buf, "DEBUG: ");
LOG_DEBUG(temp);
break;
}
cbuf_append(buf, temp);
if (hub_is_running(hub))
{
msg = adc_msg_construct(ADC_CMD_IMSG, 5 + adc_msg_escape_length(cbuf_get(buf)) + 2);
adc_msg_add_argument_string(msg, cbuf_get(buf));
route_to_operators(hub, msg);
adc_msg_free(msg);
}
cbuf_destroy(buf);
}
struct server_alt_port_data struct server_alt_port_data
{ {
struct hub_info* hub; struct hub_info* hub;
@@ -751,6 +806,54 @@ static void unload_ssl_certificates(struct hub_info* hub)
} }
#endif /* SSL_SUPPORT */ #endif /* SSL_SUPPORT */
// #ifdef BOT_SUPPORT
static void route_privmsg_to_operators(struct hub_user* bot, sid_t from, const char* escaped_msg, int action)
{
struct hub_info* hub = bot->hub;
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list);
while (user)
{
if (from != user->id.sid && user_flag_get(user, flag_opnotify))
{
struct adc_message* msg = adc_msg_construct_source_dest(ADC_CMD_EMSG, from, user->id.sid, strlen(escaped_msg) + (action * 4) + 7);
adc_msg_add_argument(msg, escaped_msg);
adc_msg_add_named_argument(msg, ADC_MSG_FLAG_PRIVATE, sid_to_string(bot->id.sid));
if (action) adc_msg_add_named_argument(msg, ADC_MSG_FLAG_ACTION, "1");
route_to_user(hub, user, msg);
adc_msg_free(msg);
}
user = (struct hub_user*) list_get_next(hub->users->list);
}
}
/// This receives private messages and transmits them to the connected operators.
static void hub_bot_op_notify_handle(struct hub_user* bot, struct adc_message* msg)
{
char* chat;
LOG_TRACE("Invoked hub_bot_op_notify_handle()");
switch (msg->cmd)
{
case ADC_CMD_EMSG:
case ADC_CMD_DMSG:
chat = adc_msg_get_argument(msg, 0);
LOG_DEBUG("Hub chat: \"%s\"", chat);
route_privmsg_to_operators(bot, msg->source, chat, adc_msg_has_named_argument(msg, ADC_MSG_FLAG_ACTION) ? 1 : 0);
hub_free(chat);
break;
default:
/* ignore these messages! */
break;
}
}
static void hub_bot_op_notify_create(struct hub_info* hub)
{
struct hub_user* opcom = user_create_bot(hub, "Operations", "Hub operators", hub_bot_op_notify_handle);
uman_add(hub->users, opcom);
}
// #endif
struct hub_info* hub_start_service(struct hub_config* config) struct hub_info* hub_start_service(struct hub_config* config)
{ {
struct hub_info* hub = 0; struct hub_info* hub = 0;
@@ -834,6 +937,8 @@ struct hub_info* hub_start_service(struct hub_config* config)
// Start the hub command sub-system // Start the hub command sub-system
hub->commands = command_initialize(hub); hub->commands = command_initialize(hub);
hub_bot_op_notify_create(hub);
return hub; return hub;
} }

View File

@@ -106,7 +106,7 @@ struct hub_info
struct adc_message* command_support; /* The hub's SUP command */ struct adc_message* command_support; /* The hub's SUP command */
struct adc_message* command_banner; /* The default welcome message */ struct adc_message* command_banner; /* The default welcome message */
time_t tm_started; time_t tm_started;
int status; enum hub_state status;
char* recvbuf; /* Global receive buffer */ char* recvbuf; /* Global receive buffer */
char* sendbuf; /* Global send buffer */ char* sendbuf; /* Global send buffer */
@@ -233,6 +233,20 @@ extern void hub_set_variables(struct hub_info* hub, struct acl_handle* acl);
*/ */
extern void hub_free_variables(struct hub_info* hub); extern void hub_free_variables(struct hub_info* hub);
enum notify_verbosity
{
notify_error = 0,
notify_warn = 1,
notify_info = 2,
notify_debug = 3,
};
/**
* Send a notification message to operators.
*/
extern void hub_notify(struct hub_info* hub, enum notify_verbosity verbosity, const char* fmt, ...);
/** /**
* Returns a string for the given status_message (See enum status_message). * Returns a string for the given status_message (See enum status_message).
*/ */
@@ -350,6 +364,10 @@ extern void hub_disconnect_user(struct hub_info* hub, struct hub_user* user, int
*/ */
extern void hub_logout_log(struct hub_info* hub, struct hub_user* user); extern void hub_logout_log(struct hub_info* hub, struct hub_user* user);
/**
* Returns 1 if the hub is running, and 0 otherwise.
*/
extern int hub_is_running(struct hub_info* hub);
#endif /* HAVE_UHUB_HUB_H */ #endif /* HAVE_UHUB_HUB_H */

View File

@@ -31,6 +31,10 @@ void on_login_success(struct hub_info* hub, struct hub_user* u)
user_set_state(u, state_normal); user_set_state(u, state_normal);
uman_add(hub->users, u); uman_add(hub->users, u);
// Make operators receive hub notifications by default.
if (user_is_protected(u))
user_flag_set(u, flag_opnotify);
/* Announce new user to all connected users */ /* Announce new user to all connected users */
if (user_is_logged_in(u)) if (user_is_logged_in(u))
route_info_message(hub, u); route_info_message(hub, u);

View File

@@ -19,6 +19,10 @@
#include "uhub.h" #include "uhub.h"
#ifdef SYSTEMD
#include <systemd/sd-daemon.h>
#endif
static int arg_verbose = 5; static int arg_verbose = 5;
static int arg_fork = 0; static int arg_fork = 0;
static int arg_check_config = 0; static int arg_check_config = 0;
@@ -145,7 +149,16 @@ int main_loop()
} }
#if !defined(WIN32) #if !defined(WIN32)
setup_signal_handlers(hub); setup_signal_handlers(hub);
#endif #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_set_variables(hub, &acl);
@@ -216,13 +229,17 @@ void print_usage(char* program)
" -q Quiet mode - no output\n" " -q Quiet mode - no output\n"
" -f Fork to background\n" " -f Fork to background\n"
" -l <file> Log messages to given file (default: stderr)\n" " -l <file> Log messages to given file (default: stderr)\n"
" -L Log messages to syslog\n"
" -c <file> Specify configuration file (default: " SERVER_CONFIG ")\n" " -c <file> Specify configuration file (default: " SERVER_CONFIG ")\n"
" -C Check configuration and return\n" " -C Check configuration and return\n"
" -s Show configuration parameters\n" " -s Show configuration parameters\n"
" -S Show configuration parameters, but ignore defaults\n" " -S Show configuration parameters, but ignore defaults\n"
" -h This message\n" " -h This message\n"
#ifndef WIN32 #ifndef WIN32
#ifdef SYSTEMD
" -L Log messages to journal\n"
#else
" -L Log messages to syslog\n"
#endif
" -u <user> Run as given user\n" " -u <user> Run as given user\n"
" -g <group> Run with given group permissions\n" " -g <group> Run with given group permissions\n"
" -p <file> Store pid in file (process id)\n" " -p <file> Store pid in file (process id)\n"

View File

@@ -104,7 +104,7 @@ static int cbfunc_command_add(struct plugin_handle* plugin, struct plugin_comman
cmdh->internal_handle = command; cmdh->internal_handle = command;
list_append(data->commands, cmdh); list_append(data->commands, cmdh);
command_add(plugin_get_hub(plugin)->commands, command, (void*) plugin); command_add(plugin_get_hub(plugin)->commands, command, (void*) plugin);
printf("*** Add plugin command: %s (%p, %p)\n", command->prefix, command, cmdh); LOG_DEBUG("*** Add plugin command: %s (%p, %p)\n", command->prefix, command, cmdh);
return 0; return 0;
} }
@@ -113,7 +113,7 @@ static int cbfunc_command_del(struct plugin_handle* plugin, struct plugin_comman
struct plugin_callback_data* data = get_callback_data(plugin); struct plugin_callback_data* data = get_callback_data(plugin);
struct command_handle* command = (struct command_handle*) cmdh->internal_handle; struct command_handle* command = (struct command_handle*) cmdh->internal_handle;
printf("*** Del plugin command: %s (%p, %p)\n", command->prefix, command, cmdh); LOG_DEBUG("*** Del plugin command: %s (%p, %p)\n", command->prefix, command, cmdh);
list_remove(data->commands, cmdh); list_remove(data->commands, cmdh);
command_del(plugin_get_hub(plugin)->commands, command); command_del(plugin_get_hub(plugin)->commands, command);
hub_free(command); hub_free(command);

View File

@@ -104,7 +104,19 @@ int route_to_user(struct hub_info* hub, struct hub_user* user, struct adc_messag
#endif #endif
if (!user->connection) if (!user->connection)
{
switch (user->type)
{
case user_type_client:
return 0; // No connection - we're about to drop this user.
case user_type_bot:
{
bot_recv_msg handler = (bot_recv_msg) user->ptr;
handler(user, msg);
return 0; return 0;
}
}
}
uhub_assert(msg->cache && *msg->cache); uhub_assert(msg->cache && *msg->cache);
@@ -149,6 +161,19 @@ int route_to_all(struct hub_info* hub, struct adc_message* command) /* iterate u
return 0; return 0;
} }
int route_to_operators(struct hub_info* hub, struct adc_message* command) /* iterate users */
{
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list);
while (user)
{
if (user_flag_get(user, flag_opnotify))
route_to_user(hub, user, command);
user = (struct hub_user*) list_get_next(hub->users->list);
}
return 0;
}
int route_to_subscribers(struct hub_info* hub, struct adc_message* command) /* iterate users */ int route_to_subscribers(struct hub_info* hub, struct adc_message* command) /* iterate users */
{ {
int do_send; int do_send;

View File

@@ -40,6 +40,14 @@ extern int route_to_user(struct hub_info* hub, struct hub_user*, struct adc_mess
*/ */
extern int route_to_all(struct hub_info* hub, struct adc_message* command); extern int route_to_all(struct hub_info* hub, struct adc_message* command);
/**
* Send a message to all operators.
* Technically it sends to all users with the flag_opnotify set
* which is intended to be set for only operators - allowing operators to opt-out
* of these messages.
*/
extern int route_to_operators(struct hub_info* hub, struct adc_message* command);
/** /**
* Broadcast message to all users subscribing to the type of message. * Broadcast message to all users subscribing to the type of message.
*/ */

View File

@@ -42,7 +42,6 @@ struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, s
LOG_TRACE("user_create(), hub=%p, con[sd=%d]", hub, net_con_get_sd(con)); 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)); user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
if (user == NULL) if (user == NULL)
return NULL; /* OOM */ return NULL; /* OOM */
@@ -54,6 +53,7 @@ struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, s
memcpy(&user->id.addr, addr, sizeof(struct ip_addr_encap)); memcpy(&user->id.addr, addr, sizeof(struct ip_addr_encap));
user_set_state(user, state_protocol); user_set_state(user, state_protocol);
user->type = user_type_client;
flood_control_reset(&user->flood_chat); flood_control_reset(&user->flood_chat);
flood_control_reset(&user->flood_connect); flood_control_reset(&user->flood_connect);
@@ -65,6 +65,54 @@ struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, s
return user; return user;
} }
/// generate a semi-stable CID: base32_encode(tiger({hub name} + {nick}))
static const char* generate_bot_cid(struct hub_info* hub, const char* nick)
{
static char result[MAX_CID_LEN+1];
char buf[(MAX_NICK_LEN*2)+1];
uint64_t tiger_res[3];
memset(buf, 0, sizeof(buf));
snprintf(buf, sizeof(buf), "%s%s", hub->config->hub_name, nick);
tiger((uint64_t*) buf, sizeof(buf), (uint64_t*) tiger_res);
base32_encode((unsigned char*) tiger_res, TIGERSIZE, result);
result[MAX_CID_LEN] = 0;
return result;
}
struct hub_user* user_create_bot(struct hub_info* hub, const char* nick, const char* description, bot_recv_msg msg_handler)
{
struct hub_user* user = NULL;
LOG_TRACE("user_create_bot(), hub=%p, nick=\"%s\"", hub, nick);
user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
if (user == NULL)
return NULL; /* OOM */
strcpy(user->id.nick, nick);
uman_get_free_sid(hub->users, user);
user_set_state(user, state_normal);
user->type = user_type_bot;
user->credentials = auth_cred_bot;
// The message handler
user->ptr = (void*) msg_handler;
user->info = adc_msg_construct(ADC_CMD_BINF, 15);
if (user->info)
{
adc_msg_add_argument(user->info, sid_to_string(user->id.sid));
adc_msg_add_named_argument(user->info, ADC_INF_FLAG_CLIENT_TYPE, ADC_CLIENT_TYPE_BOT);
adc_msg_add_named_argument_string(user->info, ADC_INF_FLAG_USER_AGENT, PRODUCT_STRING);
adc_msg_add_named_argument_string(user->info, ADC_INF_FLAG_NICK, nick);
adc_msg_add_named_argument_string(user->info, ADC_INF_FLAG_DESCRIPTION, description);
adc_msg_add_named_argument(user->info, ADC_INF_FLAG_CLIENT_ID, generate_bot_cid(hub, nick));
}
user->hub = hub;
return user;
}
void user_destroy(struct hub_user* user) void user_destroy(struct hub_user* user)
{ {

View File

@@ -47,6 +47,7 @@ enum user_flags
feature_link = 0x00000100, /** LINK: Hub link (not supported) */ feature_link = 0x00000100, /** LINK: Hub link (not supported) */
feature_adcs = 0x00000200, /** ADCS: ADC over TLS/SSL */ feature_adcs = 0x00000200, /** ADCS: ADC over TLS/SSL */
feature_bas0 = 0x00000400, /** BAS0: Obsolete pre-ADC/1.0 protocol version */ feature_bas0 = 0x00000400, /** BAS0: Obsolete pre-ADC/1.0 protocol version */
flag_opnotify = 0x00200000, /** User should receive operation notifications. NOTE: Only operators should have this flag! */
flag_flood = 0x00400000, /** User has been notified about flooding. */ flag_flood = 0x00400000, /** User has been notified about flooding. */
flag_muted = 0x00800000, /** User is muted (cannot chat) */ flag_muted = 0x00800000, /** User is muted (cannot chat) */
flag_ignore = 0x01000000, /** Ignore further reads */ flag_ignore = 0x01000000, /** Ignore further reads */
@@ -104,21 +105,30 @@ struct hub_user_limits
size_t hub_count_total; /** The number of hubs connected to in total */ size_t hub_count_total; /** The number of hubs connected to in total */
}; };
enum user_type
{
user_type_client, /** A user connected normally as an ADC client */
user_type_bot, /** Not really a user, but a bot inside the hub */
};
typedef void (*bot_recv_msg)(struct hub_user*, struct adc_message* msg);
struct hub_user struct hub_user
{ {
struct hub_user_info id; /** Contains nick name and CID */ struct hub_user_info id; /** Contains nick name and CID */
enum auth_credentials credentials; /** see enum user_credentials */ enum auth_credentials credentials; /** see enum user_credentials */
enum user_state state; /** see enum user_state */ enum user_state state; /** see enum user_state */
enum user_type type;
uint32_t flags; /** see enum user_flags */ uint32_t flags; /** see enum user_flags */
struct linked_list* feature_cast; /** Features supported by feature cast */ struct linked_list* feature_cast; /** Features supported by feature cast */
struct adc_message* info; /** ADC 'INF' message (broadcasted to everyone joining the hub) */ struct adc_message* info; /** ADC 'INF' message (broadcasted to everyone joining the hub) */
struct hub_info* hub; /** The hub instance this user belong to */ struct hub_info* hub; /** The hub instance this user belong to */
void* ptr;
struct ioq_recv* recv_queue; struct ioq_recv* recv_queue;
struct ioq_send* send_queue; struct ioq_send* send_queue;
struct net_connection* connection; /** Connection data */ struct net_connection* connection; /** Connection data */
struct hub_user_limits limits; /** Data used for limitation */ struct hub_user_limits limits; /** Data used for limitation */
enum user_quit_reason quit_reason; /** Quit reason (see user_quit_reason) */ enum user_quit_reason quit_reason; /** Quit reason (see user_quit_reason) */
struct flood_control flood_chat; struct flood_control flood_chat;
struct flood_control flood_connect; struct flood_control flood_connect;
struct flood_control flood_search; struct flood_control flood_search;
@@ -138,6 +148,7 @@ struct hub_user
* @return User object or NULL if not enough memory is available. * @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); extern struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, struct ip_addr_encap* addr);
extern struct hub_user* user_create_bot(struct hub_info* hub, const char* nick, const char* description, bot_recv_msg msg_handler);
/** /**
* Delete a user. * Delete a user.

View File

@@ -132,9 +132,10 @@ struct timeout_queue* net_backend_get_timeout_queue()
*/ */
int net_backend_process() int net_backend_process()
{ {
int res; int res = 0;
size_t secs = timeout_queue_get_next_timeout(&g_backend->timeout_queue, g_backend->now); 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); res = g_backend->handler.backend_poll(g_backend->data, secs * 1000);
g_backend->now = time(0); g_backend->now = time(0);

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey * Copyright (C) 2007-2013, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -145,3 +145,364 @@ void net_con_callback(struct net_connection* con, int events)
con->callback(con, events, con->ptr); 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_in6) : sizeof(struct sockaddr_in));
if (ret == 0 || (ret == -1 && net_error() == EISCONN))
{
LOG_TRACE("net_connect_job_check(): Socket connected!");
job->con = NULL;
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)
{
int ret;
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 int 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);
}
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;
int ret;
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);
}

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey * Copyright (C) 2007-2013, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -34,10 +34,41 @@ struct net_connection
NET_CON_STRUCT_COMMON 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 int net_con_get_sd(struct net_connection* con);
extern void* net_con_get_ptr(struct net_connection* con); extern void* net_con_get_ptr(struct net_connection* con);
extern struct net_connection* net_con_create(); 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_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_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_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events);

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey * Copyright (C) 2007-2013, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -366,21 +366,24 @@ extern size_t net_dns_result_size(const struct net_dns_result* res)
extern struct ip_addr_encap* net_dns_result_first(const struct net_dns_result* res) 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); struct ip_addr_encap* ipaddr = list_get_first(res->addr_list);
LOG_TRACE("net_dns_result_first() - Address: %s", ip_convert_to_string(ipaddr)); LOG_TRACE("net_dns_result_first() - Address: %s", ipaddr ? ip_convert_to_string(ipaddr) : "(no address)");
return ipaddr; return ipaddr;
} }
extern struct ip_addr_encap* net_dns_result_next(const struct net_dns_result* res) 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); struct ip_addr_encap* ipaddr = list_get_next(res->addr_list);
LOG_TRACE("net_dns_result_next() - Address: %s", ip_convert_to_string(ipaddr)); LOG_TRACE("net_dns_result_next() - Address: %s", ipaddr ? ip_convert_to_string(ipaddr) : "(no more addresses)");
return ipaddr; return ipaddr;
} }
extern void net_dns_result_free(struct net_dns_result* res) extern void net_dns_result_free(const struct net_dns_result* res)
{ {
if (!res)
return;
list_clear(res->addr_list, &hub_free); list_clear(res->addr_list, &hub_free);
list_destroy(res->addr_list); list_destroy(res->addr_list);
free_job(res->job); free_job(res->job);
hub_free(res); hub_free((struct net_dns_result*) res);
} }

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey * Copyright (C) 2007-2013, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -114,6 +114,6 @@ extern struct ip_addr_encap* net_dns_result_first(const struct net_dns_result*);
extern struct ip_addr_encap* net_dns_result_next(const struct net_dns_result*); extern struct ip_addr_encap* net_dns_result_next(const struct net_dns_result*);
/// When finished with the results /// When finished with the results
extern void net_dns_result_free(struct net_dns_result*); extern void net_dns_result_free(const struct net_dns_result*);
#endif /* HAVE_UHUB_NETWORK_DNS_RESOLVER_H */ #endif /* HAVE_UHUB_NETWORK_DNS_RESOLVER_H */

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey * Copyright (C) 2007-2013, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -57,15 +57,31 @@ size_t timeout_queue_process(struct timeout_queue* t, time_t now)
size_t pos = (size_t) t->last; size_t pos = (size_t) t->last;
size_t events = 0; size_t events = 0;
struct timeout_evt* evt = 0; struct timeout_evt* evt = 0;
uhub_assert(t->last <= now);
t->last = now; t->last = now;
// We can optimize in case we need to wrap around
// the buffer, so we only do it once
if (MAX(pos, now) - MIN(pos, now) > t->max)
{
// FIXME: Double check this calculation
pos = (now - t->max);
}
for (; pos <= now; pos++) for (; pos <= now; pos++)
{ {
while ((evt = t->events[pos % t->max])) evt = t->events[pos % t->max];
while (evt)
{
if (evt->timestamp < pos)
{ {
timeout_queue_remove(t, evt); timeout_queue_remove(t, evt);
evt->callback(evt); evt->callback(evt);
events++; events++;
} }
evt = evt->next;
}
} }
return events; return events;
} }
@@ -85,24 +101,22 @@ size_t timeout_queue_get_next_timeout(struct timeout_queue* t, time_t now)
void timeout_queue_insert(struct timeout_queue* t, struct timeout_evt* evt, size_t seconds) void timeout_queue_insert(struct timeout_queue* t, struct timeout_evt* evt, size_t seconds)
{ {
struct timeout_evt* first; struct timeout_evt* it, *first;
size_t pos = ((t->last + seconds) % t->max); size_t pos = ((t->last + seconds) % t->max);
evt->timestamp = t->last + seconds; evt->timestamp = t->last + seconds;
evt->next = 0; evt->next = 0;
first = t->events[pos]; first = t->events[pos];
if (first) if (first)
{ {
uhub_assert(first->timestamp == evt->timestamp); for (it = first; it->next; it = it->next) { }
first->prev->next = evt; it->next = evt;
evt->prev = first->prev; evt->prev = it;
first->prev = evt;
} }
else else
{ {
t->events[pos] = evt; t->events[pos] = evt;
evt->prev = evt; evt->prev = evt; // point to self.
} }
evt->next = 0; evt->next = 0;
} }

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey * Copyright (C) 2007-2013, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@@ -0,0 +1,60 @@
/*
* uhub - A tiny ADC p2p connection hub
* 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 as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "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;
}

View File

@@ -127,6 +127,10 @@
*/ */
#endif #endif
#ifdef __GNU__
#define POSIX_THREAD_SUPPORT
#endif
#define USE_SELECT #define USE_SELECT
#ifndef WINSOCK #ifndef WINSOCK
#include <sys/select.h> #include <sys/select.h>

View File

@@ -30,7 +30,6 @@
enum ADC_client_state enum ADC_client_state
{ {
ps_none, /* Not connected */ ps_none, /* Not connected */
ps_dns, /* looking up name */
ps_conn, /* Connecting... */ ps_conn, /* Connecting... */
ps_conn_ssl, /* SSL handshake */ ps_conn_ssl, /* SSL handshake */
ps_protocol, /* Have sent HSUP */ ps_protocol, /* Have sent HSUP */
@@ -68,7 +67,7 @@ struct ADC_client
struct net_connection* con; struct net_connection* con;
struct net_timer* timer; struct net_timer* timer;
struct sockaddr_storage addr; struct sockaddr_storage addr;
struct net_dns_job* dns_job; struct net_connect_handle* connect_job;
struct ADC_client_address address; struct ADC_client_address address;
char* nick; char* nick;
char* desc; char* desc;
@@ -109,7 +108,6 @@ static void ADC_client_debug(struct ADC_client* client, const char* format, ...)
static const char* ADC_client_state_string[] = static const char* ADC_client_state_string[] =
{ {
"ps_none", "ps_none",
"ps_dns",
"ps_conn", "ps_conn",
"ps_conn_ssl", "ps_conn_ssl",
"ps_protocol", "ps_protocol",
@@ -164,18 +162,12 @@ static void event_callback(struct net_connection* con, int events, void *arg)
switch (client->state) switch (client->state)
{ {
case ps_dns:
break;
case ps_conn: case ps_conn:
if (events == NET_EVENT_TIMEOUT) if (events == NET_EVENT_TIMEOUT)
{ {
client->callback(client, ADC_CLIENT_DISCONNECTED, 0); client->callback(client, ADC_CLIENT_DISCONNECTED, 0);
return; return;
} }
if (events & NET_EVENT_WRITE)
ADC_client_connect_internal(client);
break; break;
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
@@ -539,11 +531,6 @@ struct ADC_client* ADC_client_create(const char* nickname, const char* descripti
ADC_TRACE; ADC_TRACE;
struct ADC_client* client = (struct ADC_client*) hub_malloc_zero(sizeof(struct ADC_client)); struct ADC_client* client = (struct ADC_client*) hub_malloc_zero(sizeof(struct ADC_client));
int sd = net_socket_create(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sd == -1) return NULL;
client->con = net_con_create();
net_con_initialize(client->con, sd, event_callback, client, 0);
ADC_client_set_state(client, ps_none); ADC_client_set_state(client, ps_none);
client->nick = hub_strdup(nickname); client->nick = hub_strdup(nickname);
@@ -570,40 +557,42 @@ void ADC_client_destroy(struct ADC_client* client)
hub_free(client); hub_free(client);
} }
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) int ADC_client_connect(struct ADC_client* client, const char* address)
{ {
ADC_TRACE; ADC_TRACE;
if (client->state == ps_none) if (client->state == ps_none)
{ {
// Parse address and start name resolving!
if (!ADC_client_parse_address(client, address)) if (!ADC_client_parse_address(client, address))
return 0; return 0;
return 1;
}
return ADC_client_connect_internal(client);
}
int ADC_client_connect_internal(struct ADC_client* client)
{
int ret;
if (client->state == ps_dns)
{
// Done name resolving!
client->callback(client, ADC_CLIENT_CONNECTING, 0);
ADC_client_set_state(client, ps_conn);
} }
ret = net_connect(net_con_get_sd(client->con), (struct sockaddr*) &client->addr, sizeof(struct sockaddr_in));
if (ret == 0 || (ret == -1 && net_error() == EISCONN))
{
ADC_client_on_connected(client);
}
else if (ret == -1 && (net_error() == EALREADY || net_error() == EINPROGRESS || net_error() == EWOULDBLOCK || net_error() == EINTR))
{
net_con_update(client->con, NET_EVENT_READ | NET_EVENT_WRITE);
ADC_client_set_state(client, ps_conn); ADC_client_set_state(client, ps_conn);
} client->connect_job = net_con_connect(client->address.hostname, client->address.port, connect_callback, client);
else if (!client->connect_job)
{ {
ADC_client_on_disconnected(client); ADC_client_on_disconnected(client);
return 0; return 0;
@@ -611,6 +600,7 @@ int ADC_client_connect_internal(struct ADC_client* client)
return 1; return 1;
} }
static void ADC_client_on_connected(struct ADC_client* client) static void ADC_client_on_connected(struct ADC_client* client)
{ {
ADC_TRACE; ADC_TRACE;
@@ -674,43 +664,6 @@ void ADC_client_disconnect(struct ADC_client* client)
} }
} }
int ADC_client_dns_callback(struct net_dns_job* job, const struct net_dns_result* result)
{
struct ADC_client* client = (struct ADC_client*) net_dns_job_get_ptr(job);
struct ip_addr_encap* ipaddr;
LOG_WARN("ADC_client_dns_callback(): result=%p (%d)", result, net_dns_result_size(result));
memset(&client->addr, 0, sizeof(client->addr));
ipaddr = net_dns_result_first(result);
switch (ipaddr->af)
{
case AF_INET:
{
struct sockaddr_in* addr4 = (struct sockaddr_in*) &client->addr;
addr4->sin_family = AF_INET;
addr4->sin_port = htons(client->address.port);
memcpy(&addr4->sin_addr, &ipaddr->internal_ip_data.in, sizeof(struct in_addr));
break;
}
case AF_INET6:
{
struct sockaddr_in6* addr6 = (struct sockaddr_in6*) &client->addr;
addr6->sin6_family = AF_INET6;
addr6->sin6_port = htons(client->address.port);
memcpy(&addr6->sin6_addr, &ipaddr->internal_ip_data.in6, sizeof(struct in6_addr));
break;
}
default:
LOG_WARN("Unknown ipaddr!");
}
ADC_client_connect_internal(client);
return 1;
}
static int ADC_client_parse_address(struct ADC_client* client, const char* arg) static int ADC_client_parse_address(struct ADC_client* client, const char* arg)
{ {
ADC_TRACE; ADC_TRACE;
@@ -753,9 +706,6 @@ static int ADC_client_parse_address(struct ADC_client* client, const char* arg)
client->address.hostname = strndup(hub_address, &split[0] - &hub_address[0]); client->address.hostname = strndup(hub_address, &split[0] - &hub_address[0]);
client->callback(client, ADC_CLIENT_NAME_LOOKUP, 0);
ADC_client_set_state(client, ps_dns);
client->dns_job = net_dns_gethostbyname(client->address.hostname, AF_UNSPEC, ADC_client_dns_callback, client);
return 1; return 1;
} }

View File

@@ -21,7 +21,15 @@
#include <locale.h> #include <locale.h>
#ifndef WIN32 #ifndef WIN32
#ifdef SYSTEMD
#define SD_JOURNAL_SUPPRESS_LOCATION
#include <systemd/sd-journal.h>
#else
#include <syslog.h> #include <syslog.h>
#endif
static int use_syslog = 0; static int use_syslog = 0;
#endif #endif
@@ -83,7 +91,9 @@ void hub_log_initialize(const char* file, int syslog)
if (syslog) if (syslog)
{ {
use_syslog = 1; use_syslog = 1;
#ifndef SYSTEMD
openlog("uhub", LOG_PID, LOG_USER); openlog("uhub", LOG_PID, LOG_USER);
#endif
} }
#endif #endif
@@ -132,7 +142,9 @@ void hub_log_shutdown()
if (use_syslog) if (use_syslog)
{ {
use_syslog = 0; use_syslog = 0;
#ifndef SYSTEMD
closelog(); closelog();
#endif
} }
#endif #endif
} }
@@ -212,7 +224,12 @@ void hub_log(int log_verbosity, const char *format, ...)
case log_fatal: level = LOG_CRIT; break; case log_fatal: level = LOG_CRIT; break;
case log_error: level = LOG_ERR; break; case log_error: level = LOG_ERR; break;
case log_warning: level = LOG_WARNING; 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; case log_user: level = LOG_INFO | LOG_AUTH; break;
#endif
case log_info: level = LOG_INFO; break; case log_info: level = LOG_INFO; break;
case log_debug: level = LOG_DEBUG; break; case log_debug: level = LOG_DEBUG; break;
@@ -224,8 +241,13 @@ void hub_log(int log_verbosity, const char *format, ...)
if (level == 0) if (level == 0)
return; return;
#ifdef SYSTEMD
sd_journal_print(level, "%s", logmsg);
#else
level |= (LOG_USER | LOG_DAEMON); level |= (LOG_USER | LOG_DAEMON);
syslog(level, "%s", logmsg); syslog(level, "%s", logmsg);
#endif
} }
#endif #endif

43
tools/uhub-adc-redirector.py Executable file
View File

@@ -0,0 +1,43 @@
#!/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()

30
tools/uhub-nmdc-redirector.py Executable file
View File

@@ -0,0 +1,30 @@
#!/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()