Commit 77176d9b80331d81b356ba95c063e7dcfc724d54

Authored by Imanol-Mikel Barba Sabariego
1 parent 8d957e00

git-svn-id: svn://imanolbarba.net/PAD@27 c2ee353e-ed0d-4329-bf56-03aec153487f

JChatClient/bin/client
No preview for this file type
JChatClient/src/Socket.cpp
@@ -6,11 +6,6 @@ @@ -6,11 +6,6 @@
6 * En este fichero se implementan los métodos de la clase Socket definidos en Socket.h 6 * En este fichero se implementan los métodos de la clase Socket definidos en Socket.h
7 */ 7 */
8 #include "Socket.h" 8 #include "Socket.h"
9 -#include "SocketException.h"  
10 -#include <sstream>  
11 -#include <strings.h>  
12 -#include <cstdlib>  
13 -#include <netinet/tcp.h>  
14 9
15 using namespace std; 10 using namespace std;
16 11
@@ -149,8 +144,11 @@ const Socket&amp; Socket::operator &lt;&lt; ( const std::string&amp; text) @@ -149,8 +144,11 @@ const Socket&amp; Socket::operator &lt;&lt; ( const std::string&amp; text)
149 } 144 }
150 sstream << length; 145 sstream << length;
151 string len = sstream.str(); 146 string len = sstream.str();
152 - Send(len.c_str(), len.length()+1);  
153 - Send(text.c_str(), text.length()); 147 + char* msg = new char[len.length() + text.length() + 1];
  148 + strcpy(msg,len.c_str());
  149 + strcpy(msg+len.length()+1,text.c_str());
  150 + Send(msg, text.length() + len.length() + 1);
  151 + delete[] msg;
154 return *this; 152 return *this;
155 } 153 }
156 154
JChatClient/src/client.cpp
@@ -25,13 +25,6 @@ void exitClient(int signal/*!&lt;Parámetro que captura el signal recibido*/) @@ -25,13 +25,6 @@ void exitClient(int signal/*!&lt;Parámetro que captura el signal recibido*/)
25 25
26 void killThread(thread_args *t_arg) 26 void killThread(thread_args *t_arg)
27 { 27 {
28 - (t_arg->s)->Close();  
29 - pthread_mutex_lock(t_arg->mutex);  
30 - if(t_arg->s != 0)  
31 - {  
32 - delete t_arg->s;  
33 - t_arg->s = 0;  
34 - }  
35 if(t_arg != 0) 28 if(t_arg != 0)
36 { 29 {
37 delete t_arg; 30 delete t_arg;
@@ -42,42 +35,69 @@ void killThread(thread_args *t_arg) @@ -42,42 +35,69 @@ void killThread(thread_args *t_arg)
42 35
43 bool connect(Socket& s) 36 bool connect(Socket& s)
44 { 37 {
45 - string host, nick; 38 + string host, nick, response;
46 int port; 39 int port;
47 /*cout << "Hostname: "; 40 /*cout << "Hostname: ";
48 - cin >> host; 41 + getline(cin,host);
49 cout << "Port: "; 42 cout << "Port: ";
50 cin >> port;*/ 43 cin >> port;*/
51 cout << "Nickname: "; 44 cout << "Nickname: ";
52 - cin >> nick;  
53 - cin.ignore(); 45 + getline(cin,nick);
54 host = "localhost"; 46 host = "localhost";
55 port = 3001; 47 port = 3001;
56 48
57 try 49 try
58 { 50 {
  51 + s.Create();
59 s.Connect(host,port); 52 s.Connect(host,port);
60 cout << "Connected" << endl; 53 cout << "Connected" << endl;
61 connected = true; 54 connected = true;
62 s << nick; 55 s << nick;
  56 + s >> response;
  57 + while(response == "CHATNICKINVALID")
  58 + {
  59 + cout << "Spaces not allowed in nicknames, please enter another nickname: ";
  60 + getline(cin,nick);
  61 + s << nick;
  62 + s >> response;
  63 + }
  64 + while(response == "CHATNICKEXIST")
  65 + {
  66 + cout << "Nickname in use, please enter another nickname: ";
  67 + getline(cin,nick);
  68 + s << nick;
  69 + s >> response;
  70 + }
  71 + while(response == "CHATFULL")
  72 + {
  73 + cout << "Chatroom is full, please wait..." << endl;
  74 + s >> response;
  75 + }
  76 + if(response != "CHATOK")
  77 + {
  78 + cout << "Error: " << response << endl;
  79 + return false;
  80 + }
63 } 81 }
64 catch(SocketException& e) 82 catch(SocketException& e)
65 { 83 {
66 cout << e.description() << endl; 84 cout << e.description() << endl;
  85 + exit(-1);
67 } 86 }
  87 + return true;
68 } 88 }
69 89
70 void* sendThread(void* args) 90 void* sendThread(void* args)
71 { 91 {
72 string send; 92 string send;
73 struct thread_args *t_arg = (struct thread_args*)args; 93 struct thread_args *t_arg = (struct thread_args*)args;
74 - while(true) 94 + while(connected)
75 { 95 {
76 cout << "> "; 96 cout << "> ";
77 getline(cin,send); 97 getline(cin,send);
78 if(cin.eof()) 98 if(cin.eof())
79 { 99 {
80 - send = "/disconnect"; 100 + send = "/exit";
81 } 101 }
82 try 102 try
83 { 103 {
@@ -90,9 +110,6 @@ void* sendThread(void* args) @@ -90,9 +110,6 @@ void* sendThread(void* args)
90 catch(SocketException& e) 110 catch(SocketException& e)
91 { 111 {
92 cout << e.description() << endl; 112 cout << e.description() << endl;
93 - cout << "Exiting" << endl;  
94 - (t_arg->s)->Close();  
95 - exit(-1);  
96 } 113 }
97 } 114 }
98 killThread(t_arg); 115 killThread(t_arg);
@@ -104,11 +121,20 @@ void* recvThread(void* args) @@ -104,11 +121,20 @@ void* recvThread(void* args)
104 struct thread_args *t_arg = (struct thread_args*)args; 121 struct thread_args *t_arg = (struct thread_args*)args;
105 while(true) 122 while(true)
106 { 123 {
107 - *(t_arg->s) >> recv; 124 + try
  125 + {
  126 + *(t_arg->s) >> recv;
  127 + }
  128 + catch(SocketException &e)
  129 + {
  130 + connected = false;
  131 + cout << e.description() << endl;
  132 + (t_arg->s)->Close();
  133 + break;
  134 + }
108 if(recv == "DISC_OK") 135 if(recv == "DISC_OK")
109 { 136 {
110 cout << "Disconnecting" << endl; 137 cout << "Disconnecting" << endl;
111 - (t_arg->s)->Close();  
112 connected = false; 138 connected = false;
113 pthread_cond_signal(t_arg->condition); 139 pthread_cond_signal(t_arg->condition);
114 break; 140 break;
@@ -116,7 +142,6 @@ void* recvThread(void* args) @@ -116,7 +142,6 @@ void* recvThread(void* args)
116 else if(recv == "EXIT_OK") 142 else if(recv == "EXIT_OK")
117 { 143 {
118 cout << "Exiting" << endl; 144 cout << "Exiting" << endl;
119 - (t_arg->s)->Close();  
120 connected = false; 145 connected = false;
121 finished = true; 146 finished = true;
122 pthread_cond_signal(t_arg->condition); 147 pthread_cond_signal(t_arg->condition);
@@ -144,10 +169,15 @@ int main() @@ -144,10 +169,15 @@ int main()
144 thread_args *sArgs = new thread_args; 169 thread_args *sArgs = new thread_args;
145 thread_args *rArgs = new thread_args; 170 thread_args *rArgs = new thread_args;
146 pthread_t recv, send; 171 pthread_t recv, send;
147 - s.Create(); 172 + pthread_attr_t attr;
  173 + pthread_attr_init(&attr);
  174 + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
148 while (!finished) 175 while (!finished)
149 { 176 {
150 - connect(s); 177 + if(!connect(s))
  178 + {
  179 + exit(-1);
  180 + }
151 pthread_mutex_lock(&mutex); 181 pthread_mutex_lock(&mutex);
152 sArgs->mutex = &mutex; 182 sArgs->mutex = &mutex;
153 sArgs->condition = &condition; 183 sArgs->condition = &condition;
@@ -157,14 +187,17 @@ int main() @@ -157,14 +187,17 @@ int main()
157 rArgs->condition = &condition; 187 rArgs->condition = &condition;
158 rArgs->s = &s; 188 rArgs->s = &s;
159 189
160 - pthread_create(&send,NULL,sendThread,(void *)sArgs);  
161 - pthread_create(&recv,NULL,recvThread,(void *)rArgs); 190 + pthread_create(&send,&attr,sendThread,(void *)sArgs);
  191 + pthread_create(&recv,&attr,recvThread,(void *)rArgs);
162 192
163 while(connected) 193 while(connected)
164 { 194 {
165 pthread_cond_wait(&condition,&mutex); 195 pthread_cond_wait(&condition,&mutex);
166 } 196 }
167 pthread_mutex_unlock(&mutex); 197 pthread_mutex_unlock(&mutex);
  198 + pthread_join(recv,NULL);
  199 + pthread_join(send,NULL);
  200 + s.Close();
168 } 201 }
169 pthread_cond_destroy(&condition); 202 pthread_cond_destroy(&condition);
170 pthread_mutex_destroy(&mutex); 203 pthread_mutex_destroy(&mutex);
@@ -172,7 +205,5 @@ int main() @@ -172,7 +205,5 @@ int main()
172 205
173 /* TODO 206 /* TODO
174 * 207 *
175 - * disconnecting causes some real shit  
176 - * list nicks  
177 - * unicast message 208 + * CTRL+C
178 */ 209 */
179 \ No newline at end of file 210 \ No newline at end of file
JChatClient/src/include/Socket.h
@@ -9,13 +9,17 @@ @@ -9,13 +9,17 @@
9 #define SOCKET_H_ 9 #define SOCKET_H_
10 10
11 #include <iostream> 11 #include <iostream>
  12 +#include <sstream>
  13 +#include "SocketException.h"
12 #include <sys/socket.h> 14 #include <sys/socket.h>
  15 +#include <sys/types.h>
13 #include <netinet/in.h> 16 #include <netinet/in.h>
  17 +#include <netinet/tcp.h>
14 #include <arpa/inet.h> 18 #include <arpa/inet.h>
15 #include <netdb.h> 19 #include <netdb.h>
16 -#include <string>  
17 -#include <sys/types.h>  
18 #include <unistd.h> 20 #include <unistd.h>
  21 +#include <cstdlib>
  22 +#include <cstring>
19 23
20 using namespace std; 24 using namespace std;
21 25
JChatServer/bin/pad/prac2/ChatException.class 0 → 100644
No preview for this file type
JChatServer/bin/pad/prac2/Connection.class
No preview for this file type
JChatServer/bin/pad/prac2/JChat$1.class 0 → 100644
No preview for this file type
JChatServer/bin/pad/prac2/MyServerSocket.class
No preview for this file type
JChatServer/bin/pad/prac2/MySocket.class
No preview for this file type
JChatServer/bin/pad/prac2/Server.class
No preview for this file type
JChatServer/src/pad/prac2/ChatException.java 0 → 100644
  1 +package pad.prac2;
  2 +
  3 +public class ChatException extends Exception
  4 +{
  5 +
  6 + /**
  7 + *
  8 + */
  9 + private static final long serialVersionUID = 2263415822589627234L;
  10 +
  11 + public ChatException()
  12 + {
  13 + super();
  14 + }
  15 +
  16 + public ChatException(String message)
  17 + {
  18 + super(message);
  19 + }
  20 +
  21 +}
JChatServer/src/pad/prac2/Connection.java
@@ -15,11 +15,6 @@ public class Connection extends Thread @@ -15,11 +15,6 @@ public class Connection extends Thread
15 sleep = true; 15 sleep = true;
16 } 16 }
17 17
18 - public void sendMessage(String message) throws IOException  
19 - {  
20 - socket.sendMsg(message);  
21 - }  
22 -  
23 public void awake() 18 public void awake()
24 { 19 {
25 synchronized(this) 20 synchronized(this)
@@ -32,9 +27,12 @@ public class Connection extends Thread @@ -32,9 +27,12 @@ public class Connection extends Thread
32 public void finish() 27 public void finish()
33 { 28 {
34 kill = true; 29 kill = true;
35 - sleep = false; 30 + if(sleep)
  31 + {
  32 + sleep = false;
  33 + notify();
  34 + }
36 socket.close(); 35 socket.close();
37 - this.notify();  
38 } 36 }
39 37
40 public void setSock(MySocket s) 38 public void setSock(MySocket s)
@@ -42,6 +40,11 @@ public class Connection extends Thread @@ -42,6 +40,11 @@ public class Connection extends Thread
42 socket = s; 40 socket = s;
43 } 41 }
44 42
  43 + public void sendMessage(String message) throws IOException
  44 + {
  45 + socket.sendMsg(message);
  46 + }
  47 +
45 public void run() 48 public void run()
46 { 49 {
47 while(!kill) 50 while(!kill)
@@ -60,45 +63,88 @@ public class Connection extends Thread @@ -60,45 +63,88 @@ public class Connection extends Thread
60 e.printStackTrace(); 63 e.printStackTrace();
61 } 64 }
62 } 65 }
63 - String str = socket.recvMsg();  
64 - serv.addToChatroom(this, str);  
65 if(!kill) 66 if(!kill)
66 { 67 {
67 - while(true) 68 + String str;
  69 + try
68 { 70 {
69 str = socket.recvMsg(); 71 str = socket.recvMsg();
70 - if(str != null) 72 + while(str.contains(" "))
71 { 73 {
72 - try 74 + socket.sendMsg("CHATNICKINVALID");
  75 + str = socket.recvMsg();
  76 + }
  77 + while(serv.isOnline(str))
  78 + {
  79 + socket.sendMsg("CHATNICKEXIST");
  80 + str = socket.recvMsg();
  81 + }
  82 + socket.sendMsg("CHATOK");
  83 + serv.addToChatroom(this, str);
  84 + }
  85 + catch (IOException e)
  86 + {
  87 + if(!kill)
  88 + {
  89 + System.out.println("TCP: Communication with client failed while entering chatroom");
  90 + sleep = true;
  91 + serv.finishWorker(this);
  92 + }
  93 + continue;
  94 + }
  95 + while(true)
  96 + {
  97 + try
  98 + {
  99 + str = "";
  100 + str = socket.recvMsg();
  101 + if(str.equals("/disconnect"))
73 { 102 {
74 - if(str.equals("/disconnect"))  
75 - {  
76 - socket.sendMsg("DISC_OK");  
77 - kill = true;  
78 - System.out.println(serv.getNickname(this) + " disconnected");  
79 - break;  
80 - }  
81 - else if(str.equals("/exit")) 103 + socket.sendMsg("DISC_OK");
  104 + System.out.println(serv.getNickname(this) + " disconnected");
  105 + break;
  106 + }
  107 + else if(str.equals("/exit"))
  108 + {
  109 + socket.sendMsg("EXIT_OK");
  110 + System.out.println(serv.getNickname(this) + " disconnected");
  111 + break;
  112 + }
  113 + else if(str.equals("/who"))
  114 + {
  115 + socket.sendMsg(serv.listOnline());
  116 + }
  117 + else if(str.startsWith("@"))
  118 + {
  119 + try
82 { 120 {
83 - socket.sendMsg("EXIT_OK");  
84 - kill = true;  
85 - System.out.println(serv.getNickname(this) + " disconnected");  
86 - break; 121 + if(!str.contains(" "))
  122 + {
  123 + serv.sendTo(this,str.substring(1),"");
  124 + }
  125 + else
  126 + {
  127 + serv.sendTo(this,str.substring(1,str.indexOf(' ')),str.substring(str.indexOf(' ')+1));
  128 + }
87 } 129 }
88 - else 130 + catch(ChatException cE)
89 { 131 {
90 - System.out.println("FROM " + serv.getNickname(this) + ": " + str);  
91 - serv.sendToChat(this,str); 132 + socket.sendMsg(cE.getMessage());
92 } 133 }
93 } 134 }
94 - catch(IOException ioExc) 135 + else if(str.equals(""))
95 { 136 {
96 - System.out.println("TCP: Error writing to socket");  
97 break; 137 break;
98 } 138 }
  139 + else
  140 + {
  141 + System.out.println("FROM " + serv.getNickname(this) + ": " + str);
  142 + serv.sendToChat(this,str);
  143 + }
99 } 144 }
100 - else 145 + catch(IOException ioExc)
101 { 146 {
  147 + System.out.println("TCP: Error writing to socket");
102 break; 148 break;
103 } 149 }
104 } 150 }
@@ -107,5 +153,4 @@ public class Connection extends Thread @@ -107,5 +153,4 @@ public class Connection extends Thread
107 serv.finishWorker(this); 153 serv.finishWorker(this);
108 } 154 }
109 } 155 }
110 -  
111 } 156 }
JChatServer/src/pad/prac2/JChat.java
@@ -25,7 +25,7 @@ public class JChat @@ -25,7 +25,7 @@ public class JChat
25 { 25 {
26 public void run() 26 public void run()
27 { 27 {
28 - System.out.println("JChat: interrupt catched, killing server..."); 28 + System.out.println("JChat: Caught interrupt, killing server...");
29 serv.killServer(); 29 serv.killServer();
30 } 30 }
31 }); 31 });
@@ -34,8 +34,6 @@ public class JChat @@ -34,8 +34,6 @@ public class JChat
34 /* 34 /*
35 * TODO 35 * TODO
36 * 36 *
37 - * unicast message  
38 - * list nicks  
39 - * disconnect/reconnect successfully 37 + * CTRL+C
40 */ 38 */
41 } 39 }
JChatServer/src/pad/prac2/MyServerSocket.java
@@ -12,22 +12,6 @@ public class MyServerSocket extends ServerSocket @@ -12,22 +12,6 @@ public class MyServerSocket extends ServerSocket
12 super(); 12 super();
13 } 13 }
14 14
15 - public MySocket accept()  
16 - {  
17 - try  
18 - {  
19 - MySocket incoming = new MySocket();  
20 - super.implAccept(incoming);  
21 - incoming.initializeStreams();  
22 - return incoming;  
23 - }  
24 - catch(IOException ioExc)  
25 - {  
26 - System.out.println("TCP: Error accepting connection");  
27 - return null;  
28 - }  
29 - }  
30 -  
31 public void bind(String ip, int port) 15 public void bind(String ip, int port)
32 { 16 {
33 SocketAddress addr = new InetSocketAddress(ip,port); 17 SocketAddress addr = new InetSocketAddress(ip,port);
@@ -41,6 +25,14 @@ public class MyServerSocket extends ServerSocket @@ -41,6 +25,14 @@ public class MyServerSocket extends ServerSocket
41 } 25 }
42 } 26 }
43 27
  28 + public MySocket accept() throws IOException
  29 + {
  30 + MySocket incoming = new MySocket();
  31 + super.implAccept(incoming);
  32 + incoming.initializeStreams();
  33 + return incoming;
  34 + }
  35 +
