
    tf                       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Zd dlZd dlZd dl	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 d dlmZ d dlmZ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$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. d dl/m0Z0 d dl1m2Z2 d dl3m4Z4m5Z5 d dl"m6Z6 d dl7Z7d dl8Z8 e9d          Z:dZ;d Z<d Z= G d de>          Z? G d de>          Z@d ZA G d de>          ZB G d de)          ZC ejD        eC            ejD        eC            ejD        eC            G d d e>          ZE G d! d"e>          ZFd#ZG G d$ d%eC          ZH G d& d'eF          ZI G d( d)eC          ZJ G d* d+eF          ZKdS ),    N)OptionalUnionTupleDict)pformat)deque)parse)__version__)IWebSocketChannelIWebSocketChannelFrameApiIWebSocketChannelStreamingApi)ConnectingRequestConnectionRequestConnectionResponseConnectionDeny)TransportDetails)	Stopwatchwildcards2patternsencode_truncatehltypehlval)_LazyHexFormatter)ObservableMixin)Utf8Validator)XorMaskerNullcreate_xor_masker) PERMESSAGE_COMPRESSION_EXTENSION)	parse_url)PayloadExceededErrorDisconnected)_maybe_tls_reason)WebSocketProtocolWebSocketFactoryWebSocketServerProtocolWebSocketServerFactoryWebSocketClientProtocolWebSocketClientFactoryc                 P   |                                  dk    rdS t          j        |           }|j                                         }|dk    rdS |j        }|j        }|	 ddd|         }n# t          $ r d}Y nw xY w|s"t          d                    |                     |||fS )z
    Given an RFC6455 Origin URL, this returns the (scheme, host, port)
    triple. If there's no port, and the scheme isn't http or https
    then port will be None
    nullfileNi  P   )httpshttpzNo host part in Origin '{}')	lowerr	   urlsplitschemehostnameportKeyError
ValueErrorformat)urlresr0   hostr2   s        Z/var/www/surfInsights/venv3-11/lib/python3.11/site-packages/autobahn/websocket/protocol.py_url_to_originr:   M   s     yy{{fv
.

CZF v<D8D|	 "--f5DD 	 	 	DDD	  D6==cBBCCC4s   !A- -A<;A<c                     | dk    rdS t          | t                    rt          |           dk    st          d          | \  }}}d}|                    |||          }|D ]}	|	                    |          r dS dS )a  
    Internal helper. Returns True if the provided websocket_origin
    triple should be considered valid given the provided policy and
    expected host_port.

    Currently, the policy is just the list of allowedOriginsPatterns
    from the WebSocketProtocol instance. Schemes and ports are matched
    first, and only if there is not a mismatch do we compare each
    allowed-origin pattern against the host.
    r)   F   z$'websocket_origin' must be a 3-tuplez{scheme}://{host}:{port})r0   r8   r2   T)
isinstancetuplelenr4   r5   match)
websocket_originhost_scheme	host_porthost_policyorigin_schemeorigin_hostorigin_porttemplateorigin_headerorigin_patterns
             r9   _is_same_originrK   j   s     6!!u&.. Ac:J6K6Kq6P6P?@@@0@-]K *HOO $  M &  .. 	44	 5    c                   &    e Zd Zd Zd Zd Zd ZdS )TrafficStatsc                 .    |                                   d S N)resetselfs    r9   __init__zTrafficStats.__init__   s    

rL   c                     d| _         d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _	        d| _
        d| _        d S Nr   )outgoingOctetsWireLeveloutgoingOctetsWebSocketLeveloutgoingOctetsAppLeveloutgoingWebSocketFramesoutgoingWebSocketMessagesincomingOctetsWireLevelincomingOctetsWebSocketLevelincomingOctetsAppLevelincomingWebSocketFramesincomingWebSocketMessagespreopenOutgoingOctetsWireLevelpreopenIncomingOctetsWireLevelrR   s    r9   rQ   zTrafficStats.reset   sl     ()$,-)&'#'($)*&'($,-)&'#'($)*&
 /0+./+++rL   c                    | j         dk    r*t          | j                  t          | j                   z  }nd }| j        dk    r*t          | j                  t          | j                  z  }nd }| j        dk    r2t          | j        | j        z
            t          | j                  z  }nd }| j        dk    r2t          | j        | j        z
            t          | j                  z  }nd }i d| j        d| j        d| j         d|d|d| j        d| j        d	| j	        d
| j        d| j        d| j        d|d|d| j
        d| j        d| j        S )Nr   rW   rX   rY   outgoingCompressionRatiooutgoingWebSocketOverheadrZ   r[   ra   r\   r]   r^   incomingCompressionRatioincomingWebSocketOverheadr_   r`   rb   )rY   floatrX   r^   r]   rW   r\   rZ   r[   ra   r_   r`   rb   )rS   rd   rf   re   rg   s        r9   __json__zTrafficStats.__json__   s    &**',T-N'O'ORWX\XsRtRt't$$'+$&**',T-N'O'ORWX\XsRtRt't$$'+$ ,q00(-d.JTMn.n(o(orwx|  yZ  s[  s[  )[%%(,%,q00(-d.JTMn.n(o(orwx|  yZ  s[  s[  )[%%(,%W)4+G W.0QW($*EW +,DW ,-F	W
 *4+GW ,T-KW 1$2UW *4+GW /0QW )$*EW +,DW ,-FW *4+GW ,T-KW  1$2U!W 	WrL   c                 N    t          j        |                                           S rP   )jsondumpsri   rR   s    r9   __str__zTrafficStats.__str__   s    z$--//***rL   N)__name__
__module____qualname__rT   rQ   ri   rm    rL   r9   rN   rN      sT          0 0 0*(W (W (WT+ + + + +rL   rN   c                       e Zd ZdZd ZdS )FrameHeaderzX
    Thin-wrapper for storing WebSocket frame metadata.

    FOR INTERNAL USE ONLY!
    c                 L    || _         || _        || _        || _        || _        dS )a  
        Constructor.

        :param opcode: Frame opcode (0-15).
        :type opcode: int
        :param fin: Frame FIN flag.
        :type fin: bool
        :param rsv: Frame reserved flags (0-7).
        :type rsv: int
        :param length: Frame payload length.
        :type length: int
        :param mask: Frame mask (binary string) or None.
        :type mask: str
        N)opcodefinrsvlengthmask)rS   ru   rv   rw   rx   ry   s         r9   rT   zFrameHeader.__init__   s+     			rL   Nrn   ro   rp   __doc__rT   rq   rL   r9   rs   rs      s-             rL   rs   c                    |                      d                                          }|d                                         }i }i }|dd         D ]}|                    d          }|dk    r|d|                                                                         }||dz   d                                         }||v r4||xx         d                    |          z  cc<   ||xx         dz  cc<   |||<   d||<   |||fS )as  
    Parses the beginning of a HTTP request header (the data up to the 

 line) into a pair
    of status line and HTTP headers dictionary.
    Header keys are normalized to all-lower-case.

    FOR INTERNAL USE ONLY!

    :param data: The HTTP header data up to the 

 line.
    :type data: bytes

    :returns: Tuple of HTTP status line, headers and headers count.
    z
iso-8859-1r      N:z, {})decode
splitlinesstripfindr.   r5   )	datarawhttp_status_linehttp_headershttp_headers_cnthikeyvalues	            r9   parseHttpHeaderr      s(   * ++l
#
#
.
.
0
0C1v||~~LW  FF3KKq55BQB%++--%%''Ca!effIOO%%E l""S!!!V]]5%9%99!!! %%%*%%%%$)S!() %% \+;;;rL   c                   8    e Zd ZdZd Zd Zd
dZd Zd Zd Z	d	S )Timingsz}
    Helper class to track timings by key. This class also supports item access,
    iteration and conversion to string.
    c                 :    t                      | _        i | _        d S rP   )r   
_stopwatch_timingsrR   s    r9   rT   zTimings.__init__2  s    #++rL   c                 H    | j                                         | j        |<   dS )zy
        Track elapsed for key.

        :param key: Key under which to track the timing.
        :type key: str
        N)r   elapsedr   rS   r   s     r9   trackzTimings.track6  s$     "_4466crL   Tc                    || j         v r|| j         v r| j         |         | j         |         z
  }|r|dk     r&d                    t          |dz                      }nz|dk     r&d                    t          |dz                      }nN|dk     r&d                    t          |d	z                      }n"d
                    t          |                    }|                    d          S |S |rd                    d          S dS )a  
        Get elapsed difference between two previously tracked keys.

        :param startKey: First key for interval (older timestamp).
        :type startKey: str
        :param endKey: Second key for interval (younger timestamp).
        :type endKey: str
        :param formatted: If ``True``, format computed time period and return string.
        :type formatted: bool

        :returns: Computed time period in seconds (or formatted string).
        h㈵>z{} nsg    eAg{Gz?z{} usg    .A
   z{} msg     @@z{} s   zn.a.N)r   r5   roundrjust)rS   startKeyendKey	formatteddss         r9   diffzTimings.diff?  s     T]""x4='@'@f%h(??A w;;uQ_'='=>>AAXXuQ\':':;;AAVVuQY'7'788AAeAhh//Awwqzz! ||A&trL   c                 8    | j                             |d           S rP   )r   getr   s     r9   __getitem__zTimings.__getitem__`  s    }  d+++rL   c                 4    | j                                         S rP   )r   __iter__rR   s    r9   r   zTimings.__iter__c  s    }%%'''rL   c                 *    t          | j                  S rP   )r   r   rR   s    r9   rm   zTimings.__str__f  s    t}%%%rL   NT)
rn   ro   rp   r{   rT   r   r   r   r   rm   rq   rL   r9   r   r   ,  s~         
  7 7 7   B, , ,( ( (& & & & &rL   r   c                      e Zd ZdZdZg dZ	 ddgZ	 dddddddddd	Z	 dddZ	 dZ		 d	Z
	 d
Z	 dZ	 dZ	 dZdZdZdZdZdZdZdZdZdZ	 dZ	 dZ	 dZ	 dZ	 dZ	 dZ	 dZ	 dZ	 dZ 	 dZ!	 dZ"	 dZ#	 dZ$	 dZ%	 dZ&	 eeeeeee e!e"e#e$gZ'	 g d Z(	 g d!Z)	 g d"Z*	 d# Z+e,d$e-e.         fd%            Z/d& Z0d' Z1d( Z2d) Z3d* Z4d+ Z5d, Z6d- Z7d. Z8d/ Z9d0 Z:d1 Z;d2 Z<d3 Z=d4 Z>d5 Z?d6 Z@dcd8ZAd9 ZBed:fd;ZCd< ZDd= ZEd> ZFd? ZGd@ ZHdA ZIdB ZJdC ZKdD ZLdE ZMdF ZNdG ZOdH ZPdI ZQdJ ZRdddLZSdM ZTdN ZUdO ZVdP ZWdQ ZXdR ZY	 	 	 	 	 	 	 dedUZZdfdVZ[dW Z\dX Z]dfdYZ^dgdZZ_dhd[Z`did\Zad] Zbdcd^Zcd_ Zddcd`Ze	 	 	 	 djdaZfdkdbZgdKS )lr"   a   
    Protocol base class for WebSocket.

    This class implements:

      * :class:`autobahn.websocket.interfaces.IWebSocketChannel`
      * :class:`autobahn.websocket.interfaces.IWebSocketChannelFrameApi`
      * :class:`autobahn.websocket.interfaces.IWebSocketChannelStreamingApi`
    z<never connected>)	r                           r   r   r   r   )r   r   s$   258EAFA5-E914-47DA-95CA-C5AB0DC85B11r   r}      r   r<        i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  )	logOctets	logFramestrackTimingsutf8validateIncoming	applyMaskmaxFramePayloadSizemaxMessagePayloadSizeautoFragmentSize
failByDropechoCloseCodeReasonopenHandshakeTimeoutcloseHandshakeTimeout
tcpNoDelayautoPingIntervalautoPingTimeoutautoPingSizeautoPingRestartOnAnyTraffic)versions	webStatusrequireMaskedClientFramesmaskServerFramesperMessageCompressionAcceptserveFlashSocketPolicyflashSocketPolicyallowedOriginsallowedOriginsPatternsallowNullOriginmaxConnectionstrustXForwardedFor)versionacceptMaskedServerFramesmaskClientFramesserverConnectionDropTimeoutperMessageCompressionOffersr   c                     t          j                    | _        t          j                    | _        |                     dg           t                      | _        d S )Nmessage)txaiocreate_future	is_closedis_openset_valid_eventsr   _transport_detailsrR   s    r9   rT   zWebSocketProtocol.__init__(  s[    ,..*,, 	
 	 	 	 ?O>P>PrL   returnc                     | j         S )z\
        Implements :class:`autobahn.wamp.interfaces.ITransport.transport_details`.
        )r   rR   s    r9   transport_detailsz#WebSocketProtocol.transport_details7  s    
 &&rL   c                 :    | j                             d           dS )z[
        Implements :meth:`autobahn.websocket.interfaces.IWebSocketChannel.onOpen`
        zWebSocketProtocol.onOpenNlogdebugrR   s    r9   onOpenzWebSocketProtocol.onOpen>  s     	122222rL   c                 0    || _         g | _        d| _        dS )zc
        Implements :meth:`autobahn.websocket.interfaces.IWebSocketChannel.onMessageBegin`
        r   N)message_is_binarymessage_datamessage_data_total_length)rS   isBinarys     r9   onMessageBeginz WebSocketProtocol.onMessageBeginD  s"     "*)*&&&rL   c                    || _         g | _        | xj        |z  c_        | j        sd| j        cxk     r| j        k     rKn nHd| _        |                     | j        | j        d                    | j        | j                             dS d| j        cxk     r|k     rDn dS d| _	        |                     || j        d                    || j                             dS dS dS )zh
        Implements :meth:`autobahn.websocket.interfaces.IWebSocketChannel.onMessageFrameBegin`
        r   TzEreceived WebSocket message size {} exceeds payload limit of {} octetszCreceived WebSocket frame size {} exceeds payload limit of {} octetsN)
frame_length
frame_datar   
failedByMer    wasMaxMessagePayloadSizeExceeded_max_message_size_exceededr5   r   wasMaxFramePayloadSizeExceeded)rS   rx   s     r9   onMessageFrameBeginz%WebSocketProtocol.onMessageFrameBeginL  sd    #&&&0&& 
	`4-NNNN0NNNNNN8<5//0N040J0w0~0~  @D  @^  `d  `z  1{  1{| | | | | T-66666666666:3//040H0u0|0|  ~D  FJ  F^  1_  1_` ` ` ` `
	` 
	` 76rL   c                    | j         s| j        dk    r| xj        t          |          z  c_        d| j        cxk     r| j        k     rIn nFd| _        |                     | j        | j        d                    | j        | j                             | j        	                    |           dS | j
        	                    |           dS dS )zg
        Implements :meth:`autobahn.websocket.interfaces.IWebSocketChannel.onMessageFrameData`
        r   TzYreceived (partial) WebSocket message size {} (already) exceeds payload limit of {} octetsN)r   websocket_versionr   r?   r   r   r   r5   r   appendr   rS   payloads     r9   onMessageFrameDataz$WebSocketProtocol.onMessageFrameData_  s     
	0%**..#g,,>..t1RRRRD4RRRRRR<@D933D4R484N 5P  5W  5W  X\  Xv  x|  xR  5S  5ST T T !((11111&&w/////
	0 
	0rL   c                 V    | j         s|                     | j                   d| _        dS )zf
        Implements :meth:`autobahn.websocket.interfaces.IWebSocketChannel.onMessageFrameEnd`
        N)r   _onMessageFramer   rR   s    r9   onMessageFrameEndz#WebSocketProtocol.onMessageFrameEndo  s/      	2  111rL   c                 L    | j         s| j                            |           dS dS )zc
        Implements :meth:`autobahn.websocket.interfaces.IWebSocketChannel.onMessageFrame`
        N)r   r   extendr   s     r9   onMessageFramez WebSocketProtocol.onMessageFramex  s5      	.$$W-----	. 	.rL   c                 @     j         sd                     j                  } j        r j                            d                                | j                                        d| j                  } fd}t          j	        |d|           d _        dS )za
        Implements :meth:`autobahn.websocket.interfaces.IWebSocketChannel.onMessageEnd`
        rL   	onMessager   )	is_binaryc                 @    j                             d|            d S )Nz&Firing signal 'message' failed: {fail}fail)r   error)frS   s    r9   r  z-WebSocketProtocol.onMessageEnd.<locals>.error  s0    <      rL   N)
