o
    KK&hg                     @  s@  d dl mZ d dlZd dlZd dlZd dlmZ d dlmZ ddl	m
Z
mZmZmZmZmZ ddlmZ ddlmZmZmZmZmZmZmZmZmZmZ dd	lmZmZ dd
l m!Z! ddlm"Z"m#Z#m$Z$ g dZ%eeeef Z&	 G dd dej'Z(e(j)Z)e(j*Z*G dd dej'Z+e+j,Z,e+j-Z-e+j.Z.e+j/Z/dZ0	 G dd dZ1dS )    )annotationsN)	Generator)Union   )ConnectionClosedConnectionClosedErrorConnectionClosedOKInvalidStatePayloadTooBigProtocolError)	Extension)
OK_CLOSE_CODES	OP_BINARYOP_CLOSEOP_CONTOP_PINGOP_PONGOP_TEXTClose	CloseCodeFrame)RequestResponse)StreamReader)
LoggerLikeOriginSubprotocol)ProtocolSideStateSEND_EOFc                   @  s   e Zd ZdZed\ZZdS )r   z6A WebSocket connection is either a server or a client.   N)__name__
__module____qualname____doc__rangeSERVERCLIENT r)   r)   F/var/www/html/venv/lib/python3.10/site-packages/websockets/protocol.pyr   /   s    r   c                   @  s    e Zd ZdZed\ZZZZdS )r   z6A WebSocket connection is in one of these four states.   N)	r"   r#   r$   r%   r&   
CONNECTINGOPENCLOSINGCLOSEDr)   r)   r)   r*   r   9   s    r       c                   @  s  e Zd ZdZeddddMddZedNddZejdOddZedPddZ	edQddZ
edRddZdSddZdTd d!ZdUd$d%ZdVdUd'd(ZdVdUd)d*ZdWdXd/d0ZdSd1d2ZdSd3d4ZdYdZd6d7Zd[d9d:Zd\d<d=Zd]d>d?Zd^dAdBZd^dCdDZd_dGdHZd_dIdJZdTdKdLZdS )`r   a6  
    Sans-I/O implementation of a WebSocket connection.

    Args:
        side: :attr:`~Side.CLIENT` or :attr:`~Side.SERVER`.
        state: Initial state of the WebSocket connection.
        max_size: Maximum size of incoming messages in bytes;
            :obj:`None` disables the limit.
        logger: Logger for this connection; depending on ``side``,
            defaults to ``logging.getLogger("websockets.client")``
            or ``logging.getLogger("websockets.server")``;
            see the :doc:`logging guide <../../topics/logging>` for details.

    i   N)statemax_sizeloggersider   r1   r   r2   
int | Noner3   LoggerLike | NonereturnNonec                C  s   t  | _	 |d u rtd|j  }|| _	 |tj	| _
|| _|| _|| _d | _d| _d | _g | _d | _d | _d | _d | _d | _	 d| _t | _g | _g | _|  | _t| j d | _d S )Nzwebsockets.F) uuiduuid4idlogging	getLoggernamelowerr3   isEnabledForDEBUGdebugr4   r1   r2   cur_sizeexpect_continuation_frameorigin
extensionssubprotocol
close_rcvd
close_sentclose_rcvd_then_senthandshake_exceof_sentr   readereventswritesparseparsernext
parser_exc)selfr4   r1   r2   r3   r)   r)   r*   __init__Y   s6   
	


zProtocol.__init__c                 C  s   | j S )a  
        State of the WebSocket connection.

        Defined in 4.1_, 4.2_, 7.1.3_, and 7.1.4_ of :rfc:`6455`.

        .. _4.1: https://datatracker.ietf.org/doc/html/rfc6455#section-4.1
        .. _4.2: https://datatracker.ietf.org/doc/html/rfc6455#section-4.2
        .. _7.1.3: https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.3
        .. _7.1.4: https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.4

        )_staterT   r)   r)   r*   r1      s   zProtocol.statec                 C  s    | j r| j d|j || _d S )Nz= connection is %s)rB   r3   r>   rV   )rT   r1   r)   r)   r*   r1      s   
