
    hhC                     0   S r SSKrSSKrSSKJr  SSKJrJrJrJ	r	J
r
JrJrJr  SSKJr  SSKJr  SSKJr  SSKJr  SS	KJr  SS
KJr  SSKJrJrJrJr  SSKJ r   Sr!S r"Sr#S r$S r%S r& " S S5      r'S r(\" \5       " S S5      5       r) " S S5      r*g)zD
Tools for automated testing of L{twisted.pair}-based applications.
    N)deque)EAGAINEBADFEINTREINVALENOBUFSENOSYSEPERMEWOULDBLOCKwraps)implementer)DatagramProtocol)EthernetProtocol)
IPProtocol)RawUDPProtocol)	_IFNAMSIZ
_TUNSETIFFTunnelFlags_IInputOutputSystem)nativeString   c                 0    [         R                  " SU 5      $ )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)structpack)ns    [/root/1688_scrapy/alibaba-scraper/venv/lib/python3.13/site-packages/twisted/pair/testing.py_Hr      s     ;;tQ       c                 (    X-   [        U5      -   U-   $ )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}
)r   srcdstprotocolpayloads       r   	_ethernetr'   .   s    & 9r(|#g--r   c                    S[        S[        U5      -   5      -   S-   [        S5      -   [        R                  " [        R                  [        U 5      5      -   [        R                  " [        R                  [        U5      5      -   n[        [        R                  " SU5      5      nUS-	  nUS-  U-   nUS-  nUSS	 [        R                  " S
U5      -   USS -   nX2-   $ )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}
s   E    s      @r   z!10H   i  N
   z!H   )
r   lensocket	inet_ptonAF_INETr   sumr   unpackr   )r#   r$   r&   ipHeaderchecksumStep1carrychecksumStep2checksumStep3s           r   _ipr8   D   s    &	 R#g,
		 
 &	& Q%	 

6>><+<
=		> 

