blob: b66984300937b72eff2d3af4dbeb9951ba294478 [file] [log] [blame]
package com.example.g8backend.util;
import com.example.g8backend.dto.AnnounceResponseDTO;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.*;
//package com.bjtu.pt_station.common;
import com.example.g8backend.entity.Peer;
import com.dampcake.bencode.Bencode;
import com.dampcake.bencode.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.multipart.MultipartFile;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.*;
import java.util.List;
import java.util.Map;
public class BencodeUtil {
private static final Logger logger = LoggerFactory.getLogger(BencodeUtil.class);
private static final Bencode bencodeUTF8 = new Bencode(StandardCharsets.UTF_8);
private static final Bencode bencodeInfoHash = new Bencode(StandardCharsets.ISO_8859_1);
public static String encodeUTF8(Map<String, Object> map) {
byte[] encodedBytes = bencodeUTF8.encode(map);
return new String(encodedBytes, StandardCharsets.UTF_8);
}
public static String encodeISO(Map<String, Object> map) {
byte[] encodedBytes = bencodeInfoHash.encode(map);
return new String(encodedBytes, StandardCharsets.ISO_8859_1);
}
public static Map<String, Object> decodeHash(byte[] torrentBytes) throws IOException {
return bencodeInfoHash.decode(torrentBytes, Type.DICTIONARY);
}
public static Map<String, Object> decodeUTF8(byte[] torrentBytes) throws IOException {
return bencodeUTF8.decode(torrentBytes, Type.DICTIONARY);
}
public static Map<String, Object> decodeISO(byte[] torrentBytes) throws IOException {
return bencodeInfoHash.decode(torrentBytes, Type.DICTIONARY);
}
public static String calInfoHash(MultipartFile torrentFile) throws IOException {
byte[] torrentBytes = torrentFile.getBytes();
try {
Map<String, Object> dict = decodeUTF8(torrentBytes);
Map<String, Object> dictInfoHash = decodeISO(torrentBytes);
Object infoObj = dictInfoHash.get("info");
if (infoObj == null) {
logger.error("Torrent file does not contain 'info' field.");
return null;
}
byte[] infoData = bencodeInfoHash.encode((Map<?, ?>) infoObj);
return calculateInfoHash(infoData);
} catch (IOException e) {
logger.error("Failed to calculate info hash: {}", e.getMessage());
throw e;
}
}
private static String calculateInfoHash(byte[] bencodedInfo) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-1");
byte[] hashBytes = digest.digest(bencodedInfo);
StringBuilder hexString = new StringBuilder();
for (byte b : hashBytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("SHA-1 algorithm not available", e);
}
}
public static String convertToString(byte[] bytes) {
return new String(bytes, bencodeInfoHash.getCharset());
}
public static Bencode bittorrent() {
return bencodeInfoHash;
}
public static Bencode utf8() {
return bencodeUTF8;
}
public static String compactPeers(List<Peer> peers) throws UnknownHostException {
ByteBuffer buffer = ByteBuffer.allocate(6 * peers.size());
for (Peer peer : peers) {
for (byte addr : InetAddress.getByName(peer.getIpAddress()).getAddress()) {
buffer.put(addr);
}
int in = peer.getPort();
buffer.put((byte) ((in >>> 8) & 0xFF));
buffer.put((byte) (in & 0xFF));
}
return convertToString(buffer.array());
}
}
//public class BencodeUtil {
// public static byte[] encodeAnnounceResponse(AnnounceResponseDTO dto) {
// ByteArrayOutputStream out = new ByteArrayOutputStream();
// try {
// out.write('d'); // dictionary start
//
// writeString(out, "interval");
// writeInt(out, dto.getInterval());
//
// writeString(out, "peers");
// out.write('l'); // list start
// for (Map<String, Object> peer : dto.getPeers()) {
// out.write('d');
// writeString(out, "ip");
// writeString(out, (String) peer.get("ip"));
// writeString(out, "port");
// writeInt(out, ((Number) peer.get("port")).intValue());
// out.write('e');
// }
// out.write('e'); // list end
//
// out.write('e'); // dictionary end
// } catch (Exception e) {
// throw new RuntimeException("Bencoding failed", e);
// }
// return out.toByteArray();
// }
//
// private static void writeString(ByteArrayOutputStream out, String str) throws Exception {
// byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
// out.write(String.valueOf(bytes.length).getBytes(StandardCharsets.UTF_8));
// out.write(':');
// out.write(bytes);
// }
//
// private static void writeInt(ByteArrayOutputStream out, int i) throws Exception {
// out.write('i');
// out.write(String.valueOf(i).getBytes(StandardCharsets.UTF_8));
// out.write('e');
// }
//}