Ticket #4568: pb.xhtml.patch

File pb.xhtml.patch, 97.8 KB (added by jdb, 4 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>