o
    jH                     @   s:  d Z g dZddlmZ ddlmZmZ ddlmZm	Z	m
Z
m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mZ ddlmZ G dd deZG dd deZdZdd Zdd Zd%ddZd&ddZ G dd deZ!ee!G dd deZ"G dd  d e"Z#G d!d" d"e	Z$eee$G d#d$ d$e%Z&dS )'zS
The WebSockets protocol (RFC 6455), provided as a resource which wraps a
factory.
)WebSocketsResourceIWebSocketsProtocolIWebSocketsResourceWebSocketsProtocolWebSocketsProtocolWrapper    )sha1)packunpack)implementer	Interface
providedBydirectlyProvides)log)FlagsFlagConstant)Protocol)	IProtocol)	IResource)NOT_DONE_YETc                   @   s   e Zd ZdZdS )_WSExceptionzQ
    Internal exception for control flow inside the WebSockets frame parser.
    N)__name__
__module____qualname____doc__ r   r   V/var/www/html/LicenciasMiG/venv/lib/python3.10/site-packages/spyne/util/_twisted_ws.pyr      s    r   c                   @   s@   e Zd ZdZedZedZedZedZedZ	edZ
dS )	CONTROLSz#
    Control frame specifiers.
    r            	   
   N)r   r   r   r   r   CONTINUETEXTBINARYCLOSEPINGPONGr   r   r   r   r   &   s    r   z$258EAFA5-E914-47DA-95CA-C5AB0DC85B11c                 C   s   t d| tf  d S )z
    Create an B{accept} response for a given key.

    @type key: C{str}
    @param key: The key to respond to.

    @rtype: C{str}
    @return: An encoded response.
    %s%sbase64)r   _WS_GUIDdigestencodestrip)keyr   r   r   _makeAccept8   s   
r/   c                 C   sN   dd |D }t | } t| D ]\}}tt|||d  A | |< qd| S )a  
    Mask or unmask a buffer of bytes with a masking key.

    @type buf: C{str}
    @param buf: A buffer of bytes.

    @type key: C{str}
    @param key: The masking key. Must be exactly four bytes.

    @rtype: C{str}
    @return: A masked buffer of bytes.
    c                 S   s   g | ]}t |qS r   )ord).0ir   r   r   
<listcomp>S   s    z_mask.<locals>.<listcomp>    )list	enumeratechrr0   join)bufr.   r2   charr   r   r   _maskF   s
   
r<   Nc           	      C   s   t | }|durd}nd}|dkrdt|dB td|f }n|dkr1dt|d	B td
|f }nt||B }|r<d}nd}t||jB }|durRd|t| |f } d||| f }|S )a=  
    Make a frame.

    This function always creates unmasked frames, and attempts to use the
    smallest possible lengths.

    @type buf: C{str}
    @param buf: A buffer of bytes.

    @type opcode: C{CONTROLS}
    @param opcode: Which type of frame to create.

    @rtype: C{str}
    @return: A packed frame.
    N   r   i  r(      >Q}   ~   >Hr   z%s%s%s)lenr8   r   valuer<   )	r:   opcodefinmaskbufferLength
lengthMasklengthheaderframer   r   r   
_makeFrame[   s"   rM   Tc                 c   sF   d}d | }	 t|| dk rnt|| }|d@ r"td| |d@ }|d@ }zt|}W n ty>   td	| w t||d
  }|d@ }|sS|rStd|dM }d}	|dkr|t|| dk rfn||d |d  }td|d }|	d7 }	n"|dkrt|| dk rn~||d |d  }td|d }|	d7 }	|rt|||	  dk rn\|||	 ||	 d  }
|	d7 }	t|||	  |k rnA|||	 ||	 |  }|rt||
}|tj	krt|dkrtd|dd d |dd f}nd}||t
|fV  ||	| 7 }q	t||kr||d g| dd< dS g | dd< dS )z
    Parse frames in a highly compliant manner.

    @param frameBuffer: A buffer of bytes.
    @type frameBuffer: C{list}

    @param needMask: If C{True}, refuse any frame which is not masked.
    @type needMask: C{bool}
    r   r5   Tr   p   zReserved flag in frame (%d)r=      zUnknown opcode %d in framer   zReceived data not maskedr>   rA   r4   rB   r!   r?   r   N)i  zNo reason given)r9   rC   r0   r   r   lookupByValue
ValueErrorr	   r<   r%   bool)frameBufferneedMaskstartpayloadrK   rF   rE   rJ   maskedoffsetr.   datar   r   r   _parseFrames   sl   




$RrZ   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	r   zR
    A protocol which understands the WebSockets interface.

    @since: 13.1
    c                 C      dS )z
        Send a frame.
        Nr   rE   rY   rF   r   r   r   	sendFrame       zIWebSocketsProtocol.sendFramec                 C   r[   )z4
        Callback when a frame is received.
        Nr   r\   r   r   r   frameReceived   r^   z!IWebSocketsProtocol.frameReceivedc                   C   r[   )zC
        Close the connection sending a close frame first.
        Nr   r   r   r   r   loseConnection   r^   z"IWebSocketsProtocol.loseConnectionN)r   r   r   r   r]   r_   r`   r   r   r   r   r      s
    r   c                   @   sH   e Zd ZdZdZdZdd Zdd Zdd	 Zd
