o
    bk                     @   s  d Z ddlZddlZddlZddlZddlZddlmZ ddlm	Z	m
Z
mZm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mZmZmZmZmZmZmZ ddlm Z m!Z! dd	l"m#Z#m$Z$m%Z% dd
l&m'Z'm(Z( e)dZ*e)dZ+zddl,m-Z. W n e/y   dZ-Y nw e.Z-zddlm0Z1 W n e/y   dZ0Y nw e1Z0e(dkZ2dZ3e2rddlm4Z4m5Z5m6Z6m7Z7 dZ3e'8 rzddl9Z9dZ3W n e/y   dZ9Y nw G dd de
Z:ee:G dd de$j;Z<G dd de$j;Z=ee:G dd de=Z>e(dkre>Z?ne<Z?G dd de=Z@G dd dZAeeeeG dd  d eeAeZBG d!d" d"ZCeeG d#d$ d$eCeAZDe-dusAe0durFeeBe e2rOeeBee e3rWeeBe eEed%ddureeeBe d gZFdS )&z
Posix reactor base class
    N)Sequence)	Attribute	InterfaceclassImplementsimplementer)errortcpudp)ReactorBase_SignalReactorMixin)
IHalfCloseableDescriptorIReactorFDSetIReactorMulticastIReactorProcessIReactorSocketIReactorSSLIReactorTCPIReactorUDPIReactorUNIXIReactorUNIXDatagram)CONNECTION_DONECONNECTION_LOST)failurelogutil)platformplatformTypezHandler has no fileno methodzFile descriptor lost)tls)sslposixF)_signalsfdescprocessunixTc                   @   s8   e Zd ZdZedZdd Zdd Zdej	fdd	Z
d
S )_IWakeraQ  
    Interface to wake up the event loop based on the self-pipe trick.

    The U{I{self-pipe trick}<http://cr.yp.to/docs/selfpipe.html>}, used to wake
    up the main loop from another thread or a signal handler.
    This is why we have wakeUp together with doRead

    This is used by threads or signals to wake up the event loop.
     c                   C      dS )z:
        Called when the event should be wake up.
        N r'   r'   r'   </usr/lib/python3/dist-packages/twisted/internet/posixbase.pywakeUpW       z_IWaker.wakeUpc                   C   r&   )zC
        Read some data from my connection and discard it.
        Nr'   r'   r'   r'   r(   doRead\   r*   z_IWaker.doReadreasonc                 C   r&   )zB
        Called when connection was closed and the pipes.
        Nr'   )r,   r'   r'   r(   connectionLosta   r*   z_IWaker.connectionLostN)__name__
__module____qualname____doc__r   disconnectedr)   r+   r   Failurer-   r'   r'   r'   r(   r$   J   s    
r$   c                   @   s4   e Zd ZdZdZdd Zdd Zdd Zd	d
 ZdS )_SocketWakerz
    The I{self-pipe trick<http://cr.yp.to/docs/selfpipe.html>}, implemented
    using a pair of sockets rather than pipes (due to the lack of support in
    select() on Windows for pipes), used to wake up the main loop from
    another thread.
    r   c                 C   s   || _ ttjtj}|tjtjd tttjtj}|	d |
