o b\6@sdZddlZddlZddlZddlZddlmZddlmZddl m Z m Z m Z m Z ddlmZmZddlmZmZddlmZmZmZdd lmZdd lmZmZeee je je j Gd d d ej!Z"Gd ddZ#ee j$Gddde#e"Z%dS)z UDP support for IOCP reactor N)Optional) implementer)addressdefererror interfaces) isIPAddress isIPv6Address)abstract iocpsupport)ERROR_CONNECTION_REFUSEDERROR_IO_PENDINGERROR_PORT_UNREACHABLE)IReadWriteHandle)failurelogc@seZdZUdZejZejZdZ dZ e e e d<d6ddZd d Zd efd d ZddZddZddZddZddZddZddZddZd7ddZd d!Zd"d#Zd$d%Zd&d'Zd(d)Zd7d*d+Z d,d-Z!d.d/Z"d0d1Z#d2d3Z$d4d5Z%dS)8Portz 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_realPortNumber cCsx||_||_||_||_|d|_|tj ||t |j |j }t |}t||_ttd|_dS)z> Initialize with a numeric port to listen on. Ni)portprotocolreadBufferSize interface setLogStr_connectedAddr_setAddressFamilyr FileHandle__init__socket addressFamily socketType_iocp maxAddrLenfileno bytearray addressBufferstructcalcsizeaddressLengthBuffer)selfrprotor maxPacketSizereactorsktaddrLenr1B/usr/lib/python3/dist-packages/twisted/internet/iocpreactor/udp.pyr2s z Port.__init__cCsDt|jr tj|_dSt|jrtj|_dS|jr t|jddS)z8 Resolve address family for the socket. znot an IPv4 or IPv6 addressN) r rr AF_INET6r!rAF_INETrInvalidAddressErrorr+r1r1r2rFs    zPort._setAddressFamilyreturncCs2|jdurd|jjd|jdSd|jjdS)Nz not connected>)rr __class__r6r1r1r2__repr__Ss z Port.__repr__cC|jS)z) Return a socket object. )r r6r1r1r2 getHandleYzPort.getHandlecCs||dS)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_connectToProtocolr6r1r1r2startListening_s zPort.startListeningcCs|j|j|jSN)r. createSocketr!r"r6r1r1r2rCizPort.createSocketc Csz|}||j|jfWnty$}z t|j|j|d}~ww|d|_t d| |j |jfd|_ ||_|jj|_dS)Nz%s starting on %sT)rCbindrrOSErrorrCannotListenError getsocknamerrmsg _getLogPrefixr connectedr r% getFileHandle)r+r/ler1r1r2r?ls zPort._bindSocketcCs$|j|||j|dSrB)rmakeConnection startReadingr.addActiveHandler6r1r1r2r@s zPort._connectToProtocolcCs$|jr|||||dSdSrB)reading handleReaddoReadr+rcdataevtr1r1r2cbReads z Port.cbReadcCs|tjtjttfvr|jr|jdSdS|r(t dtj |d|fdSz|j t |jd|t|jWdStyKtYdSw)Nzerror in recvfrom -- %s (%s)z unknown error)errnoWSAECONNREFUSED WSAECONNRESETr rrrconnectionRefusedrrJ errorcodegetdatagramReceivedbytesbuffr# makesockaddr addr_buff BaseExceptionerrrUr1r1r2rSs, zPort.handleReadcCsvt|j|}|jd|_}|j|_}|j|_}t | ||||\}}|r7|t kr9| |||dSdSdSNr) r#EventrY _readBuffersrbr'rdr* addr_len_buffrecvfromrMr rS)r+rXrbrdrjrVrWr1r1r2rTs   z Port.doReadc Cs|jrW|d|jfvs Jz|j|WStyV}z7|jd}|tjkr0||WYd}~S|tjkr:t d|tj tj t tfvrJ|jnWYd}~dSd}~ww|dks]Jt|dswt|dsw|ddkrwt |ddt|dr|jtjkrt |ddt|dr|jtjkrt |ddz|j||WSty}z2|jd}|tjkr|||WYd}~S|tjkrt d|tj tj t tfvrWYd}~dSd}~ww)z~ Write a datagram. @param addr: should be a tuple (ip, port), can be None in connected mode. Nrzmessage too longz z0write() only accepts IP addresses, not hostnamesz*IPv6 port write() called with IPv4 addressz*IPv4 port write() called with IPv6 address)rr sendrGargsrZWSAEINTRwrite WSAEMSGSIZErMessageLengthErrorr[r\r rrr]rr r5r!r3r4sendto)r+datagramaddrsenor1r1r2rosp              z Port.writecCs|d||dS)N)rojoin)r+seqrtr1r1r2 writeSequenceszPort.writeSequencecCsH|jrtdt|st|st|d||f|_|j||fdS)z- 'Connect' to remote server. z\already connected, reconnecting is not currently supported (talk to itamar if you want this)znot an IPv4 or IPv6 address.N)r RuntimeErrorrr rr5r connect)r+hostrr1r1r2r|s  z Port.connectcCs2||j||jr|jd|jdSdSrg) stopReadingr.removeActiveHandlerL callLaterconnectionLostr6r1r1r2_loseConnections  zPort._loseConnectioncCs&|jr t}|_nd}||SrB)rLrDeferreddr)r+resultr1r1r2 stopListenings zPort.stopListeningcCstjdtdd|dS)Nz-Please use stopListening() to disconnect port) stacklevel)warningswarnDeprecationWarningrr6r1r1r2loseConnection s  zPort.loseConnectioncCsbtd|jd|_tj|||j|j |`|` t |dr/|j d|` dSdS)z& Cleans up my socket. z(UDP Port %s Closed)Nr)rrJrr rrrdoStopr closerMhasattrrcallback)r+reasonr1r1r2rs    zPort.connectionLostcCs||j}d||_dS)zP Initialize the C{logstr} attribute to be used by C{logPrefix}. z%s (UDP)N)rKrlogstr)r+ logPrefixr1r1r2r$s zPort.setLogStrcCr<)zK Returns the name of my class, to prefix log entries with. )rr6r1r1r2r+r>zPort.logPrefixcCsR|j}|jtjkrtjdg|RS|jtjkr'tjdg|ddRSdS)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 rIr!r4r IPv4Addressr3 IPv6Addressr+rtr1r1r2getHost1s   z Port.getHostcCs|jtjtj|dS)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+enabledr1r1r2setBroadcastAllowed>szPort.setBroadcastAllowedcCst|jtjtjS)z Checks if broadcast is currently allowed on this port. @return: Whether this port may broadcast. @rtype: L{bool} )boolr getsockoptrrr6r1r1r2getBroadcastAllowedGszPort.getBroadcastAllowed)rrNrB)&__name__ __module__ __qualname____doc__r r4r! SOCK_DGRAMr"dynamicReadBuffersrrint__annotations__rrstrr;r=rArCr?r@rYrSrTrorzr|rrrrrrrrrr1r1r1r2rs:     A  rc@sleZdZdZddZddZddZdd Zd d Zd d Z ddZ dddZ ddZ ddZ dddZdS)MulticastMixinz, Implement multicast functionality. cCs$|jtjtj}ttd|S)Nz@i)r r IPPROTO_IPIP_MULTICAST_IF inet_ntoar(pack)r+rr1r1r2getOutgoingInterfaceVsz#MulticastMixin.getOutgoingInterfacecCs|j||jS)z. Returns Deferred of success. )r.resolve addCallback _setInterfacerr1r1r2setOutgoingInterfaceZsz#MulticastMixin.setOutgoingInterfacecCs"t|}|jtjtj|dS)NrE)r inet_atonrrr)r+rtrr1r1r2r`s zMulticastMixin._setInterfacecC|jtjtjSrB)r rrIP_MULTICAST_LOOPr6r1r1r2getLoopbackModeerDzMulticastMixin.getLoopbackModecCs(tdt|}|jtjtj|dS)Nb)r(rrr rrr)r+moder1r1r2setLoopbackModehszMulticastMixin.setLoopbackModecCrrB)r rrIP_MULTICAST_TTLr6r1r1r2getTTLlrDzMulticastMixin.getTTLcCs$td|}|jtjtj|dS)NB)r(rr rrr)r+ttlr1r1r2setTTLos zMulticastMixin.setTTLrcC|j||j|dS)zF Join a multicast group. Returns Deferred of success. rEr.rr _joinAddr1r+rtrr1r1r2 joinGroupszMulticastMixin.joinGroupcCs|j||j||SrB)r.rr _joinAddr2)r+rtrrxr1r1r2ryszMulticastMixin._joinAddr1c Cst|}t|}|rtj}ntj}z|jtj|||WdStyA}ztt j ||g|j RWYd}~Sd}~wwrB) r rIP_ADD_MEMBERSHIPIP_DROP_MEMBERSHIPrrrGrFailurerMulticastJoinErrorrm)r+rrtrxcmder1r1r2r|s  (zMulticastMixin._joinAddr2cCr)zD Leave multicast group, return Deferred of success. rrrr1r1r2 leaveGrouprzMulticastMixin.leaveGroupN)r)rrrrrrrrrrrrrrrr1r1r1r2rQs  rc@s*eZdZdZ    d ddZdd ZdS) MulticastPortz. UDP Port that supports multicasting. rrNFcCst||||||||_dSrB)rrlistenMultiple)r+rr,rr-r.rr1r1r2rs zMulticastPort.__init__cCsBt|}|jr|tjtjdttdr|tjtjd|S)NrE SO_REUSEPORT) rrCrrr r SO_REUSEADDRrr)r+r/r1r1r2rCs  zMulticastPort.createSocket)rrNF)rrrrrrCr1r1r1r2rs r)&rrZr r(rtypingrzope.interfacertwisted.internetrrrrtwisted.internet.abstractrr twisted.internet.iocpreactorr r r#"twisted.internet.iocpreactor.constr r r'twisted.internet.iocpreactor.interfacesrtwisted.pythonrrIListeningPort IUDPTransport ISystemHandlerrrIMulticastTransportrr1r1r1r2s2   1>