summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rwxr-xr-xjava/netsvcs/Time/Clerk.java23
-rwxr-xr-xjava/netsvcs/Time/ClientTest.java94
-rwxr-xr-xjava/netsvcs/Time/Server.java23
-rwxr-xr-xjava/netsvcs/Time/TSClerkHandler.java293
-rwxr-xr-xjava/netsvcs/Time/TSClerkProcessor.java267
-rwxr-xr-xjava/netsvcs/Time/TSRequestAcceptor.java142
-rwxr-xr-xjava/netsvcs/Time/TSRequestHandler.java106
-rwxr-xr-xjava/netsvcs/Time/TSServerAcceptor.java100
-rwxr-xr-xjava/netsvcs/Time/TSServerHandler.java99
9 files changed, 1147 insertions, 0 deletions
diff --git a/java/netsvcs/Time/Clerk.java b/java/netsvcs/Time/Clerk.java
new file mode 100755
index 00000000000..f29e08e06f8
--- /dev/null
+++ b/java/netsvcs/Time/Clerk.java
@@ -0,0 +1,23 @@
+// ============================================================================
+//
+// = PACKAGE
+// netsvcs.Time
+//
+// = FILENAME
+// Clerk.java
+//
+// = AUTHOR
+// Prashant Jain
+//
+// ============================================================================
+package netsvcs.Time;
+
+// Test driver for the time server clerk
+public class Clerk
+{
+ public static void main (String [] args)
+ {
+ TSClerkProcessor clerk = new TSClerkProcessor ();
+ clerk.init (args);
+ }
+}
diff --git a/java/netsvcs/Time/ClientTest.java b/java/netsvcs/Time/ClientTest.java
new file mode 100755
index 00000000000..e5453d69243
--- /dev/null
+++ b/java/netsvcs/Time/ClientTest.java
@@ -0,0 +1,94 @@
+package netsvcs.Time;
+
+import JACE.SOCK_SAP.*;
+import java.io.*;
+import java.net.*;
+import JACE.OS.*;
+
+public class ClientTest {
+
+ public static void main(String args[])
+ {
+ // Don't worry about processing command line right now
+
+ int port = 7990;
+
+ String host = new String("flamenco.cs.wustl.edu");
+ // Why isn't the default defined?
+
+
+ SOCKStream cli_stream = new SOCKStream();
+
+ INETAddr remote_addr;
+ try {
+ remote_addr = new INETAddr(port, host);
+ } catch (UnknownHostException uhe) {
+ ACE.ERROR("UnknownHostException " + uhe);
+ return;
+ }
+
+ SOCKConnector con = new SOCKConnector();
+
+ ACE.DEBUG("Starting connect...");
+
+ // Can't do non-blocking connect in Java! Yippee!
+
+ try {
+
+ con.connect(cli_stream, remote_addr);
+
+ } catch (SocketException se) {
+
+ ACE.ERROR("Socket Exception " + se);
+ return;
+
+ } catch (IOException ie) {
+
+ ACE.ERROR("IOException " + ie);
+ return;
+ }
+
+ String input; // need new string here?
+ BufferedReader in
+ = new BufferedReader(new InputStreamReader(System.in));
+
+ try {
+
+ do {
+
+ input = in.readLine();
+
+ if (input.equals("quit"))
+ break;
+
+ cli_stream.send(new StringBuffer(input + "\n"));
+
+ StringBuffer result = new StringBuffer();
+ int chars = cli_stream.recv(result);
+ if (chars == -1)
+ System.out.println("Evil!");
+ else
+ System.out.println(result);
+
+ } while (true);
+
+ // No close_writer, etc...
+ cli_stream.close();
+
+ } catch (IOException ie) {
+
+ ACE.ERROR("IOException, loop: " + ie);
+ return;
+ }
+ }
+};
+
+
+
+
+
+
+
+
+
+
diff --git a/java/netsvcs/Time/Server.java b/java/netsvcs/Time/Server.java
new file mode 100755
index 00000000000..6b44ddf8d9f
--- /dev/null
+++ b/java/netsvcs/Time/Server.java
@@ -0,0 +1,23 @@
+// ============================================================================
+//
+// = PACKAGE
+// netsvcs.Time
+//
+// = FILENAME
+// Server.java
+//
+// = AUTHOR
+// Prashant Jain
+//
+// ============================================================================
+package netsvcs.Time;
+
+// Test driver for the time service server
+public class Server
+{
+ public static void main (String [] args)
+ {
+ TSServerAcceptor server = new TSServerAcceptor ();
+ server.init (args);
+ }
+}
diff --git a/java/netsvcs/Time/TSClerkHandler.java b/java/netsvcs/Time/TSClerkHandler.java
new file mode 100755
index 00000000000..37f7629b44a
--- /dev/null
+++ b/java/netsvcs/Time/TSClerkHandler.java
@@ -0,0 +1,293 @@
+/*************************************************
+ *
+ * = PACKAGE
+ * netsvcs.Time
+ *
+ * = FILENAME
+ * TS_Clerk_Handler.java
+ *
+ *@author Prashant Jain, Everett Anderson
+ *
+ *************************************************/
+package netsvcs.Time;
+
+import java.io.*;
+import java.util.Date;
+import JACE.OS.*;
+import JACE.Connection.*;
+import JACE.Reactor.*;
+import JACE.ASX.TimeValue;
+
+/**
+ * <hr>
+ * <p><h2>SYNOPSIS</h2>
+ *
+ * <blockquote>Requests the remote time on a server at regular
+ * intervals.</blockquote>
+ *
+ * <p><h2>DESCRIPTION</h2>
+ *
+ * <blockquote>TSClerkHandlers are created by a TSClerkProcessor. There
+ * is one handler for each server that the Clerk Processor factors into
+ * its calculations.</blockquote>
+ */
+public class TSClerkHandler extends SvcHandler
+{
+ /**
+ * Constructor. TSClerkProcessor specifies the server machine and
+ * port, as well as the interval at which to make the query.
+ */
+ public TSClerkHandler (String hostname,
+ int port,
+ TimerQueue tq,
+ int timeout,
+ TSClerkProcessor parent)
+ {
+
+ this.hostname_ = hostname;
+ this.port_ = port;
+ this.tq_ = tq;
+ this.timeout_ = timeout;
+
+ this.initialTimeout_ = timeout;
+ this.processor_ = parent;
+
+ this.sendMsg_ = new String ("TIME_UPDATE_REQUEST\n");
+ }
+
+ /**
+ * Called to start this handler in a new thread. This only
+ * does it when the state of the handler is INITIALIZING.
+ */
+ public int open (Object obj)
+ {
+ if (this.state_ != RECONNECTING) {
+
+ Thread test = new Thread(this);
+
+ new Thread (this).start ();
+
+ }
+ return 0;
+ }
+
+ /**
+ * Accessor - return the host name of the server
+ */
+ public String hostname ()
+ {
+ return this.hostname_;
+ }
+
+ /**
+ * Accessor - return the port used to contact the server
+ */
+ public int port ()
+ {
+ return this.port_;
+ }
+
+ /**
+ * Accessor - returns the difference between the local time and
+ * the remote server.
+ */
+ public long delta ()
+ {
+ return this.delta_;
+ }
+
+ /**
+ * Called when the thread starts. Schedules itself with the
+ * timer queue.
+ */
+ public void run ()
+ {
+ this.timerId_ = this.tq_.scheduleTimer (this,
+ null,
+ new TimeValue (this.timeout_),
+ new TimeValue (this.timeout_));
+
+ }
+
+ /**
+ * Accessor - return the state
+ */
+ public int state()
+ {
+ return this.state_;
+ }
+
+ /**
+ * Sets the state of the handler
+ */
+ public void state(int newState)
+ {
+ this.state_ = newState;
+ }
+
+ /**
+ * Provides a new time out interval (exponentially increasing) so
+ * that if the server doesn't respond, we don't keep trying to
+ * reconnect as often. Maximum value is 5 minutes.
+ */
+ public int recalculateTimeout()
+ {
+ this.timeout_ *= 2;
+
+ if (this.timeout_ > this.max_timeout_)
+ this.timeout_ = max_timeout_;
+
+ return this.timeout_;
+ }
+
+ /**
+ * Start the recovery from a server disconnection by closing the
+ * port and recalculating the timeout value.
+ */
+ protected void errorRecovery()
+ {
+ ACE.DEBUG("Time Service failure with server " + this.hostname_);
+
+ this.timeout_ = this.recalculateTimeout();
+
+ this.reschedule();
+ }
+
+ /**
+ * Removes this handler from the timer queue, and reschedules it
+ * (presumably with a new timeout value)
+ */
+ public void reschedule()
+ {
+ this.tq_.cancelTimer(this);
+
+ this.timerId_ = this.tq_.scheduleTimer (this,
+ null,
+ new TimeValue (this.timeout_),
+ new TimeValue (this.timeout_));
+ }
+
+ /**
+ * Called back by the timer queue. If the handler isn't connected,
+ * it tries to reconnect to the server. Otherwise, it requests
+ * the remote time. The server is said to have disconnected when
+ * an exception is thrown in the socket system, or the result is
+ * a string with length <= 0.
+ */
+ public int handleTimeout (TimeValue tv, Object obj)
+ {
+ if (this.state_ != CONNECTED) {
+
+ this.processor_.initiateConnection(this);
+
+ // If still not connected
+ if (this.state_ != CONNECTED) {
+
+ // used to set state to reconnecting here
+ this.state_ = RECONNECTING;
+
+ // Reschedule to try again later
+ this.errorRecovery();
+ return 0;
+ }
+
+ // If connected, poll the server at the requested intervals
+ this.resetTimeout();
+ }
+
+ StringBuffer ack = new StringBuffer ();
+ int ackLen;
+ try
+ {
+ // Used to calculate the turn-around time
+ long sendTime = System.currentTimeMillis();
+
+ this.peer ().send (this.sendMsg_);
+ ackLen = this.peer ().recv (ack);
+
+ long recvTime = System.currentTimeMillis();
+
+ if (ackLen <= 0) {
+ this.state_ = DISCONNECTED;
+ return -1;
+
+ } else {
+
+ long delta = (new Long(ack.toString())).longValue() - recvTime;
+
+ delta += (recvTime - sendTime) / 2;
+
+ this.delta_ = delta;
+ }
+
+ }
+ catch (NullPointerException e)
+ {
+ ACE.ERROR ("connection reset by peer");
+ this.state_ = DISCONNECTED;
+ return -1;
+ }
+ catch (IOException e)
+ {
+ ACE.ERROR (e);
+ this.state_ = DISCONNECTED;
+ return -1;
+ }
+
+ return 0;
+ }
+
+ /**
+ * Resets the timer interval to be the one supplied to the
+ * constructor.
+ */
+ public void resetTimeout()
+ {
+ this.timeout_ = this.initialTimeout_;
+
+ this.reschedule();
+ }
+
+ private TSClerkProcessor processor_;
+ // Reference used to re-establish connections
+
+ public static final int MAX_RETRY_TIMEOUT = 300;
+ // Wait at most 5 minutes before trying to reconnect
+
+ // States
+ public static final int CONNECTED = 0;
+ public static final int DISCONNECTED = 1;
+ public static final int RECONNECTING = 2;
+
+ // If there has been a failure, try reconnecting
+ // at least every MAX_RETRY_TIMEOUT seconds
+ private int max_timeout_ = MAX_RETRY_TIMEOUT;
+
+ // State of the handler
+ private int state_ = DISCONNECTED;
+
+ // Difference between the remote time and the local time.
+ private long delta_ = 0;
+
+ // Name of the remote host
+ private String hostname_;
+
+ // Port used for the connection
+ private int port_;
+
+ // Current timer interval
+ private int timeout_;
+
+ // Reference to the Clerk Processor's timer queue
+ private TimerQueue tq_;
+
+ // Message to send for a time update
+ private String sendMsg_;
+
+ // ID of the handler in the queue
+ private int timerId_;
+
+ // Desired time interval to receive updates
+ private int initialTimeout_;
+
+}
diff --git a/java/netsvcs/Time/TSClerkProcessor.java b/java/netsvcs/Time/TSClerkProcessor.java
new file mode 100755
index 00000000000..d7b1773cc9e
--- /dev/null
+++ b/java/netsvcs/Time/TSClerkProcessor.java
@@ -0,0 +1,267 @@
+/*************************************************
+ *
+ * = PACKAGE
+ * netsvcs.Time
+ *
+ * = FILENAME
+ * TSClerkProcessor.java
+ *
+ *@author Prashant Jain, Everett Anderson
+ *
+ *************************************************/
+package netsvcs.Time;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import JACE.OS.*;
+import JACE.Misc.*;
+import JACE.Connection.*;
+import JACE.Reactor.*;
+import JACE.ASX.TimeValue;
+
+/**
+ *
+ * <hr>
+ * <p><h2>SYNOPSIS</h2>
+ *
+ * <blockquote>Monitors a specified port (default 7989) and launches
+ * TSClerkHandlers when connections are made. The handlers communicate
+ * with servers and calculate the difference between the server time
+ * and local time. The Clerk Processor averages these differences
+ * and reports them to clients.</blockquote>
+ *
+ * <p><h2>DESCRIPTION</h2>
+ *
+ * <blockquote>This doesn't actually change the system clock, but it
+ * provides the average of the differences of the local and server
+ * times. A client could use this information to adjust the clock, or
+ * just use the midpoint to determine the correct network time.</blockquote>
+ *
+ */
+public class TSClerkProcessor extends Connector implements Runnable
+{
+ /**
+ * Default constructor
+ */
+ public TSClerkProcessor ()
+ {
+ this.serverArray_ = new Vector ();
+
+ }
+
+ /**
+ * Parse the command line, setup the TSRequestAcceptor, and run
+ * the Clerk Processor in its own thread.
+ */
+ public int init (String [] args)
+ {
+ // Parse arguments
+ this.parseArgs (args);
+
+ TSRequestAcceptor ra = new TSRequestAcceptor (this);
+ ra.init (args);
+
+ // Run in own thread of control so that we don't block the caller
+ new Thread (this).start ();
+ return 0;
+ }
+
+
+ /**
+ * Makes connections to the servers, schedules itself for intervals
+ * to update the delta time.
+ */
+ public void run ()
+ {
+
+ // Set up connections with all servers
+ Enumeration table = this.serverArray_.elements ();
+ while (table.hasMoreElements ())
+ {
+ this.initiateConnection((TSClerkHandler)table.nextElement());
+ }
+
+ // Set up timer
+ this.timer_id_ = this.tq_.scheduleTimer (this,
+ null,
+ new TimeValue (this.timeout_),
+ new TimeValue (this.timeout_));
+ }
+
+ /**
+ * Makes connections to the servers.
+ */
+ public void initiateConnection (TSClerkHandler handler)
+ {
+ this.open (handler.hostname(), handler.port());
+
+ try
+ {
+ // Connect to the server
+ this.connect (handler);
+
+ // Set the state of the Clerk Handler so it queries the
+ // server at intervals.
+ handler.state(TSClerkHandler.CONNECTED);
+
+ }
+ catch (UnknownHostException e)
+ {
+ ACE.ERROR (e);
+ }
+ catch (SocketException e)
+ {
+ ACE.ERROR ("Connection refused");
+ }
+ catch (InstantiationException e)
+ {
+ ACE.ERROR (e);
+ }
+ catch (IllegalAccessException e)
+ {
+ ACE.ERROR (e);
+ }
+ catch (IOException e)
+ {
+ ACE.ERROR (e);
+ }
+ }
+
+
+ /**
+ *
+ * Called by the timer queue. Calls updateTime().
+ */
+ public int handleTimeout (TimeValue tv, Object obj)
+ {
+ return this.updateTime ();
+ }
+
+ /**
+ * Calculates the delta time by averaging the results from
+ * Clerk Handler delta()'s. It only includes handlers whose
+ * state is currently CONNECTED. If they're not connected, it
+ * reschedules them to begin the error correction process of
+ * trying to reconnect to the server (possible synch problems?).
+ */
+ protected int updateTime ()
+ {
+ TSClerkHandler handler;
+ int count = 0;
+ long totalDeltaTime = 0;
+
+ Enumeration table = this.serverArray_.elements ();
+
+ while (table.hasMoreElements ())
+ {
+ handler = (TSClerkHandler) table.nextElement ();
+
+ if (handler.state() != TSClerkHandler.CONNECTED) {
+
+ // Reconnecting state means we don't need to put
+ // it in the timer queue again
+ if (handler.state() == TSClerkHandler.RECONNECTING)
+ continue;
+ else
+ if (handler.state() == TSClerkHandler.DISCONNECTED)
+ handler.state(TSClerkHandler.RECONNECTING);
+
+ handler.errorRecovery();
+ continue;
+ }
+
+ long delta = handler.delta();
+
+ ACE.DEBUG(handler.hostname() + ": " + delta);
+
+ totalDeltaTime += delta;
+ count++;
+ }
+
+ if (count > 0) {
+
+ this.timeDelta_ = totalDeltaTime / count;
+
+ ACE.DEBUG("Average deviation: " + totalDeltaTime/count);
+
+ } else
+
+ this.timeDelta_ = 0;
+
+ return 0;
+ }
+
+ /**
+ * Return the delta time.
+ */
+ public long getDelta()
+ {
+ return this.timeDelta_;
+ }
+
+ /**
+ * Parse the command line. Watches for -t <time> and
+ * -h <machine:port> switches. Must specify time
+ * value before host switches!
+ */
+ protected void parseArgs (String args[])
+ {
+ String s;
+ GetOpt opt = new GetOpt (args, "t:h:");
+ for (int c; (c = opt.next ()) != -1; )
+ {
+ switch (c)
+ {
+ case 't':
+ s = opt.optarg ();
+ this.timeout_ = (new Integer (s)).intValue ();
+ break;
+ case 'h':
+ s = opt.optarg ();
+ this.addNewHandler (s);
+ break;
+ default:
+ ACE.ERROR ("Bad command line argument: " + c);
+
+ ACE.ERROR ("Valid arguments: -t <timeout> -h <hostname>:<port> -h ...");
+ break;
+ }
+ }
+ }
+
+ /**
+ *
+ * Creates a new Clerk Handler and adds it to the serverArray_
+ */
+ private void addNewHandler (String s)
+ {
+ StringTokenizer tokens = new StringTokenizer (s, ":");
+ String hostname = tokens.nextToken ();
+
+ int port = (new Integer (tokens.nextToken ())).intValue ();
+
+ // Create new handler and add it to array of servers
+ this.serverArray_.addElement (new TSClerkHandler (hostname,
+ port,
+ this.tq_,
+ this.timeout_,
+ this));
+ }
+
+ // Vector of TSClerkHandlers, one for each server
+ private Vector serverArray_;
+
+ // Default interval at which to update the time
+ private int timeout_ = 1000;
+
+ // Timer queue which calls handleTimeout when the Clerk Processor
+ // is supposed to update the time.
+ private TimerQueue tq_ = new TimerQueue (true);
+
+ // Clerk Processor ID in the timer queue
+ private int timer_id_;
+
+ // Average of the differences of the local and server times.
+ private long timeDelta_;
+}
diff --git a/java/netsvcs/Time/TSRequestAcceptor.java b/java/netsvcs/Time/TSRequestAcceptor.java
new file mode 100755
index 00000000000..e02b0b261ba
--- /dev/null
+++ b/java/netsvcs/Time/TSRequestAcceptor.java
@@ -0,0 +1,142 @@
+/*************************************************
+ *
+ * = PACKAGE
+ * netsvcs.Time
+ *
+ * = FILENAME
+ * TSRequestAcceptor.java
+ *
+ *@author Prashant Jain, Everett Anderson
+ *
+ *************************************************/
+package netsvcs.Time;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import JACE.OS.*;
+import JACE.Misc.*;
+import JACE.Connection.*;
+import JACE.Reactor.*;
+
+/**
+ * <hr>
+ * <p><h2>SYNOPSIS</h2>
+ *
+ * <blockquote>Monitors a specified port (default 7990) and launches
+ * TSRequestHandlers when connections are made. The handlers
+ * report the average deviation from the local time when input
+ * is received to their sockets.</blockquote>
+ *
+ * <p><h2>DESCRIPTION</h2>
+ * <blockquote>This is in place of the shared memory system used in C++ ACE.
+ * The clients need to request the correct time range from the Clerk, so
+ * they can do it with <a href="ACE.SOCK_SAP.SOCKStream.html#_top_">
+ * <tt>sockets</tt></a>. An instance of TSRequestAcceptor is created
+ * and initialized in TSClerkProcessor init(). This should be the
+ * only place it's used.</blockquote>
+ *
+ * @see ACE.SOCK_SAP.SOCKAcceptor,ACE.netsvcs.Time.TSClerkProcessor
+ */
+
+public class TSRequestAcceptor extends Acceptor implements Runnable
+{
+ /**
+ * Create an instance of TSRequestAcceptor. Default constructor.
+ */
+ public TSRequestAcceptor (TSClerkProcessor parent)
+ {
+ this.parent_ = parent;
+ }
+
+ /**
+ *
+ * Process command line arguments (port), and start this instance
+ * in its own thread.
+ *
+ */
+ public int init(String [] args)
+ {
+ this.parseArgs (args);
+
+ new Thread (this).start();
+ return 0;
+ }
+
+ /**
+ *
+ * Called when the thread starts. Open the port and accept
+ * connections.
+ */
+ public void run ()
+ {
+ try {
+ this.open (this.port_);
+ while (true)
+ this.accept();
+ }
+ catch (SocketException e)
+ {
+ ACE.ERROR (e);
+ }
+ catch (InstantiationException e)
+ {
+ ACE.ERROR (e);
+ }
+ catch (IllegalAccessException e)
+ {
+ ACE.ERROR (e);
+ }
+ catch (IOException e)
+ {
+ ACE.ERROR (e);
+ }
+
+ System.err.println("Stopped accepting");
+ }
+
+ /**
+ *
+ * Parse the command line. This only looks for -p <port number>.
+ *
+ */
+ protected void parseArgs (String args[])
+ {
+ String s;
+ GetOpt opt = new GetOpt (args, "p:");
+
+ for (int c; (c = opt.next ()) != -1; )
+ {
+ switch (c)
+ {
+ case 'p':
+ s = opt.optarg ();
+ this.port_ = (new Integer (s)).intValue ();
+ break;
+ default:
+ ACE.ERROR("Invalid argument: " + c);
+ break;
+ }
+ }
+ }
+
+ /**
+ *
+ * Modifies to behavior of Acceptor accept() so the TSClerkProcessor
+ * reference can be passed to the TSRequestHandler.
+ *
+ */
+
+ protected SvcHandler makeSvcHandler ()
+ throws InstantiationException, IllegalAccessException
+ {
+ return (SvcHandler) new TSRequestHandler(parent_);
+ }
+
+ // Port to monitor
+ private int port_ = 7990;
+
+ // Reference to the Clerk Processor (which holds the time value)
+ private TSClerkProcessor parent_;
+};
+
diff --git a/java/netsvcs/Time/TSRequestHandler.java b/java/netsvcs/Time/TSRequestHandler.java
new file mode 100755
index 00000000000..dbeded22250
--- /dev/null
+++ b/java/netsvcs/Time/TSRequestHandler.java
@@ -0,0 +1,106 @@
+package netsvcs.Time;
+/*************************************************
+ *
+ * = PACKAGE
+ * netsvcs.Time
+ *
+ * = FILENAME
+ * TSRequestHandler.java
+ *
+ *@author Prashant Jain, Everett Anderson
+ *
+ *************************************************/
+import java.io.*;
+import java.util.*;
+import JACE.OS.*;
+import JACE.Connection.*;
+import JACE.Reactor.*;
+
+/**
+ * <hr>
+ * <p><h2>SYNOPSIS</h2>
+ *
+ * <blockquote>Handles giving the client the average difference between
+ * the local time and the server times.</blockquote>
+ *
+ * <p><h2>DESCRIPTION</h2>
+ *
+ * <blockquote>Whenever the RequestHandler receives input to the port, it
+ * sends the current delta (average difference time) in return as a string.
+ * Instances of this class are created by TSRequestAcceptor.</blockquote>
+ */
+public class TSRequestHandler extends SvcHandler
+{
+ /**
+ * Constructor. Takes in a reference to the Clerk Processor
+ * so it can call TSClerkProcessor getDelta().
+ */
+ public TSRequestHandler (TSClerkProcessor processor)
+ {
+ this.processor_ = processor;
+ }
+
+ /**
+ *
+ * Run this in a separate thread.
+ */
+ public int open (Object obj)
+ {
+ new Thread (this).start ();
+ return 0;
+ }
+
+ /**
+ *
+ * Called when the thread starts. This is the main code -- whenever
+ * input comes to the socket, it sends out the current delta time
+ * as a string.
+ */
+ public void run ()
+ {
+ int msgLen;
+ try
+ {
+ while (true)
+ {
+ StringBuffer msg = new StringBuffer ();
+
+ msgLen = this.peer ().recv (msg);
+
+ if (msgLen < 0)
+ break;
+ else {
+
+ // No matter what was sent in, send the average difference back
+
+ String msgOut = new String("" + this.processor_.getDelta() + '\n');
+ this.peer ().send (msgOut);
+
+ }
+ }
+ }
+ catch (NullPointerException e)
+ {
+ ACE.ERROR ("Connection reset by peer");
+ }
+ catch (IOException e)
+ {
+ ACE.ERROR (e);
+ }
+ finally
+ {
+ try
+ {
+ this.peer ().close ();
+ }
+ catch (IOException e)
+ {
+ ACE.ERROR (e);
+ }
+ }
+ }
+
+
+ // Reference to the Clerk Processor to call getDelta()
+ TSClerkProcessor processor_;
+}
diff --git a/java/netsvcs/Time/TSServerAcceptor.java b/java/netsvcs/Time/TSServerAcceptor.java
new file mode 100755
index 00000000000..2d54f7b740b
--- /dev/null
+++ b/java/netsvcs/Time/TSServerAcceptor.java
@@ -0,0 +1,100 @@
+/*************************************************
+ *
+ * = PACKAGE
+ * netsvcs.Time
+ *
+ * = FILENAME
+ * TS_Server_Acceptor.java
+ *
+ *@author Prashant Jain
+ *
+ *************************************************/
+package netsvcs.Time;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import JACE.OS.*;
+import JACE.Misc.*;
+import JACE.Connection.*;
+import JACE.Reactor.*;
+
+/**
+ * <hr>
+ * <p><h2>DESCRIPTION</h2>
+ *
+ * Acceptor: listens to a port and launches TSServerHandlers
+ * when connections are made.
+ *
+ * @see netsvcs.Time.TSServerHandler, JACE.Connection.Acceptor
+ */
+public class TSServerAcceptor extends Acceptor implements Runnable
+{
+ // Run this in its own thread
+ public int init (String [] args)
+ {
+ // Parse arguments
+ this.parseArgs (args);
+
+ // Run in own thread of control so that we don't block the caller
+ new Thread (this).start ();
+ return 0;
+ }
+
+ // Create a TSServerHandler for each client that wants to connect
+ public void run ()
+ {
+ try
+ {
+ this.setHandlerFactory (Class.forName ("netsvcs.Time.TSServerHandler"));
+ this.open (this.port_);
+ while (true)
+ this.accept ();
+ }
+ catch (ClassNotFoundException e)
+ {
+ ACE.ERROR (e);
+ }
+ catch (SocketException e)
+ {
+ ACE.ERROR ("Socket Exception: " + e);
+ }
+ catch (InstantiationException e)
+ {
+ ACE.ERROR (e);
+ }
+ catch (IllegalAccessException e)
+ {
+ ACE.ERROR (e);
+ }
+ catch (IOException e)
+ {
+ ACE.ERROR (e);
+ }
+
+ System.err.println("Stopped accepting");
+ }
+
+ // Process the command line
+ protected void parseArgs (String args[])
+ {
+ String s;
+ GetOpt opt = new GetOpt (args, "p:");
+ for (int c; (c = opt.next ()) != -1; )
+ {
+ switch (c)
+ {
+ case 'p':
+ s = opt.optarg ();
+ this.port_ = (new Integer (s)).intValue ();
+ break;
+ default:
+ ACE.ERROR ("Unknown argument: " + c);
+ break;
+ }
+ }
+ }
+
+ private int port_ = 7989;
+}
+
diff --git a/java/netsvcs/Time/TSServerHandler.java b/java/netsvcs/Time/TSServerHandler.java
new file mode 100755
index 00000000000..0fa940d2388
--- /dev/null
+++ b/java/netsvcs/Time/TSServerHandler.java
@@ -0,0 +1,99 @@
+/*************************************************
+ *
+ * = PACKAGE
+ * netsvcs.Time
+ *
+ * = FILENAME
+ * TS_Server_Handler.java
+ *
+ *@author Prashant Jain, Everett Anderson
+ *
+ *************************************************/
+package netsvcs.Time;
+
+import java.io.*;
+import java.util.*;
+import JACE.OS.*;
+import JACE.Connection.*;
+import JACE.Reactor.*;
+
+/**
+ * <hr>
+ * <p><h2>DESCRIPTION</h2>
+ *
+ * <blockquote>Handles requests from a TSClerkHandler and sends
+ * back the current local time.</blockquote>
+ *
+ * @see netsvcs.Time.TSClerkHandler. netsvcs.Time.TSServerAcceptor
+ */
+
+public class TSServerHandler extends SvcHandler
+{
+ // Constructor
+ public TSServerHandler ()
+ {
+ }
+
+ // Start this handler in its own thread
+ public int open (Object obj)
+ {
+
+ new Thread (this).start ();
+ return 0;
+ }
+
+ // Wait for messages from the Client and send the current local
+ // time back as a string.
+ public void run ()
+ {
+ int msgLen;
+ try
+ {
+ while (true)
+ {
+ // Use a new one each time since recv appends
+ StringBuffer msg = new StringBuffer ();
+
+ // Get the message from the client (blocks)
+ msgLen = this.peer ().recv (msg);
+
+ // Just keep waiting if there's a problem
+ if (msgLen <= 0)
+ break;
+
+ // Is the message for the right thing?
+ if (msg.toString().compareTo ("TIME_UPDATE_REQUEST") != 0) {
+ System.err.println("Unknown message: \"" + msg + '\"');
+ this.peer().send("\n"); // send so other side isn't stuck
+ break;
+ }
+
+ // Get local time
+ long time = System.currentTimeMillis();
+
+ // Send as a string
+ this.peer ().send ("" + time + '\n');
+
+ ACE.DEBUG("Time: " + new Date(time));
+ }
+ }
+ catch (NullPointerException e)
+ {
+ ACE.ERROR ("Connection reset by peer");
+ }
+ catch (IOException e)
+ {
+ ACE.ERROR (e);
+ }
+ finally
+ {
+ try
+ {
+ this.peer ().close ();
+ }
+ catch (IOException e)
+ {
+ }
+ }
+ }
+}