OLD | NEW |
1 # Copyright 2012, Google Inc. | 1 # Copyright 2012, Google Inc. |
2 # All rights reserved. | 2 # All rights reserved. |
3 # | 3 # |
4 # Redistribution and use in source and binary forms, with or without | 4 # Redistribution and use in source and binary forms, with or without |
5 # modification, are permitted provided that the following conditions are | 5 # modification, are permitted provided that the following conditions are |
6 # met: | 6 # met: |
7 # | 7 # |
8 # * Redistributions of source code must retain the above copyright | 8 # * Redistributions of source code must retain the above copyright |
9 # notice, this list of conditions and the following disclaimer. | 9 # notice, this list of conditions and the following disclaimer. |
10 # * Redistributions in binary form must reproduce the above | 10 # * Redistributions in binary form must reproduce the above |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 SEC_WEBSOCKET_VERSION_HEADER = 'Sec-WebSocket-Version' | 95 SEC_WEBSOCKET_VERSION_HEADER = 'Sec-WebSocket-Version' |
96 SEC_WEBSOCKET_PROTOCOL_HEADER = 'Sec-WebSocket-Protocol' | 96 SEC_WEBSOCKET_PROTOCOL_HEADER = 'Sec-WebSocket-Protocol' |
97 SEC_WEBSOCKET_EXTENSIONS_HEADER = 'Sec-WebSocket-Extensions' | 97 SEC_WEBSOCKET_EXTENSIONS_HEADER = 'Sec-WebSocket-Extensions' |
98 SEC_WEBSOCKET_DRAFT_HEADER = 'Sec-WebSocket-Draft' | 98 SEC_WEBSOCKET_DRAFT_HEADER = 'Sec-WebSocket-Draft' |
99 SEC_WEBSOCKET_KEY1_HEADER = 'Sec-WebSocket-Key1' | 99 SEC_WEBSOCKET_KEY1_HEADER = 'Sec-WebSocket-Key1' |
100 SEC_WEBSOCKET_KEY2_HEADER = 'Sec-WebSocket-Key2' | 100 SEC_WEBSOCKET_KEY2_HEADER = 'Sec-WebSocket-Key2' |
101 SEC_WEBSOCKET_LOCATION_HEADER = 'Sec-WebSocket-Location' | 101 SEC_WEBSOCKET_LOCATION_HEADER = 'Sec-WebSocket-Location' |
102 | 102 |
103 # Extensions | 103 # Extensions |
104 DEFLATE_FRAME_EXTENSION = 'deflate-frame' | 104 DEFLATE_FRAME_EXTENSION = 'deflate-frame' |
105 PERFRAME_COMPRESSION_EXTENSION = 'perframe-compress' | |
106 PERMESSAGE_COMPRESSION_EXTENSION = 'permessage-compress' | 105 PERMESSAGE_COMPRESSION_EXTENSION = 'permessage-compress' |
107 PERMESSAGE_DEFLATE_EXTENSION = 'permessage-deflate' | 106 PERMESSAGE_DEFLATE_EXTENSION = 'permessage-deflate' |
108 X_WEBKIT_DEFLATE_FRAME_EXTENSION = 'x-webkit-deflate-frame' | 107 X_WEBKIT_DEFLATE_FRAME_EXTENSION = 'x-webkit-deflate-frame' |
109 X_WEBKIT_PERMESSAGE_COMPRESSION_EXTENSION = 'x-webkit-permessage-compress' | 108 X_WEBKIT_PERMESSAGE_COMPRESSION_EXTENSION = 'x-webkit-permessage-compress' |
110 MUX_EXTENSION = 'mux_DO_NOT_USE' | 109 MUX_EXTENSION = 'mux_DO_NOT_USE' |
111 | 110 |
112 # Status codes | 111 # Status codes |
113 # Code STATUS_NO_STATUS_RECEIVED, STATUS_ABNORMAL_CLOSURE, and | 112 # Code STATUS_NO_STATUS_RECEIVED, STATUS_ABNORMAL_CLOSURE, and |
114 # STATUS_TLS_HANDSHAKE are pseudo codes to indicate specific error cases. | 113 # STATUS_TLS_HANDSHAKE are pseudo codes to indicate specific error cases. |
115 # Could not be used for codes in actual closing frames. | 114 # Could not be used for codes in actual closing frames. |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 for param_name, param_value in self._parameters: | 187 for param_name, param_value in self._parameters: |
189 if param_name == name: | 188 if param_name == name: |
190 return param_value | 189 return param_value |
191 | 190 |
192 | 191 |
193 class ExtensionParsingException(Exception): | 192 class ExtensionParsingException(Exception): |
194 def __init__(self, name): | 193 def __init__(self, name): |
195 super(ExtensionParsingException, self).__init__(name) | 194 super(ExtensionParsingException, self).__init__(name) |
196 | 195 |
197 | 196 |
198 def _parse_extension_param(state, definition, allow_quoted_string): | 197 def _parse_extension_param(state, definition): |
199 param_name = http_header_util.consume_token(state) | 198 param_name = http_header_util.consume_token(state) |
200 | 199 |
201 if param_name is None: | 200 if param_name is None: |
202 raise ExtensionParsingException('No valid parameter name found') | 201 raise ExtensionParsingException('No valid parameter name found') |
203 | 202 |
204 http_header_util.consume_lwses(state) | 203 http_header_util.consume_lwses(state) |
205 | 204 |
206 if not http_header_util.consume_string(state, '='): | 205 if not http_header_util.consume_string(state, '='): |
207 definition.add_parameter(param_name, None) | 206 definition.add_parameter(param_name, None) |
208 return | 207 return |
209 | 208 |
210 http_header_util.consume_lwses(state) | 209 http_header_util.consume_lwses(state) |
211 | 210 |
212 if allow_quoted_string: | 211 # TODO(tyoshino): Add code to validate that parsed param_value is token |
213 # TODO(toyoshim): Add code to validate that parsed param_value is token | 212 param_value = http_header_util.consume_token_or_quoted_string(state) |
214 param_value = http_header_util.consume_token_or_quoted_string(state) | |
215 else: | |
216 param_value = http_header_util.consume_token(state) | |
217 if param_value is None: | 213 if param_value is None: |
218 raise ExtensionParsingException( | 214 raise ExtensionParsingException( |
219 'No valid parameter value found on the right-hand side of ' | 215 'No valid parameter value found on the right-hand side of ' |
220 'parameter %r' % param_name) | 216 'parameter %r' % param_name) |
221 | 217 |
222 definition.add_parameter(param_name, param_value) | 218 definition.add_parameter(param_name, param_value) |
223 | 219 |
224 | 220 |
225 def _parse_extension(state, allow_quoted_string): | 221 def _parse_extension(state): |
226 extension_token = http_header_util.consume_token(state) | 222 extension_token = http_header_util.consume_token(state) |
227 if extension_token is None: | 223 if extension_token is None: |
228 return None | 224 return None |
229 | 225 |
230 extension = ExtensionParameter(extension_token) | 226 extension = ExtensionParameter(extension_token) |
231 | 227 |
232 while True: | 228 while True: |
233 http_header_util.consume_lwses(state) | 229 http_header_util.consume_lwses(state) |
234 | 230 |
235 if not http_header_util.consume_string(state, ';'): | 231 if not http_header_util.consume_string(state, ';'): |
236 break | 232 break |
237 | 233 |
238 http_header_util.consume_lwses(state) | 234 http_header_util.consume_lwses(state) |
239 | 235 |
240 try: | 236 try: |
241 _parse_extension_param(state, extension, allow_quoted_string) | 237 _parse_extension_param(state, extension) |
242 except ExtensionParsingException, e: | 238 except ExtensionParsingException, e: |
243 raise ExtensionParsingException( | 239 raise ExtensionParsingException( |
244 'Failed to parse parameter for %r (%r)' % | 240 'Failed to parse parameter for %r (%r)' % |
245 (extension_token, e)) | 241 (extension_token, e)) |
246 | 242 |
247 return extension | 243 return extension |
248 | 244 |
249 | 245 |
250 def parse_extensions(data, allow_quoted_string=False): | 246 def parse_extensions(data): |
251 """Parses Sec-WebSocket-Extensions header value returns a list of | 247 """Parses Sec-WebSocket-Extensions header value returns a list of |
252 ExtensionParameter objects. | 248 ExtensionParameter objects. |
253 | 249 |
254 Leading LWSes must be trimmed. | 250 Leading LWSes must be trimmed. |
255 """ | 251 """ |
256 | 252 |
257 state = http_header_util.ParsingState(data) | 253 state = http_header_util.ParsingState(data) |
258 | 254 |
259 extension_list = [] | 255 extension_list = [] |
260 while True: | 256 while True: |
261 extension = _parse_extension(state, allow_quoted_string) | 257 extension = _parse_extension(state) |
262 if extension is not None: | 258 if extension is not None: |
263 extension_list.append(extension) | 259 extension_list.append(extension) |
264 | 260 |
265 http_header_util.consume_lwses(state) | 261 http_header_util.consume_lwses(state) |
266 | 262 |
267 if http_header_util.peek(state) is None: | 263 if http_header_util.peek(state) is None: |
268 break | 264 break |
269 | 265 |
270 if not http_header_util.consume_string(state, ','): | 266 if not http_header_util.consume_string(state, ','): |
271 raise ExtensionParsingException( | 267 raise ExtensionParsingException( |
(...skipping 26 matching lines...) Expand all Loading... |
298 def format_extensions(extension_list): | 294 def format_extensions(extension_list): |
299 """Formats a list of ExtensionParameter objects.""" | 295 """Formats a list of ExtensionParameter objects.""" |
300 | 296 |
301 formatted_extension_list = [] | 297 formatted_extension_list = [] |
302 for extension in extension_list: | 298 for extension in extension_list: |
303 formatted_extension_list.append(format_extension(extension)) | 299 formatted_extension_list.append(format_extension(extension)) |
304 return ', '.join(formatted_extension_list) | 300 return ', '.join(formatted_extension_list) |
305 | 301 |
306 | 302 |
307 # vi:sts=4 sw=4 et | 303 # vi:sts=4 sw=4 et |
OLD | NEW |