123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- /* A small tool that decodes a raw binary message, while providing useful
- * info on corrupted messages also. */
- /* Define _ISOC99_SOURCE to get snprintf() even though otherwise in ansi-C mode */
- #define _ISOC99_SOURCE 1
- #include <stdio.h>
- #include <string.h>
- #include <pb_decode.h>
- #include "test_helpers.h"
- #define HISTORY_LEN 32
- static pb_byte_t g_history[HISTORY_LEN];
- static int g_position;
- /* This binds the pb_istream_t to stdin and logs the most recent bytes read. */
- bool callback(pb_istream_t *stream, uint8_t *buf, size_t count)
- {
- FILE *file = (FILE*)stream->state;
- size_t len = fread(buf, 1, count, file);
-
- if (len < HISTORY_LEN)
- {
- memmove(g_history, g_history + len, HISTORY_LEN - len);
- memcpy(g_history + HISTORY_LEN - len, buf, len);
- }
- else
- {
- memcpy(g_history, buf + len - HISTORY_LEN, HISTORY_LEN);
- }
-
- g_position += len;
-
- if (len == count)
- {
- return true;
- }
- else
- {
- stream->bytes_left = 0;
- return false;
- }
- }
- void print_history(int position)
- {
- int i;
-
- if (position < g_position - HISTORY_LEN)
- position = g_position - HISTORY_LEN;
-
- printf("LATEST BYTES READ (%d to %d): ", position, g_position);
-
- for (i = HISTORY_LEN - (g_position - position); i < HISTORY_LEN; i++)
- {
- printf("%02x ", g_history[i]);
- }
-
- printf("\n");
- }
- bool raw_decode(pb_istream_t *stream, const char *indent)
- {
- const char *wiretypes[8] = {"VARINT", "64BIT", "STRING", "SGRP", "EGRP", "32BIT", "????", "????"};
- while (stream->bytes_left)
- {
- uint32_t tag;
- pb_wire_type_t wire_type;
- bool eof;
- int position = g_position;
- if (!pb_decode_tag(stream, &wire_type, &tag, &eof))
- {
- if (eof)
- {
- break;
- }
- else
- {
- printf("ERROR: Failed to parse tag: %s\n", PB_GET_ERROR(stream));
- print_history(position);
- return false;
- }
- }
-
- if (tag == 0)
- {
- printf("%sterminating on zero tag\n", indent);
- return true;
- }
- printf("%sAt %d: field tag %d, wire type %d (%s)",
- indent, position, (int)tag, wire_type, wiretypes[wire_type]);
-
- if (wire_type == PB_WT_VARINT)
- {
- uint64_t value;
- position = g_position;
- if (!pb_decode_varint(stream, &value))
- {
- printf("\n%sERROR: Failed to parse varint: %s\n", indent, PB_GET_ERROR(stream));
- print_history(position);
- return false;
- }
-
- printf(", varint value (%d bytes): %llu\n",
- g_position - position, (unsigned long long)value);
- }
- else if (wire_type == PB_WT_64BIT)
- {
- uint64_t value;
- position = g_position;
- if (!pb_decode_fixed64(stream, &value))
- {
- printf("\n%sERROR: Failed to parse fixed64: %s\n", indent, PB_GET_ERROR(stream));
- print_history(position);
- return false;
- }
-
- printf(", fixed64 value (%d bytes): 0x%016llx\n",
- g_position - position, (unsigned long long)value);
- }
- else if (wire_type == PB_WT_32BIT)
- {
- uint32_t value;
- position = g_position;
- if (!pb_decode_fixed32(stream, &value))
- {
- printf("\n%sERROR: Failed to parse fixed32: %s\n", indent, PB_GET_ERROR(stream));
- print_history(position);
- return false;
- }
-
- printf(", fixed32 value (%d bytes): 0x%08lx\n",
- g_position - position, (unsigned long)value);
- }
- else if (wire_type == PB_WT_STRING)
- {
- pb_istream_t substream;
- position = g_position;
- if (!pb_make_string_substream(stream, &substream))
- {
- printf("ERROR: Failed to parse string length: %s\n", PB_GET_ERROR(stream));
- print_history(position);
- return false;
- }
- else
- {
-
- if (substream.bytes_left == 0)
- {
- printf(", empty string\n");
- }
- else
- {
- char prefix[8];
- snprintf(prefix, sizeof(prefix), "f%d> ", (int)tag);
-
- printf(", string len %d bytes, attempting recursive decode\n",
- (int)substream.bytes_left);
-
- if (!raw_decode(&substream, prefix))
- {
- printf("%sfield %d: recursive decode failed, continuing with upper level\n\n",
- indent, (int)tag);
- }
-
- pb_close_string_substream(stream, &substream);
- }
- }
- }
- else
- {
- printf("\n");
- }
- }
-
- return true;
- }
- int main()
- {
- pb_istream_t stream = {&callback, NULL, SIZE_MAX};
- stream.state = stdin;
- SET_BINARY_MODE(stdin);
- if (!raw_decode(&stream, ""))
- {
- return 1;
- } else {
- return 0;
- }
- }
|