|
#/usr/bin/env bash |
|
|
|
filename="${1?:path to pq page}" |
|
pagename="$(basename "${filename}")" |
|
|
|
_bytes2hex() { |
|
xxd -u -ps | tr -d "\n" |
|
} |
|
|
|
_hex2num() { |
|
local hex |
|
read hex |
|
printf '%s' $((0x${hex})) |
|
} |
|
|
|
_read_hex() { |
|
local byte_count="${1:?byte count}" |
|
|
|
dd bs=1 count="${byte_count}" 2>/dev/null | _bytes2hex |
|
} |
|
|
|
_read_tiny() { |
|
_read_hex 1 | _hex2num |
|
} |
|
_read_int() { |
|
_read_hex 4 | _hex2num |
|
} |
|
_read_long() { |
|
_read_hex 8 | _hex2num |
|
} |
|
|
|
_describe_payload() { |
|
local payload="${1?:payload}" |
|
|
|
_detect_deflate "${payload}" || |
|
_detect_zstd "${payload}" || |
|
_detect_cbor "${payload}" || |
|
printf "CBOR(assumed $(export LC_ALL=C; printf '%s' "${payload:0:8}" | _bytes2hex))" |
|
} |
|
|
|
_detect_deflate() { |
|
local hex_payload="${1?:hex_payload}" |
|
local possible_deflate_header=$(( 0x${hex_payload:0:4} )) |
|
|
|
# 0---1000--0----- |
|
local mask=$(( 2#1000111100100000 )) |
|
local flip=$(( 2#0000100000000000 )) |
|
local goal=$(( 2#0000000000000000 )) |
|
|
|
if (( ( ( possible_deflate_header & mask ) ^ flip ) != goal )); then |
|
return 1 |
|
fi |
|
|
|
if (( ( possible_deflate_header % 31 ) != 0 )); then |
|
return 1 |
|
fi |
|
|
|
local deflate_header=${possible_deflate_header} |
|
local flevels=(fastest fast default maximum) |
|
local flevel="${flevels[$(( (deflate_header & 2#11000000) >> 6))]}" |
|
|
|
printf '%s' "DEFLATE(${flevel})" |
|
} |
|
|
|
_detect_zstd() { |
|
local hex_payload="${1?:hex_payload}" |
|
local header_hex="${hex_payload:0:8}" |
|
|
|
if [[ "${header_hex}" == "28B52FFD" ]]; then |
|
local frame_header_descriptor_bits=$(( 0x${hex_payload:8:2} )) |
|
local fcsflag=$(( frame_header_descriptor_bits >> 6 )) |
|
local ss_flag=$(( (frame_header_descriptor_bits & 2#00100000) >> 5 )) |
|
local did_flag=$(( frame_header_descriptor_bits & 3 )) |
|
|
|
# if ss is present, there is no WindowDescriptor |
|
local fcs_byte_offset=$(( 5 + (ss_flag == 0 ? 1 : 0) + did_flag )) |
|
local fcs_hex_offset=$(( 2 * fcs_byte_offset )) |
|
local fcs_byte_length=$(( 2**(ss_flag > fcsflag ? ss_flag : fcsflag) )) |
|
local fcs_hex_length=$(( 2 * fcs_byte_length )) |
|
|
|
local fcs_hex_header_le="${hex_payload:${fcs_hex_offset}:${fcs_hex_length}}" |
|
local fcs_hex_header_be=$(printf '%s' "${fcs_hex_header_le}" | tac -rs ..) |
|
|
|
# when using 2-byte length, we add 256, otherwise we read as-is. |
|
local content_length=$(( 0x${fcs_hex_header_be} + (fcs_byte_length == 2 ? 256 : 0) )) |
|
|
|
printf '%s' "ZSTD(${content_length})" |
|
else |
|
return 1 |
|
fi |
|
} |
|
|
|
_detect_cbor() { |
|
local hex_payload="${1?:hex_payload}" |
|
local header_hex="${hex_payload:0:6}" |
|
|
|
if [[ "${header_hex}" == "D9D9F7" ]]; then |
|
printf '%s' "CBOR(self-desc)"; |
|
elif [[ "${header_hex}" == "D90100" ]]; then |
|
printf '%s' "CBOR(stringref)" |
|
elif [[ "${header_hex}" == "9F716A" ]]; then |
|
printf '%s' "CBOR(known)"; |
|
else |
|
return 1 |
|
fi |
|
} |
|
|
|
_parse_event() { |
|
local seqnum=$(_read_long) |
|
if ((seqnum <= 0)); then |
|
return 1 |
|
fi |
|
|
|
local length=$(_read_int) |
|
local hex_payload=$(_read_hex $((length))) |
|
local checksum=$(_read_hex 4) |
|
|
|
printf '%s\t%s\t%s\t%s\t%s\n' "${seqnum}" "${length}" "${checksum}" "${pagename}" "$(_describe_payload ${hex_payload})" |
|
|
|
[[ -z "${DEBUG}" ]] || (>&2 printf "%s\n" "${hex_payload}") |
|
} |
|
|
|
parse_stdin() { |
|
local version=$(_read_tiny) |
|
if (( version != 2 )); then |
|
>&2 echo "ERR: Not Logstash PQ v2" |
|
exit 1 |
|
fi |
|
|
|
while _parse_event; do :; done |
|
} |
|
|
|
parse_stdin < "${filename}" |