o
    .j                    @  s  U d dl mZ d dlZd dlZd dlZd dlmZ d dlmZ d dl	m
Z
 d dlmZmZ d dlmZmZmZ erEdd	lmZ dd
lmZ ddlmZ ddlmZmZ ddlmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$ ddlm%Z& ddlm'Z( ddlm)Z* ddlm+Z+ ddl,m-Z-m.Z.m/Z/m0Z0 ddl1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@mAZAmBZB ddlCmDZDmEZEmFZFmGZGmHZH ddlImJZJmKZKmLZL ddlMmNZNmOZOmPZP eQdZdZRejSjTejSjUejSjVejSjWdZXdZYdZZdZ[dZ\g dg d gZ]d!Z^d"Z_d#Z`d$ZaeZbd%Zcdde  Zdde ZedZfdde  Zgdde  d e2 e6 Zhd&Zid&ZjdZkdd'e  Zlde Zmdde  Znde Zodd'e  Zpd]d,d-Zqd^d2d3Zrd_d6d7Zsd8d9 e:D Ztd:eud;< e:jTejSjTe:jVejSjVe:jUejSjUe:jvejSjWe:jwejSjWe:jWejSjWiZxd<eud=< d`dAdBZydadDdEZzdadFdGZ{e dbdIdJZ|e dbdKdLZ}G dMdN dNZ~G dOdP dPeZG dQdR dRejZedci eG dSdT dTZG dUdV dVe
ZG dWdX dXZedci eG dYdZ dZZeejejejgZG d[d\ d\ZdS )d    )annotationsN)deque)	dataclass)IntEnum)	lru_cachepartial)TYPE_CHECKINGAnySequence   )QuicConfiguration)QuicLoggerTrace   )tls)DATACLASS_KWARGSUINT_VAR_MAX_SIZE)	BufferBufferReadErrorpull_ack_framepull_crypto_framepull_stream_framepush_ack_framepush_crypto_frame_bodypush_stream_frame_bodysize_uint_var)Certificate)pull_quic_header)skip_padding)events)CryptoError
CryptoPairKeyUnavailableError
NoCallback)CONNECTION_ID_MAX_SIZENON_ACK_ELICITING_FRAME_TYPESPROBING_FRAME_TYPESRETRY_INTEGRITY_TAG_SIZESTATELESS_RESET_TOKEN_SIZEQuicErrorCodeQuicFrameType
QuicHeaderQuicPacketTypeQuicProtocolVersionQuicTransportParametersQuicVersionInformationget_retry_integrity_tagget_spin_bitpretty_protocol_versionpull_quic_transport_parameterspush_quic_transport_parameters)MTU_PROBE_SIZESSMALLEST_MAX_DATAGRAM_SIZEQuicDeliveryStateQuicPacketBuilderQuicPacketBuilderStop)K_GRANULARITYQuicPacketRecoveryQuicPacketSpace)FinalSizeError
QuicStreamStreamFinishedErrorquic @  )IH01           d   )NCLIENT_EARLY_TRAFFIC_SECRETCLIENT_HANDSHAKE_TRAFFIC_SECRETCLIENT_TRAFFIC_SECRET_0)NNSERVER_HANDSHAKE_TRAFFIC_SECRETSERVER_TRAFFIC_SECRET_0   l               i   @   	      shortcutstrreturnfrozenset[tls.Epoch]c                 C  s   t dd | D S )Nc                 s  s    | ]}t | V  qd S N)EPOCH_SHORTCUTS).0i r[   H/home/thesage/.local/lib/python3.10/site-packages/qh3/quic/connection.py	<genexpr>u   s    zEPOCHS.<locals>.<genexpr>)	frozenset)rS   r[   r[   r\   EPOCHSt   s   r_   from_versionint
to_versionboolc                 C  s   | |ht jt jhkS )zz
    Return whether it is possible to perform compatible version negotiation
    from `from_version` to `to_version`.
    )r,   	VERSION_1	VERSION_2)r`   rb   r[   r[   r\   is_version_compatiblex   s   rf   cidbytesc                 C  s   t | dS )Nascii)binasciihexlifydecode)rg   r[   r[   r\   dump_cid   s   rm   c                 C  s   i | ]}t ||qS r[   )ra   )rY   vr[   r[   r\   
<dictcomp>   s    ro   zdict[int, QuicPacketType]_PACKET_TYPE_FROM_INTzdict[QuicPacketType, tls.Epoch]_EPOCH_FROM_PACKET_TYPEpacket_typer+   	tls.Epochc                 C  s   t |  S rW   )rq   )rr   r[   r[   r\   	get_epoch      rt   	stream_idc                 C  s
   | d@  S )z9
    Returns True if the stream is client initiated.
    r   r[   rv   r[   r[   r\   stream_is_client_initiated   s   
rx   c                 C  s   | d@ rdS dS )z7
    Returns True if the stream is unidirectional.
    r   TFr[   rw   r[   r[   r\   stream_is_unidirectional   s   ry   	is_clientc                 C  s   t || u p
t| S rW   rx   ry   rz   rv   r[   r[   r\   check_stream_id_for_sending      r}   c                 C  s   t || up
t| S rW   r{   r|   r[   r[   r\   check_stream_id_for_receiving   r~   r   c                   @  s   e Zd Zd	ddZdS )
Limit
frame_typera   namerT   valuec                 C  s"   || _ || _|| _d| _|| _d S Nr   )r   r   sentusedr   )selfr   r   r   r[   r[   r\   __init__   s
   
zLimit.__init__N)r   ra   r   rT   r   ra   )__name__
__module____qualname__r   r[   r[   r[   r\   r          r   c                   @  s    e Zd ZdddZdd
dZdS )QuicConnectionError
error_codera   r   
int | Nonereason_phraserT   c                 C  s   || _ || _|| _d S rW   r   r   r   r   r   r   r   r[   r[   r\   r      s   
zQuicConnectionError.__init__rU   c                 C  s2   d| j  d| j }| jd ur|d| j 7 }|S )NzError: z
, reason: z, frame_type: )r   r   r   )r   sr[   r[   r\   __str__   s   
zQuicConnectionError.__str__N)r   ra   r   r   r   rT   )rU   rT   )r   r   r   r   r   r[   r[   r[   r\   r      s    
r   c                   @  s   e Zd Zd
ddZd	S )QuicConnectionAdaptermsgrT   kwargsr	   rU   tuple[str, Any]c                 C  s   d | jd ||fS )Nz[{}] {}id)formatextra)r   r   r   r[   r[   r\   process      zQuicConnectionAdapter.processN)r   rT   r   r	   rU   r   )r   r   r   r   r[   r[   r[   r\   r      r   r   c                   @  s6   e Zd ZU ded< ded< dZded< dZded	< d
S )QuicConnectionIdrh   rg   ra   sequence_number    stateless_reset_tokenFrc   was_sentN)r   r   r   __annotations__r   r   r[   r[   r[   r\   r      s
   
 r   c                   @  s    e Zd ZdZdZdZdZdZdS )QuicConnectionStater   r   r   rR      N)r   r   r   FIRSTFLIGHT	CONNECTEDCLOSINGDRAINING
TERMINATEDr[   r[   r[   r\   r      s    r   c                   @  s"   e Zd ZddddZdddZdS )QuicNetworkPathFaddrNetworkAddressis_validatedrc   c                 C  s*   || _ d| _d| _|| _d| _t | _d S )Nr   F)r   bytes_received
bytes_sentr   local_challenge_sentr   remote_challenges)r   r   r   r[   r[   r\   r      s   zQuicNetworkPath.__init__sizera   rU   c                 C  s   | j p| j| d| j kS )NrR   )r   r   r   )r   r   r[   r[   r\   can_send   s   zQuicNetworkPath.can_sendNF)r   r   r   rc   )r   ra   rU   rc   )r   r   r   r   r   r[   r[   r[   r\   r      s    r   c                   @  s>   e Zd ZU ded< ded< ded< ded< d	ed
< ded< dS )QuicReceiveContextrs   epochrh   host_cidr   network_pathzlist[Any] | Nonequic_logger_framesfloattimer   versionN)r   r   r   r   r[   r[   r[   r\   r      s   
 r   c                   @  sz  e Zd ZdZdZdddddd)ddZed*ddZed*ddZed*ddZ	d+ddZ
d,ddZd-d d!Zed.d"d#Zed/d%d&Zed0d'd(Zed1d*d+Zd2d,d-Zejdd.fd3d4d5Zd4d:d;Zd5d=d>Zd6d*d@dAZd7dCdDZd8dEdFZd9dGdHZd:dJdKZd;dMdNZd2dOdPZd<dRdSZd=dUdVZd>dWdXZ 	?d6d?dZd[Z!d<d\d]Z"d@d_d`Z#dAdadbZ$dAdcddZ%d2dedfZ&dBdhdiZ'd2djdkZ(d9dldmZ)dCdpdqZ*d2drdsZ+dDdudvZ,dEdxdyZ-dFdzd{Z.dGd~dZ/dHddZ0dIddZ1dIddZ2dIddZ3dIddZ4dIddZ5dIddZ6dIddZ7dIddZ8dIddZ9dIddZ:dIddZ;dIddZ<dIddZ=dIddZ>dIddZ?dIddZ@dIddZAdIddZBdIddZCdIddZDdIddZEdIddZFdJddZGdJddZHdKddZIdLddÄZJdMddƄZKdNddȄZLdOdd˄ZMdPddτZNdQddӄZOdRddքZPdSddلZQ	?d6dTddބZRdUddZSdVddZTd2ddZUdWddZVd2ddZWd2ddZXdXddZY	?d6dYddZZd/ddZ[dZddZ\d[ddZ]d\ddZ^d]ddZ_d^d	d
Z`d_ddZad`ddZbdaddZcdbddZddcddZeddddZfdeddZgdfddZhdfddZig d.fdgdd Zjdhd!d"Zkdid#d$Zldhd%d&Zmdjd'd(ZndS (k  QuicConnectiona  
    A QUIC connection.

    The state machine is driven by three kinds of sources:

    - the API user requesting data to be send out (see :meth:`connect`,
      :meth:`reset_stream`, :meth:`send_ping`, :meth:`send_datagram_frame`
      and :meth:`send_stream_data`)
    - data being received from the network (see :meth:`receive_datagram`)
    - a timer firing (see :meth:`handle_timer`)

    :param configuration: The QUIC configuration to use.
    )b_configuration
