# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

unitime.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2000 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "stdnet.h"
00027 
00028 #include "nel/net/callback_client.h"
00029 #include "nel/net/callback_server.h"
00030 #include "nel/net/naming_client.h"
00031 #include "nel/net/message.h"
00032 
00033 #include "nel/net/unitime.h"
00034 
00035 using namespace NLMISC;
00036 using namespace std;
00037 
00038 namespace NLNET
00039 {
00040 
00041 TTime _CUniTime::_SyncUniTime = 0;
00042 TTime _CUniTime::_SyncLocalTime = 0;
00043 bool _CUniTime::_Simulate = false;
00044 
00045 bool _CUniTime::Sync = false;
00046 
00047 
00048 void _CUniTime::setUniTime (NLMISC::TTime uTime, NLMISC::TTime lTime)
00049 {
00050         nlstop;
00051 /*      if (Sync)
00052         {
00053                 TTime lt = getLocalTime ();
00054                 TTime delta = uTime - lTime + _SyncLocalTime - _SyncUniTime;
00055 
00056                 nlinfo ("_CUniTime::setUniTime(%"NL_I64"d, %"NL_I64"d): Resyncing delta %"NL_I64"dms",uTime,lTime,delta);
00057         }
00058         else
00059         {
00060                 nlinfo ("_CUniTime::setUniTime(%"NL_I64"d, %"NL_I64"d)",uTime,lTime);
00061                 Sync = true;
00062         }
00063         _SyncUniTime = uTime;
00064         _SyncLocalTime = lTime;
00065 */}
00066 
00067 void _CUniTime::setUniTime (NLMISC::TTime uTime)
00068 {
00069         nlstop;
00070 //      setUniTime (uTime, getLocalTime ());
00071 }
00072 
00073 
00074 
00075 TTime _CUniTime::getUniTime ()
00076 {
00077         nlstop;
00078         return 0;
00079 /*      if (!Sync)
00080         {
00081                 nlerror ("called getUniTime before calling syncUniTimeFromServer");
00082         }
00083         return getLocalTime () - (_SyncLocalTime - _SyncUniTime);
00084 */
00085 }
00086 
00087 
00088 const char *_CUniTime::getStringUniTime ()
00089 {
00090         nlstop;
00091         return getStringUniTime(_CUniTime::getUniTime());
00092 }
00093 
00094 
00095 const char *_CUniTime::getStringUniTime (TTime ut)
00096 {
00097         nlstop;
00098         static char str[512];
00099 
00100         uint32 ms = (uint32) (ut % 1000); // time in ms 1000ms dans 1s
00101         ut /= 1000;
00102 
00103         uint32 s = (uint32) (ut % 60); // time in seconds 60s dans 1mn
00104         ut /= 60;
00105 
00106         uint32 m = (uint32) (ut % 60); // time in minutes 60m dans 1h
00107         ut /= 60;
00108 
00109         uint32 h = (uint32) (ut % 9); // time in hours 9h dans 1j
00110         ut /= 9;
00111 
00112         uint32 day = (uint32) (ut % (8*4)); // time in days 8day dans 1month
00113         ut /= 8;
00114 
00115         uint32 week = (uint32) (ut % 4); // time in weeks 4week dans 1month
00116         ut /= 4;
00117 
00118         uint32 month = (uint32) (ut % 12); // time in months 12month dans 1year
00119         ut /= 12;
00120 
00121         uint  year =  (uint32) ut;      // time in years
00122 
00123         smprintf (str, 512, "%02d/%02d/%04d (week %d) %02d:%02d:%02d.%03d", day+1, month+1, year+1, week+1, h, m, s, ms);
00124         return str;
00125 }
00126 
00132 
00133 static bool GetUniversalTime;
00134 static uint32 GetUniversalTimeSecondsSince1970;
00135 static TTime GetUniversalTimeUniTime;
00136 
00137 
00138 static void cbGetUniversalTime (CMessage &msgin, TSockId from, CCallbackNetBase &netbase)
00139 {
00140         nlstop;
00141         // get the association between a date and unitime
00142         msgin.serial (GetUniversalTimeSecondsSince1970);
00143         msgin.serial (GetUniversalTimeUniTime);
00144         GetUniversalTime = true;
00145 }
00146 
00147 /***************************************************************/
00148 /******************* THE FOLLOWING CODE IS COMMENTED OUT *******/
00149 /***************************************************************
00150 static TCallbackItem UniTimeCallbackArray[] =
00151 {
00152         { "GUT", cbGetUniversalTime }
00153 };
00154 ***************************************************************/
00155 
00156 void _CUniTime::syncUniTimeFromService (CCallbackNetBase::TRecordingState rec, const CInetAddress *addr)
00157 {
00158         nlstop;
00159 /***************************************************************/
00160 /******************* THE FOLLOWING CODE IS COMMENTED OUT *******/
00161 /***************************************************************
00162         TTime deltaAdjust, lt;
00163         uint32 firstsecond, nextsecond;
00164         TTime before, after, delta;
00165 
00166         // create a message with type in the full text format
00167         CMessage msgout ("AUT");
00168         CCallbackClient server( rec, "TS.nmr" );
00169         server.addCallbackArray (UniTimeCallbackArray, sizeof (UniTimeCallbackArray) / sizeof (UniTimeCallbackArray[0]));
00170 
00171         if (addr == NULL)
00172         {
00173                 CNamingClient::lookupAndConnect ("TS", server);
00174         }
00175         else
00176         {
00177                 server.connect (*addr);
00178         }
00179 
00180         if (!server.connected()) goto error;
00181 
00182         server.send (msgout);
00183 
00184         // before time
00185         before = CTime::getLocalTime ();
00186 
00187         // receive the answer
00188         GetUniversalTime = false;
00189         while (!GetUniversalTime)
00190         {
00191                 if (!server.connected()) goto error;
00192                         
00193                 server.update ();
00194 
00195                 nlSleep( 0 );
00196         }
00197 
00198         // after, before and delta is not used. It's only for information purpose.
00199         after = CTime::getLocalTime ();
00200         delta = after - before;
00201 
00202         nlinfo ("_CUniTime::syncUniTimeFromService(): ping:%"NL_I64"dms, time:%ds, unitime:%"NL_I64"dms", delta, GetUniversalTimeSecondsSince1970, GetUniversalTimeUniTime);
00203 
00204 // <-- from here to the "-->" comment, the block must be executed in less than one second or an infinite loop occurs
00205 
00206         // get the second
00207         firstsecond = CTime::getSecondsSince1970 ();
00208         nextsecond = firstsecond+1;
00209         
00210         // wait the next start of the second (take 100% of CPU to be more accurate)
00211         while (nextsecond != CTime::getSecondsSince1970 ())
00212                 nlassert (CTime::getSecondsSince1970 () <= nextsecond);
00213 
00214 // -->
00215 
00216         // get the local time of the beginning of the next second
00217         lt = CTime::getLocalTime ();
00218 
00219         if ( ! _Simulate )
00220         {
00221                 if (abs((sint32)((TTime)nextsecond - (TTime)GetUniversalTimeSecondsSince1970)) > 10)
00222                 {
00223                         nlerror ("the time delta (between me and the Time Service) is too big (more than 10s), servers aren't NTP synchronized");
00224                         goto error;
00225                 }
00226                 
00227                 // compute the delta between the other side and our side number of second since 1970
00228                 deltaAdjust = ((TTime) nextsecond - (TTime) GetUniversalTimeSecondsSince1970) * 1000;
00229 
00230                 // adjust the unitime to the current localtime
00231                 GetUniversalTimeUniTime += deltaAdjust;
00232 
00233                 nlinfo ("_CUniTime::syncUniTimeFromService(): rtime:%ds, runitime:%"NL_I64"ds, rlocaltime:%"NL_I64"d, deltaAjust:%"NL_I64"dms", nextsecond, GetUniversalTimeUniTime, lt, deltaAdjust);
00234         }
00235         else
00236         {
00237                 nlinfo ("_CUniTime::syncUniTimeFromService(): runitime:%"NL_I64"ds, rlocaltime:%"NL_I64"d", GetUniversalTimeUniTime, lt);
00238         }
00239 
00240         _CUniTime::setUniTime (GetUniversalTimeUniTime, lt);
00241 
00242         server.disconnect ();
00243         return;
00244 
00245 error:
00246         nlerror ("Time Service is not found, lost or can't synchronize universal time");
00247 ***************************************************************/
00248 
00249 }
00250 
00251 
00252 
00258 
00259 // Server part
00260 
00261 static void cbServerAskUniversalTime (CMessage& msgin, TSockId from, CCallbackNetBase &netbase)
00262 {
00263         nlstop;
00264         TTime ut = _CUniTime::getUniTime ();
00265 
00266         // afficher l adresse de celui qui demande
00267         nlinfo("Send the universal time %"NL_I64"d to '%s'", ut, netbase.hostAddress(from).asString().c_str());
00268         
00269         CMessage msgout (netbase.getSIDA(), "GUT");
00270         msgout.serial (ut);
00271         netbase.send (msgout, from);
00272 }
00273 
00274 TCallbackItem ServerTimeServiceCallbackArray[] =
00275 {
00276         { "AUT", cbServerAskUniversalTime },
00277 };
00278 
00279 void _CUniTime::installServer (CCallbackServer *server)
00280 {
00281         nlstop;
00282         static bool alreadyAddedCallback = false;
00283         nlassert (server != NULL);
00284         nlassert (!alreadyAddedCallback);
00285 
00286         server->addCallbackArray (ServerTimeServiceCallbackArray, sizeof (ServerTimeServiceCallbackArray) / sizeof (ServerTimeServiceCallbackArray[0]));
00287         alreadyAddedCallback = true;
00288 }
00289 
00290 // Client part
00291 
00292 static bool GetClientUniversalTime;
00293 static TTime GetClientUniversalTimeUniTime;
00294 
00295 static void cbClientGetUniversalTime (CMessage &msgin, TSockId from, CCallbackNetBase &netbase)
00296 {
00297         nlstop;
00298         // get the association between a date and unitime
00299         msgin.serial (GetClientUniversalTimeUniTime);
00300         GetClientUniversalTime = true;
00301 }
00302 
00303 /***************************************************************/
00304 /******************* THE FOLLOWING CODE IS COMMENTED OUT *******/
00305 /***************************************************************
00306 static TCallbackItem ClientUniTimeCallbackArray[] =
00307 {
00308         { "GUT", cbClientGetUniversalTime }
00309 };
00310 ***************************************************************/
00311 
00312 
00313 void _CUniTime::syncUniTimeFromServer (CCallbackClient *client)
00314 {
00315         nlstop;
00316 /***************************************************************/
00317 /******************* THE FOLLOWING CODE IS COMMENTED OUT *******/
00318 /***************************************************************
00319 
00320         static bool alreadyAddedCallback = false;
00321         nlassert (client != NULL);
00322 
00323         if (!alreadyAddedCallback)
00324         {
00325                 client->addCallbackArray (ClientUniTimeCallbackArray, sizeof (ClientUniTimeCallbackArray) / sizeof (ClientUniTimeCallbackArray[0]));
00326                 alreadyAddedCallback = true;
00327         }
00328 
00329         sint attempt = 0;
00330         TTime bestdelta = 60000;        // 1 minute
00331 
00332         if (!client->connected ()) goto error;
00333 
00334         while (attempt < 10)
00335         {
00336                 CMessage msgout (client->getSIDA(), "AUT");
00337 
00338                 if (!client->connected()) goto error;
00339 
00340                 // send the message
00341                 client->send (msgout);
00342 
00343                 // before time
00344                 TTime before = CTime::getLocalTime ();
00345 
00346                 // receive the answer
00347                 GetClientUniversalTime = false;
00348                 while (!GetClientUniversalTime)
00349                 {
00350                         if (!client->connected()) goto error;
00351                                 
00352                         client->update ();
00353                 }
00354 
00355                 TTime after = CTime::getLocalTime (), delta = after - before;
00356 
00357                 if (delta < 10 || delta < bestdelta)
00358                 {
00359                         bestdelta = delta;
00360 
00361                         _CUniTime::setUniTime (GetClientUniversalTimeUniTime, (before+after)/2);
00362 
00363                         if (delta < 10) break;
00364                 }
00365                 attempt++;
00366         }
00367         client->disconnect ();
00368         nlinfo ("Universal time is %"NL_I64"dms with a mean error of %"NL_I64"dms", _CUniTime::getUniTime(), bestdelta/2);
00369         return;
00370 error:
00371         nlwarning ("there's no connection or lost or can't synchronize universal time");
00372 ***************************************************************/
00373 }
00374 
00375 
00376 //
00377 // Commands
00378 //
00379 /*
00380 NLMISC_COMMAND (time, "displays the universal time", "")
00381 {
00382         if(args.size() != 0) return false;
00383 
00384         if ( _CUniTime::Sync )
00385         {
00386                 log.displayNL ("CTime::getLocalTime(): %"NL_I64"dms, _CUniTime::getUniTime(): %"NL_I64"dms", CTime::getLocalTime (), _CUniTime::getUniTime ());
00387                 log.displayNL ("_CUniTime::getStringUniTime(): '%s'", _CUniTime::getStringUniTime());
00388         }
00389         else
00390         {
00391                 log.displayNL ("CTime::getLocalTime(): %"NL_I64"dms <Universal time not sync>", CTime::getLocalTime ());
00392         }
00393 
00394         return true;
00395 }
00396 */
00397 
00398 } // NLNET