    1   package org.apache.commons.net.time;
    2
    3   /* ====================================================================
    4    *
    5    * The Apache Software License, Version 1.1
    6    *
    7    * Copyright (c) 2003 The Apache Software Foundation.  All rights
    8    * reserved.
    9    *
    10   * Redistribution and use in source and binary forms, with or without
    11   * modification, are permitted provided that the following conditions
    12   * are met:
    13   *
    14   * 1. Redistributions of source code must retain the above copyright
    15   *    notice, this list of conditions and the following disclaimer.
    16   *
    17   * 2. Redistributions in binary form must reproduce the above copyright
    18   *    notice, this list of conditions and the following disclaimer in
    19   *    the documentation and/or other materials provided with the
    20   *    distribution.
    21   *
    22   * 3. The end-user documentation included with the redistribution, if
    23   *    any, must include the following acknowlegement:
    24   *       "This product includes software developed by the
    25   *        Apache Software Foundation (http://www.apache.org/)."
    26   *    Alternately, this acknowlegement may appear in the software itself,
    27   *    if and wherever such third-party acknowlegements normally appear.
    28   *
    29   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
    30   *    Foundation" must not be used to endorse or promote products derived
    31   *    from this software without prior written permission. For written
    32   *    permission, please contact apache@apache.org.
    33   *
    34   * 5. Products derived from this software may not be called "Apache"
    35   *    nor may "Apache" appear in their names without prior written
    36   *    permission of the Apache Group.
    37   *
    38   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
    39   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    40   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    41   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
    42   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    43   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    44   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
    45   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    46   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    47   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
    48   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    49   * SUCH DAMAGE.
    50   * ====================================================================
    51   *
    52   * This software consists of voluntary contributions made by many
    53   * individuals on behalf of the Apache Software Foundation.  For more
    54   * information on the Apache Software Foundation, please see
    55   * <http://www.apache.org/>.
    56   */
    57
    58  import java.io.DataOutputStream;
    59  import java.io.IOException;
    60  import java.net.ServerSocket;
    61  import java.net.Socket;
    62
    63  /***
    64   * The TimetSimpleServer class is a simple TCP implementation of a server
    65   * for the Time Protocol described in RFC 868.
    66   * <p>
    67   * Listens for TCP socket connections on the time protocol port and writes
    68   * the local time to socket outputStream as 32-bit integer of seconds
    69   * since midnight on 1 January 1900 GMT.
    70   * See <A HREF="ftp://ftp.rfc-editor.org/in-notes/rfc868.txt"> the spec </A> for
    71   * details.
    72   * <p>
    73   * Note this is for <B>debugging purposes only</B> and not meant to be run as a realiable time service.
    74   *
    75   * @author Jason Mathews, MITRE Corporation
    76   *
    77   * @version $Revision: 1.1 $ $Date: 2003/09/24 21:51:48 $
    78   */
    79  public class TimeTestSimpleServer implements Runnable
    80  {
    81
    82      /***
    83       * baseline time 1900-01-01T00:00:00 UTC
    84       */
    85      public static final long SECONDS_1900_TO_1970 = 2208988800L;
    86
    87      /**** The default time port.  It is set to 37 according to RFC 868. ***/
    88      public static final int DEFAULT_PORT = 37;
    89
    90      private ServerSocket server;
    91      private int port;
    92      private boolean running = false;
    93
    94      /***
    95       * Default constructor for TimetSimpleServer.
    96       * Initializes port to defaul time port.
    97       */
    98      public TimeTestSimpleServer()
    99      {
    100         port = DEFAULT_PORT;
    101     }
    102
    103     /***
    104      * Constructor for TimetSimpleServer given a specific port.
    105      */
    106     public TimeTestSimpleServer(int port)
    107     {
    108         this.port = port;
    109     }
    110
    111     public void connect() throws IOException
    112     {
    113         if (server == null)
    114         {
    115             server = new ServerSocket(port);
    116         }
    117     }
    118
    119     public int getPort()
    120     {
    121         return server == null ? port : server.getLocalPort();
    122     }
    123
    124     public boolean isRunning()
    125     {
    126         return running;
    127     }
    128
    129     /***
    130      * Start time service and provide time to client connections.
    131      * @throws IOException
    132      */
    133     public void start() throws IOException
    134     {
    135         if (server == null)
    136 	{
    137             connect();
    138 	}
    139 	if (!running)
    140 	{
    141 	    running = true;
    142 	    new Thread(this).start();
    143 	}
    144     }
    145
    146     public void run()
    147     {
    148         Socket socket = null;
    149         while (running)
    150         {
    151             try
    152             {
    153                 socket = server.accept();
    154                 DataOutputStream os = new DataOutputStream(socket.getOutputStream());
    155                 // add 500 ms to round off to nearest second
    156                 int time = (int) ((System.currentTimeMillis() + 500) / 1000 + SECONDS_1900_TO_1970);
    157                 os.writeInt(time);
    158                 os.flush();
    159             } catch (IOException e)
    160             {
    161             } finally
    162             {
    163                 if (socket != null)
    164                     try
    165                     {
    166                         socket.close();  // force closing of the socket
    167                     } catch (IOException e)
    168                     {
    169                         System.err.println("close socket error: " + e);
    170                     }
    171             }
    172         }
    173     }
    174
    175     /***
    176      * Close server socket.
    177      */
    178     public void stop()
    179     {
    180         running = false;
    181         if (server != null)
    182         {
    183             try
    184             {
    185                 server.close();  // force closing of the socket
    186             } catch (IOException e)
    187             {
    188                 System.err.println("close socket error: " + e);
    189             }
    190             server = null;
    191         }
    192     }
    193
    194     public static void main(String[] args)
    195     {
    196         TimeTestSimpleServer server = new TimeTestSimpleServer();
    197         try
    198         {
    199             server.start();
    200         } catch (IOException e)
    201         {
    202         }
    203     }
    204
    205 }