# Copyright 2002 Combex, Inc. under the terms of the MIT X license # found at http://www.opensource.org/licenses/mit-license.html ............... pragma.syntax("0.9") def makeFlexMap :DeepFrozen := def VatID :DeepFrozen := def makeVine :DeepFrozen := def Vine :DeepFrozen := makeVine.asType() def Throwable :DeepFrozen := /** * Rendezvous point for 3-vat live Granovetter introductions of Resolved remote * references (FarRefs). *

* Where we normally speak of Alice giving Bob a reference to Carol, we here * speak of the Donor (VatA) giving to the Recipient (VatB) a reference to the * Gift (Carol) residing on the Host (VatC). There is one NearGiftTable in the * Host per Donor. The Donor associates the gift with a Nonce, the Recipient's * ID, and the SwissHash of the gift. She then tells the Nonce and swissHash to * the Recipient. The Recipient asks the Host "What gift has Donor (identified * by DonorID) deposited for me at this Nonce and swissHash?". *

* A Nonce is a use-once unique number. It only needs to be "impossible" to * collide under benevolent assumptions; it doesn't need to be unguessable, so * we a 64 bit number. *

* When the donor registers the gift, the swissHash should be verified (by the * NearGiftTable's immediate client, the NonceLocator) to correspond to the * gift, which should be Near. The key under which the gift is stored is the * triple [recipient ID, nonce, swissHash]. The corresponding loopup must match * on all three, and must be satisfied immediately. To Allow services * with Near arguments the recipient's Far reference must be made to * correspond to a local Near reference, or it must become a DisconnectedRef. * In order to guarantee that the loopup can be satisfied immediately, we must * ensure that the corresponding registration arrives first. For this, we * expect to use the unimplemented Wormhole technique, documented at the above * URL. Until then, the first case must be avoided. This avoidance results in * the Lost * Resolution bug. *

* An interesting complexity: A partition could prevent the operation from * completing, in which case the Recipient cannot be left hanging, and the * association must be cleaned up.

* * @author Mark S. Miller. */ def makeNearGiftTable(whenGarbage) implements DeepFrozen { var myStuff := makeFlexMap.fromTypes(List, any) def nearGiftTable { /** * Disable this table. */ to smash(problem :Throwable) :void { myStuff := null; } /** * Make the gift available to the recipient so long as the Vine is held * onto (isn't garbage). */ to provideFor(gift :any, recipID :VatID, nonce :int, swissHash :int) :Vine { def keyTriple := [recipID, nonce, swissHash]; def result := makeVine(null); myStuff.put(keyTriple, gift); #XXX do we need to hold onto the weakPtr in order for it to be #finalized? If so, then we must. whenGarbage(result, fn { nearGiftTable.drop(keyTriple) }) return result; } /** * Lookup the gift. *

* Note that this message is named "acceptFor" whereas the corresponding * NonceLocator message is named "acceptFrom". In acceptFor, the recipient * is explicit and the donor implicit. In acceptFrom, the donor is explicit * and the recipient implicit. * * @param recipID The vatID of the vat (Bob, the gift recipient) that the * gift is being picked up for. * @param nonce Identifies (together with the recipID) the gift. */ to acceptFor(recipID :VatID, nonce :int, swissHash :int) :any { def keyTriple := [recipID, nonce, swissHash] #if absent, get/1 will throw def result := myStuff.get(keyTriple) myStuff.removeKey(keyTriple) return result } /** * Automagically called when the vine is dropped.

*

* The Donor is able to call this as well, which isn't appropriate, but * isn't dangerous, so what the hell. * * XXX E translation note: we can and therefore should now make this private */ to drop(keyTriple :Tuple[VatID, int, int]) :void { def [recipID, nonce, swissHash] := keyTriple myStuff.removeKey(keyTriple); } } return nearGiftTable }