o
    bM                     @   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re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TCP2   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;