Ticket #4568: pb.xhtml.patch

File pb.xhtml.patch, 97.8 KB (added by jdb, 6 years ago)

Adapted the lore input for the articles in the Perspective Broker section

  • doc/core/howto/pb-clients.xhtml

    diff --git a/doc/core/howto/pb-clients.xhtml b/doc/core/howto/pb-clients.xhtml
    index e6ecf86..89d2c8c 100644
    a b design choice, and it works well for simple cases.</p> 
    1515
    1616<p>In more complicated cases, for example an <code>Avatar</code> that
    1717represents a player object which is persistent in the game universe,
    18 we will want connections from the same player to use the same
    19 <code>Avatar</code>.</p>
    20 
    21 <p>Another thing which is necessary in more complicated scenarios
    22 is notifying a player asynchronously. While it is possible, of
    23 course, to allow a player to call
    24 <code>perspective_remoteListener(referencable)</code> that would
    25 mean both duplication of code and a higher latency in logging in,
    26 both bad.</p>
     18we will want connections from the same player to use the
     19same <code>Avatar</code>.</p>
     20
     21<p>Another thing which is necessary in more complicated scenarios is
     22notifying a player asynchronously. While it is possible, of course, to
     23allow a player to
     24call <code>perspective_remoteListener(referencable)</code> that would
     25mean both duplication of code and a higher latency in logging in, both
     26bad.</p>
    2727
    2828<p>In previous sections all realms looked to be identical.
    2929In this one we will show the usefulness of realms in accomplishing
  • doc/core/howto/pb-copyable.xhtml

    diff --git a/doc/core/howto/pb-copyable.xhtml b/doc/core/howto/pb-copyable.xhtml
    index 42d1bf3..f4acffb 100644
    a b dictionaries because they also contain (or reference) code, which can modify 
    6969other data structures when executed. Once previously-trusted data is
    7070subverted, the rest of the program is compromised.</p>
    7171
    72 <p>The built-in Python <q>batteries included</q> classes are relatively
    73 tame, but you still wouldn't want to let a foreign program use them to
    74 create arbitrary objects in your namespace or on your computer. Imagine a
    75 protocol that involved sending a file-like object with a <code>read()</code>
    76 method that was supposed to used later to retrieve a document. Then imagine
    77 what if that object were created with
    78 <code>os.fdopen("~/.gnupg/secring.gpg")</code>. Or an instance of
    79 <code>telnetlib.Telnet("localhost", "chargen")</code>. </p>
    80 
    81 <p>Classes you've written for your own program are likely to have far more
    82 power. They may run code during <code>__init__</code>, or even have special
    83 meaning simply because of their existence. A program might have
    84 <code>User</code> objects to represent user accounts, and have a rule that
    85 says all <code>User</code> objects in the system are referenced when
    86 authorizing a login session. (In this system, <code>User.__init__</code>
    87 would probably add the object to a global list of known users). The simple
    88 act of creating an object would give access to somebody. If you could be
    89 tricked into creating a bad object, an unauthorized user would get
    90 access.</p>
     72<p>The built-in Python <q>batteries included</q> classes are
     73relatively tame, but you still wouldn't want to let a foreign program
     74use them to create arbitrary objects in your namespace or on your
     75computer. Imagine a protocol that involved sending a file-like object
     76with a <code>read()</code> method that was supposed to used later to
     77retrieve a document. Then imagine what if that object were created
     78with <code>os.fdopen("~/.gnupg/secring.gpg")</code>. Or an instance
     79of <code>telnetlib.Telnet("localhost", "chargen")</code>. </p>
     80
     81<p>Classes you've written for your own program are likely to have far
     82more power. They may run code during <code>__init__</code>, or even
     83have special meaning simply because of their existence. A program
     84might have <code>User</code> objects to represent user accounts, and
     85have a rule that says all <code>User</code> objects in the system are
     86referenced when authorizing a login session. (In this
     87system, <code>User.__init__</code> would probably add the object to a
     88global list of known users). The simple act of creating an object
     89would give access to somebody. If you could be tricked into creating a
     90bad object, an unauthorized user would get access.</p>
    9191
    9292<p>So object creation needs to be part of a system's security design. The
    9393dotted line between <q>trusted inside</q> and <q>untrusted outside</q> needs
    contents of the object.</p> 
    117117with the <code class="API"
    118118base="twisted.spread.jelly">setUnjellyableForClass</code> function<!--
    119119
    120 --><span class="footnote"> <p>Note that, in this context, <q>unjelly</q> is
    121 a verb with the opposite meaning of <q>jelly</q>. The verb <q>to jelly</q>
    122 means to serialize an object or data structure into a sequence of bytes (or
    123 other primitive transmittable/storable representation), while <q>to
    124 unjelly</q> means to unserialize the bytestream into a live object in the
    125 receiver's memory space. <q>Unjellyable</q> is a noun, (<em>not</em> an
     120--><span class="footnote"> <p>Note that, in this
     121context, <q>unjelly</q> is a verb with the opposite meaning
     122of <q>jelly</q>. The verb <q>to jelly</q> means to serialize an object
     123or data structure into a sequence of bytes (or other primitive
     124transmittable/storable representation), while <q>to unjelly</q> means
     125to unserialize the bytestream into a live object in the receiver's
     126memory space. <q>Unjellyable</q> is a noun, (<em>not</em> an
    126127adjective), referring to the the class that serves as a destination or
    127 recipient of the unjellying process. <q>A is unjellyable into B</q> means
    128 that a serialized representation A (of some remote object) can be
    129 unserialized into a local object of type B. It is these objects <q>B</q>
    130 that are the <q>Unjellyable</q> second argument of the
    131 <code>setUnjellyableForClass</code> function.</p>
     128recipient of the unjellying process. <q>A is unjellyable into B</q>
     129means that a serialized representation A (of some remote object) can
     130be unserialized into a local object of type B. It is these
     131objects <q>B</q> that are the <q>Unjellyable</q> second argument of
     132the <code>setUnjellyableForClass</code> function.</p>
    132133
    133134<p>In particular, <q>unjellyable</q> does <em>not</em> mean <q>cannot be
    134135jellied</q>. <code class="API"
    mean to reverse the operations of <q>jellying</q>, <q>serializing</q>, and 
    139140
    140141
    141142This function takes a remote/sender class reference (either the
    142 fully-qualified name as used by the sending end, or a class object from
    143 which the name can be extracted), and a local/recipient class (used to
    144 create the local representation for incoming serialized objects). Whenever
    145 the remote end sends an object, the class name that they transmit is looked
    146 up in the table controlled by this function. If a matching class is found,
    147 it is used to create the local object. If not, you get the
    148 <code>InsecureJelly</code> exception.</p>
    149 
    150 <p>In general you expect both ends to share the same codebase: either you
    151 control the program that is running on both ends of the wire, or both
    152 programs share some kind of common language that is implemented in code
    153 which exists on both ends. You wouldn't expect them to send you an object of
    154 the MyFooziWhatZit class unless you also had a definition for that class. So
    155 it is reasonable for the Jelly layer to reject all incoming classes except
    156 the ones that you have explicitly marked with
    157 <code>setUnjellyableForClass</code>. But keep in mind that the sender's idea
    158 of a <code>User</code> object might differ from the recipient's, either
    159 through namespace collisions between unrelated packages, version skew
    160 between nodes that haven't been updated at the same rate, or a malicious
    161 intruder trying to cause your code to fail in some interesting or
    162 potentially vulnerable way.</p>
     143fully-qualified name as used by the sending end, or a class object
     144from which the name can be extracted), and a local/recipient class
     145(used to create the local representation for incoming serialized
     146objects). Whenever the remote end sends an object, the class name that
     147they transmit is looked up in the table controlled by this
     148function. If a matching class is found, it is used to create the local
     149object. If not, you get the <code>InsecureJelly</code> exception.</p>
     150
     151<p>In general you expect both ends to share the same codebase: either
     152you control the program that is running on both ends of the wire, or
     153both programs share some kind of common language that is implemented
     154in code which exists on both ends. You wouldn't expect them to send
     155you an object of the MyFooziWhatZit class unless you also had a
     156definition for that class. So it is reasonable for the Jelly layer to
     157reject all incoming classes except the ones that you have explicitly
     158marked with <code>setUnjellyableForClass</code>. But keep in mind that
     159the sender's idea of a <code>User</code> object might differ from the
     160recipient's, either through namespace collisions between unrelated
     161packages, version skew between nodes that haven't been updated at the
     162same rate, or a malicious intruder trying to cause your code to fail
     163in some interesting or potentially vulnerable way.</p>
    163164
    164165
    165166<h2>pb.Copyable</h2>
    one side to the other?</p> 
    170171<a href="listings/pb/copy_sender.py" class="py-listing">copy_sender.py</a>
    171172<a href="listings/pb/copy_receiver.tac" class="py-listing">copy_receiver.tac</a>
    172173
    173 <p>The sending side has a class called <code>LilyPond</code>. To make this
    174 eligble for transport through <code>callRemote</code> (either as an
    175 argument, a return value, or something referenced by either of those [like a
    176 dictionary value]), it must inherit from one of the four <code class="API"
    177 base="twisted.spread.pb">Serializable</code> classes. In this section,
    178 we focus on <code class="API" base="twisted.spread.pb">Copyable</code>.
    179 The copyable subclass of <code>LilyPond</code> is called
    180 <code>CopyPond</code>. We create an instance of it and send it through
    181 <code>callRemote</code> as an argument to the receiver's
    182 <code>remote_takePond</code> method. The Jelly layer will serialize
    183 (<q>jelly</q>) that object as an instance with a class name of
     174<p>The sending side has a class called <code>LilyPond</code>. To make
     175this eligble for transport through <code>callRemote</code> (either as
     176an argument, a return value, or something referenced by either of
     177those [like a dictionary value]), it must inherit from one of the
     178four <code class="API" base="twisted.spread.pb">Serializable</code>
     179classes. In this section, we focus on <code class="API"
     180base="twisted.spread.pb">Copyable</code>.  The copyable subclass
     181of <code>LilyPond</code> is called <code>CopyPond</code>. We create an
     182instance of it and send it through <code>callRemote</code> as an
     183argument to the receiver's <code>remote_takePond</code> method. The
     184Jelly layer will serialize (<q>jelly</q>) that object as an instance
     185with a class name of
    184186<q>copy_sender.CopyPond</q> and some chunk of data that represents the
    185 object's state. <code>pond.__class__.__module__</code> and
    186 <code>pond.__class__.__name__</code> are used to derive the class name
    187 string. The object's <code class="API"
    188 base="twisted.spread.pb.Copyable">getStateToCopy</code> method is
    189 used to get the state: this is provided by <code class="API"
    190 base="twisted.spread">pb.Copyable</code>, and the default just retrieves
    191 <code>self.__dict__</code>. This works just like the optional
    192 <code>__getstate__</code> method used by <code>pickle</code>. The pair of
    193 name and state are sent over the wire to the receiver.</p>
    194 
    195 <p>The receiving end defines a local class named <code>ReceiverPond</code>
    196 to represent incoming <code>LilyPond</code> instances. This class derives
    197 from the sender's <code>LilyPond</code> class (with a fully-qualified name
    198 of <code>copy_sender.LilyPond</code>), which specifies how we expect it to
    199 behave. We trust that this is the same <code>LilyPond</code> class as the
    200 sender used. (At the very least, we hope ours will be able to accept a state
    201 created by theirs). It also inherits from <code class="API"
    202 base="twisted.spread">pb.RemoteCopy</code>, which is a requirement for all
    203 classes that act in this local-representative role (those which are given to
    204 the second argument of <code>setUnjellyableForClass</code>).
    205 <code>RemoteCopy</code> provides the methods that tell the Jelly layer how
    206 to create the local object from the incoming serialized state.</p>
     187object's state. <code>pond.__class__.__module__</code>
     188and <code>pond.__class__.__name__</code> are used to derive the class
     189name string. The object's <code class="API"
     190base="twisted.spread.pb.Copyable">getStateToCopy</code> method is used
     191to get the state: this is provided by <code class="API"
     192base="twisted.spread">pb.Copyable</code>, and the default just
     193retrieves <code>self.__dict__</code>. This works just like the
     194optional <code>__getstate__</code> method used
     195by <code>pickle</code>. The pair of name and state are sent over the
     196wire to the receiver.</p>
     197
     198<p>The receiving end defines a local class
     199named <code>ReceiverPond</code> to represent
     200incoming <code>LilyPond</code> instances. This class derives from the
     201sender's <code>LilyPond</code> class (with a fully-qualified name
     202of <code>copy_sender.LilyPond</code>), which specifies how we expect
     203it to behave. We trust that this is the same <code>LilyPond</code>
     204class as the sender used. (At the very least, we hope ours will be
     205able to accept a state created by theirs). It also inherits
     206from <code class="API" base="twisted.spread">pb.RemoteCopy</code>,
     207which is a requirement for all classes that act in this
     208local-representative role (those which are given to the second
     209argument
     210of <code>setUnjellyableForClass</code>). <code>RemoteCopy</code>
     211provides the methods that tell the Jelly layer how to create the local
     212object from the incoming serialized state.</p>
    207213
    208214<p>Then <code>setUnjellyableForClass</code> is used to register the two
    209215classes. This has two effects: instances of the remote class (the first
    argument) will be allowed in through the security layer, and instances of 
    211217the local class (the second argument) will be used to contain the state that
    212218is transmitted when the sender serializes the remote object.</p>
    213219
    214 <p>When the receiver unserializes (<q>unjellies</q>) the object, it will
    215 create an instance of the local <code>ReceiverPond</code> class, and hand
    216 the transmitted state (usually in the form of a dictionary) to that object's
    217 <code class="API"
     220<p>When the receiver unserializes (<q>unjellies</q>) the object, it
     221will create an instance of the local <code>ReceiverPond</code> class,
     222and hand the transmitted state (usually in the form of a dictionary)
     223to that object's <code class="API"
    218224base="twisted.spread.pb.RemoteCopy">setCopyableState</code> method.
    219 This acts just like the <code>__setstate__</code> method that
    220 <code>pickle</code> uses when unserializing an object.
    221 <code>getStateToCopy</code>/<code>setCopyableState</code> are distinct from
    222 <code>__getstate__</code>/<code>__setstate__</code> to allow objects to be
    223 persisted (across time) differently than they are transmitted (across
    224 [memory]space).</p>
     225This acts just like the <code>__setstate__</code> method
     226that <code>pickle</code> uses when unserializing an
     227object. <code>getStateToCopy</code>/<code>setCopyableState</code> are
     228distinct from <code>__getstate__</code>/<code>__setstate__</code> to
     229allow objects to be persisted (across time) differently than they are
     230transmitted (across [memory]space).</p>
    225231
    226232<p>When this is run, it produces the following output:</p>
    227233
    Main loop terminated. 
    247253
    248254<h3>Controlling the Copied State</h3>
    249255
    250 <p>By overriding <code>getStateToCopy</code> and
    251 <code>setCopyableState</code>, you can control how the object is transmitted
    252 over the wire. For example, you might want perform some data-reduction:
    253 pre-compute some results instead of sending all the raw data over the wire.
    254 Or you could replace references to a local object on the sender's side with
    255 markers before sending, then upon receipt replace those markers with
    256 references to a receiver-side proxy that could perform the same operations
    257 against a local cache of data.</p>
     256<p>By overriding <code>getStateToCopy</code>
     257and <code>setCopyableState</code>, you can control how the object is
     258transmitted over the wire. For example, you might want perform some
     259data-reduction: pre-compute some results instead of sending all the
     260raw data over the wire.  Or you could replace references to a local
     261object on the sender's side with markers before sending, then upon
     262receipt replace those markers with references to a receiver-side proxy
     263that could perform the same operations against a local cache of
     264data.</p>
    258265
    259266<p>Another good use for <code>getStateToCopy</code> is to implement
    260 <q>local-only</q> attributes: data that is only accessible by the local
    261 process, not to any remote users. For example, a <code>.password</code>
    262 attribute could be removed from the object state before sending to a remote
    263 system. Combined with the fact that <code>Copyable</code> objects return
    264 unchanged from a round trip, this could be used to build a
    265 challenge-response system (in fact PB does this with
    266 <code>pb.Referenceable</code> objects to implement authorization as
    267 described <a href="pb-cred.xhtml">here</a>).</p>
     267<q>local-only</q> attributes: data that is only accessible by the
     268local process, not to any remote users. For example,
     269a <code>.password</code> attribute could be removed from the object
     270state before sending to a remote system. Combined with the fact
     271that <code>Copyable</code> objects return unchanged from a round trip,
     272this could be used to build a challenge-response system (in fact PB
     273does this with <code>pb.Referenceable</code> objects to implement
     274authorization as described <a href="pb-cred.xhtml">here</a>).</p>
    268275
    269276<p>Whatever <code>getStateToCopy</code> returns from the sending object will
    270277be serialized and sent over the wire; <code>setCopyableState</code> gets
    the object it lives in.</p> 
    276283<a href="listings/pb/copy2_sender.py" class="py-listing">copy2_sender.py</a>
    277284<a href="listings/pb/copy2_receiver.py" class="py-listing">copy2_receiver.py</a>
    278285
    279 <p>In this example, the classes are defined in a separate source file, which
    280 also sets up the binding between them. The <code>SenderPond</code> and
    281 <code>ReceiverPond</code> are unrelated save for this binding: they happen
    282 to implement the same methods, but use different internal instance variables
    283 to accomplish them.</p>
     286<p>In this example, the classes are defined in a separate source file,
     287which also sets up the binding between
     288them. The <code>SenderPond</code> and <code>ReceiverPond</code> are
     289unrelated save for this binding: they happen to implement the same
     290methods, but use different internal instance variables to accomplish
     291them.</p>
    284292
    285293<p>The recipient of the object doesn't even have to import the class
    286294definition into their namespace. It is sufficient that they import the class
    object called the <q>observer</q><!-- 
    426434
    427435--><span class="footnote"> this is actually a <code class="API"
    428436base="twisted.spread.pb">RemoteCacheObserver</code>, but it isn't very
    429 useful to subclass or modify, so simply treat it as a little demon that sits
    430 in your <code>pb.Cacheable</code> class and helps you distribute change
    431 notifications. The only useful thing to do with it is to run its
    432 <code>callRemote</code> method, which acts just like a normal
    433 <code>pb.Referenceable</code>'s method of the same name.</span>
     437useful to subclass or modify, so simply treat it as a little demon
     438that sits in your <code>pb.Cacheable</code> class and helps you
     439distribute change notifications. The only useful thing to do with it
     440is to run its <code>callRemote</code> method, which acts just like a
     441normal <code>pb.Referenceable</code>'s method of the same name.</span>
    434442
    435443that points at that receiver-side cache. Every time the state of the object
    436444is changed, you give a message to the observer, informing them of the
    437445change. The other method, <code>stoppedObserving</code>, is called when the
    438446remote cache goes away, so that you can stop sending updates.</p>
    439447
    440 <p>On the receiver end, you make your cache class inherit from <code
    441 class="API" base="twisted.spread">pb.RemoteCache</code>, and implement the
    442 <code>setCopyableState</code> as you would for a <code>pb.RemoteCopy</code>
    443 object. In addition, you must implement methods to receive the updates sent
    444 to the observer by the <code>pb.Cacheable</code>: these methods should have
    445 names that start with <code>observe_</code>, and match the
    446 <code>callRemote</code> invocations from the sender side just as the usual
    447 <code>remote_*</code> and <code>perspective_*</code> methods match normal
    448 <code>callRemote</code> calls. </p>
     448<p>On the receiver end, you make your cache class inherit
     449from <code class="API" base="twisted.spread">pb.RemoteCache</code>,
     450and implement the <code>setCopyableState</code> as you would for
     451a <code>pb.RemoteCopy</code> object. In addition, you must implement
     452methods to receive the updates sent to the observer by
     453the <code>pb.Cacheable</code>: these methods should have names that
     454start with <code>observe_</code>, and match
     455the <code>callRemote</code> invocations from the sender side just as
     456the usual <code>remote_*</code> and <code>perspective_*</code> methods
     457match normal <code>callRemote</code> calls. </p>
    449458
    450459<p>The first time a reference to the <code>pb.Cacheable</code> object is
    451460sent to any particular recipient, a sender-side Observer will be created for
    returns is sent to the remote end and turned into a local representation 
    455464using <code>setCopyableState</code> just like <code>pb.RemoteCopy</code>,
    456465described above (in fact it inherits from that class). </p>
    457466
    458 <p>After that, your <q>setter</q> functions on the sender side should call
    459 <code>callRemote</code> on the Observer, which causes <code>observe_*</code>
    460 methods to run on the receiver, which are then supposed to update the
    461 receiver-local (cached) state.</p>
     467<p>After that, your <q>setter</q> functions on the sender side should
     468call <code>callRemote</code> on the Observer, which
     469causes <code>observe_*</code> methods to run on the receiver, which
     470are then supposed to update the receiver-local (cached) state.</p>
    462471
    463472<p>When the receiver stops following the cached object and the last
    464473reference goes away, the <code>pb.RemoteCache</code> object can be freed.
    used to tell the <code>pb.Cacheable</code> that the Observer has gone 
    471480away.</p>
    472481
    473482<p>With the <code>pb.Cacheable</code> and <code>pb.RemoteCache</code>
    474 classes in place, bound together by a call to
    475 <code>pb.setUnjellyableForClass</code>, all that remains is to pass a
    476 reference to your <code>pb.Cacheable</code> over the wire to the remote end.
    477 The corresponding <code>pb.RemoteCache</code> object will automatically be
    478 created, and the matching methods will be used to keep the receiver-side
    479 slave object in sync with the sender-side master object.</p>
     483classes in place, bound together by a call
     484to <code>pb.setUnjellyableForClass</code>, all that remains is to pass
     485a reference to your <code>pb.Cacheable</code> over the wire to the
     486remote end.  The corresponding <code>pb.RemoteCache</code> object will
     487automatically be created, and the matching methods will be used to
     488keep the receiver-side slave object in sync with the sender-side
     489master object.</p>
    480490
    481491<h3>Example</h3>
    482492
    Main loop terminated. 
    571581  in <code class="API">twisted.spread.flavors</code>,
    572582  where <code>pb.Cacheable</code> is implemented.</li>
    573583
    574   <li><code class="API">twisted.manhole.explorer</code> uses
    575   <code>Cacheable</code>, and does some fairly interesting things with it.</li>
     584  <li><code class="API">twisted.manhole.explorer</code>
     585  uses <code>Cacheable</code>, and does some fairly interesting things
     586  with it.</li>
    576587<!--   (XXX: I've heard explorer is currently broken, it might not be a good -->
    577588<!--   example to recommend)</li> -->
    578589
  • doc/core/howto/pb-cred.xhtml

    diff --git a/doc/core/howto/pb-cred.xhtml b/doc/core/howto/pb-cred.xhtml
    index ac6ba05..11c0eee 100644
    a b easy to implement the most common use cases.</p> 
    3232
    3333<h2>Compartmentalizing Services</h2>
    3434
    35 <p>Imagine how you would write a chat server using PB. The first step might
    36 be a <code>ChatServer</code> object which had a bunch of
    37 <code>pb.RemoteReference</code>s that point at user clients. Pretend that
    38 those clients offered a <code>remote_print</code> method which lets the
    39 server print a message on the user's console. In that case, the server might
    40 look something like this:</p>
     35<p>Imagine how you would write a chat server using PB. The first step
     36might be a <code>ChatServer</code> object which had a bunch
     37of <code>pb.RemoteReference</code>s that point at user
     38clients. Pretend that those clients offered
     39a <code>remote_print</code> method which lets the server print a
     40message on the user's console. In that case, the server might look
     41something like this:</p>
    4142
    4243<pre class="python">
    4344class ChatServer(pb.Referenceable):
    class ChatServer(pb.Referenceable): 
    5960                                                         message))
    6061</pre>
    6162
    62 <p>For now, assume that all clients have somehow acquired a
    63 <code>pb.RemoteReference</code> to this <code>ChatServer</code> object,
    64 perhaps using <code>pb.Root</code> and <code>getRootObject</code> as
    65 described in the <a href="pb-usage.xhtml">previous chapter</a>. In this
    66 scheme, when a user sends a message to the group, their client runs
    67 something like the following:</p>
     63<p>For now, assume that all clients have somehow acquired
     64a <code>pb.RemoteReference</code> to this <code>ChatServer</code>
     65object, perhaps using <code>pb.Root</code>
     66and <code>getRootObject</code> as described in
     67the <a href="pb-usage.xhtml">previous chapter</a>. In this scheme,
     68when a user sends a message to the group, their client runs something
     69like the following:</p>
    6870
    6971<pre class="python">
    7072remotegroup.callRemote("sendMessage", "alice", "Hi, my name is alice.")
    cryptographic literature.</span></p> 
    9496<p>(In general, learn to get suspicious if you see any argument of a
    9597remotely-invokable method described as <q>must be X</q>)</p>
    9698
    97 <p>The best way to fix this is to keep track of the user's name locally,
    98 rather than asking them to send it to the server with each message. The best
    99 place to keep state is in an object, so this suggests we need a per-user
    100 object. Rather than choosing an obvious name<span class="footnote">the
    101 obvious name is clearly
    102 <code>ServerSidePerUserObjectWhichNobodyElseHasAccessTo</code>, but because
    103 python makes everything else so easy to read, it only seems fair to make
    104 your audience work for <em>something</em></span>, let's call this the
    105 <code>User</code> class.
     99<p>The best way to fix this is to keep track of the user's name
     100locally, rather than asking them to send it to the server with each
     101message. The best place to keep state is in an object, so this
     102suggests we need a per-user object. Rather than choosing an obvious
     103name<span class="footnote">the obvious name is
     104clearly <code>ServerSidePerUserObjectWhichNobodyElseHasAccessTo</code>,
     105but because python makes everything else so easy to read, it only
     106seems fair to make your audience work for <em>something</em></span>,
     107let's call this the <code>User</code> class.
    106108</p>
    107109
    108110<pre class="python">
    class ChatServer: 
    133135                user.send("&lt;%s&gt; says: %s" % (from_username, message))
    134136</pre>
    135137
    136 <p>Again, assume that each remote client gets access to a single
    137 <code>User</code> object, which is created with the proper username.</p>
     138<p>Again, assume that each remote client gets access to a
     139single <code>User</code> object, which is created with the proper
     140username.</p>
    138141
    139142<p>Note how the <code>ChatServer</code> object has no remote access: it
    140143isn't even <code>pb.Referenceable</code> anymore. This means that all access
    141144to it must be mediated through other objects, with code that is under your
    142145control.</p>
    143146
    144 <p>As long as Alice only has access to her own <code>User</code> object, she
    145 can no longer spoof Bob. The only way for her to invoke
    146 <code>ChatServer.sendMessage</code> is to call her <code>User</code>
    147 object's <code>remote_sendMessage</code> method, and that method uses its
    148 own state to provide the <code>from_username</code> argument. It doesn't
    149 give her any way to change that state.</p>
    150 
    151 <p>This restriction is important. The <code>User</code> object is able to
    152 maintain its own integrity because there is a wall between the object and
    153 the client: the client cannot inspect or modify internal state, like the
    154 <code>.name</code> attribute. The only way through this wall is via remote
    155 method invocations, and the only control Alice has over those invocations is
    156 when they get invoked and what arguments they are given.</p>
     147<p>As long as Alice only has access to her own <code>User</code>
     148object, she can no longer spoof Bob. The only way for her to
     149invoke <code>ChatServer.sendMessage</code> is to call
     150her <code>User</code> object's <code>remote_sendMessage</code> method,
     151and that method uses its own state to provide
     152the <code>from_username</code> argument. It doesn't give her any way
     153to change that state.</p>
     154
     155<p>This restriction is important. The <code>User</code> object is able
     156to maintain its own integrity because there is a wall between the
     157object and the client: the client cannot inspect or modify internal
     158state, like the <code>.name</code> attribute. The only way through
     159this wall is via remote method invocations, and the only control Alice
     160has over those invocations is when they get invoked and what arguments
     161they are given.</p>
    157162
    158163<div class="note">
    159164<p>No object can maintain its integrity against local threats: by design,
    everything the original object was able to do.</p> 
    165170
    166171<h3>Unforgeable References</h3>
    167172
    168 <p>Now suppose you wanted to implement group parameters, for example a mode
    169 in which nobody was allowed to talk about mattresses because some users were
    170 sensitive and calming them down after someone said <q>mattress</q> is a
    171 hassle that were best avoided altogether. Again, per-group state implies a
    172 per-group object. We'll go out on a limb and call this the
    173 <code>Group</code> object:</p>
     173<p>Now suppose you wanted to implement group parameters, for example a
     174mode in which nobody was allowed to talk about mattresses because some
     175users were sensitive and calming them down after someone
     176said <q>mattress</q> is a hassle that were best avoided
     177altogether. Again, per-group state implies a per-group object. We'll
     178go out on a limb and call this the <code>Group</code> object:</p>
    174179
    175180<pre class="python">
    176181class User(pb.Referenceable):
    class ChatServer: 
    207212</pre>
    208213
    209214
    210 <p>This example takes advantage of the fact that
    211 <code>pb.Referenceable</code> objects sent over a wire can be returned to
    212 you, and they will be turned into references to the same object that you
    213 originally sent. The client cannot modify the object in any way: all they
    214 can do is point at it and invoke its <code>remote_*</code> methods. Thus,
    215 you can be sure that the <code>.name</code> attribute remains the same as
    216 you left it. In this case, the client code would look something like
    217 this:</p>
     215<p>This example takes advantage of the fact
     216that <code>pb.Referenceable</code> objects sent over a wire can be
     217returned to you, and they will be turned into references to the same
     218object that you originally sent. The client cannot modify the object
     219in any way: all they can do is point at it and invoke
     220its <code>remote_*</code> methods. Thus, you can be sure that
     221the <code>.name</code> attribute remains the same as you left it. In
     222this case, the client code would look something like this:</p>
    218223
    219224<pre class="python">
    220225class ClientThing(pb.Referenceable):
    class ClientThing(pb.Referenceable): 
    228233        group.callRemote("send", self.remoteUser, "hi everybody")
    229234</pre>
    230235
    231 <p>The <code>User</code> object is sent from the server side, and is turned
    232 into a <code>pb.RemoteReference</code> when it arrives at the client. The
    233 client sends it back to <code>Group.remote_send</code>, and PB turns it back
    234 into a reference to the original <code>User</code> when it gets there.
    235 <code>Group.remote_send</code> can then use its <code>.name</code> attribute
    236 as the sender of the message.</p>
     236<p>The <code>User</code> object is sent from the server side, and is
     237turned into a <code>pb.RemoteReference</code> when it arrives at the
     238client. The client sends it back to <code>Group.remote_send</code>,
     239and PB turns it back into a reference to the
     240original <code>User</code> when it gets
     241there. <code>Group.remote_send</code> can then use
     242its <code>.name</code> attribute as the sender of the message.</p>
    237243
    238244<div class="note">
    239245
    240246<p>Third party references (there aren't any)</p>
    241247
    242 <p>This technique also relies upon the fact that the
    243 <code>pb.Referenceable</code> reference can <em>only</em> come from someone
    244 who holds a corresponding <code>pb.RemoteReference</code>. The design of the
    245 serialization mechanism (implemented in <code
    246 class="API">twisted.spread.jelly</code>: pb, jelly, spread.. get it?  Look for
     248<p>This technique also relies upon the fact that
     249the <code>pb.Referenceable</code> reference can <em>only</em> come
     250from someone who holds a
     251corresponding <code>pb.RemoteReference</code>. The design of the
     252serialization mechanism (implemented
     253in <code class="API">twisted.spread.jelly</code>: pb, jelly,
     254spread.. get it?  Look for
    247255<q>banana</q>, too.  What other networking framework
    248256can claim API names based on sandwich ingredients?) makes it impossible for
    249257a client to obtain a reference that they weren't explicitly given.
    number won't be in the dict, and no amount of guessing by a malicious client 
    253261will give them anything else. The dict goes away when the connection is
    254262dropped, further limiting the scope of those references.</p>
    255263
    256 <p>Futhermore, it is not possible for Bob to send <em>his</em>
    257 <code>User</code> reference to Alice (perhaps over some other PB channel
    258 just between the two of them). Outside the context of Bob's connection to
    259 the server, that reference is just a meaningless number. To prevent
    260 confusion, PB will tell you if you try to give it away: when you try to hand
    261 a <code>pb.RemoteReference</code> to a third party, you'll get an exception
    262 (implemented with an assert in pb.py:364 RemoteReference.jellyFor).</p>
     264<p>Futhermore, it is not possible for Bob to
     265send <em>his</em> <code>User</code> reference to Alice (perhaps over
     266some other PB channel just between the two of them). Outside the
     267context of Bob's connection to the server, that reference is just a
     268meaningless number. To prevent confusion, PB will tell you if you try
     269to give it away: when you try to hand
     270a <code>pb.RemoteReference</code> to a third party, you'll get an
     271exception (implemented with an assert in pb.py:364
     272RemoteReference.jellyFor).</p>
    263273
    264274<p>This helps the security model somewhat: only the client you gave the
    265275reference to can cause any damage with it. Of course, the client might be a
    reference to the wrong object.</p> 
    286296</div>
    287297
    288298
    289 <p>But again, note the vulnerability. If Alice holds a
    290 <code>RemoteReference</code> to <em>any</em> object on the server side that
    291 has a <code>.name</code> attribute, she can use that name as a spoofed
     299<p>But again, note the vulnerability. If Alice holds
     300a <code>RemoteReference</code> to <em>any</em> object on the server
     301side that has a <code>.name</code> attribute, she can use that name as
     302a spoofed
    292303<q>from</q> parameter. As a simple example, what if her client code looked
    293304like:</p>
    294305
    and she has accomplished her lifelong goal.</p> 
    312323
    313324<h3>Argument Typechecking</h3>
    314325
    315 <p>There are two techniques to close this hole. The first is to have your
    316 remotely-invokable methods do type-checking on their arguments: if
    317 <code>Group.remote_send</code> asserted <code>isinstance(from_user,
    318 User)</code> then Alice couldn't use non-User objects to do her spoofing,
    319 and hopefully the rest of the system is designed well enough to prevent her
    320 from obtaining access to somebody else's User object.</p>
     326<p>There are two techniques to close this hole. The first is to have
     327your remotely-invokable methods do type-checking on their arguments:
     328if <code>Group.remote_send</code> asserted <code>isinstance(from_user,
     329User)</code> then Alice couldn't use non-User objects to do her
     330spoofing, and hopefully the rest of the system is designed well enough
     331to prevent her from obtaining access to somebody else's User
     332object.</p>
    321333
    322334
    323335<h3>Objects as Capabilities</h3>
    324336
    325 <p>The second technique is to avoid having the client send you the objects
    326 altogether. If they don't send you anything, there is nothing to verify. In
    327 this case, you would have to have a per-user-per-group object, in which the
    328 <code>remote_send</code> method would only take a single
    329 <code>message</code> argument. The <code>UserGroup</code> object is created
    330 with references to the only <code>User</code> and <code>Group</code> objects
    331 that it will ever use, so no lookups are needed:</p>
     337<p>The second technique is to avoid having the client send you the
     338objects altogether. If they don't send you anything, there is nothing
     339to verify. In this case, you would have to have a per-user-per-group
     340object, in which the <code>remote_send</code> method would only take a
     341single <code>message</code> argument. The <code>UserGroup</code>
     342object is created with references to the only <code>User</code>
     343and <code>Group</code> objects that it will ever use, so no lookups
     344are needed:</p>
    332345
    333346<pre class="python">
    334347class UserGroup(pb.Referenceable):
    class Group: 
    352365        self.users.append(user)
    353366</pre>
    354367
    355 <p>The only message-sending method Alice has left is
    356 <code>UserGroup.remote_send</code>, and it only accepts a message: there are
    357 no remaining ways to influence the <q>from</q> name.</p>
     368<p>The only message-sending method Alice has left
     369is <code>UserGroup.remote_send</code>, and it only accepts a message:
     370there are no remaining ways to influence the <q>from</q> name.</p>
    358371
    359372<p>In this model, each remotely-accessible object represents a very small
    360373set of capabilities. Security is achieved by only granting a minimal set of
    361374abilities to each remote user.</p>
    362375
    363 <p>PB provides a shortcut which makes this technique easier to use. The
    364 <code>Viewable</code> class will be discussed <a
    365 href="#viewable">below</a>.</p>
     376<p>PB provides a shortcut which makes this technique easier to
     377use. The <code>Viewable</code> class will be
     378discussed <a href="#viewable">below</a>.</p>
    366379
    367380<h2>Avatars and Perspectives</h2>
    368381
    provide additional data, then call other methods which get things done.</p> 
    380393<q>what serves as the Avatar?</q>, and <q>how does the user get access to
    381394it?</q>.</p>
    382395
    383 <p>For PB, the first question is easy. The Avatar is a remotely-accessible
    384 object which can run code: this is a perfect description of
    385 <code>pb.Referenceable</code> and its subclasses. We shall defer the second
    386 question until the next section.</p>
     396<p>For PB, the first question is easy. The Avatar is a
     397remotely-accessible object which can run code: this is a perfect
     398description of <code>pb.Referenceable</code> and its subclasses. We
     399shall defer the second question until the next section.</p>
    387400
    388 <p>In the example above, you can think of the <code>ChatServer</code> and
    389 <code>Group</code> objects as a service. The <code>User</code> object is the
    390 user's server-side representative: everything the user is capable of doing
    391 is done by running one of its methods. Anything that the server wants to do
    392 to the user (change their group membership, change their name, delete their
    393 pet cat, whatever) is done by manipulating the <code>User</code> object.</p>
     401<p>In the example above, you can think of the <code>ChatServer</code>
     402and <code>Group</code> objects as a service. The <code>User</code>
     403object is the user's server-side representative: everything the user
     404is capable of doing is done by running one of its methods. Anything
     405that the server wants to do to the user (change their group
     406membership, change their name, delete their pet cat, whatever) is done
     407by manipulating the <code>User</code> object.</p>
    394408
    395409<p>There are multiple User objects living in peace and harmony around the
    396410ChatServer. Each has a different point of view on the services provided by
    These different points of view are called <q>Perspectives</q>. This is the 
    400414origin of the term <q>Perspective</q> in <q>Perspective Broker</q>: PB
    401415provides and controls (i.e. <q>brokers</q>) access to Perspectives.</p>
    402416
    403 <p>Once upon a time, these local-representative objects were actually called
    404 <code>pb.Perspective</code>. But this has changed with the advent of the
    405 rewritten cred system, and now the more generic term for a local
    406 representative object is an Avatar. But you will still see reference to
     417<p>Once upon a time, these local-representative objects were actually
     418called <code>pb.Perspective</code>. But this has changed with the
     419advent of the rewritten cred system, and now the more generic term for
     420a local representative object is an Avatar. But you will still see
     421reference to
    407422<q>Perspective</q> in the code, the docs, and the module names<span
    408423class="footnote">We could just go ahead and rename Perspective Broker to be
    409424Avatar Broker, but 1) that would cause massive compatibility problems, and 2)
    twisted.spread would then have to be renamed twisted.alphabetsoup, and then 
    414429the whole food-pun thing would start all over again.</span>. Just remember
    415430that perspectives and avatars are basically the same thing. </p>
    416431
    417 <p>Despite all we've been <a href="cred.xhtml">telling you</a> about how
    418 Avatars are more of a concept than an actual class, the base class from
    419 which you can create your server-side avatar-ish objects is, in fact, named
    420 <code>pb.Avatar</code><span class="footnote">The avatar-ish class is named
    421 <code>pb.Avatar</code> because <code>pb.Perspective</code> was already
    422 taken, by the (now obsolete) oldcred perspective-ish class. It is a pity,
    423 but it simply wasn't possible both replace <code>pb.Perspective</code>
     432<p>Despite all we've been <a href="cred.xhtml">telling you</a> about
     433how Avatars are more of a concept than an actual class, the base class
     434from which you can create your server-side avatar-ish objects is, in
     435fact, named <code>pb.Avatar</code><span class="footnote">The
     436avatar-ish class is named <code>pb.Avatar</code>
     437because <code>pb.Perspective</code> was already taken, by the (now
     438obsolete) oldcred perspective-ish class. It is a pity, but it simply
     439wasn't possible both replace <code>pb.Perspective</code>
    424440in-place <em>and</em> maintain a reasonable level of
    425 backwards-compatibility.</span>. These objects behave very much like
    426 <code>pb.Referenceable</code>. The only difference is that instead of
    427 offering <q>remote_FOO</q> methods, they offer <q>perspective_FOO</q>
    428 methods.</p>
    429 
    430 <p>The other way in which <code>pb.Avatar</code> differs from
    431 <code>pb.Referenceable</code> is that the avatar objects are designed to be
    432 the first thing retrieved by a cred-using remote client. Just as
    433 <code>PBClientFactory.getRootObject</code> gives the client access to a
    434 <code>pb.Root</code> object (which can then provide access to all kinds of
    435 other objects), <code>PBClientFactory.login</code> gives client access to a
    436 <code>pb.Avatar</code> object (which can return other references). </p>
     441backwards-compatibility.</span>. These objects behave very much
     442like <code>pb.Referenceable</code>. The only difference is that
     443instead of offering <q>remote_FOO</q> methods, they
     444offer <q>perspective_FOO</q> methods.</p>
     445
     446<p>The other way in which <code>pb.Avatar</code> differs
     447from <code>pb.Referenceable</code> is that the avatar objects are
     448designed to be the first thing retrieved by a cred-using remote
     449client. Just as <code>PBClientFactory.getRootObject</code> gives the
     450client access to a <code>pb.Root</code> object (which can then provide
     451access to all kinds of other
     452objects), <code>PBClientFactory.login</code> gives client access to
     453a <code>pb.Avatar</code> object (which can return other
     454references). </p>
    437455
    438456<p>So, the first half of using cred in your PB application is to create an
    439457Avatar object which implements <code>perspective_</code> methods and is
    again with two users this time.</p> 
    488506<div class="note">
    489507
    490508<p>When the client runs <code>login</code> to request the Perspective,
    491 they can provide it with an optional <code>client</code> argument (which
    492 must be a <code>pb.Referenceable</code> object). If they do, then a
    493 reference to that object will be handed to the realm's
    494 <code>requestAvatar</code> in the <code>mind</code> argument.</p>
     509they can provide it with an optional <code>client</code> argument
     510(which must be a <code>pb.Referenceable</code> object). If they do,
     511then a reference to that object will be handed to the
     512realm's <code>requestAvatar</code> in the <code>mind</code>
     513argument.</p>
    495514
    496515<p>The server-side Perspective can use it to invoke remote methods on
    497516something in the client, so that the client doesn't always have to drive the
    Perspective.</p> 
    522541our server-side Avatar. It implements a <code>perspective_foo</code> method
    523542that is exposed to the remote client.</p>
    524543
    525 <p>Second, we created a realm (an object which implements
    526 <code>IRealm</code>, and therefore implements <code>requestAvatar</code>).
    527 This realm manufactures <code>MyPerspective</code> objects. It makes as many
    528 as we want, and names each one with the avatarID (a username) that comes out
    529 of the checkers. This MyRealm object returns two other objects as well,
    530 which we will describe later.</p>
     544<p>Second, we created a realm (an object which
     545implements <code>IRealm</code>, and therefore
     546implements <code>requestAvatar</code>).  This realm
     547manufactures <code>MyPerspective</code> objects. It makes as many as
     548we want, and names each one with the avatarID (a username) that comes
     549out of the checkers. This MyRealm object returns two other objects as
     550well, which we will describe later.</p>
    531551
    532552<p>Third, we created a portal to hold this realm. The portal's job is to
    533553dispatch incoming clients to the credential checkers, and then to request
    534554Avatars for any which survive the authentication process.</p>
    535555
    536 <p>Fourth, we made a simple checker (an object which implements
    537 <code>IChecker</code>) to hold valid user/password pairs. The checker
    538 gets registered with the portal, so it knows who to ask when new
    539 clients connect.  We use a checker named
    540 <code>InMemoryUsernamePasswordDatabaseDontUse</code>, which suggests
    541 that 1: all the username/password pairs are kept in memory instead of
    542 being saved to a database or something, and 2: you shouldn't use
    543 it. The admonition against using it is because there are better
    544 schemes: keeping everything in memory will not work when you have
    545 thousands or millions of users to keep track of, the passwords will be
    546 stored in the .tap file when the application shuts down (possibly a
    547 security risk), and finally it is a nuisance to add or remove users
    548 after the checker is constructed.</p>
     556<p>Fourth, we made a simple checker (an object which
     557implements <code>IChecker</code>) to hold valid user/password
     558pairs. The checker gets registered with the portal, so it knows who to
     559ask when new clients connect.  We use a checker
     560named <code>InMemoryUsernamePasswordDatabaseDontUse</code>, which
     561suggests that 1: all the username/password pairs are kept in memory
     562instead of being saved to a database or something, and 2: you
     563shouldn't use it. The admonition against using it is because there are
     564better schemes: keeping everything in memory will not work when you
     565have thousands or millions of users to keep track of, the passwords
     566will be stored in the .tap file when the application shuts down
     567(possibly a security risk), and finally it is a nuisance to add or
     568remove users after the checker is constructed.</p>
    549569
    550570<p>Fifth, we create a <code>pb.PBServerFactory</code> to listen on a TCP
    551571port. This factory knows how to connect the remote client to the Portal, so
    protocols (non-PB) would do something similar: the factory that creates 
    554574Protocol objects will give those objects access to the Portal so
    555575authentication can take place.</p>
    556576
    557 <p>On the client side, a <code>pb.PBClientFactory</code> is created (as <a
    558 href="pb-usage.xhtml">before</a>) and attached to a TCP connection. When the
    559 connection completes, the factory will be asked to produce a Protocol, and
    560 it will create a PB object. Unlike the previous chapter, where we used
    561 <code>.getRootObject</code>, here we use <code>factory.login</code> to
    562 initiate the cred authentication process. We provide a
    563 <code>credentials</code> object, which is the client-side agent for doing
    564 our half of the authentication process. This process may involve several
    565 messages: challenges, responses, encrypted passwords, secure hashes, etc. We
    566 give our credentials object everything it will need to respond correctly (in
    567 this case, a username and password, but you could write a credential that
    568 used public-key encryption or even fancier techniques).</p>
    569 
    570 <p><code>login</code> returns a Deferred which, when it fires, will return a
    571 <code>pb.RemoteReference</code> to the remote avatar. We can then do
    572 <code>callRemote</code> to invoke a <code>perspective_foo</code> method on
     577<p>On the client side, a <code>pb.PBClientFactory</code> is created
     578(as <a href="pb-usage.xhtml">before</a>) and attached to a TCP
     579connection. When the connection completes, the factory will be asked
     580to produce a Protocol, and it will create a PB object. Unlike the
     581previous chapter, where we used <code>.getRootObject</code>, here we
     582use <code>factory.login</code> to initiate the cred authentication
     583process. We provide a <code>credentials</code> object, which is the
     584client-side agent for doing our half of the authentication
     585process. This process may involve several messages: challenges,
     586responses, encrypted passwords, secure hashes, etc. We give our
     587credentials object everything it will need to respond correctly (in
     588this case, a username and password, but you could write a credential
     589that used public-key encryption or even fancier techniques).</p>
     590
     591<p><code>login</code> returns a Deferred which, when it fires, will
     592return a <code>pb.RemoteReference</code> to the remote avatar. We can
     593then do <code>callRemote</code> to invoke a <code>perspective_foo</code> method on
    573594that Avatar.</p>
    574595
    575596
    that Avatar.</p> 
    578599<a href="listings/pb/pbAnonServer.py" class="py-listing">pbAnonServer.py</a>
    579600<a href="listings/pb/pbAnonClient.py" class="py-listing">pbAnonClient.py</a>
    580601
    581 <p>pbAnonServer.py implements a server based on pb6server.py, extending it to
    582 permit anonymous logins in addition to authenticated logins. A
    583 <code class="API" base="twisted.cred.checkers">AllowAnonymousAccess</code>
    584 checker and a <code class="API" base="twisted.cred.checkers">
    585 InMemoryUsernamePasswordDatabaseDontUse</code> checker are registered and the
    586 client's choice of credentials object determines which is used to authenticate
    587 the login.  In either case, the realm will be called on to create an avatar for
    588 the login.  <code>AllowAnonymousAccess</code> always produces an <code>avatarId
    589 </code> of <code class="API" base="twisted.cred.checkers">ANONYMOUS</code>.</p>
    590 
    591 <p>On the client side, the only change is the use of an instance of
    592 <code class="API" base="twisted.cred.credentials">Anonymous</code> when calling
    593 <code class="API" base="twisted.spread.pb">PBClientFactory.login</code>.</p>
     602<p>pbAnonServer.py implements a server based on pb6server.py,
     603extending it to permit anonymous logins in addition to authenticated
     604logins. A <code class="API"
     605base="twisted.cred.checkers">AllowAnonymousAccess</code> checker and
     606a <code class="API" base="twisted.cred.checkers">
     607InMemoryUsernamePasswordDatabaseDontUse</code> checker are registered
     608and the client's choice of credentials object determines which is used
     609to authenticate the login.  In either case, the realm will be called
     610on to create an avatar for the
     611login.  <code>AllowAnonymousAccess</code> always produces
     612an <code>avatarId</code> of <code class="API"
     613base="twisted.cred.checkers">ANONYMOUS</code>.</p>
     614
     615<p>On the client side, the only change is the use of an instance
     616of <code class="API" base="twisted.cred.credentials">Anonymous</code>
     617when calling <code class="API"
     618base="twisted.spread.pb">PBClientFactory.login</code>.</p>
    594619
    595620
    596621<h2>Using Avatars</h2>
    be described in more detail below.</p> 
    619644
    620645<h3>Making Avatars</h3>
    621646
    622 <p>In the example above, we create Avatars upon request, during
    623 <code>requestAvatar</code>. Depending upon the service, these Avatars might
    624 already exist before the connection is received, and might outlive the
    625 connection. The Avatars might also accept multiple connections.</p>
     647<p>In the example above, we create Avatars upon request,
     648during <code>requestAvatar</code>. Depending upon the service, these
     649Avatars might already exist before the connection is received, and
     650might outlive the connection. The Avatars might also accept multiple
     651connections.</p>
    626652
    627653<p>Another possibility is that the Avatars might exist ahead of time, but in
    628654a different form (frozen in a pickle and/or saved in a database). In this
    then do something with the result before it can provide an avatar. In this 
    631657case, it would probably return a Deferred so it could provide the real
    632658Avatar later, once the lookup had completed.</p>
    633659
    634 <p>Here are some possible implementations of
    635 <code>MyRealm.requestAvatar</code>:</p>
     660<p>Here are some possible implementations
     661of <code>MyRealm.requestAvatar</code>:</p>
    636662
    637663<pre class="python">
    638664    # pre-existing, static avatars
    something in the server, and if there are clients attached, it should update 
    690716them (through the <q>mind</q> argument which lets the Avatar do callRemote
    691717on the client).</p>
    692718
    693 <p>One common idiom which accomplishes this is to have the Realm tell the
    694 avatar that a remote client has just attached. The Realm can also ask the
    695 protocol to let it know when the connection goes away, so it can then inform
    696 the Avatar that the client has detached. The third member of the
    697 <code>requestAvatar</code> return tuple is a callable which will be invoked
    698 when the connection is lost.</p>
     719<p>One common idiom which accomplishes this is to have the Realm tell
     720the avatar that a remote client has just attached. The Realm can also
     721ask the protocol to let it know when the connection goes away, so it
     722can then inform the Avatar that the client has detached. The third
     723member of the <code>requestAvatar</code> return tuple is a callable
     724which will be invoked when the connection is lost.</p>
    699725
    700726<pre class="python">
    701727class MyPerspective(pb.Avatar):
    class MyRealm: 
    722748
    723749<h3>Viewable</h3> <a name="viewable" />
    724750
    725 <p>Once you have <code>IPerspective</code> objects (i.e. the Avatar) to
    726 represent users, the <code class="API"
    727 base="twisted.spread.flavors">Viewable</code> class can come into play. This
    728 class behaves a lot like <code>Referenceable</code>: it turns into a
    729 <code>RemoteReference</code> when sent over the wire, and certain methods
    730 can be invoked by the holder of that reference. However, the methods that
    731 can be called have names that start with <code>view_</code> instead of
    732 <code>remote_</code>, and those methods are always called with an extra
    733 <code>perspective</code> argument that points to the Avatar through which
    734 the reference was sent:</p>
     751<p>Once you have <code>IPerspective</code> objects (i.e. the Avatar)
     752to represent users, the <code class="API"
     753base="twisted.spread.flavors">Viewable</code> class can come into
     754play. This class behaves a lot like <code>Referenceable</code>: it
     755turns into a <code>RemoteReference</code> when sent over the wire, and
     756certain methods can be invoked by the holder of that
     757reference. However, the methods that can be called have names that
     758start with <code>view_</code> instead of <code>remote_</code>, and
     759those methods are always called with an extra <code>perspective</code>
     760argument that points to the Avatar through which the reference was
     761sent:</p>
    735762
    736763<pre class="python">
    737764class Foo(pb.Viewable):
    the same object. The <code>view_</code> methods can use the 
    745772gives them a way to do additional permission checks, do per-user accounting,
    746773etc.</p>
    747774
    748 <p>This is the shortcut which makes per-user-per-group capability objects
    749 much easier to use. Instead of creating such per-(user,group) objects, you
    750 just have per-group objects which inherit from <code>pb.Viewable</code>, and
    751 give the user references to them. The local <code>pb.Avatar</code> object
    752 will automatically show up as the <q>perspective</q> argument in the
    753 <code>view_*</code> method calls, give you a chance to involve the Avatar in
    754 the process.</p>
     775<p>This is the shortcut which makes per-user-per-group capability
     776objects much easier to use. Instead of creating such per-(user,group)
     777objects, you just have per-group objects which inherit
     778from <code>pb.Viewable</code>, and give the user references to
     779them. The local <code>pb.Avatar</code> object will automatically show
     780up as the <q>perspective</q> argument in the <code>view_*</code>
     781method calls, give you a chance to involve the Avatar in the
     782process.</p>
    755783
    756784
    757785<h3>Chat Server with Avatars</h3>
    be available for a game next saturday afternoon).</p> 
    764792
    765793<a href="listings/pb/chatserver.py" class="py-listing">chatserver.py</a>
    766794
    767 <p>Notice that the client uses <code>perspective_joinGroup</code> to both
    768 join a group and retrieve a <code>RemoteReference</code> to the
    769 <code>Group</code> object. However, the reference they get is actually to a
    770 special intermediate object called a <code>pb.ViewPoint</code>. When they do
    771 <code>group.callRemote("send", "message")</code>, their avatar is inserted
    772 into the argument list that <code>Group.view_send</code> actually sees. This
    773 lets the group get their username out of the Avatar without giving the
    774 client an opportunity to spoof someone else.</p>
     795<p>Notice that the client uses <code>perspective_joinGroup</code> to
     796both join a group and retrieve a <code>RemoteReference</code> to
     797the <code>Group</code> object. However, the reference they get is
     798actually to a special intermediate object called
     799a <code>pb.ViewPoint</code>. When they
     800do <code>group.callRemote("send", "message")</code>, their avatar is
     801inserted into the argument list that <code>Group.view_send</code>
     802actually sees. This lets the group get their username out of the
     803Avatar without giving the client an opportunity to spoof someone
     804else.</p>
    775805
    776806<p>The client side code that joins a group and sends a message would look
    777807like this:</p>
  • doc/core/howto/pb-intro.xhtml

    diff --git a/doc/core/howto/pb-intro.xhtml b/doc/core/howto/pb-intro.xhtml
    index 6d976c8..2350830 100644
    a b out through their interaction than explaining them one at a time.</p> 
    5555
    5656<ul>
    5757
    58   <li><em><code class="API" base="twisted.internet.protocol">Factory</code></em>
     58  <li><code class="API" base="twisted.internet.protocol">Factory</code>
    5959  : <code>internet/protocol.py</code></li>
    6060
    61   <li><em><code class="API" base="twisted.spread.pb">PBServerFactory</code></em>
     61  <li><code class="API" base="twisted.spread.pb">PBServerFactory</code>
    6262  : <code>spread/pb.py</code></li>
    6363
    64   <li><em><code class="API" base="twisted.spread.pb">Broker</code></em>
     64  <li><code class="API" base="twisted.spread.pb">Broker</code>
    6565  : <code>spread/pb.py</code></li>
    6666
    6767</ul>
    out through their interaction than explaining them one at a time.</p> 
    7070
    7171<ul>
    7272
    73   <li> <em><code class="API" base="twisted.spread.pb">RemoteReference</code></em>
     73  <li><code class="API" base="twisted.spread.pb">RemoteReference</code>
    7474  : <code>spread/pb.py</code> </li>
    7575
    76   <li> <em><code class="API" base="twisted.spread">pb.Root</code></em>
     76  <li><code class="API" base="twisted.spread">pb.Root</code>
    7777  : <code>spread/pb.py</code>, actually defined as
    7878  <code>twisted.spread.flavors.Root</code>
    7979  in <code>spread/flavors.py</code> </li>
    8080
    81   <li> <em><code class="API" base="twisted.spread">pb.Referenceable</code></em>
     81  <li><code class="API" base="twisted.spread">pb.Referenceable</code>
    8282  : <code>spread/pb.py</code>, actually defined as
    8383  <code>twisted.spread.flavors.Referenceable</code>
    8484  in <code>spread/flavors.py</code> </li>
    out through their interaction than explaining them one at a time.</p> 
    8989about authorization and security:</p>
    9090
    9191<ul>
    92   <li><em><code class="API" base="twisted.cred.portal">Portal</code></em>
     92  <li><code class="API" base="twisted.cred.portal">Portal</code>
    9393  : <code>cred/portal.py</code></li>
    9494
    95   <li><em><code class="API" base="twisted.cred.portal">IRealm</code></em>
     95  <li><code class="API" base="twisted.cred.portal">IRealm</code>
    9696  : <code>cred/portal.py</code></li>
    9797 
    98   <li><em><code class="API" base="twisted.spread.pb">IPerspective</code></em>
     98  <li><code class="API" base="twisted.spread.pb">IPerspective</code>
    9999  : <code>spread/pb.py</code>, which you will usually be interacting
    100100  with via pb.Avatar (a basic implementor of the interface).</li>
    101101</ul>
    published methods with the appropriate prefix. 
    205205<p>In addition to returning objects that you can call remote methods on, you
    206206can return structured copies of local objects.</p>
    207207
    208 <p>There are 2 basic flavors that allow for copying objects remotely.  Again,
    209 you can use these by subclassing them.  In order to specify what state you want
    210 to have copied when these are serialized, you can either use the Python default
    211 <code class="python">__getstate__</code> or specialized method calls for that
    212 flavor.</p>
     208<p>There are 2 basic flavors that allow for copying objects remotely.
     209Again, you can use these by subclassing them.  In order to specify
     210what state you want to have copied when these are serialized, you can
     211either use the Python default <code class="python">__getstate__</code>
     212or specialized method calls for that flavor.</p>
    213213
    214214<p>
    215215<ul>
  • doc/core/howto/pb-limits.xhtml

    diff --git a/doc/core/howto/pb-limits.xhtml b/doc/core/howto/pb-limits.xhtml
    index f0e6204..24b49c8 100644
    a b limit is 640 * 1024, defined by <code>twisted.spread.banana.SIZE_LIMIT</code>. 
    3030It's possible to raise this limit by changing this value (but take care to
    3131change it on both sides of the connection).</p>
    3232
    33   <p>Another limit imposed by Twisted's Banana implementation is a limit on
    34 the size of long integers.  The purpose of this limit is the same as the
    35 <code>SIZE_LIMIT</code>.  By default, only integers between -2 ** 448 and 2
    36 ** 448 (exclusive) can be transferred.  This limit can be changed using
    37 <code class="API">twisted.spread.banana.setPrefixLimit</code>.</p>
     33  <p>Another limit imposed by Twisted's Banana implementation is a
     34limit on the size of long integers.  The purpose of this limit is the
     35same as the <code>SIZE_LIMIT</code>.  By default, only integers
     36between -2 ** 448 and 2 ** 448 (exclusive) can be transferred.  This
     37limit can be changed
     38using <code class="API">twisted.spread.banana.setPrefixLimit</code>.</p>
    3839
    3940  <h2>Perspective Broker Limits</h2>
    4041
  • doc/core/howto/pb-usage.xhtml

    diff --git a/doc/core/howto/pb-usage.xhtml b/doc/core/howto/pb-usage.xhtml
    index c602e8a..924f9ab 100644
    a b  
    99
    1010<h2>Basic Example</h2>
    1111
    12 <p>The first example to look at is a complete (although somewhat trivial)
    13 application. It uses <code>PBServerFactory()</code> on the server side, and
    14 <code>PBClientFactory()</code> on the client side.</p>
     12<p>The first example to look at is a complete (although somewhat
     13trivial) application. It uses <code>PBServerFactory()</code> on the
     14server side, and <code>PBClientFactory()</code> on the client
     15side.</p>
    1516
    1617<a href="../examples/pbsimple.py" class="py-listing" skipLines="5"
    1718>pbsimple.py</a>
    1819<a href="../examples/pbsimpleclient.py" class="py-listing" skipLines="5"
    1920>pbsimpleclient.py</a>
    2021
    21 <p>First we look at the server. This defines an Echoer class (derived from
    22 <code class="API" base="twisted.spread">pb.Root</code>), with a method called
    23 <code>remote_echo()</code>.
    24 <code class="API" base="twisted.spread">pb.Root</code> objects (because of
    25 their inheritance of
    26 <code class="API" base="twisted.spread">pb.Referenceable</code>, described
    27 later) can define methods with names of the form <code>remote_*</code>; a
    28 client which obtains a remote reference to that
    29 <code class="API" base="twisted.spread">pb.Root</code> object will be able to
    30 invoke those methods.</p>
    31 
    32 <p>The <code class="API" base="twisted.spread">pb.Root</code>-ish object is
    33 given to a <code class="API"
    34 base="twisted.spread">pb.PBServerFactory</code><code>()</code>. This is a
    35 <code class="API" base="twisted.internet.protocol">Factory</code> object like
    36 any other: the <code class="API"
    37 base="twisted.internet.protocol">Protocol</code> objects it creates for new
    38 connections know how to speak the PB protocol. The object you give to
    39 <code>pb.PBServerFactory()</code> becomes the <q>root object</q>, which
    40 simply makes it available for the client to retrieve. The client may only
    41 request references to the objects you want to provide it: this helps you
    42 implement your security model. Because it is so common to export just a
    43 single object (and because a <code>remote_*</code> method on that one can
    44 return a reference to any other object you might want to give out), the
     22<p>First we look at the server. This defines an Echoer class (derived
     23from <code class="API" base="twisted.spread">pb.Root</code>), with a
     24method called <code>remote_echo()</code>. <code class="API"
     25base="twisted.spread">pb.Root</code> objects (because of their
     26inheritance of <code class="API"
     27base="twisted.spread">pb.Referenceable</code>, described later) can
     28define methods with names of the form <code>remote_*</code>; a client
     29which obtains a remote reference to that <code class="API"
     30base="twisted.spread">pb.Root</code> object will be able to invoke
     31those methods.</p>
     32
     33<p>The <code class="API" base="twisted.spread">pb.Root</code>-ish
     34object is given to a <code class="API"
     35base="twisted.spread">pb.PBServerFactory</code><code>()</code>. This
     36is a <code class="API" base="twisted.internet.protocol">Factory</code>
     37object like any other: the <code class="API"
     38base="twisted.internet.protocol">Protocol</code> objects it creates
     39for new connections know how to speak the PB protocol. The object you
     40give to <code>pb.PBServerFactory()</code> becomes the <q>root
     41object</q>, which simply makes it available for the client to
     42retrieve. The client may only request references to the objects you
     43want to provide it: this helps you implement your security
     44model. Because it is so common to export just a single object (and
     45because a <code>remote_*</code> method on that one can return a
     46reference to any other object you might want to give out), the
    4547simplest example is one where the <code class="API"
    46 base="twisted.spread.pb">PBServerFactory</code> is given the root object, and
    47 the client retrieves it.</p>
     48base="twisted.spread.pb">PBServerFactory</code> is given the root
     49object, and the client retrieves it.</p>
    4850
    49 <p>The client side uses
    50 <code class="API" base="twisted.spread">pb.PBClientFactory</code> to make a
    51 connection to a given port. This is a two-step process involving opening
    52 a TCP connection to a given host and port and requesting the root object
     51<p>The client side uses <code class="API"
     52base="twisted.spread">pb.PBClientFactory</code> to make a connection
     53to a given port. This is a two-step process involving opening a TCP
     54connection to a given host and port and requesting the root object
    5355using <code>.getRootObject()</code>.</p>
    5456
    5557<p>Because <code>.getRootObject()</code> has to wait until a network
    base="twisted.internet.defer">Deferred</code>s). If and when the 
    6163connection succeeds and a reference to the remote root object is
    6264obtained, this callback is run. The first argument passed to the
    6365callback is a remote reference to the distant root object.  (you can
    64 give other arguments to the callback too, see the other parameters for
    65 <code>.addCallback()</code> and <code>.addCallbacks()</code>).</p>
     66give other arguments to the callback too, see the other parameters
     67for <code>.addCallback()</code> and <code>.addCallbacks()</code>).</p>
    6668
    6769<p>The callback does:</p>
    6870
    give other arguments to the callback too, see the other parameters for 
    7072object.callRemote("echo", "hello network")
    7173</pre>
    7274
    73 <p>which causes the server's <code>.remote_echo()</code> method to be invoked.
    74 (running <code>.callRemote("boom")</code> would cause
    75 <code>.remote_boom()</code> to be run, etc). Again because of the delay
    76 involved, <code>callRemote()</code> returns a
    77 <code class="API" base="twisted.internet.defer">Deferred</code>. Assuming the
    78 remote method was run without causing an exception (including an attempt to
    79 invoke an unknown method), the callback attached to that
    80 <code class="API" base="twisted.internet.defer">Deferred</code> will be
    81 invoked with any objects that were returned by the remote method call.</p>
     75<p>which causes the server's <code>.remote_echo()</code> method to be
     76invoked.  (running <code>.callRemote("boom")</code> would
     77cause <code>.remote_boom()</code> to be run, etc). Again because of
     78the delay involved, <code>callRemote()</code> returns
     79a<code class="API"
     80base="twisted.internet.defer">Deferred</code>. Assuming the remote
     81method was run without causing an exception (including an attempt to
     82invoke an unknown method), the callback attached to
     83that <code class="API" base="twisted.internet.defer">Deferred</code>
     84will be invoked with any objects that were returned by the remote
     85method call.</p>
    8286
    8387<p>In this example, the server's <code>Echoer</code> object has a method
    8488invoked, <em>exactly</em> as if some code on the server side had done:</p>
    local. Trying to do so (as some other RPC mechanisms do, coughCORBAcough) 
    100104breaks down when faced with the asynchronous nature of the network. Using
    101105Deferreds turns out to be a very clean way to deal with the whole thing.</p>
    102106
    103 <p>The remote reference object (the one given to
    104 <code>getRootObject()</code>'s success callback) is an instance the <code
    105 class="API" base="twisted.spread.pb">RemoteReference</code> class. This means
    106 you can use it to invoke methods on the remote object that it refers to. Only
    107 instances of <code class="API"
    108 base="twisted.spread.pb">RemoteReference</code> are eligible for
    109 <code>.callRemote()</code>. The <code class="API"
    110 base="twisted.spread.pb">RemoteReference</code> object is the one that lives
    111 on the remote side (the client, in this case), not the local side (where the
    112 actual object is defined).</p>
    113 
    114 <p>In our example, the local object is that <code>Echoer()</code> instance,
    115 which inherits from <code class="API" base="twisted.spread">pb.Root</code>,
    116 which inherits from
    117 <code class="API" base="twisted.spread">pb.Referenceable</code>. It is that
    118 <code>Referenceable</code> class that makes the object eligible to be available
    119 for remote method calls<span class="footnote">There are a few other classes
    120 that can bestow this ability, but pb.Referenceable is the easiest to
    121 understand; see 'flavors' below for details on the others.</span>. If you have
    122 an object that is Referenceable, then any client that manages to get a
    123 reference to it can invoke any <code>remote_*</code> methods they please.</p>
     107<p>The remote reference object (the one given
     108to <code>getRootObject()</code>'s success callback) is an instance
     109the <code class="API" base="twisted.spread.pb">RemoteReference</code>
     110class. This means you can use it to invoke methods on the remote
     111object that it refers to. Only instances of <code class="API"
     112base="twisted.spread.pb">RemoteReference</code> are eligible
     113for <code>.callRemote()</code>. The <code class="API"
     114base="twisted.spread.pb">RemoteReference</code> object is the one that
     115lives on the remote side (the client, in this case), not the local
     116side (where the actual object is defined).</p>
     117
     118<p>In our example, the local object is that <code>Echoer()</code>
     119instance, which inherits from <code class="API"
     120base="twisted.spread">pb.Root</code>, which inherits
     121from <code class="API"
     122base="twisted.spread">pb.Referenceable</code>. It is
     123that <code>Referenceable</code> class that makes the object eligible
     124to be available for remote method calls<span class="footnote">There
     125are a few other classes that can bestow this ability, but
     126pb.Referenceable is the easiest to understand; see 'flavors' below for
     127details on the others.</span>. If you have an object that is
     128Referenceable, then any client that manages to get a reference to it
     129can invoke any <code>remote_*</code> methods they please.</p>
    124130
    125131<div class="note">
    126 <p>The <em>only</em> thing they can do is invoke those
    127 methods.  In particular, they cannot access attributes. From a security point
    128 of view, you control what they can do by limiting what the
    129 <code>remote_*</code> methods can do.</p>
    130 
    131 <p>Also note: the other classes like
    132 <code class="API" base="twisted.spread.pb">Referenceable</code> allow access to
    133 other methods, in particular <code>perspective_*</code> and <code>view_*</code>
    134 may be accessed.  Don't write local-only methods with these names, because then
    135 remote callers will be able to do more than you intended.</p>
    136 
    137 <p>Also also note: the other classes like
    138 <code class="API" base="twisted.spread">pb.Copyable</code> <em>do</em> allow
    139 access to attributes, but you control which ones they can see.</p>
     132<p>The <em>only</em> thing they can do is invoke those methods.  In
     133particular, they cannot access attributes. From a security point of
     134view, you control what they can do by limiting what
     135the <code>remote_*</code> methods can do.</p>
     136
     137<p>Also note: the other classes like <code class="API"
     138base="twisted.spread.pb">Referenceable</code> allow access to other
     139methods, in particular <code>perspective_*</code>
     140and <code>view_*</code> may be accessed.  Don't write local-only
     141methods with these names, because then remote callers will be able to
     142do more than you intended.</p>
     143
     144<p>Also also note: the other classes like <code class="API"
     145base="twisted.spread">pb.Copyable</code> <em>do</em> allow access to
     146attributes, but you control which ones they can see.</p>
    140147</div>
    141148
    142 <p>You don't have to be a
    143 <code class="API" base="twisted.spread">pb.Root</code> to be remotely callable,
    144 but you do have to be
    145 <code class="API" base="twisted.spread">pb.Referenceable</code>.  (Objects that
    146 inherit from <code class="API" base="twisted.spread">pb.Referenceable</code>
    147 but not from <code class="API" base="twisted.spread">pb.Root</code> can be
    148 remotely called, but only
    149 <code class="API" base="twisted.spread">pb.Root</code>-ish objects can be given
    150 to the <code class="API" base="twisted.spread.pb">PBServerFactory</code>.)</p>
     149<p>You don't have to be a <code class="API"
     150base="twisted.spread">pb.Root</code> to be remotely callable, but you
     151do have to be <code class="API"
     152base="twisted.spread">pb.Referenceable</code>.  (Objects that inherit
     153from <code class="API" base="twisted.spread">pb.Referenceable</code>
     154but not from <code class="API" base="twisted.spread">pb.Root</code>
     155can be remotely called, but only <code class="API"
     156base="twisted.spread">pb.Root</code>-ish objects can be given to
     157the <code class="API"
     158base="twisted.spread.pb">PBServerFactory</code>.)</p>
    151159
    152160<h2>Complete Example</h2>
    153161
    base="twisted.spread">pb.PBClientFactory.getRootObject</code> will 
    166174handle all the details of waiting for the creation of a connection.
    167175It returns a <code class="API"
    168176base="twisted.internet.defer">Deferred</code>, which will have its
    169 callback called when the reactor connects to the remote server and
    170 <code class="API" base="twisted.spread">pb.PBClientFactory</code> gets the
    171 root, and have its <code class="python">errback</code> called when the
    172 object-connection fails for any reason, whether it was host lookup
    173 failure, connection refusal, or some server-side error.
     177callback called when the reactor connects to the remote server
     178and <code class="API" base="twisted.spread">pb.PBClientFactory</code>
     179gets the root, and have its <code class="python">errback</code> called
     180when the object-connection fails for any reason, whether it was host
     181lookup failure, connection refusal, or some server-side error.
    174182</p>
    175183
    176184<p>The root object has a method called <code>remote_getTwo</code>, which
    class="python">callback</code> or <code class="python">errback</code> 
    194202will be made, depending on whether an error occurred in processing the
    195203method call.</p>
    196204
    197 <p>You can use this technique to provide access to arbitrary sets of objects.
    198 Just remember that any object that might get passed <q>over the wire</q> must
    199 inherit from <code class="API" base="twisted.spread.pb">Referenceable</code>
    200 (or one of the other flavors). If you try to pass a non-Referenceable object
    201 (say, by returning one from a <code>remote_*</code> method), you'll get an
    202 <code class="API" base="twisted.spread.jelly">InsecureJelly</code>
    203 exception<span class="footnote">This can be overridden, by subclassing one of
    204 the Serializable flavors and defining custom serialization code for your
    205 class. See <a href="pb-copyable.xhtml">Passing Complex Types</a> for
    206 details.</span>.</p>
     205<p>You can use this technique to provide access to arbitrary sets of
     206objects.  Just remember that any object that might get passed <q>over
     207the wire</q> must inherit from <code class="API"
     208base="twisted.spread.pb">Referenceable</code> (or one of the other
     209flavors). If you try to pass a non-Referenceable object (say, by
     210returning one from a <code>remote_*</code> method), you'll get
     211an <code class="API" base="twisted.spread.jelly">InsecureJelly</code>
     212exception<span class="footnote">This can be overridden, by subclassing
     213one of the Serializable flavors and defining custom serialization code
     214for your class. See <a href="pb-copyable.xhtml">Passing Complex
     215Types</a> for details.</span>.</p>
    207216
    208217
    209218<h2>References can come back to you</h2>
    210219
    211 <p>If your server gives a reference to a client, and then that client gives
    212 the reference back to the server, the server will wind up with the same
    213 object it gave out originally. The serialization layer watches for returning
    214 reference identifiers and turns them into actual objects. You need to stay
    215 aware of where the object lives: if it is on your side, you do actual method
    216 calls. If it is on the other side, you do
    217 <code>.callRemote()</code><span class="footnote">The binary nature of this
    218 local vs. remote scheme works because you cannot give RemoteReferences to a
    219 third party. If you could, then your object A could go to B, B could give it to
    220 C, C might give it back to you, and you would be hard pressed to tell if the
    221 object lived in C's memory space, in B's, or if it was really your own object,
    222 tarnished and sullied after being handed down like a really ugly picture that
    223 your great aunt owned and which nobody wants but which nobody can bear to throw
    224 out. Ok, not really like that, but you get the idea.</span>.</p>
     220<p>If your server gives a reference to a client, and then that client
     221gives the reference back to the server, the server will wind up with
     222the same object it gave out originally. The serialization layer
     223watches for returning reference identifiers and turns them into actual
     224objects. You need to stay aware of where the object lives: if it is on
     225your side, you do actual method calls. If it is on the other side, you
     226do <code>.callRemote()</code><span class="footnote">The binary nature
     227of this local vs. remote scheme works because you cannot give
     228RemoteReferences to a third party. If you could, then your object A
     229could go to B, B could give it to C, C might give it back to you, and
     230you would be hard pressed to tell if the object lived in C's memory
     231space, in B's, or if it was really your own object, tarnished and
     232sullied after being handed down like a really ugly picture that your
     233great aunt owned and which nobody wants but which nobody can bear to
     234throw out. Ok, not really like that, but you get the idea.</span>.</p>
    225235
    226236<a href="listings/pb/pb2server.py" class="py-listing">pb2server.py</a>
    227237<a href="listings/pb/pb2client.py" class="py-listing">pb2client.py</a>
    object.</p> 
    277287about when they go wrong? The Python Way is to raise an exception of some
    278288sort. The Twisted Way is the same.</p>
    279289
    280 <p>The only special thing you do is to define your <code>Exception</code>
    281 subclass by deriving it from <code class="API"
    282 base="twisted.spread">pb.Error</code>. When any remotely-invokable method
    283 (like <code>remote_*</code> or <code>perspective_*</code>) raises a
    284 <code>pb.Error</code>-derived exception, a serialized form of that Exception
    285 object will be sent back over the wire<span class="footnote">To be precise,
    286 the Failure will be sent if <em>any</em> exception is raised, not just
    287 pb.Error-derived ones. But the server will print ugly error messages if you
    288 raise ones that aren't derived from pb.Error.</span>. The other side (which
    289 did <code>callRemote</code>) will have the <q><code>errback</code></q>
    290 callback run with a <code class="API"
    291 base="twisted.python.failure">Failure</code> object that contains a copy of
    292 the exception object. This <code>Failure</code> object can be queried to
    293 retrieve the error message and a stack traceback.</p>
     290<p>The only special thing you do is to define
     291your <code>Exception</code> subclass by deriving it
     292from <code class="API" base="twisted.spread">pb.Error</code>. When any
     293remotely-invokable method (like <code>remote_*</code>
     294or <code>perspective_*</code>) raises a <code>pb.Error</code>-derived
     295exception, a serialized form of that Exception object will be sent
     296back over the wire<span class="footnote">To be precise, the Failure
     297will be sent if <em>any</em> exception is raised, not just
     298pb.Error-derived ones. But the server will print ugly error messages
     299if you raise ones that aren't derived from pb.Error.</span>. The other
     300side (which did <code>callRemote</code>) will have
     301the <q><code>errback</code></q> callback run with a <code class="API"
     302base="twisted.python.failure">Failure</code> object that contains a
     303copy of the exception object. This <code>Failure</code> object can be
     304queried to retrieve the error message and a stack traceback.</p>
    294305
    295306<p><code class="API" base="twisted.python.failure">Failure</code> is a
    296307special class, defined in <code>twisted/python/failure.py</code>, created to
    can be nested, <code>errback</code> functions can be chained. If one errback 
    299310can't handle the particular type of failure, it can be <q>passed along</q> to a
    300311errback handler further down the chain.</p>
    301312
    302 <p>For simple purposes, think of the <code>Failure</code> as just a container
    303 for remotely-thrown <code>Exception</code> objects. To extract the string that
    304 was put into the exception, use its <code>.getErrorMessage()</code> method.
    305 To get the type of the exception (as a string), look at its
    306 <code>.type</code> attribute. The stack traceback is available too. The
    307 intent is to let the errback function get just as much information about the
    308 exception as Python's normal <code>try:</code> clauses do, even though the
    309 exception occurred in somebody else's memory space at some unknown time in
    310 the past.</p>
     313<p>For simple purposes, think of the <code>Failure</code> as just a
     314container for remotely-thrown <code>Exception</code> objects. To
     315extract the string that was put into the exception, use
     316its <code>.getErrorMessage()</code> method.  To get the type of the
     317exception (as a string), look at its <code>.type</code> attribute. The
     318stack traceback is available too. The intent is to let the errback
     319function get just as much information about the exception as Python's
     320normal <code>try:</code> clauses do, even though the exception
     321occurred in somebody else's memory space at some unknown time in the
     322past.</p>
    311323
    312324<a href="listings/pb/exc_server.py" class="py-listing">exc_server.py</a>
    313325<a href="listings/pb/exc_client.py" class="py-listing">exc_client.py</a>
    got remote Exception 
    321333Main loop terminated.
    322334</pre>
    323335
    324 <p>Oh, and what happens if you raise some other kind of exception? Something
    325 that <em>isn't</em> subclassed from <code>pb.Error</code>? Well, those are
    326 called <q>unexpected exceptions</q>, which make Twisted think that something
    327 has <em>really</em> gone wrong. These will raise an exception on the
    328 <em>server</em> side. This won't break the connection (the exception is
    329 trapped, just like most exceptions that occur in response to network
    330 traffic), but it will print out an unsightly stack trace on the server's
    331 stderr with a message that says <q>Peer Will Receive PB Traceback</q>, just
    332 as if the exception had happened outside a remotely-invokable method. (This
    333 message will go the current log target, if <code class="API"
    334 base="twisted.python">log.startLogging</code> was used to redirect it). The
    335 client will get the same <code>Failure</code> object in either case, but
    336 subclassing your exception from <code>pb.Error</code> is the way to tell
    337 Twisted that you expect this sort of exception, and that it is ok to just
    338 let the client handle it instead of also asking the server to complain. Look
    339 at <code>exc_client.py</code> and change it to invoke <code>broken2()</code>
    340 instead of <code>broken()</code> to see the change in the server's
    341 behavior.</p>
    342 
    343 <p>If you don't add an <code>errback</code> function to the <code
    344 class="API" base="twisted.internet.defer">Deferred</code>, then a remote
    345 exception will still send a <code>Failure</code> object back over, but it
    346 will get lodged in the <code>Deferred</code> with nowhere to go. When that
    347 <code>Deferred</code> finally goes out of scope, the side that did
    348 <code>callRemote</code> will emit a message about an <q>Unhandled error in
    349 Deferred</q>, along with an ugly stack trace. It can't raise an exception at
    350 that point (after all, the <code>callRemote</code> that triggered the
    351 problem is long gone), but it will emit a traceback. So be a good programmer
    352 and <em>always add <code>errback</code> handlers</em>, even if they are just
    353 calls to <code class="API" base="twisted.python">log.err</code>.</p>
     336<p>Oh, and what happens if you raise some other kind of exception?
     337Something that <em>isn't</em> subclassed from <code>pb.Error</code>?
     338Well, those are called <q>unexpected exceptions</q>, which make
     339Twisted think that something has <em>really</em> gone wrong. These
     340will raise an exception on the <em>server</em> side. This won't break
     341the connection (the exception is trapped, just like most exceptions
     342that occur in response to network traffic), but it will print out an
     343unsightly stack trace on the server's stderr with a message that
     344says <q>Peer Will Receive PB Traceback</q>, just as if the exception
     345had happened outside a remotely-invokable method. (This message will
     346go the current log target, if <code class="API"
     347base="twisted.python">log.startLogging</code> was used to redirect
     348it). The client will get the same <code>Failure</code> object in
     349either case, but subclassing your exception from <code>pb.Error</code>
     350is the way to tell Twisted that you expect this sort of exception, and
     351that it is ok to just let the client handle it instead of also asking
     352the server to complain. Look at <code>exc_client.py</code> and change
     353it to invoke <code>broken2()</code> instead of <code>broken()</code>
     354to see the change in the server's behavior.</p>
     355
     356<p>If you don't add an <code>errback</code> function to
     357the <code class="API" base="twisted.internet.defer">Deferred</code>,
     358then a remote exception will still send a <code>Failure</code> object
     359back over, but it will get lodged in the <code>Deferred</code> with
     360nowhere to go. When that <code>Deferred</code> finally goes out of
     361scope, the side that did <code>callRemote</code> will emit a message
     362about an <q>Unhandled error in Deferred</q>, along with an ugly stack
     363trace. It can't raise an exception at that point (after all,
     364the <code>callRemote</code> that triggered the problem is long gone),
     365but it will emit a traceback. So be a good programmer and <em>always
     366add </em> <code>errback</code> <em> handlers</em>, even if they are just calls
     367to <code class="API" base="twisted.python">log.err</code>.</p>
    354368
    355369<h2>Try/Except blocks and <code class="API"
    356370base="twisted.python.failure">Failure.trap</code> </h2>
    357371
    358 <p>To implement the equivalent of the Python try/except blocks (which can
    359 trap particular kinds of exceptions and pass others <q>up</q> to
    360 higher-level <code>try/except</code> blocks), you can use the
    361 <code>.trap()</code> method in conjunction with multiple
    362 <code>errback</code> handlers on the <code>Deferred</code>. Re-raising an
    363 exception in an <code>errback</code> handler serves to pass that new
    364 exception to the next handler in the chain. The <code>trap</code> method is
    365 given a list of exceptions to look for, and will re-raise anything that
    366 isn't on the list. Instead of passing unhandled exceptions <q>up</q> to an
     372<p>To implement the equivalent of the Python try/except blocks (which
     373can trap particular kinds of exceptions and pass others <q>up</q> to
     374higher-level <code>try/except</code> blocks), you can use
     375the <code>.trap()</code> method in conjunction with
     376multiple <code>errback</code> handlers on
     377the <code>Deferred</code>. Re-raising an exception in
     378an <code>errback</code> handler serves to pass that new exception to
     379the next handler in the chain. The <code>trap</code> method is given a
     380list of exceptions to look for, and will re-raise anything that isn't
     381on the list. Instead of passing unhandled exceptions <q>up</q> to an
    367382enclosing <code>try</code> block, this has the effect of passing the
    368 exception <q>off</q> to later <code>errback</code> handlers on the same
    369 <code>Deferred</code>. The <code>trap</code> calls are used in chained
    370 errbacks to test for each kind of exception in sequence. </p>
     383exception <q>off</q> to later <code>errback</code> handlers on the
     384same <code>Deferred</code>. The <code>trap</code> calls are used in
     385chained errbacks to test for each kind of exception in sequence. </p>
    371386
    372387<a href="listings/pb/trap_server.py" class="py-listing">trap_server.py</a>
    373388<a href="listings/pb/trap_client.py" class="py-listing">trap_client.py</a>
    living, breathing instance of some class): one reason is that it does not 
    396411know which local class ought to be used to create an instance that
    397412corresponds to the remote object<!--   eat breaking space
    398413
    399 --><span class="footnote"><p>The naive approach of simply doing <code>import
    400 SomeClass</code> to match a remote caller who claims to have an object of
    401 type <q>SomeClass</q> could have nasty consequences for some modules that do
    402 significant operations in their <code>__init__</code> methods (think
    403 <code>telnetlib.Telnet(host='localhost', port='chargen')</code>, or even
    404 more powerful classes that you have available in your server program).
    405 Allowing a remote entity to create arbitrary classes in your namespace is
    406 nearly equivalent to allowing them to run arbitrary code.</p>
     414--><span class="footnote"><p>The naive approach of simply
     415doing <code>import SomeClass</code> to match a remote caller who
     416claims to have an object of type <q>SomeClass</q> could have nasty
     417consequences for some modules that do significant operations in
     418their <code>__init__</code> methods
     419(think <code>telnetlib.Telnet(host='localhost',
     420port='chargen')</code>, or even more powerful classes that you have
     421available in your server program).  Allowing a remote entity to create
     422arbitrary classes in your namespace is nearly equivalent to allowing
     423them to run arbitrary code.</p>
    407424
    408425<p>The <code class="API" base="twisted.spread">pb.InsecureJelly</code>
    409 exception arises because the class being sent over the wire has not been
    410 registered with the serialization layer (known as <code class="API"
    411 base="twisted.spread">jelly</code>). The easiest way to make it possible to
    412 copy entire class instances over the wire is to have them inherit from <code
    413 class="API" base="twisted.spread">pb.Copyable</code>, and then to use
    414 <code>setUnjellyableForClass(remoteClass, localClass)</code> on the
    415 receiving side. See <a href="pb-copyable.xhtml">Passing Complex Types</a>
    416 for an example.</p></span>.
    417 
    418 The receiving end of the connection gets to decide what to accept and what
    419 to reject. It indicates its disapproval by raising a <code class="API"
    420 base="twisted.spread">pb.InsecureJelly</code> exception. Because it occurs
    421 at the remote end, the exception is returned to the caller asynchronously,
    422 so an <code>errback</code> handler for the associated <code>Deferred</code>
    423 is run. That errback receives a <code>Failure</code> which wraps the
    424 <code>InsecureJelly</code>.</p>
    425 
    426 
    427 <p>Remember that <code>trap</code> re-raises exceptions that it wasn't asked
    428 to look for. You can only check for one set of exceptions per errback
    429 handler: all others must be checked in a subsequent handler.
    430 <code>check_MyException</code> shows how multiple kinds of exceptions can be
    431 checked in a single errback: give a list of exception types to
    432 <code>trap</code>, and it will return the matching member. In this case, the
    433 kinds of exceptions we are checking for (<code>MyException</code> and
    434 <code>MyOtherException</code>) may be raised by the remote end: they inherit
    435 from <code class="API" base="twisted.spread">pb.Error</code>.</p>
    436 
    437 <p>The handler can return <code>None</code> to terminate processing of the
    438 errback chain (to be precise, it switches to the callback that follows the
    439 errback; if there is no callback then processing terminates). It is a good
    440 idea to put an errback that will catch everything (no <code>trap</code>
    441 tests, no possible chance of raising more exceptions, always returns
    442 <code>None</code>) at the end of the chain. Just as with regular <code>try:
    443 except:</code> handlers, you need to think carefully about ways in which
    444 your errback handlers could themselves raise exceptions. The extra
    445 importance in an asynchronous environment is that an exception that falls
    446 off the end of the <code>Deferred</code> will not be signalled until that
    447 <code>Deferred</code> goes out of scope, and at that point may only cause a
    448 log message (which could even be thrown away if <code class="API"
    449 base="twisted.python">log.startLogging</code> is not used to point it at
    450 stdout or a log file). In contrast, a synchronous exception that is not
    451 handled by any other <code>except:</code> block will very visibly terminate
    452 the program immediately with a noisy stack trace.</p>
     426exception arises because the class being sent over the wire has not
     427been registered with the serialization layer (known
     428as <code class="API" base="twisted.spread">jelly</code>). The easiest
     429way to make it possible to copy entire class instances over the wire
     430is to have them inherit from <code class="API"
     431base="twisted.spread">pb.Copyable</code>, and then to
     432use <code>setUnjellyableForClass(remoteClass, localClass)</code> on
     433the receiving side. See <a href="pb-copyable.xhtml">Passing Complex
     434Types</a> for an example.</p></span>.
     435
     436The receiving end of the connection gets to decide what to accept and
     437what to reject. It indicates its disapproval by raising
     438a <code class="API" base="twisted.spread">pb.InsecureJelly</code>
     439exception. Because it occurs at the remote end, the exception is
     440returned to the caller asynchronously, so an <code>errback</code>
     441handler for the associated <code>Deferred</code> is run. That errback
     442receives a <code>Failure</code> which wraps
     443the <code>InsecureJelly</code>.</p>
     444
     445
     446<p>Remember that <code>trap</code> re-raises exceptions that it wasn't
     447asked to look for. You can only check for one set of exceptions per
     448errback handler: all others must be checked in a subsequent
     449handler. <code>check_MyException</code> shows how multiple kinds of
     450exceptions can be checked in a single errback: give a list of
     451exception types to <code>trap</code>, and it will return the matching
     452member. In this case, the kinds of exceptions we are checking for
     453(<code>MyException</code> and <code>MyOtherException</code>) may be
     454raised by the remote end: they inherit from <code class="API"
     455base="twisted.spread">pb.Error</code>.</p>
     456
     457<p>The handler can return <code>None</code> to terminate processing of
     458the errback chain (to be precise, it switches to the callback that
     459follows the errback; if there is no callback then processing
     460terminates). It is a good idea to put an errback that will catch
     461everything (no <code>trap</code> tests, no possible chance of raising
     462more exceptions, always returns <code>None</code>) at the end of the
     463chain. Just as with regular <code>try: except:</code> handlers, you
     464need to think carefully about ways in which your errback handlers
     465could themselves raise exceptions. The extra importance in an
     466asynchronous environment is that an exception that falls off the end
     467of the <code>Deferred</code> will not be signalled until
     468that <code>Deferred</code> goes out of scope, and at that point may
     469only cause a log message (which could even be thrown away
     470if <code class="API" base="twisted.python">log.startLogging</code> is
     471not used to point it at stdout or a log file). In contrast, a
     472synchronous exception that is not handled by any
     473other <code>except:</code> block will very visibly terminate the
     474program immediately with a noisy stack trace.</p>
    453475
    454476<p><code>callFour</code> shows another kind of exception that can occur
    455477while using <code>callRemote</code>: <code class="API"
    this guaranteed? probably not), so must be caught in a traditional 
    460482synchronous <code>try: except pb.DeadReferenceError</code> block. </p>
    461483
    462484<p>Yet another kind that can occur is a <code class="API"
    463 base="twisted.spread">pb.PBConnectionLost</code> exception. This occurs
    464 (asynchronously) if the connection was lost while you were waiting for a
    465 <code>callRemote</code> call to complete. When the line goes dead, all
    466 pending requests are terminated with this exception. Note that you have no
    467 way of knowing whether the request made it to the other end or not, nor how
    468 far along in processing it they had managed before the connection was
    469 lost. XXX: explain transaction semantics, find a decent reference.</p>
     485base="twisted.spread">pb.PBConnectionLost</code> exception. This
     486occurs (asynchronously) if the connection was lost while you were
     487waiting for a <code>callRemote</code> call to complete. When the line
     488goes dead, all pending requests are terminated with this
     489exception. Note that you have no way of knowing whether the request
     490made it to the other end or not, nor how far along in processing it
     491they had managed before the connection was lost. XXX: explain
     492transaction semantics, find a decent reference.</p>
    470493
    471494</body> </html>