o
    êi)                     @   s(  d dl Z d dlZd dlZd dlmZ d dlZd dl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 eeejf Zeeejf Zejg eje f Zejegejd f Zejeeegejd f ZG d	d
 d
eZG dd deZ G dd deZ!G dd deZ"G dd de
Z#dS )    N)TracebackType)AsyncNetworkStream)ASGITransportAsyncByteStreamRequestResponse)CloseReason   )WebSocketDisconnectWebSocketUpgradeErrorNNNc                   @   s   e Zd ZdS )ASGIWebSocketTransportErrorN)__name__
__module____qualname__ r   r   F/home/ubuntu/.local/lib/python3.10/site-packages/httpx_ws/transport.pyr      s    r   c                   @   s   e Zd ZdeddfddZdS )UnhandledASGIMessageTypemessagereturnNc                 C   
   || _ d S N)r   selfr   r   r   r   __init__      
z!UnhandledASGIMessageType.__init__)r   r   r   Messager   r   r   r   r   r      s    r   c                   @   s"   e Zd ZdejjddfddZdS )UnhandledWebSocketEventeventr   Nc                 C   r   r   )r   )r   r   r   r   r   r      r   z UnhandledWebSocketEvent.__init__)r   r   r   wsprotoeventsEventr   r   r   r   r   r      s    r   c                   @   s  e Zd Z	d$dededejjdeddf
dd	Z	de
d ef fd
dZdedB fddZd%dededB defddZd%dededB ddfddZd&ddZdeddfddZd%dedB defddZd&ddZdefddZdeddfd d!Zdedefd"d#ZdS )'ASGIWebSocketAsyncNetworkStream      ?appscope
task_groupinitial_receive_timeoutr   Nc                 C   s   || _ || _tjjjtjt tj	d | _
tjjjtjt tj	d | _|| _|| _ttjj| _| j|d |d  d| _d S )N)max_buffer_sizeheaderspathF)r$   r%   anyiostreamsstapledStapledObjectStreamcreate_memory_object_streamr   mathinf_receive_queue_send_queue_task_group_initial_receive_timeoutr   WSConnectionConnectionTypeSERVER
connectioninitiate_upgrade_connection	_aentered)r   r$   r%   r&   r'   r   r   r   r   $   s   
z(ASGIWebSocketAsyncNetworkStream.__init__c                    s  | j rtdd| _ | j| j t 4 I d H }| ddiI d H  z| | j	I d H }W n t
yA } ztd|d }~ww || j |d dkr_| I d H  t|d |d|d d	kr|d
 }|d }g }	 |  I d H }|d dksJ ||d  |ddsnqp| I d H  tt||d|d|d dksJ | | |f}| | _W d   I d H  |S 1 I d H sw   Y  |S )NzECannot use ASGIWebSocketAsyncNetworkStream in a context manager twiceTtypezwebsocket.connectzPWebSocket didn't accept the connection in time. Did you forget to call accept()?websocket.closecodereasonzwebsocket.http.response.startstatusr)   zwebsocket.http.response.bodybody	more_bodyF    )r)   contentzwebsocket.accept)r;   RuntimeErrorr4   
start_soon_run
contextlibAsyncExitStacksendreceiver5   TimeoutErrorpush_async_callbackacloser
   getappendr   r   join_build_accept_responsepop_all_exit_stack)r   stackr   estatus_coder)   rA   retvalr   r   r   
