
    i&                         d dl Z d dlZd dlZd dlmZmZmZ ddlmZm	Z	 ddl
mZmZmZ  ej                  e      Z G d d      Z G d d	      Z G d
 de      Z G d d      Z G d de      Zy)    N)DictListOptional   )
JsonObject	JsonValue)CockpitProblemCockpitProtocolErrorCockpitProtocolServerc                   $    e Zd ZdZd Zd ZddZy)ExecutionQueueaw  Temporarily delay calls to a given set of class methods.

    Functions by replacing the named function at the instance __dict__
    level, effectively providing an override for exactly one instance
    of `method`'s object.
    Queues the invocations.  Run them later with .run(), which also reverses
    the redirection by deleting the named methods from the instance.
    c                     t        j                         | _        || _        | j                  D ]  }| j	                  |        y N)collectionsdequequeuemethods_wrap)selfr   methods      0/usr/lib/python3/dist-packages/cockpit/router.py__init__zExecutionQueue.__init__   s8     &&(
ll 	FJJv	    c                 f     t        j                  j                  j                   fd       y )Nc                  >    j                   j                  | f      S r   )r   append)argsr   r   s    r   <lambda>z&ExecutionQueue._wrap.<locals>.<lambda>%   s    IZIZ\bdh[iIj r   )setattr__self____func____name__)r   r   s   ``r   r   zExecutionQueue._wrap!   s      	!9!9;jkr   Nc                     t         j                  dt        | j                               | j                  D ]
  \  }} ||   | j                  D ],  }t        |j                  |j                  j                         . y )Nz.ExecutionQueue: Running %d queued method calls)	loggerdebuglenr   r   delattrr    r!   r"   )r   r   r   s      r   runzExecutionQueue.run'   sd    Es4::W JJ 	LFDDM	 ll 	?FFOOV__%=%=>	?r   returnN)r"   
__module____qualname____doc__r   r   r(    r   r   r   r      s    l?r   r   c            
           e Zd ZU ded<   dZee   ed<   ddZddZddZ	dd	Z
d
edededdfdZd
ededdfdZdddddeddfdZd
ededdfdZd
ededddeddf
dZddddeddfdZy)EndpointRouterrouterN _Endpoint__endpoint_frozen_queuec                 4    |j                  |        || _        y r   )add_endpointr2   r   r2   s     r   r   zEndpoint.__init__4   s    D!r   r*   c                     | j                   J t        j                  d|        t        | j                  | j
                  | j                  h      | _         y )NzFreezing endpoint %s)r3   r$   r%   r   do_channel_controldo_channel_datado_killr   s    r   freeze_endpointzEndpoint.freeze_endpoint8   sK    ++333+T2'5t7N7NPTPdPdfjfrfr6s't$r   c                     | j                   J t        j                  d|        | j                   j                          d | _         y )NzThawing endpoint %s)r3   r$   r%   r(   r;   s    r   thaw_endpointzEndpoint.thaw_endpoint=   s=    ++777*D1$$((*'+$r   c                     t         r   NotImplementedErrorr;   s    r   do_closezEndpoint.do_closeD       !!r   channelcommandmessagec                     t         r   r@   )r   rD   rE   rF   s       r   r8   zEndpoint.do_channel_controlG   rC   r   datac                     t         r   r@   r   rD   rH   s      r   r9   zEndpoint.do_channel_dataJ   rC   r   host
str | Nonegroupc                     t         r   r@   )r   rK   rM   rF   s       r   r:   zEndpoint.do_killM   rC   r   c                 <    | j                   j                  ||       y r   )r2   write_channel_datarJ   s      r   send_channel_datazEndpoint.send_channel_dataQ   s    &&w5r   msgJsonObject | Nonekwargsc                      | j                   j                  |f||d| |dk(  rD| j                   j                  |    j                  |       | j                   j	                  |       y y )N)rD   rE   close)r2   write_control	endpointsremovedrop_channel)r   rD   rE   rR   rT   s        r   send_channel_controlzEndpoint.send_channel_controlT   s`     	"!!#RwR6RgKK!!$'..w7KK$$W- r   c                 @     | j                   j                  | |fi | y r   )r2   shutdown_endpoint)r   rR   rT   s      r   r]   zEndpoint.shutdown_endpoint\   s    %%%dC:6:r   r2   r1   r)   r   )r"   r+   r,   __annotations__r3   r   r   r   r<   r>   rB   strr   r8   bytesr9   r:   rQ   r   r[   r]   r.   r   r   r0   r0   0   s    8<Xn5<u
,""# " "j "UY ""s "% "D ""L " "
 "W[ "6 6E 6d 6..%(./B.NW.	.;%8 ;9 ;Y] ;r   r0   c                       e Zd Zy)RoutingErrorN)r"   r+   r,   r.   r   r   rc   rc   `   s    r   rc   c                   >    e Zd ZU ded<   d	dZdedee   fdZd