d Z	dd Z
dd ZdS )r   z
    @since: 13.1
    FNc                 C   s   t d| j   g | _dS )zH
        Log the new connection and initialize the buffer list.
        zOpening connection with %sN)r   msg	transportgetPeer_bufferselfr   r   r   connectionMade  s   
z!WebSocketsProtocol.connectionMadec                 C   s   t | jD ]C}|\}}}|tjtjtjfv r| ||| q|tjkr8|\}}t	d||f  | j
   dS |tjkrH| j
t|tjd qdS )zX
        Find frames in incoming data and pass them to the underlying protocol.
        zClosing connection: %r (%d)NT)rZ   rd   r   r"   r#   r$   r_   r%   r   ra   rb   r`   r&   writerM   r'   )rf   rL   rE   rY   rF   reasontextr   r   r   rZ     s   



zWebSocketsProtocol._parseFramesc                 C   s   t  )z(
        Callback to implement.
        )NotImplementedError)rf   rE   rY   rF   r   r   r   r_   0  s   z WebSocketsProtocol.frameReceivedc                 C   s   t |||}| j| dS )zA
        Build a frame packet and send it over the wire.
        N)rM   rb   rh   )rf   rE   rY   rF   packetr   r   r   r]   7  s   zWebSocketsProtocol.sendFramec                 C   sB   | j | z|   W dS  ty    t  | j  Y dS w )zI
        Append the data to the buffer list and parse the whole.
        N)rd   appendrZ   r   r   errrb   r`   rf   rY   r   r   r   dataReceived?  s   zWebSocketsProtocol.dataReceivedc                 C   s8   | j stdtjd}| j| d| _ | j  dS dS )aw  
        Close the connection.

        This includes telling the other side we're closing the connection.

        If the other side didn't signal that the connection is being closed,
        then we might not see their last message, but since their last message
        should, according to the spec, be a simple acknowledgement, it
        shouldn't be a problem.
        r5   TN)_disconnectingrM   r   r%   rb   rh   r`   )rf   rL   r   r   r   r`   L  s   z!WebSocketsProtocol.loseConnection)r   r   r   r   rq   rd   rg   rZ   r_   r]   rp   r`   r   r   r   r   r     s    r   c                   @   sV   e Zd ZdZejfddZdd Zdd Zdd	 Z	d
d Z
dd Zdd Zdd ZdS )r   z{
    A protocol wrapper which provides L{IWebSocketsProtocol} by making messages
    as data frames.

    @since: 13.1
    c                 C   s   || _ || _d S N)wrappedProtocoldefaultOpcode)rf   rs   rt   r   r   r   __init__i  s   
z"WebSocketsProtocolWrapper.__init__c                 C   s*   t | t| t| | | j|  dS )z
        Upon connection, provides the transport interface, and forwards ourself
        as the transport to C{self.wrappedProtocol}.
        N)r   r   r   makeConnectionrs   )rf   rb   r   r   r   rv   n  s   z(WebSocketsProtocolWrapper.makeConnectionc                 C   s   t |  g | _dS )z2
        Initialize the list of messages.
        N)r   rg   	_messagesre   r   r   r   rg   x  s   

z(WebSocketsProtocolWrapper.connectionMadec                 C   s   |  | j|d dS )zS
        Write to the websocket protocol, transforming C{data} in a frame.
        TN)r]   rt   ro   r   r   r   rh     s   zWebSocketsProtocolWrapper.writec                 C   s   |D ]}|  | qdS )z>
        Send all chunks from C{data} using C{write}.
        N)rh   )rf   rY   chunkr   r   r   writeSequence  s   z'WebSocketsProtocolWrapper.writeSequencec                 C   s   t | j|S )zT
        Forward all non-local attributes and methods to C{self.transport}.
        )getattrrb   )rf   namer   r   r   __getattr__  s   z%WebSocketsProtocolWrapper.__getattr__c                 C   s>   | j | |rd| j }g | j dd< | j| dS dS )z
        FOr each frame received, accumulate the data (ignoring the opcode), and
        forwarding the messages if C{fin} is set.
        r5   N)rw   rm   r9   rs   rp   )rf   rE   rY   rF   contentr   r   r   r_     s   z'WebSocketsProtocolWrapper.frameReceivedc                 C   s   | j | dS )zG
        Forward C{connectionLost} to C{self.wrappedProtocol}.
        N)rs   connectionLost)rf   ri   r   r   r   r~     s   z(WebSocketsProtocolWrapper.connectionLostN)r   r   r   r   r   r#   ru   rv   rg   rh   ry   r|   r_   r~   r   r   r   r   r   a  s    
