3
from slides import Lecture, NumSlide, Slide, Bullet, SubBullet, PRE, URL
6
def __init__(self, title, html):
13
def __init__(self, html):
16
server_lore = """<div class="py-listing">
17
<pre><span class="py-src-keyword">class</span> <span class="py-src-identifier">ServerObject</span><span class="py-src-op">(</span><span class="py-src-parameter">pb</span><span class="py-src-op">.</span><span class="py-src-parameter">Referenceable</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline"></span>
18
<span class="py-src-indent"> </span><span class="py-src-keyword">def</span> <span class="py-src-identifier">remote_add</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">one</span><span class="py-src-op">,</span> <span class="py-src-parameter">two</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
19
</span><span class="py-src-indent"> </span><span class="py-src-variable">answer</span> <span class="py-src-op">=</span> <span class="py-src-variable">one</span> <span class="py-src-op">+</span> <span class="py-src-variable">two</span><span class="py-src-newline">
20
</span> <span class="py-src-keyword">print</span> <span class="py-src-string">"returning result:"</span><span class="py-src-op">,</span> <span class="py-src-variable">answer</span><span class="py-src-newline">
21
</span> <span class="py-src-keyword">return</span> <span class="py-src-variable">answer</span><span class="py-src-endmarker"></span></pre>
22
<div class="py-caption">Server Code</div>
26
client_lore = """<div class="py-listing"><pre>
27
<span class="py-src-nl"></span> <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">got_RemoteReference</span><span class="py-src-op">(</span><span class="py-src-parameter">remoteref</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
28
</span> <span class="py-src-keyword">print</span> <span class="py-src-string">"asking it to add"</span><span class="py-src-newline">
29
</span> <span class="py-src-variable">deferred</span> <span class="py-src-op">=</span> <span class="py-src-variable">remoteref</span><span class="py-src-op">.</span><span class="py-src-variable">callRemote</span><span class="py-src-op">(</span><span class="py-src-string">"add"</span><span class="py-src-op">,</span> <span class="py-src-number">1</span><span class="py-src-op">,</span> <span class="py-src-number">2</span><span class="py-src-op">)</span><span class="py-src-newline">
30
</span> <span class="py-src-variable">deferred</span><span class="py-src-op">.</span><span class="py-src-variable">addCallbacks</span><span class="py-src-op">(</span><span class="py-src-variable">add_done</span><span class="py-src-op">,</span> <span class="py-src-variable">err</span><span class="py-src-op">)</span><span class="py-src-newline">
31
</span> <span class="py-src-comment"># this Deferred fires when the method call is complete
32
</span> <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">add_done</span><span class="py-src-op">(</span><span class="py-src-parameter">result</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
33
</span><span class="py-src-indent"> </span><span class="py-src-keyword">print</span> <span class="py-src-string">"addition complete, result is"</span><span class="py-src-op">,</span> <span class="py-src-variable">result</span><span class="py-src-newline">
34
</span><span class="py-src-endmarker"></span></pre><div class="py-caption">Client Code</div></div>
38
# title graphic: PB peanut butter jar, "Twist(ed)" on lid
40
"Perspective Broker: Translucent RPC in Twisted",
43
<h1>Perspective Broker: Translucent RPC in Twisted</h1>
45
<h2>Brian Warner < warner @ lothar . com > </h2>
49
Bullet("Overview/definition of RPC"),
50
Bullet("What is Perspective Broker?"),
51
Bullet("How do I use it?"),
52
Bullet("Security Issues"),
53
Bullet("Future Directions"),
56
Slide("Remote Procedure Calls",
57
Bullet("Action at a distance: separate processes, safely telling each other what to do",
58
SubBullet("Separate memory spaces"),
59
SubBullet("Usually on different machines"),
61
Bullet("Frequently called RMI these days: Remote Method Invocation"),
62
Bullet("Three basic parts: Addressing, Serialization, Waiting"),
66
Bullet("What program are you talking to?",
67
SubBullet("hostname, port number"),
68
SubBullet("Some systems use other namespaces: sunrpc")
70
Bullet("Which object in that program?"),
71
Bullet("Which method do you want to run?"),
72
Bullet("Related issues",
73
SubBullet("How do you know what the arguments are?"),
74
SubBullet("(do you care?)"),
75
SubBullet("How do you know what methods are available?"),
76
SubBullet("(do you care?)"),
80
Slide("Serialization",
81
Bullet("What happens to the arguments you send in?"),
82
Bullet("What happens to the results that are returned?",
83
SubBullet("Representation differences: endianness, word length"),
84
SubBullet("Dealing with user-defined types"),
86
Bullet("How to deal with references"),
88
Slide("The Waiting (is the hardest part)",
89
Bullet("Asynchronous: results come later, or not at all"),
90
Bullet("Need to do other work while waiting"),
93
Slide("Whither Translucence?",
94
Bullet("Not 'Transparent': don't pretend remote objects are really local",
95
SubBullet("CORBA (in C) does this, makes remote calls look like local calls"),
96
SubBullet("makes it hard to deal with the async nature of RPC"),
98
Bullet("Not 'Opaque': make it easy to deal with the differences",
99
SubBullet("Including extra failure modes, delayed results"),
102
Bullet("Exceptions and Deferreds to the rescue")),
104
Slide("Other RPC protocols",
108
Bullet("when you control both ends of the wire, use PB"),
111
Raw("Where does PB fit?",
112
"""<h2>PB sits on top of <span class=\"py-src-identifier\">twisted.internet</span></h2>
113
<img src=\"twisted-overview.png\" />
116
Slide("pb.RemoteReference",
117
Bullet(HTML("<span class=\"py-src-identifier\">pb.Referenceable</span>: Object which can be accessed by remote systems."),
118
SubBullet(HTML("Defines methods like <span class=\"py-src-identifier\">remote_foo</span> and <span class=\"py-src-identifier\">remote_bar</span> which can be invoked remotely.")),
119
SubBullet(HTML("Methods without the <span class=\"py-src-identifier\">remote_</span> prefix are local-only.")),
121
Bullet(HTML("<span class=\"py-src-identifier\">pb.RemoteReference</span>: Used by distant program to invoke methods."),
122
SubBullet(HTML("Offers <span class=\"py-src-identifier\">.callRemote()</span> to trigger remote method on a corresponding <span class=\"py-src-identifier\">pb.Referenceable</span>.")),
127
"<h2>Sample Code</h2>" + server_lore + client_lore),
128
#Slide("Simple Demo"),
129
# "better demo: manhole, or reactor running in another thread"
131
#build up from callRemote?
132
Slide("What happens to those arguments?",
133
Bullet("Basic structures should travel transparently",
134
SubBullet("Actually quite difficult in some languages"),
136
Bullet("Object graph should remain the same",
137
SubBullet("Serialization context"),
138
SubBullet("(same issues as Pickle)")),
139
Bullet("Instances of user-defined classes require more care",
140
SubBullet("User-controlled unjellying"),)
143
#serialization (skip banana)
144
Slide("40% More Sandwich Puns Than The Leading Brand",
145
Bullet("twisted.spread: python package holding other modules"),
146
Bullet("PB: remote method invocation"),
147
Bullet("Jelly: mid-level object serialization"),
148
Bullet("Banana: low-level serialization of s-expressions"),
149
Bullet("Taster: security context, decides what may be received"),
150
Bullet("Marmalade: like Jelly, but involves XML, so it's bitter"),
151
Bullet("better than the competition",
152
SubBullet("CORBA: few or no sandwich puns"),
153
SubBullet("XML-RPC: barely pronounceable"),
157
Slide("Jellying objects",
158
Bullet("'Jellying' vs 'Unjellying'"),
159
Bullet("Immutable objects are copied whole"),
160
Bullet("Mutable objects get reference IDs to insure shared references remain shared",
161
SubBullet("(within the same Jellying context)")),
164
Slide("Jellying instances",
165
Bullet(HTML("User classes inherit from one of the <span class=\"py-src-identifier\">pb.flavor</span> classes")),
166
Bullet(HTML("<span class=\"py-src-identifier\">pb.Referenceable</span>: methods can be called remotely")),
167
Bullet(HTML("<span class=\"py-src-identifier\">pb.Copyable</span>: contents are selectively copied")),
168
Bullet(HTML("<span class=\"py-src-identifier\">pb.Cacheable</span>: contents are copied and kept up to date")),
169
Bullet(HTML("Classes define <span class=\"py-src-identifier\">.getStateToCopy</span> and other methods to restrict exported state")),
172
Slide("pb.Copyable example",
173
PRE("""class SenderPond(FrogPond, pb.Copyable):
174
def getStateToCopy(self):
175
d = self.__dict__.copy()
176
d['frogsAndToads'] = d['numFrogs'] + d['numToads']
181
class ReceiverPond(pb.RemoteCopy):
182
def setCopyableState(self, state):
183
self.__dict__ = state
186
return self.frogsAndToads
188
pb.setUnjellyableForClass(SenderPond, ReceiverPond)
191
Slide("Secure Unjellying",
192
Bullet("Pickle has security problems",
193
SubBullet("Pickle will import any module the sender requests."),
194
SubBullet(HTML("2.3 gave up, removed safety checks like <span class=\"py-src-identifier\">__safe_for_unpickling__</span> .")),
196
Bullet("Jelly attempts to be safe in the face of hostile clients",
197
SubBullet("All classes rejected by default"),
198
SubBullet(HTML("<span class=\"py-src-identifier\">registerUnjellyable()</span> used to accept safe ones")),
199
SubBullet(HTML("Registered classes define <span class=\"py-src-identifier\">.setCopyableState</span> and others to process remote state")),
201
Bullet("Must mark (by subclassing) to transmit"),
204
Slide("Transformation of references in transit",
205
Bullet("All referenced objects get turned into their counterparts as they go over the wire"),
206
Bullet("References are followed recursively",
207
SubBullet("Sending a reference to a tree of objects will cause the whole thing to be transferred"),
208
SubBullet("(subject to security restrictions)"),
210
Bullet(HTML("<span class=\"py-src-identifier\">pb.flavors</span> get reference ids"),
211
SubBullet("They are recognized when they return, transformed into the original reference"),
212
SubBullet("Reference ids are scoped to the connection"),
213
SubBullet("One side-effect: no 'third party' references"),
217
Slide("Perspectives: pb.cred and the Identity/Service model",
218
Bullet("A layer to provide common authentication services to Twisted applications"),
219
Bullet(HTML("<span class=\"py-src-identifier\">Identity</span>: named user accounts with passwords")),
220
Bullet(HTML("<span class=\"py-src-identifier\">Service</span>: something a user can request access to")),
221
Bullet(HTML("<span class=\"py-src-identifier\">Perspective</span>: user accessing a service")),
222
Bullet(HTML("<span class=\"py-src-identifier\">pb.Perspective</span>: first object, a <span class=\"py-src-identifier\">pb.Referenceable</span> used to access everything else")),
226
Slide("Future directions",
227
Bullet("Other language bindings: Java, elisp, Haskell, Scheme, JavaScript, OCaml"),
228
# donovan is doing the JavaScript port
229
Bullet("Other transports: UDP, Airhook"),
230
Bullet("Componentization"),
231
Bullet("Performance improvements: C extension for Jelly"),
232
Bullet("Refactor addressing model: PB URLs"),
235
Slide("Questions", Bullet("???")),
239
lecture.renderHTML("slides", "slide-%02d.html", css="stylesheet.css")