| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | {==============================================================================| | 
					
						
							| 
									
										
										
										
											2008-04-24 07:12:01 +00:00
										 |  |  | | Project : Delphree - Synapse                                   | 002.001.000 | | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | |==============================================================================| | 
					
						
							|  |  |  | | Content: SNTP client                                                         | | 
					
						
							|  |  |  | |==============================================================================| | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  | | The contents of this file are subject to the Mozilla Public License Ver. 1.1 | | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | | (the "License"); you may not use this file except in compliance with the     | | 
					
						
							|  |  |  | | License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ |
 | 
					
						
							|  |  |  | |                                                                              | | 
					
						
							|  |  |  | | Software distributed under the License is distributed on an "AS IS" basis,   | | 
					
						
							|  |  |  | | WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for | | 
					
						
							|  |  |  | | the specific language governing rights and limitations under the License.    | | 
					
						
							|  |  |  | |==============================================================================| | 
					
						
							|  |  |  | | The Original Code is Synapse Delphi Library.                                 | | 
					
						
							|  |  |  | |==============================================================================| | 
					
						
							|  |  |  | | The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).| | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  | | Portions created by Lukas Gebauer are Copyright (c)2000,2001.                | | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | | All Rights Reserved.                                                         | | 
					
						
							|  |  |  | |==============================================================================| | 
					
						
							|  |  |  | | Contributor(s):                                                              | | 
					
						
							| 
									
										
										
										
											2008-04-24 07:12:01 +00:00
										 |  |  | |   Patrick Chevalley                                                          | | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | |==============================================================================| | 
					
						
							|  |  |  | | History: see HISTORY.HTM from distribution package                           | | 
					
						
							| 
									
										
										
										
											2008-04-23 20:48:39 +00:00
										 |  |  | |          (Found at URL: http://www.ararat.cz/synapse/)                       |
 | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | |==============================================================================} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-24 07:00:43 +00:00
										 |  |  | {$Q-} | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  | {$WEAKPACKAGEUNIT ON} | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | unit SNTPsend; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | interface | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | uses | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |   SysUtils, | 
					
						
							| 
									
										
										
										
											2008-04-24 07:12:01 +00:00
										 |  |  |   synsock, blcksock, SynaUtil; | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  | const | 
					
						
							|  |  |  |   cNtpProtocol = 'ntp'; | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  | type | 
					
						
							|  |  |  |   PNtp = ^TNtp; | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  |   TNtp = packed record | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |     mode: Byte; | 
					
						
							|  |  |  |     stratum: Byte; | 
					
						
							|  |  |  |     poll: Byte; | 
					
						
							|  |  |  |     Precision: Byte; | 
					
						
							|  |  |  |     RootDelay: Longint; | 
					
						
							|  |  |  |     RootDisperson: Longint; | 
					
						
							|  |  |  |     RefID: Longint; | 
					
						
							|  |  |  |     Ref1: Longint; | 
					
						
							|  |  |  |     Ref2: Longint; | 
					
						
							|  |  |  |     Org1: Longint; | 
					
						
							|  |  |  |     Org2: Longint; | 
					
						
							|  |  |  |     Rcv1: Longint; | 
					
						
							|  |  |  |     Rcv2: Longint; | 
					
						
							|  |  |  |     Xmit1: Longint; | 
					
						
							|  |  |  |     Xmit2: Longint; | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  |   end; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |   TSNTPSend = class(TObject) | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  |   private | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |     FNTPReply: TNtp; | 
					
						
							|  |  |  |     FNTPTime: TDateTime; | 
					
						
							| 
									
										
										
										
											2008-04-24 07:12:01 +00:00
										 |  |  |     FNTPOffset: double; | 
					
						
							|  |  |  |     FNTPDelay: double; | 
					
						
							|  |  |  |     FMaxSyncDiff: double; | 
					
						
							|  |  |  |     FSyncTime: Boolean; | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |     FSntpHost: string; | 
					
						
							|  |  |  |     FTimeout: Integer; | 
					
						
							|  |  |  |     FSock: TUDPBlockSocket; | 
					
						
							|  |  |  |     FBuffer: string; | 
					
						
							| 
									
										
										
										
											2008-04-24 07:12:01 +00:00
										 |  |  |     FLi, FVn, Fmode : byte; | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  |   public | 
					
						
							|  |  |  |     constructor Create; | 
					
						
							|  |  |  |     destructor Destroy; override; | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |     function DecodeTs(Nsec, Nfrac: Longint): TDateTime; | 
					
						
							| 
									
										
										
										
											2008-04-24 07:12:01 +00:00
										 |  |  |     procedure EncodeTs(dt: TDateTime; var Nsec, Nfrac: Longint); | 
					
						
							|  |  |  |     function GetSNTP: Boolean; | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |     function GetNTP: Boolean; | 
					
						
							|  |  |  |     function GetBroadcastNTP: Boolean; | 
					
						
							|  |  |  |   published | 
					
						
							|  |  |  |     property NTPReply: TNtp read FNTPReply; | 
					
						
							|  |  |  |     property NTPTime: TDateTime read FNTPTime; | 
					
						
							| 
									
										
										
										
											2008-04-24 07:12:01 +00:00
										 |  |  |     property NTPOffset: Double read FNTPOffset; | 
					
						
							|  |  |  |     property NTPDelay: Double read FNTPDelay; | 
					
						
							|  |  |  |     property MaxSyncDiff: double read FMaxSyncDiff write FMaxSyncDiff; | 
					
						
							|  |  |  |     property SyncTime: Boolean read FSyncTime write FSyncTime; | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |     property SntpHost: string read FSntpHost write FSntpHost; | 
					
						
							|  |  |  |     property Timeout: Integer read FTimeout write FTimeout; | 
					
						
							| 
									
										
										
										
											2008-04-24 07:07:45 +00:00
										 |  |  |     property Sock: TUDPBlockSocket read FSock; | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |   end; | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | implementation | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  | constructor TSNTPSend.Create; | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | begin | 
					
						
							|  |  |  |   inherited Create; | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |   FSock := TUDPBlockSocket.Create; | 
					
						
							|  |  |  |   FSock.CreateSocket; | 
					
						
							|  |  |  |   FTimeout := 5000; | 
					
						
							|  |  |  |   FSntpHost := cLocalhost; | 
					
						
							| 
									
										
										
										
											2008-04-24 07:12:01 +00:00
										 |  |  |   FMaxSyncDiff := 3600; | 
					
						
							|  |  |  |   FSyncTime := False; | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | end; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  | destructor TSNTPSend.Destroy; | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | begin | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |   FSock.Free; | 
					
						
							|  |  |  |   inherited Destroy; | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | end; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  | function TSNTPSend.DecodeTs(Nsec, Nfrac: Longint): TDateTime; | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | const | 
					
						
							| 
									
										
										
										
											2008-04-24 07:12:01 +00:00
										 |  |  |   maxi = 4294967295.0; | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | var | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |   d, d1: Double; | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | begin | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |   Nsec := synsock.htonl(Nsec); | 
					
						
							|  |  |  |   Nfrac := synsock.htonl(Nfrac); | 
					
						
							|  |  |  |   d := Nsec; | 
					
						
							|  |  |  |   if d < 0 then | 
					
						
							| 
									
										
										
										
											2008-04-24 07:12:01 +00:00
										 |  |  |     d := maxi + d + 1; | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |   d1 := Nfrac; | 
					
						
							|  |  |  |   if d1 < 0 then | 
					
						
							| 
									
										
										
										
											2008-04-24 07:12:01 +00:00
										 |  |  |     d1 := maxi + d1 + 1; | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |   d1 := d1 / maxi; | 
					
						
							| 
									
										
										
										
											2008-04-24 07:12:01 +00:00
										 |  |  |   d1 := Trunc(d1 * 10000) / 10000; | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |   Result := (d + d1) / 86400; | 
					
						
							|  |  |  |   Result := Result + 2; | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | end; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-24 07:12:01 +00:00
										 |  |  | procedure TSNTPSend.EncodeTs(dt: TDateTime; var Nsec, Nfrac: Longint); | 
					
						
							|  |  |  | const | 
					
						
							|  |  |  |   maxi = 4294967295.0; | 
					
						
							|  |  |  |   maxilongint = 2147483647; | 
					
						
							|  |  |  | var | 
					
						
							|  |  |  |   d, d1: Double; | 
					
						
							|  |  |  | begin | 
					
						
							|  |  |  |   d  := (dt - 2) * 86400; | 
					
						
							|  |  |  |   d1 := frac(d); | 
					
						
							|  |  |  |   d  := trunc(d); | 
					
						
							|  |  |  |   if d>maxilongint then | 
					
						
							|  |  |  |      d := d - maxi - 1; | 
					
						
							|  |  |  |   d1 := Trunc(d1 * 10000) / 10000; | 
					
						
							|  |  |  |   d1 := d1 * maxi; | 
					
						
							|  |  |  |   if d1>maxilongint then | 
					
						
							|  |  |  |      d1 := d1 - maxi - 1; | 
					
						
							|  |  |  |   Nsec:=trunc(d); | 
					
						
							|  |  |  |   Nfrac:=trunc(d1); | 
					
						
							|  |  |  |   Nsec := synsock.htonl(Nsec); | 
					
						
							|  |  |  |   Nfrac := synsock.htonl(Nfrac); | 
					
						
							|  |  |  | end; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  | function TSNTPSend.GetBroadcastNTP: Boolean; | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | var | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |   NtpPtr: PNtp; | 
					
						
							|  |  |  |   x: Integer; | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | begin | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |   Result := False; | 
					
						
							|  |  |  |   FSock.Bind('0.0.0.0', cNtpProtocol); | 
					
						
							| 
									
										
										
										
											2008-04-24 07:12:01 +00:00
										 |  |  |   FBuffer := FSock.RecvPacket(FTimeout); | 
					
						
							|  |  |  |   if FSock.LastError = 0 then | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |   begin | 
					
						
							| 
									
										
										
										
											2008-04-24 07:12:01 +00:00
										 |  |  |     x := Length(FBuffer); | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |     if (SntpHost = '0.0.0.0') or (FSock.GetRemoteSinIP = SntpHost) then | 
					
						
							|  |  |  |       if x >= SizeOf(NTPReply) then | 
					
						
							|  |  |  |       begin | 
					
						
							|  |  |  |         NtpPtr := Pointer(FBuffer); | 
					
						
							|  |  |  |         FNTPReply := NtpPtr^; | 
					
						
							|  |  |  |         FNTPTime := DecodeTs(NTPReply.Xmit1, NTPReply.Xmit2); | 
					
						
							| 
									
										
										
										
											2008-04-24 07:12:01 +00:00
										 |  |  |         if FSyncTime and ((abs(FNTPTime - GetUTTime) * 86400) <= FMaxSyncDiff) then | 
					
						
							|  |  |  |           SetUTTime(FNTPTime); | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |         Result := True; | 
					
						
							|  |  |  |       end; | 
					
						
							|  |  |  |   end; | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | end; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-24 07:12:01 +00:00
										 |  |  | function TSNTPSend.GetSNTP: Boolean; | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | var | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |   q: TNtp; | 
					
						
							|  |  |  |   NtpPtr: PNtp; | 
					
						
							|  |  |  |   x: Integer; | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | begin | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |   Result := False; | 
					
						
							|  |  |  |   FSock.Connect(sntphost, cNtpProtocol); | 
					
						
							|  |  |  |   FillChar(q, SizeOf(q), 0); | 
					
						
							|  |  |  |   q.mode := $1B; | 
					
						
							|  |  |  |   FSock.SendBuffer(@q, SizeOf(q)); | 
					
						
							| 
									
										
										
										
											2008-04-24 07:12:01 +00:00
										 |  |  |   FBuffer := FSock.RecvPacket(FTimeout); | 
					
						
							|  |  |  |   if FSock.LastError = 0 then | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |   begin | 
					
						
							| 
									
										
										
										
											2008-04-24 07:12:01 +00:00
										 |  |  |     x := Length(FBuffer); | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |     if x >= SizeOf(NTPReply) then | 
					
						
							|  |  |  |     begin | 
					
						
							|  |  |  |       NtpPtr := Pointer(FBuffer); | 
					
						
							|  |  |  |       FNTPReply := NtpPtr^; | 
					
						
							|  |  |  |       FNTPTime := DecodeTs(NTPReply.Xmit1, NTPReply.Xmit2); | 
					
						
							| 
									
										
										
										
											2008-04-24 07:12:01 +00:00
										 |  |  |       if FSyncTime and ((abs(FNTPTime - GetUTTime) * 86400) <= FMaxSyncDiff) then | 
					
						
							|  |  |  |         SetUTTime(FNTPTime); | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |       Result := True; | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  |     end; | 
					
						
							| 
									
										
										
										
											2008-04-24 07:05:26 +00:00
										 |  |  |   end; | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | end; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-24 07:12:01 +00:00
										 |  |  | function TSNTPSend.GetNTP: Boolean; | 
					
						
							|  |  |  | var | 
					
						
							|  |  |  |   q: TNtp; | 
					
						
							|  |  |  |   NtpPtr: PNtp; | 
					
						
							|  |  |  |   x: Integer; | 
					
						
							|  |  |  |   t1, t2, t3, t4 : TDateTime; | 
					
						
							|  |  |  | begin | 
					
						
							|  |  |  |   Result := False; | 
					
						
							|  |  |  |   FSock.Connect(sntphost, cNtpProtocol); | 
					
						
							|  |  |  |   FillChar(q, SizeOf(q), 0); | 
					
						
							|  |  |  |   q.mode := $1B; | 
					
						
							|  |  |  |   t1 := GetUTTime; | 
					
						
							|  |  |  |   EncodeTs(t1,q.org1,q.org2); | 
					
						
							|  |  |  |   FSock.SendBuffer(@q, SizeOf(q)); | 
					
						
							|  |  |  |   FBuffer := FSock.RecvPacket(FTimeout); | 
					
						
							|  |  |  |   if FSock.LastError = 0 then | 
					
						
							|  |  |  |   begin | 
					
						
							|  |  |  |     x := Length(FBuffer); | 
					
						
							|  |  |  |     t4 := GetUTTime; | 
					
						
							|  |  |  |     if x >= SizeOf(NTPReply) then | 
					
						
							|  |  |  |     begin | 
					
						
							|  |  |  |       NtpPtr := Pointer(FBuffer); | 
					
						
							|  |  |  |       FNTPReply := NtpPtr^; | 
					
						
							|  |  |  |       FLi := (NTPReply.mode and $C0) shr 6; | 
					
						
							|  |  |  |       FVn := (NTPReply.mode and $38) shr 3; | 
					
						
							|  |  |  |       Fmode := NTPReply.mode and $07; | 
					
						
							|  |  |  |       if (Fli < 3) and (Fmode = 4) and | 
					
						
							|  |  |  |          (NTPReply.stratum >= 1) and (NTPReply.stratum <= 15) and | 
					
						
							|  |  |  |          (NTPReply.Rcv1 <> 0) and (NTPReply.Xmit1 <> 0) | 
					
						
							|  |  |  |          then begin | 
					
						
							|  |  |  |            t2 := DecodeTs(NTPReply.Rcv1, NTPReply.Rcv2); | 
					
						
							|  |  |  |            t3 := DecodeTs(NTPReply.Xmit1, NTPReply.Xmit2); | 
					
						
							|  |  |  |            FNTPDelay := (T4 - T1) - (T2 - T3); | 
					
						
							|  |  |  |            FNTPTime := t3 + FNTPDelay / 2; | 
					
						
							|  |  |  |            FNTPOffset := (((T2 - T1) + (T3 - T4)) / 2) * 86400; | 
					
						
							|  |  |  |            FNTPDelay := FNTPDelay * 86400; | 
					
						
							|  |  |  |            if FSyncTime and ((abs(FNTPTime - t1) * 86400) <= FMaxSyncDiff) then | 
					
						
							|  |  |  |              SetUTTime(FNTPTime); | 
					
						
							|  |  |  |            Result := True; | 
					
						
							|  |  |  |            end | 
					
						
							|  |  |  |          else result:=false; | 
					
						
							|  |  |  |     end; | 
					
						
							|  |  |  |   end; | 
					
						
							|  |  |  | end; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-23 20:36:57 +00:00
										 |  |  | end. |