_is_client
_ack_delay	_close_at_close_event_connect_called_cryptos_cryptos_initial_crypto_buffers_crypto_frame_type_crypto_packet_version_crypto_retransmitted_crypto_streams_events_handshake_complete_handshake_confirmed
_host_cids_host_cid_seq_map_has_unsent_cidsr   _host_cid_seq_local_ack_delay_exponent!_local_active_connection_id_limit_local_grease_quic_version!_local_grease_transport_parameter_local_challenges#_local_initial_source_connection_id_local_max_data!_local_max_stream_data_bidi_local"_local_max_stream_data_bidi_remote_local_max_stream_data_uni_local_max_streams_bidi_local_max_streams_uni_local_next_stream_id_bidi_local_next_stream_id_uni_loss_at_network_paths
_pacing_at	_peer_cid_peer_cid_available_peer_cid_sequence_numbers_peer_retire_prior_to_peer_token_quic_logger_remote_ack_delay_exponent"_remote_active_connection_id_limit$_remote_initial_source_connection_id_remote_max_idle_timeout_remote_max_ack_delay!_ack_eliciting_sent_since_receive_remote_max_data_remote_max_data_used_remote_max_datagram_frame_size"_remote_max_stream_data_bidi_local#_remote_max_stream_data_bidi_remote_remote_max_stream_data_uni_remote_max_streams_bidi_remote_max_streams_uni_remote_version_information_retry_count_retry_source_connection_id_spaces	_spin_bit_spin_highest_pn_state_streams_streams_dirty_limits_streams_queue_streams_blocked_bidi_streams_blocked_uni_streams_finished_version_version_negotiated_compatible _version_negotiated_incompatible#_original_destination_connection_id_logger_loss_close_pending"_close_packets_received_since_send_close_packets_send_threshold_handshake_keys_discard_pending_datagrams_pending_handshake_done_pending_ping_pending_probe_pending_retire_connection_ids_streams_blocked_pending_session_ticket_fetcher_session_ticket_handler__frame_handlersr   _local_max_data_used_max_datagram_size_mtu_probe_sizes_mtu_probe_pending_initial_source_connection_id_ech_retry_configs_effective_idle_timeoutN)"original_destination_connection_idretry_source_connection_idsession_ticket_fetchersession_ticket_handlerconfigurationr   r  bytes | Noner   r!  tls.SessionTicketFetcher | Noner"  tls.SessionTicketHandler | NonerU   Nonec                  s  |j r|d u sJ d|d u sJ dn|jd usJ d|jd us&J d|d us.J d| _|j  _|j _ jrH|jrH fddtD ng  _	d  _
t _d  _d  _d _i  _i  _i  _d  _d  _d _i  _t  _d _d _tt|jd	 jstd
nd ddg _ jd	 j  _! jd	 j d	i _"d _#d _$d _%|j&d ur|j&nd _'t()tddd> dB d@  _*dt()tdd d  _+i  _, jd	 j  _-t.t/j0d|j1d _2|j3 _4|j3 _5|j3 _6t.t/j7ddd _8t.t/j9ddd _: jr	d	nd _; jrdnd _<d  _=g  _>d  _?tt|jd d _@g  _Ad	h _Bd	 _Cd _Dd  _Ed _Fd _Gd  _Hd  _Id! _Jd _K jjL _Md	 _Nd	 _Od  _Pd	 _Qd	 _Rd	 _Sd	 _Td	 _Ud  _Vd	 _W| _Xd  _Yi  _Zd _[d	 _\t]j^ __i  _`ta  _bg  _cg  _dg  _eta  _fd  _gd _hd _i jr j@j  _jn| _jtktld"tm jji _n|jor|jojp|j  jjd# _Etq|jr j  js j jE jnd$ _td  jt_ud _vd	 _wd _xd _yt  _zd _{g  _|d _}g  _~d _| _| _i d	 jtd%fd jtd%fd jtd&fd jtd&fd jtd'fd( jtd'fd) jtd&fd* jtd+fd jtd'fd, jtd'fd- jtd'fd. jtd'fd/ jtd'fd0 jtd'fd1 jtd'fd2 jtd'fd
 jtd'fi d3 jtd'fd4 jtd'fd5 jtd'fd6 jtd'fd7 jtd'fd8 jtd'fd9 jtd'fd jtd'fd: jtd'fd; jtd'fd jtd'fd< jtd%fd= jtd'fd> jtd+fd? jtd'fd@ jtd'f _d S )ANz:Cannot set original_destination_connection_id for a clientz2Cannot set retry_source_connection_id for a clientz(SSL certificate is required for a serverz(SSL private key is required for a serverz;original_destination_connection_id is required for a serverc                   s   g | ]	}| j kr|qS r[   )r  )rY   r   r   r[   r\   
<listcomp>  s    z+QuicConnection.__init__.<locals>.<listcomp>Fr      T)rg   r   r   r   r   rR   rO   big   i



rE      r      max_data)r   r   r   max_streams_bidirH   max_streams_unig   r   )rg   r   r           g?r   )rz   odcid)initial_rtt!peer_completed_address_validation
send_probemax_datagram_sizequic_loggerloggerIH01IH101rG      rN   rD   rQ   
                                                      0   1   )rz   certificateprivate_keyr   r   r8  r  probe_datagram_sizer4   r  r  r9   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   osurandomconnection_id_lengthr   rg   r   r   r   r   r   active_connection_id_limitr   ra   
