3
Z_ð]Î~  ã               @   sæ  d dl Z d dlZd dlZd dlZd dlmZ d dlmZ d dl	Z	d dl
Z
d dlZd dlZd dlZyd dlmZmZ W n, ek
r    d dlmZ d dlmZ Y nX d dlmZ d dlmZ d d	lmZ d d
lmZ d dlZx>d$D ]6Zyeei i dgƒZW n ek
�r   dZY qàX P qàW eejejfƒZ ddgZ!dZ"ee#e$ddƒƒe#e$ddƒƒ e#e$ddƒƒ e#e$ddƒƒ ƒZ%G dd„ de&ƒZ'G dd„ de(ƒZ)G dd„ de(ƒZ*G dd„ de&ƒZ+G dd„ de&ƒZ,G d d!„ d!e-ƒZ.G d"d#„ d#e*ƒZ/dS )%é    N)ÚRandom)Úerror)Úmd5Úsha1)r   )Úsha)Ú	semaphore)Úwsgi)Úsocket)Ú	get_errnoúwsaccel.utf8validatorúautobahn.utf8validatorÚ ÚWebSocketWSGIÚ	WebSockets$   258EAFA5-E914-47DA-95CA-C5AB0DC85B11iè  iì  iï  iô  i¸  i   iˆ  c                   s   e Zd Zd‡ fdd„	Z‡  ZS )Ú
BadRequestú400 Bad RequestNc                s$   t t| ƒjƒ  || _|| _|| _d S )N)ÚsuperÚ	ExceptionÚ__init__ÚstatusÚbodyÚheaders)Úselfr   r   r   )Ú	__class__© ú6/tmp/pip-build-yz_zf6az/eventlet/eventlet/websocket.pyr   9   s    zBadRequest.__init__)r   NN)Ú__name__Ú
__module__Ú__qualname__r   Ú__classcell__r   r   )r   r   r   8   s   r   c               @   s^   e Zd ZdZdd„ Zeddd„ƒZdd	„ Zd
d„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ ZdS )r   a¸  Wraps a websocket handler function in a WSGI application.

    Use it like this::

      @websocket.WebSocketWSGI
      def my_handler(ws):
          from_browser = ws.wait()
          ws.send("from server")

    The single argument to the function will be an instance of
    :class:`WebSocket`.  To close the socket, simply return from the
    function.  Note that the server will log the websocket request at
    the time of closure.
    c             C   s"   || _ d | _d| _g | _d | _d S )NT)ÚhandlerÚprotocol_versionÚsupport_legacy_versionsÚsupported_protocolsÚorigin_checker)r   r    r   r   r   r   P   s
    zWebSocketWSGI.__init__NFc                s&   ‡ ‡‡‡fdd„}|d kr|S ||ƒS )Nc                s"   ˆ | ƒ}ˆ|_ ˆ|_ˆrˆ|_|S )N)r"   r$   r#   )r    Úinst)Úclsr$   r"   r#   r   r   Ú	decorator]   s    z+WebSocketWSGI.configured.<locals>.decoratorr   )r&   r    r#   r$   r"   r'   r   )r&   r$   r"   r#   r   Ú
configuredW   s    zWebSocketWSGI.configuredc       	      C   s   dd„ |j ddƒjƒ jdƒD ƒ}d|ko:|j ddƒjƒ dksL|d	dgƒ g S y0d|krb| j|ƒ}n| jrt| j|ƒ}ntƒ ‚W nL tk
rÈ } z0|j}|jpœd}|j	p¦g }||dg| ƒ |gS d }~X nX y| j
|ƒ W n6 tjk
�r } zt|ƒtk� rþ‚ W Y d d }~X nX |jdƒ tjS )Nc             S   s   g | ]}|j ƒ ‘qS r   )Ústrip)Ú.0Úpartr   r   r   ú
<listcomp>j   s   z*WebSocketWSGI.__call__.<locals>.<listcomp>ZHTTP_CONNECTIONr   ú,ÚupgradeZHTTP_UPGRADEZ	websocketz400 Bad RequestÚ
ConnectionÚcloseÚHTTP_SEC_WEBSOCKET_VERSIONó    T)r/   r0   )r/   r0   )ÚgetÚlowerÚsplitÚ_handle_hybi_requestr"   Ú_handle_legacy_requestr   r   r   r   r    r	   r   r
   ÚACCEPTABLE_CLIENT_ERRORSÚ_send_closing_framer   ZALREADY_HANDLED)	r   ÚenvironZstart_responseZhttp_connection_partsÚwsÚer   r   r   r   r   r   Ú__call__h   s4    



