package call; import java.awt.Color; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.util.Arrays; import java.util.List; import org.apache.commons.lang3.StringUtils; public class Server extends AbstractId implements Runnable { public Server() {} private boolean listening = false; private int[] openPorts = new int[] {}; @Override public void run() { listening = true; while (listening) { ServerSocket serverSocket1 = openServerSocket(Config.DEFAULT_PORT); int normalport = serverSocket1.getLocalPort(); ServerSocket serverSocket2 = openServerSocket(Config.DEFAULT_PORT + Config.DEFAULT_PORT_OFFSET_CALL); int callport = serverSocket2.getLocalPort(); ServerSocket serverSocket3 = openServerSocket(Config.DEFAULT_PORT + Config.DEFAULT_PORT_OFFSET_CHAT); int chatport = serverSocket3.getLocalPort(); openPorts = new int[] { normalport, callport, chatport }; Config.CURRENT_PORT = normalport; new Thread(new UpnpClient(new int[] { normalport, callport, chatport }), "UpnpClient").start(); Thread listen1 = new Thread(new Listener(this, serverSocket1), "Server.Listener"); Thread listen2 = new Thread(new Listener(this, serverSocket2), "Server.Listener"); listen1.start(); listen2.start(); Util.joinThreads(listen1, listen2); } } private ServerSocket openServerSocket(int port) { ServerSocket serverSocket = null; while (serverSocket == null) { try { serverSocket = new ServerSocket(port); break; } catch (IOException e) { System.err.println("Could not listen on port: " + port + "."); serverSocket = null; Util.sleep(1000); port += 10; } } System.out.println("Server listening on port: " + port); return serverSocket; } public boolean isListening() { return listening; } public void close() { listening = false; } @Override public String toString() { return "0.0.0.0:[" + StringUtils.join(Arrays.asList(openPorts), ",") + "]"; } @Override public String getId() { return toString(); } private static class Listener implements Runnable { private final Server server; private final ServerSocket serversocket; public Listener(Server server, ServerSocket serversocket) { this.server = server; this.serversocket = serversocket; } @Override public void run() { while (server.isListening()) { try { final Socket socket = serversocket.accept(); new Thread(new Acceptor(socket), "Server.Acceptor").start(); } catch (IOException e) { System.out.println("Error in call accept loop (class Server.Listener)!"); e.printStackTrace(); } } } } private static class Acceptor implements Runnable { final Socket socket; public Acceptor(Socket socket) { this.socket = socket; } @Override public void run() { try { handle(); } catch (SocketException e) {} catch (IOException e) { System.out.println("Error in call accept loop (class Acceptor)!"); e.printStackTrace(); } } private void handle() throws IOException { socket.setReuseAddress(true); socket.setTcpNoDelay(true); SocketUtil.writeHeaders(socket.getOutputStream(), SocketUtil.RequestType.ServerCall); final InputStream instream = socket.getInputStream(); final List<String> headers = SocketUtil.readHeaders(instream); final String remoteuser = SocketUtil.getHeaderValue(headers, "user"); final String remotehost = socket.getInetAddress().getCanonicalHostName(); Contact contact; // loopback connection? if (Config.UID_S.equals(SocketUtil.getHeaderValue(headers, "UID"))) { contact = new Contact(remotehost, socket.getPort(), remoteuser, Contact.Reachability.LOOPBACK); } // normal connection else { contact = ContactList.findContact(remotehost, 0, remoteuser); if (contact == null) { contact = new Contact(remotehost, socket.getPort(), remoteuser, Contact.Reachability.UNREACHABLE); // System.out.println("No contact found for: " + // contact); } } // handle request final String request = SocketUtil.getHeaderValue(headers, "request"); if (request.toLowerCase().equals("status")) { // status connection socket.close(); } else if (request.toLowerCase().equals("ping")) { // ping connection PingClient client = new PingClient(contact, socket, headers); new Thread(client, "Server -> PingClient").start(); } else if (request.toLowerCase().equals("call")) { // call connection socket.setSoTimeout(Config.SOCKET_READ_TIMEOUT); if (!contact.isReachable()) { ContactList.addContact(contact); } CallClient client = new CallClient(contact, socket, headers); client.startCall(); Util.msg(contact).println("Incoming call.", Color.green); Util.log(contact, "Connected to call (Server)."); } else if (request.toLowerCase().equals("chat")) { // chat connection socket.setSoTimeout(Config.SOCKET_READ_TIMEOUT); if (!contact.isReachable()) { ContactList.addContact(contact); } ChatClient client = new ChatClient(contact, socket, headers); client.saveTo(new ChatCapture(contact)); new Thread(client, "Server -> ChatClient").start(); Util.log(contact, "Connected tp chat (Server)."); } else { // unknown connection Util.log(socket.toString(), "Fuck! Unknown connection type!"); for (String header : headers) { Util.log(socket.toString(), "header: " + header); } } } } }