U
    ¸~Hjˆ1  ã                   @  s  d Z ddlmZ ddlZddlZddlZddlZddlmZm	Z	 ddl
mZ ddlmZmZmZmZ ddlmZ ddlmZmZ dd	lmZmZ dd
lmZmZmZ ddlmZ ddl m!Z! ddl"m#Z# erØddl$m%Z% eeej&ej'ej(ƒG dd„ dej)ƒƒZ*eej+ƒG dd„ dee*ƒƒZ,dS )z
UDP support for IOCP reactor
é    )ÚannotationsN)ÚTYPE_CHECKINGÚOptional)Úimplementer)ÚaddressÚdeferÚerrorÚ
interfaces)ÚMulticastMixin)ÚisIPAddressÚisIPv6Address)ÚabstractÚiocpsupport)ÚERROR_CONNECTION_REFUSEDÚERROR_IO_PENDINGÚERROR_PORT_UNREACHABLE)ÚIReadWriteHandle)ÚAbstractDatagramProtocol)Úlog)ÚIOCPReactorc                   @  s  e Zd ZU dZded< ejZejZ	dZ
dZded< d@d
ddd
dddœdd„Zdd„ Zddœdd„Zdd„ Zdd„ Zddœdd„Zdd„ Zd d!„ Zd"d#„ Zd$d%„ Zd&d'„ ZdAd(d)„Zd*d+„ Zd,d-„ Zd.d/„ Zd0d1„ Zd2d3„ ZdBd4d5„Zd6d7„ Zd8d9„ Zd:d;„ Z d<d=„ Z!d>d?„ Z"dS )CÚPortzÈ
    UDP port, listening for packets.

    @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.
    r   ÚreactorFNzOptional[int]Ú_realPortNumberÚ é    Úintr   ÚstrúIOCPReactor | NoneÚNone)ÚportÚprotoÚ	interfaceÚmaxPacketSizer   Úreturnc                 C  sx   || _ || _|| _|| _|  ¡  d| _|  ¡  tj 	| |¡ t
 
| j| j¡}t | ¡ ¡}t|ƒ| _tt d¡ƒ| _dS )z>
        Initialize with a numeric port to listen on.
        NÚi)r   ÚprotocolZreadBufferSizer!   Ú	setLogStrÚ_connectedAddrÚ_setAddressFamilyr   Ú
FileHandleÚ__init__ÚsocketÚaddressFamilyÚ
socketTypeÚ_iocpZ
maxAddrLenÚfilenoÚ	bytearrayÚaddressBufferÚstructÚcalcsizeÚaddressLengthBuffer)Úselfr   r    r!   r"   r   ÚsktZaddrLen© r7   úD/tmp/pip-unpacked-wheel-ewod1tgb/twisted/internet/iocpreactor/udp.pyr*   :   s    
zPort.__init__c                 C  s@   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.
        znot an IPv4 or IPv6 addressN)	r   r!   r+   ÚAF_INET6r,   r   ÚAF_INETr   ÚInvalidAddressError©r5   r7   r7   r8   r(   U   s    



 ÿzPort._setAddressFamily©r#   c                 C  s6   | j d k	r"d| jj› d| j › d�S d| jj› d�S d S )Nú<z on ú>z not connected>)r   r%   Ú	__class__r<   r7   r7   r8   Ú__repr__b   s    
zPort.__repr__c                 C  s   | j S )z)
        Return a socket object.
        )r+   r<   r7   r7   r8   Ú	getHandleh   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Ú_connectToProtocolr<   r7   r7   r8   ÚstartListeningn   s    zPort.startListeningúsocket.socketc                 C  s   | j  | j| j¡S ©N)r   ÚcreateSocketr,   r-   r<   r7   r7   r8   rH   x   s    zPort.createSocketc              
   C  s˜   z|   ¡ }| | j| jf¡ W n4 tk
