
    Vhv@                    f   d Z ddlmZ ddlZddlmZmZ ddlmZ ddlm	Z	m
Z
mZmZ ddlmZ ddlmZ dd	lmZmZmZ dd
lmZ ddlmZmZmZmZmZmZmZmZm Z!m"Z" ddl#m$Z$ ddl%m&Z& ddl'm(Z( ddl)m*Z*m+Z+m,Z,m-Z-m.Z. ddl/m0Z1 ddl2m3Z3 ddl4m5Z5 ddl6m7Z7 ddl8m9Z9m:Z:m;Z;m<Z< ddl=m>Z> ddl?m@Z@mAZA ddlBmCZC ddlDmEZEm Z   G d dej                        ZGe G d deH             ZI G d dej                        ZJ edd eJ!      ZKe	eeef   e.gdf   ZL e3       ZM G d" d#ej                  eK         ZN G d$ d%ej                  eK         ZO ed &       G d' d(             ZPed8d)       ZQ ee+      e G d* d+e
eK                       ZReReJ   ZSeQj                  d9d,       ZUeQj                  d:d-       ZVeQj                  d;d.       ZWeQj                  d<d/       ZXeQj                  d=d0       ZYeQj                  d>d1       ZZeQj                  d?d2       Z[eQj                  d@d3       Z\dAd4Z] G d5 d6eC      Z^dBd7Z_y)CzD
Private implementation module for public L{twisted.web.websocket}.
    )annotationsN)	dataclassfield)singledispatch)CallableGenericTypeVarUnion)implementer)URL)
ConnectionConnectionTypeWSConnection)ConnectionState)
AcceptConnectionBytesMessageCloseConnectionEventPingPongRejectConnection
RejectDataRequestTextMessage)H11Handshake)RemoteProtocolError)Deferred)	IConsumer	IProtocolIPushProducerIReactorTCP
ITransport)Factory)Logger)Failure)BAD_REQUEST)URIBrowserLikePolicyForHTTPSResponse_StandardEndpointFactory)Headers)IAgentEndpointFactoryIPolicyForHTTPS)Resource)NOT_DONE_YETr   c                  D    e Zd ZdZd	dZd
dZdddZdddZddZddZ	y)WebSocketTransportz9
    The transport that can send websocket messages.
    c                     y)z&
        Send a text message.
        N )selftexts     K/home/dcms/DCMS/lib/python3.12/site-packages/twisted/web/_websocket_impl.pysendTextMessagez"WebSocketTransport.sendTextMessageA           c                     y)z'
        Send a bytes message.
        Nr3   r4   datas     r6   sendBytesMessagez#WebSocketTransport.sendBytesMessageF   r8   r9   c                     y)z0
        Drop the websocket connection.
        Nr3   )r4   codes     r6   loseConnectionz!WebSocketTransport.loseConnectionK   r8   r9   c                     y)a  
        Send a websocket Ping request to measure latency.

        @note: Per U{Mozilla's documentation
            <https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers#pings_and_pongs_the_heartbeat_of_websockets>},
            multiple 'ping' requests may be coalesced into a single 'pong', and
            unsolicited 'pong' requests must be ignored, so we do not return a
            L{deferred <twisted.internet.defer.Deferred>} here; pongs are
            delivered separately.
        Nr3   r4   payloads     r6   pingzWebSocketTransport.pingP   r8   r9   c                     y)zF
        Attach the given L{IPushProducer} to this transport.
        Nr3   r4   producers     r6   attachProducerz!WebSocketTransport.attachProducer\   r8   r9   c                     y)zT
        Detach a previously attached L{IPushProducer} from this transport.
        Nr3   r4   s    r6   detachProducerz!WebSocketTransport.detachProducera   r8   r9   Nr5   strreturnNoner<   bytesrN   rO   )  )r?   intrN   rO   r9   rC   rQ   rN   rO   rG   r    rN   rO   rN   rO   )
__name__
__module____qualname____doc__r7   r=   r@   rD   rH   rK   r3   r9   r6   r1   r1   <   s%    




r9   r1   c                      e Zd ZU dZded<   y)ConnectionRejectedz
    A websocket connection was rejected by an HTTP response.

    @ivar response: The HTTP response that describes the rejection.
    r)   responseN)rX   rY   rZ   r[   __annotations__r3   r9   r6   r]   r]   g   s     r9   r]   c                  @    e Zd ZdZd	dZd
