Merge branch 'master' of github.com:jedmccaleb/NewCoin

This commit is contained in:
Arthur Britto
2012-12-06 20:16:19 -08:00
23 changed files with 319 additions and 189 deletions

View File

@@ -143,6 +143,7 @@
<ClCompile Include="src\cpp\ripple\Peer.cpp" /> <ClCompile Include="src\cpp\ripple\Peer.cpp" />
<ClCompile Include="src\cpp\ripple\PeerDoor.cpp" /> <ClCompile Include="src\cpp\ripple\PeerDoor.cpp" />
<ClCompile Include="src\cpp\ripple\PlatRand.cpp" /> <ClCompile Include="src\cpp\ripple\PlatRand.cpp" />
<ClCompile Include="src\cpp\ripple\ProofOfWork.cpp" />
<ClCompile Include="src\cpp\ripple\PubKeyCache.cpp" /> <ClCompile Include="src\cpp\ripple\PubKeyCache.cpp" />
<ClCompile Include="src\cpp\ripple\RangeSet.cpp" /> <ClCompile Include="src\cpp\ripple\RangeSet.cpp" />
<ClCompile Include="src\cpp\ripple\RegularKeySetTransactor.cpp" /> <ClCompile Include="src\cpp\ripple\RegularKeySetTransactor.cpp" />
@@ -184,6 +185,7 @@
<ClCompile Include="src\cpp\ripple\WalletAddTransactor.cpp" /> <ClCompile Include="src\cpp\ripple\WalletAddTransactor.cpp" />
<ClCompile Include="src\cpp\ripple\WSConnection.cpp" /> <ClCompile Include="src\cpp\ripple\WSConnection.cpp" />
<ClCompile Include="src\cpp\ripple\WSDoor.cpp" /> <ClCompile Include="src\cpp\ripple\WSDoor.cpp" />
<ClCompile Include="src\cpp\ripple\WSHandler.cpp" />
<ClCompile Include="src\cpp\websocketpp\src\base64\base64.cpp" /> <ClCompile Include="src\cpp\websocketpp\src\base64\base64.cpp" />
<ClCompile Include="src\cpp\websocketpp\src\md5\md5.c" /> <ClCompile Include="src\cpp\websocketpp\src\md5\md5.c" />
<ClCompile Include="src\cpp\websocketpp\src\messages\data.cpp" /> <ClCompile Include="src\cpp\websocketpp\src\messages\data.cpp" />
@@ -295,6 +297,17 @@
<ClInclude Include="src\cpp\ripple\WSConnection.h" /> <ClInclude Include="src\cpp\ripple\WSConnection.h" />
<ClInclude Include="src\cpp\ripple\WSDoor.h" /> <ClInclude Include="src\cpp\ripple\WSDoor.h" />
<ClInclude Include="src\cpp\ripple\WSHandler.h" /> <ClInclude Include="src\cpp\ripple\WSHandler.h" />
<ClInclude Include="src\cpp\websocketpp\src\common.hpp" />
<ClInclude Include="src\cpp\websocketpp\src\connection.hpp" />
<ClInclude Include="src\cpp\websocketpp\src\endpoint.hpp" />
<ClInclude Include="src\cpp\websocketpp\src\network_utilities.hpp" />
<ClInclude Include="src\cpp\websocketpp\src\shared_const_buffer.hpp" />
<ClInclude Include="src\cpp\websocketpp\src\sockets\plain.hpp" />
<ClInclude Include="src\cpp\websocketpp\src\sockets\socket_base.hpp" />
<ClInclude Include="src\cpp\websocketpp\src\sockets\tls.hpp" />
<ClInclude Include="src\cpp\websocketpp\src\uri.hpp" />
<ClInclude Include="src\cpp\websocketpp\src\websocketpp.hpp" />
<ClInclude Include="src\cpp\websocketpp\src\websocket_frame.hpp" />
<ClInclude Include="util\pugiconfig.hpp" /> <ClInclude Include="util\pugiconfig.hpp" />
<ClInclude Include="util\pugixml.hpp" /> <ClInclude Include="util\pugixml.hpp" />
</ItemGroup> </ItemGroup>

View File

