/** INTERNAL: Send out an announcement that we are here. */
  public void announceSession() {
    rcm.logDebug("sending_announcement", (Object[]) null);

    ServiceAnnouncement outMsg = new ServiceAnnouncement(rcm.getServiceId());
    byte[] outBytes = outMsg.toBytes();

    try {
      // Create a packet to send and send it out to everyone listening
      DatagramPacket sendPacket =
          new DatagramPacket(
              outBytes,
              outBytes.length,
              InetAddress.getByName(multicastGroupAddress),
              multicastPort);
      getCommunicationSocket().send(sendPacket);

      Object[] args = null;
      rcm.logInfo("announcement_sent", args);

    } catch (Exception ex) {
      // We got an exception. Map it to an RCM exception and call the handler
      DiscoveryException discoveryEx = DiscoveryException.errorSendingAnnouncement(ex);
      rcm.handleException(discoveryEx);
    }
  }
  /** ADVANCED: Announce the local service and join the cluster */
  public void startDiscovery() {
    if (rcm.isCommandProcessorASession()) {
      rcm.getCommandProcessor().processCommand(new ProfileDiscoveryStartedCommand());
    }

    // Only start if we are currently stopped
    if (this.isDiscoveryStopped()) {
      this.rcm.getServerPlatform().launchContainerRunnable(this);
    }
  }
 /** INTERNAL: Create the multicast socket and join the multicast group. */
 public void createCommunicationSocket() {
   Object[] args = {multicastGroupAddress, "" + multicastPort};
   rcm.logDebug("initializing_discovery_resources", args);
   if (communicationSocket == null) {
     try {
       communicationSocket = new MulticastSocket(multicastPort);
       communicationSocket.setTimeToLive(getPacketTimeToLive());
       communicationSocket.joinGroup(InetAddress.getByName(multicastGroupAddress));
     } catch (IOException ex) {
       // Either we couldn't create the socket or we couldn't join the group
       DiscoveryException discoveryEx = DiscoveryException.errorJoiningMulticastGroup(ex);
       rcm.handleException(discoveryEx);
     }
   }
 }
 /**
  * ADVANCED: Stop accepting announcements from other services becoming available. Note that this
  * does not remove the local service from the cluster.
  */
 public void stopDiscovery() {
   if (rcm.isCommandProcessorASession()) {
     this.rcm.getCommandProcessor().processCommand(new ProfileDiscoveryStoppedCommand());
   }
   stopListening();
   try {
     // Put in a sleep to give the listener thread a chance to stop
     Thread.sleep(500);
   } catch (InterruptedException exception) {
   }
   communicationSocket = null;
 }
  /**
   * INTERNAL: This is the main execution method of discovery. It will create a socket to listen on,
   * create a local connection for this service and announce that we are open for business.
   */
  public void run() {
    // Initialize the communication socket
    createCommunicationSocket();

    // Create the local connection from which we will receive commands
    rcm.getTransportManager().createLocalConnection();

    // Announce to all other discovery managers that this service is up. The
    // delay allows time for posting of connections to the name service
    try {
      Thread.sleep(announcementDelay);
    } catch (InterruptedException exception) {
    }
    announceSession();

    // Listen for other sessions that are joining
    startListening();
  }
  /**
   * INTERNAL: This method puts us into the listening mode loop. This thread blocks, waiting on
   * announcements that we receive from other discovery managers.
   */
  public void startListening() {
    byte[] recvBuf = new byte[128];

    // Only stop when we get the directive to stop
    stopListening = false;
    rcm.logInfo("discovery_manager_active", (Object[]) null);
    while (!stopListening) {
      DatagramPacket recvPacket = new DatagramPacket(recvBuf, recvBuf.length);
      ServiceAnnouncement inMsg;

      // Block waiting for a message
      try {
        getCommunicationSocket().receive(recvPacket);
      } catch (IOException exception) {
        if (stopListening) {
          // We caused the exception by closing the socket
          rcm.logInfo("discovery_manager_stopped", (Object[]) null);
          return;
        } else {
          // Exception was caused by something else (e.g. network error, etc.)
          rcm.handleException(DiscoveryException.errorReceivingAnnouncement(exception));
        }
      }

      // We received a message, unmarshall it into an announcement
      try {
        inMsg = new ServiceAnnouncement(recvPacket.getData());
      } catch (Exception ex) {
        // Log a warning that we couldn't process the announcement
        Object[] args = {ex};
        rcm.logWarning("received_corrupt_announcement", args);
        continue;
      }

      // If the msg is not from ourselves, and is announcing a service on
      // the same channel as we are on then we should do something about it
      if (!rcm.getServiceId().getId().equals(inMsg.getServiceId().getId())
          && (rcm.getServiceId()
              .getChannel()
              .equalsIgnoreCase(inMsg.getServiceId().getChannel()))) {
        receivedAnnouncement(inMsg.getServiceId());
      }
    }
  }
 /** INTERNAL: Process the announcement that indicates that a new service is online */
 public void receivedAnnouncement(ServiceId serviceId) {
   Object[] args = {serviceId};
   rcm.logInfo("announcement_received", args);
   // Notify the RCM that a new service has been detected
   rcm.newServiceDiscovered(serviceId);
 }