c                 C  s&   | j turdS | jdu rtjS | jjS )z
        WebSocket close code received from the remote endpoint.

        Defined in 7.1.5_ of :rfc:`6455`.

        .. _7.1.5: https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.5

        :obj:`None` if the connection isn't closed yet.

        N)r1   r/   rH   r   ABNORMAL_CLOSUREcoderW   r)   r)   r*   
close_code   s
   

zProtocol.close_code
str | Nonec                 C  s$   | j turdS | jdu rdS | jjS )a  
        WebSocket close reason  received from the remote endpoint.

        Defined in 7.1.6_ of :rfc:`6455`.

        .. _7.1.6: https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.6

        :obj:`None` if the connection isn't closed yet.

        N )r1   r/   rH   reasonrW   r)   r)   r*   close_reason   s
   

zProtocol.close_reasonr   c                 C  sf   | j tu s	J d| jdur"| jdur"| jjtv r"| jjtv r"t}nt}|| j| j| j}| j	|_
|S )a  
        Exception to raise when trying to interact with a closed connection.

        Don't raise this exception while the connection :attr:`state`
        is :attr:`~websockets.protocol.State.CLOSING`; wait until
        it's :attr:`~websockets.protocol.State.CLOSED`.

        Indeed, the exception includes the close code and reason, which are
        known only once the connection is closed.

        Raises:
            AssertionError: If the connection isn't closed yet.

        zconnection isn't closed yetN)r1   r/   rH   rI   rY   r   r   r   rJ   rS   	__cause__)rT   exc_typeexcr)   r)   r*   	close_exc   s   

zProtocol.close_excdatabytesc                 C  s   | j | t| j dS )aH  
        Receive data from the network.

        After calling this method:

        - You must call :meth:`data_to_send` and send this data to the network.
        - You should call :meth:`events_received` and process resulting events.

        Raises:
            EOFError: If :meth:`receive_eof` was called earlier.

        N)rM   	feed_datarR   rQ   rT   rc   r)   r)   r*   receive_data   s   zProtocol.receive_datac                 C  s$   | j jrdS | j   t| j dS )a  
        Receive the end of the data stream from the network.

        After calling this method:

        - You must call :meth:`data_to_send` and send this data to the network;
          it will return ``[b""]``, signaling the end of the stream, or ``[]``.
        - You aren't expected to call :meth:`events_received`; it won't return
          any new events.

        :meth:`receive_eof` is idempotent.

        N)rM   eoffeed_eofrR   rQ   rW   r)   r)   r*   receive_eof  s   
zProtocol.receive_eoffinboolc                 C  sL   | j std| jturtd| jj  | | _ | t	t
|| dS )a  
        Send a `Continuation frame`_.

        .. _Continuation frame:
            https://datatracker.ietf.org/doc/html/rfc6455#section-5.6

        Parameters:
            data: payload containing the same kind of data
                as the initial frame.
            fin: FIN bit; set it to :obj:`True` if this is the last frame
                of a fragmented message and to :obj:`False` otherwise.

        Raises:
            ProtocolError: If a fragmented message isn't in progress.

        unexpected continuation frameconnection is N)rD   r   rV   r-   r	   r1   r>   r?   
send_framer   r   rT   rc   rk   r)   r)   r*   send_continuation#  s   
zProtocol.send_continuationTc                 C  L   | j rtd| jturtd| jj  | | _ | t	t
|| dS )a  
        Send a `Text frame`_.

        .. _Text frame:
            https://datatracker.ietf.org/doc/html/rfc6455#section-5.6

        Parameters:
            data: payload containing text encoded with UTF-8.
            fin: FIN bit; set it to :obj:`False` if this is the first frame of
                a fragmented message.

        Raises:
            ProtocolError: If a fragmented message is in progress.

        expected a continuation framern   N)rD   r   rV   r-   r	   r1   r>   r?   ro   r   r   rp   r)   r)   r*   	send_text;     
