U
    
W[ '                    @   s  d Z ddlmZmZ ddlZddlmZ ddlmZm	Z	m
Z
 ddlmZ zTd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mZmZmZmZmZ W n$ ek
r   dZd Z ZZY n2X ddlmZm Z  ddl!m"Z"m#Z#m$Z$ ddl%m&Z& ddl'm(Z( ddl)m*Z* ddl+m,Z, ddl-m.Z. ddl/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6 ddl7m8Z8m9Z9 ddl:m;Z;m<Z< ddl=m>Z>m?Z?m@Z@mAZA ddlBmCZC ddlDmEZEmFZF ddlGmHZHmIZI ddlJmKZK ddlLmMZMmNZN G dd dZOG dd de@ZPd5d!d"ZQG d#d$ d$eHZRd6d%d&ZSG d'd( d(eIZTG d)d* d*eHZUG d+d, d,eHZVG d-d. d.eHZWe
e3G d/d0 d0e>ZXe
e3G d1d2 d2eAZYG d3d4 d4eHZZdS )7z%
Tests for L{twisted.protocols.tls}.
    )divisionabsolute_importN)verifyObject)	InterfacedirectlyProvidesimplementer)	iterbytes)TLSMemoryBIOProtocolTLSMemoryBIOFactory)_PullToPush_ProducerMembrane)X509Type)TLSv1_METHODTLSv1_1_METHODTLSv1_2_METHODErrorContextConnectionTypeWantReadErrorz9pyOpenSSL 0.10 or newer required for twisted.protocol.tls)PrivateCertificateoptionsForClientTLS)ClientTLSContextServerTLSContextcertPath)!certificatesForAuthorityAndServer)connectedServerAndClient)FilePath)Failure)log)ISystemHandleISSLTransportIPushProducerIProtocolNegotiationFactoryIHandshakeListenerIOpenSSLServerConnectionCreatorIOpenSSLClientConnectionCreator)ConnectionDoneConnectionLost)DeferredgatherResults)ClientFactoryFactoryProtocolServerFactory)TaskStopped)loopbackAsynccollapsingPumpPolicy)TestCaseSynchronousTestCaseConnectionLostNotifyingProtocol)StringTransportNonStreamingProducerc                   @   s@   e Zd ZdZdZefddZdd ZeeZdd Z	d	d
 Z
dS )HandshakeCallbackContextFactorya   
    L{HandshakeCallbackContextFactory} is a factory for SSL contexts which
    allows applications to get notification when the SSL handshake completes.

    @ivar _finished: A L{Deferred} which will be called back when the handshake
        is done.
        c                 C   s   t  | _|| _d S N)r(   	_finished_method)selfmethod r>   A/usr/lib/python3/dist-packages/twisted/protocols/test/test_tls.py__init__H   s    z(HandshakeCallbackContextFactory.__init__c                 C   s   |  }||j fS )z
        Create a new L{HandshakeCallbackContextFactory} and return a two-tuple
        of it and a L{Deferred} which will fire when a connection created with
        it completes a TLS handshake.
        )r:   )clscontextFactoryr>   r>   r?   factoryAndDeferredM   s    z2HandshakeCallbackContextFactory.factoryAndDeferredc                 C   s   || j @ r| jd dS )a  
        This is the "info callback" on the context.  It will be called
        periodically by pyOpenSSL with information about the state of a
        connection.  When it indicates the handshake is complete, it will fire
        C{self._finished}.
        N)SSL_CB_HANDSHAKE_DONEr:   callback)r<   Z
connectionwhereZretr>   r>   r?   _infoX   s    
z%HandshakeCallbackContextFactory._infoc                 C   s   t | j}|| j |S )zp
        Create and return an SSL context configured to use L{self._info} as the
        info callback.
        )r   r;   Zset_info_callbackrG   )r<   contextr>   r>   r?   
getContextc   s    
z*HandshakeCallbackContextFactory.getContextN)__name__
__module____qualname____doc__rD   r   r@   rC   classmethodrG   rI   r>   r>   r>   r?   r7   <   s   	r7   c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )AccumulatingProtocola.  
    A protocol which collects the bytes it receives and closes its connection
    after receiving a certain minimum of data.

    @ivar howMany: The number of bytes of data to wait for before closing the
        connection.

    @ivar received: A L{list} of L{bytes} of the bytes received so far.
    c                 C   s
   || _ d S r9   )howMany)r<   rP   r>   r>   r?   r@   x   s    zAccumulatingProtocol.__init__c                 C   s
   g | _ d S r9   )receivedr<   r>   r>   r?   connectionMade|   s    z#AccumulatingProtocol.connectionMadec                 C   s0   | j | ttt| j | jkr,| j  d S r9   )rQ   appendsummaplenrP   	transportloseConnectionr<   datar>   r>   r?   dataReceived   s    z!AccumulatingProtocol.dataReceivedc                 C   s   | tst| d S r9   )checkr&   r   errr<   reasonr>   r>   r?   connectionLost   s    
z#AccumulatingProtocol.connectionLostN)rJ   rK   rL   rM   r@   rS   r\   ra   r>   r>   r>   r?   rO   n   s
   	rO   Fc                    s   t d t } fdd|_rFtttG fdddt}| }n| rRt }nt }t	||  |}|
d}|dkr~t }||  |fS )z\
    Create a protocol hooked up to a TLS transport hooked up to a
    StringTransport.
    l   J)c                      s    S r9   r>   r>   clientProtocolr>   r?   <lambda>       z"buildTLSProtocol.<locals>.<lambda>c                       s   e Zd Z fddZeZdS )z-buildTLSProtocol.<locals>.HardCodedConnectionc                    s    S r9   r>   )r<   tlsProtocolfakeConnectionr>   r?   clientConnectionForTLS   s    zDbuildTLSProtocol.<locals>.HardCodedConnection.clientConnectionForTLSN)rJ   rK   rL   ri   ZserverConnectionForTLSr>   rg   r>   r?   HardCodedConnection   s   rj   N)rO   r*   protocolr   r$   r%   objectr   r   r
   buildProtocolr5   makeConnection)serverrX   rh   clientFactoryrj   rB   wrapperFactorysslProtocolr>   )rc   rh   r?   buildTLSProtocol   s,      

rs   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	TLSMemoryBIOFactoryTestsz<
    Ensure TLSMemoryBIOFactory logging acts correctly.
    c                 C   sn   t  }g }|j}t| | tj| t }dd |_dd |_t	|d|}|  |  | 
|g  dS )zs
        L{TLSMemoryBIOFactory.doStart} and L{TLSMemoryBIOFactory.doStop} do
        not log any messages.
        c                   S   s   d S r9   r>   r>   r>   r>   r?   rd      re   z5TLSMemoryBIOFactoryTests.test_quiet.<locals>.<lambda>c                   S   s   d S r9   r>   r>   r>   r>   r?   rd      re   FN)r   rT   r   addObserver
addCleanupremoveObserverr-   ZdoStartZdoStopr
   assertEqual)r<   rB   ZlogsZloggerwrappedFactoryfactoryr>   r>   r?   
test_quiet   s    


z#TLSMemoryBIOFactoryTests.test_quietc                 C   s(   t  }t|dt }| d|  dS )z
        L{TLSMemoryBIOFactory.logPrefix} amends the wrapped factory's log prefix
        with a short string (C{"TLS"}) indicating the wrapping, rather than its
        full class name.
        FzServerFactory (TLS)N)r   r
   r-   rx   	logPrefix)r<   rB   rz   r>   r>   r?   test_logPrefix   s    z'TLSMemoryBIOFactoryTests.test_logPrefixc                 C   s8   G dd dt }t }t|d| }| d|  dS )z
        If the wrapped factory does not provide L{ILoggingContext},
        L{TLSMemoryBIOFactory.logPrefix} uses the wrapped factory's class name.
        c                   @   s   e Zd ZdS )zBTLSMemoryBIOFactoryTests.test_logPrefixFallback.<locals>.NoFactoryNrJ   rK   rL   r>   r>   r>   r?   	NoFactory   s   r   FzNoFactory (TLS)N)rl   r   r
   rx   r|   )r<   r   rB   rz   r>   r>   r?   test_logPrefixFallback   s    z/TLSMemoryBIOFactoryTests.test_logPrefixFallbackN)rJ   rK   rL   rM   r{   r}   r   r>   r>   r>   r?   rt      s   rt   c                    s   t  \}}ttG  fdddtt ttG dd dttttd|ddt fdd	d
