mirror of
https://e.coding.net/circlecloud/Yum.git
synced 2024-11-22 22:38:46 +00:00
feat: 添加主线程阻断检查
1.修复网络监测 2.修复配置文件错误 Signed-off-by: 502647092 <admin@yumc.pw>
This commit is contained in:
parent
acef319e0d
commit
44842a38ec
2
pom.xml
2
pom.xml
@ -3,7 +3,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>pw.yumc</groupId>
|
<groupId>pw.yumc</groupId>
|
||||||
<artifactId>Yum</artifactId>
|
<artifactId>Yum</artifactId>
|
||||||
<version>2.1</version>
|
<version>2.2</version>
|
||||||
<name>Yum</name>
|
<name>Yum</name>
|
||||||
<description>Minecraft 服务器插件管理系统</description>
|
<description>Minecraft 服务器插件管理系统</description>
|
||||||
<build>
|
<build>
|
||||||
|
@ -3,7 +3,10 @@
|
|||||||
*/
|
*/
|
||||||
package pw.yumc.Yum;
|
package pw.yumc.Yum;
|
||||||
|
|
||||||
|
import java.util.Timer;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
import cn.citycraft.CommonData.UpdatePlugin;
|
import cn.citycraft.CommonData.UpdatePlugin;
|
||||||
@ -17,6 +20,7 @@ import pw.yumc.Yum.listeners.PluginNetworkListener;
|
|||||||
import pw.yumc.Yum.listeners.SecurityListener;
|
import pw.yumc.Yum.listeners.SecurityListener;
|
||||||
import pw.yumc.Yum.managers.ConfigManager;
|
import pw.yumc.Yum.managers.ConfigManager;
|
||||||
import pw.yumc.Yum.managers.NetworkManager;
|
import pw.yumc.Yum.managers.NetworkManager;
|
||||||
|
import pw.yumc.Yum.runnables.MainThreadCheckTask;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MC插件仓库
|
* MC插件仓库
|
||||||
@ -25,15 +29,50 @@ import pw.yumc.Yum.managers.NetworkManager;
|
|||||||
* @since 2015年8月21日下午5:14:39
|
* @since 2015年8月21日下午5:14:39
|
||||||
*/
|
*/
|
||||||
public class Yum extends JavaPlugin {
|
public class Yum extends JavaPlugin {
|
||||||
NetworkManager netmgr;
|
@Override
|
||||||
|
public FileConfiguration getConfig() {
|
||||||
|
return ConfigManager.i().config;
|
||||||
|
}
|
||||||
|
|
||||||
public void initCommands() {
|
@Override
|
||||||
|
public void onDisable() {
|
||||||
|
NetworkManager.unregister();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
new YumAPI(this);
|
||||||
|
initCommands();
|
||||||
|
initListeners();
|
||||||
|
initRunnable();
|
||||||
|
new VersionChecker(this);
|
||||||
|
YumAPI.updaterepo(Bukkit.getConsoleSender());
|
||||||
|
YumAPI.updatecheck(Bukkit.getConsoleSender());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoad() {
|
||||||
|
// 初始化配置
|
||||||
|
ConfigManager.i();
|
||||||
|
// 初始化更新列
|
||||||
|
UpdatePlugin.getUpdateList();
|
||||||
|
// 启用网络注入
|
||||||
|
NetworkManager.register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化命令
|
||||||
|
*/
|
||||||
|
private void initCommands() {
|
||||||
new YumCommand(this);
|
new YumCommand(this);
|
||||||
new NetCommand(this);
|
new NetCommand(this);
|
||||||
new FileCommand(this);
|
new FileCommand(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initListeners() {
|
/**
|
||||||
|
* 初始化监听
|
||||||
|
*/
|
||||||
|
private void initListeners() {
|
||||||
if (ConfigManager.i().isSetOpEnable()) {
|
if (ConfigManager.i().isSetOpEnable()) {
|
||||||
try {
|
try {
|
||||||
final ClassLoader cl = Class.forName("pw.yumc.injected.event.SetOpEvent").getClassLoader();
|
final ClassLoader cl = Class.forName("pw.yumc.injected.event.SetOpEvent").getClassLoader();
|
||||||
@ -52,30 +91,15 @@ public class Yum extends JavaPlugin {
|
|||||||
new PluginNetworkListener(this);
|
new PluginNetworkListener(this);
|
||||||
PluginKit.scp("§a网络管理系统已启用...");
|
PluginKit.scp("§a网络管理系统已启用...");
|
||||||
}
|
}
|
||||||
|
new
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public void onDisable() {
|
* 初始化任务
|
||||||
netmgr.unregister();
|
*/
|
||||||
}
|
private void initRunnable() {
|
||||||
|
final Timer task = new Timer();
|
||||||
@Override
|
PluginKit.scp("§a线程管理系统已启用...");
|
||||||
public void onEnable() {
|
task.scheduleAtFixedRate(new MainThreadCheckTask(Thread.currentThread()), 0, 3000);
|
||||||
new YumAPI(this);
|
|
||||||
initCommands();
|
|
||||||
initListeners();
|
|
||||||
new VersionChecker(this);
|
|
||||||
YumAPI.updaterepo(Bukkit.getConsoleSender());
|
|
||||||
YumAPI.updatecheck(Bukkit.getConsoleSender());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLoad() {
|
|
||||||
// 初始化配置
|
|
||||||
ConfigManager.i();
|
|
||||||
// 初始化更新列
|
|
||||||
UpdatePlugin.getUpdateList();
|
|
||||||
// 启用网络注入
|
|
||||||
netmgr = new NetworkManager().register(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import org.bukkit.command.CommandSender;
|
|||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
import cn.citycraft.CommonData.UpdatePlugin;
|
import cn.citycraft.CommonData.UpdatePlugin;
|
||||||
|
import pw.yumc.Yum.managers.ConfigManager;
|
||||||
import pw.yumc.Yum.managers.DownloadManager;
|
import pw.yumc.Yum.managers.DownloadManager;
|
||||||
import pw.yumc.Yum.managers.PluginsManager;
|
import pw.yumc.Yum.managers.PluginsManager;
|
||||||
import pw.yumc.Yum.managers.RepositoryManager;
|
import pw.yumc.Yum.managers.RepositoryManager;
|
||||||
@ -29,20 +30,6 @@ public class YumAPI {
|
|||||||
private static RepositoryManager repo;
|
private static RepositoryManager repo;
|
||||||
private static boolean runlock = false;
|
private static boolean runlock = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化Yum管理中心
|
|
||||||
*
|
|
||||||
* @param plugin
|
|
||||||
* 插件实体
|
|
||||||
*/
|
|
||||||
public YumAPI(final Plugin plugin) {
|
|
||||||
YumAPI.main = plugin;
|
|
||||||
plugman = new PluginsManager(main);
|
|
||||||
download = new DownloadManager(main);
|
|
||||||
repo = new RepositoryManager(main);
|
|
||||||
plugman.addIgnore(main.getConfig().getStringList("ignorelist"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除插件
|
* 删除插件
|
||||||
*
|
*
|
||||||
@ -366,4 +353,18 @@ public class YumAPI {
|
|||||||
public static void upgrade(final CommandSender sender, final Plugin plugin) {
|
public static void upgrade(final CommandSender sender, final Plugin plugin) {
|
||||||
plugman.upgrade(sender, plugin);
|
plugman.upgrade(sender, plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化Yum管理中心
|
||||||
|
*
|
||||||
|
* @param plugin
|
||||||
|
* 插件实体
|
||||||
|
*/
|
||||||
|
public YumAPI(final Plugin plugin) {
|
||||||
|
YumAPI.main = plugin;
|
||||||
|
plugman = new PluginsManager(main);
|
||||||
|
download = new DownloadManager(main);
|
||||||
|
repo = new RepositoryManager(main);
|
||||||
|
plugman.addIgnore(ConfigManager.i().getIgnoreList());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,32 +1,38 @@
|
|||||||
package pw.yumc.Yum.listeners;
|
package pw.yumc.Yum.listeners;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
import cn.citycraft.PluginHelper.kit.ExceptionKit;
|
import cn.citycraft.PluginHelper.kit.PluginKit;
|
||||||
import pw.yumc.Yum.Yum;
|
import pw.yumc.Yum.Yum;
|
||||||
import pw.yumc.Yum.events.PluginNetworkEvent;
|
import pw.yumc.Yum.events.PluginNetworkEvent;
|
||||||
import pw.yumc.Yum.managers.ConfigManager;
|
import pw.yumc.Yum.managers.ConfigManager;
|
||||||
|
|
||||||
public class PluginNetworkListener implements Listener {
|
public class PluginNetworkListener implements Listener {
|
||||||
|
public String prefix = "§6[§bYum §a网络管理§6] ";
|
||||||
|
|
||||||
public PluginNetworkListener(final Yum yum) {
|
public PluginNetworkListener(final Yum yum) {
|
||||||
Bukkit.getPluginManager().registerEvents(this, yum);
|
Bukkit.getPluginManager().registerEvents(this, yum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
public void onPluginNetworkConect(final PluginNetworkEvent e) {
|
public void onPluginNetworkConect(final PluginNetworkEvent e) {
|
||||||
final Plugin plugin = e.getPlugin();
|
final Plugin plugin = e.getPlugin();
|
||||||
final String urlinfo = e.getUrl().toString();
|
final String urlinfo = e.getUrl().toString();
|
||||||
final boolean isPrimaryThread = e.isPrimaryThread();
|
final boolean isPrimaryThread = e.isPrimaryThread();
|
||||||
final String str = isPrimaryThread ? "§6[§bYum §a网络管理§6] §c插件 §6%s §c尝试在主线程访问 §e%s §4可能会导致服务器卡顿或无响应!" : "§6[§bYum §a网络监控§6] §c插件 §6%s §c尝试访问 §e%s §c请注意服务器网络安全!";
|
final String str = prefix + (isPrimaryThread ? "§c插件 §6%s §c尝试在主线程访问 §e%s §4可能会导致服务器卡顿或无响应!" : "§c插件 §6%s §c尝试访问 §e%s §c请注意服务器网络安全!");
|
||||||
if (plugin != null) {
|
if (plugin != null) {
|
||||||
Bukkit.getConsoleSender().sendMessage(String.format(str, plugin.getName(), urlinfo));
|
if (ConfigManager.i().getNetworkBlackList().contains(plugin.getName())) {
|
||||||
|
PluginKit.sc(prefix + "§4已阻止黑名单插件 §b" + plugin.getName() + " §4访问网络!");
|
||||||
|
PluginKit.sc(prefix + "§4地址: " + urlinfo);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PluginKit.sc(String.format(str, plugin.getName(), urlinfo));
|
||||||
if (!ConfigManager.i().isAllowPrimaryThread() && isPrimaryThread) {
|
if (!ConfigManager.i().isAllowPrimaryThread() && isPrimaryThread) {
|
||||||
Bukkit.getConsoleSender().sendMessage("§6[§bYum §a网络管理§6] §4已阻止插件 §b" + plugin.getName() + " §4在主线程访问网络!");
|
PluginKit.sc(prefix + "§4已阻止插件 §b" + plugin.getName() + " §4在主线程访问网络!");
|
||||||
ExceptionKit.throwException(new IOException("[Yum 网络防护] 已开启网络防护 不允许在主线程访问网络!"));
|
e.setCancelled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,18 +8,15 @@ import cn.citycraft.PluginHelper.config.FileConfig;
|
|||||||
import cn.citycraft.PluginHelper.kit.PKit;
|
import cn.citycraft.PluginHelper.kit.PKit;
|
||||||
|
|
||||||
public class ConfigManager {
|
public class ConfigManager {
|
||||||
private static List<String> blackList;
|
|
||||||
private static List<String> ignoreList;
|
|
||||||
|
|
||||||
private final static String ENABLE = "Enable";
|
private final static String ENABLE = "Enable";
|
||||||
private final static String BLACK = "Black";
|
private final static String BLACK = "Black";
|
||||||
private final static String IGNORE = "Ignore";
|
private final static String IGNORE = "Ignore";
|
||||||
|
|
||||||
private final static ConfigManager i = new ConfigManager(PKit.i());
|
private final static ConfigManager i = new ConfigManager(PKit.i());
|
||||||
|
|
||||||
private final FileConfig config;
|
public final FileConfig config;
|
||||||
private final FileConfig setop;
|
public final FileConfig setop;
|
||||||
private final FileConfig network;
|
public final FileConfig network;
|
||||||
|
|
||||||
public static ConfigManager i() {
|
public static ConfigManager i() {
|
||||||
return i;
|
return i;
|
||||||
@ -32,11 +29,11 @@ public class ConfigManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getBlackList() {
|
public List<String> getBlackList() {
|
||||||
return blackList;
|
return config.getStringList("blacklist");
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getIgnoreList() {
|
public List<String> getIgnoreList() {
|
||||||
return ignoreList;
|
return config.getStringList("ignorelist");
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getNetworkBlackList() {
|
public List<String> getNetworkBlackList() {
|
||||||
|
@ -8,8 +8,8 @@ import java.net.URI;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
|
|
||||||
|
import cn.citycraft.PluginHelper.kit.ExceptionKit;
|
||||||
import cn.citycraft.PluginHelper.kit.PluginKit;
|
import cn.citycraft.PluginHelper.kit.PluginKit;
|
||||||
import pw.yumc.Yum.Yum;
|
import pw.yumc.Yum.Yum;
|
||||||
import pw.yumc.Yum.events.PluginNetworkEvent;
|
import pw.yumc.Yum.events.PluginNetworkEvent;
|
||||||
@ -22,20 +22,19 @@ import pw.yumc.Yum.events.PluginNetworkEvent;
|
|||||||
*/
|
*/
|
||||||
public class NetworkManager {
|
public class NetworkManager {
|
||||||
|
|
||||||
public NetworkManager register(final Yum plugin) {
|
public static void register(final Yum plugin) {
|
||||||
Bukkit.getConsoleSender().sendMessage("§6[§bYum §a网络管理§6] §a注入网络管理系统 将托管服务器网络!");
|
Bukkit.getConsoleSender().sendMessage("§6[§bYum §a网络管理§6] §a注入网络管理系统 将托管服务器网络!");
|
||||||
ProxySelector.setDefault(new YumProxySelector(ProxySelector.getDefault(), plugin));
|
ProxySelector.setDefault(new YumProxySelector(ProxySelector.getDefault(), plugin));
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unregister() {
|
public static void unregister() {
|
||||||
final ProxySelector cur = ProxySelector.getDefault();
|
final ProxySelector cur = ProxySelector.getDefault();
|
||||||
if (cur instanceof YumProxySelector) {
|
if (cur instanceof YumProxySelector) {
|
||||||
ProxySelector.setDefault(((YumProxySelector) cur).getDefaultSelector());
|
ProxySelector.setDefault(((YumProxySelector) cur).getDefaultSelector());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class YumProxySelector extends ProxySelector {
|
static class YumProxySelector extends ProxySelector {
|
||||||
private final ProxySelector defaultSelector;
|
private final ProxySelector defaultSelector;
|
||||||
|
|
||||||
public YumProxySelector(final ProxySelector defaultSelector, final Yum plugin) {
|
public YumProxySelector(final ProxySelector defaultSelector, final Yum plugin) {
|
||||||
@ -53,12 +52,10 @@ public class NetworkManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Proxy> select(final URI uri) {
|
public List<Proxy> select(final URI uri) {
|
||||||
final boolean isPrimaryThread = Bukkit.isPrimaryThread();
|
final PluginNetworkEvent pne = new PluginNetworkEvent(PluginKit.getOperatePlugin(), uri, Bukkit.isPrimaryThread());
|
||||||
final Plugin plugin = PluginKit.getOperatePlugin();
|
|
||||||
final PluginNetworkEvent pne = new PluginNetworkEvent(plugin, uri, isPrimaryThread);
|
|
||||||
Bukkit.getPluginManager().callEvent(pne);
|
Bukkit.getPluginManager().callEvent(pne);
|
||||||
if (pne.isCancelled()) {
|
if (pne.isCancelled()) {
|
||||||
return null;
|
ExceptionKit.throwException(new IOException("[Yum 网络防护] 已开启网络防护 不允许在主线程访问网络!"));
|
||||||
}
|
}
|
||||||
return defaultSelector.select(uri);
|
return defaultSelector.select(uri);
|
||||||
}
|
}
|
||||||
|
53
src/main/java/pw/yumc/Yum/runnables/MainThreadCheckTask.java
Normal file
53
src/main/java/pw/yumc/Yum/runnables/MainThreadCheckTask.java
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package pw.yumc.Yum.runnables;
|
||||||
|
|
||||||
|
import java.lang.Thread.State;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import cn.citycraft.PluginHelper.kit.PKit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @since 2016年6月22日 下午4:57:32
|
||||||
|
* @author 喵♂呜
|
||||||
|
*/
|
||||||
|
public class MainThreadCheckTask extends TimerTask {
|
||||||
|
|
||||||
|
private final Thread mainThread;
|
||||||
|
|
||||||
|
public MainThreadCheckTask(final Thread mainThread) {
|
||||||
|
this.mainThread = mainThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// According to this post the thread is still in Runnable although it's waiting for
|
||||||
|
// file/http ressources
|
||||||
|
// https://stackoverflow.com/questions/20795295/why-jstack-out-says-thread-state-is-runnable-while-socketread
|
||||||
|
if (mainThread.getState() == State.RUNNABLE) {
|
||||||
|
// Based on this post we have to check the top element of the stack
|
||||||
|
// https://stackoverflow.com/questions/20891386/how-to-detect-thread-being-blocked-by-io
|
||||||
|
final StackTraceElement[] stackTrace = mainThread.getStackTrace();
|
||||||
|
final StackTraceElement topElement = stackTrace[0];
|
||||||
|
if (topElement.isNativeMethod()) {
|
||||||
|
// Socket/SQL (connect) - java.net.DualStackPlainSocketImpl.connect0
|
||||||
|
// Socket/SQL (read) - java.net.SocketInputStream.socketRead0
|
||||||
|
// Socket/SQL (write) - java.net.SocketOutputStream.socketWrite0
|
||||||
|
if (isElementEqual(topElement, "java.net.DualStackPlainSocketImpl", "connect0")
|
||||||
|
|| isElementEqual(topElement, "java.net.SocketInputStream", "socketRead0")
|
||||||
|
|| isElementEqual(topElement, "java.net.SocketOutputStream", "socketWrite0")) {
|
||||||
|
PKit.i().getLogger().log(Level.WARNING, "主线程存在网络操作 服务器处于停止状态...", stackTrace);
|
||||||
|
}
|
||||||
|
// File (in) - java.io.FileInputStream.readBytes
|
||||||
|
// File (out) - java.io.FileOutputStream.writeBytes
|
||||||
|
else if (isElementEqual(topElement, "java.io.FileInputStream", "readBytes") || isElementEqual(topElement, "java.io.FileOutputStream", "writeBytes")) {
|
||||||
|
PKit.i().getLogger().log(Level.WARNING, "主线程存在IO操作 服务器处于停止状态...", stackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isElementEqual(final StackTraceElement traceElement, final String className, final String methodName) {
|
||||||
|
return traceElement.getClassName().equals(className) && traceElement.getMethodName().equals(methodName);
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@ Enable: true
|
|||||||
#黑名单列表
|
#黑名单列表
|
||||||
Black:
|
Black:
|
||||||
- BukkitInjectedTools
|
- BukkitInjectedTools
|
||||||
|
- FeatherBoard
|
||||||
#忽略检测列表
|
#忽略检测列表
|
||||||
Ignore:
|
Ignore:
|
||||||
- Essentials
|
- Essentials
|
Loading…
Reference in New Issue
Block a user