
    ,h_             	         U d dl mZ d dlZd dlmZ d dlmZmZ d dlm	Z	 d dl
mZ d dlZd dlZd dl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mZmZmZmZ 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'm(Z) d dl*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3 d dl4Z"ejj                  dk  rd dl6m7Z7 erd dl8m9Z9 d dl:m;Z; d dl<m=Z=m>Z>m?Z?m@Z@mAZAmBZB  eC eDeE ed      j                  d      dd             dk  ZGdeHd<   eGre j                  ZJne7ZJdZKdeHd<   dZLdeHd<   dZMdeHd<   dZNdeHd<    ej                  d      ZPdeHd <    ed!      ZQ ed"eR#      ZS G d$ d%eT      ZUdMd&ZV G d' d(      ZWeddeLeMeNeKeKd)	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dNd*       ZXddeLeMeNd+	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dOd-ZY	 dPddeLeMeKeKeNd.	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dQd/ZZ	 dPddeLeMeNd+	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dRd0Z[	 	 	 	 	 	 dSd1Z\ddeLeMeNd+	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dTd2Z]eLeMeNf	 	 	 	 	 	 	 	 	 	 	 dUd4Z^deLeMeNeKeKe j                  d5	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dVd6Z` G d7 d8eT      Za G d9 d:ea      Zb G d; d<ea      Zc G d= d>eT      Zd G d? d@ea      Ze G dA dB      Zf eg       ZhdeHdC<    G dD dEeeQ         Zi G dF d3      Zj	 	 	 	 	 	 dWdGZk G dH d,e j                  j                        Zn G dI dJ      Zo G dK dL      Zpy)X    )annotationsN)OrderedDict)asynccontextmanagerAbstractAsyncContextManager)partial)
ip_address)	AnyListNoReturnOptionalUnionTypeVarTYPE_CHECKINGGenericcast)version)ConnectionTypeWSConnection)ConnectionState)	AcceptConnectionBytesMessageCloseConnectionPingPongRejectConnection
RejectDataRequestTextMessage)      )BaseExceptionGroup)TracebackType)Final)AsyncGenerator	AwaitableCallableIterable	CoroutineSequencetrio.   )r      r#   _IS_TRIO_MULTI_ERROR<   CONN_TIMEOUT   MESSAGE_QUEUE_SIZEi   MAX_MESSAGE_SIZEi   RECEIVE_BYTESztrio-websocketloggerTE)boundc                      e Zd ZdZy)TrioWebsocketInternalErrorzRaised as a fallback when open_websocket is unable to unwind an exceptiongroup
    into a single preferred exception. This should never happen, if it does then
    underlying assumptions about the internal code are incorrect.
    N__name__
__module____qualname____doc__     V/var/www/html/Resume-Scraper/venv/lib/python3.12/site-packages/trio_websocket/_impl.pyr:   r:   >       rA   r:   c                >    t        | t        j                        rd S | S N
isinstancer*   	Cancelledexcs    rB   _ignore_cancelrK   E   s    c4>>24;;rA   c                  <    e Zd ZdZdZddZddZ	 	 	 	 	 	 	 	 ddZy)	_preserve_current_exceptiona  A context manager which should surround an ``__exit__`` or
    ``__aexit__`` handler or the contents of a ``finally:``
    block. It ensures that any exception that was being handled
    upon entry is not masked by a `trio.Cancelled` raised within
    the body of the context manager.

    https://github.com/python-trio/trio/issues/1559
    https://gitter.im/python-trio/general?at=5faf2293d37a1a13d6a582cf
    _armedc                    d| _         y NFrN   selfs    rB   __init__z$_preserve_current_exception.__init__U   s	    rA   c                @    t        j                         d   d u| _        y )Nr1   )sysexc_inforO   rR   s    rB   	__enter__z%_preserve_current_exception.__enter__X   s    llnQ't3rA   c                    || j                   syt        r(t        j                  j	                  t
        |      }|d u S t        |t              r|j                  d       }|d u S t        |      }|d u S )NFc                8    t        | t        j                         S rE   rF   rI   s    rB   <lambda>z6_preserve_current_exception.__exit__.<locals>.<lambda>g   s    
3PTP^P^@_<_ rA   )	rO   r.   r*   
MultiErrorfilterrK   rG   r!   subgroup)rS   tyvaluetbfiltered_exceptions        rB   __exit__z$_preserve_current_exception.__exit__[   s{     =!%!7!7!N
 "T))	 12!&0_!` "T)) "0!6!T))rA   NreturnNone)r_   ztype[BaseException] | Noner`   zBaseException | Nonera   zTracebackType | Nonere   bool)r<   r=   r>   r?   	__slots__rT   rX   rc   r@   rA   rB   rM   rM   I   sC     I4*&* $* !	*
 
*rA   rM   )subprotocolsextra_headersmessage_queue_sizemax_message_sizereceive_buffer_sizeconnect_timeoutdisconnect_timeoutc              f   	
K   d	 f
d}d
fd}dd}d}d}d}	 t        j                         4 d{   }t        j                  ||       d{   }t	        |t        j
                        r5|j                         }	 | 	 t        j                  ||       d{   }ddd      d{    ||j                          	 |j                          yy7 7 # t        $ r}|} d}~ww xY w7 S# t        j                  ||       d{  7  }w xY w7 i# 1 d{  7  sw Y   yxY w# t        $ rH}t        |j                        dk(  r ||j                  d          d}|j                  D ]#  }t	        |t         j                        r| n-|}% || ||        ||j                  d           ||       |j                  D ]  }t	        |t              st        | ||j                  D cg c]	  }||us| nc c}w }}d}|j                  )|j                  s|j                  |j                         d}d	|z   d
z   }t!        ||      |_        d|_         ||       t#        d      |d}~ww xY w# ||j                          w w xY ww)ah  
    Open a WebSocket client connection to a host.

    This async context manager connects when entering the context manager and
    disconnects when exiting. It yields a
    :class:`WebSocketConnection` instance.

    :param str host: The host to connect to.
    :param int port: The port to connect to.
    :param str resource: The resource, i.e. URL path.
    :param Union[bool, ssl.SSLContext] use_ssl: If this is an SSL context, then
        use that context. If this is ``True`` then use default SSL context. If
        this is ``False`` then disable SSL.
    :param subprotocols: An iterable of strings representing preferred
        subprotocols.
    :param list[tuple[bytes,bytes]] extra_headers: A list of 2-tuples containing
        HTTP header key/value pairs to send with the connection request. Note
        that headers used by the WebSocket protocol (e.g.
        ``Sec-WebSocket-Accept``) will be overwritten.
    :param int message_queue_size: The maximum number of messages that will be
        buffered in the library's internal message queue.
    :param int max_message_size: The maximum message size as measured by
        ``len()``. If a message is received that is larger than this size,
        then the connection is closed with code 1009 (Message Too Big).
    :param Optional[int] receive_buffer_size: The buffer size we use to
        receive messages internally. None to let trio choose. Defaults
        to 4 KiB.
    :param float connect_timeout: The number of seconds to wait for the
        connection before timing out.
    :param float disconnect_timeout: The number of seconds to wait when closing
        the connection before timing out.
    :raises HandshakeError: for any networking error,
        client-side timeout (:exc:`ConnectionTimeout`, :exc:`DisconnectionTimeout`),
        or server rejection (:exc:`ConnectionRejected`) during handshakes.
    c                  
K   	 t        j                        5  t        | 	

       d {   cd d d        S 7 # 1 sw Y   y xY w# t         j                  $ r t        d t
        $ r}t        |d }~ww xY ww)Nuse_sslri   rj   rk   rl   rm   )r*   
fail_afterconnect_websocketTooSlowErrorConnectionTimeoutOSErrorHandshakeError)nurseryern   rj   hostrl   rk   portrm   resourceri   rs   s     rB   _open_connectionz(open_websocket.<locals>._open_connection   s     	(1 =.wdgL"/'9%5(;= == === =    	.#- 	( a'	(sZ   B A AAA	A  B AAA B A "A=1A88A==B c                   K   	 t        j                        5  | j                          d {    d d d        y 7 # 1 sw Y   y xY w# t         j                  $ r t        d w xY wwrE   )r*   rt   acloserv   DisconnectionTimeout)
connectionro   s    rB   _close_connectionz)open_websocket.<locals>._close_connection   sd     	1!34 * '')))* *)* *   	1&D0	1sG   A(A
 ><>A
 A(>AA
 A(A
 
A%%A(c                @    d}| j                   }	 | # || _         ~ ~w xY w)zIThis helper allows re-raising an exception without __context__ being set.T)__context__)rJ   __tracebackhide__contexts      rB   _raisezopen_websocket.<locals>._raise   s+     !//	I%COWs    Nr1   r    z' and the context for the user exceptionz\Both internal and user exceptions encountered. This group contains the internal exception(s)r+   FzThe trio-websocket API is not expected to raise multiple exceptions. Please report this as a bug to https://github.com/python-trio/trio-websocket)rz   trio.Nurseryre   WebSocketConnection)r   r   re   rf   )rJ   BaseExceptionre   r   )r*   open_nurseryoutcomeacapturerG   Valueunwrapr   _TRIO_EXC_GROUP_TYPElen
exceptionsrH   KeyboardInterruptr   __suppress_context__appendr!   r:   )r|   r}   r~   rs   ri   rj   rk   rl   rm   rn   ro   r   r   r   r   close_result
user_errornew_nurseryresultr{   exception_to_raisesub_excsubexcr   	eg_substreg_strs   ```````````               rB   open_websocketr   m   s    R( (1	 *.J/3LJL"$$& 	Y 	Y+"++,<kJJF&'--0#]]_
Y$$
 *1)9)9:KZ)X#XL	Y 	YT #!  _	YJ % !"J $Y)9)9:KZ)X#X#XL	Y 	Y 	Y 	Y    7q||!1<<?# 26|| 	'Ggt~~6%1%,"	' ") ):& q||A'%& || 	/G'#45'Q.	/ !/0||XVvZ?W&XXJXI %%1*:Y:Y!!*"8"89E	,.78:=>  &8
