2
3
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-14 14:37:41 +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,127 @@
/*==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/pnNetDiag/Intern.h
*
***/
#ifdef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNNETDIAG_INTERN_H
#error "Header $/Plasma20/Sources/Plasma/NucleusLib/pnNetDiag/Intern.h included more than once"
#endif
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNNETDIAG_INTERN_H
namespace ND {
extern HMODULE g_lib;
extern const wchar g_version[];
//============================================================================
enum {
kDiagSrvAuth,
kDiagSrvFile,
kNumDiagSrvs
};
//============================================================================
inline unsigned NetProtocolToSrv (ENetProtocol protocol) {
switch (protocol) {
case kNetProtocolCli2Auth: return kDiagSrvAuth;
case kNetProtocolCli2File: return kDiagSrvFile;
default: return kNumDiagSrvs;
}
}
//============================================================================
inline const wchar * SrvToString (unsigned srv) {
switch (srv) {
case kDiagSrvAuth: return L"Auth";
case kDiagSrvFile: return L"File";
DEFAULT_FATAL(srv);
}
}
} using namespace ND;
//============================================================================
struct NetDiag : AtomicRef {
bool destroyed;
CCritSect critsect;
wchar * hosts[kNumDiagSrvs];
unsigned nodes[kNumDiagSrvs];
~NetDiag ();
void Destroy ();
void SetHost (unsigned srv, const wchar host[]);
};
/*****************************************************************************
*
* SYS
*
***/
void SysStartup ();
void SysShutdown ();
/*****************************************************************************
*
* DNS
*
***/
void DnsStartup ();
void DnsShutdown ();
/*****************************************************************************
*
* ICMP
*
***/
void IcmpStartup ();
void IcmpShutdown ();
/*****************************************************************************
*
* TCP
*
***/
void TcpStartup ();
void TcpShutdown ();

View File

@ -0,0 +1,52 @@
/*==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/pnNetDiag/Pch.h
*
***/
#ifdef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNNETDIAG_PCH_H
#error "Header $/Plasma20/Sources/Plasma/NucleusLib/pnNetDiag/Pch.h included more than once"
#endif
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNNETDIAG_PCH_H
#include "pnUtils/pnUtils.h"
#include "pnNetBase/pnNetBase.h"
#include "pnAsyncCore/pnAsyncCore.h"
#include "pnProduct/pnProduct.h"
#include "pnNetCli/pnNetCli.h"
#define USES_PROTOCOL_CLI2AUTH
#define USES_PROTOCOL_CLI2FILE
#include "pnNetProtocol/pnNetProtocol.h"
#include "pnNetDiag.h"
#include "Intern.h"
#include <process.h>
#include <IPExport.h>
#include <IPTypes.h>

View File

@ -0,0 +1,180 @@
/*==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/pnNetDiag/pnNdDns.cpp
*
***/
#include "Pch.h"
#pragma hdrstop
/*****************************************************************************
*
* Internal types
*
***/
struct DNSParam {
NetDiag * diag;
FNetDiagDumpProc dump;
FNetDiagTestCallback callback;
void * param;
ENetProtocol protocol;
unsigned srv;
};
/*****************************************************************************
*
* Internal functions
*
***/
//============================================================================
static void LookupCallback (
void * param,
const wchar name[],
unsigned addrCount,
const NetAddress addrs[]
) {
ref(name);
DNSParam * p = (DNSParam *)param;
if (addrCount) {
unsigned node = NetAddressGetNode(addrs[0]);
p->diag->critsect.Enter();
{
p->diag->nodes[p->srv] = node;
}
p->diag->critsect.Leave();
wchar nodeStr[64];
NetAddressNodeToString(p->diag->nodes[p->srv], nodeStr, arrsize(nodeStr));
p->dump(L"[DNS] Success. %s --> %s", name, nodeStr);
p->callback(
p->diag,
p->protocol,
kNetSuccess,
p->param
);
}
else {
p->diag->critsect.Enter();
{
// if the hostname still matches, then clear the node
if (p->diag->hosts[p->srv] && 0 == StrCmp(p->diag->hosts[p->srv], name))
p->diag->nodes[p->srv] = 0;
}
p->diag->critsect.Leave();
p->dump(L"[DNS] Failed to resolve hostname %s", name);
p->callback(
p->diag,
p->protocol,
kNetErrNameLookupFailed,
p->param
);
}
p->diag->DecRef("DNS");
DEL(p);
}
/*****************************************************************************
*
* Module functions
*
***/
//============================================================================
void DnsStartup () {
}
//============================================================================
void DnsShutdown () {
}
/*****************************************************************************
*
* Exports
*
***/
//============================================================================
void NetDiagDns (
NetDiag * diag,
ENetProtocol protocol,
FNetDiagDumpProc dump,
FNetDiagTestCallback callback,
void * param
) {
ASSERT(diag);
ASSERT(dump);
ASSERT(callback);
unsigned srv = NetProtocolToSrv(protocol);
if (srv == kNumDiagSrvs) {
dump(L"[DNS] Unsupported protocol: %s", NetProtocolToString(protocol));
callback(diag, protocol, kNetErrNotSupported, param);
return;
}
wchar * host = nil;
diag->critsect.Enter();
{
if (diag->hosts[srv])
host = StrDup(diag->hosts[srv]);
}
diag->critsect.Leave();
if (!host) {
dump(L"[DNS] No hostname set for protocol: %s", NetProtocolToString(protocol));
callback(diag, protocol, kNetSuccess, param);
return;
}
diag->IncRef("DNS");
dump(L"[DNS] Looking up %s...", host);
DNSParam * dnsParam = NEWZERO(DNSParam);
dnsParam->diag = diag;
dnsParam->srv = srv;
dnsParam->protocol = protocol;
dnsParam->dump = dump;
dnsParam->callback = callback;
dnsParam->param = param;
AsyncCancelId cancelId;
AsyncAddressLookupName(
&cancelId,
LookupCallback,
host,
0,
dnsParam
);
FREE(host);
}

