Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
07f2290
Refactor socket usage
DanielHartl Jun 18, 2018
3799328
Network changes refactoring
DanielHartl Jun 19, 2018
25d697c
Fix video file
DanielHartl Jun 19, 2018
9182146
Fix last glitches
DanielHartl Jun 19, 2018
78cf7ea
Specify random port for client
DanielHartl Jun 19, 2018
965387d
TCP with blocking client socket
DanielHartl Jun 20, 2018
44182bc
Fix blocking client socket
DanielHartl Jun 20, 2018
5a8addc
Fix naming of file
DanielHartl Jun 21, 2018
a0ea513
Add extern definition
DanielHartl Jun 21, 2018
870f7e1
Fix HasDataToRead
DanielHartl Jun 21, 2018
0e16cd0
Works
DanielHartl Jun 22, 2018
070e3f3
Cleanup code
DanielHartl Jun 22, 2018
6eeaf74
Remove runtime check
DanielHartl Jun 22, 2018
cb4d3f3
Fix path for linux
DanielHartl Jun 22, 2018
f258435
Remove winuser.h from includes
DanielHartl Jun 22, 2018
635e76c
Fix unix build
DanielHartl Jun 22, 2018
c2ba1dd
Refactor connection handlers
DanielHartl Jun 25, 2018
a927311
Fix include
DanielHartl Jun 25, 2018
6df579f
Explicitly define all destructors
DanielHartl Jun 25, 2018
cdb5ce6
Fix signatures
DanielHartl Jun 25, 2018
bb94374
Update CMakeLists.txt
DanielHartl Jun 25, 2018
58405d6
Revert util.cpp
DanielHartl Jun 25, 2018
576db54
Handle client disconnect gracefully
danhartl Jun 25, 2018
a36a7f7
Add headers
danhartl Jun 25, 2018
695ef28
Code cleanup
DanielHartl Jun 26, 2018
6022c9f
Merge branch 'tcp-refactor' of https://github.com/DanielHartl/stratag…
DanielHartl Jun 26, 2018
2edc38b
Re-enable master.cpp
DanielHartl Jun 26, 2018
9a68896
Small fixes
DanielHartl Jun 26, 2018
277e8c9
Code review prep
danhartl Jun 26, 2018
32f7ade
Disconnect if client is non responsive
DanielHartl Jun 27, 2018
611264f
Revert earlier change
DanielHartl Jun 27, 2018
0dd50f2
Check inside socket abstraction if disconnected
DanielHartl Jun 27, 2018
748416e
More graceful exit of network game
DanielHartl Jun 27, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ set(network_SRCS
src/network/net_lowlevel.cpp
src/network/net_message.cpp
src/network/master.cpp
src/network/net_connection_handler.cpp
src/network/netconnect.cpp
src/network/network.cpp
src/network/netsockets.cpp
Expand Down Expand Up @@ -539,6 +540,7 @@ set(stratagus_generic_HDRS
src/include/net_message.h
src/include/netconnect.h
src/include/network.h
src/include/net_connection_handler.h
src/include/network/netsockets.h
src/include/parameters.h
src/include/particle.h
Expand Down
176 changes: 176 additions & 0 deletions src/include/net_connection_handler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
// _________ __ __
// / _____// |_____________ _/ |______ ____ __ __ ______
// \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
// /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
// \/ \/ \//_____/ \/
// ______________________ ______________________
// T H E W A R B E G I N S
// Stratagus - A free fantasy real time strategy game engine
//
/**@name master.cpp - The master server. */
//
// (c) Copyright 2003-2007 by Tom Zickel and Jimmy Salmon
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; only version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//

#ifndef __NET_CONNECTION_HANDLER_H__
#define __NET_CONNECTION_HANDLER_H__

#include "network/netsockets.h"

#include <memory>
#include <map>
#include <vector>

class IConnectionHandler
{
public:
virtual ~IConnectionHandler() = default;
virtual void Open(const CHost &host) = 0;
virtual bool IsValid() = 0;
virtual int HasDataToRead(int timeout) = 0;
virtual int Recv(unsigned char *buf, int len, CHost *hostFrom) = 0;
virtual void Close() = 0;
};

class IServerConnectionHandler : public IConnectionHandler
{
public:
virtual ~IServerConnectionHandler() = default;
virtual void SendToAllClients(std::vector<CHost> hosts, const unsigned char *buf, unsigned int len) = 0;
virtual void SendToClient(CHost host, const unsigned char *buf, unsigned int len) = 0;
};

class IClientConnectionHandler : public IConnectionHandler
{
public:
virtual ~IClientConnectionHandler() = default;
virtual void SendToServer(const unsigned char *buf, unsigned int len) = 0;
};

class CTCPConnectionHandler
{
public:
CTCPConnectionHandler() = default;
CTCPConnectionHandler(CTCPSocket socket) : _socket(socket) {}
bool Open(const CHost& host);
int Listen();
std::shared_ptr<CTCPConnectionHandler> Accept();
void Close();
bool Connect(const CHost& host);
int Send(const unsigned char* buf, unsigned int len);
int Recv(unsigned char* buf, int len);
void SetBlocking();
void SetNonBlocking();
//
int HasDataToRead(int timeout);
bool IsValid() const;
CHost GetHost() const;

private:
CTCPSocket _socket;
};

class CUDPConnectionHandler
{
public:
bool Open(const CHost& host);
void Close();
void Send(const CHost& host, const unsigned char* buf, unsigned int len);
int Recv(unsigned char* buf, int len, CHost* hostFrom);
void SetNonBlocking();
//
int HasDataToRead(int timeout);
bool IsValid() const;

private:
CUDPSocket _socket;
};

class CTCPServerConnectionHandler : public IServerConnectionHandler
{
public:
virtual ~CTCPServerConnectionHandler() = default;
void Open(const CHost& host) override;
bool IsValid() override { return _connectionHandler.IsValid(); }
int HasDataToRead(int timeout) override;
void SendToAllClients(std::vector<CHost> hosts, const unsigned char* buf, unsigned int len) override;
void SendToClient(CHost host, const unsigned char* buf, unsigned int len) override;
int Recv(unsigned char* buf, int len, CHost* hostFrom) override;
void Close() override;

private:
int _skipClient = 0;
CTCPConnectionHandler _connectionHandler;
std::map<CHost, std::shared_ptr<CTCPConnectionHandler>> _clientConnections;
};

class CUDPServerConnectionHandler : public IServerConnectionHandler
{
public:
virtual ~CUDPServerConnectionHandler() = default;
void Open(const CHost& host) override;
int HasDataToRead(int timeout) override { return _connectionHandler.HasDataToRead(timeout); }
void SendToAllClients(std::vector<CHost> hosts, const unsigned char* buf, unsigned int len) override;
void SendToClient(CHost host, const unsigned char* buf, unsigned int len) override;
int Recv(unsigned char* buf, int len, CHost* hostFrom) override;
bool IsValid() override { return _connectionHandler.IsValid(); }
void Close() override { _connectionHandler.Close(); }

private:
CUDPConnectionHandler _connectionHandler;
};

class CTCPClientConnectionHandler : public IClientConnectionHandler
{
public:
CTCPClientConnectionHandler(CHost serverHost)
: _serverHost(serverHost) {}

virtual ~CTCPClientConnectionHandler() = default;
void Open(const CHost &host) override;
int HasDataToRead(int timeout) override { return _connectionHandler.HasDataToRead(timeout); }
void SendToServer(const unsigned char *buf, unsigned int len) override;
int Recv(unsigned char *buf, int len, CHost *hostFrom) override;
bool IsValid() override { return _connectionHandler.IsValid(); }
void Close() override { _connectionHandler.Close(); }

private:
CHost _serverHost;
CTCPConnectionHandler _connectionHandler;
};

class CUDPClientConnectionHandler : public IClientConnectionHandler
{
public:
CUDPClientConnectionHandler(CHost serverHost)
: _serverHost(serverHost) {}

virtual ~CUDPClientConnectionHandler() = default;
void Open(const CHost &host) override;
int HasDataToRead(int timeout) override { return _connectionHandler.HasDataToRead(timeout); }
void SendToServer(const unsigned char *buf, unsigned int len) override;
int Recv(unsigned char *buf, int len, CHost *hostFrom) override;
bool IsValid() override { return _connectionHandler.IsValid(); }
void Close() override { _connectionHandler.Close(); }

private:
CHost _serverHost;
CUDPConnectionHandler _connectionHandler;
};

#endif // !__NET_CONNECTION_HANDLER_H__
2 changes: 2 additions & 0 deletions src/include/net_lowlevel.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ extern int NetListenTCP(Socket sockfd);
extern Socket NetAcceptTCP(Socket sockfd, unsigned long *clientHost, int *clientPort);


/// Set socket to blocking
extern int NetSetBlocking(Socket sockfd);
/// Set socket to non-blocking
extern int NetSetNonBlocking(Socket sockfd);
/// Wait for socket ready.
Expand Down
155 changes: 155 additions & 0 deletions src/include/netconnect.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@

//@{

/*----------------------------------------------------------------------------
-- Includes
----------------------------------------------------------------------------*/

#include "net_message.h"
#include "net_connection_handler.h"

class CHost;

Expand Down Expand Up @@ -121,4 +126,154 @@ extern void NetworkDetachFromServer(); /// Menu Loop: Client: Send GoodBye

//@}

/**
** Connect state information of network systems active in current game.
*/
struct NetworkState {
void Clear()
{
State = ccs_unused;
MsgCnt = 0;
LastFrame = 0;
}

unsigned char State; /// Menu: ConnectState
unsigned short MsgCnt; /// Menu: Counter for state msg of same type (detect unreachable)
unsigned long LastFrame; /// Last message received
// Fill in here...
};

class CServer
{
public:
void Init(const std::string &name, CServerSetup *serverSetup);

void Open(const CHost &host, bool udp);

bool IsValid() const;

int HasDataToRead(int timeout) const;

void SendToAllClients(CNetworkHost hosts[], int hostCount, const unsigned char *buf, unsigned int len);

template <typename T>
void SendMessageToSpecificClient(const CHost &host, const T &msg);

void SendMessageToSpecificClient(const CHost &host, const CInitMessage_Header &msg);

int Recv(unsigned char *buf, int len, CHost *hostFrom) const;

void Close();

void Update(unsigned long frameCounter);
void Parse(unsigned long frameCounter, const unsigned char *buf, const CHost &host);

void MarkClientsAsResync();
void KickClient(int c);

private:
int Parse_Hello(int h, const CInitMessage_Hello &msg, const CHost &host);
void Parse_Resync(const int h);
void Parse_Waiting(const int h);
void Parse_Map(const int h);
void Parse_State(const int h, const CInitMessage_State &msg);
void Parse_GoodBye(const int h);
void Parse_SeeYou(const int h);

void Send_AreYouThere(const CNetworkHost &host);
void Send_GameFull(const CHost &host);
void Send_Welcome(const CNetworkHost &host, int hostIndex);
void Send_Resync(const CNetworkHost &host, int hostIndex);
void Send_Map(const CNetworkHost &host);
void Send_State(const CNetworkHost &host);
void Send_GoodBye(const CNetworkHost &host);

private:
std::string name;
NetworkState networkStates[PlayerMax]; /// Client Host states

IServerConnectionHandler* _serverConnectionHandler = nullptr;

CServerSetup *serverSetup;
};

class CClient
{
public:
void Init(const std::string &name, CServerSetup *serverSetup, CServerSetup *localSetup, unsigned long tick);
void SetServerHost(const CHost &host) { serverHost = host; }

void Open(bool udp);

bool IsValid() const;

int HasDataToRead(int timeout);

void SendToServer(const unsigned char *buf, unsigned int len);

int Recv(unsigned char *buf, int len, CHost *hostFrom);

void Close();

bool Parse(const unsigned char *buf);
bool Update(unsigned long tick);

void DetachFromServer();

int GetNetworkState() const { return networkState.State; }

private:
bool Update_disconnected();
bool Update_detaching(unsigned long tick);
bool Update_connecting(unsigned long tick);
bool Update_connected(unsigned long tick);
bool Update_synced(unsigned long tick);
bool Update_changed(unsigned long tick);
bool Update_async(unsigned long tick);
bool Update_mapinfo(unsigned long tick);
bool Update_badmap(unsigned long tick);
bool Update_goahead(unsigned long tick);
bool Update_started(unsigned long tick);

void Send_Go(unsigned long tick);
void Send_Config(unsigned long tick);
void Send_MapUidMismatch(unsigned long tick);
void Send_Map(unsigned long tick);
void Send_Resync(unsigned long tick);
void Send_State(unsigned long tick);
void Send_Waiting(unsigned long tick, unsigned long msec);
void Send_Hello(unsigned long tick);
void Send_GoodBye(unsigned long tick);

template <typename T>
void SendRateLimited(const T &msg, unsigned long tick, unsigned long msecs);

void SetConfig(const CInitMessage_Config &msg);

void Parse_GameFull();
void Parse_LuaMismatch(const unsigned char *buf);
void Parse_EngineMismatch(const unsigned char *buf);
void Parse_Resync(const unsigned char *buf);
void Parse_Config(const unsigned char *buf);
void Parse_State(const unsigned char *buf);
void Parse_Welcome(const unsigned char *buf);
void Parse_Map(const unsigned char *buf);
void Parse_AreYouThere();

template <typename T>
void SendToServer(const T & msg);
void SendToServer(const CInitMessage_Header &msg);

private:
std::string name;
CHost serverHost; /// IP:port of server to join
NetworkState networkState;
unsigned char lastMsgTypeSent; /// Subtype of last InitConfig message sent

IClientConnectionHandler* _clientConnectionHandler = nullptr;

CServerSetup *serverSetup;
CServerSetup *localSetup;
};

#endif // !__NETCONNECT_H__
6 changes: 4 additions & 2 deletions src/include/network.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,18 @@ class CNetworkParameter
-- Variables
----------------------------------------------------------------------------*/

extern CUDPSocket NetworkFildes; /// Network file descriptor
extern bool NetworkInSync; /// Network is in sync
extern bool NetworkGame;

/*----------------------------------------------------------------------------
-- Functions
----------------------------------------------------------------------------*/

extern inline bool IsNetworkGame() { return NetworkFildes.IsValid(); }
extern inline bool IsNetworkGame() { return NetworkGame; }

extern void InitNetwork1(); /// Initialise network
extern void ExitNetwork1(); /// Cleanup network (port)
extern bool NetworkHasDataToRead();
extern void NetworkOnStartGame(); /// Initialise network data for ingame communication
extern void NetworkEvent(); /// Handle network events
extern void NetworkSync(); /// Hold in sync
Expand Down
Loading