r   joinr   trackedTimingsr   
_onMessager   firer   add_callbacks)rS   r   r  r  s   `   r9   onMessageEndzWebSocketProtocol.onMessageEnd  s      	0hht011G" 7#))+666OOGT%;<<< 		)W8N	OOA     4/// rL   c                 b    | j                             d|rt          |          nd|           dS )z^
        Implements :meth:`autobahn.websocket.interfaces.IWebSocketChannel.onMessage`
        zOWebSocketProtocol.onMessage(payload=<{payload_len} bytes)>, isBinary={isBinary}r   )payload_lenr   Nr   r   r?   )rS   r   r   s      r9   r  zWebSocketProtocol.onMessage  sC     	])07Wa 	 	
 	
 	
 	
 	
rL   c                     | j                             d|rt          |          nd           | j        t          j        k    r|                     |           dS dS )z[
        Implements :meth:`autobahn.websocket.interfaces.IWebSocketChannel.onPing`
        z7WebSocketProtocol.onPing(payload=<{payload_len} bytes>)r   r  N)r   r   r?   stater"   
STATE_OPENsendPongr   s     r9   onPingzWebSocketProtocol.onPing  si     	E)07Wa 	 	
 	
 	
 :*555MM'""""" 65rL   c                 `    | j                             d|rt          |          nd           dS )z[
        Implements :meth:`autobahn.websocket.interfaces.IWebSocketChannel.onPong`
        z7WebSocketProtocol.onPong(payload=<{payload_len} bytes>)r   r  Nr  r   s     r9   onPongzWebSocketProtocol.onPong  s@     	E)07Wa 	 	
 	
 	
 	
 	
rL   c                 B    | j                             d|||           dS )z\
        Implements :meth:`autobahn.websocket.interfaces.IWebSocketChannel.onClose`
        zLWebSocketProtocol.onClose(wasClean={wasClean}, code={code}, reason={reason}))wasCleancodereasonNr   )rS   r  r  r  s       r9   onClosezWebSocketProtocol.onClose  s7     	Z	 	 	
 	
 	
 	
 	
rL   c                    d| _         d| _        |f|dk     s$d|cxk    rdk    rn n|t          j        vs|dk    r<|                     d                    |                    rdS t          j        | _         n|| _         |et                      }|                    |          }|d         r|d         s| 	                    d	          rdS n|
                    d
          | _        | j        t          j        k    r| j        :| j                            d           | j                                         d| _        d| _        | j        j        r|                     d           dS | j        dk    r&t-          j        | j        | j                  | _        dS dS | j        t          j        k    rd| _        | j        dk    r|                     d           nY| j        r1|                     | j         t=          | j        d          d           n!|                     t          j        d           | j        j        r|                     d           dS dS | j        t          j        k    r	d| _        dS tA          d          )aQ  
        Callback when a Close frame was received. The default implementation answers by
        sending a Close when no Close was sent before. Otherwise it drops
        the TCP connection either immediately (when we are a server) or after a timeout
        (when we are a client and expect the server to drop the TCP).

        :param code: Close status code, if there was one (:class:`WebSocketProtocol`.CLOSE_STATUS_CODE_*).
        :type code: int
        :param reasonRaw: Close reason (when present, a status code MUST have been also be present).
        :type reasonRaw: bytes
        Nr   i  i  zinvalid close code {}Tr   r}   z'invalid close reason (non-UTF8 payload)utf8z?connection closed properly: canceling closing handshake timeoutabort)isReply{   r  
reasonUtf8r#  )r  r#  Flogic error)!remoteCloseCoderemoteCloseReasonr"   CLOSE_STATUS_CODES_ALLOWED_protocol_violationr5   CLOSE_STATUS_CODE_NORMALr   validate_invalid_payloadr   r  STATE_CLOSINGcloseHandshakeTimeoutCallr   r   cancelr  factoryisServerdropConnectionr   r   
call_lateronServerConnectionDropTimeoutserverConnectionDropTimeoutCallr  r   sendCloseFramer   r   STATE_CLOSED	Exception)rS   r  	reasonRawuvals        r9   onCloseFramezWebSocketProtocol.onCloseFrame  s     $!% 1E1E1E1E1E1E1E1E1E$Vg  WC  KC  KC  HL  PT  HT  HT''(?(F(Ft(L(LMM Rt'8'Q$$#'D    A**Y''C F Bs1v B(()RSS  4  *3)9)9&)A)A& :*888 -9`aaa.5577715. DM|$ 
##$#///// 3a77;@;K8:< <D888 87 Z,777 !DM%**##D#1111 + g''T-Ao^b^tvyNzNz  EI'  J  J  J  J''->-Wae'fff|$ ##%#00000
 Z,999!DMMM M***rL   c                     d| _         | j        t          j        k    r-d| _        d| _        d| _        |                     d           dS | j        	                    d           dS )z
        We (a client) expected the peer (a server) to drop the connection,
        but it didn't (in time self.serverConnectionDropTimeout).
        So we drop the connection, but set self.wasClean = False.
        NFzPWebSocket closing handshake timeout (server did not drop TCP connection in time)Tr!  zQskipping closing handshake timeout: server did indeed drop the connection in time)
r7  r  r"   r9  r  wasNotCleanReasonwasServerConnectionDropTimeoutr4  r   r   rR   s    r9   r6  z/WebSocketProtocol.onServerConnectionDropTimeout#  sl     04,:*777!DM%wD"26D/d+++++HNNnooooorL   c                    d| _         | j        t          j        t          j        fv r-d| _        d| _        d| _        |                     d           dS | j        t          j	        k    r| j
                            d           dS | j        t          j        k    r| j
                            d           dS | j        t          j        k    r| j
                            d           dS t          d	          )
z
        We expected the peer to complete the opening handshake with to us.
        It didn't do so (in time self.openHandshakeTimeout).
        So we drop the connection, but set self.wasClean = False.
        NFzWWebSocket opening handshake timeout (peer did not finish the opening handshake in time)Tr!  zeskipping opening handshake timeout: WebSocket connection is open (opening handshake already finished)zNskipping opening handshake timeout: WebSocket connection is already closing ..zJskipping opening handshake timeout: WebSocket connection is already closedr'  )openHandshakeTimeoutCallr  r"   STATE_CONNECTINGSTATE_PROXY_CONNECTINGr  r@  wasOpenHandshakeTimeoutr4  r  r   r   r/  r9  r:  rR   s    r9   onOpenHandshakeTimeoutz(WebSocketProtocol.onOpenHandshakeTimeout3  s     )-%:+<>O>fggg!DM%~D"+/D(d+++++Z,777HNN  C  D  D  D  D  DZ,:::HNNklllllZ,999HNNghhhhh M***rL   c                     d| _         | j        t          j        k    r-d| _        d| _        d| _        |                     d           dS | j        	                    d           dS )z
        We expected the peer to respond to us initiating a close handshake. It didn't
        respond (in time self.closeHandshakeTimeout) with a close response frame though.
        So we drop the connection, but set self.wasClean = False.
        NFzWWebSocket closing handshake timeout (peer did not finish the closing handshake in time)Tr!  zJskipping closing handshake timeout: WebSocket connection is already closed)
r0  r  r"   r9  r  r@  wasCloseHandshakeTimeoutr4  r   r   rR   s    r9   onCloseHandshakeTimeoutz)WebSocketProtocol.onCloseHandshakeTimeoutJ  sl     *.&:*777!DM%~D",0D)d+++++HNNghhhhhrL   c                 `    | j                             dt          |          ||||           dS )a  
        When doing automatic ping/pongs, this is called upon a successful pong.

        :param ping_sent: Posix time in ns when ping was sent.
        :param ping_seq: Sequence number of ping that was sent.
        :param pong_received: Posix time in ns when pong was received.
        :param pong_rtt: Pong roundtrip-time in ms measured.
        :param payload: The complete WebSocket ping/pong message payload
            (ping_sent 8 bytes big-endian | ping_seq 4 bytes big endian | max. 113 optional random bytes).
        zAuto ping/pong: received pending pong (size={size}) for auto-ping (sent={sent}, seq={seq}, received={received}) in RTT of {rtt} ms)sizesentseqreceivedrttNr  )rS   	ping_sentping_seqpong_receivedpong_rttr   s         r9   
onAutoPongzWebSocketProtocol.onAutoPongZ  sH     	 QWI8mYa 	 	c 	c 	c 	c 	crL   c                 \    d| _         d| _        d| _        |                     d           dS )z
        When doing automatic ping/pongs to detect broken connection, the peer
        did not reply in time to our ping. We drop the connection.
        Fz?WebSocket ping timeout (peer did not respond with pong in time)NTr!  )r  r@  autoPingTimeoutCallr4  rR   s    r9   onAutoPingTimeoutz#WebSocketProtocol.onAutoPingTimeouti  s8    
 !b#' $'''''rL   Fc                    |                                   | j        t          j        k    r| j        r#| j                            d| j        |           n(| j                            d| j        || j	                   d| _
        t          j        | _        t          j        | j        |            |                     |           dS | j                            d| j                   dS )	z5
        Drop the underlying TCP connection.
        z5dropping connection to peer {peer} with abort={abort})peerr"  z?dropping connection to peer {peer} with abort={abort}: {reason})rZ  r"  r  TzFdropping connection to peer {peer} skipped - connection already closed)rZ  N)unregisterProducerr  r"   r9  r  r   r   rZ  warnr@  droppedByMer   resolver   _closeConnection)rS   r"  s     r9   r4  z WebSocketProtocol.dropConnections  s     	!!!:*777} ]V]a]fnstttt_fjfow|  FJ  F\  ]  ]  ]#D
 +7DJM$.$///!!%(((((HNNcjnjsNtttttrL   c                 H    	 |                      t          j        |           d S rP   )_fail_connectionr"   !CLOSE_STATUS_CODE_MESSAGE_TOO_BIGr   )rS   msg_sizemax_msg_sizer  s       r9   r   z,WebSocketProtocol._max_message_size_exceeded  s(    	/!!"3"UW]^^^^^rL   z
going awayc                    | j         t          j        k    r| j                            d||           d| _        | j        r9d| _        d                    |          | _	        | 
                    d           d
S | j         t          j        k    r(|                     |t          |d          d           d
S | 
                    d           d
S | j                            d	           d
S )z1
        Fails the WebSocket connection.
        z6failing WebSocket connection (code={code}): "{reason}")r  r  TFz+I dropped the WebSocket TCP connection: {0}r!  r$  r%  z=skip failing of connection since connection is already closedN)r  r"   r9  r   r\  r   r   r  r5   r@  r4  r/  r8  r   r   )rS   r  r  s      r9   ra  z"WebSocketProtocol._fail_connection  s     :*777HMMRY]flMmmm"DO 5 %)V)])]^d)e)e&##$#///// :!2!@@@''TofVY>Z>Zdi'jjjjj ''e'44444 HNNZ[[[[[rL   c                     | j                             d|           |                     t          j        |           | j        rdS dS )a  
        Fired when a WebSocket protocol violation/error occurs.

        :param reason: Protocol violation that was encountered (human readable).
        :type reason: str

        :returns: True, when any further processing should be discontinued.
        zProtocol violation: {reason}r  TF)r   r   ra  r"    CLOSE_STATUS_CODE_PROTOCOL_ERRORr   rS   r  s     r9   r+  z%WebSocketProtocol._protocol_violation  sN     	5fEEE/PRXYYY? 	4 5rL   c                     | j                             d|           |                     t          j        |           | j        rdS dS )a  
        Fired when invalid payload is encountered. Currently, this only happens
        for text message when payload is invalid UTF-8 or close frames with
        close reason that is invalid UTF-8.

        :param reason: What was invalid for the payload (human readable).
        :type reason: str

        :returns: True, when any further processing should be discontinued.
        zInvalid payload: {reason}rg  TF)r   r   ra  r"   !CLOSE_STATUS_CODE_INVALID_PAYLOADr   ri  s     r9   r.  z"WebSocketProtocol._invalid_payload  sN     	26BBB/QSYZZZ? 	4 5rL   c                     t          | d          r| j        |k    r,|| _        | j        rt                      | _        dS d| _        dS dS )z
        Enable/disable tracking of detailed timings.

        :param enable: Turn time tracking on/off.
        :type enable: bool
        r   N)hasattrr   r   r
  )rS   enables     r9   setTrackTimingsz!WebSocketProtocol.setTrackTimings  s_     t^,, 	+0AV0K0K &D  +&-ii###&*### 1L0KrL   c           	         g }| j         D ]z}t          | |          s6t          | |t          | j        |                     | j        j        j        }n| j        j        }|                    |t          | |          |f           {| j        	                    dt          |                     d| _        d| _        |                     | j                   t                      | _        | j        j        s| j        j        t&          j        | _        nt&          j        | _        t&          j        | _        d| _        t5                      | _        d| _        t;                      | _        d| _        d| _         d| _!        d| _"        d| _#        d| _$        d| _%        d| _&        d| _'        d| _(        d| _)        d| _*        d| _+        d| _,        d| _-        | j        j        sd| _.        d| _/        d| _0        d| _1        d| _2        d| _3        d| _4        d| _5        | j6        dk    r1| j        j7        8                    | j6        | j9                  | _/        dS dS )z
        This is called by network framework when a new TCP connection has been established
        and handed over to a Protocol instance (an instance of this class).
        z
{attrs})attrsNrL   Fr   ):CONFIG_ATTRSrm  setattrgetattrr2  	__class__rn   r   r   r   r   _perMessageCompressr
  ro  r   rN   trafficStatsr3  proxyr"   rE  r  rD  SEND_STATE_GROUND
send_stater   r   
send_queue	triggeredr   utf8validatorr   r   
closedByMer   r]  r  r@  rA  rF  rI  wasServingFlashSocketPolicyFilelocalCloseCodelocalCloseReasonr(  r)  r7  rC  r0  rW  autoPingPendingautoPingPendingCallautoPingPendingSeqautoPingPendingSentr   _batched_timerr5  rG  )rS   configAttrLog
configAttrconfigAttrSources       r9   _connectionMadez!WebSocketProtocol._connectionMade  st    + 	\ 	\J4,, ;j'$,
*K*KLLL#'<#9#B  #'>#:   *gdJ.G.GIY!Z[[[[{'-*@*@AAA $(  #T./// )NN |$ 	<);)G*ADJJ*;DJ+=	
  '' +__ /4+05-
  
   !  "& /4+ (-$ ).% 05, # !%  $ "& |$ 	837D0(,%)-&#' ##' "##'  $q((,0L,G,R,R)+- -D))) )(rL   c                 P   | j                             d|           | j        j        sA| j        :| j                             d           | j                                         d| _        | j        r:| j                             d           | j                                         d| _        | j        r:| j                             d           | j                                         d| _        | j         | j                                         d| _        | j	        t          j        k    r+t          j        | _	        t          j        | j        |            | j        r| j                             d           dS | j        s| j        s<| j        5t'          |dd          }|sdnt)          |          }|r|| _        nd	| _        |                     | j        t          j        d
                    | j                             dS |                     | j        | j        | j                   dS )zc
        This is called by network framework when a transport connection was
        lost.
        z_connectionLost: {reason}rg  Nz&serverConnectionDropTimeoutCall.cancelzBAuto ping/pong: canceling autoPingPendingCall upon lost connectionzBAuto ping/pong: canceling autoPingTimeoutCall upon lost connectionz9connection dropped after serving Flash Socket Policy Filer   zLpeer dropped the TCP connection without previous WebSocket closing handshakez&connection was closed uncleanly ("{}"))r   r   r2  r3  r7  r1  r  rW  rC  r  r"   r9  r   r^  r   r  r  r]  r@  rt  r!   _onClose CLOSE_STATUS_CODE_ABNORMAL_CLOSEr5   r(  r)  )rS   r  reason_valuereason_strings       r9   _connectionLostz!WebSocketProtocol._connectionLost[  sH    	26BBB|$ 	8)M)YHNNCDDD07799937D0 # 	,HNN_```$++---'+D$# 	,HNN_```$++---'+D$ (4)00222,0D) :*777*7DJM$.$//// 	[HNNVWWWWW= 
[' @D,B,J#*67D#A#AL0<$aDDBST`BaBaM$ @1>..1.dm->-_  bJ  bQ  bQ  RV  Rh  bi  bi  j  j  j  j  jdmT-A4CYZZZZZrL   c                 d    | j                             d| j        t          |                     dS )zu
        Hook fired right after raw octets have been received, but only when
        self.logOctets == True.
        z)RX Octets from {peer} : octets = {octets})rZ  octetsNr   r   rZ  r   rS   r   s     r9   logRxOctetszWebSocketProtocol.logRxOctets  s>    
 	7$T** 	 	
 	
 	
 	
 	
rL   c                 f    | j                             d| j        |t          |                     dS )zq
        Hook fired right after raw octets have been sent, but only when
        self.logOctets == True.
        z6TX Octets to {peer} : sync = {sync}, octets = {octets})rZ  syncr  Nr  )rS   r   r  s      r9   logTxOctetszWebSocketProtocol.logTxOctets  sA    
 	D$T**	 	 	
 	
 	
 	
 	
rL   c                 4   d                     |          }| j                            d| j        |j        |j        |j        |j        rt          j	        |j                  nd|j
        |j        dk    rt          |          nt          |                     dS )z
        Hook fired right after WebSocket frame has been received and decoded,
        but only when self.logFrames == True.
        rL   zyRX Frame from {peer} : fin = {fin}, rsv = {rsv}, opcode = {opcode}, mask = {mask}, length = {length}, payload = {payload}-r}   )rZ  rv   rw   ru   ry   rx   r   N)r	  r   r   rZ  rv   rw   ru   ry   binasciib2a_hexrx   reprr   )rS   frameHeaderr   r   s       r9   
logRxFramezWebSocketProtocol.logRxFrame  s    
 xx  F%7B7GP!+"2333S%"-"4"9"9DJJJ?PQU?V?V 	 
	
 
	
 
	
 
	
 
	
rL   c                    | j                             d| j        |j        |j        |j        |j        rt          j        |j                  nd|j	        ||||j        dk    rt          |          nt          |                     dS )z
        Hook fired right after WebSocket frame has been encoded and sent, but
        only when self.logFrames == True.
        zTX Frame to {peer} : fin = {fin}, rsv = {rsv}, opcode = {opcode}, mask = {mask}, length = {length}, repeat_length = {repeat_length}, chopsize = {chopsize}, sync = {sync}, payload = {payload}r  r}   )
rZ  rv   rw   ru   ry   rx   repeat_lengthchopsizer  r   N)r   r   rZ  rv   rw   ru   ry   r  r  rx   r  r   )rS   r  r   repeatLengthr  r  s         r9   
logTxFramezWebSocketProtocol.logTxFrame  s    
 	I %7B7GP!+"2333S%&%0%71%<%<DMMMBST[B\B\ 	 	
 	
 	
 	
 	
rL   c                    | j         t          j        k    r#| j        xj        t          |          z  c_        nL| j         t          j        k    s| j         t          j        k    r"| j        xj        t          |          z  c_        | j	        r| 
                    |           | xj        |z  c_        |                                  dS )zj
        This is called by network framework upon receiving data on transport
        connection.
        N)r  r"   r  rw  r\   r?   rD  rE  rb   r   r  r   consumeDatar  s     r9   _dataReceivedzWebSocketProtocol._dataReceived  s    
 :*55555TB555Z,===O`OwAwAw<<D		I<<> 	#T"""		T		rL   c                 8   | j         t          j        k    s| j         t          j        k    r[|                                 rA| j         t          j        k    r0	 |                                 r| j         t          j        k    *dS dS dS dS | j         t          j        k    r|                                  dS | j         t          j        k    r| 	                                 dS | j         t          j        k    r| j
                            d           dS t          d          )z3
        Consume buffered (incoming) data.
        zreceived data in STATE_CLOSEDzinvalid stateN)r  r"   r  r/  processDatar9  rE  processProxyConnectrD  processHandshaker   r   r:  rR   s    r9   r  zWebSocketProtocol.consumeData  s,    :*555GXGf9f9f ""$$ 7H7U)U)U ""$$ 7H7U)U)U)U)U    )U)U
 Z,CCC$$&&&&& Z,=== !!##### Z,999 HNN:;;;;;
 O,,,rL   c                      t          d          )z(
        Process proxy connect.
        z@must implement proxy connect (client or server) in derived classr:  rR   s    r9   r  z%WebSocketProtocol.processProxyConnect  s     Z[[[rL   c                      t          d          )z.
        Process WebSocket handshake.
        z<must implement handshake (client or server) in derived classr  rR   s    r9   r  z"WebSocketProtocol.processHandshake  s     VWWWrL   c                 N    | j         sd| _         |                                  dS dS )zp
        Trigger sending stuff from send queue (which is only used for
        chopped/synched writes).
        TN)r|  _sendrR   s    r9   _triggerzWebSocketProtocol._trigger  s0    
 ~ 	!DNJJLLLLL	 	rL   c                    t          | j                  dk    rH| j                                        }| j        t          j        k    r| j                            |d                    | j        t          j        k    r)| j	        xj
        t          |d                   z  c_
        nR| j        t          j        k    s| j        t          j        k    r(| j	        xj        t          |d                   z  c_        | j        r"|                     |d         |d                    n| j                            d           t%          j        t          j        | j                   dS d| _        dS )zu
        Send out stuff from send queue. For details how this works, see
        test/trickling in the repo.
        r   r}   z1skipped delayed write, since connection is closedFN)r?   r{  popleftr  r"   r9  	transportwriter  rw  rW   rD  rE  ra   r   r  r   r   r   r5  _QUEUED_WRITE_DELAYr  r|  )rS   es     r9   r  zWebSocketProtocol._send  s8   
 t!##''))Az.;;;$$QqT***:!2!===%==QqTJ===Z#4#EEEWhWII%DDAaD		QDD> 1$$QqT1Q4000RSSS .BDJOOOOO"DNNNrL   Nc           
         |rk|dk    red}t          |          }d}|s:||z   }||k    rd}|}| j                            |||         df           ||z  }|:|                                  dS |st          | j                  dk    r2| j                            ||f           |                                  dS | j                            |           | j                            dt          | j	                  t          | j                  t          t          |                               | j        t          j        k    r#| j        xj        t          |          z  c_        nL| j        t          j        k    s| j        t          j        k    r"| j        xj        t          |          z  c_        | j        r|                     |d           dS dS )a  
        Wrapper for self.transport.write which allows to give a chopsize.
        When asked to chop up writing to TCP stream, we write only chopsize
        octets and then give up control to select() in underlying reactor so
        that bytes get onto wire immediately. Note that this is different from
        and unrelated to WebSocket data message fragmentation. Note that this
        is also different from the TcpNoDelay option which can be set on the
        socket.
        r   FTz,{func} sent {data_len} bytes for peer {peer})funcrZ  data_lenN)r?   r{  r   r  r  r  r   r   r   sendDatar   rZ  r  r"   r  rw  rW   rD  rE  ra   r   r  )rS   r   r  r  r   ndonejs           r9   r  zWebSocketProtocol.sendData;  s     	21AD		AD L66DA&&QqS	4'8999X   MMOOOOO 2s4?++a//&&d|444$$T***M$*4=$9$9$)$)$4$4(-c$ii(8(8  : : :
 :!2!===%==TJ===Z#4#EEEWhWII%DDD		QDD> 2$$T5111112 2rL   c                     | j         |j        r|                     |j                   dS |                     |j        |j                   dS )zh
        Implements :func:`autobahn.websocket.interfaces.IWebSocketChannel.sendPreparedMessage`
        N)rv  doNotCompressr  payloadHybisendMessager   binary)rS   preparedMsgs     r9   sendPreparedMessagez%WebSocketProtocol.sendPreparedMessaged  sR     #+{/H+MM+122222[0+2DEEEEErL   c                 z
   t          | j                  }| j        '|dk    r| j        d         }|dz  dk    }|dz  dz	  }|dz  }| j        d         }|dz  dk    }|d	z  }|dk    r8| j        |dk    rn*|                     d
                    |                    rdS | j        j        r | j        r|s|                     d          rdS | j        j        s | j	        s|r|                     d          rdS |dk    r|s|                     d          rdS |dk    r|                     d          rdS |dvr*|                     d                    |                    rdS |dk    r|dk    r|                     d          rdS | j        :|dk    r4|                     d                    | j        j
                            rdS n|dvr*|                     d                    |                    rdS | j        s|dk    r|                     d          rdS | j        r|dk    r|                     d          rdS | j        A|dk    r;| j        r4|                     d                    | j        j
                            rdS |rd}nd}|dk     rd|z   }	n'|dk    rd|z   }	n|d	k    rd|z   }	nt          d          ||	k    rzd}
|dk    rNt          j        d| j        |
|
dz                      d         }|dk     r|                     d           rdS |
dz  }
ns|d	k    rkt          j        d!| j        |
|
dz                      d         }|d"k    r|                     d#          rdS |d$k     r|                     d           rdS |
dz  }
n|}d}|r| j        |
|
dz            }|
dz  }
|r#|dk    r| j        rt!          ||          | _        nt%                      | _        | j        |
d         | _        t'          |||||          | _        |                                  |dk    pt          | j                  dk    S dS dS | j        j        | j                                        z
  }||k    r&| j        d|         }|}| j        |d         | _        n| j        }|}d%| _        |dk    r| j                            |          }nd%}|                     |          }|du rdS | j                                        | j        j        k    r|                                 }|du rdS t          | j                  dk    S )&z
        After WebSocket handshake has been completed, this procedure will do
        all subsequent processing of incoming bytes.
        Nr   r      p   r   r   r}      z$RSV = {} and no extension negotiatedFzunmasked client-to-server framezmasked server-to-client frame   zfragmented control frame}   z.control frame with payload length > 125 octets)r   	   r   z&control frame using reserved opcode {}r   z/received close control frame with payload len 1z&received compressed control frame [{}]r   r}   r   z#data frame using reserved opcode {}z;received continuation data frame outside fragmented messagezDreceived non-continuation data frame while inside fragmented messagez;received continuation data frame with compress bit set [{}]~   r   r'  !Hz=invalid data frame length (not using minimal length encoding)!Q    z!invalid data frame length (>2^63)i   rL   )r?   r   current_framerv  r+  r5   r2  r3  r   r   EXTENSION_NAMEinside_messager:  structunpackr   r   current_frame_maskerr   rs   onFrameBeginrx   pointerprocessonFrameData
onFrameEnd)rS   buffered_lenb	frame_fin	frame_rsvframe_opcodeframe_maskedframe_payload_len1mask_lenframe_header_lenr   frame_payload_len
frame_maskrestr   rx   r   frs                     r9   r  zWebSocketProtocol.processDatam  s   
 49~~ % q   IaLX!O	X!O	 4x IaL !DQ%&X"
 >>/;	Q334Z4a4abk4l4lmm )#(5 <( %T-K %T` %//0QRR %$u |, %T5R %Wc %//0OPP %$u  !## % )334NOO )#(5 *C//334dee )#(5 $:55334\4c4cdp4q4qrr )#(5
 $q((-?1-D-D334eff )#(5 /;	Q334\4c4cdhd|  eL  5M  5M  N  N )#(5 $944334Y4`4`am4n4noo )#(5  . )<13D3D334qrr )#(5 * )|q/@/@334z{{ )#(5 /;	QSWSf334q4x4xy}  zR  za  5b  5b  c  c )#(5   ! HH H%++'(8|$$'3..',x'7$$'3..',x'7$$#M222
  #333 A *S00,2M$	!APQE'@R,S,STU,V),s22#778wxx -',uQ+s22,2M$	!APQE'@R,S,STU,V),/AAA#778[\\ -',u,u44#778wxx -',uQ,>) "&J# %)YqQw%7
Q# D(9A(=(=$.(=4EjRc4d4d114AOO1 !%	!""DI *5\5>5>5F5?	*A *AD& %%''' -1GS^^a5GG !5u %,t/H/P/P/R/RRDt##y$' Idee,		y%	zz 3;;DAA  !!'**BU{{u (0022d6H6OOO__&&;; 5 ty>>A%%rL   c                 L   | j         j        dk    r	g | _        dS | j        sd| _        | j        1| j         j        dk    r!d| _        | j                                         nd| _        | j         j        t          j	        k    r/| j
        r(| j                                         d| _        d| _        nd| _        | j        r| j                            d           |                     | j         j        t          j        k               |                     | j         j                   dS )z-
        Begin of receive new frame.
        r  TNr   F)TTr   r   r   )r  ru   control_frame_datar  rv  rw   _isMessageCompressedstart_decompress_messager"   MESSAGE_TYPE_TEXTr   r}  rQ   "utf8validateIncomingCurrentMessageutf8validateLastr
  r   _onMessageBeginMESSAGE_TYPE_BINARY_onMessageFrameBeginrx   rR   s    r9   r  zWebSocketProtocol.onFrameBegin\  s8    $q((&(D### & i&*# +7D<N<RVW<W<W04D-,EEGGGG05D- %,0A0SSSX\XqS&,,...>BD;,>D))>CD; & @'--.>??? $$T%7%>BSBg%ghhh%%d&8&?@@@@@rL   c                    | j         j        dk    r| j                            |           dS | j        rct          |          }| j                            d|t          |                     | j	        
                    |          }t          |          }nt          |          }|}|}| j        t          j        k    r*| j        xj        |z  c_        | j        xj        |z  c_        | j        ra| j                            |          | _        | j        d         s5|                     d                    | j        d                             rdS |                     |           dS )	z1
        New data received within frame.
        r  zRX compressed [length]: octets)legnthr  r   zQencountered invalid UTF-8 while processing text message at payload octet index {}r<   FN)r  ru   r  r   r  r?   r   r   r   rv  decompress_message_datar  r"   r  rw  r]   r^   r  r}  r-  r  r.  r5   _onMessageFrameData)rS   r   compressedLenuncompressedLenls        r9   r  zWebSocketProtocol.onFrameData  s    $q((#**733333 ( $ #G4(,W55     2JJ7SS"%g,,LL !"#z.999!>>-O>>!88OK88 6 %(,(:(C(CG(L(L%,Q/ %,,  .A  .H  .H  IM  I^  _`  Ia  .b  .b  c  c %$u$$W-----rL   c                 0   | j         j        dk    r=| j        r |                     | j         | j                   |                                  nA| j        t          j        k    r| j	        xj
        dz  c_
        | j        r |                     | j         | j                   |                                  | j        r| j        r|                                  | j         j        r| j        r| j                                         | j        rB| j        d         s5|                     d                    | j        d                             rdS | j        t          j        k    r| j	        xj        dz  c_        |                                  d| _        d| _         dS )z(
        End of frame received.
        r  r}   zTUTF-8 text message payload ended within Unicode code point at payload octet index {}r<   FN)r  ru   r   r  r  processControlFramer  r"   r  rw  r_   r   _onMessageFrameEndrW  r   _cancelAutoPingTimeoutCallrv   r  rv  end_decompress_messager  r  r.  r5   r`   _onMessageEndr  rR   s    r9   r  zWebSocketProtocol.onFrameEnd  s    $q((~ M 2D4KLLL$$&&&&z.999!99Q>99~ E 2DODDD##%%%' 2D,L 2 //111!% , , F,CCEEE : )03 )00  2H  2O  2O  PT  Pe  fg  Ph  2i  2i  j  j )#(5:!2!===%??1D??""$$$&+#!rL   c                 X   d                     | j                  }d| _        | j        j        dk    rfd}d}t	          |          }|dk    r3t          j        d|dd                   d         }|dk    r
