Server.java 4.63 KB
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<Connection,String> activeConnections;
	
	public Server(String ip, int port, int rS)
	{
		try
		{
			ss = new MyServerSocket();
			lock = new ReentrantLock();
			activeConnections = new ConcurrentHashMap<Connection,String>();
			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();
				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");
				s.close();
				lock.unlock();
				return;
			}
			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<Connection> conns = activeConnections.keySet();
		Iterator<Connection> it = conns.iterator();
		Connection dest;
		while(it.hasNext())
		{
			dest = it.next();
			if(getNickname(dest).equals(nick))
			{
				dest.sendMessage("1"+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<Connection> connections = activeConnections.keySet();
		Iterator<Connection> it = connections.iterator();
		Connection conn;
		while(it.hasNext())
		{
			conn = it.next();
			if(conn != origin)
			{
				conn.sendMessage("0"+nickname + ": " + message);
			}
		}
		lock.unlock();
	}
	
	public String getNickname(Connection c)
	{
		return activeConnections.get(c);
	}
	
	public void notifyAllConnections()
	{
		lock.lock();
		Set<Connection> connections = activeConnections.keySet();
		Iterator<Connection> it = connections.iterator();
		Connection conn;
		while(it.hasNext())
		{
			conn = it.next();
			try
			{
				conn.sendMessage("USERLIST"+nickList());
			}
			catch(IOException ioExc)
			{
				System.out.println("TCP: Error writing to socket");
			}
		}
		lock.unlock();
	}
	
	public void addToChatroom(Connection c, String nickName)
	{
		activeConnections.put(c, nickName);
		System.out.println(nickName + " has entered the room");
		notifyAllConnections();
	}
	
	private void removeFromChatroom(Connection c)
	{
		activeConnections.remove(c);
		notifyAllConnections();
	}
	
	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:\n";
		ret += nickList();
		lock.unlock();
		return ret;
	}
	
	public String nickList()
	{
		String ret = "";
		Collection<String> nickNames = activeConnections.values();
		Iterator<String> it = nickNames.iterator();
		while(it.hasNext())
		{
			ret += it.next();
			ret += "\n";
		}
		return ret;
	}
	
	public void killServer()
	{
		kill = true;
		ss.close();
		finishConnections();
	}
	
	public void finishConnections()
	{
		Set<Connection> conns = activeConnections.keySet();
		Iterator<Connection> it = conns.iterator();
		while(it.hasNext())
		{
			it.next().finish();
		}
	}
}