Ë
    ÚŠ±jñ*  ã                   ób   — d Z ddlmZmZ ddlmZ ddlmZ  G d„ de«      Z G d„ d	«      Z	d	dgZ
y
)zd
HTTP/2 stream state management.

Each HTTP/2 stream represents a single request/response exchange.
é    )ÚEnumÚauto)ÚBytesIOé   )ÚHTTP2StreamErrorc                   ór   — e Zd ZdZ e«       Z e«       Z e«       Z e«       Z e«       Z	 e«       Z
 e«       Zy)Ú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© ó    úZ/var/www/io.vulcan-creative.com/venv/lib/python3.12/site-packages/gunicorn/http2/stream.pyr	   r	      s8   „ ÙBá‹6€DÙ“V€NÙ“f€OÙ‹6€DÙ›ÐÙ›ÐÙ‹V�Fr   r	   c                   óÂ   — e Zd ZdZd„ Zed„ «       Zed„ «       Zed„ «       Zed„ «       Z	dd„Z
dd„Zd	„ Zdd
„Zdd„Zd„ Zdd„Zd„ Zdd„Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zy)ÚHTTP2Streamz¡Represents a single HTTP/2 stream.

    Manages stream state, headers, and body data for a single
    request/response exchange within an HTTP/2 connection.
    c                 ó@  — || _         || _        t        j                  | _        g | _        t        «       | _        d| _        d| _	        d| _
        d| _        |j                  | _        d| _        d| _        d| _        d| _        d| _        g | _        d| _        d| _        y)z¼Initialize 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Ú_body_chunksÚ_body_eventÚ_body_complete)Úselfr   r   s      r   Ú__init__zHTTP2Stream.__init__%   s®   € ð #ˆŒØ$ˆŒô !×%Ñ%ˆŒ
ð  "ˆÔÜ#›IˆÔØ %ˆÔð !&ˆÔØ%*ˆÔ"Ø!&ˆÔð &×9Ñ9ˆÔð ˆŒð "&ˆÔð  "ˆÔØ#$ˆÔ Ø"'ˆÔð ˆÔØˆÔØ#ˆÕr   c                 ó&   — | j                   dz  dk(  S )z;Check if this is a client-initiated stream (odd stream ID).é   r   ©r   ©r/   s    r   Úis_client_streamzHTTP2Stream.is_client_streamO   ó   € ð �~‰~ Ñ! QÑ&Ð&r   c                 ó&   — | j                   dz  dk(  S )z<Check if this is a server-initiated stream (even stream ID).r2   r   r3   r4   s    r   Úis_server_streamzHTTP2Stream.is_server_streamT   r6   r   c                 óZ   — | j                   t        j                  t        j                  fv S )z&Check if this stream can receive data.)r   r	   r   r   r4   s    r   Úcan_receivezHTTP2Stream.can_receiveY   s,   € ð �z‰zÜ×ÑÜ×)Ñ)ð
ð 
ð 	
r   c                 óZ   — | j                   t        j                  t        j                  fv S )z#Check if this stream can send data.)r   r	   r   r   r4   s    r   Úcan_sendzHTTP2Stream.can_senda   s,   € ð �z‰zÜ×ÑÜ×*Ñ*ð
ð 
ð 	
r   c                 ó†  — | j                   t        j                  k(  rt        j                  | _         nY| j                   t        j                  t        j                  fvr-t        | j                  d| j                   j                  › �«      ‚| j                  j                  |«       |r| j                  «        d| _        yy)zôProcess 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_streams      r   Úreceive_headerszHTTP2Stream.receive_headersi   s™   € ð �:‰:œ×)Ñ)Ò)Ü$×)Ñ)ˆD�JØ�Z‰Z¤× 0Ñ 0´+×2OÑ2OÐPÑPÜ"Ø—‘Ø2°4·:±:·?±?Ð2CÐDóð ð
 	×Ñ×#Ñ# GÔ,áØ×#Ñ#Ô%Ø$(ˆDÕ!ð r   c                 óÂ  — | j                   s-t        | j                  d| j                  j                  › �«      ‚|rA| j
                  j                  |«       | j                  r| j                  j                  «        | j                  j                  |«       |rF| j                  «        d| _        d| _        | j                  r| j                  j                  «        yyy)zôProcess received DATA frame with streaming support.

        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)r:   r   r   r   r>   r,   Úappendr-   Úsetr    Úwriter@   r!   r.   ©r/   ÚdatarC   s      r   Úreceive_datazHTTP2Stream.receive_data�   sÂ   € ð ×ÒÜ"Ø—‘Ø/°·