%KJ".3J+:(<
 		g7t #! $s    J1E C/E 
D/$C1%.D/C3D/3D4D/8E D-E 'J1/E 1D/3	D<C??DD	D/	D*#D&
$D**D/-E /E5D86E=E 
JAJ'AJ8J	HHA3JJJ J..J1)ri   rj   rk   rl   rm   r   c               T  K   |du rt        j                         }
n/|du rd}
n(t        |t         j                        r|}
nt	        d      t
        j                  d|
dnd|||       |
t        j                  ||       d{   }n!t        j                  |||
d       d{   }|d	v r|}n| d
| }t        |t        t        j                        |||||||		      }| j                  |j                         |j                   j#                          d{    |S 7 7 ~7 
w)aj  
    Return an open WebSocket client connection to a host.

    This function is used to specify a custom nursery to run connection
    background tasks in. The caller is responsible for closing the connection.

    If you don't need a custom nursery, you should probably use
    :func:`open_websocket` instead.

    :param nursery: A Trio nursery to run background tasks in.
    :param str host: The host to connect to.
    :param int port: The port to connect to.
    :param str resource: The resource, i.e. URL path.
    :param Union[bool, ssl.SSLContext] use_ssl: If this is an SSL context, then
        use that context. If this is ``True`` then use default SSL context. If
        this is ``False`` then disable SSL.
    :param subprotocols: An iterable of strings representing preferred
        subprotocols.
    :param list[tuple[bytes,bytes]] extra_headers: A list of 2-tuples containing
        HTTP header key/value pairs to send with the connection request. Note
        that headers used by the WebSocket protocol (e.g.
        ``Sec-WebSocket-Accept``) will be overwritten.
    :param int message_queue_size: The maximum number of messages that will be
        buffered in the library's internal message queue.
    :param int max_message_size: The maximum message size as measured by
        ``len()``. If a message is received that is larger than this size,
        then the connection is closed with code 1009 (Message Too Big).
    :param Optional[int] receive_buffer_size: The buffer size we use to
        receive messages internally. None to let trio choose. Defaults
        to 4 KiB.
    :rtype: WebSocketConnection
    TFNz1`use_ssl` argument must be bool or ssl.SSLContextzConnecting to ws%s://%s:%d%sr   s)ssl_contexthttps_compatible)P     :r|   pathclient_subprotocolsclient_extra_headersrk   rl   rm   )sslcreate_default_contextrG   
SSLContext	TypeErrorr5   debugr*   open_tcp_streamopen_ssl_over_tcp_streamr   r   r   CLIENT
start_soon_reader_task_open_handshakewait)rz   r|   r}   r~   rs   ri   rj   rk   rl   rm   r   streamhost_headerr   s                 rB   ru   ru   4  s5    Z $002	E		GS^^	,KLL
LL/!sD$B ++D$7744T4#d< <yav&$V^**+(}-)/1J z../

$
$
)
)
+++% 8< ,s7   BD(D"!D(%D$&A5D(D&D($D(&D()ri   rj   rk   rl   rn   ro   rm   c               P    t        | |      \  }	}
}}t        |	|
|||||||||      S )a  
    Open a WebSocket client connection to a URL.

    This async context manager connects when entering the context manager and
    disconnects when exiting. It yields a
    :class:`WebSocketConnection` instance.

    :param str url: A WebSocket URL, i.e. `ws:` or `wss:` URL scheme.
    :param ssl_context: Optional SSL context used for ``wss:`` URLs. A default
        SSL context is used for ``wss:`` if this argument is ``None``.
    :type ssl_context: ssl.SSLContext or None
    :param subprotocols: An iterable of strings representing preferred
        subprotocols.
    :param list[tuple[bytes,bytes]] extra_headers: A list of 2-tuples containing
        HTTP header key/value pairs to send with the connection request. Note
        that headers used by the WebSocket protocol (e.g.
        ``Sec-WebSocket-Accept``) will be overwritten.
    :param int message_queue_size: The maximum number of messages that will be
        buffered in the library's internal message queue.
    :param int max_message_size: The maximum message size as measured by
        ``len()``. If a message is received that is larger than this size,
        then the connection is closed with code 1009 (Message Too Big).
    :param Optional[int] receive_buffer_size: The buffer size we use to
        receive messages internally. None to let trio choose. Defaults
        to 4 KiB.
    :param float connect_timeout: The number of seconds to wait for the
        connection before timing out.
    :param float disconnect_timeout: The number of seconds to wait when closing
        the connection before timing out.
    :raises HandshakeError: for any networking error,
        client-side timeout (:exc:`ConnectionTimeout`, :exc:`DisconnectionTimeout`),
        or server rejection (:exc:`ConnectionRejected`) during handshakes.
    )rs   ri   rj   rk   rl   rm   rn   ro   )_url_to_hostr   )urlr   ri   rj   rk   rl   rn   ro   rm   r|   r}   r~   return_ssl_contexts                rB   open_websocket_urlr     sG    Z 0<C/M,D$,$h8J!-)/'<NP PrA   c               j   K   t        ||      \  }}	}
}t        | ||	|
||||||
       d{   S 7 w)a  
    Return an open WebSocket client connection to a URL.

    This function is used to specify a custom nursery to run connection
    background tasks in. The caller is responsible for closing the connection.

    If you don't need a custom nursery, you should probably use
    :func:`open_websocket_url` instead.

    :param nursery: A nursery to run background tasks in.
    :param str url: A WebSocket URL.
    :param ssl_context: Optional SSL context used for ``wss:`` URLs.
    :type ssl_context: ssl.SSLContext or None
    :param subprotocols: An iterable of strings representing preferred
        subprotocols.
    :param list[tuple[bytes,bytes]] extra_headers: A list of 2-tuples containing
        HTTP header key/value pairs to send with the connection request. Note
        that headers used by the WebSocket protocol (e.g.
        ``Sec-WebSocket-Accept``) will be overwritten.
    :param int message_queue_size: The maximum number of messages that will be
        buffered in the library's internal message queue.
    :param int max_message_size: The maximum message size as measured by
        ``len()``. If a message is received that is larger than this size,
        then the connection is closed with code 1009 (Message Too Big).
    :param Optional[int] receive_buffer_size: The buffer size we use to
        receive messages internally. None to let trio choose. Defaults
        to 4 KiB.
    :rtype: WebSocketConnection
    rr   N)r   ru   )rz   r   r   ri   rj   rk   rl   rm   r|   r}   r~   r   s               rB   connect_websocket_urlr     sO     P 0<C/M,D$,"7D$"#8J)/	1 1 1 1s   *313c                   t        |       } t        j                  j                  |       }|j                  dvrt        d      ||j                  dk(  }n|j                  dk(  rt        d      |}|j                  }|t        d      |j                  |j                  }n|rdnd}|j                  }|sd	}d
