mirror of
https://port.numenaute.org/aleajactaest/khanat-opennel-code.git
synced 2024-11-19 13:46:13 +00:00
393 lines
11 KiB
C++
393 lines
11 KiB
C++
|
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
|
||
|
// Copyright (C) 2010 Winch Gate Property Limited
|
||
|
//
|
||
|
// This program is free software: you can redistribute it and/or modify
|
||
|
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||
|
//
|
||
|
// You should have received a copy of the GNU Affero General Public License
|
||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
#include "stdnet.h"
|
||
|
|
||
|
#include "nel/net/callback_client.h"
|
||
|
#include "nel/net/callback_server.h"
|
||
|
#include "nel/net/naming_client.h"
|
||
|
#include "nel/net/message.h"
|
||
|
|
||
|
#include "nel/net/unitime.h"
|
||
|
|
||
|
using namespace NLMISC;
|
||
|
using namespace std;
|
||
|
|
||
|
namespace NLNET
|
||
|
{
|
||
|
|
||
|
TTime _CUniTime::_SyncUniTime = 0;
|
||
|
TTime _CUniTime::_SyncLocalTime = 0;
|
||
|
bool _CUniTime::_Simulate = false;
|
||
|
|
||
|
bool _CUniTime::Sync = false;
|
||
|
|
||
|
|
||
|
void _CUniTime::setUniTime (NLMISC::TTime /* uTime */, NLMISC::TTime /* lTime */)
|
||
|
{
|
||
|
nlstop;
|
||
|
/* if (Sync)
|
||
|
{
|
||
|
TTime lt = getLocalTime ();
|
||
|
TTime delta = uTime - lTime + _SyncLocalTime - _SyncUniTime;
|
||
|
|
||
|
nlinfo ("_CUniTime::setUniTime(%"NL_I64"d, %"NL_I64"d): Resyncing delta %"NL_I64"dms",uTime,lTime,delta);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
nlinfo ("_CUniTime::setUniTime(%"NL_I64"d, %"NL_I64"d)",uTime,lTime);
|
||
|
Sync = true;
|
||
|
}
|
||
|
_SyncUniTime = uTime;
|
||
|
_SyncLocalTime = lTime;
|
||
|
*/}
|
||
|
|
||
|
void _CUniTime::setUniTime (NLMISC::TTime /* uTime */)
|
||
|
{
|
||
|
nlstop;
|
||
|
// setUniTime (uTime, getLocalTime ());
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
TTime _CUniTime::getUniTime ()
|
||
|
{
|
||
|
nlstop;
|
||
|
return 0;
|
||
|
/* if (!Sync)
|
||
|
{
|
||
|
nlerror ("called getUniTime before calling syncUniTimeFromServer");
|
||
|
}
|
||
|
return getLocalTime () - (_SyncLocalTime - _SyncUniTime);
|
||
|
*/
|
||
|
}
|
||
|
|
||
|
|
||
|
const char *_CUniTime::getStringUniTime ()
|
||
|
{
|
||
|
nlstop;
|
||
|
return getStringUniTime(_CUniTime::getUniTime());
|
||
|
}
|
||
|
|
||
|
|
||
|
const char *_CUniTime::getStringUniTime (TTime ut)
|
||
|
{
|
||
|
nlstop;
|
||
|
static char str[512];
|
||
|
|
||
|
uint32 ms = (uint32) (ut % 1000); // time in ms 1000ms dans 1s
|
||
|
ut /= 1000;
|
||
|
|
||
|
uint32 s = (uint32) (ut % 60); // time in seconds 60s dans 1mn
|
||
|
ut /= 60;
|
||
|
|
||
|
uint32 m = (uint32) (ut % 60); // time in minutes 60m dans 1h
|
||
|
ut /= 60;
|
||
|
|
||
|
uint32 h = (uint32) (ut % 9); // time in hours 9h dans 1j
|
||
|
ut /= 9;
|
||
|
|
||
|
uint32 day = (uint32) (ut % (8*4)); // time in days 8day dans 1month
|
||
|
ut /= 8;
|
||
|
|
||
|
uint32 week = (uint32) (ut % 4); // time in weeks 4week dans 1month
|
||
|
ut /= 4;
|
||
|
|
||
|
uint32 month = (uint32) (ut % 12); // time in months 12month dans 1year
|
||
|
ut /= 12;
|
||
|
|
||
|
uint year = (uint32) ut; // time in years
|
||
|
|
||
|
smprintf (str, 512, "%02d/%02d/%04d (week %d) %02d:%02d:%02d.%03d", day+1, month+1, year+1, week+1, h, m, s, ms);
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
/////////////// SYNCHRONISATION BETWEEN TIME SERVICE AND OTHER SERVICES ////////////////////////////
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
static bool GetUniversalTime;
|
||
|
static uint32 GetUniversalTimeSecondsSince1970;
|
||
|
static TTime GetUniversalTimeUniTime;
|
||
|
|
||
|
/*
|
||
|
static void cbGetUniversalTime (CMessage &msgin, TSockId from, CCallbackNetBase &netbase)
|
||
|
{
|
||
|
nlstop;
|
||
|
// get the association between a date and unitime
|
||
|
msgin.serial (GetUniversalTimeSecondsSince1970);
|
||
|
msgin.serial (GetUniversalTimeUniTime);
|
||
|
GetUniversalTime = true;
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
/***************************************************************/
|
||
|
/******************* THE FOLLOWING CODE IS COMMENTED OUT *******/
|
||
|
/***************************************************************
|
||
|
static TCallbackItem UniTimeCallbackArray[] =
|
||
|
{
|
||
|
{ "GUT", cbGetUniversalTime }
|
||
|
};
|
||
|
***************************************************************/
|
||
|
|
||
|
void _CUniTime::syncUniTimeFromService (CCallbackNetBase::TRecordingState /* rec */, const CInetAddress * /* addr */)
|
||
|
{
|
||
|
nlstop;
|
||
|
/***************************************************************/
|
||
|
/******************* THE FOLLOWING CODE IS COMMENTED OUT *******/
|
||
|
/***************************************************************
|
||
|
TTime deltaAdjust, lt;
|
||
|
uint32 firstsecond, nextsecond;
|
||
|
TTime before, after, delta;
|
||
|
|
||
|
// create a message with type in the full text format
|
||
|
CMessage msgout ("AUT");
|
||
|
CCallbackClient server( rec, "TS.nmr" );
|
||
|
server.addCallbackArray (UniTimeCallbackArray, sizeof (UniTimeCallbackArray) / sizeof (UniTimeCallbackArray[0]));
|
||
|
|
||
|
if (addr == NULL)
|
||
|
{
|
||
|
CNamingClient::lookupAndConnect ("TS", server);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
server.connect (*addr);
|
||
|
}
|
||
|
|
||
|
if (!server.connected()) goto error;
|
||
|
|
||
|
server.send (msgout);
|
||
|
|
||
|
// before time
|
||
|
before = CTime::getLocalTime ();
|
||
|
|
||
|
// receive the answer
|
||
|
GetUniversalTime = false;
|
||
|
while (!GetUniversalTime)
|
||
|
{
|
||
|
if (!server.connected()) goto error;
|
||
|
|
||
|
server.update ();
|
||
|
|
||
|
nlSleep( 0 );
|
||
|
}
|
||
|
|
||
|
// after, before and delta is not used. It's only for information purpose.
|
||
|
after = CTime::getLocalTime ();
|
||
|
delta = after - before;
|
||
|
|
||
|
nlinfo ("_CUniTime::syncUniTimeFromService(): ping:%"NL_I64"dms, time:%ds, unitime:%"NL_I64"dms", delta, GetUniversalTimeSecondsSince1970, GetUniversalTimeUniTime);
|
||
|
|
||
|
// <-- from here to the "-->" comment, the block must be executed in less than one second or an infinite loop occurs
|
||
|
|
||
|
// get the second
|
||
|
firstsecond = CTime::getSecondsSince1970 ();
|
||
|
nextsecond = firstsecond+1;
|
||
|
|
||
|
// wait the next start of the second (take 100% of CPU to be more accurate)
|
||
|
while (nextsecond != CTime::getSecondsSince1970 ())
|
||
|
nlassert (CTime::getSecondsSince1970 () <= nextsecond);
|
||
|
|
||
|
// -->
|
||
|
|
||
|
// get the local time of the beginning of the next second
|
||
|
lt = CTime::getLocalTime ();
|
||
|
|
||
|
if ( ! _Simulate )
|
||
|
{
|
||
|
if (abs((sint32)((TTime)nextsecond - (TTime)GetUniversalTimeSecondsSince1970)) > 10)
|
||
|
{
|
||
|
nlerror ("the time delta (between me and the Time Service) is too big (more than 10s), servers aren't NTP synchronized");
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
// compute the delta between the other side and our side number of second since 1970
|
||
|
deltaAdjust = ((TTime) nextsecond - (TTime) GetUniversalTimeSecondsSince1970) * 1000;
|
||
|
|
||
|
// adjust the unitime to the current localtime
|
||
|
GetUniversalTimeUniTime += deltaAdjust;
|
||
|
|
||
|
nlinfo ("_CUniTime::syncUniTimeFromService(): rtime:%ds, runitime:%"NL_I64"ds, rlocaltime:%"NL_I64"d, deltaAjust:%"NL_I64"dms", nextsecond, GetUniversalTimeUniTime, lt, deltaAdjust);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
nlinfo ("_CUniTime::syncUniTimeFromService(): runitime:%"NL_I64"ds, rlocaltime:%"NL_I64"d", GetUniversalTimeUniTime, lt);
|
||
|
}
|
||
|
|
||
|
_CUniTime::setUniTime (GetUniversalTimeUniTime, lt);
|
||
|
|
||
|
server.disconnect ();
|
||
|
return;
|
||
|
|
||
|
error:
|
||
|
nlerror ("Time Service is not found, lost or can't synchronize universal time");
|
||
|
***************************************************************/
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
/////////////// SYNCHRONISATION BETWEEN CLIENT AND SHARD ///////////////////////////////////////////
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
// Server part
|
||
|
|
||
|
static void cbServerAskUniversalTime (CMessage& /* msgin */, TSockId from, CCallbackNetBase &netbase)
|
||
|
{
|
||
|
nlstop;
|
||
|
TTime ut = _CUniTime::getUniTime ();
|
||
|
|
||
|
// afficher l adresse de celui qui demande
|
||
|
nlinfo("UT: Send the universal time %"NL_I64"d to '%s'", ut, netbase.hostAddress(from).asString().c_str());
|
||
|
|
||
|
CMessage msgout ("GUT");
|
||
|
msgout.serial (ut);
|
||
|
netbase.send (msgout, from);
|
||
|
}
|
||
|
|
||
|
TCallbackItem ServerTimeServiceCallbackArray[] =
|
||
|
{
|
||
|
{ "AUT", cbServerAskUniversalTime },
|
||
|
};
|
||
|
|
||
|
void _CUniTime::installServer (CCallbackServer *server)
|
||
|
{
|
||
|
nlstop;
|
||
|
static bool alreadyAddedCallback = false;
|
||
|
nlassert (server != NULL);
|
||
|
nlassert (!alreadyAddedCallback);
|
||
|
|
||
|
server->addCallbackArray (ServerTimeServiceCallbackArray, sizeof (ServerTimeServiceCallbackArray) / sizeof (ServerTimeServiceCallbackArray[0]));
|
||
|
alreadyAddedCallback = true;
|
||
|
}
|
||
|
|
||
|
// Client part
|
||
|
|
||
|
static bool GetClientUniversalTime;
|
||
|
static TTime GetClientUniversalTimeUniTime;
|
||
|
|
||
|
/*
|
||
|
static void cbClientGetUniversalTime (CMessage &msgin, TSockId from, CCallbackNetBase &netbase)
|
||
|
{
|
||
|
nlstop;
|
||
|
// get the association between a date and unitime
|
||
|
msgin.serial (GetClientUniversalTimeUniTime);
|
||
|
GetClientUniversalTime = true;
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
/***************************************************************/
|
||
|
/******************* THE FOLLOWING CODE IS COMMENTED OUT *******/
|
||
|
/***************************************************************
|
||
|
static TCallbackItem ClientUniTimeCallbackArray[] =
|
||
|
{
|
||
|
{ "GUT", cbClientGetUniversalTime }
|
||
|
};
|
||
|
***************************************************************/
|
||
|
|
||
|
|
||
|
void _CUniTime::syncUniTimeFromServer (CCallbackClient * /* client */)
|
||
|
{
|
||
|
nlstop;
|
||
|
/***************************************************************/
|
||
|
/******************* THE FOLLOWING CODE IS COMMENTED OUT *******/
|
||
|
/***************************************************************
|
||
|
|
||
|
static bool alreadyAddedCallback = false;
|
||
|
nlassert (client != NULL);
|
||
|
|
||
|
if (!alreadyAddedCallback)
|
||
|
{
|
||
|
client->addCallbackArray (ClientUniTimeCallbackArray, sizeof (ClientUniTimeCallbackArray) / sizeof (ClientUniTimeCallbackArray[0]));
|
||
|
alreadyAddedCallback = true;
|
||
|
}
|
||
|
|
||
|
sint attempt = 0;
|
||
|
TTime bestdelta = 60000; // 1 minute
|
||
|
|
||
|
if (!client->connected ()) goto error;
|
||
|
|
||
|
while (attempt < 10)
|
||
|
{
|
||
|
CMessage msgout ("AUT");
|
||
|
|
||
|
if (!client->connected()) goto error;
|
||
|
|
||
|
// send the message
|
||
|
client->send (msgout);
|
||
|
|
||
|
// before time
|
||
|
TTime before = CTime::getLocalTime ();
|
||
|
|
||
|
// receive the answer
|
||
|
GetClientUniversalTime = false;
|
||
|
while (!GetClientUniversalTime)
|
||
|
{
|
||
|
if (!client->connected()) goto error;
|
||
|
|
||
|
client->update ();
|
||
|
}
|
||
|
|
||
|
TTime after = CTime::getLocalTime (), delta = after - before;
|
||
|
|
||
|
if (delta < 10 || delta < bestdelta)
|
||
|
{
|
||
|
bestdelta = delta;
|
||
|
|
||
|
_CUniTime::setUniTime (GetClientUniversalTimeUniTime, (before+after)/2);
|
||
|
|
||
|
if (delta < 10) break;
|
||
|
}
|
||
|
attempt++;
|
||
|
}
|
||
|
client->disconnect ();
|
||
|
nlinfo ("Universal time is %"NL_I64"dms with a mean error of %"NL_I64"dms", _CUniTime::getUniTime(), bestdelta/2);
|
||
|
return;
|
||
|
error:
|
||
|
nlwarning ("there's no connection or lost or can't synchronize universal time");
|
||
|
***************************************************************/
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Commands
|
||
|
//
|
||
|
/*
|
||
|
NLMISC_CATEGORISED_COMMAND(nel, time, "displays the universal time", "")
|
||
|
{
|
||
|
if(args.size() != 0) return false;
|
||
|
|
||
|
if ( _CUniTime::Sync )
|
||
|
{
|
||
|
log.displayNL ("CTime::getLocalTime(): %"NL_I64"dms, _CUniTime::getUniTime(): %"NL_I64"dms", CTime::getLocalTime (), _CUniTime::getUniTime ());
|
||
|
log.displayNL ("_CUniTime::getStringUniTime(): '%s'", _CUniTime::getStringUniTime());
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
log.displayNL ("CTime::getLocalTime(): %"NL_I64"dms <Universal time not sync>", CTime::getLocalTime ());
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
} // NLNET
|