
    iH                        d Z ddlmZ ddlmZ ddlmZmZ ddlZddl	m
Z
mZ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mZmZmZmZmZ erddlmZmZmZ ddlm Z  dZ!dZ" G d d          Z#ddZ$ddZ%dS )zR
wsproto/handshake
~~~~~~~~~~~~~~~~~~

An implementation of WebSocket handshakes.
    )annotations)deque)TYPE_CHECKINGcastN   )
ConnectionConnectionStateConnectionType)AcceptConnectionEventRejectConnection
RejectDataRequest)	Extension)LocalProtocolErrorRemoteProtocolErrorgenerate_accept_tokengenerate_noncenormed_header_dictsplit_comma_header)	GeneratorIterableSequence)Headerss   13s	   websocketc                      e Zd ZdZd)dZed*d            Zed+d
            Zd,dZd-dZ	d.dZ
d/dZd0dZd1dZd2dZd3d!Zd4d#Zd5d%Zd6d'Zd(S )7H11Handshakez4A Handshake implementation for HTTP/1.1 connections.connection_typer
   returnNonec                :   |t           j        u | _        t          j        | _        | j        r$t          j        t          j                  | _        n#t          j        t          j	                  | _        d | _
        t                      | _        d | _        d | _        d S N)r
   CLIENTclientr	   
CONNECTING_stateh11r   _h11_connectionSERVER_connectionr   _events_initiating_request_nonce)selfr   s     </usr/local/lib/python3.11/dist-packages/wsproto/handshake.py__init__zH11Handshake.__init__,   sv    %)>>%0; 	>#&>#*#=#=D  #&>#*#=#=D .2%*WW37 $(    r	   c                    | j         S r!   )r%   r-   s    r.   statezH11Handshake.state:   s
    {r0   Connection | Nonec                    | j         S )z
        Return the established connection.

        This will either return the connection or raise a
        LocalProtocolError if the connection has not yet been
        established.

        :rtype: h11.Connection
        )r)   r2   s    r.   
connectionzH11Handshake.connection>   s     r0   headersr   pathbytes | strc                    | j         rd}t          |          t          j        d||          }t          j        t          j                  }|                     |                    |                     dS )z
        Initiate an upgrade connection.

        This should be used if the request has already be received and
        parsed.

        :param list headers: HTTP headers represented as a list of 2-tuples.
        :param str path: A URL path.
        z?Cannot initiate an upgrade connection when acting as the client   GETmethodtargetr7   N)r#   r   r&   r   r   r"   receive_datasend)r-   r7   r8   msgupgrade_request
h11_clients         r.   initiate_upgrade_connectionz(H11Handshake.initiate_upgrade_connectionK   sw     ; 	SC$   +VD'RRR^CJ//
*///::;;;;;r0   eventr   bytesc                   d}t          |t                    r||                     |          z  }nt          |t                    r||                     |          z  }nqt          |t
                    r||                     |          z  }nCt          |t                    r||                     |          z  }nd| d}t          |          |S )a  
        Send an event to the remote.

        This will return the bytes to send based on the event or raise
        a LocalProtocolError if the event is not valid given the
        state.

        :returns: Data to send to the WebSocket peer.
        :rtype: bytes
        r0   zEvent z$ cannot be sent during the handshake)

