U
    ¹êW[‰H  ã                   @   sœ  d Z ddlmZmZ ddlZddlZddlZddlZddlm	Z	 ddl
mZ edkrÊddlmZ ddlmZmZmZ dd	lmZmZmZ dd
lmZ ddlmZ eeeegZeeeegZeZeZeZeZn8ddlmZmZmZmZmZ ddlmZ eeegZegZddlmZ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) e	e)j*e)j+e)j,ƒG dd„ dej-ƒƒZ.e&G dd„ dƒƒZ/e	e)j0ƒG dd„ de/e.ƒƒZ1d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.
é    )ÚdivisionÚabsolute_importN)Úimplementer)ÚplatformTypeZwin32)ÚWSAEWOULDBLOCK)ÚWSAEINTRÚWSAEMSGSIZEÚWSAETIMEDOUT)ÚWSAECONNREFUSEDÚWSAECONNRESETÚWSAENETRESET)ÚWSAEINPROGRESS)ÚWSAENOPROTOOPT)ÚEWOULDBLOCKÚEINTRÚEMSGSIZEÚECONNREFUSEDÚEAGAIN)ÚENOPROTOOPT)ÚbaseÚdeferÚaddress)ÚlogÚfailure)Ú	_oldStyle)ÚabstractÚerrorÚ
interfacesc                   @   sÚ   e Zd ZdZejZejZdZ	dZ
dZd0dd„Zedd	„ ƒZd
d„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd1dd„Zdd„ Zdd„ Zdd„ Zdd„ Zd d!„ Zd2d"d#„Zd$d%„ Zd&d'„ Zd(d)„ Zd*d+„ Zd,d-„ Z d.d/„ Z!dS )3Ú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Ú é    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"   Y   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}.
        @param addressFamily: L{int}

        @param protocol: A C{DatagramProtocol} instance which will be
            connected to the C{port}.
        @type proto: 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%   )ÚsocketZfromfdÚ
socketTypeÚgetsocknameÚ_preexistingSocket)	Úclsr,   ÚfdÚaddressFamilyr$   r%   r#   r&   r*   r-   r-   r.   Ú_fromListeningDescriptorx   s    
ÿzPort._fromListeningDescriptorc                 C   s.   | j d k	rd| jj| j f S d| jjf S d S )Nz
<%s on %s>z<%s not connected>)Ú_realPortNumberr$   Ú	__class__©r*   r-   r-   r.   Ú__repr__Ÿ   s    
zPort.__repr__c                 C   s   | j S )z)
        Return a socket object.
        )r/   r9   r-   r-   r.   Ú	getHandle¥   s    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Ú_connectToProtocolr9   r-   r-   r.   ÚstartListening«   s    zPort.startListeningc              
   C   s²   | j dkrbz|  ¡ }| | j| jf¡ W qn tjk
r^ } zt | j| j|¡‚W 5 d}~X Y qnX n| 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)r2   ÚcreateInternetSocketZbindr&   r#   r/   r   ZCannotListenErrorr1   r7   r   ÚmsgÚ_getLogPrefixr$   Ú	connectedÚfileno©r*   ZsktÚler-   r-   r.   r<   ¶   s     

&
 ÿzPort._bindSocketc                 C   s   | j  | ¡ |  ¡  d S ©N)r$   ZmakeConnectionZstartReadingr9   r-   r-   r.   r=   Ø   s    zPort._connectToProtocolc              
   C   sÜ   d}|| j k rØz| j | j¡\}}W nd tjk
