001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.runtime.net.ntp;
020
021import java.io.IOException;
022import java.net.DatagramPacket;
023import java.net.DatagramSocket;
024import java.net.InetAddress;
025
026
027
028/**
029 * NtpClient - an NTP client for Java.  This program connects to an NTP server
030 */
031public final class NtpClient    {
032        
033        
034        private String serverName;
035        
036
037        /**
038         * default constructor of the class
039         * @param serverName
040         */
041        public NtpClient(String serverName) {
042                this.serverName=serverName;
043        }
044        
045
046        
047        /**
048         * returns the offest from the ntp server to local system
049         * @return
050         * @throws IOException
051         */
052        public long getOffset() throws IOException {
053                /// Send request
054                DatagramSocket socket = new DatagramSocket();
055                socket.setSoTimeout(10000);
056                InetAddress address = InetAddress.getByName(serverName);
057                byte[] buf = new NtpMessage().toByteArray();
058                DatagramPacket packet = new DatagramPacket(buf, buf.length, address, 123);
059                
060                // Set the transmit timestamp *just* before sending the packet
061                NtpMessage.encodeTimestamp(packet.getData(), 40, (System.currentTimeMillis()/1000.0) + 2208988800.0);
062                
063                socket.send(packet);
064                
065                // Get response
066                packet = new DatagramPacket(buf, buf.length);
067                socket.receive(packet);
068                
069                // Immediately record the incoming timestamp
070                double destinationTimestamp = (System.currentTimeMillis()/1000.0) + 2208988800.0;
071                
072                
073                // Process response
074                NtpMessage msg = new NtpMessage(packet.getData());
075                //double roundTripDelay = (destinationTimestamp-msg.originateTimestamp) - (msg.receiveTimestamp-msg.transmitTimestamp);
076                double localClockOffset = ((msg.receiveTimestamp - msg.originateTimestamp) + (msg.transmitTimestamp - destinationTimestamp)) / 2;
077                
078                return (long) (localClockOffset*1000);
079        }
080        
081        /**
082         * returns the current time from ntp server in ms from 1970
083         * @return
084         * @throws IOException
085         */
086        public long currentTimeMillis() throws IOException {
087                return System.currentTimeMillis()+getOffset();
088        }
089        
090        /*
091        public static void main(String[] args) throws IOException{
092                NtpClient ntp=new NtpClient("time.nist.gov");
093                
094        }
095        public static void main(String[] args) throws IOException
096        {
097                
098                String serverName="time.nist.gov";
099                
100                
101                
102                
103                /// Send request
104                DatagramSocket socket = new DatagramSocket();
105                InetAddress address = InetAddress.getByName(serverName);
106                byte[] buf = new NtpMessage().toByteArray();
107                DatagramPacket packet = new DatagramPacket(buf, buf.length, address, 123);
108                
109                // Set the transmit timestamp *just* before sending the packet
110                // ToDo: Does this improve performance or not?
111                NtpMessage.encodeTimestamp(packet.getData(), 40, (System.currentTimeMillis()/1000.0) + 2208988800.0);
112                
113                socket.send(packet);
114                
115                // Get response
116                packet = new DatagramPacket(buf, buf.length);
117                socket.receive(packet);
118                
119                // Immediately record the incoming timestamp
120                double destinationTimestamp = (System.currentTimeMillis()/1000.0) + 2208988800.0;
121                
122                
123                // Process response
124                NtpMessage msg = new NtpMessage(packet.getData());
125                double roundTripDelay = (destinationTimestamp-msg.originateTimestamp) - (msg.receiveTimestamp-msg.transmitTimestamp);
126                double localClockOffset = ((msg.receiveTimestamp - msg.originateTimestamp) + (msg.transmitTimestamp - destinationTimestamp)) / 2;
127                
128                
129                // Display response
130                
131                socket.close();
132        }*/
133        
134        
135}