o
    RhtF                     @   s  d Z ddlmZ ddlmZmZmZmZmZm	Z	m
Z
mZmZ 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 dd
lmZmZmZmZm Z m!Z! dZ"G dd dZ#dee$ de	e de
e% fddZ&dee$ dee de	e fddZ'dS )zR
wsproto/handshake
~~~~~~~~~~~~~~~~~~

An implementation of WebSocket handshakes.
    )deque)	castDequeDict	GeneratorIterableListOptionalSequenceUnionN   )
ConnectionConnectionStateConnectionType)AcceptConnectionEventRejectConnection
RejectDataRequest)	Extension)Headers)generate_accept_tokengenerate_nonceLocalProtocolErrornormed_header_dictRemoteProtocolErrorsplit_comma_headers   13c                   @   s&  e Zd ZdZdeddfddZedefddZede	e
 fd	d
Zdedeeef ddfddZdedefddZde	e ddfddZdeeddf fddZdejdefddZdedefddZdedefddZdedefddZdedefd d!Zdej defd"d#Z!defd$d%Z"dS )&H11Handshakez4A Handshake implementation for HTTP/1.1 connections.connection_typereturnNc                 C   sV   |t ju | _tj| _| jrttj| _nttj	| _d | _
t | _d | _d | _d S N)r   CLIENTclientr   
CONNECTING_stateh11r   _h11_connectionSERVER_connectionr   _events_initiating_request_nonce)selfr    r-   S/home/air/sanwanet/backup_V2/venv/lib/python3.10/site-packages/wsproto/handshake.py__init__*   s   
zH11Handshake.__init__c                 C      | j S r    )r$   r,   r-   r-   r.   state8   s   zH11Handshake.statec                 C   r0   )zReturn 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(   r1   r-   r-   r.   
connection<   s   
zH11Handshake.connectionheaderspathc                 C   s>   | j rtdtjd||d}ttj}| || dS )zInitiate 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targetr4   N)r"   r   r%   r   r   r!   receive_datasend)r,   r4   r5   upgrade_request
h11_clientr-   r-   r.   initiate_upgrade_connectionH   s   z(H11Handshake.initiate_upgrade_connectioneventc                 C   s   d}t |tr|| |7 }|S t |tr|| |7 }|S t |tr,|| |7 }|S t |tr:|| |7 }|S t	d| d)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
            zEvent z$ cannot be sent during the handshake)

isinstancer   _initiate_connectionr   _acceptr   _rejectr   _send_reject_datar   r,   r?   datar-   r-   r.   r;   [   s    


	


zH11Handshake.sendrG   c                 C   s^  | j |pd 	 z| j  }W n tjy   tdt dw t|tjs0|tju s0|tj	u r2d	S | j
rt|tjr^|jdkrJ| j| | nd| jtt|j|jdd tj| _nPt|tjrxtj| _| jtt|j|jdd n6t|tjr| jt|jdd n$t|tjr| jtddd tj| _nt|tjr| j| | q	)
zReceive 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.
        r@   TzBad HTTP message
event_hinte   F)r4   status_codehas_body)rG   body_finishedN)r&   r:   
next_eventr%   r   r   rA   ConnectionClosed	NEED_DATAPAUSEDr"   InformationalResponserK   r)   append_establish_client_connectionlistr4   r   CLOSEDr$   Response	REJECTINGDatar   rG   EndOfMessager   _process_connection_request)r,   rG   r?   r-   r-   r.   r:   t   s\   




zH11Handshake.receive_datac                 c   s"    | j r| j  V  | j sdS dS )zReturn a generator that provides any events that have been generated
        by protocol activity.

        :returns: a generator that yields H11 events.
        N)r)   popleftr1   r-   r-   r.   events   s   zH11Handshake.eventsc                 C   s  |j dkrtdt dd }g }d }d }g }d}d }g }	|jD ]N\}
}|
 }
