import os
import sys
import struct
import socket
import tempfile
from os.path import join as opj
from types import FileType
from socket import SocketType
try:
import cPickle as pickle
except ImportError:
import pickle
try:
import cStringIO as StringIO
except ImportError:
import StringIO
from twisted.internet import reactor
from twisted.internet import protocol
from twisted.internet import abstract
from twisted.internet import tcp
from twisted.internet import unix
from twisted.persisted import styles
from twisted.cred import portal
from twisted.cred import checkers
from twisted.protocols import basic
from twisted.internet import unix
from twisted.application import internet
sys.path.append("../../pahan/sendmsg")
from sendmsg import sendmsg
from sendmsg import SCM_RIGHTS
class Server(unix.Server):
def sendFileDescriptors(self, fileno, data="Filler"):
"""
@param fileno: An iterable of the file descriptors to pass.
"""
payload = struct.pack("%di" % len(fileno), *fileno)
r = sendmsg(self.fileno(), data, 0, (socket.SOL_SOCKET, SCM_RIGHTS, payload))
return r
class Port(unix.Port):
transport = Server
class UNIXServer(internet._AbstractServer):
def getHost(self):
return self._port.getHost()
def _getPort(self):
from twisted.internet import reactor
return reactor.listenWith(Port, *self.args, **self.kwargs)
class _FileDescriptorPickler:
def __init__(self, fdmap):
self.fdmap = fdmap
def __id(self, fileno):
id = len(self.fdmap)
self.fdmap[id] = fileno
return id
def persistent_id(self, obj):
from twisted.internet import reactor
if obj is reactor:
return 'reactor'
elif isinstance(obj, FileType):
return '%d:file:%s' % (self.__id(obj.fileno()), obj.mode)
elif isinstance(obj, SocketType):
return '%d:socket' % (self.__id(obj.fileno()),)
elif isinstance(obj, styles.Ephemeral):
print 'Serializing ephemeral', obj
return obj.__dict__.copy()
else:
return None
def FileDescriptorPickler(s, fdmap):
ph = _FileDescriptorPickler(fdmap)
p = pickle.Pickler(s)
p.persistent_id = ph.persistent_id
return p
class FileDescriptorSendingProtocol(basic.LineReceiver):
"""
Must be used with L{Port} as the transport.
"""
def __init__(self, idmap):
self.idmap = idmap
def lineReceived(self, line):
try:
files = self.idmap[int(line)]
except ValueError:
log.msg("Peer sent us a bogus ID")
except KeyError:
log.msg("Peer sent us an unassigned ID")
except:
log.err()
else:
files = files.items()
files.sort()
self.transport.sendFileDescriptors([f[1] for f in files])
return
self.transport.loseConnection()
class FileDescriptorSendingFactory(protocol.ServerFactory):
protocol = FileDescriptorSendingProtocol
def __init__(self, idmap):
self.idmap = idmap
def buildProtocol(self, addr):
p = self.protocol(self.idmap)
return p
from gluhgluh import pb
class UserStateSender(pb.Avatar):
id = 0
def __init__(self, client):
self.idmap = {}
# PB Object for talking to our peer
self.client = client
self.dir = tempfile.mkdtemp()
self.path = tempfile.mktemp(dir=self.dir)
self.factory = FileDescriptorSendingFactory(self.idmap)
self.server = UNIXServer(opj(self.dir, self.path), self.factory)
self.server.startService()
reactor.callLater(1, sendSomeState, self)
def logout(self):
self.server.stopService()
# This is BUNK with a capital BUNK
reactor.callLater(0, os.rmdir, self.dir)
def sendUserState(self, state):
"""Transmit the given state to this service's peer.
"""
d = {}
s = StringIO.StringIO()
p = FileDescriptorPickler(s, d)
p.dump(state)
state = s.getvalue()
self.id += 1
self.idmap[self.id] = d
return self._sendUserStateWithID(self.id, state, opj(self.dir, self.path))
def _sendUserStateWithID(self, id, state, path):
return self.client.callRemote("takeResponsibility", id, state, path)
class Realm:
__implements__ = (portal.IRealm,)
def requestAvatar(self, avatarId, mind, *interfaces):
print 'saaaaaaaaw'
if pb.IPerspective not in interfaces:
raise NotImplementedError
a = UserStateSender(mind)
return pb.IPerspective, a, a.logout
def sendSomeState(avatar):
from twisted.web import server
from twisted.web.woven import dirlist
from twisted.internet import reactor
port = reactor.listenTCP(19191, server.Site(dirlist.DirectoryLister(".")))
avatar.sendUserState(port)
from gluhgluh import PBServerFactory
def main():
r = Realm()
p = portal.Portal(r)
c = checkers.InMemoryUsernamePasswordDatabaseDontUse(username="password")
p.registerChecker(c)
f = PBServerFactory(p)
from twisted.application import internet
return internet.TCPServer(10301, f)
from twisted.application import service
application = service.Application("Copyover Server")
main().setServiceParent(application)
syntax highlighted by Code2HTML, v. 0.9.1