from_bytesr   r   r   r   r   r)   MAX_DATAr/  r   max_stream_datar   r   r   MAX_STREAMS_BIDIr   MAX_STREAMS_UNIr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   idle_timeoutr  r   r   r   r   r   r   r   r   r   r   r   r  r   r   r   r   r   r   r   setr   r  r  r  r  r  r  r  r  r   r:  rm   r	  r9  start_tracer:   r5  _send_prober
  max_ack_delayr  r  r  r  r  r  r  r  r  r  r  r  _handle_padding_framer_   _handle_ping_frame_handle_ack_frame_handle_reset_stream_frame_handle_stop_sending_frame_handle_crypto_frame_handle_new_token_frame_handle_stream_frame_handle_max_data_frame_handle_max_stream_data_frame_handle_max_streams_bidi_frame_handle_max_streams_uni_frame_handle_data_blocked_frame!_handle_stream_data_blocked_frame_handle_streams_blocked_frame_handle_new_connection_id_frame"_handle_retire_connection_id_frame_handle_path_challenge_frame_handle_path_response_frame_handle_connection_close_frame_handle_handshake_done_frame_handle_datagram_frame_QuicConnection__frame_handlers)r   r#  r  r   r!  r"  r[   r(  r\   r   w  s  	







	
 !zQuicConnection.__init__ra   c                 C  s
   t | jS rW   )lenr   r(  r[   r[   r\   open_outbound_streamsZ  s   
z$QuicConnection.open_outbound_streamsc                 C     | j S rW   )r   r(  r[   r[   r\   max_concurrent_bidi_streams^     z*QuicConnection.max_concurrent_bidi_streamsc                 C  r}  rW   )r   r(  r[   r[   r\   max_concurrent_uni_streamsb  r  z)QuicConnection.max_concurrent_uni_streamstls.CipherSuite | Nonec                 C  s   | j jr	| j jjS d S rW   )r   key_schedulecipher_suiter(  r[   r[   r\   
get_cipherf  r   zQuicConnection.get_cipherX509Certificate | Nonec                 C     | j jS rW   )r   peer_certificater(  r[   r[   r\   get_peercerti  ru   zQuicConnection.get_peercertlist[X509Certificate]c                 C  r  rW   )r   peer_certificate_chainr(  r[   r[   r\   get_issuercertsl  ru   zQuicConnection.get_issuercertsc                 C  r}  rW   )r   r(  r[   r[   r\   r#  o  r  zQuicConnection.configurationrh   c                 C  r}  rW   )r  r(  r[   r[   r\   r  s  r  z1QuicConnection.original_destination_connection_idc                 C  r}  )a  
        ECH retry configurations from the server, if ECH was rejected.

        When the server rejects ECH and provides updated configurations,
        they are stored here. The application can use these to retry
        the connection with updated ECH configs.
        )r  r(  r[   r[   r\   ech_retry_configsw  s   	z QuicConnection.ech_retry_configsrc   c                 C  s    t | dr| jdur| jjS dS )zE
        Whether ECH was offered and accepted by the server.
        r   NF)hasattrr   ech_acceptedr(  r[   r[   r\   r    s   zQuicConnection.ech_acceptedc                 C  s"   | j r| | j |   dS dS )z
        Switch to the next available connection ID and retire
        the previous one.

        After calling this method call :meth:`datagrams_to_send` to retrieve data
        which needs to be sent.
        N)r   _retire_peer_cidr   _consume_peer_cidr(  r[   r[   r\   change_connection_id  s   z#QuicConnection.change_connection_id r   r   r   r   rT   c                 C  s8   | j du r| jtvrtj|||d| _ d| _dS dS dS )a  
        Close the connection.

        :param error_code: An error code indicating why the connection is
                           being closed.
        :param reason_phrase: A human-readable explanation of why the
                              connection is being closed.
        Nr   T)r   r   
END_STATESr   ConnectionTerminatedr  r   r[   r[   r\   close  s   
zQuicConnection.closer   r   nowr   c                 C  s`   | j r| jr
J dd| _t|ddg| _| jjdur!| jj| _n| jjd | _| j|d dS )aK  
        Initiate the TLS handshake.

        This method can only be called for clients and a single time.

        After calling this method call :meth:`datagrams_to_send` to retrieve data
        which needs to be sent.

        :param addr: The network address of the remote peer.
        :param now: The current time.
        z:connect() can only be called for clients and a single timeT)r   Nr   r  )	r   r   r   r   r   original_versionr  supported_versions_connect)r   r   r  r[   r[   r\   connect  s   zQuicConnection.connect"list[tuple[bytes, NetworkAddress]]c                   s  | j d }| jtjj }|j r|jjnd}|| | j	t
jkr+| jr+| jdur+n| j	tv r2g S t| j| j| jdd | j D | jj| j| j| j| jd	}| jrg }| jsh|tjjtjftjjtjfg7 }|tjjtjf |D ]$\}}| j| }	|	j r| ||	 | j!||| jj"| jj#| jj$d qt| j%&d| jj"| jj$ d| _| j'd	|d
 nJ| j(j)| j(j* |_+| j,r|j+| jk r| j|_+|j-s|j.d |j/ |_0z| jstjjtjjfD ]	}| 1||| q| 2||| W n	 t3y   Y nw |4 \}
}| j5r| j6du r| jr| jtjj j r| j5d }|| _6t| j| j|t7|j8| jj| j| j| j| jd	}| tj| jtjj  |j9t:j;d| j<|fd |j=}|dkra|j>?t@| |4 \}}|r|D ]}d	|_Aql|
B| |B| |}|
r$| j D ]\}}|j8C|}|dur||_Dqd}| j}| j}| j(jE}|D ]l}||_F||||jG d |jGtjjkrd	}|jHr| jIsd	| _I| J|}|dur| jKdu s|| jKkr|| _K|dur|jLdd|jM|jD|N|jN|jNtjkr dntO| jtO| jjdd|jPidd q|r$| jr$| Qtjj |durB|j rB|jj|krB|R|d| j(S    |jT |j/}|
D ]	}|tU|7 }qJ||_/| jdury|
D ]}tU|}| jjLdddtV| |dgdd q_ fdd|
D S )a1  
        Return a list of `(data, addr)` tuples of datagrams which need to be
        sent, and the network address to which they need to be sent.

        After calling this method call :meth:`get_timer` to know when the next
        timer needs to be set.

        :param now: The current time.
        r   Nc                 S  s   i | ]\}}||j qS r[   )packet_number)rY   r   spacer[   r[   r\   ro     s    z4QuicConnection.datagrams_to_send.<locals>.<dictcomp>)	r   rz   r8  packet_numberspeer_cid
peer_tokenr9  spin_bitr   )builderr   r   r   r   z,Connection close sent (code 0x%X, reason %s)FTis_initiatorr  rR   r   capacityhandlerhandler_args)packetr  	transportpacket_sentr  )r  rr   sciddcidlengthframesheaderrawcategoryeventdatadatagrams_sentr  payload_lengthcountr  c                   s   g | ]}| fqS r[   r[   )rY   datagramr   r[   r\   r)    s    z4QuicConnection.datagrams_to_send.<locals>.<listcomp>)Wr   r   r   EpochONE_RTTsendis_valid	key_phaseexpire_previous_keysr   r   r   r  r   r  r7   r   r   r  r   itemsr   rg   r   r   r   r  r   INITIALr+   	HANDSHAKEappendstart_packet_write_connection_close_framer   r   r   r	  debug_close_beginr
  congestion_windowbytes_in_flightmax_flight_bytesr  r   r   r   max_total_bytes_write_handshake_write_applicationr8   flushr  r  dictr  start_framer)   PING_on_mtu_probe_deliveryremaining_flight_space_buffer
push_bytesrh   is_pmtu_probeextendgetr  on_packet_sent	sent_timer   is_ack_elicitingr   _idle_deadliner   	log_eventr   rr   rm   
sent_bytes_discard_epochretain_previous_keysget_probe_timeoutr   r{  UDP_HEADER_SIZE)r   r  r   _onertt_crypto
_kp_beforer  epoch_packet_typesr   rr   crypto	datagramspackets
probe_sizeprobe_builderpad_sizeprobe_datagramsprobe_packets	probe_pktr  pnsent_handshaker9  spacesloss_on_packet_sentr  deadlinenp_bytes_sentr  r  r[   r  r\   datagrams_to_send  sf  


















z QuicConnection.datagrams_to_sendFc                 C  s   |r| j S | jS )zT
        Return the stream ID for the next stream created by this endpoint.
        )r   r   )r   is_unidirectionalr[   r[   r\   get_next_available_stream_id  s   z+QuicConnection.get_next_available_stream_idfloat | Nonec                 C  s   | j }| jtvrH| jjD ]}|jdur|du s|j|k r|j}q| j | _| jdur7|du s4| j|k r7| j}| jdurH|du sE| j|k rH| j}|S )z_
        Return the time at which the timer should fire or None if no timer is needed.
        N)	r   r   r  r
  r  ack_atget_loss_detection_timer   r   )r   timer_atr  r[   r[   r\   	get_timer  s   



zQuicConnection.get_timerc                 C  s.   | j }|dkr	dS d| j  }|t|| S )z
        Compute the next idle-timeout deadline, or None if no idle
        timeout is in effect. RFC 9000 10.1.1: the idle timeout period
        MUST be at least three times the current PTO.
        r   NrR   )r  r
  r  max)r   r  timeoutfloorr[   r[   r\   r    s
   zQuicConnection._idle_deadlinec                 C  sz   | j dur || j kr | jdu rtjtjtjdd| _|   dS | j	dur9|| j	kr;| j
d | jj|d dS dS dS )z
        Handle the timer.

        After calling this method call :meth:`datagrams_to_send` to retrieve data
        which needs to be sent.

        :param now: The current time.
        NzIdle timeoutr   zLoss detection triggeredr  )r   r   r   r  r(   INTERNAL_ERRORr)   PADDING
_close_endr   r	  r  r
  on_loss_detection_timeoutr   r  r[   r[   r\   handle_timer  s   

zQuicConnection.handle_timerevents.QuicEvent | Nonec                 C  s   | j r| j  S dS )zy
        Retrieve the next event from the event buffer.

        Returns `None` if there are no buffered events.
        N)r   popleftr(  r[   r[   r\   
next_event  s   
zQuicConnection.next_eventr  c           *   
   C  sL  | j tv r,| j tjkr*| jdur*|  jd7  _| j| jkr*d| _|  jd9  _d| _dS t|}| j	}| j
}| jj}|durO|jdddt| |dgd	d
 | |}|js^| j|7  _| jdu ri| || _t|}	d}
| jj}|
|	k r$|
}zt||
|\
}}}}}}}}}}W n ty   |dur|jdddd|	| idd
 Y dS w t| }|}
||}|r|du r|dur|jddddid
 dS |tjkrt|||||||t|d}| j||d dS |dur|| jjvr|dur|jdddd|idd
 dS |tjkr*t|||||||t|d}| j ||||t!  |d dS d}|s^| j tj"u r^|tj#krP|durN|jdddd|idd
 dS d}|g| _$|| _%| &| t'| }|t(j)j#kro| j*| }n| j+| }|t(j)j,kr| j-t(j)j. }n| j-| }zD|t(j)j.t(j)j,fv r|j/j0nd}|dur|1| |2||| ||j3\}} }!|dur|j/j0|kr|4|d| j56    W n t7y }" z:| j89|" |dur|jdddd|idd
 |r	|t(j)j:t(j)j.fv r	| j;s	| j5j<|d d| _;W Y d}"~"qsd}"~"w t=y^ }" z?| j89|" |dur3|jdddd|idd
 | >|rT| j8?d t@jAtBjCddd| _| D  W Y d}"~"dS W Y d}"~"qsd}"~"ww |tj.krhd}#nd}#|d |#@ r}| jEtBjFtGjHd d dS d}$|durg }$|jdd!|$|!|I|tJ|tJ|d"d|id#d
 |!|j3kr|!d |_3|!|jKv r| j8dur| j89d$||! qs|s|t(j)j:kr| Lt(j)j# | jMjNdu r|| jM_Od| jM_N| j tj"u r|| _P| QtjR |tj.kr|!| jSkrtT|d }%|r
|% | _Un|%| _U|!| _S|s8| jVr8|t(j)j.kr8d| _V| Lt(j)j: |dur8|jd%d&d'| jUid
 tW||||$||d(}&z| X|&| |\}'}(W n$ tYyq }" z| j89|" | jE|"jZ|"j[|"j\d W Y d}"~"nd}"~"ww | j tv s|| jr~dS | || _d| _]|s|&j^| j^kr|t(j)j.kr| j89d)tJ|&j^| |&j^| _^| _  |js|t(j)j:kr| j89d*|j` d|_|| j$vr| j$a| | j$b|})|)r|(s|!|jckr| j89d+|j` | j$d|) | j$ed| | j5f  |jgs|!|jckr	|!|_c||_h|jKi|! |'r|jjdu r|| jk |_j|
|	k sxdS dS ),aM  
        Handle an incoming datagram.

        After calling this method call :meth:`datagrams_to_send` to retrieve data
        which needs to be sent.

        :param data: The datagram which was received.
        :param addr: The network address from which the datagram was received.
        :param now: The current time.
        Nr   r   r   Tr  datagrams_receivedr  r  r  packet_droppedheader_parse_errorr  triggerr  r  unknown_connection_id)r   rr   packet_lengthdestination_cid
source_cidtokenintegrity_tagr  )r  r  unsupported_version)r  packet_without_tagr  Ffirst_packet_not_initialrR   key_unavailabler  payload_decrypt_errorz"Stateless reset received from peerzStateless resetr   r,  rA  zReserved bits must be zeropacket_received)r  rr   r  r  r  z+Discarding duplicate packet: epoch=%s pn=%dconnectivityspin_bit_updatedstate)r   r   r   r   r   r   zPeer switching to CID %s (%d)z&Network path %s validated by handshakezNetwork path %s promoted)lr   r  r   r   r   r  r  r  r{  r   r   r   rX  r  r  _find_network_pathr   r   r   r  r   r  _pull_quic_header_raw
ValueErrorrp   r+   VERSION_NEGOTIATIONr*   list#_receive_version_negotiation_packetr  RETRY_receive_retry_packetr&   r   r  r   r  _initializerq   r   r  r   r   ZERO_RTTr   r  recvr  r  decrypt_packetexpected_packet_numberr  r
  r  r!   r	  r  r  r   reschedule_datar   _is_stateless_resetinfor   r  r(   NO_ERRORr  r  PROTOCOL_VIOLATIONr)   r  rr   rm   	ack_queuer  r   r   rg   r   
_set_stater   r   r0   r   r  r   _payload_receivedr   r   r   r   r   r   r  r   r  indexlargest_received_packetpopinsertreset_for_new_path	discardedlargest_received_timeaddr  r   )*r   r  r   r  r  r9  rz   
cid_lengthr   	_data_len_offsethost_cid_seq_map_get	start_offr  _packet_type_int_packet_length_destination_cid_source_cid_token_integrity_tag_supported_versionsencrypted_offend_off_packet_typedestination_cid_seqr  crypto_frame_requiredr   r  r  r  plain_headerplain_payloadr  excreserved_maskr   r  contextr  
is_probingidxr[   r[   r\   receive_datagram  sv  


























  zQuicConnection.receive_datagramc                 C  s$   | j sJ d| jtjj   dS )z;
        Request an update of the encryption keys.
        z/cannot change key before handshake is confirmedN)r   r   r   r  r  
update_keyr(  r[   r[   r\   request_key_update  s   z!QuicConnection.request_key_updaterv   c                 C  s   |  |}|j| dS )ah  
        Abruptly terminate the sending part of a stream.

        This method has no effect if a reset has already been triggered either by a
        call to :meth:`reset_stream` or by the reception of a STOP_SENDING frame.

        :param stream_id: The stream's ID.
        :param error_code: An error code indicating why the stream is being reset.
        N)_get_or_create_stream_for_sendsenderresetr   rv   r   streamr[   r[   r\   reset_stream  s   

zQuicConnection.reset_streamuidc                 C     | j | dS )z`
        Send a PING frame to the peer.

        :param uid: A unique ID for this PING.
        N)r  r  )r   r`  r[   r[   r\   	send_ping     zQuicConnection.send_pingc                 C  ra  )zS
        Send a DATAGRAM frame.

        :param data: The data to be sent.
        N)r  r  )r   r  r[   r[   r\   send_datagram_frame  rc  z"QuicConnection.send_datagram_frame
end_streamc                 C  s   |  |}|jj||d dS )z
        Send data on the specific stream.

        :param stream_id: The stream's ID.
        :param data: The data to be sent.
        :param end_stream: If set to `True`, the FIN bit will be set.
        )re  N)rZ  r[  write)r   rv   r  re  r^  r[   r[   r\   send_stream_data  s   

zQuicConnection.send_stream_datac                 C  sB   t | j|s
td| j|d}|du rtd|j| dS )z
        Request termination of the receiving part of a stream.

        :param stream_id: The stream's ID.
        :param error_code: An error code indicating why the stream is being stopped.
        z@Cannot stop receiving on a local-initiated unidirectional streamNz*Cannot stop receiving on an unknown stream)r   r   r$  r   r  receiverstopr]  r[   r[   r\   stop_stream  s   zQuicConnection.stop_streamalpn_protocolc                 C  s   | j jD ]\}}|t jjkr| |  nqttjt jj	 | j
dd| jso| jso| jdurb| jjD ]/}|| jkr; n'|| jjv rat| j|ra|| _| j| | jt jj< t jj|  fg| j _ nq2d| _| jdt| j | jtj|d dS )z
        Callback which is invoked by the TLS engine at most once, when the
        ALPN negotiation completes.

        At this point, TLS extensions have been received so we can parse the
        transport parameters.
        z%No QUIC transport parameters receivedr   NTNegotiated protocol version %s)rk  ) r   received_extensionsExtensionTypeQUIC_TRANSPORT_PARAMETERS_parse_transport_parametersr   r(   CRYPTO_ERRORAlertDescriptionmissing_extensionr   r   r  r   available_versionsr  r   r  rf   r   r   r  r  _serialize_transport_parametershandshake_extensionsr	  r  r1   r   r  r   ProtocolNegotiated)r   rk  ext_typeext_datar   r[   r[   r\   _alpn_handler   sF   	




zQuicConnection._alpn_handlerc                 C      t | j|sttj|dddS )z^
        Check the specified stream can receive data or raises a QuicConnectionError.
        zStream is send-onlyr   N)r   r   r   r(   STREAM_STATE_ERRORr   r   rv   r[   r[   r\   _assert_stream_can_receive8     z)QuicConnection._assert_stream_can_receivec                 C  r{  )z[
        Check the specified stream can send data or raises a QuicConnectionError.
        zStream is receive-onlyr   N)r}   r   r   r(   r|  r}  r[   r[   r\   _assert_stream_can_sendC  r  z&QuicConnection._assert_stream_can_sendc                 C  s.   | j d| _| jdt| jj| jj dS )z
        Update the destination connection ID by taking the next
        available connection ID provided by the peer.
        r   zSwitching to CID %s (%d)N)r   r9  r   r	  r  rm   rg   r   r(  r[   r[   r\   r  N  s   
z QuicConnection._consume_peer_cidr  c                 C  s8   |d| j    | _|r| tj dS | tj dS )z,
        Begin the close procedure.
        rR   N)r
  r  r   r5  r   r   r   )r   r  r  r[   r[   r\   r  [  s   zQuicConnection._close_beginc                 C  sb   d| _ | j D ]}| | q| j| j | tj	 | j
dur/| jj| j
 d| _
dS dS )z*
        End the close procedure.
        N)r   r   keysr  r   r  r   r5  r   r   r   r   r9  	end_trace)r   r   r[   r[   r\   r  e  s   

zQuicConnection._close_endc                 C  s@   | j sJ | || _| | jj | jd| j | 	  dS )z-
        Start the client handshake.
        r   N)
r   r  r   r*  r   rg   r   handle_messager   _push_crypto_datar	  r[   r[   r\   r  t  s
   
zQuicConnection._connectr   rs   c                 C  s   | j | js?| jd| | j|   |tjjkr.| j	
 D ]}t|j_t|j_|  q| j| j |  d| j | _d S d S )NzDiscarding epoch %sT)r   r<  r	  r  r   teardownr   r  r  r   valuesr"   r,  _teardown_cbr  r
  discard_space)r   r   r  r[   r[   r\   r    s   
zQuicConnection._discard_epochc                 C  s>   | j tjj }|j s|j r| jd |	  dS dS )a  
        RFC 9001 4.9.3: 0-RTT keys MUST be discarded once they are no
        longer needed.

        - A server MUST discard 0-RTT keys after receiving a 1-RTT
          packet, or earlier if it has decided not to accept 0-RTT.
        - A client MUST discard 0-RTT keys when it receives the
          Handshake keys (or as soon as the handshake is confirmed).

        0-RTT shares the 1-RTT packet-number space, so we only tear down
        the crypto pair; there is no separate ``QuicPacketSpace`` to
        discard.
        zDiscarding 0-RTT keysN)
r   r   r  r+  r  r  r,  r	  r  r  )r   zero_rttr[   r[   r\   _discard_zero_rtt_keys  s
   z%QuicConnection._discard_zero_rtt_keysr   c                 C  s4   | j D ]}|j|kr|  S q| jd| t|S )NzNetwork path %s discovered)r   r   r	  r  r   )r   r   r   r[   r[   r\   r"    s   

z!QuicConnection._find_network_pathr=   c                 C  s   || j v rt| j|d}|du rrt|| ju r!ttj|ddt	|r.| j
}d}| j}n	| j}| j}| j}|d d }||jkrJttj|dd||jkrR||_| jd| d	 t|||t	| d
 }| j|< | j| |S )zI
        Get or create a stream in response to a received frame.
        NzWrong stream initiatorr   r   r   r   zToo many streams openStream z created by peer)rv   max_stream_data_localmax_stream_data_remotewritable)r  r>   r   r  rx   r   r   r(   r|  ry   r   r   r   r   r   r   STREAM_LIMIT_ERRORr   r	  r  r=   r  r  )r   r   rv   r^  r  r  max_streamsstream_countr[   r[   r\   _get_or_create_stream  sF   


z$QuicConnection._get_or_create_streamc                 C  s   t | j|s
td| j|d}|du rrt|| jur tdt|r0d}| j}| j}| j	}n| j
}| j}| j}| j}t|}t|||| d }| j|< | j| |r\|d | _n|d | _|d |krrd|_|| d| _|S )z
        Get or create a QUIC stream in order to send data to the peer.

        This always occurs as a result of an API call.
        z8Cannot send data on peer-initiated unidirectional streamNz1Cannot send data on unknown peer-initiated streamr   )rv   r  r  readabler   T)r}   r   r$  r   r  rx   ry   r   r   r  r   r   r   r  r=   r  r  r   r   
is_blockedr  )r   rv   r^  r  r  r  streams_blockedr  r[   r[   r\   rZ    s>   

z-QuicConnection._get_or_create_stream_for_sendsession_tickettls.SessionTicketc                 C  s<   |j d ur|j tkrttjtjd|j  d| | d S )NzInvalid max_early_data value r   )max_early_data_sizeMAX_EARLY_DATAr   r(   r3  r)   CRYPTOr  )r   r  r[   r[   r\   _handle_session_ticket  s   

z%QuicConnection._handle_session_ticketr  c                   s  t jd"i djjdjjdjjdjjdjjdj	dj
dj	r+d ntd	jjd
jjdjjdjjdjjdjjdjjdjjdjj_ jjd urntjjtsntdjjj _jjrtjjd tstdjjj _jjrdttjjv rtdjjj _t jj  fgj _!jj"}j	r|d ur|j#r|jjjkrjj"j _"|j$tkr|j%D ]\}}|t jjkrj&|dd  nqшj'j _(j)d urj)j _*j+d urj,j _-j.j _/d#fdd i _0jj1D ]}t2 }|j3|j	|d |j0|< q fdd t j4j5t j4j6t j4j7t j4j8fD _9j0j: j9t j4j5< t j4j5t;t<d!t j4j7t;t<d!t j4j8t;t<d!i_=t j4j5t> t j4j7t> t j4j8t> i_?t j4j5t@ t j4j7t@ t j4j8t@ i_AtBjAC jD_Ed S )$Nalpn_protocolscadatacafilecapathcipher_suitesrz   r:  max_early_dataserver_nameverify_modehostname_checks_common_nameassert_fingerprintverify_hostnameech_config_listsignature_algorithmsoffer_ec_key_shares offer_certificate_status_requestzqh3 v1.0+ no longer support passing cryptography certificate objects within a QuicConfiguration object. Use configuration.load_cert_chain(...) instead using PEM encoded values.r   cryptographyzqh3 v1.0+ no longer support passing cryptography private key object within a QuicConfiguration object. Use configuration.load_cert_chain(...) instead using PEM encoded values.T)from_session_ticketr   rs   rU   r    c                   sl   g d| j  }d| dd| dg}| j  }| j }tt j|t j|t j|t j|dS )N)initial0rtt	handshake1rttserver__secretclient_)recv_setup_cbrecv_teardown_cbsend_setup_cbsend_teardown_cb)r   r   r    r   _log_key_updated_log_key_retired)r   
epoch_namesecret_namesrecv_secret_namesend_secret_namer(  r[   r\   create_crypto_pairw  s   






z6QuicConnection._initialize.<locals>.create_crypto_pair)rg   rz   r   c                   s   i | ]}| |qS r[   r[   )rY   r   )r  r[   r\   ro     s    z.QuicConnection._initialize.<locals>.<dictcomp>r  r[   )r   rs   rU   r    )Fr   Contextr   r  r  r  r  r#  r  r   r	  r  r  r  r  r  r  r  r  r  r  rS  
isinstanceX509CertificateRuntimeErrorcertificate_chainrT  rT   typecertificate_private_keyrn  ro  ru  rv  r  r  r  other_extensionsrp  rz  alpn_cbr  get_session_ticket_cbr  r  new_session_ticket_cb_update_traffic_keyupdate_traffic_key_cbr   r  r    setup_initialr  r  r+  r  r  r   r  r   CRYPTO_BUFFER_SIZEr   r=   r   r;   r   r&  r  r
  r  )r   r  r  rx  ry  r   pairr[   )r  r   r\   r*    s   
	

















zQuicConnection._initializerT  r   bufr   c           	      C  s   t |\}}|tjkr|  |  |  || j> d }| jdur.|j| j|| | j	|j
 }| d d }||jkrIttj|dd| jjs\|j
tjjtjjfv r\d| j_| jj||||j| jom|j
tjjk d dS )z&
        Handle an ACK frame.
        @B Nr   zACK acknowledges unsent packetr   T)r  ack_rangeset	ack_delayr  reset_pto_count)r   r)   ACK_ECNpull_uint_varr   r   r   r  encode_ack_framer   r   boundsr  r   r(   r3  r
  r6  r   r  r  r  on_ack_receivedr   r   r  )	r   rT  r   r  r  ack_delay_encodedr  r  largest_ackedr[   r[   r\   rf    s>   



z QuicConnection._handle_ack_framec                 C  s   |  }|tjkr|  }nd}|  }z
||d}W n ty)   d}Y nw | jdur<|j| jj	|||d | j
d|| | jdu r\tj|||d| _| jd|jd dS dS )z2
        Handle a CONNECTION_CLOSE frame.
        Nutf8r  r   z0Connection close received (code 0x%X, reason %s)Fr  )r  r)   TRANSPORT_CLOSE
pull_bytesrl   UnicodeDecodeErrorr   r   r  encode_connection_close_framer	  r  r   r   r  r  r   )r   rT  r   r  r   reason_lengthr   r[   r[   r\   rw    s>   



z-QuicConnection._handle_connection_close_framec              
   C  sj  zt |\}}W n ty } z
ttj|t|dd}~ww t|}| jdur3|j	| j
|| | j|j }|| |j  }	|	tkrNttj|dd|j||}
|
dur
|| _|j| _z| jj|
j| j|jd |   W n< tjy } z| jj| _ttjt|j |t|dd}~w tj y } zttjt|j |t|dd}~ww | j!s| jj"tj#j$tj#j%fv rd| _!| j&sd| _'d| _(d| _)| j*| j+_,| -  | .  | j/	t0j1| jj2| jj3| jj4d | j5dd | j5dd | j67d	| jj2 dS dS dS | j67d
|j | j&s/|jtj8j9kr1| j:s3| j+j;|j<d d| _:dS dS dS dS )z(
        Handle a CRYPTO frame.
        r   Nztoo much crypto buffering)r   T)rk  early_data_acceptedsession_resumedFr  zALPN negotiated protocol %sz+Duplicate CRYPTO data received for epoch %sr  )=r   r$  r   r(   FRAME_ENCODING_ERRORrT   r{  r   r   r  encode_crypto_framer   r   rh  starting_offsetMAX_PENDING_CRYPTOCRYPTO_BUFFER_EXCEEDEDhandle_framer   r   r   r   r  r  r   r  AlertECHRequiredr  r  rq  ra   descriptionAlertr   r!  StateCLIENT_POST_HANDSHAKESERVER_POST_HANDSHAKEr   r  r   r  r   r
  rc  r  _replenish_connection_idsr   r   HandshakeCompletedalpn_negotiatedr  r  _unblock_streamsr	  r  r  r  r   r/  r   )r   rT  r   r  offsetr  rR  r  r^  pendingr  r[   r[   r\   ri  	  s   



(
z#QuicConnection._handle_crypto_framec                 C  sd   |  }| jdur|j| jj|d || jjkr0| j jd9  _| jd| jj	| jj dS dS )z.
        Handle a DATA_BLOCKED frame.
        N)limitr   z1Local %s raised to %d in response to DATA_BLOCKED)
r  r   r   r  encode_data_blocked_framer   r   r	  r  r   r   rT  r   r  r  r[   r[   r\   rp  }  s   
z)QuicConnection._handle_data_blocked_framec                 C  s   |  }|tjkr| }n|j| }||}| jdur(|j| jj	|d | j
jdu s8|  | | j
jkr@ttj|dd| jtj|d dS )z*
        Handle a DATAGRAM frame.
        Nr  zUnexpected DATAGRAM framer   r  )tellr)   DATAGRAM_WITH_LENGTHr  r  r  r   r   r  encode_datagram_framer   max_datagram_frame_sizer   r(   r3  r   r   DatagramFrameReceived)r   rT  r   r  startr  r  r[   r[   r\   ry    s"   




z%QuicConnection._handle_datagram_framec                 C  sn   | j dur|j| j   | jsttj|dd| js5| 	t
jj d| _d| j_| j| j_|   dS dS )z0
        Handle a HANDSHAKE_DONE frame.
        Nz+Clients must not send HANDSHAKE_DONE framesr   T)r   r   r  encode_handshake_done_framer   r   r(   r3  r   r  r   r  r  r
  r6  r   rc  r  r   rT  r   r  r[   r[   r\   rx    s"   

z+QuicConnection._handle_handshake_done_framec                 C  sP   |  }| jdur|j| jj||d || jkr&| jd| || _dS dS )zm
        Handle a MAX_DATA frame.

        This adjusts the total amount of we can send to the peer.
        Nr   maximumzRemote max_data raised to %d)r  r   r   r  encode_connection_limit_framer   r	  r  )r   rT  r   r  r/  r[   r[   r\   rl    s   


z%QuicConnection._handle_max_data_framec                 C  sr   |  }|  }| jdur|j| jj||d | || | ||}||jkr7| j	d|| ||_dS dS )z|
        Handle a MAX_STREAM_DATA frame.

        This adjusts the amount of data we can send on a specific stream.
        Nr  rv   z-Stream %d remote max_stream_data raised to %d)
r  r   r   r  encode_max_stream_data_framer  r  r  r	  r  )r   rT  r   r  rv   r\  r^  r[   r[   r\   rm    s$   


z,QuicConnection._handle_max_stream_data_framec                 C  t   |  }|tkrttj|dd| jdur!|j| jj||d || j	kr8| j
d| || _	| jdd dS dS )z
        Handle a MAX_STREAMS_BIDI frame.

        This raises number of bidirectional streams we can initiate to the peer.
        "Maximum Streams cannot exceed 2^60r   Nr  z$Remote max_streams_bidi raised to %dFr  )r  STREAM_COUNT_MAXr   r(   r  r   r   r  r  r   r	  r  r  r   rT  r   r  r  r[   r[   r\   rn  	  $   

z-QuicConnection._handle_max_streams_bidi_framec                 C  r	  )z
        Handle a MAX_STREAMS_UNI frame.

        This raises number of unidirectional streams we can initiate to the peer.
        r
  r   Nr  z#Remote max_streams_uni raised to %dTr  )r  r  r   r(   r  r   r   r  r  r   r	  r  r  r  r[   r[   r\   ro  )	  r  z,QuicConnection._handle_max_streams_uni_framec                   s  |  }|  }| }||}|t}|rt|tkr&ttj|dd j	dur9|j
 j	j||||d ||krEttj|ddt| j _d}	 fdd jD }
 jj|k rgd	}	|
d
 j  fdd jD  _| jkr| jvr jt|||d  j| |
D ]} | q|	r   dt j  jkrttj|ddt jt jd tkrttj|dddS )z3
        Handle a NEW_CONNECTION_ID frame.
        z.Length must be greater than 0 and less than 20r   Nconnection_idretire_prior_tor   r   z/Retire Prior To is greater than Sequence NumberFc                   s   g | ]
}|j  jk r|qS r[   r   r   rY   rg   r(  r[   r\   r)  p	  
    zBQuicConnection._handle_new_connection_id_frame.<locals>.<listcomp>Tr   c                   s   g | ]
}|j  jkr|qS r[   r  r  r(  r[   r\   r)  z	  r  rg   r   r   r   zToo many active connection IDsr   z'Too many pending retired connection IDs)r  
pull_uint8r  r'   r{  r#   r   r(   r  r   r   r  encode_new_connection_id_framer3  r  r   r   r   r   r:  r   r   r>  r  r  r   CONNECTION_ID_LIMIT_ERRORr  minMAX_PENDING_RETIRES)r   rT  r   r  r   r  r  r  r   
change_cidretirequic_connection_idr[   r(  r\   rs  F	  s   









z.QuicConnection._handle_new_connection_id_framec                 C  sL   |  }||}| jdur|j| jj|d | js$ttj	|dddS )z+
        Handle a NEW_TOKEN frame.
        N)r  z&Clients must not send NEW_TOKEN framesr   )
r  r  r   r   r  encode_new_token_framer   r   r(   r3  )r   rT  r   r  r  r  r[   r[   r\   rj  	  s   

z&QuicConnection._handle_new_token_framec                 C  s,   t | | jdur|j| j  dS dS )z)
        Handle a PADDING frame.
        N)_skip_paddingr   r   r  encode_padding_framer  r[   r[   r\   rd  	  s   
z$QuicConnection._handle_padding_framec                 C  sP   | d}| jdur|j| jj|d t|jjtk r&|jj| dS dS )z0
        Handle a PATH_CHALLENGE frame.
        rO   Nr  )	r  r   r   r  encode_path_challenge_framer{  r   r   MAX_REMOTE_CHALLENGES)r   rT  r   r  r  r[   r[   r\   ru  	  s   

z+QuicConnection._handle_path_challenge_framec                 C  st   | d}| jdur|j| jj|d z| j|}W n ty,   tt	j
|ddw | jd|j d|_dS )z/
        Handle a PATH_RESPONSE frame.
        rO   Nr  z!Response does not match challenger   z&Network path %s validated by challengeT)r  r   r   r  encode_path_response_framer   r9  KeyErrorr   r(   r3  r	  r  r   r   )r   rT  r   r  r  r   r[   r[   r\   rv  	  s    


z*QuicConnection._handle_path_response_framec                 C  s$   | j dur|j| j   dS dS )z&
        Handle a PING frame.
        N)r   r   r  encode_ping_framer  r[   r[   r\   re  	  s   
z!QuicConnection._handle_ping_framec              
   C  s8  |  }|  }|  }| jdur|j| jj|||d | || | ||}||jkr7tt	j
|ddtd||jj }| jj| | jjkrRtt	j
|dd| jd||| z
|jj||d}	W n ty{ }
 z
tt	j|t|
dd}
~
ww |	dur| j|	 | j j|7  _|dkr| j| dS dS )	z.
        Handle a RESET_STREAM frame.
        Nr   
final_sizerv   Over stream data limitr   r   Over connection data limitz6Stream %d reset by peer (error code %d, final size %d))r   r&  )r  r   r   r  encode_reset_stream_framer~  r  r  r   r(   FLOW_CONTROL_ERRORr  rh  highest_offsetr   r   r   r	  r  handle_resetr<   FINAL_SIZE_ERRORrT   r   r   r>  )r   rT  r   r  rv   r   r&  r^  newly_receivedr  rR  r[   r[   r\   rg  
  s`   


z)QuicConnection._handle_reset_stream_framec                 C  s   |  }| jdur|j| j| || jkr ttj|ddt	| j
D ]<\}}|j|kra|j|jkr<ttj|dd| jdt|j|j | j
|= | j|jd | jtj|jd  nq%|   dS )z6
        Handle a RETIRE_CONNECTION_ID frame.
        Nz#Cannot retire unknown connection IDr   z#Cannot retire current connection IDzPeer retiring CID %s (%d)r  )r  r   r   r  !encode_retire_connection_id_framer   r   r(   r3  	enumerater   r   rg   r   r	  r  rm   r   r9  r   r   ConnectionIdRetiredr  )r   rT  r   r  r   r7  r  r[   r[   r\   rt  A
  s@   



z1QuicConnection._handle_retire_connection_id_framec                 C  sr   |  }|  }| jdur|j| jj||d | || | ||}|jj|d | j	t
j||d dS )z.
        Handle a STOP_SENDING frame.
        Nr   rv   )r   )r  r   r   r  encode_stop_sending_framer  r  r[  r\  r   r   StopSendingReceived)r   rT  r   r  rv   r   r^  r[   r[   r\   rh  n
  s   
z)QuicConnection._handle_stop_sending_framec              
   C  sd  zt ||\}}}}W n ty! } z
