Search code examples
c++structmarshallingpaddingpack

Serialized C++ struct with 3-byte blocks?


I have a C++ application which is sending a serialized struct to my C# app, and I would like to automatically copy the bytes directly to a new struct I created in C#. However, the struct sent over the network seems to have 3-byte blocks, which seems quite weird.

Here is C++ struct:

typedef struct ATTQueryAgentStateConfEvent_t {
  ATTWorkMode_t workMode;  /* enum type */
  ATTTalkState_t talkState;  /* enum type */
  long reasonCode;
  ATTWorkMode_t pendingWorkMode;   /* enum type */
  long pendingReasonCode;
} ATTQueryAgentStateConfEvent_t;

The struct I created in C#:

[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct ATTQueryAgentStateConfEvent_t
{
    public ATTWorkMode_t workMode;  /* enum type */
    public ATTTalkState_t talkState;  /* enum type */
    public long reasonCode;
    public ATTWorkMode_t pendingWorkMode;  /* enum type */
    public long pendingReasonCode;
};

And here are the bytes received from C++ app (the first 6 bytes seem to be some header):

02 00 68 00 30 0f 0a 01 03 0a 01 01 02 01 00 0a 01 ff 02 01 00
                        ^^       ^^       ^^       ^^       ^^

Above I have marked the values I am expecting to receive (3, 1, 0, -1, 0). I have experimented with different Pack values when defining the C# struct, but it is simply not parsed correctly. This is the command I am using to fill the struct in C#:

ATTQueryAgentStateConfEvent_t stateDetails = (ATTQueryAgentStateConfEvent_t)Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(confPrivData.data, 6), typeof(ATTQueryAgentStateConfEvent_t));

Am I doing something wrong, or this C++ app is using some custom serializer? I would expect C++ enums and longs to be 4 bytes... I know I can extract the values byte by byte, but I would like to automate it, if possible. Thanks for any tips.


Solution

  • As said in my comment you gave no information about what serializer is being used. However, the format reminds me of Abstract Syntax Notation One (ASN1) and the example stream given is actually valid, i.e. type IDs match those specified in ASN1 (30 = SEQUENCE, 02 = INTEGER, ...) You should find plenty of libraries being able to deserialize ASN1 streams, but I have no experience about C#, so I can't give you any suggestion at this point.