o
    di                  
   @   s  d dl Z d dlZd dlZd dlZd dlmZmZ d dlmZ ddl	m
Z
mZmZ ddlmZmZmZ ddlmZ ddlmZmZmZm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"m#Z# ddl$m%Z%m&Z&m'Z'm(Z( ddl)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1 ddl2m3Z3m4Z4 ddl5m6Z6 ddl7m8Z8 ddl9m:Z:m;Z; ddl<m=Z= ddl>m?Z? dZ@dZAddgZBeCeDZEdeFe+ deFe* deFe+ fddZGdeFe+ deFe+ deFe+ fd d!ZHd"eFe- d#eFe- deFe- fd$d%ZId&e+d'e+deJfd(d)ZKd*ejLd+e#ddfd,d-ZMd.e(d*ejLddfd/d0ZNd1eOeP dePfd2d3ZQd4e;d5eJd6ePdejLfd7d8ZRd9e8d:ePd;ePd6ePdejLf
d<d=ZSd&ePd'ePdePfd>d?ZTd&ePd'ePdePfd@dAZUd;ePdePfdBdCZVdDeejW dee= fdEdFZXG dGdH dHeZYdS )I    N)OptionalUnion)AsyncIOEventEmitter   )clockrtpsdp)CODECSHEADER_EXTENSIONSis_rtx)RTCTrackEvent)InternalErrorInvalidAccessErrorInvalidStateErrorOperationError)MediaStreamTrack)RTCBundlePolicyRTCConfiguration)RTCDataChannelRTCDataChannelParameters)RTCCertificateRTCDtlsParametersRTCDtlsTransport)RTCIceCandidateRTCIceGathererRTCIceParametersRTCIceTransport)RTCRtpCodecCapabilityRTCRtpCodecParametersRTCRtpDecodingParametersRTCRtpHeaderExtensionParametersRTCRtpParametersRTCRtpReceiveParametersRTCRtpRtxParametersRTCRtpSendParameters)RemoteStreamTrackRTCRtpReceiver)RTCRtpSender)RTCRtpTransceiver)RTCSctpCapabilitiesRTCSctpTransport)RTCSessionDescription)RTCStatsReportz0.0.0.0	   audiovideocodecs	preferredreturnc                 C   s   |s| S t tt| }ttt|d d u}g }tdd |D ]4}| D ]/}|j |j krQ|j|jkrQ|| |rO|D ]}|jd |jkrN||  nq= nq"q|S )Nc                 S   s
   t |  S N)r   x r6   L/home/ubuntu/.local/lib/python3.10/site-packages/aiortc/rtcpeerconnection.py<lambda>>      
 z)filter_preferred_codecs.<locals>.<lambda>apt)	listfilterr   nextmimeTypelower
parametersappendpayloadType)r0   r1   
rtx_codecsrtx_enabledfilteredprefcodecrtxr6   r6   r7   filter_preferred_codecs4   s&   

rI   local_codecsremote_codecsc                    s   g }i }|D ]Z t  r. jd}t|tr-||v r-|| } j|jkr-|t  q| D ]/}t	| r_t|} j
tjv rF j
|_
tt fdd|j|_|| |||j
<  nq0q|S )Nr:   c                    s
   |  j v S r3   )rtcpFeedbackr4   cr6   r7   r8   i   r9   z$find_common_codecs.<locals>.<lambda>)r   r@   get
isinstanceint	clockRaterA   copydeepcopyis_codec_compatiblerB   r   DYNAMIC_PAYLOAD_TYPESr;   r<   rL   )rJ   rK   commoncommon_baser:   baserG   r6   rM   r7   find_common_codecsR   s0   




