添加bt与tracker交互
Change-Id: I1327c2ed89a76bee8e2abeb8cb3014b56357689a
diff --git a/src/main/java/com/pt/service/TrackerService.java b/src/main/java/com/pt/service/TrackerService.java
new file mode 100644
index 0000000..7167ff3
--- /dev/null
+++ b/src/main/java/com/pt/service/TrackerService.java
@@ -0,0 +1,76 @@
+package com.pt.service;
+
+import com.pt.entity.TorrentMeta;
+import com.pt.repository.TorrentMetaRepository;
+import com.pt.utils.BencodeCodec;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+@Service
+public class TrackerService {
+
+ private final Map<String, List<PeerInfo>> torrentPeers = new ConcurrentHashMap<>();
+
+ @Autowired
+ private TorrentMetaRepository torrentMetaRepository;
+
+ public byte[] handleAnnounce(Map<String, String[]> params, String ipAddress) {
+ try {
+ if (!params.containsKey("info_hash") || !params.containsKey("peer_id") || !params.containsKey("port")) {
+ return BencodeCodec.encode(Map.of("failure reason", "Missing required parameters"));
+ }
+
+ String infoHash = decodeParam(params.get("info_hash")[0]);
+ TorrentMeta meta = torrentMetaRepository.findByInfoHash(infoHash);
+ if (meta == null) {
+ return BencodeCodec.encode(Map.of("failure reason", "Invalid info_hash"));
+ }
+
+ String peerId = decodeParam(params.get("peer_id")[0]);
+ int port = Integer.parseInt(params.get("port")[0]);
+
+ PeerInfo peer = new PeerInfo(ipAddress, port, peerId);
+
+ torrentPeers.computeIfAbsent(infoHash, k -> new CopyOnWriteArrayList<>());
+ List<PeerInfo> peers = torrentPeers.get(infoHash);
+
+ boolean exists = peers.stream().anyMatch(p -> p.peerId.equals(peerId));
+ if (!exists) {
+ peers.add(peer);
+ }
+
+ List<String> ips = peers.stream().map(p -> p.ip).toList();
+ List<Integer> ports = peers.stream().map(p -> p.port).toList();
+ byte[] peerBytes = BencodeCodec.buildCompactPeers(ips, ports);
+
+ return BencodeCodec.buildTrackerResponse(1800, peerBytes);
+ } catch (Exception e) {
+ return BencodeCodec.encode(Map.of("failure reason", "Internal server error"));
+ }
+ }
+
+ private String decodeParam(String raw) {
+ return new String(raw.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
+ }
+
+ private static class PeerInfo {
+ String ip;
+ int port;
+ String peerId;
+
+ public PeerInfo(String ip, int port, String peerId) {
+ this.ip = ip;
+ this.port = port;
+ this.peerId = peerId;
+ }
+ }
+}
+