1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
|
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
"""
Server-side of an example for sending file descriptors between processes over
UNIX sockets. This server accepts connections on a UNIX socket and sends one
file descriptor to them, along with the name of the file it is associated with.
To run this example, run this program with two arguments: a path giving a UNIX
socket to listen on (must not exist) and a path to a file to send to clients
which connect (must exist). For example:
$ python sendfd.py /tmp/sendfd.sock /etc/motd
It will listen for client connections until stopped (eg, using Control-C). Most
interesting behavior happens on the client side.
See recvfd.py for the client side of this example.
"""
if __name__ == "__main__":
import sendfd
raise SystemExit(sendfd.main())
import sys
from twisted.internet import reactor
from twisted.internet.protocol import Factory
from twisted.protocols.basic import LineOnlyReceiver
from twisted.python.filepath import FilePath
from twisted.python.log import startLogging
class SendFDProtocol(LineOnlyReceiver):
def connectionMade(self):
# Open the desired file and keep a reference to it - keeping it open
# until we know the other side has it. Closing it early will prevent
# it from actually being sent.
self.fObj = self.factory.content.open()
# Tell the transport to send it. It is not necessarily sent when this
# method returns. The reactor may need to run for a while longer before
# that happens.
self.transport.sendFileDescriptor(self.fObj.fileno())
# Send along *at least* one byte, since one file descriptor was sent.
# In this case, send along the name of the file to let the other side
# have some idea what they're getting.
encoding = sys.getfilesystemencoding()
self.sendLine(self.factory.content.path.encode(encoding))
# Give the other side a minute to deal with this. If they don't close
# the connection by then, we will do it for them.
self.timeoutCall = reactor.callLater(60, self.transport.loseConnection)
def connectionLost(self, reason):
# Clean up the file object, it is no longer needed.
self.fObj.close()
self.fObj = None
# Clean up the timeout, if necessary.
if self.timeoutCall.active():
self.timeoutCall.cancel()
self.timeoutCall = None
def main():
address = FilePath(sys.argv[1])
content = FilePath(sys.argv[2])
if address.exists():
raise SystemExit("Cannot listen on an existing path")
if not content.isfile():
raise SystemExit("Content file must exist")
startLogging(sys.stdout)
serverFactory = Factory()
serverFactory.content = content
serverFactory.protocol = SendFDProtocol
reactor.listenUNIX(address.path, serverFactory)
reactor.run()
|