o
    bF                     @   s8  d Z ddlZzddlmZ W n	 ey   Y nw ddl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 dd
lmZ G dd dZeejG dd dZeejejG dd dZdd Zdd ZG dd dZ 		d#ddZ!eeddfddZ"dd Z#G dd  d Z$d$d!d"Z%dS )%z0
Utilities and helpers for simulating a network
    N)Error)directlyProvidesimplementer)error
interfaces)TCP4ClientEndpointTCP4ServerEndpoint)ConnectionRefusedError)FactoryProtocol)MemoryReactorClock)Failurec                   @   s*   e Zd Zdd ZdefddZdd ZdS )	TLSNegotiationc                 C   s   || _ || _d| _|| _d S )NF)objconnectStatesentreadyToSend)selfr   r    r   4/usr/lib/python3/dist-packages/twisted/test/iosim.py__init__   s   
zTLSNegotiation.__init__returnc                 C   s   d| j dS )NzTLSNegotiation())r   r   r   r   r   __repr__"   s   zTLSNegotiation.__repr__c                 C   s&   | j |j st |_|  d S d S N)r   iosimVerifyNativeOpenSSLErrordisconnectReasonloseConnection)r   othertptr   r   r   pretendToVerify%   s   zTLSNegotiation.pretendToVerifyN)__name__
__module____qualname__r   strr   r"   r   r   r   r   r      s    r   c                   @   s   e Zd ZdZdS )FakeAddressz]
    The default address type for the host and peer of L{FakeTransport}
    connections.
    N)r#   r$   r%   __doc__r   r   r   r   r'   .   s    r'   c                   @   s  e Zd ZdZee fddZdZdZ	dZ
edZdZdZdZd;ddZd	ef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d$d% Z d&d' Z!d(d) Z"d<d+d,Z#d-d. Z$d/d0 Z%d1d2 Z&d3d4 Z'd5d6 Z(d7d8 Z)d9d: Z*dS )=FakeTransportz
    A wrapper around a file-like object to make it behave as a Transport.

    This doesn't actually stream the file to the attached protocol,
    and is thus useful mainly as a utility for debugging protocols.
    c                 C   s   t t| S r   )intnext)counterr   r   r   <lambda>?   s    zFakeTransport.<lambda>r   zConnection doneNc                 C   sH   || _ || _g | _|  | _|du rt }|| _|du rt }|| _dS )a  
        @param protocol: This transport will deliver bytes to this protocol.
        @type protocol: L{IProtocol} provider

        @param isServer: C{True} if this is the accepting side of the
            connection, C{False} if it is the connecting side.
        @type isServer: L{bool}

        @param hostAddress: The value to return from C{getHost}.  L{None}
            results in a new L{FakeAddress} being created to use as the value.
        @type hostAddress: L{IAddress} provider or L{None}

        @param peerAddress: The value to return from C{getPeer}.  L{None}
            results in a new L{FakeAddress} being created to use as the value.
        @type peerAddress: L{IAddress} provider or L{None}
        N)protocolisServerstream_nextserialserialr'   hostAddresspeerAddress)r   r.   r/   r3   r4   r   r   r   r   H   s   

zFakeTransport.__init__r   c                 C   s    d | jrdpd| j| jjjS )NzFakeTransport<{},{},{}>SC)formatr/   r2   r.   	__class__r#   r   r   r   r   r   d   s
   zFakeTransport.__repr__c                 C   s4   | j rd S | jd ur| j| d S | j| d S r   )disconnectingtlstlsbufappendr0   )r   datar   r   r   writek   s
   
zFakeTransport.writec                 C   s"   | j r| js| j   d S d S d S r   producerstreamingProducerresumeProducingr   r   r   r   _checkProduceru   s   zFakeTransport._checkProducerc                 C   s    || _ || _|s|  dS dS )z.
        From abstract.FileDescriptor
        Nr?   )r   r@   	streamingr   r   r   registerProducer{   s
   zFakeTransport.registerProducerc                 C   s
   d | _ d S r   )r@   r   r   r   r   unregisterProducer      