t|	 dt
fdd	d
tfdd	fdd	dd\}}}|||fS )a  
    Construct a client and server L{TLSMemoryBIOProtocol} connected by an IO
    pump.

    @param greetingData: The data which should be written in L{connectionMade}.
    @type greetingData: L{bytes}

    @return: 3-tuple of client, server, L{twisted.test.iosim.IOPump}
    c                       s<   e Zd ZdZdZ fddZfddZdd Z  ZS )	z*handshakingClientAndServer.<locals>.ClientFNc                    s&   t  |   d k	r"| j d S r9   )superrS   rX   writerR   )Client	__class__clientGreetingDatar>   r?   rS      s    z9handshakingClientAndServer.<locals>.Client.connectionMadec                    s$   d| _ | j | _ r | j  d S NT)	handshookrX   getPeerCertificatepeerAfterHandshakeZabortConnectionrR   )clientAbortAfterHandshaker>   r?   handshakeCompleted   s    z=handshakingClientAndServer.<locals>.Client.handshakeCompletedc                 S   s   d S r9   r>   r_   r>   r>   r?   ra      s    z9handshakingClientAndServer.<locals>.Client.connectionLost)	rJ   rK   rL   r   r   rS   r   ra   __classcell__r>   )r   r   r   )r   r?   r      s
   r   c                   @   s    e Zd ZdZdd Zdd ZdS )z*handshakingClientAndServer.<locals>.ServerFc                 S   s
   d| _ d S r   )
handshakedrR   r>   r>   r?   r     s    z=handshakingClientAndServer.<locals>.Server.handshakeCompletedc                 S   s   d S r9   r>   r_   r>   r>   r?   ra     s    z9handshakingClientAndServer.<locals>.Server.connectionLostN)rJ   rK   rL   r   r   ra   r>   r>   r>   r?   Server   s   r   example.comZ	trustRootTc                      s    dS Ni?B r>   r>   )r   r>   r?   rd     re   z,handshakingClientAndServer.<locals>.<lambda>)ZisClientry   Fc                      s    dS r   r>   r>   )r   r>   r?   rd     re   c                      s
     d S r9   rm   r>   )serverFr>   r?   rd     re   c                      s
     d S r9   r   r>   )clientFr>   r?   rd     re   )Zgreet)r   r   r#   rO   rl   r
   r   r*   forProtocoloptionsr-   r   )r   r   authCert
serverCertclientro   pumpr>   )r   r   r   r   r   r   r?   handshakingClientAndServer   s*    

 

r   c                   @   s    e Zd ZdZdd Zdd ZdS )DeterministicTLSMemoryBIOTestsz
    Test for the implementation of L{ISSLTransport} which runs over another
    transport.

    @note: Prefer to add test cases to this suite, in this style, using
        L{connectedServerAndClient}, rather than returning L{Deferred}s.
    c                 C   sh   t  \}}}| |jjd | |jjd |  | |jjd | |jjd | |jjd dS )a  
        The completion of the TLS handshake calls C{handshakeCompleted} on
        L{Protocol} objects that provide L{IHandshakeListener}.  At the time
        C{handshakeCompleted} is invoked, the transport's peer certificate will
        have been initialized.
        FTN)r   rx   wrappedProtocolr   r   flushassertIsNotr   )r<   r   ro   r   r>   r>   r?   test_handshakeNotification$  s    z9DeterministicTLSMemoryBIOTests.test_handshakeNotificationc                 C   s0   t dd\}}}|j}|  | |jg  dS )a  
        If some data is written to the transport in C{connectionMade}, but
        C{handshakeDone} doesn't like something it sees about the handshake, it
        can use C{abortConnection} to ensure that the application never
        receives that data.
        s   untrustworthyTN)r   r   r   rx   rQ   )r<   r   ro   r   ZwrappedServerProtocolr>   r>   r?   test_handshakeStopWriting4  s    
z8DeterministicTLSMemoryBIOTests.test_handshakeStopWritingN)rJ   rK   rL   rM   r   r   r>   r>   r>   r?   r     s   r   c                   @   s   e Zd Z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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d0d1 Zd2d3 Zd4d5 Zd6d7 Zd8S )9TLSMemoryBIOTestsze
    Tests for the implementation of L{ISSLTransport} which runs over another
    L{ITransport}.
    c                 C   s.   t dd}| t| | t| dS )zj
        L{TLSMemoryBIOProtocol} instances provide L{ISSLTransport} and
        L{ISystemHandle}.
        N)r	   
assertTruer    
providedByr   )r<   protor>   r>   r?   test_interfacesI  s    
z!TLSMemoryBIOTests.test_interfacesc                 C   sr   G dd dt }G dd dt}t }t }t|d|}| }t|| t|t }|| | 	|
| dS )zw
        L{TLSMemoryBIOProtocol} instances provide the interfaces provided by
        the transport they wrap.
        c                   @   s   e Zd ZdS )zDTLSMemoryBIOTests.test_wrappedProtocolInterfaces.<locals>.ITransportNr~   r>   r>   r>   r?   
ITransportX  s   r   c                   @   s   e Zd Zdd ZdS )zETLSMemoryBIOTests.test_wrappedProtocolInterfaces.<locals>.MyTransportc                 S   s   d S r9   r>   rZ   r>   r>   r?   r   \  s    zKTLSMemoryBIOTests.test_wrappedProtocolInterfaces.<locals>.MyTransport.writeN)rJ   rK   rL   r   r>   r>   r>   r?   MyTransport[  s   r   TN)r   rl   r*   r   r
   r   r	   r,   rn   r   r   )r<   r   r   rp   rB   rq   rX   rf   r>   r>   r?   test_wrappedProtocolInterfacesS  s      

z0TLSMemoryBIOTests.test_wrappedProtocolInterfacesc                 C   sH   t  }t }t|d|}t|t }t }|| | | t	 dS )a/  
        L{TLSMemoryBIOProtocol.getHandle} returns the L{OpenSSL.SSL.Connection}
        instance it uses to actually implement TLS.

        This may seem odd.  In fact, it is.  The L{OpenSSL.SSL.Connection} is
        not actually the "system handle" here, nor even an object the reactor
        knows about directly.  However, L{twisted.internet.ssl.Certificate}'s
        C{peerFromTransport} and C{hostFromTransport} methods depend on being
        able to get an L{OpenSSL.SSL.Connection} object in order to work
        properly.  Implementing L{ISystemHandle.getHandle} like this is the
        easiest way for those APIs to be made to work.  If they are changed,
        then it may make sense to get rid of this implementation of
        L{ISystemHandle} and return the underlying socket instead.
        TN)
r*   r   r
   r	   r,   r5   rn   assertIsInstanceZ	getHandler   )r<   rz   rB   rq   r   rX   r>   r>   r?   test_getHandlek  s    
z TLSMemoryBIOTests.test_getHandlec                    sr   t   t } fdd|_t }t|d|}|d}t }|| |  j	 | 
 j	| |  j	| dS )z
        When L{TLSMemoryBIOProtocol} is connected to a transport, it connects
        the protocol it wraps to a transport.
        c                      s    S r9   r>   r>   rb   r>   r?   rd     re   z7TLSMemoryBIOTests.test_makeConnection.<locals>.<lambda>TN)r,   r*   rk   r   r
   rm   r5   rn   ZassertIsNotNonerX   r   assertIs)r<   rp   rB   rq   rr   rX   r>   rb   r?   test_makeConnection  s      

z%TLSMemoryBIOTests.test_makeConnectionc           
      C   sl   t  }t|_t \}}t|d|}|d}t }t|_t }t|d|}|d}t	||}	||||	fS )z@
        Start handshake between TLS client and server.
        TNF)
r*   r,   rk   r7   rC   r
   rm   r-   r   r/   )
r<   rp   clientContextFactoryhandshakeDeferredrq   sslClientProtocolserverFactoryserverContextFactorysslServerProtocolconnectionDeferredr>   r>   r?   handshakeProtocols  s.      
  

z$TLSMemoryBIOTests.handshakeProtocolsc                 C   s   |   \}}}}|S )zr
        The TLS handshake is performed when L{TLSMemoryBIOProtocol} is
        connected to a transport.
        )r   )r<   	tlsClient	tlsServerr   _r>   r>   r?   test_handshake  s    z TLSMemoryBIOTests.test_handshakec                    s   t   t } fdd|_t }t|d|}|d}t  t }fdd|_tt	 }t
|}||}t|d|}|d}	t|	|}
dd } | | t |
gS )	z
        L{TLSMemoryBIOProtocol} reports errors in the handshake process to the
        application-level protocol object using its C{connectionLost} method
        and disconnects the underlying transport.
        c                      s   t  S r9   r3   r>   clientConnectionLostr>   r?   rd     s   z9TLSMemoryBIOTests.test_handshakeFailure.<locals>.<lambda>TNc                      s   t  S r9   r3   r>   )serverConnectionLostr>   r?   rd     s   Fc                 S   s   | j t d S r9   )lostConnectionReasontrapr   )rk   r>   r>   r?   cbConnectionLost  s    zATLSMemoryBIOTests.test_handshakeFailure.<locals>.cbConnectionLost)r(   r*   rk   r7   r
   rm   r-   r   r   Z
getContentr   ZloadPEMr   r/   addCallbackr)   )r<   rp   r   rq   r   r   ZcertificateDataZcertificater   r   r   r   r>   )r   r   r?   test_handshakeFailure  sB    
  



  



 z'TLSMemoryBIOTests.test_handshakeFailurec           	         s|   t  }t|_t \}}t|d|}|dt }t|_t }t|d|}|d}t	|  fdd}|
| |S )z
        L{TLSMemoryBIOProtocol.getPeerCertificate} returns the
        L{OpenSSL.crypto.X509Type} instance representing the peer's
        certificate.
        TNFc                    s*     } |t  |dd d S )NZsha1s;   23:4B:72:99:2E:5D:5E:2B:02:C3:BC:1B:7C:50:67:05:4F:60:FF:C9)r   r   r   rx   Zdigest)ignoredZcertr<   r   r>   r?   cbHandshook  s    z>TLSMemoryBIOTests.test_getPeerCertificate.<locals>.cbHandshook)r*   r,   rk   r7   rC   r
   rm   r-   r   r/   r   )	r<   rp   r   r   rq   r   r   r   r   r>   r   r?   test_getPeerCertificate  s.      
  


z)TLSMemoryBIOTests.test_getPeerCertificatec                    s   dt   t } fdd|_t \}}t|d|}|d}ttt	 }fdd|_t
 }t|d|}|d}t|| fdd	}	||	 fd
d}
||
 |S )
        Bytes written to L{TLSMemoryBIOProtocol} before the handshake is
        complete are received by the protocol on the other side of the
        connection once the handshake succeeds.
        
   some bytesc                      s    S r9   r>   r>   rb   r>   r?   rd   "  re   z<TLSMemoryBIOTests.test_writeAfterHandshake.<locals>.<lambda>TNc                      s    S r9   r>   r>   serverProtocolr>   r?   rd   ,  re   Fc                    s    j  S r9   rX   r   r   )rc   r   r[   r>   r?   r   6  s    z?TLSMemoryBIOTests.test_writeAfterHandshake.<locals>.cbHandshookc                    s    dj  d S Nre   rx   joinrQ   r   r[   r<   r   r>   r?   cbDisconnected?  s    zBTLSMemoryBIOTests.test_writeAfterHandshake.<locals>.cbDisconnected)r,   r*   rk   r7   rC   r
   rm   rO   rW   r-   r   r/   r   )r<   rp   r   r   rq   r   r   r   r   r   r   r>   )rc   r   r[   r<   r   r?   test_writeAfterHandshake  s8      
  



z*TLSMemoryBIOTests.test_writeAfterHandshakec                    s   t  }||_t \}}t|d|}|d}tt t }fdd|_t	 }	t|	d|}|d}
t
|
|} fdd}|| |S )z{
        Run test where client sends data before handshake, given the sending
        protocol and expected bytes.
        TNc                      s    S r9   r>   r>   r   r>   r?   rd   V  re   z<TLSMemoryBIOTests.writeBeforeHandshakeTest.<locals>.<lambda>Fc                    s    dj  d S r   r   r   r   r>   r?   cbConnectionDonea  s    zDTLSMemoryBIOTests.writeBeforeHandshakeTest.<locals>.cbConnectionDone)r*   rk   r7   rC   r
   rm   rO   rW   r-   r   r/   r   )r<   ZsendingProtocolr[   rp   r   r   rq   r   r   r   r   r   r   r>   r   r?   writeBeforeHandshakeTestF  s0      
  


z*TLSMemoryBIOTests.writeBeforeHandshakeTestc                    s$   d G  fdddt }| | S )r   r   c                       s   e Zd Z fddZdS )zJTLSMemoryBIOTests.test_writeBeforeHandshake.<locals>.SimpleSendingProtocolc                    s   | j   d S r9   r   rR   r[   r>   r?   rS   p  s    zYTLSMemoryBIOTests.test_writeBeforeHandshake.<locals>.SimpleSendingProtocol.connectionMadeNrJ   rK   rL   rS   r>   r   r>   r?   SimpleSendingProtocolo  s   r   r,   r   r<   r   r>   r   r?   test_writeBeforeHandshakeg  s    z+TLSMemoryBIOTests.test_writeBeforeHandshakec                    s$   d G  fdddt }| | S )z
        Bytes written to L{TLSMemoryBIOProtocol} with C{writeSequence} are
        received by the protocol on the other side of the connection.
        r   c                       s   e Zd Z fddZdS )zCTLSMemoryBIOTests.test_writeSequence.<locals>.SimpleSendingProtocolc                    s   | j tt  d S r9   rX   writeSequencelistr   rR   r   r>   r?   rS   }  s    zRTLSMemoryBIOTests.test_writeSequence.<locals>.SimpleSendingProtocol.connectionMadeNr   r>   r   r>   r?   r   |  s   r   r   r   r>   r   r?   test_writeSequencev  s    z$TLSMemoryBIOTests.test_writeSequencec                    s$   d G  fdddt }| | S )z
        Bytes written to L{TLSMemoryBIOProtocol} after C{loseConnection} is
        called are not transmitted (unless there is a registered producer,
        which will be tested elsewhere).
        r   c                       s   e Zd Z fddZdS )zNTLSMemoryBIOTests.test_writeAfterLoseConnection.<locals>.SimpleSendingProtocolc                    s4   | j   | j   | j d | j dg d S )N   hello   world)rX   r   rY   r   rR   r   r>   r?   rS     s    
z]TLSMemoryBIOTests.test_writeAfterLoseConnection.<locals>.SimpleSendingProtocol.connectionMadeNr   r>   r   r>   r?   r     s   r   r   r   r>   r   r?   test_writeAfterLoseConnection  s    z/TLSMemoryBIOTests.test_writeAfterLoseConnectionc                    s>   d g G  fdddt }|d}|fddS )zV
        Writing C{unicode} to L{TLSMemoryBIOProtocol} throws a C{TypeError}.
        Zhelloc                       s   e Zd Z fddZdS )zQTLSMemoryBIOTests.test_writeUnicodeRaisesTypeError.<locals>.SimpleSendingProtocolc                    sJ   z| j   W n tk
