o
    i1W                     @   sx   d Z ddlmZ ddlmZmZmZmZmZ ddl	m
Z
 ddlmZ dadadadadadd	 ZG d
d dZdgZdS )zc
HTTP/2 server connection implementation.

Uses the hyper-h2 library for HTTP/2 protocol handling.
    )BytesIO   )
HTTP2ErrorHTTP2ProtocolErrorHTTP2ConnectionErrorHTTP2NotAvailableHTTP2ErrorCode)HTTP2Stream)HTTP2RequestNc                   C   sd   t durdS z!ddlma  ddlma ddlma ddl	m
a ddlma W dS  ty1   t w )z$Lazily import h2 library components.Nr   )_h2h2.connection
connection	h2.configconfig
_h2_config	h2.eventsevents
_h2_eventsh2.exceptions
exceptions_h2_exceptionsh2.settingssettings_h2_settingsImportErrorr    r   r   M/home/ubuntu/.local/lib/python3.10/site-packages/gunicorn/http2/connection.py
_import_h2   s   r   c                   @   s   e Zd ZdZdZdd Zdd Zd5dd	Zd
d Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zd5ddZdd Zd6d!d"Zd#d$ Zd5d%d&Zd7d(d)Zd8d+d,Zd-d. Zed/d0 Zd1d2 Zd3d4 ZdS )9HTTP2ServerConnectionzHTTP/2 server-side connection handler.

    Manages the HTTP/2 connection state and multiplexed streams.
    This class wraps the h2 library and provides a higher-level
    interface for gunicorn workers.
    i   c                 C   sx   t   || _|| _|| _i | _g | _|j| _|j| _	|j
| _|j| _tjddd}tj|d| _t | _d| _d| _dS )a.  Initialize an HTTP/2 server connection.

        Args:
            cfg: Gunicorn configuration object
            sock: SSL socket with completed handshake
            client_addr: Client address tuple (host, port)

        Raises:
            HTTP2NotAvailable: If h2 library is not installed
        Fzutf-8)client_sideheader_encoding)r   N)r   cfgsockclient_addrstreams_pending_requestshttp2_initial_window_sizeinitial_window_sizehttp2_max_concurrent_streamsmax_concurrent_streamshttp2_max_frame_sizemax_frame_sizehttp2_max_header_list_sizemax_header_list_sizer   H2Configurationr   H2Connectionh2_connr   _read_buffer_closed_initialized)selfr!   r"   r#   r   r   r   r   __init__:   s$   
zHTTP2ServerConnection.__init__c              
   C   sZ   | j rdS | jtjj| jtjj| jtjj	| j
tjj| ji | j  |   d| _ dS )zSend initial HTTP/2 settings to client.

        Should be called after the SSL handshake completes and
        before processing any data.
        NT)r3   r0   update_settingsr   SettingCodesMAX_CONCURRENT_STREAMSr)   INITIAL_WINDOW_SIZEr'   MAX_FRAME_SIZEr+   MAX_HEADER_LIST_SIZEr-   initiate_connection_send_pending_datar4   r   r   r   r<   e   s   





z)HTTP2ServerConnection.initiate_connectionNc              
   C   s  |du r#z	| j | j}W n ttfy" } ztd| d}~ww |s*d| _g S z| j|}W n t	j
yL } z| jtjd tt|d}~w t	jye } z| jtjd tt|d}~w t	jy } zt|dd}|dur~| j|d n| jtjd tt|d}~w t	jy } z| jtjd tt|d}~w t	jy } z| jtjd tt|d}~ww g }|D ]}| |}|dur|| q|   |S )aA  Process received data and return completed requests.

        Args:
            data: Optional bytes to process. If None, reads from socket.

        Returns:
            list: List of HTTP2Request objects for completed requests

        Raises:
            HTTP2ConnectionError: On protocol or connection errors
        NzSocket read error: T
error_coder@   )r"   recvREAD_BUFFER_SIZEOSErrorIOErrorr   r2   r0   receive_datar   FlowControlErrorcloser   FLOW_CONTROL_ERRORr   strFrameTooLargeErrorFRAME_SIZE_ERRORInvalidSettingsValueErrorgetattrPROTOCOL_ERRORTooManyStreamsErrorREFUSED_STREAMProtocolError_handle_eventappendr=   )r4   dataer   r@   completed_requestseventrequestr   r   r   rE   z   sX   

z"HTTP2ServerConnection.receive_datac                 C   s   t |tjr| |S t |tjr| |S t |tjr!| |S t |tjr.| 	| dS t |tj
r7	 dS t |tjrD| | dS t |tjrM	 dS t |tjrZ| | dS t |tjre| |S dS )zHandle a single h2 event.

        Args:
            event: h2 event object

        Returns:
            HTTP2Request if a request is complete, None otherwise
        N)
isinstancer   RequestReceived_handle_request_receivedDataReceived_handle_data_receivedStreamEnded_handle_stream_endedStreamReset_handle_stream_resetWindowUpdatedPriorityUpdated_handle_priority_updatedSettingsAcknowledgedConnectionTerminated_handle_connection_terminatedTrailersReceived_handle_trailers_receivedr4   rW   r   r   r   rR      s0   	






