Commit e5db999b31e67683ad0e75b2e3ae4bc255dac6d7

Authored by Imanol-Mikel Barba Sabariego
1 parent 823b4632

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

JChatServer/.classpath 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<classpath>
  3 + <classpathentry kind="src" path="src"/>
  4 + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
  5 + <classpathentry kind="output" path="bin"/>
  6 +</classpath>
JChatServer/.project 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<projectDescription>
  3 + <name>JChatServer</name>
  4 + <comment></comment>
  5 + <projects>
  6 + </projects>
  7 + <buildSpec>
  8 + <buildCommand>
  9 + <name>org.eclipse.jdt.core.javabuilder</name>
  10 + <arguments>
  11 + </arguments>
  12 + </buildCommand>
  13 + </buildSpec>
  14 + <natures>
  15 + <nature>org.eclipse.jdt.core.javanature</nature>
  16 + </natures>
  17 +</projectDescription>
JChatServer/.settings/org.eclipse.jdt.core.prefs 0 → 100644
  1 +eclipse.preferences.version=1
  2 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
  3 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
  4 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
  5 +org.eclipse.jdt.core.compiler.compliance=1.7
  6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate
  7 +org.eclipse.jdt.core.compiler.debug.localVariable=generate
  8 +org.eclipse.jdt.core.compiler.debug.sourceFile=generate
  9 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
  10 +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
  11 +org.eclipse.jdt.core.compiler.source=1.7
JChatServer/bin/pad/prac2/ChatException.class 0 → 100644
No preview for this file type
JChatServer/bin/pad/prac2/Connection.class 0 → 100644
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/JChat.class 0 → 100644
No preview for this file type
JChatServer/bin/pad/prac2/MyServerSocket.class 0 → 100644
No preview for this file type
JChatServer/bin/pad/prac2/MySocket.class 0 → 100644
No preview for this file type
JChatServer/bin/pad/prac2/Server.class 0 → 100644
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 0 → 100644
  1 +package pad.prac2;
  2 +
  3 +import java.io.IOException;
  4 +
  5 +public class Connection extends Thread
  6 +{
  7 + private MySocket socket;
  8 + private Server serv;
  9 + private boolean sleep, kill;
  10 +
  11 + public Connection(Server s)
  12 + {
  13 + serv = s;
  14 + kill = false;
  15 + sleep = true;
  16 + }
  17 +
  18 + public void awake()
  19 + {
  20 + synchronized(this)
  21 + {
  22 + sleep = false;
  23 + this.notify();
  24 + }
  25 + }
  26 +
  27 + public void finish()
  28 + {
  29 + kill = true;
  30 + if(sleep)
  31 + {
  32 + sleep = false;
  33 + notify();
  34 + }
  35 + socket.close();
  36 + }
  37 +
  38 + public void setSock(MySocket s)
  39 + {
  40 + socket = s;
  41 + }
  42 +
  43 + public void sendMessage(String message) throws IOException
  44 + {
  45 + socket.sendMsg(message);
  46 + }
  47 +
  48 + public void run()
  49 + {
  50 + while(!kill)
  51 + {
  52 + while(sleep)
  53 + {
  54 + try
  55 + {
  56 + synchronized(this)
  57 + {
  58 + wait();
  59 + }
  60 + }
  61 + catch (InterruptedException e)
  62 + {
  63 + e.printStackTrace();
  64 + }
  65 + }
  66 + if(!kill)
  67 + {
  68 + String str;
  69 + try
  70 + {
  71 + str = socket.recvMsg();
  72 + while(str.contains(" "))
  73 + {
  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 = "/disconnect";
  100 + str = socket.recvMsg();
  101 + if(str.equals("/disconnect"))
  102 + {
  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
  120 + {
  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 + }
  129 + }
  130 + catch(ChatException cE)
  131 + {
  132 + socket.sendMsg(cE.getMessage());
  133 + }
  134 + }
  135 + else
  136 + {
  137 + System.out.println("FROM " + serv.getNickname(this) + ": " + str);
  138 + serv.sendToChat(this,str);
  139 + }
  140 + }
  141 + catch(IOException ioExc)
  142 + {
  143 + System.out.println("TCP: Error writing to socket");
  144 + System.out.println(serv.getNickname(this) + " disconnected");
  145 + break;
  146 + }
  147 + }
  148 + sleep = true;
  149 + }
  150 + serv.finishWorker(this);
  151 + }
  152 + }
  153 +}