|dd         }|                     ||          rdS n| j        j        d	k    r|                     |           nk| j        j        d
k    rY| j	        r;	 || j	        k    rt          j        d|dd                   d         }t          j        d|dd                   d         }t          j                    }t          ||z
  dz            }|                     |||||           | j        r| j                                         d| _	        d| _        d| _        | j        r/| j        j                            | j        | j                  | _        n| j                            d           n!#  | j                            d           Y nxY w|                     |           n	 dS )z>
        Process a completely received control frame.
        rL   Nr   r}   r  r   r   Fr  r   >Q>Lr   i@B z)Auto ping/pong: received non-pending pongT)r	  r  r  ru   r?   r  r  r>  _onPingr  timetime_nsintrU  rW  r1  r  r   r2  r  r5  _sendAutoPingr  r   r\  _onPong)	rS   r   r  r;  llrQ  rR  rS  rT  s	            r9   r  z%WebSocketProtocol.processControlFrame  sJ    ((4233"& $))DIWBAvv}T71Q3<88;66 'I  y11 u
 &!++LL!!!! &",, # OO$"666$*M$$D$DQ$G	 $*=wqt}#E#Ea#H(,#&	(AU'J#K#K	8]HV]^^^3 > 4;;===/3,3703700 7;|7R7]7] $ 5 $ 28 8D4
 &QRRROHMM"MNNNNN LL!!!!
 ts   DG2 2HrL   Tc	           	         |t                    dk     r0t          d                    |t                                        |}	d                    fdt	          |t                    z            D                       d|t                    z           z   }
nt                    }	}
d}|r|dz  }||dz  d	z  z  }||dz  z  }d}|s&| j        j        s| j        s| j        j        rp| j        ri|dz  }|s*t          j
        d
t          j        d                    }|}nd}|	dk    r-| j        r&t          ||	          }|                    |
          }n|
}nd}|
}d}|	dk    r||	z  }nQ|	dk    r|dz  }t          j
        d|	          }n0|	dk    r|dz  }t          j
        d|	          }nt          d          d                    |                    dd          |                    dd          |||g          }|dv r| j        xj        dz  c_        | j        r,t)          ||||	|          }|                     ||||           |                     |||           dS )aO  
        Send out frame. Normally only used internally via sendMessage(),
        sendPing(), sendPong() and sendClose().

        This method deliberately allows to send invalid frames (that is frames
        invalid per-se, or frames invalid because of protocol state). Other
        than in fuzzing servers, calling methods will ensure that no invalid
        frames are sent.

        In addition, this method supports explicit specification of payload
        length. When payload_len is given, it will always write that many
        octets to the stream. It'll wrap within payload, resending parts of
        that when more octets were requested The use case is again for fuzzing
        server which want to sent increasing amounts of payload data to peers
        without having to construct potentially large messages themselves.
        Nr}   zJcannot construct repeated payload with length {} from payload of length {}rL   c                     g | ]}S rq   rq   ).0_r   s     r9   
<listcomp>z/WebSocketProtocol.sendFrame.<locals>.<listcomp>@  s    OOOq7OOOrL   r   r  r   r   !I    r    r  r  r  r  r  invalid payload lengthbigr  )r?   r:  r5   r	  ranger2  r3  r   r   r  packrandomgetrandbitsr   r   r  to_bytesrw  rZ   r   rs   r  r  )rS   ru   r   rv   rw   ry   r  r  r  r  plb0b1mvmaskerplmelr   r  s     `                r9   	sendFramezWebSocketProtocol.sendFrame#  s   2 "7||a l s st  BE  FM  BN  BN  !O  !O  P  P  PAOOOOE+W2M,N,NOOOPPSZ[v\gjmnujvjv\v[vSwwBBGAB  	6NB
sQw1n
fsl  	- 	$2G 	T\Mb 	gkg| 	&LB 
 {4);B)?)?@@ 1uuu*433nnR(( BC88!GBB&[[#IBT1%%BB$$$#IBT1%%BB4555hhAu--r{{1e/D/Db"cRSSY55:55> 	O%fc34@@KOOK+xNNN 	c4*****rL   c                    | j         t          j        k    rdS |rPt          |          }|dk    r"t	          d                    |                    |                     d|           dS |                     d           dS )z]
        Implements :func:`autobahn.websocket.interfaces.IWebSocketChannel.sendPing`
        Nr  z@invalid payload for PING (payload length must be <= 125, was {})r  ru   r   ru   r  r"   r  r?   r:  r5   r!  rS   r   r  s      r9   sendPingzWebSocketProtocol.sendPing  s     :*555F 	%GA3ww b i ijk l lmmmNN!WN55555NN!N$$$$$rL   c                 r   | j                             d           d | _        t          j                    | _        | xj        dz  c_        d                    t          j	        d| j                  t          j	        d| j                  t          j        | j        dz
            g          | _        |                     | j                   | j        re| j                             d| j        t!          | j                             | j        j                            | j        | j                  | _        d S d S )	Nz+Auto ping/pong: sending ping auto-ping/pongr}   rL   r  r  r   z@Expecting pong in {seconds} seconds for auto-ping ({size} bytes))secondsrL  )r   r   r  r  r  r  r  r	  r  r  osurandomr   r  r'  r   r?   r2  r  r5  rX  rW  rR   s    r9   r  zWebSocketProtocol._sendAutoPing  s(   DEEE#' #'<>> 1$"xxT4;S)T)T)/T4;R)S)S)+D4E4J)K)K)M  N  N 	d*+++ 		HNNR,-..    
 (,|'B'M'M$&( (D$$$		 		rL   c                 z   | j                             d           | j                                         d| _        d| _        | j        r | j                                         d| _        | j        rK| j                             d           | j        j        	                    | j        | j
                  | _        dS dS )z
        When data is received from client, use it in leu of timely PONG response - cancel pending timeout call
        that will drop connection. See https://github.com/crossbario/autobahn-python/issues/1327
        z3Cancelling autoPingTimeoutCall due to incoming dataNzScheduling auto-ping/pong)r   r   rW  r1  r  r  r   r2  r  r5  r  rR   s    r9   r  z,WebSocketProtocol._cancelAutoPingTimeoutCall  s    
 	LMMM '')))#' ## 	,$++---'+D$   	HNN6777'+|'B'M'M%"( (D$$$	 	rL   c                    | j         t          j        k    rdS |rPt          |          }|dk    r"t	          d                    |                    |                     d|           dS |                     d           dS )z]
        Implements :func:`autobahn.websocket.interfaces.IWebSocketChannel.sendPong`
        Nr  z@invalid payload for PONG (payload length must be <= 125, was {})r   r#  r$  r%  r&  s      r9   r  zWebSocketProtocol.sendPong  s     :*555F 	&GA3ww b i ijk l lmmmNN"gN66666NN"N%%%%%rL   c                    | j         t          j        k    r| j                            d           dS | j         t          j        k    r| j                            d           dS | j         t          j        t          j        fv rt          d          | j         t          j	        k    rd}||t          j        d|          z  }|||z  }|                     d|           t          j        | _         | | _        || _        || _        | j        r<| j        d	k    r3| j        j                            | j        | j                  | _        dS dS dS t          d
          )z
        Send a close frame and update protocol state. Note, that this is
        an internal method which deliberately allows not send close
        frame with invalid payload.
        z3ignoring sendCloseFrame since connection is closingz7ignoring sendCloseFrame since connection already closedz+cannot close a connection not yet connectedrL   Nr  r   r#  r   r'  )r  r"   r/  r   r   r9  rE  rD  r:  r  r  r  r!  r~  r  r  r   r2  r  r5  rJ  r0  )rS   r  r&  r#  r   s        r9   r8  z WebSocketProtocol.sendCloseFrame  sn    :*888HNNPQQQQQZ,999HNNTUUUUUZ-DFWFhiiiIJJJZ,777 G6;tT222%:%NN!WN555 +8DJ")kDO #'D$.D!  4#=#A#A151L1W1W.02 2... #A#A M***rL   c                    |~t          |          t          k    r/t          d                    t          |                              |dk    r1d|cxk    rdk    s$n t          d                    |                    |i|t          d          t          |          t          k    r/t          d                    t          |                              t          |d	          }nd}|                     ||d
           dS )z^
        Implements :func:`autobahn.websocket.interfaces.IWebSocketChannel.sendClose`
        Nz5invalid type '{}' for close code (must be an integer)r   i  i  z9invalid close code {} (must be 1000 or from [3000, 4999])zclose reason without close codez)reason must be of type unicode (was '{}')r$  Fr%  )typer  r:  r5   strr   r8  )rS   r  r  r&  s       r9   	sendClosezWebSocketProtocol.sendClose  s    DzzS   W ^ ^_cdh_i_i j jkkk t||TT%9%9%9%9T%9%9%9%9 [ b bcg h hiii| ABBBF||s"" K R RSWX^S_S_ ` `aaa(55JJJ*eLLLLLrL   c                 h   | j         t          j        k    rdS | j        t          j        k    rt          d          |rt          j        nt          j        | _        t          j	        | _        | j
        #|s!d| _        | j
                                         nd| _        | j        xj        dz  c_        dS )za
        Implements :func:`autobahn.websocket.interfaces.IWebSocketChannel.beginMessage`
        Nz?WebSocketProtocol.beginMessage invalid in current sending stateTFr}   )r  r"   r  rz  ry  r:  r  r  send_message_opcodeSEND_STATE_MESSAGE_BEGINrv  send_compressedstart_compress_messagerw  r[   )rS   r   r  s      r9   beginMessagezWebSocketProtocol.beginMessage  s     :*555F ?/AAA]^^^LT#}#4#H#HZkZ} +D #//#'D $;;====#(D 33q83333rL   c                    | j         t          j        k    rdS | j        t          j        t          j        fvr't          d                    | j                            t          |          t          k    s|dk     s|dk    rt          d          || _
        | j        xj        dz  c_        | j        j        s| j        s| j        j        r4| j        r-t#          j        dt'          j        d                    | _        nd| _        | j        r(|dk    r"| j        rt/          | j        |          | _        nt3                      | _        d}| j        t          j        k    r+|| j        d	z  z  }| j        r|d
z  }t          j        | _        n	 d}| j        r|d	z  }| j        }nd}d}|dk    r||z  }nQ|dk    r|dz  }t#          j        d|          }n0|dk    r|dz  }t#          j        d|          }nt          d          d                    |                    dd          |                    dd          ||g          }|                     |           t          j        | _        dS )zf
        Implements :func:`autobahn.websocket.interfaces.IWebSocketChannel.beginMessageFrame`
        NzIWebSocketProtocol.beginMessageFrame invalid in current sending state [{}]r   r  z&invalid value for message frame lengthr}   r  r  r  @   rL   r  r  r  r  r  r  r  r  ) r  r"   r  rz  r5  SEND_STATE_INSIDE_MESSAGEr:  r5   r0  r  send_message_frame_lengthrw  rZ   r2  r3  r   r   r  r  r  r  send_message_frame_maskr   r   send_message_frame_maskerr   r4  r6  r	  r  r  SEND_STATE_INSIDE_MESSAGE_FRAME)rS   rx   r  r  r  r   headers          r9   beginMessageFramez#WebSocketProtocol.beginMessageFrame/  s    :*555F ?#4#MO`Oz"{{{gnnoso~  A  A  A<<3&1**9K0K0KDEEE)/&11Q611% 	0$*? 	0T\EZ 	0_c_t 	0 ,2;tV=OPR=S=S+T+TD((
 ,0D( ' 	=FQJJ4>J->t?[]c-d-dD**-:__D*
 ?/HHH$*S00B# #l"/IDOO ' 	&LB-BBBS==&LBBv#IBT6**BB)))#IBT6**BB4555 2;;q%00"++a2G2GRPQQf ,KrL   c                    | j         t          j        k    rdS | j        s"| j        xj        t          |          z  c_        | j        xj        t          |          z  c_        | j        t          j	        k    rt          d          t          |          }| j                                        |z   | j        k    r2| j        | j                                        z
  }||z
   }|d|         }n(|}| j        | j                                        z
  |z
  }|}| j                            |          }|                     ||           | j                                        | j        k    rt          j        | _        |S )zi
        Implements :func:`autobahn.websocket.interfaces.IWebSocketChannel.sendMessageFrameData`
        NzGWebSocketProtocol.sendMessageFrameData invalid in current sending state)r  )r  r"   r  r6  rw  rY   r?   rX   rz  r?  r:  r>  r  r<  r  r  r;  )rS   r   r  rlr  r  r  r  s           r9   sendMessageFrameDataz&WebSocketProtocol.sendMessageFrameData  so    :*555F# 	E44GD4466#g,,F66?/OOOefff\\)1133b84;YYY.1O1W1W1Y1YYA!V9D!BBA1D4R4Z4Z4\4\\_``DB ,44R88 	c%%% )1133t7UUU/IDO rL   c                    | j         t          j        k    rdS | j        r<| j                                        }| j        xj        t          |          z  c_        nd}| 	                    d|d           t          j
        | _        dS )z_
        Implements :func:`autobahn.websocket.interfaces.IWebSocketChannel.endMessage`
        NrL   r   T)ru   r   rv   )r  r"   r  r6  rv  end_compress_messagerw  rX   r?   r!  ry  rz  r   s     r9   