| v r|d
|j                  z   z  }||||fS )a  
    Convert a WebSocket URL to a (host,port,resource) tuple.

    The returned ``ssl_context`` is either the same object that was passed in,
    or if ``ssl_context`` is None, then a bool indicating if a default SSL
    context needs to be created.

    :param str url: A WebSocket URL.
    :type ssl_context: ssl.SSLContext or None
    :returns: A tuple of ``(host, port, resource, ssl_context)``.
    )wswssz,WebSocket URL scheme must be "ws:" or "wss:"r   r   z+SSL context must be None for ws: URL schemezURL host must not be Noner   r   /?)
strurllibparseurlsplitscheme
ValueErrorhostnamer}   r   query)r   r   partsr   r|   r}   path_qss          rB   r   r     s     c(CLL!!#&E||=(GHH"\\U2		FGG(>>D|455zzzz(sbjjG 
cz3$$w 222rA   c                  K   t        |t        t        j                        |||||||	      }	| j	                  |	j
                         |	j                  j                          d{    |	S 7 w)a  
    Wrap an arbitrary stream in a WebSocket connection.

    This is a low-level function only needed in rare cases. In most cases, you
    should use :func:`open_websocket` or :func:`open_websocket_url`.

    :param nursery: A Trio nursery to run background tasks in.
    :param stream: A Trio stream to be wrapped.
    :type stream: trio.abc.Stream
    :param str host: A host string that will be sent in the ``Host:`` header.
    :param str resource: A resource string, i.e. the path component to be
        accessed on the server.
    :param subprotocols: An iterable of strings representing preferred
        subprotocols.
    :param list[tuple[bytes,bytes]] extra_headers: A list of 2-tuples containing
        HTTP header key/value pairs to send with the connection request. Note
        that headers used by the WebSocket protocol (e.g.
        ``Sec-WebSocket-Accept``) will be overwritten.
    :param int message_queue_size: The maximum number of messages that will be
        buffered in the library's internal message queue.
    :param int max_message_size: The maximum message size as measured by
        ``len()``. If a message is received that is larger than this size,
        then the connection is closed with code 1009 (Message Too Big).
    :param Optional[int] receive_buffer_size: The buffer size we use to
        receive messages internally. None to let trio choose. Defaults
        to 4 KiB.
    :rtype: WebSocketConnection
    r   N)r   r   r   r   r   r   r   r   )
rz   r   r|   r~   ri   rj   rk   rl   rm   r   s
             rB   wrap_client_streamr     so     P %V^**+(}-)/1J z../

$
$
)
)
+++ ,s   A$A/&A-'A/WebSocketRequestc                   K   t        |t        t        j                        |||      }| j	                  |j
                         |j                          d{   }|S 7 w)aa  
    Wrap an arbitrary stream in a server-side WebSocket.

    This is a low-level function only needed in rare cases. In most cases, you
    should use :func:`serve_websocket`.

    :param nursery: A nursery to run background tasks in.
    :param stream: A stream to be wrapped.
    :param int message_queue_size: The maximum number of messages that will be
        buffered in the library's internal message queue.
    :param int max_message_size: The maximum message size as measured by
        ``len()``. If a message is received that is larger than this size,
        then the connection is closed with code 1009 (Message Too Big).
    :param Optional[int] receive_buffer_size: The buffer size we use to
        receive messages internally. None to let trio choose. Defaults
        to 4 KiB.
    :type stream: trio.abc.Stream
    :rtype: WebSocketRequest
    rk   rl   rm   N)r   r   r   SERVERr   r   _get_request)rz   r   rk   rl   rm   r   requests          rB   wrap_server_streamr   I  s]     4 %^**+-)/1J z../++--GN .s   AA!AA!)handler_nurseryrk   rl   rm   rn   ro   task_statusc          
       K   |t        t        j                  ||      }nt        t        j                  |||d      } |        d{   }t	        | |||||||	      }|j                  |
       d{    y7 27 w)u?  
    Serve a WebSocket over TCP.

    This function supports the Trio nursery start protocol: ``server = await
    nursery.start(serve_websocket, …)``. It will block until the server
    is accepting connections and then return a :class:`WebSocketServer` object.

    Note that if ``host`` is ``None`` and ``port`` is zero, then you may get
    multiple listeners that have *different port numbers!*

    :param handler: An async function that is invoked with a request
        for each new connection.
    :param host: The host interface to bind. This can be an address of an
        interface, a name that resolves to an interface address (e.g.
        ``localhost``), or a wildcard address like ``0.0.0.0`` for IPv4 or
        ``::`` for IPv6. If ``None``, then all local interfaces are bound.
    :type host: str, bytes, or None
    :param int port: The port to bind to.
    :param ssl_context: The SSL context to use for encrypted connections, or
        ``None`` for unencrypted connection.
    :type ssl_context: ssl.SSLContext or None
    :param handler_nursery: An optional nursery to spawn handlers and background
        tasks in. If not specified, a new nursery will be created internally.
    :param int message_queue_size: The maximum number of messages that will be
        buffered in the library's internal message queue.
    :param int max_message_size: The maximum message size as measured by
        ``len()``. If a message is received that is larger than this size,
        then the connection is closed with code 1009 (Message Too Big).
    :param Optional[int] receive_buffer_size: The buffer size we use to
        receive messages internally. None to let trio choose. Defaults
        to 4 KiB.
    :param float connect_timeout: The number of seconds to wait for a client
        to finish connection handshake before timing out.
    :param float disconnect_timeout: The number of seconds to wait for a client
        to finish the closing handshake before timing out.
    :param task_status: Part of Trio nursery start protocol.
    :returns: This function runs until cancelled.
    N)r|   T)r|   r   r   rk   rl   rm   rn   ro   r   )r   r*   open_tcp_listenersopen_ssl_over_tcp_listenersWebSocketServerrun)handlerr|   r}   r   r   rk   rl   rm   rn   ro   r   r   	listenersservers                 rB   serve_websocketr   o  s     p $T%<%<dN$,,!
 )**I'-)/'-	F ***
--- + .s$   AB
A=,B7A?8B?Bc                      e Zd ZdZy)ry   z^
    There was an error during connection or disconnection with the websocket
    server.
    Nr;   r@   rA   rB   ry   ry     rC   rA   ry   c                      e Zd ZdZy)rw   z<There was a timeout when connecting to the websocket server.Nr;   r@   rA   rB   rw   rw     s    FrA   rw   c                      e Zd ZdZy)r   zAThere was a timeout when disconnecting from the websocket server.Nr;   r@   rA   rB   r   r     s    KrA   r   c                  ,     e Zd ZdZd fdZddZ xZS )ConnectionClosedzv
    A WebSocket operation cannot be completed because the connection is closed
    or in the process of closing.
    c                2    t         |   |       || _        yzX
        Constructor.

        :param reason:
        :type reason: CloseReason
        N)superrT   reason)rS   r   	__class__s     rB   rT   zConnectionClosed.__init__  s     	 rA   c                N    | j                   j                   d| j                   dS ) Return representation. <>)r   r<   r   rR   s    rB   __repr__zConnectionClosed.__repr__  s$    ..))*!DKK=::rA   )r   CloseReason | Nonere   rf   re   r   r<   r=   r>   r?   rT   r   __classcell__r   s   @rB   r   r     s    ;rA   r   c                  <     e Zd ZdZ	 	 	 	 	 	 	 	 d fdZddZ xZS )ConnectionRejectedzq
    A WebSocket connection could not be established because the server rejected
    the connection attempt.
    c                R    t         |   |||       || _        || _        || _        yr   )r   rT   status_codeheadersbody)rS   r   r   r  r   s       rB   rT   zConnectionRejected.__init__  s,     	gt4&	rA   c                N    | j                   j                   d| j                   dS )r   z<status_code=r   )r   r<   r   rR   s    rB   r   zConnectionRejected.__repr__  s'    ..))*-8H8H7IKKrA   )r   intr   tuple[tuple[bytes, bytes], ...]r  bytes | Nonere   rf   r   r   r   s   @rB   r   r     s9     1 	
 
(LrA   r   c                  V    e Zd ZdZddZed	d       Zed
d       Zedd       Zd
dZ	y)CloseReasonz8 Contains information about why a WebSocket was closed. c                (   || _         	 t        j                  |      j                  | _        || _        y# t
        $ rS d|cxk  rdk  rn nd| _        n3d|cxk  rdk  rn nd| _        nd|cxk  rdk  rn nd	| _        nd
| _        Y || _        yw xY w)z]
        Constructor.

        :param int code:
        :param Optional[str] reason:
          i  RFC_RESERVEDi  i  IANA_RESERVEDi  i  PRIVATE_RESERVEDINVALID_CODEN)_codewsframeprotor  name_namer   _reasonrS   coder   s      rB   rT   zCloseReason.__init__  s     

	,%11$7<<DJ   	,t#t#+
