Change the server authentication method

This commit is contained in:
方块君 2022-07-22 21:21:12 +08:00
parent 8030ef8034
commit e62b1d4967
4 changed files with 130 additions and 79 deletions

View File

@ -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);
}
}
}

View File

@ -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<String, SocketDataWait<?>> 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();
}

View File

@ -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;
}
}

View File

@ -5,5 +5,6 @@ public enum PacketEnum {
PlayerList,
Player,
HttpPacket,
AuthPacket,
HeartBeat
}