rˆ } zD|jd }|tkrTW Y ¢,dS |tkrv| jrl| j	 
¡  W Y ¢
dS ‚ W 5 d}~X Y qX |t|ƒ7 }| jtjkr®|dd… }z| j	 ||¡ W q   t ¡  Y qX qdS )z=
        Called when my socket is ready for reading.
        r   Né   )ÚmaxThroughputr/   Zrecvfromr%   r   ÚargsÚ_sockErrReadIgnoreÚ_sockErrReadRefuser(   r$   ÚconnectionRefusedÚlenr5   ÚAF_INET6ZdatagramReceivedr   Úerr)r*   ÚreadÚdataÚaddrÚseÚnor-   r-   r.   ÚdoReadÝ   s(    




zPort.doReadc              
   C   sÜ  | j rž|d| j fkst‚z| j |¡W S  tjk
r˜ } zR|jd }|tkr^|  |¡ W Y ¢0S |tkrrt 	d¡‚n|t
kr†| j ¡  n‚ W 5 d}~X Y nX n:|dksªt‚t |d ¡sât |d ¡sâ|d dkrât |d d¡‚t |d ¡s |d dkr| jtjkrt |d d¡‚t |d ¡rL| jtjkrLt |d d¡‚z| j ||¡W S  tjk
rÖ } zX|jd }|tkrš|  ||¡ W Y ¢2S |tkr°t 	d¡‚n|t
krÄW Y ¢
dS ‚ W 5 d}~X Y nX dS )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(   ÚAssertionErrorr/   Úsendr   rJ   r   Úwriter   ZMessageLengthErrorr   r$   rM   r   ÚisIPAddressÚisIPv6AddressÚInvalidAddressErrorr5   rO   ÚAF_INETZsendto)r*   ZdatagramrS   rT   rU   r-   r-   r.   rY   þ   s`    
ÿ
þþ
ÿþ
ÿ ÿ




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)rY   Újoin)r*   ÚseqrS   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   rZ   r[   r   r\   r/   Úconnect)r*   Zhostr#   r-   r-   r.   rd   J  s     ÿ
zPort.connectc                 C   s"   |   ¡  | jr| j d| j¡ d S )Nr   )ZstopReadingrC   r,   Z	callLaterÚconnectionLostr9   r-   r-   r.   Ú_loseConnectionW  s    zPort._loseConnectionc                 C   s&   | j rt ¡  }| _nd }|  ¡  |S rG   )rC   r   ZDeferredÚdrf   )r*   Úresultr-   r-   r.   ÚstopListening]  s
    zPort.stopListeningc                 C   s   t jdtdd |  ¡  d S )Nz-Please use stopListening() to disconnect portrH   )Ú
stacklevel)ÚwarningsÚwarnÚDeprecationWarningri   r9   r-   r-   r.   ÚloseConnectionf  s    zPort.loseConnectionc                 C   sd   t  d| j ¡ d| _d| _tj | |¡ | j ¡  | j	 
¡  | `	| `t| dƒr`| j d¡ | `dS )z&
        Cleans up my socket.
        z(UDP Port %s Closed)Néÿÿÿÿrg   )r   rA   r7   rI   r   r!   re   r$   ZdoStopr/   ÚcloserD   Úhasattrrg   Úcallback)r*   Úreasonr-   r-   r.   re   k  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)rB   r$   Úlogstr)r*   Ú	logPrefixr-   r-   r.   r'   |  s    zPort.setLogStrc                 C   sD   t  | j¡rtj| _n*t  | j¡r,tj| _n| jr@t 	| jd¡‚dS )z8
        Resolve address family for the socket.
        rb   N)
r   r[   r&   r/   rO   r5   rZ   r]   r   r\   r9   r-   r-   r.   r)   „  s    

 ÿzPort._setAddressFamilyc                 C   s   | j S )z0
        Return the prefix to log with.
        )rt   r9   r-   r-   r.   ru   ‘  s    zPort.logPrefixc                 C   sJ   | j  ¡ }| jt jkr$tjd|žŽ S | jt jkrFtjd|dd… žŽ 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}
        ÚUDPNrH   )rv   )rv   )r/   r1   r5   r]   r   ZIPv4AddressrO   ZIPv6Address©r*   rS   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}
        )ÚoperatorÚtruthr/   Ú
getsockoptrz   r{   r9   r-   r-   r.   ÚgetBroadcastAllowed±  s    ÿzPort.getBroadcastAllowed)r   r    N)N)N)"Ú__name__Ú
__module__Ú__qualname__Ú__doc__r/   r]   r5   Z
SOCK_DGRAMr0   rI   r7   r2   r"   Úclassmethodr6   r:   r;   r>   r<   r=   rV   rY   ra   rd   rf   ri   rn   re   r'   r)   ru   rx   r}   r   r-   r-   r-   r.   r   <   s8   

&"!
<	
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_IFZ	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Ú_setInterfacerw   r-   r-   r.   ÚsetOutgoingInterfaceÈ  s    z#MulticastMixin.setOutgoingInterfacec                 C   s"   t  |¡}| j  t jt j|¡ dS )Nr?   )r/   Ú	inet_atonry   rˆ   r‰   )r*   rS   rŒ   r-   r-   r.   r   Í  s    
zMulticastMixin._setInterfacec                 C   s   | j  t jt j¡S rG   )r/   r€   rˆ   ÚIP_MULTICAST_LOOPr9   r-   r-   r.   ÚgetLoopbackModeÓ  s    zMulticastMixin.getLoopbackModec                 C   s*   t  dt |¡¡}| j tjtj|¡ d S )NÚb)rŠ   r‹   r~   r   r/   ry   rˆ   r“   )r*   Úmoder-   r-   r.   ÚsetLoopbackMode×  s    zMulticastMixin.setLoopbackModec                 C   s   | j  t jt j¡S rG   )r/   r€   rˆ   ÚIP_MULTICAST_TTLr9   r-   r-   r.   ÚgetTTLÜ  s    zMulticastMixin.getTTLc                 C   s$   t  d|¡}| j tjtj|¡ d S )NÚB)rŠ   r‹   r/   ry   rˆ   r˜   )r*   Zttlr-   r-   r.   ÚsetTTLà  s    zMulticastMixin.setTTLr   c                 C   s   | j  |¡ | j|d¡S )z4Join a multicast group. Returns Deferred of success.r?   ©r,   rŽ   r   Ú
_joinAddr1©r*   rS   r&   r-   r-   r.   Ú	joinGroupå  s    zMulticastMixin.joinGroupc                 C   s   | j  |¡ | j||¡S rG   )r,   rŽ   r   Ú
_joinAddr2)r*   rS   r&   r_   r-   r-   r.   r   ê  s    zMulticastMixin._joinAddr1c              
   C   sˆ   t  |¡}t  |¡}|r t j}nt j}z| j  t j||| ¡ W nB t jk
r‚ } z"t tj	||f|j
žŽ ¡ W Y ¢S d }~X Y nX d S rG   )r/   r’   ZIP_ADD_MEMBERSHIPZIP_DROP_MEMBERSHIPry   rˆ   r   r   ZFailureZMulticastJoinErrorrJ   )r*   r&   rS   r_   ÚcmdÚer-   r-   r.   r    î  s    

zMulticastMixin._joinAddr2c                 C   s   | j  |¡ | j|d¡S )z2Leave multicast group, return Deferred of success.r   rœ   rž   r-   r-   r.   Ú
leaveGroupû  s    zMulticastMixin.leaveGroupN)r   )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   sz   t  | ¡}| jrv| tjtjd¡ ttdƒrvz| tjtjd¡ W n2 tj	k
rt } z|j
tkrbn‚ W 5 d }~X Y nX |S )Nr?   ÚSO_REUSEPORT)r   r@   r¥   ry   r/   rz   ZSO_REUSEADDRrq   r¦   r   Úerrnor   rE   r-   r-   r.   r@     s    


z"MulticastPort.createInternetSocket)r   r    NF)r‚   rƒ   r„   r…   r"   r@   r-   r-   r-   r.   r¤     s       ÿ
	r¤   )2r…   Z
__future__r   r   r/   r~   rŠ   rk   Zzope.interfacer   Ztwisted.python.runtimer   r§   r   r   r   r	   r
   r   r   r   r   r   rK   rL   r   r   r   r   r   Ztwisted.internetr   r   r   Ztwisted.pythonr   r   Ztwisted.python._oldstyler   r   r   r   ZIListeningPortZIUDPTransportZISystemHandler!   r   r‡   ZIMulticastTransportr¤   r-   r-   r-   r.   Ú<module>   sT   ÿ
 þ   C