U
    h]                     @  s
  d dl mZ d dlZd dlZd dlZd dlZd dlZd dlZd dl	Zd dl
Zd dlZd dlZddlmZ ddlmZmZmZ ddlmZmZmZ ddlmZmZmZ ddlmZ d	d
lmZ edZ dddddZ!G dd dej"Z#G dd deZ$G dd dZ%dS )    )annotationsN   )AsyncNetworkStream)ConnectionNotAvailableLocalProtocolErrorRemoteProtocolError)OriginRequestResponse)	AsyncLockAsyncSemaphoreAsyncShieldCancellation)Trace   )AsyncConnectionInterfacezhttpcore.http2r	   boolrequestreturnc                 C  s   t dd | jD S )Nc                 s  s*   | ]"\}}|  d kp |  dkV  qdS )s   content-length   transfer-encodingNlower.0kv r   9/tmp/pip-unpacked-wheel-a8helrha/httpcore/_async/http2.py	<genexpr>   s   z#has_body_headers.<locals>.<genexpr>)anyheaders)r   r   r   r   has_body_headers   s    r!   c                   @  s   e Zd ZdZdZdZdS )HTTPConnectionStater   r      N)__name__
__module____qualname__ACTIVEIDLECLOSEDr   r   r   r   r"   $   s   r"   c                   @  s  e Zd ZdZejjddZdUddddd	d
ZdddddZ	dddddZ
ddddddZddddddZdddddddZddddddZddddd d!Zddd"dd#d$Zddd%dd&d'ZdVdd(ddd)d*Zd+dd,d-d.Zddd/d0d1Zdd2d3d4Zdd5dd6d7Zdddd8d9Zddddd:d;Zdd<d=d>d?Zd<d2d@dAZd<d2dBdCZd<d2dDdEZd<d2dFdGZdHd2dIdJZdHd2dKdLZd d2dMdNZ dWdOdPdQddRdSdTZ!dS )XAsyncHTTP2Connection   F)Zvalidate_inbound_headersNr   r   zfloat | None)originstreamkeepalive_expiryc                 C  s   || _ || _|| _tjj| jd| _tj	| _
d | _d| _t | _t | _t | _t | _d| _d| _d| _i | _d | _d | _d | _d S )N)configr   F)_origin_network_stream_keepalive_expiryh2
connectionZH2ConnectionCONFIG	_h2_stater"   r(   _state
_expire_at_request_countr   
_init_lock_state_lock
_read_lock_write_lock_sent_connection_init_used_all_stream_ids_connection_error_events_connection_terminated_read_exception_write_exception)selfr,   r-   r.   r   r   r   __init__.   s&    zAsyncHTTP2Connection.__init__r	   r
   r   c                   sx  |  |jjs(td|jj d| j | j4 I d H < | jtjtj	fkrh|  j
d7  _
d | _tj| _nt W 5 Q I d H R X | j4 I d H  | jslzFd|i}tdt||4 I d H  | jf |I d H  W 5 Q I d H R X W nH tk
r$ } z(t  |  I d H  W 5 Q R X |W 5 d }~X Y nX d| _d| _| jjj}t|| _t|| j D ]}| j I d H  qTW 5 Q I d H R X | j I d H  z| j }g | j|< W n4 tj j!k
r   d| _"|  j
d8  _
t Y nX z||d}tdt||4 I d H  | j#||dI d H  W 5 Q I d H R X td	t||4 I d H  | j$||dI d H  W 5 Q I d H R X td
t||4 I d H (}| j%||dI d H \}	}
|	|
f|_&W 5 Q I d H R X t'|	|
t(| ||dd| j)|ddW S  tk
rr } zt H d|i}tdt||4 I d H  | j*|dI d H  W 5 Q I d H R X W 5 Q R X t+|tj j,r^| j-rVt.| j-t/||W 5 d }~X Y nX d S )NzAttempted to send request to z on connection to r   r   Zsend_connection_initTr   	stream_idZsend_request_headersZsend_request_bodyZreceive_response_headersrH   s   HTTP/2)http_versionZnetwork_streamrH   )statusr    content
extensionsrH   response_closed)0can_handle_requesturlr,   RuntimeErrorr0   r;   r7   r"   r'   r(   r9   r8   r   r:   r>   r   logger_send_connection_initBaseExceptionr   aclose_max_streamsr6   local_settingsmax_concurrent_streamsr   _max_streams_semaphorerangeacquireZget_next_available_stream_idrA   r3   
exceptionsZNoAvailableStreamIDErrorr?   _send_request_headers_send_request_body_receive_responsereturn_valuer
   HTTP2ConnectionByteStreamr1   _response_closed
