Skip to content

Commit

Permalink
Merge pull request #88 from polserver/network-improvements
Browse files Browse the repository at this point in the history
Network improvements
  • Loading branch information
frozenblit committed Apr 26, 2019
2 parents 4210683 + 0bed27c commit 88c22ed
Show file tree
Hide file tree
Showing 67 changed files with 654 additions and 854 deletions.
7 changes: 2 additions & 5 deletions docs/docs.polserver.com/pol100/configfiles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ Listener
<explain>The right-hand-side "Life", "Mana", and "Stamina" are Vital names that MUST be defined in vitals.cfg.</explain>
<explain>MaxSkillID allows you to use new client skills, but setting it too high can crash older clients. You must define attributes.cfg/uoskills.cfg entries for each skillID up to MaxSkillID (default 57).</explain>
<explain>The Protocol and Listener sections are optional.</explain>
<explain>Each Listener section allows you to listen for different client encryption types on different ports. This means you can listen for "1.26.4" clients on port 5003 and "ignition" clients on port 5555. Valid encryption types are found in the pol.cfg section. If you use Listeners set ListenPort in pol.cfg to 0.</explain>
<explain>Each Listener section allows you to listen for different client encryption types on different ports. This means you can listen for "1.26.4" clients on port 5003 and "ignition" clients on port 5555. Valid encryption types are found in the pol.cfg section.</explain>
<explain>KeepClients: if set to 1 clients keep this listener port even after different gameserver select; actually 1 is the old behaviour and 0 the old behaviour of pol.cfg ListenPort</explain>
<explain>AOSResistances: This flag aids in deciding which version of Armor to send in the StatMsg packets. With this enabled, a client who uses an account with AOS Expansion enabled will see their Physical Resist instead of AR member.</explain>
<explain>MethodScript: General Methodscript for characters Deprecated!</explain>
Expand Down Expand Up @@ -474,7 +474,7 @@ GameServer
<explain>IP address must match the address in the clients' login.cfg files. This means if your game server is on a LAN not accessable from the internet (doing port forwarding from a router), you must define this game server IP as your router's internet IP address.</explain>
<explain>--ip-- attempts to find your non-LAN, non-localhost IP address. If you have a multihomed server, this may behave strangely.</explain>
<explain>--lan-- attempts to find you non-routable LAN IP address, if any (i.e. '192.168.*.*' or '10.*.*.*').</explain>
<explain>Port is the listening port of the Game Server, not the login server (though they may be the same). See ListenPort in pol.cfg</explain>
<explain>Port is the listening port of the Game Server, not the login server (though they may be the same). It's often the listener's Port in uoclients.cfg</explain>
<explain>Example IPMatch value: 192.168.0.0/255.255.255.0 would prevent anyone with an IP address other than 192.168.0.* from seeing the gameserver.</explain>
<explain>AcctMatch lines have one account name per line, and are those accounts to show the given server to on login to the 'login server'.</explain>
<related>movecost.cfg</related>
Expand Down Expand Up @@ -889,10 +889,8 @@ UoDataFileRoot=(path to UO MUL files)
WorldDataPath=(path to POL Data files {default data/})
RealmDataPath=(path to POL Realm files {default realm/})
PidFilePath=(where POL will write its .pid file {default ./})
[ListenPort=(integer TCP port)]
[ClientEncryptionVersion=(string {default none})]
[CountResourceTiles=(1/0 {default 1}]
[Multithread=(1/0 {default 1})]
[WebServer=(1/0 {default 0})]
[WebServerPort=(int port {default 8080})]
[IgnoreLoadErrors=(1/0 {default 0})]
Expand Down Expand Up @@ -963,7 +961,6 @@ PidFilePath=(where POL will write its .pid file {default ./})
default for both is "none"
<explain>Clarification: for ClientEncryptionVersion, the allowable values are 'major.minor.build', '2.0.0x', 'ignition', 'uorice', and 'none'. Here, 'ignition', 'uorice', and 'none' all mean 'no encryption'.</explain>
<explain>Due to autocalculation 'major.minor.build' means setting a listener for client 7.0.4.1 '7.0.4' (no patch)</explain>
<explain>ListenPort is now optional, use uoclient.cfg Listener sections to define listening ports.</explain>
<explain>AssertionFailureAction options: abort: (like old behavior) aborts immediately, without saving data. continue: allows execution to continue. shutdown: attempts graceful shutdown. shutdown-nosave: attempts graceful shutdown, without saving data. If the assertion occurred during execution of a script, either 'shutdown', 'shutdown-nosave', or 'continue' will abort that script, displaying the script name and PC.</explain>
<explain>Hint: LogLevel can be used to debug issues at startup of POL and various other places (unloadall for example). By setting this higher than 1, up to 11 (just sounds good), it will force printing of better information to help you find out problems during Loading and such. Setting it for example, above 0, core will start spitting out "Checkpoint" data during startup to say what it is about to load/process. Such as the configuration, load realms, load multis, etc etc.</explain>
<explain>DiscardOldEvents: if set instead of discarding new event if queue is full it discards oldest event and adds the new event</explain>
Expand Down
16 changes: 15 additions & 1 deletion docs/docs.polserver.com/pol100/corechanges.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,23 @@
<ESCRIPT>
<header>
<topic>Latest Core Changes</topic>
<datemodified>03-19-2019</datemodified>
<datemodified>04-26-2019</datemodified>
</header>
<version name="POL100">
<entry>
<date>04-26-2019</date>
<author>Nando:</author>
<change type="Changed">Improved connection handling. Linux won't be limited to 1024 clients anymore, recent Windows shouldn't be affected besides some slight performance gain.</change>
<change type="Note">POL now requires at least Windows Vista / Server 2008. Let us know if Windows XP was important to you.</change>
<change type="Removed">pol.cfg option &quot;ListenPort&quot;. It was deprecated since 2012 (and likely didn't work). You should use a Listener in uoclient.cfg.</change>
<change type="Removed">pol.cfg option &quot;Multithread&quot;. It was deprecated since 2016 and unstable. Also removed the method OS::System_RPM(), which was only useful for singlethreaded POL.</change>
</entry>
<entry>
<date>04-26-2019</date>
<author>Turley:</author>
<change type="Added">pol.cfg setting &quot;LoginServerTimeout&quot;. Defines a timeout for new connections to the loginserver.<br/>
Defaults to 10 minutes, should give enough time to select a character.</change>
</entry>
<entry>
<date>03-19-2019</date>
<author>Kevin:</author>
Expand Down
6 changes: 0 additions & 6 deletions docs/docs.polserver.com/pol100/osem.xml
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,6 @@ const SCRIPTOPT_CAN_ACCESS_OFFLINE_MOBILES := 4;</code></explain>
<return>1 on success</return>
</function>

<function name="System_RPM">
<prototype>System_RPM()</prototype>
<explain>returns the system RPM, which is the number of "game loop rotations" completed in the last minute. </explain>
<return>Last System RPM integer</return>
</function>

<function name="Clear_Event_Queue">
<prototype>Clear_Event_Queue()</prototype>
<explain>Empties the current script's event queue</explain>
Expand Down
17 changes: 10 additions & 7 deletions pol-core/clib/CMakeSources.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ set (clib_sources
Debugging/LogSink.cpp
Debugging/LogSink.h
Header_Windows.h
Header_Windows.h
Program/ProgramConfig.cpp
Program/ProgramConfig.h
Program/ProgramMain.cpp
Expand Down Expand Up @@ -53,6 +52,16 @@ set (clib_sources
message_queue.h
mlog.cpp
mlog.h
network/sckutil.cpp
network/sckutil.h
network/singlepoller.h
network/singlepollers/pollingwithpoll.h
network/singlepollers/pollingwithselect.h
network/sockets.h
network/socketsvc.cpp
network/socketsvc.h
network/wnsckt.cpp
network/wnsckt.h
opnew.cpp
opnew.h
passert.cpp
Expand All @@ -61,10 +70,6 @@ set (clib_sources
random.h
rawtypes.h
refptr.h
sckutil.cpp
sckutil.h
socketsvc.cpp
socketsvc.h
spinlock.h
stlutil.h
stracpy.cpp
Expand All @@ -84,8 +89,6 @@ set (clib_sources
wallclock.cpp
wallclock.h
weakptr.h
wnsckt.cpp
wnsckt.h
xmain.cpp
#pol_global_config_win.h
#vld.h
Expand Down
3 changes: 2 additions & 1 deletion pol-core/clib/cfgfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,8 @@ void ConfigFile::open( const char* i_filename )
fp = fopen( i_filename, "rt" );
if ( !fp )
{
ERROR_PRINT << "Unable to open configuration file " << _filename << "\n";
POLLOG_ERROR << "Unable to open configuration file " << _filename << " " << errno << ": "
<< std::strerror( errno ) << "\n";
throw std::runtime_error( std::string( "Unable to open configuration file " ) + _filename );
}
#endif
Expand Down
File renamed without changes.
File renamed without changes.
56 changes: 56 additions & 0 deletions pol-core/clib/network/singlepoller.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#pragma once
#ifndef H_SINGLEPOLLER
#define H_SINGLEPOLLER

#include "sockets.h"

#include "singlepollers/pollingwithpoll.h"
//#include "singlepollers/pollingwithselect.h"

namespace Pol
{
namespace Clib
{
// This only works for Linux and Windows more recent than Windows Vista / Windows Server 2008. Let
// us know if anyone still needs Windows XP support (PollingWithSelect). If no one complains, we
// should remove pollingwithselect in the near future.
using PollingStrategy = PollingWithPoll;

class SinglePoller
{
public:
explicit SinglePoller( SOCKET socket ) : poller( socket ){};

int wait_for_events() { return poller.wait_for_events(); }

// Note that not every poller will support usec resolution. I should find a way around it.
void set_timeout( int timeout_sec, int timeout_usec )
{
poller.set_timeout( timeout_sec, timeout_usec );
}

bool incoming() { return poller.incoming(); }
bool error() { return poller.error(); }
bool writable() { return poller.writable(); }

bool prepare( bool notify_writable )
{
if ( !poller.valid_socket() )
return false;

poller.reset();
poller.notify_on_incoming();
poller.notify_on_error();
if ( notify_writable )
poller.notify_on_writable();

return true;
}

private:
PollingStrategy poller;
};
} // namespace Clib
} // namespace Pol

#endif
88 changes: 88 additions & 0 deletions pol-core/clib/network/singlepollers/pollingwithpoll.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#pragma once
#ifndef H_POLLINGWITHPOLL
#define H_POLLINGWITHPOLL

#include "../../passert.h"
#include "../sockets.h"

#ifdef _WIN32

// compatibility wrapper for windows
int poll( struct pollfd* fds, ULONG nfds, int timeout )
{
return WSAPoll( fds, nfds, timeout );
};

#else

#include <poll.h>

#endif

namespace Pol
{
namespace Clib
{
class PollingWithPoll
{
public:
explicit PollingWithPoll( SOCKET socket )
: default_timeout{0, 0}, processed( false )
{
fdList.fd = socket;
reset();
}

void reset()
{
processed = false;

fdList.events = 0;
fdList.revents = 0;
}

void notify_on_incoming() { fdList.events |= POLLIN; }
void notify_on_error() {} // do nothing, poll() always notifies on error
void notify_on_writable() { fdList.events |= POLLOUT; }

bool incoming() { return ( processed ) ? ( (fdList.revents & POLLIN) != 0 ) : false; }
bool error() { return ( processed ) ? ( ( fdList.revents & POLLERR ) != 0 ) : false; }
bool writable() { return ( processed ) ? ( ( fdList.revents & POLLOUT ) != 0 ) : false; }

void set_timeout( int timeout_sec, int timeout_usec )
{
default_timeout.tv_sec = timeout_sec;
default_timeout.tv_usec = timeout_usec;
}

int wait_for_events()
{
passert( valid_socket() );

// ugly conversion, maybe change everything to use ms
int timeout_ms = 1000 * default_timeout.tv_sec + default_timeout.tv_usec / 1000;

// if timeout is non-zero but below 1ms, cap at 1ms
if ( default_timeout.tv_usec != 0 && timeout_ms == 0 )
timeout_ms = 1;

int res = poll( &fdList, 1, timeout_ms );

// only mark as processed if we don't have errors
if ( res >= 0 )
processed = true;

return res;
}

bool valid_socket() { return fdList.fd != INVALID_SOCKET; }

private:
pollfd fdList; // a list of 1, this is a single poller

timeval default_timeout;
bool processed;
};
} // namespace Clib
} // namespace Pol
#endif
83 changes: 83 additions & 0 deletions pol-core/clib/network/singlepollers/pollingwithselect.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#pragma once
#ifndef H_POLLINGWITHSELECT
#define H_POLLINGWITHSELECT

#include "../../passert.h"
#include "../sockets.h"

namespace Pol
{
namespace Clib
{
class PollingWithSelect
{
public:
explicit PollingWithSelect( SOCKET socket )
: socket( socket ), default_timeout{0, 0}, processed( false )
{
reset();
}

void reset()
{
processed = false;
FD_ZERO( &c_recv_fd );
FD_ZERO( &c_err_fd );
FD_ZERO( &c_send_fd );
}

void notify_on_incoming() { FD_SET( socket, &c_recv_fd ); }
void notify_on_error() { FD_SET( socket, &c_err_fd ); }
void notify_on_writable() { FD_SET( socket, &c_send_fd ); }

bool incoming() { return ( processed ) ? FD_ISSET( socket, &c_recv_fd ) : false; }
bool error() { return ( processed ) ? FD_ISSET( socket, &c_err_fd ) : false; }
bool writable() { return ( processed ) ? FD_ISSET( socket, &c_send_fd ) : false; }

void set_timeout( int timeout_sec, int timeout_usec )
{
default_timeout.tv_sec = timeout_sec;
default_timeout.tv_usec = timeout_usec;
}

int wait_for_events()
{
passert( valid_socket() );

// Linux requires nfds to be the largest descriptor + 1, Windows doesn't care
const int nfds = socket + 1;
timeval c_select_timeout = default_timeout;

int res = select( nfds, &c_recv_fd, &c_send_fd, &c_err_fd, &c_select_timeout );

// only mark as processed if we don't have errors, otherwise the sets are the same as we
// provided
if ( res >= 0 )
processed = true;

return res;
}

bool valid_socket()
{
#ifndef _WIN32
// Linux and other non-windows OS can't handle FDs larger than FD_SETSIZE when using select()
return socket != INVALID_SOCKET && socket < FD_SETSIZE;
#else
return socket != INVALID_SOCKET;
#endif
}

private:
fd_set c_recv_fd;
fd_set c_err_fd;
fd_set c_send_fd;

SOCKET socket;
timeval default_timeout;
bool processed;
};
} // namespace Clib
} // namespace Pol

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,14 @@ typedef int socklen_t;

typedef int SOCKET;

#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

#define SOCKET_ERRNO( x ) x
#define socket_errno errno
Expand Down
Loading

0 comments on commit 88c22ed

Please sign in to comment.