44 public void close() 36 public void close()
45 { 37 {
46 try 38 try
JChatServer/src/pad/prac2/MySocket.java
@@ -45,28 +45,13 @@ public class MySocket extends Socket @@ -45,28 +45,13 @@ public class MySocket extends Socket
45 } 45 }
46 } 46 }
47 47
48 - public void close()  
49 - {  
50 - try  
51 - {  
52 - super.shutdownInput();  
53 - super.shutdownOutput();  
54 - super.close();  
55 - }  
56 - catch(IOException ioExc)  
57 - {  
58 - System.out.println("TCP: Error while closing socket");  
59 - }  
60 - }  
61 -  
62 public void sendMsg(String msg) throws IOException 48 public void sendMsg(String msg) throws IOException
63 { 49 {
64 String length = new Integer(msg.length()).toString(); 50 String length = new Integer(msg.length()).toString();
65 - this.write(length + '\0');  
66 - this.write(msg); 51 + this.write(length + '\0' + msg);
67 } 52 }
68 53
69 - public String recvMsg() 54 + public String recvMsg() throws IOException
70 { 55 {
71 String len,str; 56 String len,str;
72 int length; 57 int length;
@@ -100,28 +85,34 @@ public class MySocket extends Socket @@ -100,28 +85,34 @@ public class MySocket extends Socket
100 } 85 }
101 } 86 }
102 87
103 - public String readLine() 88 + public String readLine() throws IOException
104 { 89 {
105 - try 90 +
  91 + String line = "";
  92 + char[] c = new char[1];
  93 + while(true)
106 { 94 {
107 - String line = "";  
108 - char[] c = new char[1];  
109 - while(true) 95 + input.read(c,0,1);
  96 + if(c[0] == '\0')
110 { 97 {
111 - input.read(c,0,1);  
112 - if(c[0] == '\0')  
113 - {  
114 - break;  
115 - }  
116 - line += c[0]; 98 + break;
117 } 99 }
118 - return line; 100 + line += c[0];
  101 + }
  102 + return line;
  103 + }
  104 +
  105 + public void close()
  106 + {
  107 + try
  108 + {
  109 + super.shutdownInput();
  110 + super.shutdownOutput();
  111 + super.close();
119 } 112 }
120 catch(IOException ioExc) 113 catch(IOException ioExc)
121 { 114 {
122 - System.out.println("TCP: Error retrieving data from remote endpoint");  
123 - return null; 115 + System.out.println("TCP: Error while closing socket");
124 } 116 }
125 } 117 }
126 -  
127 } 118 }
128 \ No newline at end of file 119 \ No newline at end of file
JChatServer/src/pad/prac2/Server.java
1 package pad.prac2; 1 package pad.prac2;
2 2
3 import java.io.IOException; 3 import java.io.IOException;
  4 +import java.util.Collection;