z#HTTP2ServerConnection._handle_eventc                 C   s2   |j }|j}t|| }|| j|< |j|dd dS )z{Handle RequestReceived event (HEADERS frame).

        Args:
            event: RequestReceived event with headers
        F
end_streamN)	stream_idheadersr	   r$   receive_headers)r4   rW   rm   rn   streamr   r   r   r[      s
   

z.HTTP2ServerConnection._handle_request_receivedc              	   C   s   |j }|j}| j|}|du rdS |j|dd t|dkrOz| jjt||d | jjt|dd |   W dS  t	t
jfyN   | jtjd Y dS w dS )zHandle DataReceived event.

        Args:
            event: DataReceived event with body data

        Returns:
            None (request completion handled by StreamEnded)
        NFrk   r   )rm   r?   )rm   rT   r$   getrE   lenr0   increment_flow_control_windowr=   
ValueErrorr   rF   rG   r   rH   )r4   rW   rm   rT   rp   r   r   r   r]      s"   	
z+HTTP2ServerConnection._handle_data_receivedc                 C   s4   |j }| j|}|du rdS d|_t|| j| jS )zHandle StreamEnded event.

        Args:
            event: StreamEnded event

        Returns:
            HTTP2Request for the completed request
        NT)rm   r$   rq   request_completer
   r!   r#   r4   rW   rm   rp   r   r   r   r_     s   	z*HTTP2ServerConnection._handle_stream_endedc                 C   s.   |j }| j|}|dur||j dS dS )ziHandle StreamReset event (RST_STREAM frame).

        Args:
            event: StreamReset event
        N)rm   r$   rq   resetr@   rv   r   r   r   ra   *  s
   z*HTTP2ServerConnection._handle_stream_resetc                 C   s
   d| _ dS )zwHandle ConnectionTerminated event (GOAWAY frame).

        Args:
            event: ConnectionTerminated event
        TNr2   rj   r   r   r   rg   7  s   
z3HTTP2ServerConnection._handle_connection_terminatedc                 C   s:   |j }| j|}|du rdS ||j t|| j| jS )zHandle TrailersReceived event.

        Args:
            event: TrailersReceived event with trailer headers

        Returns:
            HTTP2Request if this completes the request
        N)rm   r$   rq   receive_trailersrn   r
   r!   r#   rv   r   r   r   ri   @  s   	z/HTTP2ServerConnection._handle_trailers_receivedc                 C   s4   | j |j}|dur|j|j|j|jd dS dS )zHandle PriorityUpdated event (PRIORITY frame).

        Args:
            event: PriorityUpdated event with priority info
        N)weight
depends_on	exclusive)r$   rq   rm   update_priorityrz   r{   r|   )r4   rW   rp   r   r   r   rd   T  s   
z.HTTP2ServerConnection._handle_priority_updatedc                 C   s   |dk s|dkrt d| | j|}|du r!t d| ddt|fg}|D ]\}}|| t|f q*| jj||dd	 |   dS )
a  Send an informational response (1xx) on a stream.

        This is used for 103 Early Hints and other 1xx responses.
        Informational responses are sent before the final response
        and do not end the stream.

        Args:
            stream_id: The stream ID
            status: HTTP status code (100-199)
            headers: List of (name, value) header tuples

        Raises:
            HTTP2Error: If status is not in 1xx range
        d      zInvalid informational status: NzStream z
 not found:statusFrk   )	r   r$   rq   rI   rS   lowerr0   send_headersr=   )r4   rm   statusrn   rp   response_headersnamevaluer   r   r   send_informationalb  s   z(HTTP2ServerConnection.send_informationalc           
      C   s   | j |}|du rdS dt|fg}|D ]\}}|| t|f q|du p.t|dk}	z'| jj|||	d |j||	d |   |rTt|dkrT| j	||dd W dS  t
jyj   |  | | Y dS w )a  Send a response on a stream.

        Args:
            stream_id: The stream ID to respond on
            status: HTTP status code (int)
            headers: List of (name, value) header tuples
            body: Optional response body bytes

        Raises:
            HTTP2Error: If stream not found or in invalid state

        Returns:
            bool: True if response sent, False if stream was already closed
        NFr   r   rk   T)r$   rq   rI   rS   r   rr   r0   r   r=   	send_datar   StreamClosedErrorrG   cleanup_stream)
r4   rm   r   rn   bodyrp   r   r   r   rl   r   r   r   send_response  s&   
z#HTTP2ServerConnection.send_responsec                 C   s  ddl }d}z| }|| j|j W n ttfy    Y dS w d}zt|D ]t}| j	|}|dkr8|} nr|j
dd}|rz	| j| j}	W n tttjfyW   Y  nZw |	s_d| _ nYz| j|	}
W n tjyr   Y  nMw |
D ]}t|tjr|j|krd} nqut|tjrd| _d} nqu|   q( n*q(| j	|}W |  |S W |  |S W |  |S W |  |S W |  |S W |  |S |  w )zWait for flow control window to become positive.

        Returns:
            int: Available window size, or -1 if waiting failed
        r   N2   g?)timeoutT)	selectorsDefaultSelectorregisterr"   
