/* Josh Holtrop * 2008-10-30 * CS656 * Lab3 */ import java.net.InetAddress; import java.net.MalformedURLException; import de.uniba.wiai.lspi.chord.data.URL; import de.uniba.wiai.lspi.chord.service.*; import de.uniba.wiai.lspi.chord.service.impl.*; import java.io.*; import java.util.*; import java.net.*; public class ChatClient { private PresenceService myPServ; private String myUserName; private Thread myListenThread; private ChatClientListener myListener; private RegistrationInfo myRegistrationInfo; /** * This class provides a thread to listen for incoming connections. */ private class ChatClientListener implements Runnable { ServerSocket mySocket; public ChatClientListener() { try { /* Just listen on any available TCP port */ mySocket = new ServerSocket(0); } catch (Exception e) { System.err.println("Error creating listener thread!"); e.printStackTrace(); System.exit(-1); } } public int getPort() { return mySocket.getLocalPort(); } public String getHost() { return mySocket.getInetAddress().getHostName(); } /* called when the thread is first scheduled */ public void run() { Socket s; /* wait indefinitely for new connections */ for (;;) { try { s = mySocket.accept(); Thread cclt = new Thread(new ChatClientListenerThread(s)); cclt.start(); } catch (Exception e) { } } } /** * This class provides a listener for any connections that come in. * All it does is print any received chat messages from the remote * user to this user's screen. */ public class ChatClientListenerThread implements Runnable { Socket mySocket; public ChatClientListenerThread(Socket s) { mySocket = s; } public void run() { try { InputStream is = mySocket.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); while (!mySocket.isClosed()) { /* read and print a message from a peer */ String in = br.readLine(); if (in == null) break; System.out.println(in); System.out.print("> "); } } catch (Exception e) { return; } } } } /* construct the main ChatClient object */ public ChatClient(PresenceService pserv, String userName) { myPServ = pserv; myUserName = userName; } public void run() { try { myListener = new ChatClientListener(); myRegistrationInfo = new RegistrationInfo(myUserName, InetAddress.getLocalHost().getHostName(), myListener.getPort(), true); if (!register()) { return; } } catch (Exception e) { e.printStackTrace(); return; } /* Start a thread to listen for connections in */ myListenThread = new Thread(myListener); myListenThread.start(); mainloop(); } /* call the register function in the presence service */ private boolean register() { try { myPServ.register(myRegistrationInfo); } catch (Exception e) { System.out.println("Exception caught when registering!"); e.printStackTrace(); return false; } return true; } /* call the unregister function in the presence service */ private boolean unregister() { try { myPServ.unregister(myUserName); } catch (Exception e) { System.out.println("Exception caught when unregistering!"); e.printStackTrace(); return false; } return true; } /* this is the main wait-for-input-and-respond loop */ private void mainloop() { BufferedReader br = new BufferedReader( new InputStreamReader(System.in)); String line; try { for (;;) { /* print a prompt */ System.out.print("> "); /* read a line of input */ line = br.readLine(); if (line == null) break; line = line.trim(); if (line.equals("")) continue; /* break the input into the command word, and the rest */ String command, rest; int spaceIndex = line.indexOf(' '); if (spaceIndex > 0) { command = line.substring(0, spaceIndex); rest = line.substring(spaceIndex + 1); rest = rest.trim(); } else { command = line; rest = ""; } if (command.equals("help") || command.equals("?")) { System.out.println("Commands:"); System.out.println(" friends - view a list of all peers on the system"); System.out.println(" talk {username} {message} - send message to username"); System.out.println(" broadcast {message} - send message to every available user"); System.out.println(" busy - set status to busy/away"); System.out.println(" available - set status to busy/away"); System.out.println(" exit - disconnect and exit program"); } else if (command.equals("talk")) { String user = ""; int idx; if ((idx = rest.indexOf(' ')) > 0) { user = rest.substring(0, idx); RegistrationInfo ri = myPServ.lookup(user); if (ri == null) { System.err.println("Could not find user \"" + user + "\"!"); } else { /* only send a message to available users */ if (ri.getStatus()) { String message = rest.substring(idx + 1); sendUserMessage(user, message); } else { System.out.println(user + " is busy!"); } } } else { System.out.println("Syntax: talk {user} {message}"); } } else if (command.equals("busy")) { if (myRegistrationInfo.getStatus()) { myRegistrationInfo = new RegistrationInfo( myRegistrationInfo.getUserName(), myRegistrationInfo.getHost(), myRegistrationInfo.getPort(), false ); unregister(); register(); System.out.println("Status set to busy"); } } else if (command.equals("available")) { if (!myRegistrationInfo.getStatus()) { myRegistrationInfo = new RegistrationInfo( myRegistrationInfo.getUserName(), myRegistrationInfo.getHost(), myRegistrationInfo.getPort(), true ); unregister(); register(); System.out.println("Status set to available"); } } else if (command.equals("exit")) { myListenThread.interrupt(); break; } else { System.out.println("Unrecognized Command! Type 'help' or '?' for help!"); } } } catch (Exception e) { e.printStackTrace(); } unregister(); try { myPServ.leave(); /* Leave the Chord network */ } catch (Exception e) { e.printStackTrace(); } System.exit(0); } /* a useful subroutine to break out the task of sending a * message to a particular user */ private void sendUserMessage(String user, String message) { try { RegistrationInfo ri = myPServ.lookup(user); if (ri != null) { Socket s = new Socket(InetAddress.getByName(ri.getHost()), ri.getPort()); OutputStream os = s.getOutputStream(); message = myUserName + ": " + message; os.write(message.getBytes()); s.close(); } } catch (Exception e) { System.err.println("Error sending message"); e.printStackTrace(); } } public static void main(String[] args) { boolean master = false; String user = "user"; String host = "localhost"; int argIndex = 0; for (String s : args) { if (s.equals("-master")) master = true; else { switch (argIndex) { case 0: user = s.replace(' ', '_'); break; case 1: host = s; break; default: usage(); } argIndex++; } } // Load the Chord properties files PropertiesLoader.loadPropertyFile(); ChordClient chordClient = new ChordClient(host, master); PresenceService pServ = new PresenceServiceImpl(chordClient); ChatClient chatClient = new ChatClient(pServ, user); chatClient.run(); } private static void usage() { System.err.println("Usage: java ChatClient [-master] {user} {host}"); System.exit(42); } }