
    Ϫf7                        d 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 ddl	m
Z
mZmZ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mZ  eeej<                  ej>                  ej@                         G d dejB                               Z" G d d      Z# eejH                         G d de#e"             Z%y)z
UDP support for IOCP reactor
    N)Optional)implementer)addressdefererror
interfaces)isIPAddressisIPv6Address)abstractiocpsupport)ERROR_CONNECTION_REFUSEDERROR_IO_PENDINGERROR_PORT_UNREACHABLE)IReadWriteHandle)failurelogc                       e Zd ZU dZej
                  Zej                  ZdZ	dZ
ee   ed<   ddZd ZdefdZd	 Zd
 Zd Zd Zd Zd Zd Zd ZddZd Zd Zd Zd Zd ZddZ d Z!d Z"d Z#d Z$d Z%y)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.
    FN_realPortNumberc                    || _         || _        || _        || _        | j	                          d| _        | j                          t        j                  j                  | |       t        j                  | j                  | j                        }t        j                  |j                               }t!        |      | _        t!        t%        j&                  d            | _        y)z>
        Initialize with a numeric port to listen on.
        Ni)portprotocolreadBufferSize	interface	setLogStr_connectedAddr_setAddressFamilyr   
FileHandle__init__socketaddressFamily
socketType_iocp
maxAddrLenfileno	bytearrayaddressBufferstructcalcsizeaddressLengthBuffer)selfr   protor   maxPacketSizereactorsktaddrLens           B/usr/lib/python3/dist-packages/twisted/internet/iocpreactor/udp.pyr    zPort.__init__2   s     	+"" $$T73mmD..@""3::<0&w/#,V__S-A#B     c                    t        | j                        rt        j                  | _        yt        | j                        rt        j                  | _        y| j                  r t        j                  | j                  d      y)z8
        Resolve address family for the socket.
        znot an IPv4 or IPv6 addressN)	r
   r   r!   AF_INET6r"   r	   AF_INETr   InvalidAddressErrorr,   s    r2   r   zPort._setAddressFamilyF   s]     (!'D(!'D^^++ =  r3   returnc                     | j                   'd| j                  j                   d| j                    dS d| j                  j                   dS )N<z on >z not connected>)r   r   	__class__r8   s    r2   __repr__zPort.__repr__S   sO    +t}}../tD4H4H3IKKt}}../??r3   c                     | j                   S )z)
        Return a socket object.
        )r!   r8   s    r2   	getHandlezPort.getHandleY        {{r3   c                 D    | j                          | j                          y)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_connectToProtocolr8   s    r2   startListeningzPort.startListening_   s     	!r3   c                 b    | j                   j                  | j                  | j                        S N)r/   createSocketr"   r#   r8   s    r2   rH   zPort.createSocketi   s#    ||((););T__MMr3   c                    	 | j                         }|j                  | j                  | j                  f       |j                         d   | _        t        j                  | j                  | j                        d| j                         d| _        || _        | j                  j                  | _        y # t        $ r0}t        j                  | j                  | j                  |      d }~ww xY w)N   z starting on T)rH   bindr   r   OSErrorr   CannotListenErrorgetsocknamer   r   msg_getLogPrefixr   	connectedr!   r&   getFileHandle)r,   r0   les      r2   rC   zPort._bindSocketl   s    	I##%CHHdnndii01  #03!!$--0$2F2FH	

 ![[//  	I))$..$))RHH	Is   7B8 8	C1+C,,C1c                     | j                   j                  |        | j                          | j                  j	                  |        y rG   )r   makeConnectionstartReadingr/   addActiveHandler8   s    r2   rD   zPort._connectToProtocol   s2    $$T*$$T*r3   c                 d    | j                   r$| j                  |||       | j                          y y rG   )reading
handleReaddoReadr,   rcdataevts       r2   cbReadzPort.cbRead   s'    <<OOBc*KKM r3   c                    |t         j                  t         j                  t        t        fv r(| j
                  r| j                  j                          y y |r;t        j                  dt         j                  j                  |d      d|d       y 	 | j                  j                  t        |j                  d |       t        j                   |j"                               y # t$        $ r t        j&                          Y y w xY w)Nzerror in recvfrom -- zunknown errorz ())errnoWSAECONNREFUSEDWSAECONNRESETr   r   r   r   connectionRefusedr   rO   	errorcodegetdatagramReceivedbytesbuffr$   makesockaddr	addr_buffBaseExceptionerrr\   s       r2   rZ   zPort.handleRead   s    !!$"	
 
 ""//1 #GG??&&r?;RA
..#((5D/*E,>,>s}},M ! 	s   AC# #DDc                 |   t        j                  | j                  |       }| j                  d   x|_        }| j
                  x|_        }| j                  x|_        }t        j                  | j                         ||||      \  }}|r4|t        k7  r*| j                  j                  d| j                  |||       y y y Nr   )r$   Eventr`   _readBuffersrk   r(   rm   r+   addr_len_buffrecvfromrR   r   r/   	callLater)r,   r_   rk   rm   rt   r]   r^   s          r2   r[   zPort.doRead   s    kk$++t,++A..4$($6$66	,0,D,DDM>> $	=#
D "(( LL""1dkk2tSA )2r3   c                    | j                   r.|d| j                   fv sJ 	 | j                  j                  |      S |dk7  sJ t#        |d         s/t%        |d         s!|d   dk7  rt        j&                  |d   d      t#        |d         r6| j(                  t        j*                  k(  rt        j&                  |d   d      t%        |d         r6| j(                  t        j,                  k(  rt        j&                  |d   d      	 | j                  j/                  ||      S # t        $ r}|j                  d   }|t
        j                  k(  r| j                  |      cY d}~S |t
        j                  k(  rt        j                  d      |t
        j                  t
        j                  t        t        fv r| j                  j!                          n Y d}~yd}~ww xY w# t        $ r}|j                  d   }|t
        j                  k(  r| j                  ||      cY d}~S |t
        j                  k(  rt        j                  d      |t
        j                  t
        j                  t        t        fv rY d}~y d}~ww xY w)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   r!   sendrL   argsrc   WSAEINTRwriteWSAEMSGSIZEr   MessageLengthErrorrd   re   r   r   r   rf   r	   r
   r7   r"   r5   r6   sendto)r,   datagramaddrsenos        r2   r{   z
Port.write   sF    D$"5"56666{{''11" 4<<Q(%d1g.G},//GO  47#(:(:foo(M//GI  T!W%$*<*<*N//GI {{))(D99E  WWQZ'::h//5,,,223EFF))'',*	  MM335 6F  WWQZ'::h555,,,223EFF))'',*	  #sO   D$ G" $	G-2GG%A0GG"	J+3I>J$AI>=I>>Jc                 F    | j                  dj                  |      |       y )Nr3   )r{   join)r,   seqr   s      r2   writeSequencezPort.writeSequence   s    

388C=$'r3   c                     | j                   rt        d      t        |      s!t        |      st	        j
                  |d      ||f| _         | j                  j                  ||f       y)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   r7   r!   connect)r,   hostr   s      r2   r   zPort.connect   sf     4  4 t)<++D2PQQ#TlT4L)r3   c                     | j                          | j                  j                  |        | j                  r'| j                  j	                  d| j
                         y y rq   )stopReadingr/   removeActiveHandlerQ   rv   connectionLostr8   s    r2   _loseConnectionzPort._loseConnection  sF    ''->>LL""1d&9&9: r3   c                 z    | j                   rt        j                         x}| _        nd }| j	                          |S rG   )rQ   r   Deferreddr   )r,   results     r2   stopListeningzPort.stopListening
  s2    >>#nn..FTVFr3   c                 \    t        j                  dt        d       | j                          y )Nz-Please use stopListening() to disconnect port   )
stacklevel)warningswarnDeprecationWarningr   r8   s    r2   loseConnectionzPort.loseConnection  s%    ;	

 	r3   c                 Z   t        j                  d| j                  z         d| _        t        j                  j                  | |       | j                  j                          | j                  j                          | `| `
t        | d      r| j                  j                  d       | `yy)z&
        Cleans up my socket.
        z(UDP Port %s Closed)Nr   )r   rO   r   r   r   r   r   doStopr!   closerR   hasattrr   callback)r,   reasons     r2   r   zPort.connectionLost  s     	&)=)==>#**48K4FFOOD! r3   c                 N    | j                  | j                        }d|z  | _        y)zP
        Initialize the C{logstr} attribute to be used by C{logPrefix}.
        z%s (UDP)N)rP   r   logstr)r,   	logPrefixs     r2   r   zPort.setLogStr)  s$     &&t}}5	 9,r3   c                     | j                   S )zK
        Returns the name of my class, to prefix log entries with.
        )r   r8   s    r2   r   zPort.logPrefix0  rA   r3   c                 
   | j                   j                         }| j                  t         j                  k(  rt	        j
                  dg| S | j                  t         j                  k(  rt	        j                  dg|dd  S y)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!   rN   r"   r6   r   IPv4Addressr5   IPv6Addressr,   r   s     r2   getHostzPort.getHost6  sq     {{&&(/&&u4t446??2&&u:Ra:: 3r3   c                 v    | j                   j                  t         j                  t         j                  |       y)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,   enableds     r2   setBroadcastAllowedzPort.setBroadcastAllowedC  s&     	v00&2E2EwOr3   c                     t        | j                  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   r8   s    r2   getBroadcastAllowedzPort.getBroadcastAllowedL  s,     DKK**6+<+<f>Q>QRSSr3   )     NrG   )&__name__
__module____qualname____doc__r!   r6   r"   
SOCK_DGRAMr#   dynamicReadBuffersr   r   int__annotations__r    r   strr>   r@   rE   rH   rC   rD   r`   rZ   r[   r{   r   r   r   r   r   r   r   r   r   r   r    r3   r2   r   r      s     NNM""J &*OXc])C(@# @"N0(+

,B$?B(*;-;PTr3   r   c                   V    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
dd	Zd
 Zd ZddZy)MulticastMixinz,
    Implement multicast functionality.
    c                     | j                   j                  t         j                  t         j                        }t        j                  t        j                  d|            S )Nz@i)r!   r   