zWebSocketWSGI.__call__c             C   sª  d|kr|d j ƒ }nd|kr(|d }ntdƒ‚d|krNd| _d|krTtƒ ‚nd| _| jdkr°| j|d ƒ}| j|d ƒ}d|d	 _|d	 jdƒ}tjd
||ƒ| }t	|ƒj
ƒ }d}|jdƒdkrÆd}d||jdƒ|jdƒ|jdƒf }	|jdƒ}
|
d k	�r|	d|
 7 }	| jdk�r<dtj|jdƒƒ d tj|	ƒ d }nV| jdk�rŠdtj|jdƒƒ d tj|jddƒƒ d tj|	ƒ d | }ntdƒ‚|j|ƒ t||| jƒS )Nzeventlet.inputzgunicorn.socketz8No eventlet.input or gunicorn.socket present in environ.ZHTTP_SEC_WEBSOCKET_KEY1éL   ZHTTP_SEC_WEBSOCKET_KEY2éK   é   z
wsgi.inputz>IIr;   zwsgi.url_schemeÚhttpsÚwssz%s://%s%s%sÚ	HTTP_HOSTÚSCRIPT_NAMEÚ	PATH_INFOÚQUERY_STRINGú?sg   HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
WebSocket-Origin: ÚHTTP_ORIGINs   
WebSocket-Location: s   

sj   HTTP/1.1 101 WebSocket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Origin: s   
Sec-WebSocket-Protocol: ÚHTTP_SEC_WEBSOCKET_PROTOCOLÚdefaults   
Sec-WebSocket-Location: z#Unknown WebSocket protocol version.)Ú
get_socketr   r!   r   Ú_extract_numberÚcontent_lengthÚreadÚstructÚpackr   Údigestr3   ÚsixÚbÚ
ValueErrorÚsendallr   )r   r:   ÚsockÚkey1Úkey2Zkey3ÚkeyÚresponseÚschemeÚlocationÚqsÚhandshake_replyr   r   r   r7   Œ   sF    




(	B
z$WebSocketWSGI._handle_legacy_requestc             C   s¼   |d krd S i }x¦|j dƒD ]˜}|j dƒ}i }xf|dd … D ]V}|j dƒ}t|ƒdkrld||d jƒ jƒ < q<|d jƒ jdƒjƒ ||d jƒ jƒ < q<W |j|d jƒ jƒ g ƒj|ƒ qW |S )Nr-   ú;é   ú=Tr   ú")r5   Úlenr)   r4   Ú
setdefaultÚappend)r   ÚheaderÚresÚextÚpartsÚconfigr+   Zkey_valr   r   r   Ú_parse_extension_headerÊ   s    

*"z%WebSocketWSGI._parse_extension_headerc             C   s  |sd S |j dƒ}|d krd S xä|D ]Ü}|j ddƒ|j ddƒdœ}ttjdƒ}|j dƒ}|d k	r¤|dkrr||d< n2t|j d|ƒƒ|d< d	|d   koœdkn  s¤q$|j d
ƒ}|d k	� rþ|dkrÊ||d
< n4t|j d
|ƒƒ|d
< d	|d
   koôdkn  � sþq$|S W d S )Nzpermessage-deflateÚserver_no_context_takeoverFÚclient_no_context_takeover)rl   rm   é   Úserver_max_window_bitsTr@   Úclient_max_window_bits)r3   ÚminÚzlibÚ	MAX_WBITSÚint)r   Ú
