1
0
mirror of https://github.com/stefanocasazza/ULib.git synced 2025-10-05 19:18:01 +08:00
This commit is contained in:
stefanocasazza 2017-06-19 20:24:31 +02:00
parent a66201800c
commit c6a85f2261
44 changed files with 972 additions and 209 deletions

View File

@ -28,7 +28,7 @@ The current version offers the following features :
* Support for aliases/redirection. * Support for aliases/redirection.
* Support for switch the site to a maintenance page only. * Support for switch the site to a maintenance page only.
* Support for URL traffic based throttling (experimental). * Support for URL traffic based throttling (experimental).
* Support for overriden of error messages by local document (ErrorDocument/40x|500.html). * Support for overriden of error messages by local document (ex. ErrorDocument/400.html).
* Support for RewriteRule (lighttpd-like) that check for file existence as they do on Apache, some CMS (SilverStripe) require it. * Support for RewriteRule (lighttpd-like) that check for file existence as they do on Apache, some CMS (SilverStripe) require it.
* Support for (apache-like) log [NCSA extended/combined format](http://httpd.apache.org/docs/2.0/mod/mod_log_config.html) * Support for (apache-like) log [NCSA extended/combined format](http://httpd.apache.org/docs/2.0/mod/mod_log_config.html)
* Support for [JSONRequest](http://json.org/JSONRequest.html). * Support for [JSONRequest](http://json.org/JSONRequest.html).
@ -69,6 +69,7 @@ The current version offers the following features :
* [DNS rebinding](http://en.wikipedia.org/wiki/DNS_rebinding) prevention by RFC1918 filtering and Host header validation. * [DNS rebinding](http://en.wikipedia.org/wiki/DNS_rebinding) prevention by RFC1918 filtering and Host header validation.
* selective uri support (DOS regex) for [HTTP Strict Transport Security](https://developer.mozilla.org/en/Security/HTTP_Strict_Transport_Security). * selective uri support (DOS regex) for [HTTP Strict Transport Security](https://developer.mozilla.org/en/Security/HTTP_Strict_Transport_Security).
* Immune to [Slow Read DoS attack](http://code.google.com/p/slowhttptest/) * Immune to [Slow Read DoS attack](http://code.google.com/p/slowhttptest/)
* Provide evasive action in the event of an HTTP DoS or DDoS attack or brute force attack.
* [High SSL server quality score](https://www.ssllabs.com/ssltest/analyze.html?d=wifi-aaa2.comune.fi.it) * [High SSL server quality score](https://www.ssllabs.com/ssltest/analyze.html?d=wifi-aaa2.comune.fi.it)
## Who is Using ULib ## Who is Using ULib

38
configure vendored
View File

@ -1050,6 +1050,7 @@ enable_http2
enable_check_time enable_check_time
enable_classic enable_classic
enable_throttling enable_throttling
enable_evasive
enable_alias enable_alias
enable_welcome enable_welcome
enable_ACL enable_ACL
@ -1793,6 +1794,7 @@ Optional Features:
--enable-check-time enable server check time between request for parallelization [default=no] --enable-check-time enable server check time between request for parallelization [default=no]
--enable-classic enable server classic model support [default=no] --enable-classic enable server classic model support [default=no]
--enable-throttling enable server bandwidth throttling support [default=no] --enable-throttling enable server bandwidth throttling support [default=no]
--enable-evasive enable server evasive action support [default=no]
--enable-alias enable alias URI support [default=yes] --enable-alias enable alias URI support [default=yes]
--enable-welcome enable welcome message support [default=no] --enable-welcome enable welcome message support [default=no]
--enable-ACL enable ACL filtering support [default=no] --enable-ACL enable ACL filtering support [default=no]
@ -26478,6 +26480,24 @@ $as_echo "#define U_THROTTLING_SUPPORT 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_throttling" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_throttling" >&5
$as_echo "$enable_throttling" >&6; } $as_echo "$enable_throttling" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if you want to enable to provide evasive action in the event of an HTTP DoS or DDoS attack or brute force attack" >&5
$as_echo_n "checking if you want to enable to provide evasive action in the event of an HTTP DoS or DDoS attack or brute force attack... " >&6; }
# Check whether --enable-evasive was given.
if test "${enable_evasive+set}" = set; then :
enableval=$enable_evasive;
fi
if test -z "$enable_evasive"; then
enable_evasive="no"
fi
if test "$enable_evasive" = "yes"; then
$as_echo "#define U_EVASIVE_SUPPORT 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_evasive" >&5
$as_echo "$enable_evasive" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if you want to enable alias URI support" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if you want to enable alias URI support" >&5
$as_echo_n "checking if you want to enable alias URI support... " >&6; } $as_echo_n "checking if you want to enable alias URI support... " >&6; }
# Check whether --enable-alias was given. # Check whether --enable-alias was given.
@ -32849,17 +32869,20 @@ if test "x$ac_cv_crc32_intrinsics" = xyes; then
esac esac
fi fi
fi fi
##########################
if test "$ac_cv_c_compiler_gnu" = "yes" -a "x$GCC_IS_CLANG" = xno; then if test "$ac_cv_c_compiler_gnu" = "yes" -a "x$GCC_IS_CLANG" = xno; then
if test "$enable_static" = "yes" -a "$enable_shared" = "no" -a "$enable_stdcpp" = "yes"; then if test "$enable_static" = "yes" -a "$enable_shared" = "no" -a "$enable_stdcpp" = "yes"; then
gcc_lib=`gcc -print-libgcc-file-name`
gcc_dir=`dirname $gcc_lib`
if test -f "$gcc_dir/libstdc++.a"; then ## if test -f "$gcc_dir/libstdc++.a"; then
ULIB_LIBS="$ULIB_LIBS $gcc_dir/libstdc++.a $gcc_lib" ## gcc_lib=`gcc -print-libgcc-file-name`
else ## gcc_dir=`dirname $gcc_lib`
ULIB_LIBS="$ULIB_LIBS -lstdc++ -lgcc" ## ULIB_LIBS="$ULIB_LIBS $gcc_dir/libstdc++.a $gcc_lib"
fi ## else
## ULIB_LIBS="$ULIB_LIBS -lstdc++ -lgcc"
## fi
ULIB_LIBS="$ULIB_LIBS -lstdc++ -lgcc"
else else
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use libgcc" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use libgcc" >&5
$as_echo_n "checking whether to use libgcc... " >&6; } $as_echo_n "checking whether to use libgcc... " >&6; }
@ -32883,7 +32906,6 @@ fi
fi fi
fi fi
##########################
# Check for availablity of "old style" C++ strstream header # Check for availablity of "old style" C++ strstream header
for ac_header in strstream.h for ac_header in strstream.h

View File

@ -2541,17 +2541,20 @@ if test "x$ac_cv_crc32_intrinsics" = xyes; then
esac esac
fi fi
fi fi
##########################
if test "$ac_cv_c_compiler_gnu" = "yes" -a "x$GCC_IS_CLANG" = xno; then if test "$ac_cv_c_compiler_gnu" = "yes" -a "x$GCC_IS_CLANG" = xno; then
if test "$enable_static" = "yes" -a "$enable_shared" = "no" -a "$enable_stdcpp" = "yes"; then if test "$enable_static" = "yes" -a "$enable_shared" = "no" -a "$enable_stdcpp" = "yes"; then
gcc_lib=`gcc -print-libgcc-file-name`
gcc_dir=`dirname $gcc_lib`
if test -f "$gcc_dir/libstdc++.a"; then ## if test -f "$gcc_dir/libstdc++.a"; then
ULIB_LIBS="$ULIB_LIBS $gcc_dir/libstdc++.a $gcc_lib" ## gcc_lib=`gcc -print-libgcc-file-name`
else ## gcc_dir=`dirname $gcc_lib`
ULIB_LIBS="$ULIB_LIBS -lstdc++ -lgcc" ## ULIB_LIBS="$ULIB_LIBS $gcc_dir/libstdc++.a $gcc_lib"
fi ## else
## ULIB_LIBS="$ULIB_LIBS -lstdc++ -lgcc"
## fi
ULIB_LIBS="$ULIB_LIBS -lstdc++ -lgcc"
else else
AC_MSG_CHECKING([whether to use libgcc]) AC_MSG_CHECKING([whether to use libgcc])
AC_ARG_ENABLE(libgcc, AC_ARG_ENABLE(libgcc,
@ -2568,7 +2571,6 @@ if test "$ac_cv_c_compiler_gnu" = "yes" -a "x$GCC_IS_CLANG" = xno; then
) )
fi fi
fi fi
##########################
# Check for availablity of "old style" C++ strstream header # Check for availablity of "old style" C++ strstream header
AC_CHECK_HEADERS([strstream.h]) AC_CHECK_HEADERS([strstream.h])

View File

@ -71,6 +71,17 @@
# #
# if PREFORK_CHILD is not defined is as case (>1) with num process the number of CPU in the system # if PREFORK_CHILD is not defined is as case (>1) with num process the number of CPU in the system
# ---------------------------------------------------------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------------------------------------------------------
# This directive are for evasive action in the event of an HTTP DoS or DDoS attack or brute force attack
# ----------------------------------------------------------------------------------------------------------------------------------------
# DOS_PAGE_COUNT this is the threshhold for the number of requests for the same page (or URI) per page interval
# DOS_PAGE_INTERVAL the interval for the page count threshhold; defaults to 1 second intervals
# DOS_SITE_COUNT this is the threshhold for the total number of requests for any object by the same client per site interval
# DOS_SITE_INTERVAL the interval for the site count threshhold; defaults to 1 second intervals
# DOS_BLOCKING_PERIOD the blocking period is the amount of time (in seconds) that a client will be blocked for if they are added to the blocking list (defaults to 10)
# DOS_WHITE_LIST list of comma separated IP addresses of trusted clients can be whitelisted to insure they are never denied (IPADDR[/MASK])
# DOS_EMAIL_NOTIFY the email address to send a message whenever an IP address becomes blacklisted
# DOS_SYSTEM_COMMAND the system command specified will be executed whenever an IP address becomes blacklisted. Use %v to denote the IP address of the blacklisted IP
# ----------------------------------------------------------------------------------------------------------------------------------------
userver { userver {

View File

@ -117,6 +117,17 @@ public:
// 1 - classic, forking after accept client) // 1 - classic, forking after accept client)
// >1 - pool of process serialize plus monitoring process) // >1 - pool of process serialize plus monitoring process)
// --------------------------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------------------------
// This directive are for evasive action in the event of an HTTP DoS or DDoS attack or brute force attack
// ---------------------------------------------------------------------------------------------------------------------------------------
// DOS_PAGE_COUNT this is the threshhold for the number of requests for the same page (or URI) per page interval
// DOS_PAGE_INTERVAL the interval for the page count threshhold; defaults to 1 second intervals
// DOS_SITE_COUNT this is the threshhold for the total number of requests for any object by the same client per site interval
// DOS_SITE_INTERVAL the interval for the site count threshhold; defaults to 1 second intervals
// DOS_BLOCKING_PERIOD the blocking period is the amount of time (in seconds) that a client will be blocked for if they are added to the blocking list (defaults to 10)
// DOS_WHITE_LIST list of comma separated IP addresses of trusted clients can be whitelisted to insure they are never denied (IPADDR[/MASK])
// DOS_EMAIL_NOTIFY the email address to send a message whenever an IP address becomes blacklisted
// DOS_SYSTEM_COMMAND the system command specified will be executed whenever an IP address becomes blacklisted. Use %v to denote the IP address of the blacklisted IP
// ---------------------------------------------------------------------------------------------------------------------------------------
# ifdef U_SSL_SOCKET # ifdef U_SSL_SOCKET
UServer_Base::bssl = true; UServer_Base::bssl = true;

View File

@ -40,6 +40,7 @@ public:
if (subject == U_NOT_FOUND) U_ERROR("cannot find mail header subject on input data"); if (subject == U_NOT_FOUND) U_ERROR("cannot find mail header subject on input data");
// ----------------------------------------------------------------------------------------------------------------------------
// scanf mail header Subject: from request // scanf mail header Subject: from request
// ---------------------------------------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------------------------------------
// "Subject: %*[^"]\"%[^"]\", %*[^"]\"%[^"]\", %*[^"]\"%[^"]\"" // "Subject: %*[^"]\"%[^"]\", %*[^"]\"%[^"]\", %*[^"]\"%[^"]\""

View File

@ -19,13 +19,13 @@
#define U_PRINT_MEM_USAGE #define U_PRINT_MEM_USAGE
#ifdef DEBUG #ifdef DEBUG
#define U_MAIN_END(value) return value # define U_MAIN_END(value) return value
# ifdef U_STDCPP_ENABLE # ifdef U_STDCPP_ENABLE
# undef U_PRINT_MEM_USAGE # undef U_PRINT_MEM_USAGE
# define U_PRINT_MEM_USAGE UApplication::printMemUsage(); # define U_PRINT_MEM_USAGE UApplication::printMemUsage();
# endif # endif
#else #else
#define U_MAIN_END(value) ::exit(value) # define U_MAIN_END(value) ::exit(value)
#endif #endif
#define U_MAIN \ #define U_MAIN \

View File

@ -205,6 +205,9 @@ static inline uint32_t u_findEndHeader1(const char* restrict s, uint32_t n) /* f
U_INTERNAL_TRACE("u_findEndHeader1(%.*s,%u)", U_min(n,128), s, n) U_INTERNAL_TRACE("u_findEndHeader1(%.*s,%u)", U_min(n,128), s, n)
U_INTERNAL_ASSERT_POINTER(s) U_INTERNAL_ASSERT_POINTER(s)
U_INTERNAL_ASSERT_MAJOR(n, 0)
if (u_get_unalignedp32(s+n-4) == U_MULTICHAR_CONSTANT32('\r','\n','\r','\n')) return (n-4);
p = memmem(s, n, U_CONSTANT_TO_PARAM(U_CRLF2)); p = memmem(s, n, U_CONSTANT_TO_PARAM(U_CRLF2));

View File

@ -472,22 +472,9 @@ public:
return _insertDataStorage(op); return _insertDataStorage(op);
} }
bool insertDataStorage(const UString& _key, int _flag = RDB_INSERT_WITH_PADDING) bool insertDataStorage(const char* s, uint32_t n, int _flag = RDB_INSERT) // SSL session cache...
{ {
U_TRACE(0, "URDBObjectHandler<UDataStorage*>::insertDataStorage(%V,%d)", _key.rep, _flag) U_TRACE(0, "URDBObjectHandler<UDataStorage*>::insertDataStorage(%.*S,%u,%d)", n, s, n, _flag)
U_CHECK_MEMORY
U_INTERNAL_ASSERT_POINTER(pDataStorage)
pDataStorage->setKeyIdDataSession(_key);
return insertDataStorage(_flag);
}
void insertDataStorage(const char* s, uint32_t n)
{
U_TRACE(0, "URDBObjectHandler<UDataStorage*>::insertDataStorage(%.*S,%u)", n, s, n)
U_CHECK_MEMORY U_CHECK_MEMORY
@ -495,7 +482,14 @@ public:
pDataStorage->setKeyIdDataSession(s, n); pDataStorage->setKeyIdDataSession(s, n);
(void) insertDataStorage(RDB_INSERT); // SSL session cache... return insertDataStorage(_flag);
}
bool insertDataStorage(const UString& _key, int _flag = RDB_INSERT_WITH_PADDING)
{
U_TRACE(0, "URDBObjectHandler<UDataStorage*>::insertDataStorage(%V,%d)", _key.rep, _flag)
return insertDataStorage(U_STRING_TO_PARAM(_key), _flag);
} }
UString getKeyID() const { return pDataStorage->keyid; } UString getKeyID() const { return pDataStorage->keyid; }

View File

@ -145,6 +145,19 @@ typedef struct uhttpinfo {
unsigned char flag[16]; unsigned char flag[16];
} uhttpinfo; } uhttpinfo;
/**
* GET is used to retrieve a resource on the server.
* HEAD is used to retrieve some information about the document, but don't need the document itself.
* POST says that you are providing some information of your own (i.e., in forms). This may change the state of the server in some way, such as creating a record in a database.
* PUT is used to replace or create a new document on the server.
* DELETE is used to remove a document on the server.
* TRACE is used for protocol debugging purposes.
* OPTIONS is used when the client looks for other methods which can be used on the document.
* CONNECT is used when a client needs to talk to an HTTPS server through a proxy server.
*
* Other HTTP methods that you may see (LINK, UNLINK, and PATCH) are less clearly defined
*/
enum HTTPMethodType { enum HTTPMethodType {
/* request methods */ /* request methods */
HTTP_GET = 0x00000001, HTTP_GET = 0x00000001,

View File

@ -144,7 +144,7 @@ union uustringrep { ustringrep* p1; UStringRep* p2; };
class U_EXPORT ULib { class U_EXPORT ULib {
public: public:
ULib(const char* mempool) { init(mempool, U_NULLPTR); } ULib(const char* mempool) { init(mempool, U_NULLPTR); }
~ULib() { end(); } ~ULib() { end(); }
static void end(); static void end();
static void init(const char* mempool, char** argv); static void init(const char* mempool, char** argv);

View File

@ -808,6 +808,9 @@
/* enable client response partial write support */ /* enable client response partial write support */
#undef U_CLIENT_RESPONSE_PARTIAL_WRITE_SUPPORT #undef U_CLIENT_RESPONSE_PARTIAL_WRITE_SUPPORT
/* enable server evasive action support */
#undef U_EVASIVE_SUPPORT
/* enable GDB stack dump support */ /* enable GDB stack dump support */
#undef U_GDB_STACK_DUMP_ENABLE #undef U_GDB_STACK_DUMP_ENABLE

View File

@ -98,6 +98,7 @@ vClientImage = new client_type[UNotifier::max_connection]; } }
class UHTTP; class UHTTP;
class UHTTP2; class UHTTP2;
class UCommand; class UCommand;
class UEvasive;
class UDayLight; class UDayLight;
class UTimeStat; class UTimeStat;
class USSLSocket; class USSLSocket;
@ -111,6 +112,7 @@ class UHttpPlugIn;
class UFCGIPlugIn; class UFCGIPlugIn;
class USCGIPlugIn; class USCGIPlugIn;
class UThrottling; class UThrottling;
class USmtpClient;
class UNoCatPlugIn; class UNoCatPlugIn;
class UGeoIPPlugIn; class UGeoIPPlugIn;
class UClient_Base; class UClient_Base;
@ -136,9 +138,9 @@ public:
U_MEMORY_ALLOCATOR U_MEMORY_ALLOCATOR
U_MEMORY_DEALLOCATOR U_MEMORY_DEALLOCATOR
// ----------------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------------------------
// UServer - configuration parameters // UServer - configuration parameters
// ----------------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------------------------
// ENABLE_IPV6 flag indicating the use of ipv6 // ENABLE_IPV6 flag indicating the use of ipv6
// SERVER host name or ip address for the listening socket // SERVER host name or ip address for the listening socket
// PORT port number for the listening socket // PORT port number for the listening socket
@ -189,7 +191,18 @@ public:
// PREFORK_CHILD number of child server processes created at startup ( 0 - serialize, no forking // PREFORK_CHILD number of child server processes created at startup ( 0 - serialize, no forking
// 1 - classic, forking after client accept // 1 - classic, forking after client accept
// >1 - pool of serialized processes plus monitoring process) // >1 - pool of serialized processes plus monitoring process)
// ----------------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------------------------
// This directive are for evasive action in the event of an HTTP DoS or DDoS attack or brute force attack
// --------------------------------------------------------------------------------------------------------------------------------------
// DOS_PAGE_COUNT this is the threshhold for the number of requests for the same page (or URI) per page interval
// DOS_PAGE_INTERVAL the interval for the page count threshhold; defaults to 1 second intervals
// DOS_SITE_COUNT this is the threshhold for the total number of requests for any object by the same client per site interval
// DOS_SITE_INTERVAL the interval for the site count threshhold; defaults to 1 second intervals
// DOS_BLOCKING_PERIOD the blocking period is the amount of time (in seconds) that a client will be blocked for if they are added to the blocking list (defaults to 10)
// DOS_WHITE_LIST list of comma separated IP addresses of trusted clients can be whitelisted to insure they are never denied (IPADDR[/MASK])
// DOS_EMAIL_NOTIFY the email address to send a message whenever an IP address becomes blacklisted
// DOS_SYSTEM_COMMAND the system command specified will be executed whenever an IP address becomes blacklisted. Use %v to denote the IP address of the blacklisted IP
// --------------------------------------------------------------------------------------------------------------------------------------
static void run(); // loop waiting for connection static void run(); // loop waiting for connection
@ -225,9 +238,6 @@ public:
static void setMsgWelcome(const UString& msg); static void setMsgWelcome(const UString& msg);
#endif #endif
#if defined(U_LINUX) && defined(ENABLE_THREAD)
#endif
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// MANAGE PLUGIN MODULES // MANAGE PLUGIN MODULES
// ------------------------------------------------------------------- // -------------------------------------------------------------------
@ -283,7 +293,7 @@ public:
char buffer4[512]; char buffer4[512];
char buffer5[512]; char buffer5[512];
char buffer6[512]; char buffer6[512];
char buffer7[431]; char buffer7[402];
// --------------------------------- // ---------------------------------
uint8_t flag_sigterm; uint8_t flag_sigterm;
// --------------------------------- // ---------------------------------
@ -296,12 +306,14 @@ public:
// --------------------------------- // ---------------------------------
sem_t lock_user1; sem_t lock_user1;
sem_t lock_user2; sem_t lock_user2;
sem_t lock_evasive;
sem_t lock_throttling; sem_t lock_throttling;
sem_t lock_rdb_server; sem_t lock_rdb_server;
sem_t lock_data_session; sem_t lock_data_session;
sem_t lock_db_not_found; sem_t lock_db_not_found;
char spinlock_user1[1]; char spinlock_user1[1];
char spinlock_user2[1]; char spinlock_user2[1];
char spinlock_evasive[1];
char spinlock_throttling[1]; char spinlock_throttling[1];
char spinlock_rdb_server[1]; char spinlock_rdb_server[1];
char spinlock_data_session[1]; char spinlock_data_session[1];
@ -353,6 +365,7 @@ public:
#define U_SRV_CNT_PARALLELIZATION UServer_Base::ptr_shared_data->cnt_parallelization #define U_SRV_CNT_PARALLELIZATION UServer_Base::ptr_shared_data->cnt_parallelization
#define U_SRV_LOCK_USER1 &(UServer_Base::ptr_shared_data->lock_user1) #define U_SRV_LOCK_USER1 &(UServer_Base::ptr_shared_data->lock_user1)
#define U_SRV_LOCK_USER2 &(UServer_Base::ptr_shared_data->lock_user2) #define U_SRV_LOCK_USER2 &(UServer_Base::ptr_shared_data->lock_user2)
#define U_SRV_LOCK_EVASIVE &(UServer_Base::ptr_shared_data->lock_evasive)
#define U_SRV_LOCK_THROTTLING &(UServer_Base::ptr_shared_data->lock_throttling) #define U_SRV_LOCK_THROTTLING &(UServer_Base::ptr_shared_data->lock_throttling)
#define U_SRV_LOCK_RDB_SERVER &(UServer_Base::ptr_shared_data->lock_rdb_server) #define U_SRV_LOCK_RDB_SERVER &(UServer_Base::ptr_shared_data->lock_rdb_server)
#define U_SRV_LOCK_SSL_SESSION &(UServer_Base::ptr_shared_data->lock_ssl_session) #define U_SRV_LOCK_SSL_SESSION &(UServer_Base::ptr_shared_data->lock_ssl_session)
@ -360,6 +373,7 @@ public:
#define U_SRV_LOCK_DB_NOT_FOUND &(UServer_Base::ptr_shared_data->lock_db_not_found) #define U_SRV_LOCK_DB_NOT_FOUND &(UServer_Base::ptr_shared_data->lock_db_not_found)
#define U_SRV_SPINLOCK_USER1 UServer_Base::ptr_shared_data->spinlock_user1 #define U_SRV_SPINLOCK_USER1 UServer_Base::ptr_shared_data->spinlock_user1
#define U_SRV_SPINLOCK_USER2 UServer_Base::ptr_shared_data->spinlock_user2 #define U_SRV_SPINLOCK_USER2 UServer_Base::ptr_shared_data->spinlock_user2
#define U_SRV_SPINLOCK_EVASIVE UServer_Base::ptr_shared_data->spinlock_evasive
#define U_SRV_SPINLOCK_THROTTLING UServer_Base::ptr_shared_data->spinlock_throttling #define U_SRV_SPINLOCK_THROTTLING UServer_Base::ptr_shared_data->spinlock_throttling
#define U_SRV_SPINLOCK_RDB_SERVER UServer_Base::ptr_shared_data->spinlock_rdb_server #define U_SRV_SPINLOCK_RDB_SERVER UServer_Base::ptr_shared_data->spinlock_rdb_server
#define U_SRV_SPINLOCK_SSL_SESSION UServer_Base::ptr_shared_data->spinlock_ssl_session #define U_SRV_SPINLOCK_SSL_SESSION UServer_Base::ptr_shared_data->spinlock_ssl_session
@ -633,6 +647,24 @@ protected:
static void initThrottlingServer(); static void initThrottlingServer();
#endif #endif
#ifdef U_EVASIVE_SUPPORT // provide evasive action in the event of an HTTP DoS or DDoS attack or brute force attack
static bool bwhitelist;
static UString* emailAddress;
static UString* whitelist_IP;
static UEvasive* evasive_rec;
static UString* systemCommand;
static USmtpClient* emailClient;
static UVector<UIPAllow*>* vwhitelist_IP;
static URDBObjectHandler<UDataStorage*>* db_evasive;
static uint32_t blocking_period, page_interval, page_count, site_interval, site_count;
static void initEvasive();
static bool checkHitUriStats();
static bool checkHitSiteStats();
static bool checkHitStats(const char* key, uint32_t key_len, uint32_t interval, uint32_t count);
static bool checkHold(in_addr_t client, const char* client_address, uint32_t client_address_len);
#endif
UServer_Base(UFileConfig* pcfg = U_NULLPTR); UServer_Base(UFileConfig* pcfg = U_NULLPTR);
virtual ~UServer_Base(); virtual ~UServer_Base();
@ -716,6 +748,7 @@ private:
friend class UHTTP; friend class UHTTP;
friend class UHTTP2; friend class UHTTP2;
friend class UEvasive;
friend class UDayLight; friend class UDayLight;
friend class UTimeStat; friend class UTimeStat;
friend class USSLSocket; friend class USSLSocket;

View File

@ -204,10 +204,40 @@ public:
static bool scanfHeaderRequest(const char* ptr, uint32_t size); static bool scanfHeaderRequest(const char* ptr, uint32_t size);
static bool scanfHeaderResponse(const char* ptr, uint32_t size); static bool scanfHeaderResponse(const char* ptr, uint32_t size);
static bool readHeaderResponse(USocket* socket, UString& buffer); static bool readHeaderResponse(USocket* socket, UString& buffer);
static bool isValidRequest( const char* ptr, uint32_t size) __pure;
static bool isValidRequestExt(const char* ptr, uint32_t size) __pure;
static bool readBodyResponse(USocket* socket, UString* buffer, UString& body); static bool readBodyResponse(USocket* socket, UString* buffer, UString& body);
static bool isValidRequest(const char* ptr, uint32_t sz)
{
U_TRACE(0, "UHTTP::isValidRequest(%.*S,%u)", 30, ptr, sz)
U_INTERNAL_ASSERT_MAJOR(sz, 0)
U_INTERNAL_DUMP("sz = %u UClientImage_Base::size_request = %u", sz, UClientImage_Base::size_request)
if (u_get_unalignedp32(ptr+sz-4) == U_MULTICHAR_CONSTANT32('\r','\n','\r','\n')) U_RETURN(true);
U_RETURN(false);
}
static bool isValidRequestExt(const char* ptr, uint32_t sz)
{
U_TRACE(0, "UHTTP::isValidRequestExt(%.*S,%u)", 30, ptr, sz)
U_INTERNAL_ASSERT_MAJOR(sz, 0)
if (sz >= U_CONSTANT_SIZE("GET / HTTP/1.0\r\n\r\n") &&
isValidMethod(ptr) &&
(isValidRequest(ptr, sz) ||
(UClientImage_Base::size_request &&
isValidRequest(ptr, UClientImage_Base::size_request)) ||
memmem(ptr, sz, U_CONSTANT_TO_PARAM(U_CRLF2)) != U_NULLPTR))
{
U_RETURN(true);
}
U_RETURN(false);
}
#ifndef U_HTTP2_DISABLE #ifndef U_HTTP2_DISABLE
static bool copyHeaders(UStringRep* key, void* elem); static bool copyHeaders(UStringRep* key, void* elem);
static bool upgradeHeaders(UStringRep* key, void* elem) static bool upgradeHeaders(UStringRep* key, void* elem)

View File

@ -247,6 +247,17 @@ AC_DEFUN([AC_COMPILATION_OPTIONS],[
fi fi
AC_MSG_RESULT([$enable_throttling]) AC_MSG_RESULT([$enable_throttling])
AC_MSG_CHECKING(if you want to enable to provide evasive action in the event of an HTTP DoS or DDoS attack or brute force attack)
AC_ARG_ENABLE(evasive,
[ --enable-evasive enable server evasive action support [[default=no]]])
if test -z "$enable_evasive"; then
enable_evasive="no"
fi
if test "$enable_evasive" = "yes"; then
AC_DEFINE(U_EVASIVE_SUPPORT, 1, [enable server evasive action support])
fi
AC_MSG_RESULT([$enable_evasive])
AC_MSG_CHECKING(if you want to enable alias URI support) AC_MSG_CHECKING(if you want to enable alias URI support)
AC_ARG_ENABLE(alias, AC_ARG_ENABLE(alias,
[ --enable-alias enable alias URI support [[default=yes]]]) [ --enable-alias enable alias URI support [[default=yes]]])

View File

@ -65,7 +65,7 @@ void UApplication::printMemUsage()
UServer_Base::getStats().rep, UServer_Base::getStats().rep,
(double)vsz / (1024.0 * 1024.0), (double)vsz / (1024.0 * 1024.0),
(double)rss / (1024.0 * 1024.0), UNotifier::max_nfd_ready, UServer_Base::max_depth, UServer_Base::nread_again, UServer_Base::nread, (double)rss / (1024.0 * 1024.0), UNotifier::max_nfd_ready, UServer_Base::max_depth, UServer_Base::nread_again, UServer_Base::nread,
(UServer_Base::nread_again * 100) / UServer_Base::nread, UServer_Base::wakeup_for_nothing, UNotifier::bepollet_threshold); (UServer_Base::nread_again * 100) / (UServer_Base::nread ? UServer_Base::nread : 1), UServer_Base::wakeup_for_nothing, UNotifier::bepollet_threshold);
ostrstream os(buffer + len, sizeof(buffer) - len); ostrstream os(buffer + len, sizeof(buffer) - len);

View File

@ -312,7 +312,6 @@ void ULib::init(const char* mempool, char** argv)
void ULib::end() void ULib::end()
{ {
#if defined(U_STDCPP_ENABLE) && defined(DEBUG) #if defined(U_STDCPP_ENABLE) && defined(DEBUG)
UApplication::printMemUsage(); UApplication::printMemUsage();
#endif #endif

View File

@ -58,9 +58,7 @@ bool USmtpClient::_connectServer(const UString& server, unsigned int port, int t
U_INTERNAL_ASSERT_EQUALS(u_buffer_len, 0) U_INTERNAL_ASSERT_EQUALS(u_buffer_len, 0)
// NB: the last argument (0) is necessary... u_buffer_len = u__snprintf(u_buffer,U_BUFFER_SIZE,U_CONSTANT_TO_PARAM("Sorry, couldn't connect to server '%v:%u'%R"),server.rep,port,0); // NB: the last argument (0) is necessary...
u_buffer_len = u__snprintf(u_buffer, U_BUFFER_SIZE, U_CONSTANT_TO_PARAM("Sorry, couldn't connect to server '%v:%u'%R"), server.rep, port, 0);
} }
else else
{ {
@ -91,6 +89,7 @@ bool USmtpClient::_connectServer(UFileConfig& cfg, unsigned int port, int timeou
U_ASSERT_EQUALS(cfg.empty(), false) U_ASSERT_EQUALS(cfg.empty(), false)
// ----------------------------------------------------------------------------------------------------------------------
// USmtpClient - configuration parameters // USmtpClient - configuration parameters
// ---------------------------------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------------------------------
// SMTP_SERVER host name or ip address for server // SMTP_SERVER host name or ip address for server

View File

@ -31,7 +31,7 @@ bool URPCClient_Base::readResponse(USocket* sk, UString& buffer, UString& respon
buffer.size_adjust_force(U_TOKEN_NM); buffer.size_adjust_force(U_TOKEN_NM);
} }
U_INTERNAL_DUMP("buffer = %V response = %V)", buffer.rep, response.rep) U_INTERNAL_DUMP("buffer = %V response = %V", buffer.rep, response.rep)
if (buffer) U_RETURN(true); if (buffer) U_RETURN(true);

View File

@ -944,6 +944,15 @@ void UClientImage_Base::prepareForRead()
UServer_Base::client_address_len = u__strlen(UServer_Base::client_address, __PRETTY_FUNCTION__); UServer_Base::client_address_len = u__strlen(UServer_Base::client_address, __PRETTY_FUNCTION__);
U_INTERNAL_DUMP("UServer_Base::client_address = %.*S", U_CLIENT_ADDRESS_TO_TRACE) U_INTERNAL_DUMP("UServer_Base::client_address = %.*S", U_CLIENT_ADDRESS_TO_TRACE)
# ifdef U_EVASIVE_SUPPORT
if (UServer_Base::checkHold(socket->remoteIPAddress().getInAddr(), U_CLIENT_ADDRESS_TO_PARAM))
{
abortive_close();
return;
}
# endif
} }
else else
{ {
@ -959,6 +968,10 @@ void UClientImage_Base::prepareForRead()
UEventFd::fd = socket->iSockDesc; UEventFd::fd = socket->iSockDesc;
} }
#ifdef U_EVASIVE_SUPPORT
if (UServer_Base::checkHitSiteStats()) return;
#endif
#ifdef U_THROTTLING_SUPPORT #ifdef U_THROTTLING_SUPPORT
UServer_Base::initThrottlingClient(); UServer_Base::initThrottlingClient();
#endif #endif
@ -968,15 +981,17 @@ bool UClientImage_Base::genericRead()
{ {
U_TRACE_NO_PARAM(0, "UClientImage_Base::genericRead()") U_TRACE_NO_PARAM(0, "UClientImage_Base::genericRead()")
#ifdef DEBUG #if defined(DEBUG) || defined(U_EVASIVE_SUPPORT)
if (UNLIKELY(socket->iSockDesc == -1)) if (UNLIKELY(socket->iSockDesc == -1))
{ {
# ifndef U_EVASIVE_SUPPORT
U_WARNING("genericRead(): " U_WARNING("genericRead(): "
"UEventFd::fd = %d socket->iSockDesc = %d " "UEventFd::fd = %d socket->iSockDesc = %d "
"UNotifier::num_connection = %d UNotifier::min_connection = %d " "UNotifier::num_connection = %d UNotifier::min_connection = %d "
"UServer_Base::isParallelizationChild() = %b sfd = %d UEventFd::op_mask = %B", "UServer_Base::isParallelizationChild() = %b sfd = %d UEventFd::op_mask = %B",
UEventFd::fd, socket->iSockDesc, UNotifier::num_connection, UNotifier::min_connection, UEventFd::fd, socket->iSockDesc, UNotifier::num_connection, UNotifier::min_connection,
UServer_Base::isParallelizationChild(), sfd, UEventFd::op_mask); UServer_Base::isParallelizationChild(), sfd, UEventFd::op_mask);
# endif
U_ClientImage_state = U_PLUGIN_HANDLER_ERROR; U_ClientImage_state = U_PLUGIN_HANDLER_ERROR;
@ -986,6 +1001,8 @@ bool UClientImage_Base::genericRead()
U_INTERNAL_ASSERT_EQUALS(socket->iSockDesc, UEventFd::fd) U_INTERNAL_ASSERT_EQUALS(socket->iSockDesc, UEventFd::fd)
U_gettimeofday // NB: optimization if it is enough a time resolution of one second...
startRequest(); startRequest();
rstart = 0; rstart = 0;
@ -1068,8 +1085,6 @@ start:
U_INTERNAL_ASSERT_EQUALS(U_ClientImage_pipeline, false) U_INTERNAL_ASSERT_EQUALS(U_ClientImage_pipeline, false)
U_INTERNAL_ASSERT_EQUALS(U_ClientImage_data_missing, false) U_INTERNAL_ASSERT_EQUALS(U_ClientImage_data_missing, false)
U_gettimeofday // NB: optimization if it is enough a time resolution of one second...
if (genericRead() == false) if (genericRead() == false)
{ {
if (U_ClientImage_state == U_PLUGIN_HANDLER_AGAIN && if (U_ClientImage_state == U_PLUGIN_HANDLER_AGAIN &&

View File

@ -29,7 +29,7 @@ static void usp_fork_fortune()
U_NEW(UOrmStatement, pstmt_fortune, UOrmStatement(*psql_fortune, U_CONSTANT_TO_PARAM("SELECT id, message FROM Fortune"))); U_NEW(UOrmStatement, pstmt_fortune, UOrmStatement(*psql_fortune, U_CONSTANT_TO_PARAM("SELECT id, message FROM Fortune")));
if (UOrmDriver::isPGSQL()) *psql_fortune << "BEGIN ISOLATION LEVEL SERIALIZABLE; COMMIT"; // if (UOrmDriver::isPGSQL()) *psql_fortune << "BEGIN ISOLATION LEVEL SERIALIZABLE; COMMIT";
U_NEW(Fortune, pfortune, Fortune); U_NEW(Fortune, pfortune, Fortune);
@ -70,6 +70,7 @@ pstmt_fortune->execute();
do { do {
U_NEW(Fortune, item, Fortune(*pfortune)); U_NEW(Fortune, item, Fortune(*pfortune));
pvfortune->push_back(item); pvfortune->push_back(item);
} }
while (pstmt_fortune->nextRow()); while (pstmt_fortune->nextRow());

View File

@ -28,7 +28,7 @@ static void usp_fork_query()
U_NEW(UOrmStatement, pstmt_query, UOrmStatement(*psql_query, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?"))); U_NEW(UOrmStatement, pstmt_query, UOrmStatement(*psql_query, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?")));
if (UOrmDriver::isPGSQL()) *psql_query << "BEGIN TRANSACTION"; // if (UOrmDriver::isPGSQL()) *psql_query << "BEGIN TRANSACTION";
U_NEW(World, pworld_query, World); U_NEW(World, pworld_query, World);

View File

@ -5,14 +5,11 @@ TechEmpower Web Framework Benchmarks
<!--#declaration <!--#declaration
#include "world.h" #include "world.h"
static World* pworld_update; static World* pworld_update;
static UOrmSession* psql_update; static UString* pquery;
static UOrmStatement* pstmt1; static UOrmSession* psql_update;
static UOrmStatement* pstmt2; static UOrmStatement* pstmt;
#ifndef AS_cpoll_cppsp_DO
static UVector<World*>* pvworld_update; static UVector<World*>* pvworld_update;
#endif
static void usp_fork_update() static void usp_fork_update()
{ {
@ -27,20 +24,18 @@ static void usp_fork_update()
return; return;
} }
U_NEW(UOrmStatement, pstmt1, UOrmStatement(*psql_update, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?"))); U_NEW(UOrmStatement, pstmt, UOrmStatement(*psql_update, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?")));
U_NEW(UOrmStatement, pstmt2, UOrmStatement(*psql_update, U_CONSTANT_TO_PARAM("UPDATE World SET randomNumber = ? WHERE id = ?")));
if (UOrmDriver::isPGSQL()) *psql_update << "SET synchronous_commit TO OFF"; // if (UOrmDriver::isPGSQL()) *psql_update << "SET synchronous_commit TO OFF";
U_NEW(World, pworld_update, World); U_NEW(World, pworld_update, World);
pstmt1->use( pworld_update->id); pstmt->use( pworld_update->id);
pstmt1->into(pworld_update->randomNumber); pstmt->into(pworld_update->randomNumber);
pstmt2->use( pworld_update->randomNumber, pworld_update->id);
U_NEW(UString, pquery, UString(U_CAPACITY));
#ifndef AS_cpoll_cppsp_DO
U_NEW(UVector<World*>, pvworld_update, UVector<World*>(500)); U_NEW(UVector<World*>, pvworld_update, UVector<World*>(500));
#endif
} }
#ifdef DEBUG #ifdef DEBUG
@ -50,16 +45,12 @@ static void usp_end_update()
delete psql_update; delete psql_update;
if (pstmt1 && if (pstmt)
pstmt2)
{ {
delete pstmt1; delete pstmt;
delete pstmt2; delete pquery;
delete pworld_update; delete pworld_update;
# ifndef AS_cpoll_cppsp_DO
delete pvworld_update; delete pvworld_update;
# endif
} }
} }
#endif #endif
@ -68,30 +59,56 @@ static void usp_end_update()
Content-Type: application/json Content-Type: application/json
--> -->
<!--#code <!--#code
char* ptr;
World* pworld;
char* query = pquery->data();
int i = 0, num_queries = UHTTP::getFormFirstNumericValue(1, 500); int i = 0, num_queries = UHTTP::getFormFirstNumericValue(1, 500);
#ifdef AS_cpoll_cppsp_DO (void) memcpy(query, "UPDATE World SET randomNumber = v.randomNumber FROM (VALUES",
USP_PUTS_CHAR('['); U_CONSTANT_SIZE("UPDATE World SET randomNumber = v.randomNumber FROM (VALUES"));
#endif ptr = query + U_CONSTANT_SIZE("UPDATE World SET randomNumber = v.randomNumber FROM (VALUES");
while (true) while (true)
{ {
pworld_update->id = u_get_num_random(10000-1); pworld_update->id = u_get_num_random(10000-1);
pstmt1->execute(); pstmt->execute();
pworld_update->randomNumber = u_get_num_random(10000-1); pworld_update->randomNumber = u_get_num_random(10000-1);
pstmt2->execute();
#ifdef AS_cpoll_cppsp_DO
USP_PRINTF("{\"id\":%u,\"randomNumber\":%u}", pworld_update->id, pworld_update->randomNumber);
#else
World* pworld;
U_NEW(World, pworld, World(*pworld_update)); U_NEW(World, pworld, World(*pworld_update));
pvworld_update->push_back(pworld); pvworld_update->push_back(pworld);
if (++i == num_queries) break;
}
pvworld_update->sort();
#ifdef AS_cpoll_cppsp_DO
USP_PUTS_CHAR('[');
#endif
i = 0;
while (true)
{
pworld = pvworld_update->at(i);
*ptr++ = '(';
ptr = u_num2str32(pworld->id, ptr);
u_put_unalignedp16(ptr, U_MULTICHAR_CONSTANT16(',',' '));
ptr += 2;
ptr = u_num2str32(pworld->randomNumber, ptr);
u_put_unalignedp16(ptr, U_MULTICHAR_CONSTANT16(')',','));
ptr += 2;
#ifdef AS_cpoll_cppsp_DO
USP_PRINTF("{\"id\":%u,\"randomNumber\":%u}", pworld->id, pworld->randomNumber);
#endif #endif
if (++i == num_queries) break; if (++i == num_queries) break;
@ -103,8 +120,12 @@ while (true)
#ifdef AS_cpoll_cppsp_DO #ifdef AS_cpoll_cppsp_DO
USP_PUTS_CHAR(']'); USP_PUTS_CHAR(']');
#else
USP_OBJ_JSON_stringify(*pvworld_update);
pvworld_update->clear();
#endif #endif
(void) memcpy(ptr-1, ") AS v (id, randomNumber) WHERE World.id = v.id;",
U_CONSTANT_SIZE(") AS v (id, randomNumber) WHERE World.id = v.id;")+1);
*psql_update << query;
pvworld_update->clear();
--> -->

View File

@ -32,6 +32,13 @@ public:
U_TRACE_REGISTER_OBJECT(5, World, "%u,%u", _id, _randomNumber) U_TRACE_REGISTER_OBJECT(5, World, "%u,%u", _id, _randomNumber)
} }
World(const World& w) : id(w.id), randomNumber(w.randomNumber)
{
U_TRACE_REGISTER_OBJECT(5, World, "%p", &w)
U_MEMORY_TEST_COPY(w)
}
~World() ~World()
{ {
U_TRACE_UNREGISTER_OBJECT(5, World) U_TRACE_UNREGISTER_OBJECT(5, World)
@ -73,6 +80,30 @@ public:
stmt->bindResult(U_ORM_TYPE_HANDLER(randomNumber, unsigned int)); stmt->bindResult(U_ORM_TYPE_HANDLER(randomNumber, unsigned int));
} }
// SERVICE
bool operator<(const World& other) const { return cmp_obj(&id, &other.id); }
static int cmp_obj(const void* a, const void* b)
{
U_TRACE(5, "World::cmp_obj(%p,%p)", a, b)
# ifdef U_STDCPP_ENABLE
/**
* The comparison function must follow a strict-weak-ordering
*
* 1) For all x, it is not the case that x < x (irreflexivity)
* 2) For all x, y, if x < y then it is not the case that y < x (asymmetry)
* 3) For all x, y, and z, if x < y and y < z then x < z (transitivity)
* 4) For all x, y, and z, if x is incomparable with y, and y is incomparable with z, then x is incomparable with z (transitivity of incomparability)
*/
return (((const World*)a)->id < (((const World*)b)->id));
# else
return (*(const World**)a)->id < ((*(const World**)b)->id);
# endif
}
#ifdef DEBUG #ifdef DEBUG
const char* dump(bool breset) const const char* dump(bool breset) const
{ {

View File

@ -22,6 +22,10 @@
#include <ulib/utility/services.h> #include <ulib/utility/services.h>
#include <ulib/net/server/server.h> #include <ulib/net/server/server.h>
#ifdef U_EVASIVE_SUPPORT
# include <ulib/net/client/smtp.h>
#endif
#ifdef _MSWINDOWS_ #ifdef _MSWINDOWS_
# include <ws2tcpip.h> # include <ws2tcpip.h>
#else #else
@ -1000,7 +1004,7 @@ public:
uint8_t min_loadavg_remote = 255; uint8_t min_loadavg_remote = 255;
uint32_t min_loadavg_remote_ip = 0; uint32_t min_loadavg_remote_ip = 0;
while ((iBytesTransferred = U_SYSCALL(recvfrom, "%d,%p,%u,%u,%p,%p", fd_sock, datagram, sizeof(datagram), MSG_DONTWAIT, (sockaddr*)&(saddr.psaGeneric), &slDummy)) > 0) while ((iBytesTransferred = U_SYSCALL(recvfrom,"%d,%p,%u,%u,%p,%p",fd_sock,datagram,sizeof(datagram),MSG_DONTWAIT,(sockaddr*)&(saddr.psaGeneric),&slDummy)) > 0)
{ {
U_DUMP("Received datagram from (%S:%u) = (%u,%#.*S)", U_DUMP("Received datagram from (%S:%u) = (%u,%#.*S)",
UIPAddress::toString(saddr.psaIP4Addr.sin_addr.s_addr).rep, ntohs(saddr.psaIP4Addr.sin_port), iBytesTransferred, iBytesTransferred, datagram) UIPAddress::toString(saddr.psaIP4Addr.sin_addr.s_addr).rep, ntohs(saddr.psaIP4Addr.sin_port), iBytesTransferred, iBytesTransferred, datagram)
@ -1100,6 +1104,371 @@ private:
ULock* UServer_Base::lock_ocsp_staple; ULock* UServer_Base::lock_ocsp_staple;
UThread* UServer_Base::pthread_ocsp; UThread* UServer_Base::pthread_ocsp;
# endif # endif
/**
* This code provide evasive action in the event of an HTTP DoS or DDoS attack or brute force attack. It is also designed to be a
* detection tool, and can be easily configured to talk to ipchains, firewalls, routers, and etcetera. Detection is performed by
* creating an internal dynamic hash table of IP Addresses and URIs, and denying any single IP address from any of the following:
*
* - Requesting the same page more than a few times per second
* - Making more than 50 concurrent requests per second
* - Making any requests while temporarily blacklisted (on a blocking list)
*
* This method has worked well in both single-server script attacks as well as distributed attacks, but just like other evasive tools,
* is only as useful to the point of bandwidth and processor consumption (e.g. the amount of bandwidth and processor required to
* receive/process/respond to invalid requests), which is why it's a good idea to integrate this with your firewalls and routers.
*
* This code has a built-in cleanup mechanism and scaling capabilities. Because of this, legitimate requests are rarely ever compromised,
* only legitimate attacks. Even a user repeatedly clicking on 'reload' should not be affected unless they do it maliciously,
*
* A web hit request comes in. The following steps take place:
*
* - The IP address of the requestor is looked up on the temporary blacklist.
* - The IP address of the requestor is hashed into a "key". A lookup is performed in the listener's internal hash table to determine if
* the same host has requested more than 50 objects within the past second.
* - The IP address of the requestor and the URI are both hashed into a "key". A lookup is performed in the listener's internal hash table
* to determine if the same host has requested this page more than 3 within the past 1 second.
*
* If any of the above are true, a RESET is sent. This conserves bandwidth and system resources in the event of a DoS attack. Additionally,
* a system command and/or an email notification can also be triggered to block all the originating addresses of a DDoS attack.
*
* Once a single RESET incident occurs, evasive code now blocks the entire IP address for a period of 10 seconds (configurable). If the host
* requests a page within this period, it is forced to wait even longer. Since this is triggered from requesting the same URL multiple times
* per second, this again does not affect legitimate users.
*
* The blacklist can/should be configured to talk to your network's firewalls and/or routers to push the attack out to the front lines, but
* this is not required. This tool is *excellent* at fending off request-based DoS attacks or scripted attacks, and brute force attacks.
* When integrated with firewalls or IP filters, evasive code can stand up to even large attacks. Its features will prevent you from wasting
* bandwidth or having a few thousand CGI scripts running as a result of an attack.
*
* If you do not have an infrastructure capable of fending off any other types of DoS attacks, chances are this tool will only help you to the
* point of your total bandwidth or server capacity for sending RESET's. Without a solid infrastructure and address filtering tool in place, a
* heavy distributed DoS will most likely still take you offline
*/
# ifdef U_EVASIVE_SUPPORT
class U_NO_EXPORT UEvasive : public UDataStorage {
public:
uint32_t timestamp, count;
// COSTRUTTORE
UEvasive()
{
U_TRACE_REGISTER_OBJECT(0, UEvasive, "", 0)
(void) memset(&timestamp, 0, sizeof(uint32_t) * 2);
}
~UEvasive()
{
U_TRACE_UNREGISTER_OBJECT(0, UEvasive)
if (UServer_Base::db_evasive)
{
UServer_Base::db_evasive->close();
delete UServer_Base::db_evasive;
}
}
// define method VIRTUAL of class UDataStorage
virtual char* toBuffer()
{
U_TRACE_NO_PARAM(0, "UEvasive::toBuffer()")
U_CHECK_MEMORY
U_INTERNAL_ASSERT_EQUALS(u_buffer_len, 0)
U_MEMCPY(u_buffer, &timestamp, u_buffer_len = sizeof(uint32_t) * 2);
U_INTERNAL_ASSERT_MINOR(u_buffer_len, U_BUFFER_SIZE)
buffer_len = u_buffer_len;
U_RETURN(u_buffer);
}
virtual void fromData(const char* ptr, uint32_t len)
{
U_TRACE(0, "UEvasive::fromData(%.*S,%u)", len, ptr, len)
U_CHECK_MEMORY
U_INTERNAL_ASSERT_POINTER(ptr)
U_INTERNAL_ASSERT(len >= sizeof(uint32_t) * 2)
U_MEMCPY(&timestamp, ptr, sizeof(uint32_t) * 2);
}
#if defined(DEBUG) && defined(U_STDCPP_ENABLE)
const char* dump(bool breset) const { return ""; }
#endif
private:
U_DISALLOW_COPY_AND_ASSIGN(UEvasive)
};
void UServer_Base::initEvasive()
{
U_TRACE_NO_PARAM(0, "UServer_Base::initEvasive()")
U_INTERNAL_ASSERT_EQUALS(db_evasive, U_NULLPTR)
U_NEW(UEvasive, evasive_rec, UEvasive);
U_NEW(URDBObjectHandler<UDataStorage*>, db_evasive, URDBObjectHandler<UDataStorage*>(U_STRING_FROM_CONSTANT("../db/Evasive"), -1, evasive_rec));
if (isPreForked())
{
U_INTERNAL_ASSERT_POINTER(ptr_shared_data)
U_INTERNAL_ASSERT_DIFFERS(ptr_shared_data, MAP_FAILED)
db_evasive->setShared(U_SRV_LOCK_EVASIVE, U_SRV_SPINLOCK_EVASIVE);
}
bool result = db_evasive->open(1024 * 1024, false, true); // NB: we don't want truncate (we have only the journal)...
U_SRV_LOG("%sdb initialization of Evasive %s: size(%u)", (result ? "" : "WARNING: "), (result ? "success" : "failed"), db_evasive->size());
if (result) db_evasive->reset(); // Initialize the db to contain no entries
else
{
delete db_evasive;
db_evasive = U_NULLPTR;
}
}
bool UServer_Base::checkHold(in_addr_t client, const char* client_address, uint32_t client_address_len)
{
U_TRACE(0, "UServer_Base::checkHold(%u,%.*S,%u)", client, client_address_len, client_address, client_address_len)
U_INTERNAL_ASSERT_POINTER(db_evasive)
if ((bwhitelist = (whitelist_IP && UIPAllow::isAllowed(client, *vwhitelist_IP))) == false) // Check whitelist
{
U_gettimeofday // NB: optimization if it is enough a time resolution of one second...
// First see if the IP itself is on "hold"
if (db_evasive->getDataStorage(client_address, client_address_len))
{
U_INTERNAL_DUMP("diff = %u evasive_rec->count = %u", u_now->tv_sec - evasive_rec->timestamp, evasive_rec->count)
if ((u_now->tv_sec - evasive_rec->timestamp) < blocking_period)
{
// Make it wait longer in blacklist land
evasive_rec->timestamp = u_now->tv_sec;
(void) db_evasive->putDataStorage();
U_RETURN(true);
}
}
}
U_RETURN(false);
}
bool UServer_Base::checkHitStats(const char* key, uint32_t key_len, uint32_t interval, uint32_t count)
{
U_TRACE(0, "UServer_Base::checkHitStats(%.*S,%u,%u,%u)", key_len, key, key_len, interval, count)
U_INTERNAL_ASSERT_POINTER(db_evasive)
U_INTERNAL_ASSERT_EQUALS(bwhitelist, false)
if (db_evasive->getDataStorage(key, key_len) == false)
{
evasive_rec->count = 0;
evasive_rec->timestamp = u_now->tv_sec;
}
else
{
// If site/URI is being hit too much, add to "hold" list
uint32_t diff = u_now->tv_sec - evasive_rec->timestamp;
U_INTERNAL_DUMP("diff = %u evasive_rec->count = %u", diff, evasive_rec->count)
if (diff < interval &&
evasive_rec->count >= count)
{
char msg[256];
uint32_t msg_len = (count == site_count
? u__snprintf(msg, sizeof(msg), U_CONSTANT_TO_PARAM("it has requested more than %u objects within the past %u seconds"), site_count, site_interval)
: u__snprintf(msg, sizeof(msg), U_CONSTANT_TO_PARAM("it has requested the same page more than %u within the past %u seconds"), page_count, page_interval));
evasive_rec->count = 0;
evasive_rec->timestamp = u_now->tv_sec;
(void) db_evasive->insertDataStorage(U_CLIENT_ADDRESS_TO_PARAM, RDB_REPLACE);
U_DEBUG("blacklisting address %.*S, possible DoS attack: %.*s", U_CLIENT_ADDRESS_TO_TRACE, msg_len, msg);
U_SRV_LOG("WARNING: blacklisting address %.*S, possible DoS attack: %.*s", U_CLIENT_ADDRESS_TO_TRACE, msg_len, msg);
UClientImage_Base::abortive_close();
if (emailAddress ||
systemCommand)
{
// Perform system functions and/or email notification
pid_t pid = UServer_Base::startNewChild();
if (pid > 0) U_RETURN(true); // parent
// child
if (systemCommand)
{
static int fd_stderr;
if (fd_stderr == 0) fd_stderr = UServices::getDevNull("/tmp/dos_system_command.err");
UString cmd(U_CAPACITY);
cmd.snprintf(U_STRING_TO_PARAM(*systemCommand), U_CLIENT_ADDRESS_TO_TRACE, msg_len, msg);
UString output = UCommand::outputCommand(cmd, U_NULLPTR, -1, fd_stderr);
UServer_Base::logCommandMsgError(cmd.data(), true);
if (UCommand::exit_value) U_WARNING("DOS system command failed: EXIT_VALUE=%d RESPONSE=%V", UCommand::exit_value, output.rep);
}
if (emailAddress)
{
UString server, rcpt;
uint32_t index = emailAddress->find(':');
if (index == U_NOT_FOUND)
{
rcpt = *emailAddress;
server = *UString::str_localhost;
}
else
{
rcpt = emailAddress->substr(index+1);
server = emailAddress->substr(0U, index).copy();
}
if (emailClient->_connectServer(server) == false)
{
if (u_buffer_len)
{
U_WARNING("%.*s", u_buffer_len, u_buffer);
u_buffer_len = 0;
}
}
else
{
UString body(100U);
body.snprintf(U_CONSTANT_TO_PARAM("blacklisting address %.*S, possible DoS attack: %.*s"), U_CLIENT_ADDRESS_TO_TRACE, msg_len, msg);
emailClient->setMessageBody(body);
emailClient->setRecipientAddress(rcpt);
emailClient->setMessageSubject(U_STRING_FROM_CONSTANT("possible DoS attack"));
# ifdef USE_LIBSSL
bool ok = emailClient->sendMessage(true);
# else
bool ok = emailClient->sendMessage(false);
# endif
if (ok == false)
{
emailClient->setStatus();
U_WARNING("DOS email notification to %.*S failed: %.*s", U_STRING_TO_TRACE(*emailAddress), u_buffer_len, u_buffer);
u_buffer_len = 0;
}
}
}
if (pid == 0) UServer_Base::endNewChild();
}
U_RETURN(true);
}
if (diff >= interval) evasive_rec->count = 0; // Reset our hit count list as necessary
evasive_rec->count++;
evasive_rec->timestamp = u_now->tv_sec;
}
(void) db_evasive->putDataStorage();
U_RETURN(false);
}
bool UServer_Base::checkHitSiteStats()
{
U_TRACE_NO_PARAM(0, "UServer_Base::checkHitSiteStats()")
U_INTERNAL_ASSERT_POINTER(db_evasive)
if (bwhitelist == false)
{
char key[32];
U_gettimeofday // NB: optimization if it is enough a time resolution of one second...
if (checkHitStats(key, u__snprintf(key, sizeof(key), U_CONSTANT_TO_PARAM("%.*s_SITE"), U_CLIENT_ADDRESS_TO_TRACE), site_interval, site_count)) U_RETURN(true);
}
U_RETURN(false);
}
bool UServer_Base::checkHitUriStats()
{
U_TRACE_NO_PARAM(0, "UServer_Base::checkHitUriStats()")
U_INTERNAL_ASSERT_POINTER(db_evasive)
if (bwhitelist == false)
{
uint32_t sz = U_http_info.uri_len;
const char* ptr = U_http_info.uri;
# ifdef U_ALIAS
if (*UClientImage_Base::request_uri) // The interpreted pathname of the original requested document (relative to the document root)
{
sz = UClientImage_Base::request_uri->size();
ptr = UClientImage_Base::request_uri->data();
}
# endif
UString key(UServer_Base::client_address_len + sz);
key.snprintf(U_CONSTANT_TO_PARAM("%.*s%.*s"), U_CLIENT_ADDRESS_TO_TRACE, sz, ptr);
if (checkHitStats(U_STRING_TO_PARAM(key), page_interval, page_count)) U_RETURN(true);
}
U_RETURN(false);
}
bool UServer_Base::bwhitelist;
uint32_t UServer_Base::page_count;
uint32_t UServer_Base::site_count;
uint32_t UServer_Base::site_interval;
uint32_t UServer_Base::page_interval;
uint32_t UServer_Base::blocking_period;
UString* UServer_Base::emailAddress;
UString* UServer_Base::whitelist_IP;
UString* UServer_Base::systemCommand;
UEvasive* UServer_Base::evasive_rec;
USmtpClient* UServer_Base::emailClient;
UVector<UIPAllow*>* UServer_Base::vwhitelist_IP;
URDBObjectHandler<UDataStorage*>* UServer_Base::db_evasive;
# endif
#endif #endif
#ifdef U_LINUX #ifdef U_LINUX
@ -1243,6 +1612,16 @@ UServer_Base::~UServer_Base()
if (throttling_mask) delete throttling_mask; if (throttling_mask) delete throttling_mask;
#endif #endif
#ifdef U_EVASIVE_SUPPORT
if (evasive_rec) delete evasive_rec;
if (vwhitelist_IP)
{
delete whitelist_IP;
delete vwhitelist_IP;
}
#endif
#ifdef U_WELCOME_SUPPORT #ifdef U_WELCOME_SUPPORT
if (msg_welcome) delete msg_welcome; if (msg_welcome) delete msg_welcome;
#endif #endif
@ -1528,6 +1907,17 @@ void UServer_Base::loadConfigParam()
// 1 - classic, forking after client accept // 1 - classic, forking after client accept
// >1 - pool of serialized processes plus monitoring process // >1 - pool of serialized processes plus monitoring process
// -------------------------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------------------------
// This directive are for evasive action in the event of an HTTP DoS or DDoS attack or brute force attack
// --------------------------------------------------------------------------------------------------------------------------------------
// DOS_PAGE_COUNT this is the threshhold for the number of requests for the same page (or URI) per page interval
// DOS_PAGE_INTERVAL the interval for the page count threshhold; defaults to 1 second intervals
// DOS_SITE_COUNT this is the threshhold for the total number of requests for any object by the same client per site interval
// DOS_SITE_INTERVAL the interval for the site count threshhold; defaults to 1 second intervals
// DOS_BLOCKING_PERIOD the blocking period is the amount of time (in seconds) that a client will be blocked for if they are added to the blocking list (defaults to 10)
// DOS_WHITE_LIST list of comma separated IP addresses of trusted clients can be whitelisted to insure they are never denied (IPADDR[/MASK])
// DOS_EMAIL_NOTIFY the email address to send a message whenever an IP address becomes blacklisted
// DOS_SYSTEM_COMMAND the system command specified will be executed whenever an IP address becomes blacklisted. Use %v to denote the IP address of the blacklisted IP
// --------------------------------------------------------------------------------------------------------------------------------------
#ifdef USE_LIBSSL #ifdef USE_LIBSSL
U_INTERNAL_DUMP("bssl = %b", bssl) U_INTERNAL_DUMP("bssl = %b", bssl)
@ -1659,14 +2049,13 @@ void UServer_Base::loadConfigParam()
if (x) if (x)
{ {
U_NEW(UString, allow_IP, UString(x)); U_INTERNAL_ASSERT_EQUALS(allow_IP, U_NULLPTR)
U_NEW(UVector<UIPAllow*>, vallow_IP, UVector<UIPAllow*>); U_NEW(UVector<UIPAllow*>, vallow_IP, UVector<UIPAllow*>);
if (UIPAllow::parseMask(*allow_IP, *vallow_IP) == 0) if (UIPAllow::parseMask(x, *vallow_IP)) U_NEW(UString, allow_IP, UString(x));
else
{ {
delete allow_IP;
allow_IP = U_NULLPTR;
delete vallow_IP; delete vallow_IP;
vallow_IP = U_NULLPTR; vallow_IP = U_NULLPTR;
} }
@ -1678,14 +2067,13 @@ void UServer_Base::loadConfigParam()
if (x) if (x)
{ {
U_NEW(UString, allow_IP_prv, UString(x)); U_INTERNAL_ASSERT_EQUALS(allow_IP_prv, U_NULLPTR)
U_NEW(UVector<UIPAllow*>, vallow_IP_prv, UVector<UIPAllow*>); U_NEW(UVector<UIPAllow*>, vallow_IP_prv, UVector<UIPAllow*>);
if (UIPAllow::parseMask(*allow_IP_prv, *vallow_IP_prv) == 0) if (UIPAllow::parseMask(x, *vallow_IP_prv)) U_NEW(UString, allow_IP_prv, UString(x));
else
{ {
delete allow_IP_prv;
allow_IP_prv = U_NULLPTR;
delete vallow_IP_prv; delete vallow_IP_prv;
vallow_IP_prv = U_NULLPTR; vallow_IP_prv = U_NULLPTR;
} }
@ -1694,6 +2082,96 @@ void UServer_Base::loadConfigParam()
enable_rfc1918_filter = cfg->readBoolean(U_CONSTANT_TO_PARAM("ENABLE_RFC1918_FILTER")); enable_rfc1918_filter = cfg->readBoolean(U_CONSTANT_TO_PARAM("ENABLE_RFC1918_FILTER"));
#endif #endif
#ifdef U_EVASIVE_SUPPORT
/**
* This is the threshhold for the number of requests for the same page (or URI) per page interval.
* Once the threshhold for that interval has been exceeded (defaults to 3), the IP address of the client will be added to the blocking list
*/
page_count = cfg->readLong(U_CONSTANT_TO_PARAM("DOS_PAGE_COUNT"), 3);
/**
* The interval for the page count threshhold; defaults to 1 second intervals
*/
page_interval = cfg->readLong(U_CONSTANT_TO_PARAM("DOS_PAGE_INTERVAL"), 1);
/**
* This is the threshhold for the total number of requests for any object by the same client per site interval.
* Once the threshhold for that interval has been exceeded (defaults to 50), the IP address of the client will be added to the blocking list
*/
site_count = cfg->readLong(U_CONSTANT_TO_PARAM("DOS_SITE_COUNT"), 50);
/**
* The interval for the site count threshhold; defaults to 1 second intervals
*/
site_interval = cfg->readLong(U_CONSTANT_TO_PARAM("DOS_SITE_INTERVAL"), 1);
/**
* The blocking period is the amount of time (in seconds) that a client will be blocked for if they are added to the blocking list (defaults to 10).
* During this time, all subsequent requests from the client will result in a abortive close and the timer being reset (e.g. another 10 seconds).
* Since the timer is reset for every subsequent request, it is not necessary to have a long blocking period; in the event of a DoS attack, this
* timer will keep getting reset
*/
blocking_period = cfg->readLong(U_CONSTANT_TO_PARAM("DOS_BLOCKING_PERIOD"), 10);
/**
* IP addresses of trusted clients can be whitelisted to insure they are never denied. The purpose of whitelisting is to protect software, scripts, local
* searchbots, or other automated tools from being denied for requesting large amounts of data from the server. Whitelisting should *not* be used to add
* customer lists or anything of the sort, as this will open the server to abuse. This module is very difficult to trigger without performing some type of
* malicious attack, and for that reason it is more appropriate to allow the module to decide on its own whether or not an individual customer should be blocked
*/
x = cfg->at(U_CONSTANT_TO_PARAM("DOS_WHITE_LIST"));
if (x)
{
U_INTERNAL_ASSERT_EQUALS(whitelist_IP, U_NULLPTR)
U_NEW(UVector<UIPAllow*>, vwhitelist_IP, UVector<UIPAllow*>);
if (UIPAllow::parseMask(x, *vwhitelist_IP)) U_NEW(UString, whitelist_IP, UString(x));
else
{
delete vwhitelist_IP;
vwhitelist_IP = U_NULLPTR;
}
}
/**
* If this value is set, an email will be sent to the address specified whenever an IP address becomes blacklisted
*/
x = cfg->at(U_CONSTANT_TO_PARAM("DOS_EMAIL_NOTIFY"));
if (x)
{
U_INTERNAL_ASSERT_EQUALS(emailClient, U_NULLPTR)
U_INTERNAL_ASSERT_EQUALS(emailAddress, U_NULLPTR)
U_NEW(UString, emailAddress, UString(x));
U_NEW(USmtpClient, emailClient, USmtpClient(UClientImage_Base::bIPv6));
}
/**
* If this value is set, the system command specified will be executed whenever an IP address becomes blacklisted.
* This is designed to enable system calls to ip filter or other tools. Use %.*s to denote the IP address of the blacklisted IP
*/
x = cfg->at(U_CONSTANT_TO_PARAM("DOS_SYSTEM_COMMAND"));
if (x)
{
U_INTERNAL_ASSERT_EQUALS(systemCommand, U_NULLPTR)
U_NEW(UString, systemCommand, UString(x));
}
#endif
// If you want the webserver to run as a process of a defined user, you can do it. // If you want the webserver to run as a process of a defined user, you can do it.
// For the change of user to work, it's necessary to execute the server with root privileges. // For the change of user to work, it's necessary to execute the server with root privileges.
// If it's started by a user that that doesn't have root privileges, this step will be omitted // If it's started by a user that that doesn't have root privileges, this step will be omitted
@ -2546,6 +3024,9 @@ void UServer_Base::init()
UTimer::insert(pstat); UTimer::insert(pstat);
#endif #endif
(void) UFile::_mkdir("../db");
#ifdef U_THROTTLING_SUPPORT #ifdef U_THROTTLING_SUPPORT
if (db_throttling) if (db_throttling)
{ {
@ -2647,6 +3128,10 @@ void UServer_Base::init()
if (throttling_mask) initThrottlingServer(); if (throttling_mask) initThrottlingServer();
#endif #endif
#ifdef U_EVASIVE_SUPPORT
initEvasive();
#endif
if (cfg) cfg->clear(); if (cfg) cfg->clear();
UInterrupt::syscall_restart = false; UInterrupt::syscall_restart = false;
@ -3087,6 +3572,26 @@ try_accept:
U_INTERNAL_DUMP("client_address = %.*S", CLIENT_ADDRESS_LEN, CLIENT_ADDRESS) U_INTERNAL_DUMP("client_address = %.*S", CLIENT_ADDRESS_LEN, CLIENT_ADDRESS)
#ifdef U_EVASIVE_SUPPORT
if (checkHold(CSOCKET->remoteIPAddress().getInAddr(), CLIENT_ADDRESS, CLIENT_ADDRESS_LEN))
{
CSOCKET->abortive_close();
# if defined(ENABLE_THREAD) && !defined(USE_LIBEVENT) && defined(U_SERVER_THREAD_APPROACH_SUPPORT)
if (preforked_num_kids != -1)
# endif
{
U_INTERNAL_ASSERT_DIFFERS(socket_flags & O_NONBLOCK, 0)
# ifndef USE_LIBEVENT
goto try_next;
# endif
}
goto next;
}
#endif
#if defined(_MSWINDOWS_) && !defined(USE_LIBEVENT) #if defined(_MSWINDOWS_) && !defined(USE_LIBEVENT)
if (CSOCKET->iSockDesc >= FD_SETSIZE) if (CSOCKET->iSockDesc >= FD_SETSIZE)
{ {

View File

@ -3015,7 +3015,7 @@ loop:
if (nerror == NO_ERROR) if (nerror == NO_ERROR)
{ {
U_INTERNAL_ASSERT_MAJOR(pConnection->out_window, 0) if (pConnection->out_window == 0) goto loop;
U_INTERNAL_DUMP("pStreamOld = %u pStream = %u", pStreamOld, pStream) U_INTERNAL_DUMP("pStreamOld = %u pStream = %u", pStreamOld, pStream)
@ -3416,8 +3416,6 @@ read_request:
if (sz == 0) if (sz == 0)
{ {
// sz = 0 U_http_info.uri_len = 0 U_http2_settings_len = 0 U_ClientImage_close = false
if (U_http2_settings_len) if (U_http2_settings_len)
{ {
// NB: not OPTION upgrade... // NB: not OPTION upgrade...

View File

@ -289,7 +289,8 @@ UString UStringExt::dos2unix(const UString& s, bool unix2dos)
if (c == '\n') if (c == '\n')
{ {
if (unix2dos) *str++ = '\r'; if (unix2dos) *str++ = '\r';
*str++ = '\n';
*str++ = '\n';
continue; continue;
} }

View File

@ -1650,38 +1650,6 @@ __pure bool UHTTP::isValidMethod(const char* ptr)
U_RETURN(false); U_RETURN(false);
} }
__pure bool UHTTP::isValidRequest(const char* ptr, uint32_t sz)
{
U_TRACE(0, "UHTTP::isValidRequest(%.*S,%u)", 30, ptr, sz)
U_INTERNAL_ASSERT_MAJOR(sz, 0)
U_INTERNAL_DUMP("sz = %u UClientImage_Base::size_request = %u", sz, UClientImage_Base::size_request)
if (u_get_unalignedp32(ptr+sz-4) == U_MULTICHAR_CONSTANT32('\r','\n','\r','\n')) U_RETURN(true);
U_RETURN(false);
}
__pure bool UHTTP::isValidRequestExt(const char* ptr, uint32_t sz)
{
U_TRACE(0, "UHTTP::isValidRequestExt(%.*S,%u)", 30, ptr, sz)
U_INTERNAL_ASSERT_MAJOR(sz, 0)
if (sz >= U_CONSTANT_SIZE("GET / HTTP/1.0\r\n\r\n") &&
isValidMethod(ptr) &&
(isValidRequest(ptr, sz) ||
(UClientImage_Base::size_request &&
isValidRequest(ptr, UClientImage_Base::size_request)) ||
u_findEndHeader1(ptr, sz) != U_NOT_FOUND))
{
U_RETURN(true);
}
U_RETURN(false);
}
bool UHTTP::scanfHeaderRequest(const char* ptr, uint32_t size) bool UHTTP::scanfHeaderRequest(const char* ptr, uint32_t size)
{ {
U_TRACE(0, "UHTTP::scanfHeaderRequest(%.*S,%u)", size, ptr, size) U_TRACE(0, "UHTTP::scanfHeaderRequest(%.*S,%u)", size, ptr, size)
@ -1998,6 +1966,7 @@ U_NO_EXPORT bool UHTTP::readHeaderRequest()
{ {
U_TRACE_NO_PARAM(0, "UHTTP::readHeaderRequest()") U_TRACE_NO_PARAM(0, "UHTTP::readHeaderRequest()")
void* p;
uint32_t sz = UClientImage_Base::request->size(); uint32_t sz = UClientImage_Base::request->size();
const char* ptr = UClientImage_Base::request->data(); const char* ptr = UClientImage_Base::request->data();
@ -2033,9 +2002,9 @@ U_NO_EXPORT bool UHTTP::readHeaderRequest()
if (u_get_unalignedp32(ptr) == U_MULTICHAR_CONSTANT32('\r','\n','\r','\n')) U_RETURN(true); if (u_get_unalignedp32(ptr) == U_MULTICHAR_CONSTANT32('\r','\n','\r','\n')) U_RETURN(true);
sz = u_findEndHeader1(ptr+2, sz-U_http_info.startHeader-2); p = memmem(ptr+U_CONSTANT_SIZE(U_CRLF), sz-U_http_info.startHeader-U_CONSTANT_SIZE(U_CRLF), U_CONSTANT_TO_PARAM(U_CRLF2));
if (sz != U_NOT_FOUND) sz += U_http_info.startHeader-2; if (p) sz = U_http_info.startHeader + (const char*)p - ptr;
else else
{ {
# ifdef USE_LIBSSL # ifdef USE_LIBSSL
@ -2073,6 +2042,7 @@ bool UHTTP::readHeaderResponse(USocket* sk, UString& buffer)
U_INTERNAL_ASSERT_POINTER(sk) U_INTERNAL_ASSERT_POINTER(sk)
void* p;
const char* ptr; const char* ptr;
uint32_t sz = buffer.size(); uint32_t sz = buffer.size();
@ -2147,9 +2117,9 @@ loop: sz = buffer.size();
U_INTERNAL_ASSERT_EQUALS(u_get_unalignedp16(ptr), U_MULTICHAR_CONSTANT16('\r','\n')) U_INTERNAL_ASSERT_EQUALS(u_get_unalignedp16(ptr), U_MULTICHAR_CONSTANT16('\r','\n'))
sz = u_findEndHeader1(ptr+U_CONSTANT_SIZE(U_CRLF), sz-U_http_info.startHeader-U_CONSTANT_SIZE(U_CRLF)); p = memmem(ptr+U_CONSTANT_SIZE(U_CRLF), sz-U_http_info.startHeader-U_CONSTANT_SIZE(U_CRLF), U_CONSTANT_TO_PARAM(U_CRLF2));
if (sz != U_NOT_FOUND) sz += U_http_info.startHeader-U_CONSTANT_SIZE(U_CRLF); if (p) sz = U_http_info.startHeader + (const char*)p - ptr;
else else
{ {
sz = USocketExt::readWhileNotToken(sk, buffer, U_CONSTANT_TO_PARAM(U_CRLF2), UServer_Base::timeoutMS); sz = USocketExt::readWhileNotToken(sk, buffer, U_CONSTANT_TO_PARAM(U_CRLF2), UServer_Base::timeoutMS);
@ -3658,9 +3628,8 @@ bool UHTTP::handlerCache()
const char* ptr1 = ptr+UClientImage_Base::size_request; const char* ptr1 = ptr+UClientImage_Base::size_request;
if (isValidMethod(ptr1) == false || if (isValidMethod(ptr1) == false ||
( isValidRequest(ptr1, UClientImage_Base::size_request) == false && u_findEndHeader1(ptr1, UClientImage_Base::size_request) == U_NOT_FOUND)
u_findEndHeader1(ptr1, UClientImage_Base::size_request) == U_NOT_FOUND))
{ {
U_RETURN(false); U_RETURN(false);
} }
@ -3986,7 +3955,8 @@ int UHTTP::handlerREAD()
U_INTERNAL_DUMP("UClientImage_Base::size_request = %u U_http_info.clength = %u", UClientImage_Base::size_request, U_http_info.clength) U_INTERNAL_DUMP("UClientImage_Base::size_request = %u U_http_info.clength = %u", UClientImage_Base::size_request, U_http_info.clength)
/* NB: readBodyRequest() depend on UClientImage_Base::request /**
* NB: readBodyRequest() depend on UClientImage_Base::request
* *
* if (UClientImage_Base::size_request < UClientImage_Base::request->size()) * if (UClientImage_Base::size_request < UClientImage_Base::request->size())
* { * {
@ -4314,6 +4284,10 @@ manage:
UClientImage_Base::isRequestInFileCache()) // => 3) UClientImage_Base::isRequestInFileCache()) // => 3)
{ {
file_in_cache: file_in_cache:
# ifdef U_EVASIVE_SUPPORT
if (UServer_Base::checkHitUriStats()) U_RETURN(U_PLUGIN_HANDLER_ERROR);
# endif
# if defined(U_HTTP_STRICT_TRANSPORT_SECURITY) || defined(USE_LIBSSL) # if defined(U_HTTP_STRICT_TRANSPORT_SECURITY) || defined(USE_LIBSSL)
if (isValidation() == false) U_RETURN(U_PLUGIN_HANDLER_FINISHED); if (isValidation() == false) U_RETURN(U_PLUGIN_HANDLER_FINISHED);
# endif # endif
@ -4435,6 +4409,10 @@ file_exist_and_need_to_be_processed: // NB: if we can't service the content of f
UClientImage_Base::setRequestNeedProcessing(); UClientImage_Base::setRequestNeedProcessing();
} }
# ifdef U_EVASIVE_SUPPORT
if (UServer_Base::checkHitUriStats()) U_RETURN(U_PLUGIN_HANDLER_ERROR);
# endif
# if defined(U_HTTP_STRICT_TRANSPORT_SECURITY) || defined(USE_LIBSSL) # if defined(U_HTTP_STRICT_TRANSPORT_SECURITY) || defined(USE_LIBSSL)
if (isValidation() == false) U_RETURN(U_PLUGIN_HANDLER_FINISHED); if (isValidation() == false) U_RETURN(U_PLUGIN_HANDLER_FINISHED);
# endif # endif
@ -4442,6 +4420,15 @@ file_exist_and_need_to_be_processed: // NB: if we can't service the content of f
goto end; goto end;
} }
#ifdef U_EVASIVE_SUPPORT
if (UClientImage_Base::isRequestNotFound() == false && // => 4)
UClientImage_Base::isRequestAlreadyProcessed() == false && // => 5)
UServer_Base::checkHitUriStats())
{
U_RETURN(U_PLUGIN_HANDLER_ERROR);
}
#endif
#if defined(U_HTTP_STRICT_TRANSPORT_SECURITY) || defined(USE_LIBSSL) #if defined(U_HTTP_STRICT_TRANSPORT_SECURITY) || defined(USE_LIBSSL)
if ( UClientImage_Base::isRequestNotFound() == false && // => 4) if ( UClientImage_Base::isRequestNotFound() == false && // => 4)
(UClientImage_Base::isRequestAlreadyProcessed() || // => 5) (UClientImage_Base::isRequestAlreadyProcessed() || // => 5)

View File

@ -4,7 +4,7 @@ fw_depends mysql ulib
# Travis is broken # Travis is broken
if [ "$TRAVIS" != "true" ]; then if [ "$TRAVIS" != "true" ]; then
MAX_THREADS=$(( 3 * $CPU_COUNT / 2 )) MAX_THREADS=$CPU_COUNT
else else
MAX_THREADS=$(( 2 * $CPU_COUNT )) MAX_THREADS=$(( 2 * $CPU_COUNT ))
fi fi

View File

@ -29,7 +29,7 @@ static void usp_fork_fortune()
U_NEW(UOrmStatement, pstmt_fortune, UOrmStatement(*psql_fortune, U_CONSTANT_TO_PARAM("SELECT id, message FROM Fortune"))); U_NEW(UOrmStatement, pstmt_fortune, UOrmStatement(*psql_fortune, U_CONSTANT_TO_PARAM("SELECT id, message FROM Fortune")));
if (UOrmDriver::isPGSQL()) *psql_fortune << "BEGIN ISOLATION LEVEL SERIALIZABLE; COMMIT"; // if (UOrmDriver::isPGSQL()) *psql_fortune << "BEGIN ISOLATION LEVEL SERIALIZABLE; COMMIT";
U_NEW(Fortune, pfortune, Fortune); U_NEW(Fortune, pfortune, Fortune);
@ -70,6 +70,7 @@ pstmt_fortune->execute();
do { do {
U_NEW(Fortune, item, Fortune(*pfortune)); U_NEW(Fortune, item, Fortune(*pfortune));
pvfortune->push_back(item); pvfortune->push_back(item);
} }
while (pstmt_fortune->nextRow()); while (pstmt_fortune->nextRow());

View File

@ -28,7 +28,7 @@ static void usp_fork_query()
U_NEW(UOrmStatement, pstmt_query, UOrmStatement(*psql_query, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?"))); U_NEW(UOrmStatement, pstmt_query, UOrmStatement(*psql_query, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?")));
if (UOrmDriver::isPGSQL()) *psql_query << "BEGIN TRANSACTION"; // if (UOrmDriver::isPGSQL()) *psql_query << "BEGIN TRANSACTION";
U_NEW(World, pworld_query, World); U_NEW(World, pworld_query, World);

View File

@ -5,14 +5,11 @@ TechEmpower Web Framework Benchmarks
<!--#declaration <!--#declaration
#include "world.h" #include "world.h"
static World* pworld_update; static World* pworld_update;
static UOrmSession* psql_update; static UString* pquery;
static UOrmStatement* pstmt1; static UOrmSession* psql_update;
static UOrmStatement* pstmt2; static UOrmStatement* pstmt;
#ifndef AS_cpoll_cppsp_DO
static UVector<World*>* pvworld_update; static UVector<World*>* pvworld_update;
#endif
static void usp_fork_update() static void usp_fork_update()
{ {
@ -27,20 +24,18 @@ static void usp_fork_update()
return; return;
} }
U_NEW(UOrmStatement, pstmt1, UOrmStatement(*psql_update, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?"))); U_NEW(UOrmStatement, pstmt, UOrmStatement(*psql_update, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?")));
U_NEW(UOrmStatement, pstmt2, UOrmStatement(*psql_update, U_CONSTANT_TO_PARAM("UPDATE World SET randomNumber = ? WHERE id = ?")));
if (UOrmDriver::isPGSQL()) *psql_update << "SET synchronous_commit TO OFF"; // if (UOrmDriver::isPGSQL()) *psql_update << "SET synchronous_commit TO OFF";
U_NEW(World, pworld_update, World); U_NEW(World, pworld_update, World);
pstmt1->use( pworld_update->id); pstmt->use( pworld_update->id);
pstmt1->into(pworld_update->randomNumber); pstmt->into(pworld_update->randomNumber);
pstmt2->use( pworld_update->randomNumber, pworld_update->id);
U_NEW(UString, pquery, UString(U_CAPACITY));
#ifndef AS_cpoll_cppsp_DO
U_NEW(UVector<World*>, pvworld_update, UVector<World*>(500)); U_NEW(UVector<World*>, pvworld_update, UVector<World*>(500));
#endif
} }
#ifdef DEBUG #ifdef DEBUG
@ -50,16 +45,12 @@ static void usp_end_update()
delete psql_update; delete psql_update;
if (pstmt1 && if (pstmt)
pstmt2)
{ {
delete pstmt1; delete pstmt;
delete pstmt2; delete pquery;
delete pworld_update; delete pworld_update;
# ifndef AS_cpoll_cppsp_DO
delete pvworld_update; delete pvworld_update;
# endif
} }
} }
#endif #endif
@ -68,30 +59,56 @@ static void usp_end_update()
Content-Type: application/json Content-Type: application/json
--> -->
<!--#code <!--#code
char* ptr;
World* pworld;
char* query = pquery->data();
int i = 0, num_queries = UHTTP::getFormFirstNumericValue(1, 500); int i = 0, num_queries = UHTTP::getFormFirstNumericValue(1, 500);
#ifdef AS_cpoll_cppsp_DO (void) memcpy(query, "UPDATE World SET randomNumber = v.randomNumber FROM (VALUES",
USP_PUTS_CHAR('['); U_CONSTANT_SIZE("UPDATE World SET randomNumber = v.randomNumber FROM (VALUES"));
#endif ptr = query + U_CONSTANT_SIZE("UPDATE World SET randomNumber = v.randomNumber FROM (VALUES");
while (true) while (true)
{ {
pworld_update->id = u_get_num_random(10000-1); pworld_update->id = u_get_num_random(10000-1);
pstmt1->execute(); pstmt->execute();
pworld_update->randomNumber = u_get_num_random(10000-1); pworld_update->randomNumber = u_get_num_random(10000-1);
pstmt2->execute();
#ifdef AS_cpoll_cppsp_DO
USP_PRINTF("{\"id\":%u,\"randomNumber\":%u}", pworld_update->id, pworld_update->randomNumber);
#else
World* pworld;
U_NEW(World, pworld, World(*pworld_update)); U_NEW(World, pworld, World(*pworld_update));
pvworld_update->push_back(pworld); pvworld_update->push_back(pworld);
if (++i == num_queries) break;
}
pvworld_update->sort();
#ifdef AS_cpoll_cppsp_DO
USP_PUTS_CHAR('[');
#endif
i = 0;
while (true)
{
pworld = pvworld_update->at(i);
*ptr++ = '(';
ptr = u_num2str32(pworld->id, ptr);
u_put_unalignedp16(ptr, U_MULTICHAR_CONSTANT16(',',' '));
ptr += 2;
ptr = u_num2str32(pworld->randomNumber, ptr);
u_put_unalignedp16(ptr, U_MULTICHAR_CONSTANT16(')',','));
ptr += 2;
#ifdef AS_cpoll_cppsp_DO
USP_PRINTF("{\"id\":%u,\"randomNumber\":%u}", pworld->id, pworld->randomNumber);
#endif #endif
if (++i == num_queries) break; if (++i == num_queries) break;
@ -103,8 +120,12 @@ while (true)
#ifdef AS_cpoll_cppsp_DO #ifdef AS_cpoll_cppsp_DO
USP_PUTS_CHAR(']'); USP_PUTS_CHAR(']');
#else
USP_OBJ_JSON_stringify(*pvworld_update);
pvworld_update->clear();
#endif #endif
(void) memcpy(ptr-1, ") AS v (id, randomNumber) WHERE World.id = v.id;",
U_CONSTANT_SIZE(") AS v (id, randomNumber) WHERE World.id = v.id;")+1);
*psql_update << query;
pvworld_update->clear();
--> -->

View File

@ -32,6 +32,13 @@ public:
U_TRACE_REGISTER_OBJECT(5, World, "%u,%u", _id, _randomNumber) U_TRACE_REGISTER_OBJECT(5, World, "%u,%u", _id, _randomNumber)
} }
World(const World& w) : id(w.id), randomNumber(w.randomNumber)
{
U_TRACE_REGISTER_OBJECT(5, World, "%p", &w)
U_MEMORY_TEST_COPY(w)
}
~World() ~World()
{ {
U_TRACE_UNREGISTER_OBJECT(5, World) U_TRACE_UNREGISTER_OBJECT(5, World)
@ -73,6 +80,30 @@ public:
stmt->bindResult(U_ORM_TYPE_HANDLER(randomNumber, unsigned int)); stmt->bindResult(U_ORM_TYPE_HANDLER(randomNumber, unsigned int));
} }
// SERVICE
bool operator<(const World& other) const { return cmp_obj(&id, &other.id); }
static int cmp_obj(const void* a, const void* b)
{
U_TRACE(5, "World::cmp_obj(%p,%p)", a, b)
# ifdef U_STDCPP_ENABLE
/**
* The comparison function must follow a strict-weak-ordering
*
* 1) For all x, it is not the case that x < x (irreflexivity)
* 2) For all x, y, if x < y then it is not the case that y < x (asymmetry)
* 3) For all x, y, and z, if x < y and y < z then x < z (transitivity)
* 4) For all x, y, and z, if x is incomparable with y, and y is incomparable with z, then x is incomparable with z (transitivity of incomparability)
*/
return (((const World*)a)->id < (((const World*)b)->id));
# else
return (*(const World**)a)->id < ((*(const World**)b)->id);
# endif
}
#ifdef DEBUG #ifdef DEBUG
const char* dump(bool breset) const const char* dump(bool breset) const
{ {

View File

@ -18,8 +18,8 @@ cat <<EOF >inp/server.cf
userver { userver {
PORT 10001 PORT 10001
WELCOME_MSG "generic server ready." WELCOME_MSG "generic server ready."
ALLOWED_IP localhost ALLOWED_IP 127.0.0.1
#ALLOWED_IP localhost,10.30.0.0/16 #ALLOWED_IP 127.0.0.1,10.30.0.0/16
LOG_FILE server.log LOG_FILE server.log
LOG_FILE_SZ 1M LOG_FILE_SZ 1M
PLUGIN echo PLUGIN echo

View File

@ -1,8 +1,8 @@
userver { userver {
PORT 10001 PORT 10001
WELCOME_MSG "generic server ready." WELCOME_MSG "generic server ready."
ALLOWED_IP localhost ALLOWED_IP 127.0.0.1
#ALLOWED_IP localhost,10.30.0.0/16 #ALLOWED_IP 127.0.0.1,10.30.0.0/16
LOG_FILE server.log LOG_FILE server.log
LOG_FILE_SZ 1M LOG_FILE_SZ 1M
PLUGIN echo PLUGIN echo

View File

@ -100,6 +100,8 @@ done
upload_test $2:8080 upload_test $2:8080
kill_server userver_tcp kill_server userver_tcp
$SLEEP
pkill userver_tcp 2>/dev/null
} }
# function : creat_config # function : creat_config
@ -117,6 +119,7 @@ userver {
RUN_AS_USER nobody RUN_AS_USER nobody
#MIN_SIZE_FOR_SENDFILE 2k #MIN_SIZE_FOR_SENDFILE 2k
REQ_TIMEOUT 30 REQ_TIMEOUT 30
DOS_WHITE_LIST 127.0.0.1,10.30.0.0/16
LOG_FILE webserver$1.log LOG_FILE webserver$1.log
LOG_FILE_SZ 1M LOG_FILE_SZ 1M
LOG_MSG_SIZE -1 LOG_MSG_SIZE -1

View File

@ -30,6 +30,7 @@ cat <<EOF >inp/webserver.cfg
userver { userver {
PORT 8080 PORT 8080
RUN_AS_USER apache RUN_AS_USER apache
DOS_WHITE_LIST 127.0.0.1,10.30.0.0/16
LOG_FILE web_server_multiclient.log LOG_FILE web_server_multiclient.log
LOG_FILE_SZ 1M LOG_FILE_SZ 1M
LOG_MSG_SIZE -1 LOG_MSG_SIZE -1

View File

@ -112,6 +112,7 @@ userver {
RUN_AS_USER nobody RUN_AS_USER nobody
REQ_TIMEOUT 30 REQ_TIMEOUT 30
#MIN_SIZE_FOR_SENDFILE 2k #MIN_SIZE_FOR_SENDFILE 2k
DOS_WHITE_LIST 127.0.0.1,10.30.0.0/16
LOG_FILE webserver_ssl$1.log LOG_FILE webserver_ssl$1.log
LOG_FILE_SZ 1M LOG_FILE_SZ 1M
LOG_MSG_SIZE -1 LOG_MSG_SIZE -1

View File

@ -1,14 +1,17 @@
See http://www.debian.org/ for information about Debian GNU/Linux. See http://www.debian.org/ for information about Debian GNU/Linux.
Four Debian releases are available on the main site: Four Debian releases are available on the main site:
Debian 7.11, or wheezy. Access this release through dists/oldstable Debian 7.11, or wheezy. Access this release through dists/oldoldstable
Debian 7.11 was released Saturday, 4th June 2016. Debian 7.11 was released Saturday, 4th June 2016.
Debian 8.8, or jessie. Access this release through dists/stable Debian 8.8, or jessie. Access this release through dists/oldstable
Debian 8.8 was released Saturday, 6th May 2017. Debian 8.8 was released Saturday, 6th May 2017.
Testing, or stretch. Access this release through dists/testing. The Debian 9.0, or stretch. Access this release through dists/stable
current tested development snapshot is named stretch. Packages which Debian 9.0 was released Saturday, 17th June 2017.
Testing, or buster. Access this release through dists/testing. The
current tested development snapshot is named buster. Packages which
have been tested in unstable and passed automated tests propagate to have been tested in unstable and passed automated tests propagate to
this release. this release.

View File

@ -2,6 +2,10 @@ SERVER {
PORT 8080 PORT 8080
DOS_WHITE_LIST 127.0.0.1,10.30.0.0/16
DOS_EMAIL_NOTIFY mail.unirel.com:stefano.casazza2@unirel.com
DOS_SYSTEM_COMMAND "sh -c 'echo %.*s: %.*s >> /tmp/dos_blacklist.txt'"
LOG_FILE rdb_server.log LOG_FILE rdb_server.log
LOG_FILE_SZ 1M LOG_FILE_SZ 1M

View File

@ -43,14 +43,17 @@ URL: ftp://ftp.at.debian.org/debian/README
See http://www.debian.org/ for information about Debian GNU/Linux. See http://www.debian.org/ for information about Debian GNU/Linux.
Four Debian releases are available on the main site: Four Debian releases are available on the main site:
Debian 7.9, or wheezy. Access this release through dists/oldstable Debian 7.11, or wheezy. Access this release through dists/oldoldstable
Debian 7.9 was released Saturday, 5th September 2015. Debian 7.11 was released Saturday, 4th June 2016.
Debian 8.3, or jessie. Access this release through dists/stable Debian 8.8, or jessie. Access this release through dists/oldstable
Debian 8.3 was released Saturday, 23rd January 2016. Debian 8.8 was released Saturday, 6th May 2017.
Testing, or stretch. Access this release through dists/testing. The Debian 9.0, or stretch. Access this release through dists/stable
current tested development snapshot is named stretch. Packages which Debian 9.0 was released Saturday, 17th June 2017.
Testing, or buster. Access this release through dists/testing. The
current tested development snapshot is named buster. Packages which
have been tested in unstable and passed automated tests propagate to have been tested in unstable and passed automated tests propagate to
this release. this release.
@ -105,7 +108,7 @@ the <a href="mailto:webmaster@unirel.com">webmaster</a>.
<address> <address>
<a href="/">www.unirel.com</a><br /> <a href="/">www.unirel.com</a><br />
<span>Wed Mar 2 18:45:49 2016<br /> <span>Mon Jun 19 14:01:54 2017<br />
Apache/2.0.49 (Linux/SuSE)</span> Apache/2.0.49 (Linux/SuSE)</span>
</address> </address>
</body> </body>

View File

@ -1,14 +1,17 @@
See http://www.debian.org/ for information about Debian GNU/Linux. See http://www.debian.org/ for information about Debian GNU/Linux.
Four Debian releases are available on the main site: Four Debian releases are available on the main site:
Debian 7.9, or wheezy. Access this release through dists/oldstable Debian 7.11, or wheezy. Access this release through dists/oldoldstable
Debian 7.9 was released Saturday, 5th September 2015. Debian 7.11 was released Saturday, 4th June 2016.
Debian 8.3, or jessie. Access this release through dists/stable Debian 8.8, or jessie. Access this release through dists/oldstable
Debian 8.3 was released Saturday, 23rd January 2016. Debian 8.8 was released Saturday, 6th May 2017.
Testing, or stretch. Access this release through dists/testing. The Debian 9.0, or stretch. Access this release through dists/stable
current tested development snapshot is named stretch. Packages which Debian 9.0 was released Saturday, 17th June 2017.
Testing, or buster. Access this release through dists/testing. The
current tested development snapshot is named buster. Packages which
have been tested in unstable and passed automated tests propagate to have been tested in unstable and passed automated tests propagate to
this release. this release.

View File

@ -61,7 +61,7 @@ U_EXPORT main(int argc, char* argv[], char* env[])
int result; int result;
UString host(argv[1]); UString host(argv[1]);
URDBClient<UTCPSocket> x(0); URDBClient<UTCPSocket> x(U_NULLPTR);
if (x.setHostPort(host, 8080) && x.connect()) if (x.setHostPort(host, 8080) && x.connect())
{ {

View File

@ -14,7 +14,7 @@ U_EXPORT main (int argc, char* argv[], char* env[])
U_TRACE(5,"main(%d)",argc) U_TRACE(5,"main(%d)",argc)
UFileConfig fcg; UFileConfig fcg;
UServerExample server(0); UServerExample server(U_NULLPTR);
UString plugin_dir(argv[1]), plugin_list(argv[2]); UString plugin_dir(argv[1]), plugin_list(argv[2]);
if (argv[3]) if (argv[3])