@@ -31,6 +31,9 @@
<Filter Include="Source Files\websocketpp"> <Filter Include="Source Files\websocketpp">
<UniqueIdentifier>{92775c5f-dc9f-4a97-a9a6-6d4bd4e424b4}</UniqueIdentifier> <UniqueIdentifier>{92775c5f-dc9f-4a97-a9a6-6d4bd4e424b4}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="Header Files\websocket">
<UniqueIdentifier>{cd4c41c0-3ee6-49f8-8322-d11422b892f9}</UniqueIdentifier>
</Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="src\cpp\database\database.cpp"> <ClCompile Include="src\cpp\database\database.cpp">
@@ -351,6 +354,12 @@
<ClCompile Include="src\cpp\ripple\AccountItems.cpp"> <ClCompile Include="src\cpp\ripple\AccountItems.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\cpp\ripple\ProofOfWork.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\cpp\ripple\WSHandler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="util\pugiconfig.hpp"> <ClInclude Include="util\pugiconfig.hpp">
@@ -656,6 +665,39 @@
<ClInclude Include="src\cpp\ripple\AccountItems.h"> <ClInclude Include="src\cpp\ripple\AccountItems.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\cpp\websocketpp\src\common.hpp">
<Filter>Header Files\websocket</Filter>
</ClInclude>
<ClInclude Include="src\cpp\websocketpp\src\connection.hpp">
<Filter>Header Files\websocket</Filter>
</ClInclude>
<ClInclude Include="src\cpp\websocketpp\src\endpoint.hpp">
<Filter>Header Files\websocket</Filter>
</ClInclude>
<ClInclude Include="src\cpp\websocketpp\src\network_utilities.hpp">
<Filter>Header Files\websocket</Filter>
</ClInclude>
<ClInclude Include="src\cpp\websocketpp\src\shared_const_buffer.hpp">
<Filter>Header Files\websocket</Filter>
</ClInclude>
<ClInclude Include="src\cpp\websocketpp\src\uri.hpp">
<Filter>Header Files\websocket</Filter>
</ClInclude>
<ClInclude Include="src\cpp\websocketpp\src\websocket_frame.hpp">
<Filter>Header Files\websocket</Filter>
</ClInclude>
<ClInclude Include="src\cpp\websocketpp\src\websocketpp.hpp">
<Filter>Header Files\websocket</Filter>
</ClInclude>
<ClInclude Include="src\cpp\websocketpp\src\sockets\plain.hpp">
<Filter>Header Files\websocket</Filter>
</ClInclude>
<ClInclude Include="src\cpp\websocketpp\src\sockets\socket_base.hpp">
<Filter>Header Files\websocket</Filter>
</ClInclude>
<ClInclude Include="src\cpp\websocketpp\src\sockets\tls.hpp">
<Filter>Header Files\websocket</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="wallet.xml" /> <None Include="wallet.xml" />

View File