View File

@ -0,0 +1,246 @@
/*==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/pnNetDiag/pnNdIcmp.cpp
*
***/
#include "Pch.h"
#pragma hdrstop
/*****************************************************************************
*
* Local types
*
***/
typedef HANDLE (PASCAL FAR * FIcmpCreateFile) ();
typedef DWORD (PASCAL FAR * FIcmpSendEcho) (
HANDLE icmpHandle,
DWORD destinationAddress,
LPVOID requestData,
WORD requestSize,
PIP_OPTION_INFORMATION options,
LPVOID replyBuffer,
DWORD replySize,
DWORD timeoutMs
);
struct PingParam {
NetDiag * diag;
FNetDiagDumpProc dump;
FNetDiagTestCallback callback;
void * param;
ENetProtocol protocol;
unsigned srv;
};
/*****************************************************************************
*
* Local data
*
***/
static const unsigned kPingCount = 5;
static const unsigned kPayloadBytes = 32;
static FIcmpCreateFile IcmpCreateFile;
static FIcmpSendEcho IcmpSendEcho;
static byte s_payload[kPayloadBytes];
/*****************************************************************************
*
* Local functions
*
***/
//============================================================================
static const wchar * IpStatusToString (ULONG status) {
switch (status) {
case IP_SUCCESS: return L"IP_SUCCESS";
case IP_BUF_TOO_SMALL: return L"IP_BUF_TOO_SMALL";
case IP_DEST_NET_UNREACHABLE: return L"IP_DEST_NET_UNREACHABLE";
case IP_DEST_HOST_UNREACHABLE: return L"IP_DEST_HOST_UNREACHABLE";
case IP_DEST_PROT_UNREACHABLE: return L"IP_DEST_PROT_UNREACHABLE";
case IP_DEST_PORT_UNREACHABLE: return L"IP_DEST_PORT_UNREACHABLE";
case IP_NO_RESOURCES: return L"IP_NO_RESOURCES";
case IP_BAD_OPTION: return L"IP_BAD_OPTION";
case IP_HW_ERROR: return L"IP_HW_ERROR";
case IP_PACKET_TOO_BIG: return L"IP_PACKET_TOO_BIG";
case IP_REQ_TIMED_OUT: return L"IP_REQ_TIMED_OUT";
case IP_BAD_REQ: return L"IP_BAD_REQ";
case IP_BAD_ROUTE: return L"IP_BAD_ROUTE";
case IP_TTL_EXPIRED_TRANSIT: return L"IP_TTL_EXPIRED_TRANSIT";
case IP_TTL_EXPIRED_REASSEM: return L"IP_TTL_EXPIRED_REASSEM";
case IP_PARAM_PROBLEM: return L"IP_PARAM_PROBLEM";
case IP_SOURCE_QUENCH: return L"IP_SOURCE_QUENCH";
case IP_OPTION_TOO_BIG: return L"IP_OPTION_TOO_BIG";
case IP_BAD_DESTINATION: return L"IP_BAD_DESTINATION";
default: return L"Unknown error";
}
}
//============================================================================
static void __cdecl PingThreadProc (void * param) {
PingParam * p = (PingParam *)param;
HANDLE icmp = IcmpCreateFile();
if (!icmp) {
p->dump(L"[ICMP] Failed to create ICMP handle");
p->callback(p->diag, p->protocol, kNetErrFileNotFound, p->param);
return;
}
char addr[64];
wchar waddr[64];
NetAddressNodeToString(p->diag->nodes[p->srv], waddr, arrsize(waddr));
StrToAnsi(addr, waddr, arrsize(addr));
ENetError result = kNetSuccess;
byte reply[kPayloadBytes + sizeof(ICMP_ECHO_REPLY)];
for (unsigned i = 0; i < kPingCount; ++i) {
DWORD retval = IcmpSendEcho(
icmp,
inet_addr(addr),
s_payload,
sizeof(s_payload),
NULL,
reply,
sizeof(reply),
4000
);
PICMP_ECHO_REPLY pEchoReply = (PICMP_ECHO_REPLY)reply;
if (retval) {
p->dump(L"[ICMP] Reply from %s. ms=%u", waddr, pEchoReply->RoundTripTime);
}
else {
result = kNetErrConnectFailed;
p->dump(L"[ICMP] No reply from %s. %s", waddr, IpStatusToString(pEchoReply->Status));
}
}
p->callback(p->diag, p->protocol, result, p->param);
p->diag->DecRef("ICMP");
DEL(p);
}
/*****************************************************************************
*
* Module functions
*
***/
//============================================================================
void IcmpStartup () {
if (g_lib) {
IcmpCreateFile = (FIcmpCreateFile)GetProcAddress(g_lib, "IcmpCreateFile");
IcmpSendEcho = (FIcmpSendEcho)GetProcAddress(g_lib, "IcmpSendEcho");
}
MemSet(s_payload, (byte)((unsigned_ptr)&s_payload >> 4), arrsize(s_payload));
}
//============================================================================
void IcmpShutdown () {
IcmpCreateFile = nil;
IcmpSendEcho = nil;
}
/*****************************************************************************
*
* Exports
*
***/
//============================================================================
void NetDiagIcmp (
NetDiag * diag,
ENetProtocol protocol,
FNetDiagDumpProc dump,
FNetDiagTestCallback callback,
void * param
) {
ASSERT(diag);
ASSERT(dump);
ASSERT(callback);
if (!IcmpCreateFile || !IcmpSendEcho) {
dump(L"[ICMP] Failed to load IP helper API");
callback(diag, protocol, kNetErrNotSupported, param);
return;
}
unsigned srv = NetProtocolToSrv(protocol);
if (srv == kNumDiagSrvs) {
dump(L"[ICMP] Unsupported protocol: %s", NetProtocolToString(protocol));
callback(diag, protocol, kNetErrNotSupported, param);
return;
}
unsigned node = 0;
diag->critsect.Enter();
{
node = diag->nodes[srv];
}
diag->critsect.Leave();
if (!node) {
dump(L"[ICMP] No address set for protocol: %s", NetProtocolToString(protocol));
callback(diag, protocol, kNetSuccess, param);
return;
}
wchar nodeStr[64];
NetAddressNodeToString(node, nodeStr, arrsize(nodeStr));
dump(L"[ICMP] Pinging %s with %u bytes of data...", nodeStr, kPayloadBytes);
PingParam * pingParam = NEWZERO(PingParam);
pingParam->diag = diag;
pingParam->srv = srv;
pingParam->protocol = protocol;
pingParam->dump = dump;
pingParam->callback = callback;
pingParam->param = param;
diag->IncRef("ICMP");
_beginthread(PingThreadProc, 0, pingParam);
}