isinstancer   _initiate_connectionr   _acceptr   _rejectr   _send_reject_datar   )r-   rE   datarA   s       r.   r@   zH11Handshake.send`   s     eW%% 	D--e444DD/00 
	DLL'''DD/00 	DLL'''DDz** 	D**5111DDF5FFFC$   r0   rM   bytes | Nonec                N   | j                             |pd           	 	 | j                                         }n2# t          j        $ r  d}t	          |t                                w xY wt          |t          j                  s|t          j        u s|t          j	        u rd	S | j
        rt          |t          j                  r|j        dk    r/| j                            |                     |                     n| j                            t          t!          |j                  |j        d                     t$          j        | _        nRt          |t          j                  rSt$          j        | _        | j                            t          t!          |j                  |j        d                     nt          |t          j                  r/| j                            t1          |j        d                     nt          |t          j                  r:| j                            t1          dd                     t$          j        | _        nGt          |t          j                  r-| j                            |                     |                     )
z
        Receive data from the remote.

        A list of events that the remote peer triggered by sending
        this data can be retrieved with :meth:`events`.

        :param bytes data: Data received from the WebSocket peer.
        r0   TzBad HTTP message
event_hinte   F)r7   status_codehas_body)rM   body_finishedN)r'   r?   
next_eventr&   r   r   rH   ConnectionClosed	NEED_DATAPAUSEDr#   InformationalResponserS   r*   append_establish_client_connectionlistr7   r	   CLOSEDr%   Response	REJECTINGDatar   rM   EndOfMessager   _process_connection_request)r-   rM   rE   rA   s       r.   r?   zH11Handshake.receive_data{   s    	))$+#666-	M,7799*   ()$4$6$6    5#"677CM))CJ&&{ MeS%>?? 9(C//++D,M,Me,T,TUUUU++,(,U](;(;,1,=).     '6&<s|44 9"1";DKL''($($7$7(-(9%)       sx00 9L''"
%HHH     s'788 9L''
4(P(P(PQQQ"1"8DKE3;// M##D$D$DU$K$KLLL[-	Ms	   9 /A(Generator[Event, None, None]c              #  `   K   | j         r$| j                                         V  | j         "dS dS )z
        Return a generator that provides any events that have been generated
        by protocol activity.

        :returns: a generator that yields H11 events.
        N)r*   popleftr2   s    r.   eventszH11Handshake.events   sL       l 	),&&((((( l 	) 	) 	) 	) 	)r0   h11.Requestr   c           	        |j         dk    rd}t          |t                                d }g }d }d }g }d}d }	g }
|j        D ]\  }}|                                }|dk    rt          |          }n|dk    r|                    d          }K|dk    r#|                    t          |                     t|d	k    r|}n:|d
k    r#|                    t          |                     |dk    r|}	n|dk    r|}|
                    ||f           |t          d |D                       sd}t          |t                                |	t          k    r.d}t          |t          dt          fg|	rdnd                    |d}t          |t                                |                                t          k    r:dt                                           d}t          |t                                |d}t          |t                                t          ||
|||j                            d                    | _        | j        S )Nr;   zRequest method must be GETrP   r0   
   connections   hostidna   sec-websocket-extensions   sec-websocket-key   sec-websocket-protocols   sec-websocket-version   upgradec              3  F   K   | ]}|                                 d k    V  dS upgradeNlower.0tokens     r.   	<genexpr>z;H11Handshake._process_connection_request.<locals>.<genexpr>   @       0
 0
+0EKKMMY&0
 0
 0
 0
 0
 0
