1
from twisted.cred import error
2
from twisted.spread import pb
4
class PerspectiveInUse(error.Unauthorized):
5
"""Raised when a client requests a perspective already connected to another.
7
# XXX: Is there any information this exception should carry, i.e.
8
# the Perspective in question.
9
# the client it's currently attached to.
10
# the Identity which attached it.
13
class SingleClientPerspective_PB(pb.Perspective):
14
"""One client may attach to me at a time.
16
With verbose logging and some detection for lost connections.
21
# This example is from cvstoys.actions.pb.Notifiee.
23
def brokerAttached(self, ref, identity, broker):
24
log.msg("%(identityName)s<auth%(authID)X>@"
25
"%(peer)s<broker%(brokerID)X> "
26
"requests attaching client %(client)s to "
27
"%(perspectiveName)s@%(serviceName)s" %
28
{'identityName': identity.name,
29
'authID': id(identity.authorizer),
30
'peer': broker.transport.getPeer(),
31
'brokerID': id(broker),
33
'perspectiveName': self.getPerspectiveName(),
34
'serviceName': self.service.getServiceName(),
38
oldclient, oldid, oldbroker = self.client
40
brokerstr = "<broker%X>" % (id(oldbroker),)
42
brokerstr = "<no broker>"
44
"%(pn)s@%(sn)s already has client %(client)s "
45
"from %(id)s@%(broker)s" %
46
{'pn': self.getPerspectiveName(),
47
'sn': self.service.getServiceName(),
52
# Here's the part that checks is the currently connected client
53
# has a stale connection. It *shouldn't* happen, but if it did,
54
# it would suck to not be able to sign back on because the system
55
# wouldn't believe you were logged off.
56
if (not oldbroker) or (oldbroker.connected and oldbroker.transport):
58
brokerstr = "%s%s" % (oldbroker.transport.getPeer(),
60
log.msg("%s@%s refusing new client %s from broker %s." %
61
(self.getPerspectiveName(),
62
self.service.getServiceName(),
64
raise PerspectiveInUse("This perspective %r already has a "
65
"client. (Connected by %r from %s.)"
66
% (self, oldid.name, brokerstr))
68
log.msg("BUG: Broker %s disconnected but client %s never"
69
"detached.\n(I'm dropping the old client and "
70
"allowing a new one to attach.)" %
71
(oldbroker, self.client,))
72
self.brokerDetached(self, self.client, identity, oldbroker)
73
# proceed with normal attach
75
self.client = (ref, identity, broker)
78
def detached(self, ref, identity):
81
def sendMessage(self, message):
82
"""Send a message to my client.
84
(This isn't a defined Perspective method, just an example of something
85
you would define in your sub-class to use to talk to your client.)
87
# Using 'assert' in this case is probably not a good idea for real
88
# code. Define an exception, or choose to let it pass without comment,
89
# as your needs see fit.
90
assert self.client is not None, "No client to send a message to!"
91
# This invokes remote_message(message) on the client object.
92
self.client.callRemote("message", message)
94
def __getstate__(self):
95
state = styles.Versioned.__getstate__(self)