%%,
%%/
+
	,s   $5 ABBc                    | j                   S )z% (Read-only) The numeric close code. )r  rR   s    rB   r  zCloseReason.code       zzrA   c                    | j                   S )z, (Read-only) The human-readable close code. )r  rR   s    rB   r  zCloseReason.name  r  rA   c                    | j                   S )z) (Read-only) An arbitrary reason string. )r  rR   s    rB   r   zCloseReason.reason  s     ||rA   c                    | j                   j                   d| j                   d| j                   d| j                   dS )z$ Show close code, name, and reason. z<code=z, name=z	, reason=r   )r   r<   r  r  r   rR   s    rB   r   zCloseReason.__repr__#  s?    ..))*		{'$))Idkk]!M 	MrA   Nr  r  r   
str | Nonere   rf   re   r  r   re   r  )
r<   r=   r>   r?   rT   propertyr  r  r   r   r@   rA   rB   r  r    sL    B*      MrA   r  NULLc                  (    e Zd ZdZddZddZddZy)	Futurez: Represents a value that will be available in the future. c                h    t        t        t              | _        t	        j
                         | _        y)z Constructor. N)r   r6   r  _valuer*   Event_value_eventrR   s    rB   rT   zFuture.__init__.  s     a JJLrA   c                F    || _         | j                  j                          y)zT
        Set a value, which will notify any waiters.

        :param value:
        N)r#  r%  set)rS   r`   s     rB   	set_valuezFuture.set_value5  s     rA   c                   K   | j                   j                          d{    | j                  t        usJ | j                  S 7 $w)z|
        Wait for this future to have a value, then return it.

        :returns: The value set by ``set_value()``.
        N)r%  r   r#  r  rR   s    rB   
wait_valuezFuture.wait_value>  s>      $$&&&{{$&&{{ 	's   AA%ANrd   )r`   r6   re   rf   )re   r6   )r<   r=   r>   r?   rT   r(  r*  r@   rA   rB   r!  r!  ,  s    D) rA   r!  c                      e Zd ZdZ	 	 	 	 	 	 ddZedd       Zedd       Zedd       Zedd       Z	edd       Z
ddd		 	 	 	 	 dd
Zddd	 	 	 	 	 	 	 ddZy)r   z
    Represents a handshake presented by a client to a server.

    The server may modify the handshake or leave it as is. The server should
    call ``accept()`` to finish the handshake and obtain a connection object.
    c                     || _         || _        y)zz
        Constructor.

        :param WebSocketConnection connection:
        :type event: wsproto.events.Request
        N)_connection_event)rS   r   events      rB   rT   zWebSocketRequest.__init__P  s     &rA   c                .    | j                   j                  S )zi
        HTTP headers represented as a list of (name, value) pairs.

        :rtype: list[tuple]
        )r.  rj   rR   s    rB   r   zWebSocketRequest.headers^  s     {{(((rA   c                .    | j                   j                  S )z>
        The requested URL path.

        :rtype: str
        )r.  targetrR   s    rB   r   zWebSocketRequest.pathg  s     {{!!!rA   c                @    t        | j                  j                        S )zZ
        A tuple of protocols proposed by the client.

        :rtype: tuple[str]
        )tupler.  ri   rR   s    rB   proposed_subprotocolsz&WebSocketRequest.proposed_subprotocolsp  s     T[[--..rA   c                .    | j                   j                  S )zS
        The connection's local endpoint.

        :rtype: Endpoint or str
        )r-  localrR   s    rB   r7  zWebSocketRequest.localy  s     %%%rA   c                .    | j                   j                  S )zT
        The connection's remote endpoint.

        :rtype: Endpoint or str
        )r-  remoterR   s    rB   r9  zWebSocketRequest.remote  s     &&&rA   Nsubprotocolrj   c                  K   |g }| j                   j                  | j                  ||       d{    | j                   S 7 w)a  
        Accept the request and return a connection object.

        :param subprotocol: The selected subprotocol for this connection.
        :type subprotocol: str or None
        :param extra_headers: A list of 2-tuples containing key/value pairs to
            send as HTTP headers.
        :type extra_headers: list[tuple[bytes,bytes]] or None
        :rtype: WebSocketConnection
        N)r-  _acceptr.  )rS   r;  rj   s      rB   acceptzWebSocketRequest.accept  sG        M&&t{{KOOO 	Ps   /AAA)rj   r  c               r   K   |xs g }|xs d}| j                   j                  |||       d{    y7 w)a#  
        Reject the handshake.

        :param int status_code: The 3 digit HTTP status code. In order to be
            RFC-compliant, this should NOT be 101, and would ideally be an
            appropriate code in the range 300-599.
        :param list[tuple[bytes,bytes]] extra_headers: A list of 2-tuples
            containing key/value pairs to send as HTTP headers.
        :param body: If provided, this data will be sent in the response
            body, otherwise no response body will be sent.
        :type body: bytes or None
        rA   N)r-  _reject)rS   r   rj   r  s       rB   rejectzWebSocketRequest.reject  s9     & &+{s&&{M4HHHs   -757)r   r   r/  wsproto.events.Requestre   rf   )re   list[tuple[bytes, bytes]]r   )re   ztuple[str, ...]re   Endpoint | str)r;  r  rj    list[tuple[bytes, bytes]] | Nonere   r   )r   r  rj   rF  r  r  re   rf   )r<   r=   r>   r?   rT   r  r   r   r5  r7  r9  r>  rA  r@   rA   rB   r   r   I  s    ' & 
	 ) ) " " / / & & ' ' #':>	     8	 
 
 2 ;?!II 8	I
 I 
IrA   c               D   d\  }}t        | t        j                        r| j                  }n2t        | t        j                        r| j
                  j                  }d}|r4|r|j                         n|j                         ^}}}t        |||      }|S t        |       }|S )a*  
    Construct an endpoint from a stream.

    :param trio.Stream stream:
    :param bool local: If true, return local endpoint. Otherwise return remote.
    :returns: An endpoint instance or ``repr()`` for streams that cannot be
        represented as an endpoint.
    :rtype: Endpoint or str
    rQ   T)
