Im implementing an app for downloading torrent from .torrent files as a study project for CLI tools and native applications using GraalVM. Im having problems when trying to create a connection with a UDP tracker. Im able to send the connection request but the receive request is ranging forever. I researched everywhere but i couldn’t find why it’s not working. This is the java class responsible for connecting to the UDP tracker:
package org.jtorr.service.impl;
import com.dampcake.bencode.Bencode;
import org.jtorr.component.generator.TransactionIdGenerator;
import org.jtorr.exception.TrackerServiceException;
import org.jtorr.model.bencode.BencodeData;
import org.jtorr.model.bencode.TrackerResponse;
import org.jtorr.model.tracker.TrackerUDPConnect;
import org.jtorr.service.TrackerService;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
public class UdpTrackerServiceImpl implements TrackerService {
private static final int DEFAULT_PORT = 6969;
private final DatagramSocket datagramSocket;
private final TransactionIdGenerator transactionIdGenerator;
private final Bencode bencode;
public UdpTrackerServiceImpl() {
try {
datagramSocket = new DatagramSocket(DEFAULT_PORT);
transactionIdGenerator = new TransactionIdGenerator();
bencode = new Bencode();
} catch (SocketException e) {
throw new TrackerServiceException("Error instantiating service: " + e.getMessage(), e);
}
}
@Override
public TrackerResponse getPeersInfoFromTracker(BencodeData bencodeData, String peerId, String infoHash) {
var uri = announceToURI(bencodeData.announce());
createConnectionRequest(uri);
return null;
}
private URI announceToURI(String announce) {
try {
return new URI(announce);
} catch (URISyntaxException e) {
throw new TrackerServiceException("Error creating URI from announce: " + e.getMessage(), e);
}
}
private void createConnectionRequest(URI uri) {
try {
var transactionId = transactionIdGenerator.generate();
var buff = TrackerUDPConnect.builder()
.transactionId(transactionId)
.build()
.getBytes();
var address = InetAddress.getByName(uri.getHost());
var packet = new DatagramPacket(buff, buff.length, address, uri.getPort());
datagramSocket.send(packet);
packet = new DatagramPacket(buff, buff.length);
datagramSocket.receive(packet);
var response = new String(packet.getData(), 0, packet.getLength());
System.out.println(response);
} catch (UnknownHostException e) {
throw new TrackerServiceException("Error connecting to host: " + e.getMessage(), e);
} catch (IOException e) {
throw new TrackerServiceException("Error creating connection with tracker: " + e.getMessage(), e);
}
}
}
I’ve thought that maybe ubuntu was blocking the UDP connection somehow. I’ve tried freeing up the port by doing the following: sudo ufw allow 38438/udp.
But that had no effect in the problem.
I`ve checked to see if it was a firewall problem but firewall is disabled in ubuntu.
To use a UDP tracker you must do the following: Connect, Announce. Scrape is used for getting data on multiple sample hashes.
I recommend that you use the same UDP socket for all UDP trackers as it would save bandwidth and ports, typical with other programs like Transmission.
Note that if you fail to send what I have shown the tracker will likely never respond... Really annoying for debugging...
As of BEP-15 specifications the connection request should look like this - every number is Big Endian.
Example of possible actions
Java Impl
And you should receive something like this
Java Impl
Now for the announce, now that you have the connection ID.
Announce request as of BEP-15
Java Impl
And finally for the Announce response.
Java Impl
For more details take a look at my project: https://github.com/DrBrad/JTorrent