danicoin/src/PaymentGateService/PaymentGateService.cpp
2016-01-18 15:33:29 +00:00

240 lines
6.7 KiB
C++
Executable file

// Copyright (c) 2011-2016 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "PaymentGateService.h"
#include <future>
#include "Common/SignalHandler.h"
#include "InProcessNode/InProcessNode.h"
#include "Logging/LoggerRef.h"
#include "PaymentGate/PaymentServiceJsonRpcServer.h"
#include "CryptoNoteCore/CoreConfig.h"
#include "CryptoNoteCore/Core.h"
#include "CryptoNoteProtocol/CryptoNoteProtocolHandler.h"
#include "P2p/NetNode.h"
#include "PaymentGate/WalletFactory.h"
#include <System/Context.h>
#ifdef ERROR
#undef ERROR
#endif
#ifdef _WIN32
#include <direct.h>
#else
#include <unistd.h>
#endif
using namespace PaymentService;
void changeDirectory(const std::string& path) {
if (chdir(path.c_str())) {
throw std::runtime_error("Couldn't change directory to \'" + path + "\': " + strerror(errno));
}
}
void stopSignalHandler(PaymentGateService* pg) {
pg->stop();
}
bool PaymentGateService::init(int argc, char** argv) {
if (!config.init(argc, argv)) {
return false;
}
logger.setMaxLevel(static_cast<Logging::Level>(config.gateConfiguration.logLevel));
logger.addLogger(consoleLogger);
Logging::LoggerRef log(logger, "main");
if (config.gateConfiguration.testnet) {
log(Logging::INFO) << "Starting in testnet mode";
currencyBuilder.testnet(true);
}
if (!config.gateConfiguration.serverRoot.empty()) {
changeDirectory(config.gateConfiguration.serverRoot);
log(Logging::INFO) << "Current working directory now is " << config.gateConfiguration.serverRoot;
}
fileStream.open(config.gateConfiguration.logFile, std::ofstream::app);
if (!fileStream) {
throw std::runtime_error("Couldn't open log file");
}
fileLogger.attachToStream(fileStream);
logger.addLogger(fileLogger);
return true;
}
WalletConfiguration PaymentGateService::getWalletConfig() const {
return WalletConfiguration{
config.gateConfiguration.containerFile,
config.gateConfiguration.containerPassword
};
}
const CryptoNote::Currency PaymentGateService::getCurrency() {
return currencyBuilder.currency();
}
void PaymentGateService::run() {
System::Dispatcher localDispatcher;
System::Event localStopEvent(localDispatcher);
this->dispatcher = &localDispatcher;
this->stopEvent = &localStopEvent;
Tools::SignalHandler::install(std::bind(&stopSignalHandler, this));
Logging::LoggerRef log(logger, "run");
if (config.startInprocess) {
runInProcess(log);
} else {
runRpcProxy(log);
}
this->dispatcher = nullptr;
this->stopEvent = nullptr;
}
void PaymentGateService::stop() {
Logging::LoggerRef log(logger, "stop");
log(Logging::INFO) << "Stop signal caught";
if (dispatcher != nullptr) {
dispatcher->remoteSpawn([&]() {
if (stopEvent != nullptr) {
stopEvent->set();
}
});
}
}
void PaymentGateService::runInProcess(Logging::LoggerRef& log) {
if (!config.coreConfig.configFolderDefaulted) {
if (!Tools::directoryExists(config.coreConfig.configFolder)) {
throw std::runtime_error("Directory does not exist: " + config.coreConfig.configFolder);
}
} else {
if (!Tools::create_directories_if_necessary(config.coreConfig.configFolder)) {
throw std::runtime_error("Can't create directory: " + config.coreConfig.configFolder);
}
}
log(Logging::INFO) << "Starting Payment Gate with local node";
CryptoNote::Currency currency = currencyBuilder.currency();
CryptoNote::core core(currency, NULL, logger);
CryptoNote::CryptoNoteProtocolHandler protocol(currency, *dispatcher, core, NULL, logger);
CryptoNote::NodeServer p2pNode(*dispatcher, protocol, logger);
protocol.set_p2p_endpoint(&p2pNode);
core.set_cryptonote_protocol(&protocol);
log(Logging::INFO) << "initializing p2pNode";
if (!p2pNode.init(config.netNodeConfig)) {
throw std::runtime_error("Failed to init p2pNode");
}
log(Logging::INFO) << "initializing core";
CryptoNote::MinerConfig emptyMiner;
core.init(config.coreConfig, emptyMiner, true);
std::promise<std::error_code> initPromise;
auto initFuture = initPromise.get_future();
std::unique_ptr<CryptoNote::INode> node(new CryptoNote::InProcessNode(core, protocol));
node->init([&initPromise, &log](std::error_code ec) {
if (ec) {
log(Logging::WARNING, Logging::YELLOW) << "Failed to init node: " << ec.message();
} else {
log(Logging::INFO) << "node is inited successfully";
}
initPromise.set_value(ec);
});
auto ec = initFuture.get();
if (ec) {
throw std::system_error(ec);
}
log(Logging::INFO) << "Spawning p2p server";
System::Event p2pStarted(*dispatcher);
System::Context<> context(*dispatcher, [&]() {
p2pStarted.set();
p2pNode.run();
});
p2pStarted.wait();
runWalletService(currency, *node);
p2pNode.sendStopSignal();
context.get();
node->shutdown();
core.deinit();
p2pNode.deinit();
}
void PaymentGateService::runRpcProxy(Logging::LoggerRef& log) {
log(Logging::INFO) << "Starting Payment Gate with remote node";
CryptoNote::Currency currency = currencyBuilder.currency();
std::unique_ptr<CryptoNote::INode> node(
PaymentService::NodeFactory::createNode(
config.remoteNodeConfig.daemonHost,
config.remoteNodeConfig.daemonPort));
runWalletService(currency, *node);
}
void PaymentGateService::runWalletService(const CryptoNote::Currency& currency, CryptoNote::INode& node) {
PaymentService::WalletConfiguration walletConfiguration{
config.gateConfiguration.containerFile,
config.gateConfiguration.containerPassword
};
std::unique_ptr<CryptoNote::IWallet> wallet (WalletFactory::createWallet(currency, node, *dispatcher));
service = new PaymentService::WalletService(currency, *dispatcher, node, *wallet, walletConfiguration, logger);
std::unique_ptr<PaymentService::WalletService> serviceGuard(service);
try {
service->init();
} catch (std::exception& e) {
Logging::LoggerRef(logger, "run")(Logging::ERROR, Logging::BRIGHT_RED) << "Failed to init walletService reason: " << e.what();
return;
}
if (config.gateConfiguration.printAddresses) {
// print addresses and exit
std::vector<std::string> addresses;
service->getAddresses(addresses);
for (const auto& address: addresses) {
std::cout << "Address: " << address << std::endl;
}
} else {
PaymentService::PaymentServiceJsonRpcServer rpcServer(*dispatcher, *stopEvent, *service, logger);
rpcServer.start(config.gateConfiguration.bindAddress, config.gateConfiguration.bindPort);
try {
service->saveWallet();
} catch (std::exception& ex) {
Logging::LoggerRef(logger, "saveWallet")(Logging::WARNING, Logging::YELLOW) << "Couldn't save container: " << ex.what();
}
}
}