o
    ¯bŽM  ã                   @   sª  d 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 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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&m'Z'm(Z( ddl)m*Z*m+Z+m,Z, zddl-m.Z/ W n e0yƒ   dZ1Y nw e/Z1eej2eej3iZ4eeej5ej6ƒG dd„ dej7e(e#ƒƒZ8e1dur«ee8ej9ƒ G dd„ de$e%e8ƒZ:G dd„ de8ƒZ;G dd„ de"ƒZ!eej<ƒG dd„ de(eƒƒZ=dS )z
TCP support for IOCP reactor
é    N)ÚOptional)ÚclassImplementsÚimplementer)ÚaddressÚdeferÚerrorÚ
interfacesÚmain)Ú	_LogOwnerÚisIPv6Address)Ú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)ÚstartTLSc                   @   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urFd0dd „Zd!d"„ Zd#d$„ Zd/d%d&„Zd'd(„ Zd)d*„ Zd+d,„ Zd-d.„ ZdS )1Ú
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© r,   úB/usr/lib/python3/dist-packages/twisted/internet/iocpreactor/tcp.pyr#   ?   s   
zConnection.__init__c                 C   ó   | j S r!   )r$   ©r(   r,   r,   r-   Ú	getHandleE   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(   Úrbufferr,   r,   r-   r6   H   s   


zConnection.dataReceivedc                 C   s   t  |  ¡ ||¡S r!   )Ú_iocpÚrecvr&   )r(   ÚbufflistÚevtr,   r,   r-   ÚreadFromHandleW   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   )Ú
memoryviewr8   Úsendr&   Ú
SEND_LIMITÚtobytes)r(   Úbuffr;   Ú	writeViewr,   r,   r-   ÚwriteToHandleZ   s   ÿzConnection.writeToHandlec                 C   sx   z| j  d¡ W n	 ty   Y nw t | jd ¡}|r:z| ¡  W d S  ty9   t 	¡ }t
 ¡  |  |¡ Y d S w d S )Né   )r$   ÚshutdownÚOSErrorr   ÚIHalfCloseableProtocolr'   ÚwriteConnectionLostÚBaseExceptionr   ÚFailurer   ÚerrÚconnectionLost)r(   ÚpÚfr,   r,   r-   Ú_closeWriteConnectiond   s   ÿýýz Connection._closeWriteConnectionc                 C   sZ   t  | jd ¡}|r&z| ¡  W d S  ty%   t ¡  |  t 	¡ ¡ Y d S w |  |¡ d S r!   )
r   rG   r'   ÚreadConnectionLostrI   r   rK   rL   r   rJ   )r(   ÚreasonrM   r,   r,   r-   rP   r   s   þzConnection.readConnectionLostc                 C   sX   | j rd S tj | |¡ |d u p| tj¡ }|  |¡ | j}| `| `	| `
| |¡ d S r!   )Údisconnectedr   r"   rL   Úcheckr   ÚConnectionAbortedÚ_closeSocketr'   r$   r&   )r(   rQ   ÚisCleanr'   r,   r,   r-   rL   }   s   
zConnection.connectionLostc                 C   r.   )zN
        Return the prefix to log with when I own the logging thread.
        )Úlogstrr/   r,   r,   r-   Ú	logPrefix‰   ó   zConnection.logPrefixc                 C   ó   t | j tjtj¡ƒS r!   )Úboolr$   Ú
