o
    di}                     @   sP  U d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlmZ d dl	m
Z
mZ d dlmZmZ d dlmZmZ d dl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m Z  d	dl!m"Z" d	dl#m$Z$m%Z%m&Z&m'Z'm(Z( e)e*Z+dZ,dZ-dZ.dZ/d	Z0dZ1d	Z2dZ3dZ4dZ5dZ6dZ7dZ8dZ9dZ:d	Z;dZ<dZ=dZ>dZ?dZ@dZAdZBd ZCd!ZDdZEdZFd ZGd	ZHdZId"ZJd#ZKd$ZLd%ZMd&ZNd'ZOd(ZPd)ZQeeReeSeTf  ZUd*d+d,eVfd-d.ZWd/eTd,eXeReSeTf  fd0d1ZYd2eXeReSeTf  d,eTfd3d4ZZd5eSd,eSfd6d7Z[d8eSd,eSfd9d:Z\d8eSd,eSfd;d<Z]G d=d+ d+Z^G d>d? d?e^Z_G d@dA dAe_Z`G dBdC dCe^ZaG dDdE dEe^ZbG dFdG dGe^ZcG dHdI dIe_ZdG dJdK dKe^ZeG dLdM dMe_ZfG dNdO dOe_ZgG dPdQ dQe^ZhG dRdS dSehZiG dTdU dUehZjG dVdW dWe_ZkG dXdY dYe^ZlG dZd[ d[e^ZmG d\d] d]e^ZnG d^d_ d_e^Zoeceiejelefege`emenedebeaeoekeegZpeqd`da epD ZrdbeTd,eReSeSeSeXe^ f fdcddZsdeeSdfeSdgeSd*e^d,eTf
dhdiZteG djdk dkZueG dldm dmZveG dndo doZweuewevdpZxeqeSeeyeu eyew eyev f f ezdq< G drds dsZ{eG dtdu duZ|G dvdw dweZ}dS )x    N)deque)CallableIterator)	dataclassfield)packunpack_from)DequeOptionalUnioncast)value)AsyncIOEventEmitter   )InvalidStateError)RTCDataChannelRTCDataChannelParameters)RTCDtlsTransport)random32
uint16_add	uint16_gt	uint32_gt
uint32_gte   <   i  i           
      g      ?g      ?g      @l                       i  i            2   3   5   8   9   chunkChunkreturnc                 C   s   | j jS N)	__class____name__)r-    r3   K/home/ubuntu/.local/lib/python3.10/site-packages/aiortc/rtcsctptransport.py
chunk_typeN   s   r5   bodyc                 C   sj   g }d}|t | d kr3td| |\}}||| |d ||  f ||t| 7 }|t | d ks|S )Nr   r   !HH)lenr   appendpadl)r6   paramspos
param_typeparam_lengthr3   r3   r4   decode_paramsR   s   r?   r;   c                 C   sN   d}d}| D ]\}}t |d }||7 }|td||| 7 }dt| }q|S )N    r   r7       )r8   r   r:   )r;   r6   paddingr=   param_valuer>   r3   r3   r4   encode_params\   s   rD   lengthc                 C   s   | d }|r
d| S dS )Nr   r   r3   )rE   mr3   r3   r4   r:   g   s   r:   ac                 C   s   | d t  S Nr   SCTP_TSN_MODULOrG   r3   r3   r4   tsn_minus_onel      rL   c                 C   s   | d t  S rH   rI   rK   r3   r3   r4   tsn_plus_onep   rM   rN   c                   @   sD   e Zd ZdZddededdfdd	Zdefd
dZdefddZ	dS )r.   r   r@   flagsr6   r/   Nc                 C   s   || _ || _d S r0   rP   r6   selfrP   r6   r3   r3   r4   __init__w      
zChunk.__init__c                 C   s<   | j }td| j| jt|d | }|dtt| 7 }|S )N!BBHr   rA   )r6   r   typerP   r8   r:   )rS   r6   datar3   r3   r4   	__bytes__{   s   zChunk.__bytes__c                 C   s   t |  d| j dS )Nz(flags=))r5   rP   rS   r3   r3   r4   __repr__   s   zChunk.__repr__)r   r@   )
r2   
__module____qualname__rW   intbytesrT   rY   strr\   r3   r3   r3   r4   r.   t   s
    c                   @   :   e Zd Zd
dedee ddfddZedefdd	ZdS )BaseParamsChunkr   NrP   r6   r/   c                 C   s"   || _ |rt|| _d S g | _d S r0   )rP   r?   r;   rR   r3   r3   r4   rT      s   
zBaseParamsChunk.__init__c                 C   s
   t | jS r0   )rD   r;   r[   r3   r3   r4   r6      s   
zBaseParamsChunk.bodyr   N	r2   r]   r^   r_   r
   r`   rT   propertyr6   r3   r3   r3   r4   rc      s    rc   c                   @      e Zd ZdZdS )
AbortChunk   Nr2   r]   r^   rW   r3   r3   r3   r4   rh          rh   c                   @   rg   )CookieAckChunk   Nrj   r3   r3   r3   r4   rl      rk   rl   c                   @   rg   )CookieEchoChunkr   Nrj   r3   r3   r3   r4   rn      rk   rn   c                   @   s   e Zd ZU dZeed< eed< eed< ee ed< ee ed< eed< eed< eed	< ee ed
< ddedee	 ddfddZ
de	fddZdefddZdS )	DataChunkr   _acked
_abandoned
_book_size_expiry_max_retransmits_misses_retransmit_sent_count
_sent_timeNrP   r6   r/   c                 C   sX   || _ |rtd|\| _| _| _| _|dd  | _d S d| _d| _d| _d| _d| _d S )Nz!LHHL   r   r@   )rP   r   tsn	stream_id
stream_seqprotocol	user_datarR   r3   r3   r4   rT      s   
zDataChunk.__init__c              	   C   sR   dt | j }td| j| j|| j| j| j| j| j }|d r'|dt	| 7 }|S )Nr#   z!BBHLHHLr   rA   )
r8   r~   r   rW   rP   rz   r{   r|   r}   r:   )rS   rE   rX   r3   r3   r4   rY      s"   
zDataChunk.__bytes__c              	   C   &   d| j  d| j d| j d| j d	S )NzDataChunk(flags=z, tsn=z, stream_id=z, stream_seq=rZ   )rP   rz   r{   r|   r[   r3   r3   r4   r\         zDataChunk.__repr__rd   )r2   r]   r^   rW   bool__annotations__r_   r
   floatr`   rT   rY   ra   r\   r3   r3   r3   r4   ro      s   
 ro   c                   @   rg   )
