diff --git a/libbitdht/src/bitdht/bdconnection.cc b/libbitdht/src/bitdht/bdconnection.cc new file mode 100644 index 000000000..46cecaad9 --- /dev/null +++ b/libbitdht/src/bitdht/bdconnection.cc @@ -0,0 +1,1376 @@ +/* + * bitdht/bdconnection.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2011 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + +#include "bitdht/bdiface.h" + +#include "bitdht/bdnode.h" +#include "bitdht/bdconnection.h" +#include "bitdht/bdmsgs.h" + +#if 0 +#include "bitdht/bencode.h" +#include "bitdht/bdmsgs.h" + +#include "util/bdnet.h" + +#include +#include + +#include +#include +#include +#endif + + +/************************************************************************************************************ +******************************************** Message Interface ********************************************** +************************************************************************************************************/ + +/* Outgoing Messages */ +std::string getConnectMsgType(int msgtype) +{ + switch(msgtype) + { + case BITDHT_MSG_TYPE_CONNECT_REQUEST: + return "ConnectRequest"; + break; + case BITDHT_MSG_TYPE_CONNECT_REPLY: + return "ConnectReply"; + break; + case BITDHT_MSG_TYPE_CONNECT_START: + return "ConnectStart"; + break; + case BITDHT_MSG_TYPE_CONNECT_ACK: + return "ConnectAck"; + break; + default: + return "ConnectUnknown"; + break; + } +} + +void bdNode::msgout_connect_genmsg(bdId *id, bdToken *transId, int msgtype, bdId *srcAddr, bdId *destAddr, int mode, int status) +{ +#ifdef DEBUG_NODE_MSGOUT + std::cerr << "bdNode::msgout_connect_genmsg() Type: " << getConnectMsgType(msgtype); + std::cerr << " TransId: "; + bdPrintTransId(std::cerr, transId); + std::cerr << " From: "; + mFns->bdPrintId(std::cerr, id); + std::cerr << " SrcAddr: "; + mFns->bdPrintId(std::cerr, srcAddr); + std::cerr << " DestAddr: "; + mFns->bdPrintId(std::cerr, destAddr); + std::cerr << " Mode: " << mode; + std::cerr << " Status: " << status; + std::cerr << std::endl; +#endif + + registerOutgoingMsg(id, transId, msgtype); + + /* create string */ + char msg[10240]; + int avail = 10240; + + int blen = bitdht_connect_genmsg(transId, &(mOwnId), msgtype, srcAddr, destAddr, mode, status, msg, avail-1); + sendPkt(msg, blen, id->addr); + + +} + +void bdNode::msgin_connect_genmsg(bdId *id, bdToken *transId, int msgtype, + bdId *srcAddr, bdId *destAddr, int mode, int status) +{ + std::list::iterator it; + +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNode::msgin_connect_genmsg() Type: " << getConnectMsgType(msgtype); + std::cerr << " TransId: "; + bdPrintTransId(std::cerr, transId); + std::cerr << " From: "; + mFns->bdPrintId(std::cerr, id); + std::cerr << " SrcAddr: "; + mFns->bdPrintId(std::cerr, srcAddr); + std::cerr << " DestAddr: "; + mFns->bdPrintId(std::cerr, destAddr); + std::cerr << " Mode: " << mode; + std::cerr << " Status: " << status; + std::cerr << std::endl; +#else + (void) transId; +#endif + + /* switch to actual work functions */ + uint32_t peerflags = 0; + switch(msgtype) + { + case BITDHT_MSG_TYPE_CONNECT_REQUEST: + peerflags = BITDHT_PEER_STATUS_RECV_CONNECT_MSG; + mCounterRecvConnectRequest++; + + recvedConnectionRequest(id, srcAddr, destAddr, mode); + + break; + case BITDHT_MSG_TYPE_CONNECT_REPLY: + peerflags = BITDHT_PEER_STATUS_RECV_CONNECT_MSG; + mCounterRecvConnectReply++; + + recvedConnectionReply(id, srcAddr, destAddr, mode, status); + + break; + case BITDHT_MSG_TYPE_CONNECT_START: + peerflags = BITDHT_PEER_STATUS_RECV_CONNECT_MSG; + mCounterRecvConnectStart++; + + recvedConnectionStart(id, srcAddr, destAddr, mode, status); + + break; + case BITDHT_MSG_TYPE_CONNECT_ACK: + peerflags = BITDHT_PEER_STATUS_RECV_CONNECT_MSG; + mCounterRecvConnectAck++; + + recvedConnectionAck(id, srcAddr, destAddr, mode); + + break; + default: + break; + } + + /* received message - so peer must be good */ + addPeer(id, peerflags); + +} + + +/************************************************************************************************************ +****************************************** Connection Initiation ******************************************** +************************************************************************************************************/ + + +/* This is called to initialise a connection. + * the callback could be with regard to: + * a Direct EndPoint. + * a Proxy Proxy, or an Proxy EndPoint. + * a Relay Proxy, or an Relay EndPoint. + * + * We have two alternatives: + * 1) Direct Endpoint. + * 2) Using a Proxy. + */ + +int bdNode::requestConnection(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode) +{ + /* check if connection obj already exists */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdNode::requestConnection() Mode: " << mode; + std::cerr << " Target: "; + mFns->bdPrintNodeId(std::cerr, id); + std::cerr << " Local NetAddress: "; + mFns->bdPrintAddr(std::cerr, laddr); + std::cerr << std::endl; +#endif + + if (mode == BITDHT_CONNECT_MODE_DIRECT) + { + return requestConnection_direct(laddr, target); + } + else + { + return requestConnection_proxy(laddr, target, mode); + } +} + +int bdNode::checkExistingConnectionAttempt(bdNodeId *target) +{ + std::map::iterator it; + it = mConnectionRequests.find(*target); + if (it != mConnectionRequests.end()) + { +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdNode::checkExistingConnectAttempt() Found Existing Connection!"; + std::cerr << std::endl; +#endif + return 1; + } + return 0; +} + +int bdNode::requestConnection_direct(struct sockaddr_in *laddr, bdNodeId *target) +{ + +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdNode::requestConnection_direct()"; + std::cerr << std::endl; +#endif + /* create a bdConnect, and put into the queue */ + int mode = BITDHT_CONNECT_MODE_DIRECT; + bdConnectionRequest connreq; + + if (checkExistingConnectionAttempt(target)) + { + return 0; + } + + connreq.setupDirectConnection(laddr, target); + + /* grab any peers from any existing query */ + std::list::iterator qit; + for(qit = mLocalQueries.begin(); qit != mLocalQueries.end(); qit++) + { + if (!((*qit)->mId == (*target))) + { + continue; + } + + /* matching query */ + /* find any potential proxies (must be same DHT type XXX TODO) */ + (*qit)->result(connreq.mPotentialProxies); + + /* will only be one matching query.. so end loop */ + break; + } + + /* now look in the bdSpace as well */ + +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdNode::requestConnection_direct() Init Connection State"; + std::cerr << std::endl; + std::cerr << connreq; + std::cerr << std::endl; +#endif + + /* push connect onto queue, for later completion */ + + mConnectionRequests[*target] = connreq; + + /* connection continued via iterator */ + return 1; +} + + +int bdNode::requestConnection_proxy(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode) +{ + +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdNode::requestConnection_proxy()"; + std::cerr << std::endl; +#endif + + /* create a bdConnect, and put into the queue */ + + bdConnectionRequest connreq; + connreq.setupProxyConnection(laddr, target, mode); + + /* grab any peers from any existing query */ + std::list::iterator qit; + for(qit = mLocalQueries.begin(); qit != mLocalQueries.end(); qit++) + { + if (!((*qit)->mId == (*target))) + { + continue; + } + + /* matching query */ + /* find any potential proxies (must be same DHT type XXX TODO) */ + (*qit)->proxies(connreq.mPotentialProxies); + + /* will only be one matching query.. so end loop */ + break; + } + + /* find closest acceptable peers, + * and trigger a search for target... + * this will hopefully find more suitable proxies. + */ + + std::list excluding; + std::multimap nearest; + +#define CONNECT_NUM_PROXY_ATTEMPTS 10 + int number = CONNECT_NUM_PROXY_ATTEMPTS; + + mNodeSpace.find_nearest_nodes_with_flags(target, number, excluding, nearest, + BITDHT_PEER_STATUS_DHT_FOF | + BITDHT_PEER_STATUS_DHT_FRIEND); + + number = CONNECT_NUM_PROXY_ATTEMPTS - number; + + mNodeSpace.find_nearest_nodes_with_flags(target, number, excluding, nearest, + BITDHT_PEER_STATUS_DHT_APPL | + BITDHT_PEER_STATUS_DHT_VERSION); + + std::multimap::iterator it; + for(it = nearest.begin(); it != nearest.end(); it++) + { + bdNodeId midId; + mFns->bdRandomMidId(target, &(it->second.id), &midId); + /* trigger search */ + send_query(&(it->second), &midId); + } + + /* push connect onto queue, for later completion */ + mConnectionRequests[*target] = connreq; + + return 1; +} + + +/** This function needs the Potential Proxies to be tested against DHT_APPL flags **/ +void bdNode::addPotentialConnectionProxy(bdId *srcId, bdId *target) +{ + std::map::iterator it; + for(it = mConnectionRequests.begin(); it != mConnectionRequests.end(); it++) + { + if (target->id == it->first) + { + it->second.addPotentialProxy(srcId); + } + } +} + +void bdNode::iterateConnectionRequests() +{ + std::map::iterator it; + for(it = mConnectionRequests.begin(); it != mConnectionRequests.end(); it++) + { + /* check status of connection */ + if (it->second.mState == BITDHT_CONNREQUEST_INIT) + { + /* kick off the connection if possible */ + //startConnectionAttempt(it->second); + } + } +} + + +/************************************************************************************************************ +****************************************** Outgoing Triggers ************************************************ +************************************************************************************************************/ + +/*** Called by iterator. + * initiates the connection startup + * + * srcConnAddr must contain Own ID + Connection Port (DHT or TOU depending on Mode). + * + * For a DIRECT Connection: proxyId == destination Id, and mode == DIRECT. + * + * For RELAY | PROXY Connection: + * + * In all cases, destConnAddr doesn't need to contain a valid address. + */ + +int bdNode::startConnectionAttempt(bdId *proxyId, bdId *srcConnAddr, bdId *destConnAddr, int mode) +{ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdNode::startConnectionAttempt()"; + std::cerr << std::endl; +#endif + + /* Check for existing Connection */ + bdConnection *conn = findExistingConnectionBySender(proxyId, srcConnAddr, destConnAddr); + if (conn) + { + /* ERROR */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdNode::startConnectAttempt() ERROR EXISTING CONNECTION"; + std::cerr << std::endl; +#endif + return 0; + } + + /* INSTALL a NEW CONNECTION */ + // not offically playing by the rules, but it should work. + conn = newConnectionBySender(proxyId, srcConnAddr, destConnAddr); + + conn->ConnectionSetup(proxyId, srcConnAddr, destConnAddr, mode); + + /* push off message */ + bdToken *transId; + int msgtype = BITDHT_MSG_TYPE_CONNECT_REQUEST; + int status = BITDHT_CONNECT_ANSWER_OKAY; + + msgout_connect_genmsg(&(conn->mProxyId), transId, msgtype, &(conn->mSrcConnAddr), &(conn->mDestConnAddr), conn->mMode, status); + + return 1; +} + +/* This will be called in response to a callback. + * the callback could be with regard to: + * a Direct EndPoint. + * a Proxy Proxy, or an Proxy EndPoint. + * a Relay Proxy, or an Relay EndPoint. + * + * If we are going to store the minimal amount in the bdNode about connections, + * then the parameters must contain all the information: + * + * case 1: + * + */ + +void bdNode::AuthConnectionOk(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc) +{ + +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdNode::AuthConnectionOk()"; + std::cerr << std::endl; +#endif + + /* Check for existing Connection */ + bdConnection *conn = findExistingConnection(&(srcId->id), &(proxyId->id), &(destId->id)); + if (!conn) + { + /* ERROR */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdNode::AuthConnectionOk() ERROR NO EXISTING CONNECTION"; + std::cerr << std::endl; +#endif + return; + } + + /* we need to continue the connection */ + if (mode == BITDHT_CONNECT_MODE_DIRECT) + { + if (conn->mState == BITDHT_CONNECTION_WAITING_AUTH) + { + /* This pushes it into the START/ACK cycle, + * which handles messages elsewhere + */ + conn->AuthoriseDirectConnection(srcId, proxyId, destId, mode, loc); + } + else + { + /* ERROR */ + + } + return; + } + + if (loc == BD_PROXY_CONNECTION_END_POINT) + { + if (conn->mState == BITDHT_CONNECTION_WAITING_AUTH) + { + /*** XXX MUST RECEIVE THE ADDRESS FROM DEST for connection */ + conn->AuthoriseEndConnection(srcId, proxyId, destId, mode, loc); + + /* we respond to the proxy which will finalise connection */ + bdToken *transId; + int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; + int status = BITDHT_CONNECT_ANSWER_OKAY; + msgout_connect_genmsg(&(conn->mProxyId), transId, msgtype, &(conn->mSrcConnAddr), &(conn->mDestConnAddr), conn->mMode, status); + + return; + } + else + { + + /* ERROR */ + } + } + + if (conn->mState == BITDHT_CONNECTION_WAITING_AUTH) + { + /* otherwise we are the proxy (for either), pass on the request */ + + /* XXX SEARCH for ID of peer */ + + conn->AuthoriseProxyConnection(srcId, proxyId, destId, mode, loc); + + bdToken *transId; + int msgtype = BITDHT_MSG_TYPE_CONNECT_REQUEST; + int status = BITDHT_CONNECT_ANSWER_OKAY; + msgout_connect_genmsg(&(conn->mDestId), transId, msgtype, &(conn->mSrcConnAddr), &(conn->mDestConnAddr), conn->mMode, status); + } + else + { + /* ERROR */ + } + + return; +} + + +void bdNode::AuthConnectionNo(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc) +{ + +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdNode::AuthConnectionNo()"; + std::cerr << std::endl; +#endif + + /* Check for existing Connection */ + bdConnection *conn = findExistingConnection(&(srcId->id), &(proxyId->id), &(destId->id)); + if (!conn) + { + /* ERROR */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdNode::AuthConnectionNo() ERROR NO EXISTING CONNECTION"; + std::cerr << std::endl; +#endif + return; + } + + /* we need to continue the connection */ + + if (mode == BITDHT_CONNECT_MODE_DIRECT) + { + /* we respond to the proxy which will finalise connection */ + bdToken *transId; + int status = BITDHT_CONNECT_ANSWER_NOK; + int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; + msgout_connect_genmsg(&(conn->mSrcId), transId, msgtype, + &(conn->mSrcConnAddr), &(conn->mDestConnAddr), mode, status); + + cleanConnection(&(srcId->id), &(proxyId->id), &(destId->id)); + return; + } + + if (loc == BD_PROXY_CONNECTION_END_POINT) + { + /* we respond to the proxy which will finalise connection */ + bdToken *transId; + int status = BITDHT_CONNECT_ANSWER_NOK; + int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; + msgout_connect_genmsg(&(conn->mProxyId), transId, msgtype, + &(conn->mSrcConnAddr), &(conn->mDestConnAddr), mode, status); + + cleanConnection(&(srcId->id), &(proxyId->id), &(destId->id)); + + return; + } + + /* otherwise we are the proxy (for either), reply FAIL */ + bdToken *transId; + int status = BITDHT_CONNECT_ANSWER_NOK; + int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; + msgout_connect_genmsg(&(conn->mSrcId), transId, msgtype, + &(conn->mSrcConnAddr), &(conn->mDestConnAddr), mode, status); + + cleanConnection(&(srcId->id), &(proxyId->id), &(destId->id)); + + return; +} + + + + + +void bdNode::iterateConnections() +{ + std::map::iterator it; + std::list eraseList; + time_t now = time(NULL); + + for(it = mConnections.begin(); it != mConnections.end(); it++) + { + if (now - it->second.mLastEvent > BD_CONNECTION_MAX_TIMEOUT) + { + /* cleanup event */ + eraseList.push_back(it->first); + continue; + } + + if ((it->second.mState == BITDHT_CONNECTION_WAITING_ACK) && + (now - it->second.mLastStart > BD_CONNECTION_START_RETRY_PERIOD)) + { + if (it->second.mRetryCount > BD_CONNECTION_START_MAX_RETRY) + { + /* connection failed! cleanup */ + callbackConnect(&(it->second.mSrcId),&(it->second.mProxyId),&(it->second.mDestId), + it->second.mMode, it->second.mPoint, BITDHT_CONNECT_CB_FAILED); + + /* add to erase list */ + eraseList.push_back(it->first); + } + else + { + it->second.mLastStart = now; + it->second.mRetryCount++; + if (!it->second.mSrcAck) + { + bdToken *transId; + int msgtype = BITDHT_MSG_TYPE_CONNECT_START; + msgout_connect_genmsg(&(it->second.mSrcId), transId, msgtype, + &(it->second.mSrcConnAddr), &(it->second.mDestConnAddr), + it->second.mMode, it->second.mBandwidth); + } + if (!it->second.mDestAck) + { + bdToken *transId; + int msgtype = BITDHT_MSG_TYPE_CONNECT_START; + msgout_connect_genmsg(&(it->second.mDestId), transId, msgtype, + &(it->second.mSrcConnAddr), &(it->second.mDestConnAddr), + it->second.mMode, it->second.mBandwidth); + } + } + } + } + + /* clean up */ + while(eraseList.size() > 0) + { + bdProxyTuple tuple = eraseList.front(); + eraseList.pop_front(); + + std::map::iterator eit = mConnections.find(tuple); + mConnections.erase(eit); + } +} + + + + +/************************************************************************************************************ +****************************************** Callback Functions ******************************************** +************************************************************************************************************/ + + +void bdNode::callbackConnect(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int point, int cbtype) +{ + /* This is overloaded at a higher level */ +} + + +/************************************************************************************************************ +************************************** ProxyTuple + Connection State **************************************** +************************************************************************************************************/ + +int operator<(const bdProxyTuple &a, const bdProxyTuple &b) +{ + if (a.srcId < b.srcId) + { + return 1; + } + + if (a.srcId == b.srcId) + { + if (a.proxyId < b.proxyId) + { + return 1; + } + else if (a.proxyId == b.proxyId) + { + if (a.destId < b.destId) + { + return 1; + } + } + } + return 0; +} + +int operator==(const bdProxyTuple &a, const bdProxyTuple &b) +{ + if ((a.srcId == b.srcId) && (a.proxyId == b.proxyId) && (a.destId == b.destId)) + { + return 1; + } + return 0; +} + +bdConnection::bdConnection() +{ + ///* Connection State, and TimeStamp of Update */ + //int mState; + //time_t mLastEvent; + // + ///* Addresses of Start/Proxy/End Nodes */ + //bdId mSrcId; + //bdId mDestId; + //bdId mProxyId; + // + ///* Where we are in the connection, + //* and what connection mode. + //*/ + //int mPoint; + //int mMode; + // + ///* must have ip:ports of connection ends (if proxied) */ + //bdId mSrcConnAddr; + //bdId mDestConnAddr; + // + //int mBandwidth; + // + ///* START/ACK Finishing ****/ + //time_t mLastStart; /* timer for retries */ + //int mRetryCount; /* retry counter */ + // + //bool mSrcAck; + //bool mDestAck; + // + //// Completion TS. + //time_t mCompletedTS; +} + + +bdConnection *bdNode::findExistingConnection(bdNodeId *srcId, bdNodeId *proxyId, bdNodeId *destId) +{ + bdProxyTuple tuple(srcId, proxyId, destId); + std::map::iterator it = mConnections.find(tuple); + if (it == mConnections.end()) + { + return NULL; + } + + return &(it->second); +} + +bdConnection *bdNode::newConnection(bdNodeId *srcId, bdNodeId *proxyId, bdNodeId *destId) +{ + bdProxyTuple tuple(srcId, proxyId, destId); + bdConnection conn; + + mConnections[tuple] = conn; + std::map::iterator it = mConnections.find(tuple); + if (it == mConnections.end()) + { + return NULL; + } + return &(it->second); +} + +int bdNode::cleanConnection(bdNodeId *srcId, bdNodeId *proxyId, bdNodeId *destId) +{ + bdProxyTuple tuple(srcId, proxyId, destId); + bdConnection conn; + + std::map::iterator it = mConnections.find(tuple); + if (it == mConnections.end()) + { + return 0; + } + mConnections.erase(it); + + return 1; +} + + +int bdNode::determinePosition(bdNodeId *sender, bdNodeId *src, bdNodeId *dest) +{ + int pos = BD_PROXY_CONNECTION_UNKNOWN_POINT; + if (mOwnId == *src) + { + pos = BD_PROXY_CONNECTION_START_POINT; + } + else if (mOwnId == *dest) + { + pos = BD_PROXY_CONNECTION_END_POINT; + } + else + { + pos = BD_PROXY_CONNECTION_MID_POINT; + } + return pos; +} + +int bdNode::determineProxyId(bdNodeId *sender, bdNodeId *src, bdNodeId *dest, bdNodeId *proxyId) +{ + int pos = determinePosition(sender, src, dest); + switch(pos) + { + case BD_PROXY_CONNECTION_START_POINT: + case BD_PROXY_CONNECTION_END_POINT: + *proxyId = *sender; + return 1; + break; + default: + case BD_PROXY_CONNECTION_MID_POINT: + *proxyId = mOwnId; + return 1; + break; + } + return 0; +} + + + +bdConnection *bdNode::findExistingConnectionBySender(bdId *sender, bdId *src, bdId *dest) +{ + bdNodeId proxyId; + bdNodeId *senderId = &(sender->id); + bdNodeId *srcId = &(src->id); + bdNodeId *destId = &(dest->id); + determineProxyId(senderId, srcId, destId, &proxyId); + + return findExistingConnection(srcId, &proxyId, destId); +} + +bdConnection *bdNode::newConnectionBySender(bdId *sender, bdId *src, bdId *dest) +{ + bdNodeId proxyId; + bdNodeId *senderId = &(sender->id); + bdNodeId *srcId = &(src->id); + bdNodeId *destId = &(dest->id); + determineProxyId(senderId, srcId, destId, &proxyId); + + return newConnection(srcId, &proxyId, destId); +} + + +int bdNode::cleanConnectionBySender(bdId *sender, bdId *src, bdId *dest) +{ + bdNodeId proxyId; + bdNodeId *senderId = &(sender->id); + bdNodeId *srcId = &(src->id); + bdNodeId *destId = &(dest->id); + determineProxyId(senderId, srcId, destId, &proxyId); + + return cleanConnection(srcId, &proxyId, destId); +} + + +/************************************************************************************************************ +****************************************** Received Connect Msgs ******************************************** +************************************************************************************************************/ + + +/* This function is triggered by a CONNECT_REQUEST message. + * it will occur on both the Proxy/Dest in the case of a Proxy (PROXY | RELAY) and on the Dest (DIRECT) nodes. + * + * In all cases, we store the request and ask for authentication. + * + */ + + + +int bdNode::recvedConnectionRequest(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode) +{ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdNode::recvedConnectionRequest()"; + std::cerr << std::endl; +#endif + /* Check for existing Connection */ + bdConnection *conn = findExistingConnectionBySender(id, srcConnAddr, destConnAddr); + if (conn) + { + /* ERROR */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdNode::recvedConnectionRequest() ERROR EXISTING CONNECTION"; + std::cerr << std::endl; +#endif + return 0; + } + + /* INSTALL a NEW CONNECTION */ + conn = bdNode::newConnectionBySender(id, srcConnAddr, destConnAddr); + + int point = 0; + if (mode == BITDHT_CONNECT_MODE_DIRECT) + { +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdNode::recvedConnectionRequest() Installing DIRECT CONNECTION"; + std::cerr << std::endl; +#endif + + /* we are actually the end node, store stuff, get auth and on with it! */ + point = BD_PROXY_CONNECTION_END_POINT; + + conn->ConnectionRequestDirect(id, srcConnAddr, destConnAddr); + + callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), + conn->mMode, conn->mPoint, BITDHT_CONNECT_CB_AUTH); + } + else + { + /* check if we are proxy, or end point */ + bool areProxy = (srcConnAddr->id == id->id); + if (areProxy) + { + point = BD_PROXY_CONNECTION_MID_POINT; + + conn->ConnectionRequestProxy(id, srcConnAddr, destConnAddr, mode); + + callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), + conn->mMode, conn->mPoint, BITDHT_CONNECT_CB_AUTH); + } + else + { + point = BD_PROXY_CONNECTION_END_POINT; + + conn->ConnectionRequestEnd(id, srcConnAddr, destConnAddr, mode); + + callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), + conn->mMode, conn->mPoint, BITDHT_CONNECT_CB_AUTH); + } + } + return 1; +} + + +/* This function is triggered by a CONNECT_REPLY message. + * it will occur on either the Proxy or Source. And indicates YES / NO to the connection, + * as well as supplying address info to the proxy. + * + */ + +int bdNode::recvedConnectionReply(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int status) +{ + /* retrieve existing connection data */ + bdConnection *conn = findExistingConnectionBySender(id, srcConnAddr, destConnAddr); + if (!conn) + { + /* ERROR */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdNode::recvedConnectionReply() ERROR NO EXISTING CONNECTION"; + std::cerr << std::endl; +#endif + return 0; + } + + switch(conn->mPoint) + { + case BD_PROXY_CONNECTION_START_POINT: + case BD_PROXY_CONNECTION_END_POINT: /* NEVER EXPECT THIS */ + case BD_PROXY_CONNECTION_UNKNOWN_POINT: /* NEVER EXPECT THIS */ + default: /* NEVER EXPECT THIS */ + { + + /* Only situation we expect this, is if the connection is not allowed. + * DEST has sent back an ERROR Message + */ + + if ((status == BITDHT_CONNECT_ANSWER_NOK) && (conn->mPoint == BD_PROXY_CONNECTION_START_POINT)) + { + /* connection is killed */ + + } + else + { + /* ERROR in protocol */ + } + + /* do Callback for Failed Connection */ + callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), + conn->mMode, conn->mPoint, BITDHT_CONNECT_CB_FAILED); + + /* Kill Connection always */ + cleanConnectionBySender(id, srcConnAddr, destConnAddr); + + return 0; + } + break; + + case BD_PROXY_CONNECTION_MID_POINT: + { + /* We are proxy. and OK / NOK for connection proceed. + */ + + if ((status == BITDHT_CONNECT_ANSWER_OKAY) && (conn->mState == BITDHT_CONNECTION_WAITING_REPLY)) + { + /* OK, continue connection! */ + + /* Upgrade Connection to Finishing Mode */ + conn->upgradeProxyConnectionToFinish(id, srcConnAddr, destConnAddr, mode, status); + + /* do Callback for Pending Connection */ + callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), + conn->mMode, conn->mPoint, BITDHT_CONNECT_CB_PENDING); + } + else + { + /* do Callback for Failed Connection */ + callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), + conn->mMode, conn->mPoint, BITDHT_CONNECT_CB_FAILED); + + /* send on message to SRC */ + bdToken *transId; + int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; + msgout_connect_genmsg(&(conn->mSrcId), transId, msgtype, &(conn->mSrcConnAddr), &(conn->mDestConnAddr), mode, status); + + /* connection is killed */ + cleanConnectionBySender(id, srcConnAddr, destConnAddr); + } + return 0; + } + break; + } + return 0; +} + + +/* This function is triggered by a CONNECT_START message. + * it will occur on both the Src/Dest in the case of a Proxy (PROXY | RELAY) and on the Src (DIRECT) nodes. + * + * parameters are checked against pending connections. + * Acks are set, and connections completed if possible (including callback!). + */ + +int bdNode::recvedConnectionStart(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int bandwidth) +{ + /* retrieve existing connection data */ + bdConnection *conn = findExistingConnectionBySender(id, srcConnAddr, destConnAddr); + if (!conn) + { + /* ERROR */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdNode::recvedConnectionStart() ERROR NO EXISTING CONNECTION"; + std::cerr << std::endl; +#endif + return 0; + } + + + if (conn->mPoint == BD_PROXY_CONNECTION_MID_POINT) + { + /* ERROR */ + } + + /* check state */ + if ((conn->mState != BITDHT_CONNECTION_WAITING_START) || (conn->mState != BITDHT_CONNECTION_COMPLETED)) + { + /* ERROR */ + + return 0; + } + + /* ALL Okay, Send ACK */ + + bdToken *transId; + int msgtype = BITDHT_MSG_TYPE_CONNECT_ACK; + int status = BITDHT_CONNECT_ANSWER_OKAY; + msgout_connect_genmsg(id, transId, msgtype, &(conn->mSrcId), &(conn->mDestId), mode, status); + + /* do complete Callback */ + + /* flag as completed */ + if (conn->mState != BITDHT_CONNECTION_COMPLETED) + { + /* Store Final Addresses */ + time_t now = time(NULL); + + conn->mSrcConnAddr = *srcConnAddr; + conn->mDestConnAddr = *destConnAddr; + conn->mState = BITDHT_CONNECTION_COMPLETED; + conn->mCompletedTS = now; + + if (conn->mPoint == BD_PROXY_CONNECTION_START_POINT) + { + /* callback to connect to Dest address! */ + // Slightly different callback, use ConnAddr for start message! + callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestConnAddr), + conn->mMode, conn->mPoint, BITDHT_CONNECT_CB_START); + + } + else + { + /* callback to connect to Src address! */ + // Slightly different callback, use ConnAddr for start message! + callbackConnect(&(conn->mSrcConnAddr),&(conn->mProxyId),&(conn->mDestId), + conn->mMode, conn->mPoint, BITDHT_CONNECT_CB_START); + + } + } + /* don't delete, if ACK is lost, we want to be able to re-respond */ + + return 1; +} + + +/* This function is triggered by a CONNECT_ACK message. + * it will occur on both the Proxy (PROXY | RELAY) and on the Dest (DIRECT) nodes. + * + * parameters are checked against pending connections. + * Acks are set, and connections completed if possible (including callback!). + */ + +int bdNode::recvedConnectionAck(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode) +{ + /* retrieve existing connection data */ + bdConnection *conn = findExistingConnectionBySender(id, srcConnAddr, destConnAddr); + if (!conn) + { + /* ERROR */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdNode::recvedConnectionStart() ERROR NO EXISTING CONNECTION"; + std::cerr << std::endl; +#endif + return 0; + } + + if (conn->mPoint == BD_PROXY_CONNECTION_START_POINT) + { + /* ERROR */ + } + + /* check state */ + if (conn->mState != BITDHT_CONNECTION_WAITING_ACK) + { + /* ERROR */ + + return 0; + } + + if (id->id == srcConnAddr->id) + { + /* recved Ack from source */ + conn->mSrcAck = true; + } + else if (id->id == destConnAddr->id) + { + /* recved Ack from dest */ + conn->mDestAck = true; + } + + if (conn->mSrcAck && conn->mDestAck) + { + /* connection complete! cleanup */ + if (conn->mMode == BITDHT_CONNECT_MODE_DIRECT) + { + int mode = conn->mMode | BITDHT_CONNECT_ANSWER_OKAY; + /* callback to connect to Src address! */ + // Slightly different callback, use ConnAddr for start message! + callbackConnect(&(conn->mSrcConnAddr),&(conn->mProxyId),&(conn->mDestId), + conn->mMode, conn->mPoint, BITDHT_CONNECT_CB_START); + + } + else + { + int mode = conn->mMode | BITDHT_CONNECT_ANSWER_OKAY; + callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), + conn->mMode, conn->mPoint, BITDHT_CONNECT_CB_PROXY); + + } + + /* Finished Connection! */ + cleanConnectionBySender(id, srcConnAddr, destConnAddr); + } + return 1; +} + + + +/************************************************************************************************************ +********************************* Connection / ConnectionRequest Functions ********************************** +************************************************************************************************************/ + +// Initialise a new Connection (request by User) + +// Any Connection initialised at Source (START_POINT), prior to Auth. +int bdConnection::ConnectionSetup(bdId *proxyId, bdId *srcConnAddr, bdId *destConnAddr, int mode) +{ + mState = BITDHT_CONNECTION_WAITING_START; /* or REPLY, no AUTH required */ + mLastEvent = time(NULL); + mSrcId = *srcConnAddr; /* self, IP unknown */ + mDestId = *destConnAddr; /* dest, IP unknown */ + mProxyId = *proxyId; /* full proxy/dest address */ + + mPoint = BD_PROXY_CONNECTION_START_POINT; + mMode = mode; + + mSrcConnAddr = *srcConnAddr; /* self */ + mDestConnAddr = *destConnAddr; /* IP unknown */ + + /* don't bother with START/ACK parameters */ + + return 1; +} + + + +// Initialise a new Connection. (receiving a Connection Request) +// Direct Connection initialised at Destination (END_POINT), prior to Auth. +int bdConnection::ConnectionRequestDirect(bdId *id, bdId *srcConnAddr, bdId *destConnAddr) +{ + mState = BITDHT_CONNECTION_WAITING_AUTH; + mLastEvent = time(NULL); + mSrcId = *id; + mDestId = *destConnAddr; /* self, IP unknown */ + mProxyId = *id; /* src */ + + mPoint = BD_PROXY_CONNECTION_END_POINT; + mMode = BITDHT_CONNECT_MODE_DIRECT; + + mSrcConnAddr = *srcConnAddr; + mDestConnAddr = *destConnAddr; /* self */ + + /* don't bother with START/ACK parameters */ + + return 1; +} + + +// Proxy Connection initialised at Proxy (MID_POINT), prior to Auth. +int bdConnection::ConnectionRequestProxy(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode) +{ + mState = BITDHT_CONNECTION_WAITING_AUTH; + mLastEvent = time(NULL); + mSrcId = *id; + mDestId = *destConnAddr; /* self, IP unknown */ + //mProxyId = *id; /* own id, doesn't matter */ + + mPoint = BD_PROXY_CONNECTION_MID_POINT; + mMode = mode; + + mSrcConnAddr = *srcConnAddr; + mDestConnAddr = *destConnAddr; /* other peer, IP unknown */ + + /* don't bother with START/ACK parameters */ + + return 1; +} + + +// Proxy Connection initialised at Destination (END_POINT), prior to Auth. +int bdConnection::ConnectionRequestEnd(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode) +{ + mState = BITDHT_CONNECTION_WAITING_AUTH; + mLastEvent = time(NULL); + mSrcId = *srcConnAddr; /* src IP unknown */ + mDestId = *destConnAddr; /* self, IP unknown */ + mProxyId = *id; /* src */ + + mPoint = BD_PROXY_CONNECTION_END_POINT; + mMode = mode; + + mSrcConnAddr = *srcConnAddr; + mDestConnAddr = *destConnAddr; /* self */ + + /* don't bother with START/ACK parameters */ + + return 1; +} + +// Received AUTH, step up to next stage. +int bdConnection::AuthoriseProxyConnection(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc) +{ + mState = BITDHT_CONNECTION_WAITING_REPLY; + mLastEvent = time(NULL); + + //mSrcId, (peer) should be okay. + //mDestId (other peer) install now (just received) + mDestId = *destId; + //mProxyId (self) doesn't matter. + + // mPoint, mMode should be okay. + + // mSrcConnAddr should be okay. + // mDestConnAddr is still pending. + + /* don't bother with START/ACK parameters */ + + return 1; +} + + +int bdConnection::AuthoriseEndConnection(bdId *srcId, bdId *proxyId, bdId *destConnAddr, int mode, int loc) +{ + mState = BITDHT_CONNECTION_WAITING_START; + mLastEvent = time(NULL); + + //mSrcId, (peer) should be okay. + //mDestId (self) doesn't matter. + //mProxyId (peer) should be okay. + + // mPoint, mMode should be okay. + + // mSrcConnAddr should be okay. + // Install the correct destConnAddr. (just received) + mDestConnAddr = *destConnAddr; + + // Initialise the START/ACK Parameters. + mRetryCount = 0; + mLastStart = 0; + mSrcAck = false; + mDestAck = true; // Automatic ACK, as it is from us. + mCompletedTS = 0; + + return 1; +} + + + + +// Auth of the Direct Connection, means we move straight to WAITING_ACK mode. +int bdConnection::AuthoriseDirectConnection(bdId *srcId, bdId *proxyId, bdId *destConnAddr, int mode, int loc) +{ + mState = BITDHT_CONNECTION_WAITING_ACK; + mLastEvent = time(NULL); + + //mSrcId, (peer) should be okay. + //mDestId (self) doesn't matter. + //mProxyId (peer) should be okay. + + // mPoint, mMode should be okay. + + // mSrcConnAddr should be okay. + // Install the correct destConnAddr. (just received) + mDestConnAddr = *destConnAddr; + + // Initialise the START/ACK Parameters. + mRetryCount = 0; + mLastStart = 0; + mSrcAck = false; + mDestAck = true; // Automatic ACK, as it is from us. + mCompletedTS = 0; + + return 1; +} + +// Proxy Connection => at Proxy, Ready to send out Start and get back ACKs!! +int bdConnection::upgradeProxyConnectionToFinish(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int status) +{ + mState = BITDHT_CONNECTION_WAITING_ACK; + mLastEvent = time(NULL); + + //mSrcId,mDestId should be okay. + //mProxyId, not set, doesn't matter. + + // mPoint, mMode should be okay. + + // mSrcConnAddr should be okay. + // Install the correct destConnAddr. (just received) + mDestConnAddr = *destConnAddr; + + // Initialise the START/ACK Parameters. + mRetryCount = 0; + mLastStart = 0; + mSrcAck = false; + mDestAck = false; + mCompletedTS = 0; + + return 1; +} + + + + + +int bdConnectionRequest::setupDirectConnection(struct sockaddr_in *laddr, bdNodeId *target) +{ + return 0; +} + +int bdConnectionRequest::setupProxyConnection(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode) +{ + return 0; +} + +int bdConnectionRequest::addPotentialProxy(bdId *srcId) +{ + return 0; +} + + + + diff --git a/libbitdht/src/bitdht/bdconnection.h b/libbitdht/src/bitdht/bdconnection.h new file mode 100644 index 000000000..ff4667852 --- /dev/null +++ b/libbitdht/src/bitdht/bdconnection.h @@ -0,0 +1,144 @@ +#ifndef BITDHT_CONNECTION_H +#define BITDHT_CONNECTION_H + +/* + * bitdht/bdconnection.h + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2011 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "bitdht/bdiface.h" + + +/************************************************************************************************************ +************************************** ProxyTuple + Connection State **************************************** +************************************************************************************************************/ + +#define BITDHT_CONNREQUEST_INIT 1 +#define BITDHT_CONNREQUEST_INPROGRESS 2 +#define BITDHT_CONNREQUEST_DONE 3 + + +#define BITDHT_CONNECTION_WAITING_AUTH 1 +#define BITDHT_CONNECTION_WAITING_REPLY 2 +#define BITDHT_CONNECTION_WAITING_START 3 +#define BITDHT_CONNECTION_WAITING_ACK 4 +#define BITDHT_CONNECTION_COMPLETED 5 + + +#define BD_CONNECTION_START_RETRY_PERIOD 10 +#define BD_CONNECTION_START_MAX_RETRY 3 +#define BD_CONNECTION_MAX_TIMEOUT 30 + + + +class bdProxyTuple +{ + public: + bdProxyTuple() { return; } + bdProxyTuple(bdNodeId *s, bdNodeId *p, bdNodeId *d) + :srcId(*s), proxyId(*p), destId(*d) { return; } + + bdNodeId srcId; + bdNodeId proxyId; + bdNodeId destId; +}; + +int operator<(const bdProxyTuple &a, const bdProxyTuple &b); +int operator==(const bdProxyTuple &a, const bdProxyTuple &b); + + +class bdConnection +{ + public: + bdConnection(); + + /** Functions to tweak the connection status */ + + // User initialised Connection. + int ConnectionSetup(bdId *proxyId, bdId *srcConnAddr, bdId *destConnAddr, int mode); + + // Initialise a new Connection. (receiving a Connection Request) + int ConnectionRequestDirect(bdId *id, bdId *srcConnAddr, bdId *destConnAddr); + int ConnectionRequestProxy(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode); + int ConnectionRequestEnd(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode); + + // Setup Finishing Stage, (receiving a Connection Reply). + int upgradeProxyConnectionToFinish(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int status); + + int AuthoriseDirectConnection(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc); + int AuthoriseProxyConnection(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc); + int AuthoriseEndConnection(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc); + + /* Connection State, and TimeStamp of Update */ + int mState; + time_t mLastEvent; + + /* Addresses of Start/Proxy/End Nodes */ + bdId mSrcId; + bdId mDestId; + bdId mProxyId; + + /* Where we are in the connection, + * and what connection mode. + */ + int mPoint; + int mMode; + + /* must have ip:ports of connection ends (if proxied) */ + bdId mSrcConnAddr; + bdId mDestConnAddr; + + int mBandwidth; + + /* START/ACK Finishing ****/ + time_t mLastStart; /* timer for retries */ + int mRetryCount; /* retry counter */ + + bool mSrcAck; + bool mDestAck; + + // Completion TS. + time_t mCompletedTS; + + +}; + +class bdConnectionRequest +{ + public: + int setupDirectConnection(struct sockaddr_in *laddr, bdNodeId *target); + int setupProxyConnection(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode); + + int addPotentialProxy(bdId *srcId); + + std::list mPotentialProxies; + + int mState; + + int stuff; +}; + + +#endif + diff --git a/libbitdht/src/bitdht/bdiface.h b/libbitdht/src/bitdht/bdiface.h index 6d826ccb8..ea5e2e912 100644 --- a/libbitdht/src/bitdht/bdiface.h +++ b/libbitdht/src/bitdht/bdiface.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #include "util/bdnet.h" @@ -121,15 +122,60 @@ virtual void bdPrintNodeId(std::ostream &out, const bdNodeId *a) = 0; #define BITDHT_PEER_STATUS_MASK_RECVD 0x000000ff #define BITDHT_PEER_STATUS_MASK_DHT 0x0000ff00 +#define BITDHT_PEER_STATUS_MASK_KNOWN 0x00ff0000 #define BITDHT_PEER_STATUS_RECV_PONG 0x00000001 #define BITDHT_PEER_STATUS_RECV_NODES 0x00000002 #define BITDHT_PEER_STATUS_RECV_HASHES 0x00000004 +#define BITDHT_PEER_STATUS_RECV_CONNECT_MSG 0x00000008 #define BITDHT_PEER_STATUS_DHT_ENGINE 0x00000100 #define BITDHT_PEER_STATUS_DHT_APPL 0x00000200 #define BITDHT_PEER_STATUS_DHT_VERSION 0x00000400 +#define BITDHT_PEER_STATUS_DHT_WHITELIST 0x00010000 +#define BITDHT_PEER_STATUS_DHT_FOF 0x00020000 +#define BITDHT_PEER_STATUS_DHT_FRIEND 0x00040000 + + + +#define BITDHT_CONNECT_MASK_MODE 0x000000ff +#define BITDHT_CONNECT_MASK_ANSWER 0x0000ff00 + +#define BITDHT_CONNECT_MODE_DIRECT 0x00000001 +#define BITDHT_CONNECT_MODE_PROXY 0x00000002 +#define BITDHT_CONNECT_MODE_RELAY 0x00000004 + +#define BITDHT_CONNECT_ANSWER_OKAY 0x00000100 +#define BITDHT_CONNECT_ANSWER_NOK 0x00000200 +#define BITDHT_CONNECT_ANSWER_NCONN 0x00000400 + +#define BITDHT_CONNECT_ANSWER_TOAUTH 0x00001000 + + +/* Definitions of bdSpace Peer and Bucket are publically available, + * so we can expose the bucket entries for the gui. + */ + +class bdPeer +{ + public: + bdId mPeerId; + uint32_t mPeerFlags; + time_t mLastSendTime; + time_t mLastRecvTime; + time_t mFoundTime; /* time stamp that peer was found */ +}; + +class bdBucket +{ + public: + + bdBucket(); + /* list so we can queue properly */ + std::list entries; +}; + /* Status options */ #define BITDHT_QUERY_READY 1 @@ -145,6 +191,18 @@ virtual void bdPrintNodeId(std::ostream &out, const bdNodeId *a) = 0; #define BITDHT_QFLAGS_DO_IDLE 2 #define BITDHT_QFLAGS_INTERNAL 4 // means it runs through startup. +/* Connect Callback Flags */ +#define BITDHT_CONNECT_CB_AUTH 1 +#define BITDHT_CONNECT_CB_PENDING 2 +#define BITDHT_CONNECT_CB_START 3 +#define BITDHT_CONNECT_CB_PROXY 4 +#define BITDHT_CONNECT_CB_FAILED 5 + +#define BD_PROXY_CONNECTION_UNKNOWN_POINT 0 +#define BD_PROXY_CONNECTION_START_POINT 1 +#define BD_PROXY_CONNECTION_MID_POINT 2 +#define BD_PROXY_CONNECTION_END_POINT 3 + class BitDhtCallback { public: @@ -156,6 +214,11 @@ virtual int dhtNodeCallback(const bdId * /*id*/, uint32_t /*peerflags*/) { ret // must be implemented. virtual int dhtPeerCallback(const bdId *id, uint32_t status) = 0; virtual int dhtValueCallback(const bdNodeId *id, std::string key, uint32_t status) = 0; + + // connection callback. Not required for basic behaviour, but forced for initial development. +virtual int dhtConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId *destId, + uint32_t mode, uint32_t point, uint32_t cbtype) = 0; /* { return 0; } */ + }; @@ -168,6 +231,10 @@ virtual void addFindNode(bdNodeId *id, uint32_t mode) = 0; virtual void removeFindNode(bdNodeId *id) = 0; virtual void findDhtValue(bdNodeId *id, std::string key, uint32_t mode) = 0; + /***** Connections Requests *****/ +virtual void ConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode) = 0; +virtual void ConnectionAuth(bdId *srcId, bdId *proxyId, bdId *destId, uint32_t mode, uint32_t loc, uint32_t answer) = 0; + /***** Add / Remove Callback Clients *****/ virtual void addCallback(BitDhtCallback *cb) = 0; virtual void removeCallback(BitDhtCallback *cb) = 0; @@ -175,6 +242,7 @@ virtual void removeCallback(BitDhtCallback *cb) = 0; /***** Get Results Details *****/ virtual int getDhtPeerAddress(const bdNodeId *id, struct sockaddr_in &from) = 0; virtual int getDhtValue(const bdNodeId *id, std::string key, std::string &value) = 0; +virtual int getDhtBucket(const int idx, bdBucket &bucket) = 0; /* stats and Dht state */ virtual int startDht() = 0; diff --git a/libbitdht/src/bitdht/bdmanager.cc b/libbitdht/src/bitdht/bdmanager.cc index 2ab1147ba..bcb76cfdf 100644 --- a/libbitdht/src/bitdht/bdmanager.cc +++ b/libbitdht/src/bitdht/bdmanager.cc @@ -54,6 +54,7 @@ * #define DEBUG_MGR_PKT 1 ***/ +//#define DEBUG_MGR 1 bdNodeManager::bdNodeManager(bdNodeId *id, std::string dhtVersion, std::string bootfile, bdDhtFunctions *fns) :bdNode(id, dhtVersion, bootfile, fns) @@ -423,9 +424,9 @@ void bdNodeManager::QueryRandomLocalNet() int bdNodeManager::status() { /* do status of bdNode */ -#ifdef DEBUG_MGR +//#ifdef DEBUG_MGR printState(); -#endif +//#endif checkStatus(); @@ -434,10 +435,10 @@ int bdNodeManager::status() mBdNetworkSize = mNodeSpace.calcNetworkSizeWithFlag( BITDHT_PEER_STATUS_DHT_APPL); -#ifdef DEBUG_MGR +//#ifdef DEBUG_MGR std::cerr << "BitDHT NetworkSize: " << mNetworkSize << std::endl; std::cerr << "BitDHT App NetworkSize: " << mBdNetworkSize << std::endl; -#endif +//#endif return 1; } @@ -794,6 +795,11 @@ int bdNodeManager::getDhtValue(const bdNodeId *id, std::string key, std::string return 1; } +int bdNodeManager::getDhtBucket(const int idx, bdBucket &bucket) +{ + return mNodeSpace.getDhtBucket(idx, bucket); +} + /***** Add / Remove Callback Clients *****/ @@ -870,7 +876,7 @@ void bdNodeManager::doPeerCallback(const bdId *id, uint32_t status) #ifdef DEBUG_MGR std::cerr << "bdNodeManager::doPeerCallback()"; - mFns->bdPrintNodeId(std::cerr, id); + mFns->bdPrintId(std::cerr, id); std::cerr << "status: " << status; std::cerr << std::endl; #endif @@ -900,6 +906,8 @@ void bdNodeManager::doValueCallback(const bdNodeId *id, std::string key, uint32_ return; } + + /******************* Internals *************************/ int bdNodeManager::isBitDhtPacket(char *data, int size, struct sockaddr_in & from) @@ -1006,12 +1014,12 @@ bdDebugCallback::~bdDebugCallback() { } -int bdDebugCallback::dhtPeerCallback(const bdNodeId *id, uint32_t status) +int bdDebugCallback::dhtPeerCallback(const bdId *id, uint32_t status) { #ifdef DEBUG_MGR std::cerr << "bdDebugCallback::dhtPeerCallback() Id: "; #endif - bdStdPrintNodeId(std::cerr, id); + bdStdPrintId(std::cerr, id); #ifdef DEBUG_MGR std::cerr << " status: " << std::hex << status << std::dec << std::endl; #endif @@ -1033,3 +1041,65 @@ int bdDebugCallback::dhtValueCallback(const bdNodeId *id, std::string key, uint3 } + + + +/******************* Connection Stuff ********************/ + + + +void bdNodeManager::ConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode) +{ + bdNode::requestConnection(laddr, target, mode); +} + +void bdNodeManager::ConnectionAuth(bdId *srcId, bdId *proxyId, bdId *destId, uint32_t mode, uint32_t loc, uint32_t answer) +{ + if (answer) + { + AuthConnectionOk(srcId, proxyId, destId, mode, loc); + } + else + { + AuthConnectionNo(srcId, proxyId, destId, mode, loc); + } +} + + + /***** Connections Requests *****/ + + // Overloaded from bdnode for external node callback. +void bdNodeManager::callbackConnect(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int point, int cbtype) +{ + std::cerr << "bdNodeManager::callbackConnect()"; + std::cerr << std::endl; + +#ifdef DEBUG_MGR +#endif + /* search list */ + std::list::iterator it; + for(it = mCallbacks.begin(); it != mCallbacks.end(); it++) + { + (*it)->dhtConnectCallback(srcId, proxyId, destId, mode, point, cbtype); + } + return; +} + +int bdDebugCallback::dhtConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId *destId, + uint32_t mode, uint32_t point, uint32_t cbtype) +{ +#ifdef DEBUG_MGR + std::cerr << "bdDebugCallback::dhtConnectCallback() Type: " << cbtype; + std::cerr << " srcId: "; + bdStdPrintId(std::cerr, srcId); + std::cerr << " proxyId: "; + bdStdPrintId(std::cerr, proxyId); + std::cerr << " destId: "; + bdStdPrintId(std::cerr, destId); + std::cerr << " mode: " << mode; + std::cerr << " point: " << point << std::endl; +#endif + + return 1; +} + diff --git a/libbitdht/src/bitdht/bdmanager.h b/libbitdht/src/bitdht/bdmanager.h index 67d1cc13a..eea22a42f 100644 --- a/libbitdht/src/bitdht/bdmanager.h +++ b/libbitdht/src/bitdht/bdmanager.h @@ -113,6 +113,13 @@ virtual void removeCallback(BitDhtCallback *cb); /***** Get Results Details *****/ virtual int getDhtPeerAddress(const bdNodeId *id, struct sockaddr_in &from); virtual int getDhtValue(const bdNodeId *id, std::string key, std::string &value); +virtual int getDhtBucket(const int idx, bdBucket &bucket); + + /***** Connection Interface ****/ +virtual void ConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode); +virtual void ConnectionAuth(bdId *srcId, bdId *proxyId, bdId *destId, + uint32_t mode, uint32_t loc, uint32_t answer); + /* stats and Dht state */ virtual int startDht(); @@ -124,7 +131,9 @@ virtual uint32_t statsBDVersionSize(); /* same version as us! */ // Overloaded from bdnode for external node callback. virtual void addPeer(const bdId *id, uint32_t peerflags); - + // Overloaded from bdnode for external node callback. +virtual void callbackConnect(bdId *srcId, bdId *proxyId, bdId *destId, + int mode, int point, int cbtype); int isBitDhtPacket(char *data, int size, struct sockaddr_in &from); private: @@ -162,8 +171,10 @@ class bdDebugCallback: public BitDhtCallback { public: ~bdDebugCallback(); -virtual int dhtPeerCallback(const bdNodeId *id, uint32_t status); +virtual int dhtPeerCallback(const bdId *id, uint32_t status); virtual int dhtValueCallback(const bdNodeId *id, std::string key, uint32_t status); +virtual int dhtConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId *destId, + uint32_t mode, uint32_t point, uint32_t cbtype); }; diff --git a/libbitdht/src/bitdht/bdmsgs.cc b/libbitdht/src/bitdht/bdmsgs.cc index 1e2b218ea..adee2062b 100644 --- a/libbitdht/src/bitdht/bdmsgs.cc +++ b/libbitdht/src/bitdht/bdmsgs.cc @@ -831,3 +831,176 @@ int beMsgGetUInt32(be_node *n, uint32_t *port) } + + + + + +/******************************************************************************************************************** + * CONNECTION EXTENSIONS + * + */ + + /* +ping Query = {"t":"aa", "y":"q", "q":"ping", "a":{"id":"abcdefghij0123456789"}} +bencoded = d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe + */ + + /* +Response = {"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"}} +bencoded = d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re + */ + + /* +find_node Query = {"t":"aa", "y":"q", "q":"find_node", "a": {"id":"abcdefghij0123456789", "target":"mnopqrstuvwxyz123456"}} +bencoded = d1:ad2:id20:abcdefghij01234567896:target20:mnopqrstuvwxyz123456e1:q9:find_node1:t2:aa1:y1:qe + */ + +#if 0 +int bitdht_find_node_msg(bdToken *tid, bdNodeId *id, bdNodeId *target, + char *msg, int avail) +{ +#ifdef DEBUG_MSGS + fprintf(stderr, "bitdht_find_node_msg()\n"); +#endif + + be_node *dict = be_create_dict(); + + be_node *iddict = be_create_dict(); + be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); + be_node *targetnode = be_create_str_wlen((char *) target->data, BITDHT_KEY_LEN); + + be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); + be_node *yqrnode = be_create_str("q"); + be_node *findnode = be_create_str("find_node"); + + be_add_keypair(iddict, "id", idnode); + be_add_keypair(iddict, "target", targetnode); + be_add_keypair(dict, "a", iddict); + + be_add_keypair(dict, "t", tidnode); + be_add_keypair(dict, "y", yqrnode); + be_add_keypair(dict, "q", findnode); + +#ifdef DEBUG_MSG_DUMP + /* dump answer */ + be_dump(dict); +#endif + + int blen = be_encode(dict, msg, avail); + be_free(dict); + + return blen; +} +#endif + +/**** + * Thinking about the format of this message. + * id: ownId is stanard in all other messages, so should keep the same!. + * src: + * target: + * mode: d,p or r + * + * A -> B -> C + * direct: A ------> B + * ---> id:A src:A target:B mode:d + * <--- id:B src:A target:B mode:d a:OK + * + * proxy: A ------> B -------> C + * A->B id:A src:A target:C mode:p q + * + * a) + * B->A id:B src:A target:C mode:p r:NOK + * + * b) + * B->C id:B src:A target:C mode:p q + * C->B id:C src:A target:C mode:p r:NOK + * B->A id:B src:A target:C mode:p r:NOK + * + * c) + * B->C id:B src:A target:C mode:p q + * C->B id:C src:A target:C mode:p r:OK + * B->A id:B src:A target:C mode:p r:OK + * connect happens. + * Dropped packets will affect this! + * + * + * REQUIRED BITS FOR A MESSAGE + * 1) DIRECT + * -> REQUEST, ownId, targetId, transId, mode. + * -> RESPONSE, ownId, targetId, transId, mode, answer. + * + * 2) PROXY + */ + + +int bitdht_connect_genmsg(bdToken *tid, bdNodeId *id, int msgtype, bdId *src, bdId *dest, int mode, int status, char *msg, int avail) +{ +#ifdef DEBUG_MSGS + fprintf(stderr, "bitdht_connect_genmsg()\n"); +#endif + + be_node *dict = be_create_dict(); + + be_node *iddict = be_create_dict(); + + be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); + + std::string srcEnc = encodeCompactNodeId(src); + std::string destEnc = encodeCompactNodeId(dest); + + be_node *srcnode = be_create_str_wlen(srcEnc.c_str(), BITDHT_COMPACTNODEID_LEN); + be_node *destnode = be_create_str_wlen(destEnc.c_str(), BITDHT_COMPACTNODEID_LEN); + be_node *typenode = be_create_int(msgtype); + be_node *statusnode = be_create_int(status); + + be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); + be_node *yqrnode = be_create_str("q"); + be_node *cmdnode = be_create_str("connect"); + +#define CONNECT_MODE_DIRECT 0x0001 +#define CONNECT_MODE_PROXY 0x0002 +#define CONNECT_MODE_RELAY 0x0004 + + be_node *modenode = NULL; + switch(mode) + { + case CONNECT_MODE_DIRECT: + modenode = be_create_str("d"); + break; + case CONNECT_MODE_PROXY: + modenode = be_create_str("p"); + break; + case CONNECT_MODE_RELAY: + modenode = be_create_str("r"); + break; + default: + modenode = be_create_str("u"); + break; + } + + be_add_keypair(iddict, "id", idnode); + be_add_keypair(iddict, "src", srcnode); + be_add_keypair(iddict, "dest", destnode); + be_add_keypair(iddict, "mode", modenode); + be_add_keypair(iddict, "status", statusnode); + be_add_keypair(iddict, "type", typenode); + + be_add_keypair(dict, "a", iddict); + + be_add_keypair(dict, "t", tidnode); + be_add_keypair(dict, "y", yqrnode); + be_add_keypair(dict, "q", cmdnode); + +#ifdef DEBUG_MSG_DUMP + /* dump answer */ + be_dump(dict); +#endif + + int blen = be_encode(dict, msg, avail); + be_free(dict); + + return blen; +} + + diff --git a/libbitdht/src/bitdht/bdmsgs.h b/libbitdht/src/bitdht/bdmsgs.h index 598a9c4a7..fac17a0b2 100644 --- a/libbitdht/src/bitdht/bdmsgs.h +++ b/libbitdht/src/bitdht/bdmsgs.h @@ -45,6 +45,16 @@ #define BITDHT_MSG_TYPE_POST_HASH 8 #define BITDHT_MSG_TYPE_REPLY_POST 9 +// THESE ARE EXTENSIONS +// CONNECTIONS. +#define BITDHT_MSG_TYPE_CONNECT_REQUEST 101 +#define BITDHT_MSG_TYPE_CONNECT_REPLY 102 +#define BITDHT_MSG_TYPE_CONNECT_START 103 +#define BITDHT_MSG_TYPE_CONNECT_ACK 104 + +// FANCY HASHES. + + #define BITDHT_COMPACTNODEID_LEN 26 #define BITDHT_COMPACTPEERID_LEN 6 @@ -78,6 +88,10 @@ int bitdht_reply_announce_msg(bdToken *tid, bdNodeId *id, char *msg, int avail); +// Extensions. +int bitdht_connect_genmsg(bdToken *tid, bdNodeId *id, int msgtype, bdId *src, bdId *dest, int mode, int status, char *msg, int avail); + + //int response_peers_message() //int response_closestnodes_message() diff --git a/libbitdht/src/bitdht/bdnode.cc b/libbitdht/src/bitdht/bdnode.cc index f80ad5c77..0a359f9e4 100644 --- a/libbitdht/src/bitdht/bdnode.cc +++ b/libbitdht/src/bitdht/bdnode.cc @@ -80,7 +80,7 @@ void bdNode::restartNode() bdPeer peer; while(mStore.getPeer(&peer)) { - addPotentialPeer(&(peer.mPeerId)); + addPotentialPeer(&(peer.mPeerId), NULL); } } @@ -317,21 +317,15 @@ void bdNode::iteration() /* go through the possible queries */ if (query->nextQuery(id, targetNodeId)) { - /* push out query */ - bdToken transId; - genNewTransId(&transId); - //registerOutgoingMsg(&id, &transId, BITDHT_MSG_TYPE_FIND_NODE); - - msgout_find_node(&id, &transId, &targetNodeId); - #ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::iteration() Find Node Req for : "; + std::cerr << "bdNode::iteration() send_query("; mFns->bdPrintId(std::cerr, &id); - std::cerr << " searching for : "; + std::cerr << ","; mFns->bdPrintNodeId(std::cerr, &targetNodeId); + std::cerr << ")"; std::cerr << std::endl; #endif - mCounterQueryNode++; + send_query(&id, &targetNodeId); sentMsgs++; sentQueries++; } @@ -376,6 +370,26 @@ void bdNode::iteration() //printQueries(); } +void bdNode::send_query(bdId *id, bdNodeId *targetNodeId) +{ + /* push out query */ + bdToken transId; + genNewTransId(&transId); + //registerOutgoingMsg(&id, &transId, BITDHT_MSG_TYPE_FIND_NODE); + + msgout_find_node(id, &transId, targetNodeId); + +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNode::send_query() Find Node Req for : "; + mFns->bdPrintId(std::cerr, &id); + std::cerr << " searching for : "; + mFns->bdPrintNodeId(std::cerr, &targetNodeId); + std::cerr << std::endl; +#endif + mCounterQueryNode++; +} + + #define LPF_FACTOR (0.90) void bdNode::doStats() @@ -408,12 +422,31 @@ void bdNode::doStats() mLpfRecvReplyQueryHash *= (LPF_FACTOR); mLpfRecvReplyQueryHash += (1.0 - LPF_FACTOR) * mCounterRecvReplyQueryHash; + // connection stats. + mLpfConnectRequest *= (LPF_FACTOR); + mLpfConnectRequest += (1.0 - LPF_FACTOR) * mCounterConnectRequest; + mLpfConnectReply *= (LPF_FACTOR); + mLpfConnectReply += (1.0 - LPF_FACTOR) * mCounterConnectReply; + mLpfConnectStart *= (LPF_FACTOR); + mLpfConnectStart += (1.0 - LPF_FACTOR) * mCounterConnectStart; + mLpfConnectAck *= (LPF_FACTOR); + mLpfConnectAck += (1.0 - LPF_FACTOR) * mCounterConnectAck; + + mLpfRecvConnectRequest *= (LPF_FACTOR); + mLpfRecvConnectRequest += (1.0 - LPF_FACTOR) * mCounterRecvConnectRequest; + mLpfRecvConnectReply *= (LPF_FACTOR); + mLpfRecvConnectReply += (1.0 - LPF_FACTOR) * mCounterRecvConnectReply; + mLpfRecvConnectStart *= (LPF_FACTOR); + mLpfRecvConnectStart += (1.0 - LPF_FACTOR) * mCounterRecvConnectStart; + mLpfRecvConnectAck *= (LPF_FACTOR); + mLpfRecvConnectAck += (1.0 - LPF_FACTOR) * mCounterRecvConnectAck; resetCounters(); } void bdNode::printStats(std::ostream &out) { + out << "bdNode::printStats()" << std::endl; out << " Send Recv: "; out << std::endl; @@ -438,6 +471,24 @@ void bdNode::printStats(std::ostream &out) out << " mLpfRecvQueryHash/sec : " << std::setw(10) << mLpfRecvQueryHash; out << std::endl; out << std::endl; + + out << " mLpfConnectRequest/sec : " << std::setw(10) << mLpfConnectRequest; + out << std::endl; + out << " mLpfConnectReply/sec : " << std::setw(10) << mLpfConnectReply; + out << std::endl; + out << " mLpfConnectStart/sec : " << std::setw(10) << mLpfConnectStart; + out << std::endl; + out << " mLpfConnectAck/sec : " << std::setw(10) << mLpfConnectAck; + out << std::endl; + out << " mLpfRecvConnectReq/sec : " << std::setw(10) << mLpfRecvConnectRequest; + out << std::endl; + out << " mLpfRecvConnReply/sec : " << std::setw(10) << mLpfRecvConnectReply; + out << std::endl; + out << " mLpfRecvConnStart/sec : " << std::setw(10) << mLpfRecvConnectStart; + out << std::endl; + out << " mLpfRecvConnectAck/sec : " << std::setw(10) << mLpfRecvConnectAck; + out << std::endl; + out << std::endl; } void bdNode::resetCounters() @@ -456,6 +507,16 @@ void bdNode::resetCounters() mCounterRecvQueryHash = 0; mCounterRecvReplyFindNode = 0; mCounterRecvReplyQueryHash = 0; + + mCounterConnectRequest = 0; + mCounterConnectReply = 0; + mCounterConnectStart = 0; + mCounterConnectAck = 0; + + mCounterRecvConnectRequest = 0; + mCounterRecvConnectReply = 0; + mCounterRecvConnectStart = 0; + mCounterRecvConnectAck = 0; } void bdNode::resetStats() @@ -479,14 +540,14 @@ void bdNode::resetStats() } -void bdNode::checkPotentialPeer(bdId *id) +void bdNode::checkPotentialPeer(bdId *id, bdId *src) { bool isWorthyPeer = false; /* also push to queries */ std::list::iterator it; for(it = mLocalQueries.begin(); it != mLocalQueries.end(); it++) { - if ((*it)->addPotentialPeer(id, 0)) + if ((*it)->addPotentialPeer(id, src, 0)) { isWorthyPeer = true; } @@ -494,12 +555,12 @@ void bdNode::checkPotentialPeer(bdId *id) if (isWorthyPeer) { - addPotentialPeer(id); + addPotentialPeer(id, src); } } -void bdNode::addPotentialPeer(bdId *id) +void bdNode::addPotentialPeer(bdId *id, bdId *src) { mPotentialPeers.push_back(*id); } @@ -571,21 +632,23 @@ void bdNode::addQuery(const bdNodeId *id, uint32_t qflags) { std::list startList; - std::multimap nearest; - std::multimap::iterator it; + std::multimap nearest; + std::multimap::iterator it; - mNodeSpace.find_nearest_nodes(id, BITDHT_QUERY_START_PEERS, startList, nearest); + //mNodeSpace.find_nearest_nodes(id, BITDHT_QUERY_START_PEERS, startList, nearest, 0); + + mNodeSpace.find_nearest_nodes(id, BITDHT_QUERY_START_PEERS, nearest); fprintf(stderr, "bdNode::addQuery("); mFns->bdPrintNodeId(std::cerr, id); fprintf(stderr, ")\n"); - for(it = nearest.begin(); it != nearest.end(); it++) - { - startList.push_back(it->second); - } + for(it = nearest.begin(); it != nearest.end(); it++) + { + startList.push_back(it->second); + } - bdQuery *query = new bdQuery(id, startList, qflags, mFns); + bdQuery *query = new bdQuery(id, startList, qflags, mFns); mLocalQueries.push_back(query); } @@ -645,12 +708,15 @@ void bdNode::processRemoteQuery() case BD_QUERY_NEIGHBOURS: { /* search bdSpace for neighbours */ - std::list excludeList; - std::list nearList; + //std::list excludeList; + + std::list nearList; std::multimap nearest; std::multimap::iterator it; - mNodeSpace.find_nearest_nodes(&(query.mQuery), BITDHT_QUERY_NEIGHBOUR_PEERS, excludeList, nearest); + //mNodeSpace.find_nearest_nodes(&(query.mQuery), BITDHT_QUERY_NEIGHBOUR_PEERS, excludeList, nearest, 0); + + mNodeSpace.find_nearest_nodes(&(query.mQuery), BITDHT_QUERY_NEIGHBOUR_PEERS, nearest); for(it = nearest.begin(); it != nearest.end(); it++) { @@ -1588,7 +1654,7 @@ void bdNode::msgin_reply_find_node(bdId *id, bdToken *transId, std::list & /* add neighbours to the potential list */ for(it = nodes.begin(); it != nodes.end(); it++) { - checkPotentialPeer(&(*it)); + checkPotentialPeer(&(*it), id); } /* received reply - so peer must be good */ @@ -1874,3 +1940,6 @@ bdNodeNetMsg::~bdNodeNetMsg() } + + + diff --git a/libbitdht/src/bitdht/bdnode.h b/libbitdht/src/bitdht/bdnode.h index 27d961a50..96f871f26 100644 --- a/libbitdht/src/bitdht/bdnode.h +++ b/libbitdht/src/bitdht/bdnode.h @@ -34,6 +34,8 @@ #include "bitdht/bdhash.h" #include "bitdht/bdhistory.h" +#include "bitdht/bdconnection.h" + #define BD_QUERY_NEIGHBOURS 1 #define BD_QUERY_HASH 2 @@ -106,13 +108,17 @@ class bdNode virtual void addPeer(const bdId *id, uint32_t peerflags); void printState(); - void checkPotentialPeer(bdId *id); - void addPotentialPeer(bdId *id); + void checkPotentialPeer(bdId *id, bdId *src); + void addPotentialPeer(bdId *id, bdId *src); void addQuery(const bdNodeId *id, uint32_t qflags); void clearQuery(const bdNodeId *id); void QueryStatus(std::map &statusMap); + /* connection functions */ + void requestConnection(bdNodeId *id, uint32_t modes); + void allowConnection(bdNodeId *id, uint32_t modes); + void iterationOff(); void iteration(); void processRemoteQuery(); @@ -127,6 +133,8 @@ void incomingMsg(struct sockaddr_in *addr, char *msg, int len); void sendPkt(char *msg, int len, struct sockaddr_in addr); void recvPkt(char *msg, int len, struct sockaddr_in addr); + /* internal assistance functions */ + void send_query(bdId *id, bdNodeId *targetNodeId); /* message out */ /* output functions (send msg) */ void msgout_ping(bdId *id, bdToken *transId); @@ -184,6 +192,65 @@ void recvPkt(char *msg, int len, struct sockaddr_in addr); void resetCounters(); void resetStats(); + + /****************************** Connection Code (in bdconnection.cc) ****************************/ + + /* Connections: Messages */ + + void msgout_connect_genmsg(bdId *id, bdToken *transId, int msgtype, + bdId *srcAddr, bdId *destAddr, int mode, int status); + void msgin_connect_genmsg(bdId *id, bdToken *transId, int type, + bdId *srcAddr, bdId *destAddr, int mode, int status); + + /* Connections: Initiation */ + + int requestConnection(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode); + int requestConnection_direct(struct sockaddr_in *laddr, bdNodeId *target); + int requestConnection_proxy(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode); + + int checkExistingConnectionAttempt(bdNodeId *target); + void addPotentialConnectionProxy(bdId *srcId, bdId *target); + void iterateConnectionRequests(); + + /* Connections: Outgoing */ + + int startConnectionAttempt(bdId *proxyId, bdId *srcConnAddr, bdId *destConnAddr, int mode); + void AuthConnectionOk(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc); + void AuthConnectionNo(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc); + void iterateConnections(); + + + /* Connections: Utility State */ + + bdConnection *findExistingConnection(bdNodeId *srcId, bdNodeId *proxyId, bdNodeId *destId); + bdConnection *newConnection(bdNodeId *srcId, bdNodeId *proxyId, bdNodeId *destId); + int cleanConnection(bdNodeId *srcId, bdNodeId *proxyId, bdNodeId *destId); + + int determinePosition(bdNodeId *sender, bdNodeId *src, bdNodeId *dest); + int determineProxyId(bdNodeId *sender, bdNodeId *src, bdNodeId *dest, bdNodeId *proxyId); + + bdConnection *findExistingConnectionBySender(bdId *sender, bdId *src, bdId *dest); + bdConnection *newConnectionBySender(bdId *sender, bdId *src, bdId *dest); + int cleanConnectionBySender(bdId *sender, bdId *src, bdId *dest); + + // Overloaded Generalised Connection Callback. + virtual void callbackConnect(bdId *srcId, bdId *proxyId, bdId *destId, + int mode, int point, int cbtype); + + /* Connections: */ + int recvedConnectionRequest(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode); + int recvedConnectionReply(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int status); + int recvedConnectionStart(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int bandwidth); + int recvedConnectionAck(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode); + + private: + + std::map mConnections; + std::map mConnectionRequests; + + + /****************************** Connection Code (in bdconnection.cc) ****************************/ + protected: @@ -218,6 +285,11 @@ void recvPkt(char *msg, int len, struct sockaddr_in addr); double mCounterQueryHash; double mCounterReplyFindNode; double mCounterReplyQueryHash; + // connection stats. + double mCounterConnectRequest; + double mCounterConnectReply; + double mCounterConnectStart; + double mCounterConnectAck; double mCounterRecvPing; double mCounterRecvPong; @@ -225,6 +297,11 @@ void recvPkt(char *msg, int len, struct sockaddr_in addr); double mCounterRecvQueryHash; double mCounterRecvReplyFindNode; double mCounterRecvReplyQueryHash; + // connection stats. + double mCounterRecvConnectRequest; + double mCounterRecvConnectReply; + double mCounterRecvConnectStart; + double mCounterRecvConnectAck; double mLpfOutOfDatePing; double mLpfPings; @@ -233,6 +310,11 @@ void recvPkt(char *msg, int len, struct sockaddr_in addr); double mLpfQueryHash; double mLpfReplyFindNode; double mLpfReplyQueryHash; + // connection stats. + double mLpfConnectRequest; + double mLpfConnectReply; + double mLpfConnectStart; + double mLpfConnectAck; double mLpfRecvPing; double mLpfRecvPong; @@ -240,6 +322,12 @@ void recvPkt(char *msg, int len, struct sockaddr_in addr); double mLpfRecvQueryHash; double mLpfRecvReplyFindNode; double mLpfRecvReplyQueryHash; + // connection stats. + double mLpfRecvConnectRequest; + double mLpfRecvConnectReply; + double mLpfRecvConnectStart; + double mLpfRecvConnectAck; + }; diff --git a/libbitdht/src/bitdht/bdpeer.cc b/libbitdht/src/bitdht/bdpeer.cc index e6b747cc1..10d99d00e 100644 --- a/libbitdht/src/bitdht/bdpeer.cc +++ b/libbitdht/src/bitdht/bdpeer.cc @@ -337,7 +337,10 @@ int bdSpace::clear() } -int bdSpace::find_nearest_nodes(const bdNodeId *id, int number, std::list /*excluding*/, std::multimap &nearest) + +int bdSpace::find_nearest_nodes_with_flags(const bdNodeId *id, int number, + std::list /* excluding */, + std::multimap &nearest, uint32_t with_flag) { std::multimap closest; std::multimap::iterator mit; @@ -363,16 +366,19 @@ int bdSpace::find_nearest_nodes(const bdNodeId *id, int number, std::list { for(eit = it->entries.begin(); eit != it->entries.end(); eit++) { - mFns->bdDistance(id, &(eit->mPeerId.id), &dist); - closest.insert(std::pair(dist, eit->mPeerId)); + if ((!with_flag) || (with_flag & eit->mPeerFlags)) + { + mFns->bdDistance(id, &(eit->mPeerId.id), &dist); + closest.insert(std::pair(dist, eit->mPeerId)); #if 0 - std::cerr << "Added NodeId: "; - bdPrintNodeId(std::cerr, &(eit->mPeerId.id)); - std::cerr << " Metric: "; - bdPrintNodeId(std::cerr, &(dist)); - std::cerr << std::endl; + std::cerr << "Added NodeId: "; + bdPrintNodeId(std::cerr, &(eit->mPeerId.id)); + std::cerr << " Metric: "; + bdPrintNodeId(std::cerr, &(dist)); + std::cerr << std::endl; #endif + } } } @@ -429,6 +435,15 @@ int bdSpace::find_nearest_nodes(const bdNodeId *id, int number, std::list return 1; } +int bdSpace::find_nearest_nodes(const bdNodeId *id, int number, + std::multimap &nearest) +{ + std::list excluding; + uint32_t with_flag = 0; + + return find_nearest_nodes_with_flags(id, number, excluding, nearest, with_flag); +} + int bdSpace::out_of_date_peer(bdId &id) { @@ -591,6 +606,7 @@ int bdSpace::add_peer(const bdId *id, uint32_t peerflags) newPeer.mPeerId = *id; newPeer.mLastRecvTime = ts; newPeer.mLastSendTime = ts; //???? + newPeer.mFoundTime = ts; newPeer.mPeerFlags = peerflags; buck.entries.push_back(newPeer); @@ -764,6 +780,16 @@ int bdSpace::printDHT() } +int bdSpace::getDhtBucket(const int idx, bdBucket &bucket) +{ + if ((idx < 0) || (idx > (int) buckets.size() - 1 )) + { + return 0; + } + bucket = buckets[idx]; + return 1; +} + uint32_t bdSpace::calcNetworkSize() { std::vector::iterator it; diff --git a/libbitdht/src/bitdht/bdpeer.h b/libbitdht/src/bitdht/bdpeer.h index 7d8f74f34..6c5be5409 100644 --- a/libbitdht/src/bitdht/bdpeer.h +++ b/libbitdht/src/bitdht/bdpeer.h @@ -116,6 +116,10 @@ int operator==(const bdId &a, const bdId &b); //std::string bdConvertToPrintable(std::string input); +/**** + * DEFINED in bdiface.h + * + class bdPeer { public: @@ -124,21 +128,22 @@ class bdPeer uint32_t mPeerFlags; time_t mLastSendTime; time_t mLastRecvTime; - time_t mFoundTime; /* time stamp that peer was found */ + time_t mFoundTime; // time stamp that peer was found }; - - class bdBucket { public: bdBucket(); - /* list so we can queue properly */ + // list so we can queue properly std::list entries; }; + * + * + *****/ class bdSpace { @@ -150,11 +155,16 @@ int clear(); /* accessors */ int find_nearest_nodes(const bdNodeId *id, int number, - std::list excluding, std::multimap &nearest); + std::multimap &nearest); + +int find_nearest_nodes_with_flags(const bdNodeId *id, int number, + std::list excluding, + std::multimap &nearest, uint32_t with_flag); int out_of_date_peer(bdId &id); // side-effect updates, send flag on peer. int add_peer(const bdId *id, uint32_t mode); int printDHT(); +int getDhtBucket(const int idx, bdBucket &bucket); uint32_t calcNetworkSize(); uint32_t calcNetworkSizeWithFlag(uint32_t withFlag); diff --git a/libbitdht/src/bitdht/bdquery.cc b/libbitdht/src/bitdht/bdquery.cc index bd5e10c0f..406897ff3 100644 --- a/libbitdht/src/bitdht/bdquery.cc +++ b/libbitdht/src/bitdht/bdquery.cc @@ -104,6 +104,17 @@ bool bdQuery::result(std::list &answer) return (i > 0); } +bool bdQuery::proxies(std::list &answer) +{ + /* get all the matches to our query */ + std::list::iterator it; + int i = 0; + for(it = mPotentialProxies.begin(); it != mPotentialProxies.end(); it++, i++) + { + answer.push_back(it->mPeerId); + } + return (i > 0); +} int bdQuery::nextQuery(bdId &id, bdNodeId &targetNodeId) { @@ -399,7 +410,7 @@ int bdQuery::addPeer(const bdId *id, uint32_t mode) * simple list of closest. */ -int bdQuery::addPotentialPeer(const bdId *id, uint32_t mode) +int bdQuery::addPotentialPeer(const bdId *id, const bdId *src, uint32_t mode) { bdMetric dist; time_t ts = time(NULL); @@ -541,6 +552,44 @@ int bdQuery::addPotentialPeer(const bdId *id, uint32_t mode) #ifdef DEBUG_QUERY fprintf(stderr, "Flagging as Potential Peer!\n"); #endif + + /* finally if it is an exact match, add as potential proxy */ + int bucket = mFns->bdBucketDistance(&dist); + if ((bucket == 0) && (src != NULL)) + { + +#ifdef DEBUG_QUERY + fprintf(stderr, "Bucket = 0, Have Potential Proxy!\n"); +#endif + std::list::iterator it; + for(it = mPotentialProxies.begin(); it != mPotentialProxies.end(); it++) + { + if (*src == it->mPeerId) + { + /* found it ;( */ +#ifdef DEBUG_QUERY + fprintf(stderr, "Source Already in Potential Proxy List, updating timestamp!\n"); +#endif + it->mLastRecvTime = ts; + break; + } + } + if (it == mPotentialProxies.end()) + { +#ifdef DEBUG_QUERY + fprintf(stderr, "Adding Source to Potential Proxy List:\n"); +#endif + /* add it in */ + bdPeer peer; + peer.mPeerId = *src; + peer.mLastSendTime = 0; + peer.mLastRecvTime = ts; + peer.mFoundTime = ts; + + mPotentialProxies.push_back(peer); + } + } + retval = 1; return retval; } @@ -590,6 +639,18 @@ int bdQuery::printQuery() fprintf(stderr," LastRecv: %ld ago", ts-it->second.mLastRecvTime); fprintf(stderr, "\n"); } + + std::list::iterator lit; + fprintf(stderr, "\nPotential Proxies:\n"); + for(lit = mPotentialProxies.begin(); lit != mPotentialProxies.end(); lit++) + { + fprintf(stderr, "ProxyId: "); + mFns->bdPrintId(std::cerr, &(lit->mPeerId)); + fprintf(stderr," Found: %ld ago", ts-lit->mFoundTime); + fprintf(stderr," LastSent: %ld ago", ts-lit->mLastSendTime); + fprintf(stderr," LastRecv: %ld ago", ts-lit->mLastRecvTime); + fprintf(stderr, "\n"); + } #else // shortened version. fprintf(stderr, "Closest Available Peer: "); @@ -615,6 +676,18 @@ int bdQuery::printQuery() fprintf(stderr," LastRecv: %ld ago", ts-it->second.mLastRecvTime); } fprintf(stderr, "\n"); + + std::list::iterator lit; + fprintf(stderr, "Potential Proxies:\n"); + for(lit = mPotentialProxies.begin(); lit != mPotentialProxies.end(); lit++) + { + fprintf(stderr, "ProxyId: "); + mFns->bdPrintId(std::cerr, &(lit->mPeerId)); + fprintf(stderr," Found: %ld ago", ts-lit->mFoundTime); + fprintf(stderr," LastSent: %ld ago", ts-lit->mLastSendTime); + fprintf(stderr," LastRecv: %ld ago", ts-lit->mLastRecvTime); + fprintf(stderr, "\n"); + } #endif return 1; diff --git a/libbitdht/src/bitdht/bdquery.h b/libbitdht/src/bitdht/bdquery.h index 1c700032f..a0fa633e0 100644 --- a/libbitdht/src/bitdht/bdquery.h +++ b/libbitdht/src/bitdht/bdquery.h @@ -44,12 +44,13 @@ class bdQuery // get the answer. bool result(std::list &answer); +bool proxies(std::list &answer); // returning results get passed to all queries. //void addNode(const bdId *id, int mode); int nextQuery(bdId &id, bdNodeId &targetId); int addPeer(const bdId *id, uint32_t mode); -int addPotentialPeer(const bdId *id, uint32_t mode); +int addPotentialPeer(const bdId *id, const bdId *src, uint32_t mode); int printQuery(); // searching for @@ -67,6 +68,7 @@ int printQuery(); // closest peers std::multimap mClosest; std::multimap mPotentialClosest; + std::list mPotentialProxies; bdDhtFunctions *mFns; }; diff --git a/libbitdht/src/bitdht/bdstddht.cc b/libbitdht/src/bitdht/bdstddht.cc index 4d11b1a53..b63e82749 100644 --- a/libbitdht/src/bitdht/bdstddht.cc +++ b/libbitdht/src/bitdht/bdstddht.cc @@ -116,6 +116,43 @@ void bdStdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *m } } +int bdStdLoadNodeId(bdNodeId *id, std::string input) +{ + uint8_t *a_data = (uint8_t *) id->data; + int reqlen = BITDHT_KEY_LEN * 2; + if (input.size() < reqlen) + { + return 0; + } + + for(int i = 0; i < BITDHT_KEY_LEN; i++) + { + char ch1 = input[2 * i]; + char ch2 = input[2 * i + 1]; + uint8_t value1 = 0; + uint8_t value2 = 0; + + /* do char1 */ + if (ch1 >= '0' && ch1 <= '9') + value1 = (ch1 - '0'); + else if (ch1 >= 'A' && ch1 <= 'F') + value1 = (ch1 - 'A' + 10); + else if (ch1 >= 'a' && ch1 <= 'f') + value1 = (ch1 - 'a' + 10); + + /* do char2 */ + if (ch2 >= '0' && ch2 <= '9') + value2 = (ch2 - '0'); + else if (ch2 >= 'A' && ch2 <= 'F') + value2 = (ch2 - 'A' + 10); + else if (ch2 >= 'a' && ch2 <= 'f') + value2 = (ch2 - 'a' + 10); + + a_data[i] = (value1 << 4) + value2; + } + return 1; +} + std::string bdStdConvertToPrintable(std::string input) { std::ostringstream out; diff --git a/libbitdht/src/bitdht/bdstddht.h b/libbitdht/src/bitdht/bdstddht.h index 8e8bf47d8..72c487df3 100644 --- a/libbitdht/src/bitdht/bdstddht.h +++ b/libbitdht/src/bitdht/bdstddht.h @@ -52,6 +52,8 @@ int bdStdBucketDistance(const bdNodeId *a, const bdNodeId *b); void bdStdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *mid); +int bdStdLoadNodeId(bdNodeId *id, std::string input); + void bdStdPrintId(std::ostream &out, const bdId *a); void bdStdPrintNodeId(std::ostream &out, const bdNodeId *a); diff --git a/libbitdht/src/libbitdht.pro b/libbitdht/src/libbitdht.pro index 0c3a1d6b6..ee7685527 100644 --- a/libbitdht/src/libbitdht.pro +++ b/libbitdht/src/libbitdht.pro @@ -103,6 +103,7 @@ HEADERS += \ udp/udplayer.h \ udp/udpstack.h \ udp/udpbitdht.h \ + bitdht/bdconnection.h \ SOURCES += \ bitdht/bencode.c \ @@ -121,5 +122,6 @@ SOURCES += \ udp/udplayer.cc \ udp/udpstack.cc \ udp/udpbitdht.cc \ + bitdht/bdconnection.cc \ diff --git a/libbitdht/src/tests/bdmgr_multitest.cc b/libbitdht/src/tests/bdmgr_multitest.cc index 594c1598f..4d9902e0d 100644 --- a/libbitdht/src/tests/bdmgr_multitest.cc +++ b/libbitdht/src/tests/bdmgr_multitest.cc @@ -93,7 +93,7 @@ int main(int argc, char **argv) } if (it != nodes.end()) { - nit->second->addPotentialPeer((bdId *) &(it->first)); + nit->second->addPotentialPeer((bdId *) &(it->first), NULL); } } } diff --git a/libbitdht/src/tests/bdnode_multitest1.cc b/libbitdht/src/tests/bdnode_multitest1.cc index 11e6790a4..13a381c97 100644 --- a/libbitdht/src/tests/bdnode_multitest1.cc +++ b/libbitdht/src/tests/bdnode_multitest1.cc @@ -90,7 +90,7 @@ int main(int argc, char **argv) int peeridx = rand() % n_nodes; bdId pid = portIdx[peeridx]; - node->addPotentialPeer(&pid); + node->addPotentialPeer(&pid, NULL); } } diff --git a/libbitdht/src/tests/bdquery_test.cc b/libbitdht/src/tests/bdquery_test.cc index c3dd9527e..b4c8e980b 100644 --- a/libbitdht/src/tests/bdquery_test.cc +++ b/libbitdht/src/tests/bdquery_test.cc @@ -63,7 +63,7 @@ int main(int argc, char **argv) std::multimap nearest; std::multimap::iterator it; - space.find_nearest_nodes(&(queryId.id), N_PEERS_TO_START, startList, nearest); + space.find_nearest_nodes(&(queryId.id), N_PEERS_TO_START, nearest); for(it = nearest.begin(); it != nearest.end(); it++) { diff --git a/libbitdht/src/tests/bdspace_test2.cc b/libbitdht/src/tests/bdspace_test2.cc index 26a2608f0..ca9e7f024 100644 --- a/libbitdht/src/tests/bdspace_test2.cc +++ b/libbitdht/src/tests/bdspace_test2.cc @@ -56,10 +56,9 @@ int main(int argc, char **argv) { bdId tmpId; bdStdRandomId(&tmpId); - std::list list1; std::multimap list2; - space.find_nearest_nodes(&(tmpId.id), N_PEERS_TO_FIND, list1, list2); + space.find_nearest_nodes(&(tmpId.id), N_PEERS_TO_FIND, list2); } return 1; diff --git a/libbitdht/src/udp/udpbitdht.cc b/libbitdht/src/udp/udpbitdht.cc index 5f2a184a4..fe9897065 100644 --- a/libbitdht/src/udp/udpbitdht.cc +++ b/libbitdht/src/udp/udpbitdht.cc @@ -118,6 +118,24 @@ void UdpBitDht::removeCallback(BitDhtCallback *cb) mBitDhtManager->removeCallback(cb); } +void UdpBitDht::ConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode) +{ + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + + mBitDhtManager->ConnectionRequest(laddr, target, mode); +} + + + +void UdpBitDht::ConnectionAuth(bdId *srcId, bdId *proxyId, bdId *destId, uint32_t mode, uint32_t loc, uint32_t answer) +{ + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + + mBitDhtManager->ConnectionAuth(srcId, proxyId, destId, mode, loc, answer); +} + + + int UdpBitDht::getDhtPeerAddress(const bdNodeId *id, struct sockaddr_in &from) { bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ @@ -132,6 +150,13 @@ int UdpBitDht::getDhtValue(const bdNodeId *id, std::string key, std::string &va return mBitDhtManager->getDhtValue(id, key, value); } +int UdpBitDht::getDhtBucket(const int idx, bdBucket &bucket) +{ + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + + return mBitDhtManager->getDhtBucket(idx, bucket); +} + /* stats and Dht state */ int UdpBitDht:: startDht() diff --git a/libbitdht/src/udp/udpbitdht.h b/libbitdht/src/udp/udpbitdht.h index 41ed51757..11c99814d 100644 --- a/libbitdht/src/udp/udpbitdht.h +++ b/libbitdht/src/udp/udpbitdht.h @@ -67,9 +67,14 @@ virtual void findDhtValue(bdNodeId *id, std::string key, uint32_t mode); virtual void addCallback(BitDhtCallback *cb); virtual void removeCallback(BitDhtCallback *cb); + /***** Connections Requests *****/ +virtual void ConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode); +virtual void ConnectionAuth(bdId *srcId, bdId *proxyId, bdId *destId, uint32_t mode, uint32_t loc, uint32_t answer); + /***** Get Results Details *****/ virtual int getDhtPeerAddress(const bdNodeId *id, struct sockaddr_in &from); virtual int getDhtValue(const bdNodeId *id, std::string key, std::string &value); +virtual int getDhtBucket(const int idx, bdBucket &bucket); /* stats and Dht state */ virtual int startDht();