
    ϪfI                        d Z ddlZ	 ddlmZ 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      Z eej2                         G d d             Z eej6                  ej8                         G d d             Zd Zd Z G d d      Z 	 	 	 ddZ!eedddfdZ"d Z# G d d      Z$ddZ%y# e$ r Y w xY w)z0
Utilities and helpers for simulating a network
    N)Error)directlyProvidesimplementer)error
interfaces)TCP4ClientEndpointTCP4ServerEndpoint)ConnectionRefusedError)FactoryProtocol)MemoryReactorClock)Failurec                   $    e Zd Zd ZdefdZd Zy)TLSNegotiationc                 <    || _         || _        d| _        || _        y )NF)objconnectStatesentreadyToSend)selfr   r   s      4/usr/lib/python3/dist-packages/twisted/test/iosim.py__init__zTLSNegotiation.__init__   s     (	'    returnc                 "    d| j                   dS )NzTLSNegotiation())r   r   s    r   __repr__zTLSNegotiation.__repr__!   s     A..r   c                     | j                   j                  |j                         s t               |_        |j	                          y y N)r   iosimVerifyNativeOpenSSLErrordisconnectReasonloseConnection)r   othertpts      r   pretendToVerifyzTLSNegotiation.pretendToVerify$   s6     xx##EII.#5#7C   /r   N)__name__
__module____qualname__r   strr   r'    r   r   r   r      s    (/# /!r   r   c                       e Zd ZdZy)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   r.   c                       e Zd ZdZ e ej                         fd      ZdZdZ	dZ
 ej                  d      ZdZdZdZd dZdefdZd	 Zd
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Z d Z!d Z"d!dZ#d Z$d Z%d Z&d Z'd Z(d Z)d Z*y)"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                 *    t        t        |             S r    )intnext)counters    r   <lambda>zFakeTransport.<lambda>>   s    T']AS r   r   zConnection doneNc                     || _         || _        g | _        | j                         | _        |
t               }|| _        |
t               }|| _        y)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   r8   r9   r=   r>   s        r   r   zFakeTransport.__init__G   sS    " ! &&(%-K&%-K&r   r   c                     dj                  | j                  xr dxs d| j                  | j                  j                  j
                        S )NzFakeTransport<{},{},{}>SC)formatr9   r<   r8   	__class__r(   r   s    r   r   zFakeTransport.__repr__c   s@    (//MM!c(SKKMM##,,
 	
r   c                     | j                   ry | j                  | j                  j                  |       y | j                  j                  |       y r    )disconnectingtlstlsbufappendr:   )r   datas     r   writezFakeTransport.writej   s<    88KKt$KKt$r   c                 l    | j                   r(| j                  s| j                   j                          y y y r    producerstreamingProducerresumeProducingr   s    r   _checkProducerzFakeTransport._checkProducert   s*     ==!7!7MM))+ "8=r   c                 F    || _         || _        |s|j                          yy)z.
        From abstract.FileDescriptor
        NrL   )r   rM   	streamings      r   registerProducerzFakeTransport.registerProducerz   s'     !!*$$& r   c                     d | _         y r    )rM   r   s    r   unregisterProducerz FakeTransport.unregisterProducer   s	    r   c                 D    | j                          | j                          y r    )rU   r$   r   s    r   stopConsumingzFakeTransport.stopConsuming   s    !r   c                 D    | j                  dj                  |             y )Nr   )rJ   join)r   iovecs     r   writeSequencezFakeTransport.writeSequence   s    