ttj|t|dd}~ww t|}	| jdur9|j	| jj
||||d | || | ||}
||	 |
jkrTttj|ddtd||	 |
jj }| jj| | jjkrqttj|ddz
|
j|||}W n ty } z
ttj|t|dd}~ww |dur| j	| | j j|7  _|dkr| j|
 dS dS )z(
        Handle a STREAM frame.
        r   Nrw   r'  r   r(  )r   r$  r   r(   r  rT   r{  r   r   r  encode_stream_framer~  r  r  r*  r  rh  r+  r   r   r   r  r<   r-  r   r   r>  )r   rT  r   r  rv   r  r  finrR  r  r^  r.  r  r[   r[   r\   rk  
  s`   
z#QuicConnection._handle_stream_framec                 C  s   |  }|  }| jdur|j| jj||d | || | ||}|jjsI|j	rK||j	krM| j	d9  _	| j
d||j	 | j| dS dS dS dS )z5
        Handle a STREAM_DATA_BLOCKED frame.
        N)r  rv   r   zOStream %d local max_stream_data raised to %d in response to STREAM_DATA_BLOCKED)r  r   r   r   encode_stream_data_blocked_framer~  r  rh  is_finishedr  r	  r  r   r>  )r   rT  r   r  rv   r  r^  r[   r[   r\   rq  
  s0   

z0QuicConnection._handle_stream_data_blocked_framec                 C  sP   |  }|tkrttj|dd| jdur&|j| jj|t	j
k|d dS dS )z1
        Handle a STREAMS_BLOCKED frame.
        r
  r   Nr  r  )r  r  r   r(   r  r   r   r  encode_streams_blocked_framer)   STREAMS_BLOCKED_UNIr  r[   r[   r\   rr  
  s   
z,QuicConnection._handle_streams_blocked_framekey_typer  c                 C  *   | j dur| j jdd||dd dS dS )z'
        Log a key retirement.
        Nsecuritykey_retiredr=  r  r  r   r  r   r=  r  r[   r[   r\   r       

zQuicConnection._log_key_retiredc                 C  r>  )z#
        Log a key update.
        Nr?  key_updatedrA  r  rB  rC  r[   r[   r\   r    rD  zQuicConnection._log_key_updateddeliveryr6   r  r;   highest_ackedc                 C  s$   |t jkr|jd|d  dS dS )zE
        Callback when an ACK frame is acknowledged or lost.
        r   r   N)r6   ACKEDr4  subtract)r   rF  r  rG  r[   r[   r\   _on_ack_delivery  s   
zQuicConnection._on_ack_deliveryr  r   c                 C  s   |t jkr
d|_dS dS )zX
        Callback when a MAX_DATA or MAX_STREAMS frame is acknowledged or lost.
        r   N)r6   rH  r   )r   rF  r  r[   r[   r\   _on_connection_limit_delivery#  s   

z,QuicConnection._on_connection_limit_deliveryr  c                 C  s:   |t jkr|r| jrd| _dS dS | jrd| _dS dS dS )z
        Callback when a STREAMS_BLOCKED frame is acknowledged or lost.

        Re-arms the pending flag on loss if blocked streams still exist,
        per RFC 9000 13.3 (SHOULD retransmit if conditions persist).
        TN)r6   rH  r  r  r  )r   rF  r  r[   r[   r\   _on_streams_blocked_delivery,  s   
	

z+QuicConnection._on_streams_blocked_deliveryc                 C  s   |t jkr
d| _dS dS )zO
        Callback when a HANDSHAKE_DONE frame is acknowledged or lost.
        TN)r6   rH  r  )r   rF  r[   r[   r\   _on_handshake_done_delivery=  s   

z*QuicConnection._on_handshake_done_deliveryr^  c                 C  s$   |t jkrd|_| j| dS dS )zP
        Callback when a MAX_STREAM_DATA frame is acknowledged or lost.
        r   N)r6   rH  max_stream_data_local_sentr   r>  )r   rF  r^  r[   r[   r\   _on_max_stream_data_deliveryD  s   
z+QuicConnection._on_max_stream_data_deliveryr  r   c                 C  s   |t jkrd|_d| _dS dS )zR
        Callback when a NEW_CONNECTION_ID frame is acknowledged or lost.
        FTN)r6   rH  r   r   )r   rF  r  r[   r[   r\   _on_new_connection_id_deliveryN  s   

z-QuicConnection._on_new_connection_id_deliveryuidsSequence[int]c                 C  sR   |t jkr!| jd|rdnd |D ]}| jtj|d qdS | j	| dS )zE
        Callback when a PING frame is acknowledged or lost.
        zReceived PING%s responser  z (probe))r`  N)
