o
    ¯bóF  ã                   @   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}|r�t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>