isinstanceProtocolErrorrB   r   r   )rE   r   Z
sci_kwargsexcZlocal_settings_max_streams_rH   kwargstracerK   r    r   r   r   handle_async_requestU   s    
   &
$

$$    
,

z)AsyncHTTP2Connection.handle_async_requestNonec                   sl   t jjdt jjjdt jjjdt jjjdid| j_| jjt jjj	= | j
  | jd | |I dH  dS )z
        The HTTP/2 connection requires some initial setup before we can start
        using individual request/response streams on it.
        Tr   d   r+   )clientZinitial_values   N)r3   settingsZSettingsSettingCodesZENABLE_PUSHMAX_CONCURRENT_STREAMSZMAX_HEADER_LIST_SIZEr6   rW   ZENABLE_CONNECT_PROTOCOLZinitiate_connectionincrement_flow_control_window_write_outgoing_data)rE   r   r   r   r   rS      s        

z*AsyncHTTP2Connection._send_connection_initint)r   rH   r   c                   s   t | }dd |jD d }d|jfd|fd|jjfd|jjfgdd |jD  }| jj|||d	 | jjd
|d | 	|I dH  dS )z@
        Send the request headers to a given stream ID.
        c                 S  s    g | ]\}}|  d kr|qS )   hostr   r   r   r   r   
<listcomp>   s      z>AsyncHTTP2Connection._send_request_headers.<locals>.<listcomp>r   s   :methods
   :authoritys   :schemes   :pathc                 S  s(   g | ] \}}|  d kr|  |fqS ))rt   r   r   r   r   r   r   ru      s
   )
end_streamrm   rI   N)
r!   r    methodrP   schemetargetr6   send_headersrq   rr   )rE   r   rH   rv   	authorityr    r   r   r   r]      s    


z*AsyncHTTP2Connection._send_request_headersc                   s^   t |sdS t|jtjst|j2 z 3 dH W }| |||I dH  q$6 | ||I dH  dS )zP
        Iterate over the request body sending it to a given stream ID.
        N)r!   rc   r-   typingAsyncIterableAssertionError_send_stream_data_send_end_stream)rE   r   rH   datar   r   r   r^      s    z'AsyncHTTP2Connection._send_request_bodybytes)r   rH   r   r   c                   sb   |r^|  ||I dH }tt||}|d| ||d  }}| j|| | |I dH  q dS )zI
        Send a single chunk of data in one or more data frames.
        N)_wait_for_outgoing_flowminlenr6   Z	send_datarr   )rE   r   rH   r   Zmax_flow
