o
    a:                     @   s   d 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 ddlm	Z	m
Z
 ddlT ddlmZ dgZG d	d
 d
ZG dd dZG dd dZdS )z

    N   )ABNF)	WebSocketgetdefaulttimeout)*)_loggingWebSocketAppc                   @   s    e Zd ZdZdd Zdd ZdS )
Dispatcherz
    Dispatcher
    c                 C      || _ || _d S Nappping_timeoutselfr   r    r   0/usr/lib/python3/dist-packages/websocket/_app.py__init__)      
zDispatcher.__init__c                 C   s\   | j jr,t }|| j jjtj || j}|r| sd S |  |	  | j jsd S d S r   )
r   keep_running	selectorsDefaultSelectorregistersock
EVENT_READselectr   close)r   r   read_callbackcheck_callbackselrr   r   r   read-   s   zDispatcher.readN)__name__
__module____qualname____doc__r   r!   r   r   r   r   r	   %   s    r	   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	SSLDispatcherz
    SSLDispatcher
    c                 C   r
   r   r   r   r   r   r   r   >   r   zSSLDispatcher.__init__c                 C   s4   | j jr|  }|r| sd S |  | j jsd S d S r   )r   r   r   )r   r   r   r   r    r   r   r   r!   B   s   zSSLDispatcher.readc                 C   s^   | j jj}| r|gS t }||tj || j}|	  t
|dkr-|d d S d S )Nr   )r   r   Zpendingr   r   r   r   r   r   r   len)r   r   r   r    r   r   r   r   J   s   
zSSLDispatcher.selectN)r"   r#   r$   r%   r   r!   r   r   r   r   r   r&   :   s
    r&   c                   @   sx   e Zd ZdZ							dddZejfddZdd	 Zd
d Z									dddZ
dd Zdd Zdd ZdS )r   z_
    Higher level of APIs are provided. The interface is like JavaScript WebSocket object.
    NTc                 C   sv   || _ |dur	|ng | _|| _|| _|| _|| _|| _|| _|| _|| _	|	| _
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.
        NFr   )urlheadercookieon_open
on_messageon_dataon_erroron_closeon_pingon_pongon_cont_messager   get_mask_keyr   last_ping_tmlast_pong_tmsubprotocols)r   r(   r)   r+   r,   r.   r/   r0   r1   r2   r   r3   r*   r6   r-   r   r   r   r   ^   s"   ?
zWebSocketApp.__init__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   sendZ"WebSocketConnectionClosedException)r   dataopcoder   r   r   r7      s
   zWebSocketApp.sendc                 K   s,   d| _ | jr| jjdi | d| _dS dS )z-
        Close websocket connection.
        FNr   )r   r   r   )r   kwargsr   r   r   r      s
   
zWebSocketApp.closec              
   C   st   | |s8t | _| jr1z| j| W n ty0 } ztd| W Y d }~d S d }~ww | |rd S d S )Nz send_ping routine terminated: {})	waittimer4   r   Zping	Exceptionr   Zwarningformat)r   intervaleventZpayloadexr   r   r   
_send_ping   s   

zWebSocketApp._send_pingr    Fc                    s  durdkrt d|dur|dk rt dr$|r$|kr$t d|s(g }|s,i }jr3t ddd_d_d_d fdd		zktj||jdu|
dd
_jt	  jj
jjj||||	j||||d |s{}j |rt  tjj| |fdd_  fdd}fdd}|jj|| W dS  tttfy } zj| t|trʂ   t|t W  Y d}~S d}~ww )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.
        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.

        Returns
        -------
        teardown: bool
            False if caught KeyboardInterrupt, True if 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 openedTc                    sb   r  r     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)	Zis_alivesetjoinr   r   r   _get_close_args	_callbackr/   )close_frameclose_status_codeZclose_reason)r@   r   threadr   r   teardown  s   

z*WebSocketApp.run_forever.<locals>.teardown)sockoptssloptZfire_cont_frameskip_utf8_validationZenable_multithread)r)   r*   http_proxy_hosthttp_proxy_porthttp_no_proxyhttp_proxy_authr6   hostoriginsuppress_origin
proxy_type)targetargsc                     s    j s S  jd\} }| tjkr|S | tjkr&  j|j dS | tj	kr:t

  _  j|j dS | tjkrZ jrZ  j|j|j|j   j|j|j dS |j}| tjkrg|d}  j||jd   j| dS )NTutf-8)r   r   Zrecv_data_framer   ZOPCODE_CLOSEZOPCODE_PINGrG   r0   r8   ZOPCODE_PONGr<   r5   r1   ZOPCODE_CONTr2   r-   r9   ZfinOPCODE_TEXTdecoder,   )Zop_codeframer8   )r   rK   r   r   r!   K  s4   



	

z&WebSocketApp.run_forever.<locals>.readc                     sT    r(t   j  k} jj dk }jj  k}jr(| r(|s$|r(tddS )Nr   zping/pong timed outT)r<   r4   r5   ZWebSocketTimeoutException)Zhas_timeout_expiredZ$has_pong_not_arrived_after_last_pingZhas_pong_arrived_too_late)r   r   r   r   checke  s   z'WebSocketApp.run_forever.<locals>.checkr   )ZWebSocketExceptionr   r   r4   r5   r   r3   r2   Z
settimeoutr   Zconnectr(   r)   r*   r6   create_dispatcherrG   r+   	threadingZEventZThreadrB   Zdaemonstartr!   r=   KeyboardInterrupt
SystemExitr.   
isinstance)r   rL   rM   Zping_intervalr   Zping_payloadrO   rP   rQ   rR   rN   rS   rT   
dispatcherrU   rV   r!   r]   er   )r@   r   r   rK   rJ   r   run_forever   sl   4

zWebSocketApp.run_foreverc                 C   s&   |pd}| j  rt| |S t| |S )N
   )r   Zis_sslr&   r	   )r   r   Ztimeoutr   r   r   r^   z  s   


zWebSocketApp.create_dispatcherc                 C   sb   | j r|s	ddgS |jr-t|jdkr-d|jd  |jd  }|jdd d}||gS ddg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)
        N      r   r   rY   )r/   r8   r'   r[   )r   rH   rI   reasonr   r   r   rF     s   
zWebSocketApp._get_close_argsc              
   G   sx   |r:z|| g|R   W d S  t y9 } z td|| | jr.| | | W Y d }~d S W Y d }~d S d }~ww d S )Nzerror from callback {}: {})r=   r   errorr>   r.   )r   callbackrX   re   r   r   r   rG     s   zWebSocketApp._callback)NNNNNNNNTNNNN)NNr   NrC   NNNNFNNNFN)r"   r#   r$   r%   r   r   rZ   r7   r   rB   rf   r^   rF   rG   r   r   r   r   r   Y   s4    
R	

 ')r%   r   sysr_   r<   	tracebackZ_abnfr   Z_corer   r   _exceptionsrC   r   __all__r	   r&   r   r   r   r   r   <module>   s    