6>><+<
=	> " fh78MRE"V+u4M!F*M
 }v{{4??(23-OHr   c                     [        U 5      [        U5      -   [        [        U5      S-   5      -   [        S5      -   nX2-   $ )aR  
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   )r   r-   )r#   r$   r&   	udpHeaders       r   _udpr<   v   sM    & 	3
S'	 S\A
		 Q%	  r   c                       \ rS rSrSrSr\" \S5      r\	" \
S5      r\" \S5      r\rSrS r\S	 5       r\S
 5       rS rS rS rSrg)Tunnel   z
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 unavailablezOperation would blockzInterrupted function calli   c                     Xl         X l        SU l        SU l        SU l        [        5       U l        [        5       U l        [        5       U l        g)z
@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requestedNamenamer   
readBufferwriteBufferpendingSignals)selfrA   rB   fileModes       r   __init__Tunnel.__init__   sC      #!	' 7#gr   c                 R    U R                   U R                  R                  -  (       + $ )z`
If the file descriptor for this tunnel is open in blocking mode,
C{True}.  C{False} otherwise.
)rB   rA   
O_NONBLOCKrI   s    r   blockingTunnel.blocking   s      NNT[[%;%;;<<r   c                 Z    [        U R                  U R                  R                  -  5      $ )zb
If the file descriptor for this tunnel is marked as close-on-exec,
C{True}.  C{False} otherwise.
)boolrB   rA   	O_CLOEXECrO   s    r   closeOnExecTunnel.closeOnExec   s"     DNNT[[%:%::;;r   c                     U R                   [        R                  R                  -  (       a  [	        SS[
        US9nU R                  R                  U5        g)a  
Deliver a datagram to this tunnel's read buffer.  This makes it
available to be read later using the C{read} method.

@param datagram: The IPv4 datagram to deliver.  If the mode of this
    tunnel is TAP then ethernet framing will be added automatically.
@type datagram: L{bytes}
s         s   r"   N)rC   r   IFF_TAPvaluer'   _IPv4rF   appendrI   datagrams     r   addToReadBufferTunnel.addToReadBuffer   sC     ??[00666 [5(H 	x(r   c                 *   U R                   (       a\  U R                  [        R                  R                  -  (       a  SnOS[
        -  nUS-  nX R                   R                  5       SU -   $ U R                  (       a
  [        5       eU R                  e)a  
Read a datagram out of this tunnel.

@param limit: The maximum number of bytes from the datagram to return.
    If the next datagram is larger than this, extra bytes are dropped
    and lost forever.
@type limit: L{int}

@raise OSError: Any of the usual I/O problems can result in this
    exception being raised with some particular error number set.

@raise IOError: Any of the usual I/O problems can result in this
    exception being raised with some particular error number set.

@return: The datagram which was read from the tunnel.  If the tunnel
    mode does not include L{TunnelFlags.IFF_NO_PI} then the datagram is
    prefixed with a 4 byte PI header.
@rtype: L{bytes}
r       r   N)
rF   rC   r   	IFF_NO_PIrY   _PI_SIZEpopleftrP   NotImplementedErrornonBlockingExceptionStyle)rI   limitheaders      r   readTunnel.read   sv    ( ??!6!6!<!<<
 !8+
OO335fu===]]%''000r   c                    U R                   (       a*  U R                   R                  5         [        [        S5      e[	        U5      U R
                  :  a  [        [        S5      eU R                  R                  U5        [	        U5      $ )a;  
Write a datagram into this tunnel.

@param datagram: The datagram to write.
@type datagram: L{bytes}

@raise IOError: Any of the usual I/O problems can result in this
    exception being raised with some particular error number set.

@return: The number of bytes of the datagram which were written.
@rtype: L{int}
zInterrupted system callzNo buffer space available)	rH   rd   OSErrorr   r-   SEND_BUFFER_SIZEr   rG   r[   r\   s     r   writeTunnel.write  sk     '')%!:;;x=4000'#>??)8}r   )rE   rB   rH   rF   rD   rA   rC   rG   N)__name__
__module____qualname____firstlineno____doc___DEVICE_NAMEIOErrorr   EAGAIN_STYLErl   r   EWOULDBLOCK_STYLEr   EINTR_STYLErf   rm   rK   propertyrP   rU   r^   ri   rn   __static_attributes__ r   r   r>   r>      s     #L 6#EFL-DE %!<=K ,&. = = < <)"!1Fr   r>   c                 0   ^  [        T 5      U 4S j5       nU$ )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.
c                 p   > TR                   U R                  ;  a  [        [        S5      eT" U /UQ70 UD6$ )NzOperation not permitted)rp   permissionsrl   r
   )rI   argskwargsoriginals      r   permissionChecker&_privileged.<locals>.permissionChecker+  s:    D$4$44%!:;;.t.v..r   r   )r   r   s   ` r   _privilegedr     s#     8_/ /
 r   c                   |    \ rS rSrSrSrSrSrSrS r	S r
S	 r\SS j5       rS rS rS r\S 5       rS rS rSrg
)MemoryIOSystemi4  z
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          r   c                 2    0 U l         0 U l        SS1U l        g )Nopenioctl_devices
_openFilesr   rO   s    r   rK   MemoryIOSystem.__init__G  s    "G,r   c                 <    U R                   UR                  5          $ )a   
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}
)r   fileno)rI   ports     r   	getTunnelMemoryIOSystem.getTunnelL  s     t{{}--r   c                      X R                   U'   g)z
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   )rI   rE   clss      r   registerSpecialDevice$MemoryIOSystem.registerSpecialDeviceY  s     "dr   Nc                     XR                   ;   aF  U R                  nU =R                  S-  sl        U R                   U   " XU5      U R                  U'   U$ [        [        S5      e)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   zFunction not implemented)r   _counterr   rl   r	   )rI   rE   flagsmodefds        r   r   MemoryIOSystem.openf  sV    0 == BMMQM"&--"5d4"HDOOBIf899r   c                 |     U R                   U   R                  U5      $ ! [         a    [        [        S5      ef = f)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)r   ri   KeyErrorrl   r   )rI   r   rg   s      r   ri   MemoryIOSystem.read  s>    	8??2&++E22 	8%!677	8     ;c                 |     U R                   U   R                  U5      $ ! [         a    [        [        S5      ef = f)zr
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   )r   rn   r   rl   r   )rI   r   datas      r   rn   MemoryIOSystem.write  s>    	8??2&,,T22 	8%!677	8r   c                 \     U R                   U	 g! [         a    [        [        S5      ef = f)zj
Discard the in-memory buffer and other in-memory state for the given
file descriptor.

@see: L{os.close}
r   N)r   r   rl   r   )rI   r   s     r   closeMemoryIOSystem.close  s0    	8# 	8%!677	8s    +c                 h    U R                   U   nU[        :w  a  [        [
        S5      e[        R                  " S[        4-  U5      u  pVXdl	        XTl
        US[        S-
   S-   Ul        [        R                  " S[        4-  UR                  U5      $ ! [         a    [        [        S5      ef = f)zo
Perform some configuration change to the in-memory state for the given
file descriptor.

@see: L{fcntl.ioctl}
r   zRequest or args is not valid.z%dsHN   s   123)r   r   rl   r   r   r   r   r2   r   rC   rD   rE   r   )rI   r   requestr   tunnelrE   r   s          r   r   MemoryIOSystem.ioctl  s    	8__R(F j &"ABB]]6YL#8$?
 #?Y]+f4{{6YL0&++tDD  	8%!677	8s   B B1c           
          SnSn[        UUS   [        XBS   US9S9n[        U R                  R	                  5       5      nUS   R                  U5        X44$ )a  
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})
z10.1.2.3iaS  r   r   )r#   r$   r&   )r8   r<   listr   valuesr^   )rI   r]   addresssrcIPsrcPort
serialized	openFiless          r   sendUDPMemoryIOSystem.sendUDP  sd    " 
W!*hG

 //12	!$$Z0r   c                     [        X5      $ )a  
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)rI   r   hostr   s       r   
receiveUDPMemoryIOSystem.receiveUDP  s    & &&r   r   N)rp   rq   rr   rs   rt   r   O_RDWRrN   rT   rK   r   r   r   r   ri   rn   r   r   r   r   r{   r|   r   r   r   r   4  so    	 HFJI-
." : :<
8
8
8 E E, >'r   r   c                   $    \ rS rSrSrS rS rSrg)r   i  z
A socket-like object which can be used to read UDP datagrams from
tunnel-like file descriptors managed by a L{MemoryIOSystem}.
c                     Xl         X l        g r   )_system_fileno)rI   rA   r   s      r   rK   _FakePort.__init__  s    r   c                   ^
^ U R                   R                  U R                     R                  R	                  5       n/ m
[        5       nU
4S jnXCl        [        5       nUR                  SU5        [        5       mTR                  SU5        U R                   R                  U R                     R                  nU[        R                  R                  -  (       a)  [        5       nUR                  ST5        UR                  nOU4S jnU[        R                  R                  -  (       + n	U	(       a	  U[         S nU" U5        T
S   SU $ )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                 (   > TR                  U 5        g r   )r[   )r]   r   	datagramss     r   capture_FakePort.recv.<locals>.capture  s    X&r   i90     r    c                 .   > TR                  U S S S S 5      $ r   )datagramReceived)r   ips    r   <lambda> _FakePort.recv.<locals>.<lambda>   s    B,?,?dD$-r   Nr   )r   r   r   rG   rd   r   r   r   addProtor   rC   r   rX   rY   r   rb   rc   )rI   nbytesr   receiverr   udpr   etherr   	dataHasPIr   r   s             @@r   recv_FakePort.recv  s    ||&&t||4@@HHJ	#%	' %,!UH%\
B||&&t||4??+%%+++$&ENN5"%$55   5 5 ; ;;<		?D|GV$$r   )r   r   N)rp   rq   rr   rs   rt   rK   r   r{   r|   r   r   r   r     s    
,%r   r   )+rt   r.   r   collectionsr   errnor   r   r   r   r   r	   r
   r   	functoolsr   zope.interfacer   twisted.internet.protocolr   twisted.pair.ethernetr   twisted.pair.ipr   twisted.pair.rawudpr   twisted.pair.tuntapr   r   r   r   twisted.python.compatr   rc   r   rZ   r'   r8   r<   r>   r   r   r   r|   r   r   <module>r      s       S S S  & 6 2 & . W W . 
  	.,/d<H HV*  !}' }' "}'@6% 6%r   