dZ	y)RoutingRuler1   r2   c                     || _         y r   )r2   r6   s     r   r   zRoutingRule.__init__g   s	    r   optionsr*   c                     t         )a]  Check if a routing rule applies to a given 'open' message.

        This should inspect the options dictionary and do one of the following three things:

            - return an Endpoint to handle this channel
            - raise a RoutingError to indicate that the open should be rejected
            - return None to let the next rule run
        r@   )r   rg   s     r   
apply_rulezRoutingRule.apply_rulej   s
     "!r   Nc                     t         r   r@   r;   s    r   shutdownzRoutingRule.shutdownu   rC   r   r^   r)   )
r"   r+   r,   r_   r   r   r   r0   ri   rk   r.   r   r   re   re   d   s*    	"* 	"(1C 	""r   re   c            	       f   e Zd ZU ee   ed<   eeef   ed<   ded<   e	j                  ed<   dZeed<   dee   fdZd	efd
Zded	efdZded	dfdZded	dfdZd$deddded	dfdZddddded	dfdZdededed	dfdZdeded	dfdZd	efdZdZee	j8                     ed <   d!ee   d	dfd"Zd%d#Zy)&r1   routing_rulesopen_channelszdict[Endpoint, set[str]]rX   no_endpointsF_eofc                     |D ]	  }| |_          || _        i | _        i | _        t	        j
                         | _        | j                  j                          y r   )r2   rm   rn   rX   asyncioEventro   set)r   rm   rules      r   r   zRouter.__init__   sO    ! 	DDK	*#MMOr   r*   c                     i S )z7Used by the 'info' channel.  Gets overridden in Bridge.r.   r;   s    r   infozRouter.info   s    	r   rg   c                     | j                   D ]E  }t        j                  d|       |j                  |      }|-t        j                  d|       |c S  t        j                  d       t	        d      )Nz  applying rule %sz    resulting endpoint is %sz  No rules matchedznot-supported)rm   r$   r%   ri   rc   )r   rg   ru   endpoints       r   check_ruleszRouter.check_rules   sh    && 	0DLL-t4w/H#;XF	0 LL-.//r   rD   Nc                     	 | j                   j                  |       t        j                  d|       y # t        $ r$ t        j                  d|| j                          Y y w xY w)Nzrouter dropped channel %sz.trying to drop non-existent channel %s from %s)rn   popr$   r%   KeyErrorerror)r   rD   s     r   rZ   zRouter.drop_channel   sT    	h""7+LL4g> 	hLLI7TXTfTfg	hs   14 *A! A!ry   c                 f    t               | j                  |<   | j                  j                          y r   )rt   rX   ro   clear)r   ry   s     r   r5   zRouter.add_endpoint   s$    #&5x !r   rR   rS   rT   c                    | j                   j                  |      }t        j                  d|||       |D ])  } | j                  |fd|d| | j                  |       + | j                   s| j                  j                          | j                  rjt        j                  d| j                          | j                   s=| j                  r0t        j                  d       | j                  j                          y y y y )Nz'shutdown_endpoint(%s, %s) will close %srV   rE   rD     endpoints remaining: %rz  close transport)rX   r|   r$   r%   rW   rZ   ro   rt   rp   	transportrV   )r   ry   rR   rT   channelsrD   s         r   r]   zRouter.shutdown_endpoint   s    >>%%h/>&RZ[ 	'GDsOGWOOg&	' ~~!!# 99LL4dnnE>>dnn01$$& '5> r   rK   rL   rM   rF   c                     t        | j                        }t        j                  d||t	        |             |D ]  }|j                  |||        y )Nz+do_kill(%s, %s).  Considering %d endpoints.)rt   rX   r$   r%   r&   r:   )r   rK   rM   rF   rX   ry   s         r   r:   zRouter.do_kill   sK    '	BD%QTU^Q_`! 	3HT5'2	3r   rE   c                    | j                   t        d      |dk(  r|| j                  v rt        d      	 t        j	                  d||j                  d             | j                  |      }|| j                  |<   | j                  |   j                  |       n	 | j                  |   }|j                  |||       y # t        $ r,}| j                  |j                         d|       Y d }~y d }~ww xY w# t        $ r Y y w xY w)Nz,channel control message received before initopenzchannel is already openz5Trying to find endpoint for new channel %s payload=%spayloadrV   r   )	init_hostr
   rn   r$   r%   getrz   rc   rW   	get_attrsrX   addr}   r8   )r   rD   rE   rF   ry   excs         r   channel_control_receivedzRouter.channel_control_received   s   >>!&'UVV
 f$,,,*+DEETV]_f_j_jkt_uv++G4
 +3Dw'NN8$((1--g6 	##GWg>   ""3==?GW"U  s)   7C  C8  	C5	"C00C58	DDrH   c                     | j                   t        d      	 | j                  |   }|j	                  ||       y # t        $ r Y y w xY w)Nz)channel data message received before init)r   r
   rn   r}   r9   )r   rD   rH   ry   s       r   channel_data_receivedzRouter.channel_data_received   sS    >>!&'RSS	))'2H 	  $/  		s   ; 	AAc                     t         j                  d|        t        | j                        }|D ]  }|j	                           d| _        t         j                  d| j                         t        | j                        S )Nzeof_received(%r)Tr   )r$   r%   rt   rX   rB   rp   bool)r   rX   ry   s      r   eof_receivedzRouter.eof_received   se    '.'	! 	 H	  	0$..ADNN##r   _communication_doner   c                     | j                   s| j                          | j                  :|| j                  j                  d        y | j                  j	                  |       y y r   )rp   r   r   
