/**
   * Put the JAIN-SIP stack in a state where it cannot receive any data and frees the network ports
   * used. That is to say remove JAIN-SIP <tt>ListeningPoint</tt>s and <tt>SipProvider</tt>s.
   */
  @SuppressWarnings("unchecked") // jain-sip legacy code
  private void stopListening() {
    try {
      this.secureJainSipProvider.removeSipListener(this);
      this.stack.deleteSipProvider(this.secureJainSipProvider);
      this.secureJainSipProvider = null;
      this.clearJainSipProvider.removeSipListener(this);
      this.stack.deleteSipProvider(this.clearJainSipProvider);
      this.clearJainSipProvider = null;

      Iterator<ListeningPoint> it = this.stack.getListeningPoints();
      Vector<ListeningPoint> lpointsToRemove = new Vector<ListeningPoint>();
      while (it.hasNext()) {
        lpointsToRemove.add(it.next());
      }

      it = lpointsToRemove.iterator();
      while (it.hasNext()) {
        this.stack.deleteListeningPoint(it.next());
      }

      this.stack.stop();
      if (logger.isTraceEnabled()) logger.trace("stopped listening");
    } catch (ObjectInUseException ex) {
      logger.fatal("Failed to stop listening", ex);
    }
  }
  /**
   * Initializes and binds a socket that on a random port number. The method would try to bind on a
   * random port and retry 5 times until a free port is found.
   *
   * @return the socket that we have initialized on a randomport number.
   */
  private DatagramSocket initRandomPortSocket() {
    DatagramSocket resultSocket = null;
    String bindRetriesStr =
        NetaddrActivator.getConfigurationService().getString(BIND_RETRIES_PROPERTY_NAME);

    int bindRetries = 5;

    if (bindRetriesStr != null) {
      try {
        bindRetries = Integer.parseInt(bindRetriesStr);
      } catch (NumberFormatException ex) {
        logger.error(
            bindRetriesStr
                + " does not appear to be an integer. "
                + "Defaulting port bind retries to "
                + bindRetries,
            ex);
      }
    }

    int currentlyTriedPort = NetworkUtils.getRandomPortNumber();

    // we'll first try to bind to a random port. if this fails we'll try
    // again (bindRetries times in all) until we find a free local port.
    for (int i = 0; i < bindRetries; i++) {
      try {
        resultSocket = new DatagramSocket(currentlyTriedPort);
        // we succeeded - break so that we don't try to bind again
        break;
      } catch (SocketException exc) {
        if (exc.getMessage().indexOf("Address already in use") == -1) {
          logger.fatal(
              "An exception occurred while trying to create" + "a local host discovery socket.",
              exc);
          resultSocket = null;
          return null;
        }
        // port seems to be taken. try another one.
        logger.debug("Port " + currentlyTriedPort + " seems in use.");
        currentlyTriedPort = NetworkUtils.getRandomPortNumber();
        logger.debug("Retrying bind on port " + currentlyTriedPort);
      }
    }

    return resultSocket;
  }
  /**
   * Constructor for this class. Creates the JAIN-SIP stack.
   *
   * @throws OperationFailedException if creating the stack fails.
   */
  SipStackSharing() throws OperationFailedException {
    // init of the stack
    try {
      SipFactory sipFactory = SipFactory.getInstance();
      sipFactory.setPathName("org.jitsi.gov.nist");

      Properties sipStackProperties = new SipStackProperties();

      // Create SipStack object
      this.stack = sipFactory.createSipStack(sipStackProperties);
      if (logger.isTraceEnabled()) logger.trace("Created stack: " + this.stack);

      // set our custom address resolver managing SRV records
      AddressResolverImpl addressResolver = new AddressResolverImpl();
      ((SIPTransactionStack) this.stack).setAddressResolver(addressResolver);

      SipActivator.getNetworkAddressManagerService().addNetworkConfigurationChangeListener(this);
    } catch (Exception ex) {
      logger.fatal("Failed to get SIP Factory.", ex);
      throw new OperationFailedException(
          "Failed to get SIP Factory", OperationFailedException.INTERNAL_ERROR, ex);
    }
  }