package pad.prac2; import java.io.IOException; import java.util.Collection; import java.util.Iterator; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Server { private MyServerSocket ss; private int roomSize; private boolean kill; private Connection[] workerPool; private int freeWorkers; private Lock lock; private Condition availableWorkers; private ConcurrentHashMap activeConnections; public Server(String ip, int port, int rS) { try { ss = new MyServerSocket(); lock = new ReentrantLock(); activeConnections = new ConcurrentHashMap(); roomSize = rS; freeWorkers = roomSize; kill = false; availableWorkers = lock.newCondition(); workerPool = new Connection[roomSize]; for(int i = 0; i < roomSize; i++) { workerPool[i] = new Connection(this); workerPool[i].start(); } ss.bind(ip, port); } catch(IOException ioExc) { System.out.println("TCP: Error initializating server socket"); } } public void startServer() { while(!kill) { try { MySocket incoming = ss.accept(); System.out.println("Accepted connection from " + incoming.getInetAddress()); startWorker(incoming); } catch(IOException ioExc) { if(!kill) { System.out.println("TCP: Error accepting connection"); break; } } } } public void startWorker(MySocket s) { lock.lock(); while(freeWorkers == 0) { try { s.sendMsg("CHATFULL"); synchronized(this) { availableWorkers.await(); } } catch(InterruptedException intExc) { intExc.printStackTrace(); } catch(IOException ioExc) { System.out.println("TCP: Error while sending message to client"); } } workerPool[roomSize - freeWorkers].setSock(s); workerPool[roomSize - freeWorkers].awake(); workerPool[roomSize - freeWorkers] = null; freeWorkers--; lock.unlock(); } public void finishWorker(Connection c) { lock.lock(); removeFromChatroom(c); freeWorkers++; workerPool[roomSize - freeWorkers] = c; availableWorkers.signal(); lock.unlock(); } public void sendTo(Connection orig, String nick, String msg) throws IOException, ChatException { lock.lock(); System.out.println("FROM " + getNickname(orig) + " TO " + nick + ": " + msg); msg = getNickname(orig) + ": " + msg; Set conns = activeConnections.keySet(); Iterator it = conns.iterator(); Connection dest; while(it.hasNext()) { dest = it.next(); if(getNickname(dest).equals(nick)) { dest.sendMessage(msg); lock.unlock(); return; } } lock.unlock(); throw new ChatException("No such nickname"); } public void sendToChat(Connection origin, String message) throws IOException { lock.lock(); String nickname = activeConnections.get(origin); Set connections = activeConnections.keySet(); Iterator it = connections.iterator(); Connection conn; while(it.hasNext()) { conn = it.next(); if(conn != origin) { conn.sendMessage(nickname + ": " + message); } } lock.unlock(); } public String getNickname(Connection c) { return activeConnections.get(c); } public void addToChatroom(Connection c, String nickName) { activeConnections.put(c, nickName); System.out.println(nickName + " has entered the room"); } private void removeFromChatroom(Connection c) { activeConnections.remove(c); } public boolean isOnline(String nick) { return activeConnections.contains(nick); } public String listOnline() { lock.lock(); String ret = new Integer(activeConnections.size()).toString(); ret += " people currently online:"; Collection nickNames = activeConnections.values(); Iterator it = nickNames.iterator(); while(it.hasNext()) { ret += "\n"; ret += it.next(); } lock.unlock(); return ret; } public void killServer() { kill = true; ss.close(); finishConnections(); } public void finishConnections() { Set conns = activeConnections.keySet(); Iterator it = conns.iterator(); while(it.hasNext()) { it.next().finish(); } } }