B
    @¦CZP,  ã               @   sˆ   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 d dlm	Z	 dZ
dd„ Zddd	„Zdd
d„ZG dd„ deƒZG dd„ deƒZdS )é    N)Ú	b64decodeÚ	b64encode)Úsha1s$   258EAFA5-E914-47DA-95CA-C5AB0DC85B11c             C   s4   t | tƒr|  d¡} nt | tƒs(t| ƒ} d|  }|S )znPack the message inside ``00`` and ``FF``
    As per the dataframing section (5.3) for the websocket spec
    zutf-8u    %sÃ¿)Ú
isinstanceZunicodeÚencodeÚstr)ÚmessageÚpacked© r
   ú1lib/python3.7/site-packages/werkzeug/websocket.pyÚpack_message   s    

r   Fc             C   s„   |rt | ƒ} d|d@ B }t| ƒ}|dkr8t d||¡}n:|dkrZ|dk rZt d|d|¡}n|dkrrt d|d	|¡}||  t|ƒd
fS )zõ Encode a HyBi style WebSocket frame.
    Optional opcode:
        0x0 - continuation
        0x1 - text frame (base64 encode buf)
        0x2 - binary frame (use raw buf)
        0x8 - connection close
        0x9 - ping
        0xA - pong
    é€   é   é}   z>BBi   z>BBHé~   z>BBQé   r   )r   ÚlenÚstructÚpack)ÚbufÚopcodeÚbase64Úb1Zpayload_lenÚheaderr
   r
   r   Úencode_hybi   s    
r   c          
   C   s  ddddddddddœ	}t | ƒ}||d< ||d k r8|S t d| ¡\}}|d@ |d	< |d
@ d? |d< |d
@ d? }|d@ |d< |d dkr´d|d< ||d k r |S t d| ¡\|d< n6|d dkrêd|d< ||d k rØ|S t d| ¡\|d< |d |d  |d  }||k r|S || |d< |r|| |d |d d … |d< d }}	|d dkrêt d| |d |d d … ¡d }
|d d }d}x`tdt|d d ƒƒD ]F}t d| |d|  |d|d   … ¡d }|t d|
|A ¡7 }q W |d d rn|d d }|d }|| }d}	xTtd|ƒD ]F}t d| ||  ¡d }t d| ||  ¡d }
|	t|
|A ƒ7 }	q$W ||	 |d< n| |d |d  |… |d< |r¼|d	 dkr¼t	|d ƒ|d< |d	 dkr|d dkrìt d|d ¡|d< |d dkr|d dd… |d < |S )!z$Decode HyBi style WebSocket packets.r   é   N)	Úfinr   ÚmaskÚhlenÚlengthÚpayloadÚleftÚ
close_codeÚclose_reasonr!   r   z>BBr   r   r   é   r   r   r   r   é   z>xxHé
   z>xxQr   Ú z<Ié   ÚIÚBr    )r(   r   é   z>Hr"   é   r#   )
r   r   Zunpack_fromZunpackZxrangeÚintr   ÚrangeÚchrr   )r   r   ÚfZblenr   Zb2Zhas_maskZfull_lenÚbÚcÚdataZof1Úir   ÚlZof2r
   r
   r   Údecode_hybi1   sz    
$,r6   c               @   s$   e Zd Zdd„ Zdd„ Zdd„ ZdS )ÚWebSocketWSGIc             C   s
   || _ d S )N)Úhandler)Úselfr8   r
   r
   r   Ú__init__†   s    zWebSocketWSGI.__init__c             C   s   d S )Nr
   )r9   Úwsr
   r
   r   Úverify_client‰   s    zWebSocketWSGI.verify_clientc          
   C   sì  |  d¡ d¡dkr$|d  ¡ dks4|ddgƒ g S |d }t||ƒ}d	}|d
 }|  d¡}|rxt|ƒ}t|ƒdkr†|ddgƒ g S g }	|  d¡}
g }|
rÊx,|
 d¡D ]}| ¡ }||	kr¨| |¡ q¨W |rà|dd 	|¡ 7 }g }|  d¡}g }|r*x0| d¡D ]"}| ¡ }||kr| |¡ qW |rB|dd 	|¡ 7 }|d|  d¡|  d¡||j
tt|t ƒ ¡ ƒf 7 }n|d|  d¡|  d¡|f 7 }| |¡ y|  |¡ W n8 tjk
ræ } z|d tjkrÖ‚ W d d }~X Y nX tS )NZHTTP_CONNECTIONZUpgradeéÿÿÿÿZHTTP_UPGRADEZ	websocketz400 Bad Request)Z
ConnectionÚclosezgunicorn.socketzKHTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Z	PATH_INFOZHTTP_SEC_WEBSOCKET_KEYé   ZHTTP_SEC_WEBSOCKET_PROTOCOLú,zSec-WebSocket-Protocol: %s
z, ZHTTP_SEC_WEBSOCKET_EXTENSIONSzSec-WebSocket-Extensions: %s
ztSec-WebSocket-Origin: %s
Sec-WebSocket-Location: ws://%s%s
Sec-WebSocket-Version: %s
Sec-WebSocket-Accept: %s

ZHTTP_ORIGINZ	HTTP_HOSTz7WebSocket-Origin: %s
WebSocket-Location: ws://%s%s

r   )ÚgetÚfindÚlowerÚ	WebSocketr   r   ÚsplitÚstripÚappendÚjoinÚversionr   r   ÚWS_KEYZdigestÚsendallr8   ÚsocketÚerrorÚerrnoZEPIPEZALREADY_HANDLED)r9   ÚenvironZstart_responseÚsockr;   Zhandshake_replyÚpathÚkeyZws_keyZ	protocolsZsubprotocolsZws_protocolsÚsZextsÚ
extensionsZws_extensionsZextÚer
   r
   r   Ú__call__Œ   sj    






zWebSocketWSGI.__call__N)Ú__name__Ú
__module__Ú__qualname__r:   r<   rV   r
   r
   r
   r   r7   „   s   r7   c               @   s@   e Zd Zddd„Zdd„ Zdd„ Zdd	„ Zddd„Zdd„ ZdS )rD   éL   c          	   C   s\   || _ yt| d¡ƒ}W n ttfk
r4   d}Y nX || _d| _d| _d| _t	 
¡ | _d S )NZHTTP_SEC_WEBSOCKET_VERSIONrZ   Fó    )Ú_socketr-   rA   Ú
ValueErrorÚ	TypeErrorrI   ÚclosedZacceptedÚ_bufÚcollectionsÚdequeÚ_msgs)r9   rP   rO   rI   r
   r
   r   r:   Þ   s    
zWebSocket.__init__c             C   s"  g }d}| j }x|r| jdkr„t|dd}|d dkr>P nD|d dkrTd	| _P n.| |d ¡ |d
 r~||d
  d… }nd}qt|d ƒ}|dkrØ| d¡}|dkr¬P | |d|…  dd¡¡ ||d d… }q|dkrt|d ƒdksþtd| ƒ‚d	| _P qt	d| ƒ‚qW || _ |S )a0   Parses for messages in the buffer *buf*.  It is assumed that
        the buffer contains the start character for a message, but that it
        may contain only part of the rest of the message.
        Returns an array of messages, and the buffer remainder that
        didn't contain any full messages.r   )r$   r+   é   F)r   r    Nr   r+   Tr!   r[   õ   Ã¿r=   r(   zutf-8Úreplaceéÿ   z Unexpected closing handshake: %rz6Don't understand how to parse this type of message: %r)
r`   rI   r6   r_   rG   ÚordrB   ÚdecodeÚAssertionErrorr]   )r9   ÚmsgsZend_idxr   ÚframeZ
frame_typer
   r
   r   Ú_parse_messagesê   s:    



