a hG@sdZddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl mZmZmZddlmZmZedjZeddddZdZeeZd ZGd d d ejZGd d d ejZ GdddZ!Gdddeej"Z"GdddeZ#GdddZ$dS)zKBi-directional asyncio.Transport implementations based on file descriptors.N)AnyClassVarSequence) JsonObjectget_int)argsreturncGst|dkrtddS)Nrzprctl() failed) sys_prctlOSError)rr 6/usr/lib/python3.9/site-packages/cockpit/transports.pyprctl's ricseZdZUdZeeed<ejed<ej ed<ded<eed<eed<e ed <e ed <e ed <d Z e ed <dHejej eeddfdd Z ddddZ e dddZddddZddddZddddZdddd ZdId!dd"d#d$Ze dd%d&Zddd'd(Zedd)d*Zd+dd,d-ZdJd.d.dd/d0d1Zddd2d3Zddd4d5Zddd6d7Zedd8d9d:Zedd8d;d<Zddd=d>Zej dd?d@Z!e ddAdBZ"ej ddCdDdEZ#dddFdGZ$Z%S)K _Transporti BLOCK_SIZE_loop _protocolzcollections.deque[bytes] | None_queue_in_fd_out_fd_closing _is_reading_eofF _eio_is_eofNzdict[str, object] | None)loopprotocolin_fdout_fdextracst|||_||_td||||d|_d|_d|_d|_ ||_ ||_ t |d||krnt |d|j||dS)Nz/Created transport %s for protocol %s, fds %d %dF)super__init__rrloggerdebugrrrrrros set_blockingZconnection_maderesume_reading)selfrrrrr __class__r r r!Bs    z_Transport.__init__r c Cstd||j|jzt|jtj}Wnfty<YdSt y}z<|j rb|j t j krbd}n| |WYd}~dSWYd}~n d}~00|dkrtdt||j|n(td||j}|s|dS)NzRead ready on %s %s %dz read %d bytesz got EOF)r"r#rrr$readrrBlockingIOErrorr rerrnoZEIOabortlenZ data_received _close_readerZ eof_receivedclose)r'dataexcZ keep_openr r r _read_ready]s$  $  z_Transport._read_readycCs|jSN)rr'r r r is_readingvsz_Transport.is_readingcCs|d|_dSNr) pause_readingrr7r r r r1ysz_Transport._close_readercCs|jr|j|jd|_dSNF)rr remove_readerrr7r r r r:}sz_Transport.pause_readingcCs,|js(|jdkr(|j|j|jd|_dS)NrT)rrr add_readerr5r7r r r r&sz_Transport.resume_readingcCsdSr6r r7r r r _closesz_Transport._closezException | None)r4r cCs4d|_|||j|jj||dSNT)rr1_remove_write_queuerZ call_soonrZconnection_lostr>)r'r4r r r r/s z_Transport.abortcCstdSr6NotImplementedErrorr7r r r can_write_eofsz_Transport.can_write_eofcCs6d|_|jdur&td||n td|dS)NTz%s got EOF. closing backend.z,%s got EOF. bytes in queue, deferring close)rrr"r#_write_eof_nowr7r r r write_eofs    z_Transport.write_eofcCs"|jdurdStdd|jDS)Nrcss|]}t|VqdSr6)r0).0blockr r r r+z3_Transport.get_write_buffer_size..)rsumr7r r r get_write_buffer_sizes z _Transport.get_write_buffer_sizeztuple[int, int]cCsdS)N)rrr r7r r r get_write_buffer_limitssz"_Transport.get_write_buffer_limits int | None)highlowr cCsdSr6r )r'rMrNr r r set_write_buffer_limitssz"_Transport.set_write_buffer_limitscCstdSr6rAr7r r r rDsz_Transport._write_eof_nowc Cstd|zt|j|j}WnDty6d}Yn0tyd}z||WYd}~dSd}~00td||r|j }t ||krtd|j ||dq|t |8}td|qr|js td| |j rtd||jr |dS)Nz%s _write_readyrz, successfully wrote %d bytes from the queuez incomplete block. Stop.z& removed complete block. %d remains.z%s queue drained.z'%s queue drained. closing backend now.)r"r#r$writevrrr-r r/popleftr0 appendleftr@rrDr)r'n_bytesr4rGr r r _write_readys2          z_Transport._write_readycCs,|jdur(|j|j|jd|_dSr6)rrZresume_writingrZ remove_writerrr7r r r r@s  z_Transport._remove_write_queue)r3r cCs>td||j|j|j|jt|f|_|j dS)Nz!%s creating write queue for fd %s) r"r#rrZ add_writerrT collectionsdequerrZ pause_writingr'r3r r r _create_write_queuesz_Transport._create_write_queuec Cs|jrtd|jdS|jdurb|j|t|jtkr^d|j}|j |j|dSzt |j|}WnDt yd}Yn0t y}z||WYd}~dSd}~00|t|kr|||ddS)Nz+ignoring write() to closing transport fd %ir+r)rr"r#rrappendr0IOV_MAXjoinclearr$writer-r r/rX)r'r3Zall_datarSr4r r r r]s&        z_Transport.writecCs2|jr dSd|_||jdur&dS|dSr?)rr1rr/r7r r r r2s z_Transport.closecCs|jSr6)rr7r r r get_protocol sz_Transport.get_protocolcCs|jSr6)rr7r r r is_closing sz_Transport.is_closing)rr cCstdSr6rA)r'rr r r set_protocolsz_Transport.set_protocolcCs |dSr6)r>r7r r r __del__sz_Transport.__del__)rrN)N)NN)&__name__ __module__ __qualname__rrint__annotations__asyncioAbstractEventLoopProtocolboolrr!r5r8r1r:r&r>r/rCrErJrKrOrDrTr@bytesrXr]r2Z BaseProtocolr^r_r`ra __classcell__r r r(r r3sP     !  rc@seZdZdZddddZdS)SubprocessProtocolzBAn extension to asyncio.Protocol for use with SubprocessTransport.Nr*cCstdS)z"Called when subprocess has exited.NrAr7r r r process_exitedsz!SubprocessProtocol.process_exited)rbrcrd__doc__rnr r r r rmsrmc@seZdZedddZdS) WindowSize)valuecCst|d|_t|d|_dS)Nrowscols)rrrrs)r'rqr r r r!s zWindowSize.__init__N)rbrcrdrr!r r r r rpsrpcs(eZdZUdZdZded<dZded<dZded<ded <d d ee d d dZ dddddZ d dde j eee ededfddZeddddZedddZddddZedd d!Zddd"d#Zee jd$d%d&Zejdd'd(d)Zddd*d+Zddd,d-Zddd.d/Z Z!S)0SubprocessTransportaA bi-directional transport speaking with stdin/out of a subprocess. Note: this is not really a normal SubprocessTransport. Although it implements the entire API of asyncio.SubprocessTransport, it is not designed to be used with asyncio.SubprocessProtocol objects. Instead, it pair with normal Protocol objects which also implement the SubprocessProtocol defined in this module (which only has a process_exited() method). Whatever the protocol writes is sent to stdin, and whatever comes from stdout is given to the Protocol via the .data_received() function. If stderr is configured as a pipe, the transport will separately collect data from it, making it available via the .get_stderr() method. NrL_pty_fdzsubprocess.Popen[bytes] | None_process _returncodezSpooler | None_stderrFresetrzr cCs(|jdur |jj|djddSdSdS)Nryreplace)errors)rxgetdecode)r'rzr r r get_stderr9s zSubprocessTransport.get_stderrzsubprocess.Popen[bytes])processr c sddfdd ddfdd }ttddfdd }ztjj|Wn`ttfyd }tj|d}|durt }| jt j||| j|Yn0dS) Nr*cs"tdjjsjdS)NzProcess exited with status %d)r"r#rwrrrnr r7r r flag_exit@sz1SubprocessTransport.watch_exit..flag_exitcs\tjd\}}zt|_Wnty:|_Yn0jtdSNr) r$waitpidpidwaitstatus_to_exitcoderw ValueErrorrr<r2)rstatusrZpidfdrr'r r pidfd_readyFs    z3SubprocessTransport.watch_exit..pidfd_ready)rcoder cs|_dSr6rw)rr)rrr'r r child_watch_firedQsz9SubprocessTransport.watch_exit..child_watch_firedZ!_cockpit_transports_child_watcher)rer$ pidfd_openrrr=AttributeErrorr getattrrgZSafeChildWatcherZ attach_loopsetattrZadd_child_handler)r'rrrZquarkZwatcherr rr watch_exit?s    zSubprocessTransport.watch_exit)ptywindowzWindowSize | None)rrrrrkwargsc  sddfdd }r|t\|_}|dur6||||d<tj|f|||dd||_t||j|j} } d|_n8tj|ftj tj |d||_|jj } |jj } |jj durt||jj |_nd|_t||| | ||jdS)Nr*cs$tttjr tdtjddSr)r SET_PDEATHSIGsignalSIGTERMfcntlioctltermiosZ TIOCSCTTYr rr r preexec_fnts z0SubprocessTransport.__init__..preexec_fnstderrT)stdinstdoutrZstart_new_session)rrr)r$openptyruset_window_size subprocessPopenrvr2rPIPErfilenorrSpoolerrxr r!r) r'rrrrrrrZ session_fdrrr(rr r!js6      zSubprocessTransport.__init__)sizer c Cs$t|jtjtd|j|jdS)NZ2H4x) rrrurZ TIOCSWINSZstructpackrrrs)r'rr r r rsz#SubprocessTransport.set_window_sizer*cCs |jjduSr6)rvrr7r r r rCsz!SubprocessTransport.can_write_eofcCs|jjd|_dSr9)rvrr2rr7r r r rDs z"SubprocessTransport._write_eof_nowcCs|jjSr6)rvrr7r r r get_pidszSubprocessTransport.get_pidcCs|jSr6rr7r r r get_returncodesz"SubprocessTransport.get_returncode)fdr cCstdSr6rA)r'rr r r get_pipe_transportsz&SubprocessTransport.get_pipe_transport)sigr cCsp|jdur td||jjdSz&t|jj|td||jjWn$tyjtd||jjYn0dS)Nz3won't attempt %s to process %i. It exited already.zsent %s to process %iz3can't send %s to process %i. It's exited just now.)rwr"r#rvrr$killProcessLookupError)r'rr r r send_signals  zSubprocessTransport.send_signalcCs|tjdSr6)rrrr7r r r terminateszSubprocessTransport.terminatecCs|tjdSr6)rrSIGKILLr7r r r rszSubprocessTransport.killcCsz|jdurt|jd|_|jdurv|jjdurF|jjd|j_z |Wn"tyttd|jj Yn0dS)Nzcan't kill %i due to EPERM) rur$r2rvrrPermissionErrorr"r#rr7r r r r>s       zSubprocessTransport._close)"rbrcrdrorurfrvrwrjstrrrrgrhrmrrr!rprrCrDrerr TransportrrZSignalsrrrr>rlr r r(r rt$s6    0.rtcsNeZdZdZd ejejeedfdd Ze ddd Z d dd d Z Z S)StdioTransportzA bi-directional transport that corresponds to stdin/out. Can talk to just about anything: - files - pipes - character devices (including terminals) - sockets rr)rrrrcst||||dSr6)r r!)r'rrrrr(r r r!szStdioTransport.__init__r*cCsdSr;r r7r r r rCszStdioTransport.can_write_eofNcCs tddS)NzCan't write EOF to stdout) RuntimeErrorr7r r r rDszStdioTransport._write_eof_now)rr) rbrcrdrorgrhrirer!rjrCrDrlr r r(r rs rc@seZdZUdZejed<eed<ded<ejedddZd d d d Z e d d dZ dde e dddZ d d ddZd d ddZd S)rzConsumes data from an fd, storing it in a buffer. This makes a copy of the fd, so you don't have to worry about holding it open. r_fdz list[bytes] _contents)rrcCs@||_d|_g|_t||_t|jd||j|jdS)NrF)rrrr$dupr%r=r5)r'rrr r r r!s  zSpooler.__init__Nr*cCs^zt|jd}Wn(ty&YdSty:d}Yn0|dkrR|j|n|dS)Ni r+)r$r,rr-r rrYr2rWr r r r5s   zSpooler._read_readycCs,|jdkrdSt|jgggdgggfkS)NrFr)rselectr7r r r _is_readys zSpooler._is_readyFryr{cCs,|r|qd|j}|r(g|_|S)Nr+)rr5r[r)r'rzresultr r r rs   z Spooler.getcCs.|jdkr*|j|jt|jd|_dSr9)rrr<r$r2r7r r r r2"s  z Spooler.closecCs |dSr6)r2r7r r r ra(szSpooler.__del__)rbrcrdrorgrhrfrer!r5rjrrkrr2rar r r r rs    r)%rorgrUZctypesr.rZloggingr$rrrrrtypingrrrZjsonutilrrZCDLLrr rerZ getLoggerrbr"rZrrrirmrprtrrr r r r s6  e: