o
    4ήc,                     @   s   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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mZmZ G d	d
 d
e jZdS )    N)unquote)ConnectionTypeevents)ConnectionState)PerMessageDeflate)RemoteProtocolError)TRACE_LOG_LEVEL)get_local_addrget_path_with_query_stringget_remote_addris_sslc                   @   s   e Zd Zd(ddZdd Zdd Zdd	 Zd
d Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' ZdS ))
WSProtocolNc                 C   s   |j s|  || _|j| _|pt | _t	d| _
|j| _|j| _|j| _|j| _d | _d | _d | _d | _d | _t | _d| _d| _tjtjd| _d| _t | _| j   d| _!d| _"d S )Nzuvicorn.errorF)connection_type     )#loadedloadconfig
loaded_appappasyncioget_event_looplooplogging	getLoggerlogger	root_pathconnectionstasksdefault_headers	transportserverclientschemeconnect_eventQueuequeuehandshake_complete
close_sentwsprotoWSConnectionr   SERVERconnread_pausedEventwritablesetbytestext)selfr   server_state_loop r6   P/tmp/pip-target-vg8gfxp4/lib/python/uvicorn/protocols/websockets/wsproto_impl.py__init__   s0   



zWSProtocol.__init__c                 C   st   | j |  || _t|| _t|| _t|rdnd| _| j	j
tkr8| jr,dt| j nd}| j	td| d S d S )Nwssws%s:%d - r   z%sWebSocket connection made)r   addr    r	   r!   r   r"   r   r#   r   levelr   tuplelog)r3   r    prefixr6   r6   r7   connection_made=   s   

zWSProtocol.connection_madec                 C   s   | j rdnd}| jd|d | j|  | jjtkr0| jr&dt	| j nd}| j
td| d| _ |d u r>| j  d S d S )	Ni    websocket.disconnecttypecoder;   r   z%sWebSocket connection lostT)r'   r&   
put_nowaitr   remover   r=   r   r"   r>   r?   r    close)r3   excrF   r@   r6   r6   r7   connection_lostH   s   zWSProtocol.connection_lostc                 C   s   d S Nr6   r3   r6   r6   r7   eof_receivedU   s   zWSProtocol.eof_receivedc              
   C   sd   z| j | W n# ty+ } z| j| j |j | j  W Y d }~d S d }~ww |   d S rL   )	r,   receive_datar   r    writesend
event_hintrI   handle_events)r3   dataerrr6   r6   r7   data_receivedX   s   zWSProtocol.data_receivedc                 C   s   | j  D ]=}t|tjr| | qt|tjr| | qt|tjr+| | qt|tj	r7| 
| qt|tjrB| | qd S rL   )r,   r   
isinstanceRequesthandle_connectTextMessagehandle_textBytesMessagehandle_bytesCloseConnectionhandle_closePinghandle_pingr3   eventr6   r6   r7   rS   a   s   
zWSProtocol.handle_eventsc                 C      | j   dS )z\
        Called by the transport when the write buffer exceeds the high water mark.
        N)r/   clearrM   r6   r6   r7   pause_writingn      zWSProtocol.pause_writingc                 C   rd   )z_
        Called by the transport when the write buffer drops below the low water mark.
        N)r/   r0   rM   r6   r6   r7   resume_writingt   rg   zWSProtocol.resume_writingc                 C   sR   | j r| jddd | jtjjdd}| j	| n| 
  | j  d S )NrC   i  rD   )rF   )r'   r&   rG   r,   rQ   r)   r   r^   r    rP   send_500_responserI   )r3   outputr6   r6   r7   shutdownz   s   zWSProtocol.shutdownc                 C   s   | j | d S rL   )r   discard)r3   taskr6   r6   r7   on_task_complete   s   zWSProtocol.on_task_completec                 C   s   || _ d|j fg}|dd |jD 7 }|jd\}}}d| jjddd| j| j	| j