r   c                   @   s   e Zd ZdZdd ZdS )r   z2
    A WebSockets resource.

    @since: 13.1
    c                 C   r[   )a  
        Build a protocol instance for the given protocol options and request.
        The returned protocol is plugged to the HTTP transport, and the
        returned protocol name, if specified, is used as
        I{Sec-WebSocket-Protocol} value. If the protocol provides
        L{IWebSocketsProtocol}, it will be connected directly, otherwise it
        will be wrapped by L{WebSocketsProtocolWrapper}.

        @param protocolNames: The asked protocols from the client.
        @type protocolNames: C{list} of C{str}

        @param request: The connecting client request.
        @type request: L{IRequest<twisted.web.iweb.IRequest>}

        @return: A tuple of (protocol, matched protocol name or C{None}).
        @rtype: C{tuple}
        Nr   )protocolNamesrequestr   r   r   lookupProtocol  r^   z"IWebSocketsResource.lookupProtocolN)r   r   r   r   r   r   r   r   r   r     s    r   c                   @   s<   e Zd ZdZdZdd Zdd Zdd Zd	d
 Zdd Z	dS )r   a.  
    A resource for serving a protocol through WebSockets.

    This class wraps a factory and connects it to WebSockets clients. Each
    connecting client will be connected to a new protocol of the factory.

    Due to unresolved questions of logistics, this resource cannot have
    children.

    @param factory: The factory producing either L{IWebSocketsProtocol} or
        L{IProtocol} providers, which will be used by the default
        C{lookupProtocol} implementation.
    @type factory: L{twisted.internet.protocol.Factory}

    @since: 13.1
    Tc                 C   s
   || _ d S rr   )_factory)rf   factoryr   r   r   ru     s   
zWebSocketsResource.__init__c                 C      t d)z
        Reject attempts to retrieve a child resource.  All path segments beyond
        the one which refers to this resource are handled by the WebSocket
        connection.
        z5Cannot get IResource children from WebSocketsResourceRuntimeError)rf   r{   r   r   r   r   getChildWithDefault     z&WebSocketsResource.getChildWithDefaultc                 C   r   )z
        Reject attempts to add a child resource to this resource.  The
        WebSocket connection handles all path segments beneath this resource,
        so L{IResource} children can never be found.
        z6Cannot put IResource children under WebSocketsResourcer   )rf   pathchildr   r   r   putChild  r   zWebSocketsResource.putChildc                 C   s   | j |j }|dfS )a  
        Build a protocol instance for the given protocol names and request.
        This default implementation ignores the protocol names and just return
        a protocol instance built by C{self._factory}.

        @param protocolNames: The asked protocols from the client.
        @type protocolNames: C{list} of C{str}

        @param request: The connecting client request.
        @type request: L{Request<twisted.web.http.Request>}

        @return: A tuple of (protocol, C{None}).
        @rtype: C{tuple}
        N)r   buildProtocolrb   rc   )rf   r   r   protocolr   r   r   r     s   z!WebSocketsResource.lookupProtocolc                 C   s  d|_ d}|jdkrd}td|j |d}|du s!d| vr+d}td|d |d	}|du s:d
| vrDd}td|d	 |d}|du rWd}td|d |d}|dkrpd}|dd td|d |ry|d dS |jd}| 	||\}}	|s|d dS |d |dd |d	d |dt
| |	r|d|	 |d |jd}
|_t|st|}| r||
j_n||
_||
 tS )a]  
        Render a request.

        We're not actually rendering a request. We are secretly going to handle
        a WebSockets connection instead.

        @param request: The connecting client request.
        @type request: L{Request<twisted.web.http.Request>}

        @return: a string if the request fails, otherwise C{NOT_DONE_YET}.
        NFGETTzrequest.methodUpgrade	websocketzrequest.getHeader("Upgrade")
Connectionupgradezrequest.getHeader("Connection")zSec-WebSocket-Keyz&request.getHeader("Sec-WebSocket-Key")zSec-WebSocket-Version13z*request.getHeader("Sec-WebSocket-Version")i  r5   zSec-WebSocket-Protocoli  e   	WebSocketzSec-WebSocket-Accept)defaultContentTypemethodprint	getHeaderlower	setHeadersetResponseCoderequestHeadersgetRawHeadersr   r/   rh   rb   r   r   r   isSecurer   rs   rv   r   )rf   r   failedr   
connectionr.   versionaskedProtocolsr   protocolNamerb   r   r   r   render  s^   











zWebSocketsResource.renderN)
r   r   r   r   isLeafru   r   r   r   r   r   r   r   r   r     s    

r   rr   )T)'r   __all__hashlibr   structr   r	   zope.interfacer
   r   r   r   twisted.pythonr   twisted.python.constantsr   r   twisted.internet.protocolr   twisted.internet.interfacesr   twisted.web.resourcer   twisted.web.serverr   	Exceptionr   r   r*   r/   r<   rM   rZ   r   r   r   r   objectr   r   r   r   r   <module>   s2   

*gZI