# Copyright 2007 Kevin Reid under the terms of the MIT X license # found at http://www.opensource.org/licenses/mit-license.html ................ pragma.syntax("0.9") pragma.enable("call-pattern") def scheme :String := "captp" def makeSwissTable :DeepFrozen := def asWaterkenBase32 :DeepFrozen := def now :DeepFrozen := def unsignedIntegerCoding :DeepFrozen := def makeLocatorUnum :DeepFrozen := def makeHub :DeepFrozen := def makeBrand :DeepFrozen := def KeyPair :DeepFrozen := any # XXX stub def makeIntroducer implements ExitViaHere, DeepFrozen { # XXX makePair wrong name since it's three facets now to makePair(config :Map, entropy :any, # XXX interface timer :any) { # XXX interface interface SturdyRef {} # XXX stub def swissTable := makeSwissTable(entropy, , ) # XXX should be weak-key and weak-value maps def negotiable := ["BOGUS_PLACEHOLDER"] # resolved when we become identified def myVatID def hub def locatorUnum := makeLocatorUnum(myVatID, swissTable, hub) def [sturdyRefPartsSealer, sturdyRefPartsUnsealer] := makeBrand("SturdyRef transparency") def sturdyRefPartsBrand := sturdyRefPartsUnsealer.getBrand() def srMap := [].asMap().diverge() # XXX either make sturdyrefs selfless and remove this table, or make it weak def getSturdyRef(vatID, searchPathStr, swissNumber) { def key := [vatID, searchPathStr, swissNumber] if (srMap.maps(key)) { return srMap[key] } def sturdyRef implements SturdyRef { to __printOn(out :TextWriter) { if (__equalizer.sameYet(vatID, myVatID)) { out.write("") } else { out.write("") } } to __optSealedDispatch(brand) { return if (brand == sturdyRefPartsBrand) { sturdyRefPartsSealer.seal(key) } } to getRcvr() { # XXX stub search path return locatorUnum.getRcvr([], vatID, swissNumber, null) } } srMap[key] := sturdyRef return sturdyRef } def introducer { to getLocatorUnum() { return locatorUnum } to getNetConfig() { throw("XXX no net config object yet") } # XXX stub to getVatID() { # XXX would it be ok to return the promise? if (Ref.isResolved(myVatID)) { return myVatID } else { throw("introducer not yet identified") } } to hasIdentity() { return Ref.isResolved(myVatID) } to isOnTheAir() { return Ref.isResolved(hub) } to negotiable() { return negotiable } # XXX stub to newVatIdentity() :KeyPair { def nid := asWaterkenBase32(entropy.nextSwiss().cryptoHash().toOctetsUnsigned()) # XXX stub introducer.setVatIdentity(def keyPair { to _getVatID() { return nid } }) # XXX stub return keyPair } to setVatIdentity(keyPair :KeyPair) :void { if (Ref.isResolved(myVatID)) { throw(`$introducer is already identified`) # XXX stub } bind myVatID := keyPair._getVatID() # XXX stub } to onTheAir() { if (!introducer.isOnTheAir()) { if (!introducer.hasIdentity()) { introducer.newVatIdentity() } bind hub := makeHub(def makeConnection {}, def outgoingConnect {}) } return negotiable } to __printOn(out :TextWriter) { if (introducer.isOnTheAir()) { out.write(``) } else { out.write("") } } } def identityMgr { to __printOn(out :TextWriter) { out.write("") # XXX stub } to makeKnown(ref) { def myVatID1 := introducer.getVatID() # checks for being identified def swissBase := entropy.nextSwiss() def swissNumber := swissTable.registerNewSwiss(ref, swissBase) def sr := getSturdyRef(myVatID1, "", swissNumber) # XXX non-stub searchpath return [sr, def timeout {}, swissBase] } # XXX other ops } def { to get(uriBody :String) { def `//*@vatID@@@searchPathStr/@{asWaterkenBase32(swissNumberBytes ? (swissNumberBytes != []))}` \ exit fn p { throw(`Malformed CapTP URI: ${if (`$p` =~ `problem: @t`) {t} else {p}}`) } \ := uriBody # XXX silly way to turn bytes into int; should be __makeInt.fromDigits(1, swissNumberBytes, 256) once that is implemented def swissNumber := unsignedIntegerCoding[swissNumberBytes.size() * 8].takingFrom(swissNumberBytes.asStream(), now)() return getSturdyRef(vatID, searchPathStr, swissNumber) } to sturdyFromURI(uri :String) { # XXX unnecessary printing # XXX deleting 'problem: ' ought to be done by printing without it def `$scheme:@uriBody` \ exit fn p { throw(`Malformed CapTP URI: ${if (`$p` =~ `problem: @t`) {t} else {p}}`) } \ := uri return [uriBody] } to sturdyToURI(sr) { # XXX guard return `$scheme:${.optUnget(sr)}` } to optUnget(specimen) { # XXX appropriate to allow imitators? could reject by requiring noncoercing DeepFrozen if (sturdyRefPartsUnsealer.amplify(specimen) =~ [[vatID, searchPathStr, swissNumber]]) { return `//*$vatID@@$searchPathStr/${asWaterkenBase32(swissNumber.toOctetsUnsigned())}` } } to optUncall(specimen) { if (.optUnget(specimen) =~ uriBody :notNull) { return [, "get", [uriBody]] } } } return [introducer, identityMgr, ] } }