net: Add most functions needed for vNodes to CConnman

This commit is contained in:
Cory Fields 2016-04-16 18:30:03 -04:00
parent 8ae2dac1c6
commit c0569c7fa1
8 changed files with 121 additions and 46 deletions

View file

@ -2267,6 +2267,72 @@ bool CConnman::RemoveAddedNode(const std::string& strNode)
return false; return false;
} }
size_t CConnman::GetNodeCount(NumConnections flags)
{
LOCK(cs_vNodes);
if (flags == CConnman::CONNECTIONS_ALL) // Shortcut if we want total
return vNodes.size();
int nNum = 0;
for(std::vector<CNode*>::const_iterator it = vNodes.begin(); it != vNodes.end(); ++it)
if (flags & ((*it)->fInbound ? CONNECTIONS_IN : CONNECTIONS_OUT))
nNum++;
return nNum;
}
void CConnman::GetNodeStats(std::vector<CNodeStats>& vstats)
{
vstats.clear();
LOCK(cs_vNodes);
vstats.reserve(vNodes.size());
for(std::vector<CNode*>::iterator it = vNodes.begin(); it != vNodes.end(); ++it) {
CNode* pnode = *it;
CNodeStats stats;
pnode->copyStats(stats);
vstats.push_back(stats);
}
}
bool CConnman::DisconnectAddress(const CNetAddr& netAddr)
{
if (CNode* pnode = FindNode(netAddr)) {
pnode->fDisconnect = true;
return true;
}
return false;
}
bool CConnman::DisconnectSubnet(const CSubNet& subNet)
{
if (CNode* pnode = FindNode(subNet)) {
pnode->fDisconnect = true;
return true;
}
return false;
}
bool CConnman::DisconnectNode(const std::string& strNode)
{
if (CNode* pnode = FindNode(strNode)) {
pnode->fDisconnect = true;
return true;
}
return false;
}
bool CConnman::DisconnectNode(NodeId id)
{
LOCK(cs_vNodes);
for(CNode* pnode : vNodes) {
if (id == pnode->id) {
pnode->fDisconnect = true;
return true;
}
}
return false;
}
void RelayTransaction(const CTransaction& tx) void RelayTransaction(const CTransaction& tx)
{ {
CInv inv(MSG_TX, tx.GetHash()); CInv inv(MSG_TX, tx.GetHash());

View file

@ -101,9 +101,18 @@ CNode* FindNode(const std::string& addrName);
CNode* FindNode(const CService& ip); CNode* FindNode(const CService& ip);
CNode* FindNode(const NodeId id); //TODO: Remove this CNode* FindNode(const NodeId id); //TODO: Remove this
class CNodeStats;
class CConnman class CConnman
{ {
public: public:
enum NumConnections {
CONNECTIONS_NONE = 0,
CONNECTIONS_IN = (1U << 0),
CONNECTIONS_OUT = (1U << 1),
CONNECTIONS_ALL = (CONNECTIONS_IN | CONNECTIONS_OUT),
};
CConnman(); CConnman();
~CConnman(); ~CConnman();
bool Start(boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError); bool Start(boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError);
@ -150,6 +159,13 @@ public:
bool RemoveAddedNode(const std::string& node); bool RemoveAddedNode(const std::string& node);
std::vector<AddedNodeInfo> GetAddedNodeInfo(); std::vector<AddedNodeInfo> GetAddedNodeInfo();
size_t GetNodeCount(NumConnections num);
void GetNodeStats(std::vector<CNodeStats>& vstats);
bool DisconnectAddress(const CNetAddr& addr);
bool DisconnectNode(const std::string& node);
bool DisconnectNode(NodeId id);
bool DisconnectSubnet(const CSubNet& subnet);
private: private:
struct ListenSocket { struct ListenSocket {
SOCKET socket; SOCKET socket;

View file

@ -50,16 +50,18 @@ ClientModel::~ClientModel()
int ClientModel::getNumConnections(unsigned int flags) const int ClientModel::getNumConnections(unsigned int flags) const
{ {
LOCK(cs_vNodes); CConnman::NumConnections connections = CConnman::CONNECTIONS_NONE;
if (flags == CONNECTIONS_ALL) // Shortcut if we want total
return vNodes.size();
int nNum = 0; if(flags == CONNECTIONS_IN)
BOOST_FOREACH(const CNode* pnode, vNodes) connections = CConnman::CONNECTIONS_IN;
if (flags & (pnode->fInbound ? CONNECTIONS_IN : CONNECTIONS_OUT)) else if (flags == CONNECTIONS_OUT)
nNum++; connections = CConnman::CONNECTIONS_OUT;
else if (flags == CONNECTIONS_ALL)
connections = CConnman::CONNECTIONS_ALL;
return nNum; if(g_connman)
return g_connman->GetNodeCount(connections);
return 0;
} }
int ClientModel::getNumBlocks() const int ClientModel::getNumBlocks() const

View file

@ -54,24 +54,21 @@ public:
void refreshPeers() void refreshPeers()
{ {
{ {
TRY_LOCK(cs_vNodes, lockNodes);
if (!lockNodes)
{
// skip the refresh if we can't immediately get the lock
return;
}
cachedNodeStats.clear(); cachedNodeStats.clear();
std::vector<CNodeStats> vstats;
if(g_connman)
g_connman->GetNodeStats(vstats);
#if QT_VERSION >= 0x040700 #if QT_VERSION >= 0x040700
cachedNodeStats.reserve(vNodes.size()); cachedNodeStats.reserve(vstats.size());
#endif #endif
Q_FOREACH (CNode* pnode, vNodes) Q_FOREACH (const CNodeStats& nodestats, vstats)
{ {
CNodeCombinedStats stats; CNodeCombinedStats stats;
stats.nodeStateStats.nMisbehavior = 0; stats.nodeStateStats.nMisbehavior = 0;
stats.nodeStateStats.nSyncHeight = -1; stats.nodeStateStats.nSyncHeight = -1;
stats.nodeStateStats.nCommonHeight = -1; stats.nodeStateStats.nCommonHeight = -1;
stats.fNodeStateStatsAvailable = false; stats.fNodeStateStatsAvailable = false;
pnode->copyStats(stats.nodeStats); stats.nodeStats = nodestats;
cachedNodeStats.append(stats); cachedNodeStats.append(stats);
} }
} }

View file

@ -876,14 +876,14 @@ void RPCConsole::showBanTableContextMenu(const QPoint& point)
void RPCConsole::disconnectSelectedNode() void RPCConsole::disconnectSelectedNode()
{ {
if(!g_connman)
return;
// Get currently selected peer address // Get currently selected peer address
QString strNode = GUIUtil::getEntryData(ui->peerWidget, 0, PeerTableModel::Address).toString(); NodeId id = GUIUtil::getEntryData(ui->peerWidget, 0, PeerTableModel::NetNodeId).toInt();
// Find the node, disconnect it and clear the selected node // Find the node, disconnect it and clear the selected node
if (CNode *bannedNode = FindNode(strNode.toStdString())) { if(g_connman->DisconnectNode(id))
bannedNode->fDisconnect = true;
clearSelectedNode(); clearSelectedNode();
} }
}
void RPCConsole::banSelectedNode(int bantime) void RPCConsole::banSelectedNode(int bantime)
{ {

View file

@ -457,7 +457,10 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
if (strMode != "template") if (strMode != "template")
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
if (vNodes.empty()) if(!g_connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0)
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Bitcoin is not connected!"); throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Bitcoin is not connected!");
if (IsInitialBlockDownload()) if (IsInitialBlockDownload())

View file

@ -89,7 +89,8 @@ UniValue getinfo(const UniValue& params, bool fHelp)
#endif #endif
obj.push_back(Pair("blocks", (int)chainActive.Height())); obj.push_back(Pair("blocks", (int)chainActive.Height()));
obj.push_back(Pair("timeoffset", GetTimeOffset())); obj.push_back(Pair("timeoffset", GetTimeOffset()));
obj.push_back(Pair("connections", (int)vNodes.size())); if(g_connman)
obj.push_back(Pair("connections", (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL)));
obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string()))); obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string())));
obj.push_back(Pair("difficulty", (double)GetDifficulty())); obj.push_back(Pair("difficulty", (double)GetDifficulty()));
obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC())); obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));

