U
    \eG]                     @   s   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eedddZ G dd de j!Z"G dd deZ#G dd dZ$dS )    N   )AsyncNetworkStream)ConnectionNotAvailableLocalProtocolErrorRemoteProtocolError)OriginRequestResponse)	AsyncLockAsyncSemaphoreAsyncShieldCancellation)Trace   )AsyncConnectionInterfacezhttpcore.http2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-4txt3dqh/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dBee	e
je dddZeedd	d
ZeddddZeeddddZeeddddZeeeddddZeeddddZeee
jee
je
jeef  f dddZeee
je dddZeee
jejjejj ejj!f dddZ"dCee
je ddddZ#ejj$ddd d!Z%edd"d#d$Z&dd%d&d'Z'ee
jejj$ dd(d)Z(eddd*d+Z)eeedd,d-Z*ee+d.d/d0Z,e+d%d1d2Z-e+d%d3d4Z.e+d%d5d6Z/e+d%d7d8Z0e1d%d9d:Z2e1d%d;d<Z3d d%d=d>Z4dDe
je
j5e6  e
je6 e
je7j8 dd?d@dAZ9dS )EAsyncHTTP2Connection   F)Zvalidate_inbound_headersN)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   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rF   s   HTTP/2)http_versionZnetwork_streamrF   )statusr   content
extensionsrF   response_closed)0can_handle_requesturlr*   RuntimeErrorr.   r9   r5   r    r%   r&   r7   r6   r   r8   r<   r   logger_send_connection_initBaseExceptionr   aclose_max_streamsr4   local_settingsmax_concurrent_streamsr   _max_streams_semaphorerangeacquireZget_next_available_stream_idr?   r1   
exceptionsZNoAvailableStreamIDErrorr=   _send_request_headers_send_request_body_receive_responsereturn_valuer	   HTTP2ConnectionByteStreamr/   _response_closed
isinstanceProtocolErrorr@   r   r   )
rC   r   kwargsexcZlocal_settings_max_streams_rF   tracerI   r   r   r   r   handle_async_requestU   s    
&
$

$$    
,

z)AsyncHTTP2Connection.handle_async_requestc                    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)r1   settingsZSettingsSettingCodesZENABLE_PUSHMAX_CONCURRENT_STREAMSZMAX_HEADER_LIST_SIZEr4   rU   ZENABLE_CONNECT_PROTOCOLZinitiate_connectionincrement_flow_control_window_write_outgoing_data)rC   r   r   r   r   rQ      s        

z*AsyncHTTP2Connection._send_connection_init)r   rF   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 ))rp   r   r   r   r   r   r   rq      s
   )
end_streamrj   rG   N)
r   r   methodrN   schemetargetr4   send_headersrn   ro   )rC   r   rF   rr   	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   ra   r+   typingAsyncIterableAssertionError_send_stream_data_send_end_stream)rC   r   rF   datar   r   r   r\      s    z'AsyncHTTP2Connection._send_request_body)r   rF   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lenr4   Z	send_dataro   )rC   r   rF   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)r4   rr   ro   )rC   r   rF   r   r   r   r|     s    z%AsyncHTTP2Connection._send_end_streamc                    sx   |  ||I dH }t|tjjr q$q d}g }|jD ]<\}}|dkrVt|jddd}q2|ds2|	||f q2||fS )zT
        Return the response status code and headers for a given stream ID.
        N   s   :statusasciiignore)errors   :)
_receive_stream_eventra   r1   eventsResponseReceivedr   intdecode
startswithappend)rC   r   rF   eventstatus_coder   r   r   r   r   r   r]     s    
z&AsyncHTTP2Connection._receive_responsec                 C  sd   |  ||I dH }t|tjjrN|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   ra   r1   r   DataReceivedZflow_controlled_lengthr4   Zacknowledge_received_dataro   r}   StreamEnded)rC   r   rF   r   amountr   r   r   _receive_response_body2  s    
z+AsyncHTTP2Connection._receive_response_bodyc                    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   )	r?   get_receive_eventspopra   r1   r   StreamResetr   )rC   r   rF   r   r   r   r   r   B  s    
z*AsyncHTTP2Connection._receive_stream_eventc                    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:   r@   last_stream_idr7   r   r   r?   r   _read_incoming_datara   r1   r   ZRemoteSettingsChangedr   rP   _receive_remote_settings_changer^   r   r   r   r   rF   r   ZConnectionTerminatedro   )rC   r   rF   r   r   r   rf   r   r   r   r   S  s@    

  	z$AsyncHTTP2Connection._receive_events)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   r1   rk   rl   rm   r   	new_valuer4   rU   rV   rT   rW   releaserY   )rC   r   rV   Znew_max_streamsr   r   r   r     s    