r6   rH  r	  r  r   r  r   PingAcknowledgedr  r  )r   rF  rQ  r`  r[   r[   r\   _on_ping_deliveryX  s   
z QuicConnection._on_ping_deliveryr  c                 C  st   |t jkr)| jd| || _|| jj_| jr$| jd |kr$| jd d| _	dS | jd| | j
  d| _	dS )zP
        Callback when an MTU probe PING frame is acknowledged or lost.
        z%MTU probe ACK'd, datagram size now %dr   NzMTU probe for %d lost, stopping)r6   rH  r	  r  r  r
  _ccr  r9  r  clear)r   rF  r  r[   r[   r\   r  e  s   




z%QuicConnection._on_mtu_probe_deliveryr   c                 C  s   |t jkr| j| dS dS )zU
        Callback when a RETIRE_CONNECTION_ID frame is acknowledged or lost.
        N)r6   rH  r  r  )r   rF  r   r[   r[   r\   !_on_retire_connection_id_deliveryw  s   
z0QuicConnection._on_retire_connection_id_deliveryplainrO  tuple[bool, bool]c                 C  s`  t |d}d}d}d}d}|j}	|j}
| j}|	 sz|
 }W n ty-   ttjdddw z|| \}}W n tyE   ttj|ddw |j	|vrSttj
