/** 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);
    }
  }
  /**
   * 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());
      }
    }
  }