EVENT_READ	TypeErrorrt   ranger0   local_flow_control_windowselectrA   rB   rC   rD   r   rQ   r2   rE   rY   r   r`   rm   rf   r=   rG   )r4   rm   r   max_wait_attemptsselresult_	availablereadyincomingr   rW   r   r   r   _wait_for_flow_control_window  s   
 
z3HTTP2ServerConnection._wait_for_flow_control_windowFc           
   	   C   s  | j |}|du rdS |}z[|r`| j|}t|| jt|}|dkr=|   | |}|dkr4W dS t|| jt|}|d| }||d }|oPt|dk}	| jj	|||	d |   |s|j	||d W dS  t
jt
jfy   |  | | Y dS w )a  Send data on a stream.

        Args:
            stream_id: The stream ID
            data: Body data bytes
            end_stream: Whether this ends the stream

        Returns:
            bool: True if data sent, False if stream was already closed
        NFr   rk   T)r$   rq   r0   r   minr+   rr   r=   r   r   r   r   rF   rG   r   )
r4   rm   rT   rl   rp   data_to_sendr   
chunk_sizechunkis_finalr   r   r   r     s6   

zHTTP2ServerConnection.send_datac                 C   s   | j |}|du rdS |jsdS g }|D ]\}}| }|dr*td| d||t|f qz| jj	||dd |
| |   W dS  tjy]   |  | | Y dS w )a  Send trailing headers on a stream.

        Trailers are headers sent after the response body, commonly used
        for gRPC status codes, checksums, and timing information.

        Args:
            stream_id: The stream ID
            trailers: List of (name, value) trailer tuples

        Raises:
            HTTP2Error: If stream not found, headers not sent, or pseudo-headers used

        Returns:
            bool: True if trailers sent, False if stream was already closed
        NF:zPseudo-header 'z' not allowed in trailersTrk   )r$   rq   response_headers_sentr   
startswithr   rS   rI   r0   r   send_trailersr=   r   r   rG   r   )r4   rm   trailersrp   trailer_headersr   r   lnamer   r   r   r     s*   


z#HTTP2ServerConnection.send_trailersc                 C   sD   |r|  nd}dtt|fg}|r|d | |||| dS )zSend an error response on a stream.

        Args:
            stream_id: The stream ID
            status_code: HTTP status code
            message: Optional error message body
            zcontent-length)zcontent-typeztext/plain; charset=utf-8N)encoderI   rr   rS   r   )r4   rm   status_codemessager   rn   r   r   r   
send_error@  s
   
z HTTP2ServerConnection.send_error   c                 C   s:   | j |}|dur|| | jj||d |   dS )zReset a stream with RST_STREAM.

        Args:
            stream_id: The stream ID to reset
            error_code: HTTP/2 error code (default: CANCEL)
        Nr?   )r$   rq   rw   r0   reset_streamr=   )r4   rm   r@   rp   r   r   r   r   O  s
   
z"HTTP2ServerConnection.reset_streamr   c                 C   sb   | j rdS d| _ |du r| jrt| j nd}z| jj|d |   W dS  ty0   Y dS w )zClose the connection gracefully with GOAWAY.

        Args:
            error_code: HTTP/2 error code (default: NO_ERROR)
            last_stream_id: Last processed stream ID (default: highest)
        NTr   r?   )r2   r$   maxkeysr0   close_connectionr=   	Exception)r4   r@   last_stream_idr   r   r   rG   ]  s   zHTTP2ServerConnection.closec              
   C   sV   | j  }|r)z	| j| W dS  ttfy( } z
d| _td| d}~ww dS )z,Send any pending data from h2 to the socket.TzSocket write error: N)r0   r   r"   sendallrC   rD   r2   r   )r4   rT   rU   r   r   r   r=   s  s   
z(HTTP2ServerConnection._send_pending_datac                 C   s   | j S )zCheck if connection is closed.rx   r>   r   r   r   	is_closed}  s   zHTTP2ServerConnection.is_closedc                 C   s   | j |d dS )zvRemove a stream after processing is complete.

        Args:
            stream_id: The stream ID to clean up
        N)r$   pop)r4   rm   r   r   r   r     s   z$HTTP2ServerConnection.cleanup_streamc                 C   s   dt | j d| j dS )Nz<HTTP2ServerConnection streams=z closed=>)rr   r$   r2   r>   r   r   r   __repr__  s   zHTTP2ServerConnection.__repr__)N)F)r   )r   N)__name__
__module____qualname____doc__rB   r5   r<   rE   rR   r[   r]   r_   ra   rg   ri   rd   r   r   r   r   r   r   r   rG   r=   propertyr   r   r   r   r   r   r   r   /   s6    +
B&"	
 ,
:,
,



r   )r   ior   errorsr   r   r   r   r   rp   r	   rX   r
   r   r   r   r   r   r   r   __all__r   r   r   r   <module>   s"       
g