dZddZddZddZddZ	y)WebSocketProtocolac  
    An object that conforms to L{WebSocketProtocol} can receive all the events
    from a websocket connection.

    @note: While this is I{sort of} like a L{byte-stream protocol
        <twisted.internet.interfaces.IProtocol>}, the interface is distinct in
        a few ways; in particular, we have discrete C{negotiationStarted} and
        C{negotiationFinished} methods, representing those events in the
        websocket handshaking process, and no C{connectionMade}; similarly,
        since websockets can natively support both text and bytes messages,
        rather than fragmentable segments of a byte stream, we have
        C{textMessageReceived} and C{bytesMessageReceived} but no
        C{dataReceived}.  Finally, this is a L{typing.Protocol} and not a
        L{zope.interface.Interface}, since it does not predate the L{typing}
        module.
    c                     y)z
        An underlying transport (e.g.: a TCP connection) has been established;
        negotiation of the websocket transport has begun.
        Nr3   r4   	transports     r6   negotiationStartedz$WebSocketProtocol.negotiationStarted   r8   r9   c                     y)zn
        Negotiation is complete: a bidirectional websocket channel is now fully
        established.
        Nr3   rJ   s    r6   negotiationFinishedz%WebSocketProtocol.negotiationFinished   r8   r9   c                     y)a  
        A Pong message was received.

        @note: Per U{the standard
            <https://www.rfc-editor.org/rfc/rfc6455#section-5.5.2>}::

                A Pong frame sent in response to a Ping frame must have identical
                "Application data" as found in the message body of the Ping frame
                being replied to.

                If an endpoint receives a Ping frame and has not yet sent Pong
                frame(s) in response to previous Ping frame(s), the endpoint MAY
                elect to send a Pong frame for only the most recently processed
                Ping frame.

            Given that some Pong frames may be dropped, this event should only
            be used in concert with the transport's L{.ping
            <WebSocketTransport.ping>} method for its intended purpose, to
            measure latency and connection durability, not to transport
            application data.
        Nr3   rB   s     r6   pongReceivedzWebSocketProtocol.pongReceived   r8   r9   c                     y)z<
        A text message was received from the peer.
        Nr3   )r4   messages     r6   textMessageReceivedz%WebSocketProtocol.textMessageReceived   r8   r9   c                     y)z=
        A bytes message was received from the peer.
        Nr3   r;   s     r6   bytesMessageReceivedz&WebSocketProtocol.bytesMessageReceived   r8   r9   c                     y)z4
        The websocket connection was lost.
        Nr3   r4   reasons     r6   connectionLostz WebSocketProtocol.connectionLost   r8   r9   N)rd   r1   rN   rO   rW   rU   )rk   rM   rN   rO   rP   rq   r%   rN   rO   )
rX   rY   rZ   r[   re   rg   ri   rl   rn   rr   r3   r9   r6   ra   ra   r   s%    ".

r9   ra   _WSPT)	covariantboundc                      e Zd ZdZddZy)WebSocketServerFactoryz
    A L{WebSocketServerFactory} is a factory for a particular kind of
    L{WebSocketProtocol} that implements server-side websocket listeners via
    L{WebSocketResource}.
    c                     y)a/  
        To conform to L{WebSocketServerFactory}, you must implement a
        C{buildProtocol} method which takes a L{Request
        <twisted.web.server.Request>} and returns a L{WebSocketProtocol}.

        @return: a L{WebSocketProtocol} that will handle the inbound
            connection.
        Nr3   )r4   requests     r6   buildProtocolz$WebSocketServerFactory.buildProtocol   r8   r9   N)rz   r   rN   rt   rX   rY   rZ   r[   r{   r3   r9   r6   rx   rx          r9   rx   c                      e Zd ZdZddZy)WebSocketClientFactoryz
    A L{WebSocketClientFactory} is a factory for a particular kind of
    L{WebSocketProtocol} that implements client-side websocket listeners via
    L{WebSocketClientEndpoint}.
    c                     y)a#  
        To conform to L{WebSocketServerFactory}, you must implement a
        C{buildProtocol} method which takes a string representing an URL and
        returns a L{WebSocketProtocol}.

        @return: a L{WebSocketProtocol} that will handle the outgoing
            connection.
        Nr3   )r4   urls     r6   r{   z$WebSocketClientFactory.buildProtocol   r8   r9   N)r   rM   rN   rt   r|   r3   r9   r6   r   r      r}   r9   r   )frozenc                  l    e Zd ZU dZded<   	 ded<   	 e e       ddf	 	 	 	 	 	 	 	 	 	 	 d	d       Zd