View File

@ -0,0 +1,851 @@
/*==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/pnNetDiag/pnNdTcp.cpp
*
***/
#include "Pch.h"
#pragma hdrstop
namespace AuthKey {
// This file excluded from pre-compiled header because it is auto-generated by the build server.
#include "pnNetBase/pnNbAuthKey.hpp"
} // AuthKey
/*****************************************************************************
*
* Local types
*
***/
struct AuthConn : AtomicRef {
NetDiag * diag;
FNetDiagDumpProc dump;
FNetDiagTestCallback callback;
void * param;
AsyncSocket sock;
AsyncCancelId cancelId;
NetCli * cli;
long pingsInRoute;
long pingsCompleted;
bool done;
ENetError error;
~AuthConn ();
};
struct AuthTrans : THashKeyVal<unsigned> {
HASHLINK(AuthTrans) link;
AuthConn * conn;
unsigned pingAtMs;
AuthTrans (AuthConn * conn);
~AuthTrans ();
};
struct FileConn : AtomicRef {
NetDiag * diag;
FNetDiagDumpProc dump;
FNetDiagTestCallback callback;
void * param;
AsyncSocket sock;
AsyncCancelId cancelId;
ARRAY(byte) recvBuffer;
long pingsInRoute;
long pingsCompleted;
bool done;
ENetError error;
~FileConn ();
};
struct FileTrans : THashKeyVal<unsigned> {
HASHLINK(FileTrans) link;
FileConn * conn;
unsigned pingAtMs;
FileTrans (FileConn * conn);
~FileTrans ();
};
/*****************************************************************************
*
* Local data
*
***/
static const unsigned kPingTimeoutMs = 5000;
static const unsigned kTimeoutCheckMs = 100;
static const unsigned kMaxPings = 15;
static long s_authProtocolRegistered;
static unsigned s_transId;
static CCritSect s_critsect;
static bool s_shutdown;
static byte s_payload[32];
static AsyncTimer * s_timer;
static HASHTABLEDECL(
AuthTrans,
THashKeyVal<unsigned>,
link
) s_authTrans;
static HASHTABLEDECL(
FileTrans,
THashKeyVal<unsigned>,
link
) s_fileTrans;
/*****************************************************************************
*
* Cli2Auth protocol
*
***/
//============================================================================
static bool Recv_PingReply (
const byte msg[],
unsigned bytes,
void *
) {
ref(bytes);
const Auth2Cli_PingReply & reply = *(const Auth2Cli_PingReply *)msg;
AuthTrans * trans;
s_critsect.Enter();
{
if (bytes < sizeof(Auth2Cli_PingReply)) {
// beta6 compatibility
if (nil != (trans = s_authTrans.Tail()))
s_authTrans.Unlink(trans);
}
else if (nil != (trans = s_authTrans.Find(reply.transId)))
s_authTrans.Unlink(trans);
}
s_critsect.Leave();
if (trans) {
unsigned replyAtMs = TimeGetMs();
trans->conn->dump(L"[TCP] Reply from SrvAuth. ms=%u", replyAtMs - trans->pingAtMs);
DEL(trans);
return true;
}
else {
return false;
}
}
//============================================================================
#define MSG(s) kNetMsg_Cli2Auth_##s
static NetMsgInitSend s_send[] = {
{ MSG(PingRequest) },
};
#undef MSG
#define MSG(s) kNetMsg_Auth2Cli_##s, Recv_##s
static NetMsgInitRecv s_recv[] = {
{ MSG(PingReply) },
};
#undef MSG
/*****************************************************************************
*
* Local functions
*
***/
//============================================================================
static unsigned TimerCallback (void *) {
unsigned timeMs = TimeGetMs();
s_critsect.Enter();
{
ENetError error = kNetErrTimeout;
{for (AuthTrans * next, * curr = s_authTrans.Head(); curr; curr = next) {
next = s_authTrans.Next(curr);
unsigned diff = timeMs - curr->pingAtMs;
if (diff > kPingTimeoutMs) {
if (!curr->conn->error)
curr->conn->error = error;
curr->conn->dump(L"[TCP] No reply from SrvAuth: %u, %s (ms=%u)", error, NetErrorToString(error), diff);
DEL(curr);
}
}}
{for (FileTrans * next, * curr = s_fileTrans.Head(); curr; curr = next) {
next = s_fileTrans.Next(curr);
unsigned diff = timeMs - curr->pingAtMs;
if (diff > kPingTimeoutMs) {
if (!curr->conn->error)
curr->conn->error = error;
curr->conn->dump(L"[TCP] No reply from SrvFile: %u, %s (ms=%u)", error, NetErrorToString(error), diff);
DEL(curr);
}
}}
}
s_critsect.Leave();
return kTimeoutCheckMs;
}
//============================================================================
static void AuthPingProc (void * param) {
AuthConn * conn = (AuthConn *)param;
while (!conn->done && conn->pingsCompleted < kMaxPings) {
if (!conn->pingsInRoute) {
AuthTrans * trans = NEW(AuthTrans)(conn);
trans->pingAtMs = TimeGetMs();
s_critsect.Enter();
for (;;) {
if (conn->done) {
conn->pingsCompleted = kMaxPings;
DEL(trans);
break;
}
while (++s_transId == 0)
NULL_STMT;
trans->SetValue(s_transId);
s_authTrans.Add(trans);
const unsigned_ptr msg[] = {
kCli2Auth_PingRequest,
trans->pingAtMs,
trans->GetValue(),
sizeof(s_payload),
(unsigned_ptr) s_payload,
};
NetCliSend(conn->cli, msg, arrsize(msg));
NetCliFlush(conn->cli);
break;
}
s_critsect.Leave();
}
AsyncSleep(10);
}
s_critsect.Enter();
{
conn->done = true;
AsyncSocketDisconnect(conn->sock, true);
NetCliDelete(conn->cli, false);
conn->cli = nil;
}
s_critsect.Leave();
conn->DecRef("Pinging");
}
//============================================================================
static bool AuthConnEncrypt (ENetError error, void * param) {
AuthConn * conn = (AuthConn *)param;
if (IS_NET_SUCCESS(error)) {
conn->dump(L"[TCP] SrvAuth stream encrypted.");
conn->dump(L"[TCP] Pinging SrvAuth with 32 bytes of data...");
conn->IncRef("Pinging");
_beginthread(AuthPingProc, 0, conn);
}
else {
conn->dump(L"[TCP] SrvAuth stream encryption failed: %u, %s", error, NetErrorToString(error));
}
return IS_NET_SUCCESS(error);
}
//============================================================================
static void NotifyAuthConnSocketConnect (AuthConn * conn) {
conn->dump(L"[TCP] SrvAuth socket established, encrypting stream...");
conn->TransferRef("Connecting", "Connected");
conn->cli = NetCliConnectAccept(
conn->sock,
kNetProtocolCli2Auth,
false,
AuthConnEncrypt,
0,
nil,
conn
);
}
//============================================================================
static void NotifyAuthConnSocketConnectFailed (AuthConn * conn) {
conn->error = kNetErrConnectFailed;
conn->cancelId = 0;
conn->dump(L"[TCP] SrvAuth socket connection failed %u, %s", conn->error, NetErrorToString(conn->error));
conn->DecRef("Connecting");
}
//============================================================================
static void NotifyAuthConnSocketDisconnect (AuthConn * conn) {
if (!conn->done && !conn->error)
conn->error = kNetErrDisconnected;
conn->cancelId = 0;
conn->dump(L"[TCP] SrvAuth socket closed: %u, %s", conn->error, NetErrorToString(conn->error));
HASHTABLEDECL(
AuthTrans,
THashKeyVal<unsigned>,
link
) authTrans;
s_critsect.Enter();
{
conn->done = true;
while (AuthTrans * trans = s_authTrans.Head())
authTrans.Add(trans);
}
s_critsect.Leave();
while (AuthTrans * trans = authTrans.Head()) {
conn->dump(L"[TCP] No reply from SrvAuth: %u, %s", conn->error, NetErrorToString(conn->error));
DEL(trans);
}
conn->DecRef("Connected");
}
//============================================================================
static bool NotifyAuthConnSocketRead (AuthConn * conn, AsyncNotifySocketRead * read) {
NetCliDispatch(conn->cli, read->buffer, read->bytes, conn);
read->bytesProcessed += read->bytes;
return true;
}
//============================================================================
static bool AuthSocketNotifyCallback (
AsyncSocket sock,
EAsyncNotifySocket code,
AsyncNotifySocket * notify,
void ** userState
) {
bool result = true;
AuthConn * conn;
switch (code) {
case kNotifySocketConnectSuccess:
conn = (AuthConn *) notify->param;
*userState = conn;
conn->sock = sock;
conn->cancelId = 0;
NotifyAuthConnSocketConnect(conn);
break;
case kNotifySocketConnectFailed:
conn = (AuthConn *) notify->param;
NotifyAuthConnSocketConnectFailed(conn);
break;
case kNotifySocketDisconnect:
conn = (AuthConn *) *userState;
NotifyAuthConnSocketDisconnect(conn);
break;
case kNotifySocketRead:
conn = (AuthConn *) *userState;
result = NotifyAuthConnSocketRead(conn, (AsyncNotifySocketRead *) notify);
break;
}
return result;
}
//============================================================================
static bool Recv_File2Cli_ManifestReply (FileConn * conn, const File2Cli_ManifestReply & msg) {
ref(conn);
FileTrans * trans;
s_critsect.Enter();
{
if (nil != (trans = s_fileTrans.Find(msg.transId)))
s_fileTrans.Unlink(trans);
}
s_critsect.Leave();
if (trans) {
unsigned replyAtMs = TimeGetMs();
trans->conn->dump(L"[TCP] Reply from SrvFile. ms=%u", replyAtMs - trans->pingAtMs);
DEL(trans);
return true;
}
else {
return false;
}
}
//============================================================================
static void FilePingProc (void * param) {
FileConn * conn = (FileConn *)param;
while (!conn->done && conn->pingsCompleted < kMaxPings) {
if (!conn->pingsInRoute) {
FileTrans * trans = NEW(FileTrans)(conn);
trans->pingAtMs = TimeGetMs();
s_critsect.Enter();
for (;;) {
if (conn->done) {
conn->pingsCompleted = kMaxPings;
DEL(trans);
break;
}
while (++s_transId == 0)
NULL_STMT;
trans->SetValue(s_transId);
s_fileTrans.Add(trans);
Cli2File_ManifestRequest msg;
StrCopy(msg.group, L"External", arrsize(msg.group));
msg.messageId = kCli2File_ManifestRequest;
msg.transId = trans->GetValue();
msg.messageBytes = sizeof(msg);
msg.buildId = 0;
AsyncSocketSend(conn->sock, &msg, sizeof(msg));
break;
}
s_critsect.Leave();
}
AsyncSleep(10);
}
s_critsect.Enter();
{
conn->done = true;
AsyncSocketDisconnect(conn->sock, true);
}
s_critsect.Leave();
conn->DecRef("Pinging");
}
//============================================================================
static void NotifyFileConnSocketConnect (FileConn * conn) {
conn->TransferRef("Connecting", "Connected");
conn->dump(L"[TCP] SrvFile socket established");
conn->dump(L"[TCP] Pinging SrvFile...");
conn->IncRef("Pinging");
_beginthread(FilePingProc, 0, conn);
}
//============================================================================
static void NotifyFileConnSocketConnectFailed (FileConn * conn) {
conn->error = kNetErrConnectFailed;
conn->cancelId = 0;
conn->dump(L"[TCP] SrvFile socket connection failed %u, %s", conn->error, NetErrorToString(conn->error));
conn->DecRef("Connecting");
}
//============================================================================
static void NotifyFileConnSocketDisconnect (FileConn * conn) {
if (!conn->done && !conn->error)
conn->error = kNetErrDisconnected;
conn->cancelId = 0;
conn->dump(L"[TCP] SrvFile socket closed: %u, %s", conn->error, NetErrorToString(conn->error));
HASHTABLEDECL(
FileTrans,
THashKeyVal<unsigned>,
link
) fileTrans;
s_critsect.Enter();
{
conn->done = true;
while (FileTrans * trans = s_fileTrans.Head())
fileTrans.Add(trans);
}
s_critsect.Leave();
while (FileTrans * trans = fileTrans.Head()) {
conn->dump(L"[TCP] No reply from SrvFile: %u, %s", conn->error, NetErrorToString(conn->error));
DEL(trans);
}
conn->DecRef("Connected");
}
//============================================================================
static bool NotifyFileConnSocketRead (FileConn * conn, AsyncNotifySocketRead * read) {
conn->recvBuffer.Add(read->buffer, read->bytes);
read->bytesProcessed += read->bytes;
for (;;) {
if (conn->recvBuffer.Count() < sizeof(dword))
return true;
dword msgSize = *(dword *)conn->recvBuffer.Ptr();
if (conn->recvBuffer.Count() < msgSize)
return true;
const Cli2File_MsgHeader * msg = (const Cli2File_MsgHeader *) conn->recvBuffer.Ptr();
if (msg->messageId != kFile2Cli_ManifestReply) {
conn->dump(L"[TCP] SrvFile received unexpected message. id: %u", msg->messageId);
return false;
}
if (!Recv_File2Cli_ManifestReply(conn, *(const File2Cli_ManifestReply *)msg))
return false;
conn->recvBuffer.Move(0, msgSize, conn->recvBuffer.Count() - msgSize);
conn->recvBuffer.ShrinkBy(msgSize);
}
}
//============================================================================
static bool FileSocketNotifyCallback (
AsyncSocket sock,
EAsyncNotifySocket code,
AsyncNotifySocket * notify,
void ** userState
) {
bool result = true;
FileConn * conn;
switch (code) {
case kNotifySocketConnectSuccess:
conn = (FileConn *) notify->param;
*userState = conn;
conn->sock = sock;
conn->cancelId = 0;
NotifyFileConnSocketConnect(conn);
break;
case kNotifySocketConnectFailed:
conn = (FileConn *) notify->param;
NotifyFileConnSocketConnectFailed(conn);
break;
case kNotifySocketDisconnect:
conn = (FileConn *) *userState;
NotifyFileConnSocketDisconnect(conn);
break;
case kNotifySocketRead:
conn = (FileConn *) *userState;
result = NotifyFileConnSocketRead(conn, (AsyncNotifySocketRead *) notify);
break;
}
return result;
}
//============================================================================
static void StartAuthTcpTest (
NetDiag * diag,
const NetAddress & addr,
FNetDiagDumpProc dump,
FNetDiagTestCallback callback,
void * param
) {
if (0 == AtomicSet(&s_authProtocolRegistered, 1)) {
MemSet(
s_payload,
(byte)((unsigned_ptr)&s_payload >> 4),
sizeof(s_payload)
);
NetMsgProtocolRegister(
kNetProtocolCli2Auth,
false,
s_send, arrsize(s_send),
s_recv, arrsize(s_recv),
AuthKey::kDhGValue,
BigNum(sizeof(AuthKey::kDhXData), AuthKey::kDhXData),
BigNum(sizeof(AuthKey::kDhNData), AuthKey::kDhNData)
);
}
wchar addrStr[128];
NetAddressToString(addr, addrStr, arrsize(addrStr), kNetAddressFormatAll);
dump(L"[TCP] Connecting to SrvAuth at %s...", addrStr);
diag->IncRef("TCP");
AuthConn * conn = NEWZERO(AuthConn);
conn->diag = diag;
conn->dump = dump;
conn->callback = callback;
conn->param = param;
conn->IncRef("Connecting");
Cli2Auth_Connect connect;
connect.hdr.connType = (byte) kConnTypeCliToAuth;
connect.hdr.hdrBytes = sizeof(connect.hdr);
connect.hdr.buildId = BuildId();
connect.hdr.buildType = BuildType();
connect.hdr.branchId = BranchId();
connect.hdr.productId = ProductId();
connect.data.token = kNilGuid;
connect.data.dataBytes = sizeof(connect.data);
AsyncSocketConnect(
&conn->cancelId,
addr,
AuthSocketNotifyCallback,
conn,
&connect,
sizeof(connect),
0,
0
);
}
//============================================================================
static void StartFileTcpTest (
NetDiag * diag,
const NetAddress & addr,
FNetDiagDumpProc dump,
FNetDiagTestCallback callback,
void * param
) {
wchar addrStr[128];
NetAddressToString(addr, addrStr, arrsize(addrStr), kNetAddressFormatAll);
dump(L"[TCP] Connecting to SrvFile at %s...", addrStr);
diag->IncRef("TCP");
FileConn * conn = NEWZERO(FileConn);
conn->diag = diag;
conn->dump = dump;
conn->callback = callback;
conn->param = param;
conn->IncRef("Connecting");
Cli2File_Connect connect;
connect.hdr.connType = kConnTypeCliToFile;
connect.hdr.hdrBytes = sizeof(connect.hdr);
connect.hdr.buildId = 0;
connect.hdr.buildType = BuildType();
connect.hdr.branchId = BranchId();
connect.hdr.productId = ProductId();
connect.data.buildId = BuildId();
connect.data.serverType = kSrvTypeNone;
connect.data.dataBytes = sizeof(connect.data);
AsyncSocketConnect(
&conn->cancelId,
addr,
FileSocketNotifyCallback,
conn,
&connect,
sizeof(connect),
0,
0
);
}
/*****************************************************************************
*
* AuthConn
*
***/
//============================================================================
AuthConn::~AuthConn () {
if (cli)
NetCliDelete(cli, false);
if (sock)
AsyncSocketDelete(sock);
callback(diag, kNetProtocolCli2Auth, error, param);
diag->DecRef("TCP");
}
/*****************************************************************************
*
* AuthTrans
*
***/
//============================================================================
AuthTrans::AuthTrans (AuthConn * conn)
: conn(conn)
{
conn->IncRef("Ping");
AtomicAdd(&conn->pingsInRoute, 1);
}
//============================================================================
AuthTrans::~AuthTrans () {
AtomicAdd(&conn->pingsCompleted, 1);
AtomicAdd(&conn->pingsInRoute, -1);
conn->DecRef("Ping");
}
/*****************************************************************************
*
* FileConn
*
***/
//============================================================================
FileConn::~FileConn () {
if (sock)
AsyncSocketDelete(sock);
callback(diag, kNetProtocolCli2File, error, param);
diag->DecRef("TCP");
}
/*****************************************************************************
*
* FileTrans
*
***/
//============================================================================
FileTrans::FileTrans (FileConn * conn)
: conn(conn)
{
conn->IncRef("Ping");
AtomicAdd(&conn->pingsInRoute, 1);
}
//============================================================================
FileTrans::~FileTrans () {
AtomicAdd(&conn->pingsCompleted, 1);
AtomicAdd(&conn->pingsInRoute, -1);
conn->DecRef("Ping");
}
/*****************************************************************************
*
* Module functions
*
***/
//============================================================================
void TcpStartup () {
s_shutdown = false;
AsyncTimerCreate(&s_timer, TimerCallback, 0, nil);
}
//============================================================================
void TcpShutdown () {
s_shutdown = true;
AsyncTimerDeleteCallback(s_timer, TimerCallback);
s_timer = nil;
}
/*****************************************************************************
*
* Exports
*
***/
//============================================================================
void NetDiagTcp (
NetDiag * diag,
ENetProtocol protocol,
unsigned port,
FNetDiagDumpProc dump,
FNetDiagTestCallback callback,
void * param
) {
ASSERT(diag);
ASSERT(dump);
ASSERT(callback);
unsigned srv = NetProtocolToSrv(protocol);
if (srv == kNumDiagSrvs) {
dump(L"[TCP] Unsupported protocol: %s", NetProtocolToString(protocol));
callback(diag, protocol, kNetErrNotSupported, param);
return;
}
unsigned node;
NetAddress addr;
diag->critsect.Enter();
{
node = diag->nodes[srv];
}
diag->critsect.Leave();
if (!node) {
dump(L"[TCP] No address set for protocol: %s", NetProtocolToString(protocol));
callback(diag, protocol, kNetSuccess, param);
return;
}
NetAddressFromNode(node, port, &addr);
switch (protocol) {
case kNetProtocolCli2Auth:
StartAuthTcpTest(diag, addr, dump, callback, param);
break;
case kNetProtocolCli2File:
StartFileTcpTest(diag, addr, dump, callback, param);
break;
DEFAULT_FATAL(protocol);
}
}

