protocol buffers - protocol - decodificador en bruto para el formato de protobufs
protocol buffers download (4)
Como se señaló en la respuesta de Michel de Ruiter , es posible que su mensaje protobuf tenga un length-prefix . Suponiendo que sí, esta respuesta debería ayudar.
(NOTA: Para la mayoría de los comandos a continuación, asumo que su mensaje protobuf está almacenado en un archivo llamado input
).
protoc --decode_raw
+ dd
para un solo mensaje:
Si se trata simplemente de un solo mensaje, entonces de hecho puede aprovechar protoc --decode_raw
, pero protoc --decode_raw
debe eliminar el encabezado de prefijo de longitud. Suponiendo que el encabezado tenga 4 bytes de longitud, puede usar dd
para quitar el encabezado de la input
y luego input
la salida en protoc
.
dd bs=1 skip=4 if=input 2>/dev/null | protoc --decode_raw
protoc-decode-lenprefix --decode_raw
para un solo mensaje:
También escribí un script que maneja la eliminación de encabezados automáticamente:
protoc-decode-lenprefix --decode_raw < input
Esta secuencia de comandos es simplemente una envoltura encima de protoc --decode_raw
, pero maneja el análisis del encabezado de prefijo de longitud y luego invoca protoc
.
Ahora, este script no es muy útil en este caso, porque podemos usar el truco de dd
anterior para quitar el encabezado. Sin embargo, supongamos que tenemos un flujo de datos (por ejemplo, un archivo o un flujo de TCP) que contiene varios mensajes que están enmarcados con encabezados de longitud prefijo ...
protoc-decode-lenprefix --decode_raw
para un flujo de mensajes:
En lugar de un solo mensaje de protobuf en el archivo de entrada, digamos que la input
contenía múltiples mensajes de protobuf que están enmarcados por encabezados de prefijo de longitud. En este caso, no es posible usar el truco de dd
, ya que realmente necesita leer el contenido del encabezado de longitud-prefijo para determinar cuánto tiempo será el mensaje subsiguiente en la secuencia y, por lo tanto, cuántos bytes habrá antes del siguiente encabezado + mensaje. mentiras. Entonces, en lugar de preocuparse por todo eso, simplemente puede usar protoc-decode-lenprefix
nuevo:
protoc-decode-lenprefix --decode_raw < input
protoc-decode-lenprefix --decode ... foo.proto
para un flujo de mensajes
Esta secuencia de comandos también se puede usar para descodificar completamente los mensajes con prefijo de longitud (en lugar de simplemente "descodificarlos"). Se supone que tiene acceso a los archivos .proto
que definen el mensaje protobuf, al igual que el comando envuelto protoc
. La sintaxis de invocación es idéntica a protoc --decode
. Por ejemplo, al usar el truco de dd
con protoc --decode
, junto con la entrada como un archivo task.info Mesos , la sintaxis se ve así:
dd bs=1 skip=4 if=task.info 2>/dev/null | /
protoc --decode mesos.internal.Task /
-I MESOS_CODE/src -I MESOS_CODE/include /
MESOS_CODE/src/messages/messages.proto
Y los parámetros son idénticos cuando se utiliza protoc-decode-lenprefix
cat task.info | /
protoc-decode-lenprefix --decode mesos.internal.Task /
-I MESOS_CODE/src -I MESOS_CODE/include /
MESOS_CODE/src/messages/messages.proto
Me gustaría encontrar una manera de convertir un mensaje binario protobuf en una descripción legible por humanos de los datos contenidos, sin usar los archivos .proto.
El fondo es que tengo un mensaje .proto de que el analizador lo rechazó en Android, pero no está del todo claro por qué. Podría pasar el mensaje a mano, pero es bastante tedioso.
Intenté protoc --decode_raw
, pero solo da el error "Error al analizar la entrada". Busco en Google con la esperanza / esperando que alguien hubiera hecho una buena utilidad web que podría hacer esto, pero no ha encontrado nada obvio.
Solo espero obtener una salida como:
field 1: varint: 128
field 4: string: "foo"
Cualquier puntero en la dirección correcta sería bienvenido!
Para la posteridad: las tools búfer de protocolo de Google tienen la capacidad de decodificar buffers en bruto.
Simplemente envíele el búfer desconocido y pase el indicador --decode_raw
$ cat has_no_proto.buff | protoc --decode_raw
2 {
2: "Error retrieving information from server. [RH-02]"
}
Así que aquí hay un mensaje con el campo 2 configurado para un mensaje incrustado que, a su vez, tiene su segundo campo configurado con una cadena que me dice que hice enojar a Google Play.
La información de tipo no es definitiva (parece que intentará mostrar todos los datos binarios como cadenas, pero se cumple su requisito de distinción varint / string / submessage).
Podría intentar forzarlo a través del plugin wireshark, o probablemente podría tomar prestada la parte "lector" de algunas de las implementaciones (sé cómo haría esto en C #, por ejemplo, pero dudo que eso sea lo que quiso decir).
Sin embargo, tenga cuidado: la cadena en los búferes de protocolo no significa realmente "cadena", podría ser:
- una cadena UTF-8
- un BLOB en bruto de datos arbitrarios
- un mensaje secundario
- una matriz "empaquetada"
- (probablemente algo mas lo estoy olvidando)
Si tiene un archivo binario que contiene (¿múltiples?) Mensajes de protobuf con prefijo de longitud, protoc ‒‒decode_raw < file
no puede analizarlo debido a los prefijos de longitud. Una forma simple de protoc
es dividir el archivo en sus mensajes consecutivos y luego convertir cada uno con protoc
.
Mi toma:
var fs = File.OpenRead(filename));
var buffer = new byte[4096];
int size;
for (int part = 1; Serializer.TryReadLengthPrefix(fs, PrefixStyle.Base128, out size); part++) {
long startPosition = fs.Position;
using (var writer = File.OpenWrite(string.Format("{0}[{1}].pb", filename, part))) {
for (int bytesToRead = size; bytesToRead > 0; ) {
int bytesRead = fs.Read(buffer, 0, Math.Min(bytesToRead, buffer.Length));
bytesToRead -= bytesRead;
if (bytesRead <= 0) // End of file.
break;
writer.Write(buffer, 0, bytesRead);
}
}
}