o
    bH                     @   s`  d Z ddlZddlZddlZddlmZ ddlmZ ddlm	Z	 e	dkrWddl
mZ ddl
mZ dd	l
mZmZmZmZmZmZmZ eeeegZeeeegZeZeZeZeZndd
l
mZmZmZmZmZmZ eeegZegZddlmZmZmZm Z m!Z!m"Z" ddl#m$Z$m%Z% ee"j&e"j'e"j(G dd dej)Z*G dd dZ+ee"j,G dd de+e*Z-dS )a  
Various asynchronous UDP classes.

Please do not use this module directly.

@var _sockErrReadIgnore: list of symbolic error constants (from the C{errno}
    module) representing socket errors where the error is temporary and can be
    ignored.

@var _sockErrReadRefuse: list of symbolic error constants (from the C{errno}
    module) representing socket errors that indicate connection refused.
    N)Optional)implementer)platformTypewin32)WSAEINPROGRESS)WSAEWOULDBLOCK)WSAECONNREFUSEDWSAECONNRESETWSAEINTRWSAEMSGSIZEWSAENETRESETWSAENOPROTOOPTWSAETIMEDOUT)EAGAINECONNREFUSEDEINTREMSGSIZEENOPROTOOPTEWOULDBLOCK)abstractaddressbasedefererror
interfaces)failurelogc                   @   s   e Zd ZU dZejZejZdZ	dZ
ee ed< dZd2ddZed	d
 ZdefddZdd Zdd Zdd Zdd Zdd Zd3ddZdd Zdd Zdd Zd d! Zd"d# Zd3d$d%Zd&d' Z d(d) Z!d*d+ Z"d,d- Z#d.d/ Z$d0d1 Z%dS )4Porta  
    UDP port, listening for packets.

    @ivar maxThroughput: Maximum number of bytes read in one event
        loop iteration.

    @ivar addressFamily: L{socket.AF_INET} or L{socket.AF_INET6}, depending on
        whether this port is listening on an IPv4 address or an IPv6 address.

    @ivar _realPortNumber: Actual port number being listened on. The
        value will be L{None} until this L{Port} is listening.

    @ivar _preexistingSocket: If not L{None}, a L{socket.socket} instance which
        was created and initialized outside of the reactor and will be used to
        listen for connections (instead of a new socket being created by this
        L{Port}).
    i   N_realPortNumber     c                 C   s@   t j| | || _|| _|| _|| _|   d| _| 	  dS )a  
        @param port: A port number on which to listen.
        @type port: L{int}

        @param proto: A C{DatagramProtocol} instance which will be
            connected to the given C{port}.
        @type proto: L{twisted.internet.protocol.DatagramProtocol}

        @param interface: The local IPv4 or IPv6 address to which to bind;
            defaults to '', ie all IPv4 addresses.
        @type interface: L{str}

        @param maxPacketSize: The maximum packet size to accept.
        @type maxPacketSize: L{int}

        @param reactor: A reactor which will notify this C{Port} when
            its socket is ready for reading or writing. Defaults to
            L{None}, ie the default global reactor.
        @type reactor: L{interfaces.IReactorFDSet}
        N)
r   BasePort__init__portprotocolmaxPacketSize	interface	setLogStr_connectedAddr_setAddressFamily)selfr#   protor&   r%   reactor r-   6/usr/lib/python3/dist-packages/twisted/internet/udp.pyr"   [   s   zPort.__init__c           	      C   s8   t ||| j}| d }| d||||d}||_|S )a  
        Create a new L{Port} based on an existing listening
        I{SOCK_DGRAM} socket.

        @param reactor: A reactor which will notify this L{Port} when
            its socket is ready for reading or writing. Defaults to
            L{None}, ie the default global reactor.
        @type reactor: L{interfaces.IReactorFDSet}

        @param fd: An integer file descriptor associated with a listening
            socket.  The socket must be in non-blocking mode.  Any additional
            attributes desired, such as I{FD_CLOEXEC}, must also be set already.
        @type fd: L{int}

        @param addressFamily: The address family (sometimes called I{domain}) of
            the existing socket.  For example, L{socket.AF_INET}.
        @type addressFamily: L{int}

        @param protocol: A C{DatagramProtocol} instance which will be
            connected to the C{port}.
        @type protocol: L{twisted.internet.protocol.DatagramProtocol}

        @param maxPacketSize: The maximum packet size to accept.
        @type maxPacketSize: L{int}

        @return: A new instance of C{cls} wrapping the socket given by C{fd}.
        @rtype: L{Port}
        r   N)r&   r,   r%   )socketfromfd
socketTypegetsockname_preexistingSocket)	clsr,   fdaddressFamilyr$   r%   r#   r&   r*   r-   r-   r.   _fromListeningDescriptory   s    zPort._fromListeningDescriptorreturnc                 C   s2   | j d urd| jj d| j  dS d| jj dS )N<z on >z not connected>)r   r$   	__class__r*   r-   r-   r.   __repr__   s   
zPort.__repr__c                 C      | j S )z)
        Return a socket object.
        )r/   r<   r-   r-   r.   	getHandle      zPort.getHandlec                 C   s   |    |   dS )z
        Create and bind my socket, and begin listening on it.

        This is called on unserialization, and must be called after creating a
        server to begin listening on the specified port.
        N)_bindSocket_connectToProtocolr<   r-   r-   r.   startListening   s   zPort.startListeningc              
   C   s   | j du r*z|  }|| j| jf W n ty) } z	t| j| j|d}~ww | j }d| _ | d | _	t
d| | j| j	f  d| _|| _| jj| _dS )aJ  
        Prepare and assign a L{socket.socket} instance to
        C{self.socket}.

        Either creates a new SOCK_DGRAM L{socket.socket} bound to
        C{self.interface} and C{self.port} or takes an existing
        L{socket.socket} provided via the
        L{interfaces.IReactorSocket.adoptDatagramPort} interface.
        N   z%s starting on %s)r3   createInternetSocketbindr&   r#   OSErrorr   CannotListenErrorr2   r   r   msg_getLogPrefixr$   	connectedr/   filenor*   sktler-   r-   r.   rA      s&   

zPort._bindSocketc                 C   s   | j |  |   d S N)r$   makeConnectionstartReadingr<   r-   r-   r.   rB      s   zPort._connectToProtocolc              
   C   s   d}|| j k rsz| j| j\}}W n0 tyB } z$|jd }|tv r*W Y d}~dS |tv r=| jr6| j	
  W Y d}~dS  d}~ww |t|7 }| jtjkrU|dd }z	| j	|| W n tyk   t  Y nw || j k sdS dS )z=
        Called when my socket is ready for reading.
        r   N   )maxThroughputr/   recvfromr%   rG   args_sockErrReadIgnore_sockErrReadRefuser(   r$   connectionRefusedlenr6   AF_INET6datagramReceivedBaseExceptionr   err)r*   readdataaddrsenor-   r-   r.   doRead   s0   



zPort.doReadc              
   C   s  | j rO|d| j fv sJ z| j|W S  tyN } z/|jd }|tkr/| |W  Y d}~S |tkr8t	d|t
krB| j  n W Y d}~dS d}~ww |dksUJ t|d sqt|d sq|d dkrqt|d dt|d s~|d dkr| jtjkrt|d dt|d r| jtjkrt|d dz| j||W S  ty } z*|jd }|tkr| ||W  Y d}~S |tkrt	d|t
krW Y d}~dS  d}~ww )az  
        Write a datagram.

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

        @type addr: L{tuple} containing L{str} as first element and L{int} as
            second element, or L{None}
        @param addr: A tuple of (I{stringified IPv4 or IPv6 address},
            I{integer port number}); can be L{None} in connected mode.
        Nr   zmessage too longz<broadcast>z0write() only accepts IP addresses, not hostnamesz7IPv6 port write() called with IPv4 or broadcast addressz*IPv4 port write() called with IPv6 address)r(   r/   sendrG   rV   r   writer   r   MessageLengthErrorr   r$   rY   r   isIPAddressisIPv6AddressInvalidAddressErrorr6   r[   AF_INETsendto)r*   datagramra   rb   rc   r-   r-   r.   rf     sb   



z
Port.writec                 C   s   |  d|| dS )a  
        Write a datagram constructed from an iterable of L{bytes}.

        @param seq: The data that will make up the complete datagram to be
            written.
        @type seq: an iterable of L{bytes}

        @type addr: L{tuple} containing L{str} as first element and L{int} as
            second element, or L{None}
        @param addr: A tuple of (I{stringified IPv4 or IPv6 address},
            I{integer port number}); can be L{None} in connected mode.
            N)rf   join)r*   seqra   r-   r-   r.   writeSequence@  s   zPort.writeSequencec                 C   sL   | j rtdt|st|st|d||f| _ | j||f dS )z-
        'Connect' to remote server.
        z:already connected, reconnecting is not currently supportednot an IPv4 or IPv6 address.N)	r(   RuntimeErrorr   rh   ri   r   rj   r/   connect)r*   hostr#   r-   r-   r.   rt   O  s   
zPort.connectc                 C   s&   |    | jr| jd| j d S d S )Nr   )stopReadingrK   r,   	callLaterconnectionLostr<   r-   r-   r.   _loseConnection\  s   zPort._loseConnectionc                 C   s&   | j rt  }| _nd }|   |S rP   )rK   r   Deferreddry   )r*   resultr-   r-   r.   stopListeninga  s
   zPort.stopListeningc                 C   s   t jdtdd |   d S )Nz-Please use stopListening() to disconnect portrS   )
stacklevel)warningswarnDeprecationWarningr}   r<   r-   r-   r.   loseConnectioni  s   zPort.loseConnectionc                 C   sh   t d| j  d| _d| _tj| | | j  | j	
  | `	| `t| dr2| jd | `dS dS )z&
        Cleans up my socket.
        z(UDP Port %s Closed)Nr{   )r   rI   r   rT   r   r!   rx   r$   doStopr/   closerL   hasattrr{   callback)r*   reasonr-   r-   r.   rx   q  s   