IPPROTO_IPIP_MULTICAST_IF	inet_ntoar)   pack)r,   r   s     r2   getOutgoingInterfacez#MulticastMixin.getOutgoingInterface[  s@    KK""6#4#4f6L6LMD! 455r3   c                 j    | j                   j                  |      j                  | j                        S )z.
        Returns Deferred of success.
        )r/   resolveaddCallback_setInterfacer   s     r2   setOutgoingInterfacez#MulticastMixin.setOutgoingInterface_  s*     ||##D)55d6H6HIIr3   c                     t        j                  |      }| j                   j                  t         j                  t         j                  |       y)NrJ   )r!   	inet_atonr   r   r   )r,   r   r   s      r2   r   zMulticastMixin._setInterfacee  s7    T"v00&2H2H!Lr3   c                 r    | j                   j                  t         j                  t         j                        S rG   )r!   r   r   IP_MULTICAST_LOOPr8   s    r2   getLoopbackModezMulticastMixin.getLoopbackModej  s%    {{%%f&7&79Q9QRRr3   c                     t        j                  dt        |            }| j                  j	                  t        j
                  t        j                  |       y )Nb)r)   r   r   r!   r   r   r   )r,   modes     r2   setLoopbackModezMulticastMixin.setLoopbackModem  s8    {{3T
+v00&2J2JDQr3   c                 r    | j                   j                  t         j                  t         j                        S rG   )r!   r   r   IP_MULTICAST_TTLr8   s    r2   getTTLzMulticastMixin.getTTLq  s%    {{%%f&7&79P9PQQr3   c                     t        j                  d|      }| j                  j                  t        j                  t        j
                  |       y )NB)r)   r   r!   r   r   r   )r,   ttls     r2   setTTLzMulticastMixin.setTTLt  s4    kk#s#v00&2I2I3Or3   c                 n    | j                   j                  |      j                  | j                  |d      S )zF
        Join a multicast group. Returns Deferred of success.
        rJ   r/   r   r   