z FakeTransport.unregisterProducerc                 C   s   |    |   d S r   )rF   r   r   r   r   r   stopConsuming   s   zFakeTransport.stopConsumingc                 C   s   |  d| d S )N    )r>   join)r   iovecr   r   r   writeSequence   s   zFakeTransport.writeSequencec                 C   s
   d| _ d S NTr9   r   r   r   r   r      rG   zFakeTransport.loseConnectionc                 C   s
   d| _ dS )zp
        For the time being, this is the same as loseConnection; no buffered
        data will be lost.
        TNrN   r   r   r   r   abortConnection   s   
zFakeTransport.abortConnectionc                 C   s,   | j d ur	t }n| j}| jt| d S r   )r:   r   r   r.   connectionLostr   )r   errr   r   r   reportDisconnect   s   
zFakeTransport.reportDisconnectc                 C   s   dS )zM
        Identify this transport/event source to the logging system.
        iosimr   r   r   r   r   	logPrefix   s   zFakeTransport.logPrefixc                 C      | j S r   )r4   r   r   r   r   getPeer      zFakeTransport.getPeerc                 C   rU   r   )r3   r   r   r   r   getHost   rW   zFakeTransport.getHostc                 C      d S r   r   r   r   r   r   rB         zFakeTransport.resumeProducingc                 C   rY   r   r   r   r   r   r   pauseProducing   rZ   zFakeTransport.pauseProducingc                 C   s   |    d S r   )r   r   r   r   r   stopProducing   s   zFakeTransport.stopProducingTc                 C   s    | j |A }t||| _g | _d S r   )r/   r   r:   r;   )r   contextFactorybeNormalr   r   r   r   startTLS   s   

zFakeTransport.startTLSc                 C   sB   | j }|rg | _ d|S | jdur| jjrd| j_| jS dS dS )z
        Get the pending writes from this transport, clearing them from the
        pending buffer.

        @return: the bytes written with C{transport.write}
        @rtype: L{bytes}
        rI   NT)r0   rJ   r:   r   r   )r   r5   r   r   r   getOutBuffer   s   

zFakeTransport.getOutBufferc                 C   sx   t |tr4| jd usJ | jjr.| j||  d | _| jd }| _| | t| tj	 d S d| j_
d S | j| d S rM   )
isinstancer   r:   r   r"   r;   rL   r   r   ISSLTransportr   r.   dataReceived)r   bufbr   r   r   bufferReceived   s   

zFakeTransport.bufferReceivedc                 C   rY   r   r   r   r   r   r   getTcpKeepAlive   rZ   zFakeTransport.getTcpKeepAlivec                 C   rY   r   r   r   r   r   r   getTcpNoDelay   rZ   zFakeTransport.getTcpNoDelayc                 C   rY   r   r   r   r   r   r   loseWriteConnection   rZ   z!FakeTransport.loseWriteConnectionc                 C   rY   r   r   r   enabledr   r   r   setTcpKeepAlive   rZ   zFakeTransport.setTcpKeepAlivec                 C   rY   r   r   rj   r   r   r   setTcpNoDelay   rZ   zFakeTransport.setTcpNoDelay)NN)T)+r#   r$   r%   r(   staticmethod	itertoolscountr1   closedr9   disconnectedr   ConnectionDoner   r@   rA   r:   r   r&   r   r>   rC   rE   rF   rH   rL   r   rO   rR   rT   rV   rX   rB   r[   r\   r_   r`   rf   rg   rh   ri   rl   rm   r   r   r   r   r)   6   sF    


		
r)   c                 C      t | ddS )z
    Create and return a new in-memory transport hooked up to the given protocol.

    @param clientProtocol: The client protocol to use.
    @type clientProtocol: L{IProtocol} provider

    @return: The transport.
    @rtype: L{FakeTransport}
    Fr/   r)   )clientProtocolr   r   r   makeFakeClient      
