a
    &ñ»jtF  ã                   @   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#ee$ e	e e
e% dœdd„Z&ee$ ee e	e dœ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eddœdd„Zeedœdd„ƒZee	e
 dœd	d
„ƒZeeeef ddœdd„Zeedœdd„Ze	e ddœdd„Zeeddf dœdd„Zejedœdd„Zeedœdd„Zeedœdd„Zeedœdd„Zeedœdd „Zej edœd!d"„Z!edœd#d$„Z"dS )%ÚH11Handshakez4A Handshake implementation for HTTP/1.1 connections.N)Úconnection_typeÚreturnc                 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-   ú7E:\soccer\ml_env\Lib\site-packages\wsproto/handshake.pyÚ__init__*   s    zH11Handshake.__init__)r   c                 C   s   | j S r    )r$   ©r,   r-   r-   r.   Ústate8   s    zH11Handshake.statec                 C   s   | 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(   r0   r-   r-   r.   Ú
connection<   s    
zH11Handshake.connection)ÚheadersÚpathr   c                 C   s>   | j rtdƒ‚tjd||d�}t 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Útargetr3   N)r"   r   r%   r   r   r!   Úreceive_dataÚsend)r,   r3   r4   Zupgrade_requestZ
h11_clientr-   r-   r.   Úinitiate_upgrade_connectionH   s    ÿz(H11Handshake.initiate_upgrade_connection)Úeventr   c                 C   s€   d}t |tƒr||  |¡7 }n^t |tƒr8||  |¡7 }nDt |tƒrR||  |¡7 }n*t |tƒrl||  |¡7 }nt	d|› d�ƒ‚|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
        ó    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.send)rD   r   c                 C   sj  | j  |pd¡ z| j  ¡ }W n" tjy@   tdtƒ d�‚Y n0 t|tjƒsb|tju sb|tj	u rf�qf| j
�rFt|tjƒrÀ|jdkr˜| j |  |¡¡ n&| j tt|jƒ|jdd�¡ tj| _n„t|tjƒrôtj| _| j tt|jƒ|jdd�¡ nPt|tjƒ�r| j t|jdd�¡ n*t|tjƒ�rd| j tddd�¡ tj| _qt|tjƒr| j |  |¡¡ qd	S )
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.
        r=   zBad HTTP message©Z
event_hintée   F)r3   Ústatus_codeÚhas_bodyT)rD   Úbody_finishedN)r&   r9   Z
next_eventr%   r   r   r>   ZConnectionClosedZ	NEED_DATAZPAUSEDr"   ÚInformationalResponserG   r)   ÚappendÚ_establish_client_connectionÚlistr3   r   ÚCLOSEDr$   ÚResponseÚ	REJECTINGÚDatar   rD   ÚEndOfMessager   Ú_process_connection_request)r,   rD   r<   r-   r-   r.   r9   t   sX    ÿ
ÿþý
ýÿ
ýÿÿ
zH11Handshake.receive_datac                 c   s   | j r| j  ¡ V  q 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)   Úpopleftr0   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 ]¢\}
}|
 ¡ }
