o
    mj                      @  sl   d Z ddlm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	 e
eZdZdZdZG dd dZdS )	u:   Sesión RTP UDP (PCMU) hacia/desde Asterisk externalMedia.    )annotationsN)Callable      c                   @  s   e Zd Zd7d8ddZed9d	d
Zed9ddZed:ddZd;ddZd<d=ddZ	d>dd Z
d?d"d#Zd@dAd(d)ZedBd+d,ZedCd.d/ZedDdEd3d4ZdFd5d6ZdS )G
RtpSessionNon_ulaw_frameCallable[[bytes], None] | NonereturnNonec                 C  sZ   || _ d | _d | _tdd| _tdd| _tdd| _d| _t	j
dd| _d| _d S )Nr         F@   )maxsize)_on_ulaw_frame
_transport_remoterandomrandint_seq
_timestamp_ssrc_closedasyncioQueue_recv_queue_warned_no_remote)selfr    r   ;/var/www/html/bot-asterisk-ari/backend/media/rtp_session.py__init__   s   
zRtpSession.__init__boolc                 C  s   | j S N)r   r   r   r   r   	is_closed   s   zRtpSession.is_closedc                 C  s
   | j d uS r!   )r   r"   r   r   r   
has_remote#   s   
zRtpSession.has_remote
int | Nonec                 C  s&   | j sd S | j d}|r|d S d S )Nsockname   )r   get_extra_info)r   r&   r   r   r   
local_port'   s   zRtpSession.local_porthoststrportintc                 C  s0   |r|dv rd}|t |f| _td|| dS )z<Fija el destino RTP (p. ej. UNICASTRTP_LOCAL_* de Asterisk).)0.0.0.0z::z[::]z	127.0.0.1zRTP remoto configurado: %s:%sN)r-   r   loggerinfo)r   r*   r,   r   r   r   
set_remote.   s   zRtpSession.set_remoter.   r   	bind_hostc                   sl   t  }G dd dt j |j fdd||fdI d H \_}j}|d u r-tdtd|| |S )Nc                   @  s    e Zd ZdddZdddZdS )z#RtpSession.start.<locals>._Protocolsessionr   r	   r
   c                 S  s
   || _ d S r!   )r3   )r   r3   r   r   r   r   9   s   
z,RtpSession.start.<locals>._Protocol.__init__databytesaddrtuple[str, int]c                 S  s   | j || d S r!   )r3   _handle_datagram)r   r4   r6   r   r   r   datagram_received<   s   z5RtpSession.start.<locals>._Protocol.datagram_receivedN)r3   r   r	   r
   r4   r5   r6   r7   r	   r
   )__name__
__module____qualname__r   r9   r   r   r   r   	_Protocol8   s    
r>   c                     s    S r!   r   r   r>   r   r   r   <lambda>@   s    z"RtpSession.start.<locals>.<lambda>)
local_addrzNo se pudo abrir socket RTPzRTP escuchando en %s:%s)	r   get_running_loopDatagramProtocolcreate_datagram_endpointr   r)   RuntimeErrorr/   r0   )r   r2   r,   loop_
bound_portr   r?   r   start5   s   zRtpSession.startr4   r5   r6   r7   c                 C  s   | j s	t|tk rd S | j|kr7| j}|| _|d u r&td|d |d  ntd|d |d |d |d  |d d@ }|tkrCd S |td  }|sMd S | jrU| | z	| j	| W d S  t
jyi   Y d S w )NzRTP remoto aprendido: %s:%sr   r'   u&   RTP remoto actualizado %s:%s → %s:%s   )r   lenRTP_HEADER_SIZEr   r/   r0   PT_PCMUr   r   
put_nowaitr   	QueueFull)r   r4   r6   prevpayload_typepayloadr   r   r   r8   I   s6   

zRtpSession._handle_datagramrR   c                 C  s   | j s| jsd S | js| jsd| _td d S t|tkr%|d t }nt|tk r5|dtt|   }t	ddt
| jd@ | jd@ | j}| jd d@ | _| jt d@ | _| j|| | j d S )	NTu   RTP: sin paquetes de Asterisk aún — no se envía audio al puente. Verificá EXTERNAL_MEDIA_ADVERTISE_HOST y firewall UDP hacia este servidor.   z!BBHII   r   r   r'   )r   r   r   r   r/   warningrK   SAMPLES_PER_PACKETstructpackrM   r   r   r   sendto)r   rR   headerr   r   r   	send_ulawk   s0   zRtpSession.send_ulaw      ?timeoutfloatbytes | Nonec                   s6   zt j| j |dI d H W S  t jy   Y d S w )N)r]   )r   wait_forr   getTimeoutError)r   r]   r   r   r   recv_ulaw_frame   s   zRtpSession.recv_ulaw_frameulawc                 C     t | dS N   )audioopulaw2lin)rd   r   r   r   ulaw_to_pcm      zRtpSession.ulaw_to_pcmpcmc                 C  re   rf   )rh   lin2ulaw)rl   r   r   r   pcm_to_ulaw   rk   zRtpSession.pcm_to_ulaw@  	from_rateto_ratec                 C  s(   ||kr| S t | dd||d \}}|S )Nrg   r'   )rh   ratecv)rl   rp   rq   	convertedrG   r   r   r   resample_pcm   s   zRtpSession.resample_pcmc                 C  s$   d| _ | jr| j  d | _d S d S )NT)r   r   closer"   r   r   r   ru      s
   

zRtpSession.closer!   )r   r   r	   r
   )r	   r    )r	   r%   )r*   r+   r,   r-   r	   r
   )r.   r   )r2   r+   r,   r-   r	   r-   r:   )rR   r5   r	   r
   )r\   )r]   r^   r	   r_   )rd   r5   r	   r5   )rl   r5   r	   r5   )ro   )rl   r5   rp   r-   rq   r-   r	   r5   )r	   r
   )r;   r<   r=   r   propertyr#   r$   r)   r1   rI   r8   r[   rc   staticmethodrj   rn   rt   ru   r   r   r   r   r      s(    


"r   )__doc__
__future__r   r   rh   loggingr   rW   typingr   	getLoggerr;   r/   rL   rV   rM   r   r   r   r   r   <module>   s    