ErrorChunk	   Nrj   r3   r3   r3   r4   r      rk   r   c                   @   L   e Zd ZdZddedee ddfddZedefd	d
Z	de
fddZdS )ForwardTsnChunk   r   NrP   r6   r/   c                 C   sz   || _ g | _|r8td|dd | _d}|t|k r6| jttttf td|| |d7 }|t|k sd S d S d| _d S )N!Lr   r   r7   )	rP   streamsr   cumulative_tsnr8   r9   r   tupler_   )rS   rP   r6   r<   r3   r3   r4   rT      s   
zForwardTsnChunk.__init__c                 C   s0   t d| j}| jD ]\}}|t d||7 }q	|S )Nr   r7   )r   r   r   )rS   r6   r{   r|   r3   r3   r4   r6      s   zForwardTsnChunk.bodyc                 C      d| j  d| j dS )NzForwardTsnChunk(cumulative_tsn=z
, streams=rZ   )r   r   r[   r3   r3   r4   r\      s   
zForwardTsnChunk.__repr__rd   r2   r]   r^   rW   r_   r
   r`   rT   rf   r6   ra   r\   r3   r3   r3   r4   r      s    r   c                   @   rg   )HeartbeatChunkr   Nrj   r3   r3   r3   r4   r      rk   r   c                   @   rg   )HeartbeatAckChunk   Nrj   r3   r3   r3   r4   r      rk   r   c                   @   rb   )BaseInitChunkr   NrP   r6   r/   c                 C   sf   || _ |rtd|\| _| _| _| _| _t|dd  | _d S d| _d| _d| _d| _d| _g | _d S )N!LLHHLr#   r   )	rP   r   initiate_tagadvertised_rwndoutbound_streamsinbound_streamsinitial_tsnr?   r;   rR   r3   r3   r4   rT      s    
zBaseInitChunk.__init__c                 C   s.   t d| j| j| j| j| j}|t| j7 }|S )Nr   )r   r   r   r   r   r   rD   r;   )rS   r6   r3   r3   r4   r6     s   zBaseInitChunk.bodyrd   re   r3   r3   r3   r4   r      s    r   c                   @   rg   )	InitChunkr   Nrj   r3   r3   r3   r4   r      rk   r   c                   @   rg   )InitAckChunkr   Nrj   r3   r3   r3   r4   r   $  rk   r   c                   @   rg   )ReconfigChunkr'   Nrj   r3   r3   r3   r4   r   (  rk   r   c                   @   sH   e Zd ZdZddedee ddfddZdefd	d
Zde	fddZ
dS )	SackChunkr   r   NrP   r6   r/   c                 C   s   || _ g | _g | _|rFtd|\| _| _}}d}t|D ]}| jtd|| |d7 }qt|D ]}| jtd||d  |d7 }q1d S d| _d| _d S )Nz!LLHHry   r7   r   r   r   )rP   gaps
duplicatesr   r   r   ranger9   )rS   rP   r6   nb_gapsnb_duplicatesr<   ir3   r3   r4   rT   /  s(   


zSackChunk.__init__c              
   C   s   ddt | jt | j   }td| j| j|| j| jt | jt | j}| jD ]}|tdg|R  7 }q&| jD ]	}|td|7 }q6|S )Nr#   r   z!BBHLLHHr7   r   )r8   r   r   r   rW   rP   r   r   )rS   rE   rX   gaprz   r3   r3   r4   rY   E  s    


zSackChunk.__bytes__c              	   C   r   )NzSackChunk(flags=z, advertised_rwnd=, cumulative_tsn=z, gaps=rZ   )rP   r   r   r   r[   r3   r3   r4   r\   W  r   zSackChunk.__repr__rd   )r2   r]   r^   rW   r_   r
   r`   rT   rY   ra   r\   r3   r3   r3   r4   r   ,  s
    r   c                   @   r   )ShutdownChunkr!   r   NrP   r6   r/   c                 C   s(   || _ |rtd|d | _d S d| _d S )Nr   r   )rP   r   r   rR   r3   r3   r4   rT   a  s   
zShutdownChunk.__init__c                 C   s   t d| jS )Nr   )r   r   r[   r3   r3   r4   r6   h  s   zShutdownChunk.bodyc                 C   r   )NzShutdownChunk(flags=r   rZ   )rP   r   r[   r3   r3   r4   r\   l  s   zShutdownChunk.__repr__rd   r   r3   r3   r3   r4   r   ^  s    r   c                   @   rg   )ShutdownAckChunkr   Nrj   r3   r3   r3   r4   r   r  rk   r   c                   @   rg   )ShutdownCompleteChunk   Nrj   r3   r3   r3   r4   r   v  rk   r   c                 c   s    | ]}|j |fV  qd S r0   )rW   ).0clsr3   r3   r4   	<genexpr>  s    r   rX   c                 C   s   t | }|dk rtdtd| \}}}td| dd }|t| dd d | dd   kr2tdg }d}||d	 krmtd
| |\}}	}
| |d	 ||
  }t|}|r_|||	|d ||
t|
 7 }||d	 ks<||||fS )Nry   z(SCTP packet length is less than 12 bytes!HHL<Lr   r          z SCTP packet has invalid checksumr   rV   rQ   )r8   