zWebSocket._parse_messagesc             C   s8   | j dkr t|ddd\}}}nt|ƒ}| j |¡ dS )a  Send a message to the browser.
        *message* should be convertable to a string; unicode objects should be
        encodable as utf-8.  Raises socket.error with errno of 32
        (broken pipe) if the socket has already been closed by the client.
        )r$   r+   rd   r(   F)r   r   N)rI   r   r   r\   rK   )r9   r   r	   ZlenheadZlentailr
   r
   r   Úsend  s
    
zWebSocket.sendc             C   sZ   xN| j sN| jrdS | j d¡}|dkr*dS |  j|7  _|  ¡ }| j  |¡ qW | j  ¡ S )a!  Waits for and deserializes messages.
        Returns a single message; the oldest not yet processed. If the client
        has already closed the connection, returns None.  This is different
        from normal socket behavior because the empty string is a valid
        websocket message.Ni   r'   )rc   r_   r\   Zrecvr`   rm   ÚextendÚpopleft)r9   Zdeltark   r
   r
   r   Úwait$  s    zWebSocket.waitFc             C   s„   | j dkr<| js<d}t|ddd\}}}| j |¡ d| _nD| j dkr€| js€y| j d¡ W n tjk
rx   |st‚ Y nX d| _d	S )
z3Sends the closing frame to the client, if required.)r$   r+   rd   r'   r+   F)r   r   TrZ   u   Ã¿ N)rI   r_   r   r\   rK   rL   rM   )r9   Zignore_send_errorsÚmsgr   ÚhÚtr
   r
   r   Ú_send_closing_frame7  s    zWebSocket._send_closing_framec             C   s"   |   ¡  | j d¡ | j ¡  dS )zcForcibly close the websocket; generally it is preferable to
        return from the handler method.TN)ru   r\   Zshutdownr>   )r9   r
   r
   r   r>   L  s    zWebSocket.closeN)rZ   )F)	rW   rX   rY   r:   rm   rn   rq   ru   r>   r
   r
   r
   r   rD   Ü   s   
-
rD   )F)F)ÚrerN   rL   r   ra   r   r   r   Zhashlibr   rJ   r   r   r6   Úobjectr7   rD   r
   r
   r
   r   Ú<module>   s   

SX