diff options
Diffstat (limited to 'java')
-rwxr-xr-x | java/netsvcs/Time/Clerk.java | 23 | ||||
-rwxr-xr-x | java/netsvcs/Time/ClientTest.java | 94 | ||||
-rwxr-xr-x | java/netsvcs/Time/Server.java | 23 | ||||
-rwxr-xr-x | java/netsvcs/Time/TSClerkHandler.java | 293 | ||||
-rwxr-xr-x | java/netsvcs/Time/TSClerkProcessor.java | 267 | ||||
-rwxr-xr-x | java/netsvcs/Time/TSRequestAcceptor.java | 142 | ||||
-rwxr-xr-x | java/netsvcs/Time/TSRequestHandler.java | 106 | ||||
-rwxr-xr-x | java/netsvcs/Time/TSServerAcceptor.java | 100 | ||||
-rwxr-xr-x | java/netsvcs/Time/TSServerHandler.java | 99 |
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) + { + } + } + } +} |