B
    &dN                 @   s   d dl Z d dlZ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dlmZ ddlmZ ddlmZmZ ddlT d	gZd aedd
ddZG dd dZG dd deZG dd deZG dd dZG dd	 d	ZdS )    N)CallableAny   )_logging)ABNF)	parse_url)	WebSocketgetdefaulttimeout)*WebSocketApp)reconnectIntervalreturnc             C   s   | a d S )N)	RECONNECT)r    r   [/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/websocket/_app.pysetReconnect)   s    r   c               @   sJ   e Zd ZdZeepeddddZeeddddZ	eedd	d
dZ
dS )DispatcherBasez
    DispatcherBase
    N)appping_timeoutr   c             C   s   || _ || _d S )N)r   r   )selfr   r   r   r   r   __init__2   s    zDispatcherBase.__init__)secondscallbackr   c             C   s   t | |  d S )N)timesleep)r   r   r   r   r   r   timeout6   s    
zDispatcherBase.timeout)r   reconnectorr   c          
   C   sn   y4t dj|tt d t| |dd W n4 tk
rh } zt dj|d W d d }~X Y nX d S )NzQreconnect() - retrying in {seconds_count} seconds [{frame_count} frames in stack])Zseconds_countframe_countT)reconnectingzUser exited {err})err)	r   infoformatleninspectstackr   r   KeyboardInterrupt)r   r   r   er   r   r   	reconnect:   s    
zDispatcherBase.reconnect)__name__
__module____qualname____doc__r   intfloatr   r   r   r'   r   r   r   r   r   .   s   r   c               @   s$   e Zd ZdZeeeddddZdS )
Dispatcherz
    Dispatcher
    N)sockread_callbackcheck_callbackr   c             C   sT   xN| j jrNt }|| j jjtj || j}|r>| s>P |  |	  qW d S )N)
r   keep_running	selectorsDefaultSelectorregisterr/   
EVENT_READselectr   close)r   r/   r0   r1   selrr   r   r   readH   s    
zDispatcher.read)r(   r)   r*   r+   socketr   r;   r   r   r   r   r.   D   s   r.   c               @   s2   e Zd ZdZeeeddddZedddZdS )	SSLDispatcherz
    SSLDispatcher
    N)r/   r0   r1   r   c             C   s,   x&| j jr&|  }|r| sP |  qW d S )N)r   r2   r7   )r   r/   r0   r1   r:   r   r   r   r;   Y   s    
zSSLDispatcher.read)r   c             C   s^   | j jj}| r|gS t }||tj || j}|	  t
|dkrZ|d d S d S )Nr   )r   r/   pendingr3   r4   r5   r6   r7   r   r8   r"   )r   r/   r9   r:   r   r   r   r7   a   s    
zSSLDispatcher.select)	r(   r)   r*   r+   r<   r   r;   listr7   r   r   r   r   r=   U   s   r=   c               @   s^   e Zd ZdZepeeddddZee	e	ddddZ
ee	dd	d
dZee	ddddZdS )WrappedDispatcherz
    WrappedDispatcher
    N)r   
dispatcherr   c             C   s$   || _ || _|| _|d|j d S )N   )r   r   rA   signalabort)r   r   r   rA   r   r   r   r   t   s    zWrappedDispatcher.__init__)r/   r0   r1   r   c             C   s&   | j || | jo | | j| d S )N)rA   r;   r   r   )r   r/   r0   r1   r   r   r   r;   z   s    zWrappedDispatcher.read)r   r   r   c             C   s   | j || d S )N)rA   r   )r   r   r   r   r   r   r   ~   s    zWrappedDispatcher.timeout)r   r   r   c             C   s   |  || d S )N)r   )r   r   r   r   r   r   r'      s    zWrappedDispatcher.reconnect)r(   r)   r*   r+   r,   r-   r.   r   r<   r   r;   r   r'   r   r   r   r   r@   p   s
   r@   c               @   s  e Zd ZdZd"eepeeeeeeeeeeeeee	ddddZ
