Permalink
Browse files

Allow increasing connection limit on linux (#3799)

With this you can now support more connections on linux, even if your system header is still set to a smaller value.

Make sure to increase the limit of open file handles with ulimit or other resource related settings.
You can change the compile time value of supported connections with ./configure --with-maxconn=value

Windows default is still 4096.
  • Loading branch information...
Lemongrass3110 committed Jan 9, 2019
1 parent 4ec0c01 commit 8ae788b643ed00713f070ab80b01496aa2715aba
Showing with 43 additions and 51 deletions.
  1. +8 −17 configure
  2. +7 −12 configure.in
  3. +21 −21 src/common/socket.cpp
  4. +7 −1 src/common/socket.hpp
@@ -1367,7 +1367,9 @@ Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--with-maxconn[=ARG] optionally set the maximum connections the core can
handle (default: 16384) NOT USED YET - EXPERIMENTAL
handle. By default the system header value will be used.
This will only be the compile time limit, make sure
you set the correct limit with ulimit on your OS.
--with-outputlogin[=ARG]
Specify the login-serv output name (defaults to
login-server)
@@ -3469,22 +3471,11 @@ fi
# Check whether --with-maxconn was given.
if test "${with_maxconn+set}" = set; then :
withval=$with_maxconn;
if test "$withval" == "no"; then
CPPFLAGS="$CPPFLAGS -DMAXCONN=16384"
else

if ! test "$withval" -ge 0 -o "$withval" -lt 0 2>&- ; then
as_fn_error $? "Invalid argument --with-maxconn=$withval ... stopping" "$LINENO" 5
else
CPPFLAGS="$CPPFLAGS -DMAXCONN=$withval"
fi
fi

else

CPPFLAGS="$CPPFLAGS -DMAXCONN=16384"


if ! test "$withval" -ge 0 -o "$withval" -lt 0 2>&- ; then
as_fn_error $? "Invalid argument --with-maxconn=$withval ... stopping" "$LINENO" 5
else
CPPFLAGS="$CPPFLAGS -DMAXCONN=$withval"
fi
fi


@@ -295,29 +295,24 @@ AC_ARG_ENABLE(


#
# Optionally set the max number of network conenctions
# the core will be support
# Optionally set the maximum number of network connections
# the core will be able to handle
#
AC_ARG_WITH(
[maxconn],
AC_HELP_STRING(
[--with-maxconn@<:@=ARG@:>@],
[optionally set the maximum connections the core can handle (default: 16384) NOT USED YET - EXPERIMENTAL]
[optionally set the maximum connections the core can handle. By default the system header value is used.]
),
[
if test "$withval" == "no"; then
CPPFLAGS="$CPPFLAGS -DMAXCONN=16384"
if ! test "$withval" -ge 0 -o "$withval" -lt 0 2>&- ; then
AC_MSG_ERROR([Invalid argument --with-maxconn=$withval ... stopping])
else

if ! test "$withval" -ge 0 -o "$withval" -lt 0 2>&- ; then
AC_MSG_ERROR([Invalid argument --with-maxconn=$withval ... stopping])
else
CPPFLAGS="$CPPFLAGS -DMAXCONN=$withval"
fi
CPPFLAGS="$CPPFLAGS -DMAXCONN=$withval"
fi
],
[
CPPFLAGS="$CPPFLAGS -DMAXCONN=16384"
CPPFLAGS="$CPPFLAGS"
]
)

@@ -66,7 +66,7 @@ typedef int socklen_t;

// global array of sockets (emulating linux)
// fd is the position in the array
static SOCKET sock_arr[FD_SETSIZE];
static SOCKET sock_arr[MAXCONN];
static int sock_arr_len = 0;

/// Returns the socket associated with the target fd.
@@ -98,7 +98,7 @@ int sock2fd(SOCKET s)
/// Returns a new fd associated with the socket.
/// If there are too many sockets it closes the socket, sets an error and
// returns -1 instead.
/// Since fd 0 is reserved, it returns values in the range [1,FD_SETSIZE[.
/// Since fd 0 is reserved, it returns values in the range [1,MAXCONN[.
///
/// @param s Socket
/// @return New fd or -1
@@ -220,7 +220,7 @@ char* sErr(int code)
fd_set readfds;
#else
// Epoll based Event Dispatcher
static int epoll_maxevents = (FD_SETSIZE / 2);
static int epoll_maxevents = (MAXCONN / 2);
static int epfd = SOCKET_ERROR;
static struct epoll_event epevent;
static struct epoll_event *epevents = nullptr;
@@ -258,12 +258,12 @@ static time_t socket_data_last_tick = 0;
// The connection is closed if it goes over the limit.
#define WFIFO_MAX (1*1024*1024)

struct socket_data* session[FD_SETSIZE];
struct socket_data* session[MAXCONN];

#ifdef SEND_SHORTLIST
int send_shortlist_array[FD_SETSIZE];// we only support FD_SETSIZE sockets, limit the array to that
int send_shortlist_array[MAXCONN];// we only support MAXCONN sockets, limit the array to that
size_t send_shortlist_count = 0;// how many fd's are in the shortlist
uint32 send_shortlist_set[(FD_SETSIZE+31)/32];// to know if specific fd's are already in the shortlist
uint32 send_shortlist_set[(MAXCONN+31)/32];// to know if specific fd's are already in the shortlist
#endif

static int create_session(int fd, RecvFunc func_recv, SendFunc func_send, ParseFunc func_parse);
@@ -483,9 +483,9 @@ int connect_client(int listen_fd)
sClose(fd);
return -1;
}
if( fd >= FD_SETSIZE )
if( fd >= MAXCONN )
{// socket number too big
ShowError("connect_client: New socket #%d is greater than can we handle! Increase the value of FD_SETSIZE (currently %d) for your OS to fix this!\n", fd, FD_SETSIZE);
ShowError("connect_client: New socket #%d is greater than can we handle! Increase the value of MAXCONN (currently %d) for your OS to fix this!\n", fd, MAXCONN);
sClose(fd);
return -1;
}
@@ -542,9 +542,9 @@ int make_listen_bind(uint32 ip, uint16 port)
sClose(fd);
return -1;
}
if( fd >= FD_SETSIZE )
if( fd >= MAXCONN )
{// socket number too big
ShowError("make_listen_bind: New socket #%d is greater than can we handle! Increase the value of FD_SETSIZE (currently %d) for your OS to fix this!\n", fd, FD_SETSIZE);
ShowError("make_listen_bind: New socket #%d is greater than can we handle! Increase the value of MAXCONN (currently %d) for your OS to fix this!\n", fd, MAXCONN);
sClose(fd);
return -1;
}
@@ -608,9 +608,9 @@ int make_connection(uint32 ip, uint16 port, bool silent,int timeout) {
sClose(fd);
return -1;
}
if( fd >= FD_SETSIZE )
if( fd >= MAXCONN )
{// socket number too big
ShowError("make_connection: New socket #%d is greater than can we handle! Increase the value of FD_SETSIZE (currently %d) for your OS to fix this!\n", fd, FD_SETSIZE);
ShowError("make_connection: New socket #%d is greater than can we handle! Increase the value of MAXCONN (currently %d) for your OS to fix this!\n", fd, MAXCONN);
sClose(fd);
return -1;
}
@@ -1417,7 +1417,7 @@ void socket_final(void)
/// Closes a socket.
void do_close(int fd)
{
if( fd <= 0 ||fd >= FD_SETSIZE )
if( fd <= 0 ||fd >= MAXCONN )
return;// invalid

flush_fifo(fd); // Try to send what's left (although it might not succeed since it's a nonblocking socket)
@@ -1526,7 +1526,7 @@ int socket_getips(uint32* ips, int max)
void socket_init(void)
{
const char *SOCKET_CONF_FILENAME = "conf/packet_athena.conf";
unsigned int rlim_cur = FD_SETSIZE;
unsigned int rlim_cur = MAXCONN;

#ifdef WIN32
{// Start up windows networking
@@ -1546,14 +1546,14 @@ void socket_init(void)
#elif defined(HAVE_SETRLIMIT) && !defined(CYGWIN)
// NOTE: getrlimit and setrlimit have bogus behaviour in cygwin.
// "Number of fds is virtually unlimited in cygwin" (sys/param.h)
{// set socket limit to FD_SETSIZE
{// set socket limit to MAXCONN
struct rlimit rlp;
if( 0 == getrlimit(RLIMIT_NOFILE, &rlp) )
{
rlp.rlim_cur = FD_SETSIZE;
rlp.rlim_cur = MAXCONN;
if( 0 != setrlimit(RLIMIT_NOFILE, &rlp) )
{// failed, try setting the maximum too (permission to change system limits is required)
rlp.rlim_max = FD_SETSIZE;
rlp.rlim_max = MAXCONN;
if( 0 != setrlimit(RLIMIT_NOFILE, &rlp) )
{// failed
const char *errmsg = error_msg();
@@ -1566,7 +1566,7 @@ void socket_init(void)
// report limit
getrlimit(RLIMIT_NOFILE, &rlp);
rlim_cur = rlp.rlim_cur;
ShowWarning("socket_init: failed to set socket limit to %d, setting to maximum allowed (original limit=%d, current limit=%d, maximum allowed=%d, %s).\n", FD_SETSIZE, rlim_ori, (int)rlp.rlim_cur, (int)rlp.rlim_max, errmsg);
ShowWarning("socket_init: failed to set socket limit to %d, setting to maximum allowed (original limit=%d, current limit=%d, maximum allowed=%d, %s).\n", MAXCONN, rlim_ori, (int)rlp.rlim_cur, (int)rlp.rlim_max, errmsg);
}
}
}
@@ -1582,7 +1582,7 @@ void socket_init(void)
ShowInfo( "Server uses '" CL_WHITE "select" CL_RESET "' as event dispatcher\n" );
#else
// Epoll based Event Dispatcher
epfd = epoll_create( FD_SETSIZE ); // 2.6.8 or newer ignores the expected socket amount argument
epfd = epoll_create( MAXCONN ); // 2.6.8 or newer ignores the expected socket amount argument

if( epfd == SOCKET_ERROR ){
ShowError( "Failed to create epoll event dispatcher: %s\n", error_msg() );
@@ -1621,7 +1621,7 @@ void socket_init(void)

bool session_isValid(int fd)
{
return ( fd > 0 && fd < FD_SETSIZE && session[fd] != NULL );
return ( fd > 0 && fd < MAXCONN && session[fd] != NULL );
}

bool session_isActive(int fd)
@@ -1703,7 +1703,7 @@ void send_shortlist_do_sends()
send_shortlist_array[i] = send_shortlist_array[send_shortlist_count];
send_shortlist_array[send_shortlist_count] = 0;

if( fd <= 0 || fd >= FD_SETSIZE )
if( fd <= 0 || fd >= MAXCONN )
{
ShowDebug("send_shortlist_do_sends: fd is out of range, corrupted memory? (fd=%d)\n", fd);
continue;
@@ -4,6 +4,8 @@
#ifndef SOCKET_HPP
#define SOCKET_HPP

#include "../config/core.hpp"

#ifdef WIN32
#include "winapi.hpp"
typedef long in_addr_t;
@@ -17,6 +19,10 @@
#include "cbasetypes.hpp"
#include "timer.hpp" // t_tick

#ifndef MAXCONN
#define MAXCONN FD_SETSIZE
#endif

#define FIFOSIZE_SERVERLINK 256*1024

// socket I/O macros
@@ -103,7 +109,7 @@ struct socket_data

// Data prototype declaration

extern struct socket_data* session[FD_SETSIZE];
extern struct socket_data* session[MAXCONN];

extern int fd_max;

0 comments on commit 8ae788b

Please sign in to comment.