B
    9d(                 @   sF  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
mZ d dlmZ d dlmZmZ d dlmZmZ d d	lmZ d d
lmZmZmZ d dlmZ d dlmZ d dlmZ ddl m!Z! e"e #ddZ$G dd deeZ%G dd deZ&G dd deZ'ddl(m)Z) ddl*m+Z+ de) de%fde+ de'fgZ,dS )    N   )
APIHandlerIPythonHandler)url_path_join)genweb)Future)IOLoopPeriodicCallback)WebSocketHandlerwebsocket_connect)HTTPRequest)
url_escapejson_decodeutf8)cast_unicode)Session)LoggingConfigurable   )GatewayClientGATEWAY_WS_PING_INTERVAL_SECS   c                   s   e Zd ZdZdZdZdZdddZdd Zdd Z	dd	 Z
d
d Zej fddZdd Zdd Zdd Zd fdd	Z fddZedd Z  ZS )WebSocketChannelsHandlerNc             C   s   t | |S )N)r   check_origin)selforigin r   f/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/notebook/gateway/handlers.pyr   $   s    z%WebSocketChannelsHandler.check_originc             C   s   dS )zVUndo the set_default_headers in IPythonHandler which doesn't make sense for websocketsNr   )r   r   r   r   set_default_headers'   s    z,WebSocketChannelsHandler.set_default_headersc             C   s   i S )Nr   )r   r   r   r   get_compression_options+   s    z0WebSocketChannelsHandler.get_compression_optionsc             C   sR   |   dkr"| jd td| ddrBt| d| j_n| 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  Z
session_idFzNo session ID specified)Zget_current_userlogwarningr   	HTTPErrorZget_argumentr   session)r   r   r   r   authenticate/   s    
z%WebSocketChannelsHandler.authenticatec             C   s6   | j d| jj t| jd| _tt	 j
d| _d S )Nz$Initializing websocket connection %s)config)Zgateway_url)r    debugrequestpathr   r%   r#   GatewayWebSocketClientr   instanceurlgateway)r   r   r   r   
initialize?   s    z#WebSocketChannelsHandler.initializec             /   s0   |    t|d| _t j|d|i|V  d S )Nascii	kernel_id)r$   r   r/   superget)r   r/   argskwargs)	__class__r   r   r1   D   s    zWebSocketChannelsHandler.getc             C   s0   | j d kr"| jd k	r"| j  d S | d d S )N    )ws_connectionping_callbackstopZping)r   r   r   r   	send_pingJ   s    
z"WebSocketChannelsHandler.send_pingc             O   s8   t | jtd | _| j  | jj|| j|  d dS )z`Handle web socket connection open to notebook server and delegate to gateway web socket handler i  )r/   message_callbackZcompression_optionsN)	r
   r9   r   r7   startr,   on_openwrite_messager   )r   r/   r2   r3   r   r   r   openQ   s    
zWebSocketChannelsHandler.openc             C   s   | j | dS )z.Forward message to gateway web socket handler.N)r,   
on_message)r   messager   r   r   r?   \   s    z#WebSocketChannelsHandler.on_messageFc                s\   | j r&t|trd}t j||d n2| jtjrXt	
tt|}| jd|  dS )zdSend message back to notebook client.  This is called via callback from self.gateway._read_messages.T)binaryz?Notebook client closed websocket connection - message dropped: N)r6   
isinstancebytesr0   r=   r    isEnabledForloggingDEBUGr   _get_message_summaryr   r   r&   )r   r@   rA   Zmsg_summary)r4   r   r   r=   `   s    
z&WebSocketChannelsHandler.write_messagec                s*   | j d| jj | j  t   d S )NzClosing websocket connection %s)r    r&   r'   r(   r,   on_closer0   )r   )r4   r   r   rH   j   s    
z!WebSocketChannelsHandler.on_closec          	   C   s   g }| d }| d|  |dkr>| d| d d   nH|dkr|| d| d d	  d
| d d  d
| d d   n
| d d|S )NZmsg_typeztype: statusz	, state: contentZexecution_stateerrorz, Zename:Zevalue	tracebackz, ... )appendjoin)r@   summaryZmessage_typer   r   r   rG   o   s    2
z-WebSocketChannelsHandler._get_message_summary)N)F)__name__
__module____qualname__r#   r,   r/   r7   r   r   r   r$   r-   r   	coroutiner1   r9   r>   r?   r=   rH   staticmethodrG   __classcell__r   r   )r4   r   r      s    

r   c                   sl   e Zd ZdZ fddZejdd Zdd Zdd	 Z	ejd
d Z
dd Zdd Zdd Zdd Z  ZS )r)   z;Proxy web socket connection to a kernel/enterprise gateway.c                s2   t  jf | d | _d | _t | _d| _d| _d S )NFr   )r0   __init__r/   wsr   	ws_futuredisconnectedretry)r   r3   )r4   r   r   rX      s    zGatewayWebSocketClient.__init__c             C   sx   d | _ || _tt jt jt|d}| j	d|  i }t j
f |}t|f|}t|| _| j| j d S )NZchannelszConnecting to )rY   r/   r   r   r*   ws_urlZkernels_endpointr   r    infoZload_connection_argsr   r   rZ   add_done_callback_connection_done)r   r/   r]   r3   r'   r   r   r   _connect   s    
zGatewayWebSocketClient._connectc             C   sX   | j s8| d kr8| | _d| _| jd| j  n| jd| j	t
 j d S )Nr   zConnection is ready: ws: zWebsocket connection has been closed via client disconnect or due to error.  Kernel with ID '{}' may not be terminated on GatewayClient: {})r[   	exceptionresultrY   r\   r    r&   r!   formatr/   r   r*   r+   )r   futr   r   r   r`      s    

