Receive data and return completed requests. Args: timeout: Optional timeout in seconds for read operation Returns: list: List of HTTP2Request objects for completed requests Raises: HTTP2ConnectionError: On protocol or connection errors
(self, timeout=None)
| 120 | self._initialized = True |
| 121 | |
| 122 | async def receive_data(self, timeout=None): |
| 123 | """Receive data and return completed requests. |
| 124 | |
| 125 | Args: |
| 126 | timeout: Optional timeout in seconds for read operation |
| 127 | |
| 128 | Returns: |
| 129 | list: List of HTTP2Request objects for completed requests |
| 130 | |
| 131 | Raises: |
| 132 | HTTP2ConnectionError: On protocol or connection errors |
| 133 | asyncio.TimeoutError: If timeout expires |
| 134 | """ |
| 135 | try: |
| 136 | if timeout is not None: |
| 137 | data = await asyncio.wait_for( |
| 138 | self.reader.read(self.READ_BUFFER_SIZE), |
| 139 | timeout=timeout |
| 140 | ) |
| 141 | else: |
| 142 | data = await self.reader.read(self.READ_BUFFER_SIZE) |
| 143 | except (OSError, IOError) as e: |
| 144 | raise HTTP2ConnectionError(f"Socket read error: {e}") |
| 145 | |
| 146 | if not data: |
| 147 | # Connection closed by peer |
| 148 | self._closed = True |
| 149 | return [] |
| 150 | |
| 151 | # Feed data to h2 |
| 152 | # Note: Specific exceptions must come before ProtocolError (their parent class) |
| 153 | try: |
| 154 | events = self.h2_conn.receive_data(data) |
| 155 | except _h2_exceptions.FlowControlError as e: |
| 156 | # Send GOAWAY with FLOW_CONTROL_ERROR |
| 157 | await self.close(error_code=HTTP2ErrorCode.FLOW_CONTROL_ERROR) |
| 158 | raise HTTP2ProtocolError(str(e)) |
| 159 | except _h2_exceptions.FrameTooLargeError as e: |
| 160 | # Send GOAWAY with FRAME_SIZE_ERROR |
| 161 | await self.close(error_code=HTTP2ErrorCode.FRAME_SIZE_ERROR) |
| 162 | raise HTTP2ProtocolError(str(e)) |
| 163 | except _h2_exceptions.InvalidSettingsValueError as e: |
| 164 | # Use error_code from h2 exception (RFC 7540 Section 6.5.2): |
| 165 | # INITIAL_WINDOW_SIZE > 2^31-1 gives FLOW_CONTROL_ERROR |
| 166 | # Other invalid settings give PROTOCOL_ERROR |
| 167 | error_code = getattr(e, 'error_code', None) |
| 168 | if error_code is not None: |
| 169 | await self.close(error_code=error_code) |
| 170 | else: |
| 171 | await self.close(error_code=HTTP2ErrorCode.PROTOCOL_ERROR) |
| 172 | raise HTTP2ProtocolError(str(e)) |
| 173 | except _h2_exceptions.TooManyStreamsError as e: |
| 174 | # Send GOAWAY with REFUSED_STREAM |
| 175 | await self.close(error_code=HTTP2ErrorCode.REFUSED_STREAM) |
| 176 | raise HTTP2ProtocolError(str(e)) |
| 177 | except _h2_exceptions.ProtocolError as e: |
| 178 | # Send GOAWAY with PROTOCOL_ERROR before raising |
| 179 | await self.close(error_code=HTTP2ErrorCode.PROTOCOL_ERROR) |