View File

@ -0,0 +1,151 @@
/*==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/pnNetDiag/pnNetDiag.cpp
*
***/
#include "Pch.h"
#pragma hdrstop
namespace ND {
/*****************************************************************************
*
* Local data
*
***/
/*****************************************************************************
*
* Module data
*
***/
HMODULE g_lib;
//const wchar g_version[] = L"miasma";
//const wchar g_version[] = L"ectomorph";
const wchar g_version[] = L"solvent";
} // namespace ND
/*****************************************************************************
*
* NetDiag
*
***/
//============================================================================
NetDiag::~NetDiag () {
for (unsigned srv = 0; srv < kNumDiagSrvs; ++srv)
FREE(hosts[srv]);
}
//============================================================================
void NetDiag::SetHost (unsigned srv, const wchar host[]) {
critsect.Enter();
{
FREE(hosts[srv]);
if (host)
hosts[srv] = StrDup(host);
else
hosts[srv] = nil;
nodes[srv] = 0;
}
critsect.Leave();
}
/*****************************************************************************
*
* Exports
*
***/
//============================================================================
void NetDiagInitialize () {
g_lib = LoadLibrary("Iphlpapi.dll");
SysStartup();
DnsStartup();
IcmpStartup();
TcpStartup();
}
//============================================================================
void NetDiagDestroy () {
TcpShutdown();
IcmpShutdown();
DnsShutdown();
SysShutdown();
if (g_lib) {
FreeLibrary(g_lib);
g_lib = nil;
}
}
//============================================================================
NetDiag * NetDiagCreate () {
NetDiag * diag = NEWZERO(NetDiag);
diag->IncRef("Lifetime");
return diag;
}
//============================================================================
void NetDiagDelete (NetDiag * diag) {
ASSERT(!diag->destroyed);
diag->destroyed = true;
diag->DecRef("Lifetime");
}
//============================================================================
void NetDiagSetHost (
NetDiag * diag,
ENetProtocol protocol,
const wchar host[]
) {
ASSERT(diag);
unsigned srv = NetProtocolToSrv(protocol);
if (srv == kNumDiagSrvs)
return;
diag->SetHost(srv, host);
}

