o
    .j.                     @  s   d dl mZ d dlZd dlmZmZmZ ddlmZ ddl	m
Z
mZ eegdf Zeejejgdf ZG dd dejZG d	d
 d
ejZdS )    )annotationsN)AnyCallablecast   )events)NetworkAddressQuicConnectionc                   @  s   e Zd Z	d;d<ddZd=d
dZd=ddZd>ddZ	d?d@ddZd=ddZd=ddZ	d=ddZ
d=ddZd=d d!ZdAd$d%ZdBd(d)ZdCd+d,ZdDd/d0ZdEd3d4Zd=d5d6Zd=d7d8Zd=d9d:ZdS )FQuicConnectionProtocolNquicr	   stream_handlerQuicStreamHandler | Nonec                 C  s   t  }t  | _d| _d | _|| _|j| _i | _	|| _
i | _t | _d | _d | _d | _d | _d | _dd | _dd | _dd | _|d urJ|| _d S dd | _d S )NFc                 S     d S N cr   r   I/home/thesage/.local/lib/python3.10/site-packages/qh3/asyncio/protocol.py<lambda>#       z1QuicConnectionProtocol.__init__.<locals>.<lambda>c                 S  r   r   r   r   r   r   r   r   $   r   c                   S  r   r   r   r   r   r   r   r   %   r   c                 S  r   r   r   )rwr   r   r   r   )   r   )asyncioget_running_loopEvent_closed
_connected_connected_waiter_looptime
_loop_time_ping_waiters_quic_stream_readersset_stream_readers_done_timer	_timer_at_transmit_task
_transport_sendto_many_connection_id_issued_handler_connection_id_retired_handler_connection_terminated_handler_stream_handler)selfr   r   loopr   r   r   __init__   s*   




zQuicConnectionProtocol.__init__returnNonec                 C     | j   |   dS )z
        Change the connection ID used to communicate with the peer.

        The previous connection ID will be retired.
        N)r"   change_connection_idtransmitr/   r   r   r   r5   +   s   
z+QuicConnectionProtocol.change_connection_idc                 C  r4   )z'
        Close the connection.
        N)r"   closer6   r7   r   r   r   r8   4      
zQuicConnectionProtocol.closeaddrr   c                 C  s    | j j||  d |   dS )zt
        Initiate the TLS handshake.

        This method can only be called for clients and a single time.
        nowN)r"   connectr    r6   )r/   r:   r   r   r   r=   ;   s   zQuicConnectionProtocol.connectFis_unidirectionalbool1tuple[asyncio.StreamReader, asyncio.StreamWriter]c                   s   | j j|d}| |S )z
        Create a QUIC stream and return a pair of (reader, writer) objects.

        The returned reader and writer objects are instances of
        :class:`asyncio.StreamReader` and :class:`asyncio.StreamWriter` classes.
        )r>   )r"   get_next_available_stream_id_create_stream)r/   r>   	stream_idr   r   r   create_streamD   s
   	
z$QuicConnectionProtocol.create_streamc                 C  r4   )z;
        Request an update of the encryption keys.
        N)r"   request_key_updater6   r7   r   r   r   rE   R   r9   z)QuicConnectionProtocol.request_key_updatec                   sF   | j  }t|}|| j|< | j| |   t|I dH  dS )z:
        Ping the peer and wait for the response.
        N)	r   create_futureidr!   r"   	send_pingr6   r   shield)r/   waiteruidr   r   r   pingY   s   

zQuicConnectionProtocol.pingc           	      C  s   d| _ |  }| j}|dur-g }d}| jj|dD ]\}}|| |}q|r,||| n| j}| jj|dD ]
\}}||| q7| j }| j	durY| j
|krY| j	  d| _	| j	du rk|durk| j|| j| _	|| _
dS )zQ
        Send pending datagrams to the peer and arm the timer if needed.
        Nr;   )r(   r    r*   r"   datagrams_to_sendappendr)   sendto	get_timerr&   r'   cancelr   call_at_handle_timer)	r/   r<   sendto_many	datagrams	send_addrdatar:   	transporttimer_atr   r   r   r6   d   s,   




zQuicConnectionProtocol.transmitc                   s   | j  I dH  dS )z7
        Wait for the connection to be closed.
        N)r   waitr7   r   r   r   wait_closed   s   z"QuicConnectionProtocol.wait_closedc                   s@   | j du s
J d| js| j | _ t| j I dH  dS dS )z9
        Wait for the TLS handshake to complete.
        Nzalready awaiting connected)r   r   r   rF   r   rI   r7   r   r   r   wait_connected   s   z%QuicConnectionProtocol.wait_connectedrX   asyncio.BaseTransportc                 C  s    t tj|| _t|dd | _d S )NrT   )r   r   DatagramTransportr)   getattrr*   )r/   rX   r   r   r   connection_made   s   z&QuicConnectionProtocol.connection_maderW   bytes | strc                 C  s0   | j jtt|||  d |   |   d S Nr;   )r"   receive_datagramr   bytesr    _process_eventsr6   )r/   rW   r:   r   r   r   datagram_received   s   z(QuicConnectionProtocol.datagram_receivedlist[bytes]c                 C  s<   |   }| jj}|D ]	}||||d q
|   |   d S rb   )r    r"   rc   re   r6   )r/   rW   r:   r<   receivedgramr   r   r   datagrams_received   s   z)QuicConnectionProtocol.datagrams_receivedeventevents.QuicEventc                 C  sZ  t |tjr| j D ]}|  qdS t |tjrM| j|jd}|du r<|j| j	v r.dS | 
|j\}}| || ||j |jrK|  dS dS t |tjr| j|jd}|dur|td|j d|j d | j|jd | j	|j dS dS t |tjr| j|jd}|dur|  | j|jd | j	|j dS dS dS )zx
        Called when a QUIC event is received.

        Reimplement this in your subclass to handle the events.
        NzStream z reset by peer (error code ))
isinstancer   ConnectionTerminatedr#   valuesfeed_eofStreamDataReceivedgetrC   r%   rB   r.   	feed_datarW   
end_streamStreamResetset_exceptionConnectionResetError
error_codepopaddStopSendingReceived)r/   rk   readerwriterr   r   r   quic_event_received   sH   

	z*QuicConnectionProtocol.quic_event_receivedrC   intc                 C  s6   t | |}t }t|d || j}|| j|< ||fS r   )QuicStreamAdapterr   StreamReaderStreamWriterr   r#   )r/   rC   adapterr}   r~   r   r   r   rB      s
   

z%QuicConnectionProtocol._create_streamc                 C  s@   t | j| j }d | _d | _| jj|d |   |   d S rb   )	maxr'   r   r   r&   r"   handle_timerre   r6   )r/   r<   r   r   r   rS      s   z$QuicConnectionProtocol._handle_timerc                 C  s6  | j }| j}| }|d urt|tjr| |j npt|tjr(| 	|j nct|tj
rZ|   | jd urB| j}d | _|t | j D ]}|t qG| j  | j  n1t|tjrt| jd urs| j}d| _d | _|d  nt|tjr| j|jd }|d ur|d  || | }|d usd S d S NT)r"   r   
next_eventrn   r   ConnectionIdIssuedr+   connection_idConnectionIdRetiredr,   ro   r-   r   rw   ConnectionErrorr!   rp   clearr   r$   HandshakeCompletedr   
set_resultPingAcknowledgedrz   rK   )r/   r   r   rk   rJ   r   r   r   re      s@   





z&QuicConnectionProtocol._process_eventsc                 C  s"   | j d u r| j| j| _ d S d S r   )r(   r   	call_soonr6   r7   r   r   r   _transmit_soon  s   
z%QuicConnectionProtocol._transmit_soonr   )r   r	   r   r   r2   r3   )r:   r   r2   r3   )F)r>   r?   r2   r@   )rX   r]   r2   r3   )rW   ra   r:   r   r2   r3   )rW   rg   r:   r   r2   r3   )rk   rl   r2   r3   )rC   r   r2   r@   )__name__
__module____qualname__r1   r5   r8   r=   rD   rE   rL   r6   r[   r\   r`   rf   rj   r   rB   rS   re   r   r   r   r   r   r
      s*    

	





 






1
	
&r
   c                      s\   e Zd Zd fddZdd	d
ZddddZdddZdddZdddZdddZ	  Z
S ) r   protocolr
   rC   r   c                   s    t    || _|| _d| _d S )NF)superr1   r   rC   _closing)r/   r   rC   	__class__r   r   r1     s   

zQuicStreamAdapter.__init__r2   r?   c                 C  s   dS r   r   r7   r   r   r   can_write_eof  s   zQuicStreamAdapter.can_write_eofNnamestrdefaultr   c                 C  s   |dkr| j S dS )zC
        Get information about the underlying QUIC stream.
        rC   N)rC   )r/   r   r   r   r   r   get_extra_info   s   z QuicStreamAdapter.get_extra_infor3   c                 C  s    | j j| j| | j   d S r   )r   r"   send_stream_datarC   r   )r/   rW   r   r   r   write'  s   zQuicStreamAdapter.writec              	   C  s   | j rd S d| _ | jjj| j}|d u rd S |j}|js |jr"d S z| jjj	| jddd W n t
tfy;   Y d S w | j  d S )NT    )ru   )r   r   r"   _streamsrs   rC   senderis_finishedreset_pendingr   AssertionErrorKeyErrorr   )r/   streamr   r   r   r   	write_eof+  s$   
zQuicStreamAdapter.write_eofc                 C  s   |    d S r   )r   r7   r   r   r   r8   >  s   zQuicStreamAdapter.closec                 C  s   | j S r   )r   r7   r   r   r   
is_closingA  s   zQuicStreamAdapter.is_closing)r   r
   rC   r   )r2   r?   r   )r   r   r   r   r2   r   r   )r   r   r   r1   r   r   r   r   r8   r   __classcell__r   r   r   r   r     s    



r   )
__future__r   r   typingr   r   r   r   r   quic.connectionr   r	   rd   QuicConnectionIdHandlerr   r   QuicStreamHandlerDatagramProtocolr
   	Transportr   r   r   r   r   <module>   s      
