o
    i'                     @   s  d Z ddlZddlZddlZddlmZ ddlZddlmZmZm	Z	 ddl
mZ ddlmZmZ ddlmZ z
ddlmZmZ W n eyQ   dd	lmZmZ Y nw dd
lmZ ddlmZ ddlmZ dd Zdd ZdZG dd dZG dd deeZ G dd de eZ!dS )z/Tornado handlers for WebSocket <-> ZMQ sockets.    N)urlparse)genioloopweb)StreamClosedError)WebSocketHandlerWebSocketClosedError)Session)json_defaultextract_dates)date_defaultr   )cast_unicode)maybe_future   )IPythonHandlerc                 C   s   |   } t| d}tj| tdd}|d| t|}d|d  g}|dd D ]}|	|d t|  q,t
jd	d
|d   |g|R  }|d| d|S )a2  serialize a message as a binary blob

    Header:

    4 bytes: number of msg parts (nbufs) as 32b int
    4 * nbufs bytes: offset for each buffer as integer as 32b int

    Offsets are from the start of the buffer, including the header.

    Returns
    -------

    The message serialized to bytes.

    buffersdefaultutf8r      r   N!I    )copylistpopjsondumpsr
   encodeinsertlenappendstructpackjoin)msgr   bmsgnbufsoffsetsbufoffsets_buf r,   T/var/www/edux/Edux_v2/venv/lib/python3.10/site-packages/notebook/base/zmqhandlers.pyserialize_binary_message   s    
r.   c              	   C   s   t d| dd d }tt dd|  | dd|d   }|d g }t|dd |dd D ]\}}|| ||  q4t|d d	}t|d
 |d
< t|d |d< |dd |d< |S )a'  deserialize a message from a binary blog

    Header:

    4 bytes: number of msg parts (nbufs) as 32b int
    4 * nbufs bytes: offset for each buffer as integer as 32b int

    Offsets are from the start of the buffer, including the header.

    Returns
    -------

    message dictionary
    z!iNr   r   r   r   r   r   r   headerparent_headerr   )	r#   unpackr   r"   zipr   loadsdecoder   )r'   r(   r)   bufsstartstopr&   r,   r,   r-   deserialize_binary_message;   s   (
"r8   i0u  c                       sj   e Zd ZdZdZdZdZdZedd Z	edd Z
ddd	Zd
d Z fddZdd Zdd Z  ZS )WebSocketMixinz"Mixin for common websocket optionsNr   c                 C   s   | j dtS )ziThe interval for websocket keep-alive pings.

        Set ws_ping_interval = 0 to disable pings.
        ws_ping_interval)settingsgetWS_PING_INTERVALselfr,   r,   r-   ping_intervala   s   zWebSocketMixin.ping_intervalc                 C   s   | j dtd| j tS )zIf no ping is received in this many milliseconds,
        close the websocket connection (VPNs, etc. can fail to cleanly close ws connections).
        Default is max of 3 pings or 30 seconds.
        ws_ping_timeout   )r;   r<   maxr@   r=   r>   r,   r,   r-   ping_timeouti   s   zWebSocketMixin.ping_timeoutc                 C   s   | j dkst| dr|  rdS | jjd}|du r|  }|du s'|du r)dS | }t|j	}||kr8dS | j rA| j |k}n| j
rMt| j
|}nd}|sY| jd|| |S )zCheck Origin == Host or Access-Control-Allow-Origin.

        Tornado >= 4 calls this method automatically, raising 403 if it returns False.
        *skip_check_originTHostNFz>Blocking Cross Origin WebSocket Attempt.  Origin: %s, Host: %s)allow_originhasattrrF   requestheadersr<   
get_originlowerr   netlocallow_origin_patboolmatchlogwarning)r?   originhostorigin_hostallowr,   r,   r-   check_origins   s2   

zWebSocketMixin.check_originc                 O      dS )zmeaningless for websocketsNr,   r?   argskwargsr,   r,   r-   clear_cookie   s   zWebSocketMixin.clear_cookiec                    sf   | j d| jj | jdkr*tj }| | _	| j	| _
t| j| j| _| j  t j|i |S )NzOpening websocket %sr   )rR   debugrJ   pathr@   r   IOLoopcurrenttime	last_ping	last_pongPeriodicCallback	send_pingping_callbackr6   superopen)r?   r[   r\   loop	__class__r,   r-   ri      s   



zWebSocketMixin.openc              	   C   s   | j du r| jdur| j  dS tj  }d|| j  }d|| j  }|d| j	 k r?|| j
kr?| jd| |   dS z| d W n ttfyW   | j  Y dS w || _dS )z'send a ping to keep the websocket aliveNg     @@   z#WebSocket ping timeout after %i ms.r   )ws_connectionrg   r7   r   r`   ra   rb   rd   rc   r@   rD   rR   rS   closepingr   r   )r?   nowsince_last_pongsince_last_pingr,   r,   r-   rf      s"   