dZy)WebSocketClientEndpointz
    A L{WebSocketClientEndpoint} describes an URL to connect to and a way of
    connecting to that URL, that can connect a L{WebSocketClientFactory} to
    that URL.
    r,   endpointFactoryrM   r   Nc                6    t        ||||      }t        ||      S )a)  
        Construct a L{WebSocketClientEndpoint} from a reactor and a URL.

        @param reactor: The reactor to use for the TCP connection.

        @param url: a string describing an URL where a websocket server lives.

        @param tlsPolicy: The TLS policy to use for HTTPS connections.

        @param connectTimeout: The number of seconds for the TCP-level
            connection timeout.

        @param bindAddress: The bind address to use for the TCP client
            connections.

        @return: the newly constructed endpoint.
        )r*   r   )clsreactorr   	tlsPolicyconnectTimeoutbindAddressr   s          r6   newzWebSocketClientEndpoint.new   s&    4 3Y
 '<<r9   c                <   K    j                   j                  t        j                   j                  j                  d                  }d fd|j                  t        j                   fd             d{   }|j                   d{   S 7 7 w)ae  
        Make an outgoing connection to this L{WebSocketClientEndpoint}'s HTTPS
        connection.

        @param protocolFactory: The constructor for the protocol.

        @return: A coroutine (that yields L{Deferred}s) that completes with the
            connected L{WebSocketProtocol} once the websocket connection is
            established.
        zutf-8c                    t        j                  j                        }t        |j	                  ddd             }|j                  | j                  t        |j                  |                   y )N )schemehostport)	r   fromTextr   rM   replacewritesend	WSRequestr   )wscthtargetr4   s       r6   clientBootstrapz8WebSocketClientEndpoint.connect.<locals>.clientBootstrap   sN    TXX&A"2DABFGGCHHYqvvv678r9   c                 ~    t        t        t        j                         j	                  j
                              S N)_WebSocketWireProtocolr   r   CLIENTr{   r   )r   protocolFactoryr4   s   r6   <lambda>z1WebSocketClientEndpoint.connect.<locals>.<lambda>'  s0    . !6!67##11$((; r9   Nr   WSConnection | Connectionr   r"   rN   rO   )
r   endpointForURIr'   	fromBytesr   encodeconnectProtocolFactoryforProtocol_done)r4   r   endpoint	connectedr   s   ``  @r6   r   zWebSocketClientEndpoint.connect  s      ''66MM$((//'23
	9
 9A8H8H''9
 3
	 __$$3
 %s$   A:B?B BBBB)r   r!   r   rM   r   r-   r   z
