o
    i$                     @   sV   d Z ddlmZmZ ddlmZ ddlmZ G dd deZG dd	 d	Z	d	dgZ
d
S )zd
HTTP/2 stream state management.

Each HTTP/2 stream represents a single request/response exchange.
    )Enumauto)BytesIO   )HTTP2StreamErrorc                   @   s:   e Zd ZdZe Ze Ze Ze Ze Z	e Z
e ZdS )StreamStatez8HTTP/2 stream states as defined in RFC 7540 Section 5.1.N)__name__
__module____qualname____doc__r   IDLERESERVED_LOCALRESERVED_REMOTEOPENHALF_CLOSED_LOCALHALF_CLOSED_REMOTECLOSED r   r   I/home/ubuntu/.local/lib/python3.10/site-packages/gunicorn/http2/stream.pyr      s    
r   c                   @   s   e Zd ZdZdd Zedd Zedd Zedd	 Zed
d Z	d-ddZ
d-ddZdd Zd-ddZd-ddZdd Zd.ddZdd Zd/dd Zd!d" Zd#d$ Zd%d& Zd'd( Zd)d* Zd+d, ZdS )0HTTP2StreamzRepresents a single HTTP/2 stream.

    Manages stream state, headers, and body data for a single
    request/response exchange within an HTTP/2 connection.
    c                 C   sd   || _ || _tj| _g | _t | _d| _d| _	d| _
d| _|j| _d| _d| _d| _d| _d| _dS )zInitialize an HTTP/2 stream.

        Args:
            stream_id: The unique stream identifier (odd for client-initiated)
            connection: The parent HTTP2ServerConnection
        FN   r   )	stream_id
connectionr   r   staterequest_headersr   request_bodyrequest_completeresponse_startedresponse_headers_sentresponse_completeinitial_window_sizewindow_sizetrailersresponse_trailerspriority_weightpriority_depends_onpriority_exclusive)selfr   r   r   r   r   __init__%   s   
zHTTP2Stream.__init__c                 C      | j d dkS )z;Check if this is a client-initiated stream (odd stream ID).   r   r   r'   r   r   r   is_client_streamJ      zHTTP2Stream.is_client_streamc                 C   r)   )z<Check if this is a server-initiated stream (even stream ID).r*   r   r+   r,   r   r   r   is_server_streamO   r.   zHTTP2Stream.is_server_streamc                 C      | j tjtjfv S )z&Check if this stream can receive data.)r   r   r   r   r,   r   r   r   can_receiveT      zHTTP2Stream.can_receivec                 C   r0   )z#Check if this stream can send data.)r   r   r   r   r,   r   r   r   can_send\   r2   zHTTP2Stream.can_sendFc                 C   sd   | j tjkrtj| _ n| j tjtjfvrt| jd| j j | j	| |r0| 
  d| _dS dS )zProcess received HEADERS frame.

        Args:
            headers: List of (name, value) tuples
            end_stream: True if END_STREAM flag is set

        Raises:
            HTTP2StreamError: If headers received in invalid state
        z Cannot receive headers in state TN)r   r   r   r   r   r   r   namer   extend_half_close_remoter   r'   headers
end_streamr   r   r   receive_headersd   s   


zHTTP2Stream.receive_headersc                 C   sB   | j st| jd| jj | j| |r|   d| _dS dS )zProcess received DATA frame.

        Args:
            data: Bytes received
            end_stream: True if END_STREAM flag is set

        Raises:
            HTTP2StreamError: If data received in invalid state
        zCannot receive data in state TN)	r1   r   r   r   r4   r   writer6   r   r'   datar9   r   r   r   receive_data|   s   

zHTTP2Stream.receive_datac                 C   4   | j st| jd| jj || _|   d| _dS )zmProcess received trailing headers.

        Args:
            trailers: List of (name, value) tuples
        z!Cannot receive trailers in state TN)r1   r   r   r   r4   r"   r6   r   r'   r"   r   r   r   receive_trailers   s   
