1   package org.apache.commons.net.time;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one or more
5    * contributor license agreements.  See the NOTICE file distributed with
6    * this work for additional information regarding copyright ownership.
7    * The ASF licenses this file to You under the Apache License, Version 2.0
8    * (the "License"); you may not use this file except in compliance with
9    * the License.  You may obtain a copy of the License at
10   *
11   *      http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  
20  import java.io.DataOutputStream;
21  import java.io.IOException;
22  import java.net.ServerSocket;
23  import java.net.Socket;
24  
25  /**
26   * The TimetSimpleServer class is a simple TCP implementation of a server
27   * for the Time Protocol described in RFC 868.
28   * <p>
29   * Listens for TCP socket connections on the time protocol port and writes
30   * the local time to socket outputStream as 32-bit integer of seconds 
31   * since midnight on 1 January 1900 GMT.
32   * See <A HREF="ftp://ftp.rfc-editor.org/in-notes/rfc868.txt"> the spec </A> for
33   * details.
34   * <p>
35   * Note this is for <B>debugging purposes only</B> and not meant to be run as a realiable time service.
36   *
37   * @author Jason Mathews, MITRE Corporation
38   *
39   * @version $Revision: 658518 $ $Date: 2008-05-21 02:04:30 +0100 (Wed, 21 May 2008) $
40   */
41  public class TimeTestSimpleServer implements Runnable
42  {
43  
44      /**
45       * baseline time 1900-01-01T00:00:00 UTC
46       */
47      public static final long SECONDS_1900_TO_1970 = 2208988800L;
48  
49      /*** The default time port.  It is set to 37 according to RFC 868. ***/
50      public static final int DEFAULT_PORT = 37;
51  
52      private ServerSocket server;
53      private int port;
54      private boolean running = false;
55  
56      /**
57       * Default constructor for TimetSimpleServer.
58       * Initializes port to defaul time port.
59       */
60      public TimeTestSimpleServer()
61      {
62          port = DEFAULT_PORT;
63      }
64  
65      /**
66       * Constructor for TimetSimpleServer given a specific port.
67       */
68      public TimeTestSimpleServer(int port)
69      {
70          this.port = port;
71      }
72  
73      public void connect() throws IOException
74      {
75          if (server == null)
76          {
77              server = new ServerSocket(port);
78          }
79      }
80  
81      public int getPort()
82      {
83          return server == null ? port : server.getLocalPort();
84      }
85  
86      public boolean isRunning()
87      {
88          return running;
89      }
90  
91      /**
92       * Start time service and provide time to client connections.
93       * @throws IOException
94       */
95      public void start() throws IOException
96      {
97          if (server == null)
98      {
99              connect();
100     }
101     if (!running)
102     {
103         running = true;
104         new Thread(this).start();
105     }
106     }
107 
108     public void run()
109     {
110         Socket socket = null;
111         while (running)
112         {
113             try
114             {
115                 socket = server.accept();
116                 DataOutputStream os = new DataOutputStream(socket.getOutputStream());
117                 // add 500 ms to round off to nearest second
118                 int time = (int) ((System.currentTimeMillis() + 500) / 1000 + SECONDS_1900_TO_1970);
119                 os.writeInt(time);
120                 os.flush();
121             } catch (IOException e)
122             {
123             } finally
124             {
125                 if (socket != null)
126                     try
127                     {
128                         socket.close();  // force closing of the socket
129                     } catch (IOException e)
130                     {
131                         System.err.println("close socket error: " + e);
132                     }
133             }
134         }
135     }
136 
137     /**
138      * Close server socket.
139      */
140     public void stop()
141     {
142         running = false;
143         if (server != null)
144         {
145             try
146             {
147                 server.close();  // force closing of the socket
148             } catch (IOException e)
149             {
150                 System.err.println("close socket error: " + e);
151             }
152             server = null;
153         }
154     }
155 
156     public static void main(String[] args)
157     {
158         TimeTestSimpleServer server = new TimeTestSimpleServer();
159         try
160         {
161             server.start();
162         } catch (IOException e)
163         {
164         }
165     }
166 
167 }