diff --git a/libbitdht/src/bitdht/bdconnection.cc b/libbitdht/src/bitdht/bdconnection.cc index 28e24ca64..5ffaf4e32 100644 --- a/libbitdht/src/bitdht/bdconnection.cc +++ b/libbitdht/src/bitdht/bdconnection.cc @@ -86,6 +86,13 @@ void bdConnectManager::setConnectionOptions(uint32_t allowedModes, uint32_t flag } +/* Setup Relay Mode */ +void bdConnectManager::setRelayMode(uint32_t mode) +{ + mRelayMode = mode; +} + + void bdConnectManager::shutdownConnections() { #ifdef DEBUG_NODE_CONNECTION @@ -2085,6 +2092,15 @@ int bdConnectManager::recvedConnectionRequest(bdId *id, bdId *srcConnAddr, bdId /* remove connection */ bdConnectManager::cleanConnectionBySender(id, srcConnAddr, destConnAddr); + /* WILL NEED CALLBACK FOR FAILED PROXY ATTEMPT - TO SUPPORT RELAYS PROPERLY + * NODE needs to know PEERS to potentially WHITELIST! + */ + if (mRelayMode == BITDHT_RELAYS_SERVER) + { + callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), + conn->mMode, conn->mPoint, param, BITDHT_CONNECT_CB_AUTH, + BITDHT_CONNECT_ERROR_NOADDRESS); + } } } else diff --git a/libbitdht/src/bitdht/bdconnection.h b/libbitdht/src/bitdht/bdconnection.h index f11fd7ec0..aa5cd8492 100644 --- a/libbitdht/src/bitdht/bdconnection.h +++ b/libbitdht/src/bitdht/bdconnection.h @@ -255,6 +255,9 @@ class bdConnectManager int recvedConnectionStart(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int delayOrBandwidth); int recvedConnectionAck(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode); + /* setup Relay Mode */ + void setRelayMode(uint32_t mode); + private: std::map mConnections; @@ -263,6 +266,8 @@ class bdConnectManager uint32_t mConfigAllowedModes; bool mConfigAutoProxy; + uint32_t mRelayMode; + /****************************** Connection Code (in bdconnection.cc) ****************************/ private: diff --git a/libbitdht/src/bitdht/bdfriendlist.cc b/libbitdht/src/bitdht/bdfriendlist.cc index 630aba2a0..bb47c582a 100644 --- a/libbitdht/src/bitdht/bdfriendlist.cc +++ b/libbitdht/src/bitdht/bdfriendlist.cc @@ -159,6 +159,33 @@ bool bdFriendList::findPeerEntry(const bdNodeId *id, bdFriendEntry &entry) } +bool bdFriendList::findPeersWithFlags(uint32_t flags, std::list &peerList) +{ +#ifdef DEBUG_FRIENDLIST + std::cerr << "bdFriendList::findPeersWithFlags(" << flags << ")"; + std::cerr << std::endl; +#endif + + /* see if it exists... */ + std::map::iterator it; + for(it = mPeers.begin(); it != mPeers.end(); it++) + { + /* if they have ALL of the flags we specified */ + if ((it->second.getPeerFlags() & flags) == flags) + { +#ifdef DEBUG_FRIENDLIST + std::cerr << "bdFriendList::findPeersWithFlags() Found: "; + bdStdPrintNodeId(std::cerr, id); + std::cerr << std::endl; +#endif + peerList.push_back(it->second.mPeerId.id); + } + } + return (peerList.size() > 0); +} + + + bool bdFriendList::print(std::ostream &out) { time_t now = time(NULL); diff --git a/libbitdht/src/bitdht/bdfriendlist.h b/libbitdht/src/bitdht/bdfriendlist.h index 825f5ad65..35cad86bb 100644 --- a/libbitdht/src/bitdht/bdfriendlist.h +++ b/libbitdht/src/bitdht/bdfriendlist.h @@ -77,6 +77,7 @@ bool updatePeer(const bdId *id, uint32_t flags); bool removePeer(const bdNodeId *id); bool findPeerEntry(const bdNodeId *id, bdFriendEntry &entry); +bool findPeersWithFlags(uint32_t flags, std::list &peerList); bool print(std::ostream &out); private: diff --git a/libbitdht/src/bitdht/bdiface.h b/libbitdht/src/bitdht/bdiface.h index af59eab38..65b24a25f 100644 --- a/libbitdht/src/bitdht/bdiface.h +++ b/libbitdht/src/bitdht/bdiface.h @@ -109,19 +109,20 @@ virtual void bdPrintNodeId(std::ostream &out, const bdNodeId *a) = 0; // DHT MODES #define BITDHT_MODE_TRAFFIC_MASK 0x00000f00 -#define BITDHT_MODE_RELAY_MASK 0x0000f000 +#define BITDHT_MODE_RELAYSERVER_MASK 0x0000f000 // These are not ORd - only one can apply. -#define BITDHT_MODE_TRAFFIC_DEFAULT 0x00000000 #define BITDHT_MODE_TRAFFIC_HIGH 0x00000100 #define BITDHT_MODE_TRAFFIC_MED 0x00000200 #define BITDHT_MODE_TRAFFIC_LOW 0x00000300 #define BITDHT_MODE_TRAFFIC_TRICKLE 0x00000400 +#define BITDHT_MODE_TRAFFIC_DEFAULT BITDHT_MODE_TRAFFIC_LOW // These are not ORd - only one can apply. -#define BITDHT_MODE_RELAYS_IGNORED 0x00000000 -#define BITDHT_MODE_RELAYS_FLAGGED 0x00001000 -#define BITDHT_MODE_RELAYS_ONLY 0x00002000 +#define BITDHT_MODE_RELAYSERVERS_IGNORED 0x00001000 +#define BITDHT_MODE_RELAYSERVERS_FLAGGED 0x00002000 +#define BITDHT_MODE_RELAYSERVERS_ONLY 0x00003000 +#define BITDHT_MODE_RELAYSERVERS_SERVER 0x00004000 /* NODE OPTIONS */ @@ -303,9 +304,9 @@ class bdQuerySummary /* Query Flags */ #define BITDHT_QFLAGS_NONE 0x0000 -#define BITDHT_QFLAGS_DISGUISE 0x0001 +#define BITDHT_QFLAGS_DISGUISE 0x0001 // Don't search directly for target. #define BITDHT_QFLAGS_DO_IDLE 0x0002 -#define BITDHT_QFLAGS_INTERNAL 0x0004 // runs through startup. +#define BITDHT_QFLAGS_INTERNAL 0x0004 // runs through startup. (limited callback) #define BITDHT_QFLAGS_UPDATES 0x0008 // Do regular updates. /* Connect Callback Flags */ @@ -323,6 +324,12 @@ class bdQuerySummary #define BITDHT_INFO_CB_TYPE_BADPEER 1 +/* Relay Modes */ +#define BITDHT_RELAYS_OFF 0 +#define BITDHT_RELAYS_ON 1 +#define BITDHT_RELAYS_ONLY 2 +#define BITDHT_RELAYS_SERVER 3 + class BitDhtCallback { diff --git a/libbitdht/src/bitdht/bdnode.cc b/libbitdht/src/bitdht/bdnode.cc index 8b88cdd2e..b48660853 100644 --- a/libbitdht/src/bitdht/bdnode.cc +++ b/libbitdht/src/bitdht/bdnode.cc @@ -111,47 +111,81 @@ void bdNode::setNodeOptions(uint32_t optFlags) #define BDNODE_LOW_MSG_RATE 5 #define BDNODE_TRICKLE_MSG_RATE 3 +/* So we are setting this up so you can independently update each parameter.... + * if the mask is empty - it'll use the previous parameter. + * + */ + + uint32_t bdNode::setNodeDhtMode(uint32_t dhtFlags) { + std::cerr << "bdNode::setNodeDhtMode(" << dhtFlags << "), origFlags: " << mNodeDhtMode; + std::cerr << std::endl; + uint32_t origFlags = mNodeDhtMode; - mNodeDhtMode = dhtFlags; + uint32_t traffic = dhtFlags & BITDHT_MODE_TRAFFIC_MASK; - - switch(traffic) + if (traffic) { - default: - case BITDHT_MODE_TRAFFIC_DEFAULT: - case BITDHT_MODE_TRAFFIC_LOW: - mMaxAllowedMsgs = BDNODE_HIGH_MSG_RATE; - break; - case BITDHT_MODE_TRAFFIC_HIGH: - mMaxAllowedMsgs = BDNODE_LOW_MSG_RATE; - break; - case BITDHT_MODE_TRAFFIC_MED: - mMaxAllowedMsgs = BDNODE_MED_MSG_RATE; - break; - case BITDHT_MODE_TRAFFIC_TRICKLE: - mMaxAllowedMsgs = BDNODE_TRICKLE_MSG_RATE; - break; + switch(traffic) + { + default: + case BITDHT_MODE_TRAFFIC_LOW: + mMaxAllowedMsgs = BDNODE_HIGH_MSG_RATE; + break; + case BITDHT_MODE_TRAFFIC_HIGH: + mMaxAllowedMsgs = BDNODE_LOW_MSG_RATE; + break; + case BITDHT_MODE_TRAFFIC_MED: + mMaxAllowedMsgs = BDNODE_MED_MSG_RATE; + break; + case BITDHT_MODE_TRAFFIC_TRICKLE: + mMaxAllowedMsgs = BDNODE_TRICKLE_MSG_RATE; + break; + } + } + else + { + dhtFlags |= (origFlags & BITDHT_MODE_TRAFFIC_MASK); } - uint32_t relay = dhtFlags & BITDHT_MODE_RELAY_MASK; - if (relay != (origFlags & BITDHT_MODE_RELAY_MASK)) + uint32_t relay = dhtFlags & BITDHT_MODE_RELAYSERVER_MASK; + if ((relay) && (relay != (origFlags & BITDHT_MODE_RELAYSERVER_MASK))) { /* changed */ switch(relay) { default: - case BITDHT_MODE_RELAYS_IGNORED: + case BITDHT_MODE_RELAYSERVERS_IGNORED: + mRelayMode = BITDHT_RELAYS_OFF; + dropRelayServers(); break; - case BITDHT_MODE_RELAYS_FLAGGED: + case BITDHT_MODE_RELAYSERVERS_FLAGGED: + mRelayMode = BITDHT_RELAYS_ON; + pingRelayServers(); break; - case BITDHT_MODE_RELAYS_ONLY: + case BITDHT_MODE_RELAYSERVERS_ONLY: + mRelayMode = BITDHT_RELAYS_ONLY; + pingRelayServers(); + break; + case BITDHT_MODE_RELAYSERVERS_SERVER: + mRelayMode = BITDHT_RELAYS_SERVER; + pingRelayServers(); break; } + mConnMgr->setRelayMode(mRelayMode); } - + else + { + dhtFlags |= (origFlags & BITDHT_MODE_RELAYSERVER_MASK); + } + + mNodeDhtMode = dhtFlags; + + std::cerr << "bdNode::setNodeDhtMode() newFlags: " << mNodeDhtMode; + std::cerr << std::endl; + return dhtFlags; } @@ -2206,5 +2240,55 @@ bdNodeNetMsg::~bdNodeNetMsg() +/**************** In/Out of Relay Mode ******************/ + +void bdNode::dropRelayServers() +{ + /* We leave them there... just drop the flags */ + uint32_t flags = BITDHT_PEER_STATUS_DHT_RELAY_SERVER; + std::list peerList; + std::list::iterator it; + + mFriendList.findPeersWithFlags(flags, peerList); + for(it = peerList.begin(); it != peerList.end(); it++) + { + mFriendList.removePeer(&(*it)); + } + + mNodeSpace.clean_node_flags(flags); +} + +void bdNode::pingRelayServers() +{ + /* if Relay's have been switched on, do search/ping to locate servers */ + std::cerr << "bdNode::pingRelayServers()"; + std::cerr << std::endl; + + bool doSearch = true; + + uint32_t flags = BITDHT_PEER_STATUS_DHT_RELAY_SERVER; + std::list peerList; + std::list::iterator it; + + mFriendList.findPeersWithFlags(flags, peerList); + for(it = peerList.begin(); it != peerList.end(); it++) + { + if (doSearch) + { + uint32_t qflags = BITDHT_QFLAGS_INTERNAL | BITDHT_QFLAGS_DISGUISE; + mQueryMgr->addQuery(&(*it), qflags); + + std::cerr << "bdNode::pingRelayServers() Adding Internal Search for Relay Server: "; + mFns->bdPrintNodeId(std::cerr, &(*it)); + std::cerr << std::endl; + + } + else + { + /* try ping - if we have an address??? */ + + } + } +} diff --git a/libbitdht/src/bitdht/bdnode.h b/libbitdht/src/bitdht/bdnode.h index 965b76b90..2b13bc2ed 100644 --- a/libbitdht/src/bitdht/bdnode.h +++ b/libbitdht/src/bitdht/bdnode.h @@ -158,6 +158,9 @@ class bdNode: public bdNodePublisher int outgoingMsg(struct sockaddr_in *addr, char *msg, int *len); void incomingMsg(struct sockaddr_in *addr, char *msg, int len); + // For Relay Mode switching. +void dropRelayServers(); +void pingRelayServers(); // Below is internal Management of incoming / outgoing messages. private: @@ -251,7 +254,9 @@ void recvPkt(char *msg, int len, struct sockaddr_in addr); uint32_t mNodeOptionFlags; uint32_t mNodeDhtMode; + uint32_t mMaxAllowedMsgs; + uint32_t mRelayMode; bdHistory mHistory; /* for understanding the DHT */ diff --git a/libbitdht/src/bitdht/bdpeer.cc b/libbitdht/src/bitdht/bdpeer.cc index 0740d2e77..3d68dafbb 100644 --- a/libbitdht/src/bitdht/bdpeer.cc +++ b/libbitdht/src/bitdht/bdpeer.cc @@ -436,6 +436,39 @@ int bdSpace::find_exactnode(const bdId *id, bdPeer &peer) } + +int bdSpace::clean_node_flags(uint32_t flags) +{ + std::cerr << "bdSpace::clean_node_flags(" << flags << ")"; + std::cerr << std::endl; + + int count = 0; + std::vector::iterator bit; + for(bit = buckets.begin(); bit != buckets.end(); bit++) + { + std::list::iterator eit; + for(eit = bit->entries.begin(); eit != bit->entries.end(); eit++) + { + if (flags & eit->mPeerFlags) + { + std::cerr << "bdSpace::clean_node_flags() Found Match: "; + mFns->bdPrintId(std::cerr, &(eit->mPeerId)); + std::cerr << " withFlags: " << eit->mPeerFlags; + std::cerr << std::endl; + + count++; + eit->mPeerFlags &= ~flags; + } + } + } + std::cerr << "bdSpace::clean_node_flags() Cleaned " << count << " Matching Peers"; + std::cerr << std::endl; + + return count; +} + + + #define BITDHT_ATTACHED_SEND_PERIOD 17 int bdSpace::scanOutOfDatePeers(std::list &peerIds) diff --git a/libbitdht/src/bitdht/bdpeer.h b/libbitdht/src/bitdht/bdpeer.h index fdba9e1aa..871f41121 100644 --- a/libbitdht/src/bitdht/bdpeer.h +++ b/libbitdht/src/bitdht/bdpeer.h @@ -190,6 +190,9 @@ uint32_t calcSpaceSizeWithFlag(uint32_t withFlag); /* special function to enable DHT localisation (i.e find peers from own network) */ bool findRandomPeerWithFlag(bdId &id, uint32_t withFlag); + /* strip out flags - to switch in/out of relay mode */ +int clean_node_flags(uint32_t flags); + /* to add later */ int updateOwnId(bdNodeId *newOwnId); diff --git a/libbitdht/src/udp/udpproxylayer.h b/libbitdht/src/udp/udpproxylayer.h new file mode 100644 index 000000000..40ba10a91 --- /dev/null +++ b/libbitdht/src/udp/udpproxylayer.h @@ -0,0 +1,186 @@ +#ifndef BITDHT_UDP_LAYER_H +#define BITDHT_UDP_LAYER_H + +/* + * udp/udplayer.h + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2004-2010 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 "util/bdthreads.h" +#include "util/bdnet.h" + +#include +#include +#include + +/* careful - duplicate definitions */ +//std::ostream &operator<<(std::ostream &out, const struct sockaddr_in &addr); +std::ostream &operator<<(std::ostream &out, struct sockaddr_in &addr); + +bool operator==(const struct sockaddr_in &addr, const struct sockaddr_in &addr2); +bool operator<(const struct sockaddr_in &addr, const struct sockaddr_in &addr2); + +std::string printPkt(void *d, int size); +std::string printPktOffset(unsigned int offset, void *d, unsigned int size); + + +/* UdpLayer ..... is the bottom layer which + * just sends and receives Udp packets. + */ + +class UdpReceiver +{ + public: +virtual ~UdpReceiver() {} +virtual int recvPkt(void *data, int size, struct sockaddr_in &from) = 0; +virtual int status(std::ostream &out) = 0; +}; + +class UdpPublisher +{ + public: +virtual ~UdpPublisher() {} +virtual int sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl) = 0; +}; + + +class UdpLayer: public bdThread +{ + public: + + UdpLayer(UdpReceiver *recv, struct sockaddr_in &local); +virtual ~UdpLayer() { return; } + +int reset(struct sockaddr_in &local); /* calls join, close, openSocket */ + +int status(std::ostream &out); + + /* setup connections */ + int closeSocket(); + int openSocket(); + + /* RsThread functions */ +virtual void run(); /* called once the thread is started */ + +void recv_loop(); /* uses callback to UdpReceiver */ + + /* Higher Level Interface */ + //int readPkt(void *data, int *size, struct sockaddr_in &from); + int sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl); + + /* monitoring / updates */ + int okay(); + int tick(); + + + /* data */ + /* internals */ + protected: + +virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from); +virtual int sendUdpPacket(const void *data, int size, const struct sockaddr_in &to); + + int setTTL(int t); + int getTTL(); + + /* low level */ + private: + + UdpReceiver *recv; + + struct sockaddr_in laddr; /* local addr */ + + int errorState; + int sockfd; + int ttl; + bool stopThread; + + bdMutex sockMtx; +}; + + +/* For Testing - drops packets */ +class LossyUdpLayer: public UdpLayer +{ + public: + LossyUdpLayer(UdpReceiver *udpr, struct sockaddr_in &local, double frac); +virtual ~LossyUdpLayer(); + + protected: + +virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from); +virtual int sendUdpPacket(const void *data, int size, const struct sockaddr_in &to); + + double lossFraction; +}; + +class PortRange +{ + public: + PortRange(); + PortRange(uint16_t lp, uint16_t up); + + bool inRange(uint16_t port); + + uint16_t lport; + uint16_t uport; +}; + + +/* For Testing - drops packets */ +class RestrictedUdpLayer: public UdpLayer +{ + public: + RestrictedUdpLayer(UdpReceiver *udpr, struct sockaddr_in &local); +virtual ~RestrictedUdpLayer(); + +void addRestrictedPortRange(int lp, int up); + + protected: + +virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from); +virtual int sendUdpPacket(const void *data, int size, const struct sockaddr_in &to); + + std::list mLostPorts; +}; + + +/* For Testing - drops packets all packets for initial minute (simulates TTL) */ +class TimedUdpLayer: public UdpLayer +{ + public: + TimedUdpLayer(UdpReceiver *udpr, struct sockaddr_in &local); +virtual ~TimedUdpLayer(); + + protected: + +virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from); +virtual int sendUdpPacket(const void *data, int size, const struct sockaddr_in &to); + + time_t mStartTime; + bool mActive; + +}; + + +#endif diff --git a/libretroshare/src/dht/p3bitdht.cc b/libretroshare/src/dht/p3bitdht.cc index 549bcd8ad..a6616bb08 100644 --- a/libretroshare/src/dht/p3bitdht.cc +++ b/libretroshare/src/dht/p3bitdht.cc @@ -83,7 +83,7 @@ virtual int dhtInfoCallback(const bdId *id, uint32_t type, uint32_t flags, std:: p3BitDht::p3BitDht(std::string id, pqiConnectCb *cb, p3NetMgr *nm, UdpStack *udpstack, std::string bootstrapfile) - :pqiNetAssistConnect(id, cb), mNetMgr(nm), dhtMtx("p3BitDht") + :p3Config(CONFIG_TYPE_BITDHT), pqiNetAssistConnect(id, cb), mNetMgr(nm), dhtMtx("p3BitDht") { mDhtStunner = NULL; mProxyStunner = NULL; @@ -91,6 +91,8 @@ p3BitDht::p3BitDht(std::string id, pqiConnectCb *cb, p3NetMgr *nm, mPeerSharer = NULL; + mRelayHandler = NULL; + std::string dhtVersion = "RS51"; // should come from elsewhere! mOwnRsId = id; @@ -131,6 +133,7 @@ p3BitDht::p3BitDht(std::string id, pqiConnectCb *cb, p3NetMgr *nm, p3BdCallback *bdcb = new p3BdCallback(this); mUdpBitDht->addCallback(bdcb); +#if 0 /* enable all modes */ /* Switched to only Proxy Mode - as Direct Connections can be unreliable - as they share the UDP with the DHT.... * We'll get these working properly and then if necessary get Direct further tested. @@ -141,6 +144,9 @@ p3BitDht::p3BitDht(std::string id, pqiConnectCb *cb, p3NetMgr *nm, BITDHT_CONNECT_MODE_PROXY, BITDHT_CONNECT_OPTION_AUTOPROXY); +#endif + + setupRelayDefaults(); } p3BitDht::~p3BitDht() @@ -162,6 +168,23 @@ void p3BitDht::setupPeerSharer(pqiNetAssistPeerShare *sharer) mPeerSharer = sharer; } + +/* Support for Outsourced Relay Handling */ + +void p3BitDht::installRelayHandler(p3BitDhtRelayHandler *handler) +{ + /* The Handler is mutex protected, as its installation can occur when the dht is already running */ + RsStackMutex stack(dhtMtx); /********* LOCKED *********/ + + mRelayHandler = handler; +} + +UdpRelayReceiver *p3BitDht::getRelayReceiver() +{ + return mRelay; +} + + void p3BitDht::start() { #ifdef DEBUG_BITDHT diff --git a/libretroshare/src/dht/p3bitdht.h b/libretroshare/src/dht/p3bitdht.h index 320bdb7d9..5df81e6d2 100644 --- a/libretroshare/src/dht/p3bitdht.h +++ b/libretroshare/src/dht/p3bitdht.h @@ -28,6 +28,7 @@ #define MRK_P3_BITDHT_H #include "pqi/pqiassist.h" +#include "pqi/p3cfgmgr.h" #include "retroshare/rsdht.h" #include @@ -118,12 +119,27 @@ class PeerAction +/****** + * Adding the ability to install alternative Handler + * for monitoring/controlling Relay Connections outside of p3bitdht. + ***/ + +class p3BitDhtRelayHandler +{ + public: + + int (*mInstallRelay)(const bdId *srcId, const bdId *destId, uint32_t mode, uint32_t &bandwidth); + int (*mLogFailedConnection)(const bdId *srcId, const bdId *destId, uint32_t mode, uint32_t errcode); +}; + + + class UdpRelayReceiver; class UdpStunner; class p3NetMgr; -class p3BitDht: public pqiNetAssistConnect, public RsDht +class p3BitDht: public p3Config, public pqiNetAssistConnect, public RsDht { public: p3BitDht(std::string id, pqiConnectCb *cb, p3NetMgr *nm, @@ -149,6 +165,7 @@ virtual int getRelayProxies(std::list &relayProxies); virtual std::string getUdpAddressString(); + /*********************************************************************************************** ********** External RsDHT Interface (defined in libretroshare/src/retroshare/rsdht.h) ********* ************************************************************************************************/ @@ -251,19 +268,61 @@ void UdpConnectionFailed_locked(DhtPeerDetails *dpd); void ReleaseProxyExclusiveMode_locked(DhtPeerDetails *dpd, bool addrChgLikely); + /*** RELAY HANDLER CODE ***/ +void installRelayHandler(p3BitDhtRelayHandler *); +UdpRelayReceiver *getRelayReceiver(); + +int RelayHandler_InstallRelayConnection(const bdId *srcId, const bdId *destId, uint32_t mode, uint32_t &bandwidth); +int RelayHandler_LogFailedProxyAttempt(const bdId *srcId, const bdId *destId, uint32_t mode, uint32_t errcode); + + + +/*********************************************************************************************** + ******************** Relay Config Stuff (TEMP - MOSTLY, in p3bitdht_relay.cc) ***************** + ********** External RsDHT Interface (defined in libretroshare/src/retroshare/rsdht.h) ********* +************************************************************************************************/ + + // Interface for controlling Relays & DHT Relay Mode +virtual int getRelayServerList(std::list &ids); +virtual int addRelayServer(std::string ids); +virtual int removeRelayServer(std::string ids); + +virtual uint32_t getRelayMode(); +virtual int setRelayMode(uint32_t mode); + +virtual int getRelayAllowance(int classIdx, uint32_t &count, uint32_t &bandwidth); +virtual int setRelayAllowance(int classIdx, uint32_t count, uint32_t bandwidth); + + private: + + // Relay Handling Code / Variables (Mutex Protected). +int setupRelayDefaults(); +int pushRelayServers(); + + std::list mRelayServerList; + uint32_t mRelayMode; + + protected: +/*****************************************************************/ +/*********************** p3config ******************************/ + /* Key Functions to be overloaded for Full Configuration */ + virtual RsSerialiser *setupSerialiser(); + virtual bool saveList(bool &cleanup, std::list&); + virtual void saveDone(); + virtual bool loadList(std::list& load); +/*****************************************************************/ + /*********************************************************************************************** ************************** Internal Accounting (p3bitdht_peers.cc) **************************** ************************************************************************************************/ public: -//bool findPeer(std::string pid) -//bool dropPeer(std::string pid); -//int addFriend(const std::string pid); -//int addFriendOfFriend(const std::string pid); -//int addOther(const std::string pid); int removePeer(const std::string pid); + // Can be used externally too. +int calculateNodeId(const std::string pid, bdNodeId *id); + private: DhtPeerDetails *addInternalPeer_locked(const std::string pid, int type); @@ -276,7 +335,6 @@ int lookupNodeId_locked(const std::string pid, bdNodeId *id); int lookupRsId_locked(const bdNodeId *id, std::string &pid); int storeTranslation_locked(const std::string pid); int removeTranslation_locked(const std::string pid); -int calculateNodeId(const std::string pid, bdNodeId *id); UdpBitDht *mUdpBitDht; /* has own mutex, is static except for creation/destruction */ UdpStunner *mDhtStunner; @@ -289,6 +347,9 @@ int calculateNodeId(const std::string pid, bdNodeId *id); RsMutex dhtMtx; + + p3BitDhtRelayHandler *mRelayHandler; + std::string mOwnRsId; bdNodeId mOwnDhtId; diff --git a/libretroshare/src/dht/p3bitdht_interface.cc b/libretroshare/src/dht/p3bitdht_interface.cc index 07ea48781..ae28ab032 100644 --- a/libretroshare/src/dht/p3bitdht_interface.cc +++ b/libretroshare/src/dht/p3bitdht_interface.cc @@ -198,7 +198,6 @@ std::string p3BitDht::getUdpAddressString() ********** External RsDHT Interface (defined in libretroshare/src/retroshare/rsdht.h) ********* ************************************************************************************************/ - void convertBdPeerToRsDhtPeer(RsDhtPeer &peer, const bdPeer &int_peer) { std::ostringstream out; diff --git a/libretroshare/src/dht/p3bitdht_peernet.cc b/libretroshare/src/dht/p3bitdht_peernet.cc index 1787104a7..642775689 100644 --- a/libretroshare/src/dht/p3bitdht_peernet.cc +++ b/libretroshare/src/dht/p3bitdht_peernet.cc @@ -516,6 +516,13 @@ int p3BitDht::ConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId bdStdPrintId(std::cerr, destId); std::cerr << std::endl; #endif + /* if there is an error code - then it is just to inform us of a failed attempt */ + if (errcode) + { + RelayHandler_LogFailedProxyAttempt(srcId, destId, mode, errcode); + /* END MID FAILED ATTEMPT */ + return 1; + } uint32_t bandwidth = 0; @@ -1622,7 +1629,7 @@ int p3BitDht::checkProxyAllowed(const bdId *srcId, const bdId *destId, int mode, /* will install the Relay Here... so that we reserve the Relay Space for later. * decide on relay bandwidth limitation as well */ - if (installRelayConnection(srcId, destId, bandwidth)) + if (RelayHandler_InstallRelayConnection(srcId, destId, mode, bandwidth)) { #ifdef DEBUG_PEERNET std::cerr << "p3BitDht::checkProxyAllowed() Successfully added Relay, Connection OKAY"; @@ -2385,4 +2392,43 @@ void p3BitDht::ConnectionFeedback(std::string pid, int mode) } +/***** Check for a RelayHandler... and call its functions preferentially */ + +int p3BitDht::RelayHandler_LogFailedProxyAttempt(const bdId *srcId, const bdId *destId, uint32_t mode, uint32_t errcode) +{ + + { + RsStackMutex stack(dhtMtx); /********* LOCKED *********/ + + if ((mRelayHandler) && (mRelayHandler->mLogFailedConnection)) + { + return mRelayHandler->mLogFailedConnection(srcId, destId, mode, errcode); + } + } + + /* NO standard handler */ + return 0; +} + + +int p3BitDht::RelayHandler_InstallRelayConnection(const bdId *srcId, const bdId *destId, + uint32_t mode, uint32_t &bandwidth) +{ + + { + RsStackMutex stack(dhtMtx); /********* LOCKED *********/ + + if ((mRelayHandler) && (mRelayHandler->mInstallRelay)) + { + return mRelayHandler->mInstallRelay(srcId, destId, mode, bandwidth); + } + } + + /* standard handler */ + return installRelayConnection(srcId, destId, bandwidth); +} + + + + diff --git a/libretroshare/src/dht/p3bitdht_relay.cc b/libretroshare/src/dht/p3bitdht_relay.cc new file mode 100644 index 000000000..d4f8fadb6 --- /dev/null +++ b/libretroshare/src/dht/p3bitdht_relay.cc @@ -0,0 +1,415 @@ +/* + * libretroshare/src/dht: p3bitdht.h + * + * BitDht interface for RetroShare. + * + * Copyright 2009-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 2 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 "retroshare@lunamutt.com". + * + */ + +#include "util/rsnet.h" +#include "dht/p3bitdht.h" + +#include "tcponudp/udprelay.h" +#include "bitdht/bdstddht.h" + +#include "serialiser/rsconfigitems.h" + + +/*********************************************************************************************** + ********** External RsDHT Interface for Dht-Relay Control ************************************* +************************************************************************************************/ + +int p3BitDht::setupRelayDefaults() +{ + //uint32_t mode = RSDHT_RELAY_ENABLED | RSDHT_RELAY_MODE_OFF; + uint32_t mode = RSDHT_RELAY_MODE_OFF; + setRelayMode(mode); + + return 1; +} + + +/**** THIS IS A TEMPORARY HACK INTERFACE - UNTIL WE HAVE MORE SOFISTICATED SYSTEM + * NB: using bdNodeIds here, rather than SSL IDS. + *****/ + +int p3BitDht::getRelayServerList(std::list &ids) +{ + RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ + + ids = mRelayServerList; + + return 1; +} + +int p3BitDht::addRelayServer(std::string id) +{ + RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ + + std::list::iterator it; + it = std::find(mRelayServerList.begin(), mRelayServerList.end(), id); + if (it == mRelayServerList.end()) + { + mRelayServerList.push_back(id); + } + + IndicateConfigChanged(); + return 1; +} + +int p3BitDht::removeRelayServer(std::string id) +{ + + RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ + + std::list::iterator it; + it = std::find(mRelayServerList.begin(), mRelayServerList.end(), id); + if (it != mRelayServerList.end()) + { + mRelayServerList.erase(it); + } + + IndicateConfigChanged(); + return 1; +} + +int p3BitDht::pushRelayServers() +{ + std::list servers; + + { + RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ + + servers = mRelayServerList; + } + + std::list::iterator it; + for(it = servers.begin(); it != servers.end(); it++) + { + /* push it to dht */ + uint32_t bdflags = BITDHT_PEER_STATUS_DHT_RELAY_SERVER; + bdId id; + bdStdLoadNodeId(&(id.id), *it); + + mUdpBitDht->updateKnownPeer(&id, 0, bdflags); + + } + return 1; +} + + +uint32_t p3BitDht::getRelayMode() +{ + RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ + + return mRelayMode; +} + +int p3BitDht::setRelayMode(uint32_t mode) +{ + if (mode & RSDHT_RELAY_ENABLED) + { + mUdpBitDht->ConnectionOptions( + BITDHT_CONNECT_MODE_DIRECT | BITDHT_CONNECT_MODE_PROXY | BITDHT_CONNECT_MODE_RELAY, + BITDHT_CONNECT_OPTION_AUTOPROXY); + } + else + { + mUdpBitDht->ConnectionOptions( + BITDHT_CONNECT_MODE_DIRECT | BITDHT_CONNECT_MODE_PROXY, + BITDHT_CONNECT_OPTION_AUTOPROXY); + } + + int relaymode = mode & RSDHT_RELAY_MODE_MASK; + + switch(relaymode) + { + case RSDHT_RELAY_MODE_OFF: + mUdpBitDht->setDhtMode(BITDHT_MODE_RELAYSERVERS_IGNORED); + break; + case RSDHT_RELAY_MODE_ON: + pushRelayServers(); + mUdpBitDht->setDhtMode(BITDHT_MODE_RELAYSERVERS_FLAGGED); + break; + case RSDHT_RELAY_MODE_SERVER: + pushRelayServers(); + mUdpBitDht->setDhtMode(BITDHT_MODE_RELAYSERVERS_SERVER); + break; + } + + { + RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ + mRelayMode = mode; + } + + IndicateConfigChanged(); + + return 1; +} + +int p3BitDht::getRelayAllowance(int classIdx, uint32_t &count, uint32_t &bandwidth) +{ + std::cerr << "p3BitDht::getRelayAllowance(" << classIdx << "): "; + if ((classIdx >= 0) && (classIdx < RSDHT_RELAY_NUM_CLASS)) + { + count = mRelay->getRelayClassMax(classIdx); + bandwidth = mRelay->getRelayClassBandwidth(classIdx); + + std::cerr << " count: " << count << " bandwidth: " << bandwidth; + std::cerr << std::endl; + return 1; + } + std::cerr << " Invalid classIdx"; + std::cerr << std::endl; + + return 0; +} + +int p3BitDht::setRelayAllowance(int classIdx, uint32_t count, uint32_t bandwidth) +{ + std::cerr << "p3BitDht::getRelayAllowance(" << classIdx << ", "; + std::cerr << ", " << count << ", " << bandwidth << ")"; + std::cerr << std::endl; + + int retval = mRelay->setRelayClassMax(classIdx, count, bandwidth); + IndicateConfigChanged(); + + return retval; +} + + +/*********************************************************************************************** + ********** External RsDHT Interface for Dht-Relay Control ************************************* +************************************************************************************************/ + +/*****************************************************************/ +/*********************** p3config ******************************/ + /* Key Functions to be overloaded for Full Configuration */ +RsSerialiser *p3BitDht::setupSerialiser() +{ + RsSerialiser *rss = new RsSerialiser ; + rss->addSerialType(new RsGeneralConfigSerialiser()); + return rss ; +} + + +bool p3BitDht::saveList(bool &cleanup, std::list &saveList) +{ + cleanup = true; + + std::cerr << "p3BitDht::saveList()"; + std::cerr << std::endl; + + + RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ + RsConfigKeyValueSet *config = new RsConfigKeyValueSet(); + + RsTlvKeyValue kv; + + /* Push Relay Class Stuff */ + int i; + for(i = 0; i < RSDHT_RELAY_NUM_CLASS; i++) + { + std::ostringstream keyout; + keyout << "RELAY_CLASS" << i; + + std::string countkey = keyout.str() + "_COUNT"; + std::string bandkey = keyout.str() + "_BANDWIDTH"; + + std::ostringstream countout; + std::ostringstream bandout; + countout << mRelay->getRelayClassMax(i); + bandout << mRelay->getRelayClassBandwidth(i); + + kv.key = countkey; + kv.value = countout.str(); + config->tlvkvs.pairs.push_back(kv); + + kv.key = bandkey; + kv.value = bandout.str(); + config->tlvkvs.pairs.push_back(kv); + } + + /* add RelayMode */ + { + std::ostringstream out; + out << mRelayMode; + + kv.key = "RELAY_MODE"; + kv.value = out.str(); + config->tlvkvs.pairs.push_back(kv); + } + + /* add Servers */ + std::list::iterator it; + for(i = 0, it = mRelayServerList.begin(); it != mRelayServerList.end(); it++, i++) + { + std::ostringstream key; + key << "RELAY_SERVER" << i; + + kv.key = key.str(); + kv.value = *it; + config->tlvkvs.pairs.push_back(kv); + } + + std::cerr << "BITDHT Save Item:"; + std::cerr << std::endl; + + config->print(std::cerr, 0); + + saveList.push_back(config); + + return true; +} + +void p3BitDht::saveDone() +{ + return; +} + +bool p3BitDht::loadList(std::list& load) +{ + std::cerr << "p3BitDht::loadList()"; + std::cerr << std::endl; + + if ((load.size() == 0) || (load.size() > 1)) + { + /* error */ + std::cerr << "p3BitDht::loadList() Error only expecting 1 item"; + std::cerr << std::endl; + return false; + } + RsItem *item = load.front(); + + RsConfigKeyValueSet *config = dynamic_cast(item); + + if (!config) + { + /* error */ + std::cerr << "p3BitDht::loadList() Error expecting item = config"; + std::cerr << std::endl; + return false; + } + + std::cerr << "BITDHT Load Item:"; + std::cerr << std::endl; + + config->print(std::cerr, 0); + + std::list servers; + int peers[RSDHT_RELAY_NUM_CLASS] = {0}; + int bandwidth[RSDHT_RELAY_NUM_CLASS] = {0}; + + bool haveMode = false; + int mode = 0; + + std::list::iterator it; + for(it = config->tlvkvs.pairs.begin(); it != config->tlvkvs.pairs.end(); it++) + { + std::string key = it->key; + std::string value = it->value; + if (0 == strncmp(key.c_str(), "RELAY_SERVER", 12)) + { + /* add to RELAY_SERVER List */ + servers.push_back(value); + std::cerr << "p3BitDht::loadList() Found Server: " << value; + std::cerr << std::endl; + } + else if (0 == strncmp(key.c_str(), "RELAY_MODE", 10)) + { + mode = atoi(value.c_str()); + haveMode = true; + + std::cerr << "p3BitDht::loadList() Found Mode: " << mode; + std::cerr << std::endl; + } + else if (0 == strncmp(key.c_str(), "RELAY_CLASS", 11)) + { + /* len check */ + if (key.length() < 14) + continue; + + int idx = 0; + uint32_t val = atoi(value.c_str()); + switch(key[11]) + { + default: + case '0': + idx = 0; + break; + case '1': + idx = 1; + break; + case '2': + idx = 2; + break; + case '3': + idx = 3; + break; + } + + if (key[13] == 'C') + { + std::cerr << "p3BitDht::loadList() Found Count(" << idx << "): "; + std::cerr << val; + std::cerr << std::endl; + peers[idx] = val; + } + else + { + std::cerr << "p3BitDht::loadList() Found Bandwidth(" << idx << "): "; + std::cerr << val; + std::cerr << std::endl; + bandwidth[idx] = val; + } + } + else + { + std::cerr << "p3BitDht::loadList() Unknown Key:value: " << key; + std::cerr << ":" << value; + std::cerr << std::endl; + } + } + + + // Cleanup config. + delete config; + + { + RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ + mRelayServerList = servers; + } + + int i; + for(i = 0; i < RSDHT_RELAY_NUM_CLASS; i++) + { + mRelay->setRelayClassMax(i, peers[i], bandwidth[i]); + } + + if (haveMode) + { + setRelayMode(mode); + } + + return true; +} + +/*****************************************************************/ + diff --git a/libretroshare/src/libretroshare.pro b/libretroshare/src/libretroshare.pro index 8875bfe9f..1fe429cf0 100644 --- a/libretroshare/src/libretroshare.pro +++ b/libretroshare/src/libretroshare.pro @@ -74,6 +74,7 @@ SOURCES += dht/p3bitdht.cc \ dht/p3bitdht_interface.cc \ dht/p3bitdht_peers.cc \ dht/p3bitdht_peernet.cc \ + dht/p3bitdht_relay.cc \ dht/connectstatebox.cc HEADERS += tcponudp/udppeer.h \ @@ -108,6 +109,7 @@ SOURCES += tcponudp/udppeer.cc \ } + test_bitdht { # DISABLE TCP CONNECTIONS... DEFINES *= P3CONNMGR_NO_TCP_CONNECTIONS @@ -121,7 +123,6 @@ test_bitdht { - use_blogs { HEADERS += services/p3blogs.h @@ -307,6 +308,8 @@ mac { HEADERS += upnp/upnputil.h SOURCES += upnp/upnputil.c + CONFIG += zeroconf + # Beautiful Hack to fix 64bit file access. QMAKE_CXXFLAGS *= -Dfseeko64=fseeko -Dftello64=ftello -Dfopen64=fopen -Dvstatfs64=vstatfs @@ -638,3 +641,14 @@ minimal { services/p3gamelauncher.cc \ services/p3photoservice.cc } + +zeroconf { + +HEADERS += zeroconf/p3zeroconf.h \ + +SOURCES += zeroconf/p3zeroconf.cc \ + + DEFINES *= RS_ENABLE_ZEROCONF + +} + diff --git a/libretroshare/src/pqi/p3cfgmgr.h b/libretroshare/src/pqi/p3cfgmgr.h index ed7769d39..8efe5394c 100644 --- a/libretroshare/src/pqi/p3cfgmgr.h +++ b/libretroshare/src/pqi/p3cfgmgr.h @@ -86,11 +86,16 @@ const uint32_t CONFIG_TYPE_HISTORY = 0x0015; /// turtle router const uint32_t CONFIG_TYPE_TURTLE = 0x0020; +/// dht (relay stuff mainly) +const uint32_t CONFIG_TYPE_BITDHT = 0x0030; + /* standard services */ const uint32_t CONFIG_TYPE_QBLOG = 0x0101; const uint32_t CONFIG_TYPE_FORUMS = 0x0102; const uint32_t CONFIG_TYPE_CHANNELS = 0x0103; + + /* CACHE ID Must be at the END so that other configurations * are loaded First (Cache Config --> Cache Loading) */ diff --git a/libretroshare/src/pqi/p3peermgr.cc b/libretroshare/src/pqi/p3peermgr.cc index 62824fe04..f869726bd 100644 --- a/libretroshare/src/pqi/p3peermgr.cc +++ b/libretroshare/src/pqi/p3peermgr.cc @@ -255,6 +255,22 @@ bool p3PeerMgrIMPL::getPeerName(const std::string &ssl_id, std::string &name) return true; } +bool p3PeerMgrIMPL::getGpgId(const std::string &ssl_id, std::string &gpgId) +{ + RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ + + /* check for existing */ + std::map::iterator it; + it = mFriendList.find(ssl_id); + if (it == mFriendList.end()) + { + return false; + } + + gpgId = it->second.gpg_id; + return true; +} + bool p3PeerMgrIMPL::getFriendNetStatus(const std::string &id, peerState &state) diff --git a/libretroshare/src/pqi/p3peermgr.h b/libretroshare/src/pqi/p3peermgr.h index 82ac5eaf8..5582e699d 100644 --- a/libretroshare/src/pqi/p3peermgr.h +++ b/libretroshare/src/pqi/p3peermgr.h @@ -182,6 +182,7 @@ virtual bool getFriendNetStatus(const std::string &id, peerState &state) = 0; virtual bool getOthersNetStatus(const std::string &id, peerState &state) = 0; virtual bool getPeerName(const std::string &ssl_id, std::string &name) = 0; +virtual bool getGpgId(const std::string &sslId, std::string &gpgId) = 0; /************* DEPRECIATED FUNCTIONS (TO REMOVE) ********/ @@ -266,6 +267,7 @@ virtual bool getFriendNetStatus(const std::string &id, peerState &state); virtual bool getOthersNetStatus(const std::string &id, peerState &state); virtual bool getPeerName(const std::string &ssl_id, std::string &name); +virtual bool getGpgId(const std::string &sslId, std::string &gpgId); /************* DEPRECIATED FUNCTIONS (TO REMOVE) ********/ diff --git a/libretroshare/src/pqi/pqiassist.h b/libretroshare/src/pqi/pqiassist.h index d90abc500..aaa9d6770 100644 --- a/libretroshare/src/pqi/pqiassist.h +++ b/libretroshare/src/pqi/pqiassist.h @@ -146,26 +146,17 @@ virtual bool dropPeer(std::string id) = 0; virtual int addBadPeer(const struct sockaddr_in &addr, uint32_t reason, uint32_t flags, uint32_t age) = 0; virtual int addKnownPeer(const std::string &pid, const struct sockaddr_in &addr, uint32_t flags) = 0; -//virtual int addFriend(const std::string pid) = 0; -//virtual int addFriendOfFriend(const std::string pid) = 0; -//virtual int addOther(const std::string pid) = 0; - - virtual void ConnectionFeedback(std::string pid, int mode) = 0; /* extract current peer status */ virtual bool getPeerStatus(std::string id, struct sockaddr_in &laddr, struct sockaddr_in &raddr, - uint32_t &type, uint32_t &mode) = 0; + uint32_t &type, uint32_t &mode) = 0; // DEPRECIATE. -virtual bool setAttachMode(bool on) = 0; - - -//virtual bool getExternalInterface(struct sockaddr_in &raddr, -// uint32_t &mode) = 0; +virtual bool setAttachMode(bool on) = 0; // FIXUP. /***** Stats for Network / DHT *****/ -virtual bool getNetworkStats(uint32_t &netsize, uint32_t &localnetsize) = 0; +virtual bool getNetworkStats(uint32_t &netsize, uint32_t &localnetsize) = 0; // DEPRECIATE. protected: std::string mPeerId; diff --git a/libretroshare/src/retroshare/rsdht.h b/libretroshare/src/retroshare/rsdht.h index 16c29b5a3..b8ae12794 100644 --- a/libretroshare/src/retroshare/rsdht.h +++ b/libretroshare/src/retroshare/rsdht.h @@ -71,6 +71,22 @@ extern RsDht *rsDht; #define RSDHT_TOU_MODE_RELAY 3 +#define RSDHT_RELAY_NUM_CLASS 4 + +#define RSDHT_RELAY_CLASS_ALL 0 +#define RSDHT_RELAY_CLASS_GENERAL 1 +#define RSDHT_RELAY_CLASS_FOF 2 +#define RSDHT_RELAY_CLASS_FRIENDS 3 + + +#define RSDHT_RELAY_MODE_MASK 0x00f0 + +#define RSDHT_RELAY_ENABLED 0x0001 + +#define RSDHT_RELAY_MODE_OFF 0x0010 +#define RSDHT_RELAY_MODE_ON 0x0020 +#define RSDHT_RELAY_MODE_SERVER 0x0040 + class RsDhtPeer { @@ -96,26 +112,18 @@ class RsDhtNetPeer std::string mRsId; uint32_t mPeerType; - uint32_t mDhtState; - //connectLogic. - std::string mConnectState; - - // connect Status - uint32_t mPeerConnectState; - // connect mode - uint32_t mPeerConnectMode; + std::string mConnectState; // connectLogic. + uint32_t mPeerConnectState; // connect Status + uint32_t mPeerConnectMode; // connect mode bool mExclusiveProxyLock; std::string mPeerConnectProxyId; - // Req Status. - uint32_t mPeerReqState; - - // Peer Cb Mgs. - std::string mCbPeerMsg; + uint32_t mPeerReqState; // Req Status. + std::string mCbPeerMsg; // Peer Cb Mgs. }; @@ -168,6 +176,19 @@ virtual int getRelayProxies(std::list &relayProxies) = 0; virtual std::string getUdpAddressString() = 0; + + // Interface for controlling Relays & DHT Relay Mode +virtual int getRelayServerList(std::list &ids) = 0; +virtual int addRelayServer(std::string ids) = 0; +virtual int removeRelayServer(std::string ids) = 0; + +virtual uint32_t getRelayMode() = 0; +virtual int setRelayMode(uint32_t mode) = 0; + +virtual int getRelayAllowance(int classIdx, uint32_t &count, uint32_t &bandwidth) = 0; +virtual int setRelayAllowance(int classIdx, uint32_t count, uint32_t bandwidth) = 0; + + #if 0 virtual std::string getPeerStatusString(); virtual std::string getDhtStatusString(); diff --git a/libretroshare/src/rsserver/rsinit.cc b/libretroshare/src/rsserver/rsinit.cc index faa98edda..8f84a8d76 100644 --- a/libretroshare/src/rsserver/rsinit.cc +++ b/libretroshare/src/rsserver/rsinit.cc @@ -1714,9 +1714,13 @@ RsTurtle *rsTurtle = NULL ; #include "util/rsdebug.h" #include "util/rsdir.h" #include "util/rsrandom.h" - -#include "upnp/upnphandler.h" -//#include "dht/opendhtmgr.h" + +#ifdef RS_ENABLE_ZEROCONF + #include "zeroconf/p3zeroconf.h" + //#include "zeroconf/p3zcnatassist.h" +#else + #include "upnp/upnphandler.h" +#endif #include "services/p3disc.h" #include "services/p3msgservice.h" @@ -1879,7 +1883,6 @@ int RsServer::StartupRetroShare() // for (std::list::iterator sslIdsIt = sslIds.begin(); sslIdsIt != sslIds.end(); sslIdsIt++) { // mConnMgr->addFriend(*sslIdsIt); // } - pqiNetAssistFirewall *mUpnpMgr = new upnphandler(); //p3DhtMgr *mDhtMgr = new OpenDHTMgr(ownId, mConnMgr, RsInitConfig::configDir); /**************************** BITDHT ***********************************/ @@ -2168,7 +2171,23 @@ int RsServer::StartupRetroShare() mNetMgr->addNetListener(mProxyStack); #endif + +#ifdef RS_ENABLE_ZEROCONF + p3ZeroConf *mZeroConf = new p3ZeroConf( + AuthGPG::getAuthGPG()->getGPGOwnId(), ownId, + mLinkMgr, mNetMgr, mPeerMgr); + mNetMgr->addNetAssistConnect(2, mZeroConf); + mNetMgr->addNetListener(mZeroConf); + + // Apple's UPnP & NAT-PMP assistance. + //p3zcNatAssist *mZcNatAssist = new p3zcNatAssist(); + //mNetMgr->addNetAssistFirewall(2, mZcNatAssist); +#else + + // Original UPnP Interface. + pqiNetAssistFirewall *mUpnpMgr = new upnphandler(); mNetMgr->addNetAssistFirewall(1, mUpnpMgr); +#endif /**************************************************************************/ /* need to Monitor too! */ @@ -2211,6 +2230,10 @@ int RsServer::StartupRetroShare() mConfigMgr->addConfiguration("turtle.cfg", tr); mConfigMgr->addConfiguration("p3disc.cfg", ad); +#ifdef RS_USE_BITDHT + mConfigMgr->addConfiguration("bitdht.cfg", mBitDht); +#endif + mPluginsManager->addConfigurations(mConfigMgr) ; ftserver->addConfiguration(mConfigMgr); diff --git a/libretroshare/src/tcponudp/udprelay.cc b/libretroshare/src/tcponudp/udprelay.cc index 6723ac525..553157c16 100644 --- a/libretroshare/src/tcponudp/udprelay.cc +++ b/libretroshare/src/tcponudp/udprelay.cc @@ -49,14 +49,17 @@ UdpRelayReceiver::UdpRelayReceiver(UdpPublisher *pub) { mClassLimit.resize(UDP_RELAY_NUM_CLASS); mClassCount.resize(UDP_RELAY_NUM_CLASS); + mClassBandwidth.resize(UDP_RELAY_NUM_CLASS); - setRelayTotal(UDP_RELAY_DEFAULT_COUNT_ALL); for(int i = 0; i < UDP_RELAY_NUM_CLASS; i++) { mClassCount[i] = 0; + mClassBandwidth[i] = 0; } + setRelayTotal(UDP_RELAY_DEFAULT_COUNT_ALL); + /* only allocate this space once */ mTmpSendPkt = malloc(MAX_RELAY_UDP_PACKET_SIZE); mTmpSendSize = MAX_RELAY_UDP_PACKET_SIZE; @@ -279,7 +282,7 @@ int UdpRelayReceiver::removeUdpRelay(UdpRelayAddrSet *addrSet) } -int UdpRelayReceiver::addUdpRelay(UdpRelayAddrSet *addrSet, int relayClass, uint32_t &bandwidth) +int UdpRelayReceiver::addUdpRelay(UdpRelayAddrSet *addrSet, int &relayClass, uint32_t &bandwidth) { RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ @@ -288,22 +291,22 @@ int UdpRelayReceiver::addUdpRelay(UdpRelayAddrSet *addrSet, int relayClass, uint int ok = (rit == mRelays.end()); if (!ok) { -//#ifdef DEBUG_UDP_RELAY +#ifdef DEBUG_UDP_RELAY std::cerr << "UdpRelayReceiver::addUdpRelay() ERROR Peer already exists!" << std::endl; -//#endif +#endif return 0; } /* will install if there is space! */ - if (installRelayClass_relayLocked(relayClass)) + if (installRelayClass_relayLocked(relayClass, bandwidth)) { -//#ifdef DEBUG_UDP_RELAY +#ifdef DEBUG_UDP_RELAY std::cerr << "UdpRelayReceiver::addUdpRelay() adding Relay" << std::endl; -//#endif +#endif /* create UdpRelay */ - UdpRelayProxy udpRelay(addrSet, relayClass); + UdpRelayProxy udpRelay(addrSet, relayClass, bandwidth); UdpRelayAddrSet alt = addrSet->flippedSet(); - UdpRelayProxy altUdpRelay(&alt, relayClass); + UdpRelayProxy altUdpRelay(&alt, relayClass, bandwidth); /* must install two (A, B) & (B, A) */ mRelays[*addrSet] = udpRelay; @@ -315,9 +318,9 @@ int UdpRelayReceiver::addUdpRelay(UdpRelayAddrSet *addrSet, int relayClass, uint return 1; } -//#ifdef DEBUG_UDP_RELAY +#ifdef DEBUG_UDP_RELAY std::cerr << "UdpRelayReceiver::addUdpRelay() WARNING Too many Relays!" << std::endl; -//#endif +#endif return 0; } @@ -359,8 +362,11 @@ int UdpRelayReceiver::removeUdpRelay_relayLocked(UdpRelayAddrSet *addrSet) return 1; } - /* Need some stats, to work out how many relays we are supporting */ -int UdpRelayReceiver::installRelayClass_relayLocked(int classIdx) + /* Need some stats, to work out how many relays we are supporting + * modified the code to allow degrading of class .... + * so if you have too many friends, they will fill a FOF spot + */ +int UdpRelayReceiver::installRelayClass_relayLocked(int &classIdx, uint32_t &bandwidth) { /* check for total number of Relays */ if (mClassCount[UDP_RELAY_CLASS_ALL] >= mClassLimit[UDP_RELAY_CLASS_ALL]) @@ -379,12 +385,25 @@ int UdpRelayReceiver::installRelayClass_relayLocked(int classIdx) } /* now check the specifics of the class */ - if (mClassCount[classIdx] >= mClassLimit[classIdx]) + while(mClassCount[classIdx] >= mClassLimit[classIdx]) { std::cerr << "UdpRelayReceiver::installRelayClass() WARNING Relay Class Limit Exceeded"; std::cerr << std::endl; + std::cerr << "UdpRelayReceiver::installRelayClass() ClassIdx: " << classIdx; + std::cerr << std::endl; + std::cerr << "UdpRelayReceiver::installRelayClass() ClassLimit: " << mClassLimit[classIdx]; + std::cerr << std::endl; + std::cerr << "UdpRelayReceiver::installRelayClass() Degrading Class =>: " << classIdx; + std::cerr << std::endl; - return 0; + classIdx--; + if (classIdx == 0) + { + std::cerr << "UdpRelayReceiver::installRelayClass() No Spaces Left"; + std::cerr << std::endl; + + return 0; + } } std::cerr << "UdpRelayReceiver::installRelayClass() Relay Class Ok, Count incremented"; @@ -393,6 +412,7 @@ int UdpRelayReceiver::installRelayClass_relayLocked(int classIdx) /* if we get here we can add one */ mClassCount[UDP_RELAY_CLASS_ALL]++; mClassCount[classIdx]++; + bandwidth = mClassBandwidth[classIdx]; return 1; } @@ -448,7 +468,7 @@ int UdpRelayReceiver::setRelayTotal(int count) } -int UdpRelayReceiver::setRelayClassMax(int classIdx, int count) +int UdpRelayReceiver::setRelayClassMax(int classIdx, int count, int bandwidth) { RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ @@ -461,6 +481,7 @@ int UdpRelayReceiver::setRelayClassMax(int classIdx, int count) } mClassLimit[classIdx] = count; + mClassBandwidth[classIdx] = bandwidth; return 1; } @@ -480,6 +501,21 @@ int UdpRelayReceiver::getRelayClassMax(int classIdx) return mClassLimit[classIdx]; } +int UdpRelayReceiver::getRelayClassBandwidth(int classIdx) +{ + RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ + + /* check the idx */ + if ((classIdx < 0) || (classIdx >= UDP_RELAY_NUM_CLASS)) + { + std::cerr << "UdpRelayReceiver::getRelayMaximum() ERROR class Idx invalid"; + std::cerr << std::endl; + return 0; + } + + return mClassBandwidth[classIdx]; +} + int UdpRelayReceiver::getRelayCount(int classIdx) { RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ @@ -840,7 +876,7 @@ UdpRelayProxy::UdpRelayProxy() mBandwidthLimit = 0; } -UdpRelayProxy::UdpRelayProxy(UdpRelayAddrSet *addrSet, int relayClass) +UdpRelayProxy::UdpRelayProxy(UdpRelayAddrSet *addrSet, int relayClass, uint32_t bandwidth) { mAddrs = *addrSet; mRelayClass = relayClass; @@ -852,18 +888,23 @@ UdpRelayProxy::UdpRelayProxy(UdpRelayAddrSet *addrSet, int relayClass) mStartTS = time(NULL); - switch(relayClass) + mBandwidthLimit = bandwidth; + /* fallback */ + if (mBandwidthLimit == 0) { - default: - case UDP_RELAY_CLASS_GENERAL: - mBandwidthLimit = RELAY_MAX_BANDWIDTH; - break; - case UDP_RELAY_CLASS_FOF: - mBandwidthLimit = RELAY_MAX_BANDWIDTH; - break; - case UDP_RELAY_CLASS_FRIENDS: - mBandwidthLimit = RELAY_MAX_BANDWIDTH; - break; + switch(relayClass) + { + default: + case UDP_RELAY_CLASS_GENERAL: + mBandwidthLimit = RELAY_MAX_BANDWIDTH; + break; + case UDP_RELAY_CLASS_FOF: + mBandwidthLimit = RELAY_MAX_BANDWIDTH; + break; + case UDP_RELAY_CLASS_FRIENDS: + mBandwidthLimit = RELAY_MAX_BANDWIDTH; + break; + } } } diff --git a/libretroshare/src/tcponudp/udprelay.h b/libretroshare/src/tcponudp/udprelay.h index 320f7626e..2387e7d81 100644 --- a/libretroshare/src/tcponudp/udprelay.h +++ b/libretroshare/src/tcponudp/udprelay.h @@ -27,6 +27,7 @@ */ #include "tcponudp/udppeer.h" +#include #include class UdpRelayAddrSet; @@ -49,7 +50,7 @@ class UdpRelayProxy { public: UdpRelayProxy(); - UdpRelayProxy(UdpRelayAddrSet *addrSet, int relayClass); + UdpRelayProxy(UdpRelayAddrSet *addrSet, int relayClass, uint32_t bandwidth); UdpRelayAddrSet mAddrs; double mBandwidth; @@ -94,18 +95,19 @@ std::ostream &operator<<(std::ostream &out, const UdpRelayEnd &ure); #define UDP_RELAY_DEFAULT_COUNT_ALL 10 #define UDP_RELAY_FRAC_GENERAL (0.2) #define UDP_RELAY_FRAC_FOF (0.5) -#define UDP_RELAY_FRAC_FRIENDS (0.8) +#define UDP_RELAY_FRAC_FRIENDS (0.3) -#define UDP_RELAY_NUM_CLASS 4 +/**** DEFINED IN EXTERNAL HEADER FILE ***/ +#define UDP_RELAY_NUM_CLASS RSDHT_RELAY_NUM_CLASS -#define UDP_RELAY_CLASS_ALL 0 -#define UDP_RELAY_CLASS_GENERAL 1 -#define UDP_RELAY_CLASS_FOF 2 -#define UDP_RELAY_CLASS_FRIENDS 3 +#define UDP_RELAY_CLASS_ALL RSDHT_RELAY_CLASS_ALL +#define UDP_RELAY_CLASS_GENERAL RSDHT_RELAY_CLASS_GENERAL +#define UDP_RELAY_CLASS_FOF RSDHT_RELAY_CLASS_FOF +#define UDP_RELAY_CLASS_FRIENDS RSDHT_RELAY_CLASS_FRIENDS // Just for some testing fun! //#define UDP_RELAY_LIFETIME_GENERAL 180 // 3 minutes -//#define UDP_RELAY_LIFETIME_FOF 360 // 6 minutes. +//#define UDP_RELAY_LIFETIME_FOF 360 // 6 minutes. //#define UDP_RELAY_LIFETIME_FRIENDS 720 // 12 minutes. #define UDP_RELAY_LIFETIME_GENERAL 1800 // 30 minutes @@ -131,15 +133,16 @@ int removeUdpPeer(UdpPeer *peer); * the end-points drop the connections */ - int addUdpRelay(UdpRelayAddrSet *addrSet, int relayClass, uint32_t &bandwidth); + int addUdpRelay(UdpRelayAddrSet *addrSet, int &relayClass, uint32_t &bandwidth); int removeUdpRelay(UdpRelayAddrSet *addrs); /* Need some stats, to work out how many relays we are supporting */ int checkRelays(); int setRelayTotal(int count); /* sets all the Relay Counts (frac based on total) */ - int setRelayClassMax(int classIdx, int count); /* set a specific class maximum */ + int setRelayClassMax(int classIdx, int count, int bandwidth); /* set a specific class maximum */ int getRelayClassMax(int classIdx); + int getRelayClassBandwidth(int classIdx); int getRelayCount(int classIdx); /* how many relays (of this type) do we have */ int RelayStatus(std::ostream &out); @@ -158,7 +161,7 @@ int status(std::ostream &out); private: int removeUdpRelay_relayLocked(UdpRelayAddrSet *addrs); - int installRelayClass_relayLocked(int classIdx); + int installRelayClass_relayLocked(int &classIdx, uint32_t &bandwidth); int removeRelayClass_relayLocked(int classIdx); /* Unfortunately, Due the reentrant nature of this classes activities... @@ -176,7 +179,7 @@ int status(std::ostream &out); RsMutex relayMtx; /* for all class data (below) */ - std::vector mClassLimit, mClassCount; + std::vector mClassLimit, mClassCount, mClassBandwidth; std::map mStreams; /* indexed by */ std::map mRelays; /* indexed by */ diff --git a/libretroshare/src/zeroconf/NOTES.txt b/libretroshare/src/zeroconf/NOTES.txt new file mode 100644 index 000000000..e8803ff60 --- /dev/null +++ b/libretroshare/src/zeroconf/NOTES.txt @@ -0,0 +1,33 @@ + +The Code in this directory refers to APPLEs ZeroConf Library. + +We have two classes: p3ZeroConf & p3ZeroConfNat +The first provides ZeroConf(Bonjour) discovery services. +The second provides UPnP & NAT-PMP Nat Port Forwarding. + +OSX +---------------- +Both should compile with no problems under OSX. +Both will be compiled by default. + +p3ZeroConf is enabled by default. +p3ZeroConfNAT will become the default PortForwarding Service (once tested). + +Windows +---------------- +Under Windows, you require Apple's header files & library to compile. +If you are missing the libraries, you can disable their compilation in libretroshare. + +Furthermore - it'll only work if the Apple DNS Service is running on the Windows PC. +p3ZeroConf will be enabled by default (if included in the compilation). +p3ZeroConfNAT will not be enabled by default. + +Linux +---------------- +Neither of these classes will compile or be enabled under Linux. +There is another library: Avahi - which provides ZeroConf services. +It is likely to have a totally different interface - +so it will have to be coded up separately. + + + diff --git a/libretroshare/src/zeroconf/p3zeroconf.cc b/libretroshare/src/zeroconf/p3zeroconf.cc new file mode 100644 index 000000000..16fd84ac0 --- /dev/null +++ b/libretroshare/src/zeroconf/p3zeroconf.cc @@ -0,0 +1,1436 @@ +/* + * libretroshare/src/zeroconf: p3zeroconf.cc + * + * ZeroConf interface for RetroShare. + * + * Copyright 2011-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 2 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 "retroshare@lunamutt.com". + * + */ + + +#include "zeroconf/p3zeroconf.h" +#include +#include +#include + +#include "pqi/authgpg.h" + +/* TODO + * + * - Get Local Port when it changes.... (need second interface?) + * - Get GpgId, SslId for all peers. + * - Able to install new sslIds for friends. + * - Hold data for all peers. + * - parse TxtRecord. + * + */ + +#define DEBUG_ZEROCONF 1 + + +#define ZC_SERVICE_STOPPED 0 +#define ZC_SERVICE_ACTIVE 1 + +#define ZC_MAX_QUERY_TIME 30 +#define ZC_MAX_RESOLVE_TIME 30 + +p3ZeroConf::p3ZeroConf(std::string gpgid, std::string sslid, pqiConnectCb *cb, p3NetMgr *nm, p3PeerMgr *pm) + :pqiNetAssistConnect(sslid, cb), mNetMgr(nm), mPeerMgr(pm), mZcMtx("p3ZeroConf") +{ + mRegistered = false; + mTextOkay = false; + mPortOkay = false; + + mOwnGpgId = gpgid; + mOwnSslId = sslid; + +#ifdef DEBUG_ZEROCONF + std::cerr << "p3ZeroConf::p3ZeroConf()" << std::endl; + std::cerr << "Using Id: " << sslid; + std::cerr << std::endl; +#endif + + mRegisterStatus = ZC_SERVICE_STOPPED; + mRegisterStatusTS = time(NULL); + mBrowseStatus = ZC_SERVICE_STOPPED; + mBrowseStatusTS = time(NULL); + mResolveStatus = ZC_SERVICE_STOPPED; + mResolveStatusTS = time(NULL); + mQueryStatus = ZC_SERVICE_STOPPED; + mQueryStatusTS = time(NULL); + + createTxtRecord(); +} + +p3ZeroConf::~p3ZeroConf() +{ + +} + + +void p3ZeroConf::start() +{ +#ifdef DEBUG_ZEROCONF + std::cerr << "p3ZeroConf::start()"; + std::cerr << std::endl; +#endif + +} + + /* pqiNetAssist - external interface functions */ +void p3ZeroConf::enable(bool on) +{ +#ifdef DEBUG_ZEROCONF + std::cerr << "p3ZeroConf::enable(" << on << ")"; + std::cerr << std::endl; +#endif + +} + +void p3ZeroConf::shutdown() /* blocking call */ +{ +} + + +void p3ZeroConf::restart() +{ +} + +bool p3ZeroConf::getEnabled() +{ + return true; +} + +bool p3ZeroConf::getActive() +{ + return true; +} + +bool p3ZeroConf::getNetworkStats(uint32_t &netsize, uint32_t &localnetsize) +{ + //netsize = mUdpBitDht->statsNetworkSize(); + //localnetsize = mUdpBitDht->statsBDVersionSize(); + return true; +} + +void p3ZeroConf::createTxtRecord() +{ + RsStackMutex stack(mZcMtx); /****** STACK LOCK MUTEX *******/ + std::ostringstream gpgidout; + std::ostringstream sslidout; + + gpgidout << "gpgid=" << mOwnGpgId; + sslidout << "sslid=" << mOwnSslId; + + std::string gpgid = gpgidout.str(); + std::string sslid = sslidout.str(); + + mTextRecord += (char) gpgid.length(); + mTextRecord += gpgid; + mTextRecord += (char) sslid.length(); + mTextRecord += sslid; + + std::cerr << "p3ZeroConf::createTxtRecord() Record: " << std::endl; + std::cerr << "------------------------------------" << std::endl; + std::cerr << mTextRecord; + std::cerr << std::endl; + std::cerr << "------------------------------------" << std::endl; + + mTextOkay = true; +} + +int procPeerTxtRecord(int txtLen, const unsigned char *txtRecord, std::string &peerGpgId, std::string &peerSslId) +{ + int txtRemaining = txtLen; + int idx = 0; + bool setGpg = false; + bool setSsl = false; + + std::cerr << "procPeerTxtRecord() processing"; + std::cerr << std::endl; + + while(txtRemaining > 0) + { + uint8_t len = txtRecord[idx]; + idx++; + txtRemaining -= 1; + + std::string record((const char *) txtRecord, idx, len); + + std::cerr << "procPeerTxtRecord() record: " << record; + std::cerr << std::endl; + + if (0 == strncmp(record.c_str(), "gpgid=", 6)) + { + peerGpgId = record.substr(6, -1); + setGpg = true; + + std::cerr << "procPeerTxtRecord() found peerGpgId: " << peerGpgId; + std::cerr << std::endl; + } + else if (0 == strncmp(record.c_str(), "sslid=", 6)) + { + peerSslId = record.substr(6, -1); + setSsl = true; + + std::cerr << "procPeerTxtRecord() found peerSslId: " << peerSslId; + std::cerr << std::endl; + } + else + { + std::cerr << "Unknown Record"; + } + idx += len; + txtRemaining -= len; + } + return (setGpg && setSsl); +} + + + /*** OVERLOADED from pqiNetListener ***/ +bool p3ZeroConf::resetListener(struct sockaddr_in &local) +{ + RsStackMutex stack(mZcMtx); /****** STACK LOCK MUTEX *******/ + + mLocalPort = ntohs(local.sin_port); + mPortOkay = true; + + if (mRegisterStatus == ZC_SERVICE_ACTIVE) + { + locked_stopRegister(); + } + return true; +} + + +/***************************************************************************** + ********* pqiNetAssistConnect - external interface functions *************** + *****************************************************************************/ + +/**** DUMMY FOR THE MOMENT *****/ + +bool p3ZeroConf::findPeer(std::string pid) +{ +#ifdef DEBUG_ZEROCONF + std::cerr << "p3ZeroConf::findPeer(" << pid << ")"; + std::cerr << std::endl; +#endif + + return true; +} + +bool p3ZeroConf::dropPeer(std::string pid) +{ +#ifdef DEBUG_ZEROCONF + std::cerr << "p3ZeroConf::dropPeer(" << pid << ")"; + std::cerr << std::endl; +#endif + + return true; +} + + + /* extract current peer status */ +bool p3ZeroConf::getPeerStatus(std::string id, + struct sockaddr_in &/*laddr*/, struct sockaddr_in &/*raddr*/, + uint32_t &/*type*/, uint32_t &/*mode*/) +{ + /* remove unused parameter warnings */ + (void) id; + +#ifdef DEBUG_ZEROCONF + std::cerr << "p3ZeroConf::getPeerStatus(" << id << ")"; + std::cerr << std::endl; +#endif + + return false; +} + +#if 0 +bool p3ZeroConf::getExternalInterface(struct sockaddr_in &/*raddr*/, + uint32_t &/*mode*/) +{ + +#ifdef DEBUG_ZEROCONF + std::cerr << "p3ZeroConf::getExternalInterface()"; + std::cerr << std::endl; +#endif + + + return false; +} + +#endif + +bool p3ZeroConf::setAttachMode(bool on) +{ + +#ifdef DEBUG_ZEROCONF + std::cerr << "p3ZeroConf::setAttachMode(" << on << ")"; + std::cerr << std::endl; +#endif + + return true; +} + +int p3ZeroConf::addBadPeer(const struct sockaddr_in &addr, uint32_t reason, uint32_t flags, uint32_t age) +{ + return 1; +} + +int p3ZeroConf::addKnownPeer(const std::string &pid, const struct sockaddr_in &addr, uint32_t flags) +{ + return 1; +} + +void p3ZeroConf::ConnectionFeedback(std::string pid, int state) +{ + return; +} + + + +/***********************************************************************************/ +/* + * + * + * ZeroConf Interface for Retroshare. + * This will use the pqiNetAssistConnect Interface (like the DHT). + * + * we will advertise ourselves using GPGID & SSLID on the zeroconf interface. + * + * Will search local network for any peers. + * If they are our friends... callback to p3NetMgr to initiate connection. + * + * + * This should be very easy to implement under OSX.... so we start with that. + * For Windows, we will use Apple's libraries... so that should be similar too. + * Linux - won't bother with zeroconf for the moment - If someone feels like implementing that.. ok. + * + * Most important is that Windows and OSX can interact. + * + * We keep a simple system here.... + * 1) Register. + * 2) Enable Browsing. + * 3) Resolve Browse results one at a time. + * 4) Callback Resolve results. + * + * + */ + + +int p3ZeroConf::tick() +{ + { + RsStackMutex stack(mZcMtx); /****** STACK LOCK MUTEX *******/ + + locked_startRegister(); + locked_startBrowse(); + } + + + checkServiceFDs(); // will cause callbacks - if data is ready. + + checkResolveAction(); + checkLocationResults(); + checkQueryAction(); + checkQueryResults(); + + return 0; +} + +void p3ZeroConf::checkServiceFDs() +{ + RsStackMutex stack(mZcMtx); /****** STACK LOCK MUTEX *******/ + + //std::cerr << "p3ZeroConf::checkServiceFDs()"; + //std::cerr << std::endl; + + if (mRegisterStatus == ZC_SERVICE_ACTIVE) + { + locked_checkFD(mRegisterRef); + } + + if (mBrowseStatus == ZC_SERVICE_ACTIVE) + { + locked_checkFD(mBrowseRef); + } + + if (mResolveStatus == ZC_SERVICE_ACTIVE) + { + locked_checkFD(mResolveRef); + + time_t age = time(NULL) - mResolveStatusTS; + if (age > ZC_MAX_RESOLVE_TIME) + { + std::cerr << "p3ZeroConf::checkServiceFDs() Killing very old Resolve request"; + std::cerr << std::endl; + locked_stopResolve(); + + } + } + + + if (mQueryStatus == ZC_SERVICE_ACTIVE) + { + locked_checkFD(mQueryRef); + + time_t age = time(NULL) - mQueryStatusTS; + if (age > ZC_MAX_QUERY_TIME) + { + std::cerr << "p3ZeroConf::checkServiceFDs() Killing very old Query request"; + std::cerr << std::endl; + locked_stopQueryIp(); + } + } +} + + +void p3ZeroConf::locked_checkFD(DNSServiceRef ref) +{ + //std::cerr << "p3ZeroConf::locked_checkFD() Start"; + //std::cerr << std::endl; + + int sockfd = DNSServiceRefSockFD(ref); + + fd_set ReadFDs, WriteFDs, ExceptFDs; + FD_ZERO(&ReadFDs); + FD_ZERO(&WriteFDs); + FD_ZERO(&ExceptFDs); + + FD_SET(sockfd, &ReadFDs); + + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + + if (select(sockfd + 1, &ReadFDs, &WriteFDs, &ExceptFDs, &timeout) < 0) + { + std::cerr << "p3zeroconf::checkFD() Select ERROR"; + std::cerr << std::endl; + return; + } + + if (FD_ISSET(sockfd, &ReadFDs)) + { + DNSServiceErrorType err = DNSServiceProcessResult(ref); + switch(err) + { + case 0: + /* ok */ + break; + default: + std::cerr << "DNSServiceProcessResult() ERROR: "; + std::cerr << displayDNSServiceError(err); + std::cerr << std::endl; + break; + } + } + + //std::cerr << "p3ZeroConf::locked_checkFD() End"; + //std::cerr << std::endl; + return; + +} + + + +int p3ZeroConf::checkResolveAction() +{ + RsStackMutex stack(mZcMtx); /****** STACK LOCK MUTEX *******/ + + if (mResolveStatus == ZC_SERVICE_ACTIVE) + { + /* Do nothing - if we are already resolving */ + + return 0; + } + + /* iterate through the Browse Results... look for unresolved one - and do it! */ + + /* check the new results Queue first */ + if (mBrowseResults.size() > 0) + { + std::cerr << "p3ZeroConf::checkResolveAction() Getting Item from BrowseResults"; + std::cerr << std::endl; + + zcBrowseResult br = mBrowseResults.front(); + mBrowseResults.pop_front(); + + locked_startResolve(br.interfaceIndex, br.serviceName, br.regtype, br.replyDomain); + } + return 1; +} + + +int p3ZeroConf::checkLocationResults() +{ + zcLocationResult lr; + + { + RsStackMutex stack(mZcMtx); /****** STACK LOCK MUTEX *******/ + + /* check the results Queue */ + if (mLocationResults.size() == 0) + { + return 0; + } + + std::cerr << "p3ZeroConf::checkLocationResults() Getting Item from LocationResults"; + std::cerr << std::endl; + + lr = mLocationResults.front(); + mLocationResults.pop_front(); + + } + + /* now callback to mPeerMgr to add new location... This will eventually get back here + * via some magic! + */ + + std::cerr << "p3ZeroConf::checkLocationResults() adding new location."; + std::cerr << std::endl; + std::cerr << "gpgid = " << lr.gpgId; + std::cerr << std::endl; + std::cerr << "sslid = " << lr.sslId; + std::cerr << std::endl; + + time_t now = time(NULL); + mPeerMgr->addFriend(lr.sslId, lr.gpgId, RS_NET_MODE_UDP, RS_VIS_STATE_STD, now); + return 1; +} + + +int p3ZeroConf::checkQueryAction() +{ + RsStackMutex stack(mZcMtx); /****** STACK LOCK MUTEX *******/ + + if (mQueryStatus == ZC_SERVICE_ACTIVE) + { + /* Do nothing - if we are already resolving */ + + return 0; + } + + /* check the new results Queue first */ + if (mResolveResults.size() > 0) + { + std::cerr << "p3ZeroConf::checkQueryAction() Getting Item from ResolveResults"; + std::cerr << std::endl; + + zcResolveResult rr = mResolveResults.front(); + mResolveResults.pop_front(); + + locked_startQueryIp(rr.interfaceIndex, rr.hosttarget, rr.gpgId, rr.sslId); + } + return 1; +} + + +int p3ZeroConf::checkQueryResults() +{ + zcQueryResult qr; + { + RsStackMutex stack(mZcMtx); /****** STACK LOCK MUTEX *******/ + + /* check the results Queue */ + if (mQueryResults.size() == 0) + { + return 0; + } + + std::cerr << "p3ZeroConf::checkQueryResults() Getting Item from QueryResults"; + std::cerr << std::endl; + + qr = mQueryResults.front(); + mQueryResults.pop_front(); + + } + + /* now callback to mLinkMgr to say we can connect */ + + std::cerr << "p3ZeroConf::checkQueryResults() linkMgr->peerConnectRequest() to start link"; + std::cerr << std::endl; + std::cerr << "to gpgid = " << qr.gpgId; + std::cerr << std::endl; + std::cerr << "sslid = " << qr.sslId; + std::cerr << std::endl; + + time_t now = time(NULL); + uint32_t flags = RS_CB_FLAG_MODE_TCP; + uint32_t source = RS_CB_DHT; // SHOULD ADD NEW SOURCE ZC??? + struct sockaddr_in dummyProxyAddr, dummySrcAddr; + mConnCb->peerConnectRequest(qr.sslId, qr.addr, dummyProxyAddr, dummySrcAddr, + source, flags, 0, 0); + + return 1; +} + + + + + + +/* First Step is to register the DNSService */ + +void p3ZeroConf_CallbackRegister( DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode, + const char *name, const char *regtype, const char *domain, void *context ) +{ + p3ZeroConf *zc = (p3ZeroConf *) context; + zc->callbackRegister(sdRef, flags, errorCode, name, regtype, domain); +} + + +int p3ZeroConf::locked_startRegister() +{ + if (mRegistered) + { + return 0; + } + + /* need, port & txtRecord setup already */ + if (!mTextOkay) + { + std::cerr << "p3ZeroConf::locked_startRegister()"; + std::cerr << "Text Not Setup"; + std::cerr << std::endl; + return 0; + } + + if (!mPortOkay) + { + std::cerr << "p3ZeroConf::locked_startRegister()"; + std::cerr << "Port Not Set"; + std::cerr << std::endl; + return 0; + } + + if (mRegisterStatus == ZC_SERVICE_ACTIVE) + { + return 0; + } + + + std::cerr << "p3ZeroConf::locked_startRegister() Registering!"; + std::cerr << std::endl; + std::cerr << "p3ZeroConf::locked_startRegister() Text: " << mTextRecord; + std::cerr << std::endl; + std::cerr << "p3ZeroConf::locked_startRegister() Port: " << mLocalPort; + std::cerr << std::endl; + + DNSServiceRef *sdRef = &mRegisterRef; + DNSServiceFlags flags = 0; /* no flags */ + uint32_t interfaceIndex = 0; /* all interfaces */ + char *name = NULL; /* may be NULL */ + + std::string regtype = "_librs._tcp"; + char *domain = NULL; /* may be NULL for all domains. */ + char *host = NULL; /* may be NULL for default hostname */ + + uint16_t port = htons(mLocalPort); + uint16_t txtLen = mTextRecord.length(); + const void *txtRecord = (void *) mTextRecord.c_str(); + DNSServiceRegisterReply callBack = p3ZeroConf_CallbackRegister; + void *context = this; + + DNSServiceErrorType errcode = DNSServiceRegister (sdRef, flags, interfaceIndex, + name, regtype.c_str(), domain, host, port, + txtLen, txtRecord, callBack, context); + + if (errcode != kDNSServiceErr_NoError) + { + std::cerr << "p3ZeroConf::locked_startRegister() ERROR: "; + std::cerr << displayDNSServiceError(errcode); + std::cerr << std::endl; + } + else + { + mRegisterStatus = ZC_SERVICE_ACTIVE; + mRegisterStatusTS = time(NULL); + mRegistered = true; + } + + return 1; +} + + + +void p3ZeroConf::callbackRegister( DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode, + const char *name, const char *regtype, const char *domain) +{ + std::cerr << "p3ZeroConf::callbackRegister()"; + std::cerr << std::endl; + + /* handle queryIp */ + if (errorCode != kDNSServiceErr_NoError) + { + std::cerr << "p3ZeroConf::callbackRegister() FAILED ERROR: "; + std::cerr << displayDNSServiceError(errorCode); + std::cerr << std::endl; + return; + } + + std::cerr << "p3ZeroConf::callbackRegister() Success"; + std::cerr << std::endl; + +} + + +void p3ZeroConf::locked_stopRegister() +{ + std::cerr << "p3ZeroConf::locked_stopRegister()"; + std::cerr << std::endl; + + if (mBrowseStatus != ZC_SERVICE_ACTIVE) + { + return; + } + + DNSServiceRefDeallocate(mRegisterRef); + + mRegisterStatus = ZC_SERVICE_STOPPED; + mRegisterStatusTS = time(NULL); + mRegistered = false; +} + + +void p3ZeroConf_CallbackBrowse( DNSServiceRef sdRef, DNSServiceFlags flags, + uint32_t interfaceIndex, DNSServiceErrorType errorCode, + const char *serviceName, const char *regtype, const char *replyDomain, void *context ) +{ + p3ZeroConf *zc = (p3ZeroConf *) context; + zc->callbackBrowse(sdRef, flags, interfaceIndex, errorCode, serviceName, regtype, replyDomain); +} + + +int p3ZeroConf::locked_startBrowse() +{ + if (mBrowseStatus == ZC_SERVICE_ACTIVE) + { + return 0; + } + + std::cerr << "p3ZeroConf::locked_startBrowse()"; + std::cerr << std::endl; + + DNSServiceRef *sdRef = &mBrowseRef; + DNSServiceFlags flags = 0; + uint32_t interfaceIndex = 0; + const char *regtype = "_librs._tcp"; + const char *domain = NULL; + DNSServiceBrowseReply callBack = p3ZeroConf_CallbackBrowse; + void *context = this; + + DNSServiceErrorType errcode = DNSServiceBrowse(sdRef, flags, interfaceIndex, + regtype, domain, callBack, context); + + if (errcode != kDNSServiceErr_NoError) + { + std::cerr << "p3ZeroConf::locked_startBrowse() ERROR: "; + std::cerr << displayDNSServiceError(errcode); + std::cerr << std::endl; + } + else + { + mBrowseStatus = ZC_SERVICE_ACTIVE; + mBrowseStatusTS = time(NULL); + } + + return 1; +} + + +void p3ZeroConf::callbackBrowse(DNSServiceRef /* sdRef */, DNSServiceFlags flags, + uint32_t interfaceIndex, DNSServiceErrorType errorCode, + const char *serviceName, const char *regtype, const char *replyDomain) +{ + std::cerr << "p3ZeroConf::callbackBrowse()"; + std::cerr << std::endl; + + /* handle queryIp */ + if (errorCode != kDNSServiceErr_NoError) + { + std::cerr << "p3ZeroConf::callbackBrowse() FAILED ERROR: "; + std::cerr << displayDNSServiceError(errorCode); + std::cerr << std::endl; + return; + } + + zcBrowseResult br; + + br.flags = flags; + br.interfaceIndex = interfaceIndex; + br.serviceName = serviceName; + br.regtype = regtype; + br.replyDomain = replyDomain; + + std::cerr << "p3ZeroConf::callbackBrowse() "; + std::cerr << " flags: " << flags; + std::cerr << " interfaceIndex: " << interfaceIndex; + std::cerr << " serviceName: " << serviceName; + std::cerr << " regtype: " << regtype; + std::cerr << " replyDomain: " << replyDomain; + std::cerr << std::endl; + + if (flags & kDNSServiceFlagsAdd) + { + std::cerr << "p3ZeroConf::callbackBrowse() Add Flags => so newly found Service => BrowseResults"; + std::cerr << std::endl; + mBrowseResults.push_back(br); + } + else + { + std::cerr << "p3ZeroConf::callbackBrowse() Missing Add Flag => so Service now dropped, Ignoring"; + std::cerr << std::endl; + } + +} + + +int p3ZeroConf::locked_stopBrowse() +{ + std::cerr << "p3ZeroConf::locked_stopBrowse()"; + std::cerr << std::endl; + + if (mBrowseStatus != ZC_SERVICE_ACTIVE) + { + return 0; + } + + DNSServiceRefDeallocate(mBrowseRef); + mBrowseStatus = ZC_SERVICE_STOPPED; + mBrowseStatusTS = time(NULL); + return 1; +} + + + +void p3ZeroConf_CallbackResolve( DNSServiceRef sdRef, DNSServiceFlags flags, + uint32_t interfaceIndex, DNSServiceErrorType errorCode, + const char *fullname, const char *hosttarget, uint16_t port, + uint16_t txtLen, const unsigned char *txtRecord, void *context ) +{ + p3ZeroConf *zc = (p3ZeroConf *) context; + zc->callbackResolve(sdRef, flags, interfaceIndex, errorCode, fullname, hosttarget, port, txtLen, txtRecord); + +} + +void p3ZeroConf::locked_startResolve(uint32_t idx, std::string name, + std::string regtype, std::string domain) +{ + if (mResolveStatus == ZC_SERVICE_ACTIVE) + { + return; + } + + std::cerr << "p3ZeroConf::locked_startResolve()"; + std::cerr << std::endl; + + DNSServiceRef *sdRef = &mResolveRef; + DNSServiceFlags flags = 0; + DNSServiceResolveReply callBack = p3ZeroConf_CallbackResolve; + void *context = (void *) this; + + DNSServiceErrorType errcode = DNSServiceResolve(sdRef, flags, idx, + name.c_str(), regtype.c_str(), domain.c_str(), callBack, context); + + if (errcode != kDNSServiceErr_NoError) + { + std::cerr << "p3ZeroConf::locked_startResolve() ERROR: "; + std::cerr << displayDNSServiceError(errcode); + std::cerr << std::endl; + } + else + { + mResolveStatus = ZC_SERVICE_ACTIVE; + mResolveStatusTS = time(NULL); + } +} + + + +void p3ZeroConf::callbackResolve( DNSServiceRef /* sdRef */, DNSServiceFlags flags, + uint32_t interfaceIndex, DNSServiceErrorType errorCode, + const char *fullname, const char *hosttarget, uint16_t port, + uint16_t txtLen, const unsigned char *txtRecord) +{ + std::cerr << "p3ZeroConf::callbackResolve()"; + std::cerr << std::endl; + + if (errorCode != kDNSServiceErr_NoError) + { + std::cerr << "p3ZeroConf::callbackResolve() FAILED ERROR: "; + std::cerr << displayDNSServiceError(errorCode); + std::cerr << std::endl; + return; + } + + /* handle resolve */ + zcResolveResult rr; + + rr.flags = flags; + rr.interfaceIndex = interfaceIndex; + rr.fullname = fullname; + rr.hosttarget = hosttarget; + rr.port = ntohs(port); + rr.txtLen = txtLen; + //rr.txtRecord = NULL; //malloc(rr.txtLen); + //memcpy(rr.txtRecord, txtRecord, txtLen); + // We must consume the txtRecord and translate into strings... + + std::cerr << "p3ZeroConf::callbackResolve() "; + std::cerr << " flags: " << flags; + std::cerr << " interfaceIndex: " << interfaceIndex; + std::cerr << " fullname: " << fullname; + std::cerr << " hosttarget: " << hosttarget; + std::cerr << " port: " << ntohs(port); + std::cerr << " txtLen: " << txtLen; + std::cerr << std::endl; + + std::string peerGpgId; + std::string peerSslId; + if (procPeerTxtRecord(txtLen, txtRecord, peerGpgId, peerSslId)) + { + rr.gpgId = peerGpgId; + rr.sslId = peerSslId; + + /* check if we care - install ssl record */ + int resolve = locked_checkResolvedPeer(rr); + if (resolve) + { + mResolveResults.push_back(rr); + } + } + + if (flags & kDNSServiceFlagsMoreComing) + { + std::cerr << "p3ZeroConf::callbackResolve() Expecting More Results.. keeping Ref"; + std::cerr << std::endl; + } + else + { + std::cerr << "p3ZeroConf::callbackResolve() Result done.. closing Ref"; + std::cerr << std::endl; + + locked_stopResolve(); + } +} + + +/* returns if we are interested in the peer */ +int p3ZeroConf::locked_checkResolvedPeer(const zcResolveResult &rr) +{ + /* if self - drop it */ + if ((rr.gpgId == mOwnGpgId) && (rr.sslId == mOwnSslId)) + { + std::cerr << "p3ZeroConf::locked_checkpeer() Found Self on LAN:"; + std::cerr << std::endl; + std::cerr << "gpgid = " << rr.gpgId; + std::cerr << std::endl; + std::cerr << "sslid = " << rr.sslId; + std::cerr << std::endl; + + return 0; + } + + /* check if peerGpgId is in structure already */ + std::map::iterator it; + it = mPeerDetails.find(rr.gpgId); + if (it == mPeerDetails.end()) + { + /* possibility we don't have any SSL ID's for this person + * check against AuthGPG() + */ + if ((AuthGPG::getAuthGPG()->isGPGAccepted(rr.gpgId)) || (rr.gpgId == mOwnGpgId)) + { + zcPeerDetails newFriend; + newFriend.gpgId = rr.gpgId; + mPeerDetails[rr.gpgId] = newFriend; + + it = mPeerDetails.find(rr.gpgId); + } + else + { + std::cerr << "p3ZeroConf::locked_checkpeer() Found Unknown peer on LAN:"; + std::cerr << std::endl; + std::cerr << "gpgid = " << rr.gpgId; + std::cerr << std::endl; + std::cerr << "sslid = " << rr.sslId; + std::cerr << std::endl; + + return 0; + } + } + + /* now see if we have an sslId */ + std::map::iterator lit; + lit = it->second.mLocations.find(rr.sslId); + if (lit == it->second.mLocations.end()) + { + /* install a new location -> flag it as this */ + zcLocationDetails loc; + loc.mSslId = rr.sslId; + loc.mStatus = ZC_STATUS_FOUND | ZC_STATUS_NEW_LOCATION; + loc.mPort = rr.port; + loc.mFullName = rr.fullname; + loc.mHostTarget = rr.hosttarget; + loc.mFoundTs = time(NULL); + + it->second.mLocations[rr.sslId] = loc; + + + std::cerr << "p3ZeroConf::locked_checkpeer() Adding New Location for:"; + std::cerr << std::endl; + std::cerr << "gpgid = " << rr.gpgId; + std::cerr << std::endl; + std::cerr << "sslid = " << rr.sslId; + std::cerr << std::endl; + std::cerr << "port = " << rr.port; + std::cerr << std::endl; + + + /* install item in ADD Queue */ + zcLocationResult locResult(rr.gpgId, rr.sslId); + mLocationResults.push_back(locResult); + + /* return 1, to resolve fully */ + return 1; + } + + + std::cerr << "p3ZeroConf::locked_checkpeer() Updating Location for:"; + std::cerr << std::endl; + std::cerr << "gpgid = " << rr.gpgId; + std::cerr << std::endl; + std::cerr << "sslid = " << rr.sslId; + std::cerr << std::endl; + std::cerr << "port = " << rr.port; + std::cerr << std::endl; + + lit->second.mStatus |= ZC_STATUS_FOUND; + lit->second.mPort = rr.port; + lit->second.mFullName = rr.fullname; + lit->second.mHostTarget = rr.hosttarget; + lit->second.mFoundTs = time(NULL); + + /* otherwise we get here - and we see if we are already connected */ + if (lit->second.mStatus & ZC_STATUS_CONNECTED) + { + return 0; + } + return 1; +} + +int p3ZeroConf::locked_stopResolve() +{ + std::cerr << "p3ZeroConf::locked_stopResolve()"; + std::cerr << std::endl; + + if (mResolveStatus != ZC_SERVICE_ACTIVE) + { + return 0; + } + + DNSServiceRefDeallocate(mResolveRef); + mResolveStatus = ZC_SERVICE_STOPPED; + mResolveStatusTS = time(NULL); + return 1; +} + + + + +void p3ZeroConf_CallbackQueryIp( DNSServiceRef sdRef, DNSServiceFlags flags, + uint32_t interfaceIndex, DNSServiceErrorType errorCode, + const char *fullname, uint16_t rrtype, uint16_t rrclass, + uint16_t rdlen, const void *rdata, uint32_t ttl, void *context ) +{ + p3ZeroConf *zc = (p3ZeroConf *) context; + zc->callbackQueryIp(sdRef, flags, interfaceIndex, errorCode, fullname, rrtype, rrclass, rdlen, rdata, ttl); + +} + +void p3ZeroConf::locked_startQueryIp(uint32_t idx, std::string hosttarget, std::string gpgId, std::string sslId) +{ + if (mQueryStatus == ZC_SERVICE_ACTIVE) + { + return; + } + + std::cerr << "p3ZeroConf::locked_startQueryIp()"; + std::cerr << std::endl; + std::cerr << "\thosttarget: " << hosttarget; + std::cerr << std::endl; + std::cerr << "\tgpgId: " << gpgId; + std::cerr << std::endl; + std::cerr << "\tsslId: " << sslId; + std::cerr << std::endl; + + + DNSServiceRef *sdRef = &mQueryRef; + DNSServiceFlags flags = 0; + uint16_t rrtype = kDNSServiceType_A; + uint16_t rrclass = kDNSServiceClass_IN; + DNSServiceQueryRecordReply callBack = p3ZeroConf_CallbackQueryIp; + void *context = (void *) this; + + DNSServiceErrorType errcode = DNSServiceQueryRecord(sdRef, flags, idx, + hosttarget.c_str(), rrtype, rrclass, callBack, context); + + if (errcode != kDNSServiceErr_NoError) + { + std::cerr << "p3ZeroConf::locked_startQueryIp() ERROR: "; + std::cerr << displayDNSServiceError(errcode); + std::cerr << std::endl; + } + else + { + std::cerr << "p3ZeroConf::locked_startQueryIp() Query Active"; + std::cerr << std::endl; + + mQueryStatus = ZC_SERVICE_ACTIVE; + mQueryStatusTS = time(NULL); + mQueryGpgId = gpgId; + mQuerySslId = sslId; + } +} + +void p3ZeroConf::callbackQueryIp( DNSServiceRef /* sdRef */, DNSServiceFlags flags, + uint32_t interfaceIndex, DNSServiceErrorType errorCode, + const char *fullname, uint16_t rrtype, uint16_t rrclass, + uint16_t rdlen, const void *rdata, uint32_t ttl) +{ + std::cerr << "p3ZeroConf::callbackQueryIp()"; + std::cerr << std::endl; + + /* handle queryIp */ + if (errorCode != kDNSServiceErr_NoError) + { + std::cerr << "p3ZeroConf::callbackQueryIp() FAILED ERROR: "; + std::cerr << displayDNSServiceError(errorCode); + std::cerr << std::endl; + return; + } + + /* handle resolve */ + zcQueryResult qr; + + qr.flags = flags; + qr.interfaceIndex = interfaceIndex; + qr.fullname = fullname; + qr.rrtype = rrtype; + qr.rrclass = rrclass; + qr.rdlen = rdlen; + //qr.rdata = NULL; //malloc(rr.rdlen); + //memcpy(rr.rdata, rdata, rdlen); + qr.ttl = ttl; + + std::cerr << "p3ZeroConf::callbackQuery() "; + std::cerr << " flags: " << flags; + std::cerr << " interfaceIndex: " << interfaceIndex; + std::cerr << " fullname: " << fullname; + std::cerr << " rrtype: " << rrtype; + std::cerr << " rrclass: " << rrclass; + std::cerr << " rdlen: " << rdlen; + std::cerr << " ttl: " << ttl; + std::cerr << std::endl; + + /* add in the query Ids, that we saved... */ + qr.sslId = mQuerySslId; + qr.gpgId = mQueryGpgId; + + if ((rrtype == kDNSServiceType_A) && (rdlen == 4)) + { + qr.addr.sin_addr.s_addr = *((uint32_t *) rdata); + + if (locked_completeQueryResult(qr)) // Saves Query Results, and fills in Port details. + { + mQueryResults.push_back(qr); + } + } + else + { + std::cerr << "p3ZeroConf::callbackQuery() Unknown rrtype"; + std::cerr << std::endl; + } + + if (flags & kDNSServiceFlagsMoreComing) + { + std::cerr << "p3ZeroConf::callbackQuery() Expecting More Results.. keeping Ref"; + std::cerr << std::endl; + } + else + { + std::cerr << "p3ZeroConf::callbackQuery() Result done.. closing Ref"; + std::cerr << std::endl; + + locked_stopQueryIp(); + } +} + + +/* returns 1 if all is good */ +int p3ZeroConf::locked_completeQueryResult(zcQueryResult &qr) +{ + /* check if peerGpgId is in structure already */ + std::map::iterator it; + it = mPeerDetails.find(qr.gpgId); + if (it == mPeerDetails.end()) + { + /* Should not be possible to get here! */ + std::cerr << "p3ZeroConf::locked_completeQueryResults() Missing GPGID"; + std::cerr << std::endl; + + return 0; + } + + /* now see if we have an sslId */ + std::map::iterator lit; + lit = it->second.mLocations.find(qr.sslId); + if (lit == it->second.mLocations.end()) + { + /* Should not be possible to get here! */ + std::cerr << "p3ZeroConf::locked_completeQueryResults() Missing SSLID"; + std::cerr << std::endl; + + return 0; + } + + + /*** NOW HAVE FOUND ENTRY, exchange info ****/ + + std::cerr << "p3ZeroConf::locked_completeQueryResults() Filling in Peer IpAddress"; + std::cerr << std::endl; + + qr.addr.sin_port = htons(lit->second.mPort); + lit->second.mAddress = qr.addr; + lit->second.mStatus |= ZC_STATUS_IPADDRESS; + lit->second.mAddrTs = time(NULL); + + /* if we have connected? */ + if (lit->second.mStatus & ZC_STATUS_CONNECTED) + { + std::cerr << "p3ZeroConf::locked_completeQueryResults() Warning Already Connected"; + std::cerr << std::endl; + } + return 1; +} + + +int p3ZeroConf::locked_stopQueryIp() +{ + std::cerr << "p3ZeroConf::locked_stopQueryIp()"; + std::cerr << std::endl; + + if (mQueryStatus != ZC_SERVICE_ACTIVE) + { + return 0; + } + + DNSServiceRefDeallocate(mQueryRef); + mQueryStatus = ZC_SERVICE_STOPPED; + mQueryStatusTS = time(NULL); + return 1; +} + + + + +std::string p3ZeroConf::displayDNSServiceError(DNSServiceErrorType errcode) +{ + std::ostringstream str; + switch(errcode) + { + default: + str << "kDNSServiceErr_??? UNKNOWN-CODE"; + break; + case kDNSServiceErr_NoError: + str << "kDNSServiceErr_NoError"; + break; + case kDNSServiceErr_Unknown: + str << "kDNSServiceErr_Unknown"; + break; + case kDNSServiceErr_NoSuchName: + str << "kDNSServiceErr_NoSuchName"; + break; + case kDNSServiceErr_NoMemory: + str << "kDNSServiceErr_NoMemory"; + break; + case kDNSServiceErr_BadParam: + str << "kDNSServiceErr_BadParam"; + break; + case kDNSServiceErr_BadReference: + str << "kDNSServiceErr_BadReference"; + break; + case kDNSServiceErr_BadState: + str << "kDNSServiceErr_BadState"; + break; + case kDNSServiceErr_BadFlags: + str << "kDNSServiceErr_BadFlags"; + break; + case kDNSServiceErr_Unsupported: + str << "kDNSServiceErr_Unsupported"; + break; + case kDNSServiceErr_NotInitialized: + str << "kDNSServiceErr_NotInitialized"; + break; + case kDNSServiceErr_AlreadyRegistered: + str << "kDNSServiceErr_AlreadyRegistered"; + break; + case kDNSServiceErr_NameConflict: + str << "kDNSServiceErr_NameConflict"; + break; + case kDNSServiceErr_Invalid: + str << "kDNSServiceErr_Invalid"; + break; + case kDNSServiceErr_Firewall: + str << "kDNSServiceErr_Firewall"; + break; + case kDNSServiceErr_Incompatible: + str << "kDNSServiceErr_Incompatible"; + break; + case kDNSServiceErr_BadInterfaceIndex: + str << "kDNSServiceErr_BadInterfaceIndex"; + break; + case kDNSServiceErr_Refused: + str << "kDNSServiceErr_Refused"; + break; + case kDNSServiceErr_NoSuchRecord: + str << "kDNSServiceErr_NoSuchRecord"; + break; + case kDNSServiceErr_NoAuth: + str << "kDNSServiceErr_NoAuth"; + break; + case kDNSServiceErr_NoSuchKey: + str << "kDNSServiceErr_NoSuchKey"; + break; + case kDNSServiceErr_NATTraversal: + str << "kDNSServiceErr_NATTraversal"; + break; + case kDNSServiceErr_DoubleNAT: + str << "kDNSServiceErr_DoubleNAT"; + break; + case kDNSServiceErr_BadTime: + str << "kDNSServiceErr_BadTime"; + break; + case kDNSServiceErr_BadSig: + str << "kDNSServiceErr_BadSig"; + break; + case kDNSServiceErr_BadKey: + str << "kDNSServiceErr_BadKey"; + break; + case kDNSServiceErr_Transient: + str << "kDNSServiceErr_Transient"; + break; + case kDNSServiceErr_ServiceNotRunning: + str << "kDNSServiceErr_ServiceNotRunning"; + break; + case kDNSServiceErr_NATPortMappingUnsupported: + str << "kDNSServiceErr_NATPortMappingUnsupported"; + break; + case kDNSServiceErr_NATPortMappingDisabled: + str << "kDNSServiceErr_NATPortMappingDisabled"; + break; +#if 0 + case kDNSServiceErr_NoRouter: + str << "kDNSServiceErr_NoRouter"; + break; + case kDNSServiceErr_PollingMode: + str << "kDNSServiceErr_PollingMode"; + break; +#endif + } + + return str.str(); +} + + + +/*********************************************************************************** + * Handle Peer Data, list of friends etc. + * + * We need data structures to handle the Info from libretroshare, + * and the info from ZeroConf too. + * + ****/ + +/* This needs to be a separate class - as we don't know which peer it is + * associated with until we have Resolved the details. + */ + +class RsZCBrowseDetails +{ + public: + RsZCBrowseDetails(); + + uint32_t mBrowseState; + time_t mBrowseUpdate; + + uint32_t mBrowseInterfaceIndex; + std::string mBrowserServiceName; + std::string mBrowserRegType; + std::string mBrowserReplyDomain; + + uint32_t mResolveInterfaceIndex; + std::string mResolveFullname; + std::string mResolveHostTarget; + uint32_t mResolvePort; + std::string mResolveTxtRecord; +}; + + + +class RsZCPeerDetails +{ + /* passed from libretroshare */ + + std::string mGpgId; + std::string mSslId; + + uint32_t mPeerStatus; /* FRIEND, FOF, ONLINE, OFFLINE */ + + /* Browse Info */ + + uint32_t mBrowseState; + time_t mBrowseUpdate; + + uint32_t mBrowseInterfaceIndex; + std::string mBrowserServiceName; + std::string mBrowserRegType; + std::string mBrowserReplyDomain; + + /* Resolve Info */ + + uint32_t mResolveInterfaceIndex; + std::string mResolveFullname; + std::string mResolveHostTarget; + uint32_t mResolvePort; + std::string mResolveTxtRecord; +}; + + + + + + + + + + + diff --git a/libretroshare/src/zeroconf/p3zeroconf.h b/libretroshare/src/zeroconf/p3zeroconf.h new file mode 100644 index 000000000..e52a76e1c --- /dev/null +++ b/libretroshare/src/zeroconf/p3zeroconf.h @@ -0,0 +1,286 @@ +/* + * libretroshare/src/zeroconf: p3zeroconf.h + * + * ZeroConf interface for RetroShare. + * + * Copyright 2011-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 2 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 "retroshare@lunamutt.com". + * + */ + + +#ifndef MRK_P3_ZEROCONF_H +#define MRK_P3_ZEROCONF_H + +#include "util/rswin.h" + +#include "pqi/pqiassist.h" +#include "retroshare/rsdht.h" + +#include +#include +#include "pqi/pqinetwork.h" +#include "pqi/pqimonitor.h" +#include "pqi/p3peermgr.h" +#include "util/rsthreads.h" + +#include + + +class zcBrowseResult +{ + public: + DNSServiceFlags flags; + uint32_t interfaceIndex; + std::string serviceName; + std::string regtype; + std::string replyDomain; +}; + + +class zcResolveResult +{ + public: + zcResolveResult() { return; } // :txtRecord(NULL) { return; } + ~zcResolveResult() { return; } //{ if (txtRecord) { free(txtRecord); txtRecord = NULL; } } + + DNSServiceFlags flags; + uint32_t interfaceIndex; + std::string fullname; + std::string hosttarget; + uint16_t port; + uint16_t txtLen; + //unsigned char *txtRecord; + + // extra results. + std::string gpgId; + std::string sslId; +}; + + +class zcQueryResult +{ + public: + zcQueryResult() { return; } //:rdata(NULL) { return; } + ~zcQueryResult() {return; } //{ if (rdata) { free(rdata); rdata = NULL; } } + + DNSServiceFlags flags; + uint32_t interfaceIndex; + std::string fullname; + uint16_t rrtype; + uint16_t rrclass; + uint16_t rdlen; + //void *rdata; + uint32_t ttl; + + // Extra ones. + std::string sslId; + std::string gpgId; + struct sockaddr_in addr; +}; + + +class zcLocationResult +{ + public: + zcLocationResult() { return; } + zcLocationResult(std::string _gpgId, std::string _sslId) + :gpgId(_gpgId), sslId(_sslId) { return; } + + std::string gpgId; + std::string sslId; +}; + +#define ZC_STATUS_NEW_LOCATION 1 +#define ZC_STATUS_FOUND 2 +#define ZC_STATUS_CONNECTED 4 +#define ZC_STATUS_IPADDRESS 8 + +class zcLocationDetails +{ + public: + std::string mSslId; + time_t mFoundTs; + uint32_t mStatus; + std::string mHostTarget; + std::string mFullName; + uint16_t mPort; + + struct sockaddr_in mAddress; + time_t mAddrTs; +}; + + +class zcPeerDetails +{ + public: + + std::string gpgId; + std::map mLocations; + +}; + +class p3NetMgr; + +class p3ZeroConf: public pqiNetAssistConnect, public pqiNetListener +{ + public: + p3ZeroConf(std::string gpgid, std::string sslid, pqiConnectCb *cb, p3NetMgr *nm, p3PeerMgr *pm); +virtual ~p3ZeroConf(); + + /*** OVERLOADED from pqiNetListener ***/ + +virtual bool resetListener(struct sockaddr_in &local); + +void start(); /* starts up the thread */ + + /* pqiNetAssist - external interface functions */ +virtual int tick(); +virtual void enable(bool on); +virtual void shutdown(); /* blocking call */ +virtual void restart(); + +virtual bool getEnabled(); +virtual bool getActive(); +virtual bool getNetworkStats(uint32_t &netsize, uint32_t &localnetsize); + + /* pqiNetAssistConnect - external interface functions */ + + /* add / remove peers */ +virtual bool findPeer(std::string id); +virtual bool dropPeer(std::string id); + +virtual int addBadPeer(const struct sockaddr_in &addr, uint32_t reason, uint32_t flags, uint32_t age); +virtual int addKnownPeer(const std::string &pid, const struct sockaddr_in &addr, uint32_t flags); + + /* feedback on success failure of Connections */ +virtual void ConnectionFeedback(std::string pid, int state); + + /* extract current peer status */ +virtual bool getPeerStatus(std::string id, + struct sockaddr_in &laddr, struct sockaddr_in &raddr, + uint32_t &type, uint32_t &mode); + +virtual bool setAttachMode(bool on); + + /* pqiNetAssistConnect - external interface functions */ + + + public: + + // Callbacks must be public -> so they can be accessed. + void callbackRegister(DNSServiceRef sdRef, DNSServiceFlags flags, + DNSServiceErrorType errorCode, + const char *name, const char *regtype, const char *domain); + + void callbackBrowse(DNSServiceRef sdRef, DNSServiceFlags flags, + uint32_t interfaceIndex, DNSServiceErrorType errorCode, + const char *serviceName, const char *regtype, const char *replyDomain); + + void callbackResolve( DNSServiceRef sdRef, DNSServiceFlags flags, + uint32_t interfaceIndex, DNSServiceErrorType errorCode, + const char *fullname, const char *hosttarget, uint16_t port, + uint16_t txtLen, const unsigned char *txtRecord); + + void callbackQueryIp( DNSServiceRef sdRef, DNSServiceFlags flags, + uint32_t interfaceIndex, DNSServiceErrorType errorCode, + const char *fullname, uint16_t rrtype, uint16_t rrclass, + uint16_t rdlen, const void *rdata, uint32_t ttl); + + private: + + void createTxtRecord(); + + /* monitoring fns */ + void checkServiceFDs(); + void locked_checkFD(DNSServiceRef ref); + int checkResolveAction(); + int checkLocationResults(); + int checkQueryAction(); + int checkQueryResults(); + + /**** THESE ARE MAINLY SEMI LOCKED.... not quite sure when the callback will happen! ***/ + + int locked_startRegister(); + void locked_stopRegister(); + + int locked_startBrowse(); + int locked_stopBrowse(); + + + void locked_startResolve(uint32_t idx, std::string name, + std::string regtype, std::string domain); + int locked_checkResolvedPeer(const zcResolveResult &rr); + int locked_stopResolve(); + + void locked_startQueryIp(uint32_t idx, std::string fullname, + std::string gpgId, std::string sslId); + int locked_completeQueryResult(zcQueryResult &qr); + int locked_stopQueryIp(); + + std::string displayDNSServiceError(DNSServiceErrorType errcode); + + /**************** DATA ****************/ + + p3NetMgr *mNetMgr; + p3PeerMgr *mPeerMgr; + + RsMutex mZcMtx; + + std::string mOwnGpgId; + std::string mOwnSslId; + + bool mRegistered; + bool mTextOkay; + bool mPortOkay; + + uint16_t mLocalPort; + std::string mTextRecord; + + DNSServiceRef mRegisterRef; + DNSServiceRef mBrowseRef; + DNSServiceRef mResolveRef; + DNSServiceRef mQueryRef; + + uint32_t mRegisterStatus; + uint32_t mBrowseStatus; + uint32_t mResolveStatus; + uint32_t mQueryStatus; + + time_t mRegisterStatusTS; + time_t mBrowseStatusTS; + time_t mResolveStatusTS; + time_t mQueryStatusTS; + + std::string mQuerySslId; + std::string mQueryGpgId; + +std::list mBrowseResults; +std::list mResolveResults; +std::list mLocationResults; +std::list mQueryResults; + + + + time_t mMinuteTS; + + std::map mPeerDetails; +}; + +#endif /* MRK_P3_ZEROCONF_H */ + diff --git a/retroshare-gui/src/RetroShare.pro b/retroshare-gui/src/RetroShare.pro index c21cd5e94..64bb60dfc 100644 --- a/retroshare-gui/src/RetroShare.pro +++ b/retroshare-gui/src/RetroShare.pro @@ -307,6 +307,7 @@ HEADERS += rshare.h \ gui/settings/SoundPage.h \ gui/settings/TransferPage.h \ gui/settings/ChatPage.h \ + gui/settings/RelayPage.h \ gui/settings/AddFileAssociationDialog.h \ gui/toaster/MessageToaster.h \ gui/toaster/OnlineToaster.h \ @@ -429,6 +430,7 @@ FORMS += gui/StartDialog.ui \ gui/settings/TransferPage.ui \ gui/settings/SoundPage.ui \ gui/settings/ChatPage.ui \ + gui/settings/RelayPage.ui \ gui/settings/PluginItem.ui \ gui/toaster/MessageToaster.ui \ gui/toaster/OnlineToaster.ui \ @@ -587,6 +589,7 @@ SOURCES += main.cpp \ gui/settings/SoundPage.cpp \ gui/settings/TransferPage.cpp \ gui/settings/ChatPage.cpp \ + gui/settings/RelayPage.cpp \ gui/settings/AddFileAssociationDialog.cpp \ gui/statusbar/peerstatus.cpp \ gui/statusbar/natstatus.cpp \ diff --git a/retroshare-gui/src/gui/ForumsDialog.cpp b/retroshare-gui/src/gui/ForumsDialog.cpp index 202da0cf9..fae797d1e 100644 --- a/retroshare-gui/src/gui/ForumsDialog.cpp +++ b/retroshare-gui/src/gui/ForumsDialog.cpp @@ -566,7 +566,7 @@ void ForumsDialog::insertForums() uint32_t i = 0; uint32_t popLimit = 0; std::multimap::reverse_iterator rit; - for(rit = popMap.rbegin(); ((rit != popMap.rend()) && (i < popCount)); rit++, i++); + for(rit = popMap.rbegin(); ((rit != popMap.rend()) && (i < popCount)); rit++, i++) ; if (rit != popMap.rend()) { popLimit = rit->first; } diff --git a/retroshare-gui/src/gui/settings/RelayPage.cpp b/retroshare-gui/src/gui/settings/RelayPage.cpp new file mode 100644 index 000000000..6864b66db --- /dev/null +++ b/retroshare-gui/src/gui/settings/RelayPage.cpp @@ -0,0 +1,278 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2010 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "RelayPage.h" + +#include "rshare.h" + +#include +#include + +#include +#include +#include +#include + +#include + +RelayPage::RelayPage(QWidget * parent, Qt::WFlags flags) + : ConfigPage(parent, flags) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + QObject::connect(ui.noFriendSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateRelayOptions())); + QObject::connect(ui.noFOFSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateRelayOptions())); + QObject::connect(ui.noGeneralSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateRelayOptions())); + QObject::connect(ui.bandFriendSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateRelayOptions())); + QObject::connect(ui.bandFOFSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateRelayOptions())); + QObject::connect(ui.bandGeneralSpinBox,SIGNAL(valueChanged(int)),this,SLOT(updateRelayOptions())); + + QObject::connect(ui.addPushButton,SIGNAL(clicked()),this,SLOT(addServer())); + QObject::connect(ui.removePushButton,SIGNAL(clicked()),this,SLOT(removeServer())); + QObject::connect(ui.DhtLineEdit,SIGNAL(textChanged(const QString &)),this,SLOT(checkKey())); + + QObject::connect(ui.enableCheckBox,SIGNAL(stateChanged(int)),this,SLOT(updateEnabled())); + QObject::connect(ui.serverCheckBox,SIGNAL(stateChanged(int)),this,SLOT(updateEnabled())); + + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + + /** Saves the changes on this page */ +bool RelayPage::save(QString &errmsg) +{ + + int nFriends = ui.noFriendSpinBox->value(); + int friendBandwidth = ui.bandFriendSpinBox->value(); + + int nFOF = ui.noFOFSpinBox->value(); + int fofBandwidth = ui.bandFOFSpinBox->value(); + + int nGeneral = ui.noGeneralSpinBox->value(); + int genBandwidth = ui.bandGeneralSpinBox->value(); + + int total = nFriends + nFOF + nGeneral; + + rsDht->setRelayAllowance(RSDHT_RELAY_CLASS_ALL, total, 0); + rsDht->setRelayAllowance(RSDHT_RELAY_CLASS_FRIENDS, nFriends, 1024 * friendBandwidth); + rsDht->setRelayAllowance(RSDHT_RELAY_CLASS_FOF, nFOF, 1024 * fofBandwidth); + rsDht->setRelayAllowance(RSDHT_RELAY_CLASS_GENERAL, nGeneral, 1024 * genBandwidth); + + uint32_t relayMode = 0; + if (ui.enableCheckBox->isChecked()) + { + relayMode |= RSDHT_RELAY_ENABLED; + + if (ui.serverCheckBox->isChecked()) + { + relayMode |= RSDHT_RELAY_MODE_ON; + } + else + { + relayMode |= RSDHT_RELAY_MODE_OFF; + } + } + else + { + relayMode |= RSDHT_RELAY_MODE_OFF; + } + + rsDht->setRelayMode(relayMode); + return true; +} + + /** Loads the settings for this page */ +void RelayPage::load() +{ + uint32_t count; + uint32_t bandwidth; + rsDht->getRelayAllowance(RSDHT_RELAY_CLASS_FRIENDS, count, bandwidth); + ui.noFriendSpinBox->setValue(count); + ui.bandFriendSpinBox->setValue(bandwidth / 1000); + + rsDht->getRelayAllowance(RSDHT_RELAY_CLASS_FOF, count, bandwidth); + ui.noFOFSpinBox->setValue(count); + ui.bandFOFSpinBox->setValue(bandwidth / 1000); + + rsDht->getRelayAllowance(RSDHT_RELAY_CLASS_GENERAL, count, bandwidth); + ui.noGeneralSpinBox->setValue(count); + ui.bandGeneralSpinBox->setValue(bandwidth / 1000); + + + uint32_t relayMode = rsDht->getRelayMode(); + if (relayMode & RSDHT_RELAY_ENABLED) + { + ui.enableCheckBox->setCheckState(Qt::Checked); + if ((relayMode & RSDHT_RELAY_MODE_MASK) == RSDHT_RELAY_MODE_OFF) + { + ui.serverCheckBox->setCheckState(Qt::Unchecked); + } + else + { + ui.serverCheckBox->setCheckState(Qt::Checked); + } + } + else + { + ui.enableCheckBox->setCheckState(Qt::Unchecked); + ui.serverCheckBox->setCheckState(Qt::Unchecked); + } + + loadServers(); + updateRelayOptions(); + updateEnabled(); + checkKey(); +} + +void RelayPage::loadServers() +{ + std::list servers; + std::list::iterator it; + + rsDht->getRelayServerList(servers); + + ui.serverTreeWidget->clear(); + for(it = servers.begin(); it != servers.end(); it++) + { + QTreeWidgetItem *item = new QTreeWidgetItem(); + item->setData(0, Qt::DisplayRole, QString::fromStdString(*it)); + ui.serverTreeWidget->addTopLevelItem(item); + } +} + + + +void RelayPage::updateRelayOptions() +{ + int nFriends = ui.noFriendSpinBox->value(); + int friendBandwidth = ui.bandFriendSpinBox->value(); + + int nFOF = ui.noFOFSpinBox->value(); + int fofBandwidth = ui.bandFOFSpinBox->value(); + + int nGeneral = ui.noGeneralSpinBox->value(); + int genBandwidth = ui.bandGeneralSpinBox->value(); + + std::ostringstream tfriendout; + tfriendout << nFriends * friendBandwidth * 2; + ui.totalFriendLineEdit->setText(QString::fromStdString(tfriendout.str())); + + std::ostringstream tfofout; + tfofout << nFOF * fofBandwidth * 2; + ui.totalFOFLineEdit->setText(QString::fromStdString(tfofout.str())); + + std::ostringstream tgenout; + tgenout << nGeneral * genBandwidth * 2; + ui.totalGeneralLineEdit->setText(QString::fromStdString(tgenout.str())); + + std::ostringstream totalout; + totalout << (nFriends * friendBandwidth + + nFOF * fofBandwidth + + nGeneral * genBandwidth) * 2; + ui.totalBandwidthLineEdit->setText(QString::fromStdString(totalout.str())); + + std::ostringstream countout; + countout << (nFriends + nFOF + nGeneral); + ui.noTotalLineEdit->setText(QString::fromStdString(countout.str())); +} + +void RelayPage::updateEnabled() +{ + std::cerr << "RelayPage::updateEnabled()" << std::endl; + + if (ui.enableCheckBox->isChecked()) + { + ui.groupBox->setEnabled(true); + if (ui.serverCheckBox->isChecked()) + { + std::cerr << "RelayPage::updateEnabled() Both Enabled" << std::endl; + ui.serverGroupBox->setEnabled(true); + } + else + { + std::cerr << "RelayPage::updateEnabled() Options Only Enabled" << std::endl; + ui.serverGroupBox->setEnabled(false); + } + } + else + { + std::cerr << "RelayPage::updateEnabled() Both Disabled" << std::endl; + ui.groupBox->setEnabled(false); + ui.serverGroupBox->setEnabled(false); + } + +} + + +void RelayPage::checkKey() +{ + + std::string server = ui.DhtLineEdit->text().toStdString(); + std::cerr << "RelayPage::checkKey() length: " << server.length(); + std::cerr << std::endl; + if (server.length() == 40) + { + ui.keyOkBox->setChecked(Qt::Checked); + } + else + { + ui.keyOkBox->setChecked(Qt::Unchecked); + } +} + + +void RelayPage::addServer() +{ + std::cerr << "RelayPage::addServer()"; + std::cerr << std::endl; + + if (!ui.keyOkBox->isChecked()) + { + return; + } + + std::string server = ui.DhtLineEdit->text().toStdString(); + + bool ok = rsDht->addRelayServer(server); + if (ok) + { + ui.DhtLineEdit->setText(QString("")); + } + loadServers(); +} + +void RelayPage::removeServer() +{ + QTreeWidgetItem *item = ui.serverTreeWidget->currentItem(); + if (item) + { + std::string server = item->data(0, Qt::DisplayRole).toString().toStdString(); + rsDht->removeRelayServer(server); + } + + loadServers(); +} + + diff --git a/retroshare-gui/src/gui/settings/RelayPage.h b/retroshare-gui/src/gui/settings/RelayPage.h new file mode 100644 index 000000000..9bce561b3 --- /dev/null +++ b/retroshare-gui/src/gui/settings/RelayPage.h @@ -0,0 +1,57 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2010 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef RELAYPAGE_H +#define RELAYPAGE_H + +# include + +#include "configpage.h" +#include "ui_RelayPage.h" + +class RelayPage: public ConfigPage +{ + Q_OBJECT + + public: + RelayPage(QWidget * parent = 0, Qt::WFlags flags = 0); + ~RelayPage() {} + + /** Saves the changes on this page */ + virtual bool save(QString &/*errmsg*/); + /** Loads the settings for this page */ + virtual void load(); + + public slots: + void updateRelayOptions(); + void updateEnabled(); + void checkKey(); + void addServer(); + void removeServer(); + void loadServers(); + + private: + + Ui::RelayPage ui; +}; + +#endif //RELAYPAGE_H + diff --git a/retroshare-gui/src/gui/settings/RelayPage.ui b/retroshare-gui/src/gui/settings/RelayPage.ui new file mode 100644 index 000000000..1b5f31e5b --- /dev/null +++ b/retroshare-gui/src/gui/settings/RelayPage.ui @@ -0,0 +1,372 @@ + + + RelayPage + + + + 0 + 0 + 486 + 360 + + + + + + + + + Enable Relay Connections + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Use Relay Servers + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + true + + + Relay options + + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 110 + 20 + + + + + + + + Number + + + + + + + Qt::Horizontal + + + + 6 + 20 + + + + + + + + Bandwidth per link + + + + + + + Qt::Vertical + + + + + + + Total Bandwidth + + + + + + + Friends + + + + + + + 3 + + + 99 + + + + + + + x + + + + + + + kB/s + + + 1 + + + 100 + + + + + + + Qt::NoFocus + + + true + + + + + + + Friends of Friends + + + + + + + + + + x + + + + + + + kB/s + + + 1 + + + 100 + + + + + + + Qt::NoFocus + + + true + + + + + + + General + + + + + + + + + + x + + + + + + + kB/s + + + 1 + + + 100 + + + + + + + Qt::NoFocus + + + true + + + + + + + Qt::Horizontal + + + + + + + Qt::WheelFocus + + + true + + + + + + + Total: + + + + + + + Qt::Horizontal + + + + 123 + 20 + + + + + + + + Qt::NoFocus + + + true + + + + + + + + + + Relay Server Setup + + + + -1 + + + 0 + + + 0 + + + + + HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH; + + + + + + + + + + false + + + + + + true + + + + + + + Add Server + + + + + + + + Server Dht Key + + + + + + + + Remove Server + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/settings/rsettingswin.cpp b/retroshare-gui/src/gui/settings/rsettingswin.cpp index e2dcd37a2..2639fa22c 100644 --- a/retroshare-gui/src/gui/settings/rsettingswin.cpp +++ b/retroshare-gui/src/gui/settings/rsettingswin.cpp @@ -31,6 +31,7 @@ #include "FileAssociationsPage.h" #include "SoundPage.h" #include "TransferPage.h" +#include "RelayPage.h" #include "ChatPage.h" #include "MessagePage.h" #include "ForumPage.h" @@ -107,8 +108,9 @@ RSettingsWin::initStackedWidget() stackedWidget->addWidget(new GeneralPage(0)); stackedWidget->addWidget(new ServerPage()); stackedWidget->addWidget(new TransferPage()); + stackedWidget->addWidget(new RelayPage() ); stackedWidget->addWidget(new DirectoriesPage()); - stackedWidget->addWidget(new PluginsPage() ); + stackedWidget->addWidget(new PluginsPage() ); stackedWidget->addWidget(new NotifyPage()); stackedWidget->addWidget(new CryptoPage()); stackedWidget->addWidget(new MessagePage()); @@ -143,6 +145,10 @@ RSettingsWin::setNewPage(int page) text = tr("Transfer"); pageicon->setPixmap(QPixmap(":/images/ktorrent32.png")); break; + case Relay: + text = tr("Relay"); + pageicon->setPixmap(QPixmap(":/images/server_24x24.png")); + break; case Notify: text = tr("Notify"); pageicon->setPixmap(QPixmap(":/images/status_unknown.png")); diff --git a/retroshare-gui/src/gui/settings/rsettingswin.h b/retroshare-gui/src/gui/settings/rsettingswin.h index ae51ce2e4..4d8dd28d9 100755 --- a/retroshare-gui/src/gui/settings/rsettingswin.h +++ b/retroshare-gui/src/gui/settings/rsettingswin.h @@ -31,7 +31,7 @@ class RSettingsWin: public QDialog, private Ui::Settings Q_OBJECT public: - enum PageType { LastPage = -1, General = 0, Server, Transfer, + enum PageType { LastPage = -1, General = 0, Server, Transfer,Relay, Directories, Plugins, Notify, Security, Message, Forum, Chat, Appearance, Sound, Fileassociations }; static void showYourself(QWidget *parent, PageType page = LastPage); diff --git a/retroshare-gui/src/gui/settings/settings.ui b/retroshare-gui/src/gui/settings/settings.ui index 6dbea58ac..84bfa4219 100755 --- a/retroshare-gui/src/gui/settings/settings.ui +++ b/retroshare-gui/src/gui/settings/settings.ui @@ -107,6 +107,15 @@ :/images/ktorrent32.png:/images/ktorrent32.png + + + Relays + + + + :/images/server_24x24.png:/images/server_24x24.png + + Directories