extensionsÚdeflaterj   Zwant_configZ	max_wbitsZmwbr   r   r   Ú_negotiate_permessage_deflateÚ   s2    







z+WebSocketWSGI._negotiate_permessage_deflatec             C   sž   |sd S g }x†|j ƒ D ]z\}}tj|ƒg}xT|j ƒ D ]H\}}|dkrFq4|dkr`|jtj|ƒƒ q4|jtjd|t|ƒf ƒƒ q4W |jdj|ƒƒ qW dj|ƒS )NFTz%s=%ss   ; s   , )ÚitemsrR   rS   re   ÚstrÚjoin)r   Úparsed_extensionsri   Únamerj   Z	ext_partsrY   Úvaluer   r   r   Ú_format_extension_header   s     z&WebSocketWSGI._format_extension_headerc             C   s¸  d|kr|d j ƒ }nd|kr(|d }ntdƒ‚|d }|d"krNtdd#gd
�‚t|ƒ| _d|krftƒ ‚|jd| jdkr‚|jddƒndƒ}| jd k	r®| j|jdƒ|ƒs®tdd�‚|jdd ƒ}d }|rðx,dd„ |jdƒD ƒD ]}|| jkrØ|}P qØW |d }t	j
ttj|ƒt ƒjƒ ƒ}	dddd|	 g}
|�r>|
jdtj|ƒ ƒ i }| j|jdƒƒ}| j|ƒ}|d k	�rn||d< | j|ƒ}|d k	�r�|
jd| ƒ |jdj|
ƒd  ƒ t||| j||d!�S )$Nzeventlet.inputzgunicorn.socketz8No eventlet.input or gunicorn.socket present in environ.r1   Ú8Ú13z426 Upgrade RequiredúSec-WebSocket-Versionú8, 13)r   r   ZHTTP_SEC_WEBSOCKET_KEYrH   r@   ZHTTP_SEC_WEBSOCKET_ORIGINr   rC   z403 Forbidden)r   rI   c             s   s   | ]}|j ƒ V  qd S )N)r)   )r*   Úir   r   r   ú	<genexpr>*  s    z5WebSocketWSGI._handle_hybi_request.<locals>.<genexpr>r-   s    HTTP/1.1 101 Switching Protocolss   Upgrade: websockets   Connection: Upgrades   Sec-WebSocket-Accept: s   Sec-WebSocket-Protocol: ZHTTP_SEC_WEBSOCKET_EXTENSIONSzpermessage-deflates   Sec-WebSocket-Extensions: s   
s   

)Úprotocolru   )r   r€   )r�   r‚   )rK   r   r   rt   r!   r3   r$   r5   r#   Úbase64Ú	b64encoder   rR   rS   ÚPROTOCOL_GUIDrQ   re   rk   rw   r~   rU   rz   ÚRFC6455WebSocket)r   r:   rV   Zhybi_versionÚoriginZ	protocolsZnegotiated_protocolÚprY   rZ   r^   r{   ru   rv   Zformatted_extr   r   r   r6     sZ    











z"WebSocketWSGI._handle_hybi_requestc             C   sF   d}d}x0|D ](}|t jkr&||7 }q|dkr|d7 }qW t|ƒ| S )zš
        Utility function which, given a string like 'g98sd  5[]221@1', will
        return 9852211. Used to parse the Sec-WebSocket-Key headers.
        r   r   ú r`   )ÚstringÚdigitsrt   )r   r}   ÚoutÚspacesÚcharr   r   r   rL   H  s    


zWebSocketWSGI._extract_number)NNNF)r   r   r   Ú__doc__r   Úclassmethodr(   r=   r7   rk   rw   r~   r6   rL   r   r   r   r   r   @   s      $>&8c               @   sL   e Zd ZdZddd„Zdd„ Zdd„ Zd	d
„ Zdd„ Zddd„Z	dd„ Z
dS )r   a{  A websocket object that handles the details of
    serialization/deserialization to the socket.

    The primary way to interact with a :class:`WebSocket` object is to
    call :meth:`send` and :meth:`wait` in order to pass messages back
    and forth with the browser.  Also available are the following
    properties:

    path
        The path value of the request.  This is the same as the WSGI PATH_INFO variable,
        but more convenient.
    protocol
        The value of the Websocket-Protocol header.
    origin
        The value of the 'Origin' header.
    environ
        The full WSGI environment for this request.

    r>   c             C   s¤   |j dtjƒ| _dj|j dƒ|j ddƒ|j ddƒ |j dƒ|j dƒd	�| _|| _|j d
ƒ| _|j dƒ| _|j dƒ| _	|| _
|| _d| _d| _tjƒ | _tjƒ | _dS )zê
        :param socket: The eventlet socket
        :type socket: :class:`eventlet.greenio.GreenSocket`
        :param environ: The wsgi environment
        :param version: The WebSocket spec version to follow (default is 76)
        zwsgi.errorsz-server={shost}/{spath} client={caddr}:{cport}rC   rD   r   rE   ZREMOTE_ADDRZREMOTE_PORT)ZshostZspathZcaddrZcportrH   ZHTTP_WEBSOCKET_PROTOCOLFr2   N)r3   ÚsysÚstderrÚlogÚformatÚlog_contextr	   rŠ   r…   Úpathr:   ÚversionÚwebsocket_closedÚ_bufÚcollectionsÚdequeÚ_msgsr   Ú	SemaphoreÚ	_sendlock)r   rV   r:   rš   r   r   r   r   l  s    
zWebSocket.__init__c             C   sB   t |tjƒr|jdƒ}nt |tjƒs2tjt|ƒƒ}d| d }|S )zwPack the message inside ``00`` and ``FF``

        As per the dataframing section (5.3) for the websocket spec
        zutf-8ó    ó   ÿ)Ú
