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

Conflicts:
	src/RPCServer.cpp
This commit is contained in:
jed
2012-06-24 22:56:18 -07:00
10 changed files with 412 additions and 103 deletions

BIN
LICENSE Normal file

Binary file not shown.

View File

@@ -35,14 +35,12 @@ LedgerEntryFormat LedgerFormats[]=
},
{ "GeneratorMap", ltGENERATOR_MAP, {
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
// { S_FIELD(GeneratorID), STI_HASH160, SOE_REQUIRED, 0 },
{ S_FIELD(Generator), STI_VL, SOE_REQUIRED, 0 },
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
},
{ "Nickname", ltNICKNAME, {
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
// { S_FIELD(Nickname), STI_HASH256, SOE_REQUIRED, 0 },
{ S_FIELD(Account), STI_ACCOUNT, SOE_REQUIRED, 0 },
{ S_FIELD(MinimumOffer), STI_AMOUNT, SOE_IFFLAG, 1 },
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },

View File

@@ -1,15 +1,16 @@
#include "NetworkOPs.h"
#include <boost/bind.hpp>
#include <boost/unordered_map.hpp>
#include "utils.h"
#include "Application.h"
#include "Transaction.h"
#include "LedgerConsensus.h"
#include "LedgerTiming.h"
#include "Log.h"
#include "NewcoinAddress.h"
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
// This is the primary interface into the "client" portion of the program.
// Code that wants to do normal operations on the network such as
@@ -669,4 +670,92 @@ Json::Value NetworkOPs::getServerInfo()
return info;
}
//
// Monitoring:: publisher side
//
void NetworkOPs::pubAccountInfo(const NewcoinAddress& naAccountID, const Json::Value& jvObj)
{
boost::interprocess::sharable_lock<boost::interprocess::interprocess_upgradable_mutex> sl(mMonitorLock);
subInfoMapType::iterator simIterator = mSubAccountInfo.find(naAccountID);
if (simIterator == mSubAccountInfo.end())
{
// Address not found do nothing.
nothing();
}
else
{
// Found it.
BOOST_FOREACH(InfoSub* ispListener, simIterator->second)
{
ispListener->send(jvObj);
}
}
}
//
// Monitoring
//
void NetworkOPs::subAccountInfo(InfoSub* ispListener, const std::vector<NewcoinAddress>& vnaAccountIDs)
{
boost::interprocess::scoped_lock<boost::interprocess::interprocess_upgradable_mutex> sl(mMonitorLock);
BOOST_FOREACH(NewcoinAddress naAccountID, vnaAccountIDs)
{
subInfoMapType::iterator simIterator = mSubAccountInfo.find(naAccountID);
if (simIterator == mSubAccountInfo.end())
{
// Not found
boost::unordered_set<InfoSub*> usisElement;
usisElement.insert(ispListener);
mSubAccountInfo.insert(simIterator, make_pair(naAccountID, usisElement));
}
else
{
// Found
simIterator->second.insert(ispListener);
}
}
}
void NetworkOPs::unsubAccountInfo(InfoSub* ispListener, const std::vector<NewcoinAddress>& vnaAccountIDs)
{
boost::interprocess::scoped_lock<boost::interprocess::interprocess_upgradable_mutex> sl(mMonitorLock);
BOOST_FOREACH(NewcoinAddress naAccountID, vnaAccountIDs)
{
subInfoMapType::iterator simIterator = mSubAccountInfo.find(naAccountID);
if (simIterator == mSubAccountInfo.end())
{
// Not found. Done.
nothing();
}
else
{
// Found
simIterator->second.erase(ispListener);
if (simIterator->second.empty())
{
// Don't need hash entry.
mSubAccountInfo.erase(simIterator);
}
}
}
}
void NetworkOPs::subAccountChanges(InfoSub* ispListener, const uint256 uLedgerHash)
{
}
void NetworkOPs::unsubAccountChanges(InfoSub* ispListener)
{
}
// vim:ts=4

View File

@@ -1,13 +1,16 @@
#ifndef __NETWORK_OPS__
#define __NETWORK_OPS__
#include "LedgerMaster.h"
#include "AccountState.h"
#include "RippleState.h"
#include "LedgerMaster.h"
#include "NicknameState.h"
#include "RippleState.h"
#include "SerializedValidation.h"
// #include <boost/asio.hpp>
#include <boost/interprocess/sync/interprocess_upgradable_mutex.hpp>
#include <boost/interprocess/sync/sharable_lock.hpp>
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
// Operations that clients may wish to perform against the network
// Master operational handler, server sequencer, network tracker
@@ -15,6 +18,12 @@
class Peer;
class LedgerConsensus;
class InfoSub
{
public:
virtual void send(const Json::Value& jvObj) = 0;
};
class NetworkOPs
{
public:
@@ -41,6 +50,12 @@ protected:
void setMode(OperatingMode);
typedef boost::unordered_map<NewcoinAddress,boost::unordered_set<InfoSub*> > subInfoMapType;
typedef boost::unordered_map<NewcoinAddress,boost::unordered_set<InfoSub*> >::iterator subInfoMapIterator;
boost::interprocess::interprocess_upgradable_mutex mMonitorLock;
subInfoMapType mSubAccountInfo;
public:
NetworkOPs(boost::asio::io_service& io_service, LedgerMaster* pLedgerMaster);
@@ -133,6 +148,23 @@ public:
// client information retrieval functions
std::vector< std::pair<uint32, uint256> >
getAffectedAccounts(const NewcoinAddress& account, uint32 minLedger, uint32 maxLedger);
//
// Monitoring: publisher side
//
void pubAccountInfo(const NewcoinAddress& naAccountID, const Json::Value& jvObj);
//
// Monitoring: subscriber side
//
// --> vnaAddress: empty = all
void subAccountInfo(InfoSub* ispListener, const std::vector<NewcoinAddress>& vnaAccountIDs);
void unsubAccountInfo(InfoSub* ispListener, const std::vector<NewcoinAddress>& vnaAccountIDs);
void subAccountChanges(InfoSub* ispListener, const uint256 uLedgerHash);
void unsubAccountChanges(InfoSub* ispListener);
};
#endif

View File

@@ -1164,7 +1164,7 @@ Json::Value Peer::getJson()
{
Json::Value ret(Json::objectValue);
ret["this"] = ADDRESS(this);
//ret["this"] = ADDRESS(this);
ret["public_key"] = mNodePublic.ToString();
ret["ip"] = mIpPortConnect.first;
ret["port"] = mIpPortConnect.second;
@@ -1178,12 +1178,12 @@ Json::Value Peer::getJson()
if (mHello.has_protoversionminor() && mHello.has_protoversionmajor())
ret["protocol"] = boost::lexical_cast<std::string>(mHello.protoversionmajor()) + "." +
boost::lexical_cast<std::string>(mHello.protoversionminor());
/*
if (!mIpPort.first.empty())
{
ret["verified_ip"] = mIpPort.first;
ret["verified_port"] = mIpPort.second;
}
}*/
return ret;
}

View File

@@ -1,16 +1,4 @@
#include <iostream>
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include <openssl/md5.h>
#include "../json/reader.h"
#include "../json/writer.h"
#include "RPCServer.h"
#include "RequestParser.h"
#include "HttpReply.h"
@@ -25,6 +13,18 @@
#include "utils.h"
#include "Log.h"
#include <iostream>
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include <openssl/md5.h>
#include "../json/reader.h"
#include "../json/writer.h"
RPCServer::RPCServer(boost::asio::io_service& io_service , NetworkOPs* nopNetwork)
: mNetOps(nopNetwork), mSocket(io_service)
{
@@ -74,7 +74,6 @@ Json::Value RPCServer::RPCError(int iError)
{ rpcWRONG_PASSWORD, "wrongPassword", "Wrong password." },
{ rpcWRONG_SEED, "wrongSeed", "The regular key does not point as the master key." },
{ rpcNO_PERMISSION, "noPermission", "You don't have permission for this command." },
};
int i;
@@ -97,7 +96,7 @@ Json::Value RPCServer::RPCError(int iError)
void RPCServer::connected()
{
//std::cout << "RPC request" << std::endl;
if(mSocket.remote_endpoint().address().to_string()=="127.0.0.1") mRole=ADMIN;
if (mSocket.remote_endpoint().address().to_string()=="127.0.0.1") mRole=ADMIN;
else mRole=GUEST;
mSocket.async_read_some(boost::asio::buffer(mReadBuffer),
@@ -281,13 +280,14 @@ Json::Value RPCServer::authorize(const uint256& uLedger,
NewcoinAddress naMasterGenerator;
if(asSrc->bHaveAuthorizedKey())
if (asSrc->bHaveAuthorizedKey())
{
Json::Value obj = getMasterGenerator(uLedger, naRegularSeed, naMasterGenerator);
if (!obj.empty())
return obj;
}else
}
else
{
// Try the seed as a master seed.
naMasterGenerator = NewcoinAddress::createGeneratorPublic(naRegularSeed);
@@ -765,7 +765,7 @@ Json::Value RPCServer::doCreditSet(Json::Value& params)
NewcoinAddress naMasterGenerator;
NewcoinAddress naAccountPublic;
NewcoinAddress naAccountPrivate;
AccountState::pointer asSrc;
AccountState::pointer asSrc;
STAmount saSrcBalance;
Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate,
saSrcBalance, theConfig.FEE_DEFAULT, asSrc, naMasterGenerator);
@@ -1166,7 +1166,7 @@ Json::Value RPCServer::doSend(Json::Value& params)
NewcoinAddress naVerifyGenerator;
NewcoinAddress naAccountPublic;
NewcoinAddress naAccountPrivate;
AccountState::pointer asSrc;
AccountState::pointer asSrc;
STAmount saSrcBalance;
Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate,
saSrcBalance, saFee, asSrc, naVerifyGenerator);
@@ -1278,7 +1278,7 @@ Json::Value RPCServer::doTransitSet(Json::Value& params)
NewcoinAddress naMasterGenerator;
NewcoinAddress naAccountPublic;
NewcoinAddress naAccountPrivate;
AccountState::pointer asSrc;
AccountState::pointer asSrc;
STAmount saSrcBalance;
Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate,
saSrcBalance, theConfig.FEE_DEFAULT, asSrc, naMasterGenerator);
@@ -1630,7 +1630,7 @@ Json::Value RPCServer::doWalletAdd(Json::Value& params)
NewcoinAddress naAccountPublic;
NewcoinAddress naAccountPrivate;
AccountState::pointer asSrc;
AccountState::pointer asSrc;
STAmount saSrcBalance;
Json::Value obj = authorize(uLedger, naRegularSeed, naSrcAccountID, naAccountPublic, naAccountPrivate,
saSrcBalance, theConfig.FEE_ACCOUNT_CREATE, asSrc, naMasterGenerator);
@@ -1721,7 +1721,7 @@ Json::Value RPCServer::doWalletClaim(Json::Value& params)
else
{
// Building:
// peer_wallet_claim <account_id> <authorized_key> <encrypted_master_public_generator> <generator_pubkey> <generator_signature>
// peer_wallet_claim <account_id> <authorized_key> <encrypted_master_public_generator> <generator_pubkey> <generator_signature>
// <source_tag> [<annotation>]
//
//
@@ -1813,7 +1813,7 @@ Json::Value RPCServer::doWalletCreate(Json::Value& params)
}
// Trying to build:
// peer_wallet_create <paying_account> <paying_signature> <account_id> [<initial_funds>] [<annotation>]
// peer_wallet_create <paying_account> <paying_signature> <account_id> [<initial_funds>] [<annotation>]
NewcoinAddress naMasterGenerator;
NewcoinAddress naAccountPublic;
@@ -1965,7 +1965,7 @@ Json::Value RPCServer::doUnlScore(Json::Value& params)
return "scoring requested";
}
Json::Value RPCServer::doStop(Json::Value& params)
Json::Value RPCServer::doStop(Json::Value& params)
{
theApp->stop();
@@ -1980,7 +1980,7 @@ Json::Value RPCServer::doLogin(Json::Value& params)
std::string username = params[0u].asString();
std::string password = params[1u].asString();
if(username==theConfig.RPC_USER && password==theConfig.RPC_PASSWORD)
if (username==theConfig.RPC_USER && password==theConfig.RPC_PASSWORD)
{
//mRole=ADMIN;
return "logged in";
@@ -2002,48 +2002,48 @@ Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params
bool mAdminRequired;
unsigned int iOptions;
} commandsA[] = {
{ "account_email_set", &RPCServer::doAccountEmailSet, 2, 3, true,optCurrent },
{ "account_info", &RPCServer::doAccountInfo, 1, 2, false,optCurrent },
{ "account_lines", &RPCServer::doAccountLines, 1, 2, true,optCurrent|optClosed },
{ "account_message_set", &RPCServer::doAccountMessageSet, 3, 3, true,optCurrent },
{ "account_tx", &RPCServer::doAccountTransactions, 2, 3, true,optNetwork },
{ "account_wallet_set", &RPCServer::doAccountWalletSet, 2, 3, true,optCurrent },
{ "connect", &RPCServer::doConnect, 1, 2, true },
{ "credit_set", &RPCServer::doCreditSet, 4, 6, true,optCurrent },
{ "data_delete", &RPCServer::doDataDelete, 1, 1, true },
{ "data_fetch", &RPCServer::doDataFetch, 1, 1, true },
{ "data_store", &RPCServer::doDataStore, 2, 2, true },
{ "ledger", &RPCServer::doLedger, 0, 2, false,optNetwork },
{ "nickname_info", &RPCServer::doNicknameInfo, 1, 1, true,optCurrent },
{ "nickname_set", &RPCServer::doNicknameSet, 2, 3, true,optCurrent },
{ "password_fund", &RPCServer::doPasswordFund, 2, 3, true,optCurrent },
{ "password_set", &RPCServer::doPasswordSet, 2, 3, true,optNetwork },
{ "peers", &RPCServer::doPeers, 0, 0, true },
{ "send", &RPCServer::doSend, 3, 7, false, optCurrent },
{ "server_info", &RPCServer::doServerInfo, 0, 0, false },
{ "stop", &RPCServer::doStop, 0, 0, true },
{ "transit_set", &RPCServer::doTransitSet, 5, 5, true, optCurrent },
{ "tx", &RPCServer::doTx, 1, 1, true },
{ "account_email_set", &RPCServer::doAccountEmailSet, 2, 3, true, optCurrent },
{ "account_info", &RPCServer::doAccountInfo, 1, 2, false, optCurrent },
{ "account_lines", &RPCServer::doAccountLines, 1, 2, true, optCurrent|optClosed },
{ "account_message_set", &RPCServer::doAccountMessageSet, 3, 3, true, optCurrent },
{ "account_tx", &RPCServer::doAccountTransactions, 2, 3, true, optNetwork },
{ "account_wallet_set", &RPCServer::doAccountWalletSet, 2, 3, true, optCurrent },
{ "connect", &RPCServer::doConnect, 1, 2, true },
{ "credit_set", &RPCServer::doCreditSet, 4, 6, true, optCurrent },
{ "data_delete", &RPCServer::doDataDelete, 1, 1, true },
{ "data_fetch", &RPCServer::doDataFetch, 1, 1, true },
{ "data_store", &RPCServer::doDataStore, 2, 2, true },
{ "ledger", &RPCServer::doLedger, 0, 2, false, optNetwork },
{ "nickname_info", &RPCServer::doNicknameInfo, 1, 1, true, optCurrent },
{ "nickname_set", &RPCServer::doNicknameSet, 2, 3, true, optCurrent },
{ "password_fund", &RPCServer::doPasswordFund, 2, 3, true, optCurrent },
{ "password_set", &RPCServer::doPasswordSet, 2, 3, true, optNetwork },
{ "peers", &RPCServer::doPeers, 0, 0, true },
{ "send", &RPCServer::doSend, 3, 7, false, optCurrent },
{ "server_info", &RPCServer::doServerInfo, 0, 0, true },
{ "stop", &RPCServer::doStop, 0, 0, true },
{ "transit_set", &RPCServer::doTransitSet, 5, 5, true, optCurrent },
{ "tx", &RPCServer::doTx, 1, 1, true },
{ "unl_add", &RPCServer::doUnlAdd, 1, 2, true },
{ "unl_delete", &RPCServer::doUnlDelete, 1, 1, true },
{ "unl_list", &RPCServer::doUnlList, 0, 0, true },
{ "unl_load", &RPCServer::doUnlLoad, 0, 0, true },
{ "unl_network", &RPCServer::doUnlNetwork, 0, 0, true },
{ "unl_reset", &RPCServer::doUnlReset, 0, 0, true },
{ "unl_score", &RPCServer::doUnlScore, 0, 0, true },
{ "unl_add", &RPCServer::doUnlAdd, 1, 2, true },
{ "unl_delete", &RPCServer::doUnlDelete, 1, 1, true },
{ "unl_list", &RPCServer::doUnlList, 0, 0, true },
{ "unl_load", &RPCServer::doUnlLoad, 0, 0, true },
{ "unl_network", &RPCServer::doUnlNetwork, 0, 0, true },
{ "unl_reset", &RPCServer::doUnlReset, 0, 0, true },
{ "unl_score", &RPCServer::doUnlScore, 0, 0, true },
{ "validation_create", &RPCServer::doValidationCreate, 0, 1, false },
{ "validation_seed", &RPCServer::doValidationSeed, 0, 1, false },
{ "validation_create", &RPCServer::doValidationCreate, 0, 1, false },
{ "validation_seed", &RPCServer::doValidationSeed, 0, 1, false },
{ "wallet_accounts", &RPCServer::doWalletAccounts, 1, 1, false, optCurrent },
{ "wallet_add", &RPCServer::doWalletAdd, 3, 5, false, optCurrent },
{ "wallet_claim", &RPCServer::doWalletClaim, 2, 4, false, optNetwork },
{ "wallet_create", &RPCServer::doWalletCreate, 3, 4, false, optCurrent },
{ "wallet_propose", &RPCServer::doWalletPropose, 0, 0, false, },
{ "wallet_seed", &RPCServer::doWalletSeed, 0, 1, false, },
{ "wallet_accounts", &RPCServer::doWalletAccounts, 1, 1, false, optCurrent },
{ "wallet_add", &RPCServer::doWalletAdd, 3, 5, false, optCurrent },
{ "wallet_claim", &RPCServer::doWalletClaim, 2, 4, false, optNetwork },
{ "wallet_create", &RPCServer::doWalletCreate, 3, 4, false, optCurrent },
{ "wallet_propose", &RPCServer::doWalletPropose, 0, 0, false, },
{ "wallet_seed", &RPCServer::doWalletSeed, 0, 1, false, },
{ "login", &RPCServer::doLogin, 2, 2, true },
{ "login", &RPCServer::doLogin, 2, 2, true },
};
int i = NUMBER(commandsA);
@@ -2088,13 +2088,11 @@ void RPCServer::sendReply()
boost::asio::placeholders::error));
}
void RPCServer::handle_write(const boost::system::error_code& e)
{
//std::cout << "async_write complete " << e << std::endl;
if(!e)
if (!e)
{
// Initiate graceful connection closure.
boost::system::error_code ignored_ec;

View File

@@ -264,7 +264,6 @@ TransactionEngineResult TransactionEngine::setAuthorized(const SerializedTransac
sleGen = boost::make_shared<SerializedLedgerEntry>(ltGENERATOR_MAP);
sleGen->setIndex(Ledger::getGeneratorIndex(hGeneratorID));
// sleGen->setIFieldH160(sfGeneratorID, hGeneratorID);
sleGen->setIFieldVL(sfGenerator, vucCipher);
accounts.push_back(std::make_pair(taaCREATE, sleGen));
@@ -944,8 +943,6 @@ TransactionEngineResult TransactionEngine::doNicknameSet(const SerializedTransac
if (bMinOffer && !saMinOffer.isZero())
sleNickname->setIFieldAmount(sfMinimumOffer, saMinOffer);
// sleNickname->setIFieldH256(sfNickname, uNickname);
accounts.push_back(std::make_pair(taaCREATE, sleNickname));
}

View File

@@ -1,18 +1,31 @@
#include "WSDoor.h"
#include <iostream>
#include <boost/bind.hpp>
#include <boost/mem_fn.hpp>
#include "Application.h"
#include "Config.h"
#include "Log.h"
#include "NetworkOPs.h"
#include "utils.h"
using namespace std;
using namespace boost::asio::ip;
#include <iostream>
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/mem_fn.hpp>
#include "../json/reader.h"
#include "../json/writer.h"
//
// This is a light weight, untrusted interface for web clients.
// For now we don't provide proof. Later we will.
//
//
// Strategy:
// - We only talk to NetworkOPs (so we will work even in thin mode)
// - NetworkOPs is smart enough to subscribe and or pass back messages
//
// Generate DH for SSL connection.
static DH* handleTmpDh(SSL* ssl, int is_export, int iKeyLength)
@@ -20,17 +33,64 @@ static DH* handleTmpDh(SSL* ssl, int is_export, int iKeyLength)
return 512 == iKeyLength ? theApp->getWallet().getDh512() : theApp->getWallet().getDh1024();
}
template <typename endpoint_type>
class WSServerHandler;
//
// Storage for connection specific info
// - Subscriptions
//
class WSConnection : public InfoSub
{
public:
typedef typename websocketpp::WSDOOR_SERVER::handler::connection_ptr connection_ptr;
typedef typename websocketpp::WSDOOR_SERVER::handler::message_ptr message_ptr;
protected:
WSServerHandler<websocketpp::WSDOOR_SERVER>* mHandler;
connection_ptr mConnection;
public:
WSConnection()
: mHandler((WSServerHandler<websocketpp::WSDOOR_SERVER>*)(NULL)),
mConnection(connection_ptr()) { ; }
WSConnection(WSServerHandler<websocketpp::WSDOOR_SERVER>* wshpHandler, connection_ptr cpConnection)
: mHandler(wshpHandler), mConnection(cpConnection) { ; }
~WSConnection()
{
// XXX Unsubscribe.
nothing();
}
// Implement overriden functions from base class:
void send(const Json::Value& jvObj);
};
// A single instance of this object is made.
// This instance dispatches all events. There is no per connection persistency.
template <typename endpoint_type>
class WSServerHandler : public endpoint_type::handler {
private:
boost::shared_ptr<boost::asio::ssl::context> mCtx;
class WSServerHandler : public endpoint_type::handler
{
public:
typedef typename endpoint_type::handler::connection_ptr connection_ptr;
typedef typename endpoint_type::handler::message_ptr message_ptr;
// Private reasons to close.
enum {
crTooSlow = 4000, // Client is too slow.
};
private:
boost::shared_ptr<boost::asio::ssl::context> mCtx;
protected:
boost::mutex mMapLock;
boost::unordered_map<connection_ptr, WSConnection> mMap;
public:
WSServerHandler(boost::shared_ptr<boost::asio::ssl::context> spCtx) : mCtx(spCtx) {}
boost::shared_ptr<boost::asio::ssl::context> on_tls_init()
@@ -38,17 +98,103 @@ public:
return mCtx;
}
void on_message(connection_ptr con, message_ptr msg) {
con->send(msg->get_payload(), msg->get_opcode());
void send(connection_ptr cpClient, message_ptr mpMessage)
{
try
{
cpClient->send(mpMessage->get_payload(), mpMessage->get_opcode());
}
catch (...)
{
cpClient->close(websocketpp::close::status::value(crTooSlow), std::string("Client is too slow."));
}
}
void send(connection_ptr cpClient, const std::string& strMessage)
{
try
{
Log(lsINFO) << "Ws:: Sending '" << strMessage << "'";
cpClient->send(strMessage);
}
catch (...)
{
cpClient->close(websocketpp::close::status::value(crTooSlow), std::string("Client is too slow."));
}
}
void send(connection_ptr cpClient, const Json::Value& jvObj)
{
Json::FastWriter jfwWriter;
Log(lsINFO) << "Ws:: Object '" << jfwWriter.write(jvObj) << "'";
send(cpClient, jfwWriter.write(jvObj));
}
void on_open(connection_ptr cpClient)
{
boost::mutex::scoped_lock sl(mMapLock);
mMap[cpClient] = WSConnection(this, cpClient);
}
void on_close(connection_ptr cpClient)
{
boost::mutex::scoped_lock sl(mMapLock);
mMap.erase(cpClient);
}
void on_message(connection_ptr cpClient, message_ptr mpMessage)
{
Json::Value jvRequest;
Json::Reader jrReader;
if (mpMessage->get_opcode() != websocketpp::frame::opcode::TEXT)
{
Json::Value jvResult(Json::objectValue);
jvResult["type"] = "error";
jvResult["error"] = "wsTextRequired"; // We only accept text messages.
send(cpClient, jvResult);
}
else if (!jrReader.parse(mpMessage->get_payload(), jvRequest) || jvRequest.isNull() || !jvRequest.isObject())
{
Json::Value jvResult(Json::objectValue);
jvResult["type"] = "error";
jvResult["error"] = "jsonInvalid"; // Received invalid json.
jvResult["value"] = mpMessage->get_payload();
send(cpClient, jvResult);
}
else
{
Json::Value jvResult(Json::objectValue);
jvResult["type"] = "success";
jvResult["value"] = mpMessage->get_payload();
send(cpClient, jvResult);
}
}
void http(connection_ptr con) {
con->set_body("<!DOCTYPE html><html><head><title>WebSocket++ TLS certificate test</title></head><body><h1>WebSocket++ TLS certificate test</h1><p>This is an HTTP(S) page served by a WebSocket++ server for the purposes of confirming that certificates are working since browsers normally silently ignore certificate issues.</p></body></html>");
// Respond to http requests.
void http(connection_ptr cpClient)
{
cpClient->set_body(
"<!DOCTYPE html><html><head><title>" SYSTEM_NAME " Test</title></head>"
"<body><h1>" SYSTEM_NAME " Test</h1><p>This page shows http(s) connectivity is working.</p></body></html>");
}
};
void WSDoor::startListening()
{
// Generate a single SSL context for use by all connections.
boost::shared_ptr<boost::asio::ssl::context> mCtx;
mCtx = boost::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::sslv23);
@@ -59,20 +205,21 @@ void WSDoor::startListening()
SSL_CTX_set_tmp_dh_callback(mCtx->native_handle(), handleTmpDh);
// Construct a single handler for all requests.
websocketpp::WSDOOR_SERVER::handler::ptr handler(new WSServerHandler<websocketpp::WSDOOR_SERVER>(mCtx));
// Construct a websocket server.
mEndpoint = new websocketpp::WSDOOR_SERVER(handler);
// mEndpoint->alog().unset_level(websocketpp::log::alevel::ALL);
// mEndpoint->elog().unset_level(websocketpp::log::elevel::ALL);
Log(lsINFO) << "listening>";
// Call the main-event-loop of the websocket server.
mEndpoint->listen(
boost::asio::ip::tcp::endpoint(
boost::asio::ip::address().from_string(theConfig.WEBSOCKET_IP), theConfig.WEBSOCKET_PORT));
mEndpoint->listen(boost::asio::ip::tcp::endpoint(address().from_string(theConfig.WEBSOCKET_IP), theConfig.WEBSOCKET_PORT));
free(mEndpoint);
Log(lsINFO) << "listening<";
delete mEndpoint;
}
WSDoor* WSDoor::createWSDoor()
@@ -97,10 +244,15 @@ void WSDoor::stop()
{
if (mThread)
{
mEndpoint->stop(); // XXX Make this thread safe
mEndpoint->stop();
mThread->join();
}
}
void WSConnection::send(const Json::Value& jvObj)
{
mHandler->send(mConnection, jvObj);
}
// vim:ts=4

View File

@@ -19,8 +19,8 @@
class WSDoor
{
private:
websocketpp::WSDOOR_SERVER* mEndpoint;
boost::thread* mThread;
websocketpp::WSDOOR_SERVER* mEndpoint;
boost::thread* mThread;
void startListening();

View File

@@ -26,6 +26,49 @@
extern uint64_t htobe64(uint64_t value);
#endif
#define vt_f_black "\033[30m"
#define vt_f_red "\033[31m"
#define vt_f_green "\033[32m"
#define vt_f_yellow "\033[33m"
#define vt_f_blue "\033[34m"
#define vt_f_megenta "\033[35m"
#define vt_f_cyan "\033[36m"
#define vt_f_white "\033[37m"
#define vt_f_default "\033[39m"
#define vt_b_black "\033[40m"
#define vt_b_red "\033[41m"
#define vt_b_green "\033[42m"
#define vt_b_yellow "\033[43m"
#define vt_b_blue "\033[44m"
#define vt_b_megenta "\033[45m"
#define vt_b_cyan "\033[46m"
#define vt_b_white "\033[47m"
#define vt_b_default "\033[49m"
#define vt_f_bold_black "\033[1m\033[30m"
#define vt_f_bold_red "\033[1m\033[31m"
#define vt_f_bold_green "\033[1m\033[32m"
#define vt_f_bold_yellow "\033[1m\033[33m"
#define vt_f_bold_blue "\033[1m\033[34m"
#define vt_f_bold_megenta "\033[1m\033[35m"
#define vt_f_bold_cyan "\033[1m\033[36m"
#define vt_f_bold_white "\033[1m\033[37m"
#define vt_f_bold_default "\033[1m\033[39m"
#define vt_bold "\033[1m"
#define vt_dim "\033[2m" // does not work for xterm
#define vt_normal "\033[22m" // intensity
#define vt_n_enable "\033[7m" // negative
#define vt_n_disable "\033[27m"
#define vt_u_single "\033[4m" // underline
#define vt_u_double "\033[21m" // does not work for xterm
#define vt_u_disable "\033[24m"
#define vt_reset vt_f_default vt_b_default vt_normal vt_n_disable vt_u_disable
boost::posix_time::ptime ptEpoch();
int iToSeconds(boost::posix_time::ptime ptWhen);
boost::posix_time::ptime ptFromSeconds(int iSeconds);