r0   %Missing header, 'Connection: Upgrade'z'Missing header, 'Sec-WebSocket-Version'   Sec-WebSocket-Versioni  i  )r7   rS   z#Missing header, 'Sec-WebSocket-Key'Missing header, 'Upgrade: 'zMissing header, 'Host'ascii)
extensionsextra_headershostsubprotocolsr>   )r=   r   r   r7   rt   r   decodeextendr[   anyWEBSOCKET_VERSIONWEBSOCKET_UPGRADEr   r>   r+   )r-   rE   rA   connection_tokensr   r   keyr   rr   versionr7   namevalues                r.   rc   z(H11Handshake._process_connection_request   s    <6!!.C% 0 2 2    ! "
"$ = 	* 	*KD%::<<D}$$$6u$=$=!!||F++444!!"4U";";<<<---222##$6u$=$=>>>111##NND%=))))$C 0
 0
4E0
 0
 0
 -
 -
$ :C% 0 2 2    ''';C%+68IJK'. 7C      ;7C% 0 2 2    ==??///L/@/G/G/I/ILLLC%+--    <*C% 0 2 2    $+!!%<&&w//$
 $
 $
  ''r0   r   c                   | j         J t          | j         j                  }|d         }t          |          }dt          fdd|fg}|j        [|j        | j         j        vrd|j         }t          |          |                    d|j        	                    d          f           |j
        rFt          t          d| j         j
                  |j
                  }|r|                    d	|f           t          j        d
||j        z   d          }t          | j        rt"          j        nt"          j        |j
                  | _        t*          j        | _        | j                            |          pdS )Nrm      Upgrades
   Connectionr   s   Sec-WebSocket-Acceptzunexpected subprotocol    Sec-WebSocket-Protocolr~   zSequence[str]   Sec-WebSocket-ExtensionsrR   s   Switching Protocols)rS   r7   reasonr0   )r+   r   r   r   r   subprotocolr   r   r[   encoder   server_extensions_handshaker   r&   rZ   r   r#   r
   r"   r(   r)   r	   OPENr%   r'   r@   )	r-   rE   request_headersnonceaccept_tokenr7   rA   acceptsresponses	            r.   rJ   zH11Handshake._accept  s   '333,T-E-STT 45,U33 *+'$l3
 ( (@(MMMC0ACC(---NN*E,=,D,DW,M,MN    	G1_d&>&IJJ  G  G ;WEFFF,e11)
 
 

 &%)[KN!!n6K
 
 &*#((229c9r0   r   c                   | j         t          j        k    rd| j          }t          |          t	          |j                  }|j        s|                    d           t          j	        |j
        |          }| j                            |          pd}t          j        | _        |j        sA|| j                            t          j                              pdz  }t          j        | _        |S )Nz'Connection cannot be rejected in state )s   content-length   0)rS   r7   r0   )r3   r	   r$   r   r]   r7   rT   r[   r&   r_   rS   r'   r@   r`   r%   rb   r^   )r-   rE   rA   r7   r   rM   s         r.   rK   zH11Handshake._reject8  s    :333HDJHHC$   u}%%~ 	6NN4555<E,=wOOO#((229c%/~ 	1D(--c.>.@.@AAHSHD)0DKr0   r   c                Z   | j         t          j        k    rd| j          }t          |          | j                            t          j        |j                            pd}|j	        rA|| j                            t          j
                              pdz  }t          j        | _        |S )Nz$Cannot send rejection data in state )rM   r0   )r3   r	   r`   r   r'   r@   r&   ra   rM   rU   rb   r^   r%   )r-   rE   rA   rM   s       r.   rL   zH11Handshake._send_reject_dataJ  s    :222EEEC$   #((uz)B)B)BCCJs 	1D(--c.>.@.@AAHSHD)0DKr0   requestc                   || _         t                      | _        d|j                            d          fdt
          fdd| j        fdt          fg}|j        rB|                    dd	                    |j                                      d	          f           |j
        ri }|j
        D ]5}t          |t                    sJ |                                ||j        <   6g }|                                D ]t\  }}|                    d	          }t          |t                     r|r|                    |           G|                    d
||                    d	          fz             u|r*|                    dd	                    |          f           t#          j        d|j                            d	          ||j        z             }	| j                            |	          pdS )Ns   Hostrk   r   r   s   Sec-WebSocket-Keyr{   r   z, r~      %s; %sr      , r;   r<   r0   )r+   r   r,   r   r   r   r   r   r[   joinr   rH   r   offerr   itemsboolr&   r   r>   r   r'   r@   )
r-   r   r7   offerser   r   paramsbnamerr   s
             r.   rI   z!H11Handshake._initiate_connectionY  s   #* $&& gl))&112*+'!4;/%'89
  	NN-YYw344<<WEE    	V,.F' + +!!Y/////!"qvJ & S SfG,,fd++ S 1"))%000%%i5&--:P:P2Q&QRRRR V ;UZZ
=S=STUUU+>((11g33
 
 

 #((118S8r0   h11.InformationalResponsec                v   | j         J | j        J d }d }g }d }d}g }|j        D ]\  }}	|                                }|dk    rt	          |	          }/|dk    rt	          |	          }E|dk    r|	}N|dk    r|	                    d          }j|dk    r|	}s|                    ||	f           |t          d |D                       sd	}
t          |
t                      
          |                                t          k    r:dt                                           d}
t          |
t                      
          t          | j                  }||k    rd}
t          |
t                      
          |0|| j         j        vr"d| }
t          |
t                      
          t          |t          d| j         j                            }t!          | j        rt$          j        nt$          j        || j        j        d                   | _        t0          j        | _        t7          |||          S )Nr0   rj   rl   s   sec-websocket-acceptrn   r~   ro   c              3  F   K   | ]}|                                 d k    V  dS rq   rs   ru   s     r.   rx   z<H11Handshake._establish_client_connection.<locals>.<genexpr>  ry   r0   rz   rP   r|   r}   zBad accept tokenzunrecognized subprotocol Sequence[Extension]r   )r   r   r   )r+   r,   r7   rt   r   r   r[   r   r   r   r   r   r   client_extensions_handshaker   r   r   r#   r
   r"   r(   r'   trailing_datar)   r	   r   r%   r   )r-   rE   acceptr   r   r   rr   r7   r   r   rA   r   r   s                r.   r\   z)H11Handshake._establish_client_connection  s    '333{&&&  = 	* 	*KD%::<<D}$$$6u$=$=!222,U33...000#ll733z!!NND%=))))$C 0
 0
4E0
 0
 0
 -
 -
$ :C% 0 2 2    ==??///L/@/G/G/I/ILLLC%+--    -T[99\!!$C%c6F6H6HIIII"{$:R:_'_'_;k;;C%+--    1T/1I1TUU
 

 &%)[KN!!n6K .q1
 

 &*!k
 
 
 	
r0   strc                @    | j         j         d| j         d| j         dS )Nz(client=z, state=))	__class____name__r#   r3   r2   s    r.   __repr__zH11Handshake.__repr__  s*    .)UU4;UU
UUUUr0   N)r   r
   r   r   )r   r	   )r   r4   )r7   r   r8   r9   r   r   )rE   r   r   rF   )rM   rN   r   r   )r   rd   )rE   rh   r   r   )rE   r   r   rF   )rE   r   r   rF   )rE   r   r   rF   )r   r   r   rF   )rE   r   r   r   )r   r   )r   
__module____qualname____doc__r/   propertyr3   r6   rD   r@   r?   rg   rc   rJ   rK   rL   rI   r\   r    r0   r.   r   r   )   sa       >>) ) ) )    X 
  
  
  X
 < < < <*   67M 7M 7M 7Mr) ) ) )L( L( L( L(\(: (: (: (:T   $   )9 )9 )9 )9VC
 C
 C
 C
JV V V V V Vr0   r   	requestedIterable[str]	supportedlist[Extension]r   rN   c                   i }| D ]}|                     dd          d                                         }|D ]c}|j        |k    rV|                    |          }t	          |t
                    r|r
d||j        <   D||                    d          ||j        <   d|rg }|                                D ]\  }}|                    d          }	t	          |t
                    r|sJ |                    |	           I|dk    r|                    d|	z             h|                    d	|	|fz             d
	                    |          S dS )z
    Agree on the extensions to use returning an appropriate header value.

    This returns None if there are no agreed extensions
    ;r   r   TNr~   r0   s   %sr   r   )
splitstripr   r   rH   r   r   r   r[   r   )
r   r   r   r   r   	extensionr   r   r   
name_bytess
             r.   r   r     s    (*G 	E 	E{{3""1%++--" 	E 	EI~%%"))%00fd++ E 726	/'.4mmG.D.DGIN+	E  &"$
#MMOO 	D 	DLD&W--J&$'' D!!*----3!!%:"67777!!)z6.B"BCCCCzz*%%%4r0   acceptedr   c                ,   g }| D ]}|                     dd          d                                         }|D ]9}|j        |k    r,|                    |           |                    |            n#:d| }t          |t                                |S )Nr   r   r   zunrecognized extension rP   )r   r   r   finalizer[   r   r   )r   r   r   r   r   r   rA   s          r.   r   r     s    
 J  ||C##A&,,.." 		 		I~%%""6***!!),,, &
 3D22C% 0 2 2     r0   )r   r   r   r   r   rN   )r   r   r   r   r   r   )&r   
__future__r   collectionsr   typingr   r   r&   r6   r   r	   r
   rg   r   r   r   r   r   r   r   	utilitiesr   r   r   r   r   r   collections.abcr   r   r   r   r   r   r   r   r   r   r0   r.   <module>r      s    # " " " " "             
 


 C C C C C C C C C C R R R R R R R R R R R R R R ! ! ! ! ! !                  ==========   ! aV aV aV aV aV aV aV aVH! ! ! !H     r0   