U
    �AcjkO  ã                   @  sò  d Z ddlmZ 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mZmZ ddl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!m"Z"m#Z#m$Z$ ddl%m&Z& ddl'm(Z( ddl)m*Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1 ddl2m3Z3m4Z4m5Z5 zddl6m7Z8 W n e9k
�r:   dZ:Y nX e8Z:e�rRddl;m<Z< e ej=e"ej>iZ?ee&ej@ejAƒG dd„ dejBe1e,ƒƒZCe:dk	�ržeeCejDƒ G dd„ de-e.eCƒZEG dd„ deCƒZFG dd„ de+ƒZ*eejGƒG dd„ de1eƒƒZHdS )z
TCP support for IOCP reactor
é    )ÚannotationsN)ÚTYPE_CHECKINGÚOptionalÚUnion)ÚclassImplementsÚimplementer)ÚaddressÚdeferÚerrorÚ
interfacesÚmain)Ú	_LogOwnerÚisIPv6Address)ÚIPv4AddressÚIPv6Address)Ú	IProtocol)ÚabstractÚiocpsupport)ÚERROR_CONNECTION_REFUSEDÚERROR_IO_PENDINGÚERROR_NETWORK_UNREACHABLEÚSO_UPDATE_ACCEPT_CONTEXTÚSO_UPDATE_CONNECT_CONTEXT)ÚIReadWriteHandle)ÚProtocol)Ú	ConnectorÚ_AbortingMixinÚ_BaseBaseClientÚ_BaseTCPClientÚ_getsocknameÚ_resolveIPv6Ú_SocketCloser)ÚfailureÚlogÚreflect)ÚstartTLS)ÚIOCPReactorc                   @  sÊ   e Zd ZdZdZd/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d„ Zedk	rŒd0dd „Zd!d"„ Zd#d$„ Zd1d%d&„Zd'd(„ Zd)d*„ Zd+d,„ Zd-d.„ ZdS )2Ú
ConnectionzÞ
    @ivar TLS: C{False} to indicate the connection is in normal TCP mode,
        C{True} to indicate that TLS has been started and that operations must
        be routed through the L{TLSMemoryBIOProtocol} instance.
    FNc                 C  s&   t j | |¡ || _|j| _|| _d S ©N)r   Ú
FileHandleÚ__init__ÚsocketÚfilenoÚgetFileHandleÚprotocol)ÚselfÚsockÚprotoÚreactor© r3   úD/tmp/pip-unpacked-wheel-nrvc_22y/twisted/internet/iocpreactor/tcp.pyr*   F   s    zConnection.__init__c                 C  s   | j S r(   )r+   ©r/   r3   r3   r4   Ú	getHandleL   s    zConnection.getHandlec                 C  s@   t |tƒrn$t |tƒr t|ƒ}ntdt|ƒ ƒ‚| j |¡ dS )z`
        @param rbuffer: Data received.
        @type rbuffer: L{bytes} or L{bytearray}
        z%data must be bytes or bytearray, not N)Ú
isinstanceÚbytesÚ	bytearrayÚ	TypeErrorÚtyper.   ÚdataReceived)r/   Zrbufferr3   r3   r4   r<   O   s    


zConnection.dataReceivedc                 C  s   t  |  ¡ ||¡S r(   )Ú_iocpÚrecvr-   )r/   ZbufflistÚevtr3   r3   r4   ÚreadFromHandle^   s    zConnection.readFromHandlec                 C  s(   t |ƒ}t |  ¡ |d| j…  ¡ |¡S )zŽ
        Send C{buff} to current file handle using C{_iocp.send}. The buffer
        sent is limited to a size of C{self.SEND_LIMIT}.
        r   )Ú
memoryviewr=   Úsendr-   Z
SEND_LIMITÚtobytes)r/   Úbuffr?   Z	writeViewr3   r3   r4   ÚwriteToHandlea   s      ÿzConnection.writeToHandlec                 C  sx   z| j  d¡ W n tk
r$   Y nX t | jd ¡}|rtz| ¡  W n. tk
rr   t 	¡ }t
 ¡  |  |¡ Y nX d S )Né   )r+   ÚshutdownÚOSErrorr   ÚIHalfCloseableProtocolr.   ZwriteConnectionLostÚBaseExceptionr"   ÚFailurer#   ÚerrÚconnectionLost)r/   ÚpÚfr3   r3   r4   Ú_closeWriteConnectionk   s    z Connection._closeWriteConnectionc                 C  sZ   t  | jd ¡}|rLz| ¡  W qV tk
rH   t ¡  |  t 	¡ ¡ Y qVX n
|  |¡ d S r(   )
r   rI   r.   ÚreadConnectionLostrJ   r#   rL   rM   r"   rK   )r/   ÚreasonrN   r3   r3   r4   rQ   y   s    zConnection.readConnectionLostc                 C  sX   | j r
d S tj | |¡ |d kp,| tj¡ }|  |¡ | j}| `| `	| `
| |¡ d S r(   )Údisconnectedr   r)   rM   Úcheckr
   ZConnectionAbortedÚ_closeSocketr.   r+   r-   )r/   rR   ZisCleanr.   r3   r3   r4   rM   „   s    