| jt||d	|d	||jd
| _| jddi | j|  }|| j | j| d S )Ns   hostc                 S   s   g | ]
\}}|  |fqS r6   )lower).0keyvaluer6   r6   r7   
<listcomp>   s    z-WSProtocol.handle_connect.<locals>.<listcomp>?	websocketz2.3)versionspec_versionz1.1ascii)rE   asgihttp_versionr#   r!   r"   r   pathraw_pathquery_stringheaderssubprotocolsrE   zwebsocket.connect)r$   hostencodeextra_headerstarget	partitionr   asgi_versionr#   r!   r"   r   r   r   scoper&   rG   r   create_taskrun_asgiadd_done_callbackrn   r   r<   )r3   rc   r~   r|   _r}   rm   r6   r6   r7   rY      s*   zWSProtocol.handle_connectc                 C   R   |  j |j7  _ |jr%| jd| j d d| _ | js'd| _| j  d S d S d S )Nwebsocket.receive)rE   r2   r   T)r2   rT   message_finishedr&   rG   r-   r    pause_readingrb   r6   r6   r7   r[      s   zWSProtocol.handle_textc                 C   r   )Nr   )rE   r1   r   T)r1   rT   r   r&   rG   r-   r    r   rb   r6   r6   r7   r]      s   zWSProtocol.handle_bytesc                 C   sH   | j jtjkr| j| j |  | j	d|j
d | j  d S )NrC   rD   )r,   stater   REMOTE_CLOSINGr    rP   rQ   responser&   rG   rF   rI   rb   r6   r6   r7   r_      s   zWSProtocol.handle_closec                 C   s   | j | j|  d S rL   )r    rP   r,   rQ   r   rb   r6   r6   r7   ra      s   zWSProtocol.handle_pingc                 C   s   ddg}| j jd u r| j tjjdd}n(tjd|dd}| j |}tjdd}|| j |7 }t	 }|| j |7 }| j
| d S )	N)s   content-types   text/plain; charset=utf-8)s
   connections   closei  )status_codezInternal Server Error)r   r~   reasons   Internal Server ErrorrT   )r,   
connectionrQ   r)   r   RejectConnectionh11ResponseDataEndOfMessager    rP   )r3   r~   rj   msgr6   r6   r7   ri      s   zWSProtocol.send_500_responsec                    s   z|  | j| j| jI d H }W n ty,   | jd | js$|   | j	
  Y d S w | jsCd}| j| |   | j	
  d S |d urWd}| j|| | j	
  d S d S )NzException in ASGI application
z4ASGI callable returned without completing handshake.z4ASGI callable should return None, but returned '%s'.)r   r   receiverQ   BaseExceptionr   	exceptionr'   ri   r    rI   error)r3   resultr   r6   r6   r7   r      s&   zWSProtocol.run_asgic                    sH  | j  I d H  |d }| js|dkr]| jd| jd t| j |d}| jt	|dg  }g }| j
jr>|t  | j s[d| _| jtjj|||d}| j| d S d S |d	kr| jd
dd | jd| jd t| j d| _d| _tjdg d}| j|}| j| | j  d S d}t|| | js|dkr|d}|d}	|d u r|	n|}
| jtjj|
d}| j s| j| d S d S |d	krd| _|dd}|ddpd}| jd
|d | jtjj||d}| j s| j| | j  d S d S d}t|| d}t|| )NrE   zwebsocket.acceptz%s - "WebSocket %s" [accepted]r"   subprotocolr~   T)r   
extensionsr   zwebsocket.closerC   rB   rD   z%s - "WebSocket %s" 403i  )r   r~   zLExpected ASGI message 'websocket.accept' or 'websocket.close', but got '%s'.zwebsocket.sendr1   r2   r   rF   i  r   r   )rF   r   zJExpected ASGI message 'websocket.send' or 'websocket.close', but got '%s'.z>Unexpected ASGI message '%s', after sending 'websocket.close'.)r/   waitr'   r   infor   r
   getr   listr   ws_per_message_deflateappendr   r    
is_closingr,   rQ   r)   r   AcceptConnectionrP   r&   rG   r(   r   rI   RuntimeErrorMessager^   )r3   messagemessage_typer   r   r   rj   r   
bytes_data	text_datarT   rF   r   r6   r6   r7   rQ      s   





zWSProtocol.sendc                    s6   | j  I d H }| jr| j  rd| _| j  |S )NF)r&   r   r-   emptyr    resume_reading)r3   r   r6   r6   r7   r   2  s   
zWSProtocol.receiverL   )__name__
__module____qualname__r8   rA   rK   rN   rV   rS   rf   rh   rk   rn   rY   r[   r]   r_   ra   ri   r   rQ   r   r6   r6   r6   r7   r      s(    
'			
Qr   )r   r   urllib.parser   r   r)   r   r   wsproto.connectionr   wsproto.extensionsr   wsproto.utilitiesr   uvicorn.loggingr   uvicorn.protocols.utilsr	   r
   r   r   Protocolr   r6   r6   r6   r7   <module>   s    