001    package org.apache.commons.net.ntp;
002    /*
003     * Copyright 2001-2005 The Apache Software Foundation
004     *
005     * Licensed under the Apache License, Version 2.0 (the "License");
006     * you may not use this file except in compliance with the License.
007     * You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    import java.io.IOException;
019    import java.net.DatagramPacket;
020    import java.net.InetAddress;
021    import org.apache.commons.net.DatagramSocketClient;
022    
023    /***
024     * The NTPUDPClient class is a UDP implementation of a client for the
025     * Network Time Protocol (NTP) described in RFC 1305 as well as the
026     * Simple Network Time Protocol (SNTP) in RFC-2030. To use the class,
027     * merely open a local datagram socket with <a href="#open"> open </a>
028     * and call <a href="#getTime"> getTime </a> to retrieve the time. Then call
029     * <a href="org.apache.commons.net.DatagramSocketClient.html#close"> close </a>
030     * to close the connection properly.
031     * Successive calls to <a href="#getTime"> getTime </a> are permitted
032     * without re-establishing a connection.  That is because UDP is a
033     * connectionless protocol and the Network Time Protocol is stateless.
034     *
035     * @author Jason Mathews, MITRE Corp
036     * @version $Revision: 165675 $ $Date: 2005-05-02 21:09:55 +0100 (Mon, 02 May 2005) $
037     ***/
038    
039    public final class NTPUDPClient extends DatagramSocketClient
040    {
041        /*** The default NTP port.  It is set to 123 according to RFC 1305. ***/
042        public static final int DEFAULT_PORT = 123;
043    
044        private int _version = NtpV3Packet.VERSION_3;
045    
046        /***
047         * Retrieves the time information from the specified server and port and
048         * returns it. The time is the number of miliiseconds since
049         * 00:00 (midnight) 1 January 1900 UTC, as specified by RFC 1305.
050         * This method reads the raw NTP packet and constructs a <i>TimeInfo</i>
051         * object that allows access to all the fields of the NTP message header.
052         * <p>
053         * @param host The address of the server.
054         * @param port The port of the service.
055         * @return The time value retrieved from the server.
056         * @exception IOException If an error occurs while retrieving the time.
057         ***/
058        public TimeInfo getTime(InetAddress host, int port) throws IOException
059        {
060            // if not connected then open to next available UDP port
061            if (!isOpen())
062            {
063                open();
064            }
065    
066            NtpV3Packet message = new NtpV3Impl();
067            message.setMode(NtpV3Packet.MODE_CLIENT);
068            message.setVersion(_version);
069            DatagramPacket sendPacket = message.getDatagramPacket();
070            sendPacket.setAddress(host);
071            sendPacket.setPort(port);
072    
073            NtpV3Packet recMessage = new NtpV3Impl();
074            DatagramPacket receivePacket = recMessage.getDatagramPacket();
075    
076            /*
077             * Must minimize the time between getting the current time,
078             * timestamping the packet, and sending it out which
079             * introduces an error in the delay time.
080             * No extraneous logging and initializations here !!!
081             */
082            TimeStamp now = TimeStamp.getCurrentTime();
083    
084            // Note that if you do not set the transmit time field then originating time
085            // in server response is all 0's which is "Thu Feb 07 01:28:16 EST 2036".
086            message.setTransmitTime(now);
087    
088            _socket_.send(sendPacket);
089            _socket_.receive(receivePacket);
090    
091            long returnTime = System.currentTimeMillis();
092            // create TimeInfo message container but don't pre-compute the details yet
093            TimeInfo info = new TimeInfo(recMessage, returnTime, false);
094    
095            return info;
096        }
097    
098        /***
099         * Retrieves the time information from the specified server on the
100         * default NTP port and returns it. The time is the number of miliiseconds
101         * since 00:00 (midnight) 1 January 1900 UTC, as specified by RFC 1305.
102         * This method reads the raw NTP packet and constructs a <i>TimeInfo</i>
103         * object that allows access to all the fields of the NTP message header.
104         * <p>
105         * @param host The address of the server.
106         * @return The time value retrieved from the server.
107         * @exception IOException If an error occurs while retrieving the time.
108         ***/
109        public TimeInfo getTime(InetAddress host) throws IOException
110        {
111            return getTime(host, NtpV3Packet.NTP_PORT);
112        }
113    
114        /***
115         * Returns the NTP protocol version number that client sets on request packet
116         * that is sent to remote host (e.g. 3=NTP v3, 4=NTP v4, etc.)
117         *
118         * @return  the NTP protocol version number that client sets on request packet.
119         * @see #setVersion(int)
120         ***/
121        public int getVersion()
122        {
123            return _version;
124        }
125    
126        /***
127         * Sets the NTP protocol version number that client sets on request packet
128         * communicate with remote host.
129         *
130         * @param version the NTP protocol version number
131         ***/
132        public void setVersion(int version)
133        {
134            _version = version;
135        }
136    
137    }