finish handleAnnounce and fix bugs in torrent upload(using ISO_8859_1)

Change-Id: Ic2da7cef878bb7aa66184f04058bb2db2393190e
diff --git a/src/main/java/com/example/g8backend/service/ITrackerService.java b/src/main/java/com/example/g8backend/service/ITrackerService.java
index e522d77..055e317 100644
--- a/src/main/java/com/example/g8backend/service/ITrackerService.java
+++ b/src/main/java/com/example/g8backend/service/ITrackerService.java
@@ -1,6 +1,9 @@
 package com.example.g8backend.service;
 
 
-public interface ITrackerService {
+import com.example.g8backend.dto.AnnounceRequestDTO;
+import com.example.g8backend.dto.AnnounceResponseDTO;
 
+public interface ITrackerService {
+    AnnounceResponseDTO handleAnnounce(AnnounceRequestDTO requestDTO);
 }
diff --git a/src/main/java/com/example/g8backend/service/impl/TorrentServiceImpl.java b/src/main/java/com/example/g8backend/service/impl/TorrentServiceImpl.java
index bedb94a..199ff2a 100644
--- a/src/main/java/com/example/g8backend/service/impl/TorrentServiceImpl.java
+++ b/src/main/java/com/example/g8backend/service/impl/TorrentServiceImpl.java
@@ -17,7 +17,7 @@
     @Resource
     private TorrentMapper torrentMapper;
 
-    String tracker = "http://127.0.0.1:8080/announce/";
+    String tracker = "http://127.0.0.1:8080/tracker/announce/";
 
     @Override
     public Torrent handleTorrentUpload(File file, Long userId, String passkey) throws IOException, IllegalArgumentException {
diff --git a/src/main/java/com/example/g8backend/service/impl/TrackerServiceImpl.java b/src/main/java/com/example/g8backend/service/impl/TrackerServiceImpl.java
index c0dba70..ffb5e65 100644
--- a/src/main/java/com/example/g8backend/service/impl/TrackerServiceImpl.java
+++ b/src/main/java/com/example/g8backend/service/impl/TrackerServiceImpl.java
@@ -1,8 +1,88 @@
 package com.example.g8backend.service.impl;
 
+import com.example.g8backend.dto.AnnounceRequestDTO;
+import com.example.g8backend.dto.AnnounceResponseDTO;
+import com.example.g8backend.entity.Peer;
+import com.example.g8backend.mapper.PeerMapper;
 import com.example.g8backend.service.ITrackerService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 
+import java.util.*;
+
 @Service
 public class TrackerServiceImpl implements ITrackerService {
+    final int interval = 30;
+
+    @Autowired
+    private PeerMapper peerMapper;
+
+    @Autowired
+    private RedisTemplate<String, Object> redisTemplate;
+
+    @Override
+    public AnnounceResponseDTO handleAnnounce(AnnounceRequestDTO requestDTO) {
+        String passkey = requestDTO.getPasskey();
+        String infoHash = requestDTO.getInfoHash();
+        String peerId = requestDTO.getPeerId();
+        int port = requestDTO.getPort();
+        String ip = requestDTO.getIp();
+        double uploaded = requestDTO.getUploaded();
+        double downloaded = requestDTO.getDownloaded();
+        String event = requestDTO.getEvent();
+
+        String redisKey = "peers:" + infoHash;
+
+        if ("stopped".equalsIgnoreCase(event)) {
+            // 从 Redis 中移除 peer
+            redisTemplate.opsForSet().remove(redisKey, peerId);
+            return new AnnounceResponseDTO(interval, Collections.emptyList());
+        }
+
+        // 插入或更新 peer 信息
+        Peer existingPeer = peerMapper.getPeerByPK(peerId, infoHash, passkey);
+        if (existingPeer == null) {
+            Peer newPeer = new Peer();
+            newPeer.setPeerId(peerId);
+            newPeer.setInfo_hash(infoHash);
+            newPeer.setPasskey(passkey);
+            newPeer.setIpAddress(ip); // TODO: 从 request 获取真实 IP
+            newPeer.setPort(port);
+            newPeer.setUploaded(uploaded);
+            newPeer.setDownloaded(downloaded);
+            peerMapper.insert(newPeer);
+        } else {
+            existingPeer.setUploaded(uploaded);
+            existingPeer.setDownloaded(downloaded);
+            peerMapper.updatePeer(existingPeer.getPasskey(), existingPeer.getPeerId(), existingPeer.getInfo_hash(),
+                    existingPeer.getUploaded(), existingPeer.getDownloaded());
+        }
+
+        // 缓存 peer 到 Redis
+        redisTemplate.opsForSet().add(redisKey, peerId);
+
+        // 构造返回 peer 列表
+        List<Map<String, Object>> peerList = new ArrayList<>();
+        Set<Object> peerIds = redisTemplate.opsForSet().members(redisKey);
+        try {
+            assert peerIds != null;
+            for (Object pid : peerIds) {
+                List<Peer> peers = peerMapper.getPeerByInfoHashAndPeerId(infoHash, (String) pid);
+                for (Peer peer : peers) {
+                    if (peer != null) {
+                        Map<String, Object> peerMap = new HashMap<>();
+                        peerMap.put("ip", peer.getIpAddress());
+                        peerMap.put("port", peer.getPort());
+                        peerList.add(peerMap);
+                    }
+                }
+            }
+        } catch (Exception e) {
+            return new AnnounceResponseDTO(interval, Collections.emptyList());
+        }
+
+        return new AnnounceResponseDTO(interval, peerList);
+    }
+
 }