endMessagezWebSocketProtocol.endMessage  s     :*555F  	.CCEEG::c'llJ::: Gad;;;+=rL   c                 *   | j         t          j        k    rdS | j        r<| j        xj        t          |          z  c_        | j                            |          }| 	                    t          |                     | 
                    ||           dS )ze
        Implements :func:`autobahn.websocket.interfaces.IWebSocketChannel.sendMessageFrame`
        N)r  r"   r  r6  rw  rY   r?   rv  compress_message_datarA  rD  )rS   r   r  s      r9   sendMessageFramez"WebSocketProtocol.sendMessageFrame  s     :*555F 	N44GD44.DDWMMGs7||,,,!!'400000rL   c                    t          |          t          k    s*J d                    t          |                                t          |          t          k    s*J d                    t          |                                |Bt          |          t          k    s*J d                    t          |                                t          |          t          k    s*J d                    t          |                                t          |          t          k    s*J d                    t          |                                | j        t          j        k    rt          d          | j	        r| j	        
                    d           |rd	}nd
}| j        xj        d
z  c_        | j        |sd}| j                                         | j        xj        t!          |          z  c_        | j                            |          }| j                                        }	d                    ||	g          }t!          |          }
| j        xj        |
z  c_        n;d}t!          |          }
| j        xj        |
z  c_        | j        xj        |
z  c_        d| j        cxk     r|
k     rNn nKd| _        d                    |
| j                  }| j                            |           t3          |          ||}n| j        dk    r| j        }nd}|t!          |          |k    r|                     ||||rdnd           dS |d
k     r"t9          d                    |                    t!          |          }d}d}d}|sd||z   }||k    rd}|}|r)|                     ||||         |||rdnd           d}n!|                     d|||         ||           ||z  }|bdS dS )z`
        Implements :func:`autobahn.websocket.interfaces.IWebSocketChannel.sendMessage`
        z,"payload" must have type bytes, but was "{}"z,"isBinary" must have type bool, but was "{}"Nz/"fragmentSize" must have type int, but was "{}"z("sync" must have type bool, but was "{}"z1"doNotCompress" must have type bool, but was "{}"z$Attempt to send on a closed protocolr  r   r}   TrL   Fr   zQtried to send WebSocket message with size {} exceeding payload limit of {} octetsr   )ru   r   r  rw   z1payload fragment size must be at least 1 (was {}))ru   r   rv   r  rw   )ru   r   rv   r  )r0  bytesr5   boolr  r  r"   r  r    r
  r   rw  r[   rv  r7  rY   r?   rI  rF  r	  rX   r   r   r   r\  r   r   r!  r:  )rS   r   r   fragmentSizer  r  ru   sendCompressedpayload1payload2r  emsgpfsr  r   r  firstr  s                     r9   r  zWebSocketProtocol.sendMessage  sg    G}}%%%'U'\'\]abi]j]j'k'k%%%H~~%%%'U'\'\]abj]k]k'l'l%%%#tL'9'9S'@'@'@BsBzBz{  AM  |N  |N  CO  CO'@'@'@DzzT!!!#M#T#TUYZ^U_U_#`#`!!!M""d***,_,f,fgklygzgz,{,{***:*555EFFF 	5%%m444  	FFF33q833 #//!N$;;===44GD44/EEgNNH/DDFFHhh(344Gg,,K::kI::: #Ng,,K44C44::kI::t)7777K7777748D1fmmny{  |V  W  WDHMM$&t,,, #CC$q((+ ;#g,,#--NN&'~Jd!!cdNeeeee
 Qww S Z Z[^ _ _```GAADE 
Gq55DA XNN&'!A#,DW[fta{ababz{N|||!EENN!WQqS\tRVNWWWS  
 
 
 
 
rL   c                    g }d |                     d          D             }|D ]d}|dk    rZd |                     d          D             }t          |          dk    r&|d                                         }i }|dd         D ]}	d	 |	                     d
          D             }	|	d                                         }
t          |	          dk    rrd
                    |	dd                   }|rRt          |          dk    r|d         dk    r
|dd         }t          |          dk    r|d         dk    r
|dd         }nd}|
|vrg ||
<   ||
                             |           |                    ||f           c	 f|S )z<
        Parse the Sec-WebSocket-Extensions header.
        c                 P    g | ]#}t          |                                          $S rq   r1  r   r  xs     r9   r  z<WebSocketProtocol._parseExtensionsHeader.<locals>.<listcomp>7	  s&    :::1AGGII:::rL   , c                 6    g | ]}|                                 S rq   r   rX  s     r9   r  z<WebSocketProtocol._parseExtensionsHeader.<locals>.<listcomp>:	  s     777Qqwwyy777rL   ;r   r}   Nc                 6    g | ]}|                                 S rq   r]  rX  s     r9   r  z<WebSocketProtocol._parseExtensionsHeader.<locals>.<listcomp>?	  s     ===1QWWYY===rL   ="T)splitr?   r.   r	  r   )rS   r@  removeQuotes
extensionsextsr  ext	extensionparamspr   r   s               r9   _parseExtensionsHeaderz(WebSocketProtocol._parseExtensionsHeader2	  s    
::S(9(9::: 	 	ABww77!''#,,777s88a<< #AIF W 2 2=====djjllq66A::$'HHQqrrUOOE+ 7#&u::>>eAh#oo,1!""IE#&u::>>eBi36F6F,1#2#JE$(Ef,,*,F3Ks**51111%%y&&9::::rL   )F)FN)rL   Tr   NNNFrP   )NNF)NNFF)FNFFr   )hrn   ro   rp   r{   rZ  SUPPORTED_SPEC_VERSIONSSUPPORTED_PROTOCOL_VERSIONSSPEC_TO_PROTOCOL_VERSIONPROTOCOL_TO_SPEC_VERSIONDEFAULT_SPEC_VERSION	_WS_MAGICr  r  r  r9  rD  r/  r  rE  ry  r5  r;  r?  r,  CLOSE_STATUS_CODE_GOING_AWAYrh  "CLOSE_STATUS_CODE_UNSUPPORTED_DATACLOSE_STATUS_CODE_RESERVED1CLOSE_STATUS_CODE_NULLr  rk  "CLOSE_STATUS_CODE_POLICY_VIOLATIONrb  %CLOSE_STATUS_CODE_MANDATORY_EXTENSION CLOSE_STATUS_CODE_INTERNAL_ERROR!CLOSE_STATUS_CODE_SERVICE_RESTART!CLOSE_STATUS_CODE_TRY_AGAIN_LATERCLOSE_STATUS_CODE_UNASSIGNED1&CLOSE_STATUS_CODE_TLS_HANDSHAKE_FAILEDr*  CONFIG_ATTRS_COMMONCONFIG_ATTRS_SERVERCONFIG_ATTRS_CLIENTrT   propertyr   r   r   r   r   r   r   r   r   r  r  r  r  r  r>  r6  rG  rJ  rU  rX  r4  r   ra  r+  r.  ro  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r!  r'  r  r  r  r8  r2  r8  rA  rD  rG  rJ  r  rk  rq   rL   r9   r"   r"   j  sE         DBBB $%b' %&1!QSY[acdd $&2
 
 8I
 "   LMJ   !&'#
  $%#' '+$)-&"&!U'+$_(,%%)-&(,%,0)'+$I(,%(,%$(!-1* G":">"B"D"C"D"C"G"B"C"C
"E 1: : :"1 1 1: : :Q Q Q '8,<#= ' ' ' X'3 3 3+ + +` ` `&0 0 0   . . .! ! !0
 
 
	# 	# 	#
 
 
	
 	
 	
a+ a+ a+Fp p p + + +.i i i c c c( ( (u u u u0/ / / %A \ \ \ \6  (  ,+ + +t t tl2[ 2[ 2[j	
 	
 	


 

 


 
 
$
 
 
*  (- (- (-T\ \ \X X X  # # #>'2 '2 '2 '2RF F Fm& m& m&^'A 'A 'AR%. %. %.N*" *" *"XI I IZ "]+ ]+ ]+ ]+~% % % %  2  .& & & &)+ )+ )+ )+VM M M M:9 9 9 92SL SL SLj) ) ) )V> > >,1 1 1 1  #!%"'] ] ] ]~     rL   r"   c                       e Zd ZdZd ZdS )PreparedMessagez
    Encapsulates a prepared message to be sent later once or multiple
    times on one or more WebSocket connections.
    This can be used for optimizing Broadcast/PubSub.
    c                 f   |s|| _         || _        || _        t          |          }|rdnd}|rVd}t	          j        dt          j        d                    }|dk    r|}	n*t          ||          	                    |          }	nd}d}|}	d}
|dk    r||z  }nQ|d	k    r|d
z  }t	          j        d|          }
n0|dk    r|dz  }t	          j        d|          }
nt          d          d                    |                    dd          |                    dd          |
||	g          | _        dS )a  
        Ctor for a prepared message.

        :param payload: The message payload.
        :type payload: str
        :param isBinary: Provide `True` for binary payload.
        :type isBinary: bool
        :param applyMask: Provide `True` if WebSocket message is to be masked (required for client to server WebSocket messages).
        :type applyMask: bool
        :param doNotCompress: Iff `True`, never compress this message. This
            only applies when WebSocket compression has been negotiated on the
            WebSocket connection. Use when you know the payload incompressible
            (e.g. encrypted or already compressed).
        :type doNotCompress: bool
              r  r  r  r   rL   r  r  r  r  r  r  r  r  r}   r  N)r   r  r  r?   r  r  r  r  r   r  r:  r	  r  r  )rS   r   r   r   r  r  r  r  ry   r  r   s              r9   rT   zPreparedMessage.__init___	  se      	# #DL"DK*LL  (;lll  	B;tV%7%;%;<<DAvv'a0088AABDC 88!GBB&[[#IBT1%%BB$$$#IBT1%%BB4555 88R[[E%:%:BKK5<Q<QSUW[]`$abbrL   Nrz   rq   rL   r9   r  r  X	  s2         =c =c =c =c =crL   r  c                       e Zd ZdZddZdS )r#   z
    Mixin for
    :class:`autobahn.websocket.protocol.WebSocketClientFactory` and
    :class:`autobahn.websocket.protocol.WebSocketServerFactory`.
    Fc                 6    | j          }t          ||||          S )a$  
        Prepare a WebSocket message. This can be later sent on multiple
        instances of :class:`autobahn.websocket.WebSocketProtocol` using
        :meth:`autobahn.websocket.WebSocketProtocol.sendPreparedMessage`.

        By doing so, you can avoid the (small) overhead of framing the
        *same* payload into WebSocket messages multiple times when that
        same payload is to be sent out on multiple connections.

        :param payload: The message payload.
        :type payload: bytes
        :param isBinary: `True` iff payload is binary, else the payload must be
            UTF-8 encoded text.
        :type isBinary: bool
        :param doNotCompress: Iff `True`, never compress this message. This
            only applies when WebSocket compression has been negotiated on the
            WebSocket connection. Use when you know the payload incompressible
            (e.g. encrypted or already compressed).
        :type doNotCompress: bool

        :returns: An instance of :class:`autobahn.websocket.protocol.PreparedMessage`.
        )r3  r  )rS   r   r   r  r   s        r9   prepareMessagezWebSocketFactory.prepareMessage	  s"    . %	w)]KKKrL   Nrl  )rn   ro   rp   r{   r  rq   rL   r9   r#   r#   	  s8         L L L L L LrL   r#   a1  <!DOCTYPE html>
<html>
   <head>
      {}
      <style>
         body {{
            color: #fff;
            background-color: #027eae;
            font-family: "Segoe UI", "Lucida Grande", "Helvetica Neue", Helvetica, Arial, sans-serif;
            font-size: 16px;
         }}

         a, a:visited, a:hover {{
            color: #fff;
         }}
      </style>
   </head>
   <body>
      <h1>AutobahnPython {}</h1>
      <p>
         I am not Web server, but a <b>WebSocket Endpoint</b>.
      </p>
      <p>
         You can talk to me using the <a href="http://tools.ietf.org/html/rfc6455">WebSocket</a> protocol.
      </p>
      <p>
         For more information, please see:
         <ul>
            <li><a href="http://crossbar.io/autobahn">Autobahn</a></li>
         </ul>
      </p>
   </body>
</html>
c            
           e Zd ZdZej        ej        z   Zdede	e
e         ee
e         eeef         f         f         fdZd Zd Zd Zd Zd	 ZddZddZd Zd ZddZdS )r$   z4
    Protocol base class for WebSocket servers.
    requestr   c                 d    | j                             dt          | j                  |           dS )am  
        Callback fired during WebSocket opening handshake when new WebSocket client
        connection is about to be established.

        When you want to accept the connection, return the accepted protocol
        from list of WebSocket (sub)protocols provided by client or `None` to
        speak no specific one or when the client protocol list was empty.

        You may also return a pair of `(protocol, headers)` to send additional
        HTTP headers, with `headers` being a dictionary of key-values.

        Throw :class:`autobahn.websocket.types.ConnectionDeny` when you don't want
        to accept the WebSocket connection request.

        :param request: WebSocket connection request information.

        :returns: You may return one of: ``None``: the connection is accepted with no specific WebSocket subprotocol,
            ``str``: the connection is accepted with the returned name as the WebSocket subprotocol, or
            ``(str, dict)``: a pair of subprotocol accepted and HTTP headers to send to the client.
            You can also return a Deferred/Future that resolves/rejects to the above.
        z{func}: request={request})r  r  N)r   r   r   	onConnectrS   r  s     r9   r  z!WebSocketServerProtocol.onConnect	  s/    , 	29O9OY`aaatrL   c                     | j                             dt          | j                  | j                   t
                              |            | j        xj        dz  c_        dS )a1  
        Called by network framework when new transport connection from client was
        accepted. Default implementation will prepare for initial WebSocket opening
        handshake. When overriding in derived class, make sure to call this base class
        implementation *before* your code.
        ,{func}: connection accepted from peer {peer}r  rZ  r}   N)r   r   r   r  rZ  r"   r2  countConnectionsrR   s    r9   r  z'WebSocketServerProtocol._connectionMade
  si     	E"4#788ty 	 	J 	J 	J))$///%%*%%%%rL   c                     | j                             dt          | j                  | j        t          |                     t                              | |           | j        xj        dz  c_        dS )a!  
        Called by network framework when established transport connection from client
        was lost. Default implementation will tear down all state properly.
        When overriding in derived class, make sure to call this base class
        implementation *after* your code.
        7{func}: connection lost to peer {peer}: reason={reason}r  rZ  r  r}   N)	r   r   r   r  rZ  r   r"   r2  r  ri  s     r9   r  z'WebSocketServerProtocol._connectionLost
  sw     	P"4#788tyQVW]Q^Q^ 	 	` 	` 	`))$777%%*%%%%rL   c                      t          d          )NzAutobahn isn't a proxy serverr  rR   s    r9   r  z+WebSocketServerProtocol.processProxyConnect
  s    7888rL   c                      j                             d          }|dk    r| j                            dt	           j                  t          |                      j         d|dz             _         j                            d j                   	 t           j                  \   _	         _
        }n?# t          $ r2}                     d	                    |                    cY d}~S d}~ww xY wd
 j
        v rN j        rGd  j
        d
                             d          D             }| j         d         }|d          _         j                            d j	                    j                            d j
                    j	                                        }t#          |          dk    r-                     d                     j	                            S |d                                         dk    r/                     d                    |d                   d          S |d                                                             d          }t#          |          dk    s|d         dk    s
