//****************************************************************************** // TimeApp.java: Applet // //****************************************************************************** import java.applet.*; import java.awt.*; import java.util.*; import java.net.*; import java.io.*; //============================================================================== // Main Class for applet TimeApp // //============================================================================== public class TimeApp extends Applet { // PARAMETER SUPPORT: // Parameters allow an HTML author to pass information to the applet; // the HTML author specifies them using the tag within the // tag. The following variables are used to store the values of the // parameters. //-------------------------------------------------------------------------- // Members for applet parameters // = //-------------------------------------------------------------------------- private String m_host = "tick.usno.navy.mil"; private boolean m_SNTP = true; // Parameter names. To change a name of a parameter, you need only make // a single change. Simply modify the value of the parameter string below. //-------------------------------------------------------------------------- private final String PARAM_host = "host"; private final String PARAM_SNTP = "SNTP"; // TimeApp Class Constructor //-------------------------------------------------------------------------- public TimeApp() { // TODO: Add constructor code here } // APPLET INFO SUPPORT: // The getAppletInfo() method returns a string describing the applet's // author, copyright date, or miscellaneous information. //-------------------------------------------------------------------------- public String getAppletInfo() { return "Name: TimeApp v0.3\r\n" + "Author: Douglas W. Hogarth (http://www.niceties.com)\r\n" + "Created with Microsoft Visual J++ Version 1.1"; } // PARAMETER SUPPORT // The getParameterInfo() method returns an array of strings describing // the parameters understood by this applet. // // NewApp Parameter Information: // { "Name", "Type", "Description" }, //-------------------------------------------------------------------------- public String[][] getParameterInfo() { String[][] info = { { PARAM_host, "String", "server name" }, { PARAM_SNTP, "boolean", "true for Simple NTP" }, }; return info; } // The init() method is called by the AWT when an applet is first loaded or // reloaded. Override this method to perform whatever initialization your // applet needs, such as initializing data structures, loading images or // fonts, creating frame windows, setting the layout manager, or adding UI // components. //-------------------------------------------------------------------------- public void init() { //String m_host; //boolean m_SNTP; // PARAMETER SUPPORT // The following code retrieves the value of each parameter // specified with the tag and stores it in a member // variable. //---------------------------------------------------------------------- //String param; // host: server name //---------------------------------------------------------------------- //param = getParameter(PARAM_host); //if (param != null) // m_host = param; // SNTP: true for Simple NTP //---------------------------------------------------------------------- //param = getParameter(PARAM_SNTP); //if (param != null) // m_SNTP = Boolean.valueOf(param).booleanValue(); // If you use a ResourceWizard-generated "control creator" class to // arrange controls in your applet, you may want to call its // CreateControls() method from within this method. Remove the following // call to resize() before adding the call to CreateControls(); // CreateControls() does its own resizing. //---------------------------------------------------------------------- resize(320, 125); // TODO: Place additional initialization code here } // Place additional applet clean up code here. destroy() is called when // when you applet is terminating and being unloaded. //------------------------------------------------------------------------- public void destroy() { // TODO: Place applet cleanup code here } // TimeApp Paint Handler //-------------------------------------------------------------------------- public void paint(Graphics g) { Date start, stop, utc, zulu; DatagramSocket s = null; DatagramPacket pkt; InetAddress in; String m_host; byte buf[] = new byte[48]; int ubuf[] = new int[6]; boolean m_SNTP=false;//default needed for compiler String param; //bugbug we should be getting these parameters via init, // but Doug is lazy and hasn't learned enough yet m_host = getParameter(PARAM_host); param = getParameter(PARAM_SNTP); if (param != null) m_SNTP = Boolean.valueOf(param).booleanValue(); start = stop = new Date();//we need this to keep compiler from complaining try { s = new DatagramSocket(); // hostname "null" returns the default address for the local machine in = InetAddress.getByName(m_host); if (m_SNTP) { pkt = new DatagramPacket(buf, 48, in, 123);//IPPORT_NTP buf[0] = 0xB;//client, version 1 buf[1] = 0; buf[2] = 0; buf[3] = 0; } else pkt = new DatagramPacket(buf, 0, in, 37);//IPPORT_TIMESERVER, null packet //s.setSoTimeout(3000);//set 3 second timeout to cause java.io.InterruptedIOException start = new Date(); s.send(pkt); if (!m_SNTP)//RFC-868 pkt = new DatagramPacket(buf, 4, in, 37);//IPPORT_TIMESERVER s.receive(pkt); stop = new Date(); } catch (SecurityException e) { g.drawString("Sorry, security doesn't allow accessing "+m_host, 10, 110); g.drawString("(try save-as-file and specifying file://)", 10, 120); } catch (SocketException se) { } catch (UnknownHostException uhe) { } catch (IOException ioe) { //bugbug would a timeout get to here? } //we've got to convert from signed to unsigned if (m_SNTP) { if (buf[0]>=0) ubuf[5]=buf[0]; else ubuf[5]=256+buf[0]; if (((buf[1]<1)||(buf[1]>15)) || ((ubuf[5]&0xC0)==0xC0) || //test LI field ((buf[40]==0)&&(buf[41]==0)&&(buf[42]==0)&&(buf[43]==0))) g.drawString("Don't trust any server/UTC info above!", 10, 100); for (int i=0; i<5; i++) { if (buf[40+i]>=0) ubuf[i]=buf[40+i]; else ubuf[i]=256+buf[40+i]; } utc = new Date((long)((ubuf[0]*256.0*65536+ubuf[1]*65536+ubuf[2]*256+ubuf[3])-(60.0*60*24*365.2422*70+3974.4))*1000+(long)(ubuf[4]/256+.5)); //bugbug we didn't use the seconds fraction in a standard way } else {//RFC-868 for (int i=0; i<4; i++) { if (buf[i]>=0) ubuf[i]=buf[i]; else ubuf[i]=256+buf[i]; } utc = new Date((long)((ubuf[0]*256.0*65536+ubuf[1]*65536+ubuf[2]*256+ubuf[3])-(60.0*60*24*365.2422*70+3974.4))*1000); }//RFC-868 zulu = new Date(); s.close(); if ((stop.getTime()-start.getTime())>0) { //if m_SNTP bugbug we don't subtract time held by server (typically <.5ms) //if m_SNTP bugbug we don't check for >16*1000 (NTP.MAXDISPERSE) g.drawString("(round-trip to server took ~"+(stop.getTime()-start.getTime())+" milliseconds)", 10, 85); utc.setTime(utc.getTime()+(stop.getTime()-start.getTime())/2);//increase by one-way } g.drawString("Java(tm) thinks it was "+zulu.toLocaleString()+",", 10, 10); g.drawString("when it was really "+utc.toLocaleString(), 10, 25); if (!zulu.equals(utc)) { if (Math.abs(zulu.getTime()-utc.getTime()) < 2000) g.drawString("(your system is correct within a couple seconds).", 10, 40); else { if (zulu.after(utc)) g.drawString("(your system was ahead approximately "+(zulu.getTime()-utc.getTime())/1000+" seconds).", 10, 40); else g.drawString("(your system was behind approximately "+(utc.getTime()-zulu.getTime())/1000+" seconds).", 10, 40); g.drawString("Try to correct your system's time and test again using Refresh", 10, 55); g.drawString("(or clicking the mouse inside this applet)", 10, 70); } } else g.drawString("(your system has the correct time).", 10, 40); } // The start() method is called when the page containing the applet // first appears on the screen. The AppletWizard's initial implementation // of this method starts execution of the applet's thread. //-------------------------------------------------------------------------- public void start() { // TODO: Place additional applet start code here } // The stop() method is called when the page containing the applet is // no longer on the screen. The AppletWizard's initial implementation of // this method stops execution of the applet's thread. //-------------------------------------------------------------------------- public void stop() { } // MOUSE SUPPORT: // The mouseDown() method is called if the mouse button is pressed // while the mouse cursor is over the applet's portion of the screen. //-------------------------------------------------------------------------- public boolean mouseDown(Event evt, int x, int y) { repaint(); return true; } // TODO: Place additional applet code here }