Walnut/Persistent Secure Distributed Computing
From Erights
(→Example: Persistent eChat: put in the code from echat.e-awt) |
(→Swiss Bases) |
||
Line 8: | Line 8: | ||
===Swiss Bases=== | ===Swiss Bases=== | ||
+ | |||
+ | An Swiss Base is like the mythical numbered Swiss bank account. | ||
+ | If you know the number you can get access. | ||
+ | But in the instance of Swiss Bases it is the object but not an account you gain access to. | ||
===Example: Persistent eChat=== | ===Example: Persistent eChat=== |
Revision as of 04:09, 5 March 2008
Persistent Secure Distributed Computing
There is a problem with the programs we explored in the last chapter. The MarketPlace server, the RaceTrack server, and eChat are not persistent: once you shut them down they are gone forever. You can start up a new server with the same code, but it will not return to life with the same URI it had before. As a consequence, if you restart a server, you must redistribute the capability to access that server to all the users. This is a logistical nightmare. When we restart one of these servers, it must be able to restart with the same VatID and object IDs it had before.
If E simply allowed objects to remember their own URIs, there would be extensive opportunities for object forgery in the mobile code systems described in the next chapter. To prevent such forgeries, E uses swiss bases for persistence.
Swiss Bases
An Swiss Base is like the mythical numbered Swiss bank account. If you know the number you can get access. But in the instance of Swiss Bases it is the object but not an account you gain access to.
Example: Persistent eChat
#!/usr/bin/env rune
pragma.syntax("0.8")
# Copyright 2002 Combex, Inc. under the terms of the MIT X license
# found at http://www.opensource.org/licenses/mit-license.html ................
/**
* set up tracing; stub out all the printing for operational version
*/
def traceline(str) :void {
stderr.println(str)
}
# Ensure the user knows if he's using a clear, unencrypted connection
traceline(introducer.negotiable())
#def Title := if (introducer negotiable() == ["3DES_SDH_M"]) {
# "Secure EChat"
#} else {
# <swing:makeJOptionPane> showMessageDialog(
# null,
# "You are using DaffE, so you'll be chatting in the clear.
#To be secure, use E instead.",
# "Unencrypted DaffE Session",
# <swing:makeJOptionPane> WARNING_MESSAGE())
# "EChat"
#}
def Title := "eChat"
def chatReceiver
def sturdyChatReceiver
if (interp.getArgs() =~ [`-save`, filename]) {
throw("use persist-echat.e-awt")
} else if (interp.getArgs() =~ [`-restore`, filename]) {
throw("use persist-echat.e-awt")
} else {
traceline("once only incarnation")
introducer.onTheAir()
def [bind sturdyChatReceiver, _, _] :=
identityMgr.makeKnown(chatReceiver)
}
traceline(introducer)
traceline(sturdyChatReceiver)
/**
* return the object represented by the URI
*/
def getObjectFromURI(uri) :any {
introducer.sturdyFromURI(uri).getRcvr()
}
/**
* return the friend file
*/
def findFriendFile(chatWin) :any {
def dialog := <awt:makeFileDialog>(chatWin, "Select a Friend")
dialog.show()
var path := dialog.getFile()
if (path != null) {
path := dialog.getDirectory() + path
}
<file>[path]
}
/**
* return a file to be saved
*/
def requestSaveFile(chatWin) :any {
def dialog := <awt:makeFileDialog>(chatWin,
"Save File with Your Name",
<awt:makeFileDialog>.getSAVE())
dialog.show()
var addressName := dialog.getFile()
if (addressName != null) {
addressName := dialog.getDirectory() + addressName
}
<file>[addressName]
}
/**
* method that writes out the URI for your echat system's communication
* interface
*/
def offerMyAddress(file, uri) :void {
traceline(`$file setText("$uri")`)
file.setText(uri)
}
def set1LineComponentParameters(component) :void {
component.setPreferredSize(<awt:makeDimension>(150,25))
component.setMaximumSize(<awt:makeDimension>(1000,25))
component.setAlignmentX(0.5)
}
def chatUIMaker(chatController) :any {
# Lay out the chat window, create its components
def chatWin := <swing:makeJFrame>(Title)
def chatPane := chatWin.getContentPane()
def border := <swing:makeBoxLayout>(chatPane,1)
chatPane.setLayout(border)
traceline("p1 ui made");
def windowListener {
to windowClosing(event) :void {
chatController.leave()
traceline("trying to exit")
interp.continueAtTop()
}
match _ {}
}
chatWin.addWindowListener(windowListener)
traceline("p2 ui made");
/**
* make a button that calls the chatController
*/
def newButton(labelText, verb) :any {
# def button := <swing:makeJButton>(labelText)
def button := <swing:makeJButton>(labelText)
traceline("made button")
set1LineComponentParameters(button)
def buttonListener {
to actionPerformed(event) :void {
E.call(chatController, verb, [])
}
}
button.addActionListener(buttonListener)
traceline("button being returned")
button
}
# setNameButton
def setNameButton := newButton("Set Your Name", "setMyName")
# offerChatButton
def offerChatButton := newButton("Offer Chat", "offerSelf")
offerChatButton.setEnabled(false)
# findFriendButton
def findFriendButton := newButton("Find Friend", "findFriend")
findFriendButton.setEnabled(false)
# chatScroller that holds chatTextArea
def chatScroller := <swing:makeJScrollPane>()
chatScroller.setMaximumSize(<awt:makeDimension>(2000,1000))
chatScroller.setPreferredSize(<awt:makeDimension>(250,80))
# chatTextArea
def chatTextArea := <swing:makeJTextArea>()
chatTextArea.setLineWrap(true)
chatScroller.getViewport().add(chatTextArea)
# nextMessageBox
def nextMessageBox := <swing:makeJTextField>("Type your message here",30)
set1LineComponentParameters(nextMessageBox)
chatPane.add(nextMessageBox)
traceline("p3 ui buildt");
# sendMessageButton
def sendMessageButton := newButton("Send", "send")
sendMessageButton.setEnabled(false)
chatPane.add(JPanel`$setNameButton
$offerChatButton $findFriendButton
$chatScroller.Y
$nextMessageBox
$sendMessageButton`)
chatWin.pack()
chatWin.show()
def chatUI {
to getChatWin() :any { chatWin }
to getNameButton() :any { setNameButton }
to getOfferChatButton() :any { offerChatButton }
to getFindFriendButton() :any { findFriendButton }
to getChatTextArea() :any { chatTextArea }
to getNextMessageBox() :any { nextMessageBox }
to getSendMessageButton() :any { sendMessageButton }
}
}
/**
* facet of chatController sent to other chatter with only appropriate
* messages
*/
def chatReceiverMaker(var chatController) :any {
bind chatReceiver {
to receive(message) :void { chatController.receive(message) }
to receiveFriend(friend, name) :any {
chatController.receiveFriend(friend, name)
}
to friendIsLeaving() :void { chatController.friendIsLeaving() }
to revoke() :void { chatController := null }
}
}
/**
* @author Marc Stiegler
*/
def chatControllerMaker() :any {
def chatController := {
def chatUI := chatUIMaker(chatController)
def myChatReceiver := chatReceiverMaker(chatController)
var myName := null
var myFriend := null
var myFriendName := null
var myAddressFile := null
traceline("initialized chatController");
def showMessage(senderName, message) :void {
chatUI.getChatTextArea().append(
senderName +" says:\t"+ message + "\n")
}
def showDebug(message) :void {
# chatUI getChatTextArea() append("Debug: " + message + "\n")
}
def chatController {
/**
* transmitting functions
*/
to send() :void {
def nextMsgBox := chatUI.getNextMessageBox()
def nextMessage := nextMsgBox.getText()
nextMsgBox.setText("")
traceline("next message" + nextMessage)
myFriend <- receive(nextMessage)
showMessage(myName, nextMessage)
}
to setMyName() :void {
myName := <swing:makeJOptionPane>.showInputDialog(
"Please give me your name for this chat session")
traceline(`name: $myName`)
if (myName != null) {
chatUI.getNameButton().setLabel(myName)
chatUI.getNameButton().setEnabled(false)
chatUI.getOfferChatButton().setEnabled(true)
chatUI.getFindFriendButton().setEnabled(true)
}
}
to offerSelf() :void {
myAddressFile := requestSaveFile(chatUI.getChatWin())
if (myAddressFile != null) {
def uri := introducer.sturdyToURI(sturdyChatReceiver)
offerMyAddress(myAddressFile, uri)
}
}
to leave() :void {
if (myAddressFile != null) {
# myAddressFile delete(null)
}
myFriend <- friendIsLeaving()
chatController.disconnect("is being left")
}
to receive(message) :void {
showMessage(myFriendName, message)
}
to receiveFriend(friend, name) :any {
traceline("receiveFriend")
myFriend := friend
myFriendName := name
chatUI.getSendMessageButton().setEnabled(true)
chatUI.getOfferChatButton().setEnabled(false)
chatUI.getFindFriendButton().setEnabled(false)
chatUI.getChatTextArea().append(
myFriendName + " has arrived\n")
Ref.whenBroken(friend, def observer(prom) :void {
chatController.disconnect("disconnected")
})
traceline("received")
myName
}
to findFriend() :void {
def file := findFriendFile(chatUI.getChatWin())
if (file != null) {
def friendURI := file.getText()
showDebug("uri " + friendURI)
def friend := getObjectFromURI(friendURI)
showDebug("obj " + friend)
when (friend <- receiveFriend(myChatReceiver, myName)) ->
done(friendName) :void {
showDebug("won against all odds")
chatController.receiveFriend(friend, friendName)
} catch problem {
showDebug("clobbered: " + problem)
chatController.disconnect("is unreachable")
}
showDebug("sent me")
}
}
to friendIsLeaving() :void {
chatController.disconnect("is leaving")
}
to disconnect(desc) :void {
chatUI.getSendMessageButton().setEnabled(false)
if (myFriendName == null) {
myFriendName := "the friend"
}
chatUI.getChatTextArea().append(
myFriendName + " " + desc + "\n")
myFriend := null
myFriendName := null
myChatReceiver.revoke()
}
}
}
}
def controller := chatControllerMaker()
traceline(interp.getArgs())
interp.blockAtTop()
Next Section: Secure Mobile Code