import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Hashtable;
class Server {
private static int port = 1337;
public static void main(String[] args) {
ServerSocket server = null;
try {
server = new ServerSocket(port);
System.out.println("Server started!");
}
catch (IOException e) {
System.err.println("Couldn't listen on port " + port);
System.err.println(e);
System.exit(1);
}
Socket client = null;
while (true) {
try {
client = server.accept();
}
catch (IOException e) {
System.err.println("Accept failed.");
System.err.println(e);
System.exit(1);
}
Thread thread = new Thread(new ClientConnection(client));
thread.start();
}
}
}
class ChatServerProtocol {
private String nickname;
private ClientConnection connection;
private static Hashtable<String, ClientConnection> nicknames = new Hashtable<String, ClientConnection>();
private static final String msg_OK = "OK";
private static final String msg_NICK_IN_USE = "NICK IN USE";
private static final String msg_SPECIFY_NICK = "SPECIFY NICK";
private static final String msg_INVALID = "INVALIC COMMAND";
private static final String msg_SEND_FAILED = "FAILED TO SEND";
private static boolean addNick(String nick, ClientConnection connection) {
if (nicknames.containsKey(nick)) {
return false;
}
else {
nicknames.put(nick, connection);
return true;
}
}
public ChatServerProtocol(ClientConnection connection) {
nickname = null;
this.connection = connection;
}
private void log(String msg) {
System.err.println(msg);
}
public boolean isAuthenticated() {
return !(nickname == null);
}
private String authenticate(String msg) {
if (msg.startsWith("NICK")) {
String tryNick = msg.substring(5);
if (addNick(tryNick, this.connection)) {
log("User " + tryNick + " joined!");
this.nickname = tryNick;
return msg_OK;
}
else {
return msg_NICK_IN_USE;
}
}
else {
return msg_SPECIFY_NICK;
}
}
private boolean sendMsg(String recipient, String msg) {
if (nicknames.contains(recipient)) {
ClientConnection c = nicknames.get(recipient);
c.sendMsg(nickname + ": " + msg);
return true;
}
else {
return false;
}
}
public String process(String msg) {
if(!isAuthenticated()) {
return authenticate(msg);
}
String[] msg_parts = msg.split(" ", 3);
String msg_type = msg_parts[0];
if(msg_type.equals("MSG")) {
if(msg_parts.length < 3) return msg_INVALID;
if(sendMsg(msg_parts[1], msg_parts[2])) return msg_OK;
else return msg_SEND_FAILED;
} else {
return msg_INVALID;
}
}
}
class ClientConnection implements Runnable{
private Socket client;
private BufferedReader in;
private PrintWriter out;
ClientConnection(Socket client) {
this.client = client;
try {
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
out = new PrintWriter(client.getOutputStream(), true);
}catch (IOException e) {
System.err.println(e);
return;
}
}
public void run() {
String msg, response;
ChatServerProtocol protocol = new ChatServerProtocol(this);
try {
while((msg = in.readLine()) != null) {
response = protocol.process(msg);
out.println("SERVER: "+response);
}
}catch (IOException e) {
System.err.println(e);
}
}
public void sendMsg(String msg){
out.println(msg);
}
}