4 import java.util.Iterator; 5 import java.util.Iterator;
5 import java.util.Set; 6 import java.util.Set;
6 import java.util.concurrent.ConcurrentHashMap; 7 import java.util.concurrent.ConcurrentHashMap;
@@ -44,35 +45,24 @@ public class Server @@ -44,35 +45,24 @@ public class Server
44 } 45 }
45 } 46 }
46 47
47 - public void sendToChat(Connection origin, String message) throws IOException  
48 - {  
49 - lock.lock();  
50 - String nickname = activeConnections.get(origin);  
51 - Set<Connection> connections = activeConnections.keySet();  
52 - Iterator<Connection> it = connections.iterator();  
53 - Connection conn;  
54 - while(it.hasNext())  
55 - {  
56 - conn = it.next();  
57 - if(conn != origin)  
58 - {  
59 - conn.sendMessage(nickname + ": " + message);  
60 - }  
61 - }  
62 - lock.unlock();  
63 - }  
64 -  
65 public void startServer() 48 public void startServer()
66 { 49 {
67 while(!kill) 50 while(!kill)
68 { 51 {
69 - MySocket incoming = ss.accept();  
70 - if(incoming != null) 52 + try
71 { 53 {
  54 + MySocket incoming = ss.accept();
72 System.out.println("Accepted connection from " + incoming.getInetAddress()); 55 System.out.println("Accepted connection from " + incoming.getInetAddress());
73 -  
74 startWorker(incoming); 56 startWorker(incoming);
75 } 57 }
  58 + catch(IOException ioExc)
  59 + {
  60 + if(!kill)
  61 + {
  62 + System.out.println("TCP: Error accepting connection");
  63 + break;
  64 + }
  65 + }
76 } 66 }
77 67
78 } 68 }
@@ -84,14 +74,20 @@ public class Server @@ -84,14 +74,20 @@ public class Server
84 { 74 {
85 try 75 try
86 { 76 {
87 - lock.unlock();  
88 - availableWorkers.await();  
89 - lock.lock(); 77 + s.sendMsg("CHATFULL");
  78 + synchronized(this)
  79 + {
  80 + availableWorkers.await();
  81 + }
90 } 82 }
91 catch(InterruptedException intExc) 83 catch(InterruptedException intExc)
92 { 84 {
93 intExc.printStackTrace(); 85 intExc.printStackTrace();
94 } 86 }
  87 + catch(IOException ioExc)
  88 + {
  89 + System.out.println("TCP: Error while sending message to client");
  90 + }
95 } 91 }
96 workerPool[roomSize - freeWorkers].setSock(s); 92 workerPool[roomSize - freeWorkers].setSock(s);
97 workerPool[roomSize - freeWorkers].awake(); 93 workerPool[roomSize - freeWorkers].awake();
@@ -100,34 +96,91 @@ public class Server @@ -100,34 +96,91 @@ public class Server
100 lock.unlock(); 96 lock.unlock();
101 } 97 }
102 98
103 - public String getNickname(Connection c)  
104 - {  
105 - return activeConnections.get(c);  
106 - }  
107 -  
108 public void finishWorker(Connection c) 99 public void finishWorker(Connection c)
109 { 100 {
110 lock.lock(); 101 lock.lock();
  102 + removeFromChatroom(c);
111 freeWorkers++; 103 freeWorkers++;
112 workerPool[roomSize - freeWorkers] = c; 104 workerPool[roomSize - freeWorkers] = c;
113 availableWorkers.signal(); 105 availableWorkers.signal();
114 lock.unlock(); 106 lock.unlock();
115 } 107 }
116 108
  109 + public void sendTo(Connection orig, String nick, String msg) throws IOException, ChatException
  110 + {
  111 + lock.lock();
  112 + System.out.println("FROM " + getNickname(orig) + " TO " + nick + ": " + msg);
  113 + msg = getNickname(orig) + ": " + msg;
  114 + Set<Connection> conns = activeConnections.keySet();
  115 + Iterator<Connection> it = conns.iterator();
  116 + Connection dest;
  117 + while(it.hasNext())
  118 + {
  119 + dest = it.next();
  120 + if(getNickname(dest).equals(nick))
  121 + {
  122 + dest.sendMessage(msg);
  123 + lock.unlock();
  124 + return;
  125 + }
  126 + }
  127 + lock.unlock();
  128 + throw new ChatException("No such nickname");
  129 + }
  130 +
  131 + public void sendToChat(Connection origin, String message) throws IOException
  132 + {
  133 + lock.lock();
  134 + String nickname = activeConnections.get(origin);
  135 + Set<Connection> connections = activeConnections.keySet();
  136 + Iterator<Connection> it = connections.iterator();
  137 + Connection conn;
  138 + while(it.hasNext())
  139 + {
  140 + conn = it.next();
  141 + if(conn != origin)
  142 + {
  143 + conn.sendMessage(nickname + ": " + message);
  144 + }
  145 + }
  146 + lock.unlock();
  147 + }
  148 +
  149 + public String getNickname(Connection c)
  150 + {
  151 + return activeConnections.get(c);
  152 + }
  153 +
