[BACK] Return to unitime.cpp CVS log [TXT][DIR] Up to Nevrax / code / nel / src / net

File: Nevrax / code / nel / src / net / unitime.cpp (download)
Revision 1.31, Fri Dec 28 10:17:21 2001 UTC (7 months ago) by lecroart
Branch: MAIN
CVS Tags: georges_v2, HEAD
Changes since 1.30: +12 -11 lines
ADDED: support of precompilated header on visual

/** \file unitime.cpp
 * _CUniTime class
 *
 * $Id: unitime.cpp,v 1.31 2001/12/28 10:17:21 lecroart Exp $
 */

/* Copyright, 2000 Nevrax Ltd.
 *
 * This file is part of NEVRAX NEL.
 * NEVRAX NEL 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 2, or (at your option)
 * any later version.

 * NEVRAX NEL 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 NEVRAX NEL; see the file COPYING. If not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 * MA 02111-1307, USA.
 */

#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;
}

static TCallbackItem UniTimeCallbackArray[] =
{
        { "GUT", cbGetUniversalTime }
};

void _CUniTime::syncUniTimeFromService (CCallbackNetBase::TRecordingState rec, const CInetAddress *addr)
{
        nlstop;
        /*
        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("Send the universal time %"NL_I64"d to '%s'", ut, netbase.hostAddress(from).asString().c_str());
        
        CMessage msgout (netbase.getSIDA(), "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;
}

static TCallbackItem ClientUniTimeCallbackArray[] =
{
        { "GUT", cbClientGetUniversalTime }
};


void _CUniTime::syncUniTimeFromServer (CCallbackClient *client)
{
        nlstop;
/*      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 (client->getSIDA(), "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_COMMAND (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