ValueErrorr   crc32cCHUNK_TYPESgetr9   r:   )rX   rE   source_portdestination_portverification_tagchecksumchunksr<   r5   chunk_flagschunk_length
chunk_body	chunk_clsr3   r3   r4   parse_packet  s$   $
r   r   r   r   c                 C   s8   t d| ||}t|}t|d | }|t d| | S )Nr   r   r   )r   r`   r   )r   r   r   r-   headerrX   r   r3   r3   r4   serialize_packet  s   r   c                   @   s`   e Zd ZU eed< eed< eed< eedZee ed< defddZ	e
d	edd fd
dZdS )StreamResetOutgoingParamrequest_sequenceresponse_sequencelast_tsn)default_factoryr   r/   c                 C   s2   t d| j| j| j}| jD ]	}|t d|7 }q|S )N!LLL!H)r   r   r   r   r   )rS   rX   streamr3   r3   r4   rY     s   
z"StreamResetOutgoingParam.__bytes__rX   c                 C   sP   t d|\}}}g }tdt|dD ]}|t d||d  q| ||||dS )Nr   ry   r   r   r   r   r   r   r   )r   r   r8   r9   )r   rX   r   r   r   r   r<   r3   r3   r4   parse  s   zStreamResetOutgoingParam.parseN)r2   r]   r^   r_   r   r   listr   r`   rY   classmethodr   r3   r3   r3   r4   r     s   
 r   c                   @   B   e Zd ZU eed< eed< defddZededd fddZd	S )
StreamAddOutgoingParamr   new_streamsr/   c                 C   s   t d| j| jd}|S )N!LHHr   )r   r   r   )rS   rX   r3   r3   r4   rY     s   z StreamAddOutgoingParam.__bytes__rX   c                 C   s   t d|\}}}| ||dS )Nr   )r   r   r   )r   rX   r   r   reservedr3   r3   r4   r     s   zStreamAddOutgoingParam.parseN	r2   r]   r^   r_   r   r`   rY   r   r   r3   r3   r3   r4   r     s   
 r   c                   @   r   )
StreamResetResponseParamr   resultr/   c                 C   s   t d| j| jS )N!LL)r   r   r   r[   r3   r3   r4   rY     s   z"StreamResetResponseParam.__bytes__rX   c                 C   s   t d|\}}| ||dS )Nr   r   r   r   )r   rX   r   r   r3   r3   r4   r     s   zStreamResetResponseParam.parseNr   r3   r3   r3   r4   r     s   
 r   )r"   r#   r$   RECONFIG_PARAM_TYPESc                   @   sV   e Zd ZdddZdeddfddZdeeeee	f  fdd	Z
d
edefddZdS )InboundStreamr/   Nc                 C   s   g | _ d| _d S Nr   )
reassemblysequence_numberr[   r3   r3   r4   rT     rU   zInboundStream.__init__r-   c                 C   sx   | j rt|j| j d jr| j | d S t| j D ]\}}|j|jks(J dt|j|jr9| j ||  d S qd S )NrO   zduplicate chunk in reassembly)r   r   rz   r9   	enumerateinsert)rS   r-   r   rchunkr3   r3   r4   	add_chunk  s   zInboundStream.add_chunkc                 c   s<   d}d }|t | jk r| j| }|d u r:|jt@  }|jt@ s)|r$d S |d7 }q|r4t|j| jr4d S |j}|}n|j|krJ|rCd S d }|d7 }q|jt	@ rd
dd | j||d  D }| jd | | j|d d   | _|r|j| jkrt| jd| _|}|j|j|fV  n|d7 }t|}|t | jk sd S d S )Nr   r   r@   c                 S   s   g | ]}|j qS r3   )r~   )r   cr3   r3   r4   
<listcomp>(  s    z.InboundStream.pop_messages.<locals>.<listcomp>)r8   r   rP   SCTP_DATA_UNORDEREDSCTP_DATA_FIRST_FRAGr   r|   r   rz   SCTP_DATA_LAST_FRAGjoinr   r{   r}   rN   )rS   r<   	start_posr-   orderedexpected_tsnr~   r3   r3   r4   pop_messages  sF   



zInboundStream.pop_messagesrz   c                 C   sT   d}d}t | jD ]\}}t||jr|}|t|j7 }q	 | j|d d | _|S )z3
        Prune chunks up to the given TSN.
        rO   r   r   N)r   r   r   rz   r8   r~   )rS   rz   r<   sizer   r-   r3   r3   r4   prune_chunks6  s   zInboundStream.prune_chunksr/   N)r2   r]   r^   rT   ro   r   r   r   r_   r`   r   r   r3   r3   r3   r4   r     s
    
)r   c                   @   s   e Zd ZU dZeed< dS )RTCSctpCapabilitiesz
    The :class:`RTCSctpCapabilities` dictionary provides information about the
    capabilities of the :class:`RTCSctpTransport`.
    maxMessageSizeN)r2   r]   r^   __doc__r_   r   r3   r3   r3   r4   r   G  s   
 r   c                       s  e Zd ZdZddededdf fddZedefd	d