|ddz|||| W n tyj   ttj|dd tyr   Y nw d	}|tjkr|d	}|tvrd	}|tvrd}n|du rd	}|	 r|sttj
tjd
d|r|sttj
tjdd|t|fS )z/
        Handle a QUIC packet payload.
        r  FNzMalformed frame typer   zUnknown frame typezUnexpected frame typezFailed to parse frameTzPacket contains no frameszPacket contains no CRYPTO frame)r   eofr  rz  r   r   r(   r  r#  r   r3  r>   r)   r  r$   r%   r  rc   )r   rT  rX  rO  r  crypto_frame_foundframe_foundr  rU  buf_eofbuf_pull_uint_varframe_handlersr   frame_handlerframe_epochsr[   r[   r\   r6    s   
	


8z QuicConnection._payload_receivedr  r*   r  c                 C  s   | j ra| jsa|j| jkra|jt|| jj|jdkra| j	dur8| j	j
ddg dt|jt|jdd|jidd	 |j| j_|j| _|  jd
7  _|j| _| jdt|j d | j|d dS | j	durw| j	j
dddd|jidd	 dS dS )z(
        Handle a retry packet.
        )r   Nr  r  retryrr   r  r  r  r  r  r   zRetrying with token (z bytes)r  r  unexpected_packetr  )r   r   r  r   r  r/   r   rg   r   r   r  rm   r  r  r  r   r   r	  r  r{  r  )r   r  r  r  r[   r[   r\   r)    sN   



z$QuicConnection._receive_retry_packetc                   sj  | j r| jtju r| js| jdur0| jjddg | j jt j	t j
dd jidd | j jv rB| jdt| j dS  fd	d
| jjD }|rS|d nd}| jdurj| jjdd j| jj|dd |du r| jd tjtjtjdd| _|   dS || _d| _| jdt| j | j|d dS | jdur| jjdddd jidd dS dS )z
        Handle a version negotiation packet.

        This is used in "Incompatible Version Negotiation", see:
        https://datatracker.ietf.org/doc/html/rfc9368#section-2.2
        Nr  r  rc  r  r  r  z7Version negotiation packet contains protocol version %sc                   s   g | ]	}| j v r|qS r[   )r  )rY   xr  r[   r\   r)  @  s
    