zHTTP2Stream.receive_trailersc                 C   sB   | j st| jd| jj d| _d| _|r|   d| _dS dS )zMark headers as sent.

        Args:
            headers: List of (name, value) tuples to send
            end_stream: True if this completes the response

        Raises:
            HTTP2StreamError: If headers cannot be sent in current state
        zCannot send headers in state TN)	r3   r   r   r   r4   r   r   _half_close_localr   r7   r   r   r   send_headers   s   

zHTTP2Stream.send_headersc                 C   s6   | j st| jd| jj |r|   d| _dS dS )zMark data as sent.

        Args:
            data: Bytes to send
            end_stream: True if this completes the response

        Raises:
            HTTP2StreamError: If data cannot be sent in current state
        zCannot send data in state TN)r3   r   r   r   r4   rB   r   r<   r   r   r   	send_data   s   

zHTTP2Stream.send_datac                 C   r?   )zMark trailers as sent and close the stream.

        Args:
            trailers: List of (name, value) trailer tuples

        Raises:
            HTTP2StreamError: If trailers cannot be sent in current state
        zCannot send trailers in state TN)r3   r   r   r   r4   r#   rB   r   r@   r   r   r   send_trailers   s   	
zHTTP2Stream.send_trailers   c                 C      t j| _d| _d| _dS )zvReset this stream with RST_STREAM.

        Args:
            error_code: HTTP/2 error code (default: CANCEL)
        TNr   r   r   r   r   )r'   
error_coder   r   r   reset   s   
zHTTP2Stream.resetc                 C   rG   )zClose this stream normally.TNrH   r,   r   r   r   close   s   
zHTTP2Stream.closeNc                 C   s>   |durt dtd|| _|dur|| _|dur|| _dS dS )a   Update stream priority from PRIORITY frame.

        Args:
            weight: Priority weight (1-256), higher = more resources
            depends_on: Stream ID this stream depends on
            exclusive: Whether this is an exclusive dependency
        Nr      )maxminr$   r%   r&   )r'   weight
depends_on	exclusiver   r   r   update_priority   s   
zHTTP2Stream.update_priorityc                 C   F   | j tjkrtj| _ dS | j tjkrtj| _ dS t| jd| j j )z(Transition to half-closed (local) state.z!Cannot half-close local in state N)	r   r   r   r   r   r   r   r   r4   r,   r   r   r   rB         zHTTP2Stream._half_close_localc                 C   rS   )z)Transition to half-closed (remote) state.z"Cannot half-close remote in state N)	r   r   r   r   r   r   r   r   r4   r,   r   r   r   r6   
  rT   zHTTP2Stream._half_close_remotec                 C   s
   | j  S )zbGet the complete request body.

        Returns:
            bytes: The request body data
        )r   getvaluer,   r   r   r   get_request_body  s   
zHTTP2Stream.get_request_bodyc                 C   s*   i }| j D ]\}}|dr|||< q|S )zExtract HTTP/2 pseudo-headers from request headers.

        Returns:
            dict: Mapping of pseudo-header names to values
                  (e.g., {':method': 'GET', ':path': '/'})
        :)r   
startswith)r'   pseudor4   valuer   r   r   get_pseudo_headers  s   
zHTTP2Stream.get_pseudo_headersc                 C   s   dd | j D S )zGet regular (non-pseudo) headers from request.

        Returns:
            list: List of (name, value) tuples for regular headers
        c                 S   s"   g | ]\}}| d s||fqS )rW   )rX   ).0r4   rZ   r   r   r   
<listcomp>1  s    z3HTTP2Stream.get_regular_headers.<locals>.<listcomp>)r   r,   r   r   r   get_regular_headers+  s   zHTTP2Stream.get_regular_headersc              	   C   s(   d| j  d| jj d| j d| j d	S )Nz<HTTP2Stream id=z state=z req_complete=z resp_complete=>)r   r   r4   r   r   r,   r   r   r   __repr__7  s   
zHTTP2Stream.__repr__)F)rF   )NNN)r   r	   r
   r   r(   propertyr-   r/   r1   r3   r:   r>   rA   rC   rD   rE   rJ   rK   rR   rB   r6   rV   r[   r^   r`   r   r   r   r   r      s4    %










r   N)r   enumr   r   ior   errorsr   r   r   __all__r   r   r   r   <module>   s     $