From e62b1d49673d69ada5d41c216728258d4758ac81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=B9=E5=9D=97=E5=90=9B?= Date: Fri, 22 Jul 2022 21:21:12 +0800 Subject: [PATCH] Change the server authentication method --- .../opencommand/socket/SocketClient.java | 114 ++++++++++-------- .../opencommand/socket/SocketServer.java | 73 ++++++----- .../opencommand/socket/packet/AuthPacket.java | 21 ++++ .../opencommand/socket/packet/PacketEnum.java | 1 + 4 files changed, 130 insertions(+), 79 deletions(-) create mode 100644 src/main/java/com/github/jie65535/opencommand/socket/packet/AuthPacket.java diff --git a/src/main/java/com/github/jie65535/opencommand/socket/SocketClient.java b/src/main/java/com/github/jie65535/opencommand/socket/SocketClient.java index 3f63331..e07ecba 100644 --- a/src/main/java/com/github/jie65535/opencommand/socket/SocketClient.java +++ b/src/main/java/com/github/jie65535/opencommand/socket/SocketClient.java @@ -2,10 +2,7 @@ package com.github.jie65535.opencommand.socket; import com.github.jie65535.opencommand.OpenCommandConfig; import com.github.jie65535.opencommand.OpenCommandPlugin; -import com.github.jie65535.opencommand.socket.packet.BasePacket; -import com.github.jie65535.opencommand.socket.packet.HeartBeat; -import com.github.jie65535.opencommand.socket.packet.HttpPacket; -import com.github.jie65535.opencommand.socket.packet.Packet; +import com.github.jie65535.opencommand.socket.packet.*; import com.github.jie65535.opencommand.socket.packet.player.Player; import emu.grasscutter.Grasscutter; import emu.grasscutter.command.CommandMap; @@ -29,8 +26,11 @@ public class SocketClient { public static boolean connect = false; + public static ReceiveThread receiveThread; + // 连接服务器 public static void connectServer() { + if (connect) return; OpenCommandConfig config = OpenCommandPlugin.getInstance().getConfig(); mLogger = OpenCommandPlugin.getInstance().getLogger(); clientThread = new ClientThread(config.socketHost, config.socketPort); @@ -80,10 +80,9 @@ public class SocketClient { // 数据包接收 private static class ReceiveThread extends Thread { private InputStream is; - private String token; + private boolean exit = false; public ReceiveThread(Socket socket) { - token = OpenCommandPlugin.getInstance().getConfig().socketToken; try { is = socket.getInputStream(); } catch (IOException e) { @@ -97,55 +96,63 @@ public class SocketClient { //noinspection InfiniteLoopStatement while (true) { try { + if (exit) { + return; + } String data = SocketUtils.readString(is); Packet packet = Grasscutter.getGsonFactory().fromJson(data, Packet.class); - if (packet.token.equals(token)) { - switch (packet.type) { - // 玩家类 - case Player: - var player = Grasscutter.getGsonFactory().fromJson(packet.data, Player.class); - switch (player.type) { - // 运行命令 - case RunCommand -> { - var command = player.data; - var playerData = OpenCommandPlugin.getInstance().getServer().getPlayerByUid(player.uid); - if (playerData == null) { - sendPacket(new HttpPacket(404, "Player not found."), packet.packetID); - return; - } - // Player MessageHandler do not support concurrency - //noinspection SynchronizationOnLocalVariableOrMethodParameter - synchronized (playerData) { - try { - var resultCollector = new MessageHandler(); - playerData.setMessageHandler(resultCollector); - CommandMap.getInstance().invoke(playerData, playerData, command); - sendPacket(new HttpPacket(200, resultCollector.getMessage()), packet.packetID); - } catch (Exception e) { - OpenCommandPlugin.getInstance().getLogger().warn("Run command failed.", e); - sendPacket(new HttpPacket(500, "error", e.getLocalizedMessage()), packet.packetID); - } finally { - playerData.setMessageHandler(null); - } - } + switch (packet.type) { + // 玩家类 + case Player: + var player = Grasscutter.getGsonFactory().fromJson(packet.data, Player.class); + switch (player.type) { + // 运行命令 + case RunCommand -> { + var command = player.data; + var playerData = OpenCommandPlugin.getInstance().getServer().getPlayerByUid(player.uid); + if (playerData == null) { + sendPacket(new HttpPacket(404, "Player not found."), packet.packetID); + return; } - // 发送信息 - case DropMessage -> { - var playerData = OpenCommandPlugin.getInstance().getServer().getPlayerByUid(player.uid); - if (playerData == null) { - return; + // Player MessageHandler do not support concurrency + //noinspection SynchronizationOnLocalVariableOrMethodParameter + synchronized (playerData) { + try { + var resultCollector = new MessageHandler(); + playerData.setMessageHandler(resultCollector); + CommandMap.getInstance().invoke(playerData, playerData, command); + sendPacket(new HttpPacket(200, resultCollector.getMessage()), packet.packetID); + } catch (Exception e) { + OpenCommandPlugin.getInstance().getLogger().warn("[OpenCommand] Run command failed.", e); + sendPacket(new HttpPacket(500, "error", e.getLocalizedMessage()), packet.packetID); + } finally { + playerData.setMessageHandler(null); } - playerData.dropMessage(player.data); } } - break; - } + // 发送信息 + case DropMessage -> { + var playerData = OpenCommandPlugin.getInstance().getServer().getPlayerByUid(player.uid); + if (playerData == null) { + return; + } + playerData.dropMessage(player.data); + } + } + break; } } catch (Throwable e) { e.printStackTrace(); + if (!sendPacket(new HeartBeat("Pong"))) { + return; + } } } } + + public void exit() { + exit = true; + } } // 客户端连接线程 @@ -172,17 +179,26 @@ public class SocketClient { @Override public void run() { try { - socket = new Socket(ip, port); connect = true; + if (receiveThread != null) { + receiveThread.exit(); + } + + socket = new Socket(ip, port); os = socket.getOutputStream(); - mLogger.info("Connect to server: " + ip + ":" + port); - new ReceiveThread(socket); + mLogger.info("[OpenCommand]Connect to server: " + ip + ":" + port); + SocketClient.sendPacket(new AuthPacket(OpenCommandPlugin.getInstance().getConfig().socketToken)); + receiveThread = new ReceiveThread(socket); } catch (IOException e) { connect = false; - mLogger.warn("Connect to server failed: " + ip + ":" + port); - mLogger.warn("[OpenCommand] Reconnect to server"); + mLogger.warn("[OpenCommand]Connect to server failed: " + ip + ":" + port); + mLogger.warn("[OpenCommand] Retry connecting to the server after 15 seconds"); + try { + Thread.sleep(15000); + } catch (InterruptedException ex) { + throw new RuntimeException(ex); + } connectServer(); - throw new RuntimeException(e); } } } diff --git a/src/main/java/com/github/jie65535/opencommand/socket/SocketServer.java b/src/main/java/com/github/jie65535/opencommand/socket/SocketServer.java index b602a87..fa36092 100644 --- a/src/main/java/com/github/jie65535/opencommand/socket/SocketServer.java +++ b/src/main/java/com/github/jie65535/opencommand/socket/SocketServer.java @@ -1,9 +1,7 @@ package com.github.jie65535.opencommand.socket; import com.github.jie65535.opencommand.OpenCommandPlugin; -import com.github.jie65535.opencommand.socket.packet.BasePacket; -import com.github.jie65535.opencommand.socket.packet.HttpPacket; -import com.github.jie65535.opencommand.socket.packet.Packet; +import com.github.jie65535.opencommand.socket.packet.*; import com.github.jie65535.opencommand.socket.packet.player.PlayerList; import emu.grasscutter.Grasscutter; import org.slf4j.Logger; @@ -87,7 +85,7 @@ public class SocketServer { var clientID = client.getKey(); var clientTime = client.getValue(); if (clientTime > TIMEOUT) { - mLogger.info("Client {} timeout, disconnect.", clientID); + mLogger.info("[OpenCommand] Client {} timeout, disconnect.", clientID); clientList.remove(clientID); clientTimeout.remove(clientID); SocketData.playerList.remove(clientID); @@ -105,6 +103,7 @@ public class SocketServer { private OutputStream os; private final String address; private final String token; + private boolean auth = false; private final HashMap> socketDataWaitList = new HashMap<>(); @@ -147,28 +146,44 @@ public class SocketServer { try { String data = SocketUtils.readString(is); Packet packet = Grasscutter.getGsonFactory().fromJson(data, Packet.class); - if (packet.token.equals(token)) { - switch (packet.type) { - // 缓存玩家列表 - case PlayerList -> { - PlayerList playerList = Grasscutter.getGsonFactory().fromJson(packet.data, PlayerList.class); - SocketData.playerList.put(address, playerList); - } - // Http信息返回 - case HttpPacket -> { - HttpPacket httpPacket = Grasscutter.getGsonFactory().fromJson(packet.data, HttpPacket.class); - var socketWait = socketDataWaitList.get(packet.packetID); - if (socketWait == null) { - mLogger.error("HttpPacket: " + packet.packetID + " not found"); - return; - } - socketWait.setData(httpPacket); - socketDataWaitList.remove(packet.packetID); - } - // 心跳包 - case HeartBeat -> { - clientTimeout.put(address, 0); + if (packet.type == PacketEnum.AuthPacket) { + AuthPacket authPacket = Grasscutter.getGsonFactory().fromJson(data, AuthPacket.class); + if (authPacket.token.equals(token)) { + auth = true; + mLogger.info("[OpenCommand] Client {} auth success", address); + clientList.put(address, this); + clientTimeout.put(address, 0); + } else { + mLogger.warn("[OpenCommand] Client {} auth failed", address); + socket.close(); + return; + } + } + if (!auth) { + mLogger.warn("[OpenCommand] Client {} auth failed", address); + socket.close(); + return; + } + switch (packet.type) { + // 缓存玩家列表 + case PlayerList -> { + PlayerList playerList = Grasscutter.getGsonFactory().fromJson(packet.data, PlayerList.class); + SocketData.playerList.put(address, playerList); + } + // Http信息返回 + case HttpPacket -> { + HttpPacket httpPacket = Grasscutter.getGsonFactory().fromJson(packet.data, HttpPacket.class); + var socketWait = socketDataWaitList.get(packet.packetID); + if (socketWait == null) { + mLogger.error("[OpenCommand] HttpPacket: " + packet.packetID + " not found"); + return; } + socketWait.setData(httpPacket); + socketDataWaitList.remove(packet.packetID); + } + // 心跳包 + case HeartBeat -> { + clientTimeout.put(address, 0); } } } catch (Throwable e) { @@ -194,16 +209,14 @@ public class SocketServer { @Override public void run() { - mLogger.info("Start socket server on port " + socketServer.getLocalPort()); + mLogger.info("[OpenCommand] Start socket server on port " + socketServer.getLocalPort()); // noinspection InfiniteLoopStatement while (true) { try { Socket accept = socketServer.accept(); String address = accept.getInetAddress() + ":" + accept.getPort(); - mLogger.info("Client connect: " + address); - ClientThread clientThread = new ClientThread(accept); - clientList.put(address, clientThread); - clientTimeout.put(address, 0); + mLogger.info("[OpenCommand] Client connect: " + address); + new ClientThread(accept); } catch (IOException e) { e.printStackTrace(); } diff --git a/src/main/java/com/github/jie65535/opencommand/socket/packet/AuthPacket.java b/src/main/java/com/github/jie65535/opencommand/socket/packet/AuthPacket.java new file mode 100644 index 0000000..d244018 --- /dev/null +++ b/src/main/java/com/github/jie65535/opencommand/socket/packet/AuthPacket.java @@ -0,0 +1,21 @@ +package com.github.jie65535.opencommand.socket.packet; + +import emu.grasscutter.Grasscutter; + +public class AuthPacket extends BasePacket { + public String token; + + public AuthPacket(String token) { + this.token = token; + } + + @Override + public String getPacket() { + return Grasscutter.getGsonFactory().toJson(this); + } + + @Override + public PacketEnum getType() { + return PacketEnum.AuthPacket; + } +} diff --git a/src/main/java/com/github/jie65535/opencommand/socket/packet/PacketEnum.java b/src/main/java/com/github/jie65535/opencommand/socket/packet/PacketEnum.java index 128be71..dadb1ff 100644 --- a/src/main/java/com/github/jie65535/opencommand/socket/packet/PacketEnum.java +++ b/src/main/java/com/github/jie65535/opencommand/socket/packet/PacketEnum.java @@ -5,5 +5,6 @@ public enum PacketEnum { PlayerList, Player, HttpPacket, + AuthPacket, HeartBeat }