[ Team LiB ] |
24.2 Creating the Server-Side ApplicationThe server-side portion of the video chat/message center application is contained within a single ASC file, main.asc. Here are the steps necessary to create the server-side part of this application:
The ASC file contains a lot of code, but fortunately, most of it is not very complex once you familiarize yourself with it. Let's look at some of the code with a little more explanation as to what is going on and why. The onConnect( ) method is a method that FlashCom automatically invokes when a new client connects to the application. FlashCom creates a new client object and passes a reference to the object as a parameter to the onConnect( ) method. In addition, we pass two custom parameters: a username and a password. The username is important because it helps the application keep track of what kinds of users are logged in (calling clients or an administrator). The password is null in the case of all calling clients, but it has the value of "adminPass" in the case of the administrator (this is something you will hardcode into the administrator client movie). The password is important because it helps to prevent a calling client from logging in with the username of "admin" (which is the username we use for the administrator). application.onConnect = function (newClient, username, password) { newClient.username = username; newClient.password = password; acceptClient(newClient); }; Analogous to the onConnect( ) method, the onDisconnect( ) method is invoked each time a client disconnects from the application. As with the onConnect( ) method, FlashCom passes a parameter to onDisconnect( ) that references the client who has just disconnected. The onDisconnect( ) method is important in this application only when the disconnecting client was on a live call. The server needs to know that the call has ended so it can alert the other client that the call has ended and can set the correct values for properties it uses to track the call status. When the administrator is online, the application keeps track of the administrator using a property named admin. And when a call is in progress, the calling client object is stored as a property named callingClient. See the acceptClient( ) function for more on these two properties. Therefore, if the disconnecting client happens to be the same client that is stored as the calling client, set the calling client to null (since there is no longer a calling client connected) and invoke a method on the administrator client to tell it that the call has ended. Alternatively, if the disconnecting client is the administrator, invoke a method on any calling client to let it know that the call has ended. Also, it is important to set callingClient to null and delete the admin property so that the application knows who is logged in and what the call status is. application.onDisconnect = function (disconnectClient) { if (application.callingClient == disconnectClient) { application.callingClient = null; if (application.admin != undefined) { application.admin.call("incomingCallEnd", null); } } if (application.admin = disconnectClient) { if (application.callingClient != null) { application.callingClient.call("adminEndCall", null); } application.callingClient = null; delete application.admin; } }; The onAppStart( ) method is automatically invoked once when the application starts. So this is where you should place actions that should occur only once. Initialize the callingClient property to null (since there is no call in progress when the application is first started) and get a remote shared object for the application to store information about messages left for the administrator. If the shared object has not been created (the first time the application runs), initialize a messageNum property, which the application uses to make sure each message is assigned a unique ID. application.onAppStart = function ( ) { application.callingClient = null; application.messagesSO = SharedObject.get("messages", true); if (application.messagesSO.getProperty("messageNum") == undefined) { application.messagesSO.setProperty("messageNum", 0); } }; The acceptClient( ) function is invoked by the onConnect( ) method every time a new client connects to the application. You should make sure that the client has not tried to log in with the username "admin", unless it is accompanied by the password "adminPass". The calling clients are not asked for a password when they log in, so the password will be undefined. The administrator password is hardcoded into the administrator client movie. So if a calling client tries to log in with the username "admin", reject the connection and exit from the function. Otherwise, accept the connection and assign methods to the client object. If the client is the administrator, also assign some administrator-only methods to the object and assign the client object reference to the admin property. The admin property does two things. First, it lets the application know that the administrator is online (so users can place calls). Second, it gives you a convenient way to invoke methods on the administrator client throughout the server-side code. function acceptClient (newClient) { if (newClient.username == "admin" && newClient.password != "adminPass") { application.rejectConnection(newClient); return; } application.acceptConnection(newClient); newClient.recordMessageInfo = recordMessageInfo; newClient.getMessageID = getMessageID; newClient.placeCall = placeCall; newClient.endCall = endCall; if (newClient.username == "admin") { application.admin = newClient; newClient.acceptIncomingCall = acceptIncomingCall; newClient.sendToLeaveMessage = sendToLeaveMessage; newClient.removeMessage = removeMessage; } } The recordMessageInfo( ) function is assigned as a method of client objects, and it is invoked when the calling client leaves a message. Although the video and audio portion of the message is published completely from the client, this server-side function records information about the message into a remote shared object. This is important because it allows the administrator to retrieve a list of messages. Each entry in the shared object contains the unique message ID, the username of the client leaving the message, and the date and time when the message was recorded. function recordMessageInfo (id) { var messages = application.messagesSO.getProperty("messages"); if (messages == undefined) { messages = new Array( ); } var infoObj = {id: id, username: this.username, dateTime: new Date( )}; messages.push(infoObj); application.messagesSO.setProperty("messages", messages); application.messagesSO.flush( ); } The removeMessage( ) function is a method of the administrator client object, and it removes a data stream (the FLV file) from the server when the administrator chooses that option. The client passes the name of the stream to this method and, using the Stream.get( ) method, retrieves a server-side reference to the stream. Then the clear( ) method removes the stream from the server. However, you also need to remove the message information from the shared object so that it no longer appears in the administrator's list of messages. Do this by looping through all the elements of the messages array until you find the matching entry. Then use the splice( ) method to remove that element, break out of the for loop, and save the updated information back to the shared object. function removeMessage (streamName) { var messageStream = Stream.get(streamName); messageStream.clear( ); var messages = application.messagesSO.getProperty("messages"); for (var i = 0; i < messages.length; i++) { if ("message" + messages[i].id == streamName) { messages.splice(i, 1); break; } } application.messagesSO.setProperty("messages", messages); application.messagesSO.flush( ); } |
[ Team LiB ] |