JChatServer/src/pad/prac2/JChat.java 0 → 100644
  1 +package pad.prac2;
  2 +
  3 +import java.util.Scanner;
  4 +
  5 +public class JChat
  6 +{
  7 + public static void main(String[] args)
  8 + {
  9 + String ip;
  10 + int port, roomSize;
  11 + Scanner in = new Scanner(System.in);
  12 + System.out.print("IP: ");
  13 + ip = in.nextLine();
  14 + System.out.print("Port: ");
  15 + port = in.nextInt();
  16 + System.out.print("Size of chatroom: ");
  17 + roomSize = in.nextInt();
  18 + in.close();
  19 + final Server serv = new Server(ip,port,roomSize);
  20 + Runtime.getRuntime().addShutdownHook(new Thread()
  21 + {
  22 + public void run()
  23 + {
  24 + System.out.println("JChat: Caught interrupt, killing server...");
  25 + serv.killServer();
  26 + }
  27 + });
  28 + serv.startServer();
  29 + }
  30 +}
JChatServer/src/pad/prac2/MyServerSocket.java 0 → 100644
  1 +package pad.prac2;
  2 +
  3 +import java.io.IOException;
  4 +import java.net.InetSocketAddress;
  5 +import java.net.ServerSocket;
  6 +import java.net.SocketAddress;
  7 +
  8 +public class MyServerSocket extends ServerSocket
  9 +{
  10 + public MyServerSocket() throws IOException
  11 + {
  12 + super();
  13 + }
  14 +
  15 + public void bind(String ip, int port)
  16 + {
  17 + SocketAddress addr = new InetSocketAddress(ip,port);
  18 + try
  19 + {
  20 + super.bind(addr, 5);
  21 + }
  22 + catch(IOException ioExc)
  23 + {
  24 + System.out.println("TCP: Error binding socket to address");
  25 + }
  26 + }
  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 +
  36 + public void close()
  37 + {
  38 + try
  39 + {
  40 + super.close();
  41 + }
  42 + catch(IOException ioExc)
  43 + {
  44 + System.out.println("TCP: Error while closing socket");
  45 + }
  46 + }
  47 +}
