user冲突, pt/bt交互(待完善版)

Change-Id: I7530921962ac82ad1a896ae3c120416256f787e0
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 4620775..a7cb21b 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -5,9 +5,14 @@
   </component>
   <component name="ChangeListManager">
     <list default="true" id="f008fe30-0711-42e2-bb33-17dcfdbad387" name="Changes" comment="pom">
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/example/myproject/controller/TrackerController.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/example/myproject/dto/param/AnnounceRequest.java" afterDir="false" />
       <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/src/main/java/com/example/myproject/config/WebConfig.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/example/myproject/config/WebConfig.java" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/src/main/java/com/example/myproject/controller/TorrentController.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/example/myproject/controller/TorrentController.java" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/src/main/java/com/example/myproject/mapper/UserMapper.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/example/myproject/mapper/UserMapper.java" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/src/main/java/com/example/myproject/service/serviceImpl/TorrentServiceImpl.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/example/myproject/service/serviceImpl/TorrentServiceImpl.java" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/mapper/UserMapper.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/mapper/UserMapper.class" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/service/serviceImpl/TorrentServiceImpl.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/service/serviceImpl/TorrentServiceImpl.class" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/uploads/torrents/1749131044219.jpg" beforeDir="false" />
     </list>
     <option name="SHOW_DIALOG" value="false" />
     <option name="HIGHLIGHT_CONFLICTS" value="true" />
diff --git a/src/main/java/com/example/myproject/controller/TrackerController.java b/src/main/java/com/example/myproject/controller/TrackerController.java
new file mode 100644
index 0000000..204b3b9
--- /dev/null
+++ b/src/main/java/com/example/myproject/controller/TrackerController.java
@@ -0,0 +1,87 @@
+package com.example.myproject.controller;
+
+import cn.hutool.core.util.HexUtil;
+
+import com.example.myproject.dto.param.AnnounceRequest;
+//import com.example.myproject.service.AnnounceService;
+//import com.example.myproject.utils.BinaryFieldUtil;
+import com.turn.ttorrent.bcodec.BEncoder;
+//import com.example.myproject.utils.IPUtils;
+
+
+
+
+import javax.servlet.http.HttpServletRequest;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.client.RestTemplate;
+
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+@Slf4j
+@RestController
+@RequiredArgsConstructor
+public class TrackerController {
+
+//    private final AnnounceService announceService;
+
+    private final RestTemplate restTemplate = new RestTemplate();
+
+    @GetMapping("/announce")
+    public ResponseEntity<byte[]> announce(HttpServletRequest request,
+                                           @ModelAttribute AnnounceRequest announceRequest,
+                                           @RequestHeader(name = "User-Agent") String ua,
+                                           @RequestHeader(name = "want-digest", required = false) String wantDigest) {
+
+        // 1. 获取请求参数原始字符串(方便解析peerId、infoHash等)
+        String queryStrings = request.getQueryString();
+        log.info("收到announce汇报:" + queryStrings);
+        //收到announce汇报:passkey=1&info_hash=%c8%8e%8ak8%09%97%1b%ab4%3a%a2%c3%bf%c3%22%05%f2j%d1&peer_id=-qB453A-9nl.HBf73dry&port=62128&uploaded=0&downloaded=0&left=1711543&corrupt=0&key=A0B2541D&event=started&numwant=200&compact=1&no_peer_id=1&supportcrypto=1&redundant=0
+        //
+        // 2. 获取客户端IP
+        // 3. 提取peerId和infoHash(二进制字段)
+//        byte[] peerId = BinaryFieldUtil.matchPeerId(queryStrings);
+//        String peerIdHex = HexUtil.encodeHexStr(peerId);
+//        byte[] infoHash = BinaryFieldUtil.matchInfoHash(queryStrings);
+
+//        log.info("peerid:" + peerId);
+//        log.info("infohash" + infoHash);
+
+//        String ipAddr = IPUtils.getIpAddr();
+//
+//
+//
+//        // 4. 设置AnnounceRequest其他字段
+//        announceRequest.setSeeder(announceRequest.getLeft() != null && announceRequest.getLeft().equals(0L));
+//        announceRequest.setInfoHash(infoHash);
+//        announceRequest.setPeerId(peerId);
+//        announceRequest.setPeerIdHex(peerIdHex);
+//        announceRequest.setRemoteAddr(ipAddr);
+//        announceRequest.setWantDigest(wantDigest);
+//        announceRequest.setUserAgent(ua);
+
+//        // 5. 先调用业务层处理,比如记录用户状态
+//        announceService.announce(announceRequest);
+
+        // 6. 转发请求到真正tracker(6969端口)
+
+        // 构造转发URL
+        String trackerUrl = "http://localhost:6969/announce" + (queryStrings != null ? "?" + queryStrings : "");
+
+        // 使用RestTemplate发起GET请求,直接获取二进制响应(bencode)
+        ResponseEntity<byte[]> trackerResponse = restTemplate.getForEntity(trackerUrl, byte[].class);
+
+        // 7. 直接将tracker返回的二进制数据,作为响应返回给客户端
+        return ResponseEntity.ok()
+                .header("Content-Type", "text/plain") // bencode通常用text/plain,或者 application/x-bittorrent
+                .body(trackerResponse.getBody());
+
+    }
+}
+
diff --git a/src/main/java/com/example/myproject/dto/param/AnnounceRequest.java b/src/main/java/com/example/myproject/dto/param/AnnounceRequest.java
new file mode 100644
index 0000000..8f9b068
--- /dev/null
+++ b/src/main/java/com/example/myproject/dto/param/AnnounceRequest.java
@@ -0,0 +1,120 @@
+package com.example.myproject.dto.param;
+
+import com.example.myproject.entity.TorrentEntity;
+import com.example.myproject.entity.User;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+
+
+@Data
+@Slf4j
+public class AnnounceRequest {
+    //来自客户端的请求如下
+    // qBittorrent v4.5.5
+    //{
+    //  "passkey": "xxxxxxxx",
+    //  "info_hash": "%5d%df%19%a2%85%03",
+    //  "peer_id": "-qB4550-NJ4pxxxkx)za",
+    //  "port": 14042,
+    //  "uploaded": 0,
+    //  "downloaded": 0,
+    //  "left": 135621375,
+    //  "corrupt": 0,
+    //  "key": "B99DE91E",
+    //  "event": "started",
+    //  "numwant": 200,
+    //  "compact": 1,
+    //  "no_peer_id": 1,
+    //  "supportcrypto": 1,
+    //  "redundant": 0,
+    //  "ipv6": [
+    //    "1111:222",
+    //    "1111:333"
+    //  ]
+    //}
+
+
+    private String passkey;
+
+
+    private byte[] infoHash;
+
+
+    private String peer_id;
+    private byte[] peerId;
+
+
+    private String peerIdHex;
+
+    private String event = "";
+
+
+    private String ipv6;
+
+
+    private String ipv4;
+
+
+    private String ip;
+
+
+    private String key;
+
+
+    private Integer port;
+
+
+    private Integer numwant = 200;
+
+
+    private Long downloaded = -1L;
+
+
+    private Long uploaded = -1L;
+
+    private Long left = -1L;
+
+
+    private Long redundant = 0L;
+
+
+    private Integer compact;
+
+
+    private Integer no_peer_id;
+
+
+    private Boolean seeder;
+
+
+    private String remoteAddr;
+
+
+    private String userAgent;
+
+
+    private String wantDigest;
+
+    private User user;
+
+
+    private TorrentEntity torrent;
+
+
+    public boolean isNoPeerId() {
+        boolean noPeerId = Integer.valueOf(1).equals(getNo_peer_id());
+
+        return noPeerId;
+    }
+
+    public interface EventType {
+        // started, completed, stopped (或为空,这与未指定相同).
+        //
+        String started = "started";
+        String completed = "completed";
+        String stopped = "stopped";
+        String paused = "paused";
+        String empty = "";
+    }
+
+}
diff --git a/src/main/java/com/example/myproject/mapper/UserMapper.java b/src/main/java/com/example/myproject/mapper/UserMapper.java
index 3a29b64..1752801 100644
--- a/src/main/java/com/example/myproject/mapper/UserMapper.java
+++ b/src/main/java/com/example/myproject/mapper/UserMapper.java
@@ -28,4 +28,8 @@
     
     boolean hasRole(@Param("userId") Long userId, @Param("role") String role);
 
