
    =Xcq\                       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ejP                        Z)e)jT                  Z*e)jV                  Z+ G d dejP                        Z,e,jZ                  Z-e,j\                  Z.e,j^                  Z/e,j`                  Z0dZ1	  G d d      Z2y)    )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                  &    e Zd ZdZ ed      \  ZZy)r!   z6A WebSocket connection is either a server or a client.   N)__name__
__module____qualname____doc__rangeSERVERCLIENT     7/usr/lib/python3/dist-packages/websockets/connection.pyr!   r!   ,   s    @1XNFFr.   r!   c                  *    e Zd ZdZ ed      \  ZZZZy)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    @(-a%Jgvr.   r"   r.   c                  0   e Zd ZdZeddf	 	 	 	 	 	 	 	 	 ddZedd       Zej                  dd       Zedd       Z	edd       Z
ed d	       Zd!d
Zd"dZd#dZd$d#dZd$d#dZd%d&dZd!dZd!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y).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   Nc                H   t        j                         | _        	 |0t        j                  d|j
                  j                                }|| _        	 |j                  t        j                        | _
        || _        || _        || _        d | _        d| _        d | _        g | _        d | _        d | _        d | _        d | _        d | _        	 d| _        t1               | _        g | _        g | _        | j9                         | _        t=        | j:                         d | _        y )Nzwebsockets.F) uuiduuid4idlogging	getLoggernamelowerloggerisEnabledForDEBUGdebugsidestatemax_size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)selfrC   rD   rE   r?   s        r/   __init__zConnection.__init__V   s    "ZZ\B >&&TYY__5F4G'HIF"() ((7
 	 
 ! (, */& )-+-26 ,0+/48! 37	  #n#%#%jjlT[[/3r.   c                    | j                   S )zm
        WebSocket connection state.

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

        )_staterW   s    r/   rD   zConnection.state   s     {{r.   c                v    | j                   r&| j                  j                  d|j                         || _        y )Nz= connection is %s)rB   r?   r=   rZ   )rW   rD   s     r/   rD   zConnection.state   s)    ::KK2EJJ?r.   c                n    | j                   t        ury| j                  y| 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  )rD   r5   rK   coder[   s    r/   
close_codezConnection.close_code   s0     ::V#__$??'''r.   c                n    | j                   t        ury| j                  y| j                  j                  S )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 )rD   r5   rK   reasonr[   s    r/   close_reasonzConnection.close_reason   s0     ::V#__$??)))r.   c                d   | j                   t        u sJ d       | j                  K| j                  ?| 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 yet)rD   r5   rK   rL   r_   r   r   r   rM   rV   	__cause__)rW   exc_typeexcs      r/   	close_exczConnection.close_exc   s      zzV#B%BB# OO'+$$6$$6)H,H (OOOO%%!
 
r.   c                d    | j                   j                  |       t        | j                         y)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)rP   	feed_datarU   rT   rW   datas     r/   receive_datazConnection.receive_data   s"     	d#T[[r.   c                b    | j                   j                          t        | j                         y)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)rP   feed_eofrU   rT   r[   s    r/   receive_eofzConnection.receive_eof  s      	T[[r.   c                    | j                   st        d      | | _         | j                  t        t        ||             y)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)rG   r   
send_framer   r   rW   rm   fins      r/   send_continuationzConnection.send_continuation  s8    " -- ?@@-0&gtS12r.   c                    | j                   rt        d      | | _         | j                  t        t        ||             y)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)rG   r   rt   r   r   ru   s      r/   	send_textzConnection.send_text,  s8      )) ?@@-0&gtS12r.   c                    | j                   rt        d      | | _         | j                  t        t        ||             y)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.

        ry   N)rG   r   rt   r   r   ru   s      r/   send_binaryzConnection.send_binaryA  s8      )) ?@@-0&is34r.   c                   | j                   rt        d      ||dk7  rt        d      t        dd      }d}nt        ||      }|j                         }| j	                  t        t        |             || _        t        | _	        y)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

        ry   Nrb   z#cannot send a reason without a codei  r.   )
rG   r   r   	serializert   r   r   rL   r4   rD   rW   r_   rc   closerm   s        r/   
send_closezConnection.send_closeV  s|      )) ?@@<|#$IJJ$OED$'E??$D 	h-.
r.   c                B    | j                  t        t        |             y)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)rt   r   r   rl   s     r/   	send_pingzConnection.send_pingv       	gt,-r.   c                B    | j                  t        t        |             y)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)rt   r   r   rl   s     r/   	send_pongzConnection.send_pong  r   r.   c                |   | j                   t        u rR|dk7  rMt        ||      }|j                         }| j	                  t        t        |             || _        t        | _         | j                  t        u r| j                  s| j                          | j                         | _        t        | j                         y)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.
        r^   N)rD   r3   r   r~   rt   r   r   rL   r4   rC   r+   rO   send_eofdiscardrT   rU   r   s        r/   failzConnection.fail  s    & ::t|dF+(h 56"'$
 99t}}MMO llnT[[r.   c                .    | j                   g c}| _         |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.
        )rQ   )rW   rQ   s     r/   events_receivedzConnection.events_received  s     #kk2r.   c                .    | j                   g c}| _         |S )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.

        )rR   )rW   rR   s     r/   data_to_sendzConnection.data_to_send  s    " #kk2r.   c                F    | j                   t        u xs | 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)rD   r4   rN   r[   s    r/   close_expectedzConnection.close_expected  s#    , zzW$F(:(:$(FFr.   c              #    K   	 	 | j                   j                         E d{   r2| j                  r| j                  j                  d       t	        d      | j
                  d}n2| j                  | j
                  }n| j
                  | j                  z
  }t        j                  | j                   j                  | j                  t        u || j                        E d{   }| j                  r| j                  j                  d|       | j                  |       7 7 B# t        $ r,}| j                  dt!        |             || _        Y d}~nd}~wt        $ r,}| j                  dt!        |             || _        Y d}~nd}~wt$        $ r<}| j                  d	|j&                   d
|j(                          || _        Y d}~nd}~wt*        $ r,}| j                  dt!        |             || _        Y d}~nNd}~wt,        $ r?}| j                  j/                  dd       | j                  d       || _        Y d}~nd}~ww xY wd t1        d      w)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)maskrE   rI   z< %si  r^   i  z at position i  zparser failed)exc_infoi  z"parse() shouldn't step after error)rP   at_eofrB   r?   EOFErrorrE   rF   r   rS   
read_exactrC   r+   rI   
recv_framer   r   strrV   UnicodeDecodeErrorrc   startr   	ExceptionerrorAssertionError)rW   rE   framerh   s       r/   rS   zConnection.parse  s    5	"#{{11333zz))'2
 ##=>>==(#H]]*#}}H#}}t}}<H
 $);;KK**f,%#	$  ::KK%%fe4&= 3&  	"IIdCH%!DOO 	"IIdCH%!DOO! 	"IIdszzl-		{CD!DOO 	"IIdCH%!DOO 	"KKo=IIdO!DOO		" 	ABBs   ID) D$CD) $D'%A D) 'D) )	I2"EII%"FII2G
II"H=II5IIIIc              #    K   | j                   t        u | j                  k(  sJ | j                  j	                         E d{   s=| j                  j                          | j                  j	                         E d{   s=| j                  r| j                  j                  d       | j                   t        u r| j                          t        | _        d t        d      7 7 jw)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)rC   r+   rO   rP   r   r   rB   r?   r,   r   r5   rD   r   r[   s    r/   r   zConnection.discard=  s      		V#777"kk00222KK! #kk00222::KKg& 99MMO
 ABB 32s*   ?C*C&;C*=C(>C*A$C*(C*c                   |j                   t        u s|j                   t        u rH| j                  t	        d      |j
                  r	d| _        nt        |j                        | _        n|j                   t        u rV| j                  t	        d      |j
                  r	d| _        n| xj                  t        |j                        z  c_        n|j                   t        u r-t        t        |j                        }| j                  |       nM|j                   t        u rn9|j                   t        u rt        j                  |j                        | _        | j"                  t$        u r| j&                  J d| _        | j                  t	        d      | j"                  t*        u rL| j                  t        t        |j                               | j                   | _        d| _        t$        | _        | j,                  t.        u r| j1                          | j3                         | _        t7        | j4                         nt9        d|j                   d      | j:                  j=                  |       y)	z-
        Process an incoming frame.

        Nry   rs   Fzincomplete fragmented messageTzunexpected opcode: 02x)opcoder   r   rF   r   rv   lenrm   r   r   r   r   rt   r   r   rS   rK   rD   r4   rL   rM   r3   rC   r+   r   r   rT   rU   r   rQ   append)rW   r   
pong_frames      r/   r   zConnection.recv_frame[  s   
 <<7"elli&?}}(#$CDDyy $ #EJJ\\W$}}$#$CDDyy $UZZ0\\W$ w

3JOOJ'\\W$ \\X% $kk%**5DOzzW$222,1)}}(#$CDD zzT!
 h

 ;<"&//,0)$
 yyF"
 ,,.DK !#6u||C6H!IJJ5!r.   c                J   | j                   t        ur#t        d| j                   j                   d      | j                  r| j
                  j	                  d|       | j                  j                  |j                  | j                  t        u | j                               y )Nz#cannot write to a WebSocket in the z statez> %s)r   rI   )rD   r3   r   r=   rB   r?   rR   r   r~   rC   r,   rI   )rW   r   s     r/   rt   zConnection.send_frame  s|    ::T!5djjoo5FfM  ::KKfe,OOf!4OQ	
r.   c                    | j                   rJ d| _         | j                  r| j                  j                  d       | j                  j	                  t
               y )NTz> EOF)rO   rB   r?   rR   r   r#   r[   s    r/   r   zConnection.send_eof  sA    ==  ::KKg&8$r.   )
rC   r!   rD   r"   rE   Optional[int]r?   zOptional[LoggerLike]returnNone)r   r"   )rD   r"   r   r   )r   r   )r   zOptional[str])r   r
   )rm   bytesr   r   )r   r   )rm   r   rv   boolr   r   )T)Nrb   )r_   r   rc   r   r   r   )rb   )r_   intrc   r   r   r   )r   zList[Event])r   zList[bytes])r   r   )r   zGenerator[None, None, None])r   r   r   r   )r&   r'   r(   r)   r3   rX   propertyrD   setterr`   rd   ri   rn   rq   rw   rz   r|   r   r   r   r   r   r   r   rS   r   r   rt   r   r-   r.   r/   r    r    F   s   $ "''+A4A4 A4  	A4
 %A4 
A4F   \\ 
 ( (" * *" ! !J &3,3*5*@..'V (G4BCHC<N"d

%r.   r    )3
__future__r   enumr;   r8   typingr   r   r   r   r   
exceptionsr
   r   r   r   r   r   rI   r   framesr   r   r   r   r   r   r   r   r   http11r   r   streamsr   r   r   r   __all__EventIntEnumr!   r+   r,   r"   r2   r3   r4   r5   r#   r    r-   r.   r/   <module>r      s    "    9 9  "
 
 
 & ! 3 3 	gx&' A4<<  
	1DLL 1 
zz
--	  Ex	% x	%r.   