rx   c                 C   rt   )z
    Create and return a new in-memory transport hooked up to the given protocol.

    @param serverProtocol: The server protocol to use.
    @type serverProtocol: L{IProtocol} provider

    @return: The transport.
    @rtype: L{FakeTransport}
    Tru   rv   )serverProtocolr   r   r   makeFakeServer  ry   r{   c                   @   s,   e Zd ZdZdd Zd
ddZd
ddZd	S )IOPumpz
    Utility to pump data between clients and servers for protocol testing.

    Perhaps this is a utility worthy of being in protocol.py?
    c                 C   s"   || _ || _|| _|| _|| _d S r   )clientserverclientIOserverIOdebug)r   r}   r~   r   r   r   r   r   r   r     s
   
zIOPump.__init__Fc                 C   s.   d}t dD ]}| |rd}q |S J d)zk
        Pump until there is no more input or output.

        Returns whether any data was moved.
        Fi  Tr   zToo long)rangepump)r   r   resultxr   r   r   flush&  s   
zIOPump.flushc                 C   s$  | j s|r	td | j }| j }| j  | j  | j s"|r:td |r0tdt|  |r:tdt|  |rB| j| |rJ| j| |sN|rPdS | jjrp| jj	sp| j s]|ratd d| j_	d| j_| j
  dS | jjr| jj	s| j s}|rtd d| j_	d| j_| j
  dS dS )	zX
        Move data back and forth.

        Returns whether any data was moved.
        z
-- GLUG --.zC: zS: Tz* Cz* SF)r   printr   r`   r   rC   reprrf   r9   rr   rR   )r   r   sDatacDatar   r   r   r   6  sB   









zIOPump.pumpNF)r#   r$   r%   r(   r   r   r   r   r   r   r   r|     s
    
r|   FTc                 C   s4   |  | | | t|| |||}|r|  |S )aN  
    Create a new L{IOPump} connecting two protocols.

    @param serverProtocol: The protocol to use on the accepting side of the
        connection.
    @type serverProtocol: L{IProtocol} provider

    @param serverTransport: The transport to associate with C{serverProtocol}.
    @type serverTransport: L{FakeTransport}

    @param clientProtocol: The protocol to use on the initiating side of the
        connection.
    @type clientProtocol: L{IProtocol} provider

    @param clientTransport: The transport to associate with C{clientProtocol}.
    @type clientTransport: L{FakeTransport}

    @param debug: A flag indicating whether to log information about what the
        L{IOPump} is doing.
    @type debug: L{bool}

    @param greet: Should the L{IOPump} be L{flushed <IOPump.flush>} once before
        returning to put the protocols into their post-handshake or
        post-server-greeting state?
    @type greet: L{bool}

    @return: An L{IOPump} which connects C{serverProtocol} and
        C{clientProtocol} and delivers bytes between them when it is pumped.
    @rtype: L{IOPump}
    )makeConnectionr|   r   )rz   serverTransportrw   clientTransportr   greetr   r   r   r   connect`  s   
&

r   c           
   	   C   s4   | }|  }||}||}	||t ||	||||fS )a  
    Connect a given server and client class to each other.

    @param ServerClass: a callable that produces the server-side protocol.
    @type ServerClass: 0-argument callable returning L{IProtocol} provider.

    @param ClientClass: like C{ServerClass} but for the other side of the
        connection.
    @type ClientClass: 0-argument callable returning L{IProtocol} provider.

    @param clientTransportFactory: a callable that produces the transport which
        will be attached to the protocol returned from C{ClientClass}.
    @type clientTransportFactory: callable taking (L{IProtocol}) and returning
        L{FakeTransport}

    @param serverTransportFactory: a callable that produces the transport which
        will be attached to the protocol returned from C{ServerClass}.
    @type serverTransportFactory: callable taking (L{IProtocol}) and returning
        L{FakeTransport}

    @param debug: Should this dump an escaped version of all traffic on this
        connection to stdout for inspection?
    @type debug: L{bool}

    @param greet: Should the L{IOPump} be L{flushed <IOPump.flush>} once before
        returning to put the protocols into their post-handshake or
        post-server-greeting state?
    @type greet: L{bool}

    @return: the client protocol, the server protocol, and an L{IOPump} which,
        when its C{pump} and C{flush} methods are called, will move data
        between the created client and server protocol instances.
    @rtype: 3-L{tuple} of L{IProtocol}, L{IProtocol}, L{IOPump}
    )r   )