|
dkr`t|ƒ}nr|
dkrv| d¡}q>n\|
dkr�| t|ƒ¡ q>nB|
d	krž|}n4|
d
kr¸| t|ƒ¡ q>n|
dkrÆ|}n|
dkrÒ|}|	 |
|f¡ q>|d u sþt	dd„ |D ƒƒ�stdtƒ d�‚|t
k�r:tdtdt
fg|�r.dndd�d�‚|d u �rRtdtƒ d�‚| ¡ dk�rntdtƒ d�‚|d u �r†tdtƒ d�‚t||	|||j d¡d�| _| jS )Nr5   zRequest method must be GETrE   r=   ó
   connections   hostÚidnaó   sec-websocket-extensionsó   sec-websocket-keyó   sec-websocket-protocols   sec-websocket-versionó   upgradec                 s   s   | ]}|  ¡ d kV  qdS ©ÚupgradeN©Úlower©Ú.0Útokenr-   r-   r.   Ú	<genexpr>Ú   s   z;H11Handshake._process_connection_request.<locals>.<genexpr>ú%Missing header, 'Connection: Upgrade'z'Missing header, 'Sec-WebSocket-Version'ó   Sec-WebSocket-Versioniª  i�  )r3   rG   z#Missing header, 'Sec-WebSocket-Key'ó	   websocketú$Missing header, 'Upgrade: WebSocket'zMissing header, 'Host'Úascii)Ú
extensionsÚextra_headersÚhostÚsubprotocolsr8   )r7   r   r   r3   r_   r   ÚdecodeÚextendrK   ÚanyÚWEBSOCKET_VERSIONr   r8   r*   )r,   r<   Úconnection_tokensri   rk   Úkeyrl   r]   Úversionr3   ÚnameÚvaluer-   r-   r.   rS   ·   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rv|j| j jvr`td|j› �ƒ‚| d|j d¡f¡ |j	r¨t
ttt | j j	ƒ|j	ƒ}|r¨| d|f¡ tjd	||j d
�}t| jrÊtjntj|j	ƒ| _tj| _| j |¡pîdS )NrY   ©ó   Upgrades	   WebSocket©s
   Connectionrw   s   Sec-WebSocket-Acceptzunexpected subprotocol ó   Sec-WebSocket-Protocolrh   ó   Sec-WebSocket-ExtensionsrF   ©rG   r3   r=   )r*   r   rj   r   Úsubprotocolrl   r   rK   Úencoderi   Úserver_extensions_handshaker   r
   Ústrr%   rJ   r   r"   r   r!   r'   r(   r   ÚOPENr$   r&   r:   )r,   r<   Zrequest_headersÚnonceÚaccept_tokenr3   ÚacceptsÚresponser-   r-   r.   r@   þ   s<    ý
ÿþ
ÿþzH11Handshake._acceptc                 C   s†   | j tjkrtd| j  ƒ‚t|jƒ}|js4| d¡ tj	|j
|d�}| j |¡pRd}tj| _|js‚|| j t ¡ ¡pvd7 }tj| _|S )Nz)Connection cannot be rejected in state %s)s   content-lengthó   0r{   r=   )r1   r   r#   r   rM   r3   rH   rK   r%   rO   rG   r&   r:   rP   r$   rR   rN   )r,   r<   r3   r„   rD   r-   r-   r.   rA   %  s    ÿ

