/**
  * Used to send a message to a subset of endpoints in the call, primary use case being a message
  * that has originated from an endpoint (as opposed to a message originating from the bridge and
  * being sent to all endpoints in the call, for that see broadcastMessageOnDataChannels below
  *
  * @param msg
  * @param endpoints
  */
 public void sendMessageOnDataChannels(String msg, List<Endpoint> endpoints) {
   for (Endpoint endpoint : endpoints) {
     try {
       endpoint.sendMessageOnDataChannel(msg);
     } catch (IOException e) {
       logger.error("Failed to send message on data channel.", e);
     }
   }
 }
  /**
   * Notifies this instance that a specific <tt>SctpConnection</tt> has become ready i.e. connected
   * to a/the remote peer and operational.
   *
   * @param sctpConnection the <tt>SctpConnection</tt> which has become ready and is the cause of
   *     the method invocation
   */
  private void sctpConnectionReady(SctpConnection sctpConnection) {
    /*
     * We want to fire initial events over the SctpConnection as soon as it
     * is ready, we do not want to fire them multiple times i.e. every time
     * the SctpConnection becomes ready.
     */
    sctpConnection.removeChannelListener(webRtcDataStreamListener);

    if (!isExpired() && !sctpConnection.isExpired() && sctpConnection.isReady()) {
      Endpoint endpoint = sctpConnection.getEndpoint();

      if (endpoint != null) endpoint = getEndpoint(endpoint.getID());
      if (endpoint != null) {
        /*
         * It appears that this Conference, the SctpConnection and the
         * Endpoint are in states which allow them to fire the initial
         * events.
         */
        Endpoint dominantSpeaker = speechActivity.getDominantEndpoint();

        if (dominantSpeaker != null) {
          try {
            endpoint.sendMessageOnDataChannel(
                createDominantSpeakerEndpointChangeEvent(dominantSpeaker));
          } catch (IOException e) {
            logger.error("Failed to send message on data channel.", e);
          }
        }

        /*
         * Determining the instant at which an SctpConnection associated
         * with an Endpoint becomes ready (i.e. connected to the remote
         * peer and operational) is a multi-step ordeal. The Conference
         * class implements the procedure so do not make other classes
         * implement it as well.
         */
        endpoint.sctpConnectionReady(sctpConnection);
      }
    }
  }