|d         dvr/                     d                    |d                   d          S |d                                          _        	 t)          j         j                  \  }}	}
}}}|dk    s|	dk    r	 |dk    r(                     d                    |                    S |
 _        t)          j        |           _        nG#                       d                    |d                                                             cY S xY wd  j
        vr                     d!          S |d          dk    r                     d"          S  j
        d                                           _         j                            d#          dk    rW j                            d$          s< j                            d#d          \  }}	 t9          t;          |                                                    }nj# t<          $ r]                      d%                    t;          |                                          t;           j                                      cY S w xY w j        j         rW| j        j         k    rF                     d&                    |t;           j                   j        j                             S n j                            d'           | _        d( j
        vr j!        rd) j        v r4t#           j        d)                   dk    rtD          j#        $                     j        d)         d                   }|%                                &                                '                                }d* j        v rrt#           j        d*                   dk    rTt9           j        d*         d                   } j                            d+||,            (                    ||           n` j                            d-|.            )                    |           n. j                            d/            (                                  *                    d01           dS                      d2d3          S d0} j
        d(                             d          D ]0}|                                +                                d4k    rd5} n1|s3                     d6                     j
        d(                             S d7 j
        vr                     d8          S d0} j
        d7                             d          D ]0}|                                +                                d(k    rd5} n1|s3                     d9                     j
        d7                             S d: j
        vr/ j                            d;                                d<          S  j                            d=           |d:         dk    r                     d>          S 	 t9           j
        d:                   }nC# t<          $ r6                      d?                     j
        d:                             cY S w xY w| j,        vrut[           j,                  }|.                                 d/                    d@ |D                       }                     dA                    ||          dBdC|fg          S | _0        dD j
        v rldE  j
        dD                             d          D             }i }|D ]5}||v r*                     dF                    |                    c S d||<   6| _1        ng  _1         j0        dGk     rdH}ndI}d _2        | j
        v r||         dk    r                     dJ          S  j
        |                                          _2        	 tg           j2                  }n?# t<          $ r2}                     dK                    |                    cY d}~S d}~ww xY wd5}nd0}|r|dLk    r j        j4        rd5}n;tk          | j        j6        rdMndN j        j         p j        j7         j8                  }|s-                     dO                     j2                            S dP j
        vr                     dQ          S |dP         dk    r                     dR          S  j
        dP                                         } t#          |           dSk    r(                     dT                    |                     S | dUd         dVk    r(                     dW                    |                     S | ddU         D ]1}|dXvr+                     dY                    ||                     c S 2g  _9        dZ j
        v rF|dZ         dk    r                     d[          S  :                     j
        dZ                    _9         j         |dz   d          _         |  _;         j<        dk    r. j        j=         j<        k    r                     d\d]^           dS t}           j         j
         j         j         j         j0         j2         j1         j9        	  	        }!t          j@         jA        |!          }" fd_}#t          jB        |" jC        |#           dS  jD        rȉ j                             d`          }$|$dk    r j                            da            jD        rk j                            db jE        c            F                     jE        G                    dd                     d5 _H         *                                 dS  j                            de           dS dS dS )fzJ
        Process WebSocket opening handshake request from client.
           

r   z?{func} found end of HTTP request header at byte {end_of_header})r  end_of_headerNr   z received HTTP request:

{data}

)r   z@Error during parsing of HTTP status line / request headers : {0}zx-forwarded-forc                 6    g | ]}|                                 S rq   r]  rX  s     r9   r  z<WebSocketServerProtocol.processHandshake.<locals>.<listcomp>;
  s     ```1QWWYY```rL   rZ  9received HTTP status line in opening handshake : {status}status6received HTTP headers in opening handshake : {headers}headersr<   z!Bad HTTP request status line "{}"GETzHTTP method "{}" not allowedi  r   /HTTPr}   )z1.1Unsupported HTTP version "{}"i  r[  z;HTTP requested resource contains a fragment identifier "{}"z0Bad HTTP request resource - could not parse "{}"r8   z5HTTP Host header missing in opening handshake requestzDHTTP Host header appears more than once in opening handshake requestr~   ]z*invalid port "{}" in HTTP Host header "{}"zHport {} in HTTP Host header "{}" does not match server listening port {}zOskipping opening handshake port checking - neither WS URL nor external port setupgraderedirectafterzvHTTP Upgrade header missing : render server status page and meta-refresh-redirecting to {url} after {duration} seconds)r6   durationz6HTTP Upgrade header missing : 303-redirecting to {url})r6   z7HTTP Upgrade header missing : render server status pageFr!  HTTP Upgrade header missingi  	websocketTzNHTTP Upgrade headers do not include "websocket" value (case-insensitive): "{}"
connectionHTTP Connection header missingzOHTTP Connection headers do not include "upgrade" value (case-insensitive): "{}"zsec-websocket-versionzHixie76 protocol detectedz=WebSocket connection denied - Hixie76 protocol not supported.zHybi protocol detectedzUHTTP Sec-WebSocket-Version header appears more than once in opening handshake requestzScould not parse HTTP Sec-WebSocket-Version header "{}" in opening handshake requestc                 ,    g | ]}t          |          S rq   )r1  rX  s     r9   r  z<WebSocketServerProtocol.processHandshake.<locals>.<listcomp>
  s    3331A333rL   z;WebSocket version {} not supported (supported versions: {})  zSec-WebSocket-Versionsec-websocket-protocolc                 P    g | ]#}t          |                                          $S rq   rW  rX  s     r9   r  z<WebSocketServerProtocol.processHandshake.<locals>.<listcomp>
  s&    lllS^^lllrL   zGduplicate protocol "{}" specified in HTTP Sec-WebSocket-Protocol headerr   zsec-websocket-originoriginzFHTTP Origin header appears more than once in opening handshake requestzHTTP Origin header invalid: {}r)   r,   r-   z5WebSocket connection denied: origin '{0}' not allowedzsec-websocket-keyz%HTTP Sec-WebSocket-Key header missingzQHTTP Sec-WebSocket-Key header appears more than once in opening handshake request   z:bad Sec-WebSocket-Key (length must be 24 ASCII chars) "{}"z==z4bad Sec-WebSocket-Key (invalid base64 encoding) "{}"z@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/zFbad character "{}" in Sec-WebSocket-Key (invalid base64 encoding) "{}"sec-websocket-extensionszXHTTP Sec-WebSocket-Extensions header appears more than once in opening handshake requestz%maximum number of connections reachedi  )r  c                    t          | j        t                    r,                    | j        j        | j        j                   d S j                            d|            j                            dt          j	        |                                          d
                    | j                  t          j                  S )Nz1Unexpected exception in onConnect ['{err.value}'])errz{tb})tbzInternal server error: {})r=   r   r   failHandshaker  r  r   r\  r   failure_format_tracebackr5   INTERNAL_SERVER_ERROR)r  rS   s    r9   forward_errorz?WebSocketServerProtocol.processHandshake.<locals>.forward_error_  s    !#)^<< G**39+;SY^LLLLL &Y_bcccf1OPS1T1TUUU#112M2T2TUXU^2_2_ao  bF   G   G  GrL   s   <policy-file-request/> z)received Flash Socket Policy File requestz+sending Flash Socket Policy File :
{policy})policyr   zNo Flash Policy File served. You might want to serve a Flask Socket Policy file on the destination port since you received a request for it. See WebSocketServerFactory.serveFlashSocketPolicy and WebSocketServerFactory.flashSocketPolicy)Ir   r   r   r   r   r  r   http_request_datar   r   r   r:  r  r5   r   rc  rZ  r?   r   http_request_urir	   urlparsehttp_request_pathparse_qshttp_request_paramshttp_request_hostendswithrsplitr  r1  r4   r2  externalPortr   	hyperlinkURL	from_textto_uri	normalizeto_textsendServerStatussendRedirectr4  r.   r   sortedreverser	  r   websocket_protocolsrA   r:   r   rK   isSecurer2   r   websocket_extensionsrk  _wskeyr   r  r   r   	as_futurer  r  succeedHandshaker   r   r  encoder  )%rS   r  r   r  	addressestrusted_addressesrC  vsr0   netlocpathri  queryfragmentr   rj  r2   r6   r  upgradeWebSocketr<  connectionUpgradecr   svsvs	protocolsppwebsocket_origin_header_keyorigin_tuplehave_originorigin_is_allowedr   r  r  r  flash_policy_file_requests%   `                                    r9   r  z(WebSocketServerProtocol.processHandshake 
  s    	':;;AHNN\ &t'< = =US`MaMa  c c c &*Y/A0A/A%BD"HNN6+    xM\]a]sMtMtJ%t'8:J:J x x x))*l*s*stu*v*vwwwwwwwwx
 !D$555$:Q5``0ABS0T0Z0Z[^0_0_```	$-t/F.F.G.G$H!-a0	 HNNK,     HNNH)     &,,..B2ww!||))*M*T*TUYUj*k*klll!u{{}}%%))*H*O*OPRSTPU*V*VX[\\\A$$S))B2ww!||r!u"Q%w2F2F))*I*P*PQSTUQV*W*WY\]]] %'qEKKMMD!tBG.QUQfBgBg?vuh R<<6R<< r>>--.k.r.rs{.|.|}}} *.&+0>%+@+@((t))*\*c*cdfghdidododqdq*r*rsssss T...))*abbb'!++))*pqqq%)%6v%>%D%D%F%FD"%**3//144T=S=\=\]`=a=a4/66sA>>A@s17799~~..DD! @ @ @--.Z.a.abefgfmfmfofobpbpbefjf|b}b}/ / @ @ @ @ @@
 <, vt|888#112|  3D  3D  EI  KN  OS  Oe  Kf  Kf  hl  ht  hA  3B  3B   C   C  C 9 HNN#tuuu)*&  111 > (R!T%===#dF^_iFjBkBknoBoBo  (m55d6Nz6Z[\6]^^!jjll4466>>@@"d&>>>3tG_`gGhCiCilmCmCm$'(@(I!(L$M$ME HNN!]$').	 +    !11#u==== HNN X$' +    !--c2222'`aaa--///''e'444F--.KSQQQ$&y177<<  7799??$$33'+$E 4 $ a))*z  +B  +B  CG  CT  U^  C_  +`  +`  a  a  a 4#444))*JKKK %&|4::3??  7799??$$	11(,%E 2 % e))*{  +C  +C  DH  DU  Vb  Dc  +d  +d  e  e  e 'd.???:;;;))*ijjj7888#$;<q@@--  /F  G  G  Gx!$"34K"LMMGG! x x x--  /D  /K  /K  LP  L]  ^u  Lv  /w  /w  x  x  x  x  xx dm++ DM**

hh3333344))*g*n*novx{*|*|*-,CS+I*JL L L
 *1& (4+<<<llT5FG_5`5f5fgj5k5klll	" " "ABww#112{  3C  3C  DE  3F  3F   G   G  G  G  G !1+4((+-(
 %**.D++ /7+$&D!*d.???#$?@1DD--.vwww(,(9:U(V(\(\(^(^%#1$2G#H#HLL!   --8??BB        # $ 6))dl.J)(,%%(7$#'<#8Df1FT\5F3	) )% ) --&&,fT-B&C&C   #$*;;;))*QRRR 34q88))*}~~~#$78>>@@C3xx2~~))*f*m*mnq*r*rsss233x4))*`*g*ghk*l*lmmm"X G G^^^--.v.}.}~  BE  /F  /F  G  G  G  G  G _
 )+D%)T->>>#$>?!CC--  /I  J  J  J 150K0KDL]^xLy0z0zD- 	-!"3"4"45DI
 DK "Q&&4<+H4K^+^+^ ""#JQT"UUUUU
 ,DI,0,=,0,B,0,B,0,D,0,B,0,A,0,D,0,EG G  ODNG<<G G G G G #At'<mLLLLL( 	(,	7T(U(U%(A--JKKK. HNNF#5 #   
 MM$"8"?"?"G"GHHH;?D8'')))))HNNC    #	 	--su   "B; ;
C7'C2,C72C7AM 9 M AN.R A$S32S3c# #=d#"d#j" "
k,'kkkc                 V   d}i }t          |          t          k    r7t          |          dk    r|d         }t          |          dk    r|d         }n|}||| j        vrt	          d          || _        | j        }g | _        g }g }| j        D ]\  }}| j	        
                    d||           |t          v rzt          |         }		 |	d                             |          }
|                    |
           j# t          $ r.}|                     t          |                    cY d}~c S d}~ww xY w| j	        
                    d|	           t          |          dk    r|                     |          }|t          |j                 }	|	d
                             | j        j        |          | _        | j                            | j                   |                    |                                           n| j	        
                    d|           d}| j        j        r"|d                    | j        j                  z  }|dz  }|dz  }| j        j                                        |                                fD ]}|D ]|}t7          |d         t          f          r
|d         g}n0	 t9          |d                   }n# t:          $ r |d         g}Y nw xY w|D ]!}|d                    |d         |          z  }"}| j        |d                    | j                  z  }t=          j                    }|                     |!                    d          tD          j#        z              tI          j%        |&                                          }|d                    |'                                          z  }t          |          dk    r+|d                    d(                    |                    z  }|dz  }d}| j	        
                    d|           | )                    |!                    d                     |r>| j	        
                    dtU          |                     | )                    |           || _+        tD          j,        | _-        | j.        :| j	        
                    d           | j.        /                                 d| _.        d| _0        d| _1        | j2        r/| j        j3        4                    | j2        | j5                  | _6        | j7        r| j7        8                    d           | 9                                 tu          j;        | j<        d           t          | j=                  dk    r| >                                 dS dS )zl
        Callback after onConnect() returns successfully. Generates the response for the handshake.
        Nr   r}   z;protocol accepted must be from the list client sent or None?parsed WebSocket extension '{extension}' with params '{params}'rh  ri  OfferzSclient requested '{extension}' extension we don't support or which is not activated)rh  PMCEzXclient request permessage-compress extension, but we did not accept any offer [{offers}])offersz"HTTP/1.1 101 Switching Protocols
Server: {}
Upgrade: WebSocket
Connection: Upgrade
{}: {}
Sec-WebSocket-Protocol: {}
r   zSec-WebSocket-Accept: {}
Sec-WebSocket-Extensions: {}
rZ  
z"sending HTTP response:

{response}responsez%sending HTTP response body:

{octets})r  openHandshakeTimeoutCall.cancelFr   )?r0  r>   r?   r  r:  websocket_protocol_in_user  websocket_extensions_in_user  r   r   r   r	   r   r  r1  r   r  create_from_offer_acceptr2  r3  rv  get_extension_stringserverr5   r  itemsr=   iter	TypeErrorhashlibsha1updater  r"   rr  base64	b64encodedigestr   r	  r  r   http_response_datar  r  rC  r1  r  r  r   r  r5  r  r  r
  r   _onOpenr   r^  r   r   r  )rS   r7   protocolr  r   extensionResponse
pmceOffersrh  ri  r  offerr  acceptr  headers_sourceuhheader_valuesheader_valuer  sec_websocket_acceptresponse_bodys                        r9   r  z(WebSocketServerProtocol.succeedHandshake  s    993xx!||q63xx!||a&HT5M)M)MYZZZ)1&k ,.( 
 $(#< 	 	YHNNQ#     <<<7	B6 M//77E%%e,,,,  6 6 6--c!ff55555555556 0'      z??Q55jAAF!78MN+/<+P+PQUQ]Qfhn+o+o(0778PQQQ!(()D)D)F)FGGGG6%     >< 	I,33DL4GHHHH0011
  $|399;;W]]__M 	M 	MN$ 
