ó
ù2¢\c           @   sr  d  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 Wn! e k
 ry d d l m Z n Xd 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 d d l m Z m Z d d	 l m Z d
 d l m Z d „  Z d „  Z d Z d e f d „  ƒ  YZ d e e f d „  ƒ  YZ  d e  e f d „  ƒ  YZ! d S(   s/   Tornado handlers for WebSocket <-> ZMQ sockets.iÿÿÿÿN(   t   urlparse(   t   gent   ioloopt   web(   t   StreamClosedError(   t   WebSocketHandlert   WebSocketClosedError(   t   Session(   t   date_defaultt   extract_dates(   t   cast_unicodei   (   t   IPythonHandlerc         C   s  |  j  ƒ  }  t |  j d ƒ ƒ } t j d k  rR g  | D] } | j ƒ  ^ q7 } n  t j |  d t ƒj	 d ƒ } | j
 d | ƒ t | ƒ } d | d g } x- | d  D]! } | j | d t | ƒ ƒ q¨ Wt j d	 d
 | d | | Œ } | j
 d | ƒ d j | ƒ S(   s2  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.

    t   buffersi   i   t   defaultt   utf8i    i   iÿÿÿÿt   !t   It    (   i   i   (   t   copyt   listt   popt   syst   version_infot   tobytest   jsont   dumpsR   t   encodet   insertt   lent   appendt   structt   packt   join(   t   msgR   t   xt   bmsgt   nbufst   offsetst   buft   offsets_buf(    (    s8   lib/python2.7/site-packages/notebook/base/zmqhandlers.pyt   serialize_binary_message   s    "!c         C   sî   t  j d |  d  ƒ d } t t  j d d | |  d d | d !ƒ ƒ } | j d ƒ g  } x9 t | d  | d ƒ D]  \ } } | j |  | | !ƒ qt Wt j | d j d ƒ ƒ } t	 | d	 ƒ | d	 <t	 | d
 ƒ | d
 <| d | d <| S(   s'  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
    s   !ii   i    R   R   i   iÿÿÿÿR   t   headert   parent_headerR   N(
   R   t   unpackR   R   t   Nonet   zipR   t   loadst   decodeR	   (   R#   R$   R%   t   bufst   startt   stopR!   (    (    s8   lib/python2.7/site-packages/notebook/base/zmqhandlers.pyt   deserialize_binary_message=   s    /$i0u  t   WebSocketMixinc           B   st   e  Z d  Z d	 Z d Z d Z d	 Z e d „  ƒ Z	 e d „  ƒ Z
 d	 d „ Z d „  Z d „  Z d „  Z d „  Z RS(
   s"   Mixin for common websocket optionsi    c         C   s   |  j  j d t ƒ S(   sq   The interval for websocket keep-alive pings.
        
        Set ws_ping_interval = 0 to disable pings.
        t   ws_ping_interval(   t   settingst   gett   WS_PING_INTERVAL(   t   self(    (    s8   lib/python2.7/site-packages/notebook/base/zmqhandlers.pyt   ping_intervalc   s    c         C   s#   |  j  j d t d |  j t ƒ ƒ S(   sÉ   If 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.
        t   ws_ping_timeouti   (   R6   R7   t   maxR:   R8   (   R9   (    (    s8   lib/python2.7/site-packages/notebook/base/zmqhandlers.pyt   ping_timeoutk   s    c         C   s  |  j  d k s* t |  d ƒ r. |  j ƒ  r. t S|  j j j d ƒ } | d k r^ |  j ƒ  } n  | d k sv | d k rz t S| j	 ƒ  } t
 | ƒ j } | | k r¥ t S|  j  rÀ |  j  | k } n* |  j rä t |  j j | ƒ ƒ } n t } | s	|  j j d | | ƒ n  | S(   s   Check Origin == Host or Access-Control-Allow-Origin.
        
        Tornado >= 4 calls this method automatically, raising 403 if it returns False.
        t   *t   skip_check_origint   Hosts>   Blocking Cross Origin WebSocket Attempt.  Origin: %s, Host: %sN(   t   allow_origint   hasattrR?   t   Truet   requestt   headersR7   R,   t
   get_origint   lowerR    t   netloct   allow_origin_patt   boolt   matcht   Falset   logt   warning(   R9   t   origint   hostt   origin_hostt   allow(    (    s8   lib/python2.7/site-packages/notebook/base/zmqhandlers.pyt   check_originu   s*    		c         O   s   d S(   s   meaningless for websocketsN(    (   R9   t   argst   kwargs(    (    s8   lib/python2.7/site-packages/notebook/base/zmqhandlers.pyt   clear_cookieœ   s    c         O   s–   |  j  j d |  j j ƒ |  j d k r} t j j ƒ  } | j ƒ  |  _	 |  j	 |  _
 t j |  j |  j ƒ |  _ |  j j ƒ  n  t t |  ƒ j | | Ž  S(   Ns   Opening websocket %si    (   RM   t   debugRD   t   pathR:   R   t   IOLoopt   currentt   timet	   last_pingt	   last_pongt   PeriodicCallbackt	   send_pingt   ping_callbackR1   t   superR4   t   open(   R9   RT   RU   t   loop(    (    s8   lib/python2.7/site-packages/notebook/base/zmqhandlers.pyRb       s    c         C   sï   |  j  d k r/ |  j d k	 r/ |  j j ƒ  d St j j ƒ  j ƒ  } d | |  j } d | |  j	 } | d |  j
 k  r© | |  j k r© |  j j d | ƒ |  j ƒ  d Sy |  j d ƒ Wn% t t f k
 rá |  j j ƒ  d SX| |  _	 d S(   s'   send a ping to keep the websocket aliveNg     @@i   s#   WebSocket ping timeout after %i ms.R   (   t   ws_connectionR,   R`   R2   R   RY   RZ   R[   R]   R\   R:   R=   RM   RN   t   closet   pingR   R   (   R9   t   nowt   since_last_pongt   since_last_ping(    (    s8   lib/python2.7/site-packages/notebook/base/zmqhandlers.pyR_   ®   s     "
c         C   s   t  j j ƒ  j ƒ  |  _ d  S(   N(   R   RY   RZ   R[   R]   (   R9   t   data(    (    s8   lib/python2.7/site-packages/notebook/base/zmqhandlers.pyt   on_pongÆ   s    N(   t   __name__t
   __module__t   __doc__R,   R`   R\   R]   t   streamt   propertyR:   R=   RS   RV   Rb   R_   Rk   (    (    (    s8   lib/python2.7/site-packages/notebook/base/zmqhandlers.pyR4   \   s   
'			t   ZMQStreamHandlerc           B   s8   e  Z e j d k  r! d „  Z n  d d „ Z d „  Z RS(   i   i   c         O   s<   |  j  d  k r+ t t |  ƒ j | | Ž  n |  j  j ƒ  d  S(   N(   Ro   R,   Ra   R   t
   send_errorRe   (   R9   RT   RU   (    (    s8   lib/python2.7/site-packages/notebook/base/zmqhandlers.pyRr   Î   s    c         C   s’   t  | t ƒ r | } n* |  j j | ƒ \ } } |  j j | ƒ } | rU | | d <n  | d ro t | ƒ } | St j | d t ƒ} t	 | ƒ Sd S(   s»  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.
        
        t   channelR   R   N(
   t
   isinstancet   dictt   sessiont   feed_identitiest   deserializeR(   R   R   R   R
   (   R9   t   msg_or_listRs   R!   t   identst   msg_listR&   t   smsg(    (    s8   lib/python2.7/site-packages/notebook/base/zmqhandlers.pyt   _reserialize_replyÙ   s    	
c         C   sì   |  j  d  k s | j ƒ  r9 |  j j d ƒ |  j ƒ  d  St | d d  ƒ } y |  j | d | ƒ} Wn, t k
 r’ |  j j	 d | d t
 ƒd  SXy  |  j | d t | t ƒ ƒWn2 t t f k
 rç |  j j d ƒ |  j ƒ  d  SXd  S(   Ns%   zmq message arrived on closed channelRs   s   Malformed message: %rt   exc_infot   binary(   Rd   R,   t   closedRM   RN   Re   t   getattrR}   t	   Exceptiont   criticalRC   t   write_messageRt   t   bytesR   R   (   R9   Ro   R{   Rs   R!   (    (    s8   lib/python2.7/site-packages/notebook/base/zmqhandlers.pyt   _on_zmq_replyó   s     
 
(   i   i   N(   Rl   Rm   t   tornadoR   Rr   R,   R}   R†   (    (    (    s8   lib/python2.7/site-packages/notebook/base/zmqhandlers.pyRq   Ê   s   t   AuthenticatedZMQStreamHandlerc           B   s>   e  Z d  „  Z d „  Z e j d „  ƒ Z d „  Z d „  Z RS(   c         C   s   d S(   sp   Undo the set_default_headers in IPythonHandler
        
        which doesn't make sense for websockets
        N(    (   R9   (    (    s8   lib/python2.7/site-packages/notebook/base/zmqhandlers.pyt   set_default_headers  s    c         C   sx   |  j  ƒ  d k r4 |  j j d ƒ t j d ƒ ‚ n  |  j d t ƒ rd t |  j d ƒ ƒ |  j	 _	 n |  j j d ƒ d S(   s¡   Run before finishing the GET request
        
        Extend this method to add logic that should fire before
        the websocket finishes completing.
        s*   Couldn't authenticate WebSocket connectioni“  t
   session_ids   No session ID specifiedN(
   t   get_current_userR,   RM   RN   R   t	   HTTPErrort   get_argumentRL   R
   Rv   (   R9   (    (    s8   lib/python2.7/site-packages/notebook/base/zmqhandlers.pyt   pre_get  s    c         o   sG   |  j  ƒ  } t j | ƒ Vt t |  ƒ j | | Ž  } t j | ƒ Vd  S(   N(   RŽ   R   t   maybe_futureRa   Rˆ   R7   (   R9   RT   RU   t   res(    (    s8   lib/python2.7/site-packages/notebook/base/zmqhandlers.pyR7   "  s    c         C   s2   |  j  j d |  j j ƒ t d |  j ƒ |  _ d  S(   Ns$   Initializing websocket connection %st   config(   RM   RW   RD   RX   R   R‘   Rv   (   R9   (    (    s8   lib/python2.7/site-packages/notebook/base/zmqhandlers.pyt
   initialize+  s    c         C   s   |  j  j d d  ƒ S(   Nt   websocket_compression_options(   R6   R7   R,   (   R9   (    (    s8   lib/python2.7/site-packages/notebook/base/zmqhandlers.pyt   get_compression_options/  s    (	   Rl   Rm   R‰   RŽ   R   t	   coroutineR7   R’   R”   (    (    (    s8   lib/python2.7/site-packages/notebook/base/zmqhandlers.pyRˆ   	  s
   				("   Rn   t   osR   R   t   warningsR   t   urllib.parseR    t   ImportErrorR‡   R   R   R   t   tornado.iostreamR   t   tornado.websocketR   R   t   jupyter_client.sessionR   t   jupyter_client.jsonutilR   R	   t   ipython_genutils.py3compatR
   t   handlersR   R(   R3   R8   t   objectR4   Rq   Rˆ   (    (    (    s8   lib/python2.7/site-packages/notebook/base/zmqhandlers.pyt   <module>   s.   	 	n?