zConnection.connectionLostc                 C  s   | j S )zN
        Return the prefix to log with when I own the logging thread.
        )Úlogstrr5   r3   r3   r4   Ú	logPrefix�   s    zConnection.logPrefixc                 C  s   t | j tjtj¡ƒS r(   )Úboolr+   Ú
getsockoptÚIPPROTO_TCPÚTCP_NODELAYr5   r3   r3   r4   ÚgetTcpNoDelay–   s    zConnection.getTcpNoDelayc                 C  s   | j  t jt j|¡ d S r(   )r+   Ú
setsockoptrZ   r[   ©r/   Zenabledr3   r3   r4   ÚsetTcpNoDelay™   s    zConnection.setTcpNoDelayc                 C  s   t | j tjtj¡ƒS r(   )rX   r+   rY   Ú
SOL_SOCKETÚSO_KEEPALIVEr5   r3   r3   r4   ÚgetTcpKeepAliveœ   s    zConnection.getTcpKeepAlivec                 C  s   | j  t jt j|¡ d S r(   )r+   r]   r`   ra   r^   r3   r3   r4   ÚsetTcpKeepAliveŸ   s    zConnection.setTcpKeepAliveTc                 C  s   t | ||tjƒ dS )z9
            @see: L{ITLSTransport.startTLS}
            N)Ú	_startTLSr   r)   )r/   ZcontextFactoryÚnormalr3   r3   r4   r%   ¤   s    zConnection.startTLSc                 C  s0   | j r
dS | jr| j |¡ ntj | |¡ dS )zò
        Write some data, either directly to the underlying handle or, if TLS
        has been started, to the L{TLSMemoryBIOProtocol} for it to encrypt and
        send.

        @see: L{twisted.internet.interfaces.ITransport.write}
        N)rS   ÚTLSr.   Úwriter   r)   )r/   Údatar3   r3   r4   rg   ª   s
    zConnection.writec                 C  s0   | j r
dS | jr| j |¡ ntj | |¡ dS )zú
        Write some data, either directly to the underlying handle or, if TLS
        has been started, to the L{TLSMemoryBIOProtocol} for it to encrypt and
        send.

        @see: L{twisted.internet.interfaces.ITransport.writeSequence}
        N)rS   rf   r.   ÚwriteSequencer   r)   )r/   Ziovecr3   r3   r4   ri   ¹   s
    zConnection.writeSequencec                 C  s0   | j r| jr,| js,| j ¡  ntj | |¡ dS )z®
        Close the underlying handle or, if TLS has been started, first shut it
        down.

        @see: L{twisted.internet.interfaces.ITransport.loseConnection}
        N)rf   Ú	connectedÚdisconnectingr.   ÚloseConnectionr   r)   )r/   rR   r3   r3   r4   rl   È   s    zConnection.loseConnectionc                 C  s*   | j r| j ||¡ ntj | ||¡ dS )zc
        Register a producer.

        If TLS is enabled, the TLS connection handles this.
        N)rf   r.   ÚregisterProducerr   r)   )r/   ZproducerZ	streamingr3   r3   r4   rm   Õ   s    zConnection.registerProducerc                 C  s"   | j r| j ¡  ntj | ¡ dS )ze
        Unregister a producer.

        If TLS is enabled, the TLS connection handles this.
        N)rf   r.   ÚunregisterProducerr   r)   r5   r3   r3   r4   rn   ä   s    zConnection.unregisterProducerc                 C  s   d S r(   r3   r5   r3   r3   r4   ÚgetHostï   s    zConnection.getHostc                 C  s   d S r(   r3   r5   r3   r3   r4   ÚgetPeeró   s    zConnection.getPeer)N)T)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rf   r*   r6   r<   r@   rE   rP   rQ   rM   rW   r\   r_   rb   rc   rd   r%   rg   ri   rl   rm   rn   ro   rp   r3   r3   r3   r4   r'   <   s0   



r'   c                   @  sT   e Zd ZdZejZejZdZ	e
Zdd„ Zdd„ Zdd„ Zd	d
„ Zdd„ Zdd„ ZdS )ÚClientzº
    @ivar _tlsClientDefault: Always C{True}, indicating that this is a client
        connection, and by default when TLS is negotiated this class will act as
        a TLS client.
    Tc                 C  s*   |d krd}|| _ t | |||||¡ d S )N)Ú r   )r2   r   r*   )r/   ÚhostÚportÚbindAddressÚ	connectorr2   r3   r3   r4   r*   	  s    zClient.__init__c                 C  s   | j  | j| j¡S )zd
        Create a socket registered with the IOCP reactor.

        @see: L{_BaseTCPClient}
        )r2   ÚcreateSocketÚaddressFamilyÚ
socketTyper5   r3   r3   r4   ÚcreateInternetSocket  s    zClient.createInternetSocketc                 C  s   | ` | `dS )z–
        Clean up potentially circular references to the socket and to its
        C{getFileHandle} method.

        @see: L{_BaseBaseClient}
        N)r+   r-   r5   r3   r3   r4   Ú_collectSocketDetails  s    zClient._collectSocketDetailsc                 C  s   | j  | ¡ dS )z^
        Remove the active handle from the reactor.

        @see: L{_BaseBaseClient}
        N)r2   ÚremoveActiveHandler5   r3   r3   r4   Ú_stopReadingAndWriting!  s    zClient._stopReadingAndWritingc              	   C  s²   |r0t  ||¡}|  t |tj |d¡f¡¡ n~| j tj	t
t d| j ¡ ¡¡ | j |  ¡ ¡| _d| _|  | j¡}|d | _| jd krštƒ | _|  ¡  n| j | ¡ |  ¡  d S )NzUnknown errorÚPTz,client)ÚconnectExErrorsÚgetZfailIfNotConnectedr
   ZgetConnectErrorÚerrnoÚ	errorcoder+   r]   r`   r   ÚstructÚpackr,   rz   ÚbuildProtocolrp   r.   rj   Ú_getLogPrefixrV   r   rl   ÚmakeConnectionÚstartReading)r/   Úrcrh   r?   rW   r3   r3   r4   Ú	cbConnect)  s&    ÿý


zClient.cbConnectc                 C  sf   t | dƒsd S tjst‚| j | ¡ t | j| ¡}t | j	 
¡ | j|¡}|rb|tkrb|  |d|¡ d S )Nrz   r   )Úhasattrr=   Zhave_connectexÚAssertionErrorr2   ÚaddActiveHandleÚEventrŽ   Úconnectr+   r,   ZrealAddressr   )r/   r?   r�   r3   r3   r4   Ú	doConnectG  s    

zClient.doConnectN)rq   rr   rs   rt   r+   ÚAF_INETr|   ÚSOCK_STREAMr}   Ú_tlsClientDefaultr'   Z_commonConnectionr*   r~   r   r�   rŽ   r”   r3   r3   r3   r4   ru   ü   s   	ru   c                   @  sJ   e Zd ZdZdZdddddddœd	d
„Zddœdd„Zdd„ Zdd„ ZdS )ÚServeraV  
    Serverside socket-stream connection class.

    I am a serverside network connection transport; a socket which came from an
    accept() on a server.

    @ivar _tlsClientDefault: Always C{False}, indicating that this is a server
        connection, and by default when TLS is negotiated this class will act as
        a TLS server.
    Fzsocket.socketr   zUnion[IPv4Address, IPv6Address]Úintr&   )r0   r.   Ú
clientAddrÚ
serverAddrÚ	sessionnor2   c                 C  sv   t  | |||¡ || _|| _|| _|  | j¡}|› d|› d| jj› �| _d 	| jj
j| j| jj¡| _d| _|  ¡  dS )a  
        Server(sock, protocol, client, server, sessionno)

        Initialize me with a socket, a protocol, a descriptor for my peer (a
        tuple of host, port describing the other end of the connection), an
        instance of Port, and a session number.
        ú,z<{} #{} on {}>TN)r'   r*   r›   rš   rœ   rŠ   r.   rw   rV   ÚformatÚ	__class__rq   rx   Úrepstrrj   rŒ   )r/   r0   r.   rš   r›   rœ   r2   rW   r3   r3   r4   r*   c  s    ýzServer.__init__Ústr©Úreturnc                 C  s   | j S )z=
        A string representation of this connection.
        )r    r5   r3   r3   r4   Ú__repr__�  s    zServer.__repr__c                 C  s   | j S )zW
        Returns an IPv4Address.

        This indicates the server's address.
        )r›   r5   r3   r3   r4   ro   ‡  s    zServer.getHostc                 C  s   | j S )zW
        Returns an IPv4Address.

        This indicates the client's address.
        )rš   r5   r3   r3   r4   rp   �  s    zServer.getPeerN)	rq   rr   rs   rt   r—   r*   r¤   ro   rp   r3   r3   r3   r4   r˜   U  s   r˜   c                   @  s   e Zd Zdd„ ZdS )r   c                 C  s   t | j| j| j| | jƒS r(   )ru   rw   rx   ry   r2   r5   r3   r3   r4   Ú_makeTransport™  s    zConnector._makeTransportN)rq   rr   rs   r¥   r3   r3   r3   r4   r   ˜  s   r   c                   @  s°   e Zd ZU dZdZdZejZej	Z
ejZdZdZded< dZd!d	d
„Zddœdd„Zdd„ Ze ej¡fdd„ZeZdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Z dd „ Z!dS )"ÚPortFr   NzOptional[int]Ú_realPortNumberÚTCPé2   rv   c                 C  s:   || _ || _|| _|| _|| _t|ƒr6tj| _t	j
| _d S r(   )rx   ÚfactoryÚbacklogÚ	interfacer2   r   r+   ÚAF_INET6r|   r   r   Ú_addressType)r/   rx   rª   r«   r¬   r2   r3   r3   r4   r*   ±  s    zPort.__init__r¡   r¢   c                 C  s6   | j d k	r d | j| jj| j ¡S d | j| jj¡S d S )Nz<{} of {} on {}>z<{} of {} (not listening)>)r§   rž   rŸ   rª   r5   r3   r3   r4   r¤   »  s    
ýþzPort.__repr__c              
   C  s  zH| j  | j| j¡}| jtjkr0t| j| jƒ}n| j| jf}| 	|¡ W n4 t
k
r| } zt | j| j|¡‚W 5 d }~X Y nX t | ¡ ¡| _| ¡ d | _t d|  | j¡| jf ¡ | j ¡  | | j¡ d| _d| _| j  | ¡ || _| jj| _|  ¡  d S )NrF   z%s starting on %sTF)r2   r{   r|   r}   r+   r­   r    r¬   rx   ÚbindrH   r
   ZCannotListenErrorr=   Z
maxAddrLenr,   ÚaddrLenÚgetsocknamer§   r#   ÚmsgrŠ   rª   ZdoStartÚlistenr«   rj   rS   r‘   r-   ÚdoAccept)r/   ZsktÚaddrÚler3   r3   r4   ÚstartListeningÈ  s.    $ÿÿ

zPort.startListeningc                 C  s2   d| _ | jr.t ¡ | _| j d| j|¡ | jS dS )zæ
        Stop accepting connections on this port.

        This will shut down my socket and call self.connectionLost().
        It returns a deferred which will fire successfully when the
        port is actually closed.
        Tr   N)rk   rj   r	   ZDeferredÚdeferredr2   Z	callLaterrM   )r/   ZconnDoner3   r3   r4   rl   è  s
    
zPort.loseConnectionc                 C  s    t  d| j› d| j› d�¡ dS )z.
        Log message for closing port
        ú(z Port z Closed)N)r#   r²   Ú_typer§   r5   r3   r3   r4   Ú_logConnectionLostMsgø  s    zPort._logConnectionLostMsgc                 C  s°   |   ¡  d| _d}t| dƒr&| j}| `d| _| j | ¡ d| _|  d¡ | `	| `
