Skip to content

Instantly share code, notes, and snippets.

@shylent
Created November 30, 2010 21:56
Show Gist options
  • Save shylent/722498 to your computer and use it in GitHub Desktop.
Save shylent/722498 to your computer and use it in GitHub Desktop.
from twisted.internet import main, reactor
from twisted.internet.abstract import FileDescriptor
from twisted.internet.error import ConnectionDone
from twisted.internet.fdesc import writeToFD
from twisted.internet.interfaces import IReadDescriptor, IWriteDescriptor
from twisted.internet.protocol import Protocol
from twisted.python import log
from twisted.python.filepath import FilePath
from zope.interface import implements
import errno
import os
import sys
from twisted.internet.task import LoopingCall
class FIFOFileDescriptor(FileDescriptor):
def __init__(self, path, _reactor=None):
self._fd = None
self.path = path
FileDescriptor.__init__(self, _reactor)
def fileno(self):
return self._fd
def connectionLost(self, reason):
FileDescriptor.connectionLost(self, reason)
self.protocol.connectionLost(reason)
def logPrefix(self):
return "%s: %s" % (self.__class__.__name__, self.path.path)
class FIFOReader(FIFOFileDescriptor):
chunk_size = 8192
implements(IReadDescriptor)
def startReading(self):
if self.connected:
FileDescriptor.startReading(self)
return
self._fd = os.open(self.path.path, os.O_RDONLY | os.O_NONBLOCK)
self.connected = 1
FileDescriptor.startReading(self)
def doRead(self):
while True:
try:
output = os.read(self.fileno(), self.chunk_size)
except (OSError, IOError), err:
if err.args[0] in (errno.EAGAIN, errno.EINTR):
return
else:
return main.CONNECTION_LOST
if not output:
return main.CONNECTION_DONE
self.protocol.dataReceived(output)
class FIFOWriter(FIFOFileDescriptor):
implements(IWriteDescriptor)
def startWriting(self):
if self.connected:
FileDescriptor.startWriting(self)
return
self._fd = os.open(self.path.path, os.O_WRONLY | os.O_NONBLOCK)
self.connected = 1
FileDescriptor.startWriting(self)
def writeSomeData(self, data):
return writeToFD(self.fileno(), data)
class ReconnectingFIFOListener(Protocol):
noisy = True
def __init__(self, _reactor=None):
if _reactor is not None:
self._reactor = _reactor
else:
self._reactor = reactor
def dataReceived(self, data):
if self.noisy:
log.msg("Got data from fifo: %r" % data)
def connectionLost(self, reason):
if reason.check(ConnectionDone) is not None:
if self.noisy:
log.msg("Reached EOF, reconnecting")
listenToFIFO(self, self.transport.path, self._reactor)
else:
log.err(reason)
class LoopingWriter(Protocol):
def connectionMade(self):
c = LoopingCall(self.transport.write, 'I are the data!\n')
c.start(3)
def listenToFIFO(proto, path, _reactor=None):
if _reactor is None:
_reactor = reactor
fifo = FIFOReader(path, _reactor)
fifo.protocol = proto
proto.makeConnection(fifo)
fifo.startReading()
def writeToFIFO(proto, path, _reactor=None):
if _reactor is None:
_reactor = reactor
fifo = FIFOWriter(path, _reactor)
fifo.protocol = proto
proto.makeConnection(fifo)
fifo.startWriting()
def _main():
log.startLogging(sys.stdout)
listenToFIFO(ReconnectingFIFOListener(), FilePath('foo'))
writeToFIFO(LoopingWriter(), FilePath('foo'))
if __name__ == '__main__':
reactor.callWhenRunning(_main)
reactor.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment