6

我正在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 做到这一点,或者我希望错过一些简单的东西。

4

1 回答 1

5

好吧,我不是种子专家,但我认为您面临的挑战是您从中提取的编码数据表示将SHA1哈希编码为 20 个原始字节的数据。

您不能在 HTTP 请求的 GET 部分中发送这样的原始数据,因此您需要对其进行编码。根据规范,似乎对原始数据进行urlencoding是这样做的官方方式。(例如,其他选项是将其转换为人类可读的十六进制字符串)。

从此替代 Bittorrent 规范

跟踪器是响应 HTTP GET 请求的 HTTP/HTTPS 服务。这些请求包括来自客户端的指标,这些指标可帮助跟踪器保留有关种子的整体统计信息。响应包括一个对等列表,可帮助客户端参与 torrent。基本 URL 由元信息 (.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 参数发送。

借助一些 SO 帮助(我如何对字符串进行 URL 编码),这里有一些代码可以塑造成最终产品,但符合规范文档以获得正确的输出:

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

祝你好运!

于 2012-08-12T05:56:13.487 回答