zPort.connectionLostc                 C   s   |  | j}d| | _dS )zP
        Initialize the C{logstr} attribute to be used by C{logPrefix}.
        z%s (UDP)N)rJ   r$   logstr)r*   	logPrefixr-   r-   r.   r'     s   zPort.setLogStrc                 C   sH   t | jrtj| _dS t | jrtj| _dS | jr"t	| jddS )z8
        Resolve address family for the socket.
        rr   N)
r   ri   r&   r/   r[   r6   rh   rk   r   rj   r<   r-   r-   r.   r)     s   zPort._setAddressFamilyc                 C   r>   )z0
        Return the prefix to log with.
        )r   r<   r-   r-   r.   r     r@   zPort.logPrefixc                 C   sR   | j  }| jt jkrtjdg|R  S | jt jkr'tjdg|dd R  S dS )z
        Return the local address of the UDP connection

        @returns: the local address of the UDP connection
        @rtype: L{IPv4Address} or L{IPv6Address}
        UDPNrS   )r/   r2   r6   rk   r   IPv4Addressr[   IPv6Addressr*   ra   r-   r-   r.   getHost  s   
zPort.getHostc                 C   s   | j t jt j| dS )z
        Set whether this port may broadcast. This is disabled by default.

        @param enabled: Whether the port may broadcast.
        @type enabled: L{bool}
        N)r/   