chunk_sizechunkr   r   r   r   	  s    z&AsyncHTTP2Connection._send_stream_datac                   s    | j | | |I dH  dS )z`
        Send an empty data frame on on a given stream ID with the END_STREAM flag set.
        N)r6   rv   rr   )rE   r   rH   r   r   r   r     s    z%AsyncHTTP2Connection._send_end_streamz%tuple[int, list[tuple[bytes, bytes]]]c                   s   |  ||I dH }t|tjjr q$q d}g }|jdk	s:t|jD ]<\}}|dkrdt|jddd}q@|	ds@|
||f q@||fS )zT
        Return the response status code and headers for a given stream ID.
        N   s   :statusasciiignore)errors   :)_receive_stream_eventrc   r3   eventsResponseReceivedr    r~   rs   decode
startswithappend)rE   r   rH   eventstatus_coder    r   r   r   r   r   r_     s    
z&AsyncHTTP2Connection._receive_responsetyping.AsyncIterator[bytes]c                 C s   |  ||I dH }t|tjjrj|jdk	s.t|jdk	s<t|j}| j	|| | 
|I dH  |jV  q t|tjjr q|q dS )z]
        Iterator that returns the bytes of the response body for a given stream ID.
        N)r   rc   r3   r   DataReceivedZflow_controlled_lengthr~   r   r6   Zacknowledge_received_datarr   StreamEnded)rE   r   rH   r   amountr   r   r   _receive_response_body5  s    
z+AsyncHTTP2Connection._receive_response_bodyzKh2.events.ResponseReceived | h2.events.DataReceived | h2.events.StreamEndedc                   sJ   | j |s | ||I dH  q | j | d}t|tjjrFt||S )z
        Return the next available event for a given stream ID.

        Will read more data from the network if required.
        Nr   )	rA   get_receive_eventspoprc   r3   r   StreamResetr   )rE   r   rH   r   r   r   r   r   G  s    z*AsyncHTTP2Connection._receive_stream_eventz
int | Nonec                   sL  | j 4 I dH  | jdk	rR| jj}|rH|rH||krH|  jd8  _t t| j|dksh| j|s(| |I dH }|D ]}t	|t
jjrtdt|4 I dH }| |I dH  ||_W 5 Q I dH R X q|t	|t
jjt
jjt
jjt
jjfr|j| jkr&| j|j | q|t	|t
jjr||| _q|W 5 Q I dH R X | |I dH  dS )zp
        Read some data from the network until we see one or more events
        for a given stream ID.
        Nr   Zreceive_remote_settings)r<   rB   last_stream_idr9   r   r   rA   r   _read_incoming_datarc   r3   r   ZRemoteSettingsChangedr   rR   _receive_remote_settings_changer`   r   r   r   r   rH   r   ZConnectionTerminatedrr   )rE   r   rH   r   r   r   rh   r   r   r   r   V  s@    

  	z$AsyncHTTP2Connection._receive_eventszh2.events.RemoteSettingsChanged)r   r   c                   s   |j tjjj}|rt|j| jj	j
}|r|| jkr|| jkr`| j I d H  |  jd7  _q6|| jk r| j I d H  |  jd8  _q`d S )Nr   )Zchanged_settingsr   r3   rn   ro   rp   r   	new_valuer6   rW   rX   rV   rY   releaser[   )rE   r   rX   Znew_max_streamsr   r   r   r     s    

z4AsyncHTTP2Connection._receive_remote_settings_change)rH   r   c              
     s   | j  I d H  | j|= | j4 I d H n | jrD| jsD|  I d H  nL| jtjkr| jstj	| _| j
d k	r|t }|| j
 | _| jr|  I d H  W 5 Q I d H R X d S N)rY   r   rA   r;   rB   rU   r7   r"   r'   r(   r2   time	monotonicr8   r?   )rE   rH   nowr   r   r   rb     s    
z%AsyncHTTP2Connection._response_closedr   c                   s&   | j   tj| _| j I d H  d S r   )r6   Zclose_connectionr"   r)   r7   r1   rU   rE   r   r   r   rU     s    
zAsyncHTTP2Connection.aclosezlist[h2.events.Event]c              
     s   |j di }|dd }| jd k	r*| jz*| j| j|I d H }|dkrRtdW n2 tk
r } z|| _d| _|W 5 d }~X Y nX | j	
|}|S )Ntimeoutread    zServer disconnectedT)rM   r   rC   r1   r   READ_NUM_BYTESr   	Exceptionr@   r6   Zreceive_data)rE   r   timeoutsr   r   re   r   r   r   r   r     s    
	z(AsyncHTTP2Connection._read_incoming_datac                   s   |j di }|dd }| j4 I d H l | j }| jd k	rD| jz| j||I d H  W n2 tk
r } z|| _d| _	|W 5 d }~X Y nX W 5 Q I d H R X d S )Nr   writeT)
rM   r   r=   r6   data_to_sendrD   r1   r   r   r@   )rE   r   r   r   r   re   r   r   r   rr     s    

	z)AsyncHTTP2Connection._write_outgoing_datac                   sZ   | j |}| j j}t||}|dkrV| |I dH  | j |}| j j}t||}q|S )a  
        Returns the maximum allowable outgoing flow for a given stream.

        If the allowable flow is zero, then waits on the network until
        WindowUpdated frames have increased the flow rate.
        https://tools.ietf.org/html/rfc7540#section-6.9
        r   N)r6   Zlocal_flow_control_windowZmax_outbound_frame_sizer   r   )rE   r   rH   Z
