Otium
Otium

Reputation: 1098

Sending packets over UDP to torrent trackers in Objective-C with CocoaAsyncSocket

I am attempting to create a torrent scraper in objective-c, I am using CocoaAsyncSocket to send the data packets over UDP. Following the BitTorrent UDP Tracker Protocol. I have verified using Wireshark that packets have been sent, but the tracker does not send anything back. I am assuming I am doing something wrong in putting together the data that is sent, since I have very little experience with data manipulation. Right now I am just trying to successfully complete the connect request of the protocol. Here is the code

-(void)connect {

     NSString *host = @"tracker.publicbt.com";
     GCDAsyncUdpSocket *socket = [[GCDAsyncUdpSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
     [socket connectToHost:host onPort:80 error:nil];


}

-(void)udpSocket:(GCDAsyncUdpSocket *)sock didConnectToAddress:(NSData *)address {
    uint64_t connection_id = htonl(0x41727101980);
    uint32_t action = htonl(0);
    uint32_t transaction_id = htonl(122);
    NSMutableData *data = [NSMutableData data];
    [data appendBytes:&connection_id length:sizeof(connection_id)];
    [data appendBytes:&action length:sizeof(action)];
    [data appendBytes:&transaction_id length:sizeof(transaction_id)];
    [sock sendData:data toAddress:address withTimeout:-1 tag:1];

}

Upvotes: 0

Views: 534

Answers (2)

mamackenzie
mamackenzie

Reputation: 1166

Now I think I know the problem.

Since the connection ID must be initialized to that exact value, you need to make sure that it is intact. You are making a mistake in that htonl() returns a uint32_t, which is not going to be what you want. You need to break the connection id into 2 parts and independently convert them to network byte order.

uint64_t wholeConnectionID = 0x41727101980LLU;

uint32_t connectionID[2];
connectionID[0] = htonl(wholeConnectionID >> 32);
connectionID[1] = htonl(wholeConnectionID & 0xffffffff);

// ...

[data appendBytes:connectionID length:sizeof(connectionID)];

If this doesn't solve your problem, it will at least be a required step to get to that point anyways.

Upvotes: 1

mamackenzie
mamackenzie

Reputation: 1166

I think you need to call a method to actually get the socket to start receiving:

- (BOOL)beginReceiving:(NSError **)errPtr;

This will ensure that the delegate method is invoked every time a packet comes in.

Upvotes: 1

Related Questions