U
    Qe                     @  s   d Z ddlmZ ddlZddlZddlZddlmZmZ ddl	Z
ddl
mZ ddlmZ erlddlmZmZ dd	d
ddZG dd de
jjZdS )z9Tornado websocket handler to serve a terminal interface.
    )annotationsN)TYPE_CHECKINGAny)gen)run_on_executor)PtyWithClientsTermManagerBasezstr | bytesstr)sreturnc                 C  s   t | tr| dS | S )Nzutf-8)
isinstancebytesdecode)r
    r   2lib/python3.8/site-packages/terminado/websocket.py_cast_unicode   s    

r   c                      s   e Zd ZdZdddddZd(dd	d
ddZd)ddd fddZdddddZdddddZe	j
dddddZddddZddddZd*ddd!d"d#Zed$d%dddd&d'Z  ZS )+
TermSocketz Handler for a terminal websocketr   None)term_managerr   c                 C  sN   || _ d| _d| _d| _|j| _tt| _	d| _
ttdddk| _dS )zInitialize the handler. )NNNZLOG_TERMINAL_OUTPUTZfalsetrue)r   	term_namesizeterminalZblocking_io_executor_blocking_io_executorloggingZ	getLogger__name___logger_user_commandr	   lowerosgetenv_enable_output_logging)selfr   r   r   r   
initialize   s    zTermSocket.initializeNz
str | Nonebool)originr   c                 C  s*   |p| j jdd}|dk	s t| |S )z1Deprecated: backward-compat for terminado <= 0.5.ZOriginr   N)ZrequestZheadersgetAssertionErrorZcheck_origin)r#   r&   r   r   r   origin_check,   s    zTermSocket.origin_checkr   )url_componentr   c                   s   t  | | jd| t|}|p(d| _| j|| _| jj	
|  | di g | jd| j d}| jj }|s|q| }||7 }qv|r| | dS )zWebsocket connection opened.

        Call our terminal manager to get a terminal, and connect to it as a
        client.
        zTermSocket.open: %sZttyZsetupzTermSocket.open: Opened %sr   N)superopenr   infor   r   r   Zget_terminalr   clientsappendsend_json_messageZread_buffercopypoplefton_pty_read)r#   r*   ZbufferedZpreopen_bufferr
   	__class__r   r   r,   2   s     

zTermSocket.openr	   )textr   c                 C  s   |  d|g dS )z$Data read from pty; send to frontendstdoutN)r0   r#   r6   r   r   r   r3   O   s    zTermSocket.on_pty_read)contentr   c                 C  sL   t |}| | | jrH|d dkrHt|d trH| d|d   dS )z"Send a json message on the socket.r   r7      zSTDOUT: N)jsondumpsZwrite_messager"   r   r	   log_terminal_output)r#   r9   Zjson_msgr   r   r   r0   S   s    

 zTermSocket.send_json_message)messager   c                 c  s   t |}|d }| jdk	s t|dkrx| |d V  | jr|d dkrd| d| j  d| _q|  j|d 7  _n |dkr|dd	 | _| j	  dS )
zHandle incoming websocket message

        We send JSON arrays, where the first element is a string indicating
        what kind of message this is. Data associated with the message follows.
        r   Nstdinr:   zSTDIN: r   Zset_size   )
r;   loadsr   r(   stdin_to_ptyprocr"   r=   r   r   resize_to_smallest)r#   r>   ZcommandZmsg_typer   r   r   
on_message[   s    
zTermSocket.on_message)r   c                 C  s:   | j d | jr*| jj|  | j  | j|  dS )zHandle websocket closing.

        Disconnect from our terminal, and tell the terminal manager we're
        disconnecting.
        zWebsocket closedN)r   r-   r   r.   removerD   r   Zclient_disconnectedr#   r   r   r   on_closer   s
    
zTermSocket.on_closec                 C  s    |  ddg |   d| _dS )z9Terminal closed: tell the frontend, and close the socket.Z
disconnectr:   N)r0   closer   rG   r   r   r   on_pty_died~   s    zTermSocket.on_pty_diedr   )logr   c                 C  s   | j | dS )zg
        Logs the terminal input/output
        :param log: log line to write
        :return:
        N)r   debug)r#   rK   r   r   r   r=      s    zTermSocket.log_terminal_outputr   )executorc                 C  s   | j dk	r| j j| dS )a   Handles stdin messages sent on the websocket.

        This is a blocking call that should NOT be performed inside the
        server primary event loop thread. Messages must be handled
        asynchronously to prevent blocking on the PTY buffer.
        N)r   Zptyprocwriter8   r   r   r   rC      s    
zTermSocket.stdin_to_ptyproc)N)N)r   )r   
__module____qualname____doc__r$   r)   r,   r3   r0   r   	coroutinerE   rH   rJ   r=   r   rC   __classcell__r   r   r4   r   r      s   r   )rQ   Z
__future__r   r;   r   r    typingr   r   Ztornado.websocketZtornador   Ztornado.concurrentr   Zterminado.managementr   r   r   Z	websocketZWebSocketHandlerr   r   r   r   r   <module>   s   