View file

@ -36,9 +36,10 @@ UniValue getconnectioncount(const UniValue& params, bool fHelp)
+ HelpExampleRpc("getconnectioncount", "") + HelpExampleRpc("getconnectioncount", "")
); );
LOCK2(cs_main, cs_vNodes); if(!g_connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
return (int)vNodes.size(); return (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL);
} }
UniValue ping(const UniValue& params, bool fHelp) UniValue ping(const UniValue& params, bool fHelp)
@ -64,19 +65,6 @@ UniValue ping(const UniValue& params, bool fHelp)
return NullUniValue; return NullUniValue;
} }
static void CopyNodeStats(std::vector<CNodeStats>& vstats)
{
vstats.clear();
LOCK(cs_vNodes);
vstats.reserve(vNodes.size());
BOOST_FOREACH(CNode* pnode, vNodes) {
CNodeStats stats;
pnode->copyStats(stats);
vstats.push_back(stats);
}
}
UniValue getpeerinfo(const UniValue& params, bool fHelp) UniValue getpeerinfo(const UniValue& params, bool fHelp)
{ {
if (fHelp || params.size() != 0) if (fHelp || params.size() != 0)
@ -127,10 +115,11 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp)
+ HelpExampleRpc("getpeerinfo", "") + HelpExampleRpc("getpeerinfo", "")
); );
LOCK(cs_main); if(!g_connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
vector<CNodeStats> vstats; vector<CNodeStats> vstats;
CopyNodeStats(vstats); g_connman->GetNodeStats(vstats);
UniValue ret(UniValue::VARR); UniValue ret(UniValue::VARR);
@ -253,11 +242,12 @@ UniValue disconnectnode(const UniValue& params, bool fHelp)
+ HelpExampleRpc("disconnectnode", "\"192.168.0.6:8333\"") + HelpExampleRpc("disconnectnode", "\"192.168.0.6:8333\"")
); );
CNode* pNode = FindNode(params[0].get_str()); if(!g_connman)
if (pNode == NULL) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes");
pNode->fDisconnect = true; bool ret = g_connman->DisconnectNode(params[0].get_str());
if (!ret)
throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes");
return NullUniValue; return NullUniValue;
} }
@ -435,7 +425,6 @@ UniValue getnetworkinfo(const UniValue& params, bool fHelp)
); );
LOCK(cs_main); LOCK(cs_main);
UniValue obj(UniValue::VOBJ); UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("version", CLIENT_VERSION)); obj.push_back(Pair("version", CLIENT_VERSION));
obj.push_back(Pair("subversion", strSubVersion)); obj.push_back(Pair("subversion", strSubVersion));
@ -443,7 +432,8 @@ UniValue getnetworkinfo(const UniValue& params, bool fHelp)
obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices))); obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices)));
obj.push_back(Pair("localrelay", fRelayTxes)); obj.push_back(Pair("localrelay", fRelayTxes));
obj.push_back(Pair("timeoffset", GetTimeOffset())); obj.push_back(Pair("timeoffset", GetTimeOffset()));
obj.push_back(Pair("connections", (int)vNodes.size())); if(g_connman)
obj.push_back(Pair("connections", (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL)));
obj.push_back(Pair("networks", GetNetworksInfo())); obj.push_back(Pair("networks", GetNetworksInfo()));
obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()))); obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
UniValue localAddresses(UniValue::VARR); UniValue localAddresses(UniValue::VARR);