/**
   * Load the STUN configuration from a stream.
   *
   * @param stunConfigStream An InputStream with the configuration file.
   * @return A list of loaded servers
   */
  public ArrayList loadSTUNServers(java.io.InputStream stunConfigStream) {
    final ArrayList serversList = new ArrayList();
    String serverName;
    int serverPort;

    try {
      final XmlPullParser parser = new MXParser();
      parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
      parser.setInput(stunConfigStream, "UTF-8");

      int eventType = parser.getEventType();
      do {
        if (eventType == XmlPullParser.START_TAG) {

          // Parse a STUN server definition
          if (parser.getName().equals("stunServer")) {

            serverName = null;
            serverPort = -1;

            // Parse the hostname
            parser.next();
            parser.next();
            serverName = parser.nextText();

            // Parse the port
            parser.next();
            parser.next();
            try {
              serverPort = Integer.parseInt(parser.nextText());
            } catch (final Exception e) {
            }

            // If we have a valid hostname and port, add
            // it to the list.
            if (serverName != null && serverPort != -1) {
              final STUNService service = new STUNService(serverName, serverPort);

              serversList.add(service);
            }
          }
        }
        eventType = parser.next();

      } while (eventType != XmlPullParser.END_DOCUMENT);

    } catch (final XmlPullParserException e) {
      LOGGER.error(e.getMessage(), e);
    } catch (final IOException e) {
      LOGGER.error(e.getMessage(), e);
    }

    currentServer = bestSTUNServer(serversList);

    return serversList;
  }
  /**
   * Load a list of services: STUN servers and ports. Some public STUN servers are:
   *
   * <p>
   *
   * <pre>
   *               iphone-stun.freenet.de:3478
   *               larry.gloo.net:3478
   *               stun.xten.net:3478
   *               stun.fwdnet.net
   *               stun.fwd.org (no DNS SRV record)
   *               stun01.sipphone.com (no DNS SRV record)
   *               stun.softjoys.com (no DNS SRV record)
   *               stun.voipbuster.com (no DNS SRV record)
   *               stun.voxgratia.org (no DNS SRV record)
   *               stun.noc.ams-ix.net
   * </pre>
   *
   * <p>This list should be contained in a file in the "META-INF" directory
   *
   * @return a list of services
   */
  public ArrayList loadSTUNServers() {
    final ArrayList serversList = new ArrayList();

    // Load the STUN configuration
    try {
      // Get an array of class loaders to try loading the config from.
      final ClassLoader[] classLoaders = new ClassLoader[2];
      classLoaders[0] = new STUNResolver() {}.getClass().getClassLoader();
      classLoaders[1] = Thread.currentThread().getContextClassLoader();

      for (final ClassLoader classLoader : classLoaders) {
        final Enumeration stunConfigEnum = classLoader.getResources(STUNSERVERS_FILENAME);

        while (stunConfigEnum.hasMoreElements() && serversList.isEmpty()) {
          final URL url = (URL) stunConfigEnum.nextElement();
          java.io.InputStream stunConfigStream = null;

          stunConfigStream = url.openStream();
          serversList.addAll(loadSTUNServers(stunConfigStream));
          stunConfigStream.close();
        }
      }
    } catch (final Exception e) {
      LOGGER.error(e.getMessage(), e);
    }

    return serversList;
  }