ejfeedddd	Zdd
ddZdd
ddZdd
ddZdd
ddZd#eeepeepeeeepeeeepeeeeeeeeedddZd$eeeedddZeedddZeeddd d!ZdS )%r   z_
    Higher level of APIs are provided. The interface is like JavaScript WebSocket object.
    NT)urlheaderon_open
on_messageon_erroron_closeon_pingon_pongon_cont_messager2   get_mask_keycookiesubprotocolson_datar<   r   c             C   s   || _ |dk	r|ng | _|| _|| _|| _|| _|| _|| _|| _|| _	|	| _
d| _|| _d| _d| _d| _d| _d| _d| _d| _d| _|| _|| _d| _dS )a	  
        WebSocketApp initialization

        Parameters
        ----------
        url: str
            Websocket url.
        header: list or dict
            Custom header for websocket handshake.
        on_open: function
            Callback object which is called at opening websocket.
            on_open has one argument.
            The 1st argument is this class object.
        on_message: function
            Callback object which is called when received data.
            on_message has 2 arguments.
            The 1st argument is this class object.
            The 2nd argument is utf-8 data received from the server.
        on_error: function
            Callback object which is called when we get error.
            on_error has 2 arguments.
            The 1st argument is this class object.
            The 2nd argument is exception object.
        on_close: function
            Callback object which is called when connection is closed.
            on_close has 3 arguments.
            The 1st argument is this class object.
            The 2nd argument is close_status_code.
            The 3rd argument is close_msg.
        on_cont_message: function
            Callback object which is called when a continuation
            frame is received.
            on_cont_message has 3 arguments.
            The 1st argument is this class object.
            The 2nd argument is utf-8 string which we get from the server.
            The 3rd argument is continue flag. if 0, the data continue
            to next frame data
        on_data: function
            Callback object which is called when a message received.
            This is called before on_message or on_cont_message,
            and then on_message or on_cont_message is called.
            on_data has 4 argument.
            The 1st argument is this class object.
            The 2nd argument is utf-8 string which we get from the server.
            The 3rd argument is data type. ABNF.OPCODE_TEXT or ABNF.OPCODE_BINARY will be came.
            The 4th argument is continue flag. If 0, the data continue
        keep_running: bool
            This parameter is obsolete and ignored.
        get_mask_key: function
            A callable function to get new mask keys, see the
            WebSocket.set_mask_key's docstring for more information.
        cookie: str
            Cookie value.
        subprotocols: list
            List of available sub protocols. Default is None.
        socket: socket
            Pre-initialized stream socket.
        NFr    )rE   rF   rO   rG   rH   rQ   rI   rJ   rK   rL   rM   r2   rN   r/   last_ping_tmlast_pong_tmping_thread	stop_pingping_intervalr   ping_payloadrP   prepared_sockethas_errored)r   rE   rF   rG   rH   rI   rJ   rK   rL   rM   r2   rN   rO   rP   rQ   r<   r   r   r   r      s0    BzWebSocketApp.__init__)dataopcoder   c             C   s$   | j r| j ||dkr tddS )a  
        send message

        Parameters
        ----------
        data: str
            Message to send. If you set opcode to OPCODE_TEXT,
            data must be utf-8 string or unicode.
        opcode: int
            Operation code of data. Default is OPCODE_TEXT.
        r   zConnection is already closed.N)r/   send"WebSocketConnectionClosedException)r   r[   r\   r   r   r   r]      s    zWebSocketApp.send)r   c             K   s$   d| _ | jr | jjf | d| _dS )z-
        Close websocket connection.
        FN)r2   r/   r8   )r   kwargsr   r   r   r8      s    zWebSocketApp.closec             C   s<   d | _ | _t | _tj| jd| _d| j_| j	  d S )Nr   )targetT)
rS   rT   	threadingEventrV   Thread
_send_pingrU   daemonstart)r   r   r   r   _start_ping_thread   s
    
zWebSocketApp._start_ping_threadc             C   s<   | j r| j   | jr,| j r,| jd d | _| _d S )N   r   )rV   setrU   is_alivejoinrS   rT   )r   r   r   r   _stop_ping_thread  s
    
zWebSocketApp._stop_ping_threadc          
   C   s   | j | jrd S xt| j | js| jrt | _ytd | j| j	 W q t
k
r } ztdj|d W d d }~X Y qX qW d S )NzSending pingzFailed to send ping: {err})r   )rV   waitrW   r/   r   rS   r   debugZpingrX   	Exceptionr!   )r   r&   r   r   r   rd     s    

zWebSocketApp._send_pingr   rR   F)sockoptssloptrW   r   rX   http_proxy_hosthttp_proxy_porthttp_no_proxyhttp_proxy_authhttp_proxy_timeoutskip_utf8_validationhostoriginrA   suppress_origin
proxy_typer'   r   c                s  dkrt |dk	r$|dkr$td|dk	r<|dk r<td|rT|rT||krTtds\g sdi jrrtd|_|_|_d_dtddfd	d
dtdd 	
fddtdfddtdfdd dt	ttdfddt
|tjd   srx4jrtdjtt d  qXW jS )a  
        Run event loop for WebSocket framework.

        This loop is an infinite loop and is alive while websocket is available.

        Parameters
        ----------
        sockopt: tuple
            Values for socket.setsockopt.
            sockopt must be tuple
            and each element is argument of sock.setsockopt.
        sslopt: dict
            Optional dict object for ssl socket option.
        ping_interval: int or float
            Automatically send "ping" command
            every specified period (in seconds).
            If set to 0, no ping is sent periodically.
        ping_timeout: int or float
            Timeout (in seconds) if the pong message is not received.
        ping_payload: str
            Payload message to send with each ping.
        http_proxy_host: str
            HTTP proxy host name.
        http_proxy_port: int or str
            HTTP proxy port. If not set, set to 80.
        http_no_proxy: list
            Whitelisted host names that don't use the proxy.
        http_proxy_timeout: int or float
            HTTP proxy timeout, default is 60 sec as per python-socks.
        http_proxy_auth: tuple
            HTTP proxy auth information. tuple of username and password. Default is None.
        skip_utf8_validation: bool
            skip utf8 validation.
        host: str
            update host header.
        origin: str
            update origin header.
        dispatcher: Dispatcher object
            customize reading data from socket.
        suppress_origin: bool
            suppress outputting origin header.
        proxy_type: str
            type of proxy from: http, socks4, socks4a, socks5, socks5h
        reconnect: int
            delay interval when reconnecting

        Returns
        -------
        teardown: bool
            False if the `WebSocketApp` is closed or caught KeyboardInterrupt,
            True if any other exception was raised during a loop.
        Nr   zEnsure ping_timeout > 0zEnsure ping_interval >= 0z#Ensure ping_interval > ping_timeoutzsocket is already openedT)close_framer   c                sN       d _ jr j   | r*| nd\}}d _  j|| dS )a  
            Tears down the connection.

            Parameters
            ----------
            close_frame: ABNF frame
                If close_frame is set, the on_close handler is invoked
                with the statusCode and reason from the provided frame.
            FN)rl   r2   r/   r8   _get_close_args	_callbackrJ   )r|   close_status_codeZclose_reason)r   r   r   teardownm  s    
z*WebSocketApp.run_forever.<locals>.teardownF)r   r   c                s   | rj rj   tjjd k	dd_ j t  ylj jjj	j
j	
jd td jr  j j j   W n6 tttttfk
r } z||  W d d }~X Y nX d S )NT)rp   rq   Zfire_cont_framerw   Zenable_multithread)rF   rO   rr   rs   rt   ru   rv   rP   rx   ry   rz   r{   r<   zWebsocket connected)r/   shutdownr   rN   rM   
settimeoutr	   connectrE   rF   rO   rP   rY   r   r    rW   rg   r~   rG   r;   r^   ConnectionRefusedErrorr%   
SystemExitro   )r   r&   )checkrA   handleDisconnectrx   rt   ru   rr   rs   rv   ry   r{   r;   r   rw   rp   rq   rz   r   r   setSock  s0    



z)WebSocketApp.run_forever.<locals>.setSock)r   c           
      s2  j s S yjd\} }W n6 ttfk
