Skip to content
Permalink
Browse files

Merge pull request #88 from polserver/network-improvements

Network improvements
  • Loading branch information...
frozenblit committed Apr 26, 2019
2 parents 4210683 + 0bed27c commit 88c22edc771429948543d9e4324cc1379740b2fd
Showing with 654 additions and 854 deletions.
  1. +2 −5 docs/docs.polserver.com/pol100/configfiles.xml
  2. +15 −1 docs/docs.polserver.com/pol100/corechanges.xml
  3. +0 −6 docs/docs.polserver.com/pol100/osem.xml
  4. +10 −7 pol-core/clib/CMakeSources.cmake
  5. +2 −1 pol-core/clib/cfgfile.cpp
  6. 0 pol-core/clib/{ → network}/sckutil.cpp
  7. 0 pol-core/clib/{ → network}/sckutil.h
  8. +56 −0 pol-core/clib/network/singlepoller.h
  9. +88 −0 pol-core/clib/network/singlepollers/pollingwithpoll.h
  10. +83 −0 pol-core/clib/network/singlepollers/pollingwithselect.h
  11. +4 −6 pol-core/{pol → clib}/network/sockets.h
  12. +6 −13 pol-core/clib/{ → network}/socketsvc.cpp
  13. +3 −6 pol-core/clib/{ → network}/socketsvc.h
  14. +20 −13 pol-core/clib/{ → network}/wnsckt.cpp
  15. +9 −6 pol-core/clib/{ → network}/wnsckt.h
  16. +3 −3 pol-core/clib/streamsaver.cpp
  17. +9 −1 pol-core/doc/core-changes.txt
  18. +1 −2 pol-core/pol/CMakeSources.cmake
  19. +4 −1 pol-core/pol/accounts/accounts.cpp
  20. +15 −1 pol-core/pol/containr.cpp
  21. +3 −3 pol-core/pol/create.cpp
  22. +1 −1 pol-core/pol/crypt/crypt.h
  23. +1 −1 pol-core/pol/crypt/cryptbase.h
  24. +2 −32 pol-core/pol/decay.cpp
  25. +5 −4 pol-core/pol/decay.h
  26. +1 −0 pol-core/pol/dropitem.cpp
  27. +2 −7 pol-core/pol/globals/network.cpp
  28. +1 −4 pol-core/pol/globals/network.h
  29. +2 −4 pol-core/pol/globals/state.cpp
  30. +0 −3 pol-core/pol/globals/state.h
  31. +5 −5 pol-core/pol/login.cpp
  32. +6 −0 pol-core/pol/miscmsg.cpp
  33. +3 −3 pol-core/pol/module/httpmod.cpp
  34. +2 −2 pol-core/pol/module/httpmod.h
  35. +3 −9 pol-core/pol/module/osmod.cpp
  36. +0 −4 pol-core/pol/module/osmod.h
  37. +6 −6 pol-core/pol/module/polsystemmod.cpp
  38. +12 −11 pol-core/pol/network/auxclient.cpp
  39. +5 −5 pol-core/pol/network/auxclient.h
  40. +4 −5 pol-core/pol/network/client.h
  41. +2 −27 pol-core/pol/network/clientio.cpp
  42. +10 −0 pol-core/pol/network/clientio.h
  43. +35 −66 pol-core/pol/network/clientthread.cpp
  44. +15 −20 pol-core/pol/network/sockio.cpp
  45. +2 −19 pol-core/pol/network/sockio.h
  46. +30 −249 pol-core/pol/pol.cpp
  47. +9 −9 pol-core/pol/polcfg.cpp
  48. +4 −4 pol-core/pol/polcfg.h
  49. +9 −8 pol-core/pol/poldbg.cpp
  50. +2 −40 pol-core/pol/polsem.cpp
  51. +0 −3 pol-core/pol/polsem.h
  52. +3 −3 pol-core/pol/polwww.cpp
  53. +0 −3 pol-core/pol/profile.h
  54. +0 −14 pol-core/pol/schedule.cpp
  55. +0 −2 pol-core/pol/schedule.h
  56. +0 −22 pol-core/pol/scrsched.cpp
  57. +3 −5 pol-core/pol/scrsched.h
  58. +5 −12 pol-core/pol/scrstore.cpp
  59. +0 −5 pol-core/pol/spells.cpp
  60. +0 −1 pol-core/pol/spells.h
  61. +0 −21 pol-core/pol/stubdata.h
  62. +24 −57 pol-core/pol/tasks.cpp
  63. +28 −15 pol-core/pol/uimport.cpp
  64. +5 −4 pol-core/pol/uoclient.h
  65. +68 −49 pol-core/pol/uolisten.cpp
  66. +6 −7 pol-core/support/pol.cfg.example
  67. +0 −8 pol-core/support/scripts/os.em
@@ -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>
@@ -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>
@@ -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})]
@@ -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>
@@ -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>
@@ -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>
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
File renamed without changes.
File renamed without changes.
@@ -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
@@ -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
@@ -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
@@ -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
Oops, something went wrong.

0 comments on commit 88c22ed

Please sign in to comment.
You can’t perform that action at this time.