_joinAddr1r,   r   r   s      r2   	joinGroupzMulticastMixin.joinGroupx  -     ||##D)55dooyRSTTr3   c                 n    | j                   j                  |      j                  | j                  ||      S rG   )r/   r   r   
_joinAddr2)r,   r   r   r   s       r2   r   zMulticastMixin._joinAddr1~  s+    ||##I.::4??DRVWWr3   c                    t        j                  |      }t        j                  |      }|rt         j                  }nt         j                  }	 | j                   j	                  t         j
                  |||z          y # t        $ r>}t        j                  t        j                  ||g|j                         cY d }~S d }~ww xY wrG   )r!   r   IP_ADD_MEMBERSHIPIP_DROP_MEMBERSHIPr   r   rL   r   Failurer   MulticastJoinErrorry   )r,   r   r   r   cmdes         r2   r   zMulticastMixin._joinAddr2  s    %$$Y/	**C++C	WKK""6#4#4c4);KL 	W??5#;#;D)#Uaff#UVV	Ws   .A> >	C3C :C Cc                 n    | j                   j                  |      j                  | j                  |d      S )zD
        Leave multicast group, return Deferred of success.
        r   r   r   s      r2   
leaveGroupzMulticastMixin.leaveGroup  r   r3   N)r   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r3   r2   r   r   V  sG    6J
SRRPUX
WUr3   r   c                   &    e Zd ZdZ	 	 	 	 ddZd Zy)MulticastPortz.
    UDP Port that supports multicasting.
    Nc                 F    t         j                  | |||||       || _        y rG   )r   r    listenMultiple)r,   r   r-   r   r.   r/   r   s          r2   r    zMulticastPort.__init__  s"     	dD%M7K,r3   c                 $   t         j                  |       }| j                  rn|j                  t        j
                  t        j                  d       t        t        d      r/|j                  t        j
                  t        j                  d       |S )NrJ   SO_REUSEPORT)	r   rH   r   r   r!   r   SO_REUSEADDRr   r   )r,   r0   s     r2   rH   zMulticastPort.createSocket  sb    %NN6,,f.A.A1Ev~.v00&2E2EqI
r3   )r   r   NF)r   r   r   r   r    rH   r   r3   r2   r   r     s     
-r3   r   )&r   rc   r!   r)   r   typingr   zope.interfacer   twisted.internetr   r   r   r   twisted.internet.abstractr	   r
   twisted.internet.iocpreactorr   r   r$   "twisted.internet.iocpreactor.constr   r   r   'twisted.internet.iocpreactor.interfacesr   twisted.pythonr   r   IListeningPortIUDPTransportISystemHandler   r   r   IMulticastTransportr   r   r3   r2   <module>r     s         & > > @ G 
 E ' 	qT8 qTqTh	;U ;U| Z++,ND  -r3   