View File

@ -0,0 +1,129 @@
/*==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/pnNetDiag/pnNetDiag.h
*
***/
#ifndef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNNETDIAG_PNNETDIAG_H
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNNETDIAG_PNNETDIAG_H
#define PNNETDIAG_INCLUDED
#ifdef PLNETGAMELIB_INCLUDED
#error "pnNetDiag and plNetGameLib libraries may not be included in the same project because they invalidate each other's pnNetCli settings"
#endif
/*****************************************************************************
*
* Module
*
***/
void NetDiagInitialize ();
void NetDiagDestroy ();
/*****************************************************************************
*
* NetDiag
*
***/
struct NetDiag;
NetDiag * NetDiagCreate ();
void NetDiagDelete (NetDiag * diag);
void NetDiagSetHost (
NetDiag * diag,
ENetProtocol protocol,
const wchar name[]
);
typedef void ( __cdecl * FNetDiagDumpProc)(
const wchar fmt[],
...
);
typedef void (*FNetDiagTestCallback)(
NetDiag * diag,
ENetProtocol protocol,
ENetError result,
void * param
);
//============================================================================
// Test: SYS
// Gather system information
//============================================================================
void NetDiagSys (
NetDiag * diag,
FNetDiagDumpProc dump,
FNetDiagTestCallback callback,
void * param
);
//============================================================================
// Test: DNS
// Lookup server address
//============================================================================
void NetDiagDns (
NetDiag * diag,
ENetProtocol protocol,
FNetDiagDumpProc dump,
FNetDiagTestCallback callback,
void * param
);
//============================================================================
// Test: ICMP
// Send out 5 sequential ICMP ping packets to the server
//============================================================================
void NetDiagIcmp (
NetDiag * diag,
ENetProtocol protocol,
FNetDiagDumpProc dump,
FNetDiagTestCallback callback,
void * param
);
//============================================================================
// Test: TCP
// Connect to server and measure bandwidth
//============================================================================
void NetDiagTcp (
NetDiag * diag,
ENetProtocol protocol,
unsigned port, // 0 --> use default client port
FNetDiagDumpProc dump,
FNetDiagTestCallback callback,
void * param
);
#endif // PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNNETDIAG_PNNETDIAG_H

