o
    _cq\                     @  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mZm	Z	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 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,j0Z0dZ1	 G dd dZ2dS )    )annotationsN)	GeneratorListOptionalTypeUnion   )ConnectionClosedConnectionClosedErrorConnectionClosedOKInvalidStatePayloadTooBigProtocolError)	Extension)	OK_CLOSE_CODES	OP_BINARYOP_CLOSEOP_CONTOP_PINGOP_PONGOP_TEXTCloseFrame)RequestResponse)StreamReader)
LoggerLikeOriginSubprotocol)
Connection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+   @/usr/local/lib/python3.10/dist-packages/websockets/connection.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!   6   s    r!       c                   @  s  e Zd ZdZeddfdLddZedMddZejdNddZedOddZ	edPddZ
edQddZdRddZdSdd ZdTd#d$ZdUdTd&d'ZdUdTd(d)ZdVdWd.d/ZdRd0d1ZdRd2d3ZdXdYd5d6ZdZd8d9Zd[d;d<Zd\d=d>Zd]d@dAZd]dBdCZd^dFdGZd^dHdIZdSdJdKZdS )_r   a5  
    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` to disable 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sider    stater!   max_sizeOptional[int]loggerOptional[LoggerLike]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lowerr7   isEnabledForDEBUGdebugr3   r4   r5   cur_sizeexpect_continuation_frameorigin
extensionsZsubprotocol
close_rcvd
close_sentclose_rcvd_then_senthandshake_exceof_sentr   readereventswritesparseparsernext
parser_exc)selfr3   r4   r5   r7   r+   r+   r,   __init__V   s6   



zConnection.__init__c                 C  s   | j S )zm
        WebSocket connection state.

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

        )_staterU   r+   r+   r,   r4      s   zConnection.statec                 C  s    | j r| j d|j || _d S )Nz= connection is %s)rD   r7   r@   rW   )rU   r4   r+   r+   r,   r4      s   
c                 C  $   | j turdS | jdu rdS | jjS )z
        `WebSocket close code`_.

        .. _WebSocket close code:
            https://www.rfc-editor.org/rfc/rfc6455.html#section-7.1.5

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

        N  )r4   r1   rI   coderX   r+   r+   r,   
close_code   
   

zConnection.close_codeOptional[str]c                 C  rY   )z
        `WebSocket close reason`_.

        .. _WebSocket close reason:
            https://www.rfc-editor.org/rfc/rfc6455.html#section-7.1.6

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

        N )r4   r1   rI   reasonrX   r+   r+   r,   close_reason   r]   zConnection.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.connection.State.CLOSING`; wait until
        it's :attr:`~websockets.connection.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)r4   r1   rI   rJ   r[   r   r   r
   rK   rT   	__cause__)rU   exc_typeexcr+   r+   r,   	close_exc   s$   

zConnection.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)rN   	feed_datarS   rR   rU   rf   r+   r+   r,   receive_data   s   zConnection.receive_datac                 C  s   | j   t| j dS )aw  
        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.
        - You aren't expected to call :meth:`events_received`; it won't return
          any new events.

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

        N)rN   feed_eofrS   rR   rX   r+   r+   r,   receive_eof  s   
zConnection.receive_eoffinboolc                 C  s,   | j std| | _ | 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 frameN)rF   r   
send_framer   r   rU   rf   rm   r+   r+   r,   send_continuation  s   zConnection.send_continuationTc                 C  ,   | j rtd| | _ | 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 frameN)rF   r   rp   r   r   rq   r+   r+   r,   	send_text,     zConnection.send_textc                 C  rs   )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.

        rt   N)rF   r   rp   r   r   rq   r+   r+   r,   send_binaryA  rv   zConnection.send_binaryr_   r[   r`   strc                 C  sh   | j rtd|du r|dkrtdtdd}d}n	t||}| }| tt| || _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 a fragmented message is being sent, if the code
                isn't valid, or if a reason is provided without a code

        rt   Nr_   z#cannot send a reason without a codei  r2   )
rF   r   r   	serializerp   r   r   rJ   r0   r4   rU   r[   r`   closerf   r+   r+   r,   
send_closeV  s   


zConnection.send_closec                 C     |  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.

        N)rp   r   r   ri   r+   r+   r,   	send_pingv     zConnection.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.

        N)rp   r   r   ri   r+   r+   r,   	send_pong  r   zConnection.send_pongintc                 C  sp   | j tu r |dkr t||}| }| tt| || _t| _ | j	t
