1
0
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-20 12:19:10 +00:00

Initial Commit of CyanWorlds.com Engine Open Source Client/Plugin

This commit is contained in:
JWPlatt
2011-03-12 12:34:52 -05:00
commit a20a222fc2
3976 changed files with 1301355 additions and 0 deletions

View File

@ -0,0 +1,114 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
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, either version 3 of the License, or
(at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnNetCli/Intern.h
*
***/
#ifdef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNNETCLI_INTERN_H
#error "Header $/Plasma20/Sources/Plasma/NucleusLib/pnNetCli/Intern.h included more than once"
#endif
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNNETCLI_INTERN_H
namespace pnNetCli {
/*****************************************************************************
*
* Channel
*
***/
struct NetMsgChannel;
NetMsgChannel * NetMsgChannelLock (
unsigned protocol,
bool server,
unsigned * largestRecv
);
void NetMsgChannelUnlock (
NetMsgChannel * channel
);
const NetMsgInitRecv * NetMsgChannelFindRecvMessage (
NetMsgChannel * channel,
unsigned messageId
);
const NetMsgInitSend * NetMsgChannelFindSendMessage (
NetMsgChannel * channel,
unsigned messageId
);
void NetMsgChannelGetDhConstants (
const NetMsgChannel * channel,
unsigned * dh_g,
const BigNum ** dh_xa, // client: dh_x server: dh_a
const BigNum ** dh_n
);
/*****************************************************************************
*
* Encrypt
*
***/
void NetMsgCryptClientStart (
NetMsgChannel * channel,
unsigned seedBytes,
const byte seedData[],
BigNum * clientSeed,
BigNum * serverSeed
);
void NetMsgCryptServerConnect (
NetMsgChannel * channel,
unsigned seedBytes,
const byte seedData[],
BigNum * clientSeed
);
/*****************************************************************************
*
* Utils
*
***/
class CInputAccumulator {
ARRAY(byte) buffer;
byte * curr;
public:
CInputAccumulator ();
void Add (unsigned count, const byte * data);
bool Get (unsigned count, void * dest); // returns false if request cannot be fulfilled
bool Eof () const;
void Clear ();
void Compact ();
};
} using namespace pnNetCli;

View File

@ -0,0 +1,45 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
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, either version 3 of the License, or
(at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnNetCli/Pch.h
*
***/
#ifdef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNNETCLI_PCH_H
#error "Header $/Plasma20/Sources/Plasma/NucleusLib/pnNetCli/Pch.h included more than once"
#endif
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNNETCLI_PCH_H
#include "pnUtils/pnUtils.h"
#include "pnNetBase/pnNetBase.h"
#include "pnAsyncCore/pnAsyncCore.h"
#include "pnNetCli.h"
#include "Intern.h"
#include <malloc.h>

View File

@ -0,0 +1,400 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
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, either version 3 of the License, or
(at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnNetCli/pnNcChannel.cpp
*
***/
#include "Pch.h"
#pragma hdrstop
namespace pnNetCli {
/*****************************************************************************
*
* Private
*
***/
struct ChannelCrit {
~ChannelCrit ();
ChannelCrit ();
inline void Enter () { m_critsect.Enter(); }
inline void Leave () { m_critsect.Leave(); }
inline void EnterSafe () { if (m_init) m_critsect.Enter(); }
inline void LeaveSafe () { if (m_init) m_critsect.Leave(); }
private:
bool m_init;
CCritSect m_critsect;
};
struct NetMsgChannel : AtomicRef {
LINK(NetMsgChannel) m_link;
unsigned m_protocol;
bool m_server;
// Message definitions
unsigned m_largestRecv;
ARRAY(NetMsgInitSend) m_sendMsgs;
ARRAY(NetMsgInitRecv) m_recvMsgs;
// Diffie-Hellman constants
unsigned m_dh_g;
BigNum m_dh_xa; // client: dh_x server: dh_a
BigNum m_dh_n;
};
static ChannelCrit s_channelCrit;
static LIST(NetMsgChannel) * s_channels;
/****************************************************************************
*
* ChannelCrit
*
***/
//===========================================================================
ChannelCrit::ChannelCrit () {
m_init = true;
}
//===========================================================================
ChannelCrit::~ChannelCrit () {
EnterSafe();
if (s_channels) {
while (NetMsgChannel * const channel = s_channels->Head()) {
s_channels->Unlink(channel);
channel->DecRef("ChannelLink");
}
DEL(s_channels);
s_channels = nil;
}
LeaveSafe();
}
/*****************************************************************************
*
* Internal functions
*
***/
//===========================================================================
// Returns max size of message in bytes
static unsigned ValidateMsg (const NetMsg & msg) {
ASSERT(msg.fields);
ASSERT(msg.count);
unsigned maxBytes = sizeof(word); // for message id
bool prevFieldWasVarCount = false;
for (unsigned i = 0; i < msg.count; i++) {
const NetMsgField & field = msg.fields[i];
for (;;) {
bool gotVarCount = false;
bool gotVarField = false;
if (field.type == kNetMsgFieldVarCount) {
if (gotVarField || gotVarCount)
FATAL("Msg definition may only include one variable length field");
gotVarCount = true;
break;
}
if (field.type == kNetMsgFieldVarPtr || field.type == kNetMsgFieldRawVarPtr) {
if (gotVarField || gotVarCount)
FATAL("Msg definition may only include one variable length field");
if (!prevFieldWasVarCount)
FATAL("Variable length field must preceded by variable length count field");
gotVarField = true;
break;
}
if (gotVarField)
FATAL("Variable length field must be the last field in message definition");
break;
}
prevFieldWasVarCount = false;
switch (field.type) {
case kNetMsgFieldInteger:
maxBytes += sizeof(qword);
break;
case kNetMsgFieldReal:
maxBytes += sizeof(double);
break;
case kNetMsgFieldVarPtr:
case kNetMsgFieldRawVarPtr:
break;
case kNetMsgFieldVarCount:
prevFieldWasVarCount = true;
// fall-thru...
case kNetMsgFieldString:
case kNetMsgFieldPtr:
case kNetMsgFieldRawPtr:
case kNetMsgFieldData:
case kNetMsgFieldRawData:
maxBytes += msg.fields[i].count * msg.fields[i].size;
break;
DEFAULT_FATAL(field.type);
}
}
return maxBytes;
}
//===========================================================================
template<class T>
static unsigned MaxMsgId (const T msgs[], unsigned count) {
unsigned maxMsgId = 0;
for (unsigned i = 0; i < count; i++) {
ASSERT(msgs[i].msg.count);
maxMsgId = max(msgs[i].msg.messageId, maxMsgId);
}
return maxMsgId;
}
//===========================================================================
static void AddSendMsgs_CS (
NetMsgChannel * channel,
const NetMsgInitSend src[],
unsigned count
) {
channel->m_sendMsgs.GrowToFit(MaxMsgId(src, count), true);
for (const NetMsgInitSend * term = src + count; src < term; ++src) {
NetMsgInitSend * const dst = &channel->m_sendMsgs[src[0].msg.messageId];
// check to ensure that the message id isn't already used
ASSERT(!dst->msg.count);
*dst = *src;
ValidateMsg(dst->msg);
}
}
//===========================================================================
static void AddRecvMsgs_CS (
NetMsgChannel * channel,
const NetMsgInitRecv src[],
unsigned count
) {
channel->m_recvMsgs.GrowToFit(MaxMsgId(src, count), true);
for (const NetMsgInitRecv * term = src + count; src < term; ++src) {
ASSERT(src->recv);
NetMsgInitRecv * const dst = &channel->m_recvMsgs[src[0].msg.messageId];
// check to ensure that the message id isn't already used
ASSERT(!dst->msg.count);
// copy the message handler
*dst = *src;
const unsigned bytes = ValidateMsg(dst->msg);
channel->m_largestRecv = max(channel->m_largestRecv, bytes);
}
}
//===========================================================================
static NetMsgChannel * FindChannel_CS (unsigned protocol, bool server) {
if (!s_channels)
return nil;
NetMsgChannel * channel = s_channels->Head();
for (; channel; channel = s_channels->Next(channel)) {
if ((channel->m_protocol == protocol) && (channel->m_server == server))
break;
}
return channel;
}
//===========================================================================
static NetMsgChannel * FindOrCreateChannel_CS (unsigned protocol, bool server) {
if (!s_channels) {
s_channels = NEW(LIST(NetMsgChannel));
s_channels->SetLinkOffset(offsetof(NetMsgChannel, m_link));
}
// find or create protocol
NetMsgChannel * channel = FindChannel_CS(protocol, server);
if (!channel) {
channel = NEW(NetMsgChannel);
channel->m_protocol = protocol;
channel->m_server = server;
channel->m_largestRecv = 0;
s_channels->Link(channel);
channel->IncRef("ChannelLink");
}
return channel;
}
/*****************************************************************************
*
* Module functions
*
***/
//============================================================================
NetMsgChannel * NetMsgChannelLock (
unsigned protocol,
bool server,
unsigned * largestRecv
) {
NetMsgChannel * channel;
s_channelCrit.Enter();
if (nil != (channel = FindChannel_CS(protocol, server))) {
*largestRecv = channel->m_largestRecv;
channel->IncRef("ChannelLock");
}
else {
*largestRecv = 0;
}
s_channelCrit.Leave();
return channel;
}
//============================================================================
void NetMsgChannelUnlock (
NetMsgChannel * channel
) {
s_channelCrit.Enter();
{
channel->DecRef("ChannelLock");
}
s_channelCrit.Leave();
}
//============================================================================
const NetMsgInitRecv * NetMsgChannelFindRecvMessage (
NetMsgChannel * channel,
unsigned messageId
) {
// Is message in range?
if (messageId >= channel->m_recvMsgs.Count())
return nil;
// Is message defined?
const NetMsgInitRecv * recvMsg = &channel->m_recvMsgs[messageId];
if (!recvMsg->msg.count)
return nil;
// Success!
return recvMsg;
}
//============================================================================
const NetMsgInitSend * NetMsgChannelFindSendMessage (
NetMsgChannel * channel,
unsigned messageId
) {
// Is message in range?
ASSERT(messageId < channel->m_sendMsgs.Count());
// Is message defined?
const NetMsgInitSend * sendMsg = &channel->m_sendMsgs[messageId];
ASSERTMSG(sendMsg->msg.count, "NetMsg not found for send");
return sendMsg;
}
//============================================================================
void NetMsgChannelGetDhConstants (
const NetMsgChannel * channel,
unsigned * dh_g,
const BigNum ** dh_xa,
const BigNum ** dh_n
) {
*dh_g = channel->m_dh_g;
*dh_xa = &channel->m_dh_xa;
*dh_n = &channel->m_dh_n;
}
} // namespace pnNetCli
/*****************************************************************************
*
* Exports
*
***/
//===========================================================================
void NetMsgProtocolRegister (
unsigned protocol,
bool server,
const NetMsgInitSend sendMsgs[],
unsigned sendMsgCount,
const NetMsgInitRecv recvMsgs[],
unsigned recvMsgCount,
unsigned dh_g,
const BigNum & dh_xa, // client: dh_x server: dh_a
const BigNum & dh_n
) {
s_channelCrit.EnterSafe();
{
NetMsgChannel * channel = FindOrCreateChannel_CS(protocol, server);
// make sure no connections have been established on this protocol, otherwise
// we'll be modifying a live data structure; NetCli's don't lock their protocol
// to operate on it once they have linked to it!
ASSERT(channel->GetRefCount() == 1);
channel->m_dh_g = dh_g;
channel->m_dh_xa = dh_xa;
channel->m_dh_n = dh_n;
if (sendMsgCount)
AddSendMsgs_CS(channel, sendMsgs, sendMsgCount);
if (recvMsgCount)
AddRecvMsgs_CS(channel, recvMsgs, recvMsgCount);
}
s_channelCrit.LeaveSafe();
}
//===========================================================================
void NetMsgProtocolDestroy (unsigned protocol, bool server) {
s_channelCrit.EnterSafe();
if (NetMsgChannel * channel = FindChannel_CS(protocol, server)) {
s_channels->Unlink(channel);
channel->DecRef("ChannelLink");
}
s_channelCrit.LeaveSafe();
}

View File

@ -0,0 +1,135 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
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, either version 3 of the License, or
(at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnNetCli/pnNcEncrypt.cpp
*
***/
#include "Pch.h"
#pragma hdrstop
namespace pnNetCli {
/****************************************************************************
*
* Diffie-Hellman constants
*
// g and n are pregenerated and published
// (built into both client and server software)
BigNum g(4);
BigNum n; n.RandPrime(kKeyBits, &seed);
// a and x are pregenerated; a is built into server software, and x is
// built into client software
BigNum a; a.Rand(kKeyBits, &seed);
BigNum x; x.PowMod(g, a, n);
// client chooses b and y on connect, and sends y to the server
BigNum b; b.Rand(kKeyBits, &seed);
BigNum y; y.PowMod(g, b, n);
// server computes key: k = y^a mod n
BigNum ka; ka.PowMod(y, a, n);
// client computes key: k = x^b mod n
BigNum kb; kb.PowMod(x, b, n);
***/
COMPILER_ASSERT(IS_POW2(kNetDiffieHellmanKeyBits));
/*****************************************************************************
*
* Private
*
***/
//============================================================================
// TODO: Cache computed keys
static void GetCachedServerKey (
NetMsgChannel * channel,
BigNum * ka,
const BigNum & dh_y
) {
// Get diffie-hellman constants
unsigned DH_G;
const BigNum * DH_A;
const BigNum * DH_N;
NetMsgChannelGetDhConstants(channel, &DH_G, &DH_A, &DH_N);
// Compute the result
ka->PowMod(dh_y, *DH_A, *DH_N);
}
/*****************************************************************************
*
* Module functions
*
***/
//============================================================================
void NetMsgCryptClientStart (
NetMsgChannel * channel,
unsigned seedBytes,
const byte seedData[],
BigNum * clientSeed,
BigNum * serverSeed
) {
unsigned DH_G;
const BigNum * DH_X;
const BigNum * DH_N;
NetMsgChannelGetDhConstants(channel, &DH_G, &DH_X, &DH_N);
// Client chooses b and y on connect
BigNum g(DH_G);
BigNum seed(seedBytes, seedData);
BigNum b; b.Rand(kNetDiffieHellmanKeyBits, &seed);
// Client computes key: kb = x^b mod n
clientSeed->PowMod(*DH_X, b, *DH_N);
// Client sends y to server
serverSeed->PowMod(g, b, *DH_N);
}
//============================================================================
void NetMsgCryptServerConnect (
NetMsgChannel * channel,
unsigned seedBytes,
const byte seedData[],
BigNum * clientSeed
) {
// Server computes client key: ka = y^a mod n
const BigNum dh_y(seedBytes, seedData);
GetCachedServerKey(channel, clientSeed, dh_y);
}
} // namespace pnNetCli

View File

@ -0,0 +1,84 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
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, either version 3 of the License, or
(at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnNetCli/pnNcUtils.cpp
*
***/
#include "Pch.h"
#pragma hdrstop
/*****************************************************************************
*
* CInputAccumulator
*
***/
//============================================================================
CInputAccumulator::CInputAccumulator () {
buffer.Reserve(1);
curr = buffer.Ptr();
}
//============================================================================
void CInputAccumulator::Add (unsigned count, const byte * data) {
// LogMsg(kLogPerf, L"Adding %u bytes to accumulator %p", count, this);
unsigned offset = curr - buffer.Ptr();
buffer.Add(data, count);
curr = buffer.Ptr() + offset;
}
//============================================================================
bool CInputAccumulator::Get (unsigned count, void * dest) {
if (curr + count > buffer.Term())
return false;
// LogMsg(kLogPerf, L"Removing %u bytes from accumulator %p", count, this);
MemCopy(dest, curr, count);
curr += count;
return true;
}
//============================================================================
bool CInputAccumulator::Eof () const {
return curr >= buffer.Ptr() + buffer.Count();
}
//============================================================================
void CInputAccumulator::Clear () {
buffer.SetCount(0);
curr = buffer.Ptr();
}
//============================================================================
void CInputAccumulator::Compact () {
unsigned diff = curr - buffer.Ptr();
unsigned newCount = buffer.Count() - diff;
buffer.Move(0, diff, newCount);
buffer.SetCount(newCount);
curr = buffer.Ptr();
}

View File

@ -0,0 +1,423 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
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, either version 3 of the License, or
(at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnNetCli/pnNetCli.h
*
***/
#ifndef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNNETCLI_PNNETCLI_H
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNNETCLI_PNNETCLI_H
/*****************************************************************************
*
*
How to create a message sender/receiver:
1. Define message ids
enum {
kMsgMoveObject,
kMsgPlayerJoin,
kMsgPing,
kMsgPingReply,
// etc.
};
2. Define packed message structures
#include <PshPack1.h>
struct MoveObject {
dword messageId;
dword objectId;
float newPos[3];
};
struct PlayerJoin {
dword messageId;
dword playerId;
wchar name[kPlayerNameMaxLength];
byte data[kPlayerDataMaxLength];
dword vaultDataLen;
byte vaultData[1]; // vaultData[vaultDataLen], actually
// no more fields after variable-length data
};
struct Ping {
dword messageId;
dword pingTimeMs;
};
struct PingReply {
dword messageId;
dword pingTimeMs;
}
#include <PopPack.h>
3. Define message fields
static const NetMsgField kFieldObjectId = NET_MSG_FIELD_DWORD();
static const NetMsgField kFieldPlayerId = NET_MSG_FIELD_DWORD();
static const NetMsgField kFieldObjectPos = NET_MSG_FIELD_FLOAT_ARRAY(3);
static const NetMsgField kFieldPlayerName = NET_MSG_FIELD_STRING(kPlayerNameMaxLength);
static const NetMsgField kFieldPlayerData = NET_MSG_FIELD_PTR(kPlayerDataMaxLength);
static const NetMsgField kFieldVaultDataLen = NET_MSG_FIELD_VAR_COUNT(kVaultDataMaxLength);
static const NetMsgField kFieldVaultData = NET_MSG_FIELD_VAR_PTR();
static const NetMsgField kFieldPingTimeMs = NET_MSG_FIELD_DWORD();
4. Build field and message description blocks
// MoveObject
static const NetMsgField s_moveObjectFields[] = {
kFieldObjectId,
kFieldObjectPos,
};
static const NetMsg s_msgMoveObject = NET_MSG(kMsgMoveObject, s_msgMoveObjectFields);
// PlayerJoin
static const NetMsgField s_playerJoinFields[] = {
kFieldPlayerId,
kFieldPlayerName,
kFieldPlayerData,
kFieldVaultDataLen,
kFieldVaultData,
};
static const NetMsg s_playerJoin = NET_MSG(kMsgPlayerJoin, s_msgPlayerJoin);
5. Register message description blocks
// for server:
static const NetMsgInitSend s_srvSend[] = {
{ s_moveObject },
{ s_playerJoin },
{ s_ping },
};
static const NetMsgInitRecv s_srvRecv[] = {
{ s_pingReply, RecvMsgPingReply },
};
s_srvConn = NetMsgProtocolRegister(
kNetProtocolCliToGame,
true,
s_srvSend, arrsize(s_srvSend),
s_srvRecv, arrsize(s_srvRecv)
);
// for client:
static const NetMsgInitSend s_cliSend[] = {
{ s_pingReply },
};
static const NetMsgInitRecv s_cliRecv[] = {
{ s_moveObject, RecvMsgMoveObject },
{ s_playerJoin, RecvMsgPlayerJoin },
{ s_ping, RecvMsgPing },
};
s_cliConn = NetMsgProtocolRegister(
kNetProtocolCliToGame,
false,
s_cliSend, arrsize(s_cliSend),
s_cliRecv, arrsize(s_cliRecv)
);
5. Send messages
static void SendMoveObject (NetCli client, const Object * obj) {
const unsigned_ptr msgMoveObject[] = {
kMsgMoveObject,
obj->id,
3, (unsigned_ptr) &obj->pos,
};
NetCliSend(client, msgMoveObject, arrsize(msgMoveObject));
}
static void SendPlayerJoin (NetCli client, const Player * player) {
const unsigned_ptr msgPlayerJoin[] = {
kMsgPlayerJoin,
player->name,
player->data,
player->vault->Count(),
player->vault->Ptr()
};
NetCliSend(client, msgPlayerJoin, arrsize(msgPlayerJoin));
};
static void SendPing (NetCli player) {
const unsigned_ptr msgPing[] = {
kMsgPing,
TimeGetMs(),
};
NetCliSend(player, msgPing, arrsize(msgPing));
}
6. Receive messages
bool RecvMsgPing (const byte msg[], NetCli * from, void * param) {
Player * player = (Player *) param;
const Ping * ping = (const Ping *) msg;
const unsigned_ptr msgPingReply[] = {
kMsgPingReply,
ping->pingTimeMs,
};
MsgConnSend(from, msgPingReply, arrsize(msgPingReply));
}
*
***/
/*****************************************************************************
*
* Constants
*
***/
/*****************************************************************************
*
* Field definition types
*
***/
enum ENetMsgFieldType {
// Compressable fields
kNetMsgFieldInteger,
kNetMsgFieldReal,
kNetMsgFieldString, // variable length unicode string
kNetMsgFieldData, // data with length <= sizeof(dword)
kNetMsgFieldPtr, // pointer to fixed length data
kNetMsgFieldVarPtr, // pointer to variable length data
// Non-compressible fields (images, sounds, encrypted data, etc)
kNetMsgFieldRawData, // data with length <= sizeof(dword)
kNetMsgFieldRawPtr, // pointer to fixed length data
kNetMsgFieldRawVarPtr, // pointer to variable length data
kNetMsgFieldVarCount, // count for kNetMsgFieldVarPtr and kNetMsgFieldRawVarPtr
kNumNetMsgFieldTypes
};
struct NetMsgField {
ENetMsgFieldType type; // element type
unsigned count; // max number of elements
unsigned size; // element size
};
struct NetMsg {
const char * name;
unsigned messageId;
const NetMsgField * fields;
unsigned count;
};
// Opaque types
struct NetCli;
struct NetCliQueue;
/*****************************************************************************
*
* Msg and field definition macros
*
***/
#define NET_MSG(msgId, msgFields) { #msgId, msgId, msgFields, arrsize(msgFields) }
#define NET_MSG_FIELD(type, count, size) { type, count, size }
#define NET_MSG_FIELD_BYTE() NET_MSG_FIELD(kNetMsgFieldInteger, 0, sizeof(byte))
#define NET_MSG_FIELD_WORD() NET_MSG_FIELD(kNetMsgFieldInteger, 0, sizeof(word))
#define NET_MSG_FIELD_DWORD() NET_MSG_FIELD(kNetMsgFieldInteger, 0, sizeof(dword))
#define NET_MSG_FIELD_QWORD() NET_MSG_FIELD(kNetMsgFieldInteger, 0, sizeof(qword))
#define NET_MSG_FIELD_FLOAT() NET_MSG_FIELD(kNetMsgFieldReal, 0, sizeof(float))
#define NET_MSG_FIELD_DOUBLE() NET_MSG_FIELD(kNetMsgFieldReal, 0, sizeof(double))
#define NET_MSG_FIELD_BYTE_ARRAY(maxCount) NET_MSG_FIELD(kNetMsgFieldInteger, maxCount, sizeof(byte))
#define NET_MSG_FIELD_WORD_ARRAY(maxCount) NET_MSG_FIELD(kNetMsgFieldInteger, maxCount, sizeof(word))
#define NET_MSG_FIELD_DWORD_ARRAY(maxCount) NET_MSG_FIELD(kNetMsgFieldInteger, maxCount, sizeof(dword))
#define NET_MSG_FIELD_QWORD_ARRAY(maxCount) NET_MSG_FIELD(kNetMsgFieldInteger, maxCount, sizeof(qword))
#define NET_MSG_FIELD_FLOAT_ARRAY(maxCount) NET_MSG_FIELD(kNetMsgFieldReal, maxCount, sizeof(float))
#define NET_MSG_FIELD_DOUBLE_ARRAY(maxCount) NET_MSG_FIELD(kNetMsgFieldReal, maxCount, sizeof(double))
#define NET_MSG_FIELD_STRING(maxLength) NET_MSG_FIELD(kNetMsgFieldString, maxLength, sizeof(wchar))
#define NET_MSG_FIELD_DATA(maxBytes) NET_MSG_FIELD(kNetMsgFieldData, maxBytes, 1)
#define NET_MSG_FIELD_PTR(maxBytes) NET_MSG_FIELD(kNetMsgFieldPtr, maxBytes, 1)
#define NET_MSG_FIELD_RAW_DATA(maxBytes) NET_MSG_FIELD(kNetMsgFieldRawData, maxBytes, 1)
#define NET_MSG_FIELD_RAW_PTR(maxBytes) NET_MSG_FIELD(kNetMsgFieldRawPtr, maxBytes, 1)
#define NET_MSG_FIELD_VAR_PTR() NET_MSG_FIELD(kNetMsgFieldVarPtr, 0, 0)
#define NET_MSG_FIELD_RAW_VAR_PTR() NET_MSG_FIELD(kNetMsgFieldRawVarPtr, 0, 0)
#define NET_MSG_FIELD_VAR_COUNT(elemSize, maxCount) NET_MSG_FIELD(kNetMsgFieldVarCount, maxCount, elemSize)
/*****************************************************************************
*
* Message channels
*
***/
struct NetMsgInitSend {
NetMsg msg;
};
struct NetMsgInitRecv {
NetMsg msg;
bool (* recv)(const byte msg[], unsigned bytes, void * param);
};
void NetMsgProtocolRegister (
unsigned protocol, // from pnNetBase/pnNbProtocol.h
bool server,
const NetMsgInitSend sendMsgs[], // messages this program can send
unsigned sendMsgCount,
const NetMsgInitRecv recvMsgs[], // messages this program can receive
unsigned recvMsgCount,
// Diffie-Hellman keys
unsigned dh_g,
const BigNum & dh_xa, // client: dh_x server: dh_a
const BigNum & dh_n
);
void NetMsgProtocolDestroy (
unsigned protocol,
bool server
);
/*****************************************************************************
*
* NetCliQueue
*
***/
NetCliQueue * NetCliQueueCreate (
unsigned flushTimeMs
);
void NetCliQueueDestroy (
NetCliQueue * queue
);
void NetCliQueueFlush (
NetCliQueue * queue
);
float NetCliQueueQueryFlush (
NetCliQueue * queue
);
/*****************************************************************************
*
* NetCli
*
***/
typedef bool (* FNetCliEncrypt) (
ENetError error,
void * encryptParam
);
NetCli * NetCliConnectAccept (
AsyncSocket sock,
unsigned protocol,
bool unbuffered,
FNetCliEncrypt encryptFcn,
unsigned seedBytes, // optional
const byte seedData[], // optional
void * encryptParam // optional
);
#ifdef SERVER
NetCli * NetCliListenAccept (
AsyncSocket sock,
unsigned protocol,
bool unbuffered,
FNetCliEncrypt encryptFcn,
unsigned seedBytes, // optional
const byte seedData[], // optional
void * encryptParam // optional
);
#endif
#ifdef SERVER
void NetCliListenReject (
AsyncSocket sock,
ENetError error
);
#endif
void NetCliClearSocket (
NetCli * cli
);
void NetCliSetQueue (
NetCli * cli,
NetCliQueue * queue
);
void NetCliDisconnect (
NetCli * cli,
bool hardClose
);
void NetCliDelete (
NetCli * cli,
bool deleteSocket
);
void NetCliFlush (
NetCli * cli
);
void NetCliSend (
NetCli * cli,
const unsigned_ptr msg[],
unsigned count
);
bool NetCliDispatch (
NetCli * cli,
const byte buffer[],
unsigned bytes,
void * param
);
#endif // PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNNETCLI_PNNETCLI_H