JChatServer/src/pad/prac2/MySocket.java 0 → 100644
  1 +package pad.prac2;
  2 +
  3 +import java.io.BufferedReader;
  4 +import java.io.IOException;
  5 +import java.io.InputStreamReader;
  6 +import java.io.OutputStream;
  7 +import java.net.InetSocketAddress;
  8 +import java.net.Socket;
  9 +import java.net.SocketAddress;
  10 +
  11 +public class MySocket extends Socket
  12 +{
  13 + private BufferedReader input;
  14 + private OutputStream output;
  15 +
  16 + public MySocket()
  17 + {
  18 + super();
  19 + }
  20 +
  21 + public void connect(String host, int port)
  22 + {
  23 + SocketAddress addr = new InetSocketAddress(host,port);
  24 + try
  25 + {
  26 + super.connect(addr);
  27 + initializeStreams();
  28 + }
  29 + catch(IOException ioExc)
  30 + {
  31 + System.out.println("TCP: Error occured while connecting to remote host");
  32 + }
  33 + }
  34 +
  35 + public void initializeStreams()
  36 + {
  37 + try
  38 + {
  39 + output = super.getOutputStream();
  40 + input = new BufferedReader(new InputStreamReader(super.getInputStream()));
  41 + }
  42 + catch(IOException ioExc)
  43 + {
  44 + System.out.println("TCP: Error initializing socket");
  45 + }
  46 + }
  47 +
  48 + public void sendMsg(String msg) throws IOException
  49 + {
  50 + String length = new Integer(msg.length()).toString();
  51 + this.write(length + '\0' + msg);
  52 + }
  53 +
  54 + public String recvMsg() throws IOException
  55 + {
  56 + String len,str;
  57 + int length;
  58 + len = this.readLine();
  59 + if(len == "")
  60 + {
  61 + return len;
  62 + }
  63 + length = Integer.parseInt(len);
  64 + str = this.read(length);
  65 + return str;
  66 + }
  67 +
  68 + public void write(String str) throws IOException
  69 + {
  70 + output.write(str.getBytes());
  71 + }
  72 +
  73 + public String read(int bytes)
  74 + {
  75 + char[] buffer = new char[bytes];
  76 + try
  77 + {
  78 + input.read(buffer, 0, bytes);
  79 + return new String(buffer);
  80 + }
  81 + catch(IOException ioExc)
  82 + {
  83 + System.out.println("TCP: Error retrieving data from remote endpoint");
  84 + return null;
  85 + }
  86 + }
  87 +
  88 + public String readLine() throws IOException
  89 + {
  90 +
  91 + String line = "";
  92 + char[] c = new char[1];
  93 + while(true)
  94 + {
  95 + input.read(c,0,1);
  96 + if(c[0] == '\0')
  97 + {
  98 + break;
  99 + }
  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();
  112 + }
  113 + catch(IOException ioExc)
  114 + {
  115 + System.out.println("TCP: Error while closing socket");
  116 + }
  117 + }
  118 +}