d ||  | \}}W d   n1 sAw   Y  |d |d || _|| _| jj| _dS )Initialize.   )z	127.0.0.1r   Nr   )reactorsocketAF_INETSOCK_STREAM
setsockoptIPPROTO_TCPTCP_NODELAY
contextlibclosingbindlistenconnectgetsocknameacceptsetblockingrwfileno)selfr7   clientserverreader
clientaddrr'   r'   r(   __init__r   s"   



z_SocketWaker.__init__c              
   C   sP   zt | jjd W dS  ty' } z|jd tjkr W Y d}~dS d}~ww )zSend a byte to my connection.   xr   N)r   untilConcludesrG   sendOSErrorargserrnoWSAEWOULDBLOCKrI   er'   r'   r(   r)      s   z_SocketWaker.wakeUpc                 C   s(   z	| j d W dS  ty   Y dS w )z4
        Read some data from my connection.
            N)rF   recvrR   rI   r'   r'   r(   r+      s
   z_SocketWaker.doReadc                 C   s   | j   | j  d S N)rF   closerG   )rI   r,   r'   r'   r(   r-      s   
z_SocketWaker.connectionLostN)	r.   r/   r0   r1   r2   rN   r)   r+   r-   r'   r'   r'   r(   r4   g   s    	r4   c                   @   s4   e Zd ZdZdZdZdZdd Zdd Zdd	 Z	dS )
_FDWakera  
    The I{self-pipe trick<http://cr.yp.to/docs/selfpipe.html>}, used to wake
    up the main loop from another thread or a signal handler.

    L{_FDWaker} is a base class for waker implementations based on
    writing to a pipe being monitored by the reactor.

    @ivar o: The file descriptor for the end of the pipe which can be
        written to wake up a reactor monitoring this waker.

    @ivar i: The file descriptor which should be monitored in order to
        be awoken by this waker.
    r   Nc                    sX   | _ t \ _ _t j t j t j t j  fdd _dS )r5   c                      s    j S r[   )ir'   rZ   r'   r(   <lambda>   s    z#_FDWaker.__init__.<locals>.<lambda>N)	r7   ospiper^   or!   setNonBlocking_setCloseOnExecrH   rI   r7   r'   rZ   r(   rN      s   z_FDWaker.__init__c                 C   s   t |  dd  dS )zA
        Read some bytes from the pipe and discard them.
        c                 S   s   d S r[   r'   )datar'   r'   r(   r_      r*   z!_FDWaker.doRead.<locals>.<lambda>N)r!   
readFromFDrH   rZ   r'   r'   r(   r+      s   z_FDWaker.doReadc              	   C   sL   t | dsdS | j| jfD ]}zt| W q ty   Y qw | `| `dS )zClose both ends of my pipe.rb   N)hasattrr^   rb   r`   r\   rR   )rI   r,   fdr'   r'   r(   r-      s   
z_FDWaker.connectionLost)
r.   r/   r0   r1   r2   r^   rb   rN   r+   r-   r'   r'   r'   r(   r]      s    
r]   c                   @      e Zd ZdZdd ZdS )
_UnixWakerz
    This class provides a simple interface to wake up the event loop.

    This is used by threads or signals to wake up the event loop.
    c              
   C   s\   | j dur,zttj| j d W dS  ty+ } z|jtjkr  W Y d}~dS d}~ww dS )z)Write one byte to the pipe, and flush it.NrO   )rb   r   rP   r`   writerR   rT   EAGAINrV   r'   r'   r(   r)      s   
z_UnixWaker.wakeUpN)r.   r/   r0   r1   r)   r'   r'   r'   r(   rk      s    rk   c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )_SIGCHLDWakerz}
    L{_SIGCHLDWaker} can wake up a reactor whenever C{SIGCHLD} is
    received.

    @see: L{twisted.internet._signals}
    c                 C   s   t | | d S r[   )r]   rN   re   r'   r'   r(   rN      s   z_SIGCHLDWaker.__init__c                 C   s   t | j dS )zJ
        Install the handler necessary to make this waker active.
        N)r    installHandlerrb   rZ   r'   r'   r(   install   s   z_SIGCHLDWaker.installc                 C   s   t d dS )zC
        Remove the handler which makes this waker active.
        N)r    ro   rZ   r'   r'   r(   	uninstall   s   z_SIGCHLDWaker.uninstallc                 C   s   t |  t  dS )a  
        Having woken up the reactor in response to receipt of
        C{SIGCHLD}, reap the process which exited.

        This is called whenever the reactor notices the waker pipe is
        writeable, which happens soon after any call to the C{wakeUp}
        method.
        N)r]   r+   r"   reapAllProcessesrZ   r'   r'   r(   r+      s   
	z_SIGCHLDWaker.doReadN)r.   r/   r0   r1   rN   rp   rr   r+   r'   r'   r'   r(   rn      s    rn   c                   @   s<   e Zd ZdZejee ejee ifddZ	dS )_DisconnectSelectableMixinz>
    Mixin providing the C{_disconnectSelectable} method.
    c                 C   sx   |  | ||j}|r-|r!|jtjkr!t|r!|| dS | | |	| dS | | |	t
