summaryrefslogtreecommitdiffstats
path: root/dev/h2/mkhdr.sh
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xdev/h2/mkhdr.sh80
1 files changed, 68 insertions, 12 deletions
diff --git a/dev/h2/mkhdr.sh b/dev/h2/mkhdr.sh
index 4d129fa..4ed1a07 100755
--- a/dev/h2/mkhdr.sh
+++ b/dev/h2/mkhdr.sh
@@ -4,9 +4,13 @@
# All fields are optional. 0 assumed when absent.
USAGE=\
-"Usage: %s [-l <len> ] [-t <type>] [-f <flags>] [-i <sid>] [ -d <data> ] > hdr.bin
+"Usage: %s [-l <len> ] [-t <type>] [-f <flags>[,...]] [-i <sid>] [ -d <data> ]
+ [ -e <name> <value> ]* [ -r|-R raw ] [ -h | --help ] > hdr.bin
Numbers are decimal or 0xhex. Not set=0. If <data> is passed, it points
- to a file that is read and chunked into frames of <len> bytes.
+ to a file that is read and chunked into frames of <len> bytes. -e
+ encodes a headers frame (by default) with all headers at once encoded
+ in literal. Use type 'p' for the preface. Use -r to pass raw data or
+ -R to pass raw hex codes (hex digit pairs, blanks ignored).
Supported symbolic types (case insensitive prefix match):
DATA (0x00) PUSH_PROMISE (0x05)
@@ -25,6 +29,8 @@ LEN=
TYPE=
FLAGS=
ID=
+RAW=
+HDR=( )
die() {
[ "$#" -eq 0 ] || echo "$*" >&2
@@ -48,7 +54,7 @@ mkframe() {
local T="${2:-0}"
local F="${3:-0}"
local I="${4:-0}"
- local t f
+ local t f f2 f3
# get the first match in this order
for t in DATA:0x00 HEADERS:0x01 RST_STREAM:0x03 SETTINGS:0x04 PING:0x06 \
@@ -66,17 +72,37 @@ mkframe() {
die
fi
- # get the first match in this order
- for f in ES:0x01 EH:0x04 PAD:0x08 PRIO:0x20; do
- if [ -z "${f##${F^^*}*}" ]; then
- F="${f##*:}"
+ # get the first match in this order, for each entry delimited by ','.
+ # E.g.: "-f ES,EH"
+ f2=${F^^*}; F=0
+
+ while [ -n "$f2" ]; do
+ f3="${f2%%,*}"
+ tmp=""
+ for f in ES:0x01 EH:0x04 PAD:0x08 PRIO:0x20; do
+ if [ -n "$f3" -a -z "${f##${f3}*}" ]; then
+ tmp="${f#*:}"
+ break
+ fi
+ done
+
+ if [ -n "$tmp" ]; then
+ F=$(( F | tmp ))
+ f2="${f2#$f3}"
+ f2="${f2#,}"
+ elif [ -z "${f3##[X0-9A-F]*}" ]; then
+ F=$(( F | f3 ))
+ f2="${f2#$f3}"
+ f2="${f2#,}"
+ else
+ echo "Unknown flag(s) '$f3'" >&2
+ usage "${0##*}"
+ die
fi
done
- if [ -n "${F##[0-9]*}" ]; then
- echo "Unknown type '$T'" >&2
- usage "${0##*}"
- die
+ if [ -n "$f2" ]; then
+ F="${f2} | ${F}"
fi
L=$(( L )); T=$(( T )); F=$(( F )); I=$(( I ))
@@ -110,6 +136,9 @@ while [ -n "$1" -a -z "${1##-*}" ]; do
-f) FLAGS="$2" ; shift 2 ;;
-i) ID="$2" ; shift 2 ;;
-d) DATA="$2" ; shift 2 ;;
+ -r) RAW="$2" ; shift 2 ;;
+ -R) RAW="$(printf $(echo -n "${2// /}" | sed -e 's/\([^ ][^ ]\)/\\\\x\1/g'))" ; shift 2 ;;
+ -e) TYPE=1; HDR[${#HDR[@]}]="$2=$3"; shift 3 ;;
-h|--help) usage "${0##*}"; quit;;
*) usage "${0##*}"; die ;;
esac
@@ -135,8 +164,35 @@ if [ -n "${ID##[0-9]*}" ]; then
die
fi
-if [ -z "$DATA" ]; then
+if [ "$TYPE" = "p" ]; then
+ printf "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
+elif [ -z "$DATA" ]; then
+ # If we're trying to emit literal headers, let's pre-build the raw data
+ # and measure their total length.
+ if [ ${#HDR[@]} -gt 0 ]; then
+ # limited to 127 bytes for name and value
+ for h in "${HDR[@]}"; do
+ n=${h%%=*}
+ v=${h#*=}
+ nl=${#n}
+ vl=${#v}
+ nl7=$(printf "%02x" $((nl & 127)))
+ vl7=$(printf "%02x" $((vl & 127)))
+ RAW="${RAW}\x40\x${nl7}${n}\x${vl7}${v}"
+ done
+ fi
+
+ # compute length if RAW set
+ if [ -n "$RAW" ]; then
+ LEN=$(printf "${RAW}" | wc -c)
+ fi
+
mkframe "$LEN" "$TYPE" "$FLAGS" "$ID"
+
+ # now emit the literal data of advertised length
+ if [ -n "$RAW" ]; then
+ printf "${RAW}"
+ fi
else
# read file $DATA in <LEN> chunks and send it in multiple frames
# advertising their respective lengths.