package io.robe.websocket; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.eclipse.jetty.websocket.api.CloseStatus; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.WebSocketListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.concurrent.ConcurrentHashMap; public abstract class WebSocket implements WebSocketListener { private static final Logger LOGGER = LoggerFactory.getLogger(WebSocket.class); private static final ConcurrentHashMap<String, WebSocket> activeWebSockets = new ConcurrentHashMap<>(); private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); private String uuid; private Session currentSession; public abstract String onConnect(Session session); public abstract void onMessage(Session session, String message); public abstract void onMessage(Session session, byte[] bytes); public abstract void onClose(Session session, int status, String reason); public abstract void onError(Throwable error); @Override public void onWebSocketBinary(byte[] bytes, int i, int i1) { LOGGER.info("CLIENT: {} received byte message length: {}", currentSession.getRemoteAddress().toString(), bytes.length); onMessage(currentSession, bytes); } @Override public void onWebSocketText(String message) { LOGGER.info("CLIENT: {} received text message length: {}", currentSession.getRemoteAddress().toString(), message.length()); onMessage(currentSession, message); } @Override public void onWebSocketClose(int i, String reason) { LOGGER.info("CLIENT: {} closed connection because of {}.", currentSession.getRemoteAddress().toString(), reason); activeWebSockets.remove(uuid); onClose(currentSession, i, reason); currentSession = null; } @Override public void onWebSocketConnect(Session session) { this.currentSession = session; LOGGER.info("CLIENT: {} connection received.", session.getRemoteAddress().toString()); String uuid = onConnect(session); if (uuid == null || uuid.trim().isEmpty()) { try { session.getRemote().sendString(toJson(new Packet(Packet.Type.UNAUTHORISED, "", null))); } catch (IOException e) { e.printStackTrace(); session.close(new CloseStatus(-1, "Can't reply connection UUID to client.")); } } else { this.uuid = uuid; activeWebSockets.put(uuid, this); try { session.getRemote().sendString(toJson(new Packet(Packet.Type.CONNECTED, "", null))); } catch (IOException e) { e.printStackTrace(); session.close(new CloseStatus(-1, "Can't reply connection UUID to client.")); } } } @Override public void onWebSocketError(Throwable error) { LOGGER.info("Error occurred {}.", error.getMessage()); onError(error); } public Session getCurrentSession() { return currentSession; } public static void sendText(Packet packet) throws IOException { WebSocket webSocket = activeWebSockets.get(packet.getReceiver()); if (webSocket != null) webSocket.currentSession.getRemote().sendString(toJson(packet)); } public static String toJson(Packet packet) throws JsonProcessingException { return OBJECT_MAPPER.writeValueAsString(packet); } }