From 2f7f213f1d8d97fb065482a029d5f3113341e03e Mon Sep 17 00:00:00 2001
From: PluieM <644202913@qq.com>
Date: Wed, 19 Jun 2024 15:31:38 +0800
Subject: [PATCH 1/5] =?UTF-8?q?1=E3=80=81=E6=96=B0=E5=A2=9E=E4=B8=80?=
=?UTF-8?q?=E4=B8=AA=E5=9F=BA=E4=BA=8E=E7=8A=B6=E6=80=81=E6=9C=BA=E6=A8=A1?=
=?UTF-8?q?=E5=9E=8B=E7=9A=84=E8=A7=84=E5=88=99=E6=A8=A1=E5=9D=97=202?=
=?UTF-8?q?=E3=80=81=E5=B0=86=E8=A7=84=E5=88=99=E8=AE=A2=E9=98=85=E5=92=8C?=
=?UTF-8?q?Peer=E9=BB=91=E5=90=8D=E5=8D=95=E7=9A=84=E5=8C=B9=E9=85=8D?=
=?UTF-8?q?=E6=A8=A1=E5=9D=97=E5=9F=BA=E4=BA=8E=E6=96=B0=E7=9A=84=E8=A7=84?=
=?UTF-8?q?=E5=88=99=E8=A7=84=E5=88=99=E6=A8=A1=E5=9D=97=E8=BF=9B=E8=A1=8C?=
=?UTF-8?q?=E9=87=8D=E6=9E=84=203=E3=80=81=E5=BE=AE=E8=B0=83=E8=A7=84?=
=?UTF-8?q?=E5=88=99=E8=AE=A2=E9=98=85=E6=A8=A1=E5=9D=97=E6=96=B9=E4=BE=BF?=
=?UTF-8?q?=E5=90=8E=E7=BB=AD=E5=8A=A0=E5=85=A5=E6=9B=B4=E5=A4=9A=E8=AE=A2?=
=?UTF-8?q?=E9=98=85=E8=A7=84=E5=88=99=E7=9A=84=E5=8C=B9=E9=85=8D=E7=B1=BB?=
=?UTF-8?q?=E5=9E=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pom.xml | 5 +
.../peerbanhelper/PeerBanHelperServer.java | 110 +++++++++++----
.../module/AbstractRuleBlocker.java | 33 +++++
.../peerbanhelper/module/MatchEvents.java | 27 ++++
.../module/MatchResultDetail.java | 5 +
.../peerbanhelper/module/PeerMatchRecord.java | 21 +++
.../peerbanhelper/module/PeerState.java | 27 ++++
.../peerbanhelper/module/RuleBlocker.java | 115 ++++++++++++++++
.../module/impl/rule/PeerIdBlocker.java | 70 ++++++++++
...BlackRuleList.java => RuleSubBlocker.java} | 125 +++++++-----------
.../module/impl/webapi/RuleSubController.java | 50 +++----
.../com/ghostchu/peerbanhelper/text/Lang.java | 2 +
.../peerbanhelper/util/rule/RuleMatcher.java | 31 +++++
.../peerbanhelper/util/rule/SubRuleType.java | 19 +++
.../{IPBanMatcher.java => IPMatcher.java} | 23 ++--
src/main/resources/profile.yml | 4 +-
16 files changed, 523 insertions(+), 144 deletions(-)
create mode 100644 src/main/java/com/ghostchu/peerbanhelper/module/AbstractRuleBlocker.java
create mode 100644 src/main/java/com/ghostchu/peerbanhelper/module/MatchEvents.java
create mode 100644 src/main/java/com/ghostchu/peerbanhelper/module/MatchResultDetail.java
create mode 100644 src/main/java/com/ghostchu/peerbanhelper/module/PeerMatchRecord.java
create mode 100644 src/main/java/com/ghostchu/peerbanhelper/module/PeerState.java
create mode 100644 src/main/java/com/ghostchu/peerbanhelper/module/RuleBlocker.java
create mode 100644 src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/PeerIdBlocker.java
rename src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/{IPBlackRuleList.java => RuleSubBlocker.java} (82%)
create mode 100644 src/main/java/com/ghostchu/peerbanhelper/util/rule/RuleMatcher.java
create mode 100644 src/main/java/com/ghostchu/peerbanhelper/util/rule/SubRuleType.java
rename src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/{IPBanMatcher.java => IPMatcher.java} (79%)
diff --git a/pom.xml b/pom.xml
index f29042df..3bfa71a1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -403,5 +403,10 @@
provided
linux
+
+ com.alibaba.cola
+ cola-component-statemachine
+ 5.0.0
+
diff --git a/src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java b/src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java
index 894d0369..8105f578 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java
@@ -71,6 +71,8 @@ public class PeerBanHelperServer {
@Getter
private final long banDuration;
@Getter
+ private final long disconnectDuration;
+ @Getter
private final int httpdPort;
@Getter
private final boolean hideFinishLogs;
@@ -95,19 +97,22 @@ public class PeerBanHelperServer {
@Getter
private DatabaseHelper databaseHelper;
@Getter
- private ModuleManager moduleManager;
+ private final ModuleManager moduleManager;
@Getter
@Nullable
private IPDB ipdb = null;
private WatchDog banWaveWatchDog;
@Getter
private JavalinWebContainer webContainer;
-
+ @Getter
+ // private List matchRecords = new CopyOnWriteArrayList<>();
+ private final Map matchRecords = new ConcurrentHashMap<>();
public PeerBanHelperServer(String pbhServerAddress, YamlConfiguration profile, YamlConfiguration mainConfig) throws SQLException {
this.pbhServerAddress = pbhServerAddress;
this.profile = profile;
this.banDuration = profile.getLong("ban-duration");
+ this.disconnectDuration = profile.getLong("disconnect-duration");
this.mainConfig = mainConfig;
this.httpdPort = mainConfig.getInt("server.http");
this.hideFinishLogs = mainConfig.getBoolean("logger.hide-finish-log");
@@ -374,7 +379,7 @@ public void banWave() {
banWaveWatchDog.setLastOperation("Reset last status");
// 声明基本集合
// 需要重启的种子列表
- Map> needRelaunched = new ConcurrentHashMap<>();
+ Map> needRelaunched = new ConcurrentHashMap<>();
// 被解除封禁的对等体列表
banWaveWatchDog.setLastOperation("Remove expired bans");
Collection unbannedPeers = removeExpiredBans();
@@ -386,6 +391,43 @@ public void banWave() {
// 更新 LIVE_PEERS 用于数据展示
banWaveWatchDog.setLastOperation("Update live peers");
executor.submit(() -> updateLivePeers(peers));
+ // ===============基于 状态机 的封禁逻辑
+ banWaveWatchDog.setLastOperation("Check Bans New");
+ // long t1 = System.currentTimeMillis();
+ // 断开连接超时剔除
+ matchRecords.values().stream().filter(ele -> ele.getResult().state() == PeerState.ACTIVE && ele.getResult().expireTime() < System.currentTimeMillis())
+ .map(ele -> ele.getPeer().getAddress()).forEach(matchRecords::remove);
+ // 封禁超时解禁后剔除
+ matchRecords.values().stream().filter(ele -> ele.getResult().state() == PeerState.BAN && ele.getResult().expireTime() < System.currentTimeMillis())
+ .map(ele -> ele.getPeer().getAddress()).forEach(ele -> {
+ unbanPeer(ele);
+ matchRecords.remove(ele);
+ });
+ // 按模块并行检查标记Peer
+ List ruleBlockers = moduleManager.getModules().stream().filter(ele -> ele instanceof RuleBlocker).toList();
+ CountDownLatch fsmLatch = new CountDownLatch(ruleBlockers.size());
+ ruleBlockers.forEach(ele -> {
+ RuleBlocker blocker = (RuleBlocker) ele;
+ try (TimeoutProtect protect = new TimeoutProtect(ExceptedTime.CHECK_BANS.getTimeout(), (t) -> {
+ log.warn(Lang.TIMING_CHECK_BANS);
+ fsmLatch.countDown();
+ })) {
+ protect.getService().submit(() -> {
+ blocker.runCheck();
+ fsmLatch.countDown();
+ });
+ }
+ });
+ fsmLatch.await();
+ // 标记完成后将结果为Ban的Peer封禁
+ banWaveWatchDog.setLastOperation("Add banned peers into banlist New");
+ matchRecords.values().stream().filter(ele -> ele.getResult().state() == PeerState.BAN && !BAN_LIST.containsKey(ele.getPeer().getAddress()))
+ .forEach(record -> Optional.ofNullable(needRelaunched.get(record.getDownloader())).ifPresentOrElse(torrents ->
+ banPeer(record.getDownloader(), record.getTorrent(), record.getPeer(), record.getResult().moduleContext().getClass().getName(), record.getResult().rule(), record.getResult().reason(), bannedPeers, torrents), () -> {
+ List torrents = new ArrayList<>();
+ banPeer(record.getDownloader(), record.getTorrent(), record.getPeer(), record.getResult().moduleContext().getClass().getName(), record.getResult().rule(), record.getResult().reason(), bannedPeers, torrents);
+ needRelaunched.put(record.getDownloader(), torrents);
+ }));
// ========== 处理封禁逻辑 ==========
Map> downloaderBanDetailMap = new ConcurrentHashMap<>();
banWaveWatchDog.setLastOperation("Check Bans");
@@ -399,25 +441,20 @@ public void banWave() {
try (TimeoutProtect protect = new TimeoutProtect(ExceptedTime.ADD_BAN_ENTRY.getTimeout(), (t) -> {
log.warn(Lang.TIMING_ADD_BANS);
})) {
- downloaderBanDetailMap.forEach((downloader, details) -> {
- List relaunch = Collections.synchronizedList(new ArrayList<>());
- details.forEach(detail -> {
- protect.getService().submit(() -> {
+ downloaderBanDetailMap.forEach((downloader, details) -> Optional.ofNullable(needRelaunched.get(downloader)).ifPresentOrElse(torrents ->
+ details.forEach(detail -> protect.getService().submit(() -> {
if (detail.result().action() == PeerAction.BAN) {
- IPDBResponse ipdbResponse = queryIPDB(detail.peer().getAddress());
- BanMetadata banMetadata = new BanMetadata(detail.result().moduleContext().getClass().getName(), downloader.getName(),
- System.currentTimeMillis(), System.currentTimeMillis() + banDuration,
- detail.torrent(), detail.peer(), detail.result().rule(), detail.result().reason(),
- ipdbResponse.cityResponse(), ipdbResponse.asnResponse());
- bannedPeers.add(banMetadata);
- relaunch.add(detail.torrent());
- banPeer(banMetadata, detail.torrent(), detail.peer());
- log.warn(Lang.BAN_PEER, detail.peer().getAddress(), detail.peer().getPeerId(), detail.peer().getClientName(), detail.peer().getProgress(), detail.peer().getUploaded(), detail.peer().getDownloaded(), detail.torrent().getName(), detail.result().reason());
+ banPeer(downloader, detail.torrent(), detail.peer(), detail.result().moduleContext().getClass().getName(), detail.result().rule(), detail.result().reason(), bannedPeers, torrents);
}
- });
- });
- needRelaunched.put(downloader, relaunch);
- });
+ })), () -> {
+ List torrents = new ArrayList<>();
+ details.forEach(detail -> protect.getService().submit(() -> {
+ if (detail.result().action() == PeerAction.BAN) {
+ banPeer(downloader, detail.torrent(), detail.peer(), detail.result().moduleContext().getClass().getName(), detail.result().rule(), detail.result().reason(), bannedPeers, torrents);
+ }
+ }));
+ needRelaunched.put(downloader, torrents);
+ }));
}
banWaveWatchDog.setLastOperation("Apply banlist");
// 如果需要,则应用更改封禁列表到下载器
@@ -435,6 +472,8 @@ public void banWave() {
log.info(Lang.BAN_WAVE_CHECK_COMPLETED, downloadersCount, torrentsCount, peersCount, bannedPeers.size(), unbannedPeers.size(), System.currentTimeMillis() - startTimer);
}
banWaveWatchDog.setLastOperation("Completed");
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
} finally {
banWaveWatchDog.feed();
metrics.recordCheck();
@@ -474,6 +513,15 @@ private void updateLivePeers(Map>> peers) {
torrent, p, ipdbResponse.cityResponse(), ipdbResponse.asnResponse()
);
livePeers.put(address, metadata);
+ // 更新匹配记录
+ if (matchRecords.containsKey(address)) {
+ PeerMatchRecord peerMatchRecord = matchRecords.get(address);
+ peerMatchRecord.setDownloader(downloader);
+ peerMatchRecord.setTorrent(torrent);
+ peerMatchRecord.setPeer(p);
+ } else {
+ matchRecords.put(address, new PeerMatchRecord(downloader, torrent, p, new MatchResultDetail(null, PeerState.INIT, "N/A", "no matches", 0)));
+ }
});
})));
}
@@ -534,7 +582,8 @@ public Collection removeExpiredBans() {
private void registerModules() {
log.info(Lang.WAIT_FOR_MODULES_STARTUP);
moduleManager.register(new IPBlackList(this, profile));
- moduleManager.register(new PeerIdBlacklist(this, profile));
+ //moduleManager.register(new PeerIdBlacklist(this, profile));
+ moduleManager.register(new PeerIdBlocker(this, profile));
moduleManager.register(new ClientNameBlacklist(this, profile));
moduleManager.register(new ProgressCheatBlocker(this, profile));
moduleManager.register(new MultiDialingBlocker(this, profile));
@@ -542,7 +591,7 @@ private void registerModules() {
moduleManager.register(new AutoRangeBan(this, profile));
moduleManager.register(new BtnNetworkOnline(this, profile));
moduleManager.register(new DownloaderCIDRBlockList(this, profile));
- moduleManager.register(new IPBlackRuleList(this, profile, databaseHelper));
+ moduleManager.register(new RuleSubBlocker(this, profile, databaseHelper));
moduleManager.register(new PBHMetricsController(this, profile));
moduleManager.register(new PBHBanController(this, profile, databaseHelper));
moduleManager.register(new PBHMetadataController(this, profile));
@@ -674,10 +723,18 @@ public Map getBannedPeers() {
/**
* 以指定元数据封禁一个特定的对等体
*
- * @param peer 对等体 IP 地址
- * @param banMetadata 封禁元数据
+ * @param peer 对等体 IP 地址
*/
- public void banPeer(@NotNull BanMetadata banMetadata, @NotNull Torrent torrentObj, @NotNull Peer peer) {
+ public void banPeer(@NotNull Downloader downloader, @NotNull Torrent torrent, @NotNull Peer peer, @NotNull String module, @NotNull String ruleName, @NotNull String reason, @NotNull Collection bannedPeers, @NotNull List relaunch) {
+ if (BAN_LIST.containsKey(peer.getAddress())) {
+ return;
+ }
+ relaunch.add(torrent);
+ IPDBResponse ipdbResponse = queryIPDB(peer.getAddress());
+ BanMetadata banMetadata = new BanMetadata(module, downloader.getName(),
+ System.currentTimeMillis(), System.currentTimeMillis() + banDuration,
+ torrent, peer, ruleName, reason, ipdbResponse.cityResponse(), ipdbResponse.asnResponse());
+ bannedPeers.add(banMetadata);
BAN_LIST.put(peer.getAddress(), banMetadata);
metrics.recordPeerBan(peer.getAddress(), banMetadata);
banListInvoker.forEach(i -> i.add(peer.getAddress(), banMetadata));
@@ -697,7 +754,8 @@ public void banPeer(@NotNull BanMetadata banMetadata, @NotNull Torrent torrentOb
} else {
banMetadata.setReverseLookup("N/A");
}
- Main.getEventBus().post(new PeerBanEvent(peer.getAddress(), banMetadata, torrentObj, peer));
+ Main.getEventBus().post(new PeerBanEvent(peer.getAddress(), banMetadata, torrent, peer));
+ log.warn(Lang.BAN_PEER, peer.getAddress(), peer.getPeerId(), peer.getClientName(), peer.getProgress(), peer.getUploaded(), peer.getDownloaded(), torrent.getName(), reason);
}
public List getDownloaders() {
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/AbstractRuleBlocker.java b/src/main/java/com/ghostchu/peerbanhelper/module/AbstractRuleBlocker.java
new file mode 100644
index 00000000..8cf2c35b
--- /dev/null
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/AbstractRuleBlocker.java
@@ -0,0 +1,33 @@
+package com.ghostchu.peerbanhelper.module;
+
+import com.alibaba.cola.statemachine.StateMachine;
+import com.ghostchu.peerbanhelper.PeerBanHelperServer;
+import org.bspfsystems.yamlconfiguration.file.YamlConfiguration;
+
+public abstract class AbstractRuleBlocker extends AbstractFeatureModule implements RuleBlocker {
+
+ public StateMachine stateMachine;
+
+ public AbstractRuleBlocker(PeerBanHelperServer server, YamlConfiguration profile) {
+ super(server, profile);
+ }
+
+ @Override
+ public boolean isConfigurable() {
+ return true;
+ }
+
+ @Override
+ public void onEnable() {
+ stateMachine = ruleSmBuilder().build(getConfigName());
+ }
+
+ @Override
+ public void onDisable() {
+ }
+
+ @Override
+ public StateMachine getStateMachine() {
+ return stateMachine;
+ }
+}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/MatchEvents.java b/src/main/java/com/ghostchu/peerbanhelper/module/MatchEvents.java
new file mode 100644
index 00000000..557364df
--- /dev/null
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/MatchEvents.java
@@ -0,0 +1,27 @@
+package com.ghostchu.peerbanhelper.module;
+
+/**
+ *
+ */
+public enum MatchEvents {
+ /**
+ * 匹配规则
+ */
+ MATCH,
+ /**
+ * 命中规则
+ */
+ HIT,
+ /**
+ * 通过规则
+ */
+ PASS,
+ /**
+ * 断开
+ */
+ DISCONNECT,
+ /**
+ * 超时
+ */
+ TIMEOUT
+}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/MatchResultDetail.java b/src/main/java/com/ghostchu/peerbanhelper/module/MatchResultDetail.java
new file mode 100644
index 00000000..a0c3e7b8
--- /dev/null
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/MatchResultDetail.java
@@ -0,0 +1,5 @@
+package com.ghostchu.peerbanhelper.module;
+
+public record MatchResultDetail(FeatureModule moduleContext, PeerState state, String rule, String reason,
+ long expireTime) {
+}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/PeerMatchRecord.java b/src/main/java/com/ghostchu/peerbanhelper/module/PeerMatchRecord.java
new file mode 100644
index 00000000..219f2a9d
--- /dev/null
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/PeerMatchRecord.java
@@ -0,0 +1,21 @@
+package com.ghostchu.peerbanhelper.module;
+
+import com.ghostchu.peerbanhelper.downloader.Downloader;
+import com.ghostchu.peerbanhelper.peer.Peer;
+import com.ghostchu.peerbanhelper.torrent.Torrent;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * Peer匹配记录
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class PeerMatchRecord {
+ Downloader downloader;
+ Torrent torrent;
+ Peer peer;
+ MatchResultDetail result;
+}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/PeerState.java b/src/main/java/com/ghostchu/peerbanhelper/module/PeerState.java
new file mode 100644
index 00000000..fbcc0c73
--- /dev/null
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/PeerState.java
@@ -0,0 +1,27 @@
+package com.ghostchu.peerbanhelper.module;
+
+/**
+ * Peer状态
+ */
+public enum PeerState {
+ /**
+ * 初始化
+ */
+ INIT,
+ /**
+ * 匹配
+ */
+ MATCH,
+ /**
+ * 封禁
+ */
+ BAN,
+ /**
+ * 活跃
+ */
+ ACTIVE,
+ /**
+ * 结束
+ */
+ END
+}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/RuleBlocker.java b/src/main/java/com/ghostchu/peerbanhelper/module/RuleBlocker.java
new file mode 100644
index 00000000..15663c91
--- /dev/null
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/RuleBlocker.java
@@ -0,0 +1,115 @@
+package com.ghostchu.peerbanhelper.module;
+
+import com.alibaba.cola.statemachine.StateMachine;
+import com.alibaba.cola.statemachine.builder.StateMachineBuilder;
+import com.alibaba.cola.statemachine.builder.StateMachineBuilderFactory;
+import com.ghostchu.peerbanhelper.PeerBanHelperServer;
+import com.ghostchu.peerbanhelper.text.Lang;
+import org.slf4j.Logger;
+
+import java.util.Optional;
+
+/**
+ * 基于状态机模型的规则模块接口
+ */
+public interface RuleBlocker extends FeatureModule {
+
+ /**
+ * 规则状态机构造器
+ *
+ * @return 状态机构造器
+ */
+ default StateMachineBuilder ruleSmBuilder() {
+ StateMachineBuilder fsmBuilder = StateMachineBuilderFactory.create();
+ fsmBuilder.externalTransitions().fromAmong(PeerState.INIT, PeerState.ACTIVE).to(PeerState.MATCH).on(MatchEvents.MATCH)
+ .perform((from, to, event, context) -> {
+ // 匹配
+ CheckResult result = shouldBanPeer(context);
+ if (result.hit()) {
+ context.setResult(new MatchResultDetail(this, to, result.rule(), result.reason(), System.currentTimeMillis() + getServer().getDisconnectDuration()));
+ triggerEvent(MatchEvents.HIT, context);
+ } else {
+ context.setResult(new MatchResultDetail(this, to, "N/A", "No matches", System.currentTimeMillis() + getServer().getDisconnectDuration()));
+ triggerEvent(MatchEvents.PASS, context);
+ }
+ });
+ fsmBuilder.externalTransition().from(PeerState.MATCH).to(PeerState.ACTIVE).on(MatchEvents.PASS)
+ .perform((from, to, event, context) -> {
+ // 活跃
+ context.setResult(new MatchResultDetail(this, to, "N/A", "No matches", System.currentTimeMillis() + getServer().getDisconnectDuration()));
+ });
+ fsmBuilder.externalTransition().from(PeerState.MATCH).to(PeerState.BAN).on(MatchEvents.HIT)
+ .perform((from, to, event, context) -> {
+ // 封禁
+ getLogger().info(Lang.RULE_MODULE_PEER_BAN, getName(), context.getPeer().getAddress());
+ context.setResult(new MatchResultDetail(this, to, context.getResult().rule(), context.getResult().reason(), System.currentTimeMillis() + getServer().getBanDuration()));
+ });
+ /*fsmBuilder.externalTransition().from(PeerState.ACTIVE).to(PeerState.END).on(PeerEvents.DISCONNECT)
+ .perform((from, to, event, context) -> {
+ // 断开连接
+ getLogger().info(Lang.RULE_MODULE_PEER_DISCONNECT, context.getPeer().getPeerId(), context.getPeer().getAddress().getIp(), context.getPeer().getAddress().getPort());
+ context.setResult(new MatchResultDetail(this, to, null, null, 0));
+ });
+ fsmBuilder.externalTransition().from(PeerState.BAN).to(PeerState.END).on(PeerEvents.TIMEOUT)
+ .perform((from, to, event, context) -> {
+ // 解除封禁
+ getLogger().info(Lang.RULE_MODULE_PEER_BAN_TIMEOUT, context.getPeer().getPeerId(), context.getPeer().getAddress().getIp(), context.getPeer().getAddress().getPort());
+ context.setResult(new MatchResultDetail(this, to, null, null, 0));
+ });*/
+ return fsmBuilder;
+ }
+
+ /**
+ * 获取Server
+ *
+ * @return Server
+ */
+ PeerBanHelperServer getServer();
+
+ /**
+ * 获取Logger
+ *
+ * @return Logger
+ */
+ Logger getLogger();
+
+ /**
+ * 获取状态机
+ *
+ * @return 状态机
+ */
+ StateMachine getStateMachine();
+
+ /**
+ * 是否应该封禁Peer
+ *
+ * @param ctx 匹配上下文
+ * @return 是否封禁
+ */
+ CheckResult shouldBanPeer(PeerMatchRecord ctx);
+
+ /**
+ * 运行规则检查
+ */
+ default void runCheck() {
+ // long t1 = System.currentTimeMillis();
+ getServer().getLivePeersSnapshot().keySet().forEach(peerAddress -> Optional.ofNullable(getServer().getMatchRecords().get(peerAddress)).ifPresent(record -> triggerEvent(MatchEvents.MATCH, record)));
+ // long t2 = System.currentTimeMillis();
+ // getLogger().debug(Lang.RULE_MODULE_MATCH_TIME, getName(), t2 - t1);
+ }
+
+ /**
+ * 触发事件
+ *
+ * @param event 事件
+ * @param context 上下文
+ */
+ default void triggerEvent(MatchEvents event, PeerMatchRecord context) {
+ getStateMachine().fireEvent(context.getResult().state(), event, context);
+ }
+
+ record CheckResult(boolean hit, String rule, String reason) {
+
+ }
+
+}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/PeerIdBlocker.java b/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/PeerIdBlocker.java
new file mode 100644
index 00000000..a517ef80
--- /dev/null
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/PeerIdBlocker.java
@@ -0,0 +1,70 @@
+package com.ghostchu.peerbanhelper.module.impl.rule;
+
+import com.ghostchu.peerbanhelper.PeerBanHelperServer;
+import com.ghostchu.peerbanhelper.module.AbstractRuleBlocker;
+import com.ghostchu.peerbanhelper.module.PeerMatchRecord;
+import com.ghostchu.peerbanhelper.text.Lang;
+import com.ghostchu.peerbanhelper.util.rule.Rule;
+import com.ghostchu.peerbanhelper.util.rule.RuleMatchResult;
+import com.ghostchu.peerbanhelper.util.rule.RuleParser;
+import com.ghostchu.peerbanhelper.web.Role;
+import io.javalin.http.Context;
+import io.javalin.http.HttpStatus;
+import lombok.extern.slf4j.Slf4j;
+import org.bspfsystems.yamlconfiguration.file.YamlConfiguration;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+public class PeerIdBlocker extends AbstractRuleBlocker {
+
+ private List bannedPeers;
+
+ public PeerIdBlocker(PeerBanHelperServer server, YamlConfiguration profile) {
+ super(server, profile);
+ }
+
+ @Override
+ public Logger getLogger() {
+ return log;
+ }
+
+ @Override
+ public @NotNull String getName() {
+ return "PeerId Blocker";
+ }
+
+ @Override
+ public @NotNull String getConfigName() {
+ return "peer-id-blacklist";
+ }
+
+ @Override
+ public void onEnable() {
+ stateMachine = ruleSmBuilder().build(getConfigName());
+ reloadConfig();
+ getServer().getWebContainer().javalin()
+ .get("/api/modules/" + getConfigName(), this::handleWebAPI, Role.USER_READ);
+ }
+
+ public void reloadConfig() {
+ this.bannedPeers = RuleParser.parse(getConfig().getStringList("banned-peer-id"));
+ }
+
+ private void handleWebAPI(Context ctx) {
+ ctx.status(HttpStatus.OK);
+ ctx.json(Map.of("peerId", bannedPeers.stream().map(Rule::toPrintableText).toList()));
+ }
+
+ @Override
+ public CheckResult shouldBanPeer(PeerMatchRecord ctx) {
+ RuleMatchResult matchResult = RuleParser.matchRule(bannedPeers, ctx.getPeer().getPeerId());
+ if (matchResult.hit()) {
+ return new CheckResult(true, matchResult.rule().toString(), String.format(Lang.MODULE_PID_MATCH_PEER_ID, matchResult.rule()));
+ }
+ return new CheckResult(false, null, null);
+ }
+}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/IPBlackRuleList.java b/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/RuleSubBlocker.java
similarity index 82%
rename from src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/IPBlackRuleList.java
rename to src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/RuleSubBlocker.java
index 80984a64..4b0d0236 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/IPBlackRuleList.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/RuleSubBlocker.java
@@ -5,18 +5,16 @@
import com.ghostchu.peerbanhelper.database.DatabaseHelper;
import com.ghostchu.peerbanhelper.database.RuleSubInfo;
import com.ghostchu.peerbanhelper.database.RuleSubLog;
-import com.ghostchu.peerbanhelper.module.AbstractRuleFeatureModule;
-import com.ghostchu.peerbanhelper.module.BanResult;
+import com.ghostchu.peerbanhelper.module.AbstractRuleBlocker;
import com.ghostchu.peerbanhelper.module.IPBanRuleUpdateType;
-import com.ghostchu.peerbanhelper.module.PeerAction;
+import com.ghostchu.peerbanhelper.module.PeerMatchRecord;
import com.ghostchu.peerbanhelper.module.impl.webapi.common.SlimMsg;
-import com.ghostchu.peerbanhelper.peer.Peer;
import com.ghostchu.peerbanhelper.text.Lang;
-import com.ghostchu.peerbanhelper.torrent.Torrent;
import com.ghostchu.peerbanhelper.util.HTTPUtil;
import com.ghostchu.peerbanhelper.util.IPAddressUtil;
import com.ghostchu.peerbanhelper.util.rule.MatchResult;
-import com.ghostchu.peerbanhelper.util.rule.matcher.IPBanMatcher;
+import com.ghostchu.peerbanhelper.util.rule.RuleMatcher;
+import com.ghostchu.peerbanhelper.util.rule.matcher.IPMatcher;
import com.github.mizosoft.methanol.MutableRequest;
import com.google.common.hash.HashCode;
import com.google.common.hash.Hashing;
@@ -27,6 +25,7 @@
import org.bspfsystems.yamlconfiguration.configuration.ConfigurationSection;
import org.bspfsystems.yamlconfiguration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
import java.io.File;
import java.io.IOException;
@@ -37,57 +36,46 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
-import java.util.concurrent.ExecutorService;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
-/**
- * IP黑名单远程订阅模块
- */
-@Getter
@Slf4j
-public class IPBlackRuleList extends AbstractRuleFeatureModule {
+public class RuleSubBlocker extends AbstractRuleBlocker {
final private DatabaseHelper db;
- private List ipBanMatchers;
+ @Getter
+ private List ruleMatchers;
+ @Getter
private long checkInterval = 86400000; // 默认24小时检查一次
private ScheduledExecutorService scheduledExecutorService;
- public IPBlackRuleList(PeerBanHelperServer server, YamlConfiguration profile, DatabaseHelper db) {
+ public RuleSubBlocker(PeerBanHelperServer server, YamlConfiguration profile, DatabaseHelper db) {
super(server, profile);
this.db = db;
}
@Override
- public boolean isConfigurable() {
- return true;
- }
-
- @Override
- public boolean isCheckCacheable() {
- return true;
- }
-
- @Override
- public boolean needCheckHandshake() {
- return false;
+ public @NotNull String getName() {
+ return "Rule Sub Blocker";
}
@Override
- public @NotNull String getName() {
- return "IP Blacklist Rule List";
+ public @NotNull String getConfigName() {
+ return "rule-sub-blockers";
}
@Override
- public @NotNull String getConfigName() {
- return "ip-address-blocker-rules";
+ public Logger getLogger() {
+ return log;
}
@Override
public void onEnable() {
+ stateMachine = ruleSmBuilder().build(getConfigName());
ConfigurationSection config = getConfig();
// 读取检查间隔
checkInterval = config.getLong("check-interval", checkInterval);
@@ -95,47 +83,12 @@ public void onEnable() {
scheduledExecutorService.scheduleAtFixedRate(this::reloadConfig, 0, checkInterval, TimeUnit.MILLISECONDS);
}
- @Override
- public void onDisable() {
- }
-
- @Override
- public @NotNull BanResult shouldBanPeer(@NotNull Torrent torrent, @NotNull Peer peer, @NotNull ExecutorService ruleExecuteExecutor) {
- long t1 = System.currentTimeMillis();
- String ip = peer.getAddress().getIp();
- List results = new ArrayList<>();
- try (var service = Executors.newVirtualThreadPerTaskExecutor()) {
- ipBanMatchers.forEach(rule -> service.submit(() -> {
- results.add(new IPBanResult(rule.getRuleName(), rule.match(ip)));
- }));
- }
- AtomicReference matchRule = new AtomicReference<>();
- boolean mr = results.stream().anyMatch(ipBanResult -> {
- try {
- boolean match = ipBanResult.matchResult() == MatchResult.TRUE;
- if (match) {
- matchRule.set(ipBanResult);
- }
- return match;
- } catch (Exception e) {
- log.error(Lang.IP_BAN_RULE_MATCH_ERROR, e);
- return false;
- }
- });
- long t2 = System.currentTimeMillis();
- log.debug(Lang.IP_BAN_RULE_MATCH_TIME, t2 - t1);
- if (mr) {
- return new BanResult(this, PeerAction.BAN, ip, String.format(Lang.MODULE_IBL_MATCH_IP_RULE, matchRule.get().ruleName()));
- }
- return new BanResult(this, PeerAction.NO_ACTION, "N/A", "No matches");
- }
-
/**
* Reload the configuration for this module.
*/
private void reloadConfig() {
- if (null == ipBanMatchers) {
- ipBanMatchers = new ArrayList<>();
+ if (null == ruleMatchers) {
+ ruleMatchers = new ArrayList<>();
}
ConfigurationSection config = getConfig();
// 读取检查间隔
@@ -152,6 +105,27 @@ private void reloadConfig() {
}
}
+ @Override
+ public CheckResult shouldBanPeer(PeerMatchRecord ctx) {
+ String ip = ctx.getPeer().getAddress().getIp();
+ AtomicReference result = new AtomicReference<>(new CheckResult(false, null, null));
+ CountDownLatch latch = new CountDownLatch(ruleMatchers.size());
+ try (var service = Executors.newVirtualThreadPerTaskExecutor()) {
+ ruleMatchers.forEach(matcher -> service.submit(() -> {
+ if (matcher.match(ip) == MatchResult.TRUE) {
+ result.set(new CheckResult(true, matcher.getRuleName(), Lang.MODULE_IBL_MATCH_IP_RULE.replace("{}", matcher.getRuleName())));
+ }
+ latch.countDown();
+ }));
+ }
+ try {
+ latch.await();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ return result.get();
+ }
+
/**
* 更新规则
*
@@ -162,7 +136,7 @@ public SlimMsg updateRule(@NotNull ConfigurationSection rule, IPBanRuleUpdateTyp
String ruleId = rule.getName();
if (!rule.getBoolean("enabled", false)) {
// 检查ipBanMatchers是否有对应的规则,有则删除
- ipBanMatchers.removeIf(ele -> ele.getRuleId().equals(ruleId));
+ ruleMatchers.removeIf(ele -> ele.getRuleId().equals(ruleId));
// 未启用跳过更新逻辑
return new SlimMsg(false, Lang.IP_BAN_RULE_DISABLED.replace("{}", ruleId));
}
@@ -183,10 +157,10 @@ public SlimMsg updateRule(@NotNull ConfigurationSection rule, IPBanRuleUpdateTyp
// 加载远程订阅文件出错,尝试从本地缓存中加载
if (ruleFile.exists()) {
// 如果一致,但ipBanMatchers没有对应的规则内容,则加载内容
- if (ipBanMatchers.stream().noneMatch(ele -> ele.getRuleId().equals(ruleId))) {
+ if (ruleMatchers.stream().noneMatch(ele -> ele.getRuleId().equals(ruleId))) {
try {
fileToIPList(name, ruleFile, ipAddresses, subnetAddresses);
- ipBanMatchers.add(new IPBanMatcher(ruleId, name, ipAddresses, subnetAddresses));
+ ruleMatchers.add(new IPMatcher(ruleId, name, ipAddresses, subnetAddresses));
log.warn(Lang.IP_BAN_RULE_USE_CACHE, name);
result.set(new SlimMsg(false, Lang.IP_BAN_RULE_USE_CACHE.replace("{}", name)));
} catch (IOException ex) {
@@ -217,7 +191,7 @@ public SlimMsg updateRule(@NotNull ConfigurationSection rule, IPBanRuleUpdateTyp
tempFile.renameTo(ruleFile);
} else {
// 如果一致,但ipBanMatchers没有对应的规则内容,则加载内容
- if (ipBanMatchers.stream().noneMatch(ele -> ele.getRuleId().equals(ruleId))) {
+ if (ruleMatchers.stream().noneMatch(ele -> ele.getRuleId().equals(ruleId))) {
ent_count = fileToIPList(name, tempFile, ipAddresses, subnetAddresses);
} else {
log.info(Lang.IP_BAN_RULE_NO_UPDATE, name);
@@ -228,12 +202,12 @@ public SlimMsg updateRule(@NotNull ConfigurationSection rule, IPBanRuleUpdateTyp
// ip列表或者subnet列表不为空代表需要更新matcher
if (!ipAddresses.isEmpty() || !subnetAddresses.isEmpty()) {
// 如果已经存在则更新,否则添加
- ipBanMatchers.stream().filter(ele -> ele.getRuleId().equals(ruleId)).findFirst().ifPresentOrElse(ele -> {
+ ruleMatchers.stream().filter(ele -> ele.getRuleId().equals(ruleId)).findFirst().ifPresentOrElse(ele -> {
ele.setData(name, ipAddresses, subnetAddresses);
log.info(Lang.IP_BAN_RULE_UPDATE_SUCCESS, name);
result.set(new SlimMsg(true, Lang.IP_BAN_RULE_UPDATE_SUCCESS.replace("{}", name)));
}, () -> {
- ipBanMatchers.add(new IPBanMatcher(ruleId, name, ipAddresses, subnetAddresses));
+ ruleMatchers.add(new IPMatcher(ruleId, name, ipAddresses, subnetAddresses));
log.info(Lang.IP_BAN_RULE_LOAD_SUCCESS, name);
result.set(new SlimMsg(true, Lang.IP_BAN_RULE_LOAD_SUCCESS.replace("{}", name)));
});
@@ -400,9 +374,4 @@ public void changeCheckInterval(long checkInterval) throws IOException {
scheduledExecutorService = Executors.newScheduledThreadPool(1, r -> Thread.ofVirtual().name("IPBlackRuleList - Update Thread").unstarted(r));
scheduledExecutorService.scheduleAtFixedRate(this::reloadConfig, 0, checkInterval, TimeUnit.MILLISECONDS);
}
-
- record IPBanResult(String ruleName, MatchResult matchResult) {
- }
}
-
-
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/RuleSubController.java b/src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/RuleSubController.java
index 7640f027..20f565d4 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/RuleSubController.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/RuleSubController.java
@@ -4,7 +4,7 @@
import com.ghostchu.peerbanhelper.database.RuleSubInfo;
import com.ghostchu.peerbanhelper.module.AbstractFeatureModule;
import com.ghostchu.peerbanhelper.module.IPBanRuleUpdateType;
-import com.ghostchu.peerbanhelper.module.impl.rule.IPBlackRuleList;
+import com.ghostchu.peerbanhelper.module.impl.rule.RuleSubBlocker;
import com.ghostchu.peerbanhelper.module.impl.webapi.common.SlimMsg;
import com.ghostchu.peerbanhelper.module.impl.webapi.common.StdMsg;
import com.ghostchu.peerbanhelper.text.Lang;
@@ -25,7 +25,7 @@
@Slf4j
public class RuleSubController extends AbstractFeatureModule {
- IPBlackRuleList ipBlackRuleList;
+ RuleSubBlocker ruleSubBlocker;
public RuleSubController(PeerBanHelperServer server, YamlConfiguration profile) {
super(server, profile);
@@ -48,8 +48,8 @@ public boolean isConfigurable() {
@Override
public void onEnable() {
- getServer().getModuleManager().getModules().stream().filter(ele -> ele.getConfigName().equals("ip-address-blocker-rules")).findFirst().ifPresent(ele -> {
- ipBlackRuleList = (IPBlackRuleList) ele;
+ getServer().getModuleManager().getModules().stream().filter(ele -> ele instanceof RuleSubBlocker).findFirst().ifPresent(ele -> {
+ ruleSubBlocker = (RuleSubBlocker) ele;
getServer().getWebContainer().javalin()
// 查询检查间隔
.get("/api/sub/interval", this::getCheckInterval, Role.USER_READ)
@@ -88,7 +88,7 @@ public void onDisable() {
* @param ctx 上下文
*/
private void getCheckInterval(Context ctx) {
- ctx.json(new StdMsg(true, Lang.IP_BAN_RULE_CHECK_INTERVAL_QUERY_SUCCESS, ipBlackRuleList.getCheckInterval()));
+ ctx.json(new StdMsg(true, Lang.IP_BAN_RULE_CHECK_INTERVAL_QUERY_SUCCESS, ruleSubBlocker.getCheckInterval()));
}
/**
@@ -99,7 +99,7 @@ private void getCheckInterval(Context ctx) {
private void changeCheckInterval(Context ctx) {
try {
long interval = JsonUtil.readObject(ctx.body()).get("checkInterval").getAsLong();
- ipBlackRuleList.changeCheckInterval(interval);
+ ruleSubBlocker.changeCheckInterval(interval);
ctx.json(new SlimMsg(true, Lang.IP_BAN_RULE_CHECK_INTERVAL_UPDATED));
} catch (Exception e) {
ctx.status(HttpStatus.BAD_REQUEST);
@@ -122,8 +122,8 @@ private void logs(Context ctx, String ruleId) {
Map map = new HashMap<>();
map.put("pageIndex", pageIndex);
map.put("pageSize", pageSize);
- map.put("results", ipBlackRuleList.queryRuleSubLogs(ruleId, pageIndex, pageSize));
- map.put("total", ipBlackRuleList.countRuleSubLogs(ruleId));
+ map.put("results", ruleSubBlocker.queryRuleSubLogs(ruleId, pageIndex, pageSize));
+ map.put("total", ruleSubBlocker.countRuleSubLogs(ruleId));
ctx.json(new StdMsg(true, Lang.IP_BAN_RULE_LOG_QUERY_SUCCESS, map));
} catch (Exception e) {
log.error(Lang.IP_BAN_RULE_LOG_QUERY_ERROR, e);
@@ -139,7 +139,7 @@ private void logs(Context ctx, String ruleId) {
*/
private SlimMsg updateAll() {
AtomicReference result = new AtomicReference<>();
- ipBlackRuleList.getRuleSubsConfig().getKeys(false).stream().map(this::update).filter(ele -> !ele.success()).findFirst().ifPresentOrElse(result::set, () -> result.set(new SlimMsg(true, Lang.IP_BAN_RULE_ALL_UPDATED)));
+ ruleSubBlocker.getRuleSubsConfig().getKeys(false).stream().map(this::update).filter(ele -> !ele.success()).findFirst().ifPresentOrElse(result::set, () -> result.set(new SlimMsg(true, Lang.IP_BAN_RULE_ALL_UPDATED)));
return result.get();
}
@@ -153,11 +153,11 @@ private SlimMsg update(String ruleId) {
if (ruleId == null || ruleId.isEmpty()) {
return new SlimMsg(false, Lang.IP_BAN_RULE_NO_ID);
}
- ConfigurationSection configurationSection = ipBlackRuleList.getRuleSubsConfig().getConfigurationSection(ruleId);
+ ConfigurationSection configurationSection = ruleSubBlocker.getRuleSubsConfig().getConfigurationSection(ruleId);
if (null == configurationSection) {
return new SlimMsg(false, Lang.IP_BAN_RULE_CANT_FIND.replace("{}", ruleId));
}
- return ipBlackRuleList.updateRule(configurationSection, IPBanRuleUpdateType.MANUAL);
+ return ruleSubBlocker.updateRule(configurationSection, IPBanRuleUpdateType.MANUAL);
}
/**
@@ -175,7 +175,7 @@ private void switcher(Context ctx) throws SQLException, IOException {
ctx.json(new SlimMsg(false, Lang.IP_BAN_RULE_ENABLED_WRONG_PARAM));
return;
}
- RuleSubInfo ruleSubInfo = ipBlackRuleList.getRuleSubInfo(ruleId);
+ RuleSubInfo ruleSubInfo = ruleSubBlocker.getRuleSubInfo(ruleId);
if (null == ruleSubInfo) {
ctx.status(HttpStatus.BAD_REQUEST);
ctx.json(new SlimMsg(false, Lang.IP_BAN_RULE_CANT_FIND.replace("{}", ruleId)));
@@ -183,8 +183,8 @@ private void switcher(Context ctx) throws SQLException, IOException {
}
String msg = (enabled ? Lang.IP_BAN_RULE_ENABLED : Lang.IP_BAN_RULE_DISABLED).replace("{}", ruleSubInfo.ruleName());
if (enabled != ruleSubInfo.enabled()) {
- ConfigurationSection configurationSection = ipBlackRuleList.saveRuleSubInfo(new RuleSubInfo(ruleId, enabled, ruleSubInfo.ruleName(), ruleSubInfo.subUrl(), 0, 0));
- ipBlackRuleList.updateRule(configurationSection, IPBanRuleUpdateType.MANUAL);
+ ConfigurationSection configurationSection = ruleSubBlocker.saveRuleSubInfo(new RuleSubInfo(ruleId, enabled, ruleSubInfo.ruleName(), ruleSubInfo.subUrl(), 0, 0));
+ ruleSubBlocker.updateRule(configurationSection, IPBanRuleUpdateType.MANUAL);
log.info(msg);
ctx.json(new SlimMsg(true, msg));
} else {
@@ -200,14 +200,14 @@ private void switcher(Context ctx) throws SQLException, IOException {
*/
private void delete(Context ctx) throws IOException, SQLException {
String ruleId = ctx.pathParam("ruleId");
- RuleSubInfo ruleSubInfo = ipBlackRuleList.getRuleSubInfo(ruleId);
+ RuleSubInfo ruleSubInfo = ruleSubBlocker.getRuleSubInfo(ruleId);
if (null == ruleSubInfo) {
ctx.status(HttpStatus.BAD_REQUEST);
ctx.json(new SlimMsg(false, Lang.IP_BAN_RULE_CANT_FIND.replace("{}", ruleId)));
return;
}
- ipBlackRuleList.deleteRuleSubInfo(ruleId);
- ipBlackRuleList.getIpBanMatchers().removeIf(ele -> ele.getRuleId().equals(ruleId));
+ ruleSubBlocker.deleteRuleSubInfo(ruleId);
+ ruleSubBlocker.getRuleMatchers().removeIf(ele -> ele.getRuleId().equals(ruleId));
String msg = Lang.IP_BAN_RULE_DELETED.replace("{}", ruleSubInfo.ruleName());
log.info(msg);
ctx.json(new SlimMsg(true, msg));
@@ -230,7 +230,7 @@ private void save(Context ctx, String ruleId, boolean isAdd) throws SQLException
ctx.json(new SlimMsg(false, Lang.IP_BAN_RULE_NO_ID));
return;
}
- RuleSubInfo ruleSubInfo = ipBlackRuleList.getRuleSubInfo(ruleId);
+ RuleSubInfo ruleSubInfo = ruleSubBlocker.getRuleSubInfo(ruleId);
if (isAdd && ruleSubInfo != null) {
// 新增时检查规则是否存在
ctx.status(HttpStatus.BAD_REQUEST);
@@ -259,10 +259,10 @@ private void save(Context ctx, String ruleId, boolean isAdd) throws SQLException
subUrl = ruleSubInfo.subUrl();
}
}
- ConfigurationSection configurationSection = ipBlackRuleList.saveRuleSubInfo(new RuleSubInfo(ruleId, isAdd || ruleSubInfo.enabled(), ruleName, subUrl, 0, 0));
+ ConfigurationSection configurationSection = ruleSubBlocker.saveRuleSubInfo(new RuleSubInfo(ruleId, isAdd || ruleSubInfo.enabled(), ruleName, subUrl, 0, 0));
assert configurationSection != null;
try {
- SlimMsg msg = ipBlackRuleList.updateRule(configurationSection, IPBanRuleUpdateType.MANUAL);
+ SlimMsg msg = ruleSubBlocker.updateRule(configurationSection, IPBanRuleUpdateType.MANUAL);
if (!msg.success()) {
ctx.status(HttpStatus.BAD_REQUEST);
ctx.json(msg);
@@ -272,9 +272,9 @@ private void save(Context ctx, String ruleId, boolean isAdd) throws SQLException
} catch (Exception e) {
// 更新失败时回滚
if (isAdd) {
- ipBlackRuleList.deleteRuleSubInfo(ruleId);
+ ruleSubBlocker.deleteRuleSubInfo(ruleId);
} else {
- ipBlackRuleList.saveRuleSubInfo(ruleSubInfo);
+ ruleSubBlocker.saveRuleSubInfo(ruleSubInfo);
}
ctx.status(HttpStatus.BAD_REQUEST);
ctx.json(new SlimMsg(false, Lang.IP_BAN_RULE_URL_WRONG.replace("{}", ruleName)));
@@ -288,7 +288,7 @@ private void save(Context ctx, String ruleId, boolean isAdd) throws SQLException
* @return 响应
*/
private StdMsg get(String ruleId) throws SQLException {
- return new StdMsg(true, Lang.IP_BAN_RULE_INFO_QUERY_SUCCESS, ipBlackRuleList.getRuleSubInfo(ruleId));
+ return new StdMsg(true, Lang.IP_BAN_RULE_INFO_QUERY_SUCCESS, ruleSubBlocker.getRuleSubInfo(ruleId));
}
/**
@@ -297,10 +297,10 @@ private StdMsg get(String ruleId) throws SQLException {
* @return 响应
*/
private StdMsg list() throws SQLException {
- List list = ipBlackRuleList.getRuleSubsConfig().getKeys(false).stream().toList();
+ List list = ruleSubBlocker.getRuleSubsConfig().getKeys(false).stream().toList();
List data = new ArrayList<>(list.size());
for (String s : list) {
- data.add(ipBlackRuleList.getRuleSubInfo(s));
+ data.add(ruleSubBlocker.getRuleSubInfo(s));
}
return new StdMsg(true, Lang.IP_BAN_RULE_INFO_QUERY_SUCCESS, data);
}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/text/Lang.java b/src/main/java/com/ghostchu/peerbanhelper/text/Lang.java
index b2f7e123..5fad4b5f 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/text/Lang.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/text/Lang.java
@@ -211,4 +211,6 @@ public class Lang {
public static final String GUI_TITLE_LOADED = "PeerBanHelper (%s) - %s (%s)";
public static final String WEBVIEW_DISABLED_WEBKIT_NOT_INCLUDED = "未找到 JavaFx Web 模块,您正在使用精简构建,WebUI 选项卡未启用";
public static final String WEBVIEW_ENABLED = "已找到 JavaFx Web,WebUI 选项卡已启用";
+ public static final String RULE_MODULE_MATCH_TIME = "规则模块 {} 匹配花费时间:{}ms";
+ public static final String RULE_MODULE_PEER_BAN = "[封禁] 规则模块 {} : {} ";
}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/util/rule/RuleMatcher.java b/src/main/java/com/ghostchu/peerbanhelper/util/rule/RuleMatcher.java
new file mode 100644
index 00000000..7a8819cf
--- /dev/null
+++ b/src/main/java/com/ghostchu/peerbanhelper/util/rule/RuleMatcher.java
@@ -0,0 +1,31 @@
+package com.ghostchu.peerbanhelper.util.rule;
+
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.ToString;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 规则Matcher
+ */
+@Getter
+@Slf4j
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public abstract class RuleMatcher extends AbstractMatcher {
+
+ private final String ruleId;
+
+ private final SubRuleType ruleType;
+
+ protected String ruleName;
+
+ public RuleMatcher(SubRuleType ruleType, String ruleId, String ruleName, Object... ruleData) {
+ this.ruleType = ruleType;
+ this.ruleId = ruleId;
+ setData(ruleName, ruleData);
+ }
+
+ public abstract void setData(String ruleName, Object... ruleData);
+
+}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/util/rule/SubRuleType.java b/src/main/java/com/ghostchu/peerbanhelper/util/rule/SubRuleType.java
new file mode 100644
index 00000000..f0af99af
--- /dev/null
+++ b/src/main/java/com/ghostchu/peerbanhelper/util/rule/SubRuleType.java
@@ -0,0 +1,19 @@
+package com.ghostchu.peerbanhelper.util.rule;
+
+/**
+ * 订阅规则类型
+ */
+public enum SubRuleType {
+ /**
+ * IP/CIDR
+ */
+ IP,
+ /**
+ * 子串
+ */
+ SUBSTR,
+ /**
+ * 前缀
+ */
+ PREFIX
+}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/IPBanMatcher.java b/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/IPMatcher.java
similarity index 79%
rename from src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/IPBanMatcher.java
rename to src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/IPMatcher.java
index e46e50f6..c6f9c4ea 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/IPBanMatcher.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/IPMatcher.java
@@ -2,13 +2,13 @@
import com.ghostchu.peerbanhelper.text.Lang;
import com.ghostchu.peerbanhelper.util.IPAddressUtil;
-import com.ghostchu.peerbanhelper.util.rule.AbstractMatcher;
import com.ghostchu.peerbanhelper.util.rule.MatchResult;
+import com.ghostchu.peerbanhelper.util.rule.RuleMatcher;
+import com.ghostchu.peerbanhelper.util.rule.SubRuleType;
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import inet.ipaddr.IPAddress;
import lombok.EqualsAndHashCode;
-import lombok.Getter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
@@ -20,26 +20,21 @@
@Slf4j
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
-public class IPBanMatcher extends AbstractMatcher {
+public class IPMatcher extends RuleMatcher {
- @Getter
- private final String ruleId;
-
- @Getter
- private String ruleName;
private List subnets;
private List ips;
private BloomFilter bloomFilter;
- public IPBanMatcher(String ruleId, String ruleName, List ips, List subnets) {
- this.ruleId = ruleId;
- setData(ruleName, ips, subnets);
+ public IPMatcher(String ruleId, String ruleName, Object... ruleData) {
+ super(SubRuleType.IP, ruleId, ruleName, ruleData);
}
- public void setData(String ruleName, List ips, List subnets) {
+ @Override
+ public void setData(String ruleName, Object... ruleData) {
this.ruleName = ruleName;
- this.ips = ips;
- this.subnets = subnets;
+ this.ips = ruleData.length > 0 ? (List) ruleData[0] : List.of();
+ this.subnets = ruleData.length > 1 ? (List) ruleData[1] : List.of();
bloomFilter = BloomFilter.create(Funnels.stringFunnel(StandardCharsets.UTF_8), ips.size(), 0.01);
ips.forEach(ip -> bloomFilter.put(ip.toString()));
}
diff --git a/src/main/resources/profile.yml b/src/main/resources/profile.yml
index 20959fec..5d2614fa 100644
--- a/src/main/resources/profile.yml
+++ b/src/main/resources/profile.yml
@@ -5,6 +5,8 @@ check-interval: 5000
update-live-peers-interval: 13000
# 封禁持续时间(单位:毫秒)
ban-duration: 86400000
+# 断开连接判定时间(单位:毫秒)
+disconnect-duration: 60000
# 功能模块
module:
# PeerId 封禁
@@ -162,7 +164,7 @@ module:
# keep-hunting为true时有效,和cache-lifespan相似,对被猎杀IP的缓存持续时间
keep-hunting-time: 2592000
# 订阅规则
- ip-address-blocker-rules:
+ rule-sub-blockers:
enabled: false
# 检查间隔
check-interval: 86400000 # 24小时检查一次 毫秒
From b0cce39469b6770e7934a424bcbbc8bb89a71151 Mon Sep 17 00:00:00 2001
From: PluieM <644202913@qq.com>
Date: Wed, 19 Jun 2024 20:54:22 +0800
Subject: [PATCH 2/5] =?UTF-8?q?=E8=A7=84=E5=88=99=E8=AE=A2=E9=98=85?=
=?UTF-8?q?=E6=94=AF=E6=8C=81=E8=AE=A2=E9=98=85=E4=BB=A5=E4=B8=8B=E5=8C=B9?=
=?UTF-8?q?=E9=85=8D=E7=B1=BB=E5=9E=8B=20IP/PEER=5FID=5FCONTAINS/PEER=5FID?=
=?UTF-8?q?=5FSTARTS=5FWITH/CLIENT=5FNAME=5FCONTAINS/CLIENT=5FNAME=5FSTART?=
=?UTF-8?q?S=5FWITH?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../peerbanhelper/PeerBanHelperServer.java | 5 +-
.../config/ProfileUpdateScript.java | 11 +-
.../database/DatabaseHelper.java | 6 +-
.../peerbanhelper/database/RuleSubLog.java | 4 +-
.../module/AbstractRuleBlocker.java | 10 ++
.../peerbanhelper/module/RuleBlocker.java | 8 +-
...uleUpdateType.java => RuleUpdateType.java} | 2 +-
.../module/impl/rule/PeerIdBlocker.java | 9 +-
.../module/impl/rule/RuleSubBlocker.java | 165 ++++++++++++------
.../module/impl/webapi/RuleSubController.java | 54 +++---
.../com/ghostchu/peerbanhelper/text/Lang.java | 57 +++---
.../peerbanhelper/util/rule/RuleMatcher.java | 12 +-
.../peerbanhelper/util/rule/RuleType.java | 27 +++
.../peerbanhelper/util/rule/SubRuleType.java | 19 --
.../util/rule/matcher/IPMatcher.java | 12 +-
.../util/rule/matcher/PrefixMatcher.java | 48 +++++
.../util/rule/matcher/SubStrMatcher.java | 48 +++++
src/main/resources/profile.yml | 2 +
18 files changed, 341 insertions(+), 158 deletions(-)
rename src/main/java/com/ghostchu/peerbanhelper/module/{IPBanRuleUpdateType.java => RuleUpdateType.java} (66%)
create mode 100644 src/main/java/com/ghostchu/peerbanhelper/util/rule/RuleType.java
delete mode 100644 src/main/java/com/ghostchu/peerbanhelper/util/rule/SubRuleType.java
create mode 100644 src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/PrefixMatcher.java
create mode 100644 src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/SubStrMatcher.java
diff --git a/src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java b/src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java
index 8105f578..2e7087e8 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java
@@ -71,7 +71,7 @@ public class PeerBanHelperServer {
@Getter
private final long banDuration;
@Getter
- private final long disconnectDuration;
+ private final long disconnectTimeout;
@Getter
private final int httpdPort;
@Getter
@@ -105,14 +105,13 @@ public class PeerBanHelperServer {
@Getter
private JavalinWebContainer webContainer;
@Getter
- // private List matchRecords = new CopyOnWriteArrayList<>();
private final Map matchRecords = new ConcurrentHashMap<>();
public PeerBanHelperServer(String pbhServerAddress, YamlConfiguration profile, YamlConfiguration mainConfig) throws SQLException {
this.pbhServerAddress = pbhServerAddress;
this.profile = profile;
this.banDuration = profile.getLong("ban-duration");
- this.disconnectDuration = profile.getLong("disconnect-duration");
+ this.disconnectTimeout = profile.getLong("disconnect-timeout");
this.mainConfig = mainConfig;
this.httpdPort = mainConfig.getInt("server.http");
this.hideFinishLogs = mainConfig.getBoolean("logger.hide-finish-log");
diff --git a/src/main/java/com/ghostchu/peerbanhelper/config/ProfileUpdateScript.java b/src/main/java/com/ghostchu/peerbanhelper/config/ProfileUpdateScript.java
index c2e1befa..95ed445a 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/config/ProfileUpdateScript.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/config/ProfileUpdateScript.java
@@ -3,6 +3,7 @@
import com.ghostchu.peerbanhelper.text.Lang;
import com.google.gson.JsonObject;
import lombok.extern.slf4j.Slf4j;
+import org.bspfsystems.yamlconfiguration.configuration.ConfigurationSection;
import org.bspfsystems.yamlconfiguration.file.YamlConfiguration;
import java.util.ArrayList;
@@ -18,6 +19,15 @@ public ProfileUpdateScript(YamlConfiguration conf) {
this.conf = conf;
}
+ @UpdateScript(version = 8)
+ public void subModuleUpdate() {
+ conf.set("disconnect-timeout", 60000);
+ conf.set("module.rule-sub-blockers", conf.getConfigurationSection("module.ip-address-blocker-rules"));
+ conf.set("module.ip-address-blocker-rules", null);
+ ConfigurationSection rules = conf.getConfigurationSection("module.rule-sub-blockers.rules");
+ rules.getKeys(false).forEach(ruleId -> rules.getConfigurationSection(ruleId).set("type", "IP"));
+ }
+
@UpdateScript(version = 7)
public void progressCheckerIPPrefixLength() {
conf.set("module.progress-cheat-blocker.ipv4-prefix-length", 32);
@@ -33,7 +43,6 @@ public void subModule() {
conf.set("module.ip-address-blocker-rules.rules.example-rule.url", "https://example.com/example.txt");
}
-
@UpdateScript(version = 4)
public void ipDatabase() {
conf.set("module.ip-address-blocker.asns", new ArrayList<>());
diff --git a/src/main/java/com/ghostchu/peerbanhelper/database/DatabaseHelper.java b/src/main/java/com/ghostchu/peerbanhelper/database/DatabaseHelper.java
index 80ddd70a..5eb43714 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/database/DatabaseHelper.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/database/DatabaseHelper.java
@@ -1,6 +1,6 @@
package com.ghostchu.peerbanhelper.database;
-import com.ghostchu.peerbanhelper.module.IPBanRuleUpdateType;
+import com.ghostchu.peerbanhelper.module.RuleUpdateType;
import com.ghostchu.peerbanhelper.text.Lang;
import lombok.Cleanup;
import lombok.extern.slf4j.Slf4j;
@@ -366,7 +366,7 @@ public List queryRuleSubLogs(String ruleId, int pageIndex, int pageS
set.getString("rule_id"),
set.getLong("update_time"),
set.getInt("ent_count"),
- IPBanRuleUpdateType.valueOf(set.getString("update_type"))
+ RuleUpdateType.valueOf(set.getString("update_type"))
));
}
return infos;
@@ -383,7 +383,7 @@ public List queryRuleSubLogs(String ruleId, int pageIndex, int pageS
* @param updateType 更新类型
* @throws SQLException SQL异常
*/
- public void insertRuleSubLog(String ruleId, int count, IPBanRuleUpdateType updateType) throws SQLException {
+ public void insertRuleSubLog(String ruleId, int count, RuleUpdateType updateType) throws SQLException {
try (Connection connection = manager.getConnection()) {
PreparedStatement ps;
ps = connection.prepareStatement("INSERT INTO rule_sub_logs (rule_id, update_time, ent_count, update_type) VALUES (?,?,?,?)");
diff --git a/src/main/java/com/ghostchu/peerbanhelper/database/RuleSubLog.java b/src/main/java/com/ghostchu/peerbanhelper/database/RuleSubLog.java
index ab557f50..d4658267 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/database/RuleSubLog.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/database/RuleSubLog.java
@@ -1,11 +1,11 @@
package com.ghostchu.peerbanhelper.database;
-import com.ghostchu.peerbanhelper.module.IPBanRuleUpdateType;
+import com.ghostchu.peerbanhelper.module.RuleUpdateType;
public record RuleSubLog(
String ruleId,
long updateTime,
int count,
- IPBanRuleUpdateType updateType
+ RuleUpdateType updateType
) {
}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/AbstractRuleBlocker.java b/src/main/java/com/ghostchu/peerbanhelper/module/AbstractRuleBlocker.java
index 8cf2c35b..a342e945 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/module/AbstractRuleBlocker.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/AbstractRuleBlocker.java
@@ -2,10 +2,17 @@
import com.alibaba.cola.statemachine.StateMachine;
import com.ghostchu.peerbanhelper.PeerBanHelperServer;
+import com.ghostchu.peerbanhelper.util.rule.Rule;
+import lombok.Getter;
import org.bspfsystems.yamlconfiguration.file.YamlConfiguration;
+import java.util.List;
+
public abstract class AbstractRuleBlocker extends AbstractFeatureModule implements RuleBlocker {
+ @Getter
+ public List rules;
+
public StateMachine stateMachine;
public AbstractRuleBlocker(PeerBanHelperServer server, YamlConfiguration profile) {
@@ -20,6 +27,7 @@ public boolean isConfigurable() {
@Override
public void onEnable() {
stateMachine = ruleSmBuilder().build(getConfigName());
+ init();
}
@Override
@@ -30,4 +38,6 @@ public void onDisable() {
public StateMachine getStateMachine() {
return stateMachine;
}
+
+ public abstract void init();
}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/RuleBlocker.java b/src/main/java/com/ghostchu/peerbanhelper/module/RuleBlocker.java
index 15663c91..afc06789 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/module/RuleBlocker.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/RuleBlocker.java
@@ -26,22 +26,22 @@ default StateMachineBuilder ruleSmBuild
// 匹配
CheckResult result = shouldBanPeer(context);
if (result.hit()) {
- context.setResult(new MatchResultDetail(this, to, result.rule(), result.reason(), System.currentTimeMillis() + getServer().getDisconnectDuration()));
+ context.setResult(new MatchResultDetail(this, to, result.rule(), result.reason(), System.currentTimeMillis() + getServer().getDisconnectTimeout()));
triggerEvent(MatchEvents.HIT, context);
} else {
- context.setResult(new MatchResultDetail(this, to, "N/A", "No matches", System.currentTimeMillis() + getServer().getDisconnectDuration()));
+ context.setResult(new MatchResultDetail(this, to, "N/A", "No matches", System.currentTimeMillis() + getServer().getDisconnectTimeout()));
triggerEvent(MatchEvents.PASS, context);
}
});
fsmBuilder.externalTransition().from(PeerState.MATCH).to(PeerState.ACTIVE).on(MatchEvents.PASS)
.perform((from, to, event, context) -> {
// 活跃
- context.setResult(new MatchResultDetail(this, to, "N/A", "No matches", System.currentTimeMillis() + getServer().getDisconnectDuration()));
+ context.setResult(new MatchResultDetail(this, to, "N/A", "No matches", System.currentTimeMillis() + getServer().getDisconnectTimeout()));
});
fsmBuilder.externalTransition().from(PeerState.MATCH).to(PeerState.BAN).on(MatchEvents.HIT)
.perform((from, to, event, context) -> {
// 封禁
- getLogger().info(Lang.RULE_MODULE_PEER_BAN, getName(), context.getPeer().getAddress());
+ getLogger().debug(Lang.RULE_MODULE_PEER_BAN, getName(), context.getPeer().getAddress());
context.setResult(new MatchResultDetail(this, to, context.getResult().rule(), context.getResult().reason(), System.currentTimeMillis() + getServer().getBanDuration()));
});
/*fsmBuilder.externalTransition().from(PeerState.ACTIVE).to(PeerState.END).on(PeerEvents.DISCONNECT)
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/IPBanRuleUpdateType.java b/src/main/java/com/ghostchu/peerbanhelper/module/RuleUpdateType.java
similarity index 66%
rename from src/main/java/com/ghostchu/peerbanhelper/module/IPBanRuleUpdateType.java
rename to src/main/java/com/ghostchu/peerbanhelper/module/RuleUpdateType.java
index 72f70ac1..f1daa49f 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/module/IPBanRuleUpdateType.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/RuleUpdateType.java
@@ -1,6 +1,6 @@
package com.ghostchu.peerbanhelper.module;
-public enum IPBanRuleUpdateType {
+public enum RuleUpdateType {
AUTO,
MANUAL
}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/PeerIdBlocker.java b/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/PeerIdBlocker.java
index a517ef80..376c7574 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/PeerIdBlocker.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/PeerIdBlocker.java
@@ -43,17 +43,12 @@ public Logger getLogger() {
}
@Override
- public void onEnable() {
- stateMachine = ruleSmBuilder().build(getConfigName());
- reloadConfig();
+ public void init() {
+ this.bannedPeers = RuleParser.parse(getConfig().getStringList("banned-peer-id"));
getServer().getWebContainer().javalin()
.get("/api/modules/" + getConfigName(), this::handleWebAPI, Role.USER_READ);
}
- public void reloadConfig() {
- this.bannedPeers = RuleParser.parse(getConfig().getStringList("banned-peer-id"));
- }
-
private void handleWebAPI(Context ctx) {
ctx.status(HttpStatus.OK);
ctx.json(Map.of("peerId", bannedPeers.stream().map(Rule::toPrintableText).toList()));
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/RuleSubBlocker.java b/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/RuleSubBlocker.java
index 4b0d0236..a815016f 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/RuleSubBlocker.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/RuleSubBlocker.java
@@ -6,15 +6,18 @@
import com.ghostchu.peerbanhelper.database.RuleSubInfo;
import com.ghostchu.peerbanhelper.database.RuleSubLog;
import com.ghostchu.peerbanhelper.module.AbstractRuleBlocker;
-import com.ghostchu.peerbanhelper.module.IPBanRuleUpdateType;
import com.ghostchu.peerbanhelper.module.PeerMatchRecord;
+import com.ghostchu.peerbanhelper.module.RuleUpdateType;
import com.ghostchu.peerbanhelper.module.impl.webapi.common.SlimMsg;
import com.ghostchu.peerbanhelper.text.Lang;
import com.ghostchu.peerbanhelper.util.HTTPUtil;
import com.ghostchu.peerbanhelper.util.IPAddressUtil;
import com.ghostchu.peerbanhelper.util.rule.MatchResult;
import com.ghostchu.peerbanhelper.util.rule.RuleMatcher;
+import com.ghostchu.peerbanhelper.util.rule.RuleType;
import com.ghostchu.peerbanhelper.util.rule.matcher.IPMatcher;
+import com.ghostchu.peerbanhelper.util.rule.matcher.PrefixMatcher;
+import com.ghostchu.peerbanhelper.util.rule.matcher.SubStrMatcher;
import com.github.mizosoft.methanol.MutableRequest;
import com.google.common.hash.HashCode;
import com.google.common.hash.Hashing;
@@ -47,8 +50,7 @@
public class RuleSubBlocker extends AbstractRuleBlocker {
final private DatabaseHelper db;
- @Getter
- private List ruleMatchers;
+
@Getter
private long checkInterval = 86400000; // 默认24小时检查一次
private ScheduledExecutorService scheduledExecutorService;
@@ -83,37 +85,50 @@ public void onEnable() {
scheduledExecutorService.scheduleAtFixedRate(this::reloadConfig, 0, checkInterval, TimeUnit.MILLISECONDS);
}
- /**
- * Reload the configuration for this module.
- */
- private void reloadConfig() {
- if (null == ruleMatchers) {
- ruleMatchers = new ArrayList<>();
- }
- ConfigurationSection config = getConfig();
- // 读取检查间隔
- checkInterval = config.getLong("check-interval", checkInterval);
+ @Override
+ public void init() {
// 读取规则
ConfigurationSection rules = getRuleSubsConfig();
if (null != rules) {
for (String ruleId : rules.getKeys(false)) {
ConfigurationSection rule = rules.getConfigurationSection(ruleId);
assert rule != null;
- updateRule(rule, IPBanRuleUpdateType.AUTO);
+ updateRule(rule, RuleUpdateType.AUTO);
}
- log.info(Lang.IP_BAN_RULE_UPDATE_FINISH);
+ log.info(Lang.SUB_RULE_UPDATE_FINISH);
}
}
+ /**
+ * Reload the configuration for this module.
+ */
+ private void reloadConfig() {
+ if (null == rules) {
+ rules = new ArrayList<>();
+ }
+ ConfigurationSection config = getConfig();
+ // 读取检查间隔
+ checkInterval = config.getLong("check-interval", checkInterval);
+ init();
+ }
+
@Override
public CheckResult shouldBanPeer(PeerMatchRecord ctx) {
- String ip = ctx.getPeer().getAddress().getIp();
AtomicReference result = new AtomicReference<>(new CheckResult(false, null, null));
- CountDownLatch latch = new CountDownLatch(ruleMatchers.size());
+ CountDownLatch latch = new CountDownLatch(rules.size());
try (var service = Executors.newVirtualThreadPerTaskExecutor()) {
- ruleMatchers.forEach(matcher -> service.submit(() -> {
- if (matcher.match(ip) == MatchResult.TRUE) {
- result.set(new CheckResult(true, matcher.getRuleName(), Lang.MODULE_IBL_MATCH_IP_RULE.replace("{}", matcher.getRuleName())));
+ rules.forEach(matcher -> service.submit(() -> {
+ String matchStr;
+ Object type = matcher.metadata().get("type");
+ if (type == RuleType.PEER_ID_STARTS_WITH || type == RuleType.PEER_ID_CONTAINS) {
+ matchStr = ctx.getPeer().getPeerId();
+ } else if (type == RuleType.CLIENT_NAME_STARTS_WITH || type == RuleType.CLIENT_NAME_CONTAINS) {
+ matchStr = ctx.getPeer().getClientName();
+ } else {
+ matchStr = ctx.getPeer().getAddress().getIp();
+ }
+ if (matcher.match(matchStr) == MatchResult.TRUE) {
+ result.set(new CheckResult(true, matcher.metadata().get("name").toString(), String.format(Lang.MODULE_IBL_MATCH_SUB_RULE, matcher.metadata().get("name").toString())));
}
latch.countDown();
}));
@@ -131,17 +146,18 @@ public CheckResult shouldBanPeer(PeerMatchRecord ctx) {
*
* @param rule 规则
*/
- public SlimMsg updateRule(@NotNull ConfigurationSection rule, IPBanRuleUpdateType updateType) {
+ public SlimMsg updateRule(@NotNull ConfigurationSection rule, RuleUpdateType updateType) {
AtomicReference result = new AtomicReference<>();
String ruleId = rule.getName();
if (!rule.getBoolean("enabled", false)) {
// 检查ipBanMatchers是否有对应的规则,有则删除
- ruleMatchers.removeIf(ele -> ele.getRuleId().equals(ruleId));
+ rules.removeIf(ele -> ele.metadata().get("id").equals(ruleId));
// 未启用跳过更新逻辑
- return new SlimMsg(false, Lang.IP_BAN_RULE_DISABLED.replace("{}", ruleId));
+ return new SlimMsg(false, Lang.SUB_RULE_DISABLED.replace("{}", ruleId));
}
String name = rule.getString("name", ruleId);
String url = rule.getString("url");
+ RuleType ruleType = RuleType.valueOf(Optional.ofNullable(rule.getString("type")).orElse("IP"));
if (null != url && url.startsWith("http")) {
// 解析远程订阅
String ruleFileName = ruleId + ".txt";
@@ -151,28 +167,41 @@ public SlimMsg updateRule(@NotNull ConfigurationSection rule, IPBanRuleUpdateTyp
File ruleFile = new File(dir, ruleFileName);
List ipAddresses = new ArrayList<>();
List subnetAddresses = new ArrayList<>();
+ List fileLines = new ArrayList<>();
HTTPUtil.retryableSend(HTTPUtil.getHttpClient(false, null), MutableRequest.GET(url), HttpResponse.BodyHandlers.ofFile(Path.of(tempFile.getPath()))).whenComplete((pathHttpResponse, throwable) -> {
if (throwable != null) {
tempFile.delete();
// 加载远程订阅文件出错,尝试从本地缓存中加载
if (ruleFile.exists()) {
// 如果一致,但ipBanMatchers没有对应的规则内容,则加载内容
- if (ruleMatchers.stream().noneMatch(ele -> ele.getRuleId().equals(ruleId))) {
+ if (rules.stream().noneMatch(ele -> ele.metadata().get("id").equals(ruleId))) {
try {
- fileToIPList(name, ruleFile, ipAddresses, subnetAddresses);
- ruleMatchers.add(new IPMatcher(ruleId, name, ipAddresses, subnetAddresses));
- log.warn(Lang.IP_BAN_RULE_USE_CACHE, name);
- result.set(new SlimMsg(false, Lang.IP_BAN_RULE_USE_CACHE.replace("{}", name)));
+ switch (ruleType) {
+ case PEER_ID_STARTS_WITH, CLIENT_NAME_STARTS_WITH -> {
+ fileToLines(name, ruleFile, fileLines);
+ rules.add(new PrefixMatcher(ruleType, ruleId, name, fileLines));
+ }
+ case PEER_ID_CONTAINS, CLIENT_NAME_CONTAINS -> {
+ fileToLines(name, ruleFile, fileLines);
+ rules.add(new SubStrMatcher(ruleType, ruleId, name, fileLines));
+ }
+ default -> {
+ fileToIPList(name, ruleFile, ipAddresses, subnetAddresses);
+ rules.add(new IPMatcher(ruleId, name, ipAddresses, subnetAddresses));
+ }
+ }
+ log.warn(Lang.SUB_RULE_USE_CACHE, name);
+ result.set(new SlimMsg(false, Lang.SUB_RULE_USE_CACHE.replace("{}", name)));
} catch (IOException ex) {
- log.error(Lang.IP_BAN_RULE_LOAD_FAILED, name, ex);
- result.set(new SlimMsg(false, Lang.IP_BAN_RULE_LOAD_FAILED.replace("{}", name)));
+ log.error(Lang.SUB_RULE_LOAD_FAILED, name, ex);
+ result.set(new SlimMsg(false, Lang.SUB_RULE_LOAD_FAILED.replace("{}", name)));
}
} else {
- result.set(new SlimMsg(false, Lang.IP_BAN_RULE_UPDATE_FAILED.replace("{}", name)));
+ result.set(new SlimMsg(false, Lang.SUB_RULE_UPDATE_FAILED.replace("{}", name)));
}
} else {
// log.error(Lang.IP_BAN_RULE_LOAD_FAILED, name, throwable);
- result.set(new SlimMsg(false, Lang.IP_BAN_RULE_LOAD_FAILED.replace("{}", name)));
+ result.set(new SlimMsg(false, Lang.SUB_RULE_LOAD_FAILED.replace("{}", name)));
}
throw new RuntimeException(throwable);
}
@@ -185,55 +214,91 @@ public SlimMsg updateRule(@NotNull ConfigurationSection rule, IPBanRuleUpdateTyp
int ent_count = 0;
if (!tempHash.equals(ruleHash)) {
// 规则文件不存在或者规则文件与临时文件sha256不一致则需要更新
- ent_count = fileToIPList(name, tempFile, ipAddresses, subnetAddresses);
+ ent_count = switch (ruleType) {
+ case PEER_ID_STARTS_WITH, PEER_ID_CONTAINS, CLIENT_NAME_STARTS_WITH, CLIENT_NAME_CONTAINS ->
+ fileToLines(name, ruleFile, fileLines);
+ default -> fileToIPList(name, tempFile, ipAddresses, subnetAddresses);
+ };
// 更新后重命名临时文件
ruleFile.delete();
tempFile.renameTo(ruleFile);
} else {
// 如果一致,但ipBanMatchers没有对应的规则内容,则加载内容
- if (ruleMatchers.stream().noneMatch(ele -> ele.getRuleId().equals(ruleId))) {
- ent_count = fileToIPList(name, tempFile, ipAddresses, subnetAddresses);
+ if (rules.stream().noneMatch(ele -> ele.metadata().get("id").equals(ruleId))) {
+ ent_count = switch (ruleType) {
+ case PEER_ID_STARTS_WITH, PEER_ID_CONTAINS, CLIENT_NAME_STARTS_WITH,
+ CLIENT_NAME_CONTAINS -> fileToLines(name, ruleFile, fileLines);
+ default -> fileToIPList(name, tempFile, ipAddresses, subnetAddresses);
+ };
} else {
- log.info(Lang.IP_BAN_RULE_NO_UPDATE, name);
- result.set(new SlimMsg(true, Lang.IP_BAN_RULE_NO_UPDATE.replace("{}", name)));
+ log.info(Lang.SUB_RULE_NO_UPDATE, name);
+ result.set(new SlimMsg(true, Lang.SUB_RULE_NO_UPDATE.replace("{}", name)));
}
tempFile.delete();
}
// ip列表或者subnet列表不为空代表需要更新matcher
- if (!ipAddresses.isEmpty() || !subnetAddresses.isEmpty()) {
+ if (!ipAddresses.isEmpty() || !subnetAddresses.isEmpty() || !fileLines.isEmpty()) {
// 如果已经存在则更新,否则添加
- ruleMatchers.stream().filter(ele -> ele.getRuleId().equals(ruleId)).findFirst().ifPresentOrElse(ele -> {
- ele.setData(name, ipAddresses, subnetAddresses);
- log.info(Lang.IP_BAN_RULE_UPDATE_SUCCESS, name);
- result.set(new SlimMsg(true, Lang.IP_BAN_RULE_UPDATE_SUCCESS.replace("{}", name)));
+ rules.stream().filter(ele -> ele.metadata().get("id").equals(ruleId)).findFirst().ifPresentOrElse(ele -> {
+ switch (ruleType) {
+ case PEER_ID_STARTS_WITH, PEER_ID_CONTAINS, CLIENT_NAME_STARTS_WITH,
+ CLIENT_NAME_CONTAINS -> ((RuleMatcher) ele).setData(name, fileLines);
+ default -> ((IPMatcher) ele).setData(name, ipAddresses, subnetAddresses);
+ }
+ log.info(Lang.SUB_RULE_UPDATE_SUCCESS, name);
+ result.set(new SlimMsg(true, Lang.SUB_RULE_UPDATE_SUCCESS.replace("{}", name)));
}, () -> {
- ruleMatchers.add(new IPMatcher(ruleId, name, ipAddresses, subnetAddresses));
- log.info(Lang.IP_BAN_RULE_LOAD_SUCCESS, name);
- result.set(new SlimMsg(true, Lang.IP_BAN_RULE_LOAD_SUCCESS.replace("{}", name)));
+ switch (ruleType) {
+ case PEER_ID_STARTS_WITH, CLIENT_NAME_STARTS_WITH ->
+ rules.add(new PrefixMatcher(ruleType, ruleId, name, fileLines));
+ case PEER_ID_CONTAINS, CLIENT_NAME_CONTAINS ->
+ rules.add(new SubStrMatcher(ruleType, ruleId, name, fileLines));
+ default -> rules.add(new IPMatcher(ruleId, name, ipAddresses, subnetAddresses));
+ }
+ log.info(Lang.SUB_RULE_LOAD_SUCCESS, name);
+ result.set(new SlimMsg(true, Lang.SUB_RULE_LOAD_SUCCESS.replace("{}", name)));
});
}
if (ent_count > 0) {
// 更新日志
try {
db.insertRuleSubLog(ruleId, ent_count, updateType);
- result.set(new SlimMsg(true, Lang.IP_BAN_RULE_UPDATED.replace("{}", name)));
+ result.set(new SlimMsg(true, Lang.SUB_RULE_UPDATED.replace("{}", name)));
} catch (SQLException e) {
- log.error(Lang.IP_BAN_RULE_UPDATE_LOG_ERROR, ruleId, e);
- result.set(new SlimMsg(false, Lang.IP_BAN_RULE_UPDATE_LOG_ERROR.replace("{}", name)));
+ log.error(Lang.SUB_RULE_UPDATE_LOG_ERROR, ruleId, e);
+ result.set(new SlimMsg(false, Lang.SUB_RULE_UPDATE_LOG_ERROR.replace("{}", name)));
}
} else {
- result.set(new SlimMsg(true, Lang.IP_BAN_RULE_NO_UPDATE.replace("{}", name)));
+ result.set(new SlimMsg(true, Lang.SUB_RULE_NO_UPDATE.replace("{}", name)));
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}).join();
} else {
- result.set(new SlimMsg(false, Lang.IP_BAN_RULE_URL_WRONG.replace("{}", name)));
+ result.set(new SlimMsg(false, Lang.SUB_RULE_URL_WRONG.replace("{}", name)));
}
return result.get();
}
+ /**
+ * 读取规则文件并转为字符串列表
+ *
+ * @param ruleName 规则名称
+ * @param ruleFile 规则文件
+ * @param lines 字符串列表
+ * @return 加载的行数
+ */
+ private int fileToLines(String ruleName, File ruleFile, List lines) throws IOException {
+ AtomicInteger count = new AtomicInteger();
+ Files.readLines(ruleFile, StandardCharsets.UTF_8).forEach(ele -> {
+ count.getAndIncrement();
+ log.debug(Lang.SUB_RULE_LOAD_CONTENT, ruleName, ele);
+ lines.add(ele);
+ });
+ return count.get();
+ }
+
/**
* 读取规则文件并转为IpList
* 其中ipv4网段地址转为精确ip
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/RuleSubController.java b/src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/RuleSubController.java
index 20f565d4..5cef0dba 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/RuleSubController.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/RuleSubController.java
@@ -3,7 +3,7 @@
import com.ghostchu.peerbanhelper.PeerBanHelperServer;
import com.ghostchu.peerbanhelper.database.RuleSubInfo;
import com.ghostchu.peerbanhelper.module.AbstractFeatureModule;
-import com.ghostchu.peerbanhelper.module.IPBanRuleUpdateType;
+import com.ghostchu.peerbanhelper.module.RuleUpdateType;
import com.ghostchu.peerbanhelper.module.impl.rule.RuleSubBlocker;
import com.ghostchu.peerbanhelper.module.impl.webapi.common.SlimMsg;
import com.ghostchu.peerbanhelper.module.impl.webapi.common.StdMsg;
@@ -88,7 +88,7 @@ public void onDisable() {
* @param ctx 上下文
*/
private void getCheckInterval(Context ctx) {
- ctx.json(new StdMsg(true, Lang.IP_BAN_RULE_CHECK_INTERVAL_QUERY_SUCCESS, ruleSubBlocker.getCheckInterval()));
+ ctx.json(new StdMsg(true, Lang.SUB_RULE_CHECK_INTERVAL_QUERY_SUCCESS, ruleSubBlocker.getCheckInterval()));
}
/**
@@ -100,10 +100,10 @@ private void changeCheckInterval(Context ctx) {
try {
long interval = JsonUtil.readObject(ctx.body()).get("checkInterval").getAsLong();
ruleSubBlocker.changeCheckInterval(interval);
- ctx.json(new SlimMsg(true, Lang.IP_BAN_RULE_CHECK_INTERVAL_UPDATED));
+ ctx.json(new SlimMsg(true, Lang.SUB_RULE_CHECK_INTERVAL_UPDATED));
} catch (Exception e) {
ctx.status(HttpStatus.BAD_REQUEST);
- ctx.json(new SlimMsg(false, Lang.IP_BAN_RULE_CHECK_INTERVAL_WRONG_PARAM));
+ ctx.json(new SlimMsg(false, Lang.SUB_RULE_CHECK_INTERVAL_WRONG_PARAM));
}
}
@@ -124,11 +124,11 @@ private void logs(Context ctx, String ruleId) {
map.put("pageSize", pageSize);
map.put("results", ruleSubBlocker.queryRuleSubLogs(ruleId, pageIndex, pageSize));
map.put("total", ruleSubBlocker.countRuleSubLogs(ruleId));
- ctx.json(new StdMsg(true, Lang.IP_BAN_RULE_LOG_QUERY_SUCCESS, map));
+ ctx.json(new StdMsg(true, Lang.SUB_RULE_LOG_QUERY_SUCCESS, map));
} catch (Exception e) {
- log.error(Lang.IP_BAN_RULE_LOG_QUERY_ERROR, e);
+ log.error(Lang.SUB_RULE_LOG_QUERY_ERROR, e);
ctx.status(HttpStatus.BAD_REQUEST);
- ctx.json(new SlimMsg(false, Lang.IP_BAN_RULE_LOG_QUERY_WRONG_PARAM));
+ ctx.json(new SlimMsg(false, Lang.SUB_RULE_LOG_QUERY_WRONG_PARAM));
}
}
@@ -139,7 +139,7 @@ private void logs(Context ctx, String ruleId) {
*/
private SlimMsg updateAll() {
AtomicReference result = new AtomicReference<>();
- ruleSubBlocker.getRuleSubsConfig().getKeys(false).stream().map(this::update).filter(ele -> !ele.success()).findFirst().ifPresentOrElse(result::set, () -> result.set(new SlimMsg(true, Lang.IP_BAN_RULE_ALL_UPDATED)));
+ ruleSubBlocker.getRuleSubsConfig().getKeys(false).stream().map(this::update).filter(ele -> !ele.success()).findFirst().ifPresentOrElse(result::set, () -> result.set(new SlimMsg(true, Lang.SUB_RULE_ALL_UPDATED)));
return result.get();
}
@@ -151,13 +151,13 @@ private SlimMsg updateAll() {
*/
private SlimMsg update(String ruleId) {
if (ruleId == null || ruleId.isEmpty()) {
- return new SlimMsg(false, Lang.IP_BAN_RULE_NO_ID);
+ return new SlimMsg(false, Lang.SUB_RULE_NO_ID);
}
ConfigurationSection configurationSection = ruleSubBlocker.getRuleSubsConfig().getConfigurationSection(ruleId);
if (null == configurationSection) {
- return new SlimMsg(false, Lang.IP_BAN_RULE_CANT_FIND.replace("{}", ruleId));
+ return new SlimMsg(false, Lang.SUB_RULE_CANT_FIND.replace("{}", ruleId));
}
- return ruleSubBlocker.updateRule(configurationSection, IPBanRuleUpdateType.MANUAL);
+ return ruleSubBlocker.updateRule(configurationSection, RuleUpdateType.MANUAL);
}
/**
@@ -172,19 +172,19 @@ private void switcher(Context ctx) throws SQLException, IOException {
enabled = JsonUtil.readObject(ctx.body()).get("enabled").getAsBoolean();
} catch (Exception e) {
ctx.status(HttpStatus.BAD_REQUEST);
- ctx.json(new SlimMsg(false, Lang.IP_BAN_RULE_ENABLED_WRONG_PARAM));
+ ctx.json(new SlimMsg(false, Lang.SUB_RULE_ENABLED_WRONG_PARAM));
return;
}
RuleSubInfo ruleSubInfo = ruleSubBlocker.getRuleSubInfo(ruleId);
if (null == ruleSubInfo) {
ctx.status(HttpStatus.BAD_REQUEST);
- ctx.json(new SlimMsg(false, Lang.IP_BAN_RULE_CANT_FIND.replace("{}", ruleId)));
+ ctx.json(new SlimMsg(false, Lang.SUB_RULE_CANT_FIND.replace("{}", ruleId)));
return;
}
- String msg = (enabled ? Lang.IP_BAN_RULE_ENABLED : Lang.IP_BAN_RULE_DISABLED).replace("{}", ruleSubInfo.ruleName());
+ String msg = (enabled ? Lang.SUB_RULE_ENABLED : Lang.SUB_RULE_DISABLED).replace("{}", ruleSubInfo.ruleName());
if (enabled != ruleSubInfo.enabled()) {
ConfigurationSection configurationSection = ruleSubBlocker.saveRuleSubInfo(new RuleSubInfo(ruleId, enabled, ruleSubInfo.ruleName(), ruleSubInfo.subUrl(), 0, 0));
- ruleSubBlocker.updateRule(configurationSection, IPBanRuleUpdateType.MANUAL);
+ ruleSubBlocker.updateRule(configurationSection, RuleUpdateType.MANUAL);
log.info(msg);
ctx.json(new SlimMsg(true, msg));
} else {
@@ -203,12 +203,12 @@ private void delete(Context ctx) throws IOException, SQLException {
RuleSubInfo ruleSubInfo = ruleSubBlocker.getRuleSubInfo(ruleId);
if (null == ruleSubInfo) {
ctx.status(HttpStatus.BAD_REQUEST);
- ctx.json(new SlimMsg(false, Lang.IP_BAN_RULE_CANT_FIND.replace("{}", ruleId)));
+ ctx.json(new SlimMsg(false, Lang.SUB_RULE_CANT_FIND.replace("{}", ruleId)));
return;
}
ruleSubBlocker.deleteRuleSubInfo(ruleId);
- ruleSubBlocker.getRuleMatchers().removeIf(ele -> ele.getRuleId().equals(ruleId));
- String msg = Lang.IP_BAN_RULE_DELETED.replace("{}", ruleSubInfo.ruleName());
+ ruleSubBlocker.getRules().removeIf(ele -> ele.metadata().get("id").equals(ruleId));
+ String msg = Lang.SUB_RULE_DELETED.replace("{}", ruleSubInfo.ruleName());
log.info(msg);
ctx.json(new SlimMsg(true, msg));
}
@@ -227,20 +227,20 @@ private void save(Context ctx, String ruleId, boolean isAdd) throws SQLException
}
if (ruleId == null || ruleId.isEmpty()) {
ctx.status(HttpStatus.BAD_REQUEST);
- ctx.json(new SlimMsg(false, Lang.IP_BAN_RULE_NO_ID));
+ ctx.json(new SlimMsg(false, Lang.SUB_RULE_NO_ID));
return;
}
RuleSubInfo ruleSubInfo = ruleSubBlocker.getRuleSubInfo(ruleId);
if (isAdd && ruleSubInfo != null) {
// 新增时检查规则是否存在
ctx.status(HttpStatus.BAD_REQUEST);
- ctx.json(new SlimMsg(false, Lang.IP_BAN_RULE_ID_CONFLICT.replace("{}", ruleId)));
+ ctx.json(new SlimMsg(false, Lang.SUB_RULE_ID_CONFLICT.replace("{}", ruleId)));
return;
}
if (!isAdd && ruleSubInfo == null) {
// 更新时检查规则是否存在
ctx.status(HttpStatus.BAD_REQUEST);
- ctx.json(new SlimMsg(false, Lang.IP_BAN_RULE_CANT_FIND.replace("{}", ruleId)));
+ ctx.json(new SlimMsg(false, Lang.SUB_RULE_CANT_FIND.replace("{}", ruleId)));
return;
}
String ruleName = subInfo.ruleName();
@@ -248,7 +248,7 @@ private void save(Context ctx, String ruleId, boolean isAdd) throws SQLException
if (isAdd) {
if (ruleName == null || subUrl == null || ruleName.isEmpty() || subUrl.isEmpty()) {
ctx.status(HttpStatus.BAD_REQUEST);
- ctx.json(new SlimMsg(false, Lang.IP_BAN_RULE_PARAM_WRONG));
+ ctx.json(new SlimMsg(false, Lang.SUB_RULE_PARAM_WRONG));
return;
}
} else {
@@ -262,13 +262,13 @@ private void save(Context ctx, String ruleId, boolean isAdd) throws SQLException
ConfigurationSection configurationSection = ruleSubBlocker.saveRuleSubInfo(new RuleSubInfo(ruleId, isAdd || ruleSubInfo.enabled(), ruleName, subUrl, 0, 0));
assert configurationSection != null;
try {
- SlimMsg msg = ruleSubBlocker.updateRule(configurationSection, IPBanRuleUpdateType.MANUAL);
+ SlimMsg msg = ruleSubBlocker.updateRule(configurationSection, RuleUpdateType.MANUAL);
if (!msg.success()) {
ctx.status(HttpStatus.BAD_REQUEST);
ctx.json(msg);
return;
}
- ctx.json(new SlimMsg(true, Lang.IP_BAN_RULE_SAVED));
+ ctx.json(new SlimMsg(true, Lang.SUB_RULE_SAVED));
} catch (Exception e) {
// 更新失败时回滚
if (isAdd) {
@@ -277,7 +277,7 @@ private void save(Context ctx, String ruleId, boolean isAdd) throws SQLException
ruleSubBlocker.saveRuleSubInfo(ruleSubInfo);
}
ctx.status(HttpStatus.BAD_REQUEST);
- ctx.json(new SlimMsg(false, Lang.IP_BAN_RULE_URL_WRONG.replace("{}", ruleName)));
+ ctx.json(new SlimMsg(false, Lang.SUB_RULE_URL_WRONG.replace("{}", ruleName)));
}
}
@@ -288,7 +288,7 @@ private void save(Context ctx, String ruleId, boolean isAdd) throws SQLException
* @return 响应
*/
private StdMsg get(String ruleId) throws SQLException {
- return new StdMsg(true, Lang.IP_BAN_RULE_INFO_QUERY_SUCCESS, ruleSubBlocker.getRuleSubInfo(ruleId));
+ return new StdMsg(true, Lang.SUB_RULE_INFO_QUERY_SUCCESS, ruleSubBlocker.getRuleSubInfo(ruleId));
}
/**
@@ -302,7 +302,7 @@ private StdMsg list() throws SQLException {
for (String s : list) {
data.add(ruleSubBlocker.getRuleSubInfo(s));
}
- return new StdMsg(true, Lang.IP_BAN_RULE_INFO_QUERY_SUCCESS, data);
+ return new StdMsg(true, Lang.SUB_RULE_INFO_QUERY_SUCCESS, data);
}
/**
diff --git a/src/main/java/com/ghostchu/peerbanhelper/text/Lang.java b/src/main/java/com/ghostchu/peerbanhelper/text/Lang.java
index 5fad4b5f..3c553872 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/text/Lang.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/text/Lang.java
@@ -21,7 +21,7 @@ public class Lang {
public static final String ERR_INVALID_RULE_SYNTAX = "规则 {} 的表达式无效,请检查是否存在拼写错误";
public static final String MODULE_CNB_MATCH_CLIENT_NAME = "匹配 ClientName (UserAgent): %s";
public static final String MODULE_IBL_MATCH_IP = "匹配 IP 规则: %s";
- public static final String MODULE_IBL_MATCH_IP_RULE = "匹配 IP黑名单订阅 规则: %s";
+ public static final String MODULE_IBL_MATCH_SUB_RULE = "匹配 订阅规则: %s";
public static final String MODULE_IBL_MATCH_ASN = "匹配 ASN 规则: %s";
public static final String MODULE_IBL_MATCH_REGION = "匹配国家或地区 ISO 代码规则: %s";
public static final String MODULE_IBL_EXCEPTION_GEOIP = "匹配 GeoIP 信息时出现异常,请反馈错误给开发者";
@@ -169,36 +169,37 @@ public class Lang {
public static final String IP_BAN_RULE_MATCH_TIME = "匹配IP黑名单订阅规则花费时间:{}";
public static final String IP_BAN_RULE_UPDATE_TYPE_AUTO = "自动更新";
public static final String IP_BAN_RULE_UPDATE_TYPE_MANUAL = "手动更新";
- public static final String IP_BAN_RULE_UPDATE_FINISH = "IP黑名单规则订阅完毕";
- public static final String IP_BAN_RULE_NO_UPDATE = "IP黑名单订阅规则 {} 未发生更新";
- public static final String IP_BAN_RULE_UPDATE_SUCCESS = "IP黑名单订阅规则 {} 更新成功";
- public static final String IP_BAN_RULE_UPDATE_FAILED = "IP黑名单订阅规则 {} 更新失败";
- public static final String IP_BAN_RULE_LOAD_SUCCESS = "IP黑名单订阅规则 {} 加载成功";
- public static final String IP_BAN_RULE_UPDATE_LOG_ERROR = "[错误] IP黑名单订阅规则 {} 更新日志失败";
- public static final String IP_BAN_RULE_USE_CACHE = "[警告] IP黑名单订阅规则 {} 订阅失败,使用本地缓存加载成功";
- public static final String IP_BAN_RULE_LOAD_FAILED = "[错误] IP黑名单订阅规则 {} 加载失败";
+ public static final String SUB_RULE_UPDATE_FINISH = "规则订阅完毕";
+ public static final String SUB_RULE_NO_UPDATE = "订阅规则 {} 未发生更新";
+ public static final String SUB_RULE_UPDATE_SUCCESS = "订阅规则 {} 更新成功";
+ public static final String SUB_RULE_UPDATE_FAILED = "订阅规则 {} 更新失败";
+ public static final String SUB_RULE_LOAD_SUCCESS = "订阅规则 {} 加载成功";
+ public static final String SUB_RULE_UPDATE_LOG_ERROR = "[错误] 订阅规则 {} 更新日志失败";
+ public static final String SUB_RULE_USE_CACHE = "[警告] 订阅规则 {} 订阅失败,使用本地缓存加载成功";
+ public static final String SUB_RULE_LOAD_FAILED = "[错误] 订阅规则 {} 加载失败";
public static final String IP_BAN_RULE_LOAD_CIDR = "IP黑名单订阅规则 {} 加载CIDR : {}";
public static final String IP_BAN_RULE_LOAD_IP = "IP黑名单订阅规则 {} 加载精确IP : {}";
+ public static final String SUB_RULE_LOAD_CONTENT = "订阅规则 {} 加载内容 : {}";
public static final String RULE_SUB_API_INTERNAL_ERROR = "[错误] 订阅规则API遇到非预期错误";
- public static final String IP_BAN_RULE_NO_ID = "[错误] IP黑名单订阅规则ID为空";
- public static final String IP_BAN_RULE_ID_CONFLICT = "[错误] IP黑名单订阅规则ID冲突: {}";
- public static final String IP_BAN_RULE_CANT_FIND = "[错误] 未找到IP黑名单订阅规则: {}";
- public static final String IP_BAN_RULE_PARAM_WRONG = "[错误] IP黑名单订阅规则参数错误";
- public static final String IP_BAN_RULE_URL_WRONG = "[错误] IP黑名单订阅规则 {} URL错误";
- public static final String IP_BAN_RULE_ENABLED = "IP黑名单订阅规则 {} 已启用";
- public static final String IP_BAN_RULE_DISABLED = "IP黑名单订阅规则 {} 已禁用";
- public static final String IP_BAN_RULE_UPDATED = "IP黑名单订阅规则 {} 已更新";
- public static final String IP_BAN_RULE_ALL_UPDATED = "IP黑名单订阅规则已全部更新";
- public static final String IP_BAN_RULE_SAVED = "IP黑名单订阅规则已保存";
- public static final String IP_BAN_RULE_DELETED = "IP黑名单订阅规则 {} 已删除";
- public static final String IP_BAN_RULE_INFO_QUERY_SUCCESS = "IP黑名单订阅规则查询成功";
- public static final String IP_BAN_RULE_LOG_QUERY_SUCCESS = "IP黑名单订阅规则更新日志查询成功";
- public static final String IP_BAN_RULE_LOG_QUERY_ERROR = "IP黑名单订阅规则更新日志查询出错";
- public static final String IP_BAN_RULE_LOG_QUERY_WRONG_PARAM = "IP黑名单订阅规则更新日志查询参数错误";
- public static final String IP_BAN_RULE_CHECK_INTERVAL_QUERY_SUCCESS = "IP黑名单订阅规则更新间隔查询成功";
- public static final String IP_BAN_RULE_CHECK_INTERVAL_WRONG_PARAM = "IP黑名单订阅规则更新间隔参数错误";
- public static final String IP_BAN_RULE_CHECK_INTERVAL_UPDATED = "IP黑名单订阅规则更新间隔设置成功";
- public static final String IP_BAN_RULE_ENABLED_WRONG_PARAM = "IP黑名单订阅规则启用禁用参数错误";
+ public static final String SUB_RULE_NO_ID = "[错误] 订阅规则ID为空";
+ public static final String SUB_RULE_ID_CONFLICT = "[错误] 订阅规则ID冲突: {}";
+ public static final String SUB_RULE_CANT_FIND = "[错误] 未找到订阅规则: {}";
+ public static final String SUB_RULE_PARAM_WRONG = "[错误] 订阅规则参数错误";
+ public static final String SUB_RULE_URL_WRONG = "[错误] 订阅规则 {} URL错误";
+ public static final String SUB_RULE_ENABLED = "订阅规则 {} 已启用";
+ public static final String SUB_RULE_DISABLED = "订阅规则 {} 已禁用";
+ public static final String SUB_RULE_UPDATED = "订阅规则 {} 已更新";
+ public static final String SUB_RULE_ALL_UPDATED = "订阅规则已全部更新";
+ public static final String SUB_RULE_SAVED = "订阅规则已保存";
+ public static final String SUB_RULE_DELETED = "订阅规则 {} 已删除";
+ public static final String SUB_RULE_INFO_QUERY_SUCCESS = "订阅规则查询成功";
+ public static final String SUB_RULE_LOG_QUERY_SUCCESS = "订阅规则更新日志查询成功";
+ public static final String SUB_RULE_LOG_QUERY_ERROR = "订阅规则更新日志查询出错";
+ public static final String SUB_RULE_LOG_QUERY_WRONG_PARAM = "IP黑名单订阅规则更新日志查询参数错误";
+ public static final String SUB_RULE_CHECK_INTERVAL_QUERY_SUCCESS = "订阅规则更新间隔查询成功";
+ public static final String SUB_RULE_CHECK_INTERVAL_WRONG_PARAM = "订阅规则更新间隔参数错误";
+ public static final String SUB_RULE_CHECK_INTERVAL_UPDATED = "订阅规则更新间隔设置成功";
+ public static final String SUB_RULE_ENABLED_WRONG_PARAM = "IP黑名单订阅规则启用禁用参数错误";
public static final String WEBAPI_AUTH_INVALID_TOKEN = "登录失败,Token 无效";
public static final String WEBAPI_AUTH_OK = "登录成功";
public static final String WEBAPI_AUTH_BANNED_TOO_FREQ = "登录错误次数过多,此 IP 地址已被暂时封禁";
diff --git a/src/main/java/com/ghostchu/peerbanhelper/util/rule/RuleMatcher.java b/src/main/java/com/ghostchu/peerbanhelper/util/rule/RuleMatcher.java
index 7a8819cf..951a60f1 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/util/rule/RuleMatcher.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/util/rule/RuleMatcher.java
@@ -1,14 +1,14 @@
package com.ghostchu.peerbanhelper.util.rule;
import lombok.EqualsAndHashCode;
-import lombok.Getter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
+import java.util.Map;
+
/**
* 规则Matcher
*/
-@Getter
@Slf4j
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@@ -16,11 +16,11 @@ public abstract class RuleMatcher extends AbstractMatcher {
private final String ruleId;
- private final SubRuleType ruleType;
+ private final RuleType ruleType;
protected String ruleName;
- public RuleMatcher(SubRuleType ruleType, String ruleId, String ruleName, Object... ruleData) {
+ public RuleMatcher(RuleType ruleType, String ruleId, String ruleName, Object... ruleData) {
this.ruleType = ruleType;
this.ruleId = ruleId;
setData(ruleName, ruleData);
@@ -28,4 +28,8 @@ public RuleMatcher(SubRuleType ruleType, String ruleId, String ruleName, Object.
public abstract void setData(String ruleName, Object... ruleData);
+ public Map metadata() {
+ return Map.of("id", ruleId, "name", ruleName, "type", ruleType);
+ }
+
}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/util/rule/RuleType.java b/src/main/java/com/ghostchu/peerbanhelper/util/rule/RuleType.java
new file mode 100644
index 00000000..8eef6eb3
--- /dev/null
+++ b/src/main/java/com/ghostchu/peerbanhelper/util/rule/RuleType.java
@@ -0,0 +1,27 @@
+package com.ghostchu.peerbanhelper.util.rule;
+
+/**
+ * 订阅规则类型
+ */
+public enum RuleType {
+ /**
+ * IP/CIDR
+ */
+ IP,
+ /**
+ * peer-id子串
+ */
+ PEER_ID_CONTAINS,
+ /**
+ * peer-id前缀
+ */
+ PEER_ID_STARTS_WITH,
+ /**
+ * client-name子串
+ */
+ CLIENT_NAME_CONTAINS,
+ /**
+ * client-name前缀
+ */
+ CLIENT_NAME_STARTS_WITH
+}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/util/rule/SubRuleType.java b/src/main/java/com/ghostchu/peerbanhelper/util/rule/SubRuleType.java
deleted file mode 100644
index f0af99af..00000000
--- a/src/main/java/com/ghostchu/peerbanhelper/util/rule/SubRuleType.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.ghostchu.peerbanhelper.util.rule;
-
-/**
- * 订阅规则类型
- */
-public enum SubRuleType {
- /**
- * IP/CIDR
- */
- IP,
- /**
- * 子串
- */
- SUBSTR,
- /**
- * 前缀
- */
- PREFIX
-}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/IPMatcher.java b/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/IPMatcher.java
index c6f9c4ea..f85e733b 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/IPMatcher.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/IPMatcher.java
@@ -4,7 +4,7 @@
import com.ghostchu.peerbanhelper.util.IPAddressUtil;
import com.ghostchu.peerbanhelper.util.rule.MatchResult;
import com.ghostchu.peerbanhelper.util.rule.RuleMatcher;
-import com.ghostchu.peerbanhelper.util.rule.SubRuleType;
+import com.ghostchu.peerbanhelper.util.rule.RuleType;
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import inet.ipaddr.IPAddress;
@@ -15,7 +15,6 @@
import java.nio.charset.StandardCharsets;
import java.util.List;
-import java.util.Map;
@Slf4j
@EqualsAndHashCode(callSuper = true)
@@ -27,7 +26,7 @@ public class IPMatcher extends RuleMatcher {
private BloomFilter bloomFilter;
public IPMatcher(String ruleId, String ruleName, Object... ruleData) {
- super(SubRuleType.IP, ruleId, ruleName, ruleData);
+ super(RuleType.IP, ruleId, ruleName, ruleData);
}
@Override
@@ -60,11 +59,6 @@ public void setData(String ruleName, Object... ruleData) {
return MatchResult.DEFAULT;
}
- @Override
- public Map metadata() {
- return Map.of("rule", ruleName);
- }
-
@Override
public @NotNull String matcherName() {
return Lang.RULE_MATCHER_SUB_RULE;
@@ -72,6 +66,6 @@ public Map metadata() {
@Override
public String matcherIdentifier() {
- return "peerbanhelper:ipbanmatcher";
+ return "peerbanhelper:ipmatcher";
}
}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/PrefixMatcher.java b/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/PrefixMatcher.java
new file mode 100644
index 00000000..56c94669
--- /dev/null
+++ b/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/PrefixMatcher.java
@@ -0,0 +1,48 @@
+package com.ghostchu.peerbanhelper.util.rule.matcher;
+
+import com.ghostchu.peerbanhelper.text.Lang;
+import com.ghostchu.peerbanhelper.util.rule.MatchResult;
+import com.ghostchu.peerbanhelper.util.rule.RuleMatcher;
+import com.ghostchu.peerbanhelper.util.rule.RuleType;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import lombok.extern.slf4j.Slf4j;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+@Slf4j
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class PrefixMatcher extends RuleMatcher {
+
+ private List prefixes;
+
+ public PrefixMatcher(RuleType ruleType, String ruleId, String ruleName, Object... ruleData) {
+ super(ruleType, ruleId, ruleName, ruleData);
+ }
+
+ @Override
+ public void setData(String ruleName, Object... ruleData) {
+ this.ruleName = ruleName;
+ this.prefixes = ruleData.length > 0 ? (List) ruleData[0] : List.of();
+ }
+
+ @Override
+ public @NotNull MatchResult match0(@NotNull String content) {
+ if (prefixes.parallelStream().anyMatch(content::startsWith)) {
+ return MatchResult.TRUE;
+ }
+ return MatchResult.DEFAULT;
+ }
+
+ @Override
+ public @NotNull String matcherName() {
+ return Lang.RULE_MATCHER_SUB_RULE;
+ }
+
+ @Override
+ public String matcherIdentifier() {
+ return "peerbanhelper:prefixmatcher";
+ }
+}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/SubStrMatcher.java b/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/SubStrMatcher.java
new file mode 100644
index 00000000..f6c84513
--- /dev/null
+++ b/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/SubStrMatcher.java
@@ -0,0 +1,48 @@
+package com.ghostchu.peerbanhelper.util.rule.matcher;
+
+import com.ghostchu.peerbanhelper.text.Lang;
+import com.ghostchu.peerbanhelper.util.rule.MatchResult;
+import com.ghostchu.peerbanhelper.util.rule.RuleMatcher;
+import com.ghostchu.peerbanhelper.util.rule.RuleType;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import lombok.extern.slf4j.Slf4j;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+@Slf4j
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class SubStrMatcher extends RuleMatcher {
+
+ private List subStrs;
+
+ public SubStrMatcher(RuleType ruleType, String ruleId, String ruleName, Object... ruleData) {
+ super(ruleType, ruleId, ruleName, ruleData);
+ }
+
+ @Override
+ public void setData(String ruleName, Object... ruleData) {
+ this.ruleName = ruleName;
+ this.subStrs = ruleData.length > 0 ? (List) ruleData[0] : List.of();
+ }
+
+ @Override
+ public @NotNull MatchResult match0(@NotNull String content) {
+ if (subStrs.parallelStream().anyMatch(content::contains)) {
+ return MatchResult.TRUE;
+ }
+ return MatchResult.DEFAULT;
+ }
+
+ @Override
+ public @NotNull String matcherName() {
+ return Lang.RULE_MATCHER_SUB_RULE;
+ }
+
+ @Override
+ public String matcherIdentifier() {
+ return "peerbanhelper:substrmatcher";
+ }
+}
diff --git a/src/main/resources/profile.yml b/src/main/resources/profile.yml
index 5d2614fa..9bbb8b5b 100644
--- a/src/main/resources/profile.yml
+++ b/src/main/resources/profile.yml
@@ -174,6 +174,8 @@ module:
dh_torrents:
# 是否启用
enabled: false
+ # 匹配类型 IP PEER_ID_CONTAINS PEER_ID_STARTS_WITH CLIENT_NAME_CONTAINS CLIENT_NAME_STARTS_WITH
+ type: IP
# 显示名称
name: dh_torrents
# 规则文件订阅地址
From f05b6bdf09a7a9710e18a82d6084ddd55ded194c Mon Sep 17 00:00:00 2001
From: PluieM <644202913@qq.com>
Date: Wed, 19 Jun 2024 22:08:56 +0800
Subject: [PATCH 3/5] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=BB=9F=E8=AE=A1?=
=?UTF-8?q?=E9=A1=B5=E9=9D=A2=E9=83=A8=E5=88=86=E5=85=83=E7=B4=A0=E6=9C=AA?=
=?UTF-8?q?=E6=98=BE=E7=A4=BA=E7=9A=84=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ghostchu/peerbanhelper/module/impl/rule/RuleSubBlocker.java | 2 +-
.../java/com/ghostchu/peerbanhelper/util/rule/RuleMatcher.java | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/RuleSubBlocker.java b/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/RuleSubBlocker.java
index a815016f..fd2323c2 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/RuleSubBlocker.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/RuleSubBlocker.java
@@ -128,7 +128,7 @@ public CheckResult shouldBanPeer(PeerMatchRecord ctx) {
matchStr = ctx.getPeer().getAddress().getIp();
}
if (matcher.match(matchStr) == MatchResult.TRUE) {
- result.set(new CheckResult(true, matcher.metadata().get("name").toString(), String.format(Lang.MODULE_IBL_MATCH_SUB_RULE, matcher.metadata().get("name").toString())));
+ result.set(new CheckResult(true, matcher.metadata().get("rule").toString(), String.format(Lang.MODULE_IBL_MATCH_SUB_RULE, matcher.metadata().get("rule").toString())));
}
latch.countDown();
}));
diff --git a/src/main/java/com/ghostchu/peerbanhelper/util/rule/RuleMatcher.java b/src/main/java/com/ghostchu/peerbanhelper/util/rule/RuleMatcher.java
index 951a60f1..98f34a68 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/util/rule/RuleMatcher.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/util/rule/RuleMatcher.java
@@ -29,7 +29,7 @@ public RuleMatcher(RuleType ruleType, String ruleId, String ruleName, Object...
public abstract void setData(String ruleName, Object... ruleData);
public Map metadata() {
- return Map.of("id", ruleId, "name", ruleName, "type", ruleType);
+ return Map.of("id", ruleId, "rule", ruleName, "type", ruleType);
}
}
From ef101b3b6d6da29f6c97d46b840fa2e04c33a38c Mon Sep 17 00:00:00 2001
From: PluieM <644202913@qq.com>
Date: Thu, 20 Jun 2024 16:41:06 +0800
Subject: [PATCH 4/5] =?UTF-8?q?1=E3=80=81=E4=BD=BF=E7=94=A8=E6=B3=9B?=
=?UTF-8?q?=E5=9E=8B=E9=87=8D=E6=9E=84RuleMatcher=202=E3=80=81=E7=B2=BE?=
=?UTF-8?q?=E7=AE=80RuleBlocker=E7=9A=84=E8=B0=83=E7=94=A8=E9=80=BB?=
=?UTF-8?q?=E8=BE=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../peerbanhelper/PeerBanHelperServer.java | 76 ++++++-------
.../module/AbstractRuleBlocker.java | 8 +-
.../peerbanhelper/module/MatchEvents.java | 4 -
.../module/MatchResultDetail.java | 15 ++-
.../module/PeerMatchContext.java | 18 +++
.../peerbanhelper/module/PeerState.java | 4 -
.../peerbanhelper/module/RuleBlocker.java | 106 ++++++++++++------
.../module/impl/rule/RuleSubBlocker.java | 62 +++-------
.../module/impl/webapi/RuleSubController.java | 16 +--
.../com/ghostchu/peerbanhelper/text/Lang.java | 18 +--
.../peerbanhelper/util/rule/RuleMatcher.java | 7 +-
.../util/rule/matcher/IPMatcher.java | 26 ++++-
.../util/rule/matcher/PrefixMatcher.java | 12 +-
.../util/rule/matcher/SubStrMatcher.java | 14 ++-
.../peerbanhelper/util/time/ExceptedTime.java | 4 +-
15 files changed, 218 insertions(+), 172 deletions(-)
create mode 100644 src/main/java/com/ghostchu/peerbanhelper/module/PeerMatchContext.java
diff --git a/src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java b/src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java
index 2e7087e8..411ec7d5 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java
@@ -105,7 +105,7 @@ public class PeerBanHelperServer {
@Getter
private JavalinWebContainer webContainer;
@Getter
- private final Map matchRecords = new ConcurrentHashMap<>();
+ private final Map matchRecords = new ConcurrentHashMap<>();
public PeerBanHelperServer(String pbhServerAddress, YamlConfiguration profile, YamlConfiguration mainConfig) throws SQLException {
this.pbhServerAddress = pbhServerAddress;
@@ -392,41 +392,25 @@ public void banWave() {
executor.submit(() -> updateLivePeers(peers));
// ===============基于 状态机 的封禁逻辑
banWaveWatchDog.setLastOperation("Check Bans New");
- // long t1 = System.currentTimeMillis();
- // 断开连接超时剔除
- matchRecords.values().stream().filter(ele -> ele.getResult().state() == PeerState.ACTIVE && ele.getResult().expireTime() < System.currentTimeMillis())
- .map(ele -> ele.getPeer().getAddress()).forEach(matchRecords::remove);
- // 封禁超时解禁后剔除
- matchRecords.values().stream().filter(ele -> ele.getResult().state() == PeerState.BAN && ele.getResult().expireTime() < System.currentTimeMillis())
- .map(ele -> ele.getPeer().getAddress()).forEach(ele -> {
- unbanPeer(ele);
- matchRecords.remove(ele);
- });
- // 按模块并行检查标记Peer
+ // 按模块并行检查Peer
List ruleBlockers = moduleManager.getModules().stream().filter(ele -> ele instanceof RuleBlocker).toList();
- CountDownLatch fsmLatch = new CountDownLatch(ruleBlockers.size());
- ruleBlockers.forEach(ele -> {
- RuleBlocker blocker = (RuleBlocker) ele;
- try (TimeoutProtect protect = new TimeoutProtect(ExceptedTime.CHECK_BANS.getTimeout(), (t) -> {
- log.warn(Lang.TIMING_CHECK_BANS);
- fsmLatch.countDown();
- })) {
+ try (TimeoutProtect protect = new TimeoutProtect(ExceptedTime.RUN_BLOCKER.getTimeout(), (t) -> {
+ log.warn(Lang.TIMING_CHECK_BANS);
+ })) {
+ ruleBlockers.forEach(ele -> {
+ RuleBlocker blocker = (RuleBlocker) ele;
protect.getService().submit(() -> {
- blocker.runCheck();
- fsmLatch.countDown();
+ try (TimeoutProtect banProtect = new TimeoutProtect(ExceptedTime.BAN_PEER.getTimeout(), (t) -> log.warn(Lang.TIMING_ADD_BANS))) {
+ blocker.runCheck(
+ null, (record) ->
+ banProtect.getService().submit(() ->
+ banPeer(record.getDownloader(), record.getTorrent(), record.getPeer(), record.getResult().getModuleContext().getClass().getName(), record.getResult().getRule(), record.getResult().getReason(), bannedPeers, needRelaunched)
+ ), null, null
+ );
+ }
});
- }
- });
- fsmLatch.await();
- // 标记完成后将结果为Ban的Peer封禁
- banWaveWatchDog.setLastOperation("Add banned peers into banlist New");
- matchRecords.values().stream().filter(ele -> ele.getResult().state() == PeerState.BAN && !BAN_LIST.containsKey(ele.getPeer().getAddress()))
- .forEach(record -> Optional.ofNullable(needRelaunched.get(record.getDownloader())).ifPresentOrElse(torrents ->
- banPeer(record.getDownloader(), record.getTorrent(), record.getPeer(), record.getResult().moduleContext().getClass().getName(), record.getResult().rule(), record.getResult().reason(), bannedPeers, torrents), () -> {
- List torrents = new ArrayList<>();
- banPeer(record.getDownloader(), record.getTorrent(), record.getPeer(), record.getResult().moduleContext().getClass().getName(), record.getResult().rule(), record.getResult().reason(), bannedPeers, torrents);
- needRelaunched.put(record.getDownloader(), torrents);
- }));
+ });
+ }
// ========== 处理封禁逻辑 ==========
Map> downloaderBanDetailMap = new ConcurrentHashMap<>();
banWaveWatchDog.setLastOperation("Check Bans");
@@ -443,16 +427,15 @@ public void banWave() {
downloaderBanDetailMap.forEach((downloader, details) -> Optional.ofNullable(needRelaunched.get(downloader)).ifPresentOrElse(torrents ->
details.forEach(detail -> protect.getService().submit(() -> {
if (detail.result().action() == PeerAction.BAN) {
- banPeer(downloader, detail.torrent(), detail.peer(), detail.result().moduleContext().getClass().getName(), detail.result().rule(), detail.result().reason(), bannedPeers, torrents);
+ banPeer(downloader, detail.torrent(), detail.peer(), detail.result().moduleContext().getClass().getName(), detail.result().rule(), detail.result().reason(), bannedPeers, needRelaunched);
}
})), () -> {
- List torrents = new ArrayList<>();
details.forEach(detail -> protect.getService().submit(() -> {
if (detail.result().action() == PeerAction.BAN) {
- banPeer(downloader, detail.torrent(), detail.peer(), detail.result().moduleContext().getClass().getName(), detail.result().rule(), detail.result().reason(), bannedPeers, torrents);
+ banPeer(downloader, detail.torrent(), detail.peer(), detail.result().moduleContext().getClass().getName(), detail.result().rule(), detail.result().reason(), bannedPeers, needRelaunched);
}
}));
- needRelaunched.put(downloader, torrents);
+ //needRelaunched.put(downloader, torrents);
}));
}
banWaveWatchDog.setLastOperation("Apply banlist");
@@ -471,8 +454,6 @@ public void banWave() {
log.info(Lang.BAN_WAVE_CHECK_COMPLETED, downloadersCount, torrentsCount, peersCount, bannedPeers.size(), unbannedPeers.size(), System.currentTimeMillis() - startTimer);
}
banWaveWatchDog.setLastOperation("Completed");
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
} finally {
banWaveWatchDog.feed();
metrics.recordCheck();
@@ -513,13 +494,14 @@ private void updateLivePeers(Map>> peers) {
);
livePeers.put(address, metadata);
// 更新匹配记录
- if (matchRecords.containsKey(address)) {
- PeerMatchRecord peerMatchRecord = matchRecords.get(address);
+ String recordKey = downloader.getName() + "@" + torrent.getHash() + "@" + address.getIp();
+ if (matchRecords.containsKey(recordKey)) {
+ PeerMatchRecord peerMatchRecord = matchRecords.get(recordKey);
peerMatchRecord.setDownloader(downloader);
peerMatchRecord.setTorrent(torrent);
peerMatchRecord.setPeer(p);
} else {
- matchRecords.put(address, new PeerMatchRecord(downloader, torrent, p, new MatchResultDetail(null, PeerState.INIT, "N/A", "no matches", 0)));
+ matchRecords.put(recordKey, new PeerMatchRecord(downloader, torrent, p, new MatchResultDetail(null, PeerState.INIT, "N/A", "no matches", System.currentTimeMillis() + disconnectTimeout)));
}
});
})));
@@ -724,11 +706,17 @@ public Map getBannedPeers() {
*
* @param peer 对等体 IP 地址
*/
- public void banPeer(@NotNull Downloader downloader, @NotNull Torrent torrent, @NotNull Peer peer, @NotNull String module, @NotNull String ruleName, @NotNull String reason, @NotNull Collection bannedPeers, @NotNull List relaunch) {
+ public synchronized void banPeer(@NotNull Downloader downloader, @NotNull Torrent torrent, @NotNull Peer peer, @NotNull String module, @NotNull String ruleName, @NotNull String reason, @NotNull Collection bannedPeers, @NotNull Map> needRelaunched) {
if (BAN_LIST.containsKey(peer.getAddress())) {
return;
}
- relaunch.add(torrent);
+ Optional.ofNullable(needRelaunched.get(downloader)).ifPresentOrElse(torrents -> {
+ if (torrents.contains(torrent)) {
+ torrents.add(torrent);
+ } else {
+ needRelaunched.put(downloader, List.of(torrent));
+ }
+ }, () -> needRelaunched.put(downloader, List.of(torrent)));
IPDBResponse ipdbResponse = queryIPDB(peer.getAddress());
BanMetadata banMetadata = new BanMetadata(module, downloader.getName(),
System.currentTimeMillis(), System.currentTimeMillis() + banDuration,
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/AbstractRuleBlocker.java b/src/main/java/com/ghostchu/peerbanhelper/module/AbstractRuleBlocker.java
index a342e945..c96dbca7 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/module/AbstractRuleBlocker.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/AbstractRuleBlocker.java
@@ -2,7 +2,7 @@
import com.alibaba.cola.statemachine.StateMachine;
import com.ghostchu.peerbanhelper.PeerBanHelperServer;
-import com.ghostchu.peerbanhelper.util.rule.Rule;
+import com.ghostchu.peerbanhelper.util.rule.RuleMatcher;
import lombok.Getter;
import org.bspfsystems.yamlconfiguration.file.YamlConfiguration;
@@ -11,9 +11,9 @@
public abstract class AbstractRuleBlocker extends AbstractFeatureModule implements RuleBlocker {
@Getter
- public List rules;
+ public List rules;
- public StateMachine stateMachine;
+ public StateMachine stateMachine;
public AbstractRuleBlocker(PeerBanHelperServer server, YamlConfiguration profile) {
super(server, profile);
@@ -35,7 +35,7 @@ public void onDisable() {
}
@Override
- public StateMachine getStateMachine() {
+ public StateMachine getStateMachine() {
return stateMachine;
}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/MatchEvents.java b/src/main/java/com/ghostchu/peerbanhelper/module/MatchEvents.java
index 557364df..34862357 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/module/MatchEvents.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/MatchEvents.java
@@ -4,10 +4,6 @@
*
*/
public enum MatchEvents {
- /**
- * 匹配规则
- */
- MATCH,
/**
* 命中规则
*/
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/MatchResultDetail.java b/src/main/java/com/ghostchu/peerbanhelper/module/MatchResultDetail.java
index a0c3e7b8..924655c1 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/module/MatchResultDetail.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/MatchResultDetail.java
@@ -1,5 +1,16 @@
package com.ghostchu.peerbanhelper.module;
-public record MatchResultDetail(FeatureModule moduleContext, PeerState state, String rule, String reason,
- long expireTime) {
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class MatchResultDetail {
+ private FeatureModule moduleContext;
+ private PeerState state;
+ private String rule;
+ private String reason;
+ private long expireTime;
}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/PeerMatchContext.java b/src/main/java/com/ghostchu/peerbanhelper/module/PeerMatchContext.java
new file mode 100644
index 00000000..849ebb83
--- /dev/null
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/PeerMatchContext.java
@@ -0,0 +1,18 @@
+package com.ghostchu.peerbanhelper.module;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.function.Consumer;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class PeerMatchContext {
+ private PeerMatchRecord record;
+ private Consumer activeFunc;
+ private Consumer banFunc;
+ private Consumer disconnectFunc;
+ private Consumer timeoutFunc;
+}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/PeerState.java b/src/main/java/com/ghostchu/peerbanhelper/module/PeerState.java
index fbcc0c73..bf93b873 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/module/PeerState.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/PeerState.java
@@ -8,10 +8,6 @@ public enum PeerState {
* 初始化
*/
INIT,
- /**
- * 匹配
- */
- MATCH,
/**
* 封禁
*/
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/RuleBlocker.java b/src/main/java/com/ghostchu/peerbanhelper/module/RuleBlocker.java
index afc06789..3747c44c 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/module/RuleBlocker.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/RuleBlocker.java
@@ -7,7 +7,11 @@
import com.ghostchu.peerbanhelper.text.Lang;
import org.slf4j.Logger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
import java.util.Optional;
+import java.util.function.Consumer;
/**
* 基于状态机模型的规则模块接口
@@ -19,43 +23,44 @@ public interface RuleBlocker extends FeatureModule {
*
* @return 状态机构造器
*/
- default StateMachineBuilder ruleSmBuilder() {
- StateMachineBuilder fsmBuilder = StateMachineBuilderFactory.create();
- fsmBuilder.externalTransitions().fromAmong(PeerState.INIT, PeerState.ACTIVE).to(PeerState.MATCH).on(MatchEvents.MATCH)
- .perform((from, to, event, context) -> {
- // 匹配
- CheckResult result = shouldBanPeer(context);
- if (result.hit()) {
- context.setResult(new MatchResultDetail(this, to, result.rule(), result.reason(), System.currentTimeMillis() + getServer().getDisconnectTimeout()));
- triggerEvent(MatchEvents.HIT, context);
- } else {
- context.setResult(new MatchResultDetail(this, to, "N/A", "No matches", System.currentTimeMillis() + getServer().getDisconnectTimeout()));
- triggerEvent(MatchEvents.PASS, context);
- }
- });
- fsmBuilder.externalTransition().from(PeerState.MATCH).to(PeerState.ACTIVE).on(MatchEvents.PASS)
+ default StateMachineBuilder ruleSmBuilder() {
+ StateMachineBuilder fsmBuilder = StateMachineBuilderFactory.create();
+ fsmBuilder.externalTransitions().fromAmong(PeerState.INIT, PeerState.ACTIVE).to(PeerState.ACTIVE).on(MatchEvents.PASS)
.perform((from, to, event, context) -> {
// 活跃
- context.setResult(new MatchResultDetail(this, to, "N/A", "No matches", System.currentTimeMillis() + getServer().getDisconnectTimeout()));
+ Optional.ofNullable(context.getActiveFunc()).ifPresent(func -> func.accept(context.getRecord()));
+ // 更新过期时间
+ context.getRecord().getResult().setState(to);
+ context.getRecord().getResult().setExpireTime(System.currentTimeMillis() + getServer().getDisconnectTimeout());
});
- fsmBuilder.externalTransition().from(PeerState.MATCH).to(PeerState.BAN).on(MatchEvents.HIT)
+ fsmBuilder.externalTransitions().fromAmong(PeerState.INIT, PeerState.ACTIVE).to(PeerState.BAN).on(MatchEvents.HIT)
.perform((from, to, event, context) -> {
// 封禁
- getLogger().debug(Lang.RULE_MODULE_PEER_BAN, getName(), context.getPeer().getAddress());
- context.setResult(new MatchResultDetail(this, to, context.getResult().rule(), context.getResult().reason(), System.currentTimeMillis() + getServer().getBanDuration()));
+ getLogger().debug(Lang.RULE_MODULE_PEER_HIT, getName(), context.getRecord().getPeer().getAddress());
+ // 执行封禁操作
+ Optional.ofNullable(context.getBanFunc()).ifPresent(func -> func.accept(context.getRecord()));
+ // 更新匹配结果
+ context.getRecord().getResult().setModuleContext(this);
+ context.getRecord().getResult().setState(to);
+ context.getRecord().getResult().setExpireTime(System.currentTimeMillis() + getServer().getBanDuration());
});
- /*fsmBuilder.externalTransition().from(PeerState.ACTIVE).to(PeerState.END).on(PeerEvents.DISCONNECT)
+ fsmBuilder.externalTransitions().fromAmong(PeerState.INIT, PeerState.ACTIVE).to(PeerState.END).on(MatchEvents.DISCONNECT)
.perform((from, to, event, context) -> {
// 断开连接
- getLogger().info(Lang.RULE_MODULE_PEER_DISCONNECT, context.getPeer().getPeerId(), context.getPeer().getAddress().getIp(), context.getPeer().getAddress().getPort());
- context.setResult(new MatchResultDetail(this, to, null, null, 0));
+ getLogger().debug(Lang.RULE_MODULE_PEER_DISCONNECT, getName(), context.getRecord().getPeer().getAddress());
+ // 执行断开操作
+ Optional.ofNullable(context.getDisconnectFunc()).ifPresent(func -> func.accept(context.getRecord()));
+ // 更新匹配结果
+ context.getRecord().setResult(new MatchResultDetail(this, to, null, null, 0));
});
- fsmBuilder.externalTransition().from(PeerState.BAN).to(PeerState.END).on(PeerEvents.TIMEOUT)
+ fsmBuilder.externalTransition().from(PeerState.BAN).to(PeerState.END).on(MatchEvents.TIMEOUT)
.perform((from, to, event, context) -> {
- // 解除封禁
- getLogger().info(Lang.RULE_MODULE_PEER_BAN_TIMEOUT, context.getPeer().getPeerId(), context.getPeer().getAddress().getIp(), context.getPeer().getAddress().getPort());
- context.setResult(new MatchResultDetail(this, to, null, null, 0));
- });*/
+ getLogger().debug(Lang.RULE_MODULE_PEER_BAN_TIMEOUT, getName(), context.getRecord().getPeer().getAddress());
+ // 执行解禁操作
+ Optional.ofNullable(context.getTimeoutFunc()).ifPresent(func -> func.accept(context.getRecord()));
+ // 更新匹配结果
+ context.getRecord().setResult(new MatchResultDetail(this, to, null, null, 0));
+ });
return fsmBuilder;
}
@@ -78,7 +83,7 @@ default StateMachineBuilder ruleSmBuild
*
* @return 状态机
*/
- StateMachine getStateMachine();
+ StateMachine getStateMachine();
/**
* 是否应该封禁Peer
@@ -91,9 +96,46 @@ default StateMachineBuilder ruleSmBuild
/**
* 运行规则检查
*/
- default void runCheck() {
+ default void runCheck(Consumer activeFunc, Consumer banFunc, Consumer disconnectFunc, Consumer timeoutFunc) {
// long t1 = System.currentTimeMillis();
- getServer().getLivePeersSnapshot().keySet().forEach(peerAddress -> Optional.ofNullable(getServer().getMatchRecords().get(peerAddress)).ifPresent(record -> triggerEvent(MatchEvents.MATCH, record)));
+ List removeLIst = new ArrayList<>();
+ Map matchRecords = getServer().getMatchRecords();
+ matchRecords.forEach((key, record) -> {
+ // 构建匹配上下文
+ PeerMatchContext context = new PeerMatchContext(record, activeFunc, banFunc, disconnectFunc, timeoutFunc);
+ MatchResultDetail result = record.getResult();
+ switch (result.getState()) {
+ case INIT, ACTIVE:
+ if (result.getExpireTime() < System.currentTimeMillis()) {
+ // 已经超时的记录直接归到END状态
+ triggerEvent(MatchEvents.DISCONNECT, context);
+ break;
+ }
+ // 判断是否需要封禁
+ CheckResult banResult = shouldBanPeer(record);
+ if (banResult.hit()) {
+ // 命中
+ context.getRecord().getResult().setRule(banResult.rule());
+ context.getRecord().getResult().setReason(banResult.reason());
+ triggerEvent(MatchEvents.HIT, context);
+ } else {
+ // 通过
+ triggerEvent(MatchEvents.PASS, context);
+ }
+ break;
+ case BAN:
+ if (result.getExpireTime() < System.currentTimeMillis()) {
+ // 已经超时的记录直接归到END状态
+ triggerEvent(MatchEvents.TIMEOUT, context);
+ }
+ break;
+ default:
+ // END状态直接移除
+ removeLIst.add(key);
+ break;
+ }
+ });
+ removeLIst.forEach(matchRecords::remove);
// long t2 = System.currentTimeMillis();
// getLogger().debug(Lang.RULE_MODULE_MATCH_TIME, getName(), t2 - t1);
}
@@ -104,8 +146,8 @@ default void runCheck() {
* @param event 事件
* @param context 上下文
*/
- default void triggerEvent(MatchEvents event, PeerMatchRecord context) {
- getStateMachine().fireEvent(context.getResult().state(), event, context);
+ default void triggerEvent(MatchEvents event, PeerMatchContext context) {
+ getStateMachine().fireEvent(context.getRecord().getResult().getState(), event, context);
}
record CheckResult(boolean hit, String rule, String reason) {
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/RuleSubBlocker.java b/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/RuleSubBlocker.java
index fd2323c2..744eec32 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/RuleSubBlocker.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/impl/rule/RuleSubBlocker.java
@@ -13,7 +13,6 @@
import com.ghostchu.peerbanhelper.util.HTTPUtil;
import com.ghostchu.peerbanhelper.util.IPAddressUtil;
import com.ghostchu.peerbanhelper.util.rule.MatchResult;
-import com.ghostchu.peerbanhelper.util.rule.RuleMatcher;
import com.ghostchu.peerbanhelper.util.rule.RuleType;
import com.ghostchu.peerbanhelper.util.rule.matcher.IPMatcher;
import com.ghostchu.peerbanhelper.util.rule.matcher.PrefixMatcher;
@@ -39,7 +38,6 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
-import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@@ -115,7 +113,6 @@ private void reloadConfig() {
@Override
public CheckResult shouldBanPeer(PeerMatchRecord ctx) {
AtomicReference result = new AtomicReference<>(new CheckResult(false, null, null));
- CountDownLatch latch = new CountDownLatch(rules.size());
try (var service = Executors.newVirtualThreadPerTaskExecutor()) {
rules.forEach(matcher -> service.submit(() -> {
String matchStr;
@@ -130,14 +127,8 @@ public CheckResult shouldBanPeer(PeerMatchRecord ctx) {
if (matcher.match(matchStr) == MatchResult.TRUE) {
result.set(new CheckResult(true, matcher.metadata().get("rule").toString(), String.format(Lang.MODULE_IBL_MATCH_SUB_RULE, matcher.metadata().get("rule").toString())));
}
- latch.countDown();
}));
}
- try {
- latch.await();
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
return result.get();
}
@@ -153,7 +144,7 @@ public SlimMsg updateRule(@NotNull ConfigurationSection rule, RuleUpdateType upd
// 检查ipBanMatchers是否有对应的规则,有则删除
rules.removeIf(ele -> ele.metadata().get("id").equals(ruleId));
// 未启用跳过更新逻辑
- return new SlimMsg(false, Lang.SUB_RULE_DISABLED.replace("{}", ruleId));
+ return new SlimMsg(false, String.format(Lang.SUB_RULE_DISABLED, ruleId));
}
String name = rule.getString("name", ruleId);
String url = rule.getString("url");
@@ -166,7 +157,6 @@ public SlimMsg updateRule(@NotNull ConfigurationSection rule, RuleUpdateType upd
File tempFile = new File(dir, "temp_" + ruleFileName);
File ruleFile = new File(dir, ruleFileName);
List ipAddresses = new ArrayList<>();
- List subnetAddresses = new ArrayList<>();
List fileLines = new ArrayList<>();
HTTPUtil.retryableSend(HTTPUtil.getHttpClient(false, null), MutableRequest.GET(url), HttpResponse.BodyHandlers.ofFile(Path.of(tempFile.getPath()))).whenComplete((pathHttpResponse, throwable) -> {
if (throwable != null) {
@@ -186,8 +176,8 @@ public SlimMsg updateRule(@NotNull ConfigurationSection rule, RuleUpdateType upd
rules.add(new SubStrMatcher(ruleType, ruleId, name, fileLines));
}
default -> {
- fileToIPList(name, ruleFile, ipAddresses, subnetAddresses);
- rules.add(new IPMatcher(ruleId, name, ipAddresses, subnetAddresses));
+ fileToIPList(name, ruleFile, ipAddresses);
+ rules.add(new IPMatcher(ruleId, name, ipAddresses));
}
}
log.warn(Lang.SUB_RULE_USE_CACHE, name);
@@ -197,13 +187,13 @@ public SlimMsg updateRule(@NotNull ConfigurationSection rule, RuleUpdateType upd
result.set(new SlimMsg(false, Lang.SUB_RULE_LOAD_FAILED.replace("{}", name)));
}
} else {
+ log.error(Lang.SUB_RULE_UPDATE_FAILED, name);
result.set(new SlimMsg(false, Lang.SUB_RULE_UPDATE_FAILED.replace("{}", name)));
}
} else {
// log.error(Lang.IP_BAN_RULE_LOAD_FAILED, name, throwable);
result.set(new SlimMsg(false, Lang.SUB_RULE_LOAD_FAILED.replace("{}", name)));
}
- throw new RuntimeException(throwable);
}
try {
HashCode ruleHash = null;
@@ -217,7 +207,7 @@ public SlimMsg updateRule(@NotNull ConfigurationSection rule, RuleUpdateType upd
ent_count = switch (ruleType) {
case PEER_ID_STARTS_WITH, PEER_ID_CONTAINS, CLIENT_NAME_STARTS_WITH, CLIENT_NAME_CONTAINS ->
fileToLines(name, ruleFile, fileLines);
- default -> fileToIPList(name, tempFile, ipAddresses, subnetAddresses);
+ default -> fileToIPList(name, tempFile, ipAddresses);
};
// 更新后重命名临时文件
ruleFile.delete();
@@ -228,7 +218,7 @@ public SlimMsg updateRule(@NotNull ConfigurationSection rule, RuleUpdateType upd
ent_count = switch (ruleType) {
case PEER_ID_STARTS_WITH, PEER_ID_CONTAINS, CLIENT_NAME_STARTS_WITH,
CLIENT_NAME_CONTAINS -> fileToLines(name, ruleFile, fileLines);
- default -> fileToIPList(name, tempFile, ipAddresses, subnetAddresses);
+ default -> fileToIPList(name, tempFile, ipAddresses);
};
} else {
log.info(Lang.SUB_RULE_NO_UPDATE, name);
@@ -237,13 +227,13 @@ public SlimMsg updateRule(@NotNull ConfigurationSection rule, RuleUpdateType upd
tempFile.delete();
}
// ip列表或者subnet列表不为空代表需要更新matcher
- if (!ipAddresses.isEmpty() || !subnetAddresses.isEmpty() || !fileLines.isEmpty()) {
+ if (!ipAddresses.isEmpty() || !fileLines.isEmpty()) {
// 如果已经存在则更新,否则添加
rules.stream().filter(ele -> ele.metadata().get("id").equals(ruleId)).findFirst().ifPresentOrElse(ele -> {
switch (ruleType) {
case PEER_ID_STARTS_WITH, PEER_ID_CONTAINS, CLIENT_NAME_STARTS_WITH,
- CLIENT_NAME_CONTAINS -> ((RuleMatcher) ele).setData(name, fileLines);
- default -> ((IPMatcher) ele).setData(name, ipAddresses, subnetAddresses);
+ CLIENT_NAME_CONTAINS -> ele.setData(name, fileLines);
+ default -> ele.setData(name, ipAddresses);
}
log.info(Lang.SUB_RULE_UPDATE_SUCCESS, name);
result.set(new SlimMsg(true, Lang.SUB_RULE_UPDATE_SUCCESS.replace("{}", name)));
@@ -253,7 +243,7 @@ public SlimMsg updateRule(@NotNull ConfigurationSection rule, RuleUpdateType upd
rules.add(new PrefixMatcher(ruleType, ruleId, name, fileLines));
case PEER_ID_CONTAINS, CLIENT_NAME_CONTAINS ->
rules.add(new SubStrMatcher(ruleType, ruleId, name, fileLines));
- default -> rules.add(new IPMatcher(ruleId, name, ipAddresses, subnetAddresses));
+ default -> rules.add(new IPMatcher(ruleId, name, ipAddresses));
}
log.info(Lang.SUB_RULE_LOAD_SUCCESS, name);
result.set(new SlimMsg(true, Lang.SUB_RULE_LOAD_SUCCESS.replace("{}", name)));
@@ -263,7 +253,7 @@ public SlimMsg updateRule(@NotNull ConfigurationSection rule, RuleUpdateType upd
// 更新日志
try {
db.insertRuleSubLog(ruleId, ent_count, updateType);
- result.set(new SlimMsg(true, Lang.SUB_RULE_UPDATED.replace("{}", name)));
+ result.set(new SlimMsg(true, String.format(Lang.SUB_RULE_UPDATED, name)));
} catch (SQLException e) {
log.error(Lang.SUB_RULE_UPDATE_LOG_ERROR, ruleId, e);
result.set(new SlimMsg(false, Lang.SUB_RULE_UPDATE_LOG_ERROR.replace("{}", name)));
@@ -276,7 +266,7 @@ public SlimMsg updateRule(@NotNull ConfigurationSection rule, RuleUpdateType upd
}
}).join();
} else {
- result.set(new SlimMsg(false, Lang.SUB_RULE_URL_WRONG.replace("{}", name)));
+ result.set(new SlimMsg(false, String.format(Lang.SUB_RULE_URL_WRONG, name)));
}
return result.get();
}
@@ -306,35 +296,15 @@ private int fileToLines(String ruleName, File ruleFile, List lines) thro
*
* @param ruleName 规则名称
* @param ruleFile 规则文件
- * @param ips 精确ip列表
- * @param subnets 网段列表
+ * @param ips ip列表
* @return 加载的行数
*/
- private int fileToIPList(String ruleName, File ruleFile, List ips, List subnets) throws IOException {
+ private int fileToIPList(String ruleName, File ruleFile, List ips) throws IOException {
AtomicInteger count = new AtomicInteger();
Files.readLines(ruleFile, StandardCharsets.UTF_8).forEach(ele -> {
count.getAndIncrement();
- IPAddress ipAddress = IPAddressUtil.getIPAddress(ele);
- // 判断是否是网段
- List ipsList = new ArrayList<>();
- if (null != ipAddress.getNetworkPrefixLength()) {
- if (ipAddress.isIPv4Convertible() && ipAddress.getNetworkPrefixLength() >= 20) {
- // 前缀长度 >= 20 的ipv4网段地址转为精确ip
- ipAddress.nonZeroHostIterator().forEachRemaining(ipsList::add);
- } else {
- subnets.add(ipAddress);
- log.debug(Lang.IP_BAN_RULE_LOAD_CIDR, ruleName, ipAddress);
- }
- } else {
- ipsList.add(ipAddress);
- }
- ipsList.forEach(ip -> {
- if (ip.isIPv4Convertible()) {
- ip = ip.toIPv4().withoutPrefixLength();
- }
- ips.add(ip);
- log.debug(Lang.IP_BAN_RULE_LOAD_IP, ruleName, ip);
- });
+ log.debug(Lang.IP_BAN_RULE_LOAD_CIDR, ruleName, ele);
+ ips.add(IPAddressUtil.getIPAddress(ele));
});
return count.get();
}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/RuleSubController.java b/src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/RuleSubController.java
index 5cef0dba..fd5bc9ff 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/RuleSubController.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/module/impl/webapi/RuleSubController.java
@@ -155,7 +155,7 @@ private SlimMsg update(String ruleId) {
}
ConfigurationSection configurationSection = ruleSubBlocker.getRuleSubsConfig().getConfigurationSection(ruleId);
if (null == configurationSection) {
- return new SlimMsg(false, Lang.SUB_RULE_CANT_FIND.replace("{}", ruleId));
+ return new SlimMsg(false, String.format(Lang.SUB_RULE_CANT_FIND, ruleId));
}
return ruleSubBlocker.updateRule(configurationSection, RuleUpdateType.MANUAL);
}
@@ -178,10 +178,10 @@ private void switcher(Context ctx) throws SQLException, IOException {
RuleSubInfo ruleSubInfo = ruleSubBlocker.getRuleSubInfo(ruleId);
if (null == ruleSubInfo) {
ctx.status(HttpStatus.BAD_REQUEST);
- ctx.json(new SlimMsg(false, Lang.SUB_RULE_CANT_FIND.replace("{}", ruleId)));
+ ctx.json(new SlimMsg(false, String.format(Lang.SUB_RULE_CANT_FIND, ruleId)));
return;
}
- String msg = (enabled ? Lang.SUB_RULE_ENABLED : Lang.SUB_RULE_DISABLED).replace("{}", ruleSubInfo.ruleName());
+ String msg = String.format(enabled ? Lang.SUB_RULE_ENABLED : Lang.SUB_RULE_DISABLED, ruleSubInfo.ruleName());
if (enabled != ruleSubInfo.enabled()) {
ConfigurationSection configurationSection = ruleSubBlocker.saveRuleSubInfo(new RuleSubInfo(ruleId, enabled, ruleSubInfo.ruleName(), ruleSubInfo.subUrl(), 0, 0));
ruleSubBlocker.updateRule(configurationSection, RuleUpdateType.MANUAL);
@@ -203,12 +203,12 @@ private void delete(Context ctx) throws IOException, SQLException {
RuleSubInfo ruleSubInfo = ruleSubBlocker.getRuleSubInfo(ruleId);
if (null == ruleSubInfo) {
ctx.status(HttpStatus.BAD_REQUEST);
- ctx.json(new SlimMsg(false, Lang.SUB_RULE_CANT_FIND.replace("{}", ruleId)));
+ ctx.json(new SlimMsg(false, String.format(Lang.SUB_RULE_CANT_FIND, ruleId)));
return;
}
ruleSubBlocker.deleteRuleSubInfo(ruleId);
ruleSubBlocker.getRules().removeIf(ele -> ele.metadata().get("id").equals(ruleId));
- String msg = Lang.SUB_RULE_DELETED.replace("{}", ruleSubInfo.ruleName());
+ String msg = String.format(Lang.SUB_RULE_DELETED, ruleSubInfo.ruleName());
log.info(msg);
ctx.json(new SlimMsg(true, msg));
}
@@ -234,13 +234,13 @@ private void save(Context ctx, String ruleId, boolean isAdd) throws SQLException
if (isAdd && ruleSubInfo != null) {
// 新增时检查规则是否存在
ctx.status(HttpStatus.BAD_REQUEST);
- ctx.json(new SlimMsg(false, Lang.SUB_RULE_ID_CONFLICT.replace("{}", ruleId)));
+ ctx.json(new SlimMsg(false, String.format(Lang.SUB_RULE_ID_CONFLICT, ruleId)));
return;
}
if (!isAdd && ruleSubInfo == null) {
// 更新时检查规则是否存在
ctx.status(HttpStatus.BAD_REQUEST);
- ctx.json(new SlimMsg(false, Lang.SUB_RULE_CANT_FIND.replace("{}", ruleId)));
+ ctx.json(new SlimMsg(false, String.format(Lang.SUB_RULE_CANT_FIND, ruleId)));
return;
}
String ruleName = subInfo.ruleName();
@@ -277,7 +277,7 @@ private void save(Context ctx, String ruleId, boolean isAdd) throws SQLException
ruleSubBlocker.saveRuleSubInfo(ruleSubInfo);
}
ctx.status(HttpStatus.BAD_REQUEST);
- ctx.json(new SlimMsg(false, Lang.SUB_RULE_URL_WRONG.replace("{}", ruleName)));
+ ctx.json(new SlimMsg(false, String.format(Lang.SUB_RULE_URL_WRONG, ruleName)));
}
}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/text/Lang.java b/src/main/java/com/ghostchu/peerbanhelper/text/Lang.java
index 3c553872..9b1bba87 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/text/Lang.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/text/Lang.java
@@ -182,16 +182,16 @@ public class Lang {
public static final String SUB_RULE_LOAD_CONTENT = "订阅规则 {} 加载内容 : {}";
public static final String RULE_SUB_API_INTERNAL_ERROR = "[错误] 订阅规则API遇到非预期错误";
public static final String SUB_RULE_NO_ID = "[错误] 订阅规则ID为空";
- public static final String SUB_RULE_ID_CONFLICT = "[错误] 订阅规则ID冲突: {}";
- public static final String SUB_RULE_CANT_FIND = "[错误] 未找到订阅规则: {}";
+ public static final String SUB_RULE_ID_CONFLICT = "[错误] 订阅规则ID冲突: %s";
+ public static final String SUB_RULE_CANT_FIND = "[错误] 未找到订阅规则: %s";
public static final String SUB_RULE_PARAM_WRONG = "[错误] 订阅规则参数错误";
- public static final String SUB_RULE_URL_WRONG = "[错误] 订阅规则 {} URL错误";
- public static final String SUB_RULE_ENABLED = "订阅规则 {} 已启用";
- public static final String SUB_RULE_DISABLED = "订阅规则 {} 已禁用";
- public static final String SUB_RULE_UPDATED = "订阅规则 {} 已更新";
+ public static final String SUB_RULE_URL_WRONG = "[错误] 订阅规则 %s URL错误";
+ public static final String SUB_RULE_ENABLED = "订阅规则 %s 已启用";
+ public static final String SUB_RULE_DISABLED = "订阅规则 %s 已禁用";
+ public static final String SUB_RULE_UPDATED = "订阅规则 %s 已更新";
public static final String SUB_RULE_ALL_UPDATED = "订阅规则已全部更新";
public static final String SUB_RULE_SAVED = "订阅规则已保存";
- public static final String SUB_RULE_DELETED = "订阅规则 {} 已删除";
+ public static final String SUB_RULE_DELETED = "订阅规则 %s 已删除";
public static final String SUB_RULE_INFO_QUERY_SUCCESS = "订阅规则查询成功";
public static final String SUB_RULE_LOG_QUERY_SUCCESS = "订阅规则更新日志查询成功";
public static final String SUB_RULE_LOG_QUERY_ERROR = "订阅规则更新日志查询出错";
@@ -213,5 +213,7 @@ public class Lang {
public static final String WEBVIEW_DISABLED_WEBKIT_NOT_INCLUDED = "未找到 JavaFx Web 模块,您正在使用精简构建,WebUI 选项卡未启用";
public static final String WEBVIEW_ENABLED = "已找到 JavaFx Web,WebUI 选项卡已启用";
public static final String RULE_MODULE_MATCH_TIME = "规则模块 {} 匹配花费时间:{}ms";
- public static final String RULE_MODULE_PEER_BAN = "[封禁] 规则模块 {} : {} ";
+ public static final String RULE_MODULE_PEER_HIT = "规则模块 {} : {} 命中";
+ public static final String RULE_MODULE_PEER_DISCONNECT = "规则模块 {} : {} 已断开连接";
+ public static final String RULE_MODULE_PEER_BAN_TIMEOUT = "规则模块 {} : {} 已解禁";
}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/util/rule/RuleMatcher.java b/src/main/java/com/ghostchu/peerbanhelper/util/rule/RuleMatcher.java
index 98f34a68..c9e6f1bc 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/util/rule/RuleMatcher.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/util/rule/RuleMatcher.java
@@ -4,6 +4,7 @@
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
+import java.util.List;
import java.util.Map;
/**
@@ -12,7 +13,7 @@
@Slf4j
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
-public abstract class RuleMatcher extends AbstractMatcher {
+public abstract class RuleMatcher extends AbstractMatcher {
private final String ruleId;
@@ -20,13 +21,13 @@ public abstract class RuleMatcher extends AbstractMatcher {
protected String ruleName;
- public RuleMatcher(RuleType ruleType, String ruleId, String ruleName, Object... ruleData) {
+ public RuleMatcher(RuleType ruleType, String ruleId, String ruleName, List ruleData) {
this.ruleType = ruleType;
this.ruleId = ruleId;
setData(ruleName, ruleData);
}
- public abstract void setData(String ruleName, Object... ruleData);
+ public abstract void setData(String ruleName, List ruleData);
public Map metadata() {
return Map.of("id", ruleId, "rule", ruleName, "type", ruleType);
diff --git a/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/IPMatcher.java b/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/IPMatcher.java
index f85e733b..667e7f98 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/IPMatcher.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/IPMatcher.java
@@ -14,26 +14,42 @@
import org.jetbrains.annotations.NotNull;
import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
@Slf4j
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
-public class IPMatcher extends RuleMatcher {
+public class IPMatcher extends RuleMatcher {
private List subnets;
private List ips;
private BloomFilter bloomFilter;
- public IPMatcher(String ruleId, String ruleName, Object... ruleData) {
+ public IPMatcher(String ruleId, String ruleName, List ruleData) {
super(RuleType.IP, ruleId, ruleName, ruleData);
}
@Override
- public void setData(String ruleName, Object... ruleData) {
+ public void setData(String ruleName, List ruleData) {
this.ruleName = ruleName;
- this.ips = ruleData.length > 0 ? (List) ruleData[0] : List.of();
- this.subnets = ruleData.length > 1 ? (List) ruleData[1] : List.of();
+ this.ips = new ArrayList<>();
+ this.subnets = new ArrayList<>();
+ Optional.ofNullable(ruleData).ifPresent(list -> list.forEach(ipAddress -> {
+ // 判断是否是网段
+ if (null != ipAddress.getNetworkPrefixLength()) {
+ if (ipAddress.isIPv4Convertible() && ipAddress.getNetworkPrefixLength() >= 20) {
+ // 前缀长度 >= 20 的ipv4网段地址转为精确ip
+ ipAddress.nonZeroHostIterator().forEachRemaining(ips::add);
+ } else {
+ subnets.add(ipAddress);
+ log.debug(Lang.IP_BAN_RULE_LOAD_CIDR, ruleName, ipAddress);
+ }
+ } else {
+ ips.add(ipAddress);
+ }
+ }));
bloomFilter = BloomFilter.create(Funnels.stringFunnel(StandardCharsets.UTF_8), ips.size(), 0.01);
ips.forEach(ip -> bloomFilter.put(ip.toString()));
}
diff --git a/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/PrefixMatcher.java b/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/PrefixMatcher.java
index 56c94669..54a23137 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/PrefixMatcher.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/PrefixMatcher.java
@@ -9,28 +9,30 @@
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
+import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
@Slf4j
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
-public class PrefixMatcher extends RuleMatcher {
+public class PrefixMatcher extends RuleMatcher {
private List prefixes;
- public PrefixMatcher(RuleType ruleType, String ruleId, String ruleName, Object... ruleData) {
+ public PrefixMatcher(RuleType ruleType, String ruleId, String ruleName, List ruleData) {
super(ruleType, ruleId, ruleName, ruleData);
}
@Override
- public void setData(String ruleName, Object... ruleData) {
+ public void setData(String ruleName, List ruleData) {
this.ruleName = ruleName;
- this.prefixes = ruleData.length > 0 ? (List) ruleData[0] : List.of();
+ Optional.ofNullable(ruleData).ifPresentOrElse(list -> this.prefixes = list, () -> this.prefixes = new ArrayList<>());
}
@Override
public @NotNull MatchResult match0(@NotNull String content) {
- if (prefixes.parallelStream().anyMatch(content::startsWith)) {
+ if (prefixes.stream().anyMatch(content::startsWith)) {
return MatchResult.TRUE;
}
return MatchResult.DEFAULT;
diff --git a/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/SubStrMatcher.java b/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/SubStrMatcher.java
index f6c84513..43787874 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/SubStrMatcher.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/util/rule/matcher/SubStrMatcher.java
@@ -9,28 +9,30 @@
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
+import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
@Slf4j
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
-public class SubStrMatcher extends RuleMatcher {
+public class SubStrMatcher extends RuleMatcher {
- private List subStrs;
+ private List subs;
- public SubStrMatcher(RuleType ruleType, String ruleId, String ruleName, Object... ruleData) {
+ public SubStrMatcher(RuleType ruleType, String ruleId, String ruleName, List ruleData) {
super(ruleType, ruleId, ruleName, ruleData);
}
@Override
- public void setData(String ruleName, Object... ruleData) {
+ public void setData(String ruleName, List ruleData) {
this.ruleName = ruleName;
- this.subStrs = ruleData.length > 0 ? (List) ruleData[0] : List.of();
+ Optional.ofNullable(ruleData).ifPresentOrElse(list -> this.subs = list, () -> this.subs = new ArrayList<>());
}
@Override
public @NotNull MatchResult match0(@NotNull String content) {
- if (subStrs.parallelStream().anyMatch(content::contains)) {
+ if (subs.stream().anyMatch(content::contains)) {
return MatchResult.TRUE;
}
return MatchResult.DEFAULT;
diff --git a/src/main/java/com/ghostchu/peerbanhelper/util/time/ExceptedTime.java b/src/main/java/com/ghostchu/peerbanhelper/util/time/ExceptedTime.java
index 7c017cb2..b619888b 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/util/time/ExceptedTime.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/util/time/ExceptedTime.java
@@ -9,7 +9,9 @@ public enum ExceptedTime {
CHECK_BANS(30 * 1000),
ADD_BAN_ENTRY(30 * 1000),
APPLY_BANLIST(30 * 1000),
- STAGE_BAN_WAVE(COLLECT_PEERS.timeout + CHECK_BANS.timeout + ADD_BAN_ENTRY.timeout + APPLY_BANLIST.timeout + 10 * 1000);
+ STAGE_BAN_WAVE(COLLECT_PEERS.timeout + CHECK_BANS.timeout + ADD_BAN_ENTRY.timeout + APPLY_BANLIST.timeout + 10 * 1000),
+ RUN_BLOCKER(30 * 1000),
+ BAN_PEER(3 * 1000);
@Getter
private final long timeout;
From 747e552caaf3872092492cb134b1e5acc4bff85d Mon Sep 17 00:00:00 2001
From: PluieM <644202913@qq.com>
Date: Thu, 20 Jun 2024 16:46:03 +0800
Subject: [PATCH 5/5] =?UTF-8?q?=E8=B0=83=E6=95=B4merge=E9=81=97=E6=BC=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java b/src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java
index 956be299..9a8860c5 100644
--- a/src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java
+++ b/src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java
@@ -1,6 +1,5 @@
package com.ghostchu.peerbanhelper;
-import com.ghostchu.peerbanhelper.alert.AlertManager;
import com.ghostchu.peerbanhelper.btn.BtnNetwork;
import com.ghostchu.peerbanhelper.database.DatabaseHelper;
import com.ghostchu.peerbanhelper.database.DatabaseManager;
@@ -106,7 +105,7 @@ public class PeerBanHelperServer {
@Getter
private JavalinWebContainer webContainer;
@Getter
- private final Map matchRecords = new ConcurrentHashMap<>();
+ private final Map matchRecords = new ConcurrentHashMap<>();
public PeerBanHelperServer(String pbhServerAddress, YamlConfiguration profile, YamlConfiguration mainConfig) throws SQLException {
this.pbhServerAddress = pbhServerAddress;