U
    n5{i(T  ã                   @  sh  d Z ddlmZ ddlZddlZddlmZ ddlmZm	Z	 ddl
mZmZmZ ddl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mZ dd	lmZmZ dd
lm Z  ddl!m"Z"m#Z# ddl$m%Z%m&Z& ddl'm(Z(m)Z)m*Z*m+Z+m,Z, e -d¡Z.zddl/m0Z1 W n e2k
�r   dZ0Y nX e1Z0zddl
m3Z4 W n e2k
�rL   dZ3Y nX e4Z3e&dkZ5dZ6e5�rxddl
m7Z7m8Z8 dZ6e% 9¡ �r®zddl:Z:dZ6W n e2k
�r¬   dZ:Y nX G dd„ dƒZ;e	eeeƒG dd„ de;eƒƒZ<G dd„ dƒZ=e	eƒG dd„ de=e;ƒƒZ>e0dk	�se3dk	�r ee<eƒ e5�r2ee<eeƒ e6�rBee<eƒ e?eddƒdk	�r^ee<eƒ dgZ@dS )z
Posix reactor base class
é    )ÚannotationsN)ÚSequence)ÚclassImplementsÚimplementer)ÚerrorÚtcpÚudp)ÚReactorBase)Ú
IConnectorÚIHalfCloseableDescriptorÚIReactorFDSetÚIReactorMulticastÚIReactorProcessÚIReactorSocketÚIReactorSSLÚIReactorTCPÚIReactorUDPÚIReactorUNIXÚIReactorUNIXDatagram)ÚCONNECTION_DONEÚCONNECTION_LOST)ÚClientFactory)ÚfailureÚlog)ÚplatformÚplatformTypeé   )ÚSignalHandlingÚ_ChildSignalHandlingÚ_IWakerÚ_MultiSignalHandlingÚ_WakerzFile descriptor lost)Útls)ÚsslÚposixF)ÚprocessÚunixTc                   @  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  st   |   |¡ | |j¡}|rV|r@|jtjkr@t |¡r@| |¡ qp|  |¡ | 	|¡ n|  |¡ | 	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   Z
providedByZreadConnectionLostÚremoveWriterZconnectionLostr   ÚFailure)ÚselfÚ
selectableÚwhyZisReadZfaildictÚf© r2   ú>/tmp/pip-unpacked-wheel-mnhg7r0q/twisted/internet/posixbase.pyÚ_disconnectSelectableU   s    
ÿ
þý

z0_DisconnectSelectableMixin._disconnectSelectableN)
Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r+   r   r-   ZConnectionLostr4   r2   r2   r2   r3   r'   P   s   
  þûr'   c                      s  e Zd ZU dZdZddœdd„Zdd„ Zd	dœ‡ fd
d„Zdi dddddfdd„Zd<dd„Z	d=dd„Z
d>dd„Zd?dd„Zd@dd„ZdAd d!„Zer¬ejejejfZd"ed#< nejejfZd$d%„ Zd&d'„ ZdBd(d)„ZdCd*d+„ZdDd-d.d/d0d1d2d3œd4d5„ZdEd6d7„ZdFd8d9„Zd:d;„ Z‡  ZS )GÚ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.
    Nr   )Úreturnc                 C  s   t ƒ S ©N)r!   ©r.   r2   r2   r3   Ú_wakerFactoryƒ   s    zPosixReactorBase._wakerFactoryc                 C  s.   | j s*|  ¡ | _ | j | j ¡ |  | j ¡ 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)Zwakerr=   Ú_internalReadersÚaddÚ	addReaderr<   r2   r2   r3   ÚinstallWaker†   s    
zPosixReactorBase.installWakerr   c                   s,   t ƒ  ¡ }tdkr(t|t| j| jƒfƒS |S )zj
        Customize reactor signal handling to support child processes on POSIX
        platforms.
        r$   )ÚsuperÚ_signalsFactoryr   r    r   Z_addInternalReaderZ_removeInternalReader)r.   ZbaseHandling©r*   r2   r3   rC   ’   s    
