
    F2j7                        d dl mZ d dlZd dl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mZ d	Zd
ZdZdZdZdZdZdZdZdZdZdZdZdZdZdZ d!dZ! G d d          Z" G d d          Z# G d d           Z$dS )"    )annotationsN)AnyCallableIterable   )QuicPacketPacerQuicRttMonitorRangeSet   )QuicLoggerTrace)QuicDeliveryStateQuicSentPacket   MbP?g      ?gư>g      ?
   g?gffffff?g       @gMbp?gMb?         xfloatreturnc                &    | dk     r|  dz   S | dz  S )Nr   gUUUUUU? r   s    Y/home/thesage/.hermes/hermes-agent/venv/lib/python3.11/site-packages/qh3/quic/recovery.py_cubic_rootr   $   s&    1uu")$%%    c                      e Zd ZddZdS )QuicPacketSpacer   Nonec                    d | _         t                      | _        d| _        d| _        d| _        d | _        d| _        d| _        d| _	        d | _
        i | _        d| _        d S )NFr           )ack_atr
   	ack_queue	discardedexpected_packet_numberlargest_received_packetlargest_received_timepacket_numberack_eliciting_in_flightlargest_acked_packet	loss_timesent_packets!time_of_last_ack_eliciting_packetselfs    r   __init__zQuicPacketSpace.__init__+   sl    $(!&'#')$37" ()$$%!'+79 9<...r   Nr   r    )__name__
__module____qualname__r2   r   r   r   r   r   *   s(        < < < < < <r   r   c                  r    e Zd ZdZddZdd	Zdd
ZddZddZddZ	ddZ
d dZd dZd!dZd"dZddZdS )#QuicCongestionControlz.
    Cubic congestion control (RFC 9438).
    max_datagram_sizeintr   r    c                   || _         t                      | _        d| _        d| _        d| _        d| _        |t          z  | _        d | _	        d| _
        d| _        d| _        | j        | _        d| _        d| _        d| _        d| _        d| _        d| _        t(          j        | _        t(          j        | _        t(          j        | _        d| _        d | _        d| _        d S )Nr#   g{Gz?r   TFr"   )_max_datagram_sizer	   _rtt_monitor_congestion_recovery_start_time_rtt	_last_ackbytes_in_flightK_INITIAL_WINDOWcongestion_windowssthresh_first_slow_start_starting_congestion_avoidance_K_W_max_W_est_cwnd_epoch_t_epochhystart_enabled_hystart_in_css_hystart_css_roundmathinf_hystart_css_baseline_min_rtt_hystart_last_round_min_rtt_hystart_current_round_min_rtt_hystart_rtt_sample_count_hystart_window_end_hystart_largest_sent_pn)r1   r9   s     r   r2   zQuicCongestionControl.__init__C   s    "3*,,/2,	 !25E!E$( "&.3+1 !" &*%*'(48H*26((59X+./&/3 -/%%%r   tr   c                ~    | j         | j        z  }t          || j        z
  dz  z  |z   }t	          || j        z            S )Nr   )rH   r<   	K_CUBIC_CrG   r:   )r1   rW   W_max_segmentstarget_segmentss       r   _W_cubiczQuicCongestionControl._W_cubicc   sA    t'>>#q47{q&88>I?T%<<===r   c                    | j         t          z  | _        d | _        d| _        d| _        d| _        | j        | _        d| _        d| _	        d| _
        |                                  d S )NTFr#   r   )r<   rB   rC   rD   rE   rF   rG   rH   rI   rJ   rK   _hystart_resetr0   s    r   _resetzQuicCongestionControl._reseth   si    !%!8;K!K!%.3+,r   c                    d| _         d| _        t          j        | _        t          j        | _        t          j        | _        d| _        d| _        dS )z
        Reset HyStart++ slow-start exit detector. Called when entering a
        fresh slow-start phase: at construction, after idle restart, and
        after persistent congestion collapse.
        Fr   N)	rM   rN   rO   rP   rQ   rR   rS   rT   rU   r0   s    r   r^   z$QuicCongestionControl._hystart_resett   sH      %"#-1X*+/8(.2h+)*&#'   r   nowc                    || _         | j        | _        | j        | _        | j        | j        z  }| j        | j        z  }t          ||z
  t          z            | _        d S N)	rK   rC   rJ   rI   rH   r<   r   rY   rG   )r1   ra   	W_max_segcwnd_segs       r   _start_epochz"QuicCongestionControl._start_epoch   sZ    1&K$"99	#d&==y83y@AAr   packetr   c                   | xj         |j        z  c_         |j        | _        | j        r| j        | j        }|j        | j        k    rm| j        | _	        t          j        | _        d| _        | j        dz   | _        | j        r3| xj        dz  c_        | j        t           k    r| j        | _        d| _        | j        | j        | j        k     r=| j        r| xj        |j        t$          z  z  c_        d S | xj        |j        z  c_        d S | j        r4| j        s-d| _        | j        | _        |                     |j                   | j        r(d| _        d| _        |                     |j                   t/          | j        | j        |j        | j        z  z  z             | _        |j        | j        z
  }|                     || j        z             }|| j        k     r| j        }n5|t/          d| j        z            k    rt/          d| j        z            }n|}|                     |          | j        k     r| j        | _        d S t/          | j        || j        z
  | j        | j        z  z  z             | _        d S )Nr   r   Fg      ?)rA   
sent_bytes	sent_timer@   rL   rD   rU   r*   rS   rR   rO   rP   rT   rV   rM   rN   K_HYSTART_CSS_ROUNDSrC   K_HYSTART_CSS_GROWTH_DIVISORrE   rF   rH   rf   r:   rI   r<   rK   r\   r?   )r1   rg   rW   W_cubictargets        r   on_packet_ackedz%QuicCongestionControl.on_packet_acked   s    11)  	1%(4$(@@@/3/RD,26(D/-.D*'+'Dq'HD$# 1''1,''*.BBB$($:DM+0D(= D$:T]$J$J# <&&%)EE&&&& &&&*;;&&&& % 4d.Q 4).&"4!!&"23332 46;3).&!!&"2333 )V->AW-WXY DK
  4=0AmmA	M22G ////3sT%;;<<<<S4#99:: }}Q$+--)-&&& *-* 66.1GGII* *&&&r   c                $   | xj         |j        z  c_         |j        | j        k    r|j        | _        | j        r| j        | j        |j        | _        | j        dk    r0|j        | j        z
  }|t          k    r| 
                                 d S d S d S )Nr#   )rA   ri   r*   rV   rL   rD   rU   r@   rj   K_CUBIC_MAX_IDLE_TIMEr_   )r1   rg   elapsed_idles      r   on_packet_sentz$QuicCongestionControl.on_packet_sent   s     11 $"???,2,@D) 	<%(0'-';D$>C!+dn<L444  44r   packetsIterable[QuicSentPacket]c                :    |D ]}| xj         |j        z  c_         d S rc   rA   ri   r1   rt   rg   s      r   on_packets_expiredz(QuicCongestionControl.on_packets_expired   s5     	6 	6F  F$55   	6 	6r   c                :    |D ]}| xj         |j        z  c_         dS )a  
        Mirror of on_packets_lost, but without congestion-control reduction.
        Used by PTO probes (RFC 9002 6.2.4): a PTO timer expiration MUST NOT
        cause prior unacknowledged packets to be marked as lost. We still
        reclaim bytes_in_flight so the application is allowed to retransmit
        the data on a fresh packet without being blocked by the congestion
        window.
        Nrw   rx   s      r   on_packets_rescheduledz,QuicCongestionControl.on_packets_rescheduled   s7      	6 	6F  F$55   	6 	6r   c                   d}|D ]}| xj         |j        z  c_         |j        }|| j        k    r|| _        | j        | j        k     r(t          | j        dt          z   z  dz            | _        n| j        | _        t          t          | j        t          z            | j	        t          z            | _        | j        | _        d| _        d| _        d S d S )Nr#   r   r   TF)rA   ri   rj   r>   rC   rH   r:   K_CUBIC_LOSS_REDUCTION_FACTORmaxr<   K_MINIMUM_WINDOWrD   rF   rM   )r1   rt   ra   lost_largest_timerg   s        r   on_packets_lostz%QuicCongestionControl.on_packets_lost   s     	1 	1F  F$55   & 0 tCCC36D0 %33!*a2O.OPSTT  #4%(D*-JJKK'*::& &D" !2DM26D/ $)D   - DCr   
