| 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()); |
| |
| } |
| } |
| |