rR } zt | j| j|¡‚W 5 d }~X Y nX | ¡ d | _t	 
d|  | j¡| jf ¡ d| _|| _| jj| _d S )Né   z%s starting on %sT)rH   Úbindr!   r   ÚOSErrorr   ZCannotListenErrorÚgetsocknamer   r   ÚmsgÚ_getLogPrefixr%   Ú	connectedr+   r/   ÚgetFileHandle)r5   r6   Úler7   r7   r8   rC   {   s    $ÿÿzPort._bindSocketc                 C  s$   | j  | ¡ |  ¡  | j | ¡ d S rG   )r%   ZmakeConnectionZstartReadingr   ZaddActiveHandler<   r7   r7   r8   rD   �   s    zPort._connectToProtocolc                 C  s    | j r|  |||¡ |  ¡  d S rG   )ÚreadingÚ
handleReadÚdoRead©r5   ÚrcÚdataÚevtr7   r7   r8   ÚcbRead”   s    zPort.cbReadc                 C  s’   |t jt jttfkr&| jrŽ| j ¡  nh|rHt 	dt j
 |d¡|f ¡ nFz(| j t|jd |… ƒt |j¡¡ W n tk
rŒ   t ¡  Y nX d S )Nzerror in recvfrom -- %s (%s)zunknown error)ÚerrnoÚWSAECONNREFUSEDÚWSAECONNRESETr   r   r'   r%   ÚconnectionRefusedr   rM   Ú	errorcodeÚgetZdatagramReceivedÚbytesÚbuffr.   ZmakesockaddrÚ	addr_buffÚBaseExceptionÚerrrU   r7   r7   r8   rS   ™   s*    üÿÿ 
ÿzPort.handleReadc                 C  sv   t  | j| ¡}| jd  |_}| j |_}| j |_}t  	|  
¡ ||||¡\}}|rr|tkrr| j d| j|||¡ d S ©Nr   )r.   ÚEventrY   Z_readBuffersra   r1   rb   r4   Úaddr_len_buffÚrecvfromrP   r   r   Ú	callLater)r5   rX   ra   rb   rg   rV   rW   r7   r7   r8   rT   ¯   s        ÿzPort.doReadc              
   C  sâ  | j r¬|d| j fkst‚z| j |¡W S  tk
r¦ } zb|jd }|tjkr^|  |¡ W Y ¢>S |tj	krtt
 d¡‚n"|tjtjttfkr”| j ¡  n‚ W 5 d}~X Y nX �n2|dks¸t‚t|d ƒsìt|d ƒsì|d dkrìt
 |d d¡‚t|d ƒ�r| jtjk�rt
 |d d¡‚t|d ƒ�rD| jtjk�rDt
 |d d¡‚z| j ||¡W S  tk
�rÜ } zh|jd }|tjk�r’|  ||¡ W Y ¢@S |tj	k�rªt
 d¡‚n"|tjtjttfk�rÊW Y ¢
dS ‚ W 5 d}~X Y nX dS )z~
        Write a datagram.

        @param addr: should be a tuple (ip, port), can be None in connected
        mode.
        Nr   zmessage too longz<broadcast>z0write() only accepts IP addresses, not hostnamesz*IPv6 port write() called with IPv4 addressz*IPv4 port write() called with IPv6 address)r'   ÚAssertionErrorr+   ÚsendrK   ÚargsrZ   ZWSAEINTRÚwriteZWSAEMSGSIZEr   ZMessageLengthErrorr[   r\   r   r   r%   r]   r   r   r;   r,   r9   r:   Úsendto)r5   ZdatagramÚaddrÚseÚnor7   r7   r8   rm   Á   sn    