| dS )z
        Utility function for disconnecting a selectable.

        Supports half-close notification, isRead should be boolean indicating
        whether error resulted from doRead().
        N)removeReaderget	__class__r   ConnectionDoner   
providedByreadConnectionLostremoveWriterr-   r   r3   )rI   
selectablewhyisReadfaildictfr'   r'   r(   _disconnectSelectable  s   


z0_DisconnectSelectableMixin._disconnectSelectableN)
r.   r/   r0   r1   r   rx   r   r3   ConnectionLostr   r'   r'   r'   r(   rt     s    
rt   c                   @   s  e Zd ZU dZeZdd ZdZdd Zdd Z	d	i dddd
dfddZ
d0ddZ	d1ddZd2ddZd3ddZd4ddZ	d5ddZerUejejejfZeej ed< nejejfZd d! Zd"d# Z	d6d$d%Zd7d&d'Zd8d(d)Z	d8d*d+Zd7d,d-Z d.d/ Z!dS )9PosixReactorBasez
    A basis for reactors that use file descriptors.

    @ivar _childWaker: L{None} or a reference to the L{_SIGCHLDWaker}
        which is used to properly notice child process termination.
    c                 C   s4   | j s| | | _ | j| j  | | j  dS dS )z
        Install a `waker' to allow threads and signals to wake up the IO thread.

        We use the self-pipe trick (http://cr.yp.to/docs/selfpipe.html) to wake
        the reactor. On Windows we use a pair of sockets.
        N)waker_wakerFactory_internalReadersadd	addReaderrZ   r'   r'   r(   installWaker?  s
   zPosixReactorBase.installWakerNc                 C   s^   t |  tdkr+tr-| js t| | _| j| j | | j | j	  t
  dS dS dS )z
        Extend the basic signal handling logic to also support
        handling SIGCHLD to know when to try to reap child processes.
        r   N)r   _handleSignalsr   processEnabled_childWakerrn   r   r   r   rp   r"   rs   rZ   r'   r'   r(   r   M  s   


zPosixReactorBase._handleSignalsc                 C   s   | j r
| j   dS dS )a  
        If a child waker was created and installed, uninstall it now.

        Since this disables reactor functionality and is only called
        when the reactor is stopping, it doesn't provide any directly
        useful functionality, but the cleanup of reactor-related
        process-global state that it does helps in unit tests
        involving multiple reactors and is generally just a nice
        thing.
        N)r   rr   rZ   r'   r'   r(   _uninstallHandler`  s   z"PosixReactorBase._uninstallHandlerr'   r   c
                 C   s   t dkr(|r|	d urtdt| ||||||||	S t| ||||||||		S t dkr]|d ur4td|d ur<td|rBtd|	rHtdtrYdd	lm}
 |
