a hP(@sddlZddlZddlZddlmZmZmZddlmZm Z ddl m Z m Z m Z eeZGdddZGdd d ZGd d d e ZGd d d ZGddde ZdS)N)DictListOptional) JsonObject JsonValue)CockpitProblemCockpitProtocolErrorCockpitProtocolServerc@s.eZdZdZddZddZdddd ZdS) ExecutionQueueawTemporarily 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. cCs*t|_||_|jD]}||qdSN) collectionsdequequeuemethods_wrap)selfrmethodr2/usr/lib/python3.9/site-packages/cockpit/router.py__init__&s  zExecutionQueue.__init__cs tjjjfdddS)Ncsj|fSr )rappend)argsrrrr1z&ExecutionQueue._wrap..)setattr__self____func____name__)rrrrrr-szExecutionQueue._wrapNreturncCsJtdt|j|jD]\}}||q|jD]}t|j|jjq0dS)Nz.ExecutionQueue: Running %d queued method calls) loggerdebuglenrrdelattrrrr)rrrrrrrun3s   zExecutionQueue.run)r __module__ __qualname____doc__rrr&rrrrr sr c@seZdZUded<dZeeed<ddddZddd d Zddd d Z ddd dZ e e e ddddZ e eddddZdde ddddZe eddddZe e deddddZd"deddd d!ZdS)#EndpointRouterrouterN _Endpoint__endpoint_frozen_queuer,cCs||||_dSr ) add_endpointr,rr,rrrr@s zEndpoint.__init__r cCs&td|t|j|j|jh|_dS)NzFreezing endpoint %s)r"r#r do_channel_controldo_channel_datado_killr-rrrrfreeze_endpointDs zEndpoint.freeze_endpointcCs td||jd|_dS)NzThawing endpoint %s)r"r#r-r&r4rrr thaw_endpointIs  zEndpoint.thaw_endpointcCstdSr NotImplementedErrorr4rrrdo_closePszEndpoint.do_closechannelcommandmessager!cCstdSr r7)rr;r<r=rrrr1SszEndpoint.do_channel_controlr;datar!cCstdSr r7rr;r?rrrr2VszEndpoint.do_channel_data str | Nonehostgroupr=r!cCstdSr r7)rrCrDr=rrrr3YszEndpoint.do_killcCs|j||dSr )r,Zwrite_channel_datar@rrrsend_channel_data]szEndpoint.send_channel_dataJsonObject | None)r;r<msgkwargsr!cKsD|jj|f||d||dkr@|jj|||j|dS)N)r;r<close)r, write_control endpointsremove drop_channel)rr;r<rGrHrrrsend_channel_control`szEndpoint.send_channel_control)rGrHr!cKs|jj||fi|dSr )r,shutdown_endpoint)rrGrHrrrrOhszEndpoint.shutdown_endpoint)N)rr'r(__annotations__r-rr rr5r6r9strrr1bytesr2r3rErrNrOrrrrr*<s  r*c@s eZdZdS) RoutingErrorN)rr'r(rrrrrSlsrSc@sFeZdZUded<ddddZeeedddZd d d d Z d S) RoutingRuler+r,r.cCs ||_dSr r.r0rrrrsszRoutingRule.__init__optionsr!cCstdS)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 Nr7)rrVrrr apply_rulevs zRoutingRule.apply_ruleNr cCstdSr r7r4rrrshutdownszRoutingRule.shutdown) rr'r(rPrrrr*rWrXrrrrrTps  rTc@s*eZdZUeeed<eeefed<ded<e j ed<dZ e ed<eedd d Z ed d d ZeedddZeddddZeddddZd.ededdddZddeddddZeeedd d!d"Zeedd#d$d%Ze d d&d'ZdZee jed(<eedd)d*d+Zdd d,d-ZdS)/r+ routing_rules open_channelszdict[Endpoint, set[str]]rK no_endpointsF_eof)rYcCs:|D] }||_q||_i|_i|_t|_|jdSr )r,rYrZrKasyncioEventr[set)rrYrulerrrrs zRouter.__init__r cCsiS)z7Used by the 'info' channel. Gets overridden in Bridge.rr4rrrinfosz Router.inforUcCsT|jD]6}td|||}|durtd||SqtdtddS)Nz applying rule %sz resulting endpoint is %sz No rules matchedz not-supported)rYr"r#rWrS)rrVr`endpointrrr check_ruless      zRouter.check_rulesN)r;r!cCsDz|j|td|Wn"ty>td||jYn0dS)Nzrouter dropped channel %sz.trying to drop non-existent channel %s from %s)rZpopr"r#KeyErrorerror)rr;rrrrMs   zRouter.drop_channel)rbr!cCst|j|<|jdSr )r_rKr[clear)rrbrrrr/s zRouter.add_endpointrF)rbrGrHr!cKs|j|}td||||D]&}|j|fd|d|||q |jsX|j|jrtd|j|js|j rtd|j dS)Nz'shutdown_endpoint(%s, %s) will close %srIr<r; endpoints remaining: %rz close transport) rKrdr"r#rJrMr[r_r\Z transportrI)rrbrGrHZchannelsr;rrrrOs     zRouter.shutdown_endpointrArBcCs:t|j}td||t||D]}||||q"dS)Nz+do_kill(%s, %s). Considering %d endpoints.)r_rKr"r#r$r3)rrCrDr=rKrbrrrr3s zRouter.do_killr:c Cs|dkr||jvrtdz"td||d||}Wn:tyv}z"|j|d|dWYd}~dSd}~00||j|<|j | |n$z|j|}Wnt yYdS0| |||dS)Nopenzchannel is already openz5Trying to find endpoint for new channel %s payload=%sZpayloadrIrh) rZr r"r#getrcrSrJZ get_attrsrKaddrer1)rr;r<r=rbexcrrrchannel_control_receiveds    zRouter.channel_control_receivedr>cCs4z|j|}Wnty"YdS0|||dSr )rZrer2)rr;r?rbrrrchannel_data_receiveds  zRouter.channel_data_receivedcCsFtd|t|j}|D] }|qd|_td|jt|jS)Nzeof_received(%r)Tri)r"r#r_rKr9r\bool)rrKrbrrr eof_receiveds   zRouter.eof_received_communication_done)rmr!cCs>|js||jdur:|dur.|jdn |j|dSr )r\rqrrZ set_resultZ set_exception)rrmrrr do_closeds  zRouter.do_closedc snt|_zBz|jIdHWnttfy6Yn0Wd|_|jIdHnd|_|jIdH0dS)zNWait until communication is complete on the router and all endpoints are done.N)r]Zget_running_loopZ create_futurerrBrokenPipeErrorConnectionResetErrorr[waitr4rrr communicateszRouter.communicate)N) rr'r(rrTrPrrQr*r]r^r\rprrrarcrMr/rrOr3rnrRrorqrrrZFuture Exceptionrsrwrrrrr+s$        r+)r]r ZloggingtypingrrrZjsonutilrrZprotocolrr r Z getLoggerrr"r r*rSrTr+rrrrs 0