package com.vdom.comms; import java.io.EOFException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.IOException; import java.io.OptionalDataException; import java.io.StreamCorruptedException; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketTimeoutException; import java.net.UnknownHostException; public class CommsOld implements Runnable { final static int TIMEOUT = 15000; // 15 seconds in ms final static boolean DEBUGGING = false; String host; int port; EventHandler parent; private boolean isServer = true; private ServerSocket pserver = null; private Socket pclient = null; private ObjectInputStream ois = null; private ObjectOutputStream oos = null; private boolean done = false; public class MonitorObject{}; MonitorObject myMonitorObject = new MonitorObject(); Event latestEvent = null; public Event doWait(){ Event e; synchronized(myMonitorObject){ while(latestEvent == null){ try{ myMonitorObject.wait(TIMEOUT); } catch(InterruptedException e1){ // TODO Auto-generated catch block e1.printStackTrace(); } if (done) return null; } //clear signal and continue running. e = latestEvent; latestEvent = null; } return e; } public void doNotify(Event e){ synchronized(myMonitorObject){ latestEvent = e; myMonitorObject.notify(); } } public CommsOld(EventHandler parent, int port) throws IOException { this.parent = parent; this.isServer = true; this.port = port; debug("Opening server socket..."); pserver = new ServerSocket(this.port); this.host = pserver.getInetAddress().getHostAddress(); debug("Opened: " + host + " / " + port); } public CommsOld(EventHandler parent, String host, int port) { this.parent = parent; this.isServer = false; this.host = host; this.port = port; } public String getHost() { return host; } public int getPort() { return port; } private void debug(String s) { s = host + ":" + port + " -- " + s; // System.err.println (":: Androminion :: " + s); if (DEBUGGING) parent.debug(s); } public boolean isConnected() { return (pclient == null ? false : pclient.isConnected()); } public void connect() throws UnknownHostException, IOException, StreamCorruptedException { if (isConnected()) return; // open a socket connection if (isServer) pclient = pserver.accept(); else pclient = new Socket(host, port); // Set read timeout, double for servers than for clients pclient.setSoTimeout(TIMEOUT * (isServer ? 2 : 1)); // open I/O streams for objects oos = new ObjectOutputStream(pclient.getOutputStream()); ois = new ObjectInputStream(pclient.getInputStream()); } private boolean disconnect() { boolean clean = true; debug("Shutting down..."); try { // close I/O streams pclient.shutdownInput(); pclient.shutdownOutput(); debug("Streams shutdown."); } catch (Exception e) { clean = false; } try { oos.close(); ois.close(); debug("Streams closed."); } catch (Exception e) { clean = false; } try { // close socket connection pclient.close(); debug("Socket closed."); } catch (Exception e) { clean = false; } if (isServer) { // close server // debug ("Stopping server..."); try { pserver.close(); debug("Server stopped"); } catch (Exception e) { clean = false; } } ois = null; oos = null; pclient = null; pserver = null; return clean; } public Event get() throws IOException { Event p = null; try { // debug("Trying to get..."); p = (Event) ois.readObject(); debug("Got: " + p.toString()); } catch (OptionalDataException e) { debug("OptionalDataException in Comms.get() -- ignoring."); } catch (ClassNotFoundException e) { debug("ClassNotFoundException in Comms.get() -- ignoring."); } catch (NullPointerException e) { debug("NullPointerException in Comms.get() -- ignoring."); } return p; } public void put(Event p) throws IOException { debug("Put: " + p.toString()); oos.writeObject(p); } private boolean ping() { try { put(new Event(Event.EType.PING)); } catch (Exception e) { debug("Exception in Comms.ping() while sending -- quitting."); e.printStackTrace(); return true; } Event p; try { p = get(); } catch (SocketTimeoutException e) { debug("Timed out in Comms.ping() -- quitting."); return true; } catch (Exception e) { debug("Exception in Comms.ping() while recving -- quitting."); e.printStackTrace(); return true; } if ((p == null) || (p.t != Event.EType.PONG)) { debug("Invalid packet in Comms.ping() -- quitting."); return true; } return false; } @Override public void run() { done = false; if (!isConnected()) { if (isServer) { try { connect(); } catch (Exception e) { debug("Failed to connect in run!"); return; } } else return; } boolean timeout, disconnect = false; Event p; while (!done) { p = null; timeout = false; try { p = get(); } catch (SocketTimeoutException e) { debug("Connection timed out..."); timeout = true; } catch (EOFException e) { debug("Socket externally closed in Comms.run() -- quitting."); disconnect = true; } catch (Exception e) { debug("Other exception in Comms.run() -- quitting."); e.printStackTrace(); disconnect = true; } if (done) break; if ((p != null) && (p.t == Event.EType.PING)) try { put(new Event(Event.EType.PONG)); } catch (Exception e) { debug("Could not pong in Comms.run() -- quitting."); e.printStackTrace(); disconnect = true; } else if ((p != null) && (p.t == Event.EType.GETSERVER)) try { put(new Event(Event.EType.SERVER).setString(host).setInteger(port)); } catch (Exception e) { debug("Could not pong server in Comms.run() -- quitting."); e.printStackTrace(); disconnect = true; } else if (p != null) { if (!parent.handle(p)) doNotify(p); } else if (timeout) disconnect = ping(); if (disconnect) { p = new Event(Event.EType.DISCONNECT); if (!parent.handle(p)) doNotify(p); done = true; } } disconnect(); debug("End of Comms.run()"); } public boolean stop() { done = true; return disconnect(); } }