r.   d Y nX | j d | j   d S )NT   bytes)rX   r   	TypeErrorrT   rY   rR   notBytesresultr>   r?   rS     s    z`TLSMemoryBIOTests.test_writeUnicodeRaisesTypeError.<locals>.SimpleSendingProtocol.connectionMadeNr   r>   r   r>   r?   r     s   r   r   c                    s     dgS r   )rx   ign)r   r<   r>   r?   rd     re   zDTLSMemoryBIOTests.test_writeUnicodeRaisesTypeError.<locals>.<lambda>)r,   r   r   )r<   r   dr>   )r   r   r<   r?    test_writeUnicodeRaisesTypeError  s
    z2TLSMemoryBIOTests.test_writeUnicodeRaisesTypeErrorc              	      s   ddddddddd	g	 G  fd
ddt }t }||_t }t|d|}|d}tttt	 t
 }fdd|_t }t|d|}|d}t||t}	 fdd}
|	|
 |	S )z
        If multiple separate TLS messages are received in a single chunk from
        the underlying transport, all of the application bytes from each
        message are delivered to the application-level protocol.
           a   b   c   d   e   f   g   h   ic                       s   e Zd Z fddZdS )zDTLSMemoryBIOTests.test_multipleWrites.<locals>.SimpleSendingProtocolc                    s    D ]}| j | qd S r9   r   )r<   br   r>   r?   rS     s    zSTLSMemoryBIOTests.test_multipleWrites.<locals>.SimpleSendingProtocol.connectionMadeNr   r>   r   r>   r?   r     s   r   TNc                      s    S r9   r>   r>   r   r>   r?   rd     re   z7TLSMemoryBIOTests.test_multipleWrites.<locals>.<lambda>Fc                    s    djd  d S r   r   r   r   r>   r?   r     s    z?TLSMemoryBIOTests.test_multipleWrites.<locals>.cbConnectionDone)r,   r*   rk   r7   r
   rm   rO   rU   rV   rW   r-   r   r/   r0   r   )r<   r   rp   r   rq   r   r   r   r   r   r   r>   r   r?   test_multipleWrites  s2      
  

z%TLSMemoryBIOTests.test_multipleWritesc                    s   d dG  fdddt }t }||_t|d}t|d|}|d}tt  t }fdd	|_t	|d}t|d
|}|d}	t
|	|}
 fdd}|
| |
S )z
        If a very long string is passed to L{TLSMemoryBIOProtocol.write}, any
        trailing part of it which cannot be send immediately is buffered and
        sent later.
        r   i   c                       s   e Zd Z fddZdS )z:TLSMemoryBIOTests.hugeWrite.<locals>.SimpleSendingProtocolc                    s   | j    d S r9   r   rR   r[   factorr>   r?   rS     s    zITLSMemoryBIOTests.hugeWrite.<locals>.SimpleSendingProtocol.connectionMadeNr   r>   r   r>   r?   r     s   r   r=   TNc                      s    S r9   r>   r>   r   r>   r?   rd     re   z-TLSMemoryBIOTests.hugeWrite.<locals>.<lambda>Fc                    s    dj   d S r   r   r   r[   r   r<   r   r>   r?   r     s    z5TLSMemoryBIOTests.hugeWrite.<locals>.cbConnectionDone)r,   r*   rk   r7   r
   rm   rO   rW   r-   r   r/   r   )r<   r=   r   rp   r   rq   r   r   r   r   r   r   r>   r   r?   	hugeWrite  s4    
  

  


zTLSMemoryBIOTests.hugeWritec                 C   s   |   S r9   )r   rR   r>   r>   r?   test_hugeWrite_TLSv1  s    z&TLSMemoryBIOTests.test_hugeWrite_TLSv1c                 C   s   | j tdS Nr   )r   r   rR   r>   r>   r?   test_hugeWrite_TLSv1_1  s    z(TLSMemoryBIOTests.test_hugeWrite_TLSv1_1c                 C   s   | j tdS r   )r   r   rR   r>   r>   r?   test_hugeWrite_TLSv1_2  s    z(TLSMemoryBIOTests.test_hugeWrite_TLSv1_2c                    sf   t   t } fdd|_t }t|d|}|d}t }t|| |j	  dd } 
|  S )z~
        If a L{TLSMemoryBIOProtocol} loses its connection unexpectedly, this is
        reported to the application.
        c                      s   t  S r9   r3   r>   r   r>   r?   rd     s   z;TLSMemoryBIOTests.test_disorderlyShutdown.<locals>.<lambda>TNc                 S   s   | j tt d S r9   )r   r   r   r'   rb   r>   r>   r?   r     s    zATLSMemoryBIOTests.test_disorderlyShutdown.<locals>.cbDisconnected)r(   r*   rk   r7   r
   rm   r,   r/   rX   rY   r   )r<   rp   r   rq   r   r   r   r>   r   r?   test_disorderlyShutdown  s"    
  



z)TLSMemoryBIOTests.test_disorderlyShutdownc                    s   G dd dt }t t }|fdd|_t \}}t|d|}|d}t |t }fdd|_t	 }t|d|}|d}	t
|	| d	d
   fdd}
||
  fdd}|| |S )z
        L{TLSMemoryBIOProtocol.loseConnection} sends a TLS close alert and
        shuts down the underlying connection cleanly on both sides, after
        transmitting all buffered data.
        c                   @   s   e Zd Zdd Zdd ZdS )zNTLSMemoryBIOTests.test_loseConnectionAfterHandshake.<locals>.NotifyingProtocolc                 S   s   t | | g | _d S r9   )r4   r@   r[   )r<   ZonConnectionLostr>   r>   r?   r@   !  s    zWTLSMemoryBIOTests.test_loseConnectionAfterHandshake.<locals>.NotifyingProtocol.__init__c                 S   s   | j | d S r9   )r[   rT   rZ   r>   r>   r?   r\   &  s    z[TLSMemoryBIOTests.test_loseConnectionAfterHandshake.<locals>.NotifyingProtocol.dataReceivedN)rJ   rK   rL   r@   r\   r>   r>   r>   r?   NotifyingProtocol   s   r   c                      s    S r9   r>   r>   rb   r>   r?   rd   ,  re   zETLSMemoryBIOTests.test_loseConnectionAfterHandshake.<locals>.<lambda>TNc                      s    S r9   r>   r>   r   r>   r?   rd   7  re   Fs	   123456890i c                    s.   j   j d j   tgS )N   x)rX   r   rY   r)   r   )chunkOfBytesr   rc   r   r   r>   r?   cbHandshakeB  s    
zHTLSMemoryBIOTests.test_loseConnectionAfterHandshake.<locals>.cbHandshakec                    sX   | \}}|j t |j t d|j  |jjj	 |jjj	 d S r   )
r   r   r&   rx   r   r[   r   rX   qZ
disconnect)r   rc   r   )r  r<   r>   r?   r   T  s    zMTLSMemoryBIOTests.test_loseConnectionAfterHandshake.<locals>.cbConnectionDone)r4   r(   r*   rk   r7   rC   r
   rm   r-   r   r/   r   )r<   r   rp   r   r   rq   r   r   r   r   r  r   r>   )r  r   rc   r<   r   r   r?   !test_loseConnectionAfterHandshake  s>    	  
  



z3TLSMemoryBIOTests.test_loseConnectionAfterHandshakec                 C   s   G dd dt }tt dt }| }t||}t }|| |d | |j	 | 
|j |ttd | |jt | |jjjd dS )zz
        The user protocol's connectionLost is only called when transport
        underlying TLS is disconnected.
        c                   @   s   e Zd ZdZdd ZdS )zTTLSMemoryBIOTests.test_connectionLostOnlyAfterUnderlyingCloses.<locals>.LostProtocolNc                 S   s
   || _ d S r9   )disconnectedr_   r>   r>   r?   ra   o  s    zcTLSMemoryBIOTests.test_connectionLostOnlyAfterUnderlyingCloses.<locals>.LostProtocol.connectionLost)rJ   rK   rL   r  ra   r>   r>   r>   r?   LostProtocolm  s   r  TNono)r  )r,   r
   r   r*   r	   r5   rn   Z_tlsShutdownFinishedr   disconnectingassertIsNoner  ra   r   r'   r]   rx   valueargs)r<   r  rq   rk   rf   rX   r>   r>   r?   ,test_connectionLostOnlyAfterUnderlyingClosesh  s     


z>TLSMemoryBIOTests.test_connectionLostOnlyAfterUnderlyingClosesc                    s|   |   \}}}}| | g  |jf fdd	}||_|d |  | |j |  dg |  |  dg |S )z
        If TLSMemoryBIOProtocol.loseConnection is called multiple times, all
        but the first call have no effect.
        c                    s     d |  S N   rT   Zshutdowncallsr>   r?   _shutdownTLS  s    
z@TLSMemoryBIOTests.test_loseConnectionTwice.<locals>._shutdownTLSr   r  )r   ZsuccessResultOfr  r   rY   r   r  rx   )r<   r   r   r   disconnectDeferredr  r>   r  r?   test_loseConnectionTwice  s    


z*TLSMemoryBIOTests.test_loseConnectionTwicec                    s\     \}}}g  |jf fdd	}|_d |   fdd}|| |S )zq
        If TLSMemoryBIOProtocol.loseConnection is called after connectionLost,
        it does nothing.
        c                    s     d |  S r  r  r  r  r>   r?   r    s    
zNTLSMemoryBIOTests.test_loseConnectionAfterConnectionLost.<locals>._shutdownTLSr   c                    s(     dg     dg d S r  )rx   rY   r   r  r<   r   r>   r?   r    s    zNTLSMemoryBIOTests.test_loseConnectionAfterConnectionLost.<locals>.disconnected)r   r  r   rY   r   )r<   r   r   r  r  r  r>   r  r?   &test_loseConnectionAfterConnectionLost  s    


z8TLSMemoryBIOTests.test_loseConnectionAfterConnectionLostc                    s`     \}}}|j}g }g  |j|_ j|_fdd}||  fdd}|| |S )zP
        Unexpected disconnects get converted to ConnectionLost errors.
        c                    s     d  j  d S Nr   )r   rX   rY   r   r   r>   r?   handshakeDone  s    
z;TLSMemoryBIOTests.test_unexpectedEOF.<locals>.handshakeDonec                    s     d t d  d S Nr   )r   r]   r'   r   r`   r<   r>   r?   r    s    z:TLSMemoryBIOTests.test_unexpectedEOF.<locals>.disconnected)r   r   rT   r\   ra   r   )r<   r   r   r  r   r[   r  r  r>   r`   r<   r   r?   test_unexpectedEOF  s    


z$TLSMemoryBIOTests.test_unexpectedEOFc                    sl     \}}}g   jj_G dd dt}|j_fdd}||  fdd}|| |S )zN
        Errors while writing cause the protocols to be disconnected.
        c                   @   s$   e Zd Zdd Zdd Zdd ZdS )z4TLSMemoryBIOTests.test_errorWriting.<locals>.Wrapperc                 S   s
   || _ d S r9   )_wrapped)r<   wrappedr>   r>   r?   r@     s    z=TLSMemoryBIOTests.test_errorWriting.<locals>.Wrapper.__init__c                 S   s   t | j|S r9   )getattrr   )r<   attrr>   r>   r?   __getattr__  s    z@TLSMemoryBIOTests.test_errorWriting.<locals>.Wrapper.__getattr__c                 W   s   t dd S )NzONO!)r   )r<   r  r>   r>   r?   send  s    z9TLSMemoryBIOTests.test_errorWriting.<locals>.Wrapper.sendN)rJ   rK   rL   r@   r$  r%  r>   r>   r>   r?   Wrapper  s   r&  c                    s     d d S r  )r   r   r  r>   r?   r    s    z:TLSMemoryBIOTests.test_errorWriting.<locals>.handshakeDonec                    s     d t d  d S r  )r   r]   r   r   r  r>   r?   r    s    z9TLSMemoryBIOTests.test_errorWriting.<locals>.disconnected)r   rT   r   ra   rl   _tlsConnectionr   )r<   r   r   r  r&  r  r  r>   r  r?   test_errorWriting  s    



