o bW@s dZddlZddlZddlZddlZddlmZmZmZm Z m Z m Z ddl m Z mZddlmZmZmZddlmZmZmZmZmZmZmZmZddlmZddlmZm Z m!Z!m"Z"dd l#m$Z$dd l%m&Z&dd l'm(Z(zdd lm)Z*Wn e+ydZ)Ynwe*Z)e,ed se+dddZ-GdddZ.GdddZ/e)re.Z.ne/Z.eej0Gddde.ej1Z1ddZ2GdddZ3Gddde3ej4Z4eej0Gddde.ej5Z6Gdd d ej7Z8eej9Gd!d"d"e3ej4Z:eej;geej<RGd#d$d$e:Z=dS)%z UNIX socket support for Twisted. End users shouldn't use this module directly - use the reactor APIs instead. Maintainer: Itamar Shtull-Trauring N)EAGAIN ECONNREFUSEDEINTREMSGSIZEENOBUFS EWOULDBLOCK)OptionalType) implementedBy implementerimplementer_only)addressbaseerror interfacesmainprotocoltcpudp)FileDescriptor)failurelockfilelogreflect) lazyByteSlice)_coerceToFilesystemEncoding)untilConcludes)sendmsgAF_UNIXz+UNIX sockets not supported on this platformcCstd|}tjtj|fgS)zh Pack an integer into an ancillary data structure suitable for use with L{sendmsg.sendmsg}. i)structpacksocket SOL_SOCKETr SCM_RIGHTS)fdpackedr'7/usr/lib/python3/dist-packages/twisted/internet/unix.py_ancillaryDescriptor)s r)c@sZeZdZUdZdZeeeed<dZ ddZ ddZ d d Z d d Z d dZddZdS) _SendmsgMixina  Mixin for stream-oriented UNIX transports which uses sendmsg and recvmsg to offer additional functionality, such as copying file descriptors into other processes. @ivar _writeSomeDataBase: The class which provides the basic implementation of C{writeSomeData}. Ultimately this should be a subclass of L{twisted.internet.abstract.FileDescriptor}. Subclasses which mix in L{_SendmsgMixin} must define this. @ivar _sendmsgQueue: A C{list} of C{int} holding file descriptors which are currently buffered before being sent. @ivar _fileDescriptorBufferSize: An C{int} giving the maximum number of file descriptors to accept and queue for sending before pausing the registered producer, if there is one. N_writeSomeDataBase@cCs g|_dSN) _sendmsgQueueselfr'r'r(__init__H z_SendmsgMixin.__init__cCst|j|jkp |j|S)a Determine whether the user-space send buffer for this transport is full or not. This extends the base determination by adding consideration of how many file descriptors need to be sent using L{sendmsg.sendmsg}. When there are more than C{self._fileDescriptorBufferSize}, the buffer is considered full. @return: C{True} if it is full, C{False} otherwise. )lenr._fileDescriptorBufferSizer+_isSendBufferFullr/r'r'r(r5Ksz_SendmsgMixin._isSendBufferFullcCs |j|||dS)zY Queue the given file descriptor to be sent and start trying to send it. N)r.append_maybePauseProducer startWriting)r0filenor'r'r(sendFileDescriptords  z _SendmsgMixin.sendFileDescriptorc Cs6t|jt|kr tSd}zg|t|jkro|j|}zttj|j|||dt|Wn4tyc}z(|j dt t fvrO|WYd}~W|jd|=St j WYd}~W|jd|=Sd}~ww|d7}|t|jksW|jd|=n|jd|=wt||}|j||}z||WSty|YSw)zg Send as much of C{data} as possible. Also send any pending file descriptors. rN)r3r.rFileDescriptorOverrunrrr"r)OSErrorargsrrrCONNECTION_LOSTrr+ writeSomeData TypeError)r0dataindexr%se limitedDataresultr'r'r(r@ls@     z_SendmsgMixin.writeSomeDatac Cszttj|j|j\}}}Wn#ty1}z|jdtkr$WYd}~dStj WYd}~Sd}~ww|D](\}}}|tj krI|tj krI| |q4t jd||||j||dq4||S)a Calls {IProtocol.dataReceived} with all available data and L{IFileDescriptorReceiver.fileDescriptorReceived} once for each received file descriptor in ancillary data. This reads up to C{self.bufferSize} bytes of data from its socket, then dispatches the data to protocol callbacks to be handled. If the connection is not lost through an error in the underlying recvmsg(), this function will return the result of the dataReceived call. rNz%(protocolName)s (on %(hostAddress)r) received unsupported ancillary data (level=%(cmsgLevel)r, type=%(cmsgType)r) from %(peerAddress)r.)format hostAddress peerAddress protocolName cmsgLevelcmsgType)rrrecvmsgr" bufferSizer=r>rrr?r#r$%_ancillaryLevelSOLSOCKETTypeSCMRIGHTSrmsggetHostgetPeer _getLogPrefixr _dataReceived)r0rB ancillaryflagsrDrKrLcmsgDatar'r'r(doReads,     z_SendmsgMixin.doReadcCs~t|d}td||}tj|jr"|D]}|j|qdStj d| | | |jd|D]}t |q5dS)a Processes ancillary data with level SOL_SOCKET and type SCM_RIGHTS, indicating that the ancillary data payload holds file descriptors. Calls L{IFileDescriptorReceiver.fileDescriptorReceived} once for each received file descriptor or logs a message if the protocol does not implement L{IFileDescriptorReceiver}. @param cmsgData: Ancillary data payload. @type cmsgData: L{bytes} rz%(protocolName)s (on %(hostAddress)r) does not provide IFileDescriptorReceiver; closing file descriptor received (from %(peerAddress)r).)rGrHrIrJN)r3r unpackrIFileDescriptorReceiver providedByrfileDescriptorReceivedrrPrQrRrSosclose)r0rWfdCountfdsr%r'r'r(rOs   z3_SendmsgMixin._ancillaryLevelSOLSOCKETTypeSCMRIGHTS)__name__ __module__ __qualname____doc__r+rr r__annotations__r4r1r5r:r@rXrOr'r'r'r(r*2s . )r*c@seZdZdZdS)_UnsupportedSendmsgMixinz Behaviorless placeholder used when C{twisted.python.sendmsg} is not available, preventing L{IUNIXTransport} from being supported. N)rbrcrdrer'r'r'r(rgsrgc@s6eZdZejZddZeddZddZ ddZ d S) Serverc Cs*t|tj||||df|||dSr-)r*r1rrh)r0sockrclientserver sessionnoreactorr'r'r(r1s zServer.__init__c Cst|tjtj}t|}||}|dur|dSd}|||| d||}d |j j j |j||_d |j j j |j||_|||S)a Create a new L{Server} based on an existing connected I{SOCK_STREAM} socket. Arguments are the same as to L{Server.__init__}, except where noted. @param fileDescriptor: An integer file descriptor associated with a connected socket. The socket must be in non-blocking mode. Any additional attributes desired, such as I{FD_CLOEXEC}, must also be set already. @return: A new instance of C{cls} wrapping the socket given by C{fileDescriptor}. Nrz<{} #{} on {}>z{},{},{})r"fromfdr SOCK_STREAMr UNIXAddress getsockname buildProtocolr_ getpeernamerGr __class__rbrlrepstrlogstrmakeConnection) clsfileDescriptorfactoryrmskt protocolAddrprotorlr0r'r'r(_fromConnectedSockets(  zServer._fromConnectedSocketcCt|jSr-r rpr"rqr/r'r'r(rQ$zServer.getHostcCst|jpdSr-)r rphostnamer/r'r'r(rR'rzServer.getPeerN) rbrcrdrrhr+r1 classmethodr~rQrRr'r'r'r(rhs ' rhcCs|dddvS)a Determine whether the given unix socket path is in a filesystem namespace. While most PF_UNIX sockets are entries in the filesystem, Linux 2.2 and above support PF_UNIX sockets in an "abstract namespace" that does not correspond to any path. This function returns C{True} if the given socket path is stored in the filesystem and C{False} if the path is in this abstract namespace. Nr;)r')pathr'r'r(_inFilesystemNamespace+s rc@seZdZddZdS) _UNIXPortcCr)zV Returns a UNIXAddress. This indicates the server's address. rr/r'r'r(rQ9sz_UNIXPort.getHostN)rbrcrdrQr'r'r'r(r8s rc@sfeZdZejZejZeZ dZ dddZ e ddZ d efd d Zd d ZddZddZddZdS)PortN2rcCs4tjj|||j|||d||_||_d|_dS)Nrm)rrr1 _buildAddrnamemodewantPID_preexistingSocket)r0fileNamerzbacklogrrmrr'r'r(r1Is  z Port.__init__cCs.t||j|j}||||d}||_|S)a Create a new L{Port} based on an existing listening I{SOCK_STREAM} socket. Arguments are the same as to L{Port.__init__}, except where noted. @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. @return: A new instance of C{cls} wrapping the socket given by C{fd}. r)r"rn addressFamily socketTyperqr)rxrmr%rzportr0r'r'r(_fromListeningDescriptorSszPort._fromListeningDescriptorreturncCs8t|jj}t|drd|td|jSd|dS)Nr"z <{} on {!r}>< (not listening)>)rqualrzrthasattrrGrr)r0 factoryNamer'r'r(__repr__fs   z Port.__repr__cCs t|Sr-r rp)r0rr'r'r(rpr2zPort._buildAddrc CsPtjtd||jtd|jf|j rOt |jd|_ |j s/td|jd|j jsOztt|jjrDt|jWn tyNYnw|jz|jdura|j}d|_n |}||jWnty}ztd|j|d}~wwt|jrt|j|j||j d|_!||_"|j"j#|_#d|_$|%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. z%s starting on %rr.lockNzCannot acquire lockTd)&r _reservedFDreserverrPrSrzrrrrFilesystemLocklockFilelockrCannotListenErrorcleanstatS_ISSOCKr^st_moderemove BaseExceptiondoStartrcreateInternetSocketbindr=rchmodrlistenr connectedr"r9 numberAccepts startReadingr0r{ler'r'r(startListeningssP             zPort.startListeningcCstdtd|jdS)z0 Log message for closing socket z(UNIX Port %s Closed)rN)rrPrrr/r'r'r(_logConnectionLostMsgszPort._logConnectionLostMsgcCs<t|jr t|j|jdur|jtj||dSr-) rrr^unlinkrunlockrrconnectionLostr0reasonr'r'r(rs    zPort.connectionLost)rrNr)rbrcrdr"rrrorrh transportrr1rrstrrrrrrr'r'r'r(rBs   6 rc@s<eZdZdZejZejZe j Z d ddZ ddZ dd ZdS) ClientzA client for Unix sockets.NrcCsjt|t|j}||_||_|_|r(t |ds(| ddt ||| |j |d|dS)Nr)r*r1r rpr connector realAddressaddrrisLocked _finishInitr BadFileError doConnectr)r0filenamerrmcheckPIDr'r'r(r1s   zClient.__init__cC t|jSr-)r rprr/r'r'r(rR zClient.getPeercCs tdSr-rr/r'r'r(rQr2zClient.getHost)Nr)rbrcrdrer"rrrorr BaseClientr+r1rRrQr'r'r'r(rs  rc@s$eZdZddZddZddZdS) ConnectorcCs"tj||||||_||_dSr-)r BaseConnectorr1r r)r0r rztimeoutrmrr'r'r(r1s zConnector.__init__cCst|j||j|jSr-)rr rmrr/r'r'r(_makeTransportszConnector._makeTransportcCs t|jSr-rr/r'r'r(getDestinationrzConnector.getDestinationN)rbrcrdr1rrr'r'r'r(rs rc@sPeZdZdZejZdddZdefdd Z d d Z d d Z dddZ ddZ dS) DatagramPortz4 Datagram UNIX port, listening for packets. rNcCs tjj|||||d||_dS)z%Initialize with address to listen on.) maxPacketSizermN)rrr1r)r0rr}rrrmr'r'r(r1s  zDatagramPort.__init__rcCs8t|jj}t|drd|d|jdSd|dS)Nr"rz on >r)rrrrtrr)r0rJr'r'r(rs   zDatagramPort.__repr__c Cst|jjdt|jz|}|jr||jWnty2}zt d|j|d}~ww|jrCt |jrCt |j|jd|_||_|jj|_dS)Nz starting on r;)rrPrrtreprrrrr=rrrr^rrrr"r9rr'r'r( _bindSockets zDatagramPort._bindSocketc Csz|j||WSty?}z+|jd}|tkr%|||WYd}~S|tkr.td|t kr3nWYd}~dSd}~ww)zWrite a datagram.rNmessage too long) r"sendtor=r>rwriterrMessageLengthErrorr)r0datagramr rDnor'r'r(r s  zDatagramPort.writecCsptdt|jtj||t|dr|j d|_ |j |` |` t|dr6|jd|`dSdS)zCleans up my socket.z(Port %s Closed)rrdN)rrPrrrBasePortrrrdoStoprr"r_r9rcallbackrr'r'r(rs     zDatagramPort.connectionLostcCst|jjd|_dS)Nz (UDP))rrrrtrvr/r'r'r( setLogStr.szDatagramPort.setLogStr)rrNr-)rbrcrdrer"rrr1rrrrrrr'r'r'r(rs    rc@sJeZdZdZ    dddZddZd d Zd d Zd dZddZ dS)ConnectedDatagramPortz+ A connected datagram UNIX socket. rrNcCs.t|tjsJt||||||||_dSr-) isinstancerConnectedDatagramProtocolrr1 remoteaddr)r0rr}rr bindAddressrmr'r'r(r1:s  zConnectedDatagramPort.__init__cCsHz||j|j|WdSty#|tYdSwr-) rr"connectr_connectToProtocolrconnectionFailedrFailurer/r'r'r(rGs z$ConnectedDatagramPort.startListeningcCs||j||`dS)z Called when a connection fails. Stop listening on the socket. @type reason: L{Failure} @param reason: Why the connection failed. N) stopListeningrrrr'r'r(rOs z&ConnectedDatagramPort.connectionFailedc Csd}||jkrbz|j|j\}}|t|7}|j|Wn<tyN}z$|jd}|t t t fvr9WYd}~dS|t krC|j nWYd}~nd}~wtyZtYnw||jksdSdS)z= Called when my socket is ready for reading. rN) maxThroughputr"recvfromrr3rdatagramReceivedr=r>rrrrconnectionRefusedrrdeferr)r0readrBrrDrr'r'r(rXZs&       zConnectedDatagramPort.doReadc Csz|j|WStyN}z;|jd}|tkr#||WYd}~S|tkr,td|t kr6|j n|t kr;nWYd}~dSWYd}~dSd}~ww)z# Write a datagram. rNr) r"sendr=r>rrrrrrrrr)r0rBrDrr'r'r(ros"   zConnectedDatagramPort.writecCrr-)r rprr/r'r'r(rRrzConnectedDatagramPort.getPeer)rrNN) rbrcrdrer1rrrXrrRr'r'r'r(r2s    r)>rer^r"rr errnorrrrrrtypingrr zope.interfacer r r twisted.internetr rrrrrrrtwisted.internet.abstractrtwisted.pythonrrrrtwisted.python.compatrtwisted.python.filepathrtwisted.python.utilrr_sendmsg ImportErrorrr)r*rgIUNIXTransportrhrrrrrrrIUNIXDatagramTransportrIUNIXDatagramConnectedTransportrrr'r'r'r(sZ  (       39  } L