Changeset View
Changeset View
Standalone View
Standalone View
support/aphlict/client/src/AphlictMaster.as
| Show All 34 Lines | final public class AphlictMaster extends Aphlict { | ||||
| */ | */ | ||||
| private var remoteServer:String; | private var remoteServer:String; | ||||
| /** | /** | ||||
| * The port number for the Aphlict Server. | * The port number for the Aphlict Server. | ||||
| */ | */ | ||||
| private var remotePort:Number; | private var remotePort:Number; | ||||
| /** | |||||
| * A dictionary mapping PHID to subscribed clients. | |||||
| */ | |||||
| private var subscriptions:Dictionary; | |||||
| private var socket:Socket; | private var socket:Socket; | ||||
| private var readBuffer:ByteArray; | private var readBuffer:ByteArray; | ||||
| public function AphlictMaster(server:String, port:Number) { | public function AphlictMaster(server:String, port:Number) { | ||||
| super(); | super(); | ||||
| this.remoteServer = server; | this.remoteServer = server; | ||||
| this.remotePort = port; | this.remotePort = port; | ||||
| this.clients = new Dictionary(); | |||||
| this.subscriptions = new Dictionary(); | |||||
| // Connect to the Aphlict Server. | // Connect to the Aphlict Server. | ||||
| this.recv.connect('aphlict_master'); | this.recv.connect('aphlict_master'); | ||||
| this.connectToServer(); | this.connectToServer(); | ||||
| this.clients = new Dictionary(); | |||||
| // Start a timer and regularly purge dead clients. | // Start a timer and regularly purge dead clients. | ||||
epriestley: These should probably be initialized before we connect to anything. | |||||
| this.timer = new Timer(AphlictMaster.PURGE_INTERVAL); | this.timer = new Timer(AphlictMaster.PURGE_INTERVAL); | ||||
| this.timer.addEventListener(TimerEvent.TIMER, this.purgeClients); | this.timer.addEventListener(TimerEvent.TIMER, this.purgeClients); | ||||
| this.timer.start(); | this.timer.start(); | ||||
| } | } | ||||
| /** | /** | ||||
| * Register a @{class:AphlictClient}. | * Register a @{class:AphlictClient}. | ||||
| */ | */ | ||||
| ▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | private function connectToServer():void { | ||||
| socket.connect(this.remoteServer, this.remotePort); | socket.connect(this.remoteServer, this.remotePort); | ||||
| this.readBuffer = new ByteArray(); | this.readBuffer = new ByteArray(); | ||||
| this.socket = socket; | this.socket = socket; | ||||
| } | } | ||||
| private function didConnectSocket(event:Event):void { | private function didConnectSocket(event:Event):void { | ||||
| this.externalInvoke('connected'); | this.externalInvoke('connected'); | ||||
| // Send subscriptions | |||||
| var phids = new Array(); | |||||
| for (var phid:String in this.subscriptions) { | |||||
| phids.push(phid); | |||||
| } | |||||
| if (phids.length) { | |||||
| this.sendSubscribeCommand(phids); | |||||
| } | |||||
| } | } | ||||
| private function didCloseSocket(event:Event):void { | private function didCloseSocket(event:Event):void { | ||||
Not Done Inline ActionsWe should probably check for phids.length before sending this. Also, all the "subscribe" stuff could go in a separate method. epriestley: We should probably check for `phids.length` before sending this. Also, all the "subscribe"… | |||||
| this.externalInvoke('close'); | this.externalInvoke('close'); | ||||
| } | } | ||||
| private function didIOErrorSocket(event:IOErrorEvent):void { | private function didIOErrorSocket(event:IOErrorEvent):void { | ||||
| this.externalInvoke('error', event.text); | this.externalInvoke('error', event.text); | ||||
| } | } | ||||
| private function didSecurityErrorSocket(event:SecurityErrorEvent):void { | private function didSecurityErrorSocket(event:SecurityErrorEvent):void { | ||||
| this.externalInvoke('error', event.text); | this.externalInvoke('error', event.text); | ||||
| } | } | ||||
| public function subscribe(client:String, phids:Array):void { | |||||
| var newPHIDs = new Array(); | |||||
| for (var i:String in phids) { | |||||
| var phid = phids[i]; | |||||
| if (!this.subscriptions[phid]) { | |||||
| this.subscriptions[phid] = new Dictionary(); | |||||
| newPHIDs.push(phid); | |||||
| } | |||||
| this.subscriptions[phid][client] = true; | |||||
| } | |||||
Not Done Inline ActionsProbably needs newPHIDs.length. epriestley: Probably needs `newPHIDs.length`. | |||||
| if (newPHIDs.length) { | |||||
| this.sendSubscribeCommand(newPHIDs); | |||||
| } | |||||
| } | |||||
| public function unsubscribe(client:String, phids:Array):void { | |||||
| var oldPHIDs = new Array(); | |||||
Not Done Inline Actionsthis.socket may not exist yet or may not be connected yet. We should set some "connected" flag in didConnectSocket() and only send this if newPHIDs.length && this.isConnected. epriestley: `this.socket` may not exist yet or may not be connected yet. We should set some "connected"… | |||||
| for (var phid:String in phids) { | |||||
| if (!this.subscriptions[phid]) { | |||||
| continue; | |||||
| } | |||||
| delete this.subscriptions[phid][client]; | |||||
| var empty = true; | |||||
| for (var key:String in this.subscriptions[phid]) { | |||||
| empty = false; | |||||
| } | |||||
| if (empty) { | |||||
| delete this.subscriptions[phid]; | |||||
| oldPHIDs.push(phid); | |||||
| } | |||||
| } | |||||
Not Done Inline ActionsLikewise. epriestley: Likewise. | |||||
| if (oldPHIDs.length) { | |||||
| this.sendUnsubscribeCommand(oldPHIDs); | |||||
| } | |||||
| } | |||||
| private function sendSubscribeCommand(phids:Array):void { | |||||
| var msg:Dictionary = new Dictionary(); | |||||
| msg['command'] = 'subscribe'; | |||||
| msg['data'] = phids; | |||||
| this.log('Sending subscribe command to server.'); | |||||
| this.socket.writeUTF(vegas.strings.JSON.serialize(msg)); | |||||
| this.socket.flush(); | |||||
Not Done Inline ActionsSame as above. epriestley: Same as above. | |||||
| } | |||||
| private function sendUnsubscribeCommand(phids:Array):void { | |||||
| var msg:Dictionary = new Dictionary(); | |||||
| msg['command'] = 'unsubscribe'; | |||||
| msg['data'] = phids; | |||||
| this.log('Sending subscribe command to server.'); | |||||
| this.socket.writeUTF(vegas.strings.JSON.serialize(msg)); | |||||
| this.socket.flush(); | |||||
| } | |||||
| private function didReceiveSocket(event:Event):void { | private function didReceiveSocket(event:Event):void { | ||||
| try { | try { | ||||
| var b:ByteArray = this.readBuffer; | var b:ByteArray = this.readBuffer; | ||||
| this.socket.readBytes(b, b.length); | this.socket.readBytes(b, b.length); | ||||
| do { | do { | ||||
| b = this.readBuffer; | b = this.readBuffer; | ||||
| b.position = 0; | b.position = 0; | ||||
| if (b.length <= 8) { | if (b.length <= 8) { | ||||
| break; | break; | ||||
| } | } | ||||
| var msg_len:Number = parseInt(b.readUTFBytes(8), 10); | var msg_len:Number = parseInt(b.readUTFBytes(8), 10); | ||||
| if (b.length >= msg_len + 8) { | if (b.length >= msg_len + 8) { | ||||
| var bytes:String = b.readUTFBytes(msg_len); | var bytes:String = b.readUTFBytes(msg_len); | ||||
| var data:Object = vegas.strings.JSON.deserialize(bytes); | var data:Object = vegas.strings.JSON.deserialize(bytes); | ||||
| var t:ByteArray = new ByteArray(); | var t:ByteArray = new ByteArray(); | ||||
| t.writeBytes(b, msg_len + 8); | t.writeBytes(b, msg_len + 8); | ||||
| this.readBuffer = t; | this.readBuffer = t; | ||||
| // Send the message to all clients. | // Send the message to all clients. | ||||
| for (var client:String in this.clients) { | for (var client:String in this.clients) { | ||||
| var subscribed = false; | |||||
| for (var i:String in data.subscribers) { | |||||
Not Done Inline Actionsthis.subscriptions[phid] might be undefined, so this could throw when accessing [client], I think. epriestley: `this.subscriptions[phid]` might be `undefined`, so this could throw when accessing `[client]`… | |||||
| var phid = data.subscribers[i]; | |||||
| if (this.subscriptions[phid] && | |||||
| this.subscriptions[phid][client]) { | |||||
| subscribed = true; | |||||
| break; | |||||
| } | |||||
| } | |||||
| if (subscribed) { | |||||
| this.log('Sending message to client: ' + client); | this.log('Sending message to client: ' + client); | ||||
| this.send.send(client, 'receiveMessage', data); | this.send.send(client, 'receiveMessage', data); | ||||
| } | } | ||||
| } | |||||
| } else { | } else { | ||||
| break; | break; | ||||
| } | } | ||||
| } while (true); | } while (true); | ||||
| } catch (err:Error) { | } catch (err:Error) { | ||||
| this.error(err); | this.error(err); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
These should probably be initialized before we connect to anything.