+    @Select("SELECT * FROM user WHERE user_id = #{userId}")
+    User selectByUserId(@Param("userId") Long userId);
+
+
 }
\ No newline at end of file
diff --git a/src/main/java/com/example/myproject/service/serviceImpl/TorrentServiceImpl.java b/src/main/java/com/example/myproject/service/serviceImpl/TorrentServiceImpl.java
index 884c65d..cb26f7a 100644
--- a/src/main/java/com/example/myproject/service/serviceImpl/TorrentServiceImpl.java
+++ b/src/main/java/com/example/myproject/service/serviceImpl/TorrentServiceImpl.java
@@ -76,7 +76,7 @@
     @Transactional
     public void uploadTorrent(MultipartFile file, TorrentUploadParam param) throws IOException {
         // 验证用户权限
-        User user = userMapper.selectById(param.getUploader());
+        User user = userMapper.selectByUserId(Long.valueOf(param.getUploader()));
         if (user == null) {
             throw new RuntimeException("用户不存在");
         }
diff --git a/target/classes/com/example/myproject/controller/TrackerController.class b/target/classes/com/example/myproject/controller/TrackerController.class
new file mode 100644
index 0000000..d1690b5
--- /dev/null
+++ b/target/classes/com/example/myproject/controller/TrackerController.class
Binary files differ
diff --git a/target/classes/com/example/myproject/dto/param/AnnounceRequest$EventType.class b/target/classes/com/example/myproject/dto/param/AnnounceRequest$EventType.class
new file mode 100644
index 0000000..9b32450
--- /dev/null
+++ b/target/classes/com/example/myproject/dto/param/AnnounceRequest$EventType.class
Binary files differ
diff --git a/target/classes/com/example/myproject/dto/param/AnnounceRequest.class b/target/classes/com/example/myproject/dto/param/AnnounceRequest.class
new file mode 100644
index 0000000..392e715
--- /dev/null
+++ b/target/classes/com/example/myproject/dto/param/AnnounceRequest.class
Binary files differ
diff --git a/target/classes/com/example/myproject/mapper/UserMapper.class b/target/classes/com/example/myproject/mapper/UserMapper.class
index 10a9ec1..74cbed4 100644
--- a/target/classes/com/example/myproject/mapper/UserMapper.class
+++ b/target/classes/com/example/myproject/mapper/UserMapper.class
Binary files differ
diff --git a/target/classes/com/example/myproject/service/serviceImpl/TorrentServiceImpl.class b/target/classes/com/example/myproject/service/serviceImpl/TorrentServiceImpl.class
index dc9600d..fecb0b7 100644
--- a/target/classes/com/example/myproject/service/serviceImpl/TorrentServiceImpl.class
+++ b/target/classes/com/example/myproject/service/serviceImpl/TorrentServiceImpl.class
Binary files differ
diff --git a/uploads/torrents/1749131044219.jpg b/uploads/torrents/1749131044219.jpg
deleted file mode 100644
index 4ba04de..0000000
--- a/uploads/torrents/1749131044219.jpg
+++ /dev/null
Binary files differ