zFQuicConnection._receive_version_negotiation_packet.<locals>.<listcomp>r   version_information)server_versionsclient_versionschosen_versionz(Could not find a common protocol versionr   Tz!Retrying with protocol version %sr  r  rd  r  )r   r   r   r   r  r   r  rr   rm   r  r  r  r  r  r	  r  r1   r   r   r  r(   r  r)   r  r   r  r  )r   r  r  commonrj  r[   rf  r\   r'    s~   


	

z2QuicConnection._receive_version_negotiation_packetc                 C  s   d}t | jtd| jk r>t| jj}| j}| j	t
||tdd || j|< |  jd7  _d}t | jtd| jk s|rEd| _dS dS )z.
        Generate new connection IDs.
        FrO   r*  r  r   TN)r{  r   r  r   rV  rW  r   rX  r   r  r   r   r   )r   addedrg   seqr[   r[   r\   r  n  s$   

z(QuicConnection._replenish_connection_idsc                 C  s6   | j dt|j|jt| jd  | j|j dS )z5
        Retire a destination connection ID.
        zRetiring CID %s (%d) [%d]r   N)r	  r  rm   rg   r   r{  r  r  )r   r  r[   r[   r\   r    s   zQuicConnection._retire_peer_cidc                 C  s6   | j  D ]\}}| j| j|j |d qd S r   )r   r  r   r[  rf  r  seek)r   r   r  r[   r[   r\   r    s   z QuicConnection._push_crypto_datac                 C  s
   d| _ d S )NT)r  r(  r[   r[   r\   rb    s   
zQuicConnection._send_prober  c                 C  s\   t |tk rdS |t d }| jjr|| jjkrdS | jD ]}|jr+||jkr+ dS qdS )z
        RFC 9000 10.3.1: detect a stateless reset by matching the trailing
        16 bytes of the UDP datagram against the stateless reset tokens
        the peer has shared with us.
        FNT)r{  r'   r   r   r   )r   r  r  rg   r[   r[   r\   r0    s   
z"QuicConnection._is_stateless_resetr  c                 C  s  z	t t|d}W n ty   ttjtjddw | jdur0|s0| jj	dd| jj
d|dd	 | jsKd
D ]}t||durJttjtj| ddq5|s|j| jkr\ttjtjdd| jrn|j| jkrnttjtjdd| jr|j| jkrttjtjdd|jdur|jdk rttjtjdd|jdur|jdkrttjtjdd|jdur|jdkrttjtjdd|jdur|jtk rttjtjdt d|jdur|j}| js|j|jvrttjtjdd|j| jkrttjtjdd|s4|jdur|j| _|jdur|jd | _| jr| j| j _| jr0| j!j"dkr0|j#dur0|j#| j!_#|j| _$|jdur>|j| _%|j&durw|j&d | _'| j(j)}| j'}|dkrb|dkrbt*||| _+n|dkrk|| _+n|dkrt|| _+nd| _+|j,| _-dD ]}t|d| }	|	durt.| d| |	 q}| j/r|jdur|j}
g }| j/D ]}t*||
}|| j0kr|r||d kr|1| q|| _/dS dS dS )z
        Parse and apply remote transport parameters.

        `from_session_ticket` is `True` when restoring saved transport parameters,
        and `False` when handling received transport parameters.
        r  z)Could not parse QUIC transport parametersr   Nr  parameters_setremoteowner
parametersr  )r  preferred_addressr   r   z is not allowed for clientsz+initial_source_connection_id does not matchz1original_destination_connection_id does not matchz)retry_source_connection_id does not matchr   z1active_connection_id_limit must be no less than 2rH  z ack_delay_exponent must be <= 20r@   zmax_ack_delay must be < 2^14z max_udp_payload_size must be >= zJversion_information's chosen_version is not included in available_versionszFversion_information's chosen_version does not match the version in useg     @@r   r3  )r/  max_stream_data_bidi_localmax_stream_data_bidi_remotemax_stream_data_unir0  r1  initial__remote_)2r2   r   r$  r   r(   TRANSPORT_PARAMETER_ERRORr)   r  r   r  encode_transport_parametersr   getattrinitial_source_connection_idr   r  r  r   r   rY  ack_delay_exponentrc  max_udp_payload_sizer5   rg  rj  rt  r   VERSION_NEGOTIATION_ERRORr   r   r   r
  r   r   r   r   r   max_idle_timeoutr   r   r_  r  r  r  r   setattrr  r  r  )r   r  r  quic_transport_parametersattrrg  localrp  paramr   peer_maxcappedr   r   r[   r[   r\   rp    s@  
	

















z*QuicConnection._parse_transport_parametersc                 C  s"  t | j| jt| jjd | jj| j| j	| j
| jj| jj| jd| jj| jjr)dt nd | jd jt| j| jjdd}| jred |_d |_| jj|_d |_d|_d|_d	|_| jd
f|_| jg| jj|j_ n| j!|_"| j#|_$| j%d ur| j%j&dd| j%j'd|dd t(d| j) d}t*|| |j+S )Ni  rL     Qr   )rj  rt  )r  rY  r  initial_max_data"initial_max_stream_data_bidi_local#initial_max_stream_data_bidi_remoteinitial_max_stream_data_uniinitial_max_streams_bidiinitial_max_streams_unir~  rc  r  quantum_readinessr   rg  i  i   s   ORIGr   r  ro  r  rq  r  rR   r  ),r-   r   r   ra   r   r_  r   r   r   r   r   r   r   r   r  quantum_readiness_testr5   r   r   r.   r  r  r   r  rc  rY  r  google_connection_optionsr   greased_transport_parameterr   rg  rt  r  r  r   r   r   r  r|  r   r  r3   r  )r   r  r  r[   r[   r\   ru    sj   




