Преобразовать торрент информация закодированный хэш от данных в кодировке url
Я создаю торрент-скребок в objective-c и использую AFNetworking для HTTP-запросов. Мне нужно отправить sha1 хэш части мета-информации для запроса трекера. Я успешно создал хэш и проверил, что он правильный. Я не могу поместить хэш в NSString, так как он не кодирует двоичные данные, поэтому я поместил его в объект NSData, а затем в параметры для отправки. Это то, что у меня есть прямо сейчас, но я всегда получаю ошибку обратно, и я бы предположил это это с методами, которые я использую для отправки хэша. Я также попытался кодировать url-адрес хэша, а затем поместить его в строку NS безрезультатно
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, или, возможно, я надеюсь, что упускаю что-то простое.
1 ответ:
Хорошо, я не эксперт по торрентам, но я думаю, что проблема, с которой вы столкнулись, заключается в том, что представление данных bencoded, которое вы извлекаете, кодирует хэш SHA1 как 20 необработанных байт данных.
Вы не можете отправить такие необработанные данные в GET-части HTTP-запроса, поэтому вам нужно будет их закодировать. Основываясь на спецификациях, кажется, что urlencoding необработанные данные являются официальным способом сделать это. (Другими вариантами было бы преобразовать его в читаемую человеком шестнадцатеричную строку, например).
Из этой альтернативной спецификации Bittorrent :
Трекер-это служба HTTP / HTTPS, которая отвечает на запросы HTTP GET. Запросы включают метрики от клиентов, которые помогают трекеру вести общую статистику о торренте. Ответ включает в себя список одноранговых узлов, который помогает клиенту участвовать в потоке. Базовый URL-адрес состоит из "объявить URL", как определено в metainfo (.торрент-файл. Затем к этому добавляются параметры URL, используя стандартные методы CGI (то есть a '? после сообщить URL-адрес, с последующим последовательностей Параметр=Значение, разделенных символом '&').
Обратите внимание, что все двоичные данные в URL (особенно info_hash и peer_id) должны быть правильно экранированы. Это означает любой байт, не входящий в набор 0-9, a-z, A-Z,'.', '- ', '_' и'~', должны быть закодированы с использованием формата "%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
Начиная с вашего массива raw 20 char C, вам нужно добраться до URLEncoded
NSString
.К сожалению, особенно с этим типом данных, простой метод - использование
stringByAddingPercentEscapesUsingEncoding
в цикле - не будет работать, потому что он не заканчивается безопасной кодировкой для отправки в качестве параметра GET.С помощью бита S. O. help (How do I URL encode a string ), вот немного кода, который вы можете сформировать в конечный продукт, но соответствует спецификации doc для правильный вывод:
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
Удачи!