o
    i1/                     @   s~   d Z ddlZddlZddlZddlZdZdZdZdZdZ	dZ
dZd	Zd
ZdZdZdZdZdZdZdZdZdZG dd dZdS )ze
WebSocket protocol handler for ASGI.

Implements RFC 6455 WebSocket protocol for ASGI applications.
    N         	   
   i  i  i  i  i  i  i  i  i  i  i  s$   258EAFA5-E914-47DA-95CA-C5AB0DC85B11c                   @   sz   e Zd Z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dZdS )WebSocketProtocolz3WebSocket connection handler for ASGI applications.c                 C   sP   || _ || _|| _|| _|| _d| _d| _d| _d| _g | _	d| _
t | _dS )a!  Initialize WebSocket protocol handler.

        Args:
            transport: asyncio transport for writing
            reader: asyncio StreamReader for reading
            scope: ASGI WebSocket scope dict
            app: ASGI application callable
            log: Logger instance
        FN )	transportreaderscopeapplogacceptedclosed
close_codeclose_reason
_fragments_fragment_opcodeasyncioQueue_receive_queue)selfr	   r
   r   r   r    r   K/home/ubuntu/.local/lib/python3.10/site-packages/gunicorn/asgi/websocket.py__init__-   s   
zWebSocketProtocol.__init__c                    s  | j ddiI dH  t|  }zKz| | j| j| jI dH  W n t	y2   | j
d Y nw W |  z|I dH  W n
 tjyI   Y nw | js[| jr]| tdI dH  dS dS dS |  z|I dH  W n
 tjyt   Y nw | js| jr| tdI dH  w w w )z#Run the WebSocket ASGI application.typezwebsocket.connectNz#Error in WebSocket ASGI applicationzApplication error)r   putr   create_task_read_framesr   r   _receive_send	Exceptionr   	exceptioncancelCancelledErrorr   r   _send_closeCLOSE_INTERNAL_ERROR)r   	read_taskr   r   r   runI   s6   zWebSocketProtocol.runc                    s   | j  I dH S )zASGI receive callable.N)r   get)r   r   r   r   r   `   s   zWebSocketProtocol._receivec                    s   |d }|dkr| j rtd| |I dH  d| _ dS |dkrV| j s(td| jr/tdd	|v rC| t|d	 d
I dH  dS d|v rT| t|d I dH  dS dS |dkrt|dt	}|dd}| 
||I dH  d| _dS dS )zASGI send callable.r   zwebsocket.acceptzWebSocket already acceptedNTzwebsocket.sendzWebSocket not acceptedzWebSocket closedtextutf-8byteszwebsocket.closecodereasonr   )r   RuntimeError_send_acceptr   _send_frameOPCODE_TEXTencodeOPCODE_BINARYr)   CLOSE_NORMALr%   )r   messagemsg_typer-   r.   r   r   r   r    d   s.   
 
zWebSocketProtocol._sendc           	         s  d}| j d D ]\}}|dkr|} nq|stdtt|t  d}dddd	| d
g}|	d}|rD|
d| d
 |	dg }|D ]#\}}t|trZ|d}t|trd|d}|
| d| d
 qL|
d
 | jd|d dS )z)Send WebSocket handshake accept response.Nheaderss   sec-websocket-keyz Missing Sec-WebSocket-Key headerasciiz"HTTP/1.1 101 Switching Protocols
zUpgrade: websocket
zConnection: Upgrade
zSec-WebSocket-Accept: z
subprotocolzSec-WebSocket-Protocol: zlatin-1z: r   )r   r/   base64	b64encodehashlibsha1WS_GUIDdigestdecoder)   append
isinstancer,   r	   writejoinr3   )	r   r6   ws_keynamevalue
accept_keyr8   r:   extra_headersr   r   r   r0      s>   






