commit e41b0cfe8ac279bb5b07ab4233ea97e47528b2e0 Author: MrLetsplay2003 Date: Sun Dec 3 21:32:09 2023 +0100 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cc39cef --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/bin/ +/target/ +/.settings/ +/.classpath +/dependency-reduced-pom.xml diff --git a/.project b/.project new file mode 100644 index 0000000..c182b3c --- /dev/null +++ b/.project @@ -0,0 +1,23 @@ + + + ShareServer + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.m2e.core.maven2Nature + org.eclipse.jdt.core.javanature + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..7874aa1 --- /dev/null +++ b/pom.xml @@ -0,0 +1,32 @@ + + 4.0.0 + me.mrletsplay + ShareServer + 0.0.1-SNAPSHOT + + + + maven-compiler-plugin + 3.8.1 + + 17 + + + + + + + + me.mrletsplay + ShareClient-Core + 1.0-SNAPSHOT + + + org.java-websocket + Java-WebSocket + 1.5.4 + + + \ No newline at end of file diff --git a/src/main/java/me/mrletsplay/shareserver/Session.java b/src/main/java/me/mrletsplay/shareserver/Session.java new file mode 100644 index 0000000..ab3f76d --- /dev/null +++ b/src/main/java/me/mrletsplay/shareserver/Session.java @@ -0,0 +1,20 @@ +package me.mrletsplay.shareserver; + +public class Session { + + private String id; + private int nextSiteID = 0; + + public Session(String id) { + this.id = id; + } + + public String getID() { + return id; + } + + public int getNewSiteID() { + return nextSiteID++; + } + +} diff --git a/src/main/java/me/mrletsplay/shareserver/SessionUser.java b/src/main/java/me/mrletsplay/shareserver/SessionUser.java new file mode 100644 index 0000000..1151d7f --- /dev/null +++ b/src/main/java/me/mrletsplay/shareserver/SessionUser.java @@ -0,0 +1,3 @@ +package me.mrletsplay.shareserver; + +public record SessionUser(Session session, int siteID) {} diff --git a/src/main/java/me/mrletsplay/shareserver/ShareServer.java b/src/main/java/me/mrletsplay/shareserver/ShareServer.java new file mode 100644 index 0000000..3af3e25 --- /dev/null +++ b/src/main/java/me/mrletsplay/shareserver/ShareServer.java @@ -0,0 +1,22 @@ +package me.mrletsplay.shareserver; + +import java.util.HashMap; +import java.util.Map; + +public class ShareServer { + + private static final Map SESSIONS = new HashMap<>(); + + public static void main(String[] args) { + new ShareWSServer().start(); + } + + public static Session getOrCreateSession(String sessionID) { + return SESSIONS.computeIfAbsent(sessionID, Session::new); + } + + public static void deleteSession(String sessionID) { + SESSIONS.remove(sessionID); + } + +} diff --git a/src/main/java/me/mrletsplay/shareserver/ShareWSServer.java b/src/main/java/me/mrletsplay/shareserver/ShareWSServer.java new file mode 100644 index 0000000..35ef215 --- /dev/null +++ b/src/main/java/me/mrletsplay/shareserver/ShareWSServer.java @@ -0,0 +1,119 @@ +package me.mrletsplay.shareserver; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.util.List; +import java.util.Objects; + +import org.java_websocket.WebSocket; +import org.java_websocket.framing.CloseFrame; +import org.java_websocket.handshake.ClientHandshake; +import org.java_websocket.server.WebSocketServer; + +import me.mrletsplay.shareclientcore.connection.RemoteConnection; +import me.mrletsplay.shareclientcore.connection.message.ChangeMessage; +import me.mrletsplay.shareclientcore.connection.message.ClientHelloMessage; +import me.mrletsplay.shareclientcore.connection.message.Message; +import me.mrletsplay.shareclientcore.connection.message.PeerJoinMessage; +import me.mrletsplay.shareclientcore.connection.message.PeerLeaveMessage; +import me.mrletsplay.shareclientcore.connection.message.ServerHelloMessage; + +public class ShareWSServer extends WebSocketServer { + + public ShareWSServer() { + super(new InetSocketAddress("0.0.0.0", 5473)); + } + + @Override + public void onOpen(WebSocket conn, ClientHandshake handshake) { + System.out.println("Client connected"); + } + + @Override + public void onClose(WebSocket conn, int code, String reason, boolean remote) { + System.out.println("Client disconnected"); + if(conn.getAttachment() != null) { + SessionUser user = conn.getAttachment(); + var peers = getPeers(user.session()); + if(peers.isEmpty()) { + ShareServer.deleteSession(reason); + return; + } + peers.forEach(peer -> send(peer, new PeerLeaveMessage(user.siteID()))); + } + } + + @Override + public void onMessage(WebSocket conn, String message) { + + } + + @Override + public void onMessage(WebSocket conn, ByteBuffer bytes) { + Message m; + try { + m = Message.deserialize(bytes); + }catch(IOException e) { + conn.close(CloseFrame.POLICY_VALIDATION, "Invalid message"); + return; + } + + if(conn.getAttachment() == null) { + // Only valid message is CLIENT_HELLO + if(m instanceof ClientHelloMessage hello) { + Session session = ShareServer.getOrCreateSession(hello.sessionID()); + int siteID = session.getNewSiteID(); + conn.setAttachment(new SessionUser(session, siteID)); + send(conn, new ServerHelloMessage(RemoteConnection.PROTOCOL_VERSION, siteID)); + getPeers(session).forEach(peer -> send(peer, new PeerJoinMessage(hello.username(), siteID))); + }else { + conn.close(CloseFrame.POLICY_VALIDATION, "First message must be CLIENT_HELLO"); + } + return; + } + + Session session = conn.getAttachment(); + if(m instanceof ChangeMessage change) { + getPeers(session).forEach(peer -> send(peer, m)); + } + +// System.out.println("Got a message"); +// getConnections().forEach(c -> { +// if(conn != c) c.send(message); +// }); + } + + private List getPeers(Session session) { + return getConnections().stream() + .filter(c -> Objects.equals(c.getAttachment(), session)) + .toList(); + } + + @Override + public void onError(WebSocket conn, Exception ex) { + + } + + @Override + public void onStart() { + + } + + public void send(WebSocket connection, Message message) { + try { + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + DataOutputStream dOut = new DataOutputStream(bOut); + + dOut.writeUTF(message.getType().name()); + message.serialize(dOut); + + connection.send(bOut.toByteArray()); + } catch (IOException e) { + connection.close(CloseFrame.PROTOCOL_ERROR); + } + } + +}