blob: dcbee69c963c5eabe4bb03692548a39828cf036d [file] [log] [blame]
package com.pt.service;
import com.pt.entity.TorrentMeta;
import com.pt.repository.TorrentMetaRepository;
import com.pt.utils.BencodeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.*;
import java.security.MessageDigest;
import java.time.LocalDateTime;
import java.util.LinkedHashMap;
import java.util.Map;
@Service
public class TorrentService {
// Tracker 服务器的 announce 地址
private static final String ANNOUNCE_URL = "http://localhost:8080/announce";
private static final int PIECE_LENGTH = 256 * 1024;
@Autowired
private TorrentMetaRepository torrentMetaRepository;
public byte[] generateTorrentBytes(String sourceFilePath) throws Exception {
File sourceFile = new File(sourceFilePath);
// 构造 info 字典
Map<String, Object> infoDict = new LinkedHashMap<>();
infoDict.put("name", sourceFile.getName());
infoDict.put("length", sourceFile.length());
infoDict.put("piece length", PIECE_LENGTH);
infoDict.put("pieces", calcPiecesHashes(sourceFile));
// 构造完整 torrent 字典
Map<String, Object> torrentDict = new LinkedHashMap<>();
torrentDict.put("announce", ANNOUNCE_URL);
torrentDict.put("info", infoDict);
// 编码成种子数据字节数组
byte[] bencodedTorrent = BencodeUtils.encode(torrentDict);
// 计算 info_hash 并保存到数据库(如果需要的话)
MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
byte[] infoEncoded = BencodeUtils.encode(infoDict);
sha1.update(infoEncoded);
String infoHash = bytesToHex(sha1.digest());
TorrentMeta meta = new TorrentMeta();
meta.setFilename(sourceFile.getName());
meta.setInfoHash(infoHash);
meta.setSize(sourceFile.length());
meta.setUploadTime(LocalDateTime.now());
torrentMetaRepository.save(meta);
return bencodedTorrent;
}
private byte[] calcPiecesHashes(File file) throws Exception {
MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
try (InputStream fis = new FileInputStream(file)) {
byte[] buffer = new byte[PIECE_LENGTH];
ByteArrayOutputStream piecesBuffer = new ByteArrayOutputStream();
int read;
while ((read = fis.read(buffer)) > 0) {
sha1.reset();
sha1.update(buffer, 0, read);
piecesBuffer.write(sha1.digest());
}
return piecesBuffer.toByteArray();
}
}
private String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
}