Walnut/Persistent Secure Distributed Computing

From Erights

Revision as of 04:03, 5 March 2008 by Zarutian (Talk)
Jump to: navigation, search


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

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

Personal tools
more tools