int | Noner   zbytes | NonerN   r   )r   zWebSocketClientFactory[_WSP]rN   rt   )	rX   rY   rZ   r[   r_   classmethodr(   r   r   r3   r9   r6   r   r      s     +* 
H 
 &?%@%)$(== = #	=
 #= "= 
!= =<%r9   r   c                     y)z,
    Handle a websocket protocol event.
    Nr3   eventprotos     r6   _handleEventr   1  r8   r9   c                      e Zd ZU ded<   ded<   ded<    ed      Zd	ed
<    ed      Zded<   dZded<   ddZddZ	ddZ
ddZd dZddZd!d"dZd#d$dZd%dZddZddZddZy)&r   r   _wsconn
_Bootstrap
_bootstraprt   _wspF)initr"   rd   zDeferred[_WSP]r   NzResponse | None_rejectResponsec                P    || _         t               | _        | j                          y r   )rd   r   r   connectionMaderc   s     r6   makeConnectionz%_WebSocketWireProtocol.makeConnectionG  s    "Z
r9   c                    | j                   j                  |        | j                  | j                  | j                         y r   )r   re   r   r   rd   rJ   s    r6   r   z%_WebSocketWireProtocol.connectionMadeL  s*    		$$T*dnn5r9   c                    | j                   j                  |       | j                   j                         D ]  }t        ||         y r   )r   receive_dataeventsr   )r4   r<   r   s      r6   dataReceivedz#_WebSocketWireProtocol.dataReceivedQ  s:    !!$'\\((* 	&E%	&r9   c                    | j                   j                  |       | j                  #| j                  j                  |       d | _        y y r   )r   rr   r   _bodyDataFinishedrp   s     r6   rr   z%_WebSocketWireProtocol.connectionLostV  sA    		  (+  226:#'D  ,r9   c                    | j                   }|J |j                  | j                  j                  t	        |                   y r   )rd   r   r   r   r   )r4   r5   r   s      r6   r7   z&_WebSocketWireProtocol.sendTextMessage]  s5    NN}}	!!+d"345r9   c                    | j                   }|J |j                  | j                  j                  t	        |                   y r   )rd   r   r   r   r   )r4   r<   r   s      r6   r=   z'_WebSocketWireProtocol.sendBytesMessageb  s5    NN}}	!!,t"456r9   c                    | j                   }|J |j                  | j                  j                  t	        |                   y r   )rd   r   r   r   r   )r4   rC   r   s      r6   rD   z_WebSocketWireProtocol.pingg  s4    NN}}	!!$w-01r9   c                    | j                   }|J |j                  | j                  j                  t	        ||                   |j                          y r   )rd   r   r   r   r   r@   )r4   r?   rq   r   s       r6   r@   z%_WebSocketWireProtocol.loseConnectionl  sC    NN}}	!!/$"?@A	r9   c                N    t        | j                        j                  |d       y )NT)r   rd   registerProducerrF   s     r6   rH   z%_WebSocketWireProtocol.attachProducerr  s    $..!228TBr9   c                J    t        | j                        j                          y r   )r   rd   unregisterProducerrJ   s    r6   rK   z%_WebSocketWireProtocol.detachProduceru  s    $..!446r9   c                    | j                   }| ` |j                  | j                         | j                  j                          y r   )r   callbackr   rg   r4   dones     r6   _completeConnectionz*_WebSocketWireProtocol._completeConnectionx  s0    zzJdii 		%%'r9   c                    | j                   J | j                  }| `|j                  t        | j                                y r   )r   r   errbackr]   r   s     r6   _rejectConnectionz(_WebSocketWireProtocol._rejectConnection~  s:    ##///zzJ'(<(<=>r9   )rd   r"   rN   rO   rW   rP   rs   rL   rT   rU   )rR   r   )r?   rS   rq   rM   rN   rO   rV   )rX   rY   rZ   r_   r   rd   r   r   r   r   r   rr   r7   r=   rD   r@   rH   rK   r   r   r3   r9   r6   r   r   8  s~     '&
J "u-Iz- "u-E>-'+O_+
6
&
(6
7
2
C7(?r9   r   c                $    |j                          y r   )r   r   s     r6   _handle_acceptConnectionr     s    	r9   c                    t               }| j                  D ]  \  }}|j                  ||        t        d| j                  d||j
                        |_        |j                          y )Nz1.1r   )r+   headersaddRawHeaderr)   status_coderd   r   r   )r   r   hdrkvs        r6   _handle_rejectConnectionr     s[    
)C 1A$UE,=,=r3XE	r9   c                    |j                   J d       |j                   j                  | j                         | j                  r|j                  j                          y y )Nz7response should never be None when receiving RejectData)r   _bodyDataReceivedr<   body_finishedrd   r@   r   s     r6   _handle_rejectDatar     sX     	)A@A)	++EJJ7&&( r9   c                N    |j                   j                  | j                         y r   )r   rl   r<   r   s     r6   _handle_textMessager     s    	JJ""5::.r9   c                N    |j                   j                  | j                         y r   )r   rn   r<   r   s     r6   _handle_bytesMessager     s    	JJ##EJJ/r9   c                    |j                   j                  |j                  j                  | j	                                      y r   )rd   r   r   r   r^   r   s     r6   _handle_pingr     s*    	OO%--,,U^^-=>?r9   c                N    |j                   j                  | j                         y r   )r   ri   rC   r   s     r6   _handle_pongr     s    	JJEMM*r9   c                &   |j                   J |j                  j                  t        j                  k7  rB|j                   j                  |j                  j                  | j                                      |j                   j                          y r   )	rd   r   stater   CLOSEDr   r   r^   r@   r   s     r6   _handle_closeConnectionr     sb    ??&&&}}o444emm001ABC	OO""$r9   c                R    | j                  t               | j                  dd       y)Nzcontent-typez
text/plains$   websocket protocol negotiation error)setResponseCoder&   	setHeader)rz   s    r6   _negotiationErrorr     s#    K(nl32r9   c                  ,     e Zd ZdZd fdZddZ xZS )WebSocketResourcez
    A L{WebSocketResource} is a L{Resource} that presents a websocket listener.
    You can install it into any twisted web server resource hierarchy.
    c                0    t         |           || _        y)a#  
        Create a L{WebSocketResource} that will respond to incoming connections
        with the given L{WebSocketServerFactory}.

        @param factory: The factory that will be used to respond to inbound
            websocket connections on appropriately formatted GET requests.
        N)super__init__factory)r4   r   	__class__s     r6   r   zWebSocketResource.__init__  s     	r9   c                   t        t        j                        }|j                  j	                         }|D cg c]  \  }}|D ]  }||f  }}}}	 |j                  ||j                         | j                  j                  |      }	|	J d       |j                  t                     }
