Package net.pms.network

Source Code of net.pms.network.HTTPServer

/*
* PS3 Media Server, for streaming any medias to your PS3.
* Copyright (C) 2008  A.Brochard
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License only.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
package net.pms.network;

import java.io.IOException;
import java.net.*;
import java.nio.channels.ClosedByInterruptException;
import java.nio.channels.ServerSocketChannel;
import java.util.concurrent.Executors;
import net.pms.Messages;
import net.pms.PMS;
import net.pms.configuration.PmsConfiguration;
import org.apache.commons.lang3.StringUtils;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.group.DefaultChannelGroup;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HTTPServer implements Runnable {
  private static final Logger LOGGER = LoggerFactory.getLogger(HTTPServer.class);
  private static final PmsConfiguration configuration = PMS.getConfiguration();
  private final int port;
  private String hostname;
  private ServerSocketChannel serverSocketChannel;
  private ServerSocket serverSocket;
  private boolean stop;
  private Thread runnable;
  private InetAddress iafinal;
  private ChannelFactory factory;
  private Channel channel;
  private NetworkInterface networkInterface;
  private ChannelGroup group;

  // XXX not used
  @Deprecated
  public InetAddress getIafinal() {
    return iafinal;
  }

  public NetworkInterface getNetworkInterface() {
    return networkInterface;
  }

  // use getNetworkInterface()
  @Deprecated
  public NetworkInterface getNi() {
    return getNetworkInterface();
  }

  public HTTPServer(int port) {
    this.port = port;
  }

  public String getURL() {
    return "http://" + hostname + ":" + port;
  }

  public String getHost() {
    return hostname;
  }

  public int getPort() {
    return port;
  }

  public boolean start() throws IOException {
    hostname = configuration.getServerHostname();
    InetSocketAddress address;

    if (StringUtils.isNotBlank(hostname)) {
      LOGGER.info("Using forced address " + hostname);
      InetAddress tempIA = InetAddress.getByName(hostname);

      if (tempIA != null && networkInterface != null && networkInterface.equals(NetworkInterface.getByInetAddress(tempIA))) {
        address = new InetSocketAddress(tempIA, port);
      } else {
        address = new InetSocketAddress(hostname, port);
      }
    } else if (isAddressFromInterfaceFound(configuration.getNetworkInterface())) { // XXX sets iafinal and networkInterface
      LOGGER.info("Using address {} found on network interface: {}", iafinal, networkInterface.toString().trim().replace('\n', ' '));
      address = new InetSocketAddress(iafinal, port);
    } else {
      LOGGER.info("Using localhost address");
      address = new InetSocketAddress(port);
    }

    LOGGER.info("Created socket: " + address);

    if (configuration.isHTTPEngineV2()) { // HTTP Engine V2
      group = new DefaultChannelGroup("myServer");
      factory = new NioServerSocketChannelFactory(
        Executors.newCachedThreadPool(),
        Executors.newCachedThreadPool()
      );

      ServerBootstrap bootstrap = new ServerBootstrap(factory);
      HttpServerPipelineFactory pipeline = new HttpServerPipelineFactory(group);
      bootstrap.setPipelineFactory(pipeline);
      bootstrap.setOption("child.tcpNoDelay", true);
      bootstrap.setOption("child.keepAlive", true);
      bootstrap.setOption("reuseAddress", true);
      bootstrap.setOption("child.reuseAddress", true);
      bootstrap.setOption("child.sendBufferSize", 65536);
      bootstrap.setOption("child.receiveBufferSize", 65536);

      try {
        channel = bootstrap.bind(address);

        group.add(channel);
      } catch (Exception e) {
        LOGGER.error("Another program is using port " + port + ", which UMS needs.");
        LOGGER.error("You can change the port UMS uses on the General Configuration tab.");
        LOGGER.trace("The error was: " + e);
        PMS.get().getFrame().setStatusCode(0, Messages.getString("PMS.141"), "icon-status-warning.png");
      }

      if (hostname == null && iafinal != null) {
        hostname = iafinal.getHostAddress();
      } else if (hostname == null) {
        hostname = InetAddress.getLocalHost().getHostAddress();
      }
    } else { // HTTP Engine V1
      serverSocketChannel = ServerSocketChannel.open();

      serverSocket = serverSocketChannel.socket();
      serverSocket.setReuseAddress(true);
      serverSocket.bind(address);

      if (hostname == null && iafinal != null) {
        hostname = iafinal.getHostAddress();
      } else if (hostname == null) {
        hostname = InetAddress.getLocalHost().getHostAddress();
      }

      runnable = new Thread(this, "HTTP Server");
      runnable.setDaemon(false);
      runnable.start();
    }

    return true;
  }

  // XXX this sets iafinal and networkInterface
  private boolean isAddressFromInterfaceFound(String networkInterfaceName) {
    NetworkConfiguration.InterfaceAssociation ia = StringUtils.isNotEmpty(networkInterfaceName) ?
      NetworkConfiguration.getInstance().getAddressForNetworkInterfaceName(networkInterfaceName) :
      null;

    if (ia == null) {
      ia = NetworkConfiguration.getInstance().getDefaultNetworkInterfaceAddress();
    }

    if (ia != null) {
      iafinal = ia.getAddr();
      networkInterface = ia.getIface();
    }

    return ia != null;
  }

  // http://www.ps3mediaserver.org/forum/viewtopic.php?f=6&t=10689&p=48811#p48811
  //
  // avoid a NPE when a) switching HTTP Engine versions and b) restarting the HTTP server
  // by cleaning up based on what's in use (not null) rather than the config state, which
  // might be inconsistent.
  //
  // NOTE: there's little in the way of cleanup to do here as PMS.reset() discards the old
  // server and creates a new one
  public void stop() {
    LOGGER.info("Stopping server on host {} and port {}...", hostname, port);

    if (runnable != null) { // HTTP Engine V1
      runnable.interrupt();
    }

    if (serverSocket != null) { // HTTP Engine V1
      try {
        serverSocket.close();
        serverSocketChannel.close();
      } catch (IOException e) {
        LOGGER.debug("Caught exception", e);
      }
    }

    if (channel != null) { // HTTP Engine V2
      if (group != null) {
        group.close().awaitUninterruptibly();
      }

      if (factory != null) {
        factory.releaseExternalResources();
      }
    }

    NetworkConfiguration.forgetConfiguration();
  }

  // XXX only used by HTTP Engine V1
  @Override
  public void run() {
    LOGGER.info("Starting DLNA Server on host {} and port {}...", hostname, port);

    while (!stop) {
      try {
        Socket socket = serverSocket.accept();
        InetAddress inetAddress = socket.getInetAddress();
        String ip = inetAddress.getHostAddress();
        // basic IP filter: solntcev at gmail dot com
        boolean ignore = false;

        if (configuration.getIpFiltering().allowed(inetAddress)) {
          LOGGER.trace("Receiving a request from: " + ip);
        } else {
          ignore = true;
          socket.close();
          LOGGER.trace("Ignoring request from: " + ip);
        }

        if (!ignore) {
          RequestHandler request = new RequestHandler(socket);
          Thread thread = new Thread(request, "Request Handler");
          thread.start();
        }
      } catch (ClosedByInterruptException e) {
        stop = true;
      } catch (IOException e) {
        LOGGER.debug("Caught exception", e);
      } finally {
        try {
          if (stop && serverSocket != null) {
            serverSocket.close();
          }

          if (stop && serverSocketChannel != null) {
            serverSocketChannel.close();
          }
        } catch (IOException e) {
          LOGGER.debug("Caught exception", e);
        }
      }
    }
  }
}
TOP

Related Classes of net.pms.network.HTTPServer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.