
    AҐiP                     x    d Z ddl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 Z G d d	      Zd	gZy)
z
Async HTTP/2 server connection implementation for ASGI workers.

Uses the hyper-h2 library for HTTP/2 protocol handling with
asyncio for non-blocking I/O.
    N   )
HTTP2ErrorHTTP2ProtocolErrorHTTP2ConnectionErrorHTTP2NotAvailableHTTP2ErrorCode)HTTP2Stream)HTTP2Requestc                  ~    t         y	 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 y# t        $ r t!               w xY 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        X/var/www/descvideos/venv/lib/python3.12/site-packages/gunicorn/http2/async_connection.py
_import_h2r      s8     "#&&.* "!!"s   ( <c                       e Zd ZdZdZd Zd ZddZd Zd Z	d	 Z
d
 Zd Zd Zd Zd Zd ZddZd ZddZd ZddZddZddZd Zed        Zd Zd Zy)AsyncHTTP2ConnectionzAsync HTTP/2 server-side connection handler for ASGI.

    Manages the HTTP/2 connection state and multiplexed streams
    using asyncio for non-blocking I/O operations.
    i   c                    t                || _        || _        || _        || _        i | _        t        j                         | _        |j                  | _
        |j                  | _        |j                  | _        |j                  | _        t"        j%                  dd      }t&        j)                  |      | _        d| _        d| _        d| _        y)aP  Initialize an async HTTP/2 server connection.

        Args:
            cfg: Gunicorn configuration object
            reader: asyncio StreamReader
            writer: asyncio StreamWriter
            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readerwriterclient_addrstreamsasyncioQueue_request_queue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_conn_closed_initialized_receive_task)selfr%   r&   r'   r(   r   s         r   __init__zAsyncHTTP2Connection.__init__:   s     	&  &mmo $'#@#@ &)&F&F#!66$'$B$B! ++# , 
 ''v'6 !!r   c           
        K   | j                   ry| j                  j                  t        j                  j
                  | j                  t        j                  j                  | j                  t        j                  j                  | j                  t        j                  j                  | j                  i       | j                  j                          | j                          d{    d| _         y7 w)zSend initial HTTP/2 settings to client.

        Should be called after the SSL handshake completes and
        before processing any data.
        NT)r9   r7   update_settingsr   SettingCodesMAX_CONCURRENT_STREAMSr0   INITIAL_WINDOW_SIZEr.   MAX_FRAME_SIZEr2   MAX_HEADER_LIST_SIZEr4   initiate_connection_send_pending_datar;   s    r   rD   z(AsyncHTTP2Connection.initiate_connectione   s       	$$%%<<d>Y>Y%%994;S;S%%44d6I6I%%::D<U<U	&
 	 	((*%%'''  	(s   C&C7(C5)C7Nc                   K   	 |Ct        j                  | j                  j                  | j                        |       d{   }n-| j                  j                  | j                         d{   }|s	d| _        g S 	 | j                  j                  |      }g }|D ]'  }| j5                  |      }||j7                  |       ) | j9                          d{    |S 7 7 u# t
        t        f$ r}t        d|       d}~ww xY w# t        j                  $ rB}| j                  t        j                         d{  7   t!        t#        |            d}~wt        j$                  $ rB}| j                  t        j&                         d{  7   t!        t#        |            d}~wt        j(                  $ rm}t+        |dd      }|| j                  |       d{  7   n)| j                  t        j,                         d{  7   t!        t#        |            d}~wt        j.                  $ rB}| j                  t        j0                         d{  7   t!        t#        |            d}~wt        j2                  $ rB}| j                  t        j,                         d{  7   t!        t#        |            d}~ww xY w7 w)ah  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
            asyncio.TimeoutError: If timeout expires
        NtimeoutzSocket read error: T
error_coderK   )r*   wait_forr&   readREAD_BUFFER_SIZEOSErrorIOErrorr   r8   r7   receive_datar   FlowControlErrorcloser   FLOW_CONTROL_ERRORr   strFrameTooLargeErrorFRAME_SIZE_ERRORInvalidSettingsValueErrorgetattrPROTOCOL_ERRORTooManyStreamsErrorREFUSED_STREAMProtocolError_handle_eventappendrE   )	r;   rI   dataer   rK   completed_requestseventrequests	            r   rQ   z!AsyncHTTP2Connection.receive_dataz   sf    		B"$--KK$$T%:%:;# 
 "[[--d.C.CDD DLI	-\\..t4F:   	3E((/G""))'2	3 %%'''!!o
 E! 	B&)<QC'@AA	B .. 	-**(I(I*JJJ$SV,,00 	-**(G(G*HHH$SV,,77 		- !L$7J%jjJj777jjN,I,IjJJJ$SV,,11 	-**(E(E*FFF$SV,,++ 	-**(E(E*FFF$SV,,	- 	(s   K ?C) C%-C) 1C'2C) 6K D K 8&K KK %C) 'C) )D8DDK K!#EEEK4#F1FF11K$H/+G.,)H/HH//K#J(I+)JK#K;J><KKK c                    t        |t        j                        r| j                  |      S t        |t        j                        r| j                  |      S t        |t        j                        r| j                  |      S t        |t        j                        r| j                  |       yt        |t        j                        r	 yt        |t        j                        r| j                  |       yt        |t        j                        r	 yt        |t        j                        r| j                  |       yt        |t        j                         r| j#                  |      S y)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r;   rc   s     r   r^   z"AsyncHTTP2Connection._handle_event   s.    eZ7780077z667--e44z556,,U33z556%%e,"  z778  z99:))%0  z>>?  z>>?..u5
  z::;11%88r   c                     |j                   }|j                  }t        ||       }|| j                  |<   |j	                  |d       y)z-Handle RequestReceived event (HEADERS frame).F
