/** * Creates a new BNSService * * @param bnsNode * The Node that the BNS is on * @//throws JCSPNetworkException * Thrown if something goes wrong in the underlying architecture */ public BNSService(NodeID bnsNode) // //throws JCSPNetworkException { // Create input and output end this.toBNS = NetChannel.one2net(bnsNode, 2, new BNSNetworkMessageFilter.FilterTX()); this.fromBNS = NetChannel.net2one(new BNSNetworkMessageFilter.FilterRX()); // Logon to the BNS BNSMessage message = new BNSMessage(); message.type = BNSMessageProtocol.LOGON_MESSAGE; message.serviceLocation = (NetChannelLocation)this.fromBNS.getLocation(); this.toBNS.write(message); // Wait for logon reply message BNSMessage logonReply = (BNSMessage)this.fromBNS.read(); // Check if we logged on OK if (logonReply.success == false) { Node.err.log(this.GetType(), "Failed to logon to BNS"); throw new JCSPNetworkException("Failed to logon to BNS"); } Node.log.log(this.GetType(), "Logged into BNS"); }
/** * Resolves a name on the BNS, retrieving the NetBarrierLocation for the NetBarrier * * @param name * The name to resolve from the BNS * @return The NetBarrierLocation of the NetBarrier declared with name * @//throws JCSPNetworkException * Thrown if something goes wrong in the underlying architecture */ public NetBarrierLocation resolve(String name) // //throws JCSPNetworkException { // Create a temporary channel to receive the incoming NetBarrierLocation NetChannelInput responseChan = NetChannel.net2one(new BNSNetworkMessageFilter.FilterRX()); // Create the resolution message BNSMessage message = new BNSMessage(); message.type = BNSMessageProtocol.RESOLVE_REQUEST; message.serviceLocation = (NetChannelLocation)responseChan.getLocation(); message.name = name; // Write resolution message to the BNS this.toBNS.write(message); // Read in reply BNSMessage reply = (BNSMessage)responseChan.read(); // Destroy temporary channel responseChan.destroy(); // Return result if (reply.success) { return(reply.location); } throw new JCSPNetworkException("Failed to resolve barrier named: " + name); }
/** * Decodes a byte array back into a BNSMessage * * @param bytes * The bytes to convert back into a BNSMessage * @return The recreated BNSMessage * @//throws IOException * Thrown if something goes wrong during the recreation */ public Object filterRX(byte[] bytes) ////throws IOException { this.byteIn = new MemoryStream(bytes); this.dis = new BinaryReader(byteIn); // Recreate the message BNSMessage msg = new BNSMessage(); msg.type = this.dis.ReadByte(); msg.success = this.dis.ReadBoolean(); msg.serviceLocation = NetChannelLocation.parse(this.dis.ReadString()); msg.location = NetBarrierLocation.parse(this.dis.ReadString()); msg.name = this.dis.ReadString(); return(msg); }
/** * Registers a Server end of a NetBarrier with the BNS * * @param name * Name to register with BNS * @param bar * Barrier to register * @return True if the name was registered successfully, false otherwise */ public Boolean register(String name, NetBarrier bar) { // Ensure only one registration can happen at a time lock (this) { // Create a new registration message BNSMessage message = new BNSMessage(); message.type = BNSMessageProtocol.REGISTER_REQUEST; message.name = name; message.serviceLocation = (NetChannelLocation)this.fromBNS.getLocation(); message.location = (NetBarrierLocation)bar.getLocation(); // Write registration message to the BNS this.toBNS.write(message); // Read in reply BNSMessage reply = (BNSMessage)this.fromBNS.read(); return(reply.success); } }
/** * Converts a BNSMessage into bytes * * @param obj * A BNSMessage to convert * @return the byte equivalent of the BNSMessage * @//throws IOException * Thrown if something goes wrong during the conversion */ public byte[] filterTX(Object obj) ////throws IOException { // First ensure we have a BNSMessage if (!(obj is BNSMessage)) { throw new IOException("Attempted to send a non BNSMessage on a BNSMessage channel"); } BNSMessage msg = (BNSMessage)obj; // Now reset the byte stream //this.baos.reset(); this.baos.Dispose(); // Write the parts of the BNSMessage to the stream this.dos.Write(msg.type); this.dos.Write(msg.success); if (msg.serviceLocation != null) { this.dos.Write(msg.serviceLocation.ToString()); } else { this.dos.Write("null"); } if (msg.location != null) { this.dos.Write(msg.location.toString()); } else { this.dos.Write("null"); } this.dos.Write(msg.name); // flush the stream this.dos.Flush(); // Get the bytes return(this.baos.ToArray()); }
/** * The run method for the BNS process */ public void run() { // Create the channel to receive incoming messages on. The index is 2. NetAltingChannelInput In = NetChannel.numberedNet2One(2, new BNSNetworkMessageFilter.FilterRX()); // We now wish to alternate upon this channel and the link lost channel Alternative alt = new Alternative(new Guard[] { this.lostLink, In }); // Loop forever while (true) { // Select next available Guard. Give priority to link failure switch (alt.priSelect()) { // We have lost the connection to a Node case 0: // Read in the NodeID of the lost Node NodeID lostNode = (NodeID)this.lostLink.read(); // Log loss of connection Node.log.log(this.GetType(), "Lost Link to: " + lostNode.toString()); // Remove the logged client this.loggedClients.Remove(lostNode); // Next get the ArrayList of any barriers registered by that Node ArrayList registeredBars = (ArrayList)this.barrierRegister[lostNode]; // If this ArrayList is null, we have no registrations if (registeredBars != null) { // There are registered barriers // Remove the list from the Hashmap this.barrierRegister.Remove(lostNode); // Now remove all the barriers registered by the Node for (IEnumerator enumerator = registeredBars.GetEnumerator(); enumerator.MoveNext();) { String toRemove = (String)enumerator.Current; this.registeredBarriers.Remove(toRemove); Node.log.log(this.GetType(), toRemove + " deregistered"); } } break; // We have received a new incoming message case 1: { // Read in the message BNSMessage message = (BNSMessage)In.read(); // Now behave based on the type of the message switch (message.type) { // We have received a logon message case BNSMessageProtocol.LOGON_MESSAGE: { // Log the logon attempt Node.log.log(this.GetType(), "Logon received from: " + message.serviceLocation.getNodeID().toString()); // try-catch loop. We don't want the BNS to fail try { // Check if the node is already logged on NetChannelOutput Out = (NetChannelOutput)this.loggedClients[message.serviceLocation.getNodeID()]; // If out is null, no previous logon received if (Out != null) { // This Node is already logged on. Send fail message // Log failed attempt Node.err.log(this.GetType(), message.serviceLocation.getNodeID().toString() + " already logged on. Rejecting"); // Create reply channel to the Node NetChannelOutput toNewRegister = NetChannel.one2net(message.serviceLocation, new BNSNetworkMessageFilter.FilterTX()); // Create the reply message BNSMessage reply = new BNSMessage(); reply.type = BNSMessageProtocol.LOGON_REPLY_MESSAGE; reply.success = false; // Asynchronously write to Node. We don't want the BNS to block toNewRegister.asyncWrite(reply); // Destroy the temporary channel toNewRegister.destroy(); } else { // Node hasn't previously registered // Log registration Node.log.log(this.GetType(), message.serviceLocation.getNodeID().toString() + " successfully logged on"); // Create the reply channel NetChannelOutput toNewRegister = NetChannel.one2net(message.serviceLocation, new BNSNetworkMessageFilter.FilterTX()); // Add the Node and reply channel to the logged clients map this.loggedClients.Add(message.serviceLocation.getNodeID(), toNewRegister); // Create a reply message BNSMessage reply = new BNSMessage(); reply.type = BNSMessageProtocol.LOGON_REPLY_MESSAGE; reply.success = true; // Write reply asynchronously to the logging on Node toNewRegister.asyncWrite(reply); } } catch (JCSPNetworkException jne) { // Catch any JCSPNetworkException. We don't let the BNS go down } break; } // A Node is attempting to register a Barrier case BNSMessageProtocol.REGISTER_REQUEST: { // Log registration attempt Node.log.log(this.GetType(), "Registeration for " + message.name + " received"); // Catch any JCSPNetworkException try { // Get the reply channel from our logged clients map NetChannelOutput Out = (NetChannelOutput)this.loggedClients[message.serviceLocation.getNodeID()]; // Check if the Node has logged on with us if (Out == null) { // The Node is not logged on. Send failure message Node.err.log(this.GetType(), "Registration failed. " + message.serviceLocation.getNodeID() + " not logged on"); // Create the channel to reply to Out = NetChannel.one2net(message.serviceLocation, new BNSNetworkMessageFilter.FilterTX()); // Create the reply message BNSMessage reply = new BNSMessage(); reply.type = BNSMessageProtocol.REGISTER_REPLY; reply.success = false; // Write message asynchronously to the Node Out.asyncWrite(reply); // Destroy the temporary channel Out.destroy(); } // The Node is registered. Now check if the name is else if (this.registeredBarriers.ContainsKey(message.name)) { // The name is already registered. Inform the register // Log the failed registration Node.err.log(this.GetType(), "Registration failed. " + message.name + " already registered"); // Create reply message BNSMessage reply = new BNSMessage(); reply.type = BNSMessageProtocol.RESOLVE_REPLY; reply.success = false; // Write the reply asynchronously. Do not block the BNS Out.asyncWrite(reply); } else { BNSMessage reply; // The name is not registered // Log successful registration Node.log.log(this.GetType(), "Registration of " + message.name + " succeeded."); // First check if any client end is waiting for this name ArrayList pending = (ArrayList)this.waitingResolves[message.name]; if (pending != null) { // We have waiting resolves. Complete for (IEnumerator enumerator = pending.GetEnumerator(); enumerator.MoveNext();) { NetChannelOutput toPending = null; // We now catch internally any JCSPNetworkException try { // Get the next waiting message BNSMessage msg = (BNSMessage)enumerator.Current; // Log resolve completion Node.log.log(this.GetType(), "Queued resolve of " + message.name + " by " + msg.serviceLocation.getNodeID() + " completed"); // Create channel to the resolver toPending = NetChannel.one2net(msg.serviceLocation, new BNSNetworkMessageFilter.FilterTX()); // Create the reply message reply = new BNSMessage(); reply.type = BNSMessageProtocol.RESOLVE_REPLY; reply.location = message.location; reply.success = true; // Write the reply asynchronously to the waiting resolver toPending.asyncWrite(reply); } catch (JCSPNetworkException jne) { // Something went wrong as we tried to send the resolution complete // message // Do nothing } finally { // Check if we need to destroy the temporary channel if (toPending != null) { toPending.destroy(); } } } // Remove the name from the pending resolves this.waitingResolves.Remove(message.name); } // We have completed any pending resolves. Now register the barrier this.registeredBarriers.Add(message.name, message.location); // Now add the registered barrier to the barriers registered by this Node ArrayList registered = (ArrayList)this.barrierRegister[message.serviceLocation.getNodeID()]; // If the ArrayList is null, we have no previous registrations if (registered == null) { // Create a new ArrayList to store the registered names registered = new ArrayList(); // Add it to the barrier register this.barrierRegister.Add(message.location.getNodeID(), registered); } // Add the name to the ArrayList registered.Add(message.name); // Log the successful registration Node.log.log(this.GetType(), message.name + " registered to " + message.location); // Create the reply message reply = new BNSMessage(); reply.type = BNSMessageProtocol.REGISTER_REPLY; reply.success = true; // Write the reply asynchronously to the Node Out.asyncWrite(reply); } } catch (JCSPNetworkException jne) { // Do nothing. Do not let the BNS break } break; } // We have received a resolve request case BNSMessageProtocol.RESOLVE_REQUEST: { // Log resolve request Node.log.log(this.GetType(), "Resolve request for " + message.name + " received"); // Catch any JCSPNetworkException try { // Check if the resolving Node is logged on NetChannelOutput Out = (NetChannelOutput)this.loggedClients[message.serviceLocation.getNodeID()]; // If the channel is null, then the Node has yet to log on with us if (Out == null) { // Node is not logged on // Log failed resolution Node.err.log(this.GetType(), "Resolve failed. " + message.serviceLocation.getNodeID() + " not logged on"); // Create connection to the receiver Out = NetChannel.one2net(message.serviceLocation, new BNSNetworkMessageFilter.FilterTX()); // Create the reply message BNSMessage reply = new BNSMessage(); reply.type = BNSMessageProtocol.RESOLVE_REPLY; reply.success = false; // Write message asynchronously to the Node Out.asyncWrite(reply); // Destroy the temporary channel Out.destroy(); } else { // Node is logged on. Now check if the name is already registered NetBarrierLocation loc = (NetBarrierLocation)this.registeredBarriers[message.name]; // If the location is null, then the name has not yet been registered if (loc == null) { // The name is not registered. We need to queue the resolve until it is // Log the queueing of the resolve Node.log.log(this.GetType(), message.name + " not registered. Queueing resolve by " + message.serviceLocation.getNodeID().toString()); // Check if any other resolvers are waiting for the channel ArrayList pending = (ArrayList)this.waitingResolves[message.name]; // If the ArrayList is null, no one else is waiting if (pending == null) { // No one else is waiting. Create a new list and add it to the waiting // resolves pending = new ArrayList(); this.waitingResolves.Add(message.name, pending); } // Add this resolve message to the list of waiting resolvers pending.Add(message); } else { // The location is not null. Send it to the resolver Node.log.log(this.GetType(), "Resolve request completed. " + message.name + " location being sent to " + message.serviceLocation.getNodeID()); // Create channel to the resolver NetChannelOutput toPending = NetChannel.one2net(message.serviceLocation, new BNSNetworkMessageFilter.FilterTX()); // Create the reply message BNSMessage reply = new BNSMessage(); reply.type = BNSMessageProtocol.RESOLVE_REPLY; reply.location = loc; reply.success = true; // Write the reply to the resolver asynchronously toPending.asyncWrite(reply); // Destroy the temporary channel toPending.destroy(); } } } catch (JCSPNetworkException jne) { // Something went wrong during the resolution. Ignore } break; } } break; } } } }