Z	ede
e fddZedefddZedefddZedefddZedefddZdeddfddZdededdfddZdddZdddZddd Zd!eddfd"d#Zd!eddfd$d%Zd&eeeef  ddfd'd(Zd&eeeef  ddfd)d*Zd+ede fd,d-Z!defd.d/Z"d0eddfd1d2Z#d!edefd3d4Z$d5edefd6d7Z%d+ed8ed0eddfd9d:Z&d!e'ddfd;d<Z(d!eddfd=d>Z)d!e*ddfd?d@Z+d!e,ddfdAdBZ-dCe.e/e0e1f ddfdDdEZ2			Fdd+ed8edGedHe
e3 dIe
e dJeddfdKdLZ4d!e'ddfdMdNZ5dCe.e/e0e1f ddfdOdPZ6ddQdRZ7ddUdVZ8ddWdXZ9ddYdZZ:d!e'ddfd[d\Z;dd]d^Z<dd_d`Z=d!e>ddfdadbZ?ddcddZ@ddedfZAddgdhZBddidjZCddkdlZDddmdnZEddodpZFdqe3ddfdrdsZGdteHddfdudvZId+eddfdwdxZJddydzZKdteHddfd{d|ZLdteHddfd}d~ZMd+ed8ed0eddfddZNdteHd0e.eef ddfddZOG dd dePjQZR  ZSS )RTCSctpTransportz
    The :class:`RTCSctpTransport` interface includes information relating to
    Stream Control Transmission Protocol (SCTP) transport.

    :param transport: An :class:`RTCDtlsTransport`.
      	transportportr/   Nc                    s  |j dkrtt   | jj| _dd | _d| _d| _	|| _
t | _td| _d| _|| _t | _g | _d| _d | _d| _d	| _i | _d| _t| _d | _g | _t  | _!d| _"d
t# | _$d | _%d| _&d | _'d| _(t | _)t*| j)| _+t*| j)| _,t- | _.i | _/t| _0d| _1t- | _2g | _3d | _4| j)| _5d| _6d | _7d | _8t9| _:d | _;d| _<d | _=d | _>d| _?d | _@d | _Ad | _Bt- | _Ci | _Dd| _Ed | _Fd S )Nclosedc                  W   s   d S r0   r3   )argsr3   r3   r4   <lambda>d  s    z+RTCSctpTransport.__init__.<locals>.<lambda>Fnewr#   Tr   i   r   )Gstater   superrT   StateCLOSED_association_state_RTCSctpTransport__log_debug_RTCSctpTransport__started_RTCSctpTransport__state_RTCSctpTransport__transportasyncioget_event_loop_looposurandom	_hmac_key_local_partial_reliability_local_portr   _local_verification_tag_remote_extensions_remote_partial_reliability_remote_port_remote_verification_tag_advertised_rwnd_inbound_streams_inbound_streams_countMAX_STREAMS_inbound_streams_max_last_received_tsn_sack_duplicatesset_sack_misordered_sack_neededUSERDATA_MAX_LENGTH_cwnd_fast_recovery_exit_fast_recovery_transmit_forward_tsn_chunk_flight_size
_local_tsnrL   _last_sacked_tsn_advanced_peer_ack_tsnr   _outbound_queue_outbound_stream_seq_outbound_streams_count_partial_bytes_acked_sent_queue_reconfig_queue_reconfig_request_reconfig_request_seq_reconfig_response_seq_srtt_rttvarSCTP_RTO_INITIAL_rto	_t1_chunk_t1_failures
_t1_handle	_t2_chunk_t2_failures
_t2_handle
_t3_handle_data_channel_id_data_channel_queue_data_channels_bundledmid)rS   r   r   r1   r3   r4   rT   ^  sr   






zRTCSctpTransport.__init__c                 C   s   | j j jdkS )Ncontrolling)r   roler[   r3   r3   r4   	is_server  s   zRTCSctpTransport.is_serverc                 C   s   | j r
t| j | jS dS )z`
        The maximum number of :class:`RTCDataChannel` that can be used simultaneously.
        N)r  minr"  r[   r3   r3   r4   maxChannels  s   zRTCSctpTransport.maxChannelsc                 C      | j S )zD
        The local SCTP port number used for data channels.
        )r  r[   r3   r3   r4   r        zRTCSctpTransport.portc                 C   r?  )z:
        The current state of the SCTP transport.
        )r   r[   r3   r3   r4   r     r@  zRTCSctpTransport.statec                 C   r?  )zT
        The :class:`RTCDtlsTransport` over which SCTP data is transmitted.
        r   r[   r3   r3   r4   r     r@  zRTCSctpTransport.transportc                 C   s
   t ddS )zb
        Retrieve the capabilities of the transport.

        :rtype: RTCSctpCapabilities
        i   )r   )r   )r   r3   r3   r4   getCapabilities  s   
z RTCSctpTransport.getCapabilitiesc                 C   s
   || _ d S r0   rA  )rS   r   r3   r3   r4   setTransport  s   
zRTCSctpTransport.setTransport
remoteCaps
remotePortc                    s   | j s?d| _ d| _|| _ttjr#d| jrdpd   fdd| _| jr*d| _	nd	| _	| j
|  | jsA|  I d
H  d
S d
S d
S )z&
        Start the transport.
        T
connectingzRTCSctpTransport(%s) serverclientc                    s   t j |  g|R  S r0   )loggerdebug)msgr   prefixr3   r4   r     s    z(RTCSctpTransport.start.<locals>.<lambda>r   r   N)r   r   r  rI  isEnabledForloggingDEBUGr<  r   r4  r   _register_data_receiver_init)rS   rD  rE  r3   rL  r4   start  s$   zRTCSctpTransport.startc                    s<   | j | jjkr|  I dH  | j|  | | jj dS )z%
        Stop the transport.
        N)r   r   r   _abortr   _unregister_data_receiver
_set_stater[   r3   r3   r4   stop  s
   zRTCSctpTransport.stopc                    s4   t  }z| |I dH  W dS  ty   Y dS w )z(
        Abort the association.
        N)rh   _send_chunkConnectionErrorrS   r-   r3   r3   r4   rT    s   zRTCSctpTransport._abortc                    sh   t  }| j|_| j|_| j|_| j|_| j	|_
| |j | |I dH  | | | | jj dS )z-
        Initialize the association.
        N)r   r  r   r  r   r"  r   r  r   r  r   _set_extensionsr;   rX  	_t1_startrV  r   COOKIE_WAITrZ  r3   r3   r4   rR    s   
