MCPcopy
hub / github.com/benoitc/gunicorn / _read_frame

Method _read_frame

gunicorn/asgi/websocket.py:262–342  ·  view source on GitHub ↗

Read a single WebSocket frame. Returns: tuple: (opcode, payload) or None if connection closed

(self)

Source from the content-addressed store, hash-verified

260 })
261
262 async def _read_frame(self): # pylint: disable=too-many-return-statements
263 """Read a single WebSocket frame.
264
265 Returns:
266 tuple: (opcode, payload) or None if connection closed
267 """
268 # Read frame header (2 bytes minimum)
269 header = await self._read_exact(2)
270 if not header:
271 return None
272
273 first_byte, second_byte = header[0], header[1]
274
275 fin = (first_byte >> 7) & 1
276 rsv1 = (first_byte >> 6) & 1
277 rsv2 = (first_byte >> 5) & 1
278 rsv3 = (first_byte >> 4) & 1
279 opcode = first_byte & 0x0F
280
281 # RSV bits must be 0 (no extensions)
282 if rsv1 or rsv2 or rsv3:
283 await self._send_close(CLOSE_PROTOCOL_ERROR, "RSV bits set")
284 return None
285
286 masked = (second_byte >> 7) & 1
287 payload_len = second_byte & 0x7F
288
289 # Client frames must be masked (RFC 6455)
290 if not masked:
291 await self._send_close(CLOSE_PROTOCOL_ERROR, "Frame not masked")
292 return None
293
294 # Extended payload length
295 if payload_len == 126:
296 ext_len = await self._read_exact(2)
297 if not ext_len:
298 return None
299 payload_len = struct.unpack("!H", ext_len)[0]
300 elif payload_len == 127:
301 ext_len = await self._read_exact(8)
302 if not ext_len:
303 return None
304 payload_len = struct.unpack("!Q", ext_len)[0]
305
306 # Read masking key
307 masking_key = await self._read_exact(4)
308 if not masking_key:
309 return None
310
311 # Read payload
312 payload = await self._read_exact(payload_len)
313 if payload is None:
314 return None
315
316 # Unmask payload
317 payload = self._unmask(payload, masking_key)
318
319 # Handle fragmented messages

Calls 3

_read_exactMethod · 0.95
_send_closeMethod · 0.95
_unmaskMethod · 0.95