388E?#r   c                     d| _         y NTrE   r   s    r   r$   zFakeTransport.loseConnection   s
    !r   c                     d| _         y)zp
        For the time being, this is the same as loseConnection; no buffered
        data will be lost.
        TNr^   r   s    r   abortConnectionzFakeTransport.abortConnection   s    
 "r   c                     | j                   t               }n| j                  }| j                  j	                  t        |             y r    )rF   r"   r#   r8   connectionLostr   )r   errs     r   reportDisconnectzFakeTransport.reportDisconnect   s7    88 %&C''C$$WS\2r   c                      y)zM
        Identify this transport/event source to the logging system.
        iosimr,   r   s    r   	logPrefixzFakeTransport.logPrefix   s     r   c                     | j                   S r    )r>   r   s    r   getPeerzFakeTransport.getPeer       r   c                     | j                   S r    )r=   r   s    r   getHostzFakeTransport.getHost   rj   r   c                      y r    r,   r   s    r   rO   zFakeTransport.resumeProducing       r   c                      y r    r,   r   s    r   pauseProducingzFakeTransport.pauseProducing   rn   r   c                 $    | j                          y r    )r$   r   s    r   stopProducingzFakeTransport.stopProducing   s    r   c                 R    | j                   |z  }t        ||      | _        g | _        y r    )r9   r   rF   rG   )r   contextFactorybeNormalr   s       r   startTLSzFakeTransport.startTLS   s'     }}x/!.,?r   c                     | j                   }|rg | _         dj                  |      S | j                  4| j                  j                  rd| j                  _        | j                  S yy)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}
        r   NT)r:   rY   rF   r   r   )r   r@   s     r   getOutBufferzFakeTransport.getOutBuffer   sV     KKDK88A;XX!xx## $xxr   c                    t        |t              r| j                  J | j                  j                  rc| j                  j	                  ||        d | _        | j
                  d c}| _        | j                  |       t        | t        j                         y d| j                  _
        y | j                  j                  |       y r]   )
isinstancer   rF   r   r'   rG   r[   r   r   ISSLTransportr   r8   dataReceived)r   bufbs      r   bufferReceivedzFakeTransport.bufferReceived   s    c>*88''' xx}}((d3 "&d4;""1% z'?'?@ (,$MM&&s+r   c                      y r    r,   r   s    r   getTcpKeepAlivezFakeTransport.getTcpKeepAlive   rn   r   c                      y r    r,   r   s    r   getTcpNoDelayzFakeTransport.getTcpNoDelay   rn   r   c                      y r    r,   r   s    r   loseWriteConnectionz!FakeTransport.loseWriteConnection   rn   r   c                      y r    r,   r   enableds     r   setTcpKeepAlivezFakeTransport.setTcpKeepAlive   rn   r   c                      y r    r,   r   s     r   setTcpNoDelayzFakeTransport.setTcpNoDelay   rn   r   )NN)T)+r(   r)   r*   r/   staticmethod	itertoolscountr;   closedrE   disconnectedr   ConnectionDoner#   rM   rN   rF   r   r+   r   rJ   rP   rS   rU   rW   r[   r$   r`   rd   rg   ri   rl   rO   rp   rr   rv   rx   r   r   r   r   r   r   r,   r   r   r1   r1   5   s     oioo.?STKFML+u++,=>H
C'8
# 
%,'$""3  ,,&r   r1   c                     t        | 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r9   r1   )clientProtocols    r   makeFakeClientr      s     %88r   c                     t        | d      S )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}
    Tr   r   )serverProtocols    r   makeFakeServerr   
  s     $77r   c                   (    e Zd ZdZddZddZddZy)IOPumpz
    Utility to pump data between clients and servers for protocol testing.

    Perhaps this is a utility worthy of being in protocol.py?
    Nc                 p    || _         || _        || _        || _        || _        |
t               }|| _        y r    )clientserverclientIOserverIOdebugr   clock)r   r   r   r   r   r   r   s          r   r   zIOPump.__init__  s9      
=&(E
r   c                 b    d}t        d      D ]  }| j                  ||      rd} |S  J d       )zk
        Pump until there is no more input or output.

        Returns whether any data was moved.
        Fi  TzToo long)rangepump)r   r   advanceClockresult_s        r   flushzIOPump.flush(  sE     t 	!Ayy- 	! !j 1r   c                 \   |r| j                   j                  d       | j                  s|rt        d       | j                  j                         }| j                  j                         }| j                  j                          | j                  j                          | j                  s|r=t        d       |rt        dt        |      z          |rt        dt        |      z          |r| j                  j                  |       |r| j                  j                  |       |s|ry| j                  j                  rl| j                  j                  sV| j                  s|rt        d       d| j                  _        d| j                  _
        | j                  j                          y| j                  j                  rl| j                  j                  sV| j                  s|rt        d       d| j                  _        d| j                  _
        | j                  j                          yy	)