end_streamN)	stream_idheadersr	   r)   receive_headers)r;   rc   r{   r|   streams        r   rh   z-AsyncHTTP2Connection._handle_request_received   sE    OO	-- Y-"(Y 	w59r   c                    |j                   }|j                  }| j                  j                  |      }|y|j	                  |d       t        |      dkD  rN	 | j                  j                  t        |      |       | j                  j                  t        |      d       yy# t        t        j                  f$ rE d| _        	 | j                  j                  t        j                         Y y# t        $ r Y Y yw xY ww xY w)zHandle DataReceived event.NFry   r   )r{   TrJ   )r{   r`   r)   getrQ   lenr7   increment_flow_control_window
ValueErrorr   rR   r8   close_connectionr   rT   	Exception)r;   rc   r{   r`   r~   s        r   rj   z*AsyncHTTP2Connection._handle_data_received   s    OO	zz!!),>DU3 t9q=::3t9PY:Z::3t9PT:U   ? ?@   $LL11^=^=^1_  ! s+   AB' ' D*C44	D=D DDc                     |j                   }| j                  j                  |      }|yd|_        t	        || j
                  | j                        S )zHandle StreamEnded event.NT)r{   r)   r   request_completer
   r%   r(   r;   rc   r{   r~   s       r   rl   z)AsyncHTTP2Connection._handle_stream_ended  sH    OO	!!),>"&FDHHd.>.>??r   c                     |j                   }| j                  j                  |      }||j                  |j                         yy)zHandle StreamReset event.N)r{   r)   r   resetrK   r   s       r   rn   z)AsyncHTTP2Connection._handle_stream_reset  s<    OO	!!),LL))* r   c                     d| _         y)z"Handle ConnectionTerminated event.TNr8   rw   s     r   rt   z2AsyncHTTP2Connection._handle_connection_terminated$  s	    r   c                     |j                   }| j                  j                  |      }|y|j                  |j                         t        || j                  | j                        S )zHandle TrailersReceived event.N)r{   r)   r   receive_trailersr|   r
   r%   r(   r   s       r   rv   z.AsyncHTTP2Connection._handle_trailers_received(  sR    OO	!!),>.FDHHd.>.>??r   c                     | j                   j                  |j                        }|3|j                  |j                  |j
                  |j                         yy)zHandle PriorityUpdated event (PRIORITY frame).

        Args:
            event: PriorityUpdated event with priority info
        N)weight
depends_on	exclusive)r)   r   r{   update_priorityr   r   r   )r;   rc   r~   s      r   rq   z-AsyncHTTP2Connection._handle_priority_updated3  sQ     !!%//2""|| ++// #  r   c                   K   |dk  s|dk\  rt        d|       | j                  j                  |      }|t        d| d      dt        |      fg}|D ]/  \  }}|j	                  |j                         t        |      f       1 | j                  j                  ||d	       | j                          d{    y7 w)
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:statusFry   )	r   r)   r   rU   r_   lowerr7   send_headersrE   )r;   r{   statusr|   r~   response_headersnamevalues           r   send_informationalz'AsyncHTTP2Connection.send_informationalA  s      C<6S==fXFGG!!),>wyk<== 'F45" 	@KD%##TZZ\3u:$>?	@
 	!!)-=%!P%%'''s   B8C:C ;Cc                 \  K   | j                   j                  |      }|ydt        |      fg}|D ]/  \  }}|j                  |j	                         t        |      f       1 |du xs t        |      dk(  }		 | j                  j                  |||	       |j                  ||	       | j                          d{    |r*t        |      dkD  r| j                  ||d       d{    y7 17 # t        j                  $ r$ |j                          | j                  |       Y yw xY ww)aX  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

        Returns:
            bool: True if response sent, False if stream was already closed
        NFr   r   ry   T)r)   r   rU   r_   r   r   r7   r   rE   	send_datar   StreamClosedErrorrS   cleanup_stream)
r;   r{   r   r|   bodyr~   r   r   r   rz   s
             r   send_responsez"AsyncHTTP2Connection.send_responsea  s+     !!),> 'F45" 	@KD%##TZZ\3u:$>?	@ T\3SY!^
	LL%%i1Aj%Y 0ZH))+++ D	AnnYnFFF , G// 	LLN	*		sO   A5D,8AC2 <C.=+C2 (C0)C2 -D,.C2 0C2 24D)&D,(D))D,c                   K   d}t        |      D ]  }| j                  j                  |      }|dkD  r|c S 	 t        j                  | j
                  j                  | j                        d       d{   }|r| j                  j                  |      }|D ]S  }t        |t        j                        r|j                  |k(  s-  yt        |t        j                        sKd| _          y | j                          d{    n	d| _         y | j                  j                  |      S 7 7 .# t        j                   $ r Y :t"        j$                  $ r Y  yw xY ww)zWait for flow control window to become positive.

        Returns:
            int: Available window size, or -1 if waiting failed
        2   r   g?rH   NT)ranger7   local_flow_control_windowr*   rL   r&   rM   rN   rQ   rf   r   rm   r{   rs   r8   rE   TimeoutErrorr   r]   )r;   r{   max_wait_attempts_	availableincomingr   rc   s           r   _wait_for_flow_control_windowz2AsyncHTTP2Connection._wait_for_flow_control_window  sK     () 	A>>yII1}  !(!1!1KK$$T%:%:;"  !\\66x@F!' &%eZ-C-CD$);')'z/N/NO+/DL#%& 11333 $(DL	 4+	> ||55i@@1 4
 '' !// s}   6E#=D46D07AD4D4E#
D4%D4-E#/D4D2D4 E#0D42D44E E#
E E#E  E#c                   K   | j                   j                  |      }|y|}	 |r| j                  j                  |      }t	        || j
                  t        |            }|dk  rW| j                          d{    | j                  |       d{   }|dk  ryt	        || j
                  t        |            }|d| }||d }|xr t        |      dk(  }	| j                  j                  |||	       | j                          d{    |r|j                  ||       y7 7 7 # t        j                  t        j                  f$ r$ |j                          | j                  |       Y yw xY w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   ry   T)r)   r   r7   r   minr2   r   rE   r   r   r   r   rR   rS   r   )
r;   r{   r`   rz   r~   data_to_sendr   
chunk_sizechunkis_finals
             r   r   zAsyncHTTP2Connection.send_data  sk     !!),>	 LLBB9M	 D,?,?\ARS
?11333&*&H&H&S SI A~$!$Y0C0CSEV!WJ$[j1+JK8%@#l*;q*@&&y%H&M--///# & Tj9 4 S 0 00.2Q2QR 	LLN	*	ss   !E6AD, 9D&:D, D(	D, E6A-D, 
D*D, D, %E6&D, (D, *D, ,AE30E62E33E6c                   K   | j                   j                  |      }|y|j                  syg }|D ]Q  \  }}|j                         }|j	                  d      rt        d| d      |j                  |t        |      f       S 	 | j                  j                  ||d       |j                  |       | j                          d{    y7 # t        j                  $ r$ |j                          | j                  |       Y yw xY w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 trailersTry   )r)   r   response_headers_sentr   
startswithr   r_   rU   r7   r   send_trailersrE   r   r   rS   r   )r;   r{   trailersr~   trailer_headersr   r   lnames           r   r   z"AsyncHTTP2Connection.send_trailers  s      !!),>++ # 	8KD%JJLE$ ?4&8Q!RSS""E3u:#67		8
	LL%%iT%R  1))+++ ,// 	LLN	*		s=   BDAC 	C
C DC 4DDDDc                    K   |r|j                         nd}dt        t        |            fg}|r|j                  d       | j	                  ||||       d{    y7 w)z#Send an error response on a stream.r   zcontent-length)zcontent-typeztext/plain; charset=utf-8N)encoderU   r   r_   r   )r;   r{   status_codemessager   r|   s         r   
send_errorzAsyncHTTP2Connection.send_error  sU     #*w~~$c#d)n56NNHI  K$GGGs   AA AA c                    K   | j                   j                  |      }||j                  |       | j                  j	                  ||       | j                          d{    y7 w)zReset a stream with RST_STREAM.NrJ   )r)   r   r   r7   reset_streamrE   )r;   r{   rK   r~   s       r   r   z!AsyncHTTP2Connection.reset_stream  sU     !!),LL$!!)
!C%%'''s   AA)!A'"A)c                   K   | j                   ryd| _         |1| j                  r#t        | j                  j                               nd}	 | j                  j                  |       | j                          d{    	 | j                  j                          | j                  j                          d{    y7 B# t        $ r Y Kw xY w7 # t        $ r Y yw xY ww)z,Close the connection gracefully with GOAWAY.NTr   rJ   )r8   r)   maxkeysr7   r   rE   r   r'   rS   wait_closed)r;   rK   last_stream_ids      r   rS   zAsyncHTTP2Connection.close  s     <<!9=S!2!2!451N	LL))Z)@))+++	KK++))+++ , 		
 , 		sl   AC/B? :B=;B?  7C 7C8C <C=B? ?	CC
CCC 	CCCCc                   K   | j                   j                         }|r?	 | j                  j                  |       | j                  j	                          d{    yy7 # t
        t        f$ r}d| _        t        d|       d}~ww xY ww)z,Send any pending data from h2 to the socket.NTzSocket write error: )	r7   r   r'   writedrainrO   rP   r8   r   )r;   r`   ra   s      r   rE   z'AsyncHTTP2Connection._send_pending_data0  s     ||((*G!!$'kk'')))  *W% G#*-A!+EFFGs:   B8A! AA! BA! !B
0BB

Bc                     | j                   S )zCheck if connection is closed.r   rF   s    r   	is_closedzAsyncHTTP2Connection.is_closed;  s     ||r   c                 <    | j                   j                  |d       y)z-Remove a stream after processing is complete.N)r)   pop)r;   r{   s     r   r   z#AsyncHTTP2Connection.cleanup_stream@  s    D)r   c                 N    dt        | j                         d| j                   dS )Nz<AsyncHTTP2Connection streams=z closed=>)r   r)   r8   rF   s    r   __repr__zAsyncHTTP2Connection.__repr__D  s0    4<<() *ll^1&	
r   )N)F)   )r   N)__name__
__module____qualname____doc__rN   r<   rD   rQ   r^   rh   rj   rl   rn   rt   rv   rq   r   r   r   r   r   r   r   rS   rE   propertyr   r   r   r   r   r   r!   r!   0   s     )"V!*F"P$L
::	@+	@(@&P&AP)V*XH(,	G  *
r   r!   )r   r*   errorsr   r   r   r   r   r~   r	   rd   r
   r   r   r   r   r   r   r!   __all__r   r   r   <module>r      sX        ! 

""Y
 Y
x "
"r   