1
2 """Base classes handy for use with PB clients.
3 """
4
5 from twisted.spread import pb
6
7 from twisted.spread.pb import PBClientFactory
8 from twisted.internet import protocol
9 from twisted.python import log
10
16
19 """Reconnecting client factory for PB brokers.
20
21 Like PBClientFactory, but if the connection fails or is lost, the factory
22 will attempt to reconnect.
23
24 Instead of using f.getRootObject (which gives a Deferred that can only
25 be fired once), override the gotRootObject method.
26
27 Instead of using the newcred f.login (which is also one-shot), call
28 f.startLogin() with the credentials and client, and override the
29 gotPerspective method.
30
31 Instead of using the oldcred f.getPerspective (also one-shot), call
32 f.startGettingPerspective() with the same arguments, and override
33 gotPerspective.
34
35 gotRootObject and gotPerspective will be called each time the object is
36 received (once per successful connection attempt). You will probably want
37 to use obj.notifyOnDisconnect to find out when the connection is lost.
38
39 If an authorization error occurs, failedToGetPerspective() will be
40 invoked.
41
42 To use me, subclass, then hand an instance to a connector (like
43 TCPClient).
44 """
45
47 PBClientFactory.__init__(self)
48 self._doingLogin = False
49 self._doingGetPerspective = False
50
52 PBClientFactory.clientConnectionFailed(self, connector, reason)
53
54
55
56 if self.continueTrying:
57 self.connector = connector
58 self.retry()
59
65
74
76
77 d = self.__dict__.copy()
78 d['connector'] = None
79 d['_callID'] = None
80 return d
81
82
83
85 raise RuntimeError, "getPerspective is one-shot: use startGettingPerspective instead"
86
89 self._doingGetPerspective = True
90 if perspectiveName == None:
91 perspectiveName = username
92 self._oldcredArgs = (username, password, serviceName,
93 perspectiveName, client)
94
96
97 (username, password,
98 serviceName, perspectiveName, client) = self._oldcredArgs
99 d = self._cbAuthIdentity(root, username, password)
100 d.addCallback(self._cbGetPerspective,
101 serviceName, perspectiveName, client)
102 d.addCallbacks(self.gotPerspective, self.failedToGetPerspective)
103
104
105
106
108 raise RuntimeError, "login is one-shot: use startLogin instead"
109
111 self._credentials = credentials
112 self._client = client
113 self._doingLogin = True
114
120
121
122
123
125 """The remote avatar or perspective (obtained each time this factory
126 connects) is now available."""
127 pass
128
130 """The remote root object (obtained each time this factory connects)
131 is now available. This method will be called each time the connection
132 is established and the object reference is retrieved."""
133 pass
134
136 """The login process failed, most likely because of an authorization
137 failure (bad password), but it is also possible that we lost the new
138 connection before we managed to send our credentials.
139 """
140 log.msg("ReconnectingPBClientFactory.failedToGetPerspective")
141 if why.check(pb.PBConnectionLost):
142 log.msg("we lost the brand-new connection")
143
144 return
145
146 self.stopTrying()
147 log.err(why)
148