1 #!/usr/bin/env python2.7
3 # Copyright 2015 gRPC authors.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 """Read from stdin a set of colon separated http headers:
18 content-type: application/grpc
19 Write a set of strings containing a hpack encoded http2 frame that
20 represents said headers."""
27 def append_never_indexed(payload_line, n, count, key, value):
28 payload_line.append(0x10)
29 assert (len(key) <= 126)
30 payload_line.append(len(key))
31 payload_line.extend(ord(c) for c in key)
32 assert (len(value) <= 126)
33 payload_line.append(len(value))
34 payload_line.extend(ord(c) for c in value)
37 def append_inc_indexed(payload_line, n, count, key, value):
38 payload_line.append(0x40)
39 assert (len(key) <= 126)
40 payload_line.append(len(key))
41 payload_line.extend(ord(c) for c in key)
42 assert (len(value) <= 126)
43 payload_line.append(len(value))
44 payload_line.extend(ord(c) for c in value)
47 def append_pre_indexed(payload_line, n, count, key, value):
48 payload_line.append(0x80 + 61 + count - n)
52 'never': append_never_indexed,
53 'inc': append_inc_indexed,
54 'pre': append_pre_indexed,
57 argp = argparse.ArgumentParser('Generate header frames')
58 argp.add_argument('--set_end_stream',
62 argp.add_argument('--no_framing',
66 argp.add_argument('--compression',
67 choices=sorted(_COMPRESSORS.keys()),
69 argp.add_argument('--hex', default=False, action='store_const', const=True)
70 args = argp.parse_args()
72 # parse input, fill in vals
74 for line in sys.stdin:
76 if line == '': continue
77 if line[0] == '#': continue
78 key_tail, value = line[1:].split(':')
79 key = (line[0] + key_tail).strip()
81 vals.append((key, value))
83 # generate frame payload binary data
85 if not args.no_framing:
86 payload_bytes.append([]) # reserve space for header
89 for key, value in vals:
91 _COMPRESSORS[args.compression](payload_line, n, len(vals), key, value)
93 payload_len += len(payload_line)
94 payload_bytes.append(payload_line)
97 if not args.no_framing:
98 flags = 0x04 # END_HEADERS
99 if args.set_end_stream:
100 flags |= 0x01 # END_STREAM
101 payload_bytes[0].extend([
102 (payload_len >> 16) & 0xff,
103 (payload_len >> 8) & 0xff,
104 (payload_len) & 0xff,
116 hex_bytes = [ord(c) for c in "abcdefABCDEF0123456789"]
124 if c in hex_bytes and last_was_hex:
140 for line in payload_bytes:
141 all_bytes.extend(line)
142 print '{%s}' % ', '.join('0x%02x' % c for c in all_bytes)
144 for line in payload_bytes: