o
    di c                  	   @   s  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m	Z	 d dl
mZmZmZmZmZ d dlZd dlmZ d dlmZ d dlmZ d dlmZ d dl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# ddl$m%Z%m&Z& ddl!m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/ ddl0m1Z1m2Z2 edddZ3edZ4edZ5e6e7Z8e9 e: e; dZ<eddG dd dZ=e=ej>ddddZ?e=ej@dd ddZAe=ejBd!d d"dZCg ZDeEe= eFd#< e?eAeCfD ]ZGzeeGjHd$ W n
 ejIy   Y qw eDJeG qd%ejKd&eLd'eLfd(d)ZMd*ejNd'ejKfd+d,ZOG d-d. d.ejPZQeG d/d0 d0ZRG d1d dZSeG d2d3 d3ZTG d4d5 d5eZUG d6d7 d7eZVG d8d9 d9eZWG d:d; d;ZXG d<d= d=eZYdS )>    N)	dataclassfield)OptionalProtocolTypeTypeVarUnion)x509)default_backend)hashes)ec)SSL)AsyncIOEventEmitter)PolicySession   )clockrtp)RTCIceTransport)RTCRtpReceiveParametersRTCRtpSendParameters)	AnyRtcpPacketRtcpByePacket
RtcpPacketRtcpPsfbPacketRtcpRrPacketRtcpRtpfbPacketRtcpSrPacket	RtpPacketis_rtcp)RTCStatsReportRTCTransportStatsCERTIFICATE_TRTCCertificate)boundKV)zsha-256zsha-384zsha-512T)frozenc                   @   sD   e Zd ZU eed< eed< eed< eed< dededefdd	Zd
S )SRTPProtectionProfilelibsrtp_profileopenssl_profile
key_lengthsalt_lengthsrcidxreturnc                 C   sB   || j  }d| j  || j  }|||| j   |||| j   S )N   )r+   r,   )selfr-   r.   	key_start
salt_start r4   K/home/ubuntu/.local/lib/python3.10/site-packages/aiortc/rtcdtlstransport.pyget_key_and_salt:   s   
z&SRTPProtectionProfile.get_key_and_saltN)__name__
__module____qualname__int__annotations__bytesr6   r4   r4   r4   r5   r(   3   s   
 r(   s   SRTP_AEAD_AES_256_GCM       )r)   r*   r+   r,   s   SRTP_AEAD_AES_128_GCM   s   SRTP_AES128_CM_SHA1_80   SRTP_PROFILES)srtp_profilecertificate	algorithmr/   c                    s:   |  t|    d fddtdt dD S )N:c                 3   s     | ]} ||d   V  qdS )r0   Nr4   .0x	hexstringr4   r5   	<genexpr>g   s    z%certificate_digest.<locals>.<genexpr>r   r0   )fingerprintX509_DIGEST_ALGORITHMShexupperjoinrangelen)rC   rD   r4   rI   r5   certificate_digeste   s   $rS   keyc              
   C   s   t t t jjttd	dg}t
j
jt
jjd}t  |||  t  |t
jdd |t
jdd }|| t t S )Nr?   ascii)tzr   )days   )r	   NameNameAttributeNameOIDCOMMON_NAMEbinasciihexlifyosurandomdecodedatetimenowtimezoneutcCertificateBuildersubject_nameissuer_name
public_keyserial_numberrandom_serial_numbernot_valid_before	timedeltanot_valid_aftersignr   SHA256r
   )rT   namerc   builderr4   r4   r5   generate_certificatej   s"   

	rs   c                   @   s    e Zd ZdZdZdZdZdZdS )Stater   r   r0         N)r7   r8   r9   NEW
CONNECTING	CONNECTEDCLOSEDFAILEDr4   r4   r4   r5   rt      s    rt   c                   @   s$   e Zd ZU dZeed< 	 eed< dS )RTCDtlsFingerprintzz
    The :class:`RTCDtlsFingerprint` dictionary includes the hash function
    algorithm and certificate fingerprint.
    rD   valueN)r7   r8   r9   __doc__strr;   r4   r4   r4   r5   r|      s   
 r|   c                   @   s   e Zd ZdZdejdejddfddZe	de
j
fdd	Zdee fd
dZedee defddZdee dejfddZdS )r#   z
    The :class:`RTCCertificate` interface enables the certificates used by an
    :class:`RTCDtlsTransport`.

    To generate a certificate and the corresponding private key use
    :func:`generateCertificate`.
    rT   certr/   Nc                 C   s   || _ || _d S N)_key_cert)r1   rT   r   r4   r4   r5   __init__   s   
zRTCCertificate.__init__c                 C   s   | j jS )z[
        The date and time after which the certificate will be considered invalid.
        )r   not_valid_after_utcr1   r4   r4   r5   expires   s   zRTCCertificate.expiresc                    s    fddt  D S )z
        Returns the list of certificate fingerprints, one of which is computed
        with the digest algorithm used in the certificate signature.
        c                    s    g | ]}t |t j|d qS ))rD   r}   )r|   rS   r   )rG   rD   r   r4   r5   
<listcomp>   s    
z2RTCCertificate.getFingerprints.<locals>.<listcomp>)rM   keysr   r4   r   r5   getFingerprints   s   
zRTCCertificate.getFingerprintsclsc                 C   s&   t t  t }t|}| ||dS )zw
        Create and return an X.509 certificate and corresponding private key.

        :rtype: RTCCertificate
        )rT   r   )r   generate_private_key	SECP256R1r
   rs   )r   rT   r   r4   r4   r5   generateCertificate   s   z"RTCCertificate.generateCertificatesrtp_profilesc                 C   sd   t t j}|t jt jB dd  || j || j	 |
d |ddd |D  |S )Nc                  W   s   dS )NTr4   )argsr4   r4   r5   <lambda>       z4RTCCertificate._create_ssl_context.<locals>.<lambda>si   ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA   :c                 s   s    | ]}|j V  qd S r   )r*   rF   r4   r4   r5   rK      s    z5RTCCertificate._create_ssl_context.<locals>.<genexpr>)r   ContextDTLS_METHOD
set_verifyVERIFY_PEERVERIFY_FAIL_IF_NO_PEER_CERTuse_certificater   use_privatekeyr   set_cipher_listset_tlsext_use_srtprP   )r1   r   ctxr4   r4   r5   _create_ssl_context   s   z"RTCCertificate._create_ssl_context)r7   r8   r9   r~   r   EllipticCurvePrivateKeyr	   Certificater   propertyrb   r   listr|   r   classmethodr   r"   r   r(   r   r   r   r4   r4   r4   r5   r#      s    
c                   @   s6   e Zd ZU dZeedZee ed< 	 dZ	e
ed< dS )RTCDtlsParameterszl
    The :class:`RTCDtlsParameters` dictionary includes information relating to
    DTLS configuration.
    )default_factoryfingerprintsautoroleN)r7   r8   r9   r~   r   r   r   r|   r;   r   r   r4   r4   r4   r5   r      s   
 r   c                   @   s   e Zd ZdeddfddZdS )DataReceiverdatar/   Nc                       d S r   r4   r1   r   r4   r4   r5   _handle_data       zDataReceiver._handle_data)r7   r8   r9   r<   r   r4   r4   r4   r5   r      s    r   c                   @   s>   e Zd ZdddZdeddfddZdededdfd	d
ZdS )RtpReceiverr/   Nc                 C   s   d S r   r4   r   r4   r4   r5   _handle_disconnect   r   zRtpReceiver._handle_disconnectpacketc                    r   r   r4   r1   r   r4   r4   r5   _handle_rtcp_packet   r   zRtpReceiver._handle_rtcp_packetarrival_time_msc                    r   r   r4   )r1   r   r   r4   r4   r5   _handle_rtp_packet   s   zRtpReceiver._handle_rtp_packetr/   N)	r7   r8   r9   r   r   r   r   r:   r   r4   r4   r4   r5   r      s    
r   c                   @   s(   e Zd ZU eed< deddfddZdS )	RtpSender_ssrcr   r/   Nc                    r   r   r4   r   r4   r4   r5   r      r   zRtpSender._handle_rtcp_packet)r7   r8   r9   r:   r;   r   r   r4   r4   r4   r5   r      s   
 r   c                   @   s   e Zd ZdZdddZ	ddedee dee d	ee	 ddf
d
dZ
dededdfddZdedeeeef  fddZdedee fddZdeddfddZdeddfddZdeeef deddfddZdS )	RtpRouterz
    Router to associate RTP/RTCP packets with streams.

    https://tools.ietf.org/html/draft-ietf-mmusic-sdp-bundle-negotiation-53
    r/   Nc                 C   s$   t  | _i | _i | _i | _i | _d S r   )set	receiverssenders	mid_table
ssrc_tablepayload_type_tabler   r4   r4   r5   r      s
   
zRtpRouter.__init__receiverssrcspayload_typesmidc                 C   sf   | j | |d ur|| j|< |D ]}|| j|< q|D ]}|| jvr(t | j|< | j| | qd S r   )r   addr   r   r   r   )r1   r   r   r   r   ssrcpayload_typer4   r4   r5   register_receiver  s   

zRtpRouter.register_receiversenderr   c                 C   s   || j |< d S r   )r   )r1   r   r   r4   r4   r5   register_sender  s   zRtpRouter.register_senderr   c                    s  t   dttttf  dd f fdd}t|tr#|| j|j	 nt|t
r6|jD ]
}|| j| q+t|ttfrN|jD ]}|| j|j	 q@ S t|ttfr|| j|j t|tr|jtjkrzt|jd D ]
}|| j| qrW  S  ty   Y  S w  S )N	recipientr/   c                    s   | d ur  |  d S d S r   )r   )r   
recipientsr4   r5   add_recipient  s   z+RtpRouter.route_rtcp.<locals>.add_recipientr   )r   r   r   r   r   
isinstancer   r   getr   r   sourcesr   reportsr   r   r   
media_ssrcfmtr   RTCP_PSFB_APPunpack_remb_fcifci
ValueError)r1   r   r   sourcereportr   r4   r   r5   
route_rtcp  s0   "



zRtpRouter.route_rtcpc                 C   sh   | j |j}| j|jt }|d ur||v r|S |d u r2t|dkr2t|d }|| j |j< |S d S )Nr   r   )r   r   r   r   r   r   rR   r   )r1   r   ssrc_receiverpt_receiverspt_receiverr4   r4   r5   	route_rtp4  s   zRtpRouter.route_rtpc                 C   sJ   | j | | | j| | | j| | j D ]	\}}|| qd S r   )r   discard_RtpRouter__discardr   r   r   items)r1   r   ptr   r4   r4   r5   unregister_receiverE  s   zRtpRouter.unregister_receiverc                 C   s   |  | j| d S r   )r   r   r1   r   r4   r4   r5   unregister_senderL  s   zRtpRouter.unregister_senderdr}   c                 C   s,   t | D ]\}}||kr|| qd S r   )r   r   pop)r1   r   r}   kvr4   r4   r5   	__discardO  s
   
zRtpRouter.__discardr   r   )r7   r8   r9   r~   r   r   r   r:   r   r   r   r   r   r   r   r   r   r   r   r   r   dictr%   r&   r   r4   r4   r4   r5   r      s*    

"r   c                       s  e Zd ZdZdedee ddf fddZede	fdd	Z
edefd
dZdefddZdFddZdeddfddZdFddZdeddfddZdFddZdFddZdefddZdeddfddZded eddfd!d"ZdFd#d$Zd%eddfd&d'Zd%ed(eddfd)d*Zd+e d(e!ddfd,d-Z"deddfd.d/Z#deddfd0d1Z$d2e	ddfd3d4Z%d5e&ddfd6d7Z'd%eddfd8d9Z(d%eddfd:d;Z)d+e ddfd<d=Z*dFd>d?Z+d@e	dAe,ddfdBdCZ-d@e	dAe,ddfdDdEZ.  Z/S )GRTCDtlsTransporta  
    The :class:`RTCDtlsTransport` object includes information relating to
    Datagram Transport Layer Security (DTLS) transport.

    :param transport: An :class:`RTCIceTransport`.
    :param certificates: A list of :class:`RTCCertificate` (only one is allowed
        currently).
    	transportcertificatesr/   Nc                    s   t |dksJ |d }t   d| _d | _d| _t | _t	 | _
tj| _dtt|  | _d | _|| _d| _d| _d| _d| _d | _d | _t| _d | _|| _d S )Nr   r   Fr   
transport_)rR   superr   	encrypted_data_receiver_roler   HeaderExtensionsMap_rtp_header_extensions_mapr   _rtp_routerrt   rw   _stater   id	_stats_id_task
_transport_RTCDtlsTransport__rx_bytes_RTCDtlsTransport__rx_packets_RTCDtlsTransport__tx_bytes_RTCDtlsTransport__tx_packets_rx_srtp_tx_srtprA   _srtp_profiles_ssl$_RTCDtlsTransport__local_certificate)r1   r   r   rC   	__class__r4   r5   r   _  s*   


zRTCDtlsTransport.__init__c                 C   s   t | jdd  S )z
        The current state of the DTLS transport.

        One of `'new'`, `'connecting'`, `'connected'`, `'closed'` or `'failed'`.
           N)r   r   lowerr   r4   r4   r5   state  s   zRTCDtlsTransport.statec                 C   s   | j S )zC
        The associated :class:`RTCIceTransport` instance.
        )r   r   r4   r4   r5   r     s   zRTCDtlsTransport.transportc                 C   s   t | j dS )zm
        Get the local parameters of the DTLS transport.

        :rtype: :class:`RTCDtlsParameters`
        )r   )r   r  r   r   r4   r4   r5   getLocalParameters  s   z#RTCDtlsTransport.getLocalParametersc              
      s   zO| j sNz| j  W n8 tjy$   |  I dH  |  I dH  Y n$ tjyD } z| d| | 	t
j W Y d}~W dS d}~ww d| _ | j rW dS W dS  tye   | d | 	t
j Y dS w )z9
        Attempt to complete the DTLS handshake.
        Nz"x DTLS handshake failed (error %s)Tz*x DTLS handshake failed (connection error))r   r  do_handshaker   WantReadError
_write_ssl
_recv_nextError_RTCDtlsTransport__log_debug
_set_statert   r{   ConnectionError)r1   excr4   r4   r5   _do_handshake  s*   
zRTCDtlsTransport._do_handshakeremoteParametersc                 C   s   | j jdd}d}d}|jD ]}|j }|tv r+|d7 }|j t||kr+|d7 }q|r2||kr?| 	d | 
tj dS dS )z
        Check remote fingerprints. There must be at least one fingerprint
        with a supported algorithm, and all supported fingerprints must
        match.
        T)as_cryptographyr   r   z.x DTLS handshake failed (fingerprint mismatch)N)r  get_peer_certificater   rD   r  rM   r}   rO   rS   r  r  rt   r{   )r1   r  rC   fingerprint_supportedfingerprint_validfrD   r4   r4   r5   _validate_peer_identity  s   


z(RTCDtlsTransport._validate_peer_identityc                 C   s   | j  }| jD ]}|j|kr| d|j   nq| d | tj dS | j 	dd|j
|j  }| jdkrG||d}||d}n||d}||d}t|tj|jd	}d
|_d|_t|| _t|tj|jd	}d
|_d|_t|| _dS )zO
        Extract the SRTP keying material and setup the SRTP sessions.
        zx DTLS handshake negotiated %sz4x DTLS handshake failed (no SRTP profile negotiated)Ns   EXTRACTOR-dtls_srtpr0   serverr   r   )rT   	ssrc_typerB   Ti   )r  get_selected_srtp_profiler  r*   r  ra   r  rt   r{   export_keying_materialr+   r,   r   r6   r   SSRC_ANY_INBOUNDr)   allow_repeat_txwindow_sizer   r   SSRC_ANY_OUTBOUNDr  )r1   r*   rB   viewsrtp_tx_keysrtp_rx_key	rx_policy	tx_policyr4   r4   r5   _setup_srtp  sJ   





zRTCDtlsTransport._setup_srtpc                    s
  | j tjks	J t|jsJ | jdkr&| jjdkr!| d n| d t	
| jj| jd| _| jdkr=| j  n| j  | tj |  I dH  | j tjkrWdS | | | j tjkrddS |   | j tjkrpdS | d | tj t|  | _dS )z
        Start DTLS transport negotiation with the parameters of the remote
        DTLS transport.

        :param remoteParameters: An :class:`RTCDtlsParameters`.
        r   controllingr  client)r   Nz- DTLS handshake complete)r   rt   rw   rR   r   r   r   r   	_set_roler   
Connectionr  r   r  r  set_accept_stateset_connect_stater  rx   r  r{   r  r)  r  ry   asyncioensure_future_RTCDtlsTransport__runr   )r1   r  r4   r4   r5   start  s8   





zRTCDtlsTransport.startc                    s   | j dur| j   d| _ | jrF| jtjtjfv rHz| j  W n
 tj	y+   Y nw z	| 
 I dH  W n	 ty>   Y nw | d dS dS dS )z4
        Stop and close the DTLS transport.
        Nz- DTLS shutdown complete)r   cancelr  r   rt   rx   ry   shutdownr   r  r  r  r  r   r4   r4   r5   stop$  s"   

zRTCDtlsTransport.stopc              
      s   zAz		 |   I d H  q ty   | jjD ]}|  qY n ty9 } zt|tjs3| 	t
  |d }~ww W | tj d S | tj w r   )r  r  r   r   r   	Exceptionr   r0  CancelledError_RTCDtlsTransport__log_warning	traceback
format_excr  rt   rz   )r1   r   r  r4   r4   r5   __run7  s"   
zRTCDtlsTransport.__runc                 C   s>   t  }|tt d| j| j| j| j| j	| j
j| jd	 |S )Nr   )		timestamptyper   packetsSentpacketsReceived	bytesSentbytesReceivediceRole	dtlsState)r    r   r!   r   current_datetimer   r   r   r   r   r   r   r	  )r1   r   r4   r4   r5   
_get_statsE  s   zRTCDtlsTransport._get_statsr   c              
      st   zt |}W n ty! } z| d| W Y d }~d S d }~ww |D ]}| j|D ]
}||I d H  q,q$d S )Nzx RTCP parsing failed: %s)r   parser   r  r   r   r   )r1   r   packetsr  r   r   r4   r4   r5   _handle_rtcp_dataX  s   z"RTCDtlsTransport._handle_rtcp_datar   c              
      sx   z	t || j}W n ty# } z| d| W Y d }~d S d }~ww | j|}|d ur:|j||dI d H  d S d S )Nzx RTP parsing failed: %sr   )r   rG  r   r   r  r   r   r   )r1   r   r   r   r  r   r4   r4   r5   _handle_rtp_datad  s   z!RTCDtlsTransport._handle_rtp_datac              
      s
  d }| j s| j }|d ur;ztj| j |dI d H }W n$ tjy:   | d | j	  | 
 I d H  Y d S w | j I d H }|  jt|7  _|  jd7  _|d }|dkr|dk r| j| z| jd}W n tjyy   d }Y n tjy   d}Y nw | 
 I d H  |d u r| d	 t|r| jr| j|I d H  d S d S d S |d
kr|dk r| jrt }z(t|r| j|}| |I d H  W d S | j|}| j||dI d H  W d S  tjy } z| d| W Y d }~d S d }~ww d S d S d S )N)timeoutzx DTLS handling timeoutr   r      @         z- DTLS shutdown by remote party      rJ  zx SRTP unprotect failed: %s)r   r  DTLSv1_get_timeoutr0  wait_forr   _recvTimeoutErrorr  DTLSv1_handle_timeoutr  r   rR   r   	bio_writerecvr   ZeroReturnErrorr  r  r   r   r   r   
current_msr   unprotect_rtcprI  	unprotectrK  	pylibsrtp)r1   rL  r   
first_byter   r  r4   r4   r5   r  p  s\   




zRTCDtlsTransport._recv_nextr   c                 C   s   | j d u sJ || _ d S r   r   r1   r   r4   r4   r5   _register_data_receiver  s   
z(RTCDtlsTransport._register_data_receiver
parametersc                 C   sT   t  }|jD ]}||j q| j| | jj|t|dd |j	D |j
d d S )Nc                 S   s   g | ]}|j qS r4   )payloadType)rG   codecr4   r4   r5   r     s    z;RTCDtlsTransport._register_rtp_receiver.<locals>.<listcomp>)r   r   r   )r   	encodingsr   r   r   	configurer   r   r   codecsmuxId)r1   r   rc  r   encodingr4   r4   r5   _register_rtp_receiver  s   