zProtocol.send_textc                 C  rr   )a  
        Send a `Binary frame`_.

        .. _Binary frame:
            https://datatracker.ietf.org/doc/html/rfc6455#section-5.6

        Parameters:
            data: payload containing arbitrary binary data.
            fin: FIN bit; set it to :obj:`False` if this is the first frame of
                a fragmented message.

        Raises:
            ProtocolError: If a fragmented message is in progress.

        rs   rn   N)rD   r   rV   r-   r	   r1   r>   r?   ro   r   r   rp   r)   r)   r*   send_binaryR  ru   zProtocol.send_binaryr\   rY   r]   strc                 C  s   | j turtd| jj  |du r%|dkrtdttj	d}d}n	t||}|
 }| tt| | jdu s=J || _t| _dS )a_  
        Send a `Close frame`_.

        .. _Close frame:
            https://datatracker.ietf.org/doc/html/rfc6455#section-5.5.1

        Parameters:
            code: close code.
            reason: close reason.

        Raises:
            ProtocolError: If the code isn't valid or if a reason is provided
                without a code.

        rn   Nr\   z#cannot send a reason without a coder0   )rV   r-   r	   r1   r>   r?   r   r   r   NO_STATUS_RCVD	serializero   r   r   rH   rI   r.   rT   rY   r]   closerc   r)   r)   r*   
send_closei  s   


zProtocol.send_closec                 C  >   | j tur| j turtd| jj  | tt	| dS )z
        Send a `Ping frame`_.

        .. _Ping frame:
            https://datatracker.ietf.org/doc/html/rfc6455#section-5.5.2

        Parameters:
            data: payload containing arbitrary binary data.

        rn   N)
rV   r-   r.   r	   r1   r>   r?   ro   r   r   rf   r)   r)   r*   	send_ping     zProtocol.send_pingc                 C  r}   )z
        Send a `Pong frame`_.

        .. _Pong frame:
            https://datatracker.ietf.org/doc/html/rfc6455#section-5.5.3

        Parameters:
            data: payload containing arbitrary binary data.

        rn   N)
rV   r-   r.   r	   r1   r>   r?   ro   r   r   rf   r)   r)   r*   	send_pong  r   zProtocol.send_pongintc                 C  s   | j tu r)|tjkr)t||}| }| tt| || _	| j
dur&d| _t| _ | jtu r5| js5|   |  | _t| j dS )a?  
        `Fail the WebSocket connection`_.

        .. _Fail the WebSocket connection:
            https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.7

        Parameters:
            code: close code
            reason: close reason

        Raises:
            ProtocolError: If the code isn't valid.
        NT)r1   r-   r   rX   r   ry   ro   r   r   rI   rH   rJ   r.   r4   r'   rL   send_eofdiscardrQ   rR   rz   r)   r)   r*   fail  s   




zProtocol.faillist[Event]c                 C     | j g }| _ |S )a*  
        Fetch events generated from data received from the network.

        Call this method immediately after any of the ``receive_*()`` methods.

        Process resulting events, likely by passing them to the application.

        Returns:
            Events read from the connection.
        )rN   )rT   rN   r)   r)   r*   events_received  s   zProtocol.events_receivedlist[bytes]c                 C  r   )a  
        Obtain data to send to the network.

        Call this method immediately after any of the ``receive_*()``,
        ``send_*()``, or :meth:`fail` methods.

        Write resulting data to the connection.

        The empty bytestring :data:`~websockets.protocol.SEND_EOF` signals
        the end of the data stream. When you receive it, half-close the TCP
        connection.

        Returns:
            Data to write to the connection.

        )rO   )rT   rO   r)   r)   r*   data_to_send  s   zProtocol.data_to_sendc                 C  s>   | j tu rdS | j tu rdS | j tu rdS | j tu sJ | jS )a  
        Tell if the TCP connection is expected to close soon.

        Call this method immediately after any of the ``receive_*()``,
        ``send_close()``, or :meth:`fail` methods.

        If it returns :obj:`True`, schedule closing the TCP connection after a
        short timeout if the other side hasn't already closed it.

        Returns:
            Whether the TCP connection is expected to close soon.

        FT)r1   r-   r.   r/   r,   rL   rW   r)   r)   r*   close_expected  s   
"

zProtocol.close_expectedGenerator[None]c              
   c  s   zO	 | j  E dH r| jr| jd td| jdu r d}n| jdu r)| j}n| j| j }tj| j j	| j
tu || jdE dH }| jrK| jd| | | q tyn } z| tjt| || _W Y d}~nd}~w ty } z| tjt| || _W Y d}~nld}~w ty } z| tj|j d|j  || _W Y d}~nJd}~w ty } z|| j | tjt| || _W Y d}~n'd}~w ty } z| jjddd	 | tj || _W Y d}~nd}~ww dV  td
)a-  
        Parse incoming data into frames.

        :meth:`receive_data` and :meth:`receive_eof` run this generator
        coroutine until it needs more data or reaches EOF.

        :meth:`parse` never raises an exception. Instead, it sets the
        :attr:`parser_exc` and yields control.

        TN< EOFzunexpected end of stream)maskr2   rF   z< %sz at position zparser failed)exc_infoz"parse() shouldn't step after error) rM   at_eofrB   r3   EOFErrorr2   rC   r   rP   
read_exactr4   r'   rF   
recv_framer   r   r   PROTOCOL_ERRORrw   rS   rX   UnicodeDecodeErrorINVALID_DATAr]   startr
   set_current_sizeMESSAGE_TOO_BIG	ExceptionerrorINTERNAL_ERRORAssertionError)rT   r2   framera   r)   r)   r*   rP   /  s^   


 zProtocol.parsec                 c  s    | j tu p
| jtu | jksJ | j E dH s%| j  | j E dH r| jr.| j	d | j t
u r<| jtur<|   t| _dV  td)z
        Discard incoming data.

        This coroutine replaces :meth:`parse`:

        - after receiving a close frame, during a normal closure (1.4);
        - after sending a close frame, during an abnormal closure (7.1.7).

        Nr   z"discard() shouldn't step after EOF)r4   r'   r1   r,   rL   rM   r   r   rB   r3   r(   r   r/   r   rW   r)   r)   r*   r   w  s   
zProtocol.discardr   r   c                 C  sj  |j tu s
|j tu r| jdurtd|jst|j| _n|j tu r=| jdu r+td|jr2d| _n{|  jt|j7  _np|j t	u rNt
t|j}| | n_|j tu rTnY|j tu rt|j| _| jtu ro| jduslJ d| _| jdurxtd| jtu r| t
t|j | j| _d| _t| _| jtu r|   |  | _t| j n	td|j d| j| dS )	z-
        Process an incoming frame.

        Nrs   rm   Fzincomplete fragmented messageTzunexpected opcode: 02x)opcoder   r   rC   r   rk   lenrc   r   r   r   r   ro   r   r   rP   rH   r1   r.   rI   rJ   r-   r4   r'   r   r   rQ   rR   r   rN   append)rT   r   
pong_framer)   r)   r*   r     sF   










zProtocol.recv_framec                 C  s6   | j r
| j d| | j|j| jtu | jd d S )Nz> %s)r   rF   )rB   r3   rO   r   ry   r4   r(   rF   )rT   r   r)   r)   r*   ro     s   zProtocol.send_framec                 C  s2   | j rJ d| _ | jr| jd | jt d S )NTz> EOF)rL   rB   r3   rO   r   r    rW   r)   r)   r*   r     s
   
zProtocol.send_eof)
r4   r   r1   r   r2   r5   r3   r6   r7   r8   )r7   r   )r1   r   r7   r8   )r7   r5   )r7   r[   )r7   r   )rc   rd   r7   r8   )r7   r8   )rc   rd   rk   rl   r7   r8   )T)Nr\   )rY   r5   r]   rw   r7   r8   )r\   )rY   r   r]   rw   r7   r8   )r7   r   )r7   r   )r7   rl   )r7   r   )r   r   r7   r8   )r"   r#   r$   r%   r-   rU   propertyr1   setterrZ   r^   rb   rg   rj   rq   rt   rv   r|   r~   r   r   r   r   r   rP   r   r   ro   r   r)   r)   r)   r*   r   I   sB    D
%


$

1


-
H

R
r   )2
__future__r   enumr<   r9   collections.abcr   typingr   
exceptionsr   r   r   r	   r
   r   rF   r   framesr   r   r   r   r   r   r   r   r   r   http11r   r   streamsr   r   r   r   __all__EventIntEnumr   r'   r(   r   r,   r-   r.   r/   r    r   r)   r)   r)   r*   <module>   s4     0