rG   r*   SocketStreamsocket	SSLStreamtransport_streamgetsocknamegetpeernameEndpointrepr)r   r7  rI  is_ssladdrr}   _endpoints           rB   _get_stream_endpointrT    s     !NFF&$++,	FDNN	+((//16++-F<N<N<PdQD$/ O <OrA   c                     e Zd ZdZ ej
                         Zddddeee	d	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d$dZ
ed%d       Zed&d       Zed&d       Zed'd       Zed'd	       Zed(d
       Zed(d       Zed)d       Zd*d+dZd+dZd,dZd-d.dZd-d.dZd/dZd0dZ	 	 	 	 	 	 	 	 d1dZ	 	 	 	 	 	 	 	 d2dZd3dZd3dZd-d+dZd4dZ d5dZ!d6dZ"d7dZ#d8dZ$d9dZ%	 	 	 	 d:dZ&d;d Z'd<d!Z(d3d"Z)d=d#Z*y)>r   z A WebSocket connection. Nr   c                  d| _         t        | j                  j                        | _        || _        t        j                         | _        || _	        d| _
        g | _        || _        |	| _        d| _        |j                  r.|J |J t!        ||t#        |xs d      |xs g       | _        nd| _        || _        d| _        d| _        d| _        d| _        d| _        t        j2                  t4        t6        t8        f      |      \  | _        | _        t?               | _         tC        tD                  | _#        t        jH                         | _%        t        jH                         | _&        t        jH                         | _'        y)aC  
        Constructor.

        Generally speaking, users are discouraged from directly instantiating a
        ``WebSocketConnection`` and should instead use one of the convenience
        functions in this module, e.g. ``open_websocket()`` or
        ``serve_websocket()``. This class has some tricky internal logic and
        timing that depends on whether it is an instance of a client connection
        or a server connection. The convenience functions handle this complexity
        for you.

        :param SocketStream stream:
        :param ws_connection wsproto.WSConnection:
        :param str host: The hostname to send in the HTTP request headers. Only
            used for client connections.
        :param str path: The URL path for this connection.
        :param list client_subprotocols: A list of desired subprotocols. Only
            used for client connections.
        :param list[tuple[bytes,bytes]] client_extra_headers: Extra headers to
            send with the connection request. Only used for client connections.
        :param int message_queue_size: The maximum number of messages that will be
            buffered in the library's internal message queue.
        :param int max_message_size: The maximum message size as measured by
            ``len()``. If a message is received that is larger than this size,
            then the connection is closed with code 1009 (Message Too Big).
        :param Optional[int] receive_buffer_size: The buffer size we use to
            receive messages internally. None to let trio choose. Defaults
            to 4 KiB.
        Nr   Tr@   )r|   r2  ri   rj   rA   )(_close_reasonnextr   CONNECTION_ID_id_streamr*   StrictFIFOLock_stream_lock_wsproto_message_size_message_parts_max_message_size_receive_buffer_size_reader_runningclientr   list_initial_request_path_subprotocol_handshake_headers_reject_status_reject_headers_reject_bodyopen_memory_channelr   bytesr   _send_channel_recv_channelr   _pingsr!  r   _connection_proposalr$  r   _close_handshake#_for_testing_peer_closed_connection)
rS   r   ws_connectionr|   r   r   r   rk   rl   rm   s
             rB   rT   zWebSocketConnection.__init__  sf   Z 59445 //1%79!13F!#####7>DQU!"5";<28b8:D! %)D!
+/CE@B151I1I%*2

2.D. 7Bm FLL\E]E_!  $zz| !%

 48::<0rA   c                    | j                   S )z
        (Read-only) The reason why the connection was or is being closed,
        else ``None``.

        :rtype: Optional[CloseReason]
        )rW  rR   s    rB   closedzWebSocketConnection.closed0  s     !!!rA   c                .    | j                   j                  S )z( (Read-only) Is this a client instance? r^  rd  rR   s    rB   	is_clientzWebSocketConnection.is_client:  s     }}###rA   c                0    | j                   j                   S )z( (Read-only) Is this a server instance? ry  rR   s    rB   	is_serverzWebSocketConnection.is_server?  s     ==''''rA   c                0    t        | j                  d      S )zX
        The local endpoint of the connection.

        :rtype: Endpoint or str
        Tr7  rT  r[  rR   s    rB   r7  zWebSocketConnection.localD  s     $DLL==rA   c                0    t        | j                  d      S )zY
        The remote endpoint of the connection.

        :rtype: Endpoint or str
        Fr~  r  rR   s    rB   r9  zWebSocketConnection.remoteM  s     $DLL>>rA   c                    | j                   S )z
        The requested URL path. For clients, this is set when the connection is
        instantiated. For servers, it is set after the handshake completes.

        :rtype: str or None
        )rg  rR   s    rB   r   zWebSocketConnection.pathV  s     zzrA   c                    | j                   S )z
        (Read-only) The negotiated subprotocol, or ``None`` if there is no
        subprotocol.

        This is only valid after the opening handshake is complete.

        :rtype: str or None
        )rh  rR   s    rB   r;  zWebSocketConnection.subprotocol`  s        rA   c                    | j                   S )z
        The HTTP headers that were sent by the remote during the handshake,
        stored as 2-tuples containing key/value pairs. Header keys are always
        lower case.

        :rtype: tuple[tuple[str,str]]
        )ri  rR   s    rB   handshake_headersz%WebSocketConnection.handshake_headersl  s     &&&rA   c                   K   t               5  | j                  ||       d{    ddd       y7 # 1 sw Y   yxY ww)a7  
        Close the WebSocket connection.

        This sends a closing frame and suspends until the connection is closed.
        After calling this method, any further I/O on this WebSocket (such as
        ``get_message()`` or ``send_message()``) will raise
        ``ConnectionClosed``.

        This method is idempotent: it may be called multiple times on the same
        connection without any errors.

        :param int code: A 4-digit code number indicating the type of closure.
        :param str reason: An optional string describing the closure.
        N)rM   _acloser  s      rB   r   zWebSocketConnection.aclosew  s?      )* 	-,,tV,,,	- 	-,	- 	-s    ?313	?3<?c                  K   | j                   ry 	 | j                  j                  t        j                  k(  r6t        dd       | _         | j                  t        ||             d {    nP| j                  j                  t        j                  t        j                  fv r| j                  j                          | j                  j                          d {    | j                  j                          d {    | j!                          d {    y 7 7 A7 !# t        $ r Y *w xY w7 # | j!                          d {  7   w xY ww)Nr	  r  r   )rW  r^  stater   OPENr  _sendr   
CONNECTING	REJECTINGrs  r'  rp  r   r   r   _close_streamr  s      rB   r  zWebSocketConnection._aclose  s     	'}}""o&:&:: &1t%<"jjd6!JKKK$$)C)C#--)/ /%%))+ $$++---'',,... $$&&& L .. 		 '$$$&&&s   EAD! (D)A2D! D!D! =D>D! ED0ED! D! D! !	D-*D2 ,D--D2 0E2EE	EEc                   K   	 | j                   j                          d{   }|S 7 # t        j                  t        j                  f$ r t        | j                        dw xY ww)a  
        Receive the next WebSocket message.

        If no message is available immediately, then this function blocks until
        a message is ready.

        If the remote endpoint closes the connection, then the caller can still
        get messages sent prior to closing. Once all pending messages have been
        retrieved, additional calls to this method will raise
        ``ConnectionClosed``. If the local endpoint closes the connection, then
        pending messages are discarded and calls to this method will immediately
        raise ``ConnectionClosed``.

        :rtype: str or bytes
        :raises ConnectionClosed: if the connection is closed.
        N)rp  receiver*   ClosedResourceErrorEndOfChannelr   rW  )rS   messages     rB   get_messagezWebSocketConnection.get_message  sc     "	A ..6688G  9(($*;*;< 	A"4#5#56D@	As%   A'* (* A'* :A$$A'c                  K   | j                   rt        | j                         || j                  v rt        d|d      |)t	        j
                  dt        j                  d            }t        j                         }|| j                  |<   | j                  t        |             d{    |j                          d{    y7 7 w)aA  
        Send WebSocket ping to remote endpoint and wait for a correspoding pong.

        Each in-flight ping must include a unique payload. This function sends
        the ping and then waits for a corresponding pong from the remote
        endpoint.

        *Note: If the remote endpoint recieves multiple pings, it is allowed to
        send a single pong. Therefore, the order of calls to ``ping()`` is
        tracked, and a pong will wake up its corresponding ping as well as all
        previous in-flight pings.*

        :param payload: The payload to send. If ``None`` then a random 32-bit
            payload is created.
        :type payload: bytes or None
        :raises ConnectionClosed: if connection is closed.
        :raises ValueError: if ``payload`` is identical to another in-flight
            ping.
        zPayload value z is already in flight.Nz!I    payload)rW  r   rq  r   structpackrandomgetrandbitsr*   r$  r  r   r   )rS   r  r/  s      rB   pingzWebSocketConnection.ping  s     ( "4#5#566dkk!~g[8NOPP?kk$(:(:2(>?G

$Gjjg.///jjl 	0s$   B+C-C.CCCCc                   K   | j                   rt        | j                         | j                  t        |xs d             d{    y7 w)z
        Send an unsolicted pong.

        :param payload: The pong's payload. If ``None``, then no payload is
            sent.
        :type payload: bytes or None
        :raises ConnectionClosed: if connection is closed
        rA   r  N)rW  r   r  r   )rS   r  s     rB   pongzWebSocketConnection.pong  s=      "4#5#566jjgn5666   AAAAc                  K   | j                   rt        | j                         t        |t              rt	        |      }n(t        |t
              rt        |      }nt        d      | j                  |       d{    y7 w)z
        Send a WebSocket message.

        :param message: The message to send.
        :type message: str or bytes
        :raises ConnectionClosed: if connection is closed, or being closed
        datazmessage must be str or bytesN)	rW  r   rG   r   r   rn  r   r   r  )rS   r  r/  s      rB   send_messagez WebSocketConnection.send_message  sh      "4#5#566gs#W-E' g.E;<<jjs   A;B=B>Bc                D    | j                   rdnd}| d| j                   S )z Connection ID and type. rd  r   -)rz  rZ  )rS   type_s     rB   __str__zWebSocketConnection.__str__  s$     NN$(($$rA   c                   K   || _         |j                  | _        | j                  t	        | j                   |             d{    | j
                  j                          y7 w)ah  
        Accept the handshake.

        This method is only applicable to server-side connections.

        :param wsproto.events.Request request:
        :param subprotocol:
        :type subprotocol: str or None
        :param list[tuple[bytes,bytes]] extra_headers: A list of 2-tuples
            containing key/value pairs to send as HTTP headers.
        r:  N)rh  r2  rg  r  r   r   r'  )rS   r   r;  rj   s       rB   r=  zWebSocketConnection._accept  s[     " (^^
jj)d6G6G') * 	* 	*  "	*s   AA&A$ A&c                  K   |r4|j                  dt        t        |            j                  d      f       t	        ||t        |            }| j                  |       d{    |r%t        |      }| j                  |       d{    t        dd      | _	        | j                  j                          y7 W7 2w)a  
        Reject the handshake.

        :param int status_code: The 3 digit HTTP status code. In order to be
            RFC-compliant, this must not be 101, and should be an appropriate
            code in the range 300-599.
        :param list[tuple[bytes,bytes]] headers: A list of 2-tuples containing
            key/value pairs to send as HTTP headers.
        :param bytes body: An optional response body.
        s   Content-lengthascii)r   r   has_bodyNr  i  zRejected WebSocket handshake)r   r   r   encoder   rg   r  r   r  rW  rs  r'  )rS   r   r   r  reject_connreject_bodys         rB   r@  zWebSocketConnection._reject  s       NN-s3t9~/D/DW/MNO&;$Z!jj%%%$$/K**[)))(/MN!!# 	& *s$   A"C $B<%&C B>1C >C c                |  K   t         j                  j                  }| j                  j                  t
        j                  k(  r/| j                  j                  t        |j                               | j                  | j                  |       d{    d| _        | j                  j                          y7 &w)z
        If a stream is closed outside of this class, e.g. due to network
        conditions or because some other code closed our stream object, then we
        cannot perform the close handshake. We just need to clean up internal
        state.
        )r  NF)r  r  ABNORMAL_CLOSUREr^  r  r   r  sendr   r`   rW  _close_web_socketrc  rs  r'  )rS   close_reasons     rB   _abort_web_socketz%WebSocketConnection._abort_web_socket0  s      $//@@==/"6"66MML4F4FGH%((666$ 	!!#	 7s   BB<B:'B<c                   K   d| _         	 t               5  | j                  j                          d{    ddd       y7 # 1 sw Y   yxY w# t        j
                  $ r Y yw xY ww)z Close the TCP connection. FN)rc  rM   r[  r   r*   BrokenResourceErrorrR   s    rB   r  z!WebSocketConnection._close_streamA  sc     $	,. ,ll))+++, ,+, ,'' 		sZ   A(
A AAAA  A(AAA A(A A%"A($A%%A(c                   K   t        ||      | _        t        | j                        }t        j	                  d| |       | j
                  j                          d{    y7 w)z
        Mark the WebSocket as closed. Close the message channel so that if any
        tasks are suspended in get_message(), they will wake up with a
        ConnectionClosed exception.
        z%s websocket closed %rN)r  rW  r   r5   r   ro  r   )rS   r  r   rJ   s       rB   r  z%WebSocketConnection._close_web_socketK  sP      )v6t112-tS9  '')))s   AA%A#A%c                   K   | j                   st        d      | j                  t        d      | j                  j                          d{   }d| _        |S 7 w)z
        Return a proposal for a WebSocket handshake.

        This method can only be called on server connections and it may only be
        called one time.

        :rtype: WebSocketRequest
        z1This method is only valid for server connections.NzTNo proposal available. Did you call this method multiple times or at the wrong time?)r|  RuntimeErrorrr  r*  )rS   proposals     rB   r   z WebSocketConnection._get_requestV  sc      ~~RSS$$,  8 9 922==??$(! @s   AAAAc                v   K   t        | |      }| j                  J | j                  j                  |       yw)z
        Handle a connection request.

        This method is async even though it never awaits, because the event
        dispatch requires an async function.

        :param event:
        N)r   rr  r(  )rS   r/  r  s      rB   _handle_request_eventz)WebSocketConnection._handle_request_eventh  s7      $D%0((44!!++H5s   79c                   K   |j                   | _        t        |j                        | _        | j
                  j                          yw)zi
        Handle an AcceptConnection event.

        :param wsproto.eventsAcceptConnection event:
        N)r;  rh  r4  rj   ri  r   r'  rS   r/  s     rB   _handle_accept_connection_eventz3WebSocketConnection._handle_accept_connection_eventu  s;      "--"'(;(;"<  "s   AA	c                   K   |j                   | _        t        |j                        | _        |j
                  s"t        | j                  | j                  d      yw)zI
        Handle a RejectConnection event.

        :param event:
        Nr  )r   rj  r4  r   rk  r  r   r  s     rB   _handle_reject_connection_eventz3WebSocketConnection._handle_reject_connection_event  sS      $//$U]]3~~$T%8%8$:N:N  s   AAc                   K   | xj                   |j                  z  c_         |j                  r,t        | j                  | j
                  | j                         yw)zC
        Handle a RejectData event.

        :param event:
        r  N)rl  r  body_finishedr   rj  rk  r  s     rB   _handle_reject_data_eventz-WebSocketConnection._handle_reject_data_event  sQ      	UZZ'$T%8%8$:N:N&&( ( s   AAc                  K   | j                   j                  t        j                  k(  rjt	        |j
                  |j                  xs d      | _        | j                  j                          | j                  |j                                d{    | j                  |j
                  |j                  xs d       d{    | j                  j                          | j                  r| j                          d{    yy7 v7 F7 
w)z]
        Handle a close event.

        :param wsproto.events.CloseConnection event:
        N)r^  r  r   REMOTE_CLOSINGr  r  r   rW  rt  r'  r  responser  rs  r|  r  r  s     rB   _handle_close_connection_eventz2WebSocketConnection._handle_close_connection_event  s      ==/"@"@@ "-UZZ9M!ND4488:**U^^-...$$UZZ1EFFF!!#
 >>$$&&&  /F 's6   BDD1DD=D?D
 DD
