diff --git a/cs656/lab3/ChatClient.java b/cs656/lab3/ChatClient.java index dc1b97d..24925d7 100644 --- a/cs656/lab3/ChatClient.java +++ b/cs656/lab3/ChatClient.java @@ -11,12 +11,308 @@ 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.io.Serializable; +import java.net.*; public class ChatClient { - Chord chord; + 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); + /* 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(); + 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) { @@ -34,7 +330,7 @@ public class ChatClient switch (argIndex) { case 0: - user = s; + user = s.replace(' ', '_'); break; case 1: host = s;