timostamm / protobuf-ts

Protobuf and RPC for TypeScript
Apache License 2.0
1.09k stars 130 forks source link

Error decoding from binary: "cant skip wire type 4" #625

Closed pmosconi closed 8 months ago

pmosconi commented 9 months ago

Hi, I am trying to migrate a python application that is a few years old to something newer and in a language I'm more comfortable with. Unfortunately I am unable to decode the message I am receiving (btw, 5 years ago the python library was the only one able to manage it).

Proto file:

package proto;

option optimize_for = LITE_RUNTIME;

message Device {
    required string deviceId = 1;
    required int32 signalStrength = 2;
    required DeviceType deviceType = 3;
    optional string uuid = 4;
}

message DevicesFrame {
    required int64 timestamp = 1;
    required int32 frameSize = 2;
    repeated Device devices = 3; 
}

enum DeviceType {
    BT = 0;
    BLE = 1;
    WIFI = 2;
}

Plugin generation options: --ts_opt output_javascript_es2020

Sample code:

import { DevicesFrame } from "./DevicesFrame.js"; // the generated plugin

const bytes = "5AEIsrbP1YIvEPQDGiMKDDFFRUNEQTgxMTg4QxDM//////////8BGAIqBkJlYWNvbhojCgwwRUVDREE4MTE4OEMQzv//////////ARgCKgZCZWFjb24aIwoMRkNFQ0RBODExODhDEMz//////////wEYAioGQmVhY29uGiEKDDY0MUNBRTRBNTREMhDL//////////8BGAIqBERhdGEaIwoMRkVFQ0RBODExODhDEM7//////////wEYAioGQmVhY29uGiEKDDY0MUNBRTRBNTRFMBDM//////////8BGAIqBERhdGEKCKe6z9WCLxD0A+IBCJy+z9WCLxD0AxojCgwxRUVDREE4MTE4OEMQy///////////ARgCKgZCZWFjb24aIwoMMEVFQ0RBODExODhDEM7//////////wEYAioGQmVhY29uGiMKDEZDRUNEQTgxMTg4QxDL//////////8BGAIqBkJlYWNvbhohCgw2NDFDQUU0QTU0RDIQy///////////ARgCKgREYXRhGiMKDEZFRUNEQTgxMTg4QxDO//////////8BGAIqBkJlYWNvbhofCgw2NDFDQUU0QTU0RTAQy///////////ARgCKgJEQQoIscLP1YIvEPQD5AEIpcbP1YIvEPQDGiMKDDFFRUNEQTgxMTg4QxDM//////////8BGAIqBkJlYWNvbhojCgwwRUVDREE4MTE4OEMQzv//////////ARgCKgZCZWFjb24aIwoMRkNFQ0RBODExODhDEMz//////////wEYAioGQmVhY29uGiEKDDY0MUNBRTRBNTREMhDL//////////8BGAIqBERhdGEaIwoMRkVFQ0RBODExODhDEM7//////////wEYAioGQmVhY29uGiEKDDY0MUNBRTRBNTRFMBDL//////////8BGAIqBERhdGEKCJrKz9WCLxD0A+IBCI7Oz9WCLxD0AxojCgwxRUVDREE4MTE4OEMQzP//////////ARgCKgZCZWFjb24aIwoMMEVFQ0RBODExODhDEM7//////////wEYAioGQmVhY29uGiMKDEZDRUNEQTgxMTg4QxDM//////////8BGAIqBkJlYWNvbhohCgw2NDFDQUU0QTU0RDIQy///////////ARgCKgREYXRhGiMKDEZFRUNEQTgxMTg4QxDO//////////8BGAIqBkJlYWNvbhofCgw2NDFDQUU0QTU0RTAQy///////////ARgCKgJEQQoIg9LP1YIvEPQD9AEI99XP1YIvEPQDGiMKDDFFRUNEQTgxMTg4QxDL//////////8BGAIqBkJlYWNvbhorCgwwRUVDREE4MTE4OEMQzv//////////ARgCKg5Qcm9iZSBSZXNwb25zZRojCgxGQ0VDREE4MTE4OEMQy///////////ARgCKgZCZWFjb24aIQoMNjQxQ0FFNEE1NEQyEMf//////////wEYAioERGF0YRorCgxGRUVDREE4MTE4OEMQzv//////////ARgCKg5Qcm9iZSBSZXNwb25zZRohCgw2NDFDQUU0QTU0RTAQy///////////ARgCKgREYXRhCgjs2c/Vgi8Q9APkAQjg3c/Vgi8Q9AMaIwoMMUVFQ0RBODExODhDEMz//////////wEYAioGQmVhY29uGiMKDDBFRUNEQTgxMTg4QxDO//////////8BGAIqBkJlYWNvbhojCgxGQ0VDREE4MTE4OEMQy///////////ARgCKgZCZWFjb24aIQoMNjQxQ0FFNEE1NEQyEMv//////////wEYAioERGF0YRojCgxGRUVDREE4MTE4OEMQzv//////////ARgCKgZCZWFjb24aIQoMNjQxQ0FFNEE1NEUwEMv//////////wEYAioERGF0YQoI1eHP1YIvEPQD0QEIyeXP1YIvEPQDGiMKDDFFRUNEQTgxMTg4QxDL//////////8BGAIqBkJlYWNvbhorCgwwRUVDREE4MTE4OEMQzv//////////ARgCKg5Qcm9iZSBSZXNwb25zZRojCgxGQ0VDREE4MTE4OEMQy///////////ARgCKgZCZWFjb24aKwoMRkVFQ0RBODExODhDEM7//////////wEYAioOUHJvYmUgUmVzcG9uc2UaIQoMNjQxQ0FFNEE1NEUwEMv//////////wEYAioERGF0YQoIvunP1YIvEPQD";
const decoded = Buffer.from(bytes, "base64");
const frame = DevicesFrame.fromBinary(decoded);
// Uncaught Error Error: cant skip wire type 4
console.log(frame);

The message should translate to this:

[
    {
      "timestamp": 1615624133426,
      "devices": [
        { "DeviceId": "1EECDA81188C", "SignalStrength": -52, "DeviceType": 2 },
        { "DeviceId": "0EECDA81188C", "SignalStrength": -50, "DeviceType": 2 },
        { "DeviceId": "FCECDA81188C", "SignalStrength": -52, "DeviceType": 2 },
        { "DeviceId": "641CAE4A54D2", "SignalStrength": -53, "DeviceType": 2 },
        { "DeviceId": "FEECDA81188C", "SignalStrength": -50, "DeviceType": 2 },
        { "DeviceId": "641CAE4A54E0", "SignalStrength": -52, "DeviceType": 2 }
      ]
    },
    { "timestamp": 1615624133927, "devices": [] },
...
]

Thanks in advance for any suggestion. paolo

timostamm commented 8 months ago

Hey Paolo, the error message suggests that there's a tag with an unexpected wire type EndGroup (4). It might be a red herring though - it's possible that there is a different issue that leads us to parse data that is not a tag as a tag.

I don't think you can avoid to take a closer look at the binary data, to understand what is actually encoded, and where the issue comes from. protobuf-ts passes the protobuf conformance test suite, so I'm suspecting that the software producing the data has a bug.

The page about Encoding on protobuf.dev is a good starting point. Even if the data you receive is broken, you could write your own deserializer using BinaryReader from protobuf-ts to parse it.