local_flowZmax_frame_sizeZflowr   r   r   r     s    
z,AsyncHTTP2Connection._wait_for_outgoing_flowr   )r,   r   c                 C  s
   || j kS r   )r0   rE   r,   r   r   r   rO     s    z'AsyncHTTP2Connection.can_handle_requestc                 C  s2   | j tjko0| j o0| j o0| jjjtj	j
jk S r   )r7   r"   r)   r@   r?   r6   Zstate_machinestater3   r4   ZConnectionStater   r   r   r   is_available  s    z!AsyncHTTP2Connection.is_availablec                 C  s   t  }| jd k	o|| jkS r   )r   r   r8   )rE   r   r   r   r   has_expired
  s    z AsyncHTTP2Connection.has_expiredc                 C  s   | j tjkS r   )r7   r"   r(   r   r   r   r   is_idle  s    zAsyncHTTP2Connection.is_idlec                 C  s   | j tjkS r   )r7   r"   r)   r   r   r   r   	is_closed  s    zAsyncHTTP2Connection.is_closedstrc                 C  s$   t | j}|d| jj d| j S )Nz
, HTTP/2, , Request Count: )r   r0   r7   namer9   r   r   r   r   info  s    
zAsyncHTTP2Connection.infoc              	   C  s6   | j j}t| j}d| d|d| jj d| j d	S )N<z [z, r   z]>)	__class__r$   r   r0   r7   r   r9   )rE   
class_namer,   r   r   r   __repr__  s    
"zAsyncHTTP2Connection.__repr__c                   s   | S r   r   r   r   r   r   
__aenter__&  s    zAsyncHTTP2Connection.__aenter__ztype[BaseException] | NonezBaseException | Noneztypes.TracebackType | None)exc_type	exc_value	tracebackr   c                   s   |   I d H  d S r   )rU   )rE   r   r   r   r   r   r   	__aexit__)  s    zAsyncHTTP2Connection.__aexit__)N)N)NNN)"r$   r%   r&   r   r3   r/   ZH2Configurationr5   rF   ri   rS   r]   r^   r   r   r_   r   r   r   r   rb   rU   r   rr   r   rO   r   r   r   r   r   r   r   r   r   r   r   r   r*   *   sB    'h!	 0	   r*   c                   @  s<   e Zd ZdddddddZdd	d
dZdd	ddZdS )ra   r*   r	   rs   rj   )r4   r   rH   r   c                 C  s   || _ || _|| _d| _d S )NF)_connection_request
_stream_id_closed)rE   r4   r   rH   r   r   r   rF   3  s    z"HTTP2ConnectionByteStream.__init__r   r   c                 C s   | j | jd}zXtdt| j |4 I d H 0 | jj| j | jd2 z3 d H W }|V  q>6 W 5 Q I d H R X W nF tk
r } z(t  |  I d H  W 5 Q R X |W 5 d }~X Y nX d S )NrG   Zreceive_response_body)	r   r   r   rR   r   r   rT   r   rU   )rE   rg   r   re   r   r   r   	__aiter__;  s     z#HTTP2ConnectionByteStream.__aiter__c              
     sZ   | j sVd| _ d| ji}tdt| j|4 I d H  | jj| jdI d H  W 5 Q I d H R X d S )NTrH   rN   rI   )r   r   r   rR   r   r   rb   )rE   rg   r   r   r   rU   K  s
    
z HTTP2ConnectionByteStream.acloseN)r$   r%   r&   rF   r   rU   r   r   r   r   ra   2  s   ra   )&
__future__r   enumloggingr   typesr|   Z	h2.configr3   Zh2.connectionZ	h2.eventsZh2.exceptionsZh2.settingsZ_backends.baser   _exceptionsr   r   r   Z_modelsr   r	   r
   Z_synchronizationr   r   r   Z_tracer   Z
interfacesr   	getLoggerrR   r!   IntEnumr"   r*   ra   r   r   r   r   <module>   s2   
    