getsockoptÚIPPROTO_TCPÚTCP_NODELAYr/   r,   r,   r-   ÚgetTcpNoDelay�   ó   zConnection.getTcpNoDelayc                 C   ó   | j  t jt j|¡ d S r!   )r$   Ú
setsockoptr]   r^   ©r(   Úenabledr,   r,   r-   ÚsetTcpNoDelay’   ó   zConnection.setTcpNoDelayc                 C   rZ   r!   )r[   r$   r\   Ú
SOL_SOCKETÚSO_KEEPALIVEr/   r,   r,   r-   ÚgetTcpKeepAlive•   r`   zConnection.getTcpKeepAlivec                 C   ra   r!   )r$   rb   rg   rh   rc   r,   r,   r-   ÚsetTcpKeepAlive˜   rf   zConnection.setTcpKeepAliveTc                 C   s   t | ||tjƒ dS )z9
            @see: L{ITLSTransport.startTLS}
            N)Ú	_startTLSr   r"   )r(   ÚcontextFactoryÚnormalr,   r,   r-   r   �   s   zConnection.startTLSc                 C   ó2   | j rdS | jr| j |¡ dS 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)rR   ÚTLSr'   Úwriter   r"   )r(   Údatar,   r,   r-   rp   £   ó
   zConnection.writec                 C   rn   )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)rR   ro   r'   ÚwriteSequencer   r"   )r(   Úiovecr,   r,   r-   rs   ²   rr   zConnection.writeSequencec                 C   s:   | j r| jr| js| j ¡  dS dS dS 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)ro   Ú	connectedÚdisconnectingr'   ÚloseConnectionr   r"   )r(   rQ   r,   r,   r-   rw   Á   s
   ÿzConnection.loseConnectionc                 C   s,   | j r| j ||¡ dS tj | ||¡ dS )zc
        Register a producer.

        If TLS is enabled, the TLS connection handles this.
        N)ro   r'   ÚregisterProducerr   r"   )r(   ÚproducerÚ	streamingr,   r,   r-   rx   Î   s   zConnection.registerProducerc                 C   s$   | j r
| j ¡  dS tj | ¡ dS )ze
        Unregister a producer.

        If TLS is enabled, the TLS connection handles this.
        N)ro   r'   ÚunregisterProducerr   r"   r/   r,   r,   r-   r{   Ý   s   zConnection.unregisterProducerc                 C   ó   d S r!   r,   r/   r,   r,   r-   ÚgetHostè   ó   zConnection.getHostc                 C   r|   r!   r,   r/   r,   r,   r-   ÚgetPeerì   r~   zConnection.getPeerr!   )T)Ú__name__Ú
__module__Ú__qualname__Ú__doc__ro   r#   r0   r6   r<   rC   rO   rP   rL   rX   r_   re   ri   rj   rk   r   rp   rs   rw   rx   r{   r}   r   r,   r,   r,   r-   r    5   s2    



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 u rd}|| _ t | |||||¡ d S )N)Ú r   )r+   r   r#   )r(   ÚhostÚportÚbindAddressÚ	connectorr+   r,   r,   r-   r#     s   zClient.__init__c                 C   s   | j  | j| j¡S )zd
        Create a socket registered with the IOCP reactor.

        @see: L{_BaseTCPClient}
        )r+   ÚcreateSocketÚaddressFamilyÚ
socketTyper/   r,   r,   r-   Ú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&   r/   r,   r,   r-   Ú_collectSocketDetails  s   zClient._collectSocketDetailsc                 C   s   | j  | ¡ dS )z^
        Remove the active handle from the reactor.

        @see: L{_BaseBaseClient}
        N)r+   ÚremoveActiveHandler/   r,   r,   r-   Ú_stopReadingAndWriting  s   zClient._stopReadingAndWritingc              	   C   s¶   |rt  ||¡}|  t |tj |d¡f¡¡ d S | j tj	t
t d| j ¡ ¡¡ | j |  ¡ ¡| _d| _|  | j¡}|d | _| jd u rOtƒ | _|  ¡  d S | j | ¡ |  ¡  d S )NzUnknown errorÚPTz,client)ÚconnectExErrorsÚgetÚfailIfNotConnectedr   ÚgetConnectErrorÚerrnoÚ	errorcoder$   rb   rg   r   ÚstructÚpackr%   r‰   ÚbuildProtocolr   r'   ru   Ú_getLogPrefixrW   r   rw   ÚmakeConnectionÚstartReading)r(   Úrcrq   r;   rX   r,   r,   r-   Ú	cbConnect"  s&   ÿý

zClient.cbConnectc                 C   sn   t | dƒsd S tjsJ ‚| j | ¡ t | j| ¡}t | j 	¡ | j
|¡}|r3|tkr5|  |d|¡ d S d S d S )Nr‰   r   )Úhasattrr8   Úhave_connectexr+   ÚaddActiveHandleÚEventrŸ   Úconnectr$   r%   ÚrealAddressr   )r(   r;   rž   r,   r,   r-   Ú	doConnect@  s   

ÿzClient.doConnectN)r€   r�   r‚   rƒ   r$   ÚAF_INETr‹   ÚSOCK_STREAMrŒ   Ú_tlsClientDefaultr    Ú_commonConnectionr#   r�   rŽ   r�   rŸ   r¦   r,   r,   r,   r-   r„   õ   s    	r„   c                   @   s:   e Zd ZdZdZdd„ Zdef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.
    Fc                 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#   Ú
serverAddrÚ
clientAddrÚ	sessionnor›   r'   r†   rW   ÚformatÚ	__class__r€   r‡   Úrepstrru   r�   )r(   r)   r'   r®   r­   r¯   r+   rX   r,   r,   r-   r#   \  s   ýzServer.__init__Úreturnc                 C   r.   )z=
        A string representation of this connection.
        )r²   r/   r,   r,   r-   Ú__repr__r  rY   zServer.__repr__c                 C   r.   )zW
        Returns an IPv4Address.

        This indicates the server's address.
        )r­   r/   r,   r,   r-   r}   x  ó   zServer.getHostc                 C   r.   )zW
        Returns an IPv4Address.

        This indicates the client's address.
        )r®   r/   r,   r,   r-   r   €  rµ   zServer.getPeerN)
r€   r�   r‚   rƒ   r©   r#   Ústrr´   r}   r   r,   r,   r,   r-   r«   N  s    r«   c                   @   s   e Zd Zdd„ ZdS )r   c                 C   s   t | j| j| j| | jƒS r!   )r„   r†   r‡   rˆ   r+   r/   r,   r,   r-   Ú_makeTransportŠ  rf   zConnector._makeTransportN)r€   r�   r‚   r·   r,   r,   r,   r-   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ee ed< dZddd	„Zd
ef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   NÚ_realPortNumberÚTCPé2   r…   c                 C   s>   || _ || _|| _|| _|| _t|ƒrtj| _t	j
| _d S d S r!   )r‡   ÚfactoryÚbacklogÚ	interfacer+   r   r$   ÚAF_INET6r‹   r   ÚIPv6AddressÚ_addressType)r(   r‡   r¼   r½   r¾   r+   r,   r,   r-   r#   £  s   þzPort.__init__r³   c                 C   s2   | j d urd | j| jj| j ¡S d | j| jj¡S )Nz<{} of {} on {}>z<{} of {} (not listening)>)r¹   r°   r±   r¼   r/   r,   r,   r-   r´   ­  s   
ýþzPort.__repr__c              
   C   sø   z$| j  | j| j¡}| jtjkrt| j| jƒ}n| j| jf}| 	|¡ W n t
y9 } z	t | j| j|¡‚d }~ww t | ¡ ¡| _| ¡ d | _t d|  | j¡| jf ¡ | j ¡  | | j¡ d| _d| _| j  | ¡ || _| jj| _|  ¡  d S )NrD   z%s starting on %sTF)r+   rŠ   r‹   rŒ   r$   r¿   r   r¾   r‡   ÚbindrF   r   ÚCannotListenErrorr8   Ú
maxAddrLenr%   ÚaddrLenÚgetsocknamer¹   r   Úmsgr›   r¼   ÚdoStartÚlistenr½   ru   rR   r¢   r&   ÚdoAccept)r(   ÚsktÚaddrÚler,   r,   r-   ÚstartListeningº  s2   €ÿÿÿ

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)rv   ru   r   ÚDeferredÚdeferredr+   Ú	callLaterrL   )r(   ÚconnDoner,   r,   r-   rw   Ú  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¹   r/   r,   r,   r-   Ú_logConnectionLostMsgê  s    zPort._logConnectionLostMsgc                 C   s²   |   ¡  d| _d}t| dƒr| j}| `d| _| j | ¡ d| _|  d¡ | `	| `
z| j ¡  W n tyH   d| _|durG| t ¡ ¡ Y dS ‚ w d| _|durW| d¡ dS dS )z'
        Cleans up the socket.
        NrÐ   TF)rÕ   r¹   r    rÐ   rR   r+   r�   ru   rU   r$   r&   r¼   ÚdoStoprI   rv   Úerrbackr   rJ   Úcallback)r(   rQ   Údr,   r,   r-   rL   ð  s0   

ûÿzPort.connectionLostc                 C   s   t  | jj¡S )zK
        Returns the name of my class, to prefix log entries with.
        )r   Úqualr¼   r±   r/   r,   r,   r-   rX     s   zPort.logPrefixc                 C   s   | j dgt| jƒ¢R Ž S )zf
        Returns an IPv4Address or IPv6Address.

        This indicates the server's address.
        rº   )rÁ   r   r$   r/   r,   r,   r-   r}     s   zPort.getHostc                 C   s,   |   ||¡ | js| js|  ¡  d S d S d S r!   )ÚhandleAcceptrv   rR   rÊ   )r(   rž   rq   r;   r,   r,   r-   ÚcbAccept  s   ÿzPort.cbAcceptc           
   	   C   sh  | j s| jrdS |rt dtj |d¡|f ¡ dS |j t	j
tt d| j	 ¡ ¡¡ t |j ¡ |j¡\}}}|| jks>J ‚d|d v rYt|d  d¡d ƒ}|d |d d|f}d|d v rtt|d  d¡d ƒ}|d |d d|f}| j | jdg|¢R Ž ¡}|d u rŒ|j ¡  d	S | j}|d | _t|j|| jdg|¢R Ž | jdg|¢R Ž || jƒ}	| |	¡ d	S )
NFz*Could not accept new connection -- %s (%s)zunknown errorr‘   ú%r   rD   rº   T)rv   rR   r   rÇ   r–   r—   r“   Únewsktrb   r$   rg   r   r˜   r™   r%   r8   Úget_accept_addrsrA   r‹   ÚintÚsplitr¼   rš   rÁ   Úcloser¯   r«   r+   rœ   )
r(   rž   r;   ÚfamilyÚlAddrÚrAddrÚscoper'   ÚsÚ	transportr,   r,   r-   rÛ   "  sL   ÿÿý
õ
ú
zPort.handleAcceptc                 C   s|   t  | j| ¡}td| jd  ƒ |_}| j | j| j	¡ |_
}t  | j ¡ | ¡ ||¡}|r:|tkr<|  ||¡ d S d S d S )Né   é   )r8   r£   rÜ   r3   rÅ   rA   r+   rŠ   r‹   rŒ   rÞ   Úacceptr$   r%   r   rÛ   )r(   r;   rA   rÞ   rž   r,   r,   r-   rÊ   U  s   
ÿÿzPort.doAccept)r»   r…   N)%r€   r�   r‚   ru   rR   rv   r$   r§   r‹   r¨   rŒ   r   ÚIPv4AddressrÁ   r¯   r¹   r   rà   Ú__annotations__rÔ   r#   r¶   r´   rÎ   r   rJ   r	   ÚCONNECTION_DONErw   ÚstopListeningrÕ   rL   rX   r}   rÜ   rÛ   rÊ   r,   r,   r,   r-   r¸   Ž  s,   
 

 3r¸   )>rƒ   r–   r$   r˜   Útypingr   Úzope.interfacer   r   Útwisted.internetr   r   r   r   r	   Útwisted.internet.abstractr
   r   Útwisted.internet.iocpreactorr   r   r8   Ú"twisted.internet.iocpreactor.constr   r   r   r   r   Ú'twisted.internet.iocpreactor.interfacesr   Útwisted.internet.protocolr   Útwisted.internet.tcpr   ÚTCPConnectorr   r   r   r   r   r   Útwisted.pythonr   r   r   Útwisted.internet._newtlsr   Ú
__startTLSÚImportErrorrk   ÚWSAECONNREFUSEDÚWSAENETUNREACHr’   ÚITCPTransportÚISystemHandler"   r    ÚITLSTransportr„   r«   ÚIListeningPortr¸   r,   r,   r,   r-   Ú<module>   sB   $	ÿþ <Y;