rZ   local_extensionsremote_extensionsc                 C   s2   g }|D ]}| D ]}|j |j kr|| qq|S r3   )urirA   )r[   r\   rW   rxlxr6   r6   r7   find_common_header_extensionsq   s   
r`   abc                 C   s   | j  |j  ks| j|jkrdS | j  dkrHdtdtfdd}dtdtjfdd}z|| ||ko<|| ||kW S  tyG   Y dS w d	S )
NFz
video/h264rN   r2   c                 S   s   t | jddS )Nzpacketization-mode0)rQ   r@   rO   rM   r6   r6   r7   packetization   s   z*is_codec_compatible.<locals>.packetizationc                 S   s   t t| jddd S )Nzprofile-level-id42E01Fr   )r   parse_h264_profile_level_idstrr@   rO   rM   r6   r6   r7   profile   s
   z$is_codec_compatible.<locals>.profileT)r>   r?   rR   r   rQ   r   H264Profile
ValueError)ra   rb   rd   rh   r6   r6   r7   rU   }   s    "rU   mediadtlsTransportc                 C   s   |j }|j}| | _|jdk| _| | _| jr(| jd j| _	| jd j
| _
nt| _	t| _
| jd u r:| | _d S | j| j_d S )N	completedr   )	transporticeGatherergetLocalCandidatesice_candidatesstateice_candidates_completegetLocalParametersiceiphostportDISCARD_HOSTDISCARD_PORTdtlsfingerprints)rk   rl   iceTransportro   r6   r6   r7   add_transport_description   s   


r~   r}   c                    s>   t | j|j}tj| I d H  |jr| d I d H  d S d S r3   )mapaddRemoteCandidaterq   asynciogatherrs   )r}   rk   corosr6   r6   r7   add_remote_candidates   s   r   midsc                 C   s.   d}	 t |}|| vr| | |S |d7 }q)z5
    Allocate a MID which has not been used yet.
    r   Tr   )rg   add)r   imidr6   r6   r7   allocate_mid   s   
r   sctplegacyr   c                 C   sn   |rt jdtd| jgd}d| j |j| j< nt jdtddgd}| j|_||j_| 	 |_
t|| j |S )Napplication	DTLS/SCTPkindrx   rh   fmtzwebrtc-datachannel zUDP/DTLS/SCTPzwebrtc-datachannel)r   MediaDescriptionrz   rx   _outbound_streams_countsctpmap	sctp_portr   muxIdgetCapabilitiessctpCapabilitiesr~   rn   )r   r   r   rk   r6   r6   r7   !create_media_description_for_sctp   s    
r   transceivercname	directionc                 C   s   t j| jtddd | jD d}||_| jj d| jj |_	t
| j| j|d|_t|_t|_d|_t j| jj|dg|_ttt|jjd rc|jt j| jj|d t jd	| jj| jjgd
g|_t|| jj |S )NzUDP/TLS/RTP/SAVPFc                 S   s   g | ]}|j qS r6   )rB   ).0rN   r6   r6   r7   
<listcomp>       z<create_media_description_for_transceiver.<locals>.<listcomp>r    r0   headerExtensionsr   T)ssrcr   FIDsemanticitems)r   r   r   rz   _codecsr   sender
_stream_id	_track_idmsidr!   _headerExtensionsr   ry   	rtcp_host	rtcp_portrtcp_muxSsrcDescription_ssrcr   r=   r<   r   r0   rA   	_rtx_ssrcGroupDescription
ssrc_groupr~   receiverrn   )r   r   r   r   rk   r6   r6   r7   (create_media_description_for_transceiver   s8   r   c                 C   s   t jt j| t j|@  S r3   r   
DIRECTIONSindexra   rb   r6   r6   r7   and_direction     r   c                 C   s   t jt j| t j|B  S r3   r   r   r6   r6   r7   or_direction  r   r   c                 C   s   | dkrdS | dkrdS | S )Nsendonlyrecvonlyr6   )r   r6   r6   r7   reverse_direction  s
   r   session_descriptionc                 C   s   | d urt t| | jdS d S )N)r   type)r+   rg   r   )r   r6   r6   r7   wrap_session_description  s
   
r   c                       s  e Zd ZdZdodee ddf 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edefddZedee fddZedefddZdee ddfddZdedefddZ	dpdeeef dedefddZdqd d!Zdefd"d#Z			$	%	&	drd'ed(ee d)ee d*ed+ed,ed-ee defd.d/Zdefd0d1Z de!e" fd2d3Z#de!e fd4d5Z$de%fd6d7Z&de!e fd8d9Z'	dod:ee ddfd;d<Z(d:eddfd=d>Z)dqd?d@Z*dqdAdBZ+dqdCdDZ,deddfdEdFZ-de.fdGdHZ/dqdIdJZ0	dodedKedLee defdMdNZ1dOedee fdPdQZ2dRedee fdSdTZ3dee4j5 fdUdVZ6dWede7fdXdYZ8dZed[e9ddfd\d]Z:dee4j5 fd^d_Z;dWede<fd`daZ=dbeddfdcddZ>dqdedfZ?dqdgdhZ@dqdidjZAdke4j5dleddfdmdnZB  ZCS )sRTCPeerConnectionz
    The :class:`RTCPeerConnection` interface represents a WebRTC connection
    between the local computer and a remote peer.

    :param configuration: An optional :class:`RTCConfiguration`.
    Nconfigurationr2   c                    s   t    t g| _t  | _|pt | _	t
 | _t
 | _i | _i | _t
 | _d | _d | _d| _d | _d | _tt | _g | _d | _d| _d| _d| _d | _d| _d | _d | _d | _ d | _!d S )NFnewstable)"super__init__r   generateCertificate _RTCPeerConnection__certificatesuuiduuid4_RTCPeerConnection__cnamer   !_RTCPeerConnection__configurationset"_RTCPeerConnection__dtlsTransports!_RTCPeerConnection__iceTransports_RTCPeerConnection__remoteDtls_RTCPeerConnection__remoteIce_RTCPeerConnection__seenMids_RTCPeerConnection__sctp$_RTCPeerConnection__sctp_mline_index_sctpLegacySdp"_RTCPeerConnection__sctpRemotePort"_RTCPeerConnection__sctpRemoteCapsrg   _RTCPeerConnection__stream_id _RTCPeerConnection__transceivers_RTCPeerConnection__closeTask#_RTCPeerConnection__connectionState&_RTCPeerConnection__iceConnectionState%_RTCPeerConnection__iceGatheringState_RTCPeerConnection__isClosed"_RTCPeerConnection__signalingState+_RTCPeerConnection__currentLocalDescription,_RTCPeerConnection__currentRemoteDescription+_RTCPeerConnection__pendingLocalDescription,_RTCPeerConnection__pendingRemoteDescription)selfr   	__class__r6   r7   r   %  s8   

zRTCPeerConnection.__init__c                 C      | j S )z
        The current connection state.

        Possible values: `"connected"`, `"connecting"`, `"closed"`, `"failed"`, `"new`".

        When the state changes, the `"connectionstatechange"` event is fired.
        )r   r   r6   r6   r7   connectionStateI     	z!RTCPeerConnection.connectionStatec                 C   r   )z
        The current ICE connection state.

        Possible values: `"checking"`, `"completed"`, `"closed"`, `"failed"`, `"new`".

        When the state changes, the `"iceconnectionstatechange"` event is fired.
        )r   r   r6   r6   r7   iceConnectionStateT  r   z$RTCPeerConnection.iceConnectionStatec                 C   r   )z
        The current ICE gathering state.

        Possible values: `"complete"`, `"gathering"`, `"new`".

        When the state changes, the `"icegatheringstatechange"` event is fired.
        )r   r   r6   r6   r7   iceGatheringState_  r   z#RTCPeerConnection.iceGatheringStatec                 C      t |  S )zw
        An :class:`RTCSessionDescription` describing the session for
        the local end of the connection.
        )r   $_RTCPeerConnection__localDescriptionr   r6   r6   r7   localDescriptionj     z"RTCPeerConnection.localDescriptionc                 C   r   )zx
        An :class:`RTCSessionDescription` describing the session for
        the remote end of the connection.
        )r   %_RTCPeerConnection__remoteDescriptionr   r6   r6   r7   remoteDescriptionr  r   z#RTCPeerConnection.remoteDescriptionc                 C   r   )z{
        An :class:`RTCSctpTransport` describing the SCTP transport being used
        for datachannels or `None`.
        )r   r   r6   r6   r7   r   z  s   zRTCPeerConnection.sctpc                 C   r   )z
        The current signaling state.

        Possible values: `"closed"`, `"have-local-offer"`, `"have-remote-offer`",
        `"stable"`.

        When the state changes, the `"signalingstatechange"` event is fired.
        )r   r   r6   r6   r7   signalingState  s   
z RTCPeerConnection.signalingState	candidatec                    s6  |dur|j du r|jdu rtd| jD ]#}|du s,|j |jks)|j| kr9|js9|jjj}|	|I dH  q| j
r_|du sR|j | j
jksN|j| jkr_| j
js_| j
jj}|	|I dH  |   }r|j}tdt|D ]"}|du r{d|| _qo|j|ks|j || jjkr|| j| qodS td dS )a-  
        Add a new :class:`RTCIceCandidate` received from the remote peer.

        The specified candidate must have a value for either `sdpMid` or
        `sdpMLineIndex`.

        :param candidate: The new remote candidate or `None` to signal
                            end-of-candidates.
        Nz2Candidate must have either sdpMid or sdpMLineIndexr   TzCRTCPeerConnection addIceCandidate called without remote description)sdpMidsdpMLineIndexrj   r   r   _get_mline_index_bundledr   rn   r   r   r   r   rk   rangelenrs   r   r   rq   rA   loggerwarning)r   r   r   r}   remote_descriptionrk   sdp_m_line_indexr6   r6   r7   addIceCandidate  sF   





	z!RTCPeerConnection.addIceCandidatetrackc                 C   s   |    |jdvrtd|j d| | | jD ] }|j|jkr:|jjdu r:|j| t|j	d|_	|j  S q| j
d|j|d}|jS )z
        Add a :class:`MediaStreamTrack` to the set of media tracks which
        will be transmitted to the remote peer.
        r.   r/   Invalid track kind ""Nr   sendrecvr   r   sender_track)#_RTCPeerConnection__assertNotClosedr   r   *_RTCPeerConnection__assertTrackHasNoSenderr   r   r  replaceTrackr   r   %_RTCPeerConnection__createTransceiver)r   r  r   r6   r6   r7   addTrack  s"   



zRTCPeerConnection.addTrackr  trackOrKindr   c                 C   sv   |    t|tr|j}|}n|}d}|dvrtd| d|tjvr,td| d|r3| | | j|||dS )z7
        Add a new :class:`RTCRtpTransceiver`.
        Nr  r  r  zInvalid direction "r  )	r
  rP   r   r   r   r   r   r  r  )r   r  r   r   r  r6   r6   r7   addTransceiver  s   


z RTCPeerConnection.addTransceiverc                    s   | j r| j I dH  dS t | _ | d | jD ]	}| I dH  q| jr.| j I dH  | jD ]}|jj I dH  |jjj I dH  q1| jr]| jj I dH  | jjj I dH  | 	  | 
  |   |   | j d dS )zM
        Terminate the ICE agent, ending ICE processing and streams.
        NclosedT)r   r   Future%_RTCPeerConnection__setSignalingStater   stopr   r   rn   +_RTCPeerConnection__updateIceGatheringState,_RTCPeerConnection__updateIceConnectionState)_RTCPeerConnection__updateConnectionStateremove_all_listeners
set_result)r   r   r6   r6   r7   close  s*   



zRTCPeerConnection.closec                    sB  |    | jdvrtd| j dt d? }t }d| d| d|_|j	tj
dd	gd
 d|_|  jD ]F}|jdv r]| |jj}t|| jt|j|j|jd}|jj}nt| j| j| jjd}| jj}|jdkrvd|j_n|j|j_|j	| q;tj
dg d
}|jD ]
}|j 	|jj q|j!	| t"|S )z
        Create an SDP answer to an offer received from a remote peer during
        the offer/answer negotiation of a WebRTC connection.

        :rtype: :class:`RTCSessionDescription`
        have-remote-offerzhave-local-pranswerz)Cannot create answer in signaling state "r      - r    IN IP4 0.0.0.0WMS*r   answerr  r   r   r   r   r   autoclientBUNDLE)#r
  r   r   r   current_ntp_timer   SessionDescriptionoriginmsid_semanticrA   r   r   r   rk   r   '_RTCPeerConnection__getTransceiverByMidr   r   r   r   r   r   _offerDirectionr   r   rn   r   r   r   _roler{   roler   groupr   )r   ntp_secondsdescriptionremote_mr   rk   rl   bundler6   r6   r7   createAnswer$  sL   






zRTCPeerConnection.createAnswerT FlabelmaxPacketLifeTimemaxRetransmitsorderedprotocol
negotiatedidc           	   	   C   sH   |dur|durt d| js|   t|||||||d}t| j|S )zf
        Create a data channel with the given label.

        :rtype: :class:`RTCDataChannel`
        Nz8Cannot specify both maxPacketLifeTime and maxRetransmits)r=  r7  r8  r9  r<  r:  r;  )rj   r   '_RTCPeerConnection__createSctpTransportr   r   )	r   r7  r8  r9  r:  r;  r<  r=  r@   r6   r6   r7   createDataChannel\  s   	z#RTCPeerConnection.createDataChannelc              	      sp  |    | jD ]}tt|j dd |j|_t|j dd |_q| j	
 }t d? }t  d| d| d _ jtjddgd d	 _d
tjdttj fdd}dttj dtdttj fdd}||  }||  }ttt|t|D ]O}|||}	|||}
|	r|	jn|
j}|	r|	jjn|
jj}|dv r| |}| |  j!t"|| j#|j$|d q|dkr|| _% j!t&| j'| j(|d qdtf fdd}t)dd | jD ]}| |   j!t"|| j#|j$t*|d q| j'r| j'j+du r| | _% j!t&| j'| j(t*|d tjdg d} j!D ]}|j,|jj q" j-| t. S )z
        Create an SDP offer for the purpose of starting a new WebRTC
        connection to a remote peer.

        :rtype: :class:`RTCSessionDescription`
        Nr  r  r   r  r   r!  r   offerr2  r2   c                 S   s   | r| j S g S r3   )rk   r2  r6   r6   r7   	get_media  s   z0RTCPeerConnection.createOffer.<locals>.get_mediark   r   c                 S   s   |t | k r
| | S d S r3   )r   )rk   r   r6   r6   r7   get_media_section  s   z8RTCPeerConnection.createOffer.<locals>.get_media_sectionr  r#  r   r$  c                      s
   t  jS r3   )r   rk   r6   rA  r6   r7   next_mline_index  s   
z7RTCPeerConnection.createOffer.<locals>.next_mline_indexc                 S   s   | j d u o| j S r3   )r   stoppedr4   r6   r6   r7   r8     r   z/RTCPeerConnection.createOffer.<locals>.<lambda>r'  )/r
  r   rI   r	   r   _preferred_codecsr   r
   r   r   rS   r   r(  r   r)  r*  r+  rA   r   r   r;   r   rQ   r   r   r   r   maxr   r   r   r,  _set_mline_indexrk   r   r   r   r   r   r   r   r<   r   r   r   r0  r   )r   r   r   r1  rB  rC  local_mediaremote_mediar   local_mr3  
media_kindr   rD  r4  rk   r6   rA  r7   createOffer|  s   










zRTCPeerConnection.createOfferc                 C      t tdd | jS )z|
        Returns the list of :class:`RTCRtpReceiver` objects that are currently
        attached to the connection.
        c                 S   r   r3   )r   r4   r6   r6   r7   r8         z0RTCPeerConnection.getReceivers.<locals>.<lambda>r;   r   r   r   r6   r6   r7   getReceivers     zRTCPeerConnection.getReceiversc                 C   rN  )zz
        Returns the list of :class:`RTCRtpSender` objects that are currently
        attached to the connection.
        c                 S   r   r3   )r   r4   r6   r6   r7   r8     rO  z.RTCPeerConnection.getSenders.<locals>.<lambda>rP  r   r6   r6   r7   
getSenders  rR  zRTCPeerConnection.getSendersc                    sP   t  }dd |  D dd |  D  }tj| I dH D ]}|| q|S )za
        Returns statistics for the connection.

        :rtype: :class:`RTCStatsReport`
        c                 S   s   g | ]}|  qS r6   )getStatsr   r5   r6   r6   r7   r     s    z.RTCPeerConnection.getStats.<locals>.<listcomp>N)r,   rS  rQ  r   r   update)r   mergedr   reportr6   r6   r7   rT    s   zRTCPeerConnection.getStatsc                 C   s
   t | jS )z
        Returns the list of :class:`RTCRtpTransceiver` objects that are currently
        attached to the connection.
        )r;   r   r   r6   r6   r7   getTransceivers  s   
z!RTCPeerConnection.getTransceiverssessionDescriptionc           	         sT  |    |du r'| jdkr|  I dH }n|  I dH }| d|j|j n	| d|j|j tj|j}|j|_| j	|dd |jdkrM| 
d n
|jd	krW| 
d
 t|jD ]'\}}|jj}| j| |jdv rz| |}|| q\|jdkr|| j_q\|jdkr| jD ]}|jsd|j_d|_q|jd	krt|jD ]&\}}|jdv r| |}|jj|jj q|jdkr| jj|jj q| jD ]}|jdv r| t!|j"|j# q| $ I dH  t|jD ]$\}}|jdv r| |}t%||jj q|jdkrt%|| jj qt&'| (  |jd	kr%|| _)d| _*dS || _*dS )a  
        Change the local description associated with the connection.

        :param sessionDescription: An :class:`RTCSessionDescription` generated
                                    by :meth:`createOffer` or :meth:`createAnswer()`
                                    or `None` to implicitly create an offer or create
                                    an answer, as needed.
        Nr  z$setLocalDescription(%s, implicit)
%szsetLocalDescription(%s)
%sTis_localr@  have-local-offerr"  r   r  r   r"  pranswer)+r
  r   r5  rM  _RTCPeerConnection__log_debugr   r   r)  parse(_RTCPeerConnection__validate_descriptionr  	enumeraterk   r   r   r   r   r   ._RTCPeerConnection__getTransceiverByMLineIndex_set_midr   r   r   	_role_set_connectionice_controllingr   rn   	_set_roler{   r/  r   _setCurrentDirectionr   r   r-  _RTCPeerConnection__gatherr~   r   ensure_future_RTCPeerConnection__connectr   r   )	r   rZ  r2  r   rk   r   r   r}   tr6   r6   r7   setLocalDescription  s~   

















z%RTCPeerConnection.setLocalDescriptionc                    s  |  d|j|j tj|j}|j|_| j|dd i }g }t|jD ]J\}}d}| j	|j
j |jdv rd}| jD ]}	|	j|jkrS|	jd|j
jfv rS|	} nq>|du r`| jd|jd}|jdu rq||j
j || ttt|j |j
j|j}
t|
std|j|
|_tt|j |j
j|_t|j }|jd	v r|!| n||_"|d
v r|j#j$st%|j|&|d|j#_'|(t)|j#|j#j$|d |j#j*}|j+| j,|< |j-| j.|< nK|jdkr)| j/s| 0  | j/jdu r|j
j| j/_|| _1|j2dkrd| _3t4|j5d | _6nd| _3|j7| _6|j8| _9| j/j*}|j+| j,| j/< |j-| j.| j/< |durp|j*}|||< |jdkrH|j:sH|j-j;|j<_=d|_:|jdkr[|j+j>dkr[|j?dd |jdkrp|j?|j+j>dkrldndd q%t@dd |jAD d}|r3|jBr3|jBd }d}| jD ]}|j|kr|j#j*} nq| j/r| j/j|kr| j/j*}tC }|jBdd }| jD ]#}|j|v r|jDs|	|j#j* |j#E| |jFE| d|_Dq| j/r| j/j|v r| j/jDs|	| j/j* | j/E| d| j/_D|D ]&}|G I dH  |j*G I dH  | jHI| | jJI|j* |K|j*d q | L  | M  | N  dd |B D }tOjP| I dH  |D ]
}| Qd|j$ qFtOR| S  |jdkrd| Td n|jdkro| Td |jdkr}|| _Ud| _VdS || _VdS )z
        Changes the remote description associated with the connection.

        :param sessionDescription: An :class:`RTCSessionDescription` created from
                                    information received over the signaling channel.
        zsetRemoteDescription(%s)
%sFr[  Nr  r   )r   r   z3Failed to set remote {} description send parametersr^  r   r  )r   r=  )r   r  r   r   r   Tr   r@  r&  server)r/  r"  c                 s   s    | ]
}|j d kr|V  qdS )r'  N)r   rU  r6   r6   r7   	<genexpr>  s    z9RTCPeerConnection.setRemoteDescription.<locals>.<genexpr>r   c                 S   s   g | ]	\}}t ||qS r6   )r   )r   r}   rk   r6   r6   r7   r     s    z:RTCPeerConnection.setRemoteDescription.<locals>.<listcomp>r  r  r   )Wr`  r   r   r)  ra  rb  rc  rk   r   r   r   r   r   r   r   r  re  rH  rI   rZ   r	   r0   rF  r   r   formatr   r`   r
   r   r   r   r   rj  r-  r   r  r%   webrtc_track_id_trackrA   r   rn   r{   r   ru   r   r   r>  r   rh   r   rQ   r   r   r   r   r   rf  iceLiterg  rh  r/  ri  r=   r0  r   r   r   setTransportr   r  r   discardr   popr  r  r  r   r   emitrl  rm  r  r   r   )r   rZ  r2  iceCandidatestrackEventsr   rk   rl   r   rn  rW   r   r}   r4  
primaryMidprimaryTransportoldTransports	slaveMidsr   eventr6   r6   r7   setRemoteDescription^  s  	






	






z&RTCPeerConnection.setRemoteDescriptionc                    sN  | j D ]U}|jj}|j}|j rY|| jv rY|| j| I d H  |jdkr2|| j| I d H  |jdkrY|j	dv rH|j
| |I d H  |j	dv rY|j| |I d H  q| jr| jj}|j}|j r| j| jv r|| j| j I d H  |jdkr|| j| j I d H  |jdkr| j| j| jI d H  d S d S d S d S d S )Nr   	connected)r   r  rp  )r   r   rn   ro   rp   r   startrr   r   currentDirectionr   send_RTCPeerConnection__localRtpreceive_RTCPeerConnection__remoteRtpr   r   r   )r   r   rl   r}   r6   r6   r7   	__connect!  sF   








zRTCPeerConnection.__connectc                    s&   t dd | j}tj| I d H  d S )Nc                 S   s
   | j  S r3   )ro   r   rn  r6   r6   r7   r8   C  r9   z,RTCPeerConnection.__gather.<locals>.<lambda>)r   r   r   r   )r   r   r6   r6   r7   __gatherB  s   zRTCPeerConnection.__gatherc                 C   s   | j rtdd S )NzRTCPeerConnection is closed)r   r   r   r6   r6   r7   __assertNotClosedF  s   z#RTCPeerConnection.__assertNotClosedc                 C   s$   |   D ]}|j|krtdqd S )NzTrack already has a sender)rS  r  r   )r   r  r   r6   r6   r7   __assertTrackHasNoSenderJ  s
   
z*RTCPeerConnection.__assertTrackHasNoSenderc                 C   s   t | jdks
| jr1t | jdkr| jd jjjj }n| jjjj }t| jj	|j
|jd}nt| jj	d}|d| j t|}|d| j |d| j | j| t|| j}|d| j | j| |   |   |   |S )Nr   )
iceServerslocal_usernamelocal_password)r  statechange)r   r   r   r   rn   ro   rt   r   r   r  usernameFragmentpasswordonr  r   r  r  r   r   r   r   r   )r   r@   ro   r}   rl   r6   r6   r7   __createDtlsTransportO  s6   z'RTCPeerConnection.__createDtlsTransportc                    s|   d } j jtjkot jdk}|r jd jj}n  }t	| _
| j
_d  j
_ j
ddtdd f fdd}d S )Nr   datachannelchannelr2   c                    s     d|  d S )Nr  )rz  )r  r   r6   r7   on_datachannel  s   z?RTCPeerConnection.__createSctpTransport.<locals>.on_datachannel)r   bundlePolicyr   
MAX_BUNDLEr   r   r   rn   '_RTCPeerConnection__createDtlsTransportr*   r   r   r   r  r   )r   rl   bundledr  r6   r   r7   __createSctpTransportt  s   

z'RTCPeerConnection.__createSctpTransportr   r	  c                    s   d }d}| j jtjkr&t| jdkr| jd jj}d}n&| jr%| jj}d}n| j jtj	krBt
t fdd| jd }|rB|jj}d}|sH|  }t| t|pO |t |d}|j|jj | j|j_||_| j| |S )NFr   Tc                    
   | j  kS r3   r   r  r  r6   r7   r8     r9   z7RTCPeerConnection.__createTransceiver.<locals>.<lambda>)r   r   r   r   )r   r  r   r  r   r   r   rn   r   BALANCEDr=   r<   r  r(   r'   r&   _set_rtcp_ssrcr   r   r   r   r   rA   )r   r   r   r	  rl   r  r   r6   r  r7   __createTransceiver  s<   
z%RTCPeerConnection.__createTransceiverr   c                       t t fdd| jd S )Nc                    r  r3   r   r4   r  r6   r7   r8     r9   z9RTCPeerConnection.__getTransceiverByMid.<locals>.<lambda>r=   r<   r   )r   r   r6   r  r7   __getTransceiverByMid  s   z'RTCPeerConnection.__getTransceiverByMidr   c                    r  )Nc                    s   |    kS r3   )r   r4   r   r6   r7   r8     s    z@RTCPeerConnection.__getTransceiverByMLineIndex.<locals>.<lambda>r  )r   r   r6   r  r7   __getTransceiverByMLineIndex  s   z.RTCPeerConnection.__getTransceiverByMLineIndexc                 C      | j p| jS r3   )r   r   r   r6   r6   r7   __localDescription     z$RTCPeerConnection.__localDescriptionr   c                 C   s6   t |j|j|jd}| j|j_|jj|j_	d|j_
|S )Nr   T)r$   r   r   r   r   rtcpr   r   r   r   mux)r   r   r   r6   r6   r7   
__localRtp  s   
zRTCPeerConnection.__localRtpmsgargsc                 G   s   t jd| g|R   d S )NzRTCPeerConnection() )r   debug)r   r  r  r6   r6   r7   __log_debug  s   zRTCPeerConnection.__log_debugc                 C   r  r3   )r   r   r   r6   r6   r7   __remoteDescription  r  z%RTCPeerConnection.__remoteDescriptionc                 C   s   |   j|  }t|j|j|jj|jjd}t	|j
r`i }|jD ]7}t|rJ|jd}t|trI||v rIt	|j
dkrIt|j
d j
d|| _q!t|j
d j
|jd||j< q!t| |_|S )N)r0   r   r   r  r:      r   )r   r   )r   rB   )r   rk   r   r"   r   r   r   r   r  r   r   r   r@   rO   rP   rQ   r#   rH   r   rB   r;   values	encodings)r   r   rk   receiveParametersr  rG   r:   r6   r6   r7   __remoteRtp  s2   