z#TLSMemoryBIOTests.test_errorWritingc                 C   s   dd }|  tj t  G dd dt}G dd dt}|t}||}t \}}t| dt	
|}ttd|d	d
t	
|}	tt|| t|	|  |t}
||}| |
| | || dS )z
        TLSMemoryBIOProtocol doesn't leave circular references that keep
        it in memory after connection is closed.
        c                    s   t  fddt D S )z
            Return the number of instances of a given type in memory.

            @param type: Type whose instances to find.

            @return: The number of instances found.
            c                 3   s   | ]}t | rd V  qdS )r  N)
isinstance).0xtyper>   r?   	<genexpr>  s     
 zVTLSMemoryBIOTests.test_noCircularReferences.<locals>.nObjectsOfType.<locals>.<genexpr>)rU   gcZget_objectsr,  r>   r,  r?   nObjectsOfType  s    zCTLSMemoryBIOTests.test_noCircularReferences.<locals>.nObjectsOfTypec                   @   s   e Zd Zdd ZdS )zCTLSMemoryBIOTests.test_noCircularReferences.<locals>.CloserProtocolc                 S   s   | j   d S r9   )rX   rY   rZ   r>   r>   r?   r\     s    zPTLSMemoryBIOTests.test_noCircularReferences.<locals>.CloserProtocol.dataReceivedN)rJ   rK   rL   r\   r>   r>   r>   r?   CloserProtocol  s   r1  c                   @   s   e Zd Zdd ZdS )zDTLSMemoryBIOTests.test_noCircularReferences.<locals>.GreeterProtocolc                 S   s   | j d d S r  r   rR   r>   r>   r?   rS     s    zSTLSMemoryBIOTests.test_noCircularReferences.<locals>.GreeterProtocol.connectionMadeNr   r>   r>   r>   r?   GreeterProtocol  s   r2  Fr   r   TN)rv   r/  enabledisabler,   r	   r   r
   r   r+   r   r   r/   rx   )r<   r0  r1  r2  ZorigTLSProtosZorigServerProtosr   r   r   rp   ZnewTLSProtosZnewServerProtosr>   r>   r?   test_noCircularReferences  s4    

 
 

z+TLSMemoryBIOTests.test_noCircularReferencesN) rJ   rK   rL   rM   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r  r(  r5  r>   r>   r>   r?   r   C  s8   
2'.!'&Nr   c                   @   s   e Zd ZdZd.d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d d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- ZdS )0TLSProducerTestszA
    The TLS transport must support the IConsumer interface.
    Fc                 C   s(   |  }|  | t|p|d |S )a  
        Drain the bytes currently pending write from a L{StringTransport}, then
        clear it, since those bytes have been consumed.

        @param transport: The L{StringTransport} to get the bytes from.
        @type transport: L{StringTransport}

        @param allowEmpty: Allow the test to pass even if the transport has no
            outgoing bytes in it.
        @type allowEmpty: L{bool}

        @return: the outgoing bytes from the given transport
        @rtype: L{bytes}
        T)r
  clearrx   bool)r<   rX   Z
allowEmptyr
  r>   r>   r?   drain2  s    zTLSProducerTests.drainNc                 C   sN   G dd dt }t|||d\}}| }|j|d | |jj |||fS )Nc                   @   s,   e Zd Zdd Zdd Zdd Zdd Zd	S )
zGTLSProducerTests.setupStreamingProducer.<locals>.HistoryStringTransportc                 S   s   t |  g | _d S r9   )r5   r@   producerHistoryrR   r>   r>   r?   r@   J  s    
zPTLSProducerTests.setupStreamingProducer.<locals>.HistoryStringTransport.__init__c                 S   s   | j d t|  d S )Npause)r:  rT   r5   pauseProducingrR   r>   r>   r?   r<  N  s    zVTLSProducerTests.setupStreamingProducer.<locals>.HistoryStringTransport.pauseProducingc                 S   s   | j d t|  d S )Nresume)r:  rT   r5   resumeProducingrR   r>   r>   r?   r>  R  s    zWTLSProducerTests.setupStreamingProducer.<locals>.HistoryStringTransport.resumeProducingc                 S   s   | j d t|  d S )Nstop)r:  rT   r5   stopProducingrR   r>   r>   r?   r@  V  s    zUTLSProducerTests.setupStreamingProducer.<locals>.HistoryStringTransport.stopProducingN)rJ   rK   rL   r@   r<  r>  r@  r>   r>   r>   r?   HistoryStringTransportI  s   rA  )rX   rh   ro   T)r5   rs   rX   registerProducerr   	streaming)r<   rX   rh   ro   rA  ZapplicationProtocolrf   producerr>   r>   r?   setupStreamingProducerG  s     
z'TLSProducerTests.setupStreamingProducerc                 C   sz   t dD ]H}| |jd}|r(|| | |jd}|rD|| |s|s qRq| |j d | |j d dS )zJ
        Transfer bytes back and forth between two TLS protocols.
           Tre   N)ranger9  rX   r\   rx   r
  )r<   rf   serverTLSProtocoliZ
clientDataZ
serverDatar>   r>   r?   flushTwoTLSProtocolsc  s    

z%TLSProducerTests.flushTwoTLSProtocolsc                 C   s,  |   \}}}| j dd\}}}| || |j}|  | t|j |  || 	|j
 d}|j
| |j
  || 	|j
 | 	|j
}	|	dd |	dd |	dd fD ]}
||
 q| |j
jd |j
  | || | |j
jd | d	|j| | |jd
dg dS )z
        If we write some data to a TLS connection that is blocked waiting for a
        renegotiation with its peer, it will pause and resume its registered
        producer exactly once.
        Tro   s   payloadr   r     NFre   r;  r=  )rE  rJ  r'  ZrenegotiateassertRaisesr   do_handshakeZ_flushSendBIOr\   r9  rX   r   rY   rx   r  unregisterProducerr   rQ   r:  )r<   cZctcpsstZspZtlscZpayloadZmessageThatUnblocksTheServerZfragmentr>   r>   r?    test_producerDuringRenegotiationv  s0    




z1TLSProducerTests.test_producerDuringRenegotiationc                 C   sJ   |   \}}}|jj  | |jd | |jdg | |jj	 dS )z
        When the TLS transport is not blocked on reads, it correctly calls
        pauseProducing on the registered producer.
        pausedr;  N)
rE  rX   rD  r<  rx   producerStater:  r   	_producer_producerPausedr<   r   rf   rD  r>   r>   r?   (test_streamingProducerPausedInNormalMode  s
    z9TLSProducerTests.test_streamingProducerPausedInNormalModec                 C   sh   |   \}}}|jj  | |jdg |jj  | |jd | |jddg | |j	j
 dS )z
        When the TLS transport is not blocked on reads, it correctly calls
        resumeProducing on the registered producer.
        r;  	producingr=  N)rE  rX   rD  r<  rx   r:  r>  rV  assertFalserW  rX  rY  r>   r>   r?   )test_streamingProducerResumedInNormalMode  s    z:TLSProducerTests.test_streamingProducerResumedInNormalModec                 C   sJ   |   \}}}|jd | |jd | |jdg | |jj dS )z
        When the TLS transport is blocked on reads, it correctly calls
        pauseProducing on the registered producer.
        r   rU  r;  N)	rE  rX   r   rx   rV  r:  r   rW  rX  r<   rc   rf   rD  r>   r>   r?   4test_streamingProducerPausedInWriteBlockedOnReadMode  s
    zETLSProducerTests.test_streamingProducerPausedInWriteBlockedOnReadModec                 C   s   |   \}}}|jdd  | |jdg tdd\}}| || | |jddg | |jj	 | |jj
 | |jd dS )	z
        When the TLS transport is blocked on reads, it correctly calls
        resumeProducing on the registered producer.
        s   hello worldi  r;  TrK  r=  r[  N)rE  rX   r   rx   r:  rs   rJ  r\  rW  rX  r  rV  )r<   rc   rf   rD  r   rH  r>   r>   r?   5test_streamingProducerResumedInWriteBlockedOnReadMode  s    zFTLSProducerTests.test_streamingProducerResumedInWriteBlockedOnReadModec                 C   s@   |   \}}}|j}t }| t|jj|d | |j| dS )zM
        Registering a streaming producer twice throws an exception.
        TN)rE  rW  rl   rM  RuntimeErrorrX   rB  r   )r<   rc   rf   rD  ZoriginalProducerZ	producer2r>   r>   r?   test_streamingProducerTwice  s      z,TLSProducerTests.test_streamingProducerTwicec                 C   s6   |   \}}}|j  | |j | |jj dS )z\
        Unregistering a streaming producer removes it, reverting to initial state.
        NrE  rX   rO  r	  rW  rD  r^  r>   r>   r?    test_streamingProducerUnregister  s    