z
        Move data back and forth, while also triggering any currently pending
        scheduled calls (i.e. C{callLater(0, f)}).

        Returns whether any data was moved.
        r   z
-- GLUG --.zC: zS: Tz* Cz* SF)r   advancer   printr   rx   r   rP   reprr   rE   r   rd   )r   r   r   sDatacDatas        r   r   zIOPump.pump8  s    JJq!::,**,**,$$&$$&::#Jed5k)*ed5k)*MM((/MM((/E==&&t}}/I/IzzUe)-DMM&*.DMM'MM**,==&&t}}/I/IzzUe)-DMM&*.DMM'MM**,r   r    )FT)r(   r)   r*   r/   r   r   r   r,   r   r   r   r     s     *r   r   FTc                     | j                  |       |j                  |       t        || ||||      }|r|j                          |S )a  
    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}

    @param clock: An optional L{Clock}. Pumping the resulting L{IOPump} will
        also increase clock time by a small increment.

    @return: An L{IOPump} which connects C{serverProtocol} and
        C{clientProtocol} and delivers bytes between them when it is pumped.
    @rtype: L{IOPump}
    r   )makeConnectionr   r   )r   serverTransportr   clientTransportr   greetr   r   s           r   connectr   e  sP    T !!/2!!/2D 

Kr   c                 h     |       } |        } ||      }	 ||      }
||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}

    @param clock: An optional L{Clock}. Pumping the resulting L{IOPump} will
        also increase clock time by a small increment.

    @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   )r   )ServerClassClientClassclientTransportFactoryserverTransportFactoryr   r   r   csciosios              r   connectedServerAndClientr     sE    \ 	AA
 
#C
 
#CaCCUCCCr   c                 4    | \  }}}}}|\  }}}	}
||k(  r||fS y)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serverInterfaces              r   _factoriesShouldConnectr     s?    . 	BL?ZZm++r   c                   >    e Zd ZdZd ZddZ e e             fdZy)ConnectionCompleterz
    A L{ConnectionCompleter} can cause synthetic TCP connections established by
    L{MemoryReactor.connectTCP} and L{MemoryReactor.listenTCP} to succeed or
    fail.
    c                     || _         y)z
        Create a L{ConnectionCompleter} from a L{MemoryReactor}.

        @param memoryReactor: The reactor to attach to.
        @type memoryReactor: L{MemoryReactor}
        N)_reactor)r   memoryReactors     r   r   zConnectionCompleter.__init__  s     &r   c           	         | j                   }t        |j                        D ]  \  }}|j                  D ]  }t	        ||      }|s|j                  j                  |       |j                  j                  |       |\  }}|j                  d      }	|j                  d      }
t        |
      }t        |	      }t        |
||	||      c c S   y)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   r   r   )r   r   r   	clientIdxr   r   	factoriesr   r   r   r   r   r   s                r   succeedOncezConnectionCompleter.succeedOnce  s     %.}/G/G%H 	!Iz+66 
3J
K	!,,33J?!,,00;3<0M=%2%@%@%FN%2%@%@%FN&4^&DO&4^&DO"&'&' 	r   c                     | j                   j                  j                  d      d   j                  | j                   j                  j                  d      |       y)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   reasons     r   failOncezConnectionCompleter.failOnce$  sF     	  $$Q'*AAMM$$((+V	
r   NF)	r(   r)   r*   r/   r   r   r   r
   r   r,   r   r   r   r     s%    &B &&<&>? 

r   r   c                     t               }t        |dd      }t        |d      }|j                  t	        j
                  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serverEndpoints       r   connectableEndpointr   1  sP     !"G'DAN'6N'--h78.w777r   )FTNr   )&r/   r   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ITLSTransportr1   r   r   r   r   r   r   r   r   r,   r   r   <module>r      s   
 	7 9 . M 9 7 7 *! !& Z  !  " Z""J$<$<=D D >DN
9
8K Kf 

7z *)


2Dj>;
 ;
|8I  		s   C CC