U
    R¹Öhí;  ã                   @  s  d dl m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	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 d d	lmZmZmZmZmZmZmZmZmZ d d
lmZ d dl m!Z! d dl"m#Z#m$Z$m%Z%m&Z&m'Z' d dl(m)Z) G dd„ dej*ƒZ+dS )é    )ÚannotationsN)ÚLiteralÚcast)Úunquote)ÚConnectionTypeÚevents)ÚConnectionState)Ú	ExtensionÚPerMessageDeflate)ÚLocalProtocolErrorÚRemoteProtocolError)	ÚASGI3ApplicationÚASGISendEventÚWebSocketAcceptEventÚWebSocketCloseEventÚWebSocketEventÚWebSocketResponseBodyEventÚWebSocketResponseStartEventÚWebSocketScopeÚWebSocketSendEvent)ÚConfig)ÚTRACE_LOG_LEVEL)ÚClientDisconnectedÚget_local_addrÚget_path_with_query_stringÚget_remote_addrÚis_ssl)ÚServerStatec                   @  s4  e Zd Zd@ddddddœdd	„Zd
ddœdd„Zdddœdd„Zddœdd„Zdddœdd„Zddœdd„Zddœdd„Z	ddœdd„Z
ddœdd „Zd!dd"œd#d$„Zd%dd&œd'd(„Zd)dd&œd*d+„Zd,dd&œd-d.„Zd/dd&œd0d1„Zd2dd&œd3d4„Zddœd5d6„Zddœd7d8„Zd9dd:œd;d<„Zd=dœd>d?„ZdS )AÚ
WSProtocolNr   r   zdict[str, typing.Any]z asyncio.AbstractEventLoop | NoneÚNone)ÚconfigÚserver_stateÚ	app_stateÚ_loopÚreturnc                 C  sÐ   |j s| ¡  || _tt|jƒ| _|p,t ¡ | _	t
 d¡| _|j| _|| _|j| _|j| _|j| _d | _d | _d | _d | _t ¡ | _d| _d| _d| _tjtjd| _d| _ t !¡ | _"| j" #¡  d| _$d| _%d S )Nzuvicorn.errorF)Zconnection_typeó    Ú )&ZloadedÚloadr    r   r   Z
loaded_appÚappÚasyncioZget_event_loopÚloopÚloggingZ	getLoggerÚloggerÚ	root_pathr"   ÚconnectionsÚtasksÚdefault_headersÚ	transportÚserverÚclientÚschemeZQueueÚqueueÚhandshake_completeÚ
close_sentÚresponse_startedÚwsprotoZWSConnectionr   ZSERVERÚconnÚread_pausedÚEventÚwritableÚsetÚbytesÚtext)Úselfr    r!   r"   r#   © rB   úO./venv/lib/python3.8/site-packages/uvicorn/protocols/websockets/wsproto_impl.pyÚ__init__'   s2    


zWSProtocol.__init__zasyncio.Transport)r1   r$   c                 C  sl   | j  | ¡ || _t|ƒ| _t|ƒ| _t|ƒr2dnd| _| j	j
tkrh| jrTd| j nd}| j	 td|¡ d S )NZwssZwsú%s:%d - r&   z%sWebSocket connection made)r.   Úaddr1   r   r2   r   r3   r   r4   r,   Úlevelr   Úlog)rA   r1   ÚprefixrB   rB   rC   Úconnection_madeW   s    

zWSProtocol.connection_madezException | None)Úexcr$   c                 C  sx   | j r
dnd}| j d|dœ¡ | j | ¡ | jjtkr\| jrHd| j nd}| j 	td|¡ d| _ |d krt| j
 ¡  d S )	Nií  éî  úwebsocket.disconnect©ÚtypeÚcoderE   r&   z%sWebSocket connection lostT)r6   r5   Ú