117 public void addToChatroom(Connection c, String nickName) 154 public void addToChatroom(Connection c, String nickName)
118 { 155 {
119 activeConnections.put(c, nickName); 156 activeConnections.put(c, nickName);
120 System.out.println(nickName + " has entered the room"); 157 System.out.println(nickName + " has entered the room");
121 } 158 }
122 159
123 - public void finishConnections() 160 + private void removeFromChatroom(Connection c)
124 { 161 {
125 - Set<Connection> conns = activeConnections.keySet();  
126 - Iterator<Connection> it = conns.iterator(); 162 + activeConnections.remove(c);
  163 + }
  164 +
  165 + public boolean isOnline(String nick)
  166 + {
  167 + return activeConnections.contains(nick);
  168 + }
  169 +
  170 + public String listOnline()
  171 + {
  172 + lock.lock();
  173 + String ret = new Integer(activeConnections.size()).toString();
  174 + ret += " people currently online:";
  175 + Collection<String> nickNames = activeConnections.values();
  176 + Iterator<String> it = nickNames.iterator();
127 while(it.hasNext()) 177 while(it.hasNext())
128 { 178 {
129 - it.next().finish(); 179 + ret += "\n";
  180 + ret += it.next();
130 } 181 }
  182 + lock.unlock();
  183 + return ret;
131 } 184 }
132 185
133 public void killServer() 186 public void killServer()
@@ -136,4 +189,14 @@ public class Server @@ -136,4 +189,14 @@ public class Server
136 ss.close(); 189 ss.close();
137 finishConnections(); 190 finishConnections();
138 } 191 }
  192 +
  193 + public void finishConnections()
  194 + {
  195 + Set<Connection> conns = activeConnections.keySet();
  196 + Iterator<Connection> it = conns.iterator();
  197 + while(it.hasNext())
  198 + {
  199 + it.next().finish();
  200 + }
  201 + }
139 } 202 }