|
dkr0t|}n6|
dkr:|d}q|
dkrF|t| q|
d	krM|}n|
d
krY|t| q|
dkr`|}n|
dkrf|}|	|
|f q|d u s{t	dd |D stdt d|t
krtdtdt
fg|rdnddd|d u rtdt d| dkrtdt d|d u rtdt dt||	|||jdd| _| jS )Nr6   zRequest method must be GETrH   r@   
   connections   hostidna   sec-websocket-extensions   sec-websocket-key   sec-websocket-protocols   sec-websocket-version   upgradec                 s       | ]	}|  d kV  qdS upgradeNlower.0tokenr-   r-   r.   	<genexpr>       
z;H11Handshake._process_connection_request.<locals>.<genexpr>%Missing header, 'Connection: Upgrade'z'Missing header, 'Sec-WebSocket-Version'   Sec-WebSocket-Versioni  i  )r4   rK   z#Missing header, 'Sec-WebSocket-Key'	   websocket$Missing header, 'Upgrade: WebSocket'zMissing header, 'Host'ascii)
extensionsextra_headershostsubprotocolsr9   )r8   r   r   r4   rh   r   decodeextendrS   anyWEBSOCKET_VERSIONr   r9   r*   )r,   r?   connection_tokensrs   ru   keyrv   rf   versionr4   namevaluer-   r-   r.   r[      s   




z(H11Handshake._process_connection_requestc                 C   s   | j d usJ t| j j}|d }t|}ddd|fg}|jd ur;|j| j jvr0td|j |d|jdf |j	rTt
ttt | j j	|j	}|rT|d|f tjd	||j d
}t| jretjntj|j	| _tj| _| j|pwdS )Nra      Upgrades	   WebSockets
   Connectionr   s   Sec-WebSocket-Acceptzunexpected subprotocol    Sec-WebSocket-Protocolrr      Sec-WebSocket-ExtensionsrJ   rK   r4   r@   )r*   r   rt   r   subprotocolrv   r   rS   encoders   server_extensions_handshaker   r
   strr%   rR   r   r"   r   r!   r'   r(   r   OPENr$   r&   r;   )r,   r?   request_headersnonceaccept_tokenr4   acceptsresponser-   r-   r.   rC      s<   

zH11Handshake._acceptc                 C   s   | j tjkrtd| j  t|j}|js|d tj	|j
|d}| j|p)d}tj| _|jsA|| jt p;d7 }tj| _|S )Nz)Connection cannot be rejected in state %s)s   content-length   0r   r@   )r2   r   r#   r   rU   r4   rL   rS   r%   rW   rK   r&   r;   rX   r$   rZ   rV   )r,   r?   r4   r   rG   r-   r-   r.   rD   %  s   

zH11Handshake._rejectc                 C   s`   | j tjkrtd| j  | jtj|jdpd}|j	r.|| jt
 p(d7 }tj| _|S )Nz$Cannot send rejection data in state )rG   r@   )r2   r   rX   r   r&   r;   r%   rY   rG   rM   rZ   rV   r$   rF   r-   r-   r.   rE   6  s   
zH11Handshake._send_reject_datarequestc           
      C   s  || _ t | _d|jdfddd| jfdtfg}|jr*|dd|jd	f |j	rxi }|j	D ]}t
|ts;J | ||j< q2g }| D ]"\}}|d	}t
|tr_|r^|| qI|d
||d	f  qI|rx|dd|f tjd|jd	||j d}	| j|	pdS )Ns   Hostr_   r   r   s   Sec-WebSocket-Keyro   r   z, rr      %s; %sr      , r6   r7   r@   )r*   r   r+   ru   r   rz   rv   rS   joinrs   rA   r   offerr~   itemsboolr%   r   r9   rt   r&   r;   )
r,   r   r4   offersers   r~   paramsbnamerf   r-   r-   r.   rB   D  sF   




z!H11Handshake._initiate_connectionc                 C   s  | j d usJ | jd usJ d }d }g }d }d}g }|jD ]9\}}	| }|dkr.t|	}q|dkr7t|	}q|dkr>|	}q|dkrH|	d}q|dkrO|	}q|||	f q|d u sdtdd	 |D sktd
t	 d| dkrxtdt	 dt
| j}
||
krtdt	 d|d ur|| j jvrtd| t	 dt|ttt | j j}t| jrtjntj|| jjd | _tj| _t|||dS )Nr@   r^   r`   s   sec-websocket-acceptrb   rr   rc   c                 s   rd   re   rg   ri   r-   r-   r.   rl     rm   z<H11Handshake._establish_client_connection.<locals>.<genexpr>rn   rH   rp   rq   zBad accept tokenzunrecognized subprotocol r   )rs   rt   r   )r*   r+   r4   rh   r   rw   rS   ry   r   r   r   rv   client_extensions_handshaker   r
   r   rs   r   r"   r   r!   r'   r&   trailing_datar(   r   r   r$   r   )r,   r?   acceptr{   r   r   rf   r4   r~   r   r   rs   r-   r-   r.   rT   o  sr   


z)H11Handshake._establish_client_connectionc                 C   s   d | jj| j| jS )Nz{}(client={}, state={}))format	__class____name__r"   r2   r1   r-   r-   r.   __repr__  s   zH11Handshake.__repr__)#r   
__module____qualname____doc__r   r/   propertyr   r2   r	   r   r3   r   r   bytesr   r>   r   r;   r:   r   r]   r%   r   r[   r   rC   r   rD   r   rE   rB   rR   rT   r   r-   r-   r-   r.   r   '   s@    

8
G'+
Ar   	requested	supportedr   c           
      C   s   i }| D ]4}| ddd  }|D ]%}|j|kr7||}t|tr+|r*d||j< q|dur7|d||j< qq|rtg }| D ]-\}}|d}	t|trY|sSJ ||	 qA|dkre|d|	  qA|d	|	|f  qAd
	|S dS )zAgree on the extensions to use returning an appropriate header value.

    This returns None if there are no agreed extensions
    ;r   r   TNrr   r@   s   %sr   r   )
splitstripr~   r   rA   r   r   r   rS   r   )
r   r   r   r   r~   	extensionr   rs   r   
name_bytesr-   r-   r.   r     s4   



	


r   acceptedc                 C   sf   g }| D ],}| ddd  }|D ]}|j|kr%|| ||  nqtd| t dq|S )Nr   r   r   zunrecognized extension rH   )r   r   r~   finalizerS   r   r   )r   r   rs   r   r~   r   r-   r-   r.   r     s   


r   )(r   collectionsr   typingr   r   r   r   r   r   r	   r
   r   r%   r3   r   r   r   r]   r   r   r   r   r   rs   r   r   	utilitiesr   r   r   r   r   r   rz   r   r   r   r   r   r-   r-   r-   r.   <module>   s8    , 
   
$