zWebSocketProtocol._send_acceptc                    s|  zzi| j sj|  I dH }|du rnX|\}}|tkr#| |I dH  nG|tkr1| t|I dH  n6|tkr6n1|tkrJ| j	d|
ddI dH  n|tkr[| j	d|dI dH  n|tkrg| |I dH  | j rW n! tjyt     ty } z| jd| W Y d}~nd}~ww W | j sd| _ | j	d| jptd	I dH  dS dS | j sd| _ | j	d| jptd	I dH  w w )
z+Read and process incoming WebSocket frames.Nzwebsocket.receiver+   )r   r*   )r   r,   zWebSocket read error: %sTzwebsocket.disconnect)r   r-   )r   _read_frameOPCODE_CLOSE_handle_closeOPCODE_PINGr1   OPCODE_PONGr2   r   r   rA   r4   OPCODE_CONTINUATION_handle_continuationr   r$   r!   r   debugr   CLOSE_ABNORMAL)r   frameopcodepayloader   r   r   r      s`   
zWebSocketProtocol._read_framesc                    s  |  dI dH }|sdS |d |d }}|d? d@ }|d? d@ }|d? d@ }|d? d@ }|d	@ }|s8|s8|rC| td
I dH  dS |d? d@ }	|d@ }
|	sZ| tdI dH  dS |
dkrs|  dI dH }|sjdS td|d }
n|
dkr|  dI dH }|sdS td|d }
|  dI dH }|sdS |  |
I dH }|du rdS | ||}|tkr| jdu r| tdI dH  dS | j	| |rd
| j}| j}g | _d| _||fS tdfS |ttfv r|s|| _|g| _tdfS ||fS ||fS )z{Read a single WebSocket frame.

        Returns:
            tuple: (opcode, payload) or None if connection closed
        r   Nr   r                  zRSV bits set   zFrame not masked~   !Hr   !QzUnexpected continuation    )_read_exactr%   CLOSE_PROTOCOL_ERRORstructunpack_unmaskrP   r   r   rB   rE   r2   r4   )r   header
first_bytesecond_bytefinrsv1rsv2rsv3rU   maskedpayload_lenext_lenmasking_keyrV   full_payloadfinal_opcoder   r   r   rK      sl   
zWebSocketProtocol._read_framec                    sD   z| j |I dH }|W S  tjy   Y dS  ty!   Y dS w )z%Read exactly n bytes from the reader.N)r
   readexactlyr   IncompleteReadErrorr!   )r   ndatar   r   r   rb   )  s   zWebSocketProtocol._read_exactc                    s"   |s|S t  fddt|D S )zUnmask WebSocket payload data.c                 3   s$    | ]\}}| |d   A V  qdS )r[   Nr   ).0ibrq   r   r   	<genexpr>8  s   " z,WebSocketProtocol._unmask.<locals>.<genexpr>)r,   	enumerate)r   rV   rq   r   r{   r   rf   3  s   zWebSocketProtocol._unmaskc                    st   t |dkr!td|dd d | _|dd jddd| _nt| _d| _| js5| | j| jI dH  d	| _dS )
zHandle incoming close frame.r   r_   Nr   r+   replace)errorsr   T)	lenrd   re   r   rA   r   CLOSE_NO_STATUSr   r%   r   rV   r   r   r   rM   :  s   
zWebSocketProtocol._handle_closec                    s   dS )z=Handle continuation frame (already processed in _read_frame).Nr   r   r   r   r   rQ   I  s    z&WebSocketProtocol._handle_continuationc                    s   t |tr|d}t|}t }|d|B  |dk r#|| n!|dk r6|d |td| n|d |td| || | j	
t| dS )	zRSend a WebSocket frame.

        Server frames are not masked (RFC 6455).
        r+      r^   i   r_   r]   r`   N)rC   strr3   r   	bytearrayrB   extendrd   packr	   rD   r,   )r   rU   rV   lengthrT   r   r   r   r1   M  s   




zWebSocketProtocol._send_framer   c                    sD   t d|}|r||ddd 7 }| t|I dH  d| _dS )zSend a close frame.r_   r+   N{   T)rd   r   r3   r1   rL   r   )r   r-   r.   rV   r   r   r   r%   j  s   
zWebSocketProtocol._send_closeN)r   )__name__
__module____qualname____doc__r   r(   r   r    r0   r   rK   rb   rf   rM   rQ   r1   r%   r   r   r   r   r   *   s    *.R
r   )r   r   r;   r=   rd   rP   r2   r4   rL   rN   rO   r5   CLOSE_GOING_AWAYrc   CLOSE_UNSUPPORTEDr   rS   CLOSE_INVALID_DATACLOSE_POLICY_VIOLATIONCLOSE_MESSAGE_TOO_BIGCLOSE_MANDATORY_EXTr&   r?   r   r   r   r   r   <module>   s0   