View File

@ -0,0 +1,161 @@
/*==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/pnNetDiag/pnNetSys.cpp
*
***/
#include "Pch.h"
#pragma hdrstop
/*****************************************************************************
*
* Local types
*
***/
typedef DWORD (PASCAL FAR * FGetAdaptersInfo)(
PIP_ADAPTER_INFO pAdapterInfo,
PULONG pOutBufLen
);
/*****************************************************************************
*
* Local data
*
***/
static FGetAdaptersInfo GetAdaptersInfo;
/*****************************************************************************
*
* Module functions
*
***/
//============================================================================
void SysStartup () {
if (g_lib) {
GetAdaptersInfo = (FGetAdaptersInfo)GetProcAddress(g_lib, "GetAdaptersInfo");
}
}
//============================================================================
void SysShutdown () {
GetAdaptersInfo = nil;
}
/*****************************************************************************
*
* Exports
*
***/
//============================================================================
void NetDiagSys (
NetDiag * diag,
FNetDiagDumpProc dump,
FNetDiagTestCallback callback,
void * param
) {
ASSERT(diag);
ASSERT(dump);
ASSERT(callback);
{ // Timestamp
wchar str[256];
qword time = TimeGetTime();
TimePrettyPrint(time, arrsize(str), str);
dump(L"[SYS] Time: %s UTC", str);
}
{ // Command line
dump(L"[SYS] Cmdline: %s", AppGetCommandLine());
}
{ // Product
wchar product[128];
ProductString(product, arrsize(product));
dump(L"[SYS] Product: %s", product);
}
{ // pnNetDiag version
dump(L"[SYS] Cognomen: '%s'", g_version);
}
{ // OS
OSVERSIONINFOEX info;
info.dwOSVersionInfoSize = sizeof(info);
GetVersionEx((OSVERSIONINFO*)&info);
dump(L"[SYS] OS Version: %u.%u", info.dwMajorVersion, info.dwMinorVersion);
dump(L"[SYS] OS Patch: %u.%u (%S)", info.wServicePackMajor, info.wServicePackMinor, info.szCSDVersion);
}
{ // System
word cpuCaps;
dword cpuVendor[3];
word cpuSignature;
CpuGetInfo(&cpuCaps, cpuVendor, &cpuSignature);
SYSTEM_INFO info;
GetSystemInfo(&info);
dump(L"[SYS] CPU Count: %u", info.dwNumberOfProcessors);
dump(L"[SYS] CPU Vendor: %.*S", sizeof(cpuVendor), cpuVendor);
}
{ // Adapters
if (!GetAdaptersInfo) {
dump(L"[SYS] Failed to load IP helper API");
callback(diag, kNetProtocolNil, kNetErrNotSupported, param);
return;
}
ULONG ulOutBufLen = 0;
GetAdaptersInfo(nil, &ulOutBufLen);
PIP_ADAPTER_INFO pInfo = (PIP_ADAPTER_INFO)ALLOC(ulOutBufLen);
PIP_ADAPTER_INFO pAdapter;
if (GetAdaptersInfo(pInfo, &ulOutBufLen) == NO_ERROR) {
pAdapter = pInfo;
while (pAdapter) {
dump(L"[SYS] NIC: %S", pAdapter->Description);
pAdapter = pAdapter->Next;
}
callback(diag, kNetProtocolNil, kNetSuccess, param);
}
else {
dump(L"[SYS] Error getting adaper list");
callback(diag, kNetProtocolNil, kNetErrFileNotFound, param);
}
FREE(pInfo);
}
}