blob: ea840e14c9c693032bf65a0f0e59dd5353b182ec [file] [log] [blame]
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.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
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"));
}
System.out.println("Received announce params: " + params);
System.out.println("Client IP: " + ipAddress);
// 用ISO-8859-1解码,确保二进制数据正确还原
String infoHash = decodeParam(params.get("info_hash")[0]);
System.out.println("Decoded info_hash (raw bytes as hex): " + bytesToHex(infoHash.getBytes("ISO-8859-1")));
Optional<TorrentMeta> meta = torrentMetaRepository.findByInfoHash(infoHash);
if (!meta.isPresent()) {
System.out.println("Invalid info_hash: not found in DB");
return BencodeCodec.encode(Map.of("failure reason", "Invalid info_hash"));
}
String peerId = decodeParam(params.get("peer_id")[0]);
System.out.println("Decoded peer_id: " + peerId);
int port = Integer.parseInt(params.get("port")[0]);
System.out.println("Port: " + port);
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);
System.out.println("Added new peer: " + peerId);
} else {
System.out.println("Peer already exists: " + peerId);
}
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) {
e.printStackTrace(); // 打印异常堆栈,方便定位错误
return BencodeCodec.encode(Map.of("failure reason", "Internal server error"));
}
}
// 辅助函数:打印字节转成16进制字符串
private String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
// decodeParam 建议用ISO-8859-1解码
private String decodeParam(String param) throws UnsupportedEncodingException {
return URLDecoder.decode(param, "ISO-8859-1");
}
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;
}
}
}