@@ -45,8 +45,8 @@ Application::Application() :
mConnectionPool(mIOService), mPeerDoor(NULL), mRPCDoor(NULL), mWSPublicDoor(NULL), mWSPrivateDoor(NULL), mConnectionPool(mIOService), mPeerDoor(NULL), mRPCDoor(NULL), mWSPublicDoor(NULL), mWSPrivateDoor(NULL),
mSweepTimer(mAuxService) mSweepTimer(mAuxService)
{ {
RAND_bytes(mNonce256.begin(), mNonce256.size()); getRand(mNonce256.begin(), mNonce256.size());
RAND_bytes(reinterpret_cast<unsigned char *>(&mNonceST), sizeof(mNonceST)); getRand(reinterpret_cast<unsigned char *>(&mNonceST), sizeof(mNonceST));
mJobQueue.setThreadCount(); mJobQueue.setThreadCount();
mSweepTimer.expires_from_now(boost::posix_time::seconds(60)); mSweepTimer.expires_from_now(boost::posix_time::seconds(60));
mSweepTimer.async_wait(boost::bind(&Application::sweep, this)); mSweepTimer.async_wait(boost::bind(&Application::sweep, this));

View File

@@ -39,6 +39,10 @@
#define SECTION_WEBSOCKET_PUBLIC_PORT "websocket_public_port" #define SECTION_WEBSOCKET_PUBLIC_PORT "websocket_public_port"
#define SECTION_WEBSOCKET_IP "websocket_ip" #define SECTION_WEBSOCKET_IP "websocket_ip"
#define SECTION_WEBSOCKET_PORT "websocket_port" #define SECTION_WEBSOCKET_PORT "websocket_port"
#define SECTION_WEBSOCKET_SECURE "websocket_secure"
#define SECTION_WEBSOCKET_SSL_CERT "websocket_ssl_cert"
#define SECTION_WEBSOCKET_SSL_CHAIN "websocket_ssl_chain"
#define SECTION_WEBSOCKET_SSL_KEY "websocket_ssl_key"
#define SECTION_VALIDATORS "validators" #define SECTION_VALIDATORS "validators"
#define SECTION_VALIDATORS_SITE "validators_site" #define SECTION_VALIDATORS_SITE "validators_site"
@@ -134,6 +138,7 @@ void Config::setup(const std::string& strConf, bool bQuiet)
RPC_PORT = 5001; RPC_PORT = 5001;
WEBSOCKET_PORT = SYSTEM_WEBSOCKET_PORT; WEBSOCKET_PORT = SYSTEM_WEBSOCKET_PORT;
WEBSOCKET_PUBLIC_PORT = SYSTEM_WEBSOCKET_PUBLIC_PORT; WEBSOCKET_PUBLIC_PORT = SYSTEM_WEBSOCKET_PUBLIC_PORT;
WEBSOCKET_SECURE = false;
NUMBER_CONNECTIONS = 30; NUMBER_CONNECTIONS = 30;
// a new ledger every minute // a new ledger every minute
@@ -256,6 +261,14 @@ void Config::load()
if (sectionSingleB(secConfig, SECTION_WEBSOCKET_PUBLIC_PORT, strTemp)) if (sectionSingleB(secConfig, SECTION_WEBSOCKET_PUBLIC_PORT, strTemp))
WEBSOCKET_PUBLIC_PORT = boost::lexical_cast<int>(strTemp); WEBSOCKET_PUBLIC_PORT = boost::lexical_cast<int>(strTemp);
if (sectionSingleB(secConfig, SECTION_WEBSOCKET_SECURE, strTemp))
WEBSOCKET_SECURE = boost::lexical_cast<bool>(strTemp);
sectionSingleB(secConfig, SECTION_WEBSOCKET_SSL_CERT, WEBSOCKET_SSL_CERT);
sectionSingleB(secConfig, SECTION_WEBSOCKET_SSL_CHAIN, WEBSOCKET_SSL_CHAIN);
sectionSingleB(secConfig, SECTION_WEBSOCKET_SSL_KEY, WEBSOCKET_SSL_KEY);
if (sectionSingleB(secConfig, SECTION_VALIDATION_SEED, strTemp)) if (sectionSingleB(secConfig, SECTION_VALIDATION_SEED, strTemp))
{ {
VALIDATION_SEED.setSeedGeneric(strTemp); VALIDATION_SEED.setSeedGeneric(strTemp);

View File

@@ -91,6 +91,10 @@ public:
std::string WEBSOCKET_IP; std::string WEBSOCKET_IP;
int WEBSOCKET_PORT; int WEBSOCKET_PORT;
bool WEBSOCKET_SECURE;
std::string WEBSOCKET_SSL_CERT;
std::string WEBSOCKET_SSL_CHAIN;
std::string WEBSOCKET_SSL_KEY;
// RPC parameters // RPC parameters
std::string RPC_IP; std::string RPC_IP;

View File

@@ -116,8 +116,7 @@ std::vector<unsigned char> CKey::encryptECIES(CKey& otherKey, const std::vector<
{ {
ECIES_ENC_IV_TYPE iv; ECIES_ENC_IV_TYPE iv;
if (RAND_bytes(static_cast<unsigned char *>(iv.begin()), ECIES_ENC_BLK_SIZE) != 1) getRand(static_cast<unsigned char *>(iv.begin()), ECIES_ENC_BLK_SIZE);
throw std::runtime_error("insufficient entropy");
ECIES_ENC_KEY_TYPE secret; ECIES_ENC_KEY_TYPE secret;
ECIES_HMAC_KEY_TYPE hmacKey; ECIES_HMAC_KEY_TYPE hmacKey;
@@ -280,8 +279,7 @@ bool checkECIES(void)
std::vector<unsigned char> message(4096); std::vector<unsigned char> message(4096);
int msglen = i%3000; int msglen = i%3000;
if (RAND_bytes(static_cast<unsigned char *>(&message.front()), msglen) != 1) getRand(static_cast<unsigned char *>(&message.front()), msglen);
throw std::runtime_error("insufficient entropy");
message.resize(msglen); message.resize(msglen);
// encrypt message with sender's private key and recipient's public key // encrypt message with sender's private key and recipient's public key

View File

@@ -867,8 +867,10 @@ void NetworkOPs::consensusViewChange()
void NetworkOPs::setMode(OperatingMode om) void NetworkOPs::setMode(OperatingMode om)
{ {
if (mMode == om) return; if (mMode == om) return;
if ((om >= omCONNECTED) && (mMode == omDISCONNECTED)) if ((om >= omCONNECTED) && (mMode == omDISCONNECTED))
mConnectTime = boost::posix_time::second_clock::universal_time(); mConnectTime = boost::posix_time::second_clock::universal_time();
Log lg((om < mMode) ? lsWARNING : lsINFO); Log lg((om < mMode) ? lsWARNING : lsINFO);
if (om == omDISCONNECTED) if (om == omDISCONNECTED)
lg << "STATE->Disconnected"; lg << "STATE->Disconnected";
@@ -878,6 +880,25 @@ void NetworkOPs::setMode(OperatingMode om)
lg << "STATE->Tracking"; lg << "STATE->Tracking";
else else
lg << "STATE->Full"; lg << "STATE->Full";
if ((om == omDISCONNECTED) || (mMode == omDISCONNECTED))
{
boost::recursive_mutex::scoped_lock sl(mMonitorLock);
if (!mSubServer.empty())
{
Json::Value jvObj(Json::objectValue);
jvObj["type"] = "serverStatus";
jvObj["server_status"] = om >= omCONNECTED ? "ok" : "noNetwork";
BOOST_FOREACH(InfoSub* ispListener, mSubServer)
{
ispListener->send(jvObj);
}
}
}
mMode = om; mMode = om;
} }
@@ -1311,19 +1332,8 @@ bool NetworkOPs::subServer(InfoSub* ispListener, Json::Value& jvResult)
jvResult["stand_alone"] = theConfig.RUN_STANDALONE; jvResult["stand_alone"] = theConfig.RUN_STANDALONE;
switch (RAND_bytes(uRandom.begin(), uRandom.size())) getRand(uRandom.begin(), uRandom.size());
{ jvResult["random"] = uRandom.ToString();
case 0:
case 1:
jvResult["random"] = uRandom.ToString();
break;
case -1:
default:
// XXX Should probably stop running.
cLog(lsFATAL) << "Internal error: unable to generate secure random.";
break;
}
return mSubServer.insert(ispListener).second; return mSubServer.insert(ispListener).second;
} }

View File

@@ -61,7 +61,7 @@ uint256 ProofOfWork::solve(int maxIterations) const
throw std::runtime_error("invalid proof of work target/iteration"); throw std::runtime_error("invalid proof of work target/iteration");
uint256 nonce; uint256 nonce;
RAND_bytes(nonce.begin(), nonce.size()); getRand(nonce.begin(), nonce.size());
std::vector<uint256> buf2; std::vector<uint256> buf2;
buf2.resize(mIterations); buf2.resize(mIterations);
@@ -112,7 +112,7 @@ bool ProofOfWork::checkSolution(const uint256& solution) const
ProofOfWorkGenerator::ProofOfWorkGenerator() : mValidTime(180) ProofOfWorkGenerator::ProofOfWorkGenerator() : mValidTime(180)
{ {
setDifficulty(1); setDifficulty(1);
RAND_bytes(mSecret.begin(), mSecret.size()); getRand(mSecret.begin(), mSecret.size());
} }
ProofOfWork ProofOfWorkGenerator::getProof() ProofOfWork ProofOfWorkGenerator::getProof()
@@ -123,7 +123,7 @@ ProofOfWork ProofOfWorkGenerator::getProof()
int now = static_cast<int>(time(NULL) / 4); int now = static_cast<int>(time(NULL) / 4);
uint256 challenge; uint256 challenge;
RAND_bytes(challenge.begin(), challenge.size()); getRand(challenge.begin(), challenge.size());
boost::mutex::scoped_lock sl(mLock); boost::mutex::scoped_lock sl(mLock);

View File

@@ -58,7 +58,6 @@ Json::Value rpcError(int iError, Json::Value jvResult)
{ rpcSRC_ACT_MISSING, "srcActMissing", "Source account does not exist." }, { rpcSRC_ACT_MISSING, "srcActMissing", "Source account does not exist." },
{ rpcSRC_AMT_MALFORMED, "srcAmtMalformed", "Source amount/currency/issuer is malformed." }, { rpcSRC_AMT_MALFORMED, "srcAmtMalformed", "Source amount/currency/issuer is malformed." },
{ rpcSRC_UNCLAIMED, "srcUnclaimed", "Source account is not claimed." }, { rpcSRC_UNCLAIMED, "srcUnclaimed", "Source account is not claimed." },
{ rpcSUCCESS, "success", "Success." },
{ rpcTXN_NOT_FOUND, "txnNotFound", "Transaction not found." }, { rpcTXN_NOT_FOUND, "txnNotFound", "Transaction not found." },
{ rpcUNKNOWN_COMMAND, "unknownCmd", "Unknown command." }, { rpcUNKNOWN_COMMAND, "unknownCmd", "Unknown command." },
{ rpcWRONG_SEED, "wrongSeed", "The regular key does not point as the master key." }, { rpcWRONG_SEED, "wrongSeed", "The regular key does not point as the master key." },

View File

@@ -4,8 +4,7 @@
#include "../json/value.h" #include "../json/value.h"
enum { enum {
rpcSUCCESS, rpcSUCCESS = 0,
rpcBAD_SYNTAX, // Must be 1 to print usage to command line. rpcBAD_SYNTAX, // Must be 1 to print usage to command line.
rpcJSON_RPC, rpcJSON_RPC,

View File

@@ -664,24 +664,16 @@ Json::Value RPCHandler::doRandom(Json::Value jvRequest)
{ {
uint256 uRandom; uint256 uRandom;
switch (RAND_bytes(uRandom.begin(), uRandom.size())) try
{ {
case 0: getRand(uRandom.begin(), uRandom.size());
case 1: Json::Value jvResult;
{ jvResult["random"] = uRandom.ToString();
Json::Value jvResult; return jvResult;
}
jvResult["random"] = uRandom.ToString(); catch (...)
{
return jvResult; return rpcError(rpcINTERNAL);
}
break;
case -1:
return rpcError(rpcNOT_SUPPORTED);
default:
return rpcError(rpcINTERNAL);
} }
} }
@@ -1572,7 +1564,7 @@ Json::Value RPCHandler::doLogLevel(Json::Value jvRequest)
if (!jvRequest.isMember("partition")) if (!jvRequest.isMember("partition"))
{ // set base log severity { // set base log severity
Log::setMinSeverity(sv, true); Log::setMinSeverity(sv, true);
return rpcError(rpcSUCCESS); return Json::objectValue;
} }
// log_level partition severity base? // log_level partition severity base?
@@ -1584,7 +1576,7 @@ Json::Value RPCHandler::doLogLevel(Json::Value jvRequest)
else if (!LogPartition::setSeverity(partition, sv)) else if (!LogPartition::setSeverity(partition, sv))
return rpcError(rpcINVALID_PARAMS); return rpcError(rpcINVALID_PARAMS);
return rpcError(rpcSUCCESS); return Json::objectValue;
} }
return rpcError(rpcINVALID_PARAMS); return rpcError(rpcINVALID_PARAMS);
@@ -2092,6 +2084,7 @@ Json::Value RPCHandler::doSubscribe(Json::Value jvRequest)
if(streamName=="server") if(streamName=="server")
{ {
mNetOps->subServer(mInfoSub, jvResult); mNetOps->subServer(mInfoSub, jvResult);
jvResult["server_status"] = mNetOps->available() ? "ok" : "noNetwork";
}else if(streamName=="ledger") }else if(streamName=="ledger")
{ {
mNetOps->subLedger(mInfoSub, jvResult); mNetOps->subLedger(mInfoSub, jvResult);

View File

@@ -792,7 +792,7 @@ void RippleAddress::setSeedRandom()
// XXX Maybe we should call MakeNewKey // XXX Maybe we should call MakeNewKey
uint128 key; uint128 key;
RAND_bytes(key.begin(), key.size()); getRand(key.begin(), key.size());
RippleAddress::setSeed(key); RippleAddress::setSeed(key);
} }

View File

@@ -78,7 +78,7 @@ void SNTPClient::resolveComplete(const boost::system::error_code& error, boost::
} }
query.mReceivedReply = false; query.mReceivedReply = false;
query.mLocalTimeSent = now; query.mLocalTimeSent = now;
RAND_bytes(reinterpret_cast<unsigned char *>(&query.mQueryNonce), sizeof(query.mQueryNonce)); getRand(reinterpret_cast<unsigned char *>(&query.mQueryNonce), sizeof(query.mQueryNonce));
reinterpret_cast<uint32*>(SNTPQueryData)[NTP_OFF_XMITTS_INT] = time(NULL) + NTP_UNIX_OFFSET; reinterpret_cast<uint32*>(SNTPQueryData)[NTP_OFF_XMITTS_INT] = time(NULL) + NTP_UNIX_OFFSET;
reinterpret_cast<uint32*>(SNTPQueryData)[NTP_OFF_XMITTS_FRAC] = query.mQueryNonce; reinterpret_cast<uint32*>(SNTPQueryData)[NTP_OFF_XMITTS_FRAC] = query.mQueryNonce;
mSocket.async_send_to(boost::asio::buffer(SNTPQueryData, 48), *sel, mSocket.async_send_to(boost::asio::buffer(SNTPQueryData, 48), *sel,

View File

@@ -1,102 +0,0 @@
//
// WSConnection
//
#include "Log.h"
SETUP_LOG();
#include "CallRPC.h" // XXX Remove this, don't provide support for RPC syntax.
#include "WSConnection.h"
#include "WSHandler.h"
#include "../json/reader.h"
#include "../json/writer.h"
WSConnection::~WSConnection()
{
mNetwork.unsubTransactions(this);
mNetwork.unsubRTTransactions(this);
mNetwork.unsubLedger(this);
mNetwork.unsubServer(this);
mNetwork.unsubAccount(this, mSubAccountInfo, true);
mNetwork.unsubAccount(this, mSubAccountInfo, false);
}
void WSConnection::send(const Json::Value& jvObj)
{
mHandler->send(mConnection, jvObj);
}
//
// Utilities
//
Json::Value WSConnection::invokeCommand(Json::Value& jvRequest)
{
if (!jvRequest.isMember("command"))
{
Json::Value jvResult(Json::objectValue);
jvResult["type"] = "response";
jvResult["result"] = "error";
jvResult["error"] = "missingCommand";
jvResult["command"] = jvRequest;
return jvResult;
}
RPCHandler mRPCHandler(&mNetwork, this);
Json::Value jvResult(Json::objectValue);
// XXX Temporarily support RPC style commands over websocket. Remove this.
if (jvRequest.isMember("params"))
{
RPCParser rpParser;
Json::Value jvRpcRequest = rpParser.parseCommand(jvRequest["command"].asString(), jvRequest["params"]);
if (jvRpcRequest.isMember("error"))
{
jvResult = jvRpcRequest;
}
else
{
jvResult["result"] = mRPCHandler.doCommand(
jvRpcRequest,
mHandler->getPublic() ? RPCHandler::GUEST : RPCHandler::ADMIN);
}
}
else
{
jvResult["result"] = mRPCHandler.doCommand(
jvRequest,
mHandler->getPublic() ? RPCHandler::GUEST : RPCHandler::ADMIN);
}
// Currently we will simply unwrap errors returned by the RPC
// API, in the future maybe we can make the responses
// consistent.
//
// Regularize result. This is duplicate code.
if (jvResult["result"].isMember("error"))
{
jvResult = jvResult["result"];
jvResult["status"] = "error";
jvResult["request"] = jvRequest;
} else {
jvResult["status"] = "success";
}
if (jvRequest.isMember("id"))
{
jvResult["id"] = jvRequest["id"];
}
jvResult["type"] = "response";
return jvResult;
}
// vim:ts=4

View File

@@ -1,10 +1,14 @@
#include "../websocketpp/src/sockets/tls.hpp" #include "../websocketpp/src/sockets/tls.hpp"
#include "../websocketpp/src/websocketpp.hpp" #include "../websocketpp/src/websocketpp.hpp"
#include "../json/value.h"
#include "WSDoor.h" #include "WSDoor.h"
#include "Application.h" #include "Application.h"
#include "Log.h" #include "Log.h"
#include "NetworkOPs.h" #include "NetworkOPs.h"
#include "CallRPC.h"
template <typename endpoint_type> template <typename endpoint_type>
class WSServerHandler; class WSServerHandler;
@@ -12,16 +16,17 @@ class WSServerHandler;
// Storage for connection specific info // Storage for connection specific info
// - Subscriptions // - Subscriptions
// //
template <typename endpoint_type>
class WSConnection : public InfoSub class WSConnection : public InfoSub
{ {
public: public:
typedef websocketpp::WSDOOR_SERVER::handler::connection_ptr connection_ptr; typedef typename endpoint_type::handler::connection_ptr connection_ptr;
typedef websocketpp::WSDOOR_SERVER::handler::message_ptr message_ptr; typedef typename endpoint_type::handler::message_ptr message_ptr;
protected: protected:
typedef void (WSConnection::*doFuncPtr)(Json::Value& jvResult, Json::Value &jvRequest); typedef void (WSConnection::*doFuncPtr)(Json::Value& jvResult, Json::Value &jvRequest);
WSServerHandler<websocketpp::WSDOOR_SERVER>* mHandler; WSServerHandler<endpoint_type>* mHandler;
connection_ptr mConnection; connection_ptr mConnection;
NetworkOPs& mNetwork; NetworkOPs& mNetwork;
@@ -30,17 +35,95 @@ public:
// : mHandler((WSServerHandler<websocketpp::WSDOOR_SERVER>*)(NULL)), // : mHandler((WSServerHandler<websocketpp::WSDOOR_SERVER>*)(NULL)),
// mConnection(connection_ptr()) { ; } // mConnection(connection_ptr()) { ; }
WSConnection(WSServerHandler<websocketpp::WSDOOR_SERVER>* wshpHandler, connection_ptr cpConnection) WSConnection(WSServerHandler<endpoint_type>* wshpHandler, connection_ptr cpConnection)
: mHandler(wshpHandler), mConnection(cpConnection), mNetwork(theApp->getOPs()) { ; } : mHandler(wshpHandler), mConnection(cpConnection), mNetwork(theApp->getOPs()) { ; }
virtual ~WSConnection();
virtual ~WSConnection()
{
mNetwork.unsubTransactions(this);
mNetwork.unsubRTTransactions(this);
mNetwork.unsubLedger(this);
mNetwork.unsubServer(this);
mNetwork.unsubAccount(this, mSubAccountInfo, true);
mNetwork.unsubAccount(this, mSubAccountInfo, false);
}
// Implement overridden functions from base class: // Implement overridden functions from base class:
void send(const Json::Value& jvObj); void send(const Json::Value& jvObj)
{
mHandler->send(mConnection, jvObj);
}
// Utilities // Utilities
Json::Value invokeCommand(Json::Value& jvRequest); Json::Value invokeCommand(Json::Value& jvRequest)
{
if (!jvRequest.isMember("command"))
{
Json::Value jvResult(Json::objectValue);
jvResult["type"] = "response";
jvResult["result"] = "error";
jvResult["error"] = "missingCommand";
jvResult["command"] = jvRequest;
return jvResult;
}
RPCHandler mRPCHandler(&mNetwork, this);
Json::Value jvResult(Json::objectValue);
// XXX Temporarily support RPC style commands over websocket. Remove this.
if (jvRequest.isMember("params"))
{
RPCParser rpParser;
Json::Value jvRpcRequest = rpParser.parseCommand(jvRequest["command"].asString(), jvRequest["params"]);
if (jvRpcRequest.isMember("error"))
{
jvResult = jvRpcRequest;
}
else
{
jvResult["result"] = mRPCHandler.doCommand(
jvRpcRequest,
mHandler->getPublic() ? RPCHandler::GUEST : RPCHandler::ADMIN);
}
}
else
{
jvResult["result"] = mRPCHandler.doCommand(
jvRequest,
mHandler->getPublic() ? RPCHandler::GUEST : RPCHandler::ADMIN);
}
// Currently we will simply unwrap errors returned by the RPC
// API, in the future maybe we can make the responses
// consistent.
//
// Regularize result. This is duplicate code.
if (jvResult["result"].isMember("error"))
{
jvResult = jvResult["result"];
jvResult["status"] = "error";
jvResult["request"] = jvRequest;
} else {
jvResult["status"] = "success";
}
if (jvRequest.isMember("id"))
{
jvResult["id"] = jvRequest["id"];
}
jvResult["type"] = "response";
return jvResult;
}
}; };
// vim:ts=4 // vim:ts=4

View File

@@ -9,6 +9,7 @@ SETUP_LOG();
#include "utils.h" #include "utils.h"
#include "WSConnection.h" #include "WSConnection.h"
#include "WSHandler.h" #include "WSHandler.h"
#include "Config.h"
#include "WSDoor.h" #include "WSDoor.h"
@@ -53,21 +54,42 @@ void WSDoor::startListening()
SSL_CTX_set_tmp_dh_callback(mCtx->native_handle(), handleTmpDh); SSL_CTX_set_tmp_dh_callback(mCtx->native_handle(), handleTmpDh);
// Construct a single handler for all requests. if(theConfig.WEBSOCKET_SECURE)
websocketpp::WSDOOR_SERVER::handler::ptr handler(new WSServerHandler<websocketpp::WSDOOR_SERVER>(mCtx, mPublic)); {
// Construct a single handler for all requests.
websocketpp::server_tls::handler::ptr handler(new WSServerHandler<websocketpp::server_tls>(mCtx, mPublic));
// Construct a websocket server. // Construct a websocket server.
mEndpoint = new websocketpp::WSDOOR_SERVER(handler); mSEndpoint = new websocketpp::server_tls(handler);
// mEndpoint->alog().unset_level(websocketpp::log::alevel::ALL); // mEndpoint->alog().unset_level(websocketpp::log::alevel::ALL);
// mEndpoint->elog().unset_level(websocketpp::log::elevel::ALL); // mEndpoint->elog().unset_level(websocketpp::log::elevel::ALL);
// Call the main-event-loop of the websocket server. // Call the main-event-loop of the websocket server.
mEndpoint->listen( mSEndpoint->listen(
boost::asio::ip::tcp::endpoint( boost::asio::ip::tcp::endpoint(
boost::asio::ip::address().from_string(mIp), mPort)); boost::asio::ip::address().from_string(mIp), mPort));
delete mEndpoint; delete mSEndpoint;
}else
{
// Construct a single handler for all requests.
websocketpp::server::handler::ptr handler(new WSServerHandler<websocketpp::server>(mCtx, mPublic));
// Construct a websocket server.
mEndpoint = new websocketpp::server(handler);
// mEndpoint->alog().unset_level(websocketpp::log::alevel::ALL);
// mEndpoint->elog().unset_level(websocketpp::log::elevel::ALL);
// Call the main-event-loop of the websocket server.
mEndpoint->listen(
boost::asio::ip::tcp::endpoint(
boost::asio::ip::address().from_string(mIp), mPort));
delete mEndpoint;
}
} }
WSDoor* WSDoor::createWSDoor(const std::string& strIp, const int iPort, bool bPublic) WSDoor* WSDoor::createWSDoor(const std::string& strIp, const int iPort, bool bPublic)
@@ -89,7 +111,11 @@ void WSDoor::stop()
{ {
if (mThread) if (mThread)
{ {
mEndpoint->stop(); if (mEndpoint)
mEndpoint->stop();
if (mSEndpoint)
mSEndpoint->stop();
mThread->join(); mThread->join();
} }

View File

@@ -10,16 +10,12 @@
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/thread.hpp> #include <boost/thread.hpp>
#if 1
#define WSDOOR_SERVER server
#else
#define WSDOOR_SERVER server_tls
#endif
class WSDoor class WSDoor
{ {
private: private:
websocketpp::WSDOOR_SERVER* mEndpoint; websocketpp::server* mEndpoint;
websocketpp::server_tls* mSEndpoint;
boost::thread* mThread; boost::thread* mThread;
bool mPublic; bool mPublic;
std::string mIp; std::string mIp;
@@ -29,7 +25,7 @@ private:
public: public:
WSDoor(const std::string& strIp, int iPort, bool bPublic) : mEndpoint(0), mThread(0), mPublic(bPublic), mIp(strIp), mPort(iPort) { ; } WSDoor(const std::string& strIp, int iPort, bool bPublic) : mEndpoint(0), mSEndpoint(0), mThread(0), mPublic(bPublic), mIp(strIp), mPort(iPort) { ; }
void stop(); void stop();

View File

@@ -2,7 +2,9 @@
#define __WSHANDLER__ #define __WSHANDLER__
#include "Application.h" #include "Application.h"
#include "Config.h"
template <typename endpoint_type>
class WSConnection; class WSConnection;
// A single instance of this object is made. // A single instance of this object is made.
@@ -25,7 +27,7 @@ private:
protected: protected:
boost::mutex mMapLock; boost::mutex mMapLock;
// For each connection maintain an associated object to track subscriptions. // For each connection maintain an associated object to track subscriptions.
boost::unordered_map<connection_ptr, boost::shared_ptr<WSConnection> > mMap; boost::unordered_map<connection_ptr, boost::shared_ptr< WSConnection<endpoint_type> > > mMap;
bool mPublic; bool mPublic;
public: public:
@@ -33,10 +35,7 @@ public:
bool getPublic() { return mPublic; }; bool getPublic() { return mPublic; };
boost::shared_ptr<boost::asio::ssl::context> on_tls_init()
{
return mCtx;
}
void send(connection_ptr cpClient, message_ptr mpMessage) void send(connection_ptr cpClient, message_ptr mpMessage)
{ {
@@ -77,7 +76,7 @@ public:
{ {
boost::mutex::scoped_lock sl(mMapLock); boost::mutex::scoped_lock sl(mMapLock);
mMap[cpClient] = boost::make_shared<WSConnection>(this, cpClient); mMap[cpClient] = boost::make_shared< WSConnection<endpoint_type> >(this, cpClient);
} }
void on_close(connection_ptr cpClient) void on_close(connection_ptr cpClient)
@@ -116,7 +115,7 @@ public:
} }
else else
{ {
boost::shared_ptr<WSConnection> conn; boost::shared_ptr< WSConnection<endpoint_type> > conn;
{ {
boost::mutex::scoped_lock sl(mMapLock); boost::mutex::scoped_lock sl(mMapLock);
conn = mMap[cpClient]; conn = mMap[cpClient];
@@ -127,6 +126,35 @@ public:
} }
} }
boost::shared_ptr<boost::asio::ssl::context> on_tls_init()
{
if(theConfig.WEBSOCKET_SECURE)
{
// create a tls context, init, and return.
boost::shared_ptr<boost::asio::ssl::context> context(new boost::asio::ssl::context(boost::asio::ssl::context::tlsv1));
try {
context->set_options(boost::asio::ssl::context::default_workarounds |
boost::asio::ssl::context::no_sslv2 |
boost::asio::ssl::context::single_dh_use);
// context->set_password_callback(boost::bind(&type::get_password, this));
if (!theConfig.WEBSOCKET_SSL_CERT.empty())
context->use_certificate_file(theConfig.WEBSOCKET_SSL_CERT, boost::asio::ssl::context::pem);
if (!theConfig.WEBSOCKET_SSL_KEY.empty())
context->use_private_key_file(theConfig.WEBSOCKET_SSL_KEY, boost::asio::ssl::context::pem);
if (!theConfig.WEBSOCKET_SSL_CHAIN.empty())
context->use_certificate_chain_file(theConfig.WEBSOCKET_SSL_CHAIN);
//context->use_tmp_dh_file("../../src/ssl/dh512.pem");
} catch (std::exception& e) {
std::cout << e.what() << std::endl;
}
return context;
}else
{
return mCtx;
}
}
// Respond to http requests. // Respond to http requests.
void http(connection_ptr cpClient) void http(connection_ptr cpClient)
{ {

View File

@@ -5,6 +5,17 @@
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/regex.hpp> #include <boost/regex.hpp>
#include <openssl/rand.h>
void getRand(unsigned char *buf, int num)
{
if (RAND_bytes(buf, num) != 1)
{
assert(false);
throw std::runtime_error("Entropy pool not seeded");
}
}
// //
// Time support // Time support
// We have our own epoch. // We have our own epoch.

View File

@@ -189,6 +189,10 @@ bool parseQuality(const std::string& strSource, uint32& uQuality);
DH* DH_der_load(const std::string& strDer); DH* DH_der_load(const std::string& strDer);
std::string DH_der_gen(int iKeyLength); std::string DH_der_gen(int iKeyLength);
void getRand(unsigned char *buf, int num);
inline static void getRand(char *buf, int num) { return getRand(reinterpret_cast<unsigned char *>(buf), num); }
inline static void getRand(void *buf, int num) { return getRand(reinterpret_cast<unsigned char *>(buf), num); }
inline std::string strGetEnv(const std::string& strKey) inline std::string strGetEnv(const std::string& strKey)
{ {
return getenv(strKey.c_str()) ? getenv(strKey.c_str()) : ""; return getenv(strKey.c_str()) ? getenv(strKey.c_str()) : "";

View File

@@ -499,12 +499,16 @@ Amount.prototype.to_human = function (opts)
if ("undefined" === typeof opts.group_sep) opts.group_sep = true; if ("undefined" === typeof opts.group_sep) opts.group_sep = true;
opts.group_width = opts.group_width || 3; opts.group_width = opts.group_width || 3;
var denominator = this._is_native ? var order = this._is_native ? consts.xns_precision : -this._offset;
consts.bi_xns_unit : var denominator = consts.bi_10.clone().pow(order);
consts.bi_10.clone().pow(-this._offset);
var int_part = this._value.divide(denominator).toString(10); var int_part = this._value.divide(denominator).toString(10);
var fraction_part = this._value.mod(denominator).toString(10); var fraction_part = this._value.mod(denominator).toString(10);
// Add leading zeros to fraction
while (fraction_part.length < order) {
fraction_part = "0" + fraction_part;
}
int_part = int_part.replace(/^0*/, ''); int_part = int_part.replace(/^0*/, '');
fraction_part = fraction_part.replace(/0*$/, ''); fraction_part = fraction_part.replace(/0*$/, '');

View File

@@ -191,6 +191,7 @@ var Remote = function (opts, trace) {
this.trusted = opts.trusted; this.trusted = opts.trusted;
this.websocket_ip = opts.websocket_ip; this.websocket_ip = opts.websocket_ip;
this.websocket_port = opts.websocket_port; this.websocket_port = opts.websocket_port;
this.websocket_ssl = opts.websocket_ssl;
this.local_sequence = opts.local_sequence; // Locally track sequence numbers this.local_sequence = opts.local_sequence; // Locally track sequence numbers
this.local_fee = opts.local_fee; // Locally set fees this.local_fee = opts.local_fee; // Locally set fees
this.id = 0; this.id = 0;
@@ -384,7 +385,8 @@ Remote.prototype._connect_start = function () {
// with self-signed certs as the user must have pre-approved the self-signed certs. // with self-signed certs as the user must have pre-approved the self-signed certs.
var self = this; var self = this;
var url = "ws://" + this.websocket_ip + ":" + this.websocket_port; var url = (this.websocket_ssl ? "wss://" : "ws://") +
this.websocket_ip + ":" + this.websocket_port;
if (this.trace) console.log("remote: connect: %s", url); if (this.trace) console.log("remote: connect: %s", url);
@@ -412,8 +414,6 @@ Remote.prototype._connect_start = function () {
}; };
if (self.online_target) { if (self.online_target) {
self._set_state('online');
// Note, we could get disconnected before this goes through. // Note, we could get disconnected before this goes through.
self._server_subscribe(); // Automatically subscribe. self._server_subscribe(); // Automatically subscribe.
} }
@@ -493,6 +493,10 @@ Remote.prototype._connect_message = function (ws, json) {
this.emit('ledger_closed', message); this.emit('ledger_closed', message);
break; break;
case 'serverStatus':
this._set_state(message.server_status === 'ok' ? 'online' : 'offline');
break;
// All other messages // All other messages
default: default:
if (this.trace) utils.logObject("remote: "+message.type+": %s", message); if (this.trace) utils.logObject("remote: "+message.type+": %s", message);
@@ -852,6 +856,10 @@ Remote.prototype._server_subscribe = function () {
self.emit('ledger_closed', message); self.emit('ledger_closed', message);
} }
if (message.server_status === "ok") {
self._set_state('online');
}
self.emit('subscribed'); self.emit('subscribed');
}) })
.request(); .request();

View File

@@ -23,6 +23,7 @@ exports.servers = {
'rpc_port' : 5005, 'rpc_port' : 5005,
'websocket_ip' : "127.0.0.1", 'websocket_ip' : "127.0.0.1",
'websocket_port' : 5006, 'websocket_port' : 5006,
'websocket_ssl' : false,
'local_sequence' : true, 'local_sequence' : true,
'local_fee' : true, 'local_fee' : true,
// 'validation_seed' : "shhDFVsmS2GSu5vUyZSPXYfj1r79h", // 'validation_seed' : "shhDFVsmS2GSu5vUyZSPXYfj1r79h",