-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
131 additions
and
98 deletions.
There are no files selected for viewing
156 changes: 83 additions & 73 deletions
156
src/main/java/cc/baka9/catseedlogin/bukkit/Communication.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
73
src/main/java/cc/baka9/catseedlogin/bungee/Communication.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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())); | ||
} | ||
|
||
|
||
} |