zWebSocketMixin.send_pingc                 C   s   t j  | _d S N)r   r`   ra   rb   rd   )r?   datar,   r,   r-   on_pong   s   zWebSocketMixin.on_pongrt   )__name__
__module____qualname____doc__rg   rc   rd   streampropertyr@   rD   rX   r]   ri   rf   rv   __classcell__r,   r,   rk   r-   r9   Z   s    


	'r9   c                       s:   e Zd Zejdk r	  fddZd	ddZdd Z  ZS )
ZMQStreamHandler)r   r   c                    s2   | j d u rtt| j|i | d S | j   d S rt   )r{   rh   r   
send_errorro   rZ   rk   r,   r-   r      s   
zZMQStreamHandler.send_errorNc                 C   sb   t |tr|}n| j|\}}| j|}|r||d< |d r&t|}|S tj|td}t	|S )a  Reserialize a reply message using JSON.

        msg_or_list can be an already-deserialized msg dict or the zmq buffer list.
        If it is the zmq list, it will be deserialized with self.session.

        This takes the msg list from the ZMQ socket and serializes the result for the websocket.
        This method should be used by self._on_zmq_reply to build messages that can
        be sent back to the browser.

        channelr   r   )

isinstancedictsessionfeed_identitiesdeserializer.   r   r   r
   r   )r?   msg_or_listr   r&   identsmsg_listr*   smsgr,   r,   r-   _reserialize_reply   s   
z#ZMQStreamHandler._reserialize_replyc              	   C   s   | j d u s	| r| jd |   d S t|dd }z	| j||d}W n ty9   | jjd|dd Y d S w z| j	|t
|td W d S  ttfy]   | jd |   Y d S w )Nz%zmq message arrived on closed channelr   )r   zMalformed message: T)exc_info)binary)rn   closedrR   rS   ro   getattrr   	Exceptioncriticalwrite_messager   bytesr   r   )r?   r{   r   r   r&   r,   r,   r-   _on_zmq_reply   s$   zZMQStreamHandler._on_zmq_replyrt   )	rw   rx   ry   tornadoversion_infor   r   r   r}   r,   r,   rk   r-   r~      s    

r~   c                       sB   e Zd Zdd Zdd Zej fddZdd Zd	d
 Z	  Z
S )AuthenticatedZMQStreamHandlerc                 C   rY   )zhUndo the set_default_headers in IPythonHandler

        which doesn't make sense for websockets
        Nr,   r>   r,   r,   r-   set_default_headers	  s   z1AuthenticatedZMQStreamHandler.set_default_headersc                 C   sT   |   du r| jd td| ddr"t| d| j_dS | jd dS )zRun before finishing the GET request

        Extend this method to add logic that should fire before
        the websocket finishes completing.
        Nz*Couldn't authenticate WebSocket connectioni  
session_idFzNo session ID specified)get_current_userrR   rS   r   	HTTPErrorget_argumentr   r   r>   r,   r,   r-   pre_get  s   
z%AuthenticatedZMQStreamHandler.pre_getc                 /   s4    |   }t|V  t j|i |}t|V  d S rt   )r   r   rh   r<   )r?   r[   r\   resrk   r,   r-   r<      s
   
z!AuthenticatedZMQStreamHandler.getc                 C   s$   | j d| jj t| jd| _d S )Nz$Initializing websocket connection %s)config)rR   r^   rJ   r_   r	   r   r   r>   r,   r,   r-   
initialize)  s   z(AuthenticatedZMQStreamHandler.initializec                 C   s   | j dd S )Nwebsocket_compression_options)r;   r<   r>   r,   r,   r-   get_compression_options-  s   z5AuthenticatedZMQStreamHandler.get_compression_options)rw   rx   ry   r   r   r   	coroutiner<   r   r   r}   r,   r,   rk   r-   r     s    r   )"rz   r   r#   sysurllib.parser   r   r   r   r   tornado.iostreamr   tornado.websocketr   r   jupyter_client.sessionr	   jupyter_client.jsonutilr
   r   ImportErrorr   ipython_genutils.py3compatr   notebook.utilsr   handlersr   r.   r8   r=   r9   r~   r   r,   r,   r,   r-   <module>   s0    n?