Package lighthouse.server

Source Code of lighthouse.server.PledgeServer

package lighthouse.server;

import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsServer;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import joptsimple.OptionSpec;
import lighthouse.LighthouseBackend;
import lighthouse.files.AppDirectory;
import lighthouse.protocol.LHUtils;
import lighthouse.threading.AffinityExecutor;
import lighthouse.wallet.PledgingWallet;
import org.bitcoinj.core.GetUTXOsMessage;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.kits.WalletAppKit;
import org.bitcoinj.params.MainNetParams;
import org.bitcoinj.params.RegTestParams;
import org.bitcoinj.params.TestNet3Params;
import org.bitcoinj.utils.BriefLogFormatter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.io.FileInputStream;
import java.net.InetSocketAddress;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyStore;
import java.security.SecureRandom;

import static lighthouse.LighthouseBackend.Mode.SERVER;

/**
* PledgeServer is a standalone HTTP server that knows how to accept pledges and vend statuses (lists of pledges).
* It can help simplify the workflow when the project owner is capable of running a web server.
*/
public class PledgeServer {
    private static final Logger log = LoggerFactory.getLogger(PledgeServer.class);
    public static final short DEFAULT_LOCALHOST_PORT = (short) LHUtils.HTTP_LOCAL_TEST_PORT;

    public static void main(String[] args) throws Exception {
        BriefLogFormatter.initVerbose();

        OptionParser parser = new OptionParser();
        OptionSpec<String> dirFlag = parser.accepts("dir").withRequiredArg();
        OptionSpec<String> netFlag = parser.accepts("net").withRequiredArg().defaultsTo("regtest");
        OptionSpec<Short> portFlag = parser.accepts("port").withRequiredArg().ofType(Short.class).defaultsTo(DEFAULT_LOCALHOST_PORT);
        OptionSpec<String> keystoreFlag = parser.accepts("keystore").withRequiredArg();
        parser.accepts("local-node");
        OptionSet options = parser.parse(args);

        NetworkParameters params;
        switch (netFlag.value(options)) {
            case "main": params = MainNetParams.get(); break;
            case "test": params = TestNet3Params.get(); break;
            case "regtest": params = RegTestParams.get(); break;
            default:
                System.err.println("--net must be one of main, test or regtest");
                return;
        }

        HttpServer server = createServer(portFlag, keystoreFlag, options);

        // Where will we store our projects and received pledges?
        if (options.has(dirFlag))
            AppDirectory.overrideAppDir(Paths.get(options.valueOf(dirFlag)));
        Path appDir = AppDirectory.initAppDir("lighthouse-server");   // Create dir if necessary.

        WalletAppKit kit = new WalletAppKit(params, appDir.toFile(), "lighthouse-server") {
            {
                walletFactory = PledgingWallet::new;
            }
        };
        if (kit.isChainFileLocked()) {
            log.error("App is already running. Please terminate the other instance or use a different directory (--dir=...)");
            return;
        }
        int minPeersSupportingGetUTXO = 2;   // Increase when the feature eventually rolls out to the network.
        if (options.has("local-node") || params == RegTestParams.get()) {
            kit.connectToLocalHost();
            minPeersSupportingGetUTXO = 1// Only local matters.
        }
        // Eventually take this out when getutxo is merged, released and people have upgraded.
        kit.setBlockingStartup(true)
           .setAutoSave(true)
           .setAutoStop(true)
           .setUserAgent("Lighthouse Server", "1.0")
           .startAsync()
           .awaitRunning();
        log.info("bitcoinj initialised");

        // Don't start up fully until we're properly set up. Eventually this can go away.
        // TODO: Make this also check for NODE_GETUTXOS flag.
        log.info("Waiting to find a peer that supports getutxo");
        kit.peerGroup().waitForPeersOfVersion(minPeersSupportingGetUTXO, GetUTXOsMessage.MIN_PROTOCOL_VERSION).get();
        log.info("Found ... starting web server on port {}", portFlag.value(options));

        // This app is mostly single threaded. It handles all requests and state changes on a single thread.
        // Speed should ideally not be an issue, as the backend blocks only rarely. If it's a problem then
        // we'll have to split the backend thread from the http server thread.
        AffinityExecutor.ServiceAffinityExecutor executor = new AffinityExecutor.ServiceAffinityExecutor("server");
        server.setExecutor(executor);
        LighthouseBackend backend = new LighthouseBackend(SERVER, kit.peerGroup(), kit.chain(), (PledgingWallet) kit.wallet(), executor);
        backend.setMinPeersForUTXOQuery(minPeersSupportingGetUTXO);
        server.createContext(LHUtils.HTTP_PATH_PREFIX, new ProjectHandler(backend));
        server.createContext("/", exchange -> {
            log.warn("404 Not Found: {}", exchange.getRequestURI());
            exchange.sendResponseHeaders(404, -1);
        });
        server.start();
    }

    private static HttpServer createServer(OptionSpec<Short> portFlag, OptionSpec<String> keystoreFlag, OptionSet options) throws Exception {
        if (options.has(keystoreFlag)) {
            // The amount of boilerplate this supposedly lightweight HTTPS server requires is stupid.
            KeyStore keyStore = KeyStore.getInstance("JKS");
            char[] password = "changeit".toCharArray();
            try (FileInputStream stream = new FileInputStream(options.valueOf(keystoreFlag))) {
                keyStore.load(stream, password);
            }
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(keyStore, password);
            TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
            tmf.init(keyStore);
            SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
            sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
            HttpsServer server = HttpsServer.create(new InetSocketAddress(portFlag.value(options)), 0);
            server.setHttpsConfigurator(new HttpsConfigurator(sslContext));
            return server;
        } else {
            return HttpServer.create(new InetSocketAddress(portFlag.value(options)), 0);
        }
    }
}
TOP

Related Classes of lighthouse.server.PledgeServer

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.