0 \ No newline at end of file 119 \ No newline at end of file
JChatServer/src/pad/prac2/Server.java 0 → 100644
  1 +package pad.prac2;
  2 +
  3 +import java.io.IOException;
  4 +import java.util.Collection;
  5 +import java.util.Iterator;
  6 +import java.util.Set;
  7 +import java.util.concurrent.ConcurrentHashMap;
  8 +import java.util.concurrent.locks.Condition;
  9 +import java.util.concurrent.locks.Lock;
  10 +import java.util.concurrent.locks.ReentrantLock;
  11 +
  12 +public class Server
  13 +{
  14 + private MyServerSocket ss;
  15 + private int roomSize;
  16 + private boolean kill;
  17 + private Connection[] workerPool;
  18 + private int freeWorkers;
  19 + private Lock lock;
  20 + private Condition availableWorkers;
  21 + private ConcurrentHashMap<Connection,String> activeConnections;
  22 +
  23 + public Server(String ip, int port, int rS)
  24 + {
  25 + try
  26 + {
  27 + ss = new MyServerSocket();
  28 + lock = new ReentrantLock();
  29 + activeConnections = new ConcurrentHashMap<Connection,String>();
  30 + roomSize = rS;
  31 + freeWorkers = roomSize;
  32 + kill = false;
  33 + availableWorkers = lock.newCondition();
  34 + workerPool = new Connection[roomSize];
  35 + for(int i = 0; i < roomSize; i++)
  36 + {
  37 + workerPool[i] = new Connection(this);
  38 + workerPool[i].start();
  39 + }
  40 + ss.bind(ip, port);
  41 + }
  42 + catch(IOException ioExc)
  43 + {
  44 + System.out.println("TCP: Error initializating server socket");
  45 + }
  46 + }
  47 +
  48 + public void startServer()
  49 + {
  50 + while(!kill)
  51 + {
  52 + try
  53 + {
  54 + MySocket incoming = ss.accept();
  55 + startWorker(incoming);
  56 + }
  57 + catch(IOException ioExc)
  58 + {
  59 + if(!kill)
  60 + {
  61 + System.out.println("TCP: Error accepting connection");
  62 + break;
  63 + }
  64 + }
  65 + }
  66 +
  67 + }
  68 +
  69 + public void startWorker(MySocket s)
  70 + {
  71 + lock.lock();
  72 + while(freeWorkers == 0)
  73 + {
  74 + try
  75 + {
  76 + s.sendMsg("CHATFULL");
  77 + s.close();
  78 + lock.unlock();
  79 + return;
  80 + }
  81 + catch(IOException ioExc)
  82 + {
  83 + System.out.println("TCP: Error while sending message to client");
  84 + }
  85 + }
  86 + workerPool[roomSize - freeWorkers].setSock(s);
  87 + workerPool[roomSize - freeWorkers].awake();
  88 + workerPool[roomSize - freeWorkers] = null;
  89 + freeWorkers--;
  90 + lock.unlock();
  91 + }
  92 +
  93 + public void finishWorker(Connection c)
  94 + {
  95 + lock.lock();
  96 + removeFromChatroom(c);
  97 + freeWorkers++;
  98 + workerPool[roomSize - freeWorkers] = c;
  99 + availableWorkers.signal();
  100 + lock.unlock();
  101 + }
  102 +
  103 + public void sendTo(Connection orig, String nick, String msg) throws IOException, ChatException
  104 + {
  105 + lock.lock();
  106 + System.out.println("FROM " + getNickname(orig) + " TO " + nick + ": " + msg);
  107 + msg = getNickname(orig) + ": " + msg;
  108 + Set<Connection> conns = activeConnections.keySet();
  109 + Iterator<Connection> it = conns.iterator();
  110 + Connection dest;
  111 + while(it.hasNext())
  112 + {
  113 + dest = it.next();
  114 + if(getNickname(dest).equals(nick))
  115 + {
  116 + dest.sendMessage(msg);
  117 + lock.unlock();
  118 + return;
  119 + }
  120 + }
  121 + lock.unlock();
  122 + throw new ChatException("No such nickname");
  123 + }
  124 +
  125 + public void sendToChat(Connection origin, String message) throws IOException
  126 + {
  127 + lock.lock();
  128 + String nickname = activeConnections.get(origin);
  129 + Set<Connection> connections = activeConnections.keySet();
  130 + Iterator<Connection> it = connections.iterator();
  131 + Connection conn;
  132 + while(it.hasNext())
  133 + {
  134 + conn = it.next();
  135 + if(conn != origin)
  136 + {
  137 + conn.sendMessage(nickname + ": " + message);
  138 + }
  139 + }
  140 + lock.unlock();
  141 + }
  142 +
  143 + public String getNickname(Connection c)
  144 + {
  145 + return activeConnections.get(c);
  146 + }
  147 +
  148 + public void addToChatroom(Connection c, String nickName)
  149 + {
  150 + activeConnections.put(c, nickName);
  151 + System.out.println(nickName + " has entered the room");
  152 + }
  153 +
  154 + private void removeFromChatroom(Connection c)
  155 + {
  156 + activeConnections.remove(c);
  157 + }
  158 +
  159 + public boolean isOnline(String nick)
  160 + {
  161 + return activeConnections.contains(nick);
  162 + }
  163 +
  164 + public String listOnline()
  165 + {
  166 + lock.lock();
  167 + String ret = new Integer(activeConnections.size()).toString();
  168 + ret += " people currently online:";
  169 + Collection<String> nickNames = activeConnections.values();
  170 + Iterator<String> it = nickNames.iterator();
  171 + while(it.hasNext())
  172 + {
  173 + ret += "\n";
  174 + ret += it.next();
  175 + }
  176 + lock.unlock();
  177 + return ret;
  178 + }
  179 +
  180 + public void killServer()
  181 + {
  182 + kill = true;
  183 + ss.close();
  184 + finishConnections();
  185 + }
  186 +
  187 + public void finishConnections()
  188 + {
  189 + Set<Connection> conns = activeConnections.keySet();
  190 + Iterator<Connection> it = conns.iterator();
  191 + while(it.hasNext())
  192 + {
  193 + it.next().finish();
  194 + }
  195 + }
  196 +}