gen_settings_ids.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 
3 # Copyright 2017 gRPC authors.
4 #
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
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
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 
17 from __future__ import print_function
18 
19 import collections
20 import sys
21 
22 import perfection
23 
24 _MAX_HEADER_LIST_SIZE = 16 * 1024 * 1024
25 
26 Setting = collections.namedtuple('Setting', 'id default min max on_error')
27 OnError = collections.namedtuple('OnError', 'behavior code')
28 clamp_invalid_value = OnError('CLAMP_INVALID_VALUE', 'PROTOCOL_ERROR')
29 disconnect_on_invalid_value = lambda e: OnError('DISCONNECT_ON_INVALID_VALUE', e
30  )
31 DecoratedSetting = collections.namedtuple('DecoratedSetting',
32  'enum name setting')
33 
34 _SETTINGS = {
35  'HEADER_TABLE_SIZE':
36  Setting(1, 4096, 0, 0xffffffff, clamp_invalid_value),
37  'ENABLE_PUSH':
38  Setting(2, 1, 0, 1, disconnect_on_invalid_value('PROTOCOL_ERROR')),
39  'MAX_CONCURRENT_STREAMS':
40  Setting(3, 0xffffffff, 0, 0xffffffff,
41  disconnect_on_invalid_value('PROTOCOL_ERROR')),
42  'INITIAL_WINDOW_SIZE':
43  Setting(4, 65535, 0, 0x7fffffff,
44  disconnect_on_invalid_value('FLOW_CONTROL_ERROR')),
45  'MAX_FRAME_SIZE':
46  Setting(5, 16384, 16384, 16777215,
47  disconnect_on_invalid_value('PROTOCOL_ERROR')),
48  'MAX_HEADER_LIST_SIZE':
49  Setting(6, _MAX_HEADER_LIST_SIZE, 0, _MAX_HEADER_LIST_SIZE,
50  clamp_invalid_value),
51  'GRPC_ALLOW_TRUE_BINARY_METADATA':
52  Setting(0xfe03, 0, 0, 1, clamp_invalid_value),
53 }
54 
55 H = open('src/core/ext/transport/chttp2/transport/http2_settings.h', 'w')
56 C = open('src/core/ext/transport/chttp2/transport/http2_settings.c', 'w')
57 
58 
59 # utility: print a big comment block into a set of files
60 def put_banner(files, banner):
61  for f in files:
62  print('/*', file=f)
63  for line in banner:
64  print(' * %s' % line, file=f)
65  print(' */', file=f)
66  print(file=f)
67 
68 
69 # copy-paste copyright notice from this file
70 with open(sys.argv[0]) as my_source:
71  copyright = []
72  for line in my_source:
73  if line[0] != '#':
74  break
75  for line in my_source:
76  if line[0] == '#':
77  copyright.append(line)
78  break
79  for line in my_source:
80  if line[0] != '#':
81  break
82  copyright.append(line)
83  put_banner([H, C], [line[2:].rstrip() for line in copyright])
84 
86  [H, C],
87  ["Automatically generated by tools/codegen/core/gen_settings_ids.py"])
88 
89 print("#ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_SETTINGS_H",
90  file=H)
91 print("#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_SETTINGS_H",
92  file=H)
93 print(file=H)
94 print("#include <stdint.h>", file=H)
95 print("#include <stdbool.h>", file=H)
96 print(file=H)
97 
98 print("#include \"src/core/ext/transport/chttp2/transport/http2_settings.h\"",
99  file=C)
100 print(file=C)
101 print("#include <grpc/support/useful.h>", file=C)
102 print("#include \"src/core/lib/transport/http2_errors.h\"", file=C)
103 print(file=C)
104 
105 p = perfection.hash_parameters(sorted(x.id for x in list(_SETTINGS.values())))
106 print(p)
107 
108 
109 def hash(i):
110  i += p.offset
111  x = i % p.t
112  y = i // p.t
113  return x + p.r[y]
114 
115 
116 decorated_settings = [
117  DecoratedSetting(hash(setting.id), name, setting)
118  for name, setting in _SETTINGS.items()
119 ]
120 
121 print('typedef enum {', file=H)
122 for decorated_setting in sorted(decorated_settings):
123  print(' GRPC_CHTTP2_SETTINGS_%s = %d, /* wire id %d */' %
124  (decorated_setting.name, decorated_setting.enum,
125  decorated_setting.setting.id),
126  file=H)
127 print('} grpc_chttp2_setting_id;', file=H)
128 print(file=H)
129 print('#define GRPC_CHTTP2_NUM_SETTINGS %d' %
130  (max(x.enum for x in decorated_settings) + 1),
131  file=H)
132 
133 print('extern const uint16_t grpc_setting_id_to_wire_id[];', file=H)
134 print('const uint16_t grpc_setting_id_to_wire_id[] = {%s};' %
135  ','.join('%d' % s for s in p.slots),
136  file=C)
137 print(file=H)
138 print(
139  "bool grpc_wire_id_to_setting_id(uint32_t wire_id, grpc_chttp2_setting_id *out);",
140  file=H)
141 cgargs = {
142  'r': ','.join('%d' % (r if r is not None else 0) for r in p.r),
143  't': p.t,
144  'offset': abs(p.offset),
145  'offset_sign': '+' if p.offset > 0 else '-'
146 }
147 print("""
148 bool grpc_wire_id_to_setting_id(uint32_t wire_id, grpc_chttp2_setting_id *out) {
149  uint32_t i = wire_id %(offset_sign)s %(offset)d;
150  uint32_t x = i %% %(t)d;
151  uint32_t y = i / %(t)d;
152  uint32_t h = x;
153  switch (y) {
154 """ % cgargs,
155  file=C)
156 for i, r in enumerate(p.r):
157  if not r:
158  continue
159  if r < 0:
160  print('case %d: h -= %d; break;' % (i, -r), file=C)
161  else:
162  print('case %d: h += %d; break;' % (i, r), file=C)
163 print("""
164  }
165  *out = (grpc_chttp2_setting_id)h;
166  return h < GPR_ARRAY_SIZE(grpc_setting_id_to_wire_id) && grpc_setting_id_to_wire_id[h] == wire_id;
167 }
168 """ % cgargs,
169  file=C)
170 
171 print("""
172 typedef enum {
173  GRPC_CHTTP2_CLAMP_INVALID_VALUE,
174  GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE
175 } grpc_chttp2_invalid_value_behavior;
176 
177 typedef struct {
178  const char *name;
179  uint32_t default_value;
180  uint32_t min_value;
181  uint32_t max_value;
182  grpc_chttp2_invalid_value_behavior invalid_value_behavior;
183  uint32_t error_value;
184 } grpc_chttp2_setting_parameters;
185 
186 extern const grpc_chttp2_setting_parameters grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS];
187 """,
188  file=H)
189 print(
190  "const grpc_chttp2_setting_parameters grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS] = {",
191  file=C)
192 i = 0
193 for decorated_setting in sorted(decorated_settings):
194  while i < decorated_setting.enum:
195  print(
196  "{NULL, 0, 0, 0, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR},",
197  file=C)
198  i += 1
199  print("{\"%s\", %du, %du, %du, GRPC_CHTTP2_%s, GRPC_HTTP2_%s}," % (
200  decorated_setting.name,
201  decorated_setting.setting.default,
202  decorated_setting.setting.min,
203  decorated_setting.setting.max,
204  decorated_setting.setting.on_error.behavior,
205  decorated_setting.setting.on_error.code,
206  ),
207  file=C)
208  i += 1
209 print("};", file=C)
210 
211 print(file=H)
212 print("#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_SETTINGS_H */",
213  file=H)
214 
215 H.close()
216 C.close()
gen_settings_ids.disconnect_on_invalid_value
disconnect_on_invalid_value
Definition: gen_settings_ids.py:29
max
int max
Definition: bloaty/third_party/zlib/examples/enough.c:170
gen_settings_ids.DecoratedSetting
DecoratedSetting
Definition: gen_settings_ids.py:31
gen_settings_ids.OnError
OnError
Definition: gen_settings_ids.py:27
gen_settings_ids.hash
def hash(i)
Definition: gen_settings_ids.py:109
gen_settings_ids.Setting
Setting
Definition: gen_settings_ids.py:26
open
#define open
Definition: test-fs.c:46
gen_settings_ids.put_banner
def put_banner(files, banner)
Definition: gen_settings_ids.py:60


grpc
Author(s):
autogenerated on Thu Mar 13 2025 02:59:23