| |||||S td
td)Nr   z1Using childFDs is not supported with usePTY=True.win32z,Setting UID is unsupported on this platform.z,Setting GID is unsupported on this platform.z1The usePTY parameter is not supported on Windows.z1Customizing childFDs is not supported on Windows.r   )Processz:spawnProcess not available since pywin32 is not installed.z0spawnProcess only available on Windows or POSIX.)r   
ValueErrorr"   
PTYProcessr   win32processtwisted.internet._dumbwin32procNotImplementedError)rI   processProtocol
executablerS   envpathuidgidusePTYchildFDsr   r'   r'   r(   spawnProcesss  sL   zPosixReactorBase.spawnProcessr%   rX   c                 C      t ||||| }|  |S )zConnects a given L{DatagramProtocol} to the given numeric UDP port.

        @returns: object conforming to L{IListeningPort}.
        )r	   PortstartListening)rI   portprotocol	interfacemaxPacketSizepr'   r'   r(   	listenUDP  s   zPosixReactorBase.listenUDPFc                 C   s    t ||||| |}|  |S )zConnects a given DatagramProtocol to the given numeric UDP port.

        EXPERIMENTAL.

        @returns: object conforming to IListeningPort.
        )r	   MulticastPortr   )rI   r   r   r   r   listenMultipler   r'   r'   r(   listenMulticast  s
   	z PosixReactorBase.listenMulticast   c                 C   s*   t sJ dt|||| |}|  |S NUNIX support is not present)unixEnabledr#   	ConnectorrB   )rI   addressfactorytimeoutcheckPIDcr'   r'   r(   connectUNIX  s   zPosixReactorBase.connectUNIX2     c                 C   s,   t sJ dt||||| |}|  |S r   )r   r#   r   r   )rI   r   r   backlogmodewantPIDr   r'   r'   r(   
listenUNIX  s   zPosixReactorBase.listenUNIXc                 C   s*   t sJ dt||||| }|  |S )z
        Connects a given L{DatagramProtocol} to the given path.

        EXPERIMENTAL.

        @returns: object conforming to L{IListeningPort}.
        r   )r   r#   DatagramPortr   )rI   r   r   r   r   r   r'   r'   r(   listenUNIXDatagram  s   z#PosixReactorBase.listenUNIXDatagramc                 C   s,   t sJ dt|||||| }|  |S )zd
        Connects a L{ConnectedDatagramProtocol} instance to a path.

        EXPERIMENTAL.
        r   )r   r#   ConnectedDatagramPortr   )rI   r   r   r   r   bindAddressr   r'   r'   r(   connectUNIXDatagram  s   z$PosixReactorBase.connectUNIXDatagram_supportedAddressFamiliesc                 C   sR   || j vr
t|tr|tjkrtj| ||}n	t	j| |||}|
  |S )a0  
        Create a new L{IListeningPort} from an already-initialized socket.

        This just dispatches to a suitable port implementation (eg from
        L{IReactorTCP}, etc) based on the specified C{addressFamily}.

        @see: L{twisted.internet.interfaces.IReactorSocket.adoptStreamPort}
        )r   r   UnsupportedAddressFamilyr   r8   AF_UNIXr#   r   _fromListeningDescriptorr   r   )rI   fileDescriptoraddressFamilyr   r   r'   r'   r(   adoptStreamPort  s   
	
z PosixReactorBase.adoptStreamPortc                 C   sD   || j vr
t|tr|tjkrtj||| S t	j|||| S )zg
        @see:
            L{twisted.internet.interfaces.IReactorSocket.adoptStreamConnection}
        )
r   r   r   r   r8   r   r#   Server_fromConnectedSocketr   )rI   r   r   r   r'   r'   r(   adoptStreamConnection  s   

