Add classes CHost and CUDPSocket.
This commit is contained in:
parent
3c8cbe8e84
commit
af53391cee
13 changed files with 487 additions and 166 deletions
|
@ -229,6 +229,7 @@ set(network_SRCS
|
|||
src/network/master.cpp
|
||||
src/network/netconnect.cpp
|
||||
src/network/network.cpp
|
||||
src/network/udpsocket.cpp
|
||||
)
|
||||
source_group(network FILES ${network_SRCS})
|
||||
|
||||
|
@ -534,6 +535,7 @@ set(stratagus_generic_HDRS
|
|||
src/include/net_message.h
|
||||
src/include/netconnect.h
|
||||
src/include/network.h
|
||||
src/include/network/udpsocket.h
|
||||
src/include/parameters.h
|
||||
src/include/particle.h
|
||||
src/include/pathfinder.h
|
||||
|
|
|
@ -114,8 +114,8 @@ extern unsigned long NetResolveHost(const std::string &host);
|
|||
/// Get local IP from network file descriptor
|
||||
extern int NetSocketAddr(const Socket sock, unsigned long *ips, int maxAddr);
|
||||
|
||||
/// Open a UDP Socket port.
|
||||
extern Socket NetOpenUDP(const char *addr, int port);
|
||||
/// Open a UDP Socket port. (param in network format)
|
||||
extern Socket NetOpenUDP(unsigned long ip, int port);
|
||||
/// Close a UDP socket port.
|
||||
extern void NetCloseUDP(Socket sockfd);
|
||||
/// Send through a UPD socket to a host:port.
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
|
||||
#include "net_message.h"
|
||||
|
||||
class CHost;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Defines
|
||||
----------------------------------------------------------------------------*/
|
||||
|
@ -101,7 +103,7 @@ extern CServerSetup LocalSetupState; /// Network menu: Multiplayer Client
|
|||
-- Functions
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
extern int FindHostIndexBy(unsigned long ip, int port);
|
||||
extern int FindHostIndexBy(const CHost &host);
|
||||
extern void NetworkServerStartGame(); /// Server user has finally hit the start game button
|
||||
extern void NetworkGamePrepareGameSettings();
|
||||
|
||||
|
@ -109,7 +111,7 @@ extern int GetNetworkState();
|
|||
|
||||
extern void NetworkInitClientConnect(); /// Setup network connect state machine for clients
|
||||
extern void NetworkInitServerConnect(int openslots); /// Setup network connect state machine for the server
|
||||
extern int NetworkParseSetupEvent(const unsigned char *buf, int size, unsigned long host, int port); /// Parse a network connect event
|
||||
extern int NetworkParseSetupEvent(const unsigned char *buf, int size, const CHost &host); /// Parse a network connect event
|
||||
extern int NetworkSetupServerAddress(const std::string &serveraddr, int port); /// Menu: Setup the server IP
|
||||
extern void NetworkProcessClientRequest(); /// Menu Loop: Send out client request messages
|
||||
extern void NetworkProcessServerRequest(); /// Menu Loop: Send out server request messages
|
||||
|
|
|
@ -35,15 +35,12 @@
|
|||
-- Includes
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "net_lowlevel.h"
|
||||
#include "network/udpsocket.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Defines
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#define IsNetworkGame() (NetworkFildes != (Socket)-1)
|
||||
|
||||
#define NetworkDefaultPort 6660 /// Default communication port
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
@ -59,7 +56,7 @@ class CUnitType;
|
|||
|
||||
extern char *NetworkAddr; /// Local network address to use
|
||||
extern int NetworkPort; /// Local network port to use
|
||||
extern Socket NetworkFildes; /// Network file descriptor
|
||||
extern CUDPSocket NetworkFildes; /// Network file descriptor
|
||||
extern int NetworkInSync; /// Network is in sync
|
||||
extern int NetworkUpdates; /// Network update each # game cycles
|
||||
extern int NetworkLag; /// Network lag (# game cycles)
|
||||
|
@ -68,6 +65,7 @@ extern int NetworkLag; /// Network lag (# game cycles)
|
|||
-- Functions
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
extern inline bool IsNetworkGame() { return NetworkFildes.IsValid(); }
|
||||
extern void InitNetwork1(); /// Initialise network part 1 (ports)
|
||||
extern void InitNetwork2(); /// Initialise network part 2
|
||||
extern void ExitNetwork1(); /// Cleanup network part 1 (ports)
|
||||
|
|
75
src/include/network/udpsocket.h
Normal file
75
src/include/network/udpsocket.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
// _________ __ __
|
||||
// / _____// |_____________ _/ |______ ____ __ __ ______
|
||||
// \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
|
||||
// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
|
||||
// /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
|
||||
// \/ \/ \//_____/ \/
|
||||
// ______________________ ______________________
|
||||
// T H E W A R B E G I N S
|
||||
// Stratagus - A free fantasy real time strategy game engine
|
||||
//
|
||||
/**@name udpsocket.h - The udp socket header file. */
|
||||
//
|
||||
// (c) Copyright 2013 by Joris Dauphin
|
||||
//
|
||||
// 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 UDPSOCKET_H
|
||||
#define UDPSOCKET_H
|
||||
|
||||
#include <string>
|
||||
|
||||
//@{
|
||||
|
||||
class CHost
|
||||
{
|
||||
public:
|
||||
CHost() : ip(0), port(0) {}
|
||||
CHost(const char *name, int port);
|
||||
CHost(unsigned long ip, int port) : ip(ip), port(port) {}
|
||||
unsigned long getIp() const { return ip; }
|
||||
int getPort() const { return port; }
|
||||
std::string toString() const;
|
||||
bool isValid() const;
|
||||
|
||||
bool operator == (const CHost &rhs) const { return ip == rhs.ip && port == rhs.port; }
|
||||
bool operator != (const CHost &rhs) const { return !(*this == rhs); }
|
||||
private:
|
||||
unsigned long ip;
|
||||
int port;
|
||||
};
|
||||
|
||||
class CUDPSocket_Impl;
|
||||
|
||||
class CUDPSocket
|
||||
{
|
||||
public:
|
||||
CUDPSocket();
|
||||
~CUDPSocket();
|
||||
bool Open(const CHost &host);
|
||||
void Close();
|
||||
void Send(const CHost &host, const void *buf, unsigned int len);
|
||||
int Recv(void *buf, int len, CHost *hostFrom);
|
||||
void SetNonBlocking();
|
||||
//
|
||||
int HasDataToRead(int timeout);
|
||||
bool IsValid() const;
|
||||
private:
|
||||
CUDPSocket_Impl *m_impl;
|
||||
};
|
||||
|
||||
//@}
|
||||
|
||||
#endif // !UDPSOCKET_H
|
|
@ -351,11 +351,12 @@ int NetSocketAddr(const Socket sock, unsigned long *ips, int maxAddr)
|
|||
/**
|
||||
** Open an UDP Socket port.
|
||||
**
|
||||
** @param ip !=0 Ip to bind in host notation.
|
||||
** @param port !=0 Port to bind in host notation.
|
||||
**
|
||||
** @return If success the socket fildes, -1 otherwise.
|
||||
*/
|
||||
Socket NetOpenUDP(const char *addr, int port)
|
||||
Socket NetOpenUDP(unsigned long ip, int port)
|
||||
{
|
||||
// open the socket
|
||||
Socket sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
@ -369,12 +370,8 @@ Socket NetOpenUDP(const char *addr, int port)
|
|||
|
||||
memset(&sock_addr, 0, sizeof(sock_addr));
|
||||
sock_addr.sin_family = AF_INET;
|
||||
if (addr) {
|
||||
sock_addr.sin_addr.s_addr = inet_addr(addr);
|
||||
} else {
|
||||
sock_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
}
|
||||
sock_addr.sin_port = htons(port);
|
||||
sock_addr.sin_addr.s_addr = ip;
|
||||
sock_addr.sin_port = port;
|
||||
// Bind the socket for listening
|
||||
if (bind(sockfd, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) < 0) {
|
||||
fprintf(stderr, "Couldn't bind to local port\n");
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
#include "interface.h"
|
||||
#include "map.h"
|
||||
#include "master.h"
|
||||
#include "net_lowlevel.h"
|
||||
#include "network.h"
|
||||
#include "parameters.h"
|
||||
#include "player.h"
|
||||
|
@ -97,12 +96,12 @@ public:
|
|||
void Init(const std::string &name, CServerSetup *serverSetup);
|
||||
|
||||
void Update(unsigned long frameCounter);
|
||||
void Parse(unsigned long frameCounter, const unsigned char *buf, unsigned long host, int port);
|
||||
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, unsigned long host, int port);
|
||||
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);
|
||||
|
@ -111,7 +110,7 @@ private:
|
|||
void Parse_SeeYou(const int h);
|
||||
|
||||
void Send_AreYouThere(const CNetworkHost &host);
|
||||
void Send_GameFull(unsigned long host, int port);
|
||||
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);
|
||||
|
@ -127,18 +126,15 @@ class CClient
|
|||
{
|
||||
public:
|
||||
void Init(const std::string &name, CServerSetup *serverSetup, CServerSetup *localSetup, unsigned long tick);
|
||||
bool SetupServerAddress(const std::string &serveraddr, int port);
|
||||
void SetServerHost(const CHost &host) { serverHost = host; }
|
||||
|
||||
bool Parse(const unsigned char *buf, unsigned long host, int port);
|
||||
bool Parse(const unsigned char *buf, const CHost &host);
|
||||
bool Update(unsigned long tick);
|
||||
|
||||
void DetachFromServer();
|
||||
|
||||
int GetNetworkState() const { return networkState.State; }
|
||||
|
||||
unsigned long GetServerIP() const { return ntohl(serverIP); }
|
||||
int GetServerPort() const { return ntohs(serverPort); }
|
||||
|
||||
private:
|
||||
bool Update_disconnected();
|
||||
bool Update_detaching(unsigned long tick);
|
||||
|
@ -179,8 +175,7 @@ private:
|
|||
|
||||
private:
|
||||
std::string name;
|
||||
unsigned long serverIP; /// IP of server to join
|
||||
int serverPort; /// Server network port to use
|
||||
CHost serverHost; /// IP:port of server to join
|
||||
NetworkState networkState;
|
||||
unsigned char lastMsgTypeSent; /// Subtype of last InitConfig message sent
|
||||
CServerSetup *serverSetup;
|
||||
|
@ -202,18 +197,18 @@ static CClient Client;
|
|||
** @param msg The message to send
|
||||
*/
|
||||
template <typename T>
|
||||
static void NetworkSendICMessage(unsigned long host, int port, const T &msg)
|
||||
static void NetworkSendICMessage(const CHost &host, const T &msg)
|
||||
{
|
||||
const unsigned char *buf = msg.Serialize();
|
||||
NetSendUDP(NetworkFildes, host, port, buf, msg.Size());
|
||||
NetworkFildes.Send(host, buf, msg.Size());
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
void NetworkSendICMessage(unsigned long host, int port, const CInitMessage_Header &msg)
|
||||
void NetworkSendICMessage(const CHost &host, const CInitMessage_Header &msg)
|
||||
{
|
||||
unsigned char *buf = new unsigned char [msg.Size()];
|
||||
msg.Serialize(buf);
|
||||
NetSendUDP(NetworkFildes, host, port, buf, msg.Size());
|
||||
NetworkFildes.Send(host, buf, msg.Size());
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
|
@ -267,22 +262,26 @@ static const char *icmsgsubtypenames[] = {
|
|||
#endif
|
||||
|
||||
template <typename T>
|
||||
static void NetworkSendICMessage_Log(unsigned long ip, int port, const T &msg)
|
||||
static void NetworkSendICMessage_Log(const CHost &host, const T &msg)
|
||||
{
|
||||
NetworkSendICMessage(ip, port, msg);
|
||||
NetworkSendICMessage(host, msg);
|
||||
|
||||
DebugPrint("Sending to %d.%d.%d.%d:%d -> %s\n"
|
||||
_C_ NIPQUAD(ntohl(ip)) _C_ ntohs(port)
|
||||
#ifdef DEBUG
|
||||
const std::string hostStr = host.toString();
|
||||
DebugPrint("Sending to %s -> %s\n" _C_ hostStr.c_str()
|
||||
_C_ icmsgsubtypenames[msg.GetHeader().GetSubType()]);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void NetworkSendICMessage_Log(unsigned long ip, int port, const CInitMessage_Header &msg)
|
||||
static void NetworkSendICMessage_Log(const CHost &host, const CInitMessage_Header &msg)
|
||||
{
|
||||
NetworkSendICMessage(ip, port, msg);
|
||||
NetworkSendICMessage(host, msg);
|
||||
|
||||
DebugPrint("Sending to %d.%d.%d.%d:%d -> %s\n"
|
||||
_C_ NIPQUAD(ntohl(ip)) _C_ ntohs(port)
|
||||
#ifdef DEBUG
|
||||
const std::string hostStr = host.toString();
|
||||
DebugPrint("Sending to %s -> %s\n" _C_ hostStr.c_str()
|
||||
_C_ icmsgsubtypenames[msg.GetSubType()]);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -307,7 +306,7 @@ void CClient::SendRateLimited(const T &msg, unsigned long tick, unsigned long ms
|
|||
networkState.MsgCnt = 0;
|
||||
lastMsgTypeSent = subtype;
|
||||
}
|
||||
NetworkSendICMessage(serverIP, serverPort, msg);
|
||||
NetworkSendICMessage(serverHost, msg);
|
||||
DebugPrint("[%s] Sending (%s:#%d)\n" _C_
|
||||
ncconstatenames[networkState.State] _C_
|
||||
icmsgsubtypenames[subtype] _C_ networkState.MsgCnt);
|
||||
|
@ -328,24 +327,12 @@ void CClient::SendRateLimited<CInitMessage_Header>(const CInitMessage_Header &ms
|
|||
networkState.MsgCnt = 0;
|
||||
lastMsgTypeSent = subtype;
|
||||
}
|
||||
NetworkSendICMessage(serverIP, serverPort, msg);
|
||||
NetworkSendICMessage(serverHost, msg);
|
||||
DebugPrint("[%s] Sending (%s:#%d)\n" _C_
|
||||
ncconstatenames[networkState.State] _C_
|
||||
icmsgsubtypenames[subtype] _C_ networkState.MsgCnt);
|
||||
}
|
||||
|
||||
bool CClient::SetupServerAddress(const std::string &serveraddr, int port)
|
||||
{
|
||||
unsigned long addr = NetResolveHost(serveraddr);
|
||||
|
||||
if (addr == INADDR_NONE) {
|
||||
return false;
|
||||
}
|
||||
serverIP = addr;
|
||||
serverPort = htons(port);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CClient::Init(const std::string &name, CServerSetup *serverSetup, CServerSetup *localSetup, unsigned long tick)
|
||||
{
|
||||
networkState.LastFrame = tick;
|
||||
|
@ -370,7 +357,7 @@ bool CClient::Update_disconnected()
|
|||
|
||||
// Spew out 5 and trust in God that they arrive
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
NetworkSendICMessage(serverIP, serverPort, message);
|
||||
NetworkSendICMessage(serverHost, message);
|
||||
}
|
||||
networkState.State = ccs_usercanceled;
|
||||
return false;
|
||||
|
@ -612,11 +599,13 @@ void CClient::SetConfig(const CInitMessage_Config &msg)
|
|||
if (i != msg.clientIndex) {
|
||||
Hosts[HostsCount] = msg.hosts[i];
|
||||
HostsCount++;
|
||||
DebugPrint("Client %d = %d.%d.%d.%d:%d [%.*s]\n" _C_
|
||||
msg.hosts[i].PlyNr _C_ NIPQUAD(ntohl(msg.hosts[i].Host)) _C_
|
||||
ntohs(msg.hosts[i].Port) _C_
|
||||
#ifdef DEBUG
|
||||
const std::string hostStr = CHost(msg.hosts[i].Host, msg.hosts[i].Port).toString();
|
||||
DebugPrint("Client %d = %s [%.*s]\n" _C_
|
||||
msg.hosts[i].PlyNr _C_ hostStr.c_str() _C_
|
||||
static_cast<int>(sizeof(msg.hosts[i].PlyName)) _C_
|
||||
msg.hosts[i].PlyName);
|
||||
#endif
|
||||
} else { // Own client
|
||||
NetLocalPlayerNumber = msg.hosts[i].PlyNr;
|
||||
DebugPrint("SELF %d [%.*s]\n" _C_ msg.hosts[i].PlyNr _C_
|
||||
|
@ -625,20 +614,23 @@ void CClient::SetConfig(const CInitMessage_Config &msg)
|
|||
}
|
||||
}
|
||||
// server is last:
|
||||
Hosts[HostsCount].Host = serverIP;
|
||||
Hosts[HostsCount].Port = serverPort;
|
||||
Hosts[HostsCount].Host = serverHost.getIp();
|
||||
Hosts[HostsCount].Port = serverHost.getPort();
|
||||
Hosts[HostsCount].PlyNr = msg.hosts[msg.hostsCount - 1].PlyNr;
|
||||
Hosts[HostsCount].SetName(msg.hosts[msg.hostsCount - 1].PlyName);
|
||||
++HostsCount;
|
||||
NetPlayers = HostsCount + 1;
|
||||
DebugPrint("Server %d = %d.%d.%d.%d:%d [%.*s]\n" _C_
|
||||
#ifdef DEBUG
|
||||
const std::string serverHostStr = serverHost.toString();
|
||||
DebugPrint("Server %d = %s [%.*s]\n" _C_
|
||||
msg.hosts[msg.hostsCount - 1].PlyNr _C_
|
||||
NIPQUAD(GetServerIP()) _C_ GetServerPort() _C_
|
||||
serverHostStr.c_str() _C_
|
||||
static_cast<int>(sizeof(msg.hosts[msg.hostsCount - 1].PlyName)) _C_
|
||||
msg.hosts[msg.hostsCount - 1].PlyName);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CClient::Parse(const unsigned char *buf, unsigned long host, int port)
|
||||
bool CClient::Parse(const unsigned char *buf, const CHost &host)
|
||||
{
|
||||
CInitMessage_Header header;
|
||||
header.Deserialize(buf);
|
||||
|
@ -646,8 +638,7 @@ bool CClient::Parse(const unsigned char *buf, unsigned long host, int port)
|
|||
if (header.GetType() != MessageInit_FromServer) {
|
||||
return true;
|
||||
}
|
||||
// Assert(host == this->serverIP);
|
||||
// Assert(port == this->serverPort);
|
||||
// Assert(host == this->serverHost);
|
||||
const unsigned char msgsubtype = header.GetSubType();
|
||||
|
||||
DebugPrint("Received %s in state %s\n" _C_ icmsgsubtypenames[msgsubtype]
|
||||
|
@ -788,8 +779,8 @@ void CClient::Parse_Welcome(const unsigned char *buf)
|
|||
NetworkLag = msg.Lag;
|
||||
NetworkUpdates = msg.Updates;
|
||||
|
||||
Hosts[0].Host = serverIP;
|
||||
Hosts[0].Port = serverPort;
|
||||
Hosts[0].Host = serverHost.getIp();
|
||||
Hosts[0].Port = serverHost.getPort();
|
||||
for (int i = 1; i < PlayerMax; ++i) {
|
||||
if (i != NetLocalHostsSlot) {
|
||||
Hosts[i] = msg.hosts[i];
|
||||
|
@ -861,8 +852,8 @@ void CClient::Parse_GameFull()
|
|||
if (networkState.State != ccs_connecting) {
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "Server at %d.%d.%d.%d:%d is full!\n",
|
||||
NIPQUAD(GetServerIP()), GetServerPort());
|
||||
const std::string serverHostStr = serverHost.toString();
|
||||
fprintf(stderr, "Server at %s is full!\n", serverHostStr.c_str());
|
||||
networkState.State = ccs_nofreeslots;
|
||||
}
|
||||
|
||||
|
@ -874,11 +865,12 @@ void CClient::Parse_ProtocolMismatch(const unsigned char *buf)
|
|||
CInitMessage_ProtocolMismatch msg;
|
||||
|
||||
msg.Deserialize(buf);
|
||||
const std::string serverHostStr = serverHost.toString();
|
||||
fprintf(stderr, "Incompatible network protocol version "
|
||||
NetworkProtocolFormatString " <-> " NetworkProtocolFormatString "\n"
|
||||
"from %d.%d.%d.%d:%d\n",
|
||||
"from %s\n",
|
||||
NetworkProtocolFormatArgs(NetworkProtocolVersion), NetworkProtocolFormatArgs(msg.Version),
|
||||
NIPQUAD(GetServerIP()), GetServerPort());
|
||||
serverHostStr.c_str());
|
||||
networkState.State = ccs_incompatiblenetwork;
|
||||
}
|
||||
|
||||
|
@ -890,10 +882,9 @@ void CClient::Parse_EngineMismatch(const unsigned char *buf)
|
|||
CInitMessage_EngineMismatch msg;
|
||||
|
||||
msg.Deserialize(buf);
|
||||
fprintf(stderr, "Incompatible Stratagus version %d <-> %d\n"
|
||||
"from %d.%d.%d.%d:%d\n",
|
||||
StratagusVersion, msg.Stratagus,
|
||||
NIPQUAD(GetServerIP()), GetServerPort());
|
||||
const std::string serverHostStr = serverHost.toString();
|
||||
fprintf(stderr, "Incompatible Stratagus version %d <-> %d\nfrom %s\n",
|
||||
StratagusVersion, msg.Stratagus, serverHostStr.c_str());
|
||||
networkState.State = ccs_incompatibleengine;
|
||||
}
|
||||
|
||||
|
@ -906,7 +897,7 @@ void CClient::Parse_AreYouThere()
|
|||
{
|
||||
const CInitMessage_Header message(MessageInit_FromClient, ICMIAH); // IAmHere
|
||||
|
||||
NetworkSendICMessage(serverIP, serverPort, message);
|
||||
NetworkSendICMessage(serverHost, message);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -942,14 +933,14 @@ void CServer::Send_AreYouThere(const CNetworkHost &host)
|
|||
{
|
||||
const CInitMessage_Header message(MessageInit_FromServer, ICMAYT); // AreYouThere
|
||||
|
||||
NetworkSendICMessage(host.Host, host.Port, message);
|
||||
NetworkSendICMessage(CHost(host.Host, host.Port), message);
|
||||
}
|
||||
|
||||
void CServer::Send_GameFull(unsigned long host, int port)
|
||||
void CServer::Send_GameFull(const CHost &host)
|
||||
{
|
||||
const CInitMessage_Header message(MessageInit_FromServer, ICMGameFull);
|
||||
|
||||
NetworkSendICMessage_Log(host, port, message);
|
||||
NetworkSendICMessage_Log(host, message);
|
||||
}
|
||||
|
||||
void CServer::Send_Welcome(const CNetworkHost &host, int index)
|
||||
|
@ -963,7 +954,7 @@ void CServer::Send_Welcome(const CNetworkHost &host, int index)
|
|||
message.hosts[i] = Hosts[i];
|
||||
}
|
||||
}
|
||||
NetworkSendICMessage_Log(host.Host, host.Port, message);
|
||||
NetworkSendICMessage_Log(CHost(host.Host, host.Port), message);
|
||||
}
|
||||
|
||||
void CServer::Send_Resync(const CNetworkHost &host, int hostIndex)
|
||||
|
@ -975,28 +966,28 @@ void CServer::Send_Resync(const CNetworkHost &host, int hostIndex)
|
|||
message.hosts[i] = Hosts[i];
|
||||
}
|
||||
}
|
||||
NetworkSendICMessage_Log(host.Host, host.Port, message);
|
||||
NetworkSendICMessage_Log(CHost(host.Host, host.Port), message);
|
||||
}
|
||||
|
||||
void CServer::Send_Map(const CNetworkHost &host)
|
||||
{
|
||||
const CInitMessage_Map message(NetworkMapName.c_str(), Map.Info.MapUID);
|
||||
|
||||
NetworkSendICMessage_Log(host.Host, host.Port, message);
|
||||
NetworkSendICMessage_Log(CHost(host.Host, host.Port), message);
|
||||
}
|
||||
|
||||
void CServer::Send_State(const CNetworkHost &host)
|
||||
{
|
||||
const CInitMessage_State message(MessageInit_FromServer, *serverSetup);
|
||||
|
||||
NetworkSendICMessage_Log(host.Host, host.Port, message);
|
||||
NetworkSendICMessage_Log(CHost(host.Host, host.Port), message);
|
||||
}
|
||||
|
||||
void CServer::Send_GoodBye(const CNetworkHost &host)
|
||||
{
|
||||
const CInitMessage_Header message(MessageInit_FromServer, ICMGoodBye);
|
||||
|
||||
NetworkSendICMessage_Log(host.Host, host.Port, message);
|
||||
NetworkSendICMessage_Log(CHost(host.Host, host.Port), message);
|
||||
}
|
||||
|
||||
void CServer::Update(unsigned long frameCounter)
|
||||
|
@ -1031,11 +1022,10 @@ void CServer::MarkClientsAsResync()
|
|||
** @param h slot number of host msg originates from
|
||||
** @param msg message received
|
||||
** @param host host which send the message
|
||||
** @param port port from where the messahe nas been sent
|
||||
**
|
||||
** @return host index
|
||||
*/
|
||||
int CServer::Parse_Hello(int h, const CInitMessage_Hello &msg, unsigned long host, int port)
|
||||
int CServer::Parse_Hello(int h, const CInitMessage_Hello &msg, const CHost &host)
|
||||
{
|
||||
if (h == -1) { // it is a new client
|
||||
for (int i = 1; i < PlayerMax - 1; ++i) {
|
||||
|
@ -1048,17 +1038,19 @@ int CServer::Parse_Hello(int h, const CInitMessage_Hello &msg, unsigned long hos
|
|||
}
|
||||
}
|
||||
if (h != -1) {
|
||||
Hosts[h].Host = host;
|
||||
Hosts[h].Port = port;
|
||||
Hosts[h].Host = host.getIp();
|
||||
Hosts[h].Port = host.getPort();
|
||||
Hosts[h].PlyNr = h;
|
||||
Hosts[h].SetName(msg.PlyName);
|
||||
DebugPrint("New client %d.%d.%d.%d:%d [%s]\n" _C_
|
||||
NIPQUAD(ntohl(host)) _C_ ntohs(port) _C_ Hosts[h].PlyName);
|
||||
#ifdef DEBUG
|
||||
const std::string hostStr = host.toString();
|
||||
DebugPrint("New client %s [%s]\n" _C_ hostStr.c_str() _C_ Hosts[h].PlyName);
|
||||
#endif
|
||||
networkStates[h].State = ccs_connecting;
|
||||
networkStates[h].MsgCnt = 0;
|
||||
} else {
|
||||
// Game is full - reject connnection
|
||||
Send_GameFull(host, port);
|
||||
Send_GameFull(host);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -1291,55 +1283,53 @@ void CServer::Parse_SeeYou(const int h)
|
|||
**
|
||||
** @param msg message received
|
||||
** @param host host which send the message
|
||||
** @param port port from where the message nas been sent
|
||||
**
|
||||
** @return 0 if the versions match, -1 otherwise
|
||||
*/
|
||||
static int CheckVersions(const CInitMessage_Hello &msg, unsigned long host, int port)
|
||||
static int CheckVersions(const CInitMessage_Hello &msg, const CHost &host)
|
||||
{
|
||||
if (msg.Stratagus != StratagusVersion) {
|
||||
fprintf(stderr, "Incompatible Stratagus version "
|
||||
"%d <-> %d\n"
|
||||
"from %d.%d.%d.%d:%d\n",
|
||||
StratagusVersion, msg.Stratagus,
|
||||
NIPQUAD(ntohl(host)), ntohs(port));
|
||||
const std::string hostStr = host.toString();
|
||||
fprintf(stderr, "Incompatible Stratagus version %d <-> %d from %s\n",
|
||||
StratagusVersion, msg.Stratagus, hostStr.c_str());
|
||||
|
||||
const CInitMessage_EngineMismatch message;
|
||||
NetworkSendICMessage_Log(host, port, message);
|
||||
NetworkSendICMessage_Log(host, message);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (msg.Version != NetworkProtocolVersion) {
|
||||
const std::string hostStr = host.toString();
|
||||
fprintf(stderr, "Incompatible network protocol version "
|
||||
NetworkProtocolFormatString " <-> "
|
||||
NetworkProtocolFormatString "\n"
|
||||
"from %d.%d.%d.%d:%d\n",
|
||||
"from %s\n",
|
||||
NetworkProtocolFormatArgs(NetworkProtocolVersion),
|
||||
NetworkProtocolFormatArgs(msg.Version),
|
||||
NIPQUAD(ntohl(host)), ntohs(port));
|
||||
hostStr.c_str());
|
||||
|
||||
const CInitMessage_ProtocolMismatch message;
|
||||
NetworkSendICMessage_Log(host, port, message);
|
||||
NetworkSendICMessage_Log(host, message);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CServer::Parse(unsigned long frameCounter, const unsigned char *buf, unsigned long host, int port)
|
||||
void CServer::Parse(unsigned long frameCounter, const unsigned char *buf, const CHost &host)
|
||||
{
|
||||
const unsigned char msgsubtype = buf[1];
|
||||
int index = FindHostIndexBy(host, port);
|
||||
int index = FindHostIndexBy(host);
|
||||
|
||||
if (index == -1) {
|
||||
if (msgsubtype == ICMHello) {
|
||||
CInitMessage_Hello msg;
|
||||
|
||||
msg.Deserialize(buf);
|
||||
if (CheckVersions(msg, host, port)) {
|
||||
if (CheckVersions(msg, host)) {
|
||||
return;
|
||||
}
|
||||
// Special case: a new client has arrived
|
||||
index = Parse_Hello(-1, msg, host, port);
|
||||
index = Parse_Hello(-1, msg, host);
|
||||
networkStates[index].LastFrame = frameCounter;
|
||||
}
|
||||
return;
|
||||
|
@ -1350,7 +1340,7 @@ void CServer::Parse(unsigned long frameCounter, const unsigned char *buf, unsign
|
|||
CInitMessage_Hello msg;
|
||||
|
||||
msg.Deserialize(buf);
|
||||
Parse_Hello(index, msg, host, port);
|
||||
Parse_Hello(index, msg, host);
|
||||
break;
|
||||
}
|
||||
case ICMResync: Parse_Resync(index); break;
|
||||
|
@ -1385,11 +1375,10 @@ void CServer::Parse(unsigned long frameCounter, const unsigned char *buf, unsign
|
|||
** @param buf Packet received
|
||||
** @param size size of the received packet.
|
||||
** @param host host which send the message
|
||||
** @param port port from where the message nas been sent
|
||||
**
|
||||
** @return 1 if packet is an InitConfig message, 0 otherwise
|
||||
*/
|
||||
int NetworkParseSetupEvent(const unsigned char *buf, int size, unsigned long host, int port)
|
||||
int NetworkParseSetupEvent(const unsigned char *buf, int size, const CHost &host)
|
||||
{
|
||||
Assert(NetConnectRunning != 0);
|
||||
|
||||
|
@ -1408,16 +1397,18 @@ int NetworkParseSetupEvent(const unsigned char *buf, int size, unsigned long hos
|
|||
}
|
||||
const unsigned char msgsubtype = header.GetSubType();
|
||||
|
||||
DebugPrint("Received %s (%d) from %d.%d.%d.%d:%d\n" _C_
|
||||
#ifdef DEBUG
|
||||
const std::string hostStr = host.toString();
|
||||
DebugPrint("Received %s (%d) from %s\n" _C_
|
||||
icmsgsubtypenames[int(msgsubtype)] _C_ msgsubtype _C_
|
||||
NIPQUAD(ntohl(host)) _C_ ntohs(port));
|
||||
|
||||
hostStr.c_str());
|
||||
#endif
|
||||
if (NetConnectRunning == 2) { // client
|
||||
if (Client.Parse(buf, host, port) == false) {
|
||||
if (Client.Parse(buf, host) == false) {
|
||||
NetConnectRunning = 0;
|
||||
}
|
||||
} else if (NetConnectRunning == 1) { // server
|
||||
Server.Parse(FrameCounter, buf, host, port);
|
||||
Server.Parse(FrameCounter, buf, host);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -1437,10 +1428,10 @@ int GetNetworkState()
|
|||
return Client.GetNetworkState();
|
||||
}
|
||||
|
||||
int FindHostIndexBy(unsigned long ip, int port)
|
||||
int FindHostIndexBy(const CHost &host)
|
||||
{
|
||||
for (int i = 0; i != PlayerMax; ++i) {
|
||||
if (Hosts[i].Host == ip && Hosts[i].Port == port) {
|
||||
if (Hosts[i].Host == host.getIp() && Hosts[i].Port == host.getPort()) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
@ -1517,7 +1508,8 @@ void NetworkServerStartGame()
|
|||
for (int i = 0; i < PlayerMax - 1; ++i) {
|
||||
printf("%02d: CO: %d Race: %d Host: ", i, ServerSetupState.CompOpt[i], ServerSetupState.Race[i]);
|
||||
if (ServerSetupState.CompOpt[i] == 0) {
|
||||
printf(" %d.%d.%d.%d:%d %s", NIPQUAD(ntohl(Hosts[i].Host)), ntohs(Hosts[i].Port), Hosts[i].PlyName);
|
||||
const std::string hostStr = CHost(Hosts[i].Host, Hosts[i].Port).toString();
|
||||
printf(" %s %s", hostStr.c_str(), Hosts[i].PlyName);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
@ -1640,26 +1632,26 @@ void NetworkServerStartGame()
|
|||
breakout:
|
||||
// Send to all clients.
|
||||
for (int i = 0; i < HostsCount; ++i) {
|
||||
const unsigned long host = message.hosts[i].Host;
|
||||
const int port = message.hosts[i].Port;
|
||||
const CHost host(message.hosts[i].Host, message.hosts[i].Port);
|
||||
|
||||
if (num[Hosts[i].PlyNr] == 1) { // not acknowledged yet
|
||||
message.clientIndex = i;
|
||||
NetworkSendICMessage_Log(host, port, message);
|
||||
NetworkSendICMessage_Log(host, message);
|
||||
} else if (num[Hosts[i].PlyNr] == 2) {
|
||||
NetworkSendICMessage_Log(host, port, statemsg);
|
||||
NetworkSendICMessage_Log(host, statemsg);
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for acknowledge
|
||||
unsigned char buf[1024];
|
||||
while (j && NetSocketReady(NetworkFildes, 1000)) {
|
||||
unsigned long host;
|
||||
int port;
|
||||
const int len = NetRecvUDP(NetworkFildes, buf, sizeof(buf), &host, &port);
|
||||
while (j && NetworkFildes.HasDataToRead(1000)) {
|
||||
CHost host;
|
||||
const int len = NetworkFildes.Recv(buf, sizeof(buf), &host);
|
||||
if (len < 0) {
|
||||
DebugPrint("*Receive ack failed: (%d) from %d.%d.%d.%d:%d\n" _C_
|
||||
len _C_ NIPQUAD(ntohl(host)) _C_ ntohs(port));
|
||||
#ifdef DEBUG
|
||||
const std::string hostStr = host.toString();
|
||||
DebugPrint("*Receive ack failed: (%d) from %s\n" _C_ len _C_ hostStr.c_str());
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
CInitMessage_Header header;
|
||||
|
@ -1670,10 +1662,11 @@ breakout:
|
|||
if (type == MessageInit_FromClient) {
|
||||
switch (subtype) {
|
||||
case ICMConfig: {
|
||||
DebugPrint("Got ack for InitConfig from %d.%d.%d.%d:%d\n"
|
||||
_C_ NIPQUAD(ntohl(host)) _C_ ntohs(port));
|
||||
|
||||
const int index = FindHostIndexBy(host, port);
|
||||
#ifdef DEBUG
|
||||
const std::string hostStr = host.toString();
|
||||
DebugPrint("Got ack for InitConfig from %s\n" _C_ hostStr.c_str());
|
||||
#endif
|
||||
const int index = FindHostIndexBy(host);
|
||||
if (index != -1) {
|
||||
if (num[Hosts[index].PlyNr] == 1) {
|
||||
num[Hosts[index].PlyNr]++;
|
||||
|
@ -1683,10 +1676,11 @@ breakout:
|
|||
break;
|
||||
}
|
||||
case ICMGo: {
|
||||
DebugPrint("Got ack for InitState from %d.%d.%d.%d:%d\n"
|
||||
_C_ NIPQUAD(ntohl(host)) _C_ ntohs(port));
|
||||
|
||||
const int index = FindHostIndexBy(host, port);
|
||||
#ifdef DEBUG
|
||||
const std::string hostStr = host.toString();
|
||||
DebugPrint("Got ack for InitState from %s\n" _C_ hostStr.c_str());
|
||||
#endif
|
||||
const int index = FindHostIndexBy(host);
|
||||
if (index != -1) {
|
||||
if (num[Hosts[index].PlyNr] == 2) {
|
||||
num[Hosts[index].PlyNr] = 0;
|
||||
|
@ -1710,9 +1704,8 @@ breakout:
|
|||
// Give clients a quick-start kick..
|
||||
const CInitMessage_Header message_go(MessageInit_FromServer, ICMGo);
|
||||
for (int i = 0; i < HostsCount; ++i) {
|
||||
const unsigned long host = Hosts[i].Host;
|
||||
const int port = Hosts[i].Port;
|
||||
NetworkSendICMessage_Log(host, port, message_go);
|
||||
const CHost host(Hosts[i].Host, Hosts[i].Port);
|
||||
NetworkSendICMessage_Log(host, message_go);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1728,10 +1721,15 @@ int NetworkSetupServerAddress(const std::string &serveraddr, int port)
|
|||
if (port == 0) {
|
||||
port = NetworkDefaultPort;
|
||||
}
|
||||
if (Client.SetupServerAddress(serveraddr, port) == false) {
|
||||
CHost host(serveraddr.c_str(), port);
|
||||
if (host.isValid() == false) {
|
||||
return 1;
|
||||
}
|
||||
DebugPrint("SELECTED SERVER: %s:%d (%d.%d.%d.%d)\n" _C_ serveraddr.c_str() _C_ Client.GetServerPort() _C_ NIPQUAD(Client.GetServerIP()));
|
||||
Client.SetServerHost(host);
|
||||
#ifdef DEBUG
|
||||
const std::string hostStr = host.toString();
|
||||
DebugPrint("SELECTED SERVER: %s [%s]\n" _C_ hostStr.c_str() _C_ serveraddr.c_str());
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -270,7 +270,7 @@ struct NetworkSelectionHeader {
|
|||
|
||||
char *NetworkAddr = NULL; /// Local network address to use
|
||||
int NetworkPort = NetworkDefaultPort; /// Local network port to use
|
||||
Socket NetworkFildes = static_cast<Socket>(-1); /// Network file descriptor
|
||||
CUDPSocket NetworkFildes; /// Network file descriptor
|
||||
int NetworkInSync = 1; /// Network is in sync
|
||||
int NetworkUpdates = 5; /// Network update each # game cycles
|
||||
int NetworkLag = 10; /// Network lag in # game cycles
|
||||
|
@ -321,7 +321,8 @@ static void NetworkBroadcast(const CNetworkPacket &packet, int numcommands)
|
|||
|
||||
// Send to all clients.
|
||||
for (int i = 0; i < HostsCount; ++i) {
|
||||
NetSendUDP(NetworkFildes, Hosts[i].Host, Hosts[i].Port, buf, CNetworkPacket::Size(numcommands));
|
||||
const CHost host(Hosts[i].Host, Hosts[i].Port);
|
||||
NetworkFildes.Send(host, buf, CNetworkPacket::Size(numcommands));
|
||||
}
|
||||
delete[] buf;
|
||||
}
|
||||
|
@ -367,7 +368,7 @@ static void NetworkSendPacket(const CNetworkCommandQueue ncq[])
|
|||
*/
|
||||
void InitNetwork1()
|
||||
{
|
||||
NetworkFildes = static_cast<Socket>(-1);
|
||||
NetworkFildes.Close();
|
||||
NetworkInSync = 1;
|
||||
|
||||
NetInit(); // machine dependent setup
|
||||
|
@ -384,16 +385,15 @@ void InitNetwork1()
|
|||
|
||||
// Our communication port
|
||||
int port = NetworkPort;
|
||||
int i;
|
||||
for (i = 0; i < 10; ++i) {
|
||||
NetworkFildes = NetOpenUDP(NetworkAddr, port + i);
|
||||
if (NetworkFildes != static_cast<Socket>(-1)) {
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
NetworkFildes.Open(CHost(NetworkAddr, port + i));
|
||||
if (NetworkFildes.IsValid()) {
|
||||
port = port + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == 10) {
|
||||
fprintf(stderr, "NETWORK: No free ports %d-%d available, aborting\n", port, port + i);
|
||||
if (NetworkFildes.IsValid() == false) {
|
||||
fprintf(stderr, "NETWORK: No free ports %d-%d available, aborting\n", port, port + 10);
|
||||
NetExit(); // machine dependent network exit
|
||||
return;
|
||||
}
|
||||
|
@ -419,10 +419,8 @@ void InitNetwork1()
|
|||
|
||||
gethostname(buf, sizeof(buf));
|
||||
DebugPrint("%s\n" _C_ buf);
|
||||
const unsigned long myHost = NetResolveHost(buf);
|
||||
const int myPort = port;
|
||||
DebugPrint("My host:port %d.%d.%d.%d:%d\n" _C_
|
||||
NIPQUAD(ntohl(myHost)) _C_ myPort);
|
||||
const std::string hostStr = CHost(buf, port).toString();
|
||||
DebugPrint("My host:port %s\n" _C_ hostStr.c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -449,10 +447,9 @@ void ExitNetwork1()
|
|||
NetworkSendPackets _C_ NetworkSendResend);
|
||||
#endif
|
||||
|
||||
NetCloseUDP(NetworkFildes);
|
||||
NetworkFildes.Close();
|
||||
NetExit(); // machine dependent setup
|
||||
|
||||
NetworkFildes = static_cast<Socket>(-1);
|
||||
NetworkInSync = 1;
|
||||
NetPlayers = 0;
|
||||
HostsCount = 0;
|
||||
|
@ -672,9 +669,8 @@ void NetworkSendSelection(CUnit **units, int count)
|
|||
const int len = CNetworkPacketHeader::Size() + CNetworkSelection::Size() * numcommands;
|
||||
|
||||
for (int i = 0; i < numteammates; ++i) {
|
||||
const unsigned long ip = Hosts[teammates[i]].Host;
|
||||
const int port = Hosts[teammates[i]].Port;
|
||||
NetSendUDP(NetworkFildes, ip, port, buf, len);
|
||||
const CHost host(Hosts[teammates[i]].Host, Hosts[teammates[i]].Port);
|
||||
NetworkFildes.Send(host, buf, len);
|
||||
}
|
||||
delete [] buf;
|
||||
}
|
||||
|
@ -743,9 +739,8 @@ void NetworkEvent()
|
|||
}
|
||||
// Read the packet.
|
||||
unsigned char buf[1024];
|
||||
unsigned long host;
|
||||
int port;
|
||||
int len = NetRecvUDP(NetworkFildes, &buf, sizeof(buf), &host, &port);
|
||||
CHost host;
|
||||
int len = NetworkFildes.Recv(&buf, sizeof(buf), &host);
|
||||
if (len < 0) {
|
||||
DebugPrint("Server/Client gone?\n");
|
||||
// just hope for an automatic recover right now..
|
||||
|
@ -759,7 +754,7 @@ void NetworkEvent()
|
|||
|
||||
// Setup messages
|
||||
if (NetConnectRunning) {
|
||||
if (NetworkParseSetupEvent(buf, len, host, port)) {
|
||||
if (NetworkParseSetupEvent(buf, len, host)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -771,10 +766,12 @@ void NetworkEvent()
|
|||
return;
|
||||
}
|
||||
|
||||
const int index = FindHostIndexBy(host, port);
|
||||
const int index = FindHostIndexBy(host);
|
||||
if (index == -1 || PlayerQuit[Hosts[index].PlyNr]) {
|
||||
DebugPrint("Not a host in play: %d.%d.%d.%d:%d\n" _C_
|
||||
NIPQUAD(ntohl(host)) _C_ ntohs(port));
|
||||
#ifdef DEBUG
|
||||
const std::string hostStr = host.toString();
|
||||
DebugPrint("Not a host in play: %s\n" _C_ hostStr.c_str());
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
const int player = Hosts[index].PlyNr;
|
||||
|
|
141
src/network/udpsocket.cpp
Normal file
141
src/network/udpsocket.cpp
Normal file
|
@ -0,0 +1,141 @@
|
|||
// _________ __ __
|
||||
// / _____// |_____________ _/ |______ ____ __ __ ______
|
||||
// \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
|
||||
// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
|
||||
// /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
|
||||
// \/ \/ \//_____/ \/
|
||||
// ______________________ ______________________
|
||||
// T H E W A R B E G I N S
|
||||
// Stratagus - A free fantasy real time strategy game engine
|
||||
//
|
||||
/**@name udpsocket.cpp - The udpsocket class. */
|
||||
//
|
||||
// (c) Copyright 2013 by Joris Dauphin
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
//@{
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Includes
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include "stratagus.h"
|
||||
|
||||
#include "network/udpsocket.h"
|
||||
#include "net_lowlevel.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
//
|
||||
// CHost
|
||||
//
|
||||
|
||||
CHost::CHost(const char *name, int port)
|
||||
{
|
||||
this->ip = NetResolveHost(name ? name : "127.0.0.1");
|
||||
this->port = htons(port);
|
||||
}
|
||||
|
||||
std::string CHost::toString() const
|
||||
{
|
||||
char buf[24]; // 127.255.255.255:65555
|
||||
sprintf(buf, "%d.%d.%d.%d:%d", NIPQUAD(ntohl(ip)), ntohs(port));
|
||||
return buf;
|
||||
}
|
||||
|
||||
bool CHost::isValid() const
|
||||
{
|
||||
return ip != 0 && port != 0;
|
||||
}
|
||||
|
||||
//
|
||||
// CUDPSocket_Impl
|
||||
//
|
||||
|
||||
class CUDPSocket_Impl
|
||||
{
|
||||
public:
|
||||
CUDPSocket_Impl() : socket((Socket)-1) {}
|
||||
~CUDPSocket_Impl() { if (IsValid()) { Close(); } }
|
||||
bool Open(const CHost &host) { socket = NetOpenUDP(host.getIp(), host.getPort()); return socket != INVALID_SOCKET; }
|
||||
void Close() { NetCloseUDP(socket); socket = ((Socket)-1); }
|
||||
void Send(const CHost &host, const void *buf, unsigned int len) { NetSendUDP(socket, host.getIp(), host.getPort(), buf, len); }
|
||||
int Recv(void *buf, int len, CHost *hostFrom)
|
||||
{
|
||||
unsigned long ip;
|
||||
int port;
|
||||
int res = NetRecvUDP(socket, buf, len, &ip, &port);
|
||||
*hostFrom = CHost(ip, port);
|
||||
return res;
|
||||
}
|
||||
void SetNonBlocking() { NetSetNonBlocking(socket); }
|
||||
int HasDataToRead(int timeout) { return NetSocketReady(socket, timeout); }
|
||||
bool IsValid() const { return socket != (Socket)-1; }
|
||||
private:
|
||||
Socket socket;
|
||||
};
|
||||
|
||||
//
|
||||
// CUDPSocket
|
||||
//
|
||||
|
||||
CUDPSocket::CUDPSocket()
|
||||
{
|
||||
m_impl = new CUDPSocket_Impl();
|
||||
}
|
||||
|
||||
CUDPSocket::~CUDPSocket()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
bool CUDPSocket::Open(const CHost &host)
|
||||
{
|
||||
return m_impl->Open(host);
|
||||
}
|
||||
|
||||
void CUDPSocket::Close()
|
||||
{
|
||||
m_impl->Close();
|
||||
}
|
||||
|
||||
void CUDPSocket::Send(const CHost &host, const void *buf, unsigned int len)
|
||||
{
|
||||
return m_impl->Send(host, buf, len);
|
||||
}
|
||||
|
||||
int CUDPSocket::Recv(void *buf, int len, CHost *hostFrom)
|
||||
{
|
||||
return m_impl->Recv(buf, len, hostFrom);
|
||||
}
|
||||
|
||||
void CUDPSocket::SetNonBlocking()
|
||||
{
|
||||
m_impl->SetNonBlocking();
|
||||
}
|
||||
|
||||
int CUDPSocket::HasDataToRead(int timeout)
|
||||
{
|
||||
return m_impl->HasDataToRead(timeout);
|
||||
}
|
||||
|
||||
bool CUDPSocket::IsValid() const
|
||||
{
|
||||
return m_impl->IsValid();
|
||||
}
|
||||
|
||||
//@}
|
|
@ -213,6 +213,7 @@ extern void beos_init(int argc, char **argv);
|
|||
|
||||
|
||||
#if defined(USE_WIN32) && ! defined(NO_STDIO_REDIRECT)
|
||||
#include "windows.h"
|
||||
#define REDIRECT_OUTPUT
|
||||
#endif
|
||||
|
||||
|
|
|
@ -943,7 +943,7 @@ void WaitEventsOneFrame()
|
|||
// Network
|
||||
int s = 0;
|
||||
if (IsNetworkGame()) {
|
||||
s = NetSocketReady(NetworkFildes, 0);
|
||||
s = NetworkFildes.HasDataToRead(0);
|
||||
if (s > 0) {
|
||||
GetCallbacks()->NetworkEvent();
|
||||
}
|
||||
|
|
|
@ -249,7 +249,7 @@ void UDPRead(Socket socket, T *obj, unsigned long *hostFrom, int *portFrom)
|
|||
class ClientUDP
|
||||
{
|
||||
public:
|
||||
explicit ClientUDP(int port) { socket = NetOpenUDP(NULL, port); }
|
||||
explicit ClientUDP(int port) { socket = NetOpenUDP(htonl(0x7F000001), htons(port)); }
|
||||
~ClientUDP() { NetCloseUDP(socket); }
|
||||
|
||||
template <typename T>
|
||||
|
|
110
tests/network/test_udpsocket.cpp
Normal file
110
tests/network/test_udpsocket.cpp
Normal file
|
@ -0,0 +1,110 @@
|
|||
// _________ __ __
|
||||
// / _____// |_____________ _/ |______ ____ __ __ ______
|
||||
// \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
|
||||
// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
|
||||
// /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
|
||||
// \/ \/ \//_____/ \/
|
||||
// ______________________ ______________________
|
||||
// T H E W A R B E G I N S
|
||||
// Stratagus - A free fantasy real time strategy game engine
|
||||
//
|
||||
/**@name test_udpsocket.cpp - The test file for net_lowlevel.cpp. */
|
||||
//
|
||||
// (c) Copyright 2013 by Joris Dauphin
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#include <UnitTest++.h>
|
||||
|
||||
#include "stratagus.h"
|
||||
|
||||
#include "network/udpsocket.h"
|
||||
|
||||
#include "net_lowlevel.h"
|
||||
|
||||
|
||||
class AutoNetwork
|
||||
{
|
||||
public:
|
||||
AutoNetwork() { NetInit(); }
|
||||
~AutoNetwork() { NetExit(); }
|
||||
};
|
||||
|
||||
TEST_FIXTURE(AutoNetwork, CHost)
|
||||
{
|
||||
const CHost host1("127.0.0.1", 6502);
|
||||
const CHost host2(htonl(0x7F000001), htons(6502));
|
||||
|
||||
CHECK(host1 == host2);
|
||||
CHECK_EQUAL(std::string("127.0.0.1:6502"), host2.toString());
|
||||
}
|
||||
|
||||
class Foo
|
||||
{
|
||||
public:
|
||||
Foo() { memset(&data, 0, sizeof(data)); }
|
||||
|
||||
void Fill()
|
||||
{
|
||||
for (int i = 0; i != 42; ++i) {
|
||||
data[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
bool Check() const
|
||||
{
|
||||
for (int i = 0; i != 42; ++i) {
|
||||
if (data[i] != i) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
char data[42];
|
||||
};
|
||||
|
||||
TEST_FIXTURE(AutoNetwork, CUDPSocket)
|
||||
{
|
||||
const CHost host1("127.0.0.1", 6501);
|
||||
const CHost host2("localhost", 6502);
|
||||
|
||||
CUDPSocket socket1;
|
||||
CUDPSocket socket2;
|
||||
|
||||
socket1.Open(host1);
|
||||
socket2.Open(host2);
|
||||
|
||||
CHECK(socket1.IsValid());
|
||||
CHECK(socket2.IsValid());
|
||||
|
||||
Foo foo2;
|
||||
foo2.Fill();
|
||||
|
||||
socket1.Send(host2, &foo2, sizeof(foo2));
|
||||
|
||||
Foo foo1;
|
||||
CHECK(foo1.Check() == false);
|
||||
|
||||
CHost from;
|
||||
CHECK(socket2.HasDataToRead(1000));
|
||||
CHECK_EQUAL(int(sizeof(foo1)), socket2.Recv(&foo1, sizeof(foo1) + 4, &from));
|
||||
|
||||
CHECK(host1 == from);
|
||||
CHECK(foo1.Check() == true);
|
||||
socket2.Close();
|
||||
CHECK(socket2.IsValid() == false);
|
||||
}
|
Loading…
Reference in a new issue