put_nowaitr.   Úremover,   rG   r   r3   rH   r1   Úclose)rA   rK   rP   rI   rB   rB   rC   Úconnection_lostd   s    zWSProtocol.connection_lost)r$   c                 C  s   d S ©NrB   ©rA   rB   rB   rC   Úeof_receivedq   s    zWSProtocol.eof_receivedr?   )Údatar$   c              
   C  s`   z| j  |¡ W nB tk
rR } z$| j | j  |j¡¡ | j ¡  W 5 d }~X Y n
X |  ¡  d S rU   )	r:   Zreceive_datar   r1   ÚwriteÚsendZ
event_hintrS   Úhandle_events)rA   rX   ÚerrrB   rB   rC   Údata_receivedt   s    zWSProtocol.data_receivedc                 C  sŠ   | j  ¡ D ]z}t|tjƒr&|  |¡ q
t|tjƒr>|  |¡ q
t|tjƒrV|  |¡ q
t|tj	ƒrn|  
|¡ q
t|tjƒr
|  |¡ q
d S rU   )r:   r   Ú
isinstanceZRequestÚhandle_connectZTextMessageÚhandle_textZBytesMessageÚhandle_bytesÚCloseConnectionÚhandle_closeZPingÚhandle_ping©rA   ÚeventrB   rB   rC   r[   ~   s    zWSProtocol.handle_eventsc                 C  s   | j  ¡  dS )z\
        Called by the transport when the write buffer exceeds the high water mark.
        N)r=   ÚclearrV   rB   rB   rC   Úpause_writing‹   s    zWSProtocol.pause_writingc                 C  s   | j  ¡  dS )z_
        Called by the transport when the write buffer drops below the low water mark.
        N)r=   r>   rV   rB   rB   rC   Úresume_writing‘   s    zWSProtocol.resume_writingc                 C  sR   | j r<| j dddœ¡ | j tjjdd¡}| j 	|¡ n|  
¡  | j ¡  d S )NrM   iô  rN   )rP   )r6   r5   rQ   r:   rZ   r9   r   rb   r1   rY   Úsend_500_responserS   )rA   ÚoutputrB   rB   rC   Úshutdown—   s    zWSProtocol.shutdownzasyncio.Task[None])Útaskr$   c                 C  s   | j  |¡ d S rU   )r/   Údiscard)rA   rm   rB   rB   rC   Úon_task_complete    s    zWSProtocol.on_task_completezevents.Request)rf   r$   c           
      C  sâ   d|j  ¡ fg}|dd„ |jD ƒ7 }|j d¡\}}}t|ƒ}| j| }| j d¡| d¡ }d| jjddœd	| j	| j
| j| j||| d¡||j| j ¡ d
i idœ| _| j ddi¡ | j |  ¡ ¡}	|	 | j¡ | j |	¡ d S )Ns   hostc                 S  s   g | ]\}}|  ¡ |f‘qS rB   )Úlower)Ú.0ÚkeyÚvaluerB   rB   rC   Ú
<listcomp>§   s     z-WSProtocol.handle_connect.<locals>.<listcomp>ú?ÚasciiZ	websocketz2.4)ÚversionZspec_versionz1.1zwebsocket.http.response)rO   ZasgiZhttp_versionr4   r2   r3   r-   ÚpathÚraw_pathÚquery_stringÚheadersÚsubprotocolsÚstateÚ
extensionsrO   zwebsocket.connect)ZhostÚencodeÚextra_headersÚtargetÚ	partitionr   r-   r    Zasgi_versionr4   r2   r3   r|   r"   ÚcopyÚscoper5   rQ   r*   Zcreate_taskÚrun_asgiZadd_done_callbackro   r/   rF   )
rA   rf   r{   ry   Ú_rz   rx   Ú	full_pathZfull_raw_pathrm   rB   rB   rC   r_   ¥   s2    
òzWSProtocol.handle_connectzevents.TextMessagec                 C  sJ   |  j |j7  _ |jrF| j d| j dœ¡ d| _ | jsFd| _| j ¡  d S )Núwebsocket.receive)rO   r@   r&   T)r@   rX   Úmessage_finishedr5   rQ   r;   r1   Úpause_readingre   rB   rB   rC   r`   Á   s    zWSProtocol.handle_textzevents.BytesMessagec                 C  sJ   |  j |j7  _ |jrF| j d| j dœ¡ d| _ | jsFd| _| j ¡  d S )Nrˆ   )rO   r?   r%   T)r?   rX   r‰   r5   rQ   r;   r1   rŠ   re   rB   rB   rC   ra   Ê   s    zWSProtocol.handle_byteszevents.CloseConnectionc                 C  sL   | j jtjkr&| j | j  | ¡ ¡¡ | j 	d|j
|jdœ¡ | j ¡  d S )NrM   ©rO   rP   Úreason)r:   r}   r   ZREMOTE_CLOSINGr1   rY   rZ   Úresponser5   rQ   rP   rŒ   rS   re   rB   rB   rC   rc   Ô   s    zWSProtocol.handle_closezevents.Pingc                 C  s   | j  | j | ¡ ¡¡ d S rU   )r1   rY   r:   rZ   r   re   rB   rB   rC   rd   Ú   s    zWSProtocol.handle_pingc                 C  s\   | j s| jrd S ddg}| j tjjd|dd¡}|| j tjjdd¡7 }| j 	|¡ d S )N)s   content-types   text/plain; charset=utf-8)s
   connections   closeiô  T©Ústatus_coder{   Zhas_bodys   Internal Server Error©rX   )