ServerClassClientClassclientTransportFactoryserverTransportFactoryr   r   csciosior   r   r   connectedServerAndClient  s
   *r   c                 C   s.   | \}}}}}|\}}}	}
||kr||fS dS )a'  
    Should the client and server described by the arguments be connected to
    each other, i.e. do their port numbers match?

    @param clientInfo: the args for connectTCP
    @type clientInfo: L{tuple}

    @param serverInfo: the args for listenTCP
    @type serverInfo: L{tuple}

    @return: If they do match, return factories for the client and server that
        should connect; otherwise return L{None}, indicating they shouldn't be
        connected.
    @rtype: L{None} or 2-L{tuple} of (L{ClientFactory},
        L{IProtocolFactory})
    Nr   )
clientInfo
serverInfo
clientHost
clientPortclientFactoryclientTimeoutclientBindAddress
serverPortserverFactoryserverBacklogserverInterfacer   r   r   _factoriesShouldConnect  s   r   c                   @   s4   e Zd ZdZdd Zd
ddZee fddZd	S )ConnectionCompleterz
    A L{ConnectionCompleter} can cause synthetic TCP connections established by
    L{MemoryReactor.connectTCP} and L{MemoryReactor.listenTCP} to succeed or
    fail.
    c                 C   s
   || _ dS )z
        Create a L{ConnectionCompleter} from a L{MemoryReactor}.

        @param memoryReactor: The reactor to attach to.
        @type memoryReactor: L{MemoryReactor}
        N)_reactor)r   memoryReactorr   r   r   r     s   
zConnectionCompleter.__init__Fc                 C   s   | j }t|jD ]?\}}|jD ]7}t||}|rF|j| |j| |\}}|d}	|d}
t	|
}t
|	}t|
||	||    S qqdS )a  
        Complete a single TCP connection established on this
        L{ConnectionCompleter}'s L{MemoryReactor}.

        @param debug: A flag; whether to dump output from the established
            connection to stdout.
        @type debug: L{bool}

        @return: a pump for the connection, or L{None} if no connection could
            be established.
        @rtype: L{IOPump} or L{None}
        N)r   	enumerate
tcpClients
tcpServersr   remove
connectorspopbuildProtocolr{   rx   r   )r   r   r   	clientIdxr   r   	factoriesr   r   rw   rz   r   r   r   r   r   succeedOnce  s,   



zConnectionCompleter.succeedOncec                 C   s(   | j jdd | j jd| dS )z
        Fail a single TCP connection established on this
        L{ConnectionCompleter}'s L{MemoryReactor}.

        @param reason: the reason to provide that the connection failed.
        @type reason: L{Failure}
        r      N)r   r   r   clientConnectionFailedr   )r   reasonr   r   r   failOnce  s   zConnectionCompleter.failOnceNr   )	r#   r$   r%   r(   r   r   r   r	   r   r   r   r   r   r     s
    
	!r   c                 C   s8   t  }t|dd}t|d}|tt |t|fS )a  
    Create an endpoint that can be fired on demand.

    @param debug: A flag; whether to dump output from the established
        connection to stdout.
    @type debug: L{bool}

    @return: A client endpoint, and an object that will cause one of the
        L{Deferred}s returned by that client endpoint.
    @rtype: 2-L{tuple} of (L{IStreamClientEndpoint}, L{ConnectionCompleter})
    z0.0.0.0i  )r   r   r   listenr
   forProtocolr   r   )r   reactorclientEndpointserverEndpointr   r   r   connectableEndpoint  s
   
r   )FTr   )&r(   ro   OpenSSL.SSLr   r   ImportErrorzope.interfacer   r   twisted.internetr   r   twisted.internet.endpointsr   r   twisted.internet.errorr	   twisted.internet.protocolr
   r   twisted.internet.testingr   twisted.python.failurer   r   IAddressr'   
ITransportITLSTransportr)   rx   r{   r|   r   r   r   r   r   r   r   r   r   <module>   sD    HM
4
1>