Compare commits
25 Commits
redblack_t
...
op_notify
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d98f013a51 | ||
|
|
2be48a13f7 | ||
|
|
70ba9d5831 | ||
|
|
f91f3ea68c | ||
|
|
5b78c0826d | ||
|
|
5c31f47bea | ||
|
|
51a8e785c0 | ||
|
|
8899e49f73 | ||
|
|
d48ef710d8 | ||
|
|
cfa210b3f3 | ||
|
|
f6f7c7a3a4 | ||
|
|
1fbde2b0fd | ||
|
|
92b65a0e14 | ||
|
|
4d438e1e90 | ||
|
|
4f3c71234b | ||
|
|
fdaadccb99 | ||
|
|
41251f8d32 | ||
|
|
3b18ae251e | ||
|
|
b452488431 | ||
|
|
143b68588a | ||
|
|
5f2b7bc069 | ||
|
|
ce68c446d1 | ||
|
|
6af0f293a6 | ||
|
|
a492f30950 | ||
|
|
a43953bc0d |
8
AUTHORS
8
AUTHORS
@@ -3,7 +3,9 @@ Authors of uhub
|
||||
|
||||
Jan Vidar Krey, Design and implementation
|
||||
E_zombie, Centos/RedHat customization scripts and heavy load testing
|
||||
FleetCommand, Hub topic
|
||||
FleetCommand, Hub topic plugin code
|
||||
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
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
## 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)
|
||||
enable_language(C)
|
||||
@@ -13,15 +13,17 @@ set (UHUB_VERSION_MINOR 4)
|
||||
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(LINK_SUPPORT "Allow hub linking" OFF)
|
||||
option(SSL_SUPPORT "Enable 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)
|
||||
|
||||
find_package(Git)
|
||||
find_package(Sqlite3)
|
||||
|
||||
if (SSL_SUPPORT)
|
||||
if (USE_OPENSSL)
|
||||
@@ -34,11 +36,18 @@ if (SSL_SUPPORT)
|
||||
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)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
include_directories("${PROJECT_SOURCE_DIR}")
|
||||
include_directories(${SQLITE3_INCLUDE_DIRS})
|
||||
|
||||
file (GLOB uhub_SOURCES ${PROJECT_SOURCE_DIR}/core/*.c)
|
||||
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(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_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_only MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_only.c)
|
||||
add_library(mod_topic MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_topic.c)
|
||||
|
||||
if (SQLITE_SUPPORT)
|
||||
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()
|
||||
|
||||
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)
|
||||
@@ -99,17 +101,22 @@ set_target_properties(
|
||||
mod_welcome
|
||||
mod_logging
|
||||
mod_auth_simple
|
||||
mod_auth_sqlite
|
||||
mod_chat_history
|
||||
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(test ${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_no_guest_downloads utils)
|
||||
target_link_libraries(mod_chat_only utils)
|
||||
target_link_libraries(mod_logging 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_logging network)
|
||||
|
||||
|
||||
if(UNIX)
|
||||
add_library(adcclient STATIC ${adcclient_SOURCES})
|
||||
add_executable(uhub-admin ${PROJECT_SOURCE_DIR}/tools/admin.c)
|
||||
@@ -172,24 +180,33 @@ if(SSL_SUPPORT)
|
||||
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")
|
||||
|
||||
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 (UNIX)
|
||||
install( TARGETS uhub 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 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 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 )
|
||||
|
||||
if (SQLITE_SUPPORT)
|
||||
install( TARGETS uhub-passwd RUNTIME DESTINATION bin )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
15
ChangeLog
15
ChangeLog
@@ -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:
|
||||
- Cleaned up code generator for config file parsing.
|
||||
- Merge pull request #5 from yorhel/master
|
||||
|
||||
@@ -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_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_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_1, "tokenizer_basic_1");
|
||||
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)
|
||||
{
|
||||
struct exo_test_data* test;
|
||||
|
||||
if (!handle)
|
||||
{
|
||||
fprintf(stderr, "exotic_add_test: failed, no handle!\n");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include <uhub.h>
|
||||
|
||||
#define MAX_EVENTS 15
|
||||
#define MAX_EVENTS 100
|
||||
static struct timeout_queue* g_queue;
|
||||
static time_t g_now;
|
||||
static size_t g_max;
|
||||
@@ -117,3 +117,28 @@ EXO_TEST(timer_process_5_events_1,{
|
||||
g_now = 4;
|
||||
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;
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
77
cmake/Modules/FindSqlite3.cmake
Normal file
77
cmake/Modules/FindSqlite3.cmake
Normal 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 )
|
||||
@@ -787,6 +787,13 @@ int adc_msg_add_argument(struct adc_message* cmd, const char* string)
|
||||
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)
|
||||
{
|
||||
@@ -866,8 +873,6 @@ int adc_msg_get_argument_index(struct adc_message* cmd, const char prefix[2])
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int adc_msg_escape_length(const char* str)
|
||||
{
|
||||
int add = 0;
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@@ -234,4 +247,5 @@ void adc_msg_unterminate(struct adc_message* cmd);
|
||||
*/
|
||||
int adc_msg_get_arg_offset(struct adc_message* msg);
|
||||
|
||||
|
||||
#endif /* HAVE_UHUB_COMMAND_H */
|
||||
|
||||
@@ -353,6 +353,7 @@ static int command_kick(struct command_base* cbase, struct hub_user* user, struc
|
||||
}
|
||||
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);
|
||||
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)
|
||||
{
|
||||
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..."));
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
hub_notify(cbase->hub, notify_warn, "Shutting down hub (%s)", user->id.nick);
|
||||
cbase->hub->status = hub_status_shutdown;
|
||||
return command_status(cbase, user, cmd, cbuf_create_const("Hub shutting down..."));
|
||||
}
|
||||
|
||||
105
src/core/hub.c
105
src/core/hub.c
@@ -653,6 +653,7 @@ static struct net_connection* start_listening_socket(const char* bind_addr, uint
|
||||
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()));
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
@@ -671,6 +672,60 @@ static struct net_connection* start_listening_socket(const char* bind_addr, uint
|
||||
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 hub_info* hub;
|
||||
@@ -751,6 +806,54 @@ static void unload_ssl_certificates(struct hub_info* hub)
|
||||
}
|
||||
#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 = 0;
|
||||
@@ -834,6 +937,8 @@ struct hub_info* hub_start_service(struct hub_config* config)
|
||||
|
||||
// Start the hub command sub-system
|
||||
hub->commands = command_initialize(hub);
|
||||
|
||||
hub_bot_op_notify_create(hub);
|
||||
return hub;
|
||||
}
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ struct hub_info
|
||||
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;
|
||||
enum hub_state status;
|
||||
char* recvbuf; /* Global receive 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);
|
||||
|
||||
|
||||
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).
|
||||
*/
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
* Returns 1 if the hub is running, and 0 otherwise.
|
||||
*/
|
||||
extern int hub_is_running(struct hub_info* hub);
|
||||
|
||||
#endif /* HAVE_UHUB_HUB_H */
|
||||
|
||||
|
||||
@@ -31,6 +31,10 @@ void on_login_success(struct hub_info* hub, struct hub_user* u)
|
||||
user_set_state(u, state_normal);
|
||||
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 */
|
||||
if (user_is_logged_in(u))
|
||||
route_info_message(hub, u);
|
||||
|
||||
@@ -19,6 +19,10 @@
|
||||
|
||||
#include "uhub.h"
|
||||
|
||||
#ifdef SYSTEMD
|
||||
#include <systemd/sd-daemon.h>
|
||||
#endif
|
||||
|
||||
static int arg_verbose = 5;
|
||||
static int arg_fork = 0;
|
||||
static int arg_check_config = 0;
|
||||
@@ -145,7 +149,16 @@ int main_loop()
|
||||
}
|
||||
#if !defined(WIN32)
|
||||
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);
|
||||
@@ -216,13 +229,17 @@ void print_usage(char* program)
|
||||
" -q Quiet mode - no output\n"
|
||||
" -f Fork to background\n"
|
||||
" -l <file> Log messages to given file (default: stderr)\n"
|
||||
" -L Log messages to syslog\n"
|
||||
" -c <file> Specify configuration file (default: " SERVER_CONFIG ")\n"
|
||||
" -C Check configuration and return\n"
|
||||
" -s Show configuration parameters\n"
|
||||
" -S Show configuration parameters, but ignore defaults\n"
|
||||
" -h This message\n"
|
||||
#ifndef WIN32
|
||||
#ifdef SYSTEMD
|
||||
" -L Log messages to journal\n"
|
||||
#else
|
||||
" -L Log messages to syslog\n"
|
||||
#endif
|
||||
" -u <user> Run as given user\n"
|
||||
" -g <group> Run with given group permissions\n"
|
||||
" -p <file> Store pid in file (process id)\n"
|
||||
|
||||
@@ -104,7 +104,7 @@ static int cbfunc_command_add(struct plugin_handle* plugin, struct plugin_comman
|
||||
cmdh->internal_handle = command;
|
||||
list_append(data->commands, cmdh);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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 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);
|
||||
command_del(plugin_get_hub(plugin)->commands, command);
|
||||
hub_free(command);
|
||||
|
||||
@@ -104,7 +104,19 @@ int route_to_user(struct hub_info* hub, struct hub_user* user, struct adc_messag
|
||||
#endif
|
||||
|
||||
if (!user->connection)
|
||||
return 0;
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 do_send;
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@@ -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));
|
||||
|
||||
user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
|
||||
|
||||
if (user == NULL)
|
||||
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));
|
||||
user_set_state(user, state_protocol);
|
||||
user->type = user_type_client;
|
||||
|
||||
flood_control_reset(&user->flood_chat);
|
||||
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;
|
||||
}
|
||||
|
||||
/// 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)
|
||||
{
|
||||
|
||||
@@ -47,6 +47,7 @@ enum user_flags
|
||||
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_opnotify = 0x00200000, /** User should receive operation notifications. NOTE: Only operators should have this flag! */
|
||||
flag_flood = 0x00400000, /** User has been notified about flooding. */
|
||||
flag_muted = 0x00800000, /** User is muted (cannot chat) */
|
||||
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 */
|
||||
};
|
||||
|
||||
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_info id; /** Contains nick name and CID */
|
||||
enum auth_credentials credentials; /** see enum user_credentials */
|
||||
enum user_state state; /** see enum user_state */
|
||||
enum user_type type;
|
||||
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 */
|
||||
void* ptr;
|
||||
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;
|
||||
@@ -138,6 +148,7 @@ struct hub_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);
|
||||
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.
|
||||
|
||||
@@ -132,10 +132,11 @@ struct timeout_queue* net_backend_get_timeout_queue()
|
||||
*/
|
||||
int net_backend_process()
|
||||
{
|
||||
int res;
|
||||
int res = 0;
|
||||
size_t secs = timeout_queue_get_next_timeout(&g_backend->timeout_queue, g_backend->now);
|
||||
|
||||
res = g_backend->handler.backend_poll(g_backend->data, secs * 1000);
|
||||
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);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -34,10 +34,41 @@ 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);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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", ip_convert_to_string(ipaddr));
|
||||
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(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_destroy(res->addr_list);
|
||||
free_job(res->job);
|
||||
hub_free(res);
|
||||
hub_free((struct net_dns_result*) res);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* 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*);
|
||||
|
||||
/// 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 */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -57,14 +57,30 @@ 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;
|
||||
|
||||
uhub_assert(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++)
|
||||
{
|
||||
while ((evt = t->events[pos % t->max]))
|
||||
evt = t->events[pos % t->max];
|
||||
while (evt)
|
||||
{
|
||||
timeout_queue_remove(t, evt);
|
||||
evt->callback(evt);
|
||||
events++;
|
||||
if (evt->timestamp < pos)
|
||||
{
|
||||
timeout_queue_remove(t, evt);
|
||||
evt->callback(evt);
|
||||
events++;
|
||||
}
|
||||
evt = evt->next;
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
struct timeout_evt* first;
|
||||
struct timeout_evt* it, *first;
|
||||
size_t pos = ((t->last + seconds) % t->max);
|
||||
evt->timestamp = t->last + seconds;
|
||||
evt->next = 0;
|
||||
|
||||
|
||||
first = t->events[pos];
|
||||
|
||||
if (first)
|
||||
{
|
||||
uhub_assert(first->timestamp == evt->timestamp);
|
||||
first->prev->next = evt;
|
||||
evt->prev = first->prev;
|
||||
first->prev = evt;
|
||||
for (it = first; it->next; it = it->next) { }
|
||||
it->next = evt;
|
||||
evt->prev = it;
|
||||
}
|
||||
else
|
||||
{
|
||||
t->events[pos] = evt;
|
||||
evt->prev = evt;
|
||||
evt->prev = evt; // point to self.
|
||||
}
|
||||
evt->next = 0;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
60
src/plugins/mod_no_guest_downloads.c
Normal file
60
src/plugins/mod_no_guest_downloads.c
Normal 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;
|
||||
}
|
||||
|
||||
@@ -127,6 +127,10 @@
|
||||
*/
|
||||
#endif
|
||||
|
||||
#ifdef __GNU__
|
||||
#define POSIX_THREAD_SUPPORT
|
||||
#endif
|
||||
|
||||
#define USE_SELECT
|
||||
#ifndef WINSOCK
|
||||
#include <sys/select.h>
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
enum ADC_client_state
|
||||
{
|
||||
ps_none, /* Not connected */
|
||||
ps_dns, /* looking up name */
|
||||
ps_conn, /* Connecting... */
|
||||
ps_conn_ssl, /* SSL handshake */
|
||||
ps_protocol, /* Have sent HSUP */
|
||||
@@ -68,7 +67,7 @@ struct ADC_client
|
||||
struct net_connection* con;
|
||||
struct net_timer* timer;
|
||||
struct sockaddr_storage addr;
|
||||
struct net_dns_job* dns_job;
|
||||
struct net_connect_handle* connect_job;
|
||||
struct ADC_client_address address;
|
||||
char* nick;
|
||||
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[] =
|
||||
{
|
||||
"ps_none",
|
||||
"ps_dns",
|
||||
"ps_conn",
|
||||
"ps_conn_ssl",
|
||||
"ps_protocol",
|
||||
@@ -164,18 +162,12 @@ static void event_callback(struct net_connection* con, int events, void *arg)
|
||||
|
||||
switch (client->state)
|
||||
{
|
||||
case ps_dns:
|
||||
break;
|
||||
|
||||
case ps_conn:
|
||||
if (events == NET_EVENT_TIMEOUT)
|
||||
{
|
||||
client->callback(client, ADC_CLIENT_DISCONNECTED, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (events & NET_EVENT_WRITE)
|
||||
ADC_client_connect_internal(client);
|
||||
break;
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
@@ -539,11 +531,6 @@ struct ADC_client* ADC_client_create(const char* nickname, const char* descripti
|
||||
ADC_TRACE;
|
||||
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);
|
||||
|
||||
client->nick = hub_strdup(nickname);
|
||||
@@ -570,40 +557,42 @@ void ADC_client_destroy(struct ADC_client* 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)
|
||||
{
|
||||
ADC_TRACE;
|
||||
if (client->state == ps_none)
|
||||
{
|
||||
// Parse address and start name resolving!
|
||||
if (!ADC_client_parse_address(client, address))
|
||||
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);
|
||||
}
|
||||
else
|
||||
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;
|
||||
@@ -611,6 +600,7 @@ int ADC_client_connect_internal(struct ADC_client* client)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void ADC_client_on_connected(struct ADC_client* client)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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->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;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,15 @@
|
||||
#include <locale.h>
|
||||
|
||||
#ifndef WIN32
|
||||
|
||||
#ifdef SYSTEMD
|
||||
#define SD_JOURNAL_SUPPRESS_LOCATION
|
||||
#include <systemd/sd-journal.h>
|
||||
|
||||
#else
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
|
||||
static int use_syslog = 0;
|
||||
#endif
|
||||
|
||||
@@ -83,7 +91,9 @@ void hub_log_initialize(const char* file, int syslog)
|
||||
if (syslog)
|
||||
{
|
||||
use_syslog = 1;
|
||||
#ifndef SYSTEMD
|
||||
openlog("uhub", LOG_PID, LOG_USER);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -132,7 +142,9 @@ void hub_log_shutdown()
|
||||
if (use_syslog)
|
||||
{
|
||||
use_syslog = 0;
|
||||
#ifndef SYSTEMD
|
||||
closelog();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -212,7 +224,12 @@ void hub_log(int log_verbosity, const char *format, ...)
|
||||
case log_fatal: level = LOG_CRIT; break;
|
||||
case log_error: level = LOG_ERR; break;
|
||||
case log_warning: level = LOG_WARNING; break;
|
||||
case log_user: level = LOG_INFO | LOG_AUTH; break;
|
||||
#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;
|
||||
|
||||
@@ -224,8 +241,13 @@ void hub_log(int log_verbosity, const char *format, ...)
|
||||
if (level == 0)
|
||||
return;
|
||||
|
||||
#ifdef SYSTEMD
|
||||
sd_journal_print(level, "%s", logmsg);
|
||||
|
||||
#else
|
||||
level |= (LOG_USER | LOG_DAEMON);
|
||||
syslog(level, "%s", logmsg);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
43
tools/uhub-adc-redirector.py
Executable file
43
tools/uhub-adc-redirector.py
Executable 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
30
tools/uhub-nmdc-redirector.py
Executable 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()
|
||||
Reference in New Issue
Block a user