z'RTCDtlsTransport._register_rtp_receiverr   c                 C   s"   | j | | jj||jd d S )N)r   )r   rg  r   r   r   )r1   r   rc  r4   r4   r5   _register_rtp_sender  s   z%RTCDtlsTransport._register_rtp_senderc                    s4   | j tjkrtd| j| |  I d H  d S )Nz)Cannot send encrypted data, not connected)r   rt   ry   r  r  sendr  r   r4   r4   r5   
_send_data  s
   zRTCDtlsTransport._send_datac                    sn   | j tjkrtdt|r| j|}n| j|}| j	|I d H  |  j
t|7  _
|  jd7  _d S )Nz(Cannot send encrypted RTP, not connectedr   )r   rt   ry   r  r   r  protect_rtcpprotectr   _sendr   rR   r   r   r4   r4   r5   	_send_rtp  s   zRTCDtlsTransport._send_rtpr   c                 C   s
   || _ d S r   )r   )r1   r   r4   r4   r5   r,    s   
zRTCDtlsTransport._set_roler	  c                 C   s2   || j kr| d| j | || _ | d d S d S )Nz
- %s -> %sstatechange)r   r  emit)r1   r	  r4   r4   r5   r    s
   
zRTCDtlsTransport._set_statec                 C   s   | j |kr
d | _ d S d S r   r`  ra  r4   r4   r5   _unregister_data_receiver  s   

z*RTCDtlsTransport._unregister_data_receiverc                 C      | j | d S r   )r   r   ra  r4   r4   r5   _unregister_rtp_receiver     z)RTCDtlsTransport._unregister_rtp_receiverc                 C   rv  r   )r   r   r   r4   r4   r5   _unregister_rtp_sender  rx  z'RTCDtlsTransport._unregister_rtp_senderc                    sj   z| j d}W n tjy   d}Y nw |r3| j|I dH  |  jt|7  _|  jd7  _dS dS )zT
        Flush outgoing data which OpenSSL put in our BIO to the transport.
        rO  rP  Nr   )	r  bio_readr   r  r   rq  r   rR   r   r   r4   r4   r5   r    s   zRTCDtlsTransport._write_sslmsgr   c                 G       t jd| | jg|R   d S NzRTCDtlsTransport(%s) )loggerdebugr   r1   r{  r   r4   r4   r5   __log_debug      zRTCDtlsTransport.__log_debugc                 G   r|  r}  )r~  warningr   r  r4   r4   r5   __log_warning  r  zRTCDtlsTransport.__log_warningr   )0r7   r8   r9   r~   r   r   r#   r   r   r   r	  r   r   r
  r  r  r)  r3  r6  r2  r    rF  r<   rI  r:   rK  r  r   rb  r   r   rk  r   r   rl  rn  rr  r,  rt   r  ru  rw  ry  r  objectr  r9  __classcell__r4   r4   r  r5   r   U  sb    	 


-
4

2


r   )Zr0  r]   rb   enumloggingr_   r:  dataclassesr   r   typingr   r   r   r   r   r^  cryptographyr	   cryptography.hazmat.backendsr
   cryptography.hazmat.primitivesr   )cryptography.hazmat.primitives.asymmetricr   OpenSSLr   pyee.asyncior   r   r    r   r   rtcicetransportr   rtcrtpparametersr   r   r   r   r   r   r   r   r   r   r   statsr    r!   r"   r%   r&   	getLoggerr7   r~  rp   SHA384SHA512rM   r(   SRTP_PROFILE_AEAD_AES_256_GCMSRTP_AEAD_AES_256_GCMSRTP_PROFILE_AEAD_AES_128_GCMSRTP_AEAD_AES_128_GCMSRTP_PROFILE_AES128_CM_SHA1_80SRTP_AES128_CM_SHA1_80rA   r   r;   rB   r)   r  appendr   r   rS   r   rs   Enumrt   r|   r#   r   r   r   r   r   r   r4   r4   r4   r5   <module>   s   
 ,
=b