r8   r6   r:   rZ   r9   r   ÚRejectConnectionÚ
RejectDatar1   rY   )rA   r{   rk   rB   rB   rC   rj   Ý   s    þzWSProtocol.send_500_responsec                 Ã  s¸   z|   | j| j| j¡I d H }W nN tk
r<   | j ¡  Y nx tk
rl   | j 	d¡ |  
¡  | j ¡  Y nHX | js”| j d¡ |  
¡  | j ¡  n |d k	r´| j d|¡ | j ¡  d S )NzException in ASGI application
z4ASGI callable returned without completing handshake.z4ASGI callable should return None, but returned '%s'.)r(   r„   ÚreceiverZ   r   r1   rS   ÚBaseExceptionr,   Z	exceptionrj   r6   Úerror)rA   ÚresultrB   rB   rC   r…   è   s    zWSProtocol.run_asgir   )Úmessager$   c              
   Ã  sè  | j  ¡ I d H  |d }| jsø|dkrÂt t|¡}| 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 |¡ qä|d	kr8| j d
ddœ¡ | j d| jd t	| jƒ¡ d| _d| _tjdg d}| j |¡}| j |¡ | j ¡  n¼|dkrät t|¡}d|d   krjdk s€n d}t||d  ƒ‚| j d| jd t	| jƒ|d ¡ d| _tj|d t|d ƒdd}| j |¡}| j |¡ d| _ nd}t|| ƒ‚nì| jsB| j sBz
|dkrxt t!|¡}| 
d¡}	| 
d¡}
|	d krD|
n|	}| j tjj"|d¡}| j ¡ s| j |¡ nš|d	krt t#|¡}d| _| 
dd¡}| 
dd¡p°d}| j d
||d œ¡ | j tjj$||d!¡}| j ¡ s| j |¡ | j ¡  nd"}t|| ƒ‚W n* t%k
r> } z
t&|‚W 5 d }~X Y nX n¢| j rÔ|d#krÂt d$|¡}| 
d%d&¡ }tj'|d' |d(}| j |¡}| j |¡ |rÒ| j d
ddœ¡ d| _| j ¡  nd)}t|| ƒ‚nd*}t|| ƒ‚d S )+NrO   zwebsocket.acceptz%s - "WebSocket %s" [accepted]r3   Úsubprotocolr{   T)r˜   r~   r€   zwebsocket.closerM   rL   rN   z%s - "WebSocket %s" 403i“  )r   r{   zwebsocket.http.response.startéd   ÚstatusiX  z*Invalid HTTP status code '%d' in response.z%s - "WebSocket %s" %drŽ   zlExpected ASGI message 'websocket.accept', 'websocket.close' or 'websocket.http.response.start' but got '%s'.zwebsocket.sendr?   r@   r   rP   iè  rŒ   r&   r‹   )rP   rŒ   zJExpected ASGI message 'websocket.send' or 'websocket.close', but got '%s'.zwebsocket.http.response.bodyr   Z	more_bodyFZbody)rX   Úbody_finishedzBExpected ASGI message 'websocket.http.response.body' but got '%s'.z>Unexpected ASGI message '%s', after sending 'websocket.close'.)(r=   Úwaitr6   Útypingr   r   r,   Úinfor„   r   Úgetr0   Úlistr    Zws_per_message_deflateÚappendr
   r1   Z
is_closingr:   rZ   r9   r   ZAcceptConnectionrY   r5   rQ   r7   r‘   rS   r   ÚRuntimeErrorr8   r   ZMessager   rb   r   r   r’   )rA   r—   Zmessage_typer˜   r€   r~   rk   rf   ÚmsgÚ
bytes_dataZ	text_datarX   rP   rŒ   rK   r›   Zreject_datarB   rB   rC   rZ   ú   sÈ    ý

ýÿ
ý
ü
ýÿ




zWSProtocol.sendr   c                 Ã  s4   | j  ¡ I d H }| jr0| j  ¡ r0d| _| j ¡  |S )NF)r5   rŸ   r;   Úemptyr1   Zresume_reading)rA   r—   rB   rB   rC   r“   s  s
    
zWSProtocol.receive)N)Ú__name__Ú
__module__Ú__qualname__rD   rJ   rT   rW   r]   r[   rh   ri   rl   ro   r_   r`   ra   rc   rd   rj   r…   rZ   r“   rB   rB   rB   rC   r   &   s(    û0
		
yr   ),Z
__future__r   r)   r+   r   r   r   Zurllib.parser   r9   r   r   Zwsproto.connectionr   Zwsproto.extensionsr	   r
   Zwsproto.utilitiesr   r   Zuvicorn._typesr   r   r   r   r   r   r   r   r   Zuvicorn.configr   Zuvicorn.loggingr   Zuvicorn.protocols.utilsr   r   r   r   r   Zuvicorn.serverr   ZProtocolr   rB   rB   rB   rC   Ú<module>   s    ,