blob: 7167ff37875ffc8d5fe7ccd1c3f5c7bae99cdf75 [file] [log] [blame]
Edwardsamaxlf1bf7ad2025-06-03 23:52:16 +08001package com.pt.service;
2
3import com.pt.entity.TorrentMeta;
4import com.pt.repository.TorrentMetaRepository;
5import com.pt.utils.BencodeCodec;
6import org.springframework.beans.factory.annotation.Autowired;
7import org.springframework.stereotype.Service;
8
9import java.nio.charset.StandardCharsets;
10import java.util.ArrayList;
11import java.util.HashMap;
12import java.util.List;
13import java.util.Map;
14import java.util.concurrent.ConcurrentHashMap;
15import java.util.concurrent.CopyOnWriteArrayList;
16
17@Service
18public class TrackerService {
19
20 private final Map<String, List<PeerInfo>> torrentPeers = new ConcurrentHashMap<>();
21
22 @Autowired
23 private TorrentMetaRepository torrentMetaRepository;
24
25 public byte[] handleAnnounce(Map<String, String[]> params, String ipAddress) {
26 try {
27 if (!params.containsKey("info_hash") || !params.containsKey("peer_id") || !params.containsKey("port")) {
28 return BencodeCodec.encode(Map.of("failure reason", "Missing required parameters"));
29 }
30
31 String infoHash = decodeParam(params.get("info_hash")[0]);
32 TorrentMeta meta = torrentMetaRepository.findByInfoHash(infoHash);
33 if (meta == null) {
34 return BencodeCodec.encode(Map.of("failure reason", "Invalid info_hash"));
35 }
36
37 String peerId = decodeParam(params.get("peer_id")[0]);
38 int port = Integer.parseInt(params.get("port")[0]);
39
40 PeerInfo peer = new PeerInfo(ipAddress, port, peerId);
41
42 torrentPeers.computeIfAbsent(infoHash, k -> new CopyOnWriteArrayList<>());
43 List<PeerInfo> peers = torrentPeers.get(infoHash);
44
45 boolean exists = peers.stream().anyMatch(p -> p.peerId.equals(peerId));
46 if (!exists) {
47 peers.add(peer);
48 }
49
50 List<String> ips = peers.stream().map(p -> p.ip).toList();
51 List<Integer> ports = peers.stream().map(p -> p.port).toList();
52 byte[] peerBytes = BencodeCodec.buildCompactPeers(ips, ports);
53
54 return BencodeCodec.buildTrackerResponse(1800, peerBytes);
55 } catch (Exception e) {
56 return BencodeCodec.encode(Map.of("failure reason", "Internal server error"));
57 }
58 }
59
60 private String decodeParam(String raw) {
61 return new String(raw.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
62 }
63
64 private static class PeerInfo {
65 String ip;
66 int port;
67 String peerId;
68
69 public PeerInfo(String ip, int port, String peerId) {
70 this.ip = ip;
71 this.port = port;
72 this.peerId = peerId;
73 }
74 }
75}
76