setsockopt
SOL_SOCKETSO_BROADCAST)r*   enabledr-   r-   r.   setBroadcastAllowed  s   zPort.setBroadcastAllowedc                 C   s   t | jtjtjS )z
        Checks if broadcast is currently allowed on this port.

        @return: Whether this port may broadcast.
        @rtype: L{bool}
        )boolr/   
getsockoptr   r   r<   r-   r-   r.   getBroadcastAllowed  s   zPort.getBroadcastAllowed)r   r    NrP   )&__name__
__module____qualname____doc__r/   rk   r6   
SOCK_DGRAMr1   rT   r   r   int__annotations__r3   r"   classmethodr7   strr=   r?   rC   rA   rB   rd   rf   rq   rt   ry   r}   r   rx   r'   r)   r   r   r   r   r-   r-   r-   r.   r   >   s:   
 

+
#
 >
	r   c                   @   sl   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dZdd Zdd ZdddZdS )MulticastMixinz,
    Implement multicast functionality.
    c                 C   s$   | j t jt j}t td|S )Nz@i)r/   r   
IPPROTO_IPIP_MULTICAST_IF	inet_ntoastructpack)r*   ir-   r-   r.   getOutgoingInterface  s   z#MulticastMixin.getOutgoingInterfacec                 C   s   | j || jS )zReturns Deferred of success.)r,   resolveaddCallback_setInterfacer   r-   r-   r.   setOutgoingInterface  s   z#MulticastMixin.setOutgoingInterfacec                 C   s"   t |}| j t jt j| dS )NrD   )r/   	inet_atonr   r   r   )r*   ra   r   r-   r-   r.   r     s   
zMulticastMixin._setInterfacec                 C      | j t jt jS rP   )r/   r   r   IP_MULTICAST_LOOPr<   r-   r-   r.   getLoopbackMode     zMulticastMixin.getLoopbackModec                 C   s(   t dt|}| jtjtj| d S )Nb)r   r   r   r/   r   r   r   )r*   moder-   r-   r.   setLoopbackMode  s   zMulticastMixin.setLoopbackModec                 C   r   rP   )r/   r   r   IP_MULTICAST_TTLr<   r-   r-   r.   getTTL  r   zMulticastMixin.getTTLc                 C   s$   t d|}| jtjtj| d S )NB)r   r   r/   r   r   r   )r*   ttlr-   r-   r.   setTTL  s   zMulticastMixin.setTTLr   c                 C      | j || j|dS )z4Join a multicast group. Returns Deferred of success.rD   r,   r   r   
_joinAddr1r*   ra   r&   r-   r-   r.   	joinGroup     zMulticastMixin.joinGroupc                 C   s   | j || j||S rP   )r,   r   r   
_joinAddr2)r*   ra   r&   ro   r-   r-   r.   r     s   zMulticastMixin._joinAddr1c              
   C   s   t |}t |}|rt j}nt j}z| j t j|||  W d S  tyA } ztt	j
