Convertir Torrent info_hash desde bencoded a URLEncoded data

Estoy creando un raspador torrent en el objective c y estoy usando AFNetworking para las requestes HTTP. Necesito enviar un hash sha1 de la parte de metainformación para una request de rastreador. He creado con éxito el hash y he verificado que es correcto. No puedo poner el hash en un NSString, ya que no codifica los datos binarys, así que lo puse en un object NSData y luego en los parameters para enviar. Esto es lo que tengo ahora, pero siempre obtengo un error, y supongo que es con los methods que estoy usando para enviar el hash. También probé url que codifica el hash y luego lo pongo en un NSString sin ningún provecho

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); }]; 

¿Alguien sabe si hay una manera posible de hacerlo con AFNetworking o tal vez estoy perdiendo algo simple.

Bien, no soy un experto en torrents, pero creo que el desafío que tienes es que la representación de datos codificados que estás obteniendo codifica el hash SHA1 como 20 bytes de datos sin procesar.

No puede enviar datos brutos como ese en la parte GET de una request HTTP, por lo que necesitará codificarla. Sobre la base de las especificaciones, parece que urlencoding los datos sin procesar es la forma oficial de hacerlo. (Otras opciones serían convertirlo a una cadena hexadecimal legible por humanos, por ejemplo).

De esta especificación alternativa de Bittorrent :

El rastreador es un service HTTP / HTTPS que responde a requestes HTTP GET. Las requestes incluyen métricas de clientes que ayudan al rastreador a mantener statistics generales sobre el torrente. La respuesta incluye una list de pares que ayuda al cliente a participar en el torrent. La URL base consiste en la "URL de anuncio" tal como se define en el file metainfo (.torrent). Luego, los parameters se agregan a esta URL, utilizando methods CGI estándar (es decir, un '?' Después de la URL anunciada, seguido de secuencias 'param = valor' separadas por '&').

Tenga en count que todos los datos binarys en la URL (en particular, info_hash y peer_id) deben escapingse correctamente. Esto significa que cualquier byte que no esté en el set 0-9, az, AZ, '.', '-', '_' y '~', debe codificarse utilizando el formatting "% nn", donde nn es el valor hexadecimal de el byte (Ver RFC1738 para más detalles).

Para un hash de 20 bytes de \x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a

La forma codificada derecha es %124Vx%9A%BC%DE%F1%23Eg%89%AB%CD%EF%124Vx%9A

Comenzando con su matriz de 20 char C, necesitará llegar a un NSString NSString .

Lamentablemente, especialmente con este tipo de datos, el método simple, que usa stringByAddingPercentEscapesUsingEncoding en un bucle, no funcionará porque no termina con una encoding segura para enviar como un parámetro GET.

Con un poco de ayuda de SO ( ¿Cómo puedo codificar una secuencia de URL? ), Aquí hay un poco de código que puede moldear en el producto final, pero cumple con el doc de especificaciones para la salida correcta:

 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); 

La salida es:

 Raw Data: <12345678 9abcdef1 23456789 abcdef12 3456789a> Encoded: %124Vx%9A%BC%DE%F1%23Eg%89%AB%CD%EF%124Vx%9A 

¡Buena suerte!