isinstancerR   Ú	text_typeÚencodeÚbinary_typerS   ry   )r   ÚmessageÚpackedr   r   r   Ú_pack_message„  s    zWebSocket._pack_messagec             C   s°   g }d}| j }x–|r¤tj|dƒ}|dkrh|jdƒ}|dkr<P |j|d|… jddƒƒ ||d d… }q|dkr–tj|dƒdksŒtd| ƒ‚d	| _P qtd
| ƒ‚qW || _ |S )a1   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`   zutf-8ÚreplaceNéÿ   z Unexpected closing handshake: %rTz6Don't understand how to parse this type of message: %réÿÿÿÿ)	rœ   rR   Ú
indexbytesÚfindre   ÚdecodeÚAssertionErrorr›   rT   )r   ÚmsgsZend_idxÚbufZ
frame_typer   r   r   Ú_parse_messages�  s$    
zWebSocket._parse_messagesc          
   C   s6   | j |ƒ}| jjƒ  z| jj|ƒ W d| jjƒ  X dS )zû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.N)rª   r¡   Úacquirer	   rU   Úrelease)r   r¨   r©   r   r   r   Úsend­  s
    

zWebSocket.sendc             C   sZ   xN| j sN| jrdS | jjdƒ}|dkr*dS |  j|7  _| jƒ }| j j|ƒ qW | j 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   r2   )rŸ   r›   r	   Úrecvrœ   r´   ÚextendÚpopleft)r   Údeltar²   r   r   r   Úwait¼  s    zWebSocket.waitFc             C   sH   | j dkrD| j rDy| jjdƒ W n tk
r<   |s8‚ Y nX d| _dS )z3Sends the closing frame to the client, if required.r>   s   ÿ TN)rš   r›   r	   rU   ÚSocketError)r   Úignore_send_errorsr   r   r   r9   Ð  s    zWebSocket._send_closing_framec             C   sx   zfy| j dƒ | jjdƒ W nF tk
rb } z*|jtjkrR| jjdj| j	|d�ƒ W Y dd}~X nX W d| jj
ƒ  X dS )zcForcibly close the websocket; generally it is preferable to
        return from the handler method.Tz {ctx} socket shutdown error: {e})Úctxr<   N)r9   r	   Úshutdownr½   ÚerrnoÚENOTCONNr–   Úwriter—   r˜   r0   )r   r<   r   r   r   r0   Ü  s    
.zWebSocket.closeN)r>   )F)r   r   r   r’   r   rª   r´   r·   r¼   r9   r0   r   r   r   r   r   W  s   

c               @   s   e Zd ZdS )ÚConnectionClosedErrorN)r   r   r   r   r   r   r   rÄ   é  s   rÄ   c                   s   e Zd Z‡ fdd„Z‡  ZS )ÚFailedConnectionErrorc                s"   t t| ƒj||ƒ || _|| _d S )N)r   rÅ   r   r¨   r   )r   r   r¨   )r   r   r   r   î  s    zFailedConnectionError.__init__)r   r   r   r   r   r   r   )r   r   rÅ   í  s   rÅ   c               @   s   e Zd ZdS )ÚProtocolErrorN)r   r   r   r   r   r   r   rÆ   ô  s   rÆ   c                   s´   e Zd Zd&‡ fdd„	ZG dd„ deƒZdd	„ Zd
d„ Zdd„ ZG dd„ deƒZ	e
d'dd„ƒZdd„ Zdd„ Zd(dd„Zd)dd„Zdd„ Zdd„ Zd d!„ Zd*d"d#„Zd+d$d%„Z‡  ZS ),r‰   é   NFc                sD   t t| ƒj|||ƒ | jƒ | _|| _|| _|p0i | _d | _d | _	d S )N)
r   r‰   r   Ú_iter_framesÚiteratorÚclientr…   ru   Ú_deflate_encÚ_deflate_dec)r   rV   r:   rš   r…   rÊ   ru   )r   r   r   r   ù  s    

zRFC6455WebSocket.__init__c               @   s&   e Zd Zdd„ Zdd„ Zd	dd„ZdS )
zRFC6455WebSocket.UTF8Decoderc             C   s,   t rt jƒ | _nd | _tjdƒ}|ƒ | _d S )NÚutf8)Úutf8validatorZUtf8ValidatorÚ	validatorÚcodecsÚgetincrementaldecoderÚdecoder)r   Zdecoderclassr   r   r   r     s
    
z%RFC6455WebSocket.UTF8Decoder.__init__c             C   s   | j r| j jƒ  | jjƒ  d S )N)rÏ   ÚresetrÒ   )r   r   r   r   rÓ     s    
z"RFC6455WebSocket.UTF8Decoder.resetFc             C   s4   | j r&| j j|ƒ\}}}}|s&tdƒ‚| jj||ƒS )NzData is not valid unicode)rÏ   ÚvalidaterT   rÒ   r°   )r   ÚdataÚfinalZvalidZeocpZc_iZt_ir   r   r   r°     s
    z#RFC6455WebSocket.UTF8Decoder.decodeN)F)r   r   r   r   rÓ   r°   r   r   r   r   ÚUTF8Decoder  s   r×   c                s\   ˆj jdƒ‰ ˆ d krd S ‡ ‡fdd„}ˆ jˆjr4dndƒr@|ƒ S ˆjd krR|ƒ ˆ_ˆjS d S )Nzpermessage-deflatec                  s(   t jt jt jˆ jˆjrdndt jƒ ƒS )Nrp   ro   )rr   ÚcompressobjÚZ_DEFAULT_COMPRESSIONÚDEFLATEDr3   rÊ   rs   r   )Úoptionsr   r   r   Ú_make  s    z;RFC6455WebSocket._get_permessage_deflate_enc.<locals>._makerm   rl   )ru   r3   rÊ   rË   )r   rÜ   r   )rÛ   r   r   Ú_get_permessage_deflate_enc  s    
z,RFC6455WebSocket._get_permessage_deflate_encc                sb   ˆj jdƒ‰ ˆ d ks| rd S ‡ ‡fdd„}ˆ jˆjr:dndƒrF|ƒ S ˆjd krX|ƒ ˆ_ˆjS d S )Nzpermessage-deflatec                  s    t jˆ jˆjrdndt jƒ ƒS )Nro   rp   )rr   Údecompressobjr3   rÊ   rs   r   )rÛ   r   r   r   rÜ   1  s    z;RFC6455WebSocket._get_permessage_deflate_dec.<locals>._makerl   rm   )ru   r3   rÊ   rÌ   )r   Úrsv1rÜ   r   )rÛ   r   r   Ú_get_permessage_deflate_dec,  s    
z,RFC6455WebSocket._get_permessage_deflate_decc             C   s@   d}x6t |ƒ|k r:| jj|t |ƒ ƒ}|s0tƒ ‚|| }qW |S )Nr2   )rc   r	   r¸   rÄ   )r   ÚnumbytesrÕ   Údr   r   r   Ú
_get_bytes?  s    zRFC6455WebSocket._get_bytesc               @   s(   e Zd Zd	dd„Zd
dd„Zdd„ ZdS )zRFC6455WebSocket.MessageNc             C   s"   || _ g | _d| _|| _|| _d S )NF)rÒ   rÕ   ÚfinishedÚopcodeÚdecompressor)r   rå   rÒ   ræ   r   r   r   r   I  s
    z!RFC6455WebSocket.Message.__init__Fc             C   s   || _ | jj|ƒ d S )N)rä   rÕ   re   )r   rÕ   rÖ   r   r   r   ÚpushP  s    zRFC6455WebSocket.Message.pushc             C   sH   dj | jƒ}| jd@  r.| jr.| jj|d ƒ}| jrD| jj|| jƒ}|S )Nr2   r@   s     ÿÿ)rz   rÕ   rå   ræ   Ú
decompressrÒ   r°   rä   )r   rÕ   r   r   r   ÚgetvalueT  s    z!RFC6455WebSocket.Message.getvalue)NN)F)r   r   r   r   rç   ré   r   r   r   r   ÚMessageH  s   

rê   r   c                s4   |d krt ˆ ƒ}t|ƒ}dj‡ ‡‡fdd„|D ƒƒS )Nr2   c             3   s0   | ](}t jt jˆ |ƒˆˆ| d   A ƒV  qdS )é   N)rR   Úint2byter®   )r*   rƒ   )rÕ   ÚmaskÚoffsetr   r   r„   a  s    z/RFC6455WebSocket._apply_mask.<locals>.<genexpr>)rc   Úrangerz   )rÕ   rí   Úlengthrî   Zcntr   )rÕ   rí   rî   r   Ú_apply_mask\  s    zRFC6455WebSocket._apply_maskc             C   sÔ   |dkr¤|sd}nzt |ƒdkrˆtjd|ƒd }| s<|tkrFtddƒ‚y| jƒ j|dd … d	ƒ}W qŒ ttfk
r„   tdd
ƒ‚Y qŒX nd}| j	|dfd� t
ƒ ‚n,|dkr¼| j|dd� n|dkrÆn
tddƒ‚d S )Nr@   iè  r`   z!Hr   iê  zUnexpected close status code.é   Tz)Close message data should be valid UTF-8.r   )Ú
close_dataé	   é
   )Úcontrol_codezUnknown control frame received.)rc   rO   Úunpack_fromÚVALID_CLOSE_STATUSrÅ   r×   r°   ÚUnicodeDecodeErrorrT   r0   rÄ   r·   )r   rå   rÕ   r   r   r   r   Ú_handle_control_framec  s0    z&RFC6455WebSocket._handle_control_framec             c   sÖ   d }ydx^| j |d�}|jd@ r2| j|j|jƒ ƒ q|rF||k	rFtdƒ‚|}|jr|jƒ }d }|V  qW W nh tk