z4AsyncHTTP2Connection._receive_remote_settings_change)rF   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)rW   r   r?   r9   r@   rS   r5   r    r%   r&   r0   time	monotonicr6   r=   )rC   rF   nowr   r   r   r`     s    
z%AsyncHTTP2Connection._response_closedr   c                    s&   | j   tj| _| j I d H  d S r   )r4   Zclose_connectionr    r'   r5   r/   rS   rC   r   r   r   rS     s    
zAsyncHTTP2Connection.aclosec              
      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)rK   r   rA   r/   r   READ_NUM_BYTESr   	Exceptionr>   r4   Zreceive_data)rC   r   timeoutsr   r}   rd   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)
rK   r   r;   r4   data_to_sendrB   r/   r   r   r>   )rC   r   r   r   r   rd   r   r   r   ro     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)r4   Zlocal_flow_control_windowZmax_outbound_frame_sizer   r   )rC   r   rF   Z
local_flowZmax_frame_sizeZflowr   r   r   r~     s    
z,AsyncHTTP2Connection._wait_for_outgoing_flow)r*   r   c                 C   s
   || j kS r   )r.   rC   r*   r   r   r   rM     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   )r5   r    r'   r>   r=   r4   Zstate_machinestater1   r2   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   r6   )rC   r   r   r   r   has_expired  s    z AsyncHTTP2Connection.has_expiredc                 C   s   | j tjkS r   )r5   r    r&   r   r   r   r   is_idle  s    zAsyncHTTP2Connection.is_idlec                 C   s   | j tjkS r   )r5   r    r'   r   r   r   r   	is_closed  s    zAsyncHTTP2Connection.is_closedc                 C   s$   t | j}|d| jj d| j S )Nz
, HTTP/2, , Request Count: )strr.   r5   namer7   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   r.   r5   r   r7   )rC   
class_namer*   r   r   r   __repr__  s    
"zAsyncHTTP2Connection.__repr__c                    s   | S r   r   r   r   r   r   
__aenter__#  s    zAsyncHTTP2Connection.__aenter__)exc_type	exc_value	tracebackr   c                    s   |   I d H  d S r   )rS   )rC   r   r   r   r   r   r   	__aexit__&  s    zAsyncHTTP2Connection.__aexit__)N)N)NNN):r"   r#   r$   r   r1   r-   ZH2Configurationr3   r   r   rx   OptionalfloatrD   r   r	   rg   rQ   r   r[   r\   bytesr{   r|   TupleListr]   AsyncIteratorr   Unionr   r   r   r   r   r   Eventr   r`   rS   r   ro   r~   boolrM   r   r   r   r   r   r   r   r   TyperR   typesTracebackTyper   r   r   r   r   r(   (   s~    )f!  
     0
   
r(   c                   @   sB   e Zd ZeeeddddZeje	 dddZ
dddd	ZdS )
r_   N)r2   r   rF   r   c                 C   s   || _ || _|| _d| _d S )NF)_connection_request
_stream_id_closed)rC   r2   r   rF   r   r   r   rD   0  s    z"HTTP2ConnectionByteStream.__init__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 )NrE   Zreceive_response_body)	r   r   r   rP   r   r   rR   r   rS   )rC   rc   r   rd   r   r   r   	__aiter__8  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 )NTrF   rL   rG   )r   r   r   rP   r   r   r`   )rC   rc   r   r   r   rS   H  s
    
z HTTP2ConnectionByteStream.aclose)r"   r#   r$   r(   r   r   rD   rx   r   r   r   rS   r   r   r   r   r_   /  s     r_   )%enumloggingr   r   rx   Z	h2.configr1   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   	getLoggerrP   r   r   IntEnumr    r(   r_   r   r   r   r   <module>   s0   
    