rV } z rB|S |W d d }~X Y nX | tjkrj|S | tjkrj	|j
 n| tjkrt _j|j
 n| tjkrjrj|j
|j|j j|j
|j nD|j
}| tjkrs|d}j||jd j| dS )NTzutf-8)r2   r/   Zrecv_data_framer^   r%   r   ZOPCODE_CLOSEZOPCODE_PINGr~   rK   r[   ZOPCODE_PONGr   rT   rL   ZOPCODE_CONTrM   rQ   r\   ZfinOPCODE_TEXTdecoderH   )Zop_codeframer&   r[   )custom_dispatcherr   r   rw   r   r   r   r;     s4    




z&WebSocketApp.run_forever.<locals>.readc                 sZ    j rVt  j  j k}  j j dk } j j  j k} jrV| rV|sN|rVtddS )Nr   zping/pong timed outT)r   r   rS   rT   ZWebSocketTimeoutException)Zhas_timeout_expiredZ$has_pong_not_arrived_after_last_pingZhas_pong_arrived_too_late)r   r   r   r     s    z'WebSocketApp.run_forever.<locals>.check)r&   r   r   c                s   d_   |s j|  t| ttfr6   rxtdj	| d  rt
dj	tt d  ntdj	| d   d S )NTz{err} - reconnect)r   zCCalling custom dispatcher reconnect [{frame_count} frames in stack])r   z{err} - goodbye)rZ   rl   r~   rI   
isinstancer%   r   r   r    r!   rn   r"   r#   r$   r'   error)r&   r   )r   rA   r'   r   r   r   r   r   r     s    z2WebSocketApp.run_forever.<locals>.handleDisconnectrh   z<Calling dispatcher reconnect [{frame_count} frames in stack])r   )N)F)F)r   ZWebSocketExceptionr/   rW   r   rX   r2   r   boolro   create_dispatcherr   rE   r   rn   r!   r"   r#   r$   r'   rZ   )r   rp   rq   rW   r   rX   rr   rs   rt   ru   rv   rw   rx   ry   rA   rz   r{   r'   r   )r   r   rA   r   rx   rt   ru   rr   rs   rv   ry   r{   r;   r'   r   r   rw   rp   rq   rz   r   r   run_forever  s>    >6 !"
zWebSocketApp.run_forever)r   rA   is_sslr   c             C   s0   |rt | ||S |pd}|r&t| |S t| |S )N
   )r@   r=   r.   )r   r   rA   r   r   r   r   r   r     s    
zWebSocketApp.create_dispatcher)r|   r   c             C   sf   | j r
|sddgS |jrZt|jdkrZd|jd  |jd  }|jdd d}||gS ddgS dS )z
        _get_close_args extracts the close code and reason from the close body
        if it exists (RFC6455 says WebSocket Connection Close Code is optional)
        NrB      r   r   zutf-8)rJ   r[   r"   r   )r   r|   r   reasonr   r   r   r}     s    
zWebSocketApp._get_close_args)r   argsr   c          
   G   sd   |r`y|| f|  W nH t k
r^ } z*tdj||d | jrN| | | W d d }~X Y nX d S )Nz%error from callback {callback}: {err})r   r   )ro   r   r   r!   rI   )r   r   r   r&   r   r   r   r~     s    zWebSocketApp._callback)NNNNNNNNTNNNNN)NNr   NrR   NNNNNFNNNFNN)NF)r(   r)   r*   r+   strr?   dictr   r   r<   r   r   r   r,   r]   r8   rg   rl   rd   tupler-   r.   r   r   r   r}   r~   r   r   r   r   r      s6          2U	        B N	)r#   r3   sysra   r   	tracebackr<   typingr   r   rR   r   Z_abnfr   _urlr   Z_corer   r	   _exceptions__all__r   r,   r   r   r.   r=   r@   r   r   r   r   r   <module>   s(   