z1TLSProducerTests.test_streamingProducerUnregisterc                 C   s@   |   \}}}|j  |j  | |j | |jj dS )zd
        Unregistering a streaming producer when no producer is registered is
        safe.
        Nrc  r^  r>   r>   r?   %test_streamingProducerUnregisterTwice  s
    

z6TLSProducerTests.test_streamingProducerUnregisterTwicec                 C   s   |   \}}}tdd\}}|s.| || n |jd |j  | || | |jj | d|jk |jd |j	ddg |j
  | |j d | |jj |jd	 |j	d
g | || | |jj | d|jd dS )zl
        Common code for tests involving writes by producer after
        loseConnection is called.
        TrK  s   x r?  r       r   re   s   won'ts   won't!s   x hello worldN)rE  rs   rJ  rX   r   rY   r\  r  r:  r   rO  ZassertNotEqualr
  r   rx   r   rQ   )r<   ZwriteBlockedOnReadrc   rf   rD  r   rH  r>   r>   r?   loseConnectionWithProducer  s&    

z+TLSProducerTests.loseConnectionWithProducerc                 C   s
   |  dS )z
        loseConnection() waits for the producer to unregister itself, then
        does a clean TLS close alert, then closes the underlying connection.
        Frg  rR   r>   r>   r?   0test_streamingProducerLoseConnectionWithProducer9  s    zATLSProducerTests.test_streamingProducerLoseConnectionWithProducerc                 C   s
   |  dS )z
        Even when writes are blocked on reading, loseConnection() waits for
        the producer to unregister itself, then does a clean TLS close alert,
        then closes the underlying connection.
        Trh  rR   r>   r>   r?   4test_streamingProducerLoseConnectionWithProducerWBORA  s    zETLSProducerTests.test_streamingProducerLoseConnectionWithProducerWBORc                 C   s   G dd dt }G dd dt}| }| j|| d\}}}| |jd |jd | |jd | |jd	g |jj	  | |jd | |jd	d
g |
d | |jd | |jd	d
g dS )z
        pauseProducing() events can come from both the TLS transport layer and
        the underlying transport. In this case, both decide to pause,
        underlying first.
        c                   @   s   e Zd ZdZdd ZdS )zbTLSProducerTests.test_streamingProducerBothTransportsDecideToPause.<locals>.PausingStringTransportFc                 S   s0   | j s | jd k	r d| _ | j  t| | d S r   )	_didPauserD  r<  r5   r   rZ   r>   r>   r?   r   S  s    
zhTLSProducerTests.test_streamingProducerBothTransportsDecideToPause.<locals>.PausingStringTransport.writeN)rJ   rK   rL   rk  r   r>   r>   r>   r?   PausingStringTransportP  s   rl  c                   @   sD   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd Zdd Z	dS )zYTLSProducerTests.test_streamingProducerBothTransportsDecideToPause.<locals>.TLSConnectionc                 S   s
   g | _ d S r9   )lrR   r>   r>   r?   r@   [  s    zbTLSProducerTests.test_streamingProducerBothTransportsDecideToPause.<locals>.TLSConnection.__init__c                 S   sF   | j s|d d }t| j dkr2| j d t | j | t|S )Nr  rU  )rm  rW   rT   r   rZ   r>   r>   r?   r%  ^  s    z^TLSProducerTests.test_streamingProducerBothTransportsDecideToPause.<locals>.TLSConnection.sendc                 S   s   d S r9   r>   rR   r>   r>   r?   set_connect_statej  s    zkTLSProducerTests.test_streamingProducerBothTransportsDecideToPause.<locals>.TLSConnection.set_connect_statec                 S   s   d S r9   r>   rR   r>   r>   r?   rN  m  s    zfTLSProducerTests.test_streamingProducerBothTransportsDecideToPause.<locals>.TLSConnection.do_handshakec                 S   s   d S r9   r>   rZ   r>   r>   r?   	bio_writep  s    zcTLSProducerTests.test_streamingProducerBothTransportsDecideToPause.<locals>.TLSConnection.bio_writec                 S   s   dS )N   Xr>   r<   sizer>   r>   r?   bio_reads  s    zbTLSProducerTests.test_streamingProducerBothTransportsDecideToPause.<locals>.TLSConnection.bio_readc                 S   s
   t  d S r9   )r   rr  r>   r>   r?   recvv  s    z^TLSProducerTests.test_streamingProducerBothTransportsDecideToPause.<locals>.TLSConnection.recvN)
rJ   rK   rL   r@   r%  ro  rN  rp  rt  ru  r>   r>   r>   r?   TLSConnectionZ  s   rv  rg   r[  r   rU  r;  r=  N)r5   rl   rE  rx   rV  rX   r   r:  rD  r>  r\   )r<   rl  rv  rX   rc   rf   rD  r>   r>   r?   1test_streamingProducerBothTransportsDecideToPauseJ  s"    
 
zBTLSProducerTests.test_streamingProducerBothTransportsDecideToPausec                 C   s,   |   \}}}|jj  | |jd dS )z
        If the underlying transport tells its producer to stopProducing(),
        this is passed on to the high-level producer.
        stoppedN)rE  rX   rD  r@  rx   rV  rY  r>   r>   r?   #test_streamingProducerStopProducing  s    z4TLSProducerTests.test_streamingProducerStopProducingc                    s   t  \}t|j |j d jjjt j  j	|j 
jj  fdd} j| t dd\}}|  jS )zM
        Non-streaming producers get wrapped as streaming producers.
        Fc                    s*     j  jj j d S r9   )r	  consumerrX   rD  r   r:   ignorerD  r<   streamingProducerrf   r>   r?   done  s    z8TLSProducerTests.test_nonStreamingProducer.<locals>.doneTrK  )rs   r6   rX   rB  rD  rW  r   r   rx   Z	_consumerr   rC  r   r   rJ  )r<   rc   r  r   rH  r>   r}  r?   test_nonStreamingProducer  s    


z*TLSProducerTests.test_nonStreamingProducerc                 C   s"   t  }t|}| tt| dS )zC
        L{_ProducerMembrane} implements L{IPushProducer}.
        N)r5   r   r   r   r!   )r<   rD  Zmembraner>   r>   r?   test_interface  s    zTLSProducerTests.test_interfacec                 C   sd   t  \}}dd |_G dd dt}|tt  | }||d | |jj | 	|j
 dS )z
        If a producer is registered after the transport has disconnected, the
        producer is not used, and its stopProducing method is called.
        c                 S   s   |  ttS r9   )r   r   r'   r`   r>   r>   r?   rd     s    zFTLSProducerTests.registerProducerAfterConnectionLost.<locals>.<lambda>c                   @   s    e Zd ZdZdd Zdd ZdS )zFTLSProducerTests.registerProducerAfterConnectionLost.<locals>.ProducerFc                 S   s   dd S )Nr  r   r>   rR   r>   r>   r?   r>    s    zVTLSProducerTests.registerProducerAfterConnectionLost.<locals>.Producer.resumeProducingc                 S   s
   d| _ d S r   )rx  rR   r>   r>   r?   r@    s    zTTLSProducerTests.registerProducerAfterConnectionLost.<locals>.Producer.stopProducingN)rJ   rK   rL   rx  r>  r@  r>   r>   r>   r?   Producer  s   r  FN)rs   ra   rl   r   r&   rB  r	  rX   rD  r   rx  )r<   rC  rc   rf   r  rD  r>   r>   r?   #registerProducerAfterConnectionLost  s    


z4TLSProducerTests.registerProducerAfterConnectionLostc                 C   s   |  d dS )z
        If a streaming producer is registered after the transport has
        disconnected, the producer is not used, and its stopProducing method
        is called.
        TNr  rR   r>   r>   r?   )test_streamingProducerAfterConnectionLost  s    z:TLSProducerTests.test_streamingProducerAfterConnectionLostc                 C   s   |  d dS )z
        If a non-streaming producer is registered after the transport has
        disconnected, the producer is not used, and its stopProducing method
        is called.
        FNr  rR   r>   r>   r?   ,test_nonStreamingProducerAfterConnectionLost  s    z=TLSProducerTests.test_nonStreamingProducerAfterConnectionLost)F)NNF)rJ   rK   rL   rM   r9  rE  rJ  rT  rZ  r]  r_  r`  rb  rd  re  rg  ri  rj  rw  ry  r  r  r  r  r  r>   r>   r>   r?   r6  -  s0   
  
%
1	G
 		r6  c                   @   s`   e Zd Z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S )NonStreamingProducerTestszP
    Non-streaming producers can be adapted into being streaming producers.
    c                    sb   t  }t|  d  jffdd	}| _|j} fdd}||   |S )zd
        Verify the consumer writes out all its data, but is not called after
        that.
        Tc                    s   |       d S r9   stopStreamingZorigr~  r>   r?   