Dc                d  K   | xj                   t        |j                        z  c_         | j                  j	                  |j                         | j                   | j
                  kD  r}d| j
                   d}d| _         g | _        t        d|      | _        | j                  t        d|             d{    | j                  j                          d{    d| _        y|j                  rt        |t              r&dj!                  t#        d	| j                              }n%d
j!                  t#        d| j                              }d| _         g | _        	 | j$                  j'                  |       d{    yy7 7 7 
# t(        j*                  t(        j,                  f$ r Y yw xY ww)z
        Handle a message event.

        :param event:
        :type event: wsproto.events.BytesMessage or wsproto.events.TextMessage
        zExceeded maximum message size: z bytesr   i  r  NFrA   zlist[bytes]r   z	list[str])r_  r   r  r`  r   ra  r  rW  r  r   rp  r   rc  message_finishedrG   r   joinr   ro  r  r*   r  r  )rS   r/  errmsgs       rB   _handle_message_eventz)WebSocketConnection._handle_message_event  sm     	c%**o-""5::. 6 663D4J4J3K6RC!"D"$D!,T3!7D**_$sCDDD$$++---#(D ## %.hhtM43F3FGHggd;0C0CDE!"D"$D((--c222 $ E- 3,,d.F.FG  	s[   B5F07F8!F0FBF0F :F;F ?F0F0F #F-*F0,F--F0c                   K   t         j                  d| |j                         | j                  |j	                                d{    y7 w)z
        Handle a PingReceived event.

        Wsproto queues a pong frame automatically, so this handler just needs to
        send it.

        :param wsproto.events.Ping event:
        z
%s ping %rN)r5   r   r  r  r  r  s     rB   _handle_ping_eventz&WebSocketConnection._handle_ping_event  s5      	\47jj)***r  c                R  K   t        |j                        }	 | j                  |   }| j                  rc| j                  j	                  d      \  }}||k7  rdnd}t
        j                  d| ||       |j                          ||k(  ry| j                  rbyy# t        $ r Y yw xY ww)a  
        Handle a PongReceived event.

        When a pong is received, check if we have any ping requests waiting for
        this pong response. If the remote endpoint skipped any earlier pings,
        then we wake up those skipped pings, too.

        This function is async even though it never awaits, because the other
        event handlers are async, too, and event dispatch would be more
        complicated if some handlers were sync.

        :param event:
        NFz [skipped]  z%s pong%s%r)rn  r  rq  KeyErrorpopitemr5   r   r'  )rS   r/  r  
ping_eventkeyskippeds         rB   _handle_pong_eventz&WebSocketConnection._handle_pong_event  s      &	W-J
 kk"kk11%8OC'.#~m3GLLgs;NN#~ kk	  	 	s.   B'B A-B'B'	B$!B'#B$$B'c                `  K   t         | j                  t        | j                  t        | j
                  t        | j                  t        | j                  t        | j                  t        | j                  t        | j                  t         | j                  i	}| j"                  r$	 | j%                  | j"                         d{    | j*                  4 d{    | j(                  rZ| j,                  j/                         D ]:  }t1        |      }	 ||   }t2        j5                  d| |        ||       d{    < 	 | j:                  j=                  | j>                         d{   }tI        |      dk(  rVt2        j5                  d|        | j,                  jJ                  tL        jN                  k7  r| jG                          d{    nqt2        j5                  d| tI        |             | j,                  jJ                  tL        jN                  k7  r	 | j,                  jQ                  |       | j(                  rZddd      d{    t2        j5                  d	|        y7 # t&        $ r d| _        Y w xY w7 7 N# t6        $ r t2        j9                  d| |       Y t&        $ r d| _        Y  w xY w7 [# t@        jB                  t@        jD                  f$ r | jG                          d{  7   Y w xY w7 =# tR        jT                  jV                  $ rk}t2        j5                  d| |       |jX                  r$| j%                  |jX                         d{  7   | j[                          d{  7   Y d}~Zd}~ww xY w7 I# 1 d{  7  sw Y   ZxY ww)
zA A background task that reads network data and generates events. NFz%s received event: %sz$%s received unknown event type: "%s"r   z*%s received zero bytes (connection closed)z%s received %d bytesz%s remote protocol error: %sz%s reader task finished).r   r  r   r  r   r  r   r  r   r  r   r  r   r  r   r  r   rf  r  r   rc  ro  r^  eventstyper5   r   r  warningr[  receive_somerb  r*   r  r  r  r   r  r   CLOSEDreceive_datawsproto	utilitiesRemoteProtocolError
event_hintr  )rS   handlersr/  
event_typer   r  r  s          rB   r   z WebSocketConnection._reader_task  s     dBB$44T@@$))$))dBB66T//33

   -jj!6!6777 %% *	3 *	3&&!]]113 E!%eJ"*:"6%<d&(
 &en,,$!%!:!:4;T;T!UUD t9>LL!M }}**o.D.DD"446663T3t9E==&&/*@*@@32248I &&*	3 *	3X 	.5a 8# -',$-*	3 -# ('Mt&(+ /4, V00$2J2JK 00222 7 #,,@@ 3%CT3O>>"&**S^^"<<<"00222	3M*	3 *	3 *	3 *	3sS  BN."I+  I(I+ N.JN.6N'J7J8J<N?(K'K(K,AN