__aenter__9   sZ   &&z*ASGIWebSocketAsyncNetworkStream.__aenter__c                    s   | j |||I d H S r   )rT   	__aexit__r   exc_typeexc_valexc_tbr   r   r   rZ   j      z)ASGIWebSocketAsyncNetworkStream.__aexit__	max_bytestimeoutc                    s   | j |dI d H }|d }|dvrt||dkr9|d}|d ur)tj|}|d}|d ur8tj|}n|dkrHtj|d |d	 }| j	|S )
N)ra   r<   >   websocket.sendr=   rb   textbytesr=   r>   r?   )
rK   r   rO   r   r    TextMessageBytesMessageCloseConnectionr9   rJ   )r   r`   ra   r   r<   data_strr   
data_bytesr   r   r   readm   s    

z$ASGIWebSocketAsyncNetworkStream.readbufferc                    s   | j | | j  D ]K}t|tjjrqt|tjjr,| d|j|j	dI d H  qt|tjj
r@| d|jdI d H  qt|tjjrT| d|jdI d H  qt|d S )Nwebsocket.disconnectr<   r>   r?   zwebsocket.receive)r<   rc   )r<   rd   )r9   receive_datar    
isinstancer   r   rg   rJ   r>   r?   re   datarf   r   )r   rk   ra   r   r   r   r   write   s$   z%ASGIWebSocketAsyncNetworkStream.writec                    s   |  ddiI d H  d S )Nr<   rl   )rJ   r   r   r   r   rN      s   z&ASGIWebSocketAsyncNetworkStream.acloser   c                       | j |I d H  d S r   )r2   rJ   r   r   r   r   rJ      r_   z$ASGIWebSocketAsyncNetworkStream.sendc                    sN   |d u rt j}t| | j I d H W  d    S 1 s w   Y  d S r   )r0   r1   r+   
fail_afterr3   rK   )r   ra   r   r   r   rK      s   $z'ASGIWebSocketAsyncNetworkStream.receivec              
      sx   | j }| j}| j}z| |||I dH  W dS  ty; } zdtjt|d}| |I dH  W Y d}~dS d}~ww )zE
        The sub-thread in which the websocket session runs.
        Nr=   rm   )r%   _asgi_receive
_asgi_sendr$   	Exceptionr   INTERNAL_ERRORstr)r   r%   rK   rJ   rV   r   r   r   r   rG      s   z$ASGIWebSocketAsyncNetworkStream._runc                    s   | j  I d H S r   )r2   rK   rr   r   r   r   ru      s   z-ASGIWebSocketAsyncNetworkStream._asgi_receivec                    rs   r   )r3   rJ   r   r   r   r   rv      r_   z*ASGIWebSocketAsyncNetworkStream._asgi_sendc                 C   s0   | dd }| dg }| jtjj||dS )Nsubprotocolr)   )rz   extra_headers)rO   r9   rJ   r   r    AcceptConnection)r   r   rz   r)   r   r   r   rR      s   z6ASGIWebSocketAsyncNetworkStream._build_accept_response)r#   r   )r   N)r   r   r   ASGIAppScoper+   abc	TaskGroupfloatr   tuplerd   rY   boolrZ   intrj   rq   rN   r   rJ   rK   rG   ru   rv   rR   r   r   r   r   r"   #   s4    


1

r"   c                	       s   e Zd Zdddeddf fddZddd	Z			dd
ee dB dedB dedB ddf fddZ	de
def fddZdejjedef  ddfddZde
dedefddZ  ZS )ASGIWebSocketTransportr#   )r'   r'   r   Nc                   s"   t  j|i | d | _|| _d S r   )superr   rT   r5   )r   r'   argskwargs	__class__r   r   r      s   
zASGIWebSocketTransport.__init__c              	      sd   t  4 I d H }|t I d H | _| | _W d   I d H  | S 1 I d H s+w   Y  | S r   )rH   rI   enter_async_contextr+   create_task_groupr4   rS   rT   )r   rU   r   r   r   rY      s   z!ASGIWebSocketTransport.__aenter__r\   r]   r^   c                    s@   t  |||I d H  | jd usJ | j|||I d H  d S r   )r   rZ   rT   r[   r   r   r   rZ      s   z ASGIWebSocketTransport.__aexit__requestc                    s   |j j}|j}|dv s|ddkrNg }|d }d ur#|d}d|j j|j j| j||j jdd |jj	D | j
|j j|j jf|d
}| ||I d H S t |I d H S )	N>   wswssupgrade	websocketzsec-websocket-protocol,c                 S   s   g | ]
\}}|  |fqS r   )lower).0kvr   r   r   
<listcomp>   s    z?ASGIWebSocketTransport.handle_async_request.<locals>.<listcomp>)
r<   r*   raw_path	root_pathschemequery_stringr)   clientserversubprotocols)urlr   r)   rO   splitr*   r   r   queryrawr   hostport_handle_ws_requestr   handle_async_request)r   r   r   r)   r   subprotocols_headerr%   r   r   r   r      s,   
z+ASGIWebSocketTransport.handle_async_requesttask_statusr"   c                   sF   t | j| j| j| j}| jd usJ | j|I d H }|| d S r   )r"   r$   r%   r4   r5   rT   r   started)r   r   streamresultr   r   r   +_create_asgi_websocket_async_network_stream   s   zBASGIWebSocketTransport._create_asgi_websocket_async_network_streamr%   c                    sf   t |jts	J || _| j| jI d H \}}|d }dd |dd  D }t	d|d|idS )Nzutf-8c              	   S   s4   g | ]}|  d krttttf |ddqS ) z: r	   )striptypingcastr   ry   r   )r   liner   r   r   r     s
    z=ASGIWebSocketTransport._handle_ws_request.<locals>.<listcomp>r	   e   network_stream)rW   r)   
extensions)
ro   r   r   r%   r4   startr   decode
splitlinesr   )r   r   r%   r   accept_responseaccept_response_linesr)   r   r   r   r     s   
z)ASGIWebSocketTransport._handle_ws_request)r   r   r   )r   r   r   r   r   rY   r<   BaseExceptionr   rZ   r   r   r   r+   r   
TaskStatusr   rd   r   r~   r   __classcell__r   r   r   r   r      s<    




r   )$rH   r0   r   typesr   r+   r   httpcorer   httpxr   r   r   r   wsproto.frame_protocolr   _exceptionsr
   r   dictry   Anyr~   r   Callable	AwaitableReceive	CoroutineSendr}   rw   r   r   r   r"   r   r   r   r   r   <module>   s*     !