package GCB; import java.lang.*; import java.net.*; import java.awt.*; import java.awt.event.*; import java.io.*; /* Communications management Communications (constructor) - create Port menu Port menu New - create a listening post/target system port Open - open a listening post/target system socket Display - display all created ports (created by either menu or API) API listen() open() send() receive() close() display() */ public class Communications { // global data static final String CODE_FILE = "Communications"; static final int CODE_REVISION = 0; static final int PASSIVE_PORT = 0; static final int ACTIVE_PORT = 1; static final String PORT_TYPE[] = {"listening port","active port"}; MainGUI mainGUI; // main window (accessible from here) Trace trace; // trace with name Communications ListHead passivePorts, // all of the passive ports activePorts; // all of the active ports ListObjectHead listeners, // all of the threads listening receivers; // all of the threads waiting for input // internal classes /* generate TCP listening port PassivePort(port name, port number) - constructor open() - start listening close() - clost the port getName - get the name of the port getSocket - get the underlying socket getFailed - get port failed flag setFailed - set port failed flag getOpened - get port open flag (listening) getListen - get port listen flag (should be listening) setListen - set port listen flag getCount - get count of connection requests display - display port status */ class PassivePort extends ListEntry { String name; // name for the port int port; // local port number ServerSocket socket; // listening socket Socket activeSocket; // (a received connection) boolean failed, // port is not usable opened, // actually listining for connection listen; // listening thread should run int count; // count of connection requests public PassivePort(String n, int p) { // port to receive connectio requests InetAddress inet; failed = false; // ready for communications opened = false; listen = true; count = 0; name = n; // convenient name port = p; try {inet = InetAddress.getByName("localhost");} catch (IOException e) { trace.write("(PassivePort) I/O error creating inet for "+ name+":"+Integer.toString(port)+ " ("+e.getMessage()+")"); mainGUI.error(Communications.CODE_FILE,"I/O error creating inet for "+name); failed = true; // socket is unusable return; } try {socket = new ServerSocket(port);} // try to open the listening port catch (IOException e) { trace.write("(PassivePort) I/O error creating ServerSocket for "+ name+":"+Integer.toString(port)+ " ("+e.getMessage()+")"); mainGUI.error(Communications.CODE_FILE,"I/O error creating ServerSocket for "+name); failed = true; // socket is unusable } catch (SecurityException e) { trace.write("(PassivePort) security violation creating ServerSocket for "+ name+":"+Integer.toString(port)+ " ("+e.getMessage()+")"); mainGUI.error(Communications.CODE_FILE,"security violation creating ServerSocket for "+name); failed = true; // socket is unusable } if (failed==false) { passivePorts.setTail(this); } opened = true; // port is now open } public Socket listen() { // start listening on the port if (failed) { // port is disabled trace.write("(PassivePort.open) port "+name+" is unusable"); mainGUI.error(Communications.CODE_FILE,"port "+name+" is unusable"); return (null); } listen = true; // actively listening try {activeSocket = socket.accept();} // start listening catch (IOException e) { // I/O error trace.write("(PassivePort.open) I/O error opening port "+name+ " ("+e.getMessage()+")"); mainGUI.error(Communications.CODE_FILE,"I/O error opening port "+name); failed = true; // port is unusable return (null); } catch (SecurityException e) { // security does not allow use trace.write("(PassivePort.open) security violation opening port "+name+ " ("+e.getMessage()+")"); mainGUI.error(Communications.CODE_FILE,"security violation opening port "+name); failed = true; // port is unusable return (null); } listen = false; // no longer listening count++; return (activeSocket); } public boolean close() { // close the port listen = false; // shut down listening if (failed) { trace.write("(PassivePort.close) port "+name+" is unusable"); passivePorts.remove(this); return false; } if (opened==false) { trace.write("(PassivePort.close) port "+name+" is not open"); mainGUI.error(Communications.CODE_FILE,"port "+name+" is not open"); failed = true; passivePorts.remove(this); return false; } opened = false; // port is now closed try {socket.close();} // actually close the port catch (IOException e) { trace.write("(PassivePort.close) I/O error closing port "+name+ " ("+e.getMessage()+")"); mainGUI.error(Communications.CODE_FILE,"I/O error closing port "+name); failed = true; // socket is unusable passivePorts.remove(this); return false; } passivePorts.remove(this); trace.write("(PassivePort.close) port "+name+" closed"); return true; } public String getName(){return name;} public ServerSocket getSocket(){return socket;} public boolean getFailed(){return failed;} public void setFailed(boolean b){failed = b;} public boolean getOpened(){return opened;} public boolean getListen(){return listen;} public void setListen(boolean b){listen = b;} public int getCount(){return count;} public void display() { if (failed) { trace.write("(PassivePort.display) port "+name+" is unusable"); mainGUI.append("port "+name+" is unusable"); return; } trace.write("(PassivePort.display) port "+name+ " ("+socket.getInetAddress().getHostName()+":"+socket.getLocalPort()+")"); mainGUI.append("listening port "+name+ " ("+socket.getInetAddress().getHostName()+":"+socket.getLocalPort()+")"); if (opened) { trace.write("(PassivePort.display) port "+name+" is open for new connections"); mainGUI.append("port "+name+" is open for new connections"); } if (listen) { trace.write("(PassivePort.display) port "+name+" allows listening thread"); mainGUI.append("port "+name+" allows listening thread"); } } } /* generate TCP port constructor: port name, port number getName - get the name of the port */ class ActivePort extends ListEntry { String name, // name for this port host, // name for this host remoteHost; // name for remote host int port, // local port number remotePort; // remote port number Socket socket; // socket for open port boolean failed, // object is unusable opened, // port is open receive; // port is able to receive input DataInputStream input; DataOutputStream output; public ActivePort(String n, String h, int p) { // host:port to connect failed = false; // ready for communications opened = false; // socket is not open receive = false; // receive cannot run name = n; // convenient name host = ""; remoteHost = h; // target system remotePort = p; socket = null; activePorts.setTail(this); } public ActivePort(String n, Socket s) { // alreay connected socket failed = false; // ready for communications name = n; // convenient name socket = s; host = socket.getLocalAddress().getHostName(); port = socket.getLocalPort(); remoteHost = socket.getInetAddress().getHostName(); remotePort = socket.getPort(); try {input = new DataInputStream(socket.getInputStream());} catch (IOException e) { trace.write("(ActivePort.open) I/O error creating input stream "+name+ " ("+e.getMessage()+")"); mainGUI.error(Communications.CODE_FILE,"I/O error creating input stream"+name); failed = true; // socket is unusable } try {output = new DataOutputStream(socket.getOutputStream());} catch (IOException e) { trace.write("(ActivePort.open) I/O error creating output stream "+name+ " ("+e.getMessage()+")"); mainGUI.error(Communications.CODE_FILE,"I/O error creating output stream"+name); failed = true; // socket is unusable } activePorts.setTail(this); opened = true; // port starts open (has socket) receive = true; // port may perform input } public boolean open() { InetAddress inet; if (failed) { trace.write("(ActivePort.open) unusable port "+name); mainGUI.error(Communications.CODE_FILE,"port "+name+" is unusable"); return (false); } if (opened) { trace.write("(ActivePort.open) port "+name+" is alread open"); mainGUI.error(Communications.CODE_FILE,"port "+name+" is alreay open"); failed = true; return (false); } try {inet = InetAddress.getByName(remoteHost);} catch (UnknownHostException e) { trace.write("(ActivePort.open) unknown host "+e.getMessage()); mainGUI.error(Communications.CODE_FILE,"unknown host"); failed = true; // socket is unusable return (false); } try {socket = new Socket(inet,remotePort);} // try to open the listening port catch (UnknownHostException e) { trace.write("(ActivePort.open) unknown host "+name+ " ("+e.getMessage()+")"); mainGUI.error(Communications.CODE_FILE,"unknown host "+name); failed = true; // socket is unusable return (false); } catch (IOException e) { /* trace.write("(ActivePort.open) I/O error opening port "+name+ " ("+e.getMessage()+")"); */ return (false); } catch (SecurityException e) { trace.write("(ActivePort.open) security violation opening port"+name+ " ("+e.getMessage()+")"); mainGUI.error(Communications.CODE_FILE,"security violation opening port"+name); failed = true; // socket is unusable return (false); } try {input = new DataInputStream(socket.getInputStream());} catch (IOException e) { trace.write("(ActivePort.open) I/O error creating input stream "+name+ " ("+e.getMessage()+")"); mainGUI.error(Communications.CODE_FILE,"I/O error creating input stream"+name); failed = true; // socket is unusable return (false); } try {output = new DataOutputStream(socket.getOutputStream());} catch (IOException e) { trace.write("(ActivePort.open) I/O error creating output stream "+name+ " ("+e.getMessage()+")"); mainGUI.error(Communications.CODE_FILE,"I/O error creating output stream"+name); failed = true; // socket is unusable return (false); } opened = true; receive = true; return (true); } public boolean send(String text) { if (failed) return false; if (opened==false) return false; try {output.writeBytes(text);} catch (IOException e) { trace.write("(ActivePort.send) I/O error writing output stream "+name+ " ("+e.getMessage()+")"); close(); return (false); } trace.write("(ActivePort.send) send to "+name+" ("+text+")"); return true; } public String receive() { String text, traceText, hexText; int inputSize = 2000; byte[] inputArea = new byte[inputSize]; int bytesRead; int i, k; if (failed) return null; if (opened==false) return null; try { bytesRead = input.read(inputArea,0,inputSize); if(bytesRead>0) { text = new String(inputArea,0,bytesRead); for(i=0; i"+ socket.getInetAddress().getHostAddress()+":"+socket.getPort()+")"); mainGUI.append("active port "+name+" is "+ " ("+socket.getLocalAddress().getHostAddress()+":"+socket.getLocalPort()+"->"+ socket.getInetAddress().getHostAddress()+":"+socket.getPort()+")"); } } // internal methods ActivePort findActive(String name) { ActivePort a = (ActivePort) activePorts.getFirst(); // find the port while (a!=null) { if (a.getName().equals(name)) return a; a = (ActivePort) a.getNext(); } return null; } // public methods // constructor for the object public Communications(MainGUI g) { // initialize the TCP/IP environment mainGUI = g; // visibility to main window trace = new Trace(g, CODE_FILE); passivePorts = new ListHead(); // list of all ports activePorts = new ListHead(); listeners = new ListObjectHead(); // list of all threads receivers = new ListObjectHead(); trace.write("start "+CODE_FILE+" r."+String.valueOf(CODE_REVISION)); } public String listen(String name, int port) { PassivePort listenPost; Socket connection; listenPost = (PassivePort) passivePorts.getFirst(); // if port does not exist, create it while (listenPost!=null) { if (listenPost.getName().equals(name)) break; // port already exists listenPost = (PassivePort) listenPost.getNext(); } if (listenPost==null) listenPost = new PassivePort(name,port); // create the listening post if (listenPost.getFailed()==true) { listenPost.close(); return null; // port is failed } connection = listenPost.listen(); if (connection==null) { trace.write("(listen) listening error "+listenPost.getName()); mainGUI.error(Communications.CODE_FILE,"listening error"+listenPost.getName()); listenPost.setFailed(true); // port is unusable return null; } String newName = listenPost.getName()+"$"+Integer.toString(listenPost.getCount()); ActivePort a = new ActivePort(newName,connection); // create a port return newName; // name for the port } public boolean open(String name, String host, int port) { PassivePort p = (PassivePort) passivePorts.getFirst(); // name must be unique while (p!=null) { if (p.getName().equals(name)) { trace.write("(open) name "+name+" is a duplicate"); mainGUI.error(CODE_FILE,"name "+name+" is a duplicate (listen)"); return false; } p = (PassivePort) p.getNext(); } ActivePort a = findActive(name); // find existing if (a!=null) { if (a.getFailed()== true || a.getOpened()==true) { trace.write("(open) name "+name+" is already open/failed"); mainGUI.error(CODE_FILE,"name "+name+" is already open/failed (active)"); return false; } return a.open(); // open the port } a = new ActivePort(name,host,port); // create a port if (a.getFailed()==true) return false; // create failed return a.open(); // open the port } public boolean open(String name) { ActivePort a = findActive(name); // find existing if (a!=null) { if (a.getFailed()== true || a.getOpened()==true) { trace.write("(open) name "+name+" is already open/failed"); mainGUI.error(CODE_FILE,"name "+name+" is already open/failed (active)"); return false; } return true; } trace.write("(open) name "+name+" does not exist"); mainGUI.error(CODE_FILE,"open name "+name+" does not exist"); return false; } public int port(String name) { ActivePort a = findActive(name); // find existing if (a!=null) return a.getPort(); trace.write("(port) name "+name+" does not exist"); mainGUI.error(CODE_FILE,"port name "+name+" does not exist"); return 0; } public int remotePort(String name) { ActivePort a = findActive(name); // find existing if (a!=null) return a.getRemotePort(); trace.write("(remotePort) name "+name+" does not exist"); mainGUI.error(CODE_FILE,"remotePort name "+name+" does not exist"); return 0; } public boolean send(String name, String text) { ActivePort a = findActive(name); // find existing if (a!=null) return a.send(text); trace.write("(send) name "+name+" does not exist"); mainGUI.error(CODE_FILE,"send name "+name+" does not exist"); return false; } public String receive(String name) { ActivePort a = findActive(name); // find existing if (a!=null) return a.receive(); trace.write("(receive) name "+name+" does not exist"); mainGUI.error(CODE_FILE,"send name "+name+" does not exist"); return null; } public void close(String name) { ActivePort a = findActive(name); // find existing if (a!=null) { a.close(); return; } PassivePort p = (PassivePort) passivePorts.getFirst(); // get port while (p!=null) { if (p.getName().equals(name)) { p.setListen(false); return; } p = (PassivePort) p.getNext(); } trace.write("(close) name "+name+" does not exist"); mainGUI.error(CODE_FILE,"send name "+name+" does not exist"); return; } public void close() { // release all TCP ports ActivePort a = (ActivePort) activePorts.getFirst(); // get port while (a!=null) { a.close(); // shut down a = (ActivePort) activePorts.getFirst(); } PassivePort p = (PassivePort) passivePorts.getFirst(); // get port while (p!=null) { p.setListen(false); // shut down listening p = (PassivePort) p.getNext(); } trace.write("closed"); trace.close(); } public void display() { // display all TCP ports PassivePort p = (PassivePort) passivePorts.getFirst(); // get port if (p!=null) mainGUI.append("Passive ports:"); while (p!=null) { p.display(); // display the port p = (PassivePort) p.getNext(); } ActivePort a = (ActivePort) activePorts.getFirst(); // get port if (a!=null) mainGUI.append("Active ports:"); while (a!=null) { a.display(); // display the port a = (ActivePort) a.getNext(); } } }