Home | nevrax.com |
|
unitime.cppGo 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 |