zH11Handshake._rejectc                 C   s`   | j tjkrtd| j › �ƒ‚| j tj|jd�¡p4d}|j	r\|| j t 
¡ ¡pPd7 }tj| _|S )Nz$Cannot send rejection data in state )rD   r=   )r1   r   rP   r   r&   r:   r%   rQ   rD   rI   rR   rN   r$   rC   r-   r-   r.   rB   6  s    
ÿzH11Handshake._send_reject_data)Úrequestr   c           
      C   s   || _ tƒ | _d|j d¡fddd| jfdtfg}|jrT| dd |j¡ d	¡f¡ |j	rði }|j	D ] }t
|tƒsvJ ‚| ¡ ||j< qdg }| ¡ D ]D\}}| d	¡}t
|tƒr¾|rÖ| |¡ q’| d
|| d	¡f ¡ q’|rð| dd |¡f¡ tjd|j d	¡||j d�}	| j |	¡�pdS )Ns   HostrW   rv   rx   s   Sec-WebSocket-Keyre   ry   z, rh   ó   %s; %srz   ó   , r5   r6   r=   )r*   r   r+   rk   r}   rp   rl   rK   Újoinri   r>   r   Úofferrt   ÚitemsÚboolr%   r   r8   rj   r&   r:   )
r,   r†   r3   ZoffersÚeri   rt   ÚparamsZbnamer]   r-   r-   r.   r?   D  sD    ûþÿ



ýz!H11Handshake._initiate_connectionc                 C   sš  | j d usJ ‚| jd usJ ‚d }d }g }d }d}g }|jD ]z\}}	| ¡ }|dkr^t|	ƒ}q:nH|dkrrt|	ƒ}q:n4|dkr‚|	}q:n$|dkr˜|	 d¡}q:n|dkr¦|	}q:| ||	f¡ q:|d u sÐtdd	„ |D ƒƒsÞtd
t	ƒ d�‚| ¡ dkrøtdt	ƒ d�‚t
| jƒ}
||
k�rtdt	ƒ d�‚|d u�rF|| j jv�rFtd|› �t	ƒ d�‚t|ttt | j jƒƒ}t| j�rntjntj|| jjd ƒ| _tj| _t|||d�S )Nr=   rV   rX   s   sec-websocket-acceptrZ   rh   r[   c                 s   s   | ]}|  ¡ d kV  qdS r\   r^   r`   r-   r-   r.   rc   �  s   z<H11Handshake._establish_client_connection.<locals>.<genexpr>rd   rE   rf   rg   zBad accept tokenzunrecognized subprotocol r   )ri   rj   r|   )r*   r+   r3   r_   r   rm   rK   ro   r   r   r   rl   Úclient_extensions_handshaker   r
   r   ri   r   r"   r   r!   r'   r&   Ztrailing_datar(   r   r€   r$   r   )r,   r<   Úacceptrq   rƒ   r|   r]   r3   rt   ru   r‚   ri   r-   r-   r.   rL   o  sr    
ÿÿÿ


þÿ
ýÿz)H11Handshake._establish_client_connectionc                 C   s   d  | jj| j| j¡S )Nz{}(client={}, state={}))ÚformatÚ	__class__Ú__name__r"   r1   r0   r-   r-   r.   Ú__repr__°  s    ÿzH11Handshake.__repr__)#r“   Ú
__module__Ú__qualname__Ú__doc__r   r/   Úpropertyr   r1   r	   r   r2   r   r   Úbytesr   r;   r   r:   r9   r   rU   r%   r   rS   r   r@   r   rA   r   rB   r?   rJ   rL   r”   r-   r-   r-   r.   r   '   s.   þ8þG',þAr   )Ú	requestedÚ	supportedr   c           
      C   sì   i }| D ]h}|  dd¡d  ¡ }|D ]J}|j|kr$| |¡}t|tƒrV|rnd||j< q$|dur$| d¡||j< q$q|règ }| ¡ D ]Z\}}| d¡}	t|tƒr²|s¦J ‚| |	¡ q‚|dkrÊ| d|	 ¡ q‚| d	|	|f ¡ q‚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   TNrh   r=   s   %sr‡   rˆ   )
ÚsplitÚstriprt   r�   r>   rŒ   r}   r‹   rK   r‰   )
rš   r›   rƒ   rŠ   rt   Ú	extensionr�   ri   rŽ   Z
name_bytesr-   r-   r.   r~   ¶  s.    





r~   )Úacceptedr›   r   c                 C   sf   g }| D ]X}|  dd¡d  ¡ }|D ]&}|j|kr$| |¡ | |¡  qq$td|› �tƒ d�‚q|S )Nrœ   r   r   zunrecognized extension rE   )r�   rž   rt   ÚfinalizerK   r   r   )r    r›   ri   r�   rt   rŸ   r-   r-   r.   r�   Ú  s    


ÿr�   )(r—   Úcollectionsr   Útypingr   r   r   r   r   r   r	   r
   r   r%   r2   r   r   r   rU   r   r   r   r   r   ri   r   r   Z	utilitiesr   r   r   r   r   r   rp   r   r   r™   r~   r�   r-   r-   r-   r.   Ú<module>   s&   , 
   þ%þ