set_resultset_exception)r   r   s     r   	do_closedzRouter.do_closed   sS    yy##/{((33D9((66s;	 0r   c                   K   | j                   J t        j                         j                         | _         	 | j                    d{    d| _         | j                  j                          d{    y7 .# t        t
        f$ r Y =w xY w7 # d| _         | j                  j                          d{  7   w xY ww)zNWait until communication is complete on the router and all endpoints are done.N)r   rr   get_running_loopcreate_futureBrokenPipeErrorConnectionResetErrorro   waitr;   s    r   communicatezRouter.communicate   s     ''///#*#;#;#=#K#K#M 		+**** (,D$ ##((*** +!56 		 +	 (,D$ ##((***sd   6B?A9 A7	A9 $B?1B2B?7A9 9BB 
BB B?%B<5B86B<<B?r   r)   ) r"   r+   r,   r   re   r_   r   r`   r0   rr   rs   rp   r   r   r   rw   rz   rZ   r5   r   r]   r:   r   ra   r   r   r   r   Future	Exceptionr   r   r.   r   r   r1   r1   y   sP   $$X&&))--D$ d;&7  j 	0: 	0( 	0hC hD h"X "$ "'( '9L '_h 'mq '"3L 3 3
 3W[ 3? ?c ?J ?[_ ?<	0S 	0 	0$ 	0	$d 	$ 59'..18	<Xi0 	<T 	<+r   r1   )rr   r   loggingtypingr   r   r   jsonutilr   r   protocolr	   r
   r   	getLoggerr"   r$   r   r0   rc   re   r1   r.   r   r   <module>r      sk       ' ' + Q Q			8	$? ?>-; -;`	> 	" "*O+" O+r   