Upload
barnard-cooper
View
222
Download
1
Embed Size (px)
DESCRIPTION
Programming Flash Communication Server Brian Lesser/Flash in the Can/April 3, 2004/ 3 Credit Where it is Due! Use Macromedia’s v2 components Heavily influenced by Macromedia’s Communication Components Different set of assumptions: –Always authenticate users. –Started as simply as possible – no framework. –Eventually built rudimentary framework to simplify code, provide common services, and provide security. –Do not need automagic creation of server-side objects.
Citation preview
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 1
Designing Real-Time Applications
Modular, Robust, Secure, and Scalable Flash Communication
Applications
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 2
Modular and Robust Applications• Cohesive loosely coupled components
– Module: Flash Component + Server-Side Object• Cohesive:
– Completely manage all streams, shared objects, and remote methods needed by the component.
– Inlcudes: model, view, and controller.– Reusable in many different applications.
• Loosely Coupled:– Can exist without most other components– Can make available public read only model to other
components (Status and PeopleList)
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 3
Credit Where it is Due!• Use Macromedia’s v2 components• Heavily influenced by Macromedia’s
Communication Components• Different set of assumptions:
– Always authenticate users.– Started as simply as possible – no framework.– Eventually built rudimentary framework to simplify
code, provide common services, and provide security.
– Do not need automagic creation of server-side objects.
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 4
Component-Based Sample Application
• People List – list of connected users• Status – allow each user to indicate
busy, away, offline, online• Shared Text – common meeting notes• Text Chat• Video Conference
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 5
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 6
Shared Text Component in Depth
• Events and data management• Server-side SharedText Class• Client-side SharedText v2 based Component
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 7
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 8
Slot Name Slot ValuecurrentUser “”length 0
blesser:peldi:
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 9
Slot Name Slot ValuecurrentUser “blesser”length 0
blesser:peldi:
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 10
Slot Name Slot ValuecurrentUser “blesser”length 11 “Agenda:
1. Introductions”
Note: All slot names are strings. Even slot names like 1 are string values.
blesser:peldi:
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 11
Slot Name Slot ValuecurrentUser “”length 11 “Agenda:
1. Introductions”
Note: All slot names are strings. Even slot names like 1 are string values.
blesser:peldi:
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 12
Slot Name Slot ValuecurrentUser “peldi”length 11 “Agenda:
1. Introductions”
Note: All slot names are strings. Even slot names like 1 are string values.
blesser:peldi:
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 13
Slot Name Slot ValuecurrentUser “peldi”length 21 “Agenda:
1. Introductions”2 “Agenda:
1. Introductions2. Project
Requirements”Note: All slot names are strings. Even slot names like 1 are string values.
blesser:peldi:
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 14
Slot Name Slot ValuecurrentUser “”length 21 “Agenda:
1. Introductions”2 “Agenda:
1. Introductions2. Project
Requirements”Note: All slot names are strings. Even slot names like 1 are string values.
blesser:peldi:
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 15
Client ServerSharedTextComponent
messagesShared Object
SharedTextComponentclient
messagesShared Object
ClientSharedTextComponent
messagesShared Object
nc.call("edit");
edit(userName)
setProperty("curentUser", userName)
data copied to client's copy of the shared object
data copied to client's copy of the shared object
onSync(ev)
onSync(list)onSync(ev)
onSync(list)
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 16
Server-Side SharedText Class
• Multiple SharedText objects can be created.
• Each has its own namespace.– pfcs/SharedText/main – pfcs/SharedText/breakout1– pfcs/SharedText/breakout2
• Format:– pfcs/ComponentClassName/name
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 17
The main.asc file - 1load("TextChat.asc");load("SharedText.asc");load("Status.asc");load("PeopleList.asc");
application.onAppStart = function(){ userList_so = SharedObject.get("private/userList"); sharedText = new SharedText("main"); textChat = new TextChat("main"); status = new Status("main"); peopleList = new PeopleList("main");}
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 18
The main.asc file - 2application.onConnect = function(client, user){ // authentication code removed... client.pfcs = {user:user}; client.pfcs.user.arrival = new Date(); client.readAccess = "pfcs/"; client.writeAccess = "pfcs/"; peopleList.addClient(client); status.addClient(client); textChat.addClient(client); sharedText.addClient(client); userList_so.setProperty(client.pfcs.user.userName, client); return true;}
application.onDisconnect = function(client){ sharedText.removeClient(client); textChat.removeClient(client); status.removeClient(client); peopleList.removeClient(client); userList_so.setProperty(client.pfcs.user.userName, null);}
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 19
/** * SharedText constructor is passed it's name. The default is main. * All component resources exist in the namespace: * pfcs/SharedText/name/ * Gets and initializes the pfcs/SharedText/name/messages so. */function SharedText(name){ this.name = name; if (!name) this.name = "main"; this.path = "pfcs/" + this.className + "/" + name; this.so = SharedObject.get(this.path + "/messages", true); this.so.ready = false; this.so.onSync = function(){ var currentUser = this.getProperty("currentUser"); if (currentUser != "") this.setProperty("currentUser", ""); } this.so.setProperty("currentUser", ""); if (typeof this.so.getProperty("length") != "number") { this.so.setProperty("length", 0); } } SharedText.prototype.className = "SharedText";
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 20
/** * Adds an object path to a client object. For example if the * path is "pfcs/SharedText/main" then the client will * have the following objects added if they do not already * exist: * client.pfcs * client.pfcs.SharedText * client.pfcs.SharedText.main */SharedText.prototype.addObjectPath = function(client){ var pathArray = this.path.split("/"); var obj = client; var name; for (var i = 0; i < pathArray.length; i++){ name = pathArray[i]; if (! obj[name]){ obj[name] = {}; } obj = obj[name]; }}
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 21
/** addClient(client) is called whenever a client needs to connect * to the shared text component. If there is only one shared text * component this is likely called when each client connects * to an instance. */SharedText.prototype.addClient = function(client){ this.addObjectPath(client); var thisComponent = this; client.pfcs[this.className][this.name].edit = function(){ thisComponent.edit(client.pfcs.user.userName); }}
/** removeClient(client) is called whenever a client no longer * needs the shared text component. If there is only one shared * text component this is likely called when each client * disconnects from an instance. */SharedText.prototype.removeClient = function(client){ var currentUser = this.so.getProperty("currentUser"); if (client.pfcs.user.userName == currentUser) { this.so.setProperty("currentUser", ""); } delete client.pfcs[this.className][this.name];}
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 22
/** * edit(userName) is called by a client to get or release control * of the shared text component. The messages shared object * currentUser slot may have one of three values. It can be * empty, contain someone else's user name or contain * the userName of the person calling this method. */SharedText.prototype.edit = function(userName){ var currentUser = this.so.getProperty("currentUser"); if (userName == currentUser) this.so.setProperty("currentUser", ""); else if (currentUser != "") return; else this.so.setProperty("currentUser", userName);}
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 23
Client-Side Shared Text Component
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 24
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 25
The SharedText.as fileimport mx.controls.NumericStepper;import mx.controls.Button;import mx.controls.TextArea;import mx.controls.Label;
class SharedText extends mx.core.UIComponent { var className:String = "SharedText"; static var symbolName:String = "SharedText"; static var symbolOwner:Object = SharedText;
//…
}
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 26
function createChildren() { var depth = 100; var instance = this; createObject("TextArea", "sharedTextArea", depth++); createObject("NumericStepper", "versionStepper", depth++); createObject("Button", "editButton", depth++); createObject("Button", "sendButton", depth++); createObject("Button", "selectButton", depth++); createObject("Button", "deleteButton", depth++); createObject("Label", "versionLabel", depth++); versionLabel.html = true; versionLabel.text = "<B>Version:</B>"; //…
editButton.addEventListener("click", this); sendButton.addEventListener("click", this); selectButton.addEventListener("click", this); deleteButton.addEventListener("click", this); versionStepper.addEventListener("change", this);}
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 27
var path:String = "pfcs/SharedText/main/";
function edit(ev) { __nc.call(path + "edit", null) if (ev.target.label == "Cancel") { replaceSharedText(); }}
function click(ev) { switch (ev.target) { case editButton : edit(ev); break; case sendButton : shareText(ev); break; case selectButton : selectText(ev); break; case deleteButton : deleteVersion(ev); break; }}
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 28
function onSync(ev) { if (ev.list.length == 0 && messages.data.length > 0){ replaceSharedText(); updateButtons(); return; } var info; for (var i in ev.list) { info = ev.list[i]; if (info.name == "length") { replaceSharedText(); } else if (info.name == "currentUser") { updateButtons(); } else if (info.name == "selectCount") { showSelection(); } }}
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 29
function replaceSharedText(ev) { var len = messages.data.length; if (len == 0) { sharedTextArea.text = ""; versionStepper.minimum = 0; versionStepper.maximum = 0; versionStepper.value = 0; return; } sharedTextArea.text = messages.data[len]; versionStepper.minimum = 1; versionStepper.maximum = len; versionStepper.value = len;}
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 30
function updateButtons() { var currentUser = messages.data.currentUser; if (currentUser == "" && __user) { editButton.enabled = true; editButton.selected = false; editButton.label = "Edit"; sendButton.enabled = false; sendButton.selected = false; selectButton.enabled = false; selectButton.selected = false; deleteButton.enabled = false; deleteButton.selected = false; sharedTextArea.editable = false; } else if (currentUser == __user.userName && __user) { editButton.enabled = true; //… } else { editButton.selected = false; //… }}
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 31
function shareText(ev) { var len = messages.data.length; if (messages.data[len] == sharedTextArea.text) { return; } len++; messages.setFPS(0); messages.data.length = len; messages.data[len] = sharedTextArea.text; messages.setFPS(12); }
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 32
Communication “Components”• Problem: components modularize
applications but can act as isolated “mini applications.”
• Solution: component interactions:– Provide model and/or view to other components– Provide controller on both client and server – Broadcast events
• Examples:– PeopleList and Status Component– PeopleGrid and Status, Pace, and Question
Components
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 33
PeopleList/Status Example• PeopleList component maintains its own
peopleList shared object mapping user names to user information.
• PeopleList can be used without the Status component.
• Status component maintains a shared object that maps user names to user connection status.
• Status component exposes the statusList shared object to the PeopleList.
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 34
Client ServerPeopleListComponent
statusListShared Object
StatusComponent
statusListShared Object
StatusComponent
onSync(list)
addClient(client)setProperty(userName,...)
setProperty(userName,...)
onSync(list)
onSync(list)
removeClient()
setStatus(status)
setProperty(userName,...)
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 35
function clone(orig) { var copy = {}; for (var p in orig) { copy[p] = orig[p]; } return copy; }
function onSync(ev){ // Get the list's dataProvider and truncate it. var dp = list.dataProvider; dp.length = 0; // Fill the dataProvider using an Array method. for (var p in __peopleList.data) { var obj = clone(__peopleList.data[p]); var status = __statusList.data[p]; if (status) { obj.status = status; // Skip this record to make a person disappear from the list if (__hideOfflineUsers && obj.status == "Offline") continue; } dp.push({label:p, data:obj}); } dp.dispatchEvent({target:dp, type:"modelChanged"}); }
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 36
Designing Secure Applications
• Authentication Components and Subclasses were not available in Macromedia’s component set
• Macromedia’s components used a root level namespace making their resources impossible to protect without altering code
• No provision for role-based access controls
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 37
Server-side Authenticationapplication methods:
• onConnect (client, credentials);– Handle different types of clients: SWF and FCS instances– Handle different credentials: guests on a local database
and enterprise users on a directory service– Standard method provided in FCS
• onAuthenticate (client, credentials);– Once you know who someone is you may want to use
different methods to authorize their connection– Non-standard application method
• onAuthorize (client, credentials);– Additional tests and post connection work– Non-standard application method
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 38
// Load the component manager and base class.load("ComponentManager.asc");load("Component.asc");
// Load the authentication and authorization object.load("Auth.asc");
// Create Auth object and componentsauth = new Auth("http://myhost.xxx/flashservices/gateway", "authDir.services.authService");cManager = new ComponentManager();
application.onConnect = function client(client, credentials){ return auth.authenticate(client, credentials);}
application.onAuthenticate = function(client, credentials){ auth.authorize(client, credentials);}
application.onAuthorize = function(client, credentials){ this.acceptConnection(client); cManager.addClient(client);}
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 39
Role-based Access• Each component has its own namespace:
– pfcs/SharedText/main – pfcs/SharedText/breakout1– pfcs/SharedText/breakout2
• Client read and write access strings:client.readAccess = “pfcs/SharedText/main; pfcs/TextChat/main/messages;pfcs/PeopleList/main”client.writeAccess = “pfcs/SharedText/main”
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 40
function Component(name){}
Component.prototype.className = "Component";
Component.prototype.addClient = function(client){ // Reject banned clients // Get list of matching user roles and extract permissions // Let subclass take it from there}
Component.prototype.removeClient = function(client){ // Remove access to this component's resources from client // Let subclass do more...}
Component.prototype.addBannedUsers = function(userHash){}
Component.prototype.clientInRoles = function(client){}
Component.prototype.addClientPath = function(path, permissions){}
Component.prototype.removeClientPath = function(path){}
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 41
Scalable Applications• Single-server multi-instance
applications• Multi-server lobby and rooms• Instance trees and components• Using Application Servers to bridge
applications and instances
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 42
Best Case: One way “Broadcast” Stream
12 Streams from server to clients.
3 Streams from root server to leaf servers.
4 Streams from leaf server to SWFs.
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 43
Worst Case: Video Conference
Each leaf sends 4 streams to the root and receives 8.Root server handles 36 streams.
Each leaf server handles 12 streams to/from the root, 4 incoming client streams, and 44 streams to clients. Total: 60.
12 Clients, each client sends one stream and receives 11.Server handles 144 Streams (12 + 11 * 12).
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 44
Three Part Components• Flash UI Component
– Connects to leaf server• Server-side leaf object
– Connects to root server and establishes any required proxies
– Adds/removes clients• Server-side root object
– Adds/removes only leaf object clients
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 45
Flash
Application Server
Database
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 46
Flash
Application Server
Database
FCS
Programming Flash Communication Server
Brian Lesser/Flash in the Can/April 3, 2004/ 47
References• flash-communications.net• flash-communications.net/technotes/fitc2004/• echo.ryerson.ca
Not do
ne ye
t!