zRTCSctpTransport._initr-   c                 C   s   t d| j|j | _d S r   )maxr  rr   rZ  r3   r3   r4   _flight_size_decrease  s   z&RTCSctpTransport._flight_size_decreasec                 C   s   |  j |j7  _ d S r0   )r  rr   rZ  r3   r3   r4   _flight_size_increase  s   z&RTCSctpTransport._flight_size_increaser;   c                 C   s4   |D ]\}}|t krd| _q|tkrt|| _qdS )zI
        Gets what extensions are supported by the remote party.
        TN)SCTP_PRSCTP_SUPPORTEDr
  SCTP_SUPPORTED_CHUNK_EXTr   r	  )rS   r;   kvr3   r3   r4   _get_extensions  s   
z RTCSctpTransport._get_extensionsc                 C   sF   g }| j r|tdf |tj |tj |tt|f dS )zH
        Sets what extensions are supported by the local party.
        r@   N)r  r9   ra  r   rW   r   rb  r`   )rS   r;   
extensionsr3   r3   r4   r[  (  s   z RTCSctpTransport._set_extensionsr{   c                 C   s    || j vrt | j |< | j | S )zI
        Get or create the inbound stream with the specified ID.
        )r  r   )rS   r{   r3   r3   r4   _get_inbound_stream4  s   

z$RTCSctpTransport._get_inbound_streamc                 C   s   t t S r0   )r_   timer[   r3   r3   r4   _get_timestamp<  rM   zRTCSctpTransport._get_timestamprX   c                    s   z
t |\}}}}W n
 ty   Y dS w tdd |D }|r,t|dks)J d}n| j}||kr<| d|| dS |D ]
}| |I dH  q>| jrU|  I dH  dS dS )z8
        Handle data received from the network.
        Nc                 S   s   g | ]	}t |tr|qS r3   )
isinstancer   r   xr3   r3   r4   r   I  s    z1RTCSctpTransport._handle_data.<locals>.<listcomp>r   r   zBad verification tag %d vs %d)r   r   r8   r  r   _receive_chunkr  
_send_sack)rS   rX   _r   r   
init_chunkexpected_tagr-   r3   r3   r4   _handle_data?  s*   zRTCSctpTransport._handle_datac                 C   s   |j rdS |jduo|j|jkp|jduo|jt k }|s dS | j|}t|ddD ]}| j| }d|_ d|_|j	t
@ r@ nq,t|t| jD ]}| j| }d|_ d|_|j	t@ r^ dS qIdS )z
        Determine if a chunk needs to be marked as abandoned.

        If it does, it marks the chunk and any other chunk belong to the same
        message as abandoned.
        TNFrO   )rq   rt   rw   rs   rh  r$  indexr   rv   rP   r   r8   r   )rS   r-   abandon	chunk_posr<   ochunkr3   r3   r4   _maybe_abandon_  s4   





zRTCSctpTransport._maybe_abandonrz   c                    s   t  j|s| jv r j| dS  j| t jD ]}|t jkr+| _q dtdt	f fdd}t
t| j _tt| j _dS )z8
        Mark an incoming data TSN as received.
        Trl  r/   c                       t |  jS r0   r   r  rl  r[   r3   r4   is_obsolete  rM   z4RTCSctpTransport._mark_received.<locals>.is_obsoleteF)r   r  r  r  r9   addsortedrN   r_   r   r   filterr  )rS   rz   r{  r3   r[   r4   _mark_received  s   zRTCSctpTransport._mark_receivedpp_idc                    s   |  |||I dH  dS )z-
        Receive data stream -> ULP.
        N)_data_channel_receive)rS   r{   r  rX   r3   r3   r4   _receive  s   zRTCSctpTransport._receivec                    s  |  d| t|tr| |I dH  dS t|tr%| |I dH  dS t|tr4| |I dH  dS t|trJt	 }|j
|_
| |I dH  dS t|tr]|  d | | jj dS t|tr|   | | jj t }| |I dH  | | | | jj dS t|tr| j| jjkr|   | | jj dS t|tr| j| jjkr|j
D ]}t|d }|dur| ||d I dH  qdS t|trJ| jrJt |j!| _"t |j!| _#|j$| _%|j&| _'| (|j
 |  d|j)|j* t+|j)| j,| _-t+| j.|j*| _.t/ }| j0|_$| j1|_&| j.|_)| j,|_*| j2|_!| 3|j
 t4d| 5 }|t67| j8|d9 7 }|j
:t;|f | |I dH  dS t|t<r| jr|j=}t>|t?ksst67| j8|dd	 d9 |d	d krz|  d
 dS | 5 }t@d|d }	|	|tA k s|	|kr|  d tB }
|
j
:tCdf | |
I dH  dS tD }| |I dH  | | jj dS t|t/r0| j| jjEkr0| F  t |j!| _"t |j!| _#|j$| _%|j&| _'| (|j
 |  d|j)|j* t+|j)| j,| _-t+| j.|j*| _.t< }|j
D ]\}}|t;kr||_= nq
| |I dH  | G| | | jjH dS t|tDrK| j| jjHkrK| F  | | jj dS t|tBro| j| jjE| jjHfv rq| F  | | jj |  d dS dS dS )z+
        Handle an incoming chunk.
        z< %sNz)x Association was aborted by remote partyr   r   z;- Peer supports %d outbound streams, %d max inbound streamsr   sha1r   zx State cookie is invalidzx State cookie has expireds           z!x Could not establish association)Ir   rj  ro   _receive_data_chunkr   _receive_sack_chunkr   _receive_forward_tsn_chunkr   r   r;   rX  rh   rV  r   r   r   
_t2_cancelSHUTDOWN_RECEIVEDr   	_t2_startSHUTDOWN_ACK_SENTr   r   r   ESTABLISHEDr   r   _receive_reconfig_paramr   r   r<  rL   r   r  r(  r   r  r   	_ssthreshre  r   r   r=  r  r  r"  r   r  r  r  r[  r   ri  hmacr   r  digestr9   SCTP_STATE_COOKIErn   r6   r8   COOKIE_LENGTHr   COOKIE_LIFETIMEr   SCTP_CAUSE_STALE_COOKIErl   r]  
_t1_cancelr\  COOKIE_ECHOED)rS   r-   heartbeat_ackshutdown_ackparamr   init_ackcookienowstamperror
cookie_ackechorc  rd  r3   r3   r4   rm    s   








*




zRTCSctpTransport._receive_chunkc                    sz   d| _ | |jrdS | |j}|| |  jt|j8  _|	 D ]}|  jt|d 7  _| j
| I dH  q%dS )z&
        Handle a DATA chunk.
        TNr   )r  r  rz   rg  r{   r   r  r8   r~   r   r  )rS   r-   inbound_streammessager3   r3   r4   r  5  s   
z$RTCSctpTransport._receive_data_chunkc                    s  d _ t j|jrdS dtdtf fdd}|j _tt| j _t	 jD ]}|t
 jkr7| _q* tt| j _tt| j _|jD ])\}} |}t|d|_| D ]}  jt|d 7  _ j| I dH  q`qM j D ]\}}  j| j7  _q|dS )	z-
        Handle a FORWARD TSN chunk.
        TNrl  r/   c                    rx  r0   ry  rz  r[   r3   r4   r{  S  rM   z@RTCSctpTransport._receive_forward_tsn_chunk.<locals>.is_obsoleter   r   )r  r   r  r   r_   r   r  r~  r  r}  rN   r   r  r   rg  r   r   r   r  r8   r  r  itemsr   )rS   r-   r{  rz   r{   r|   r  r  r3   r[   r4   r  I  s2   


z+RTCSctpTransport._receive_forward_tsn_chunkc                    s  t | j|jr
dS t }|j| _| j| jk}d}d}| jr]t| j| jd jr]| j	 }|d7 }|j
s?||j7 }| | |dkrP|jdkrP| ||j  | jr]t| j| jd js)d}|jrt }|jD ]}	t|	d |	d d D ]}
|j|
 t }|| quqh|j}| jD ]"}t |j|r n|j|v r|j