M 
MbecW-- 0%'UGMM0(,RU$ 0 0 0)+A0 %2 M ML 0 7 71| L LLHHM
M )5<CCDDbcccH |~~CJJv&&):)DDEEE%/>>6==>R>Y>Y>[>[\\\  !!A%%>EEchhO`FaFabbbH 	J 	=QQQhoof--... 	)HNN9(77     MM-((( #+ '1
 (4HNN<===)00222,0D) $!   	'+|'B'M'M%"( (D$  	0%%h///dlD))) ty>>A s0   	0C::
D2!D-%D2-D25KK! K!r  Nc                     || _         | j                            d|           |                     |||           |                     d           dS )z
        During opening handshake the client request was invalid, we send a HTTP
        error response and then drop the connection.
        0failing WebSocket opening handshake ('{reason}')rg  Fr!  N)r@  r   infosendHttpErrorResponser4  )rS   r  r  responseHeaderss       r9   r  z%WebSocketServerProtocol.failHandshake3  s[    
 "(HQWXXX""4AAA%(((((rL   c                     d                     ||          }|r*|D ]'}|d                     |d         |d                   z  }(|dz  }|                     |                    d                     dS )z/
        Send out HTTP error response.
        zHTTP/1.1 {0} {1}
z
{0}: {1}
r   r}   r  r   N)r5   r  r  )rS   r  r  r  r  r   s         r9   r  z-WebSocketServerProtocol.sendHttpErrorResponse=  s     .44T6BB 	B$ B B.55adAaDAAAJhoof--.....rL   c                    |                     d          }d}| j        j        2| j        j        dk    r"|d                    | j        j                  z  }|dz  }|d                    t	          |                    z  }|dz  }|                     |                     d                     |                     |           dS )	z/
        Send HTML page HTTP response.
        r   zHTTP/1.1 200 OK
Nr[  r  z(Content-Type: text/html; charset=UTF-8
zContent-Length: {}
r  )r  r2  r   r5   r?   r  )rS   htmlresponseBodyr  s       r9   sendHtmlz WebSocketServerProtocol.sendHtmlH  s     {{6**,<*t|/Bb/H/H,33DL4GHHHHDD077L8I8IJJJJhoof--...l#####rL   c                    d}| j         j        2| j         j        dk    r"|d                    | j         j                  z  }|d                    |          z  }|dz  }|                     |                    d                     dS )z4
        Send HTTP Redirect (303) response.
        zHTTP/1.1 303
Nr[  r  zLocation: {}
r  r   )r2  r   r5   r  r  )rS   r6   r  s      r9   r  z$WebSocketServerProtocol.sendRedirectV  s     *<*t|/Bb/H/H,33DL4GHHHH*11#666Jhoof--.....rL   r   c                     |rd                     ||          }nd}|                     t                               |t                               dS )z
        Used to send out server status/version upon receiving a HTTP/GET without
        upgrade to WebSocket header (and option serverStatus is True).
        z1<meta http-equiv="refresh" content="{};URL='{}'">r[  N)r5   r   _SERVER_STATUS_TEMPLATEr
   )rS   redirectUrlredirectAfterr  s       r9   r  z(WebSocketServerProtocol.sendServerStatusa  sS    
  	NUUVcepqqHHH-44X{KKLLLLLrL   )r  NrP   rV   )rn   ro   rp   r{   r"   r~  r  rr  r   r   r   r1  r   r   r  r  r  r  r  r  r  r  r   r  r  rq   rL   r9   r$   r$   	  s3         %8;L;``L!2 uXc]ERZ[^R_aefiknfnaoRoLp=p7q    2
+ 
+ 
+
+ 
+ 
+9 9 9b b bHm m m^) ) ) )	/ 	/ 	/ 	/$ $ $	/ 	/ 	/	M 	M 	M 	M 	M 	MrL   r$   c                       e Zd ZdZeZ	 dZ	 ddd                    e          ddfdZ		 	 	 	 	 ddZ
d Z	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd	Zd
 ZdS )r%   z
    A protocol factory for WebSocket servers.

    Implements :func:`autobahn.websocket.interfaces.IWebSocketServerChannelFactory`
    TNAutobahnPython/{}c                     d| _         d| _        d| _        t          j        dd          | _        t          j                     |                     |||||           | 	                                 d| _
        dS )zj
        Implements :func:`autobahn.websocket.interfaces.IWebSocketServerChannelFactory.__init__`
        F皙?r   bucket_seconds
chunk_sizer   N)r   r   r   r   make_batched_timerr  r  seedsetSessionParametersresetProtocolOptionsr  )rS   r6   r  r   r  r  s         r9   rT   zWebSocketServerFactory.__init__~  s     ! $6 
 
 
 	 	!!#y&'<PPP 	!!### !"rL   c                    t          |pd          \  }}}}	}
}t          |          dk    rt          d          || _        || _        || _        || _        |	| _        |
| _        || _	        |pg | _
        || _        |pi | _        || _        dS )zv
        Implements :func:`autobahn.websocket.interfaces.IWebSocketServerChannelFactory.setSessionParameters`
        ws://localhostr   z3query parameters specified for server WebSocket URLN)r   r?   r:  r6   r  r8   r2   resourcer  ri  r  r   r  r  )rS   r6   r  r   r  r  r  r8   r2   r3  r  ri  s               r9   r/  z+WebSocketServerFactory.setSessionParameters  s     :C3CZJZ9[9[64xvv;;??QRRR 		 	"b}"(rL   c                    t           j        | _        d| _        d| _        d| _        d| _        d| _        d| _        d| _	        d| _
        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d | _        d| _        d| _        d| _        d| _        d	g| _        t1          | j                  | _        d| _        d| _        d| _        d
S )zv
        Implements :func:`autobahn.websocket.interfaces.IWebSocketServerChannelFactory.resetProtocolOptions`
        TFr      r}   z`<cross-domain-policy>
     <allow-access-from domain="*" to-ports="*" />
</cross-domain-policy> c                     d S rP   rq   r  s    r9   <lambda>z=WebSocketServerFactory.resetProtocolOptions.<locals>.<lambda>      T rL   r   *N)r"   rn  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   rR   s    r9   r0  z+WebSocketServerFactory.resetProtocolOptions  s     *E$(!)-& %#$ %&" !#( $%!%&"&+#" ,:>( !"  ,0(  #e&89L&M&M##   #$rL   Fc                 *   |l|D ]=}|t           j        vr-t          d                    |t           j                            >t	          |          t	          | j                  k    r|| _        ||| j        k    r|| _        ||| j        k    r|| _        ||| j        k    r|| _        ||| j	        k    r|| _	        ||| j
        k    r|| _
        ||| j        k    r|| _        ||| j        k    r|| _        |	|	| j        k    r|	| _        |
|
| j        k    r|
| _        ||| j        k    r|| _        ||| j        k    r|| _        ||| j        k    r|| _        ||| j        k    r|| _        ||| j        k    r|| _        ||| j        k    r|| _        ||| j        k    r|| _        |U|| j        k    rJt/          |          t0          k    st/          |          t2          k    sJ d|cxk    rdk    sn J || _        |,|| j        k    r!t/          |          t6          k    sJ || _        ||| j        k    r|| _        ||| j        k    r|| _        |+|| j        k    r || _        t?          | j                  | _         |dvrtC          d          || _"        |4|| j#        k    r)t/          |          t2          k    sJ |dk    sJ || _#        |6|| j$        k    r-t/          |          t2          k    sJ |dk    sJ || _$        dS dS dS )zt
        Implements :func:`autobahn.websocket.interfaces.IWebSocketServerChannelFactory.setProtocolOptions`
        Nz:invalid WebSocket protocol version {} (allowed values: {})r   r  )TFzallowNullOrigin must be a boolr   )%r"   rn  r:  r5   setr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r0  rh   r  r   rM  r   r   r   r   r   r4   r   r   r   )rS   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   vs                              r9   setProtocolOptionsz)WebSocketServerFactory.setProtocolOptions  s   :  [ [-III#$`$g$ghik|  lY  %Z  %Z  [  [  [ J8}}DM 2 222 ( Y$.%@%@&DN+0DHa0a0a(<D%$05NRVRp5p5p-FD*',<@U,U,U$4D! Y$.%@%@&DN*/BdF^/^/^':D$ ,1F$Jd1d1d)>D&',<@U,U,U$4D!!jDO&C&C(DO*/BdF^/^/^':D$+0DHa0a0a(<D% ,1F$Jd1d1d)>D&!jDO&C&C(DO&27RVZVv7v7v/JD,',<@U,U,U$4D!&?d>R+R+R#2D #8I(I(I%%..$|2D2D2K2K2K2K,,,,,,,,,, ,D&27RVZVv7v7v344<<<</JD,!-2HDLg2g2g*@D'(->$BX-X-X%6D"%.D<O*O*O"0D*<T=P*Q*QD'-//=>>>.%.D<O*O*O''3....!Q&&&&"0D).@DD[.[.[*++s2222%****&8D### *).[.[rL   c                     | j         S )zv
        Get number of currently connected clients.

        :returns: Number of currently connected clients.
        )r  rR   s    r9   getConnectionCountz)WebSocketServerFactory.getConnectionCount`  s     $$rL   )NNNNN)NNNNNNNNNNNNNNNNNNNNNNFNN)rn   ro   rp   r{   r$   r  r3  r5   r
   rT   r/  r0  r>  r@  rq   rL   r9   r%   r%   m  s         'H H
 +22;??" "  "  "  "F "&'+$(%)*.) ) ) )8-$ -$ -$` %)%)04,059%)/315,0&*/30415&*7;,0+/(,7;26-1*.+0*..23s9 s9 s9 s9j% % % % %rL   r%   c                       e Zd ZdZej        ej        z   Zdede	e
         fdZdedefdZd Zd Zd	 Zd
 Zd Zd Zd Zd Zd ZdS )r&   z4
    Protocol base class for WebSocket clients.
    r   r   c                     dS )a  
        Callback fired after the connection is established, but before the
        handshake has started. This may return a
        :class:`autobahn.websocket.types.ConnectingRequest` instance
        (or a future which resolves to one) to control aspects of the
        handshake (or None for defaults)

        :param transport_details: Details of the transport underlying the WebSocket connection being established.

        :returns: A :class:`autobahn.websocket.types.ConnectingRequest`
            instance is returned to indicate which options should be
            used for this connection. If you wish to use the default
            behavior, ``None`` may be returned (this is the default).
        Nrq   )rS   r   s     r9   onConnectingz$WebSocketClientProtocol.onConnectingp        rL   r  c                     dS )z
        Callback fired directly after WebSocket opening handshake when new WebSocket
        connection was established from the client to a server.

        :param response: WebSocket connection response information sent by server.
        Nrq   )rS   r  s     r9   r  z!WebSocketClientProtocol.onConnect  rD  rL   c                 &   | j                             dt          | j                  | j                   t
                              |            | j        j        s"| j        j        | 	                                 dS | 
                                 dS )aC  
        Called by network framework when new transport connection to server was established. Default
        implementation will start the initial WebSocket opening handshake (or proxy connect).
        When overriding in derived class, make sure to call this base class
        implementation _before_ your code.
        r  r  N)r   r   r   r  rZ  r"   r2  r3  rx  startProxyConnectstartHandshakerR   s    r9   r  z'WebSocketClientProtocol._connectionMade  s     	E"4#788ty 	 	J 	J 	J))$///|$ 	");)G""$$$$$ !!!!!rL   c                     | j                             dt          | j                  | j        t          |                     t                              | |           dS )a  
        Called by network framework when established transport connection to server was lost. Default
        implementation will tear down all state properly.
        When overriding in derived class, make sure to call this base class
        implementation _after_ your code.
        r  r  N)r   r   r   r  rZ  r   r"   ri  s     r9   r  z'WebSocketClientProtocol._connectionLost  sa     	P"4#788tyQVW]Q^Q^ 	 	` 	` 	`))$77777rL   c                 F   d                     | j        j        | j        j                  }|d                     | j        j        | j        j                  z  }|dz  }| j                            d|           |                     |                    d                     dS )z,
        Connect to explicit proxy.
        zCONNECT {}:{} HTTP/1.1
Host: {}:{}
r  z	{request})r  r   N)r5   r2  r8   r2   r   r   r  r  r  s     r9   rG  z)WebSocketClientProtocol.startProxyConnect  s     399$,:KT\M^__(//0A4<CTUUU:{G444gnnV,,-----rL   c                 @   | j                             d          }|dk    r|| j         d|dz            }| j                            d|           t	          |          \  }}}| j                            d|           | j                            d	|
           |                                }t          |          dk     r(|                     d                    |                    S |d         	                                }|dvr(|                     d                    |                    S 	 t          |d         	                                          }nP# t          $ rC |                     d                    |d         	                                                    cY S w xY wd|cxk    rdk     s^n t          |          dk    rd                    |dd                   }	nd}	|                     d                    ||	                    S | j         |dz   d         | _         t          j        | _        t          | j                   dk    r|                                  | j        j        r|                                  |                                  dS dS )z<
        Process HTTP/CONNECT response from server.
        r  r   Nr   z%received HTTP response:

{response}