LANL
3NN.NN.(I+ +I?;N.>I??N.J J?(N+J?:N>J??NK6L;K><LNLN
N'AN(M+)NNNNNNN.N+N!N+&N.c                  K   | j                   j                  |      }| j                  4 d{    t        j	                  d| t        |             	 | j                  j                  |       d{    ddd      d{    y7 Y7 # t        j                  t        j                  f$ r> | j                          d{  7   | j                  J t        | j                        dw xY w7 m# 1 d{  7  sw Y   yxY ww)a  
        Send an event to the remote WebSocket.

        The reader task and one or more writers might try to send messages at
        the same time, so this method uses an internal lock to serialize
        requests to send data.

        :param wsproto.events.Event event:
        Nz%s sending %d bytes)r^  r  r]  r5   r   r   r[  send_allr*   r  r  r  rW  r   )rS   r/  r  s      rB   r  zWebSocketConnection._send<  s      }}!!%($$ 	E 	ELL.c$i@Ell++D111	E 	E 	E 2,,d.F.FG E,,...))55&t'9'9:DE		E 	E 	E 	Est   ,DBD!C2B2B
3B7DC0D
B6C-C*C--C20D2D8C;9D D)r   trio.abc.Streamru  zwsproto.WSConnectionr|   r  r   r  r   Iterable[str] | Noner   rF  rk   r  rl   r  rm   Union[None, int]re   rf   )re   r   )re   rg   rD  r  )re   r  )r	  Nr  )re   str | bytesrE   )r  r  re   rf   )r  r  re   rf   r   )r   r   r;  r  rj   rC  re   rf   )r   r  r   rC  r  rn  re   rf   rd   )re   r   )r/  rB  re   rf   )r/  zwsproto.events.AcceptConnectionre   rf   )r/  zwsproto.events.RejectConnectionre   rf   )r/  zwsproto.events.RejectDatare   rf   )r/  zwsproto.events.CloseConnectionre   rf   )r/  z8wsproto.events.BytesMessage | wsproto.events.TextMessagere   rf   )r/  zwsproto.events.Pingre   rf   )r/  zwsproto.events.Pongre   rf   )r/  zwsproto.events.Eventre   rf   )+r<   r=   r>   r?   	itertoolscountrY  r2   r3   r4   rT   r  rw  rz  r|  r7  r9  r   r;  r  r   r  r  r  r  r  r  r=  r@  r  r  r  r   r  r  r  r  r  r  r  r  r   r  r@   rA   rB   r   r     s   ##IOO%M  48AE"4 00=T@T@ ,T@
 T@ T@ 2T@ ?T@  T@ T@ .T@ 
T@l " " $ $ ( ( > > ? ?   	! 	! ' '-$'4.>7 &%
##  # 1	#
 
#.$$ +$ 	$
 
$6$"	*$6#
	('*#G# 
#J
+:A6FErA   c                  2    e Zd ZdZddZedd       ZddZy)rN  z# Represents a connection endpoint. c                @    t        |      | _        || _        || _        y rE   )r   addressr}   rP  )rS   r  r}   rP  s       rB   rT   zEndpoint.__init__S  s    !'*	rA   c                D   | j                   rdnd}| j                  dk(  r| j                   r| j                  dk(  r| j                   rd}ndt        | j                        z   }| j                  j                  dk(  r| d| j                   | S | d	| j                   d
| S )zT Return a URL representation of a TCP endpoint, e.g.
        ``ws://127.0.0.1:80``. r   r   r   r   r   r      z://z://[])rP  r}   r   r  r   )rS   r   port_strs      rB   r   zEndpoint.url[  s     ++4IIODKKIIHS^+H<<1$XSxj99dll^1XJ77rA   c                V    d| j                    d| j                   d| j                   dS )z! Return endpoint info as string. zEndpoint(address="z", port=z	, is_ssl=))r  r}   rP  rR   s    rB   r   zEndpoint.__repr__i  s*    #DLL>$))Idkk]Z[\\rA   N)r  z	str | intr}   r  rP  rg   re   rf   r   )r<   r=   r>   r?   rT   r  r   r   r@   rA   rB   rN  rN  Q  s$    - 8 8]rA   rN  c                      e Zd ZdZdeeeeed	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d
dZe	dd       Z
e	dd       Zej                  d	 	 	 ddZdd	Zy)r   z
    WebSocket server.

    The server class handles incoming connections on one or more ``Listener``
    objects. For each incoming connection, it creates a ``WebSocketConnection``
    instance and starts some background tasks,
    Nr   c                   t        |      dk(  rt        d      || _        || _        || _        || _        || _        || _        || _        || _	        y)a  
        Constructor.

        Note that if ``host`` is ``None`` and ``port`` is zero, then you may get
        multiple listeners that have _different port numbers!_ See the
        ``listeners`` property.

        :param handler: the async function called with a :class:`WebSocketRequest`
            on each new connection.  The call will be made
            once the HTTP handshake completes, which notably implies that the
            connection's `path` property will be valid.
        :param listeners: The WebSocket will be served on each of the listeners.
        :param handler_nursery: An optional nursery to spawn connection tasks
            inside of. If ``None``, then a new nursery will be created
            internally.
        :param Optional[int] receive_buffer_size: The buffer size we use to
            receive messages internally. None to let trio choose. Defaults
            to 4 KiB.
        :param float connect_timeout: The number of seconds to wait for a client
            to finish connection handshake before timing out.
        :param float disconnect_timeout: The number of seconds to wait for a client
            to finish the closing handshake before timing out.
        r   z)Listeners must contain at least one item.N)
r   r   _handler_handler_nursery
_listeners_message_queue_sizera  rb  _connect_timeout_disconnect_timeout)	rS   r   r   r   rk   rl   rm   rn   ro   s	            rB   rT   zWebSocketServer.__init__w  s[    F y>QHII /##5 !1$7! /#5 rA   c                    t        | j                        dkD  rt        d      | j                  d   }	 |j                  S # t
        $ r t        dt        |             dw xY w)a  Returns the requested or kernel-assigned port number.

        In the case of kernel-assigned port (requested with port=0 in the
        constructor), the assigned port will be reflected after calling
        starting the `listen` task.  (Technically, once listen reaches the
        "started" state.)

        This property only works if you have a single listener, and that
        listener must be socket-based.
        r1   z=Cannot get port because this server has more than 1 listener.r   z"This socket does not have a port: N)r   r  r  r   r}   AttributeErrorrO  )rS   listeners     rB   r}   zWebSocketServer.port  sq     t!#  ) * *>>!$	`==  	`!CDNCSTU[__	`s   A   "A"c                   g }| j                   D ]  }d\  }}t        |t        j                        r|j                  }nPt        |t        j
                        r6|j                  }t        |t        j                        sJ |j                  }d}|r3|j                         }|j                  t        |d   |d   |             |j                  t        |              |S )a   
        Return a list of listener metadata. Each TCP listener is represented as
        an ``Endpoint`` instance. Other listener types are represented by their
        ``repr()``.

        :returns: Listeners
        :rtype list[Endpoint or str]:
        rQ   Tr   r1   )r  rG   r*   SocketListenerrI  SSLListenertransport_listenerrL  r   rN  rO  )rS   r   r  rI  rP  internal_listenersocknames          rB   r   zWebSocketServer.listeners  s     +-	 	1H(NFF(D$7$78!Hd&6&67$,$?$?!!"3T5H5HII*11!--/  (1+x{F!KL  h0	1 rA   r   c               J  K   t        j                         4 d{   }t        t         j                  | j                  t        | j                        | j                        }|j                  |       d{    t        j                  ddj                  | j                  D cg c]  }t        |       c}             |j                  |        t        j                          d{    ddd      d{    y7 7 c c}w 7 7 # 1 d{  7  sw Y   yxY ww)u  
        Start serving incoming connections requests.

        This method supports the Trio nursery start protocol: ``server = await
        nursery.start(server.run, …)``. It will block until the server is
        accepting connections and then return a :class:`WebSocketServer` object.

        :param task_status: Part of the Trio nursery start protocol.
        :returns: This method never returns unless cancelled.
        N)r   zListening on %s,)r*   r   r   serve_listeners_handle_connectionre  r  r  startr5   r   r  r   r   startedsleep_forever)rS   r   rz   r  ls        rB   r   zWebSocketServer.run  s      $$& 	' 	''%d&:&:''doo)> $ 5 57O --000LL*$..9Q#a&9:<%$$&&&	' 	' 	' 19&	' 	' 	' 	'su   D#DD#AD8D9-D&D83D+D
,D0D#;D<D#DDD#D DD D#c           	       K   t        j                         4 d{   }t        |t        t        j
                        | j                  | j                  | j                        }|j                  |j                         t        j                  | j                        5 }|j                          d{   }ddd       j                  rD|j                  j!                          |j#                          d{    	 ddd      d{    y	 | j%                         d{    t        j                  | j&                        5  |j#                          d{    ddd       ddd      d{    y7 `7 # 1 sw Y   xY w7 7 7 j7 4# 1 sw Y   3xY w# t        j                  | j&                        5  |j#                          d{  7   ddd       w # 1 sw Y   w xY wxY w7 |# 1 d{  7  sw Y   yxY ww)z
        Handle an incoming connection by spawning a connection background task
        and a handler task inside a new nursery.

        :param stream:
        :type stream: trio.abc.Stream
        Nr   )r*   r   r   r   r   r   r  ra  rb  r   r   move_on_afterr  r   cancelled_caughtcancel_scopecancelr   r  r   )rS   r   rz   r   connect_scoper   s         rB   r  z"WebSocketServer._handle_connection  s     $$& 	. 	.',V^223#'#;#;!%!7!7$($=$=	?J
 z667##D$9$9: :m * 7 7 99:--$$++-mmo%%	. 	. 	..mmG,,,''(@(@A . %++---.!	. 	. 	. :: : &	. -
 .. .T''(@(@A . %++---. . .!	. 	. 	. 	.s  H	E;H	B G4F 3E>4F 8AG49F:G4?H	
FH	F %F&F *G4	FFF"G4*H	5G26H	>F  F		G4H	F FF	G4  G/ G#	GG#		G/#G,(G//G42H	4H:G=;HH	)r   -Callable[[WebSocketRequest], Awaitable[None]]r   zCSequence[trio.SSLListener[trio.SocketStream] | trio.SocketListener]r   trio.Nursery | Nonerk   r  rl   r  rm   r  rn   floatro   r  re   rf   r  )re   zlist[Endpoint | str])r    trio.TaskStatus[WebSocketServer]re   r   )r   r  re   rf   )r<   r=   r>   r?   r2   r3   r4   r0   rT   r  r}   r   r*   TASK_STATUS_IGNOREDr   r  r@   rA   rB   r   r   n  s     04"4 00=!-$0,6>,6 W,6
 -,6  ,6 ,6 .,6 ,6 ",6 
,6\ ` `(  B 9=8P8P' 6' 
	'2.rA   r   )rJ   r7   re   zE | None)r|   r   r}   r  r~   r   rs   zUnion[bool, ssl.SSLContext]ri   zOptional[Iterable[str]]rj   z#Optional[list[tuple[bytes, bytes]]]rk   r  rl   r  rm   r  rn   r  ro   r  re   z)AsyncGenerator[WebSocketConnection, None])rz   r   r|   r   r}   r  r~   r   rs   zbool | ssl.SSLContextri   r  rj   rF  rk   r  rl   r  rm   r  re   r   rE   )r   r   r   ssl.SSLContext | Noneri   r  rj   rF  rk   r  rl   r  rn   r  ro   r  rm   r  re   z0AbstractAsyncContextManager[WebSocketConnection])rz   r   r   r   r   r  ri   r  rj   rF  rk   r  rl   r  rm   r  re   r   )r   r   r   r  re   z+tuple[str, int, str, ssl.SSLContext | bool])rz   r   r   z5trio.SocketStream | trio.SSLStream[trio.SocketStream]r|   r   r~   r   ri   r  rj   rF  rk   r  rl   r  rm   r  re   r   )rz   r   r   r  rk   r  rl   r  rm   r  re   r   )r   r  r|   zstr | bytes | Noner}   r  r   r  r   r  rk   r  rl   r  rm   r  rn   r  ro   r  r   r  re   r   )r   r  r7  rg   re   rE  )q
__future__r   rV   collectionsr   
contextlibr   r   	functoolsr   	ipaddressr   r  loggingr  r   r  urllib.parser   typingr	   r
   r   r   r   r   r   r   r   importlib.metadatar   r   r*   trio.abcr  r   r   wsproto.connectionr   wsproto.frame_protocolframe_protocolr  wsproto.eventsr   r   r   r   r   r   r   r   r   wsproto.utilitiesversion_infoexceptiongroupr!   typesr"   typing_extensionsr#   collections.abcr$   r%   r&   r'   r(   r)   r4  mapr  splitr.   __annotations__r\   r   r0   r2   r3   r4   	getLoggerr5   r6   r   r7   	Exceptionr:   rK   rM   r   ru   r   r   r   r   r   r  r   ry   rw   r   r   r   r  objectr  r!  r   rT  abcAsyncResourcer   rN  r   r@   rA   rB   <module>r:     s   " 
 # G       
   ^ ^ ^ &    0 . -
 
 
 g1#'bb#CWV_-B-B3-G-K$LMPWW e W??-e  E ! % !"u "!!!"23 3CLC}% <!* !*H  -18<0,,9) ,C
C
C C
 )C *C 6C C C *C C C /C CZ *.6:0,,9LL
L L 	L #L 'L 4L L L *L Lb *.3P *.6:0,) ,,93P	3P&3P '	3P
 43P 3P 3P 3P 3P *3P 63Pr *.-1
 *.6:0,,9-1-1	-1 '-1
 '-1 4-1 -1 -1 *-1 -1`)3	)3&)3 1)3d *.6:0,,911A1 1 	1 '1 41 1 1 *1 1n 1,,9""" " 	"
 *" "X ,00,,9) ,484L4LM.:M.
M. M. '	M. )M. M. M. *M. M. M. 2M. M.`Y G GL> L;y ;(L L<)M )MX he WQZ :lI lI^  	:y	E$((00 y	Ex] ]:_. _.rA   