s||j7 }d|_
| | |j}q| jD ]0}t |j|r n'|j|vr| jd7  _|jdkrd|_| |sd|_d|_
| | d}q| jdu r<|r|r| j| jkr|  jt|t7  _n|  j|7  _| j| jkr|  j| j8  _|  jt7  _|r;t| jd dt | _| j| _d| _| jd	 j| _d| _nt|j| jrGd| _| jsP|   n|rW|    | !  | " I dH  | # I dH  dS )
z&
        Handle a SACK chunk.
        Nr   r   FTr   r   r   rO   )$r   r  r   rh  r  r  r$  r   rz   popleftrp   rr   r_  rw   _update_rtorx   r   r  r   rJ   r|  ru   rw  rv   r  r  r=  r  r#  r^  r  
_t3_cancel_t3_restart_update_advanced_peer_ack_point_data_channel_flush	_transmit)rS   r-   received_timecwnd_fully_utilizeddone
done_bytesschunklossseenr   r<   highest_seen_tsnhighest_newly_ackedr3   r3   r4   r  s  s   












z$RTCSctpTransport._receive_sack_chunkr  c                    s"  |  d| t|tr;|jD ]}| j|d | j|}|r%| | qt	|j
dd}|j
| _| |I dH  dS t|tr]|  j|j7  _t	|j
dd}|j
| _| |I dH  dS t|t	r| jr|j| jj
kr| jjD ]}| j|d | | qpd| _|  I dH  dS dS dS dS )z/
        Handle a RE-CONFIG parameter.
        z<< %sNr   r   )r   rj  r   r   r  popr6  r   _data_channel_closer   r   r(  _send_reconfig_paramr   r  r   r&  r   r!  _data_channel_closed_transmit_reconfig)rS   r  r{   channelresponse_paramr3   r3   r4   r    sB   	




z(RTCSctpTransport._receive_reconfig_paramTr~   expirymax_retransmitsr   c                    s4  |r| j |d}nd}tt|t }d}	td|D ]i}
t }d|_|s*t	|_|
dkr5| jt
O  _|
|d krB| jtO  _| j|_||_||_||_||	|	t  |_d|_d|_t|j|_||_||_d|_d|_d|_d|_|	t7 }	t| j| _| j| q|rt|d| j |< |  I dH  dS )z*
        Send data ULP -> stream.
        r   r   FN) r!  r   mathceilr8   r  r   ro   rP   r   r   r   r  rz   r{   r|   r}   r~   rq   rp   rr   rs   rt   ru   rv   rw   rx   rN   r   r9   r   r  )rS   r{   r  r~   r  r  r   r|   	fragmentsr<   fragmentr-   r3   r3   r4   _send  sF   zRTCSctpTransport._sendc                    s4   |  d| | jt| j| j| j|I dH  dS )z9
        Transmit a chunk (no bundling for now).
        z> %sN)r   r   
_send_datar   r  r  r  rZ  r3   r3   r4   rX  >  s   zRTCSctpTransport._send_chunkc                    s`   t  }t D ]\}}t||r|} nq|j|t|f | d| | |I d H  d S )Nz>> %s)	r   r   r  rj  r;   r9   r`   r   rX  )rS   r  r-   rc  r   r=   r3   r3   r4   r  L  s   
z%RTCSctpTransport._send_reconfig_paramc                    s   g }d}t | jD ]}|| j t }||kr||d d< n|||g t|}q
t }| j|_td| j	|_
| jdd |_dd |D |_| |I dH  | j  d| _dS )zJ
        Build and send a selective acknowledgement (SACK) chunk.
        NrO   r   r   c                 S   s   g | ]}t |qS r3   )r   rk  r3   r3   r4   r   n  s    z/RTCSctpTransport._send_sack.<locals>.<listcomp>F)r}  r  r  rJ   r9   rN   r   r   r^  r  r   r  r   r   rX  clearr  )rS   r   gap_nextrz   r<   sackr3   r3   r4   rn  \  s"   


zRTCSctpTransport._send_sackr   RTCSctpTransport.Statec                 C   s   || j kr| d| j | || _ || jjkr9d| _t| j D ]}|jr/|j	dkr/|
d q t|   dS || jjkrc|   |   |   d| _t| j D ]}| | qU|   dS dS )zA
        Transition the SCTP association to a new state.
        z
- %s -> %s	connectedopenr   N)r   r   r   r  r   r   r6  values
negotiated
readyState_setReadyStater   ensure_futurer  r   r  r  r  keysr  remove_all_listeners)rS   r   r  r{   r3   r3   r4   rV  u  s&   

zRTCSctpTransport._set_statec                 C   :   | j d ur| dt| j | j   d | _ d | _d S d S )Nz- T1(%s) cancel)r/  r   r5   r-  cancelr[   r3   r3   r4   r       


zRTCSctpTransport._t1_cancelc                 C   p   |  j d7  _ d | _| dt| j| j  | j tkr#| | jj d S t	
| | j | j| j| j| _d S )Nr   zx T1(%s) expired %d)r.  r/  r   r5   r-  SCTP_MAX_INIT_RETRANSrV  r   r   r   r  rX  r  
call_laterr,  _t1_expiredr[   r3   r3   r4   r       
zRTCSctpTransport._t1_expiredc                 C   D   | j d u sJ || _d| _| dt| j | j| j| j| _ d S )Nr   z- T1(%s) start)	r/  r-  r.  r   r5   r  r  r,  r  rZ  r3   r3   r4   r\    
   zRTCSctpTransport._t1_startc                 C   r  )Nz- T2(%s) cancel)r2  r   r5   r0  r  r[   r3   r3   r4   r    r  zRTCSctpTransport._t2_cancelc                 C   r  )Nr   zx T2(%s) expired %d)r1  r2  r   r5   r0  SCTP_MAX_ASSOCIATION_RETRANSrV  r   r   r   r  rX  r  r  r,  _t2_expiredr[   r3   r3   r4   r    r  zRTCSctpTransport._t2_expiredc                 C   r  )Nr   z- T2(%s) start)	r2  r0  r1  r   r5   r  r  r,  r  rZ  r3   r3   r4   r    r  zRTCSctpTransport._t2_startc                 C   st   d | _ | d | jD ]
}| |sd|_q|   d | _d| _d| _t	| j
d dt | _t| _
t|   d S )Nzx T3 expiredTr   r   r   )r3  r   r$  rw  rv   r  r  r  r#  r^  r  r  r  r   r  r  rZ  r3   r3   r4   _t3_expired  s   