±
·±Ð/@ÐAóð ñ Ø×Ñ×$Ñ$ TÔ*Ø×ÒØ× Ñ ×$Ñ$Ô&ð 	×Ñ×Ñ Ô%áØ×#Ñ#Ô%Ø$(ˆDÔ!Ø"&ˆDÔØ×ÒØ× Ñ ×$Ñ$Õ&ð  ð	 r   c                 ó²   — | j                   s-t        | j                  d| j                  j                  › �«      ‚|| _        | j                  «        d| _        y)zmProcess received trailing headers.

        Args:
            trailers: List of (name, value) tuples
        z!Cannot receive trailers in state TN)r:   r   r   r   r>   r'   r@   r!   ©r/   r'   s     r   Úreceive_trailerszHTTP2Stream.receive_trailers¡   sQ   € ð ×ÒÜ"Ø—‘Ø3°D·J±J·O±OÐ3DÐEóð ð
 !ˆŒØ×ÑÔ!Ø $ˆÕr   c                 óÆ   — | j                   s-t        | j                  d| j                  j                  › �«      ‚d| _        d| _        |r| j                  «        d| _        yy)zýMark 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)	r<   r   r   r   r>   r"   r#   Ú_half_close_localr$   rA   s      r   Úsend_headerszHTTP2Stream.send_headers±   s`   € ð �}Š}Ü"Ø—‘Ø/°·
±
·±Ð/@ÐAóð ð
 !%ˆÔØ%)ˆÔ"áØ×"Ñ"Ô$Ø%)ˆDÕ"ð r   c                 óª   — | j                   s-t        | j                  d| j                  j                  › �«      ‚|r| j                  «        d| _        yy)zÝMark 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)r<   r   r   r   r>   rP   r$   rI   s      r   Ú	send_datazHTTP2Stream.send_dataÈ   sP   € ð �}Š}Ü"Ø—‘Ø,¨T¯Z©Z¯_©_Ð,=Ð>óð ñ
 Ø×"Ñ"Ô$Ø%)ˆDÕ"ð r   c                 ó²   — | j                   s-t        | j                  d| j                  j                  › �«      ‚|| _        | j                  «        d| _        y)zÙMark 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)r<   r   r   r   r>   r(   rP   r$   rM   s     r   Úsend_trailerszHTTP2Stream.send_trailersÜ   sP   € ð �}Š}Ü"Ø—‘Ø0°·±·±Ð0AÐBóð ð "*ˆÔØ×ÑÔ Ø!%ˆÕr   c                 óJ   — t         j                  | _        d| _        d| _        y)zvReset this stream with RST_STREAM.

        Args:
            error_code: HTTP/2 error code (default: CANCEL)
        TN©r	   r   r   r$   r!   )r/   Ú