rž   tjƒ \}}}| j	|j
|jfd� Y n4 tk
r°   d S  tk
rÐ   | j	dd� ‚ Y nX d S )N)r¨   r@   zUnexpected message change.)ró   éó  úInternal Server Error)rû   rü   )Ú_recv_framerå   rú   ré   ÚRuntimeErrorrä   rÅ   r”   Úexc_infor0   r   r¨   rÄ   r   )r   Zfragmented_messager¨   rÕ   Zexc_typÚexc_valÚexc_tbr   r   r   rÈ     s.    
zRFC6455WebSocket._iter_framesc             C   s8  | j }|dƒ}tjd|ƒ\}}|d? dk}|d? d@ }|d@ }|rZ|rZd| jkrZtddƒ‚|d	@ }	|	d!krttddƒ‚|d@ dk}
|
 r˜| j r˜tddƒ‚|d@ }|	d@ rÊ|s¶tddƒ‚|dkrÈtddƒ‚n,|	rÞ|rÞtddƒ‚n|	 oè| � rötddƒ‚|dk�rtjd|dƒƒd
 }n|dk�r4tjd|dƒƒd
 }|
�rJtjd|dƒƒ}d
}| �s`|	d@ �r�|	dk�rr| jƒ nd }| j|ƒ}| j|	||d�}|�s¦|j	d|d� nŽxŒ||k �r2| j
j|| ƒ}|�sÎtƒ ‚t|ƒ}|
�rî| j||||d�}|| }y|j	||d� W n$ ttfk
�r,   tdd ƒ‚Y nX �q¨W |S )"Nrò   z!BBé   r`   rë   zpermessage-deflateiê  zhRSV1, RSV2, RSV3: MUST be 0 unless an extension is negotiated that defines meanings for non-zero values.rn   r   r@   rô   rõ   zUnknown opcode received.é€   z9A client MUST mask all frames that it sends to the serveré   z&Control frames must not be fragmented.é}   zBAll control frames MUST have a payload length of 125 bytes or lessz=Received a non-continuation opcode within fragmented message.zAReceived continuation opcode with no previous fragments received.é~   z!Hz!Qz!BBBB)rÒ   ræ   r2   )rÖ   )rð   rî   iï  zText data must be valid utf-8)r   r`   rò   r@   rô   rõ   )rã   rO   Úunpackru   rÅ   rÊ   r×   rà   rê   rç   r	   r¸   rÄ   rc   rñ   rù   rT   )r   r¨   r¸   rf   ÚarS   rä   Zrsv123rß   rå   Úmaskedrð   rí   ZreceivedrÒ   ræ   râ   Údlenr   r   r   rý   ˜  sx    





zRFC6455WebSocket._recv_frameTc                s´  d}t |tjƒr|jdƒ}d}d}| jƒ }|rp|rp|j|ƒ}||jtjƒ7 }|dd … dks`t	‚|d d… }d}t
|ƒ}	|	s€d}|rÈ|dkr”tdƒ‚|sž| r¦tdƒ‚|	dkr¶tdƒ‚tjd|d B ƒ}
n2|rÐdn|rØdnd|B }tjd||� ròd!ndB ƒ}
|�rd"nd}|	dk�r&tjd|dB |	ƒ}n.|	dk�rDtjd|dB |	ƒ}ntjd||	B ƒ}|�ržttjƒ ƒ‰ ‡ fdd„tjjdƒD ƒ}tj|||	ƒ}tjd#|žŽ }nd}dj|
|||fƒS )$NFzutf-8Tr   rë   s     ÿÿr`   é   r@   rô   rõ   zUnknown control opcode.z#Control frame cannot be a fragment.r  z$Control frame data too large (>125).z!Br  rò   iÿÿ  z!BQr  z!BHr  c                s   g | ]}ˆ j d ƒ‘qS )r@   )Úgetrandbits)r*   Ú_)Úrandr   r   r,     s    z2RFC6455WebSocket._pack_message.<locals>.<listcomp>ú!BBBBr2   éüÿÿÿr  é@   )r@   rô   rõ   r  r  r  )r  )r¤   rR   r¥   r¦   rÝ   ÚcompressÚflushrr   ÚZ_SYNC_FLUSHr±   rc   rÆ   rO   rP   r   ÚtimeÚmovesÚxranger‰   rñ   rz   )r   r¨   r	  ZcontinuationrÖ   rö   Zis_textZcompress_bitZ
compressorrð   rf   rå   Z
lengthdatarí   Zmaskdatar   )r  r   rª   á  sL    




zRFC6455WebSocket._pack_messagec             C   s   x| j D ]}|S W d S )N)rÉ   )r   rƒ   r   r   r   r¼     s    zRFC6455WebSocket.waitc          
   C   s,   | j jƒ  z| jj|ƒ W d | j jƒ  X d S )N)r¡   rµ   r	   rU   r¶   )r   Úframer   r   r   Ú_send  s    
zRFC6455WebSocket._sendc             K   s&   | j |d< | j|f|Ž}| j|ƒ d S )Nr	  )rÊ   rª   r  )r   r¨   ÚkwÚpayloadr   r   r   r·     s    
zRFC6455WebSocket.sendc             C   s†   | j dkr‚| j r‚|d k	rJ|\}}t|tjƒr8|jdƒ}tjd|ƒ| }nd}y| j|dd� W n t	k
rz   |sv‚ Y nX d| _d S )	Nr@   rÇ   zutf-8z!Hr   )rö   T)r@   rÇ   )
rš   r›   r¤   rR   r¥   r¦   rO   rP   r·   r½   )r   r¾   ró   r   ÚmsgrÕ   r   r   r   r9   #  s    
z$RFC6455WebSocket._send_closing_framec             C   s~   zly | j |dd� | jjtjƒ W nF tk
rh } z*|jtjkrX| jjdj	| j
|d�ƒ W Y dd}~X nX W d| jjƒ  X dS )zcForcibly close the websocket; generally it is preferable to
        return from the handler method.T)ró   r¾   z {ctx} socket shutdown error: {e})r¿   r<   N)r9   r	   rÀ   ÚSHUT_WRr½   rÁ   rÂ   r–   rÃ   r—   r˜   r0   )r   ró   r<   r   r   r   r0   5  s    .zRFC6455WebSocket.close)rÇ   NFN)Nr   )N)FFTN)FN)N)r   r   r   r   Úobjectr×   rÝ   rà   rã   rê   Ústaticmethodrñ   rú   rÈ   rý   rª   r¼   r  r·   r9   r0   r   r   r   )r   r   r‰   ø  s$   
	
I 
1
r‰   )r   r   )0r†   rÐ   r�   rÁ   Úrandomr   r	   r   r½   r�   rO   r”   r  rr   Úhashlibr   r   ÚImportErrorr   Zeventletr   r   Zeventlet.greenZeventlet.supportr
   rR   Z_modÚ
__import__rÎ   ÚsetÚ
ECONNRESETÚEPIPEr8   Ú__all__rˆ   Úlistrï   rø   r   r   r  r   r   rÄ   rÅ   rT   rÆ   r‰   r   r   r   r   Ú<module>   sT   

(   