public MultiCastNode(final long nodeId) throws IOException { try { this.nodeId = nodeId; this.groupAddress = InetAddress.getByAddress(GROUP_ADDRESS); if (LOG.isDebugEnabled()) { LOG.debug( "Initializing MultiCastNode for " + nodeId + " and group address " + groupAddress + "."); } setRunning(true); makePrivateSocket(); startPrivateListener(); joinGroup(); startGroupListener(); final MultiCastMessage hiMessage = new MultiCastMessage(nodeId, MultiCastMessage.Type.HI, getSender()); sendToGroup(hiMessage); if (LOG.isDebugEnabled()) { LOG.debug("Done initializing MultiCastNode for " + this.nodeId); } } catch (IOException e) { setRunning(false); throw e; } }
/** Receive loop for private messaqes. Can be stopped with {@link #setRunning(boolean)} */ private void receivePrivateMessages() { while (isRunning()) { try { final byte[] buf = new byte[BUFFER_SIZE]; final DatagramPacket receivePacket = new DatagramPacket(buf, buf.length); if (LOG.isDebugEnabled()) { LOG.debug( "Waiting for private message, listening on port " + privateSocket.getLocalPort()); } privateSocket.receive(receivePacket); // wait for a packet final String data = toString(receivePacket); if (LOG.isDebugEnabled()) { LOG.debug("Got a private message: " + data); } if (LOG.isDebugEnabled()) { LOG.debug( "Received " + data + " from " + receivePacket.getAddress() + ":" + receivePacket.getPort() + "."); } processPrivateMessage(data); } catch (IOException e) { LOG.error(BUNDLE_MARKER, e.toString(), e); } } if (LOG.isDebugEnabled()) { LOG.debug("Stopped listening to private messages."); } }
/** * Join the broadcast group. * * @throws IOException if something goes wrong */ private void joinGroup() throws IOException { groupSocket = new MulticastSocket(GROUP_PORT); groupSocket.joinGroup(groupAddress); if (LOG.isDebugEnabled()) { LOG.debug( "MultiCastNode for " + nodeId + " joined group at " + groupAddress + ":" + GROUP_PORT); } }
/** * Sends a private message. * * @param message message * @param address address to send the message to * @param port port to send the message to * @throws IOException if sending fails */ private void sendPrivateMessage( final MultiCastMessage message, final InetAddress address, final int port) throws IOException { privateSocket.send(toDatagramPacket(message.toString(), address, port)); if (LOG.isDebugEnabled()) { LOG.debug("Sent " + message + " to " + address + ":" + port); } }
/** * Fires message to all registered listeners. * * @param multiCastMessage message */ private void fireMessage(final MultiCastMessage multiCastMessage) { for (final MultiCastMessageListener multiCastMessageListener : multiCastMessageListeners) { multiCastMessageListener.processMessage(multiCastMessage); } if (multiCastMessageListeners.isEmpty() && LOG.isDebugEnabled()) { LOG.debug(BUNDLE_MARKER, "No MultiCastMessageListeners registered."); } }
/** * Processes a privately received message. * * @param message message * @throws IOException if a response request fails */ private void processPrivateMessage(final String message) throws IOException { try { final MultiCastMessage multiCastMessage = new MultiCastMessage(message); if (multiCastMessage.getType() == MultiCastMessage.Type.LS) { final InetAddress address = multiCastMessage.getSenderAddress(); final int port = multiCastMessage.getSenderPort(); // sending everything to remote private port for (final MultiCastMessage mcm : ((RegistryImpl) RegistryImpl.getInstance()).getList()) { sendPrivateMessage(mcm, address, port); } } else if (multiCastMessage.getType() == MultiCastMessage.Type.HI) { final InetAddress address = multiCastMessage.getSenderAddress(); final int port = multiCastMessage.getSenderPort(); if (multiCastMessage.getNodeId() == RegistryImpl.getInstance().getNodeId()) { if (LOG.isDebugEnabled()) { LOG.debug("HI message is from this node, doing nothing."); } } else { if (lsRequestSent < maxLsRequests) { if (LOG.isDebugEnabled()) { LOG.debug("Sending ls request to " + address); } sendPrivateMessage( new MultiCastMessage(nodeId, MultiCastMessage.Type.LS, getSender()), address, port); lsRequestSent++; } else { if (LOG.isDebugEnabled()) { LOG.debug("Max ls requests already sent, doing nothing."); } } } } else { if (multiCastMessage.isValid()) { multiCastMessage.setDirection(Direction.IN); fireMessage(multiCastMessage); } } } catch (RuntimeException e) { LOG.error(BUNDLE_MARKER, "Failed to process private message: " + e.toString(), e); } }
/** * Is notified of multicast messages. These messages are sent to the group, if their direction is * {@link org.bundlebee.registry.net.MultiCastMessage.Direction#OUT}. * * @param multiCastMessage multiCastMessage */ public void processMessage(final MultiCastMessage multiCastMessage) { if (Direction.OUT.equals(multiCastMessage.getDirection())) { this.sendToGroup(multiCastMessage); } else { if (LOG.isDebugEnabled()) { LOG.debug( "Not sending message, because its direction is not " + Direction.OUT + ", but " + multiCastMessage.getDirection()); } } }
/** * Repeatedly receive a packet from the group, process it. No messages are sent from here. * sendPacket(). */ public void receiveGroupMessages() { if (LOG.isDebugEnabled()) { LOG.debug("Starting group receive loop for " + nodeId); } while (this.isRunning()) { try { final byte[] data = new byte[BUFFER_SIZE]; // set up an empty packet final DatagramPacket packet = new DatagramPacket(data, data.length); if (LOG.isDebugEnabled()) { LOG.debug("Waiting for group message on " + groupSocket); } groupSocket.receive(packet); // wait for a packet final String msg = toString(packet); if (LOG.isDebugEnabled()) { LOG.debug( "Received group msg " + msg + " from " + packet.getAddress() + ":" + packet.getPort() + "."); } processGroupMessage(msg); } catch (SocketTimeoutException e) { if (LOG.isInfoEnabled()) { LOG.info(BUNDLE_MARKER, "GroupSocket receive timed out."); } } catch (IOException e) { LOG.error(BUNDLE_MARKER, e.toString(), e); } catch (Throwable t) { LOG.error(BUNDLE_MARKER, t.toString(), t); } } if (LOG.isDebugEnabled()) { LOG.debug("Group receive loop for " + nodeId + " was stopped."); } }
public void sendToGroup(final MultiCastMessage multiCastMessage) { if (multiCastMessage.isValid()) { // reset ls request count, when we send HI if (multiCastMessage.getType() == MultiCastMessage.Type.HI) { lsRequestSent = 0; // make sure we have a sender set // even if the directory does not know, who we are if (multiCastMessage.getValues().getProperty(MultiCastMessage.PROPERTYKEY_SENDER) == null) { multiCastMessage .getValues() .setProperty(MultiCastMessage.PROPERTYKEY_SENDER, getSender()); } } sendToGroup(multiCastMessage.toString()); } else { if (LOG.isDebugEnabled()) { LOG.debug( BUNDLE_MARKER, "not sending message, because it is not valid: " + multiCastMessage); } } }
/** * Creates the socket used for private point to point communication between two nodes. * * @throws SocketException if the socket can't be created */ private void makePrivateSocket() throws SocketException { this.privateSocket = getAvailableSocket(LOCAL_PORT); if (LOG.isDebugEnabled()) { LOG.debug("Bound private socket to port " + privateSocket.getLocalPort()); } }