zRTCSctpTransport._t3_expiredc                 C   s<   |  d | jd ur| j  d | _| j| j| j| _d S )Nz- T3 restart)r   r3  r  r  r  r,  r  r[   r3   r3   r4   r    s
   


zRTCSctpTransport._t3_restartc                 C   s0   | j d u sJ | d | j| j| j| _ d S )Nz
- T3 start)r3  r   r  r  r,  r  r[   r3   r3   r4   	_t3_start  s   
zRTCSctpTransport._t3_startc                 C   s,   | j d ur| d | j   d | _ d S d S )Nz- T3 cancel)r3  r   r  r[   r3   r3   r4   r    s
   



zRTCSctpTransport._t3_cancelc                    s^  | j dur| | j I dH  d| _ | js|   | jdur#dt }ndt }t| j| | j}d}| j	D ]6}|j
ri| jrAd| _n| j|krI dS | | d|_d|_
| jd7  _| |I dH  |ri|   d}q5| jr| j|k r| j }| j	| | | | jd7  _t |_| |I dH  | js|   | jr| j|k stdS dS dS dS )z)
        Transmit outbound data.
        Nr   r   TFr   r   )r  rX  r3  r  r  r  r=  r  r  r$  rv   r  r`  ru   rw   r  r   r  r9   rh  rx   )rS   
burst_sizecwndretransmit_earliestr-   r3   r3   r4   r    sF   








 zRTCSctpTransport._transmitc                    s   | j | jjkr=| jr?| jsA| jdt }| jtd  | _t| j| jt	| j
|d}|| _t| j| _| |I d H  d S d S d S d S )Nr   r   )r   r   r  r%  r&  RECONFIG_MAX_STREAMSr   r'  r(  rL   r  rN   r  )rS   r   r  r3   r3   r4   r  "  s$   z#RTCSctpTransport._transmit_reconfigc                 C   s   t | j| jr| j| _d}i }| jr9| jd jr9| j }|j| _|d7 }|jt@ s0|j	||j
< | jr9| jd js|rNt | _| j| j_t| | j_dS dS )zQ
        Try to advance "Advanced.Peer.Ack.Point" according to RFC 3758.
        r   r   N)r   r  r  r$  rq   r  rz   rP   r   r|   r{   r   r  r   r   r  r   )rS   r  r   r-   r3   r3   r4   r  5  s    


z0RTCSctpTransport._update_advanced_peer_ack_pointRc                 C   sx   | j du r|d | _|| _ ndt | j tt| j |   | _dt | j  t|  | _ ttt| j d| j  t| _	dS )zA
        Update RTO given a new roundtrip measurement R.
        Nr   r   r   )
r)  r*  SCTP_RTO_BETAabsSCTP_RTO_ALPHAr^  SCTP_RTO_MINr=  SCTP_RTO_MAXr,  )rS   r  r3   r3   r4   r  K  s   


"zRTCSctpTransport._update_rtor  c                 C   s   |j dvrT|d | j| jjkr*| j|j t| jdkr(t	
|   dS dS t }| jD ]}|d |kr=|| q0|| _|jdurM| j|j |d dS dS )z^
        Request closing the datachannel by sending an Outgoing Stream Reset Request.
        )closingr   r  r   r   Nr   )r  r  r   r   r  r%  r9   idr8   r   r  r  r   r5  r6  r  )rS   r  	new_queue
queue_itemr3   r3   r4   r  Y  s"   




z$RTCSctpTransport._data_channel_closec                 C   s   | j |}|d d S )Nr   )r6  r  r  )rS   r{   r  r3   r3   r4   r  r  s   z%RTCSctpTransport._data_channel_closedc                    s   | j | jjkr
dS | jrx| jsz| j \}}}|j}|du r:| j}|| jv r0|d7 }|| jv s'|| j|< |	| |t
krI| |||I dH  n'|jrVt |jd  }nd}| j|||||j|jdI dH  |t|  | jr|| jrdS dS dS dS )z
        Try to flush buffered data to the SCTP layer.

        We wait until the association is established, as we need to know
        whether we are a client or a server to correctly assign an odd/even ID
        to the data channels.
        Nr   i  )r  r  r   )r   r   r  r5  r   r  r  r4  r6  _setIdWEBRTC_DCEPr  maxPacketLifeTimerh  maxRetransmitsr   _addBufferedAmountr8   )rS   r  r}   r~   r{   r  r3   r3   r4   r  v  s8   



z$RTCSctpTransport._data_channel_flushc                 C   sJ   |j | jv rtd|j  d|| j|j < | j| jjkr#|d d S d S )NData channel with ID  already registeredr  )r  r6  r   r   r   r  r  )rS   r  r3   r3   r4   _data_channel_add_negotiated  s   z-RTCSctpTransport._data_channel_add_negotiatedc              	   C   s   |j d ur|j | jv rtd|j  d|| j|j < t}d}d}|js'|dO }|jd ur4|dO }|j}n|jd ur@|dO }|j}tdt|||t	|j
t	|j}||j
d7 }||jd7 }| j|t|f t|   d S )	Nr  r  r   r%   r   r   !BBHLHHutf8)r  r6  r   DATA_CHANNEL_RELIABLEr   r  r  r   DATA_CHANNEL_OPENr8   labelr}   encoder5  r9   r  r   r  r  )rS   r  channel_typepriorityreliabilityrX   r3   r3   r4   _data_channel_open  s<   


	z#RTCSctpTransport._data_channel_openc                    s
  |t krt|r|d }|tkrt|dkr|| jvsJ td|\}}}}}}	d}
||
|
|  d}|
|7 }
||
|
|	  d}d }d }|d@ dkrR|}n|d@ dkrZ|}t||d@ dk||||d	}t| |d
}|d || j|< | j	
|t tdtf |  I d H  | d| d S |tkr|| jv sJ | j| }|d d S d S |tkr|| jv r| j| d|d d S |tkr|| jv r| j| dd d S |tkr|| jv r| j| d| d S |tkr|| jv r| j| dd d S d S d S )Nr   ry   r  r  r   r   r   r%   )r  r   r  r  r}   r  Fr  z!Bdatachannelr   r@   )r  r8   r  r6  r   decoder   r   r  r5  r9   r   DATA_CHANNEL_ACKr  emitWEBRTC_STRINGWEBRTC_STRING_EMPTYWEBRTC_BINARYWEBRTC_BINARY_EMPTY)rS   r{   r  rX   msg_typer  r  r  label_lengthprotocol_lengthr<   r  r}   r  r  
parametersr  r3   r3   r4   r    sj   	



z&RTCSctpTransport._data_channel_receivec                 C   s   |dkr
t d}}nt|trt|d}}n|dkr"td}}nt|}}|t| | j	
|||f t|   d S )Nr  rA   r  r@   )r  rj  ra   r  r  r  r  r  r8   r5  r9   r   r  r  )rS   r  rX   r  r~   r3   r3   r4   _data_channel_send  s   

z#RTCSctpTransport._data_channel_sendc                   @   s,   e Zd ZdZdZdZdZdZdZdZ	dZ
d	S )
r  r   r   r   r   r   ri   r!   r   N)r2   r]   r^   r   r]  r  r  SHUTDOWN_PENDINGSHUTDOWN_SENTr  r  r3   r3   r3   r4   r      s    r   )r   r   )NNT)r   r  r/   N)Tr2   r]   r^   r   r   r_   rT   rf   r   r<  r
   r>  r   ra   r   r   r   r   rB  rC  rS  rW  rT  rR  ro   r_  r`  r   r   r`   re  r[  r   rg  ri  rr  rw  r  r  r.   rm  r  r   r  r   r  r   r   r   r   r  r   r  rX  r  rn  rV  r  r  r\  r  r  r   r  r  r  r  r  r  r  r  r  r   r  r  r  r  r  r  r
  enumEnumr   __classcell__r3   r3   r9  r4   r   V  s    M

	


 ! *_
9
8












5

)	$
D

r   )~r   r  r  rO  r  r  rh  collectionsr   collections.abcr   r   dataclassesr   r   structr   r   typingr	   r
   r   r   google_crc32cr   r   pyee.asyncior   
exceptionsr   rtcdatachannelr   r   rtcdtlstransportr   utilsr   r   r   r   r   	getLoggerr2   rI  r  r  r  r  SCTP_CAUSE_INVALID_STREAMr  r   r   r   r  SCTP_MAX_BURSTr  r  r  r+  r  r  rJ   r  r  SCTP_STR_RESET_OUT_REQUESTSCTP_STR_RESET_RESPONSESCTP_STR_RESET_ADD_OUT_STREAMSrb  ra  r   r  r  $DATA_CHANNEL_PARTIAL_RELIABLE_REXMIT#DATA_CHANNEL_PARTIAL_RELIABLE_TIMEDDATA_CHANNEL_RELIABLE_UNORDERED.DATA_CHANNEL_PARTIAL_RELIABLE_REXMIT_UNORDERED-DATA_CHANNEL_PARTIAL_RELIABLE_TIMED_UNORDEREDr  r  r  r  r  r   r_   r`   DataChannelQueuera   r5   r   r?   rD   r:   rL   rN   r.   rc   rh   rl   rn   ro   r   r   r   r   r   r   r   r   r   r   r   r   CHUNK_CLASSESdictr   r   r   r   r   r   r   rW   r   r   r   r   r3   r3   r3   r4   <module>   s  
 

5"2"
M