我在objective-c中创建了torrent scraper,我正在使用AFNetworking来处理HTTP请求。我需要发送跟踪器请求的元信息部分的sha1哈希值。我已成功创建哈希并验证它是否正确。我不能将哈希值放在NSString中,因为它不对二进制数据进行编码,因此我将其放在NSData对象中,然后在要发送的参数中。这就是我现在所拥有的,但我总是得到一个错误,我会假设它是使用我用来发送哈希的方法。我也尝试过对url进行编码,然后将其放入NSString中,但无效
NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
unsigned char infoHash[20];
[self.tracker generateTorrentInfoHash:infoHash];
const char peer_id[20] = "randomstringfornow";
[parameters setObject:[NSData dataWithBytes:&infoHash length:20] forKey:@"info_hash"];
[parameters setObject:[NSData dataWithBytes:&peer_id length:20] forKey:@"peer_id"];
[parameters setObject:@(8080) forKey:@"port"];
[parameters setObject:@(0) forKey:@"uploaded"];
[parameters setObject:@(self.tracker.metaInfo.totalFileSize) forKey:@"left"];
[parameters setObject:@(0) forKey:@"downloaded"];
[parameters setObject:@(0) forKey:@"compact"];
[parameters setObject:@"stopped" forKey:@"event"];
[self getPath:@"" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"%@",operation.responseString);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"%@",operation.responseString);
}];
有没有人知道AFNetworking是否有可能做到这一点,或者我希望错过一些简单的事情。
答案 0 :(得分:4)
好吧,我不是种子专家,但我认为你所遇到的挑战是你所提取的 bencoded 数据表示将SHA1哈希编码为20个原始字节数据
您无法在HTTP请求的GET部分中发送类似的原始数据,因此您需要对其进行编码。根据规范,似乎 urlencoding 原始数据是官方的方式。 (其他选项是将其转换为人类可读的十六进制字符串,例如)。
从此Alternative Bittorrent Specification:
跟踪器是HTTP / HTTPS服务,它响应HTTP GET请求。请求包括来自客户端的指标,这些指标可帮助跟踪器保留有关torrent的整体统计信息。响应包括帮助客户端参与torrent的对等列表。基本URL由metainfo(.torrent)文件中定义的“通告URL”组成。然后使用标准CGI方法将参数添加到此URL(即在声明URL之后为'?',后跟由'&'分隔的'param = value'序列)。
请注意,必须正确转义URL中的所有二进制数据(特别是info_hash和peer_id)。这意味着任何不在集合0-9,az,AZ,'。',' - ','_'和'〜'中的字节必须使用“%nn”格式进行编码,其中nn是十六进制值字节。 (有关详细信息,请参阅RFC1738。)
对于
的20字节哈希\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a
正确的编码形式为
%124Vx%9A%BC%DE%F1%23Eg%89%AB%CD%EF%124Vx%9A
从原始的20 char C数组开始,您需要访问 URLEncoded NSString
。
不幸的是,特别是对于这种类型的数据,简单的方法 - 在循环中使用stringByAddingPercentEscapesUsingEncoding
将无法工作,因为它不会以安全编码结束作为GET参数发送。
有一点S.O. help(How do I URL encode a string),这里有一些代码,你可以在最终产品中使用,但符合规范文档以获得正确的输出:
const char source[20] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf1, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x9a};
NSMutableString *output = [NSMutableString string];
NSLog(@"Raw Data: %@", [NSData dataWithBytes:source length:20]);
int sourceLen = sizeof(source);
for (int i = 0; i < sourceLen; ++i) {
const unsigned char thisChar = source[i];
if (thisChar == ' '){
[output appendString:@"+"];
} else if (thisChar == '.' || thisChar == '-' || thisChar == '_' || thisChar == '~' ||
(thisChar >= 'a' && thisChar <= 'z') ||
(thisChar >= 'A' && thisChar <= 'Z') ||
(thisChar >= '0' && thisChar <= '9')) {
[output appendFormat:@"%c", thisChar];
} else {
[output appendFormat:@"%%%02X", thisChar];
}
}
NSLog(@"Encoded: %@", output);
输出是:
Raw Data: <12345678 9abcdef1 23456789 abcdef12 3456789a>
Encoded: %124Vx%9A%BC%DE%F1%23Eg%89%AB%CD%EF%124Vx%9A
祝你好运!