latest_rttc                   || _         | j        d S | j        r
|| j        k     r|| _        | xj        dz  c_        | j        t
          k    rt          j        | j                  rt          j        | j                  rt          t          t          t          | j        t          z                      }| j        r3| j        | j        k     r!d| _        d| _        t          j        | _        d S d S | j        | j        |z   k    r"d| _        | j        | _        d| _        d S d S d S d S d S | j                            ||          r| j        | _        d S d S )Nr   Fr   T)r?   rD   rL   rS   rT   K_HYSTART_N_RTT_SAMPLErO   isfiniterR   r~   K_HYSTART_MIN_RTT_THRESHminK_HYSTART_MAX_RTT_THRESHK_HYSTART_MIN_RTT_DIVISORrM   rQ   rN   rP   r=   is_rtt_increasingrC   )r1   r   ra   
rtt_threshs       r   on_rtt_measurementz(QuicCongestionControl.on_rtt_measurement  s   	=$F ,	7D???6@3**a/** .2HHHM$"BCC IM$"EFF I !,08;TT  
 ' 4 ;<= = 05,23/=AX:::= = ;;jHI I 04, ? : 34///C IHHHHH2I I  22:sCC 7 $ 67 7r   c                    || _         | j        t          z  | _        d| _        d| _        d| _        d| _        | j        | _        d| _	        d| _
        d| _        |                                  dS )a|  
        RFC 9002 7.6: on persistent congestion the sender's cwnd is
        collapsed to the minimum window and slow-start state is reset
        so the controller re-probes capacity.

        Set ``_congestion_recovery_start_time`` to ``now`` (the time of
        the collapse), not 0.0. Otherwise, the very next packet declared
        lost (e.g. a probe sent just after collapse) passes the
        ``lost_largest_time > _congestion_recovery_start_time`` guard in
        ``on_packets_lost`` and pins ``ssthresh = MINIMUM_WINDOW``,
        terminating the new slow-start phase that this collapse was
        meant to start.
        NTFr#   r   )r>   r<   r   rC   rD   rE   rF   rG   rH   rI   rJ   rK   r^   )r1   ra   s     r   on_persistent_congestionz.QuicCongestionControl.on_persistent_congestionJ  ss     03,!%!8;K!K!%.3+,r   N)r9   r:   r   r    )rW   r   r   r:   r3   ra   r   r   r    )rg   r   r   r    )rt   ru   r   r    )rt   ru   ra   r   r   r    )r   r   ra   r   r   r    )r4   r5   r6   __doc__r2   r\   r_   r^   rf   ro   rs   ry   r{   r   r   r   r   r   r   r8   r8   >   s        0 0 0 0@> > > >

 
 
 
( ( ( (B B B BI I I IV   $6 6 6 6
6 
6 
6 
6) ) ) )@17 17 17 17f     r   r8   c                      e Zd ZdZ	 	 	 d0d1dZed2d            Zed2d            Zd3dZd4dZ	d4dZ
d5dZ	 d6d7d!Zd8d"Zd9d%Zd8d&Zd:d'Zd;d)Zd<d5d+Zd=d.Zd=d/ZdS )>QuicPacketRecoveryz0
    Packet loss and congestion controller.
       Ninitial_rttr   !peer_completed_address_validationbool
send_probeCallable[[], None]r9   r:   loggerlogging.LoggerAdapter | Nonequic_loggerQuicLoggerTrace | Noner   r    c                X   d| _         || _        g | _        || _        || _        || _        d| _        d| _        d| _        || _	        d| _
        d| _        d| _        t          j        | _        d| _        d| _        d| _        t'          |          | _        t+          |          | _        d S )Ng?r   Fr#   )max_ack_delayr   spaces_logger_quic_logger_send_probe
_pto_count
_pto_total_loss_total_rtt_initial_rtt_initialized_rtt_latest_rtt_latest_rawrO   rP   _rtt_min_rtt_smoothed_rtt_variance'_time_of_last_sent_ack_eliciting_packetr8   _ccr   _pacer)r1   r   r   r   r9   r   r   s          r   r2   zQuicPacketRecovery.__init__j  s     #1R.-/ '% ' %
  #  7:4 )):;;%&788r   c                    | j         j        S rc   )r   rA   r0   s    r   rA   z"QuicPacketRecovery.bytes_in_flight  s    x''r   c                    | j         j        S rc   )r   rC   r0   s    r   rC   z$QuicPacketRecovery.congestion_window  s    x))r   spacer   c                @   || j         v sJ | j                            t          d |j                                                             |j                                         d |_        d|_        d |_	        d| _
        | j        |                                  d S d S )Nc                    | j         S rc   )	in_flightr   s    r   <lambda>z2QuicPacketRecovery.discard_space.<locals>.<lambda>  s    Q[ r   r   )r   r   ry   filterr.   valuesclearr$   r+   r-   r   r   _log_metrics_updated)r1   r   s     r   discard_spacez QuicPacketRecovery.discard_space  s    ######((%*<*C*C*E*EFF	
 	
 	
 	  """()% (%%''''' )(r   c                <   |                                  }||j        S | j        s)|                                 d| j        z  z  }| j        |z   S d }| j        D ]}|j        dk    r|j        }|||k     r|}|d S |                                 d| j        z  z  }||z   S )Nr   r   )	_get_loss_spacer-   r   get_probe_timeoutr   r   r   r+   r/   )r1   
loss_spacetimeoutearliestr   rW   s         r   get_loss_detection_timez*QuicPacketRecovery.get_loss_detection_time  s    ))++
!'' 5 	J,,..!T_2DEG?'II!%[ 	! 	!E,q00;#q8|| H4((**a.@A'!!r   c                ~    | j         s
d| j        z  S | j        t          d| j        z  t
                    z   | j        z   S )Nr   r   )r   r   r   r~   r   K_GRANULARITYr   r0   s    r   r   z$QuicPacketRecovery.get_probe_timeout  sK    $ 	)t(((!d((-889 !	
r   c                n    d| _         d| _        d| _        t          j        | _        d| _        d| _        dS )a  
        RFC 9000 9.4 / RFC 9002 5.1: when a path is changed, RTT samples
        from the prior path are no longer representative. ``min_rtt`` in
        particular MUST be reset because the new path may have higher
        latency, and a stale ``min_rtt`` would cause spurious loss
        declarations (since loss_delay scales with max(latest_rtt,
        smoothed_rtt) but min_rtt feeds the ack-delay floor in
        ``on_ack_received``). We additionally reset the smoothed RTT so a
        fresh sample is taken on the new path.
        Fr#   N)r   r   r   rO   rP   r   r   r   r0   s    r   reset_for_new_pathz%QuicPacketRecovery.reset_for_new_path  s;     !&"  r   Tack_rangesetr
   	ack_delayra   reset_pto_countc                   d}|                                 d         dz
  }d}d}	||j        k    r||_        t          |j                                                  D ]}
|
|k    r n|
|v r|j                            |
          }|j        rd}|j        s|xj        dz  c_        |j	        r| j
                            |           |
}|j        }	|j        }||D ]\  }} |t          j        g|R   |dS ||k    r0|r-||	z
  }d}t!          || j                  }t%          |d          | _        | j        | _        | j        | j        k     r| j        | _        | j        | j        |z   k    r| xj        |z  c_        | j        sd| _        |dz  | _        || _        nId| j        z  dt3          | j        | j        z
            z  z   | _        d	| j        z  d
| j        z  z   | _        | j
                            ||           | j                            | j
        j        | j                   nd}|                     ||           |rd| _        | j         | !                    |           dS dS )a  
        Update metrics as the result of an ACK being received.

        ``reset_pto_count`` MUST be False when the caller is a client
        processing an ACK in the Initial packet space and the server has
        not yet been confirmed to have validated the client's address
        (RFC 9002 6.2.1). Resetting in that case would prematurely
        clear the PTO backoff and let a stuck handshake under-probe.
        Fr   NTr   r   g      ?g      ?g      ?g      ?ra   rC   smoothed_rttr   )log_rtt)"boundsr,   sortedr.   keyspopis_ack_elicitingis_pmtu_prober+   r   r   ro   rj   delivery_handlersr   ACKEDr   r   r~   r   r   r   r   r   r   absr   r   update_raterC   _detect_lossr   r   r   )r1   r   r   r   ra   r   r   largest_ackedlargest_newly_ackedlargest_sent_timer*   rg   dhhandlerargsr   r   s                    r   on_ack_receivedz"QuicPacketRecovery.on_ack_received  s   " !$++--a014" 5555)6E&#E$6$;$;$=$=>> 	@ 	@M},,,,+//>>* ;'+$!/ ;55:55# 5H,,V444&3#$*$4! ->)+ @ @ 1 7?$????? &F///4D/00JG It'9::I  #:u55D $(#3D $-// $ 04=9#<<<  I-  ( 
(,%%/!^"%/""%*T-?%?%#&)99K K C &" D..9I1II "
 H''
'<<<K##"&("<!/ $     G%S)))  	 DO(%%g%66666 )(r   c                    |                                  }||                     ||           d S | xj        dz  c_        | xj        dz  c_        |                     |           d S )Nr   r   )r   r   r   r   reschedule_data)r1   ra   r   s      r   on_loss_detection_timeoutz,QuicPacketRecovery.on_loss_detection_timeoutB  su    ))++
!jc22222OOq OOOOq OO  S )))))r   rg   r   c                ,   ||j         |j        <   |j        r|j        s|xj        dz  c_        |j        r]|j        r|j        s|j        | _        |j        |_        | j	        
                    |           | j        |                                  d S d S d S )Nr   )r.   r*   r   r   r+   r   rj   r   r/   r   rs   r   r   )r1   rg   r   s      r   rs   z!QuicPacketRecovery.on_packet_sentK  s    396/0 " 	/6+? 	/))Q.)) 		,& Kv/C K?E?O<:@:J7 H##F+++ ,))+++++		, 		, -,r   c                   d}| j         D ]S}t          t          d |j                                                            }|r|                     |||           d}T|r!| j        | j                            d           d}|s| j         D ]}|j        s
g }t          |j        	                                          D ]G}|j        |         }|j
        r1|j        r*|                    |           t          |          dk    r nH|r|                     |||           d}|s|s|                                  dS dS dS )a  
        Schedule some data for retransmission upon PTO expiry.

        Per RFC 9002 6.2.4, on PTO the sender MUST send one or two
        ack-eliciting packets. A PTO event MUST NOT mark prior packets as
        lost or trigger a congestion-control reduction. Here we requeue
        outstanding CRYPTO (or up to two oldest application data packets)
        so their content is included with the probe; the bytes are
        reclaimed via on_packets_rescheduled rather than on_packets_lost
        to avoid an unwarranted cwnd reduction. If nothing was rescheduled
        the caller emits a PING frame as the ack-eliciting probe.
        Fc                    | j         S rc   )is_crypto_packet)is    r   r   z4QuicPacketRecovery.reschedule_data.<locals>.<lambda>p  s	    !3 r   r   ra   TNz(Scheduled CRYPTO data for retransmissionr   )r   tupler   r.   r   _on_packets_rescheduledr   debugr   r   r   r   appendlenr   )	r1   ra   crypto_scheduledr   rt   app_rescheduledto_reschedulepnpkts	            r   r   z"QuicPacketRecovery.reschedule_data_  s    ![ 	( 	(E33U5G5N5N5P5PQQ G  (,,WEs,KKK#'  	K 8LIJJJ   	+ + +)  " !3!8!8!:!:;; " "B,R0C+ " "%,,S111}--22!E  +00eQT0UUU&*O   	 		 	 	 	r   c                   t          t          | j        rt          | j        | j                  n| j        z  t                    }|j        t          z
  }||z
  }g }d|_	        |j
                                        D ]\\  }}||j        k    r nK||k    s|j        |k    r|                    |           9|j        |z   }	|j	        |j	        |	k    r|	|_	        ]|                     |||           dS )zD
        Check whether any packets should be declared lost.
        Nr   )r~   K_TIME_THRESHOLDr   r   r   r   r   r,   K_PACKET_THRESHOLDr-   r.   itemsrj   r   _on_packets_lost)
r1   r   ra   
loss_delaypacket_thresholdtime_thresholdlost_packetsr*   rg   packet_loss_times
             r   r   zQuicPacketRecovery._detect_loss  s!     ('D($*<===&	 
 

 !58JJz)%*%7%=%=%?%? 		7 		7!M6u999 000F4D4V4V##F++++#)#3j#@ ?*eo@P.P.P&6EOl%SAAAAAr   QuicPacketSpace | Nonec                T    d }| j         D ]}|j        ||j        |j        k     r|}|S rc   )r   r-   )r1   r   r   s      r   r   z"QuicPacketRecovery._get_loss_space  sA    
[ 	# 	#E*"eo
8L&L&L"
r   Fc                   | j         j        | j         j        d}| j         j        | j         j        |d<   |r|                    | j                            | j                  | j                            | j                  | j                            | j	                  | j                            | j
                  d           | j                            dd|           d S )N)rA   cwndrD   )r   min_rttr   rtt_variancerecoverymetrics_updatedcategoryeventdata)r   rA   rC   rD   updater   encode_timer   r   r   r   	log_event)r1   r   r	  s      r   r   z'QuicPacketRecovery._log_metrics_updated  s    #x7H. 
  
 8(#x0D 	KK"&"3"?"?@P"Q"Q#0<<T]KK$($5$A$A$BT$U$U$($5$A$A$BT$U$U	    	##'8t 	$ 	
 	
 	
 	
 	
r   rt   ru   c                   g }|D ]}| xj         dz  c_         |j        |j        = |j        r7|j        r| j        xj        |j        z  c_        n|                    |           |j	        r|j        s|xj
        dz  c_
        | j        V| j                            dd| j                            |j                  |j        d           |                                  |j        }||D ]\  }} |t           j        g|R   |r[| j                            ||           | j                            | j        j        | j                   | j        rd |D             }	t1          |	          d	k    r| j        t3          d
| j        z  t6                    z   | j        z   dz  }
t3          d |	D                       t;          d |	D                       z
  }||
k    rh| j        | j                            d||
           | j                             |           | j                            | j        j        | j                   | j        |                                  d S d S d S )Nr   r  packet_lost)typer*   r  r   r   c                     g | ]}|j         	|S r   )r   .0ps     r   
<listcomp>z7QuicPacketRecovery._on_packets_lost.<locals>.<listcomp>  s     NNN11;MNQNNNr   r   r   r   c              3  $   K   | ]}|j         V  d S rc   rj   r  s     r   	<genexpr>z6QuicPacketRecovery._on_packets_lost.<locals>.<genexpr>  s$      >>qq{>>>>>>r   c              3  $   K   | ]}|j         V  d S rc   r  r  s     r   r  z6QuicPacketRecovery._on_packets_lost.<locals>.<genexpr>  s=       E E()E E E E E Er   zDPersistent congestion detected (span=%.3fs > %.3fs); collapsing cwnd)!r   r.   r*   r   r   r   rA   ri   r   r   r+   r   r  packet_typer   r   r   LOSTr   r   r   rC   r   r   r   r~   r   r   r   r   r   r   r   )r1   rt   r   ra   lost_packets_ccrg   r   r   r   	elicitingpc_durationspans               r   r   z#QuicPacketRecovery._on_packets_lost  s      	;  	;F!"6#78 3' 3
 H,,0AA,,,#**6222& 3v/C 3--2-- ,!++'' $ 1 = =f>P Q Q)/)=  ,    ))+++ )B~%' ; ;MGTG-2:T:::::  %	,H$$_#$>>>K##"&("<!/ $    $ NNNNN	y>>Q&&*a$"44mDDE,- 	#K
 >>I>>>>> E E-6E E E B B D k))<3 L..!2 $ +	   99#>>>//.2h.H)-); 0     ,))+++++K%	, %	,H -,r   c                `   g }|D ]m}|j         |j        = |j        r|                    |           |j        r|j        s|xj        dz  c_        |j        }||D ]\  }} |t          j	        g|R   n|r7| j
                            |           | j        |                                  dS dS dS )au  
        Requeue the contents of in-flight packets without declaring loss.
        Used by PTO probes (RFC 9002 6.2.4): the packet is removed from
        sent_packets and its delivery_handlers fire LOST so the stream
        sender re-enqueues the data, but congestion control is NOT informed
        and bytes_in_flight is reclaimed without applying a reduction.
        r   N)r.   r*   r   r   r   r   r+   r   r   r  r   r{   r   r   )	r1   rt   r   ra   rescheduled_ccrg   r   r   r   s	            r   r   z*QuicPacketRecovery._on_packets_rescheduled  s     02 	; 	;F"6#78 .%%f---& 3v/C 3--2-- )B~%' ; ;MGTG-2:T::::: 	,H++N;;; ,))+++++	, 	,,,r   )r   NN)r   r   r   r   r   r   r9   r:   r   r   r   r   r   r    )r   r:   )r   r   r   r    )r   r   r3   )T)r   r   r   r
   r   r   ra   r   r   r   r   r    r   )rg   r   r   r   r   r    )r   r   ra   r   r   r    )r   r   )F)rt   ru   r   r   ra   r   r   r    )r4   r5   r6   r   r2   propertyrA   rC   r   r   r   r   r   r   rs   r   r   r   r   r   r   r   r   r   r   r   e  s         "&/3.2%9 %9 %9 %9 %9N ( ( ( X( * * * X*( ( ( ($" " " "2
 
 
 
! ! ! !0 !%a7 a7 a7 a7 a7F* * * *, , , ,(- - - -^!B !B !B !BF   
 
 
 
 
,L, L, L, L,\, , , , , ,r   r   )r   r   r   r   )%
__future__r   loggingrO   typingr   r   r   _hazmatr   r	   r
   r   r   packet_builderr   r   r   r   r   K_MICRO_SECONDK_SECONDrB   r   rY   r}   rq   r   r   r   r   rl   rk   r   r   r8   r   r   r   r   <module>r)     s   " " " " " "   * * * * * * * * * * ? ? ? ? ? ? ? ? ? ? # # # # # # = = = = = = = =       	 #   !           < < < < < < < <(d d d d d d d dN	V, V, V, V, V, V, V, V, V, V,r   