r  z>received HTTP status line for proxy connect request : {status}r  z;received HTTP headers for proxy connect request : {headers}r  r   "Bad HTTP response status line "{}")HTTP/1.1zHTTP/1.0r  r}   Bad HTTP status code "{}"   i,   r[  z$HTTP proxy connect failed ({}): "{}")r   r   r   r   r   rc  r?   failProxyConnectr5   r   r  r4   r	  r"   rD  r  r  r2  r  startTLSrH  )
rS   r  r
  r   r   r   slhttp_versionstatus_coder  s
             r9   r  z+WebSocketClientProtocol.processProxyConnect  s    	':;;A!%+=MA,=+=!>HNN;+     BQQcAdAd>|-= HNNP'     HNNM$     "''))B2ww{{,,-Q-X-XYi-j-jkkk a5;;==L#;;;,,-L-S-ST`-a-abbb`!"Q%++--00 ` ` `,,-H-O-OPRSTPUP[P[P]P]-^-^_____` ;,,,,,,,,
 r77Q;; XXbf--FFF,,-S-Z-Z[fhn-o-oppp 	-!"3"4"45DI +;DJ 49~~!!  """ |$  !!!!!M s   1'E A
F&%F&c                 j    | j                             d|           |                     d           dS )z
        During initial explicit proxy connect, the server response indicates some failure and we drop the
        connection.
        z"failing proxy connect ('{reason}')rg  Tr!  N)r   r   r4  ri  s     r9   rR  z(WebSocketClientProtocol.failProxyConnect  s:    
 	;FKKK$'''''rL   c                 ,     j                             dt           j                  t	           j                                                             t          j         j	         j                  } fd} fd}t          j
        |||           |S )z4
        Start WebSocket opening handshake.
        zF{meth}: starting handshake with transport_details=
{transport_details})methr   c           	          | \t          j        j        j        j        j        j        j        j        j        j        j        j        j        j                  } 	                    |            | S )zE
            onConnecting succeeded and returned options
            N)r8   r2   r3  r  	useragentr  r  )
r   r2  r8   r2   r3  r  r[  r  r  _actuallyStartHandshake)request_optionsrS   s    r9   got_optionsz;WebSocketClientProtocol.startHandshake.<locals>.got_options  su     & #4**!\2 L0"l4<."l4
# 
# 
# ((999""rL   c                     j                             d| t          j                                                 d           d S )Nz"{meth} onConnecting failed: {fail})r  rY  Fr!  )r   r  r   rH  r4  r  rS   s    r9   options_failedz>WebSocketClientProtocol.startHandshake.<locals>.options_failed,  sR    HNN4D/00    
 e,,,4rL   )r   r   r   rH  r   r   marshalr   r  rC  r  )rS   	options_dr^  ra  s   `   r9   rH  z&WebSocketClientProtocol.startHandshake
  s     	`"4#677)01H1P1P1R1R)S)S 	 	U 	U 	U OD$5t7NOO		# 	# 	# 	# 	#,	 	 	 	 	 	I{NCCCrL   c                 r   d                     |j                  }|j        (|j        dk    r|d                     |j                  z  }|d                     |j        |j                  z  }|dz  }|dz  }|dz  }|d	z  }|j                                        D ]'}|d
                     |d         |d                   z  }(t          j        t          j
        d                    | _        |d                     | j                                                  z  }|j        rF| j        dk    r|d                     |j                  z  }n|d                     |j                  z  }t          |j                  dk    r0|d                     d                    |j                            z  }g }| j        D ])}|                    |                                           *t          |          dk    r+|d                     d                    |                    z  }|d                     t*          j        | j                           z  }|dz  }|                    d          | _        |                     | j                   | j                            dt9          | j                  |           dS )z
        Internal helper.

        Actually send the WebSocket opening handshake after receiving
        valid request options.
        zGET {} HTTP/1.1
Nr[  zUser-Agent: {}
rK  r  r  zPragma: no-cache
zCache-Control: no-cache
r  r   r}   r   zSec-WebSocket-Key: {}
r   zOrigin: {}
zSec-WebSocket-Origin: {}
r  rZ  r  zSec-WebSocket-Version: {}
r  r   z${meth}: sent HTTP request:
{request})rY  r  )r5   r3  r[  r8   r2   r  r  r  r  r*  r+  websocket_keyr   r  r   r?   r  r	  r   r   r  r"   ro  r  r  r  r   r   r   r\  )rS   r]  r  r  re  r  s         r9   r\  z/WebSocketClientProtocol._actuallyStartHandshake8  s    ,22?3KLL$0_5NRT5T5T/667PQQQG(//0DoFZ[[[//00 	--44 ")//11 	= 	=B'..r!ube<<<GG $-bjnn==299$:L:S:S:U:UVVV ! 	]|b  /667MNNN=DD_E[\\\ ())A--;BB388OLeCfCfgggG 
 5 	< 	<Ee88::;;;;z??Q=DDSXXjEYEYZZZG 	6==>O>himiu>vwww:!(!7!7d,--->VDLhEiEi& 	 	( 	( 	( 	( 	(rL   c                      j                             d          }|dk    r܉ j         d|dz             _         j                            dt           j                   j                            d                     t           j                  \   _	         _
        } j                            d j	        	            j                            d
 j
                    j	                                        }t          |          dk     r-                     d                     j	                            S |d                                         }|dk    r(                     d                    |                    S 	 t!          |d                                                   }nP# t"          $ rC                      d                    |d                                                             cY S w xY w|dk    r\t          |          dk    rd                    |dd                   }nd}                     d                    ||                    S d j
        vr                     d          S  j
        d                                                                         dk    r3                     d                     j
        d                             S d j
        vr                     d          S d} j
        d                             d          D ]0}|                                                                dk    rd} n1|s3                     d                     j
        d                             S d  j
        vr                     d!          S |d          dk    r                     d"          S  j
        d                                          }	t)          j                    }
|
                     j        t0          j        z              t5          j        |
                                                                          }|	|k    r)                     d#                    ||	                    S g  _        d$ j
        v r|d$         dk    r                     d%          S                       j
        d$                   }|D ]Q\  }} j                            d&||'           |t>          v r j                              d(          c S t>          |         }	 |d)         !                    |          }n;# tD          $ r.}                     tG          |                    cY d}~c S d}~ww xY w $                    |          }|                     d*          c S |d+         %                     j&        j'        |           _          j        (                     j                    )                     d,                    |                    c S d _)        d- j
        v r|d-         dk    r                     d.          S tG           j
        d-                                                   }|dk    rH| j&        j*        vr3                     d/                    | j&        j*                            S | _)         j         |dz   d          _         t0          j+         _,         j-        : j                            d0            j-        .                                 d _-        d _/        d _0         j1         _2         j3        r/ j&        j4        5                     j3         j6                   _7        tq           j9         j
         j2         j)         j                  }tu          j;         j<        |          } fd1} fd2}tu          j=        |||           |S dS )3zK
        Process WebSocket opening handshake response from server.
        r  r   Nr   z*{meth}: received HTTP response:
{response}r   )rY  r  r  r  r  r  r   rM  rN  r  r}   rO  e   rQ  r[  z,WebSocket connection upgrade failed [{}]: {}r  r  r  zGHTTP Upgrade header different from "websocket" (case-insensitive): "{}"r  r  FrZ  TzPHTTP Connection header does not include "upgrade" value (case-insensitive): "{}"zsec-websocket-acceptzCHTTP Sec-WebSocket-Accept header missing in opening handshake replyzRHTTP Sec-WebSocket-Accept header appears more than once in opening handshake replyz<HTTP Sec-WebSocket-Accept bogus value : expected {} / got {}r  zVHTTP Sec-WebSocket-Extensions header appears more than once in opening handshake replyr  r  z6multiple occurrence of a permessage-compress extensionResponsezMWebSocket permessage-compress extension response from server denied by clientr  z]server wants to use extension "{}" we did not request, have not implemented or did not enabler  zTHTTP Sec-WebSocket-Protocol header appears more than once in opening handshake replyzTsubprotocol selected by server "{}" not in subprotocol list requested by client "{}"r  c                 :   j                             d|            j        rj                            d                                            t          j        j        d            t          j	                  dk    r
                                 d S d S )Nz;onConnect callback completed successfully with result={res})r7   r   r   )r   r   r
  r   r  r   r^  r   r?   r   r  )r7   rS   s    r9   on_connect_successzDWebSocketClientProtocol.processHandshake.<locals>.on_connect_successK  s    \befff& 8'--h777dlD111ty>>A%%$$&&&&& &%rL   c                     j                             d|                                dd                    |                      d S )NzonConnect failed with {fail}r  r   z{})r   r  ra  r5   r`  s    r9   on_connect_failedzCWebSocketClientProtocol.processHandshake.<locals>.on_connect_failedT  sP    2     %%dDKK,=,=>>>>>rL   )>r   r   r
  r   r   r   r  r   r   r   r   rc  r?   r  r5   r   r  r4   r	  r.   r  r  r  re  r"   rr  r  r  r	  r  rk  r   rv  r	   r:  r1  r   create_from_response_acceptr2  r3  r   r  r  r  r  rC  r1  r  r  r   r   r   r  r5  r  r  r   rZ  r   r  
_onConnectr  )rS   r  r   rT  rU  rV  r  r  r  sec_websocket_accept_gotr  r  r  rh  ri  r  pmceResponser  r  spr  r   rj  rl  s   `                       r9   r  z(WebSocketClientProtocol.processHandshake  s9	    	':;;A-1Y7I8I7I-JD#HNNHvVZVkOlOl$($;$B$B6$J$J  L L L
 L[[_[rKsKsHT"D$57G HNNK,     HNNH)     &,,..B2ww{{))*N*U*UVZVk*l*lmmm a5;;==Lz))))*I*P*PQ]*^*^___]!"Q%++--00 ] ] ]))*E*L*LRPQU[[]]*[*[\\\\\]c!!
 r77Q;; XXbf--FFF))*X*_*_`kms*t*tuuu  111))*GHHH +113399;;{JJ))*s*z*z{  |M  NW  |X  +Y  +Y  Z  Z  Z 4#444))*JKKK %&|4::3??  7799??$$	11(,%E 2 % f))*|  +D  +D  EI  EV  Wc  Ed  +e  +e  f  f  f &T->>>))*oppp#$:;a??--  /C  D  D  D+/+<=S+T+Z+Z+\+\(|~~D.1B1LLMMM'-'7'F'F'M'M'O'O$+/CCC--.l.s.s  uI  Kc  /d  /d  e  e  e 02D,)T->>>#$>?!CC--  /G  H  H  H ,0+F+FtGXYsGt+u+u( ,@ "e "e'YHNNY"+% #    !$DDD  3?#'#5#56n#o#oooo?	J>+/
+;+A+A&+I+ILL( > > >#'#5#5c!ff#=#=========> "&!A!A,!O!O!>#'#5#5  7F  $G  $G  G  G  G37<3[3[\`\h\qsy3z3z08??@XYYYY  $11  3R  3Y  3Y  Zc  3d  3d   e   e  e  e  e .2D*'4+<<<#$<=AA--  /E  F  F  F*+CDJJLLMM88!777#11  3I  3P  3P  QS  UY  Ua  Uk  3l  3l   m   m  m :<6 	-!"3"4"45DI +5DJ ,8@AAA-4466604- #(D!%D%)\D" $ +/<+F+Q+Q)&, ,( *$)*.*;*.*@*.*H*.*J	L LH ::A' ' ' ' '? ? ? ? ? #57HIIIHg s1   'F/ /A
G<;G<8U
V!V?VVc                 x    || _         | j                            d|           |                     d           dS )zm
        During opening handshake the server response is invalid and we drop the
        connection.
        r  rg  Tr!  N)r@  r   r  r4  ri  s     r9   r  z%WebSocketClientProtocol.failHandshake^  sN    
 "(> 	 	
 	
 	
 	$'''''rL   N)rn   ro   rp   r{   r"   r~  r  rr  r   r   r   rC  r   NoneTyper  r  r  rG  r  rR  rH  r\  r  r  rq   rL   r9   r&   r&   i  s         %8;L;``L.> 8L]C^     "4     " " "$	8 	8 	8. . .M" M" M"^( ( (, , ,\H( H( H(TZ Z Zx
( 
( 
( 
( 
(rL   r&   c                       e Zd ZdZeZ	 dZ	 dddd                    e          ddfdZ		 	 	 	 	 	 d	dZ
d Z	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d
dZdS )r'   z
    A protocol factory for WebSocket clients.

    Implements :func:`autobahn.websocket.interfaces.IWebSocketClientChannelFactory`
    FNr'  c                     d| _         d| _        d| _        t          j        dd          | _        t          j                     |                     ||||||           | 	                                 dS )zj
        Implements :func:`autobahn.websocket.interfaces.IWebSocketClientChannelFactory.__init__`
        Fr)  r   r*  N)
r   r   r   r   r-  r  r  r.  r/  r0  )rS   r6   r  r  r[  r  rx  s          r9   rT   zWebSocketClientFactory.__init__|  s     ! $6 
 
 
 	 	!!#vy)WeTTT 	!!#####rL   c                     t          |pd          \  }}}	}
}}|| _        || _        || _        |	| _        |
| _        || _        || _        || _        |pg | _	        || _
        |pi | _        || _        dS )zv
        Implements :func:`autobahn.websocket.interfaces.IWebSocketClientChannelFactory.setSessionParameters`
        r2  N)r   r6   r  r8   r2   r3  r  ri  r  r  r[  r  rx  )rS   r6   r  r  r[  r  rx  r  r8   r2   r3  r  ri  s                r9   r/  z+WebSocketClientFactory.setSessionParameters  s     :C3CZJZ9[9[64xv 		 	"b"}"


rL   c                 4   t           j        | _        d| _        d| _        d| _        d| _        d| _        d| _        d| _	        d| _
        d| _        d| _        d| _        d| _        d| _        g | _        d | _        d| _        d| _        d| _        d| _        dS )	zv
        Implements :func:`autobahn.websocket.interfaces.IWebSocketClientChannelFactory.resetProtocolOptions`
        TFr   r}   r5  c                     d S rP   rq   r7  s    r9   r8  z=WebSocketClientFactory.resetProtocolOptions.<locals>.<lambda>  r9  rL   r   N)r"   rq  r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rR   s    r9   r0  z+WebSocketClientFactory.resetProtocolOptions  s     )=$(!(-% $#$ %&" !#( +,($%!%&" ,.(+9>( !"  ,0(((rL   c                 Z   |M|t           j        vr-t          d                    |t           j                            || j        k    r|| _        ||| j        k    r|| _        ||| j        k    r|| _        ||| j        k    r|| _        ||| j        k    r|| _        ||| j	        k    r|| _	        ||| j
        k    r|| _
        ||| j        k    r|| _        |	|	| j        k    r|	| _        |
|
| j        k    r|
| _        ||| j        k    r|| _        ||| j        k    r|| _        ||| j        k    r|| _        ||| j        k    r|| _        |t%          j        |          t%          j        | j                  k    rat+          |          t,          k    rt/          j        |          | _        n/t          d                    t+          |                              ||| j        k    r|| _        ||| j        k    r|| _        ||| j        k    r|| _        |U|| j        k    rJt+          |          t:          k    st+          |          t<          k    sJ d|cxk    rdk    sn J || _        |.|| j        k    r%t+          |          t@          k    sJ || _        dS dS dS )zt
        Implements :func:`autobahn.websocket.interfaces.IWebSocketClientChannelFactory.setProtocolOptions`
        Nz7invalid WebSocket draft version {} (allowed values: {})z?invalid type {} for perMessageCompressionOffers - expected listr   r  )!r"   rm  r:  r5   r   r   r   r   r   r   r   r   r   r   r   r   r   r   picklerl   r   r0  listcopydeepcopyr   r   r   r   rh   r  r   rM  )rS   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   s                        r9   r>  z)WebSocketClientFactory.setProtocolOptions  s~   0 /GGG Y ` `ahj{  kT  !U  !U  V  V  V$,&&&+0DHa0a0a(<D%#/4LPTPm4m4m,DD)',<@U,U,U$4D! Y$.%@%@&DN*/BdF^/^/^':D$ ,1F$Jd1d1d)>D&',<@U,U,U$4D!!jDO&C&C(DO*/BdF^/^/^':D$&27RVZVv7v7v/JD,+0DHa0a0a(<D% ,1F$Jd1d1d)>D&!jDO&C&C(DO&2v|D_7`7`djdpqu  rR  eS  eS  8S  8S/00D88 48=A\3]3]00 a h him  oJ  jK  jK  !L  !L  M  M  M&27RVZVv7v7v/JD,',<@U,U,U$4D!&?d>R+R+R#2D #8I(I(I%%..$|2D2D2K2K2K2K,,,,,,,,,, ,D&27RVZVv7v7v344<<<</JD,,, 327v7vrL   )NNNNNN)NNNNNNNNNNNNNNNNNNNN)rn   ro   rp   r{   r&   r  r3  r5   r
   rT   r/  r0  r>  rq   rL   r9   r'   r'   k  s         'H H
 .55kBB$ $ $ $@ "&$('+'+%)#'   60 0 0D $(0448,0%)/315,0&*/37;0415&*7;7;,0+/(,7;)^K ^K ^K ^K ^K ^KrL   r'   )Lr  r  r  r  r  r*  rz  r|  rk   r  typingr   r   r   r   pprintr   collectionsr   urllibr	   autobahnr
   autobahn.websocket.interfacesr   r   r   autobahn.websocket.typesr   r   r   r   autobahn.wamp.typesr   autobahn.utilr   r   r   r   r   r   r    autobahn.websocket.utf8validatorr   autobahn.websocket.xormaskerr   r   autobahn.websocket.compressr   autobahn.websocket.utilr   autobahn.exceptionr   r    r!   r   r  r0  rs  __all__r:   rK   objectrN   rs   r   r   r"   registerr  r#   r#  r$   r%   r&   r'   rq   rL   r9   <module>r     s  6      				     / / / / / / / / / / / /                              " " " " " " " " " " n m m m m m m m m m m m 0 0 0 0 0 0 W W W W W W W W W W W W W W + + + + + + ) ) ) ) ) ) : : : : : : I I I I I I I I H H H H H H - - - - - - A A A A A A A A + + + + + +      4::%  :- - -`E+ E+ E+ E+ E+6 E+ E+ E+P    &   :*< *< *<Z;& ;& ;& ;& ;&f ;& ;& ;&|f f f f f f f fR?   , - - - "  "#4 5 5 5 &  &'8 9 9 9Dc Dc Dc Dc Dcf Dc Dc DcNL L L L Lv L L LD! HE
M E
M E
M E
M E
M/ E
M E
M E
MPy% y% y% y% y%- y% y% y%x( ( ( ( (/ ( ( (DJK JK JK JK JK- JK JK JK JK JKrL   