ü
ÿ
þ
ý ÿ ÿ ÿ
ü	
z
Port.writec                 C  s   |   d |¡|¡ d S )Nó    )rm   Újoin)r5   Úseqro   r7   r7   r8   ÚwriteSequence  s    zPort.writeSequencec                 C  sH   | 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 (talk to itamar if you want this)znot an IPv4 or IPv6 address.N)r'   ÚRuntimeErrorr   r   r   r;   r+   Úconnect)r5   Úhostr   r7   r7   r8   rw     s    ÿ
zPort.connectc                 C  s.   |   ¡  | j | ¡ | jr*| j d| j¡ d S re   )ZstopReadingr   ZremoveActiveHandlerO   ri   ÚconnectionLostr<   r7   r7   r8   Ú_loseConnection  s    zPort._loseConnectionc                 C  s&   | j rt ¡  }| _nd }|  ¡  |S rG   )rO   r   ZDeferredÚdrz   )r5   Úresultr7   r7   r8   ÚstopListening  s
    zPort.stopListeningc                 C  s   t jdtdd� |  ¡  d S )Nz-Please use stopListening() to disconnect porté   )Ú
stacklevel)ÚwarningsÚwarnÚDeprecationWarningr}   r<   r7   r7   r8   ÚloseConnection!  s    ýzPort.loseConnectionc                 C  s^   t  d| j ¡ d| _tj | |¡ | j ¡  | j 	¡  | `| `
t| dƒrZ| j d¡ | `dS )z&
        Cleans up my socket.
        z(UDP Port %s Closed)Nr{   )r   rM   r   r   r)   ry   r%   ZdoStopr+   ÚcloserP   Úhasattrr{   Úcallback)r5   Úreasonr7   r7   r8   ry   )  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)rN   r%   Úlogstr)r5   Ú	logPrefixr7   r7   r8   r&   8  s    zPort.setLogStrc                 C  s   | j S )zK
        Returns the name of my class, to prefix log entries with.
        )rˆ   r<   r7   r7   r8   r‰   ?  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}
        ÚUDPNr~   )rŠ   )rŠ   )r+   rL   r,   r:   r   ÚIPv4Addressr9   ÚIPv6Address)r5   ro   r7   r7   r8   ÚgetHostE  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)r5   Zenabledr7   r7   r8   ÚsetBroadcastAllowedR  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<   r7   r7   r8   ÚgetBroadcastAllowed[  s    zPort.getBroadcastAllowed)r   r   N)N)N)#Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú__annotations__r+   r:   r,   Ú
SOCK_DGRAMr-   ZdynamicReadBuffersr   r*   r(   rA   rB   rE   rH   rC   rD   rY   rS   rT   rm   ru   rw   rz   r}   rƒ   ry   r&   r‰   r�   r‘   r”   r7   r7   r7   r8   r   #   s@   
   ú

A
	r   c                	   @  s:   e Zd ZdZdddddd	d
ddœdd„Zddœdd„ZdS )ÚMulticastPortz.
    UDP Port that supports multicasting.
    r   r   NFr   r   r   r   r’   r   )r   r    r!   r"   r   ÚlistenMultipler#   c                 C  s   t  | |||||¡ || _d S rG   )r   r*   rœ   )r5   r   r    r!   r"   r   rœ   r7   r7   r8   r*   k  s    	zMulticastPort.__init__rF   r=   c                 C  sB   t  | ¡}| jr>| tjtjd¡ ttdƒr>| tjtjd¡ |S )NrI   ÚSO_REUSEPORT)	r   rH   rœ   rŽ   r+   r�   ÚSO_REUSEADDRr…   r�   )r5   r6   r7   r7   r8   rH   w  s    

zMulticastPort.createSocket)r   r   NF)r•   r–   r—   r˜   r*   rH   r7   r7   r7   r8   r›   e  s       ùr›   )-r˜   Ú
__future__r   rZ   r+   r2   r€   Útypingr   r   Zzope.interfacer   Ztwisted.internetr   r   r   r	   Ztwisted.internet._multicastr
   Ztwisted.internet.abstractr   r   Ztwisted.internet.iocpreactorr   r   r.   Z"twisted.internet.iocpreactor.constr   r   r   Z'twisted.internet.iocpreactor.interfacesr   Ztwisted.internet.protocolr   Ztwisted.pythonr   Z$twisted.internet.iocpreactor.reactorr   ZIListeningPortZIUDPTransportZISystemHandler)   r   ZIMulticastTransportr›   r7   r7   r7   r8   Ú<module>   s8   ü  >