ϪfhC0dZddlZddlZddlmZddlmZmZmZm Z m Z m Z m Z m Z ddlmZddlmZddlmZddlmZdd lmZdd lmZdd lmZmZmZmZdd lm Z d Z!dZ"dZ#dZ$dZ%dZ&GddZ'dZ(eeGddZ)GddZ*y)zD Tools for automated testing of L{twisted.pair}-based applications. N)deque)EAGAINEBADFEINTREINVALENOBUFSENOSYSEPERM EWOULDBLOCKwraps) implementer)DatagramProtocol)EthernetProtocol) IPProtocol)RawUDPProtocol) _IFNAMSIZ _TUNSETIFF TunnelFlags_IInputOutputSystem) nativeStringc.tjd|S)z Pack an integer into a network-order two-byte string. @param n: The integer to pack. Only values that fit into 16 bits are supported. @return: The packed representation of the integer. @rtype: L{bytes} z>H)structpack)ns 6/usr/lib/python3/dist-packages/twisted/pair/testing.py_Hrs ;;tQ c*||zt|z|zS)a Construct an ethernet frame. @param src: The source ethernet address, encoded. @type src: L{bytes} @param dst: The destination ethernet address, encoded. @type dst: L{bytes} @param protocol: The protocol number of the payload of this datagram. @type protocol: L{int} @param payload: The content of the ethernet frame (such as an IP datagram). @type payload: L{bytes} @return: The full ethernet frame. @rtype: L{bytes} )rsrcdstprotocolpayloads r _ethernetr'.s& 9r(| #g --rcdtdt|zzdztdztjtjt |ztjtjt |z}t tjd|}|dz }|dz|z}|dz }|dd tjd |z|d dz}||zS) a Construct an IP datagram with the given source, destination, and application payload. @param src: The source IPv4 address as a dotted-quad string. @type src: L{bytes} @param dst: The destination IPv4 address as a dotted-quad string. @type dst: L{bytes} @param payload: The content of the IP datagram (such as a UDP datagram). @type payload: L{bytes} @return: An IP datagram header and payload. @rtype: L{bytes} sEs@rz!10HiN z!H ) rlensocket inet_ptonAF_INETrsumrunpackr)r#r$r&ipHeader checksumStep1carry checksumStep2 checksumStep3s r_ipr8Ds&  R#g,    &  & Q%    6>><+< = >   6>><+< = > " fh78M R E"V+u4M!F*M }v{{4??(23-OH g rct|t|ztt|dzztdz}||zS)a~ Construct a UDP datagram with the given source, destination, and application payload. @param src: The source port number. @type src: L{int} @param dst: The destination port number. @type dst: L{int} @param payload: The content of the UDP datagram. @type payload: L{bytes} @return: A UDP datagram header and payload. @rtype: L{bytes} r)rr-)r#r$r& udpHeaders r_udpr<vsO& 3 S'  S\A     Q%   w rceZdZdZdZeedZee dZ ee dZ eZ dZdZedZed Zd Zd Zd Zy )Tunnelz An in-memory implementation of a tun or tap device. @cvar _DEVICE_NAME: A string representing the conventional filesystem entry for the tunnel factory character special device. @type _DEVICE_NAME: C{bytes} s /dev/net/tunz Resource temporarily unavailablezOperation would blockzInterrupted function callic||_||_d|_d|_d|_t |_t |_t |_y)a @param system: An L{_IInputOutputSystem} provider to use to perform I/O. @param openFlags: Any flags to apply when opening the tunnel device. See C{os.O_*}. @type openFlags: L{int} @param fileMode: ignored N) system openFlags tunnelMode requestedNamenamer readBuffer writeBufferpendingSignals)selfr@rAfileModes r__init__zTunnel.__init__sG #! ' 7#grcJ|j|jjz S)zx If the file descriptor for this tunnel is open in blocking mode, C{True}. C{False} otherwise. )rAr@ O_NONBLOCKrHs rblockingzTunnel.blockings NNT[[%;%;;<? ? )8}rN)__name__ __module__ __qualname____doc__ _DEVICE_NAMEIOErrorr EAGAIN_STYLErfr EWOULDBLOCK_STYLEr EINTR_STYLErargrJpropertyrNrRrZrdrhrrr>r>s#L6#EFL -DE%!<=K ,&.==<<)"!1Frr>c.tfd}|S)a| Wrap a L{MemoryIOSystem} method with permission-checking logic. The returned function will check C{self.permissions} and raise L{IOError} with L{errno.EPERM} if the function name is not listed as an available permission. @param original: The L{MemoryIOSystem} instance to wrap. @return: A wrapper around C{original} that applies permission checks. clj|jvrttd|g|i|S)NzOperation not permitted)ri permissionsrfr )rHargskwargsoriginals rpermissionCheckerz&_privileged..permissionChecker+s:   D$4$4 4%!:; ;.t.v..rr )ryrzs` r _privilegedr{s# 8_// rcreZdZdZdZdZdZdZdZdZ dZ e dd Z d Z d Zd Ze dZdZdZy )MemoryIOSystemz An in-memory implementation of basic I/O primitives, useful in the context of unit testing as a drop-in replacement for parts of the C{os} module. @ivar _devices: @ivar _openFiles: @ivar permissions: @ivar _counter: i rc2i|_i|_ddh|_y)Nopenioctl)_devices _openFilesrvrMs rrJzMemoryIOSystem.__init__Gs "G,rc<|j|jS)aX Get the L{Tunnel} object associated with the given L{TuntapPort}. @param port: A L{TuntapPort} previously initialized using this L{MemoryIOSystem}. @return: The tunnel object created by a prior use of C{open} on this object on the tunnel special device file. @rtype: L{Tunnel} )rfileno)rHports r getTunnelzMemoryIOSystem.getTunnelLst{{}--rc"||j|<y)a1 Specify a class which will be used to handle I/O to a device of a particular name. @param name: The filesystem path name of the device. @type name: L{bytes} @param cls: A class (like L{Tunnel}) to instantiated whenever this device is opened. N)r)rHrDclss rregisterSpecialDevicez$MemoryIOSystem.registerSpecialDeviceYs" drNc||jvrG|j}|xjdz c_|j|||||j|<|Sttd)a A replacement for C{os.open}. This initializes state in this L{MemoryIOSystem} which will be reflected in the behavior of the other file descriptor-related methods (eg L{MemoryIOSystem.read}, L{MemoryIOSystem.write}, etc). @param name: A string giving the name of the file to open. @type name: C{bytes} @param flags: The flags with which to open the file. @type flags: C{int} @param mode: The mode with which to open the file. @type mode: C{int} @raise OSError: With C{ENOSYS} if the file is not a recognized special device file. @return: A file descriptor associated with the newly opened file description. @rtype: L{int} r~zFunction not implemented)r_counterrrfr )rHrDflagsmodefds rrzMemoryIOSystem.openfs\0 4== B MMQ M"5$--"5dE4"HDOOB If899rcz |j|j|S#t$rttdwxYw)z Try to read some bytes out of one of the in-memory buffers which may previously have been populated by C{write}. @see: L{os.read} Bad file descriptor)rrdKeyErrorrfr)rHrrbs rrdzMemoryIOSystem.reads> 8??2&++E2 2 8%!67 7 8 :cz |j|j|S#t$rttdwxYw)z Try to add some bytes to one of the in-memory buffers to be accessed by a later C{read} call. @see: L{os.write} r)rrhrrfr)rHrdatas rrhzMemoryIOSystem.writes> 8??2&,,T2 2 8%!67 7 8rcZ |j|=y#t$rttdwxYw)z Discard the in-memory buffer and other in-memory state for the given file descriptor. @see: L{os.close} rN)rrrfr)rHrs rclosezMemoryIOSystem.closes0 8# 8%!67 7 8s *cf |j|}|tk7rtt dt jdtfz|\}}||_ ||_ |dtdz dz|_ t jdtfz|j|S#t$rttdwxYw)z Perform some configuration change to the in-memory state for the given file descriptor. @see: L{fcntl.ioctl} rzRequest or args is not valid.z%dsHNs123) rrrfrrrrr2rrBrCrDr)rHrrequestrwtunnelrDrs rrzMemoryIOSystem.ioctls 8__R(F j &"AB B]]6YL#8$? d #?Y]+f4 {{6YL0&++tDD 8%!67 7 8s BB0c d}d}t||dt||d|}t|jj }|dj |||fS)ah Write an ethernet frame containing an ip datagram containing a udp datagram containing the given payload, addressed to the given address, to a tunnel device previously opened on this I/O system. @param datagram: A UDP datagram payload to send. @type datagram: L{bytes} @param address: The destination to which to send the datagram. @type address: L{tuple} of (L{bytes}, L{int}) @return: A two-tuple giving the address from which gives the address from which the datagram was sent. @rtype: L{tuple} of (L{bytes}, L{int}) z10.1.2.3iaSrr~)r#r$r&)r8r<listrvaluesrZ)rHrYaddresssrcIPsrcPort serialized openFiless rsendUDPzMemoryIOSystem.sendUDPsh" W'!*hG //12 ! $$Z0wrct||S)aa Get a socket-like object which can be used to receive a datagram sent from the given address. @param fileno: A file descriptor representing a tunnel device which the datagram will be received via. @type fileno: L{int} @param host: The IPv4 address to which the datagram was sent. @type host: L{bytes} @param port: The UDP port number to which the datagram was sent. received. @type port: L{int} @return: A L{socket.socket}-like object which can be used to receive the specified datagram. ) _FakePort)rHrhostrs r receiveUDPzMemoryIOSystem.receiveUDPs&v&&rN)rirjrkrlrO_RDWRrLrQrJrrr{rrdrhrrrrrsrrr}r}4so H FJI- . "::< 8 8 8EE, >'rr}ceZdZdZdZdZy)rz A socket-like object which can be used to read UDP datagrams from tunnel-like file descriptors managed by a L{MemoryIOSystem}. c ||_||_yr)_system_fileno)rHr@rs rrJz_FakePort.__init__s  rc~ |jj|jjj }g t } fd}||_t}|jd|t jd||jj|jj}|tjjzr)t}|jd |j }n fd}|tjjz } | r |t d}|| dd|S)a_ Receive a datagram sent to this port using the L{MemoryIOSystem} which created this object. This behaves like L{socket.socket.recv} but the data being I{sent} and I{received} only passes through various memory buffers managed by this object and L{MemoryIOSystem}. @see: L{socket.socket.recv} c(j|yr)rW)rYr datagramss rcapturez_FakePort.recv..captures   X &ri90r c.j|ddddSr)datagramReceived)rips rz _FakePort.recv.. sB,?,?dD$-rNr)rrrrFr_rrraddProtorrBrrTrUrr]r^) rHnbytesrreceiverrudpretherr dataHasPIrrs @@rrecvz_FakePort.recvs||&&t||4@@HHJ #% '%,! UH% \ B||&&t||4?? +%%++ +$&E NN5" %$55    5 5 ; ;;<  ?D|GV$$rN)rirjrkrlrJrrsrrrrs ,%rr)+rlr.r collectionsrerrnorrrrrr r r functoolsr zope.interfacertwisted.internet.protocolrtwisted.pair.ethernetrtwisted.pair.iprtwisted.pair.rawudprtwisted.pair.tuntaprrrrtwisted.python.compatrr^rrVr'r8r<r>r{r}rrsrrrs SSS&62&.WW.    .,/d