unregister  s    z<NonStreamingProducerTests.streamUntilEnd.<locals>.unregisterc                    s,      d  j j d S )Ns
   0123456789)rx   r
  r	  rD  r   r:   r  rz  r<   r~  r>   r?   doneStreaming  s    z?NonStreamingProducerTests.streamUntilEnd.<locals>.doneStreaming)r6   r   rB  rO  r   r   startStreaming)r<   rz  
nsProducerr  r  r  r>   r  r?   streamUntilEnd  s    

z(NonStreamingProducerTests.streamUntilEndc                 C   s   t  }| |S )z
        When converted to a streaming producer, the non-streaming producer
        writes out all its data, but is not called after that.
        r5   r  )r<   rz  r>   r>   r?   test_writeUntilDone  s    z-NonStreamingProducerTests.test_writeUntilDonec                    sv   G dd dt }| }t|}t|||d  fdd}|j| |j} fdd}||   |S )z}
        When the streaming producer is paused, the underlying producer stops
        getting resumeProducing calls.
        c                   @   s    e Zd ZdZdd Zdd ZdS )zDNonStreamingProducerTests.test_pause.<locals>.PausingStringTransportr   c                 S   s   t |  t | _d S r9   )r5   r@   r(   rU  rR   r>   r>   r?   r@   *  s    
zMNonStreamingProducerTests.test_pause.<locals>.PausingStringTransport.__init__c                 S   sF   |  j d7  _ t| | | j dkrB| j  | j}| `|d  d S Nr  rF  )writesr5   r   rD  r<  rU  rE   )r<   r[   r   r>   r>   r?   r   .  s    

zJNonStreamingProducerTests.test_pause.<locals>.PausingStringTransport.writeN)rJ   rK   rL   r  r@   r   r>   r>   r>   r?   rl  '  s   rl  Tc                    s     d d S )Nz$BUG: The producer should not finish!)Zfailr{  rR   r>   r?   shouldNotBeCalled>  s    z?NonStreamingProducerTests.test_pause.<locals>.shouldNotBeCalledc                    s     jjd d S r  )rx   	_coopTaskZ_pauseCountr{  r<   r~  r>   r?   rU  C  s    z4NonStreamingProducerTests.test_pause.<locals>.paused)r5   r6   r   rB  r   r   rU  r  )r<   rl  rz  r  r  r  rU  r>   r  r?   
test_pause"  s    

z$NonStreamingProducerTests.test_pausec                 C   s    G dd dt }| }| |S )a  
        When the streaming producer is paused and then resumed, the underlying
        producer starts getting resumeProducing calls again after the resume.

        The test will never finish (or rather, time out) if the resume
        producing call is not working.
        c                   @   s   e Zd ZdZdd ZdS )zENonStreamingProducerTests.test_resume.<locals>.PausingStringTransportr   c                 S   s<   |  j d7  _ t| | | j dkr8| j  | j  d S r  )r  r5   r   rD  r<  r>  rZ   r>   r>   r?   r   X  s
    

zKNonStreamingProducerTests.test_resume.<locals>.PausingStringTransport.writeNrJ   rK   rL   r  r   r>   r>   r>   r?   rl  U  s   rl  r  )r<   rl  rz  r>   r>   r?   test_resumeM  s    
z%NonStreamingProducerTests.test_resumec                    sb   G dd dt }|  t t  d j} fdd}||   |S )z
        When the streaming producer is stopped by the consumer, the underlying
        producer is stopped, and streaming is stopped.
        c                   @   s   e Zd ZdZdd ZdS )zMNonStreamingProducerTests.test_stopProducing.<locals>.StoppingStringTransportr   c                 S   s2   |  j d7  _ t| | | j dkr.| j  d S r  )r  r5   r   rD  r@  rZ   r>   r>   r?   r   k  s    
zSNonStreamingProducerTests.test_stopProducing.<locals>.StoppingStringTransport.writeNr  r>   r>   r>   r?   StoppingStringTransporth  s   r  Tc                    s,      d j j d S )Ns   012)rx   r
  r   rx  r:   r  rz  r  r<   r~  r>   r?   r  w  s    zCNonStreamingProducerTests.test_stopProducing.<locals>.doneStreaming)r5   r6   r   rB  r   r   r  )r<   r  r  r  r>   r  r?   test_stopProducingc  s    	

z,NonStreamingProducerTests.test_stopProducingc                    s   G dd dt }| }t|  d g tj tjj  jffdd	}| _	  j
 }|dd   fdd	}|| |S )
z
        Common implementation for tests where the underlying producer throws
        an exception when its resumeProducing is called.
        c                   @   s   e Zd Zdd ZdS )zINonStreamingProducerTests.resumeProducingRaises.<locals>.ThrowingProducerc                 S   s    | j dkrdd S t|  d S )NrL  r  r   )Zcounterr6   r>  rR   r>   r>   r?   r>    s    
zYNonStreamingProducerTests.resumeProducingRaises.<locals>.ThrowingProducer.resumeProducingN)rJ   rK   rL   r>  r>   r>   r>   r?   ThrowingProducer  s   r  Tc                    s   |       d S r9   r  r  r  r>   r?   r    s    zCNonStreamingProducerTests.resumeProducingRaises.<locals>.unregisterc                 S   s
   |  tS r9   )r   r.   r  r>   r>   r?   rd     re   zANonStreamingProducerTests.resumeProducingRaises.<locals>.<lambda>c                    sx      d  } t|t t|D ].\}\}}}|| ||d  q8j d S )Ns   01Zwhy)	rx   r
  ZflushLoggedErrorsrW   zipr   r]   ZassertInr:   )r   errorsfZexpectedmsgZlogMsgrz  expectedExceptionsZ
loggedMsgsr<   r~  r>   r?   rx    s      z@NonStreamingProducerTests.resumeProducingRaises.<locals>.stopped)r6   r   rB  r   ru   rT   rv   rw   rO  r  r  ZwhenDoneZ
addErrbackr   )r<   rz  r  r  r  r  r  rx  r>   r  r?   resumeProducingRaises  s    


z/NonStreamingProducerTests.resumeProducingRaisesc                    s4   t    tdfg} fdd}|| |S )z
        If the underlying producer raises an exception when resumeProducing is
        called, the streaming wrapper should log the error, unregister from
        the consumer and stop streaming.
        !failed, producing will be stoppedc                    s     j d S r9   )r	  rD  r{  rz  r<   r>   r?   cleanShutdown  s    zKNonStreamingProducerTests.test_resumeProducingRaises.<locals>.cleanShutdown)r5   r  ZeroDivisionErrorr   )r<   r  r  r>   r  r?   test_resumeProducingRaises  s    
z4NonStreamingProducerTests.test_resumeProducingRaisesc                 C   s,   t  }dd }||_| |tdftdfgS )a  
        If the underlying producer raises an exception when resumeProducing is
        called, the streaming wrapper should log the error, unregister from
        the consumer and stop streaming even if the unregisterProducer call
        also raise.
        c                   S   s
   t  d S r9   )ra  r>   r>   r>   r?   raiser  s    z^NonStreamingProducerTests.test_resumeProducingRaiseAndUnregisterProducerRaises.<locals>.raiserr  zfailed to unregister producer)r5   rO  r  r  ra  )r<   rz  r  r>   r>   r?   4test_resumeProducingRaiseAndUnregisterProducerRaises  s    zNNonStreamingProducerTests.test_resumeProducingRaiseAndUnregisterProducerRaisesc                 C   s@   t  }t|}t||}|  |  |  | |j dS )z
        stopStreaming() can be called more than once without blowing
        up. This is useful for error-handling paths.
        N)r5   r6   r   r  r  r   r:   r<   rz  r  r~  r>   r>   r?   test_stopStreamingTwice  s    
z1NonStreamingProducerTests.test_stopStreamingTwicec                 C   s,   t  }t|}t||}| tt| dS )z=
        L{_PullToPush} implements L{IPushProducer}.
        N)r5   r6   r   r   r   r!   r  r>   r>   r?   r    s    
z(NonStreamingProducerTests.test_interfaceN)rJ   rK   rL   rM   r  r  r  r  r  r  r  r  r  r  r>   r>   r>   r?   r    s    	+!0r  c                   @   s    e Zd ZdZdd Zdd ZdS )ClientNegotiationFactoryza
    A L{ClientFactory} that has a set of acceptable protocols for NPN/ALPN
    negotiation.
    c                 C   s
   || _ dS )z
        Create a L{ClientNegotiationFactory}.

        @param acceptableProtocols: The protocols the client will accept
            speaking after the TLS handshake is complete.
        @type acceptableProtocols: L{list} of L{bytes}
        NZ_acceptableProtocolsr<   acceptableProtocolsr>   r>   r?   r@     s    z!ClientNegotiationFactory.__init__c                 C   s   | j S a  
        Returns a list of protocols that can be spoken by the connection
        factory in the form of ALPN tokens, as laid out in the IANA registry
        for ALPN tokens.

        @return: a list of ALPN tokens in order of preference.
        @rtype: L{list} of L{bytes}
        r  rR   r>   r>   r?   r     s    	z,ClientNegotiationFactory.acceptableProtocolsNrJ   rK   rL   rM   r@   r  r>   r>   r>   r?   r    s   r  c                   @   s    e Zd ZdZdd Zdd ZdS )ServerNegotiationFactoryza
    A L{ServerFactory} that has a set of acceptable protocols for NPN/ALPN
    negotiation.
    c                 C   s
   || _ dS )z
        Create a L{ServerNegotiationFactory}.

        @param acceptableProtocols: The protocols the server will accept
            speaking after the TLS handshake is complete.
        @type acceptableProtocols: L{list} of L{bytes}
        Nr  r  r>   r>   r?   r@     s    z!ServerNegotiationFactory.__init__c                 C   s   | j S r  r  rR   r>   r>   r?   r    s    	z,ServerNegotiationFactory.acceptableProtocolsNr  r>   r>   r>   r?   r    s   r  c                   @   s8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS ) IProtocolNegotiationFactoryTestsa  
    Tests for L{IProtocolNegotiationFactory} inside L{TLSMemoryBIOFactory}.

    These tests expressly don't include the case where both server and client
    advertise protocols but don't have any overlap. This is because the
    behaviour here is platform-dependent and changes from version to version.
    Prior to version 1.1.0 of OpenSSL, failing the ALPN negotiation does not
    fail the handshake. At least in 1.0.2h, failing NPN *does* fail the
    handshake, at least with the callback implemented by PyOpenSSL.

    This is sufficiently painful to test that we simply don't. It's not
    necessary to validate that our offering logic works anyway: all we need to
    see is that it works in the successful case and that it degrades properly.
    c                    s   dG fdddt  t t|} fdd|_t \}}t|d|}|d}t t|} fdd|_t	 }	t|	d	|}|d}
t
|
| ||
fS )
a9  
        Start handshake between TLS client and server.

        @param clientProtocols: The protocols the client will accept speaking
            after the TLS handshake is complete.
        @type clientProtocols: L{list} of L{bytes}

        @param serverProtocols: The protocols the server will accept speaking
            after the TLS handshake is complete.
        @type serverProtocols: L{list} of L{bytes}

        @return: A L{tuple} of four different items: the client L{Protocol},
            the server L{Protocol}, a L{Deferred} that fires when the client
            first receives bytes (and so the TLS connection is complete), and a
            L{Deferred} that fires when the server first receives bytes.
        @rtype: A L{tuple} of (L{Protocol}, L{Protocol}, L{Deferred},
            L{Deferred})
        r   c                       s(   e Zd Zdd Z fddZdd ZdS )zLIProtocolNegotiationFactoryTests.handshakeProtocols.<locals>.NotifyingSenderc                 S   s
   || _ d S r9   )notifier)r<   r  r>   r>   r?   r@   P  s    zUIProtocolNegotiationFactoryTests.handshakeProtocols.<locals>.NotifyingSender.__init__c                    s   | j tt  d S r9   r   rR   r   r>   r?   rS   S  s    z[IProtocolNegotiationFactoryTests.handshakeProtocols.<locals>.NotifyingSender.connectionMadec                 S   s    | j d k	r| j |  d | _ d S r9   )r  rE   rZ   r>   r>   r?   r\   V  s    
zYIProtocolNegotiationFactoryTests.handshakeProtocols.<locals>.NotifyingSender.dataReceivedN)rJ   rK   rL   r@   rS   r\   r>   r   r>   r?   NotifyingSenderO  s   r  c                      s    S r9   r>   r>   )r  clientDataReceivedr>   r?   rd   ^  s   zEIProtocolNegotiationFactoryTests.handshakeProtocols.<locals>.<lambda>TNc                      s    S r9   r>   r>   )r  serverDataReceivedr>   r?   rd   j  s   F)r,   r(   r  rk   r7   rC   r
   rm   r  r   r/   )r<   ZclientProtocolsZserverProtocolsrp   r   r   rq   r   r   r   r   r>   )r  r  r[   r  r?   r   :  s<      
  
 z3IProtocolNegotiationFactoryTests.handshakeProtocolsc                    sD    g g \ } fdd}|fdd | |S )z
        When factories support L{IProtocolNegotiationFactory} but don't
        advertise support for any protocols, no protocols are negotiated.
        c                    s      jd   jd  d S r9   rx   ZnegotiatedProtocolr   r   r<   ro   r>   r?   checkNegotiatedProtocol  s    zaIProtocolNegotiationFactoryTests.test_negotiationWithNoProtocols.<locals>.checkNegotiatedProtocolc                    s    S r9   r>   r   r  r>   r?   rd     re   zRIProtocolNegotiationFactoryTests.test_negotiationWithNoProtocols.<locals>.<lambda>r   r   r<   r  r  r>   r   r<   ro   r  r?   test_negotiationWithNoProtocolsz  s    


z@IProtocolNegotiationFactoryTests.test_negotiationWithNoProtocolsc                    sL    ddgddg\ } fdd}|fdd | |S )z
        When factories support L{IProtocolNegotiationFactory} and support
        overlapping protocols, the first protocol is negotiated.
           h2   http/1.1c                    s      jd  jd d S )Nr  r  r   r  r>   r?   r    s    zeIProtocolNegotiationFactoryTests.test_negotiationWithProtocolOverlap.<locals>.checkNegotiatedProtocolc                    s    S r9   r>   r   r  r>   r?   rd     re   zVIProtocolNegotiationFactoryTests.test_negotiationWithProtocolOverlap.<locals>.<lambda>r  r  r>   r  r?   #test_negotiationWithProtocolOverlap  s    

zDIProtocolNegotiationFactoryTests.test_negotiationWithProtocolOverlapc                    sH    ddgg \ } fdd}|fdd | |S )z
        When factories support L{IProtocolNegotiationFactory} and only the
        client advertises, nothing is negotiated.
        r  r  c                    s      jd   jd  d S r9   r  r   r  r>   r?   r    s    z\IProtocolNegotiationFactoryTests.test_negotiationClientOnly.<locals>.checkNegotiatedProtocolc                    s    S r9   r>   r   r  r>   r?   rd     re   zMIProtocolNegotiationFactoryTests.test_negotiationClientOnly.<locals>.<lambda>r  r  r>   r  r?   test_negotiationClientOnly  s    

z;IProtocolNegotiationFactoryTests.test_negotiationClientOnlyc                    sH    g ddg\ } fdd}|fdd | |S )z
        When factories support L{IProtocolNegotiationFactory} and only the
        server advertises, nothing is negotiated.
        r  r  c                    s      jd   jd  d S r9   r  r   r  r>   r?   r    s    z\IProtocolNegotiationFactoryTests.test_negotiationServerOnly.<locals>.checkNegotiatedProtocolc                    s    S r9   r>   r   r  r>   r?   rd     re   zMIProtocolNegotiationFactoryTests.test_negotiationServerOnly.<locals>.<lambda>r  r  r>   r  r?   test_negotiationServerOnly  s    

z;IProtocolNegotiationFactoryTests.test_negotiationServerOnlyN)	rJ   rK   rL   rM   r   r  r  r  r  r>   r>   r>   r?   r  +  s   @r  )FNN)NF)[rM   Z
__future__r   r   r/  Zzope.interface.verifyr   Zzope.interfacer   r   r   Ztwisted.python.compatr   Ztwisted.protocols.tlsr	   r
   r   r   ZOpenSSL.cryptor   ZOpenSSL.SSLr   r   r   r   r   r   r   ImportErrorskipZtwisted.internet.sslr   r   Ztwisted.test.ssl_helpersr   r   r   Ztwisted.test.test_sslverifyr   Ztwisted.test.iosimr   Ztwisted.python.filepathr   Ztwisted.python.failurer   Ztwisted.pythonr   Ztwisted.internet.interfacesr   r    r!   r"   r#   r$   r%   Ztwisted.internet.errorr&   r'   Ztwisted.internet.deferr(   r)   Ztwisted.internet.protocolr*   r+   r,   r-   Ztwisted.internet.taskr.   Ztwisted.protocols.loopbackr/   r0   Ztwisted.trial.unittestr1   r2   Ztwisted.test.test_tcpr4   Ztwisted.test.proto_helpersr5   r6   r7   rO   rs   rt   r   r   r   r6  r  r  r  r  r>   r>   r>   r?   <module>   sl   ($2
"3  
:(     o   J |