z| j ¡  W n4 tk
r’   d| _|dk	rŒ| t ¡ ¡ n‚ Y nX d| _|dk	r¬| d¡ dS )z'
        Cleans up the socket.
        Nr¸   TF)r»   r§   r�   r¸   rS   r2   r€   rj   rU   r+   r-   rª   ZdoStoprJ   rk   Zerrbackr"   rK   Úcallback)r/   rR   Údr3   r3   r4   rM   þ  s,    

zPort.connectionLostc                 C  s   t  | jj¡S )zK
        Returns the name of my class, to prefix log entries with.
        )r$   Zqualrª   rŸ   r5   r3   r3   r4   rW     s    zPort.logPrefixc                 C  s   | j dt| jƒžŽ S )zf
        Returns an IPv4Address or IPv6Address.

        This indicates the server's address.
        r¨   )r¨   )r®   r   r+   r5   r3   r3   r4   ro   #  s    zPort.getHostc                 C  s$   |   ||¡ | js | js |  ¡  d S r(   )ÚhandleAcceptrk   rS   r´   )r/   r�   rh   r?   r3   r3   r4   ÚcbAccept+  s    zPort.cbAcceptc           
   	   C  s`  | j s| jrdS |r4t dtj |d¡|f ¡ dS |j t	j
tt d| j	 ¡ ¡¡ t |j ¡ |j¡\}}}|| jks|t‚d|d kr²t|d  d¡d ƒ}|d |d d|f}d|d krèt|d  d¡d ƒ}|d |d d|f}| j | jd
|žŽ ¡}|d k�r|j ¡  nD| j}|d | _t|j|| jd|žŽ | jd|žŽ || jƒ}	| |	¡ d	S d S )NFz*Could not accept new connection -- %s (%s)zunknown errorr‚   ú%r   rF   r¨   T)r¨   )r¨   )r¨   )rk   rS   r#   r²   r…   r†   r„   Únewsktr]   r+   r`   r   r‡   rˆ   r,   r=   Zget_accept_addrsrD   r|   r�   r™   Úsplitrª   r‰   r®   Úcloserœ   r˜   r2   r‹   )
r/   r�   r?   ÚfamilyZlAddrZrAddrZscoper.   ÚsÚ	transportr3   r3   r4   r¾   0  sJ    ÿÿý

ú
zPort.handleAcceptc                 C  st   t  | j| ¡}td| jd  ƒ |_}| j | j| j	¡ |_
}t  | j ¡ | ¡ ||¡}|rp|tkrp|  ||¡ d S )Né   é   )r=   r’   r¿   r9   r°   rD   r2   r{   r|   r}   rÁ   Úacceptr+   r,   r   r¾   )r/   r?   rD   rÁ   r�   r3   r3   r4   r´   c  s     ÿ
zPort.doAccept)r©   rv   N)"rq   rr   rs   rj   rS   rk   r+   r•   r|   r–   r}   r   r   r®   rœ   r§   Ú__annotations__rº   r*   r¤   r·   r"   rK   r   ZCONNECTION_DONErl   ÚstopListeningr»   rM   rW   ro   r¿   r¾   r´   r3   r3   r3   r4   r¦   �  s*   


 3r¦   )Irt   Ú
__future__r   r…   r+   r‡   Útypingr   r   r   Zzope.interfacer   r   Ztwisted.internetr   r	   r
   r   r   Ztwisted.internet.abstractr   r   Ztwisted.internet.addressr   r   Ztwisted.internet.interfacesr   Ztwisted.internet.iocpreactorr   r   r=   Z"twisted.internet.iocpreactor.constr   r   r   r   r   Z'twisted.internet.iocpreactor.interfacesr   Ztwisted.internet.protocolr   Ztwisted.internet.tcpr   ZTCPConnectorr   r   r   r   r    r!   Ztwisted.pythonr"   r#   r$   Ztwisted.internet._newtlsr%   Z
__startTLSÚImportErrorrd   Z$twisted.internet.iocpreactor.reactorr&   ZWSAECONNREFUSEDZWSAENETUNREACHrƒ   ZITCPTransportZISystemHandler)   r'   ZITLSTransportru   r˜   ZIListeningPortr¦   r3   r3   r3   r4   Ú<module>   sL   $	
  þ <
YC