Skip to content

Commit

Permalink
回退
Browse files Browse the repository at this point in the history
  • Loading branch information
shulng committed Nov 28, 2024
1 parent fff4c40 commit bada156
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 98 deletions.
156 changes: 83 additions & 73 deletions src/main/java/cc/baka9/catseedlogin/bukkit/Communication.java
Original file line number Diff line number Diff line change
@@ -1,126 +1,136 @@
package cc.baka9.catseedlogin.bukkit;

import cc.baka9.catseedlogin.bukkit.database.Cache;
import cc.baka9.catseedlogin.bukkit.object.LoginPlayer;
import cc.baka9.catseedlogin.bukkit.object.LoginPlayerHelper;
import cc.baka9.catseedlogin.util.CommunicationAuth;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.bukkit.Bukkit;
import org.bukkit.entity.Player;

import cc.baka9.catseedlogin.bukkit.database.Cache;
import cc.baka9.catseedlogin.bukkit.object.LoginPlayer;
import cc.baka9.catseedlogin.bukkit.object.LoginPlayerHelper;
import cc.baka9.catseedlogin.util.CommunicationAuth;

/**
* bukkit 与 bc 的通讯交流
*/
public class Communication {
private static ServerSocket serverSocket;
private static final ExecutorService executorService = Executors.newCachedThreadPool();

/**
* 异步关闭 socket server
*/
public static void socketServerStopAsync() {
CatSeedLogin.instance.runTaskAsync(Communication::socketServerStop);
}

public static synchronized void socketServerStop() {
closeServerSocket(serverSocket);
public static void socketServerStop() {

if (serverSocket != null && !serverSocket.isClosed()) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}

/**
* 异步启动 socket server 监听bc端发来的请求
*/
public static void socketServerStartAsync() {
CatSeedLogin.instance.runTaskAsync(Communication::socketServerStart);
}

private static synchronized void socketServerStart() {
/**
* 启动 socket server 监听bc端发来的请求
*/
private static void socketServerStart() {
try {
InetAddress inetAddress = InetAddress.getByName(Config.BungeeCord.Host);
serverSocket = new ServerSocket(Integer.parseInt(Config.BungeeCord.Port), 50, inetAddress);
acceptConnections(serverSocket);
while (!serverSocket.isClosed()) {
Socket socket;
try {
socket = serverSocket.accept();
handleRequest(socket);
} catch (IOException e) {
break;
}
}
} catch (UnknownHostException e) {
CatSeedLogin.instance.getLogger().warning("无法解析域名或IP地址: " + e.getMessage());
CatSeedLogin.instance.getLogger().warning("无法解析域名或IP地址");
e.printStackTrace();
} catch (IOException e) {
CatSeedLogin.instance.getLogger().warning("启动Socket服务器时发生错误: " + e.getMessage());
e.printStackTrace();
}
}

private static void acceptConnections(ServerSocket serverSocket) {
while (!serverSocket.isClosed()) {
try {
Socket socket = serverSocket.accept();
executorService.submit(() -> handleRequest(socket));
} catch (IOException e) {
if (serverSocket.isClosed()) break;
CatSeedLogin.instance.getLogger().warning("接受Socket连接时发生错误: " + e.getMessage());
}
}
}

private static void handleRequest(Socket socket) {
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
String requestType = bufferedReader.readLine();
if (requestType == null) return;
String playerName = bufferedReader.readLine();
switch (requestType) {
case "Connect":
handleConnectRequest(socket, playerName);
break;
case "KeepLoggedIn":
String time = bufferedReader.readLine();
String sign = bufferedReader.readLine();
handleKeepLoggedInRequest(playerName, time, sign);
break;
default:
CatSeedLogin.instance.getLogger().warning("未知请求类型: " + requestType.trim());
break;
}
} catch (IOException e) {
CatSeedLogin.instance.getLogger().warning("处理请求时发生错误: " + e.getMessage());
/**
* 处理请求
*/
private static void handleRequest(Socket socket) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String requestType = bufferedReader.readLine();
String playerName = bufferedReader.readLine();
switch (requestType) {
case "Connect":
handleConnectRequest(socket, playerName);
break;
case "KeepLoggedIn":
String time = bufferedReader.readLine();
String sign = bufferedReader.readLine();
handleKeepLoggedInRequest(playerName, time, sign);
socket.close();
break;
default:
break;
}
}

private static void handleKeepLoggedInRequest(String playerName, String time, String sign) {
// 验证请求的合法性
// 对比玩家名,时间戳,和authKey加密的结果(加密是因为如果登录服不在内网环境下,则可能会被人使用这个功能给发包来直接绕过登录)
if (CommunicationAuth.encryption(playerName, time, Config.BungeeCord.AuthKey).equals(sign)) {
CatScheduler.runTask(() -> {
// 切换主线程给予登录状态
Bukkit.getScheduler().runTask(CatSeedLogin.instance, () -> {
LoginPlayer lp = Cache.getIgnoreCase(playerName);
if (lp != null) {
LoginPlayerHelper.add(lp);
Player player = Bukkit.getPlayerExact(playerName);
if (player != null) player.updateInventory();
} else {
CatSeedLogin.instance.getLogger().warning("玩家 " + playerName.trim() + " 未找到在缓存中。");
if (player != null) {
player.updateInventory();
}
}

});
}
}

private static void handleConnectRequest(Socket socket, String playerName) {
CatScheduler.runTask(() -> {
// 切换主线程获取是否已登录
Bukkit.getScheduler().runTask(CatSeedLogin.instance, () -> {
boolean result = LoginPlayerHelper.isLogin(playerName);
sendConnectResultAsync(socket, result);
});
}

private static void sendConnectResultAsync(Socket socket, boolean result) {
executorService.submit(() -> {
try (Socket autoCloseSocket = socket) {
autoCloseSocket.getOutputStream().write(result ? 1 : 0);
autoCloseSocket.getOutputStream().flush();
} catch (IOException e) {
CatSeedLogin.instance.getLogger().warning("发送连接结果时发生错误: " + e.getMessage());
}
// 切换异步线程返回结果
CatSeedLogin.instance.runTaskAsync(() -> {
try {
socket.getOutputStream().write(result ? 1 : 0);
socket.close();
} catch (IOException e) {
e.printStackTrace();
}

});

});
}

private static void closeServerSocket(ServerSocket serverSocket) {
if (serverSocket != null && !serverSocket.isClosed()) {
try {
serverSocket.close();
} catch (IOException e) {
CatSeedLogin.instance.getLogger().warning("关闭Socket服务器时发生错误: " + e.getMessage());
}
}
}

}
73 changes: 48 additions & 25 deletions src/main/java/cc/baka9/catseedlogin/bungee/Communication.java
Original file line number Diff line number Diff line change
@@ -1,47 +1,70 @@
package cc.baka9.catseedlogin.bungee;

import java.net.Socket;
import java.io.IOException;
import cc.baka9.catseedlogin.util.CommunicationAuth;
import net.md_5.bungee.api.ProxyServer;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;

import cc.baka9.catseedlogin.util.CommunicationAuth;
import java.net.Socket;

/**
* bc 与 bukkit 的通讯交流
*/
public class Communication {
private static final String HOST = Config.Host;
private static final int PORT = Config.Port;

public static int sendConnectRequest(String playerName) {
return sendRequest("Connect", playerName);
try (Socket socket = getSocket(); BufferedWriter bufferedWriter = getSocketBufferedWriter(socket)) {
// 请求类型
bufferedWriter.write("Connect");
bufferedWriter.newLine();
// 玩家名
bufferedWriter.write(playerName);
bufferedWriter.newLine();

bufferedWriter.flush();
return socket.getInputStream().read();
} catch (IOException e) {
e.printStackTrace();
}
return 0;
}

public static void sendKeepLoggedInRequest(String playerName) {
long currentTime = System.currentTimeMillis();
String time = String.valueOf(currentTime);
String sign = CommunicationAuth.encryption(playerName, time, Config.AuthKey);
sendRequest("KeepLoggedIn", playerName, time, sign);
}
try (Socket socket = getSocket(); BufferedWriter bufferedWriter = getSocketBufferedWriter(socket)) {
// 请求类型
bufferedWriter.write("KeepLoggedIn");
bufferedWriter.newLine();
// 玩家名
bufferedWriter.write(playerName);
bufferedWriter.newLine();
// 时间戳
String time = String.valueOf(System.currentTimeMillis());
bufferedWriter.write(time);
bufferedWriter.newLine();
// 根据玩家名,时间戳,和authKey加密的结果(加密是因为如果登录服不在内网环境下,则可能会被人使用这个功能给发包来绕过登录)
String sign = CommunicationAuth.encryption(playerName, time, Config.AuthKey);
bufferedWriter.write(sign);
bufferedWriter.newLine();

private static int sendRequest(String requestType, String... messages) {
try (Socket socket = new Socket(HOST, PORT);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))) {
writeMessage(writer, requestType, messages);
return socket.getInputStream().read();
bufferedWriter.flush();
} catch (IOException e) {
return 0;
e.printStackTrace();
}
}

private static void writeMessage(BufferedWriter writer, String requestType, String... messages) throws IOException {
writer.write(requestType);
writer.newLine();
for (String message : messages) {
writer.write(message);
writer.newLine();
private static Socket getSocket() throws IOException {
try {
return new Socket(Config.Host, Config.Port);
} catch (IOException e) {
ProxyServer.getInstance().getLogger().warning("§c请检查装载登录插件的子服是否在 bungeecord.yml 中开启了bungeecord功能,以及Host和Port是否与bc端的配置相同");
throw new IOException(e);
}
writer.flush();
}

private static BufferedWriter getSocketBufferedWriter(Socket socket) throws IOException {
return new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
}


}

0 comments on commit bada156

Please sign in to comment.