z'GatewayWebSocketClient._connection_donec             C   sH   d| _ | jd k	r| j  n(| j sD| j  | jd| j   d S )NTz-_disconnect: future cancelled, disconnected: )r[   rY   closerZ   donecancelr    r&   )r   r   r   r   _disconnect   s    


z"GatewayWebSocketClient._disconnectc          
   #   sF  xj dk	rd}jsyj  V }W n4 tk
rZ } zjd|  W dd}~X Y nX |dkrjs~jdj  P  | qP qW jsBjt	
 jk rBtddd }tt	
 jdj  t	
 j| } jd7  _jd	|jt	
 jj t|V  j t }|j fd
d dS )z"Read messages from gateway server.Nz*Exception reading message from websocket: zLost connection to Gateway: 
   d   g{Gz?r   r   zKAttempting to re-establish the connection to Gateway in %s secs (%s/%s): %sc                s
     S )N)_read_messages)future)callbackr   r   r   <lambda>   r5   z7GatewayWebSocketClient._read_messages.<locals>.<lambda>)rY   r[   Zread_message	Exceptionr    rK   r!   r/   r\   r   r*   Zgateway_retry_maxrandomrandintminZgateway_retry_intervalZgateway_retry_interval_maxr^   r   sleepra   r	   current
add_futurerZ   )r   rn   r@   ejitterZretry_intervalloopr   )rn   r   r   rl      s0    $
z%GatewayWebSocketClient._read_messagesc                s.    | t }|j fdd dS )z2Web socket connection open against gateway server.c                s
     S )N)rl   )rm   )r:   r   r   r   ro      r5   z0GatewayWebSocketClient.on_open.<locals>.<lambda>N)ra   r	   ru   rv   rZ   )r   r/   r:   r3   ry   r   )r:   r   r   r<      s
    
zGatewayWebSocketClient.on_openc                s:   j dkr,t }|j fdd n
  dS )zSend message to gateway server.Nc                s
     S )N)_write_message)rm   )r@   r   r   r   ro      r5   z3GatewayWebSocketClient.on_message.<locals>.<lambda>)rY   r	   ru   rv   rZ   rz   )r   r@   ry   r   )r@   r   r   r?      s    
z!GatewayWebSocketClient.on_messagec          
   C   sZ   y | j s| jdk	r| j| W n4 tk
rT } z| jd|  W dd}~X Y nX dS )zSend message to gateway server.Nz(Exception writing message to websocket: )r[   rY   r=   rp   r    rK   )r   r@   rw   r   r   r   rz      s
    z%GatewayWebSocketClient._write_messagec             C   s   |    dS )zWeb socket closed event.N)ri   )r   r   r   r   rH      s    zGatewayWebSocketClient.on_close)rR   rS   rT   __doc__rX   r   rU   ra   r`   ri   rl   r<   r?   rz   rH   rW   r   r   )r4   r   r)      s   

	r)   c               @   s&   e Zd ZdZejejdddZdS )GatewayResourceHandlerzWRetrieves resources for specific kernelspec definitions from kernel/enterprise gateway.Tc             c   s\   | j }|||V }|d kr8| jd| d| d n| dt|d  | | d S )NzKernelspec resource 'z' for 'z7' not found.  Gateway may not support resource serving.zContent-Typer   )Zkernel_spec_managerZget_kernel_spec_resourcer    r!   Z
set_header	mimetypes
guess_typefinish)r   Zkernel_namer(   Zinclude_bodyZksmZkernel_spec_resr   r   r   r1      s    zGatewayResourceHandler.getN)T)	rR   rS   rT   r{   r   authenticatedr   rU   r1   r   r   r   r   r|      s   r|   )_kernel_id_regex)kernel_name_regexz/api/kernels/z	/channelsz/kernelspecs/z/(?P<path>.*))-osrE   r}   rq   Zbase.handlersr   r   utilsr   tornador   r   Ztornado.concurrentr   Ztornado.ioloopr	   r
   Ztornado.websocketr   r   Ztornado.httpclientr   Ztornado.escaper   r   r   Zipython_genutils.py3compatr   Zjupyter_client.sessionr   Ztraitlets.config.configurabler   Zmanagersr   intgetenvr   r   r)   r|   Zservices.kernels.handlersr   Zservices.kernelspecs.handlersr   Zdefault_handlersr   r   r   r   <module>   s.   fp