package com.cardshifter.server.model;
import java.net.InetSocketAddress;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.cardshifter.api.CardshifterSerializationException;
import com.cardshifter.api.serial.ByteTransformer;
import com.cardshifter.server.main.ServerConfiguration;
import net.zomis.cardshifter.ecs.usage.CardshifterIO;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
import com.cardshifter.api.ClientIO;
import com.cardshifter.server.clients.ClientWebSocket;
public class ServerWeb implements ConnectionHandler {
private static final Logger logger = LogManager.getLogger(ServerWeb.class);
private final InnerServer websocketServer;
/**
* Constructor.
* @param server Server instance
* @param config Uses the value of {@code config.getPortWebsocket} as port. If {@code port == 0} any available port
* is used and the real port number is set in {@code config} before returning.
*/
public ServerWeb(Server server, ServerConfiguration config) {
this.websocketServer = new InnerServer(server, config.getPortWebsocket());
config.setPortWebsocket(websocketServer.getPort());
}
private static class InnerServer extends WebSocketServer {
private final ByteTransformer transformer = CardshifterIO.createByteTransformer();
public InnerServer(Server server, int port) {
super(new InetSocketAddress(port));
this.webClients = new ConcurrentHashMap<>();
this.server = server;
}
private final Map<WebSocket, ClientWebSocket> webClients;
private final Server server;
@Override
public void onOpen(WebSocket conn, ClientHandshake handshake) {
logger.info("Connection opened: " + conn);
ClientWebSocket io = new ClientWebSocket(server, conn);
webClients.put(conn, io);
server.newClient(io);
}
@Override
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
logger.info("Connection closed: " + conn + " code " + code + " reason " + reason + " remote " + remote);
ClientIO io = webClients.remove(conn);
if (io == null) {
logger.error("Closing unknown ClientIO");
return;
}
io.close();
server.onDisconnected(io);
}
@Override
public void onMessage(WebSocket conn, String message) {
logger.info("Connection message from: " + conn + ": " + message);
ClientIO io = webClients.get(conn);
if (io == null) {
logger.error("Message was recieved from unknown ClientIO");
return;
}
try {
ClientWebSocket client = (ClientWebSocket) io;
client.handleMessage(message);
} catch (CardshifterSerializationException e) {
throw new RuntimeException(e);
}
// io.sentToServer(message);
}
@Override
public void onError(WebSocket conn, Exception ex) {
logger.warn("Connection error: " + conn, ex);
}
}
@Override
public void start() {
logger.info("Starting WebSocket server at port " + websocketServer.getPort() + "...");
websocketServer.start();
logger.info("WebSocket server started");
}
@Override
public void shutdown() throws Exception {
logger.info("Shutting down WebSocket server...");
websocketServer.stop();
logger.info("WebSocket server shutdown.");
}
}