zRTCPeerConnection.__remoteRtprr   c                 C   s   || _ | d d S )Nsignalingstatechange)r   rz  )r   rr   r6   r6   r7   __setSignalingState  s   z%RTCPeerConnection.__setSignalingStatec                 C   s   t tdd | j}t tdd | j}| jrd}n0d|v s"d|v r%d}n%|ddgs6|ddgs6d}nd|v s>d|v rAd}n	d|v rHd}nd	}|| jkr_| d
| j| || _| d | jsx| j	d u rz|t dgkr|t
|  | _	d S d S d S d S )Nc                 S   r   r3   rr   r4   r6   r6   r7   r8     rO  z;RTCPeerConnection.__updateConnectionState.<locals>.<lambda>c                 S   r   r3   r  r4   r6   r6   r7   r8     rO  r  failedr   checking
connectingr  zconnectionState %s -> %sconnectionstatechange)r   r   r   r   r   
differencer   r`  rz  r   r   rl  r  )r   
dtlsStates	iceStatesrr   r6   r6   r7   __updateConnectionState  s6   


z)RTCPeerConnection.__updateConnectionStatec                 C   s   t tdd | j}| jrd}nd|v rd}n|t dgkr!d}n	d|v r(d}nd}|| jkrA| d| j| || _| d	 d S d S )
Nc                 S   r   r3   r  r4   r6   r6   r7   r8     rO  z>RTCPeerConnection.__updateIceConnectionState.<locals>.<lambda>r  r  rm   r  r   ziceConnectionState %s -> %siceconnectionstatechange)r   r   r   r   r   r`  rz  r   statesrr   r6   r6   r7   __updateIceConnectionState  s"   
z,RTCPeerConnection.__updateIceConnectionStatec                 C   sl   t tdd | j}|t dgkrd}n	d|v rd}nd}|| jkr4| d| j| || _| d d S d S )	Nc                 S   s   | j jS r3   )ro   rr   r4   r6   r6   r7   r8   $  s    z=RTCPeerConnection.__updateIceGatheringState.<locals>.<lambda>rm   complete	gatheringr   ziceGatheringState %s -> %sicegatheringstatechange)r   r   r   r   r`  rz  r  r6   r6   r7   __updateIceGatheringState"  s   
z+RTCPeerConnection.__updateIceGatheringStater2  r\  c                 C   sR  |r*|j dkr| jdvrtd| j dn;|j dkr)| jdvr)td| j dn'|j dkr>| jdvr=td| j dn|j dkrQ| jd	vrQtd| j d|jD ])}|jjr^|jjsbtd
|j dv rq|jj	dvrqtd|j
dv r}|js}tdqT|j dv r|r|  n|  }dd |jD }dd |jD }||krtdd S d S )Nr@  )r   r]  z(Cannot handle offer in signaling state "r  r"  r  z)Cannot handle answer in signaling state ")r   r  )r]  zhave-remote-pranswerz,ICE username fragment or password is missingr^  )r&  rq  z@DTLS setup attribute must be 'active' or 'passive' for an answerr  zRTCP mux is not enabledc                 S      g | ]	}|j |jjfqS r6   r   r   r   r   rk   r6   r6   r7   r   p  s    z<RTCPeerConnection.__validate_description.<locals>.<listcomp>c                 S   r  r6   r  r  r6   r6   r7   r   q  s    z+Media sections in answer do not match offer)r   r   r   rk   ru   r  r  rj   r{   r/  r   r   r   r   )r   r2  r\  rk   r@  offer_mediaanswer_mediar6   r6   r7   __validate_description4  sj   









z(RTCPeerConnection.__validate_descriptionr3   )r  )r2   N)NNTr6  FN)D__name__
__module____qualname____doc__r   r   r   propertyrg   r   r   r   r+   r   r   r*   r   r   r   r  r   r'   r  r   r(   r  r  r5  rQ   boolr   r?  rM  r;   r&   rQ  rS  r,   rT  rY  ro  r  rm  rk  r
  r  r   r  r>  r  r,  rd  r   r)  r   r$   r  objectr`  r   r"   r  r  r  r  r  rb  __classcell__r6   r6   r   r7   r     s    $


:


#;	
 `
_
 
D
!

%
#

$
r   )Zr   rS   loggingr   typingr   r   pyee.asyncior   r6  r   r   r   r0   r	   r
   r   eventsr   
exceptionsr   r   r   r   mediastreamsr   rtcconfigurationr   r   rtcdatachannelr   r   rtcdtlstransportr   r   r   rtcicetransportr   r   r   r   rtcrtpparametersr   r   r   r    r!   r"   r#   r$   rtcrtpreceiverr%   r&   rtcrtpsenderr'   rtcrtptransceiverr(   rtcsctptransportr)   r*   rtcsessiondescriptionr+   statsr,   ry   rz   MEDIA_KINDS	getLoggerr  r   r;   rI   rZ   r`   r  rU   r   r~   r   r   rg   r   r   r   r   r   r   r)  r   r   r6   r6   r6   r7   <module>   s    (









'