||g|jR  W  Y d }~S d }~ww rP   )r/   r   IP_ADD_MEMBERSHIPIP_DROP_MEMBERSHIPr   r   rG   r   Failurer   MulticastJoinErrorrV   )r*   r&   ra   ro   cmder-   r-   r.   r     s   

(zMulticastMixin._joinAddr2c                 C   r   )z2Leave multicast group, return Deferred of success.r   r   r   r-   r-   r.   
leaveGroup  r   zMulticastMixin.leaveGroupN)r   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r-   r-   r-   r.   r     s    
r   c                   @   s*   e Zd ZdZ				d
ddZdd	 ZdS )MulticastPortz.
    UDP Port that supports multicasting.
    r   r    NFc                 C   s   t | ||||| || _dS )zX
        @see: L{twisted.internet.interfaces.IReactorMulticast.listenMulticast}
        N)r   r"   listenMultiple)r*   r#   r+   r&   r%   r,   r   r-   r-   r.   r"     s   
zMulticastPort.__init__c              
   C   s~   t | }| jr=|tjtjd ttdr=z|tjtjd W |S  t	y< } z|j
tkr0n W Y d }~|S d }~ww |S )NrD   SO_REUSEPORT)r   rE   r   r   r/   r   SO_REUSEADDRr   r   rG   errnor   rM   r-   r-   r.   rE     s    



z"MulticastPort.createInternetSocket)r   r    NF)r   r   r   r   r"   rE   r-   r-   r-   r.   r     s    
r   ).r   r/   r   r   typingr   zope.interfacer   twisted.python.runtimer   r   r   r   r   r	   r
   r   r   r   r   r   rW   rX   r   r   r   r   r   twisted.internetr   r   r   r   r   r   twisted.pythonr   r   IListeningPortIUDPTransportISystemHandler!   r   r   IMulticastTransportr   r-   r-   r-   r.   <module>   s>   $ 
   |8