error_codes     r   ÚresetzHTTP2Stream.resetî   s!   € ô !×'Ñ'ˆŒ
Ø!%ˆÔØ $ˆÕr   c                 óJ   — t         j                  | _        d| _        d| _        y)zClose this stream normally.TNrW   r4   s    r   ÚclosezHTTP2Stream.closeø   s   € ä ×'Ñ'ˆŒ
Ø!%ˆÔØ $ˆÕr   Nc                 ód   — |�t        dt        d|«      «      | _        |�|| _        |�|| _        yy)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Ú	exclusives       r   Úupdate_priorityzHTTP2Stream.update_priorityþ   sA   € ð ÐÜ#& q¬#¨c°6Ó*:Ó#;ˆDÔ ØÐ!Ø'1ˆDÔ$ØÐ Ø&/ˆDÕ#ð !r   c                 ó(  — | j                   t        j                  k(  rt        j                  | _         y| j                   t        j                  k(  rt        j
                  | _         y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   r>   r4   s    r   rP   zHTTP2Stream._half_close_local  sg   € à�:‰:œ×)Ñ)Ò)Ü$×6Ñ6ˆD�JØ�Z‰Zœ;×9Ñ9Ò9Ü$×+Ñ+ˆD�Jä"Ø—‘Ø3°D·J±J·O±OÐ3DÐEóð r   c                 ó(  — | j                   t        j                  k(  rt        j                  | _         y| j                   t        j                  k(  rt        j
                  | _         yt        | j                  d| j                   j                  › �«      ‚)z)Transition to half-closed (remote) state.z"Cannot half-close remote in state N)	r   r	   r   r   r   r   r   r   r>   r4   s    r   r@   zHTTP2Stream._half_close_remote  sg   € à�:‰:œ×)Ñ)Ò)Ü$×7Ñ7ˆD�JØ�Z‰Zœ;×8Ñ8Ò8Ü$×+Ñ+ˆD�Jä"Ø—‘Ø4°T·Z±Z·_±_Ð4EÐFóð r   c                 ó6   — | j                   j                  «       S )zbGet the complete request body.

        Returns:
            bytes: The request body data
        )r    Úgetvaluer4   s    r   Úget_request_bodyzHTTP2Stream.get_request_body%  s   € ð × Ñ ×)Ñ)Ó+Ð+r   c              ƒ   ó   K  — ddl }| j                  €G|j                  «       | _        | j                  s| j                  r| j                  j                  «        	 | j                  r| j                  j                  d«      S | j                  ry| j                  j                  «        | j                  j                  «       ƒ d{  –—†  Œq7 Œ­w)z–Read next body chunk asynchronously for streaming.

        Returns:
            bytes: Next chunk of body data, or None if body is complete.
        r   N)	Úasyncior-   ÚEventr,   r.   rG   ÚpopÚclearÚwait)r/   rj   s     r   Úread_body_chunkzHTTP2Stream.read_body_chunk-  s³   è ø€ ó 	ð ×ÑÐ#Ø&Ÿ}™}›ˆDÔð × Ò  D×$7Ò$7Ø× Ñ ×$Ñ$Ô&àà× Ò Ø×(Ñ(×,Ñ,¨QÓ/Ð/ð ×"Ò"Øð ×Ñ×"Ñ"Ô$Ø×"Ñ"×'Ñ'Ó)×)Ð)ð ð *ús   ‚CCÃCÃCc                 ó`   — i }| j                   D ]  \  }}|j                  d«      sŒ|||<   Œ |S )zÄExtract HTTP/2 pseudo-headers from request headers.

        Returns:
            dict: Mapping of pseudo-header names to values
                  (e.g., {':method': 'GET', ':path': '/'})
        ú:©r   Ú
startswith)r/   Úpseudor>   Úvalues       r   Úget_pseudo_headerszHTTP2Stream.get_pseudo_headersJ  s>   € ð ˆØ×/Ñ/ò 	%‰KˆD�%Ø�‰˜sÕ#Ø$��t’ð	%ð ˆr   c                 ór   — | j                   D ��cg c]  \  }}|j                  d«      s||f‘Œ c}}S c c}}w )zŒGet regular (non-pseudo) headers from request.

        Returns:
            list: List of (name, value) tuples for regular headers
        rq   rr   )r/   r>   ru   s      r   Úget_regular_headerszHTTP2Stream.get_regular_headersW  s>   € ð  $×3Ñ3÷
á��eØ—?‘? 3Ô'ð �5ŠMó
ð 	
ùó 
s   �3c           	      ó„   — d| j                   › d| j                  j                  › d| j                  › d| j                  › d�	S )Nz<HTTP2Stream id=z state=z req_complete=z resp_complete=ú>)r   r   r>   r!   r$   r4   s    r   Ú__repr__zHTTP2Stream.__repr__c  sO   € à˜tŸ~™~Ð.ð /Ø—Z‘Z—_‘_Ð%ð &Ø ×1Ñ1Ð2ð 3Ø!×3Ñ3Ð4°Að7ð	
r   )F)é   )NNN)r
   r   r   r   r0   Úpropertyr5   r8   r:   r<   rD   rK   rN   rQ   rS   rU   rY   r[   rc   rP   r@   rh   ro   rv   rx   r{   r   r   r   r   r      s®   „ ñò($ðT ñ'ó ð'ð ñ'ó ð'ð ñ
ó ð
ð ñ
ó ð
ó)ó0'ò@%ó *ó.*ò(&ó$%ò%ó0ò
ò
ò,ò*ò:ò

ó
r   r   N)r   Úenumr   r   Úior   Úerrorsr   r	   r   Ú__all__r   r   r   ú<module>r‚      s:   ðñ÷ Ý å $ô	�$ô 	÷K
ñ K
ð\
 ˜-Ð
(�r   