z&PosixReactorBase.adoptStreamConnectionc                 C   s<   |t jt jfvrt|tjj| ||||d}|  |S )N)r   )	r8   r9   AF_INET6r   r   r	   r   r   r   )rI   r   r   r   r   r   r'   r'   r(   adoptDatagramPort%  s   

z"PosixReactorBase.adoptDatagramPortc                 C   r   r[   )r   r   r   )rI   r   r   r   r   r   r'   r'   r(   	listenTCP3  s   zPosixReactorBase.listenTCPc                 C   s    t |||||| }|  |S r[   )r   r   rB   )rI   hostr   r   r   r   r   r'   r'   r(   
connectTCP8  s   zPosixReactorBase.connectTCPc           	   	   C   sZ   t d urt |d|}| |||||S td ur)t||||||| }|  |S J d)NTFSSL support is not present)r   TLSMemoryBIOFactoryr   r   r   rB   )	rI   r   r   r   contextFactoryr   r   
tlsFactoryr   r'   r'   r(   
connectSSL?  s   zPosixReactorBase.connectSSLc                 C   s`   t d urt |d|}| ||||}d|_|S td ur,t|||||| }|  |S J d)NFTLSr   )r   r   r   _typer   r   r   )rI   r   r   r   r   r   r   r   r'   r'   r(   	listenSSLN  s   zPosixReactorBase.listenSSLc                 C   sJ   t || j }|D ]}| | q	t |}|D ]}| | qt||B S )ag  
        Remove all readers and writers, and list of removed L{IReadDescriptor}s
        and L{IWriteDescriptor}s.

        Meant for calling from subclasses, to implement removeAll, like::

          def removeAll(self):
              return self._removeAll(self._reads, self._writes)

        where C{self._reads} and C{self._writes} are iterables.
        )setr   ru   r{   list)rI   readerswritersremovedReadersrL   removedWriterswriterr'   r'   r(   
_removeAll[  s   zPosixReactorBase._removeAll)r%   rX   )r%   rX   F)r   r   )r   r   r   )rX   r   )rX   r   N)rX   )r   r%   )r   N)"r.   r/   r0   r1   _Wakerr   r   r   r   r   r   r   r   r   r   r   r   r   r8   r9   r   r   r   r   AddressFamily__annotations__r   r   r   r   r   r   r   r   r'   r'   r'   r(   r   2  sR   
 	

:









r   c                   @   rj   )_PollLikeMixina  
    Mixin for poll-like reactors.

    Subclasses must define the following attributes::

      - _POLL_DISCONNECTED - Bitmask for events indicating a connection was
        lost.
      - _POLL_IN - Bitmask for events indicating there is input to read.
      - _POLL_OUT - Bitmask for events indicating output can be written.

    Must be mixed in to a subclass of PosixReactorBase (for
    _disconnectSelectable).
    c                 C   s   d}d}|| j @ r|| j@ s|| jv rd}t}n:t}n7z#| dkr%t}n|| j@ r0| }d}|s=|| j@ r=|	 }d}W n t
yQ   t d }t  Y nw |r]| ||| dS dS )zg
        fd is available for read or write, do the work and raise errors if
        necessary.
        NFTrq   r6   )_POLL_DISCONNECTED_POLL_IN_readsr   r   rH   _NO_FILEDESCr+   	_POLL_OUTdoWriteBaseExceptionsysexc_infor   errr   )rI   r|   ri   eventr}   inReadr'   r'   r(   _doReadOrWrite  s0   

z_PollLikeMixin._doReadOrWriteN)r.   r/   r0   r1   r   r'   r'   r'   r(   r   r  s    r   c                   @   s|   e Zd ZdZdZdZdZdd Zdd Zd	d
 Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd ZdS )_ContinuousPollinga  
    Schedule reads and writes based on the passage of time, rather than
    notification.

    This is useful for supporting polling filesystem files, which C{epoll(7)}
    does not support.

    The implementation uses L{_PollLikeMixin}, which is a bit hacky, but
    re-implementing and testing the relevant code yet again is unappealing.

    @ivar _reactor: The L{EPollReactor} that is using this instance.

    @ivar _loop: A C{LoopingCall} that drives the polling, or L{None}.

    @ivar _readers: A C{set} of C{FileDescriptor} objects that should be read
        from.

    @ivar _writers: A C{set} of C{FileDescriptor} objects that should be
        written to.
    r6         c                 C   s    || _ d | _t | _t | _d S r[   )_reactor_loopr   _readers_writersre   r'   r'   r(   rN     s   z_ContinuousPolling.__init__c                 C   sr   | j s| jr*| jdu r(ddlm}m} || j| _| j| j_| jj	|dd dS dS | jr7| j
  d| _dS dS )zh
        Start or stop a C{LoopingCall} based on whether there are readers and
        writers.
        Nr   )_EPSILONLoopingCallF)now)r   r   r   twisted.internet.taskr   r   iterater   clockstartstop)rI   r   r   r'   r'   r(   
_checkLoop  s   



z_ContinuousPolling._checkLoopc                 C   sD   t | jD ]
}| ||| j qt | jD ]
}| ||| j qdS )zX
        Call C{doRead} and C{doWrite} on all readers and writers respectively.
        N)r   r   r   r   r   r   )rI   rL   r   r'   r'   r(   r     s
   z_ContinuousPolling.iteratec                 C      | j | |   dS )zU
        Add a C{FileDescriptor} for notification of data available to read.
        N)r   r   r   rI   rL   r'   r'   r(   r        z_ContinuousPolling.addReaderc                 C   r   )zV
        Add a C{FileDescriptor} for notification of data available to write.
        N)r   r   r   rI   r   r'   r'   r(   	addWriter  r  z_ContinuousPolling.addWriterc                 C   2   z| j | W n
 ty   Y dS w |   dS )zY
        Remove a C{FileDescriptor} from notification of data available to read.
        N)r   removeKeyErrorr   r  r'   r'   r(   ru     s   z_ContinuousPolling.removeReaderc                 C   r  )zb
        Remove a C{FileDescriptor} from notification of data available to
        write.
        N)r   r  r  r   r  r'   r'   r(   r{     s   z_ContinuousPolling.removeWriterc                 C   s(   t | j| jB }| j  | j  |S )z1
        Remove all readers and writers.
        )r   r   r   clear)rI   resultr'   r'   r(   	removeAll  s   

z_ContinuousPolling.removeAllc                 C   
   t | jS )z/
        Return a list of the readers.
        )r   r   rZ   r'   r'   r(   
getReaders&     
z_ContinuousPolling.getReadersc                 C   r  )z/
        Return a list of the writers.
        )r   r   rZ   r'   r'   r(   
getWriters,  r  z_ContinuousPolling.getWritersc                 C   
   || j v S )aj  
        Checks if the file descriptor is currently being observed for read
        readiness.

        @param fd: The file descriptor being checked.
        @type fd: L{twisted.internet.abstract.FileDescriptor}
        @return: C{True} if the file descriptor is being observed for read
            readiness, C{False} otherwise.
        @rtype: C{bool}
        )r   rI   ri   r'   r'   r(   	isReading2     
z_ContinuousPolling.isReadingc                 C   r  )al  
        Checks if the file descriptor is currently being observed for write
        readiness.

        @param fd: The file descriptor being checked.
        @type fd: L{twisted.internet.abstract.FileDescriptor}
        @return: C{True} if the file descriptor is being observed for write
            readiness, C{False} otherwise.
        @rtype: C{bool}
        )r   r  r'   r'   r(   	isWriting?  r  z_ContinuousPolling.isWritingN)r.   r/   r0   r1   r   r   r   rN   r   r   r   r  ru   r{   r
  r  r  r  r  r'   r'   r'   r(   r     s"    	
r   fromfd)Gr1   r>   rT   r`   r8   r   typingr   zope.interfacer   r   r   r   twisted.internetr   r   r	   twisted.internet.baser
   r   twisted.internet.interfacesr   r   r   r   r   r   r   r   r   r   twisted.internet.mainr   r   twisted.pythonr   r   r   twisted.python.runtimer   r   ConnectionFdescWentAway
_NO_FILENOr   twisted.protocolsr   _tlsImportErrorr   _sslr   r   r    r!   r"   r#   	isWindowsr   r$   Loggerr4   r]   rk   r   rn   rt   r   r   r   getattr__all__r'   r'   r'   r(   <module>   s   0

30
$
&  AI 