u r,| js,|   |  | _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.
        rZ   N)r4   r/   r   ry   rp   r   r   rJ   r0   r3   r)   rM   send_eofdiscardrR   rS   rz   r+   r+   r,   fail  s   


zConnection.failList[Event]c                 C     | j g }| _ |S )a7  
        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:
            List[Event]: Events read from the connection.
        )rO   )rU   rO   r+   r+   r,   events_received  s   zConnection.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.connection.SEND_EOF` signals
        the end of the data stream. When you receive it, half-close the TCP
        connection.

        Returns:
            List[bytes]: Data to write to the connection.

        )rP   )rU   rP   r+   r+   r,   data_to_send  s   zConnection.data_to_sendc                 C  s   | j tu p	| jduS )a  
        Tell if the TCP connection is expected to close soon.

        Call this method immediately after any of the ``receive_*()`` 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:
            bool: Whether the TCP connection is expected to close soon.

        N)r4   r0   rL   rX   r+   r+   r,   close_expected  s   zConnection.close_expectedGenerator[None, None, 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ym } z| dt| || _W Y d}~nd}~w ty } z| dt| || _W Y d}~ncd}~w ty } z| d	|j d
|j  || _W Y d}~nBd}~w ty } z| dt| || _W Y d}~n&d}~w ty } z| jjddd | d || _W Y d}~nd}~ww dV  td)z
        Parse incoming data into frames.

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

        TN< EOFzunexpected end of stream)maskr5   rH   z< %si  rZ   i  z at position i  zparser failed)exc_infoi  z"parse() shouldn't step after error)rN   at_eofrD   r7   EOFErrorr5   rE   r   rQ   Z
read_exactr3   r)   rH   
recv_framer   r   rx   rT   UnicodeDecodeErrorr`   startr   	ExceptionerrorAssertionError)rU   r5   framerd   r+   r+   r,   rQ     s\   


 
zConnection.parsec                 c  sx    | 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 r2| 	  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)r3   r)   rM   rN   r   r   rD   r7   r*   r   r1   r4   r   rX   r+   r+   r,   r   =  s   

zConnection.discardr   r   c                 C  sr  |j tu s
|j tu r!| jdurtd|jrd| _nt|j| _n|j tu rA| jdu r/td|jr6d| _n{|  jt|j7  _np|j t	u rRt
t|j}| | n_|j tu rXnY|j tu rt|j| _| jtu rs| jduspJ d| _| jdur|t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.

        Nrt   ro   Fzincomplete fragmented messageTzunexpected opcode: 02x)opcoder   r   rE   r   rm   lenrf   r   r   r   r   rp   r   r   rQ   rI   r4   r0   rJ   rK   r/   r3   r)   r   r   rR   rS   r   rO   append)rU   r   Z
pong_framer+   r+   r,   r   [  sF   










zConnection.recv_framec                 C  sT   | j turtd| j j d| jr| jd| | j|j| j	t
u | jd d S )Nz#cannot write to a WebSocket in the z statez> %s)r   rH   )r4   r/   r   r@   rD   r7   rP   r   ry   r3   r*   rH   )rU   r   r+   r+   r,   rp     s   
zConnection.send_framec                 C  s2   | j rJ d| _ | jr| jd | jt d S )NTz> EOF)rM   rD   r7   rP   r   r"   rX   r+   r+   r,   r     s
   
zConnection.send_eof)
r3   r    r4   r!   r5   r6   r7   r8   r9   r:   )r9   r!   )r4   r!   r9   r:   )r9   r6   )r9   r^   )r9   r	   )rf   rg   r9   r:   )r9   r:   )rf   rg   rm   rn   r9   r:   )T)Nr_   )r[   r6   r`   rx   r9   r:   )r_   )r[   r   r`   rx   r9   r:   )r9   r   )r9   r   )r9   rn   )r9   r   )r   r   r9   r:   )r$   r%   r&   r'   r/   rV   propertyr4   setterr\   ra   re   rj   rl   rr   ru   rw   r|   r~   r   r   r   r   r   rQ   r   r   rp   r   r+   r+   r+   r,   r   F   sB    C	
%


 

+



D

Rr   )3
__future__r   enumr>   r;   typingr   r   r   r   r   
exceptionsr	   r
   r   r   r   r   rH   r   framesr   r   r   r   r   r   r   r   r   Zhttp11r   r   streamsr   r   r   r   __all__EventIntEnumr    r)   r*   r!   r.   r/   r0   r1   r"   r   r+   r+   r+   r,   <module>   s2     ,