ϪfIdZddlZ ddlmZddlmZmZddl m Z m Z ddl m Z mZddlmZddlmZmZdd lmZdd lmZGd d Zee j2Gd dZee j6e j8GddZdZdZGddZ ddZ!eedddfdZ"dZ#GddZ$ddZ%y#e$rYwxYw)z0 Utilities and helpers for simulating a network N)Error)directlyProvides implementer)error interfaces)TCP4ClientEndpointTCP4ServerEndpoint)ConnectionRefusedError)FactoryProtocol)MemoryReactorClock)Failurec$eZdZdZdefdZdZy)TLSNegotiationc<||_||_d|_||_y)NF)obj connectStatesent readyToSend)selfrrs 4/usr/lib/python3/dist-packages/twisted/test/iosim.py__init__zTLSNegotiation.__init__s ( 'returnc"d|jdS)NzTLSNegotiation())rrs r__repr__zTLSNegotiation.__repr__!s  A..rc|jj|js t|_|j yyN)r iosimVerifyNativeOpenSSLErrordisconnectReasonloseConnection)rothertpts rpretendToVerifyzTLSNegotiation.pretendToVerify$s6xx##EII.#5#7C    /rN)__name__ __module__ __qualname__rstrrr'rrrrs( /#/!rrceZdZdZy) FakeAddressz] The default address type for the host and peer of L{FakeTransport} connections. N)r(r)r*__doc__r,rrr.r.-srr.c eZdZdZeej fdZdZdZ dZ e jdZ dZdZdZd dZdefdZd Zd Zd Zd Zd ZdZdZdZdZdZdZdZdZ dZ!dZ"d!dZ#dZ$dZ%dZ&dZ'dZ(dZ)dZ*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*tt|Sr )intnext)counters rzFakeTransport.>sT']ASrrzConnection 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)protocolisServerstream _nextserialserialr. hostAddress peerAddress)rr8r9r=r>s rrzFakeTransport.__init__GsS"!    &&(  %-K&  %-K&rrcdj|jxrdxsd|j|jjj S)NzFakeTransport<{},{},{}>SC)formatr9r<r8 __class__r(rs rrzFakeTransport.__repr__cs@(// MM !c (S KK MM # # , ,  rc|jry|j|jj|y|jj|yr ) disconnectingtlstlsbufappendr:)rdatas rwritezFakeTransport.writejs<     88  KK  t $ KK  t $rcl|jr(|js|jjyyyr producerstreamingProducerresumeProducingrs r_checkProducerzFakeTransport._checkProducerts* ==!7!7 MM ) ) +"8=rcF||_||_|s|jyy)z. From abstract.FileDescriptor NrL)rrM streamings rregisterProducerzFakeTransport.registerProducerzs'! !*  $ $ &rcd|_yr )rMrs runregisterProducerz FakeTransport.unregisterProducers  rcD|j|jyr )rUr$rs r stopConsumingzFakeTransport.stopConsumings ! rcD|jdj|y)Nr)rJjoin)riovecs r writeSequencezFakeTransport.writeSequences 388E?#rcd|_yNTrErs rr$zFakeTransport.loseConnections !rcd|_y)zp For the time being, this is the same as loseConnection; no buffered data will be lost. TNr^rs rabortConnectionzFakeTransport.abortConnections "rc|j t}n |j}|jj t |yr )rFr"r#r8connectionLostr)rerrs rreportDisconnectzFakeTransport.reportDisconnects7 88 %&C''C $$WS\2rcy)zM Identify this transport/event source to the logging system. iosimr,rs r logPrefixzFakeTransport.logPrefixsrc|jSr )r>rs rgetPeerzFakeTransport.getPeerrc|jSr )r=rs rgetHostzFakeTransport.getHostrjrcyr r,rs rrOzFakeTransport.resumeProducing rcyr r,rs rpauseProducingzFakeTransport.pauseProducingrnrc$|jyr )r$rs r stopProducingzFakeTransport.stopProducings rcR|j|z }t|||_g|_yr )r9rrFrG)rcontextFactorybeNormalrs rstartTLSzFakeTransport.startTLSs'}}x/ !.,? rc|j}|rg|_dj|S|j4|jjrd|j_|jSyy)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} rNT)r:rYrFrr)rr@s r getOutBufferzFakeTransport.getOutBuffersV KK DK88A;  XX !xx## $ xxrct|tr|jJ|jjrc|jj ||d|_|j dc}|_|j |t|tjyd|j_ y|jj|yr]) isinstancerrFrr'rGr[rr ISSLTransportrr8 dataReceived)rbufbs rbufferReceivedzFakeTransport.bufferReceiveds c> *88' ''xx}}((d3"&d4;""1% z'?'?@(,$ MM & &s +rcyr r,rs rgetTcpKeepAlivezFakeTransport.getTcpKeepAlivernrcyr r,rs r getTcpNoDelayzFakeTransport.getTcpNoDelayrnrcyr r,rs rloseWriteConnectionz!FakeTransport.loseWriteConnectionrnrcyr r,renableds rsetTcpKeepAlivezFakeTransport.setTcpKeepAlivernrcyr r,rs r setTcpNoDelayzFakeTransport.setTcpNoDelayrnr)NN)T)+r(r)r*r/ staticmethod itertoolscountr;closedrE disconnectedrConnectionDoner#rMrNrFrr+rrJrPrSrUrWr[r$r`rdrgrirlrOrprrrvrxrrrrrrr,rrr1r15soioo.?STK FML+u++,=>H C'8 # %, '$""3     ,,&     rr1ct|dS)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} Fr9r1)clientProtocols rmakeFakeClientrs % 88rct|dS)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} Trr)serverProtocols rmakeFakeServerr s $ 77rc(eZdZdZddZddZddZy)IOPumpz Utility to pump data between clients and servers for protocol testing. Perhaps this is a utility worthy of being in protocol.py? Ncp||_||_||_||_||_| t }||_yr )clientserverclientIOserverIOdebugr clock)rrrrrrrs rrzIOPump.__init__s9       =&(E rcbd}tdD]}|j||rd}|SJd)zk Pump until there is no more input or output. Returns whether any data was moved. FiTzToo long)rangepump)rr advanceClockresult_s rflushz IOPump.flush(sE t !Ayy -  ! !j 1rc\|r|jjd|js|r td|jj }|j j }|j j|jj|js|r=td|rtdt|z|rtdt|z|r|jj||r|j j||s|ry|jjrl|jjsV|js|r tdd|j_ d|j _ |j jy|j jrl|j jsV|js|r tdd|j _ d|j_ |jjyy ) 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. rz -- GLUG --.zC: zS: Tz* Cz* SF) radvancerprintrrxrrPreprrrErrd)rrrsDatacDatas rrz IOPump.pump8s  JJ  q ! :: ,  **, **, $$& $$& :: #Jed5k)*ed5k)*  MM ( ( /  MM ( ( / E == & &t}}/I/IzzUe )-DMM &*.DMM ' MM * * , == & &t}}/I/IzzUe )-DMM &*.DMM ' MM * * ,rr )FT)r(r)r*r/rrrr,rrrrs  *rrFTc|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 } 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)makeConnectionrr)rserverTransportrclientTransportrgreetrrs rconnectresPT!!/2!!/2    D  Krc h|}|}||} ||} ||t|| || |||fS)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 } 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 ClientClassclientTransportFactoryserverTransportFactoryrrrcsciosios rconnectedServerAndClientrsE\  A A  #C  #C aCCUC CCrc4|\}}}}}|\}}} } ||k(r||fSy)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 clientTimeoutclientBindAddress serverPort serverFactory serverBacklogserverInterfaces r_factoriesShouldConnectrs?.  BL?Z Zm++rc>eZdZdZdZddZeefdZy)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 rrzConnectionCompleter.__init__s & rc |j}t|jD]\}}|jD]}t ||}|s|jj ||j j||\}}|jd} |jd} t| } t| } t| | | | |ccSy)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 tcpServersrremove connectorspop buildProtocolrrr) rrr clientIdxrr factoriesrrrrrrs r succeedOncezConnectionCompleter.succeedOnces %.}/G/G%H  !Iz+66  3J K !,,33J?!,,00;3<0M=%2%@%@%FN%2%@%@%FN&4^&DO&4^&DO"&'&'   rc|jjjddj|jjjd|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} rN)rrrclientConnectionFailedr)rreasons rfailOncezConnectionCompleter.failOnce$sF   $$Q'*AA MM $ $ ( ( +V rNF) r(r)r*r/rrrr rr,rrrrs% &B&&<&>?  rrct}t|dd}t|d}|jt j t |t|fS)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}) z0.0.0.0i)r rr listenr forProtocolr r)rreactorclientEndpointserverEndpoints rconnectableEndpointr1sP!"G'DAN'6N'--h78 .w7 77r)FTNr)&r/r OpenSSL.SSLrr" ImportErrorzope.interfacerrtwisted.internetrrtwisted.internet.endpointsrr twisted.internet.errorr twisted.internet.protocolr r twisted.internet.testingr twisted.python.failurerrIAddressr. ITransport ITLSTransportr1rrrrrrrrr,rrrs  79.M977*!!& Z !" Z " "J$<$<=D D >D N 9 8KKf   7z*)   2Dj>; ; |8I  sCC  C