þüÿz PosixReactorBase._signalsFactoryr2   r   c
                 C  sÊ   t dkrR|r6|	d k	rtdƒ‚t | ||||||||¡	S t | ||||||||	¡	S ntt dkr¾|d k	rjtdƒ‚|d k	rztdƒ‚|r†tdƒ‚|	r’tdƒ‚tr´dd	lm}
 |
| |||||ƒS td
ƒ‚ntdƒ‚d S )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%   Z
PTYProcessrF   Úwin32processZtwisted.internet._dumbwin32procÚNotImplementedError)r.   ZprocessProtocolÚ
executableÚargsÚenvÚpathÚuidÚgidZusePTYZchildFDsrF   r2   r2   r3   ÚspawnProcess¬   s\    ÿ        ÿ÷ÿÿzPosixReactorBase.spawnProcessÚ é    c                 C  s   t  ||||| ¡}| ¡  |S )z‡Connects a given L{DatagramProtocol} to the given numeric UDP port.

        @returns: object conforming to L{IListeningPort}.
        )r   ÚPortÚstartListening)r.   ÚportÚprotocolÚ	interfaceÚmaxPacketSizeÚpr2   r2   r3   Ú	listenUDPæ   s    zPosixReactorBase.listenUDPFc                 C  s    t  ||||| |¡}| ¡  |S )z˜Connects a given DatagramProtocol to the given numeric UDP port.

        EXPERIMENTAL.

        @returns: object conforming to IListeningPort.
        )r   ZMulticastPortrT   )r.   rU   rV   rW   rX   ZlistenMultiplerY   r2   r2   r3   ÚlistenMulticastñ   s    	     ÿz PosixReactorBase.listenMulticasté   c                 C  s*   t stdƒ‚t |||| |¡}| ¡  |S ©NúUNIX support is not present)ÚunixEnabledÚAssertionErrorr&   Ú	ConnectorÚconnect)r.   ÚaddressÚfactoryÚtimeoutZcheckPIDÚcr2   r2   r3   ÚconnectUNIX  s    zPosixReactorBase.connectUNIXé2   é¶  c                 C  s,   t stdƒ‚t ||||| |¡}| ¡  |S r]   )r_   r`   r&   rS   rT   )r.   rc   rd   ÚbacklogÚmodeZwantPIDrY   r2   r2   r3   Ú
listenUNIX  s    zPosixReactorBase.listenUNIXc                 C  s*   t stdƒ‚t ||||| ¡}| ¡  |S )z›
        Connects a given L{DatagramProtocol} to the given path.

        EXPERIMENTAL.

        @returns: object conforming to L{IListeningPort}.
        r^   )r_   r`   r&   ZDatagramPortrT   )r.   rc   rV   rX   rk   rY   r2   r2   r3   ÚlistenUNIXDatagram  s    z#PosixReactorBase.listenUNIXDatagramc                 C  s,   t stdƒ‚t |||||| ¡}| ¡  |S )zd
        Connects a L{ConnectedDatagramProtocol} instance to a path.

        EXPERIMENTAL.
        r^   )r_   r`   r&   ZConnectedDatagramPortrT   )r.   rc   rV   rX   rk   ÚbindAddressrY   r2   r2   r3   ÚconnectUNIXDatagram  s         ÿz$PosixReactorBase.connectUNIXDatagramzSequence[socket.AddressFamily]Ú_supportedAddressFamiliesc                 C  sR   || j krt |¡‚tr4|tjkr4t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}
        )rp   r   ÚUnsupportedAddressFamilyr_   ÚsocketÚAF_UNIXr&   rS   Ú_fromListeningDescriptorr   rT   )r.   ÚfileDescriptorÚaddressFamilyrd   rY   r2   r2   r3   ÚadoptStreamPort:  s    	

   ÿz PosixReactorBase.adoptStreamPortc                 C  sH   || j krt |¡‚tr2|tjkr2tj ||| ¡S t	j |||| ¡S dS )zg
        @see:
            L{twisted.internet.interfaces.IReactorSocket.adoptStreamConnection}
        N)
rp   r   rq   r_   rr   rs   r&   ÚServerZ_fromConnectedSocketr   )r.   ru   rv   rd   r2   r2   r3   ÚadoptStreamConnectionO  s    

   ÿz&PosixReactorBase.adoptStreamConnectionc                 C  s<   |t jt jfkrt |¡‚tjj| ||||d�}| ¡  |S )N)rX   )	rr   ÚAF_INETÚAF_INET6r   rq   r   rS   rt   rT   )r.   ru   rv   rV   rX   rY   r2   r2   r3   ÚadoptDatagramPort^  s    
    ÿz"PosixReactorBase.adoptDatagramPortc                 C  s   t  ||||| ¡}| ¡  |S r;   )r   rS   rT   )r.   rU   rd   rj   rW   rY   r2   r2   r3   Ú	listenTCPl  s    zPosixReactorBase.listenTCPç      >@ÚstrÚintz'ClientFactory'Úfloatztuple[str, int] | Noner
   )ÚhostrU   rd   re   rn   r:   c                 C  s    t  |||||| ¡}| ¡  |S r;   )r   ra   rb   )r.   r‚   rU   rd   re   rn   rf   r2   r2   r3   Ú
connectTCPq  s    zPosixReactorBase.connectTCPc           	   	   C  sb   t d k	r(t  |d|¡}|  |||||¡S td k	rRt ||||||| ¡}| ¡  |S ds^tdƒ‚d S )NTFúSSL support is not present)r"   ÚTLSMemoryBIOFactoryrƒ   r#   ra   rb   r`   )	r.   r‚   rU   rd   ÚcontextFactoryre   rn   Ú
tlsFactoryrf   r2   r2   r3   Ú
connectSSL  s           ÿzPosixReactorBase.connectSSLc                 C  sh   t d k	r0t  |d|¡}|  ||||¡}d|_|S td k	rXt |||||| ¡}| ¡  |S dsdtdƒ‚d S )NFZTLSr„   )r"   r…   r}   Ú_typer#   rS   rT   r`   )r.   rU   rd   r†   rj   rW   r‡   rY   r2   r2   r3   Ú	listenSSLŽ  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>   r(   r,   Úlist)r.   ZreadersZwritersZremovedReadersÚreaderZremovedWritersÚwriterr2   r2   r3   Ú
_removeAll›  s    zPosixReactorBase._removeAll)rQ   rR   )rQ   rR   F)r\   r   )rh   ri   r   )rR   ri   )rR   ri   N)rR   )rh   rQ   )r~   N)r\   N)rh   rQ   )r5   r6   r7   r8   Z_childWakerr=   rA   rC   rP   rZ   r[   rg   rl   rm   ro   r_   rr   rz   r{   rs   rp   Ú__annotations__rw   ry   r|   r}   rƒ   rˆ   rŠ   r�   Ú__classcell__r2   r2   rD   r3   r9   v   s\   
ö
:
     ÿ



     ÿ
ýþ ÿ


  ú   ÿ

r9   c                   @  s   e Zd ZdZdd„ ZdS )Ú_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 @ r6|| j@ s6|| jkr0d}t}q¦t}npzF| ¡ dkrJt}n0|| j@ r`| ¡ }d}|sz|| j@ rz| 	¡ }d}W n( t
k
r¤   t ¡ d }t ¡  Y nX |r¸|  |||¡ dS )zg
        fd is available for read or write, do the work and raise errors if
        necessary.
        NFTéÿÿÿÿr   )Ú_POLL_DISCONNECTEDÚ_POLL_INZ_readsr   r   ÚfilenoÚ_NO_FILEDESCZdoReadÚ	_POLL_OUTZdoWriteÚBaseExceptionÚsysÚexc_infor   Úerrr4   )r.   r/   ÚfdÚeventr0   ZinReadr2   r2   r3   Ú_doReadOrWriteÁ  s*    

z_PollLikeMixin._doReadOrWriteN)r5   r6   r7   r8   rŸ   r2   r2   r2   r3   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.
    r   é   é   c                 C  s    || _ d | _tƒ | _tƒ | _d S r;   )Ú_reactorÚ_loopr‹   Ú_readersÚ_writers)r.   Zreactorr2   r2   r3   Ú__init__  s    z_ContinuousPolling.__init__c                 C  sh   | j s| jrN| jdkrdddlm}m} || jƒ| _| j| j_| jj	|dd� n| jrd| j 
¡  d| _dS )zh
        Start or stop a C{LoopingCall} based on whether there are readers and
        writers.
        Nr   )Ú_EPSILONÚLoopingCallF)Únow)r¥   r¦   r¤   Ztwisted.internet.taskr¨   r©   Úiterater£   ZclockÚstartÚstop)r.   r¨   r©   r2   r2   r3   Ú
_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˜   )r.   r�   rŽ   r2   r2   r3   r«   /  s    z_ContinuousPolling.iteratec                 C  s   | j  |¡ |  ¡  dS )zU
        Add a C{FileDescriptor} for notification of data available to read.
        N)r¥   r?   r®   ©r.   r�   r2   r2   r3   r@   8  s    z_ContinuousPolling.addReaderc                 C  s   | j  |¡ |  ¡  dS )zV
        Add a C{FileDescriptor} for notification of data available to write.
        N)r¦   r?   r®   ©r.   rŽ   r2   r2   r3   Ú	addWriter?  s    z_ContinuousPolling.addWriterc                 C  s4   z| j  |¡ W n tk
r&   Y dS X |  ¡  dS )zY
        Remove a C{FileDescriptor} from notification of data available to read.
        N)r¥   ÚremoveÚKeyErrorr®   r¯   r2   r2   r3   r(   F  s
    z_ContinuousPolling.removeReaderc                 C  s4   z| j  |¡ W n tk
r&   Y dS X |  ¡  dS )zb
        Remove a C{FileDescriptor} from notification of data available to
        write.
        N)r¦   r²   r³   r®   r°   r2   r2   r3   r,   P  s
    z_ContinuousPolling.removeWriterc                 C  s(   t | j| jB ƒ}| j ¡  | j ¡  |S )z1
        Remove all readers and writers.
        )rŒ   r¥   r¦   Úclear)r.   Úresultr2   r2   r3   Ú	removeAll[  s    

z_ContinuousPolling.removeAllc                 C  s
   t | jƒS )z/
        Return a list of the readers.
        )rŒ   r¥   r<   r2   r2   r3   Ú
getReadersf  s    z_ContinuousPolling.getReadersc                 C  s
   t | jƒS )z/
        Return a list of the writers.
        )rŒ   r¦   r<   r2   r2   r3   Ú
getWritersl  s    z_ContinuousPolling.getWritersc                 C  s
   || j k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¥   ©r.   r�   r2   r2   r3   Ú	isReadingr  s    z_ContinuousPolling.isReadingc                 C  s
   || j kS )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¹   r2   r2   r3   Ú	isWriting  s    z_ContinuousPolling.isWritingN)r5   r6   r7   r8   r”   r•   r˜   r§   r®   r«   r@   r±   r(   r,   r¶   r·   r¸   rº   r»   r2   r2   r2   r3   r    û  s    	
r    Úfromfd)Ar8   Ú
__future__r   rr   rš   Útypingr   Zzope.interfacer   r   Ztwisted.internetr   r   r   Ztwisted.internet.baser	   Ztwisted.internet.interfacesr
   r   r   r   r   r   r   r   r   r   r   Ztwisted.internet.mainr   r   Ztwisted.internet.protocolr   Ztwisted.pythonr   r   Ztwisted.python.runtimer   r   Z_signalsr   r   r   r    r!   ZConnectionFdescWentAwayr—   Ztwisted.protocolsr"   Z_tlsÚImportErrorr#   Ú_sslr_   ZprocessEnabledr%   r&   Z	isWindowsrH   r'   r9   r’   r    ÚgetattrÚ__all__r2   r2   r2   r3   Ú<module>   sj   4	




&
  =I 