z.QuicConnection._serialize_transport_parametersr!  r   c                 C  s    | j d| jj|j || _d S )Nz%s -> %s)r	  r  r   r   )r   r!  r[   r[   r\   r5    s   
zQuicConnection._set_statec                 C  s   |r| j }| j}| j}n	| j}| j}| j}|r6|d jd |k r6|d}d|_||_	|r6|d jd |k s | jsA| jsCd| _
d S d S d S )Nr   r   F)r   r   r  r   r   r  rv   r9  r  r  r  )r   r  r  r  r  r^  r[   r[   r\   r    s   

zQuicConnection._unblock_streams	directiontls.Directionr  tls.CipherSuitesecretc           	      C  s   | j r| jdur| js| j| _d| _| jdt| j | jj}|durL| j |t	j
jkk}t| |j }|| d| j	j  d|  d |  | j| }|t	j
jkrc|jj||| jd dS |jj||| jd dS )zj
        Callback which is invoked by the TLS engine when new traffic keys are
        available.
        NTrl   
)r  r  r   )r   r   r  r  r	  r  r1   r   secrets_log_filer   	DirectionDECRYPTSECRETS_LABELSr   rf  client_randomhexr  r   ENCRYPTr  setupr,  )	r   r  r   r  r  r  	label_rowlabelr  r[   r[   r\   r    s4   

 


z"QuicConnection._update_traffic_key	challenger   c                 C  sH   || j |< t| j tkr"tt| j  }| j |= t| j tksd S d S rW   )r   r{  MAX_LOCAL_CHALLENGESnextiterr  )r   r  r   keyr[   r[   r\   _add_local_challenge  s
   
z#QuicConnection._add_local_challenger  r7   c           .   	   C  s  d }| j tjj j r| j tjj }| jtjj }tj}n| j tjj j r3| j tjj }tj}nd S | j	tjj }| j
}| jj}	| j}
| j}	 |jd u sT|j|kre| jse|	j|d| _| jd ured S ||| |re|js|jstd}| j||d | j||d d|_|jd ur|j|kr| j|||d | jr| j|d d| _|jr| j||jd	 d |j  |js| j rd}| j!D ]}|j"s| j#||d
 d}q|rd| _ | j$r| j$D ]	}| j%||d q| j$&  | j'r| j(r| j)|t*j+| j,d | j-r| j)|t*j.| j/d d| _'| j0| j1| j2fD ]L}|j3d |j4kr4| j4d9  _4| j56d|j7|j4 |j4|j8krc|j9|j:t;| j<|fd}|=|j4 |j4|_8|d urc|j>?|j@|j:|j4d q| jA}|r|D ]^}|jBjCrvqm|jDr|jBjEd |jDkr| jDd9  _D| j56d|jF|jD |jG|jDkr|j9t*jHtI| jJ|fd}|=|jF |=|jD |jD|_G|d ur|j>?|jK|jD|jFd qm|&  | jLr| M|| jL | jL&  | jr| jM|dd d| _|d ur |jNjOs | jP|||d | jQr)| jQ }z| jR||t*jSd W n tTy$   | jQU| Y nw | jQsg }d	}tV|
}d	}|jW}|jX}|jY}|j9}| jZ}|| j[ }t\}z||k r/|
| }|d7 }|jN} |jB}!| jCr|!jCr| j56d|jF d | j]|jF= | j^_|jF | jA`| qK|!jar| jb||d | jcr| jd||d n|jes"| jOs"||f  | }"|"dk r||
|< |d7 }nu| jE| }#|jg}$|$|#k r|$}#| h|"|#}%|%d ur"|%\}&}'}(})}*}+|jF},||'|+| ji|(|)f |||,|(|& |d ur|j>?|jjtk|'d@ |&|(|,d | jE|* }-||-8 }|  j[|-7  _[|-d	kr"|?| qK||
|< |d7 }||k sPW ||k rH|
| |
|< |d7 }|d7 }||k s5|
|d = |
l| n#||k rk|
| |
|< |d7 }|d7 }||k sX|
|d = |
l| w |jmr|d S |	jn|d qJ)NTr  rO   )r  r  )r  r   r  r  r  )r  Fr   )r  r  )r  r   )r  r   r  r   zLocal %s raised to %dr  r  z,Stream %d local max_stream_data raised to %dr  probecommentr  r  r^  )r  r  r   r   r  z
 discarded)r  r^  rH  rw   )or   r   r  r  r  r  r   r+   r+  r   r   r
  _pacerr  r   r  r  next_send_timer   r  r   r   rV  rW  _write_path_challenge_framer  _write_ack_framer  _write_handshake_done_framer   _write_path_response_framer  r   r   r   _write_new_connection_id_framer  !_write_retire_connection_id_framerV  r  r  _write_streams_blocked_framer)   STREAMS_BLOCKED_BIDIr   r  r<  r   r   r   r   r   r   r	  r  r   r   r  r   CONNECTION_LIMIT_FRAME_CAPACITYrK  push_uint_varr   r  r  r   rh  r9  r  r+  rv   rN  MAX_STREAM_DATAMAX_STREAM_DATA_FRAME_CAPACITYrO  r  r  _write_ping_framer[  buffer_is_empty_write_crypto_framer  _write_datagram_framer  r8   
appendleftr{  r  _flight_capacity_aead_tag_sizer   r   r   r   r  r>  discardstop_pending_write_stop_sending_framereset_pending_write_reset_stream_framer  r  r  prepare_stream_frameon_data_deliveryr6  rc   r  packet_is_emptyupdate_after_send).r   r  r   r  crypto_streamr  rr   r  handshake_completepacerstreams_queuer   r  all_sentr  r   r  r  dirty_limitsr^  datagram_pendingr   	write_idx	queue_lenread_idx	_b_buffer	_b_flight_b_aead_b_start_framer   _remote_data_remaining_push_stream_frame_bodyr[  rh  flight_space
max_offsetsdrresultf_datar   f_offsetstop_offsetprevious_send_highestframe_overheadrv   r   r[   r[   r\   r    s   
























	



P




  z!QuicConnection._write_applicationc                 C  s   | j | }|j sd S | j| }| j| }	 |tjjkr!tj}ntj	}|
|| |jd ur7| j|||d |jjsF| j|||drFd| _| jrf| jsf|tjj	ks\| j tjj	 j sf| j|dd d| _|jrkd S q)NTr  r  Fr  r  )r   r  r  r   r   r   r  r  r+   r  r  r  r  r[  r  r  r  r   r  r  )r   r  r   r  r  r  r  rr   r[   r[   r\   r  O  s:   




zQuicConnection._write_handshakec                 C  s  ||j  }t|d | j? }t|j}t|jd d}t|d d d}||krD|dkrDt|j|kr?|j  t|j|ks3t|j}ddt|d  }	|jt	j
|	| j||jfd}
t|
|j|}d |_| jd urw|j| jj|j|d |dkr|jd dkr| j|d	d
 d S d S d S )Nr  r   r   rF   r*  r  )rangesdelayrO   zACK-of-ACK triggerr  )r=  ra   r   r{  r4  r  remaining_buffer_spaceshiftr  r)   ACKrJ  r8  r   r  r   r   r  r  r  r  )r   r  r  r  r  r  ranges_countmax_payloadmax_ranges_by_spacer  r  r  r[   r[   r\   r  {  s8   

	


zQuicConnection._write_ack_framec           	      C  s   |d u r|t jjt jjfv rtj}tj}d}|d}t	|}|d u r=|j
tjt| d}|| || || n|j
tjt| d}|| || || || | jd uro|j| jj|||d d S d S )Nr  r  r  r   )r   r  r  r  r(   APPLICATION_ERRORr)   r  encoder{  r  APPLICATION_CLOSE APPLICATION_CLOSE_FRAME_CAPACITYr  r  r  TRANSPORT_CLOSE_FRAME_CAPACITYr   r   r  r  )	r   r  r   r   r   r   reason_bytesr  r  r[   r[   r\   r    s>   	







z,QuicConnection._write_connection_close_framec              	   C  s   |j }dt|j }|j|j  |j }||| }|d urM|\}}	}
|t	j
||j|
|
t| f}t||
| | jd urK|j| j||
 dS dS )NrR   TF)r[  r   next_offsetr  r  r  r  	get_framer  r)   r  r  r{  r   r   r   r  r  )r   r  r  r^  r[  r  r  framer  f_finr  r  r[   r[   r\   r    s(   

z"QuicConnection._write_crypto_framer)   c                 C  sl   |t jksJ t|}dt| | }|j||d}|| || | jdur4|j	| jj
|d dS )zl
        Write a DATAGRAM frame.

        Returns True if the frame was processed, False otherwise.
        r   r  Nr  T)r)   r  r{  r   r  r  r  r   r   r  r  )r   r  r  r   r  
frame_sizer  r[   r[   r\   r    s   


z$QuicConnection._write_datagram_framec                 C  s8   |j tjt| jd | jd ur|j| j  d S d S )N)r  r  )	r  r)   HANDSHAKE_DONEHANDSHAKE_DONE_FRAME_CAPACITYrM  r   r   r  r  )r   r  r[   r[   r\   r    s   
z*QuicConnection._write_handshake_done_framec                 C  s   d}|j tjt| j|fd}||j || |t|j	 |
|j	 |
|j d|_| jtj|j	d | jd urS|j| jj|j	||j|jd d S d S )Nr   r  Tr/  r  )r  r)   NEW_CONNECTION_ID NEW_CONNECTION_ID_FRAME_CAPACITYrP  r  r   
push_uint8r{  rg   r  r   r   r   r  r   ConnectionIdIssuedr   r   r  )r   r  r  r  r  r[   r[   r\   r    s0   

z-QuicConnection._write_new_connection_id_framec                 C  J   |j tjtd}|| |  | jd ur#|j| jj	|d d S d S Nr  r  )
r  r)   PATH_CHALLENGEPATH_CHALLENGE_FRAME_CAPACITYr  pad_datagramr   r   r  r   r   r  r  r  r[   r[   r\   r  8  s   

z*QuicConnection._write_path_challenge_framec                 C  r   r  )
r  r)   PATH_RESPONSEPATH_RESPONSE_FRAME_CAPACITYr  r  r   r   r  r"  r  r[   r[   r\   r  K  s   

z)QuicConnection._write_path_response_frame	list[int]c                 C  sb   |j tjt| jt|fd | jd|rd| dnd|j | j	d ur/|j
| j	  d S d S )Nr  zSending PING%s in packet %dz ()r  )r  r)   r  PING_FRAME_CAPACITYrT  tupler	  r  r  r   r   r  r$  )r   r  rQ  r  r[   r[   r\   r  ]  s   
z QuicConnection._write_ping_framec                 C  st   |j tjt|jjd}|j }|\}}}|| || || | jd ur8|j	
| jj|||d d S d S )Nr   r  r  r%  )r  r)   RESET_STREAMRESET_STREAM_FRAME_CAPACITYr[  on_reset_deliveryget_reset_framer  r   r   r  r)  )r   r  r^  r  r  r   r&  frame_stream_idr[   r[   r\   r  p  s&   





z(QuicConnection._write_reset_stream_framec                 C  sH   |j tjt| j|fd}|| | jd ur"|j| j	| d S d S )Nr  )
r  r)   RETIRE_CONNECTION_IDRETIRE_CONNECTION_ID_CAPACITYrW  r  r   r   r  r0  )r   r  r   r  r[   r[   r\   r    s   


z0QuicConnection._write_retire_connection_id_framec                 C  sf   |j tjt|jjd}|j }||j ||j	 | j
d ur1|j| j
j|j	|jd d S d S )Nr  r3  )r  r)   STOP_SENDINGSTOP_SENDING_FRAME_CAPACITYrh  on_stop_sending_deliveryget_stop_framer  rv   r   r   r   r  r4  )r   r  r^  r  r  r[   r[   r\   r    s   

z(QuicConnection._write_stop_sending_framec                 C  sZ   |t jk}|j|t| j|fd}|| | jd ur+|j| jj	|t jk|d d S d S )Nr  r:  )
r)   r<  r  STREAMS_BLOCKED_CAPACITYrL  r  r   r   r  r;  )r   r  r   r  is_unir  r[   r[   r\   r    s    


z+QuicConnection._write_streams_blocked_frame)r#  r   r  r$  r   r$  r!  r%  r"  r&  rU   r'  )rU   ra   )rU   r  )rU   r  )rU   r  )rU   r   )rU   rh   )rU   r$  )rU   rc   )rU   r'  )r   ra   r   r   r   rT   rU   r'  )r   r   r  r   rU   r'  )r  r   rU   r  r   )rU   r  )r  r   rU   r  )r  r   rU   r'  )rU   r  )r  rh   r   r   r  r   rU   r'  )rv   ra   r   ra   rU   r'  )r`  ra   rU   r'  )r  rh   rU   r'  )rv   ra   r  rh   re  rc   rU   r'  )rk  rT   rU   r'  )r   ra   rv   ra   rU   r'  )r  rc   r  r   rU   r'  )r   rs   rU   r'  )r   r   rU   r   )r   ra   rv   ra   rU   r=   )rv   ra   rU   r=   )r  r  rU   r'  )r  rh   rU   r'  )rT  r   r   ra   r  r   rU   r'  )r=  rT   r  rT   rU   r'  )rF  r6   r  r;   rG  ra   rU   r'  )rF  r6   r  r   rU   r'  )rF  r6   r  rc   rU   r'  )rF  r6   rU   r'  )rF  r6   r^  r=   rU   r'  )rF  r6   r  r   rU   r'  )rF  r6   rQ  rR  rU   r'  )rF  r6   r  ra   rU   r'  )rF  r6   r   ra   rU   r'  )rT  r   rX  rh   rO  rc   rU   rY  )r  r*   r  rh   r  r   rU   r'  )r  r*   r  r   rU   r'  )r  r   rU   r'  )r  rh   rU   rc   )r  rh   r  rc   rU   r'  )r!  r   rU   r'  )r  rc   rU   r'  )
r  r  r   rs   r  r  r  rh   rU   r'  )r  rh   r   r   )r  r7   r   r   r  r   rU   r'  )r  r7   r   rs   r  r   rU   r'  )r  r7   r  r;   r  r   rU   r'  )r  r7   r   rs   r   ra   r   r   r   rT   rU   r'  )r  r7   r  r;   r^  r=   rU   rc   )r  r7   r  rh   r   r)   rU   rc   )r  r7   rU   r'  )r  r7   r  r   rU   r'  )r  r7   r  rh   rU   r'  )r  r7   rQ  r  )r  r7   r^  r=   rU   r'  )r  r7   r   ra   rU   r'  )r  r7   r   r)   r  ra   rU   r'  )or   r   r   __doc__	__slots__r   propertyr|  r~  r  r  r  r  r#  r  r  r  r  r(   r2  r  r  r  r  r  r  r
  r  rW  rY  r_  rb  rd  rg  rj  rz  r~  r  r  r  r  r  r  r  r"  r  rZ  r  r*  rf  rw  ri  rp  ry  rx  rl  rm  rn  ro  rs  rj  rd  ru  rv  re  rg  rt  rh  rk  rq  rr  r  r  rJ  rK  rL  rM  rO  rP  rT  r  rW  r6  r)  r'  r  r  r  rb  r0  rp  ru  r5  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r[   r[   r[   r\   r     s
   i d
 q	
   .	8
42 4(t  e
<-:(		

^2^ bG+  6,0-r   )rS   rT   rU   rV   )r`   ra   rb   ra   rU   rc   )rg   rh   rU   rT   )rr   r+   rU   rs   )rv   ra   rU   rc   )rz   rc   rv   ra   rU   rc   r[   )
__future__r   rj   loggingrV  collectionsr   dataclassesr   enumr   	functoolsr   r   typingr   r	   r
   r#  r   r:  r   r  r   _compatr   r   _hazmatr   r   r   r   r   r   r   r   r   r   r  r   r#  r   r  r   r  r   r    r!   r"   r  r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   packet_builderr4   r5   r6   r7   r8   recoveryr9   r:   r;   r^  r<   r=   r>   	getLoggerr  r  r  r  r+  r  rX   r  r!  r  r  r  STREAM_FLAGSr  r  r  r   ACK_FRAME_CAPACITYr  r  r  r  r  r  r  r
  r  r  r  r  r  r_   rf   rm   rp   r   r(  r%  rq   rt   rx   ry   r}   r   r   	Exceptionr   LoggerAdapterr   r   r   r   r   r^   r   r   r   r  r   r[   r[   r[   r\   <module>   s    ,L













				