|j                  }|j                   j"                  }|J d       |J d       t%        |t&        |	      }|j                   j)                  |       |j+                  |
       |	j-                          t.        S c c}}}w # t        $ r-}t        j                  d||       t        |      cY d}~S d}~ww xY w)zv
        This implementation of the C{GET} HTTP method will respond to inbound
        websocket connections.
        z{request} failed with {rpe})rz   rpeNz"connection not accepted by twistedzchannel transport not connectedz"connection not accepted by wsproto)r   r   SERVERrequestHeadersgetAllRawHeadersinitiate_upgrade_connectionpathr   _logerrorr   r   r{   r   r   
connectionchannelrd   r   serverBootstrap_protocolUpgradeForWebsocketsr   rg   r/   )r4   rz   	handshakerawhkeyhvalsvalsimpleHeadersr   wsprottoSendwsconr   	wireProtos                 r6   
render_GETzWebSocketResource.render_GET  sT   
 !!6!67	$$5578;MMuuM$MMM	.11-N ++G4!G#GG! 0 23$$OO%%}???} F"FF *5/6J	55i@	""$# N # 	.JJ4g3JO$W--	.s#   D4D; ;	E1"E,&E1,E1)r   z)WebSocketServerFactory[WebSocketProtocol]rN   rO   )rz   r   rN   zbytes | int)rX   rY   rZ   r[   r   r  __classcell__)r   s   @r6   r   r     s    
	r9   r   c                     y)zC
    The server requires no bootstrapping, so this is a no-op.
    Nr3   )r   r   s     r6   r  r    r8   r9   )r   r   r   AnyWSWPrN   rO   )r   r   r   r  rN   rO   )r   r   r   r  rN   rO   )r   r   r   r  rN   rO   )r   r   r   r  rN   rO   )r   r   r   r  rN   rO   )r   r   r   r  rN   rO   )r   r   r   r  rN   rO   )r   r   r   r  rN   rO   )rz   r   rN   rQ   r   )`r[   
__future__r   typingdataclassesr   r   	functoolsr   r   r   r	   r
   zope.interfacer   	hyperlinkr   wsprotor   r   r   wsproto.connectionr   wsproto.eventsr   r   r   r   r   r   r   r   r   r   r   wsproto.handshaker   wsproto.utilitiesr   twisted.internet.deferr   twisted.internet.interfacesr   r   r    r!   r"   twisted.internet.protocolr#   r   twisted.loggerr$   twisted.python.failurer%   twisted.web._responsesr&   twisted.web.clientr'   r(   r)   r*   twisted.web.http_headersr+   twisted.web.iwebr,   r-   twisted.web.resourcer.   twisted.web.serverr/   Protocolr1   	Exceptionr]   ra   rt   r   r  rx   r   r   r   r   r  registerr   r   r   r   r   r   r   r   r   r   r  r3   r9   r6   <module>r.     ss  
 #  ( $ 4 4 &  < < .   + 1 +  A ! * .  - C ) 4( (V   B BJ v->?u\:56
CTIJ
xV__T2 $V__T2 $ $M% M% M%`   Y
H?WT] H?  H?V !!2
3       ) ) / / 0 0 @ @ + + % %3) )Xr9   