blob: 7167ff37875ffc8d5fe7ccd1c3f5c7bae99cdf75 [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.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;
}
}
}