diff --git a/libretroshare/src/pqi/authxpgp.cc b/libretroshare/src/pqi/authxpgp.cc index c15764a07..c1a77832d 100644 --- a/libretroshare/src/pqi/authxpgp.cc +++ b/libretroshare/src/pqi/authxpgp.cc @@ -50,7 +50,9 @@ xPGP_vfy.h:#define TRUST_SIGN_BAD -1 /********************************************************************************/ /********************************************************************************/ -#define AUTHXPGP_DEBUG 1 +/*********** + ** #define AUTHXPGP_DEBUG 1 + **********/ // the single instance of this. static AuthXPGP instance_sslroot; @@ -563,7 +565,57 @@ bool AuthXPGP::SaveCertificateToFile(std::string id, std::string filename) xpgpMtx.unlock(); /**** UNLOCK ****/ return valid; } - + + /**** To/From DER format ***/ + +bool AuthXPGP::LoadCertificateFromBinary(const uint8_t *ptr, uint32_t len, std::string &id) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::LoadCertificateFromFile() " << id; + std::cerr << std::endl; +#endif + + XPGP *xpgp = loadXPGPFromDER(ptr, len); + if (!xpgp) + return false; + + return ProcessXPGP(xpgp, id); + +} + +bool AuthXPGP::SaveCertificateToBinary(std::string id, uint8_t **ptr, uint32_t *len) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::SaveCertificateToBinary() " << id; + std::cerr << std::endl; +#endif + + xpgpMtx.lock(); /***** LOCK *****/ + + /* get the cert first */ + xpgpcert *cert = NULL; + bool valid = false; + std::string hash; + + if (id == mOwnId) + { + cert = mOwnCert; + valid = true; + } + else if (locked_FindCert(id, &cert)) + { + valid = true; + } + if (valid) + { + valid = saveXPGPToDER(cert->certificate, ptr, len); + } + + xpgpMtx.unlock(); /**** UNLOCK ****/ + return valid; +} + + /* Signatures */ bool AuthXPGP::SignCertificate(std::string id) { @@ -940,17 +992,44 @@ XPGP *AuthXPGP::loadXPGPFromPEM(std::string pem) return pc; } -XPGP *AuthXPGP::loadXPGPFromDER(char *data, uint32_t len) +XPGP *AuthXPGP::loadXPGPFromDER(const uint8_t *ptr, uint32_t len) { #ifdef AUTHXPGP_DEBUG std::cerr << "AuthXPGP::LoadXPGPFromDER()"; std::cerr << std::endl; #endif - /**** TODO ****/ - return NULL; + XPGP *tmp = NULL; + unsigned char **certptr = (unsigned char **) &ptr; + XPGP *xpgp = d2i_XPGP(&tmp, certptr, len); + + return xpgp; } +bool AuthXPGP::saveXPGPToDER(XPGP *xpgp, uint8_t **ptr, uint32_t *len) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::saveXPGPToDER()"; + std::cerr << std::endl; +#endif + + int certlen = i2d_XPGP(xpgp, (unsigned char **) ptr); + if (certlen > 0) + { + *len = certlen; + return true; + } + else + { + *len = 0; + return false; + } + return false; +} + + + + bool AuthXPGP::ProcessXPGP(XPGP *xpgp, std::string &id) { #ifdef AUTHXPGP_DEBUG @@ -1294,7 +1373,7 @@ std::string getX509CNString(X509_NAME *name) } -std::string getX509TypeString(X509_NAME *name, char *type, int len) +std::string getX509TypeString(X509_NAME *name, const char *type, int len) { std::string namestr; for(int i = 0; i < X509_NAME_entry_count(name); i++) diff --git a/libretroshare/src/pqi/authxpgp.h b/libretroshare/src/pqi/authxpgp.h index 1f1019cb2..b37681a89 100644 --- a/libretroshare/src/pqi/authxpgp.h +++ b/libretroshare/src/pqi/authxpgp.h @@ -103,11 +103,14 @@ virtual std::string getName(std::string id); virtual bool getDetails(std::string id, pqiAuthDetails &details); /* Load/Save certificates */ - + virtual bool LoadCertificateFromString(std::string pem, std::string &id); virtual std::string SaveCertificateToString(std::string id); virtual bool LoadCertificateFromFile(std::string filename, std::string &id); virtual bool SaveCertificateToFile(std::string id, std::string filename); + +virtual bool LoadCertificateFromBinary(const uint8_t *ptr, uint32_t len, std::string &id); +virtual bool SaveCertificateToBinary(std::string id, uint8_t **ptr, uint32_t *len); /* Signatures */ @@ -128,17 +131,21 @@ bool ValidateCertificateXPGP(XPGP *xpgp, std::string &peerId); /* validate + ge bool FailedCertificateXPGP(XPGP *xpgp, bool incoming); /* store for discovery */ bool CheckCertificateXPGP(std::string peerId, XPGP *xpgp); /* check that they are exact match */ + private: /* Helper Functions */ bool getXPGPid(XPGP *xpgp, std::string &xpgpid); bool ProcessXPGP(XPGP *xpgp, std::string &id); -XPGP * loadXPGPFromDER(char *data, uint32_t len); + XPGP * loadXPGPFromPEM(std::string pem); XPGP * loadXPGPFromFile(std::string fname, std::string hash); bool saveXPGPToFile(XPGP *xpgp, std::string fname, std::string &hash); +XPGP * loadXPGPFromDER(const uint8_t *ptr, uint32_t len); +bool saveXPGPToDER(XPGP *xpgp, uint8_t **ptr, uint32_t *len); + /*********** LOCKED Functions ******/ bool locked_FindCert(std::string id, xpgpcert **cert); diff --git a/libretroshare/src/pqi/p3authmgr.cc b/libretroshare/src/pqi/p3authmgr.cc index 6ab4047d7..3ab9e93bc 100644 --- a/libretroshare/src/pqi/p3authmgr.cc +++ b/libretroshare/src/pqi/p3authmgr.cc @@ -204,6 +204,15 @@ bool p3DummyAuthMgr::LoadCertificateFromFile(std::string filename, std::string & } bool p3DummyAuthMgr::SaveCertificateToFile(std::string id, std::string filename) +{ + return false; +} +bool p3DummyAuthMgr::LoadCertificateFromBinary(const uint8_t *ptr, uint32_t len, std::string &id) +{ + return false; +} + +bool p3DummyAuthMgr::SaveCertificateToBinary(std::string id, uint8_t **ptr, uint32_t *len) { return false; } diff --git a/libretroshare/src/pqi/p3authmgr.h b/libretroshare/src/pqi/p3authmgr.h index 8a766cc6c..5e06e0cfb 100644 --- a/libretroshare/src/pqi/p3authmgr.h +++ b/libretroshare/src/pqi/p3authmgr.h @@ -102,6 +102,12 @@ virtual std::string SaveCertificateToString(std::string id) = 0; virtual bool LoadCertificateFromFile(std::string filename, std::string &id) = 0; virtual bool SaveCertificateToFile(std::string id, std::string filename) = 0; + /* specific OpenSSL ones -> careful with pointers.... + * save will allocate space, + */ +virtual bool LoadCertificateFromBinary(const uint8_t *ptr, uint32_t len, std::string &id) = 0; +virtual bool SaveCertificateToBinary(std::string id, uint8_t **ptr, uint32_t *len) = 0; + /* Signatures */ virtual bool AuthCertificate(std::string uid) = 0; virtual bool SignCertificate(std::string id) = 0; @@ -149,6 +155,8 @@ virtual std::string SaveCertificateToString(std::string id); virtual bool LoadCertificateFromFile(std::string filename, std::string &id); virtual bool SaveCertificateToFile(std::string id, std::string filename); +virtual bool LoadCertificateFromBinary(const uint8_t *ptr, uint32_t len, std::string &id); +virtual bool SaveCertificateToBinary(std::string id, uint8_t **ptr, uint32_t *len); /* Signatures */ virtual bool AuthCertificate(std::string uid); diff --git a/libretroshare/src/pqi/p3connmgr.cc b/libretroshare/src/pqi/p3connmgr.cc index 492859b99..5188fa036 100644 --- a/libretroshare/src/pqi/p3connmgr.cc +++ b/libretroshare/src/pqi/p3connmgr.cc @@ -43,10 +43,8 @@ const uint32_t RS_STUN_LIST_MIN = 100; const uint32_t MAX_UPNP_INIT = 10; /* seconds UPnP timeout */ - #define CONN_DEBUG 1 - p3ConnectMgr::p3ConnectMgr(p3AuthMgr *am) :p3Config(CONFIG_TYPE_PEERS, "peers.cfg"), mAuthMgr(am), mDhtMgr(NULL), mUpnpMgr(NULL), mNetStatus(RS_NET_UNKNOWN), @@ -91,8 +89,10 @@ peerConnectState::peerConnectState() netMode(RS_NET_MODE_UNKNOWN), visState(RS_VIS_STATE_STD), source(0), inConnAttempt(0), connAttemptTS(0), - lc_timestamp(0), lr_timestamp(0), - nc_timestamp(0), nc_timeintvl(0) + lastcontact(0) + + //lc_timestamp(0), lr_timestamp(0), + //nc_timestamp(0), nc_timeintvl(0) { lastaddr.sin_family = AF_INET; lastaddr.sin_addr.s_addr = 0; @@ -212,7 +212,7 @@ void p3ConnectMgr::netTick() { #ifdef CONN_DEBUG - std::cerr << "p3ConnectMgr::netTick()" << std::endl; + //std::cerr << "p3ConnectMgr::netTick()" << std::endl; #endif connMtx.lock(); /* LOCK MUTEX */ @@ -258,7 +258,7 @@ void p3ConnectMgr::netTick() case RS_NET_DONE: #ifdef CONN_DEBUG - std::cerr << "p3ConnectMgr::netTick() STATUS: DONE" << std::endl; + //std::cerr << "p3ConnectMgr::netTick() STATUS: DONE" << std::endl; #endif default: break; @@ -830,7 +830,7 @@ void p3ConnectMgr::getOnlineList(std::list &peers) connMtx.unlock(); /* UNLOCK MUTEX */ for(it = mFriendList.begin(); it != mFriendList.end(); it++) { - if (it->second.state & RS_PEER_S_ONLINE) + if (it->second.state & RS_PEER_S_CONNECTED) { peers.push_back(it->first); } @@ -923,12 +923,13 @@ bool p3ConnectMgr::connectResult(std::string id, bool success, uint32_t flags) it->second.connAddrs.clear(); mDhtMgr->dropPeer(id); - /* update address */ + /* update address (will come through from DISC) */ /* change state */ it->second.state |= RS_PEER_S_CONNECTED; it->second.actions |= RS_PEER_CONNECTED; mStatusChanged = true; + it->second.lastcontact = time(NULL); /* time of connect */ return true; } @@ -939,6 +940,8 @@ bool p3ConnectMgr::connectResult(std::string id, bool success, uint32_t flags) it->second.state ^= RS_PEER_S_CONNECTED; it->second.actions |= RS_PEER_DISCONNECTED; + it->second.lastcontact = time(NULL); /* time of disconnect */ + mDhtMgr->findPeer(id); if (it->second.visState & RS_VIS_STATE_NODHT) { @@ -973,7 +976,7 @@ bool p3ConnectMgr::connectResult(std::string id, bool success, uint32_t flags) void p3ConnectMgr::peerStatus(std::string id, struct sockaddr_in laddr, struct sockaddr_in raddr, - uint32_t type, uint32_t mode, uint32_t source) + uint32_t type, uint32_t flags, uint32_t source) { std::cerr << "p3ConnectMgr::peerStatus()"; std::cerr << " id: " << id; @@ -982,7 +985,7 @@ void p3ConnectMgr::peerStatus(std::string id, std::cerr << " raddr: " << inet_ntoa(raddr.sin_addr); std::cerr << " rport: " << ntohs(raddr.sin_port); std::cerr << " type: " << type; - std::cerr << " mode: " << mode; + std::cerr << " flags: " << flags; std::cerr << " source: " << source; std::cerr << std::endl; @@ -1027,6 +1030,9 @@ void p3ConnectMgr::peerStatus(std::string id, */ it->second.source = RS_CB_DHT; it->second.dht = details; + + /* If we get a info -> then they are online */ + it->second.state |= RS_PEER_S_ONLINE; } else if (source == RS_CB_DISC) { @@ -1036,16 +1042,62 @@ void p3ConnectMgr::peerStatus(std::string id, */ it->second.source = RS_CB_DISC; it->second.disc = details; + + if (flags & RS_NET_FLAGS_ONLINE) + { + it->second.actions |= RS_PEER_ONLINE; + it->second.state |= RS_PEER_S_ONLINE; + mStatusChanged = true; + } + + /* not updating VIS status??? */ } else if (source == RS_CB_PERSON) { /* PERSON can tell us about * 1) online / offline * 2) connect address + * -> update all! */ it->second.source = RS_CB_PERSON; it->second.peer = details; + + it->second.localaddr = laddr; + it->second.serveraddr = raddr; + it->second.state |= RS_PEER_S_ONLINE; + + /* must be online to recv info (should be connected too!) + * but no need for action as should be connected already + */ + + if (flags & RS_NET_FLAGS_EXTERNAL_ADDR) + { + it->second.netMode = RS_NET_MODE_EXT; + } + else + { + it->second.netMode = RS_NET_MODE_UDP; + } + + /* always update VIS status */ + if (flags & RS_NET_FLAGS_USE_DISC) + { + it->second.visState &= (~RS_VIS_STATE_NODISC); + } + else + { + it->second.visState |= RS_VIS_STATE_NODISC; + } + + if (flags & RS_NET_FLAGS_USE_DHT) + { + it->second.visState &= (~RS_VIS_STATE_NODHT); + } + else + { + it->second.visState |= RS_VIS_STATE_NODHT; + } } if (!isFriend) diff --git a/libretroshare/src/pqi/p3connmgr.h b/libretroshare/src/pqi/p3connmgr.h index 71ad01a9e..233e3f8d5 100644 --- a/libretroshare/src/pqi/p3connmgr.h +++ b/libretroshare/src/pqi/p3connmgr.h @@ -59,6 +59,12 @@ const uint32_t RS_NET_CONN_TCP_EXTERNAL = 0x0002; const uint32_t RS_NET_CONN_UDP_DHT_SYNC = 0x0010; +/* flags of peerStatus */ +const uint32_t RS_NET_FLAGS_USE_DISC = 0x0001; +const uint32_t RS_NET_FLAGS_USE_DHT = 0x0002; +const uint32_t RS_NET_FLAGS_ONLINE = 0x0004; +const uint32_t RS_NET_FLAGS_EXTERNAL_ADDR = 0x0008; + class peerAddrInfo { public: @@ -119,15 +125,15 @@ class peerConnectState peerConnectAddress currentConnAddr; std::list connAddrs; + time_t lastcontact; /* stuff here un-used at the moment */ + //time_t c_timestamp; // last connect timestamp + //time_t lr_timestamp; // last receive timestamp - time_t lc_timestamp; // last connect timestamp - time_t lr_timestamp; // last receive timestamp - - time_t nc_timestamp; // next connect timestamp. - time_t nc_timeintvl; // next connect time interval. + //time_t nc_timestamp; // next connect timestamp. + //time_t nc_timeintvl; // next connect time interval. }; @@ -182,7 +188,7 @@ void removeMonitor(pqiMonitor *mon); /******* overloaded from pqiConnectCb *************/ virtual void peerStatus(std::string id, struct sockaddr_in laddr, struct sockaddr_in raddr, - uint32_t type, uint32_t mode, uint32_t source); + uint32_t type, uint32_t flags, uint32_t source); virtual void peerConnectRequest(std::string id, uint32_t type); virtual void stunStatus(std::string id, struct sockaddr_in addr, uint32_t flags); diff --git a/libretroshare/src/pqi/pqimonitor.h b/libretroshare/src/pqi/pqimonitor.h index 0b5036282..1156720ee 100644 --- a/libretroshare/src/pqi/pqimonitor.h +++ b/libretroshare/src/pqi/pqimonitor.h @@ -44,15 +44,16 @@ const uint32_t RS_PEER_ACTION_MASK = 0xff00; /* STATE */ const uint32_t RS_PEER_S_FRIEND = 0x0001; -const uint32_t RS_PEER_S_ONLINE = 0x0002; -const uint32_t RS_PEER_S_CONNECTED = 0x0004; /* heard from recently..*/ +const uint32_t RS_PEER_S_ONLINE = 0x0002; /* heard from recently..*/ +const uint32_t RS_PEER_S_CONNECTED = 0x0004; /* ACTIONS */ const uint32_t RS_PEER_NEW = 0x0001; /* new Peer */ const uint32_t RS_PEER_MOVED = 0x0002; /* moved from F->O or O->F */ -const uint32_t RS_PEER_CONNECTED = 0x0004; -const uint32_t RS_PEER_DISCONNECTED = 0x0008; -const uint32_t RS_PEER_CONNECT_REQ = 0x0010; +const uint32_t RS_PEER_ONLINE = 0x0004; +const uint32_t RS_PEER_CONNECTED = 0x0008; +const uint32_t RS_PEER_DISCONNECTED = 0x0010; +const uint32_t RS_PEER_CONNECT_REQ = 0x0020; /* Stun Status Flags */ //const uint32_t RS_STUN_SRC_DHT = 0x0001; @@ -105,7 +106,7 @@ class pqiConnectCb virtual ~pqiConnectCb() { return; } virtual void peerStatus(std::string id, struct sockaddr_in laddr, struct sockaddr_in raddr, - uint32_t type, uint32_t mode, uint32_t source) = 0; + uint32_t type, uint32_t flags, uint32_t source) = 0; virtual void peerConnectRequest(std::string id, uint32_t type) = 0; diff --git a/libretroshare/src/rsserver/Makefile b/libretroshare/src/rsserver/Makefile index 33de70111..0e23b8ba5 100644 --- a/libretroshare/src/rsserver/Makefile +++ b/libretroshare/src/rsserver/Makefile @@ -14,7 +14,8 @@ RSOBJ = p3face-file.o \ p3face-startup.o \ rstypes.o \ rsiface.o \ - p3peers.o + p3peers.o \ + p3rank.o # pqistrings.o \ # p3face-people.o diff --git a/libretroshare/src/rsserver/p3face-startup.cc b/libretroshare/src/rsserver/p3face-startup.cc index dea9ad601..e92311749 100644 --- a/libretroshare/src/rsserver/p3face-startup.cc +++ b/libretroshare/src/rsserver/p3face-startup.cc @@ -39,10 +39,11 @@ #include "dht/opendhtmgr.h" // Removed temporarily... -//#include "services/p3disc.h" +#include "services/p3disc.h" #include "services/p3msgservice.h" #include "services/p3chatservice.h" #include "services/p3gamelauncher.h" +#include "services/p3ranking.h" #include #include @@ -54,6 +55,7 @@ #include "pqi/pqidebug.h" #include "rsserver/p3face.h" #include "rsserver/p3peers.h" +#include "rsserver/p3rank.h" #include "rsiface/rsgame.h" /**************** PQI_USE_XPGP ******************/ @@ -602,18 +604,23 @@ int RsServer::StartupRetroShare(RsInit *config) //server->load_config(); /* create Services */ - //ad = new p3disc(sslr); // XXX + ad = new p3disc(mAuthMgr, mConnMgr); msgSrv = new p3MsgService(mConnMgr); chatSrv = new p3ChatService(mConnMgr); p3GameLauncher *gameLauncher = new p3GameLauncher(); + p3Ranking *ranking = new p3Ranking(0, NULL, "", "", 3600 * 24 * 30); - //pqih -> addService(ad); + pqih -> addService(ad); pqih -> addService(msgSrv); pqih -> addService(chatSrv); pqih -> addService(gameLauncher); + /* so need to Monitor too! */ + mConnMgr->addMonitor(ad); + /* setup the gui */ rsGameLauncher = gameLauncher; + rsRanks = new p3Rank(ranking); /* put a welcome message in! */ if (config->firsttime_run) diff --git a/libretroshare/src/rsserver/p3rank.cc b/libretroshare/src/rsserver/p3rank.cc new file mode 100644 index 000000000..d083cd638 --- /dev/null +++ b/libretroshare/src/rsserver/p3rank.cc @@ -0,0 +1,95 @@ +/* + * libretroshare/src/rsserver: p3rank.cc + * + * RetroShare C++ Interface. + * + * Copyright 2007-2008 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 "rsserver/p3rank.h" + +RsRanks *rsRanks = NULL; + +p3Rank::p3Rank(p3Ranking *ranking) + :mRank(ranking) +{ + return; +} + +p3Rank::~p3Rank() +{ + return; +} + + /* Set Sort Methods */ +bool p3Rank::setSortPeriod(uint32_t period) +{ + return mRank->setSortPeriod(period); +} + +bool p3Rank::setSortMethod(uint32_t type) +{ + return mRank->setSortMethod(type); +} + +bool p3Rank::clearPeerFilter() +{ + return mRank->clearPeerFilter(); +} + +bool p3Rank::setPeerFilter(std::list peers) +{ + return mRank->setPeerFilter(peers); +} + + /* get Ids */ +uint32_t p3Rank::getRankingsCount() +{ + return mRank->getRankingsCount(); +} + +float p3Rank::getMaxRank() +{ + return mRank->getMaxRank(); +} + +bool p3Rank::getRankings(uint32_t first, uint32_t count, std::list &rids) +{ + return mRank->getRankings(first, count, rids); +} + +bool p3Rank::getRankDetails(std::string rid, RsRankDetails &details) +{ + return mRank->getRankDetails(rid, details); +} + + + /* Add New Comment / Msg */ +std::string p3Rank::newRankMsg(std::wstring link, std::wstring title, std::wstring comment) +{ + return mRank->newRankMsg(link, title, comment); +} + +bool p3Rank::updateComment(std::string rid, std::wstring comment) +{ + return mRank->updateComment(rid, comment); +} + + diff --git a/libretroshare/src/rsserver/p3rank.h b/libretroshare/src/rsserver/p3rank.h new file mode 100644 index 000000000..1eaee8977 --- /dev/null +++ b/libretroshare/src/rsserver/p3rank.h @@ -0,0 +1,60 @@ +#ifndef RETROSHARE_P3_RANKING_INTERFACE_H +#define RETROSHARE_P3_RANKING_INTERFACE_H + +/* + * libretroshare/src/rsserver: p3rank.h + * + * RetroShare C++ Interface. + * + * Copyright 2007-2008 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 "rsiface/rsrank.h" +#include "services/p3ranking.h" + +class p3Rank: public RsRanks +{ + public: + + p3Rank(p3Ranking *ranking); +virtual ~p3Rank(); + + /* Set Sort Methods */ +virtual bool setSortPeriod(uint32_t period); +virtual bool setSortMethod(uint32_t type); +virtual bool clearPeerFilter(); +virtual bool setPeerFilter(std::list peers); + + /* get Ids */ +virtual uint32_t getRankingsCount(); +virtual float getMaxRank(); +virtual bool getRankings(uint32_t first, uint32_t count, std::list &rids); +virtual bool getRankDetails(std::string rid, RsRankDetails &details); + + /* Add New Comment / Msg */ +virtual std::string newRankMsg(std::wstring link, std::wstring title, std::wstring comment); +virtual bool updateComment(std::string rid, std::wstring comment); + + private: + + p3Ranking *mRank; +}; + +#endif diff --git a/libretroshare/src/scripts/config.mk b/libretroshare/src/scripts/config.mk index e7d11205f..9f22fa363 100644 --- a/libretroshare/src/scripts/config.mk +++ b/libretroshare/src/scripts/config.mk @@ -4,8 +4,8 @@ ########################################################################### #Define OS. # -#OS = Linux -OS = MacOSX +OS = Linux +#OS = MacOSX #OS = Cygwin #OS = Win # MinGw. ########################################################################### diff --git a/libretroshare/src/serialiser/rsdiscitems.cc b/libretroshare/src/serialiser/rsdiscitems.cc index 4356ba8ed..c02b7301c 100644 --- a/libretroshare/src/serialiser/rsdiscitems.cc +++ b/libretroshare/src/serialiser/rsdiscitems.cc @@ -113,8 +113,7 @@ void RsDiscItem::clear() { memset(&laddr, 0, sizeof(laddr)); memset(&saddr, 0, sizeof(laddr)); - connect_tr = 0; - receive_tr = 0; + contact_tf = 0; discFlags = 0; } @@ -132,8 +131,8 @@ std::ostream &RsDiscItem::print(std::ostream &out, uint16_t indent) out << " Port: " << ntohs(saddr.sin_port) << std::endl; printIndent(out, int_Indent); - out << "C/R Tr: " << connect_tr; - out << " / " << receive_tr << std::endl; + out << "Contact TimeFrame: " << contact_tf; + out << std::endl; printIndent(out, int_Indent); out << "DiscFlags: " << discFlags << std::endl; @@ -148,8 +147,7 @@ uint32_t RsDiscSerialiser::sizeItem(RsDiscItem *item) uint32_t s = 8; /* header */ s += GetTlvIpAddrPortV4Size(); /* laddr */ s += GetTlvIpAddrPortV4Size(); /* saddr */ - s += 2; /* connect_tr */ - s += 2; /* receive_tr */ + s += 2; /* contact_tf */ s += 4; /* discFlags */ return s; @@ -183,10 +181,8 @@ bool RsDiscSerialiser::serialiseItem(RsDiscItem *item, void *data, uint32_t ok &= SetTlvIpAddrPortV4(data, tlvsize, &offset, TLV_TYPE_IPV4_SERVER, &(item->saddr)); std::cerr << "RsDiscSerialiser::serialiseItem() saddress: " << ok << std::endl; - ok &= setRawUInt16(data, tlvsize, &offset, item->connect_tr); - std::cerr << "RsDiscSerialiser::serialiseItem() connect_tr: " << ok << std::endl; - ok &= setRawUInt16(data, tlvsize, &offset, item->receive_tr); - std::cerr << "RsDiscSerialiser::serialiseItem() receive_tr: " << ok << std::endl; + ok &= setRawUInt16(data, tlvsize, &offset, item->contact_tf); + std::cerr << "RsDiscSerialiser::serialiseItem() contact_tf: " << ok << std::endl; ok &= setRawUInt32(data, tlvsize, &offset, item->discFlags); std::cerr << "RsDiscSerialiser::serialiseItem() discFlags: " << ok << std::endl; @@ -241,10 +237,8 @@ RsDiscItem *RsDiscSerialiser::deserialiseItem(void *data, uint32_t *pktsize) ok &= GetTlvIpAddrPortV4(data, rssize, &offset, TLV_TYPE_IPV4_SERVER, &(item->saddr)); std::cerr << "RsDiscSerialiser::deserialiseItem() saddress: " << ok << std::endl; - ok &= getRawUInt16(data, rssize, &offset, &(item->connect_tr)); - std::cerr << "RsDiscSerialiser::deserialiseItem() connect_tr: " << ok << std::endl; - ok &= getRawUInt16(data, rssize, &offset, &(item->receive_tr)); - std::cerr << "RsDiscSerialiser::deserialiseItem() receive_tr: " << ok << std::endl; + ok &= getRawUInt16(data, rssize, &offset, &(item->contact_tf)); + std::cerr << "RsDiscSerialiser::deserialiseItem() contact_tf: " << ok << std::endl; ok &= getRawUInt32(data, rssize, &offset, &(item->discFlags)); std::cerr << "RsDiscSerialiser::deserialiseItem() discFlags: " << ok << std::endl; @@ -279,9 +273,9 @@ void RsDiscReply::clear() { memset(&laddr, 0, sizeof(laddr)); memset(&saddr, 0, sizeof(laddr)); - connect_tr = 0; - receive_tr = 0; + contact_tf = 0; discFlags = 0; + aboutId.clear(); certDER.TlvClear(); } @@ -299,12 +293,14 @@ std::ostream &RsDiscReply::print(std::ostream &out, uint16_t indent) out << " Port: " << ntohs(saddr.sin_port) << std::endl; printIndent(out, int_Indent); - out << "C/R Tr: " << connect_tr; - out << " / " << receive_tr << std::endl; + out << "Contact TimeFrame: " << contact_tf; + out << std::endl; printIndent(out, int_Indent); out << "DiscFlags: " << discFlags << std::endl; + printIndent(out, int_Indent); + out << "AboutId: " << aboutId << std::endl; certDER.print(out, int_Indent); printRsItemEnd(out, "RsDiscReply", indent); @@ -318,8 +314,8 @@ uint32_t RsDiscSerialiser::sizeReply(RsDiscReply *item) s += GetTlvIpAddrPortV4Size(); /* laddr */ s += GetTlvIpAddrPortV4Size(); /* saddr */ s += 2; /* connect_tr */ - s += 2; /* receive_tr */ s += 4; /* discFlags */ + s += GetTlvStringSize(item->aboutId); s += item->certDER.TlvSize(); return s; @@ -353,13 +349,15 @@ bool RsDiscSerialiser::serialiseReply(RsDiscReply *item, void *data, uint32_ ok &= SetTlvIpAddrPortV4(data, tlvsize, &offset, TLV_TYPE_IPV4_SERVER, &(item->saddr)); std::cerr << "RsDiscSerialiser::serialiseReply() saddress: " << ok << std::endl; - ok &= setRawUInt16(data, tlvsize, &offset, item->connect_tr); - std::cerr << "RsDiscSerialiser::serialiseReply() connect_tr: " << ok << std::endl; - ok &= setRawUInt16(data, tlvsize, &offset, item->receive_tr); - std::cerr << "RsDiscSerialiser::serialiseReply() receive_tr: " << ok << std::endl; + ok &= setRawUInt16(data, tlvsize, &offset, item->contact_tf); + std::cerr << "RsDiscSerialiser::serialiseReply() contact_tf: " << ok << std::endl; ok &= setRawUInt32(data, tlvsize, &offset, item->discFlags); std::cerr << "RsDiscSerialiser::serialiseReply() discFlags: " << ok << std::endl; + ok &= SetTlvString(data, tlvsize, &offset, + TLV_TYPE_STR_PEERID, item->aboutId); + std::cerr << "RsDiscSerialiser::serialiseReply() aboutId: " << ok << std::endl; + ok &= item->certDER.SetTlv(data, tlvsize, &offset); std::cerr << "RsDiscSerialiser::serialiseReply() discFlags: " << ok << std::endl; @@ -414,12 +412,14 @@ RsDiscReply *RsDiscSerialiser::deserialiseReply(void *data, uint32_t *pktsize) ok &= GetTlvIpAddrPortV4(data, rssize, &offset, TLV_TYPE_IPV4_SERVER, &(item->saddr)); std::cerr << "RsDiscSerialiser::deserialiseReply() saddress: " << ok << std::endl; - ok &= getRawUInt16(data, rssize, &offset, &(item->connect_tr)); - std::cerr << "RsDiscSerialiser::deserialiseReply() connect_tr: " << ok << std::endl; - ok &= getRawUInt16(data, rssize, &offset, &(item->receive_tr)); - std::cerr << "RsDiscSerialiser::deserialiseReply() receive_tr: " << ok << std::endl; + ok &= getRawUInt16(data, rssize, &offset, &(item->contact_tf)); + std::cerr << "RsDiscSerialiser::deserialiseReply() contact_tf: " << ok << std::endl; ok &= getRawUInt32(data, rssize, &offset, &(item->discFlags)); std::cerr << "RsDiscSerialiser::deserialiseReply() discFlags: " << ok << std::endl; + + ok &= GetTlvString(data, rssize, &offset, + TLV_TYPE_STR_PEERID, item->aboutId); + std::cerr << "RsDiscSerialiser::deserialiseReply() aboutId: " << ok << std::endl; ok &= item->certDER.GetTlv(data, rssize, &offset); std::cerr << "RsDiscSerialiser::deserialiseReply() certDER: " << ok << std::endl; diff --git a/libretroshare/src/serialiser/rsdiscitems.h b/libretroshare/src/serialiser/rsdiscitems.h index 5d415cf60..a5f19137b 100644 --- a/libretroshare/src/serialiser/rsdiscitems.h +++ b/libretroshare/src/serialiser/rsdiscitems.h @@ -60,8 +60,7 @@ virtual std::ostream &print(std::ostream &out, uint16_t indent = 0); struct sockaddr_in saddr; // time frame of recent connections. - uint16_t connect_tr; - uint16_t receive_tr; + uint16_t contact_tf; // flags... uint32_t discFlags; }; @@ -80,6 +79,7 @@ virtual ~RsDiscReply(); virtual void clear(); virtual std::ostream &print(std::ostream &out, uint16_t indent = 0); + std::string aboutId; RsTlvBinaryData certDER; }; diff --git a/libretroshare/src/services/Makefile b/libretroshare/src/services/Makefile index e8bb7a8a0..5ebe228da 100644 --- a/libretroshare/src/services/Makefile +++ b/libretroshare/src/services/Makefile @@ -7,8 +7,8 @@ RS_TOP_DIR = .. include $(RS_TOP_DIR)/scripts/config.mk ############################################################### -RSOBJ = p3service.o p3chatservice.o p3msgservice.o p3gamelauncher.o -#p3disc.o +RSOBJ = p3service.o p3chatservice.o p3msgservice.o \ + p3gamelauncher.o p3ranking.o p3disc.o #TESTOBJ = diff --git a/libretroshare/src/services/p3disc.cc b/libretroshare/src/services/p3disc.cc index a3e7ee753..a5cd07ad6 100644 --- a/libretroshare/src/services/p3disc.cc +++ b/libretroshare/src/services/p3disc.cc @@ -41,903 +41,77 @@ const uint32_t AUTODISC_LDI_SUBTYPE_RPLY = 0x02; const int pqidisczone = 2482; - -static int updateAutoServer(autoserver *as, RsDiscItem *di); static int convertTDeltaToTRange(double tdelta); static int convertTRangeToTDelta(int trange); -static int updateCertAvailabilityFlags(cert *c, unsigned long discFlags); -static unsigned long determineCertAvailabilityFlags(cert *c); // Operating System specific includes. #include "pqi/pqinetwork.h" +/* DISC FLAGS */ + +const uint32_t P3DISC_FLAGS_USE_DISC = 0x0001; +const uint32_t P3DISC_FLAGS_USE_DHT = 0x0002; +const uint32_t P3DISC_FLAGS_EXTERNAL_ADDR = 0x0004; +const uint32_t P3DISC_FLAGS_PEER_ONLINE = 0x0008; +const uint32_t P3DISC_FLAGS_OWN_DETAILS = 0x0010; + + +#define P3DISC_DEBUG 1 + +/****************************************************************************************** + ****************************** NEW DISCOVERY ******************************************* + ****************************************************************************************** + *****************************************************************************************/ + p3disc::p3disc(p3AuthMgr *am, p3ConnectMgr *cm) :p3Service(RS_SERVICE_TYPE_DISC), mAuthMgr(am), mConnMgr(cm) { addSerialType(new RsDiscSerialiser()); - ldata = NULL; - ldlenmax = 1024; - - local_disc = false; //true; - remote_disc = true; - - // set last check to current time, this prevents queued. - // messages at the start! (actually shouldn't matter - as they aren't connected). - ts_lastcheck = time(NULL); // 0; - - // configure... - load_configuration(); - localSetup(); - - return; -} - -p3disc::~p3disc() -{ + mRemoteDisc = true; + mLocalDisc = false; return; } int p3disc::tick() { - pqioutput(PQL_DEBUG_ALL, pqidisczone, - "p3disc::tick()"); - if (local_disc) - { - if (ts_nextlp == 0) - { - pqioutput(PQL_DEBUG_ALL, pqidisczone, - "Local Discovery On!"); - localPing(baddr); - localListen(); - } - } - else - { - pqioutput(PQL_DEBUG_ALL, pqidisczone, - "Local Discovery Off!"); - } - - // ten minute counter. - if (--ts_nextlp < 0) - { - ts_nextlp = 600; - } +#ifdef P3DISC_DEBUG - if (ts_nextlp % 300 == 0) +static int count = 0; + + if (++count % 10 == 0) + { idServers(); - - - /* remote discovery can run infrequently.... - * this is a good idea, as it ensures that - * multiple Pings aren't sent to neighbours.... - * - * only run every 5 seconds. - */ - - if (ts_nextlp % 5 != 0) - { - return 1; } - - // important bit - int nr = handleReplies(); // discards packets if not running. - if (remote_disc) - { - pqioutput(PQL_DEBUG_ALL, pqidisczone, - "Remote Discovery On!"); - newRequests(); - if ((sroot -> collectedCerts()) || (nr > 0)) - { - distillData(); - } - } - else - { - pqioutput(PQL_DEBUG_ALL, pqidisczone, - "Remote Discovery Off!"); - } - return 1; -} - -static int local_disc_def_port = 7770; -static int local_disc_secondary_port = 7870; - -int p3disc::setLocalAddress(struct sockaddr_in srvaddr) -{ - saddr = srvaddr; - return 1; -} - - -int p3disc::determineLocalNetAddr() -{ - // laddr filled in by load_configuration. - laddr.sin_port = htons(local_disc_def_port); - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - // broadcast address. - baddr.sin_family = AF_INET; - inet_aton("0.0.0.0", &(baddr.sin_addr)); - baddr.sin_port = htons(local_disc_def_port); -#else // WIN - - baddr. sin_family = AF_INET; - - // So as recommended on this site.. will use |+& to calc it. - unsigned long netmask = inet_addr("255.255.255.0"); - unsigned long netaddr = saddr.sin_addr.s_addr & netmask; - baddr.sin_addr.s_addr = netaddr | (~netmask); - - // direct works! - //baddr.sin_addr.s_addr = inet_addr("10.0.0.59"); - //baddr.sin_addr.s_addr = inet_addr("127.0.0.1"); - // broadcast! - baddr.sin_addr.s_addr = INADDR_BROADCAST; - baddr.sin_port = htons(local_disc_def_port); - - - - - #endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - { - std::ostringstream out; - out << "p3disc::determineLocalNetAddr() baddr: "; - out << inet_ntoa(baddr.sin_addr) << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); - } - - return 1; + return handleIncoming(); } -int p3disc::setupLocalPacket(int type, struct sockaddr_in *home, - struct sockaddr_in *server) -{ - if (ldata == NULL) - { - ldata = malloc(ldlenmax); - } - - // setup packet. - // 8 bytes - tag - ((char *) ldata)[0] = 'P'; - ((char *) ldata)[1] = 'Q'; - ((char *) ldata)[2] = 'I'; - ((char *) ldata)[3] = 'L'; - if (type == AUTODISC_LDI_SUBTYPE_PING) - { - ((char *) ldata)[4] = 'D'; - ((char *) ldata)[5] = 'I'; - ((char *) ldata)[6] = 'S'; - ((char *) ldata)[7] = 'C'; - } - else - { - ((char *) ldata)[4] = 'R'; - ((char *) ldata)[5] = 'P'; - ((char *) ldata)[6] = 'L'; - ((char *) ldata)[7] = 'Y'; - } - - // sockaddr copy. - ldlen = 8; - for(unsigned int i = 0; i < sizeof(*home); i++) - { - ((char *) ldata)[ldlen + i] = ((char *) home)[i]; - } - - ldlen += sizeof(*home); - for(unsigned int i = 0; i < sizeof(*server); i++) - { - ((char *) ldata)[ldlen + i] = ((char *) server)[i]; - } - ldlen += sizeof(*server); - - return 1; -} - - - - - -int p3disc::localSetup() -{ - - if (!local_disc) - { - pqioutput(PQL_DEBUG_BASIC, pqidisczone, - "p3disc::localSetup() Warning local_disc OFF!"); - return -1; - } - - //First we must attempt to open the default socket - determineLocalNetAddr(); - - int err = 0; - - lsock = socket(PF_INET, SOCK_DGRAM, 0); -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - - if (lsock < 0) - { - pqioutput(PQL_DEBUG_BASIC, pqidisczone, - "p3disc::localSetup() Cannot open UDP socket!"); - local_disc = false; - return -1; - } - - err = fcntl(lsock, F_SETFL, O_NONBLOCK); - if (err < 0) - { - pqioutput(PQL_DEBUG_BASIC, pqidisczone, - "p3disc::localSetup() Error: Cannot make socket NON-Blocking: "); - - local_disc = false; - return -1; - } - - int on = 1; - if(0 != (err =setsockopt(lsock, SOL_SOCKET, SO_BROADCAST,(void *) &on, sizeof(on)))) - { - pqioutput(PQL_DEBUG_BASIC, pqidisczone, - "p3disc::localSetup() Error: Cannot make socket Broadcast: "); - local_disc = false; - return -1; - } - else - { - pqioutput(PQL_DEBUG_BASIC, pqidisczone, - "p3disc::localSetup() Broadcast Flag Set!"); - } - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#else //WINDOWS_SYS - - if (lsock == INVALID_SOCKET) - { - pqioutput(PQL_DEBUG_BASIC, pqidisczone, - "p3disc::localSetup() Cannot open UDP socket!"); - local_disc = false; - return -1; - } - - unsigned long int on = 1; - if (0 != (err = ioctlsocket(lsock, FIONBIO, &on))) - { - pqioutput(PQL_DEBUG_BASIC, pqidisczone, - "p3disc::localSetup() Error: Cannot make socket NON-Blocking: "); - local_disc = false; - return -1; - } - - on = 1; - if(0 != (err=setsockopt(lsock, SOL_SOCKET, SO_BROADCAST,(char *) &on, sizeof(on)))) - { - pqioutput(PQL_DEBUG_BASIC, pqidisczone, - "p3disc::localSetup() Error: Cannot make socket Broadcast: "); - - local_disc = false; - return -1; - } - else - { - pqioutput(PQL_DEBUG_BASIC, pqidisczone, - "p3disc::localSetup() Broadcast Flag Set!"); - } - -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - { - std::ostringstream out; - out << "p3disc::localSetup()" << std::endl; - out << "\tSetup Family: " << laddr.sin_family; - out << std::endl; - out << "\tSetup Address: " << inet_ntoa(laddr.sin_addr); - out << std::endl; - out << "\tSetup Port: " << ntohs(laddr.sin_port) << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); - } - - if (0 != (err = bind(lsock, (struct sockaddr *) &laddr, sizeof(laddr)))) - { - std::ostringstream out; - out << "p3disc::localSetup()"; - out << " Cannot Bind to Default Address!" << std::endl; - showSocketError(out); - out << std::endl; - out << " Trying Secondary Address." << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); - - } - else - { - // ifsucessful then call localPing - // set ts to -1 and don't worry about outgoing until - // we receive a packet - std::ostringstream out; - out << "p3disc::localSetup()" << std::endl; - out << " Bound to Address." << std::endl; - out << "\tSetup Address: " << inet_ntoa(laddr.sin_addr); - out << std::endl; - out << "\tSetup Port: " << ntohs(laddr.sin_port) << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); - - ts_nextlp = -1; - ts_nextlp = 10; - localPing(baddr); - return 1; - } - - laddr.sin_port = htons(local_disc_secondary_port); - if (0 != (err = bind(lsock, (struct sockaddr *) &laddr, sizeof(laddr)))) - { - std::ostringstream out; - out << "p3disc::localSetup()"; - out << " Cannot Bind to Secondary Address!" << std::endl; - showSocketError(out); - out << std::endl; - out << " Giving Up!" << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); - local_disc = false; - return -1; - } - else - { - std::ostringstream out; - out << "p3disc::localSetup()" << std::endl; - out << " Bound to Secondary Address." << std::endl; - out << "\tSetup Address: " << inet_ntoa(laddr.sin_addr); - out << std::endl; - out << "\tSetup Port: " << ntohs(laddr.sin_port) << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); - - ts_nextlp = 10; - localPing(baddr); - return 1; - } - - // else we open a random port and set the timer - // ie - don't bind to a port..... - ts_nextlp = 10; // ping every 10 minutes. - localPing(baddr); - return 1; -} - -int p3disc::localPing(struct sockaddr_in reply_to) -{ - //This function sends a meessage out containing both cert - // and server address, as well as the ping address (if not standard) - - // so we send a packet out to that address - // (most likely broadcast address). - - // setup up the data for connection. - setupLocalPacket(AUTODISC_LDI_SUBTYPE_PING,&laddr, &saddr); - - // Cast to char for windows benefit. - int len = sendto(lsock, (char *) ldata, ldlen, 0, (struct sockaddr *) &reply_to, sizeof(reply_to)); - if (len != ldlen) - { - std::ostringstream out; - out << "p3disc::localPing()"; - out << " Failed to send Packet." << std::endl; - out << "Sent (" << len << "/" << ldlen; - out << std::endl; - out << "Addr:" << inet_ntoa(reply_to.sin_addr) << std::endl; - out << "Port:" << ntohs(reply_to.sin_port) << std::endl; - out << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); - } - else - { - std::ostringstream out; - out << "p3disc::localPing() Success!" << std::endl; - out << "Sent To Addr:" << inet_ntoa(reply_to.sin_addr) << std::endl; - out << "Sent To Port:" << ntohs(reply_to.sin_port) << std::endl; - out << "Message Size: " << len << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); - } - return 1; -} - -int p3disc::localReply(struct sockaddr_in reply_to) -{ - //This function sends a meessage out containing both cert - // and server address, as well as the ping address (if not standard) - - // so we send a packet out to that address - // (most likely broadcast address). - - // setup up the data for connection. - setupLocalPacket(AUTODISC_LDI_SUBTYPE_RPLY,&laddr, &saddr); - - // Cast to char for windows benefit. - int len = sendto(lsock, (char *) ldata, ldlen, 0, (struct sockaddr *) &reply_to, sizeof(reply_to)); - if (len != ldlen) - { - std::ostringstream out; - out << "p3disc::localPing()"; - out << " Failed to send Packet." << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); - } - - return 1; -} - - -int p3disc::localListen() -{ - //This function listens to the ping address. - //For each reply, store the result in the structure and mark as local - struct sockaddr_in addr; - struct sockaddr_in neighbour; - struct sockaddr_in server; - socklen_t alen = sizeof(addr); - int nlen = sizeof(neighbour); - int len; - int size = 0; - - while(0 < (size = recvfrom(lsock, (char *) ldata, ldlen, 0, - (struct sockaddr *) &addr, &alen))) - { - std::ostringstream out; - out << "Recved Message" << std::endl; - out << "From Addr:" << inet_ntoa(addr.sin_addr) << std::endl; - out << "From Port:" << ntohs(addr.sin_port) << std::endl; - out << "Message Size: " << size << std::endl; - - for(int i = 0; i < 8; i++) - { - out << ((char *) ldata)[i]; - } - out << std::endl; - - len = 8; - // sockaddr copy. - for(int i = 0; i < nlen; i++) - { - ((char *) &neighbour)[i] = ((char *) ldata)[len + i]; - } - len += nlen; - for(int i = 0; i < nlen; i++) - { - ((char *) &server)[i] = ((char *) ldata)[len + i]; - } - len += nlen; - - - out << "Neighbour Addr:" << inet_ntoa(neighbour.sin_addr) << std::endl; - out << "Neighbour Port:" << ntohs(neighbour.sin_port) << std::endl; - out << "Server Addr:" << inet_ntoa(server.sin_addr) << std::endl; - out << "Server Port:" << ntohs(server.sin_port) << std::endl; - - if ((laddr.sin_addr.s_addr == neighbour.sin_addr.s_addr) && - (laddr.sin_port == neighbour.sin_port)) - { - // Then We Sent it!!!! - // ignore.. - out << "Found Self! Addr - " << inet_ntoa(neighbour.sin_addr); - out << ":" << ntohs(neighbour.sin_port) << std::endl; - } - else - { - if ('D' == (((char *) ldata)[4])) // Then Ping. - { - // reply. - localReply(neighbour); - } - - addLocalNeighbour(&neighbour, &server); - } - - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); - } - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - - if ((size < 0) && (errno != EAGAIN)) - { - std::ostringstream out; - out << "Error Recieving Message" << std::endl; - out << "Errno: " << errno << std::endl; - out << socket_errorType(errno) << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); - } - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#else // WINDOWS_SYS - - if (size == SOCKET_ERROR) - { - int err = WSAGetLastError(); - if (err != WSAEWOULDBLOCK) - { - std::ostringstream out; - out << "Error Recieving Message" << std::endl; - out << "WSE: " << err << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); - } - } - -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - return 1; -} - -// This needs to be fixed up.... -// Local dicsovery disabled for the moment.... - -int p3disc::addLocalNeighbour(struct sockaddr_in *n, struct sockaddr_in *s) -{ - std::list::iterator it; - for(it = neighbours.begin(); it != neighbours.end(); it++) - { - // if the server address matches one already! - // make sure its flags as local and return. - if (0 == memcmp((char *) &((*it) -> server_addr), (char *) s, sizeof(*s))) - { - (*it) -> local = true; - return 1; - } - } - // else add it in! - autoneighbour *ln = new autoneighbour(); - ln -> server_addr = (*s); - ln -> local = true; - ln -> id = NULL; // null cert - - std::string nname = "Local Neighbour ("; - nname += inet_ntoa(ln -> server_addr.sin_addr); - nname += ")"; - - //ln -> id -> Name(nname); - - // now we call the dummy connect... - // this will only be done once per local neighbour. - // connectForExchange(ln -> server_addr); - - neighbours.push_back(ln); - // update dicovered. - distillData(); - return 1; -} - - -// Code Fragment that might be useful when local is patched up.... -/**************************************************** -int p3disc::distillLocalData() -{ - // This transforms the autoneighbour tree into - // a list of certificates with the best guess settings. - - discovered.clear(); - - pqioutput(PQL_DEBUG_BASIC, pqidisczone, "p3disc::distillData()"); - - std::list::iterator it; - std::list::iterator it2; - - // Now check for local -> remote duplicates.... - for(it = neighbours.begin(); it != neighbours.end();) - { - cert *c = (cert *) ((*it) -> id); - if (((*it) -> local) && (c == NULL)) - { - // potentially a duplicate. - bool found = false; - for(it2 = neighbours.begin(); it2 != neighbours.end(); it2++) - { - // if address is the same -> remove first version. - if ((it != it2) && (0 == memcmp((char *) &((*it) -> addr), - (char *) &((*it2) -> addr), - sizeof(struct sockaddr)))) - { - (*it2) -> local = true; - found = true; - } - } - if (found == true) - { - // remove the certless local. - it = neighbours.erase(it); - } - else - { - it++; - } - } - else - { - it++; - } - } - -******************************************/ - - -int p3disc::idServers() -{ - std::list::iterator it; - std::list::iterator nit; - int cts = time(NULL); - - std::ostringstream out; - out << "::::AutoDiscovery Neighbours::::" << std::endl; - for(it = neighbours.begin(); it != neighbours.end(); it++) - { - if ((*it) -> local) - { - out << "Local Neighbour: "; - } - else - { - out << "Friend of a friend: "; - } - cert *c = (cert *) ((*it) -> id); - - if (c != NULL) - { - if (c -> certificate != NULL) - { - out << c -> certificate -> name; - } - else - { - out << c -> Name(); - } - } - else - { - out << "UnIdentified"; - } - - out << std::endl; - out << "BG LocalAddr: "; - out << inet_ntoa((*it) -> local_addr.sin_addr); - out << ":" << ntohs((*it) -> local_addr.sin_port) << std::endl; - out << "BG Server: "; - out << inet_ntoa((*it) -> server_addr.sin_addr); - out << ":" << ntohs((*it) -> server_addr.sin_port) << std::endl; - out << " Listen TR: "; - if (((*it) -> listen) && ((*it) -> l_ts)) - { - out << cts - (*it) -> l_ts << " sec ago"; - } - else - { - out << "Never"; - } - out << " "; - - out << "Connect TR: "; - if (((*it) -> connect) && ((*it) -> c_ts)) - { - out << cts - (*it) -> c_ts << " sec ago"; - } - else - { - out << "Never"; - } - - if ((*it) -> active) - { - out << " Active!!!"; - } - out << std::endl; - - out << " -->DiscFlags: 0x" << std::hex << (*it)->discFlags; - out << std::dec << std::endl; - - for(nit = ((*it) -> neighbour_of).begin(); - nit != ((*it) -> neighbour_of).end(); nit++) - { - out << "\tConnected via: "; - if ((*nit) -> id != NULL) - { - out << ((*nit) ->id) -> Name() << "("; - out << inet_ntoa(((*nit) -> id) -> lastaddr.sin_addr); - out << ":" << ntohs(((*nit) -> id) -> lastaddr.sin_port); - out << ")"; - } - out << std::endl; - out << "\t\tServer: "; - out << inet_ntoa((*nit) -> server_addr.sin_addr); - out <<":"<< ntohs((*nit) -> server_addr.sin_port); - out << std::endl; - out << "\t\tLocalAddr: "; - out << inet_ntoa((*nit) -> local_addr.sin_addr); - out <<":"<< ntohs((*nit) -> local_addr.sin_port); - - out << std::endl; - if ((*nit) -> listen) - { - out << "\t\tListen TR:"; - out << cts - (*nit) -> l_ts << " sec ago"; - } - else - { - out << "\t\tNever Received!"; - } - out << std::endl; - if ((*nit) -> connect) - { - out << "\t\tConnect TR:"; - out << cts - (*nit) -> c_ts << " sec ago"; - } - else - { - out << "\t\tNever Connected!"; - } - out << std::endl; - out << "\t\tDiscFlags: 0x" << std::hex << (*nit)->discFlags; - out << std::dec << std::endl; - } - } - pqioutput(PQL_WARNING, pqidisczone, out.str()); - return 1; -} - - - - -int p3disc::newRequests() -{ - // Check the timestamp against the list of certs. - // If any are newer and currently active, then - // send out Discovery Request. - // This initiates the p3disc procedure. - - if (!remote_disc) - { - pqioutput(PQL_DEBUG_ALL, pqidisczone, - "p3disc::newRequests() Remote Discovery is turned off"); - return -1; - } - - pqioutput(PQL_DEBUG_ALL, pqidisczone, - "p3disc::newRequests() checkin for new neighbours"); - - // Perform operation on the cert list. - std::list::iterator it; - // Temp variable - std::list &certlist = sroot -> getCertList(); - - { - std::ostringstream out; - out << "Checking CertList!" << std::endl; - out << "last_check: " << ts_lastcheck; - out << " time(): " << time(NULL); - pqioutput(PQL_DEBUG_ALL, pqidisczone, out.str()); - } - - for(it = certlist.begin(); it != certlist.end(); it++) - { - { - std::ostringstream out; - out << "Cert: " << (*it) -> Name(); - out << " lc_ts: " << (*it) -> lc_timestamp; - out << " lr_ts: " << (*it) -> lr_timestamp; - pqioutput(PQL_DEBUG_ALL, pqidisczone, out.str()); - } - - // This should be Connected(), rather than Accepted(). - // should reply with all Accepted(), but only send to all connected(). - // if (((*it) -> Accepted()) && - // - // need >= to ensure that it will happen, - // about 1 in 5 chance of multiple newRequests if called every 5 secs. - // can live with this. (else switch to fractional seconds). - - if (((*it) -> Connected()) && - (((*it) -> lc_timestamp >= ts_lastcheck) - || ((*it) -> lr_timestamp >= ts_lastcheck))) - { - - // also must not have already sent message. - // (unless reconnection?) - // actually - this should occur, even if last - // exchange not complete. - // reconnect - -/***************************************************************************** - * No more need for ad_init silliness.... - * - //if (ad_init.end() == - // find(ad_init.begin(),ad_init.end(),*it)) - // infact - we need the opposite behaviour. - // remove if in the init list. - - std::list::iterator it2; - if (ad_init.end() != - (it2 = find(ad_init.begin(),ad_init.end(),*it))) - { - ad_init.erase(it2); - } - * - * - * - ****************************************************************************/ - - - { - // Then send message. - { - std::ostringstream out; - out << "p3disc::newRequests()"; - out << "Constructing a Message!" << std::endl; - out << "Sending to: " << (*it) -> Name(); - out << " lc_ts: " << (*it) -> lc_timestamp; - out << " lr_ts: " << (*it) -> lr_timestamp; - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); - } - - // Construct a message - RsDiscItem *di = new RsDiscItem(); - - // get our details..... - cert *own = sroot -> getOwnCert(); - - // Fill the message - di -> PeerId((*it) -> PeerId()); - di -> laddr = own -> localaddr; - di -> saddr = own -> serveraddr; - - // if we are firewalled..... (and no forwarding...) - // set received as impossible. - if (own -> Firewalled() && (!(own -> Forwarded()))) - di -> receive_tr = 0; /* invalid */ - else - di -> receive_tr = 1; /* zero time */ - - di -> connect_tr = 1; /* zero time */ - di -> discFlags = determineCertAvailabilityFlags(own); - - // Send off message - sendItem(di); - -/***************************************************************************** - * No more need for ad_init silliness.... - // push onto init list. - ad_init.push_back(*it); - * - ****************************************************************************/ - - // Finally we should also advertise the - // new connection to our neighbours???? - // SHOULD DO - NOT YET. - - } - } - } - ts_lastcheck = time(NULL); - return 1; -} - -int p3disc::handleReplies() +int p3disc::handleIncoming() { RsItem *item = NULL; - pqioutput(PQL_DEBUG_ALL, pqidisczone, "p3disc::handleReplies()"); + +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::handleIncoming()"; + std::cerr << std::endl; +#endif // if off discard item. - if (!remote_disc) + if (!mRemoteDisc) { while(NULL != (item = recvItem())) { +#ifdef P3DISC_DEBUG std::ostringstream out; - out << "p3disc::handleReplies()"; + out << "p3disc::handleIncoming()"; out << " Deleting - Cos RemoteDisc Off!" << std::endl; item -> print(out); - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + + std::cerr << out.str() << std::endl; +#endif delete item; } @@ -953,11 +127,15 @@ int p3disc::handleReplies() if (NULL == (di = dynamic_cast (item))) { + +#ifdef P3DISC_DEBUG std::ostringstream out; - out << "p3disc::handleReplies()"; + out << "p3disc::handleIncoming()"; out << "Deleting Non RsDiscItem Msg" << std::endl; item -> print(out); - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + + std::cerr << out.str() << std::endl; +#endif // delete and continue to next loop. delete item; @@ -967,1135 +145,536 @@ int p3disc::handleReplies() nhandled++; { - std::ostringstream out; - out << "p3disc::handleReplies()"; - out << " Received Message!" << std::endl; - di -> print(out); - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); +#ifdef P3DISC_DEBUG + std::ostringstream out; + out << "p3disc::handleIncoming()"; + out << " Received Message!" << std::endl; + di -> print(out); + + std::cerr << out.str() << std::endl; +#endif } - // if discovery reply then respondif haven't already. + // if discovery reply then respond if haven't already. if (NULL != (dri = dynamic_cast (di))) { - // add to data tree. - handleDiscoveryData(dri); + recvPeerFriendMsg(dri); } else /* Ping */ { - handleDiscoveryPing(di); - - /* find the certificate */ - certsign sign; - convert_to_certsign(di->PeerId(), sign); - cert *peer = getSSLRoot() -> findcertsign(sign); - if (peer) - { - sendDiscoveryReply(peer); - pqioutput(PQL_DEBUG_BASIC, pqidisczone, - "After Reply to Ping"); - } - else - { - pqioutput(PQL_ALERT, pqidisczone, - "Failed to Match disc Ping ID"); - } + recvPeerOwnMsg(di); } delete di; } return nhandled; } -int p3disc::sendDiscoveryReply(cert *p) + + + /************* from pqiMonitor *******************/ +void p3disc::statusChange(const std::list &plist) { - if (!remote_disc) - return -1; - - // So to send a discovery reply .... we need to.... - // 1) generate a list of our neighbours..... - pqioutput(PQL_DEBUG_BASIC, pqidisczone, - "p3disc::sendDiscoveryReply() Generating Messages!"); - - std::list::iterator it; - // Temp variable - std::list &certlist = sroot -> getCertList(); - int good_certs = 0; - int cts = time(NULL); - - for(it = certlist.begin(); it != certlist.end(); it++) - { - // if accepted and has connected (soon) - if ((*it) -> Accepted()) - { - good_certs++; - - { - std::ostringstream out; - out << "p3disc::sendDiscoveryReply()"; - out << " Found Neighbour Cert!" << std::endl; - out << "Encoding: "<<(*it)->Name() << std::endl; - out << "Encoding(2): "<<(*it)->certificate->name << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); - } - - // Construct a message - RsDiscReply *di = new RsDiscReply(); - - // Fill the message - // Set Target as input cert. - di -> PeerId(p -> PeerId()); - - // set the server address. - di -> laddr = (*it) -> localaddr; - di -> saddr = (*it) -> serveraddr; - - // set the timeframe since last connection. - if ((*it) -> lr_timestamp <= 0) - { - di -> receive_tr = 0; - } - else - { - di -> receive_tr = convertTDeltaToTRange(cts - (*it) -> lr_timestamp); - } - - if ((*it) -> lc_timestamp <= 0) - { - di -> connect_tr = 0; - } - else - { - di -> connect_tr = convertTDeltaToTRange(cts - (*it) -> lc_timestamp); - } - di -> discFlags = determineCertAvailabilityFlags(*it); - - // actually ned to copy certificate to array - // for proper cert stuff. - -/**************** PQI_USE_XPGP ******************/ -#if defined(PQI_USE_XPGP) - int len = i2d_XPGP((*it) -> certificate, (unsigned char **) &(di -> certDER.bin_data)); -#else /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - int len = i2d_X509((*it) -> certificate, (unsigned char **) &(di -> certDER.bin_data)); -#endif /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - if (len > 0) - { - di -> certDER.bin_len = len; - std::ostringstream out; - out << "Cert Encoded(" << len << ")" << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); - } - else - { - pqioutput(PQL_DEBUG_BASIC, pqidisczone, "Failed to Encode Cert"); - di -> certDER.bin_len = 0; - } - - // Send off message - sendItem(di); - pqioutput(PQL_DEBUG_BASIC, pqidisczone, "Sent DI Message"); - } - else - { - std::ostringstream out; - out << "p3disc::sendDiscoveryReply()"; - out << "Not Sending Cert: " << std::endl; - out << (*it) -> Name() << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); - } - - } - - { - std::ostringstream out; - out << "p3disc::sendDiscoveryReply()"; - out << "Found " << good_certs << " Certs" << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); - } - - return 1; -} - - -int p3disc::handleDiscoveryPing(RsDiscItem *di) -{ - std::list::iterator it; - - // as already connected.... certificate available. - certsign sign; - convert_to_certsign(di->PeerId(), sign); - cert *c = getSSLRoot() -> findcertsign(sign); - - if (c == NULL) - return -1; - - { - std::ostringstream out; - out << "p3disc::handleDiscoveryPing()" << std::endl; - di -> print(out); - out << "RECEIVED Self Describing RsDiscItem!"; - out << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); - } - - // The first check is whether this packet came from - // the cert in the reply. - - // Local address is always right! - // No User control anyway! - c -> localaddr = di -> laddr; - - // The Rest of this should only be set - // if we are in autoconnect mode..... - // else should be done manually. - // ----> Think we should do this always (is disc from then) - /**************************** - if (!(c -> Manual())) - ****************************/ - { - - // if the connect addr isn't valid. - if (!isValidNet(&(c -> lastaddr.sin_addr))) - { - // set it all - c -> serveraddr = di -> saddr; - pqioutput(PQL_WARNING, pqidisczone, - "lastaddr !Valid -> serveraddr=di->saddr"); - } - // if the connect addr == dispkt.local - else if (0 == inaddr_cmp(c -> lastaddr, di -> laddr)) - { - // set it all - c -> serveraddr = di -> saddr; - c -> Local(true); - pqioutput(PQL_WARNING, pqidisczone, - "lastaddr=di->laddr -> Local & serveraddr=di->saddr"); - } - else if (0 == inaddr_cmp(c -> lastaddr, di -> saddr)) - { - pqioutput(PQL_WARNING, pqidisczone, - "lastaddr=di->saddr -> !Local & serveraddr=di->saddr"); - c -> serveraddr = di -> saddr; - c -> Local(false); - } - else - { - pqioutput(PQL_WARNING, pqidisczone, - "lastaddr!=(di->laddr|di->saddr) -> !Local,serveraddr left"); - c -> Local(false); - } - - updateCertAvailabilityFlags(c, di->discFlags); - - } - /**************************** - else - { - pqioutput(PQL_WARNING, pqidisczone, - "peer is Manual -> leaving server settings"); - if (0 == inaddr_cmp(c -> lastaddr, di -> laddr)) - { - pqioutput(PQL_WARNING, pqidisczone, - "c->lastaddr=di->laddr -> local"); - c -> Local(true); - } - else - { - pqioutput(PQL_WARNING, pqidisczone, - "c->lastaddr!=di->laddr -> !local"); - c -> Local(false); - } - - } - ****************************/ - - // Now add it into the system. - // check if it exists already...... - for(it = neighbours.begin(); it != neighbours.end(); it++) - { - cert *c2 = (cert *) (*it) -> id; -/**************** PQI_USE_XPGP ******************/ -#if defined(PQI_USE_XPGP) - if ((c2 != NULL) && (0 == XPGP_cmp( - c -> certificate, c2 -> certificate))) -#else /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - if ((c2 != NULL) && (0 == X509_cmp( - c -> certificate, c2 -> certificate))) -#endif /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - { - // matching.... - // update it....; - pqioutput(PQL_DEBUG_BASIC, pqidisczone, "Updating Certificate (AN)!"); - - (*it)-> local = c -> Local(); - updateAutoServer((*it), di); - - /* now look through the neighbours_of */ - std::list::iterator nit; - for(nit = ((*it) -> neighbour_of).begin(); - nit != ((*it) -> neighbour_of).end(); nit++) - { - - /* check if we already have a autoserver.... */ - if ((*it)->id == (*nit)->id) - { - /* we already have one */ - // update it....; - pqioutput(PQL_DEBUG_BASIC, pqidisczone, - "Updating Certificate (AS)!"); - - updateAutoServer(*nit, di); - return 0; - } - } - - pqioutput(PQL_DEBUG_BASIC, pqidisczone, - "Adding Certificate (AS)!"); - - /* if we get here, we need to add an autoserver */ - autoserver *as = new autoserver(); - as -> id = c; - updateAutoServer(as, di); - (*it) -> neighbour_of.push_back(as); - - return 1; - } - } - - // if get here must add a autoneighbour + an autoserver. - - autoneighbour *an = new autoneighbour(); - an -> id = c; - an -> local = c -> Local(); - updateAutoServer(an, di); - - // add autoserver to an. - autoserver *as = new autoserver(); - as -> id = c; - updateAutoServer(as, di); - - an -> neighbour_of.push_back(as); - neighbours.push_back(an); - - return 1; -} - - -int p3disc::handleDiscoveryData(RsDiscReply *di) -{ - std::list::iterator it; - - { - std::ostringstream out; - out << "p3disc::handleDiscoveryData()" << std::endl; - di -> print(out); - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); - } - - - certsign sign; - convert_to_certsign(di->PeerId(), sign); - cert *di_peer = getSSLRoot() -> findcertsign(sign); - if (!di_peer) - { - std::ostringstream out; - out << "p3disc::handleDiscoveryData() BAD Id" << std::endl; - di -> print(out); - pqioutput(PQL_ALERT, pqidisczone, out.str()); - delete di; - return 0; - } - - - /* WIN/LINUX Difference. - */ -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - const unsigned char *certptr = (const unsigned char *) di -> certDER.bin_data; -#else - unsigned char *certptr = (unsigned char *) di -> certDER.bin_data; +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::statusChange()"; + std::cerr << std::endl; #endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + /* get a list of all online peers */ + std::list onlineIds; + mConnMgr->getOnlineList(onlineIds); - // load up the certificate..... -/**************** PQI_USE_XPGP ******************/ -#if defined(PQI_USE_XPGP) - - XPGP *tmp = NULL; - XPGP *xpgp = d2i_XPGP(&tmp, (unsigned char **) &certptr, di -> certDER.bin_len); - if (xpgp == NULL) - return -1; + std::list::const_iterator pit; + /* if any have switched to 'connected' then we notify */ + for(pit = plist.begin(); pit != plist.end(); pit++) { - std::ostringstream out; - out << "p3disc::handleDiscoveryData()" << std::endl; - out << "certificate name: " << xpgp -> name << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); - } - - // if a duplicate with ad/or sslroot; - cert *c = sroot -> makeCertificateXPGP(xpgp); - if (c == NULL) - { - pqioutput(PQL_DEBUG_BASIC, pqidisczone, - "Failed to Create Certificate"); - // delete the cert. - XPGP_free(xpgp); - return -1; - } - - -#else /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - - X509 *tmp = NULL; - X509 *x509 = d2i_X509(&tmp, &certptr, di -> certLen); - if (x509 == NULL) - return -1; - { - std::ostringstream out; - out << "p3disc::handleDiscoveryData()" << std::endl; - out << "certificate name: " << x509 -> name << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); - } - - // if a duplicate with ad/or sslroot; - cert *c = sroot -> makeCertificate(x509); - if (c == NULL) - { - pqioutput(PQL_DEBUG_BASIC, pqidisczone, - "Failed to Create Certificate"); - // delete the cert. - X509_free(x509); - return -1; - } - -#endif /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - - - // So have new/existing cert; - // check if it exists already...... - for(it = neighbours.begin(); it != neighbours.end(); it++) - { - cert *c2 = (cert *) (*it) -> id; - -/**************** PQI_USE_XPGP ******************/ -#if defined(PQI_USE_XPGP) - if ((c2 != NULL) && (0 == XPGP_cmp( - c -> certificate, c2 -> certificate))) -#else /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - if ((c2 != NULL) && (0 == X509_cmp( - c -> certificate, c2 -> certificate))) -#endif /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ + if ((pit->state & RS_PEER_S_FRIEND) && + (pit->actions & RS_PEER_CONNECTED)) { - // matching.... check neighbours of.... - // for the source of the message. - - std::list::iterator nit; - for(nit = ((*it) -> neighbour_of).begin(); - nit != ((*it) -> neighbour_of).end(); nit++) - { - - -/**************** PQI_USE_XPGP ******************/ -#if defined(PQI_USE_XPGP) - if (0 == XPGP_cmp( -#else /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - if (0 == X509_cmp( -#endif /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - ((cert *) (*nit) -> id) -> certificate, - di_peer -> certificate)) - { - - // update it....; - pqioutput(PQL_DEBUG_BASIC, pqidisczone, - "Updating Certificate!"); - - updateAutoServer(*nit, di); - - return 0; - } - } - - // if we get to here - add neighbour of info. - autoserver *as = new autoserver(); - as -> id = di_peer; - - // add in some more ....as -> addr = (di -> ); - - updateAutoServer(as, di); - - (*it) -> neighbour_of.push_back(as); - - return 1; + /* send our details to them */ + sendOwnDetails(pit->id); } } - - // if get here must add a autoneighbour + autoserver. - - { - std::ostringstream out; - out << "p3disc::handleDiscoveryData()" << std::endl; - out << "Adding New AutoNeighbour:" << c -> Name() << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); - } - - autoneighbour *an = new autoneighbour(); - an -> id = c; - // initial guess. - an -> local_addr = di -> laddr; - an -> server_addr = di -> saddr; - an -> local = false; - - autoserver *as = new autoserver(); - as -> id = di_peer; - - updateAutoServer(as, di); - - an -> neighbour_of.push_back(as); - - neighbours.push_back(an); - - return 1; } -int p3disc::collectCerts() +void p3disc::respondToPeer(std::string id) { + /* get a peer lists */ - // First get any extras from the CollectedCerts Queue. - // if the cert matches an existing one.... update + discard - // else add in.... - - std::list::iterator it; - std::list::iterator it2; +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::respondToPeer() id: " << id; + std::cerr << std::endl; +#endif - cert *nc; - while(NULL != (nc = sroot -> getCollectedCert())) + std::list friendIds; + std::list onlineIds; + std::list::iterator it; + + mConnMgr->getFriendList(friendIds); + mConnMgr->getOnlineList(onlineIds); + + /* Check that they have DISC on */ { - // check for matching certs. - bool found = false; - + /* get details */ + peerConnectState detail; + if (!mConnMgr->getFriendNetStatus(id, detail)) { - std::ostringstream out; - out << "p3disc::collectCert: " << std::endl; - out << "Name: " << nc -> Name() << std::endl; - out << "CN: " << nc -> certificate -> name << std::endl; - - out << " From: "; - out << inet_ntoa(nc -> lastaddr.sin_addr); - out << ":" << ntohs(nc -> lastaddr.sin_port) << std::endl; - out << " Local: "; - out << inet_ntoa(nc -> localaddr.sin_addr); - out << ":" << ntohs(nc -> localaddr.sin_port) << std::endl; - out << " Server: "; - out << inet_ntoa(nc -> serveraddr.sin_addr); - out << ":" << ntohs(nc -> serveraddr.sin_port) << std::endl; - out << " Listen TS:"; - out << nc -> lr_timestamp << " "; - out << "Connect TR:"; - out << nc -> lc_timestamp << std::endl; - out << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + /* major error! */ + return; } - - for(it = neighbours.begin(); (!found) && (it != neighbours.end()); it++) + if (detail.visState & RS_VIS_STATE_NODISC) { - cert *c = (cert *) ((*it) -> id); -/**************** PQI_USE_XPGP ******************/ -#if defined(PQI_USE_XPGP) - if ((c != NULL) && - (0 == XPGP_cmp(c -> certificate, nc -> certificate))) -#else /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - if ((c != NULL) && - (0 == X509_cmp(c -> certificate, nc -> certificate))) -#endif /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - { - /* addresses handled already .... - * by sslroot. (more intelligent decisions). - * update timestamps so we don't overwrite - * the uptodate cert data. - */ - - found = true; - if ((nc -> lc_timestamp > 0) && - ((unsigned) nc -> lc_timestamp > (*it) -> c_ts)) - { - // connect.... timestamp - (*it) -> connect = true; - (*it) -> c_ts = nc -> lc_timestamp; - // don't make this decision here. - //(*it) -> server_addr = nc -> lastaddr; - } - - if ((nc -> lr_timestamp > 0) && - ((unsigned) nc -> lr_timestamp > (*it) -> l_ts)) - { - // received.... timestamp - (*it) -> listen = true; - (*it) -> l_ts = nc -> lr_timestamp; - } - - if ((c != nc) || - (c -> certificate != nc -> certificate)) - { - std::ostringstream out; - out << "Warning Dup/Diff Mem "; - out << " Found in p3Disc!"; - out << std::endl; - pqioutput(PQL_ALERT, pqidisczone, out.str()); - exit(1); - } - } - } - if (!found) - { - // add into the list..... - autoneighbour *an = new autoneighbour(); - an -> id = nc; - - // initial guess. - an -> local_addr = nc -> localaddr; - an -> server_addr = nc -> serveraddr; - an -> local = false; - - if (nc -> lc_timestamp > 0) - { - an -> c_ts = nc -> lc_timestamp; - an -> connect = true; - } - else - { - an -> c_ts = 0; - an -> connect = false; - } - - if (nc -> lr_timestamp > 0) - { - an -> l_ts = nc -> lr_timestamp; - an -> listen = true; - } - else - { - an -> l_ts = 0; - an -> listen = false; - } - - neighbours.push_back(an); + /* don't have DISC enabled */ + return; } } - return 1; -} -int p3disc::distillData() -{ - // This transforms the autoneighbour tree into - // a list of certificates with the best guess settings. - - // get any extra. from sslroot. - collectCerts(); - - discovered.clear(); - - std::ostringstream out; - out << "p3disc::distillData()" << std::endl; - - std::list::iterator it; - std::list::iterator it2; - std::list::iterator nit; - cert *own = sroot -> getOwnCert(); - - for(it = neighbours.begin(); it != neighbours.end(); it++) + /* send them a list of all friend's details */ + for(it = friendIds.begin(); it != friendIds.end(); it++) { - /* for the moment this is going to be a simplistic - * (and non-fault tolerent design).... - * we will take the most up-to-date values.... from the friends of neighbours. - * - * if these are more up-to-date than both the - * (1) neighbour (*it) and - * (2) the actual certificate and - * (3) we are not connected... then - * - * (a) we update the addresses and timestamps on the neighbour. - * (b) addresses on the certificate. - * - * Therefore - * cert has (1) our connect times, (2) best guess server. - * neighbour has uptodate times/servers from last distill. - * - * NOTE this requires a better algorithm. - * - */ - - unsigned int mr_connect = 0; - unsigned int mr_listen = 0; - - unsigned int mr_both = 0; /* connect or receive */ - /* three fields below match most recent (of either) */ - struct sockaddr_in mr_server; - struct sockaddr_in mr_local; - unsigned int mr_flags = 0; - - /* if we find a neighbour_of, which is the same cert. - * then we have the definitive answer already - * (and it has been installed) - */ - - bool haveDefinitive = false; - - cert *c = (cert *) (*it) -> id; - for(nit = ((*it) -> neighbour_of).begin(); - nit != ((*it) -> neighbour_of).end(); nit++) + /* get details */ + peerConnectState detail; + if (!mConnMgr->getFriendNetStatus(*it, detail)) { - out << "\tDistill Connected via: "; - if ((*nit) -> id != NULL) - { - out << ((*nit) ->id) -> Name(); - } - out << std::endl; - out << "\t\tServer: "; - out << inet_ntoa((*nit)->server_addr.sin_addr); - out << ":" << ntohs((*nit)->server_addr.sin_port); - out << std::endl; - if ((*nit)->id == (*it)->id) - { - haveDefinitive = true; - out << "\t\tIs Definitive Answer!"; - out << std::endl; - } - - if ((*nit) -> listen) - { - if ((*nit)->l_ts > mr_listen) - { - mr_listen = (*nit)->l_ts; - if (mr_listen > mr_both) - { - mr_both = mr_listen; - mr_server = (*nit) -> server_addr; - mr_local = (*nit) -> local_addr; - mr_flags = (*nit) -> discFlags; - } - } - } - - if ((*nit) -> connect) - { - if ((*nit) -> c_ts > mr_connect) - { - mr_connect = (*nit)->c_ts; - if (mr_connect > mr_both) - { - mr_both = mr_connect; - mr_server = (*nit) -> server_addr; - mr_local = (*nit) -> local_addr; - mr_flags = (*nit) -> discFlags; - } - } - } - } - - if ((c == own) || (haveDefinitive)) - { - out << c -> Name(); - out << ": Is Own or Definitive: no Update..."; - out << std::endl; - - discovered.push_back(c); + /* major error! */ continue; } - if ((mr_both > (*it)-> c_ts) && (mr_both > (*it)-> l_ts)) + if (!(detail.visState & RS_VIS_STATE_NODISC)) { - (*it) -> server_addr = mr_server; - (*it) -> local_addr = mr_local; - (*it) -> discFlags = mr_flags; - + sendPeerDetails(id, *it); /* (dest (to), source (cert)) */ } - - /* now we can check against (*it) */ - if ((!(*it)->listen) || ((*it)-> l_ts < mr_listen)) - { - (*it) -> listen = true; - (*it)-> l_ts = mr_listen; - } - - if ((!(*it)->connect) || ((*it)-> c_ts < mr_connect)) - { - (*it) -> connect = true; - (*it)-> c_ts = mr_connect; - } - - /* XXX fixme ***/ - // Finally we can update the certificate, if auto - // is selected.... or not in use. - if (!(c -> Connected())) - { - out << "Checking: " << c -> Name() << std::endl; - - // if empty local - if (0 == inaddr_cmp(c -> localaddr, INADDR_ANY)) - { - out << "\tUpdating NULL Local Addr:" << std::endl; - out << "\t\tOld: "; - out << inet_ntoa(c->localaddr.sin_addr); - out << ":" << ntohs(c->localaddr.sin_port); - c -> localaddr = (*it) -> local_addr; - out << "\t\tNew: "; - out << inet_ntoa(c->localaddr.sin_addr); - out << ":" << ntohs(c->localaddr.sin_port); - } - - // if empty server ..... - if (0 == inaddr_cmp(c -> serveraddr, INADDR_ANY)) - { - out << "\tUpdating NULL Serv Addr:" << std::endl; - out << "\t\tOld: "; - out << inet_ntoa(c->serveraddr.sin_addr); - out << ":" << ntohs(c->serveraddr.sin_port); - c -> serveraddr = (*it) -> server_addr; - out << "\t\tNew: "; - out << inet_ntoa(c->serveraddr.sin_addr); - out << ":" << ntohs(c->serveraddr.sin_port); - } - // if local (second as should catch empty) - else if ((0 == inaddr_cmp((*it) -> server_addr, - c -> localaddr))) - //&& (inaddr_local(c -> localaddr)) - { - out << "\tMaking Local..." << std::endl; - c -> Local(true); - } - - // Finally the key update .... - // check only against the latest data.... - - if (mr_both) - { - // - unsigned int cert_both = c -> lc_timestamp; - if (cert_both < (unsigned) c -> lr_timestamp) - { - cert_both = c -> lr_timestamp; - } - - int log_delta = -1; /* invalid log */ - if (mr_both > cert_both) - { - log_delta = (int) log10((double) (mr_both - cert_both)); - } - - /* if a peer has connected more recently than us */ - if (log_delta > 3) // or > 10000 (secs), or ~3 hours. - { - out << "\tUpdating OLD Addresses:" << std::endl; - out << "\t\tOld Local: "; - out << inet_ntoa(c->serveraddr.sin_addr); - out << ":" << ntohs(c->serveraddr.sin_port); - out << std::endl; - out << "\t\tOld Server: "; - out << inet_ntoa(c->serveraddr.sin_addr); - out << ":" << ntohs(c->serveraddr.sin_port); - out << std::endl; - if (c->Firewalled()) - { - out << "\t\tFireWalled/"; - } - else - { - out << "\t\tNot FireWalled/"; - } - if (c->Forwarded()) - { - out << "Forwarded"; - } - else - { - out << "Not Forwarded"; - } - out << std::endl; - - if (0!=inaddr_cmp(mr_server, INADDR_ANY)) - { - c -> serveraddr = mr_server; - } - - if (0!=inaddr_cmp(mr_local, INADDR_ANY)) - { - c -> localaddr = mr_local; - } - - updateCertAvailabilityFlags(c, mr_flags); - - out << "\t\tNew: "; - out << inet_ntoa(c->serveraddr.sin_addr); - out << ":" << ntohs(c->serveraddr.sin_port); - out << "\t\tNew Local: "; - out << inet_ntoa(c->serveraddr.sin_addr); - out << ":" << ntohs(c->serveraddr.sin_port); - out << std::endl; - out << "\t\tNew Server: "; - out << inet_ntoa(c->serveraddr.sin_addr); - out << ":" << ntohs(c->serveraddr.sin_port); - out << std::endl; - if (c->Firewalled()) - { - out << "\t\tFireWalled/"; - } - else - { - out << "\t\tNot FireWalled/"; - } - if (c->Forwarded()) - { - out << "Forwarded"; - } - else - { - out << "Not Forwarded"; - } - out << std::endl; - } - } - } - discovered.push_back(c); } - pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); - idServers(); - return 1; -} -std::list &p3disc::getDiscovered() -{ - return discovered; -} - -static const std::string pqi_adflags("PQI_ADFLAGS"); - -int p3disc::save_configuration() -{ - if (sroot == NULL) - return -1; - - std::string localflags; - if (local_disc) - localflags += "L"; - if (remote_disc) - localflags += "R"; - sroot -> setSetting(pqi_adflags, localflags); - return 1; -} - - -// load configuration from sslcert -> owncert() -// instead of from the configuration files. - -int p3disc::load_configuration() -{ - unsigned int i = 0; - - if (sroot == NULL) - return -1; - - Person *p = sroot -> getOwnCert(); - if (p == NULL) - return -1; - laddr = p -> localaddr; - //laddr.sin_family = AF_INET; - - saddr = p -> serveraddr; - local_firewalled = p -> Firewalled(); - local_forwarded = p -> Forwarded(); - - std::string localflags = sroot -> getSetting(pqi_adflags); - // initially drop out gracefully. - if (localflags.length() == 0) - return 1; - if (i < localflags.length()) - if (local_disc = ('L' == localflags[i])) - i++; - if (i < localflags.length()) - if (remote_disc = ('R' == localflags[i])) - i++; - // temp turn on! - local_disc = false; // true; - remote_disc = true; - return 1; -} - - -std::list p3disc::potentialproxy(cert *target) -{ - std::list certs; - // search the discovery tree for proxies for target. - - std::list::iterator it; - std::list::iterator nit; - - pqioutput(PQL_DEBUG_BASIC, pqidisczone, - "p3disc::potentialproxy()"); - - for(it = neighbours.begin(); it != neighbours.end(); it++) + /* send their details to all online peers */ + for(it = onlineIds.begin(); it != onlineIds.end(); it++) { - cert *c = (cert *) (*it) -> id; - if (c == target) + peerConnectState detail; + if (!mConnMgr->getFriendNetStatus(*it, detail)) { - // found target. - for(nit = ((*it) -> neighbour_of).begin(); - nit != ((*it) -> neighbour_of).end(); nit++) - { - /* can't use target as proxy */ - cert *pp = (cert *) (*nit)->id; - if ((pp -> Connected()) && (target != pp)) - { - std::ostringstream out; - out << "Potential Proxy: "; - out << pp -> Name(); - certs.push_back(pp); - pqioutput(PQL_DEBUG_BASIC, pqidisczone, - out.str()); - } - } + /* major error! */ + continue; + } - return certs; + if (!(detail.visState & RS_VIS_STATE_NODISC)) + { + sendPeerDetails(*it, id); /* (dest (to), source (cert)) */ } } - - pqioutput(PQL_DEBUG_BASIC, pqidisczone, - "p3disc::potentialproxy() No proxies found"); - // empty list. - return certs; } -std::list p3disc::requestStunServers() +/*************************************************************************************/ +/* Output Network Msgs */ +/*************************************************************************************/ +void p3disc::sendOwnDetails(std::string to) { - - /* loop through all the possibilities - * - * find the ones which aren't firewalled. - * - * get their addresses. + /* setup: + * IP local / external + * availability (TCP LOCAL / EXT, UDP ...) */ - cert *own = sroot -> getOwnCert(); - std::list stunList; - - std::list::iterator it; - for(it = neighbours.begin(); it != neighbours.end(); it++) + // Then send message. { - cert *c = (cert *) (*it) -> id; - - /* if flags are correct, and the address looks - * valid. - */ - -/* switch on Local Stun for testing */ -/* - * #define STUN_ALLOW_LOCAL_NET 1 - */ - - -#ifdef STUN_ALLOW_LOCAL_NET - bool isExtern = true; -#else - bool isExtern = (!c->Firewalled()) || - (c->Firewalled() && c->Forwarded()); +#ifdef P3DISC_DEBUG + std::ostringstream out; + out << "p3disc::sendOwnDetails()"; + out << "Constructing a RsDiscItem Message!" << std::endl; + out << "Sending to: " << to; + std::cerr << out.str() << std::endl; #endif - - if (isExtern) - { - // second level of checks. - // if we will connect, and haven't -> they are probably - // offline. - if (c->Accepted() && (!c->Connected())) - { - std::ostringstream out; - out << "Offline Friend: "; - out << c -> Name(); - out << " not available for Stun"; - pqioutput(PQL_DEBUG_ALERT, pqidisczone, out.str()); - isExtern = false; - } - - // and address looks good. - // - // and not in our subnet (external to us) - } - - - if (isExtern) - { - std::ostringstream out; - out << "Potential Stun Server: "; - out << c -> Name(); - out << std::endl; - out << " ServerAddr: " << inet_ntoa(c->serveraddr.sin_addr); - out << " : " << ntohs(c->serveraddr.sin_port); - out << std::endl; - out << " LocalAddr: " << inet_ntoa(c->localaddr.sin_addr); - out << " : " << ntohs(c->localaddr.sin_port); - out << std::endl; - -#ifdef STUN_ALLOW_LOCAL_NET - if (isValidNet(&(c->serveraddr.sin_addr)) && - (!sameNet(&(own->serveraddr.sin_addr), &(c->serveraddr.sin_addr)))) -#else - if ((isValidNet(&(c->serveraddr.sin_addr))) && - (!isPrivateNet(&(c->serveraddr.sin_addr))) && - (!sameNet(&(own->localaddr.sin_addr), &(c->serveraddr.sin_addr))) && - (!sameNet(&(own->serveraddr.sin_addr), &(c->serveraddr.sin_addr)))) -#endif - { - out << " -- Chose Server Address"; - out << std::endl; - stunList.push_back(c->serveraddr); - } -#ifdef STUN_ALLOW_LOCAL_NET - else if (isValidNet(&(c->localaddr.sin_addr))) -#else - else if ((!c->Firewalled()) && - (isValidNet(&(c->localaddr.sin_addr))) && - (!isPrivateNet(&(c->localaddr.sin_addr))) && - (!sameNet(&(own->localaddr.sin_addr), &(c->localaddr.sin_addr)))) -#endif - { - out << " -- Chose Local Address"; - out << std::endl; - stunList.push_back(c->localaddr); - } - else - { - out << "<=> Invalid / Private Addresses"; - out << std::endl; - } - pqioutput(PQL_DEBUG_ALERT, pqidisczone, out.str()); - } - else - { - std::ostringstream out; - out << "Non-Stun Neighbour: "; - out << c -> Name(); - pqioutput(PQL_DEBUG_ALERT, pqidisczone, out.str()); - } } - return stunList; + // Construct a message + RsDiscItem *di = new RsDiscItem(); + + /* components: + * laddr + * saddr + * contact_tf + * discFlags + */ + + peerConnectState detail; + if (!mConnMgr->getOwnNetStatus(detail)) + { + /* major error! */ + return; + } + + // Fill the message + di -> PeerId(to); + di -> laddr = detail.localaddr; + di -> saddr = detail.serveraddr; + di -> contact_tf = 0; + + /* construct disc flags */ + if (!(detail.visState & RS_VIS_STATE_NODISC)) + { + di->discFlags |= P3DISC_FLAGS_USE_DISC; + } + + if (!(detail.visState & RS_VIS_STATE_NODHT)) + { + di->discFlags |= P3DISC_FLAGS_USE_DHT; + } + + if ((detail.netMode == RS_NET_MODE_EXT) || + (detail.netMode & RS_NET_MODE_UPNP)) + { + di->discFlags |= P3DISC_FLAGS_EXTERNAL_ADDR; + } + di->discFlags |= P3DISC_FLAGS_OWN_DETAILS; + + /* send msg */ + sendItem(di); +} + + /* (dest (to), source (cert)) */ +void p3disc::sendPeerDetails(std::string to, std::string about) +{ + /* setup: + * Certificate. + * IP local / external + * availability ... + * last connect (0) if online. + */ + + /* send it off */ + { +#ifdef P3DISC_DEBUG + std::ostringstream out; + out << "p3disc::sendPeerDetails()"; + out << " Sending details of: " << about; + out << " to: " << to << std::endl; + std::cerr << out.str() << std::endl; +#endif + } + + + peerConnectState detail; + if (!mConnMgr->getFriendNetStatus(about, detail)) + { + /* major error! */ + return; + } + + // Construct a message + RsDiscReply *di = new RsDiscReply(); + + // Fill the message + // Set Target as input cert. + di -> PeerId(to); + di -> aboutId = about; + + // set the server address. + di -> laddr = detail.localaddr; + di -> saddr = detail.serveraddr; + + if (detail.state & RS_PEER_S_CONNECTED) + { + di -> contact_tf = 0; + } + else + { + di -> contact_tf = convertTDeltaToTRange(time(NULL) - detail.lastcontact); + } + + /* construct disc flags */ + di->discFlags = 0; + + /* NOTE we should not be sending packet if NODISC is set.... + * checked elsewhere... so don't check. + */ + di->discFlags |= P3DISC_FLAGS_USE_DISC; + + if (!(detail.visState & RS_VIS_STATE_NODHT)) + { + di->discFlags |= P3DISC_FLAGS_USE_DHT; + } + + if (detail.netMode == RS_NET_MODE_EXT) + { + di->discFlags |= P3DISC_FLAGS_EXTERNAL_ADDR; + } + + if (detail.state & RS_PEER_S_CONNECTED) + { + di->discFlags |= P3DISC_FLAGS_PEER_ONLINE; + } + + uint32_t certLen = 0; + + unsigned char **binptr = (unsigned char **) &(di -> certDER.bin_data); + mAuthMgr->SaveCertificateToBinary(about, binptr, &certLen); + if (certLen > 0) + { + di -> certDER.bin_len = certLen; +#ifdef P3DISC_DEBUG + std::cerr << "Cert Encoded(" << certLen << ")" << std::endl; +#endif + } + else + { +#ifdef P3DISC_DEBUG + std::cerr << "Failed to Encode Cert" << std::endl; +#endif + di -> certDER.bin_len = 0; + } + + // Send off message + sendItem(di); + +#ifdef P3DISC_DEBUG + std::cerr << "Sent DI Message" << std::endl; +#endif +} + + +/*************************************************************************************/ +/* Input Network Msgs */ +/*************************************************************************************/ +void p3disc::recvPeerOwnMsg(RsDiscItem *item) +{ +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::recvPeerOwnMsg() From: " << item->PeerId() << std::endl; +#endif + + /* tells us their exact address (mConnectMgr can ignore if it looks wrong) */ + uint32_t type = 0; + uint32_t flags = 0; + + /* translate flags */ + if (item->discFlags & P3DISC_FLAGS_USE_DISC) + { + flags |= RS_NET_FLAGS_USE_DISC; + } + if (item->discFlags & P3DISC_FLAGS_USE_DHT) + { + flags |= RS_NET_FLAGS_USE_DHT; + } + if (item->discFlags & P3DISC_FLAGS_PEER_ONLINE) + { + flags |= RS_NET_FLAGS_ONLINE; + } + + /* generate type */ + type = RS_NET_CONN_TCP_LOCAL; + if (item->discFlags & P3DISC_FLAGS_EXTERNAL_ADDR) + { + type |= RS_NET_CONN_TCP_EXTERNAL; + } + + mConnMgr->peerStatus(item->PeerId(), item->laddr, item->saddr, + type, flags, RS_CB_PERSON); + + /* now reply with all details */ + respondToPeer(item->PeerId()); + + addDiscoveryData(item->PeerId(), item->PeerId(), + item->laddr, item->saddr, item->discFlags, time(NULL)); + + /* cleanup (handled by caller) */ +} + + +void p3disc::recvPeerFriendMsg(RsDiscReply *item) +{ + +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::recvPeerFriendMsg() From: " << item->PeerId(); + std::cerr << " About " << item->aboutId; + std::cerr << std::endl; +#endif + + /* tells us their exact address (mConnectMgr can ignore if it looks wrong) */ + + /* load certificate */ + std::string peerId; + + uint8_t *certptr = (uint8_t *) item->certDER.bin_data; + uint32_t len = item->certDER.bin_len; + + bool loaded = mAuthMgr->LoadCertificateFromBinary(certptr, len, peerId); + + uint32_t type = 0; + uint32_t flags = 0; + + /* translate flags */ + if (item->discFlags & P3DISC_FLAGS_USE_DISC) + { + flags |= RS_NET_FLAGS_USE_DISC; + } + if (item->discFlags & P3DISC_FLAGS_USE_DHT) + { + flags |= RS_NET_FLAGS_USE_DHT; + } + if (item->discFlags & P3DISC_FLAGS_PEER_ONLINE) + { + flags |= RS_NET_FLAGS_ONLINE; + } + + /* generate type */ + type = RS_NET_CONN_TCP_LOCAL; + if (item->discFlags & P3DISC_FLAGS_EXTERNAL_ADDR) + { + type |= RS_NET_CONN_TCP_EXTERNAL; + } + + if (loaded) + { + mConnMgr->peerStatus(peerId, item->laddr, + item->saddr, type, flags, RS_CB_DISC); + } + + addDiscoveryData(item->PeerId(), peerId, item->laddr, item->saddr, item->discFlags, time(NULL)); + + /* cleanup (handled by caller) */ +} + + +/*************************************************************************************/ +/* Storing Network Graph */ +/*************************************************************************************/ + + +int p3disc::addDiscoveryData(std::string fromId, std::string aboutId, + struct sockaddr_in laddr, struct sockaddr_in raddr, uint32_t flags, time_t ts) +{ + /* Store Network information */ + + std::map::iterator it; + if (neighbours.end() == (it = neighbours.find(aboutId))) + { + /* doesn't exist */ + autoneighbour an; + + /* an data */ + an.id = aboutId; + an.validAddrs = false; + an.discFlags = 0; + an.ts = 0; + + neighbours[aboutId] = an; + + it = neighbours.find(aboutId); + } + + /* it always valid */ + + /* just update packet */ + + autoserver as; + + as.id = fromId; + as.localAddr = laddr; + as.remoteAddr = raddr; + as.discFlags = flags; + as.ts = ts; + + bool authDetails = (as.id == it->second.id); + + /* KEY decision about address */ + if ((authDetails) || + ((!(it->second.authoritative)) && (as.ts > it->second.ts))) + { + /* copy details to an */ + it->second.authoritative = authDetails; + it->second.ts = as.ts; + it->second.validAddrs = true; + it->second.localAddr = as.localAddr; + it->second.remoteAddr = as.remoteAddr; + it->second.discFlags = as.discFlags; + } + + (it->second).neighbour_of[fromId] = as; + + /* do we update network address info??? */ + return 1; + } +/*************************************************************************************/ +/* Extracting Network Graph Details */ +/*************************************************************************************/ + +bool p3disc::potentialproxies(std::string id, std::list proxyIds) +{ + /* find id -> and extract the neighbour_of ids */ + std::map::iterator it; + std::map::iterator sit; + if (neighbours.end() == (it = neighbours.find(id))) + { + return false; + } + + for(sit = it->second.neighbour_of.begin(); + sit != it->second.neighbour_of.end(); sit++) + { + proxyIds.push_back(sit->first); + } + return true; +} + + +int p3disc::idServers() +{ + std::map::iterator nit; + std::map::iterator sit; + int cts = time(NULL); + + std::ostringstream out; + out << "::::AutoDiscovery Neighbours::::" << std::endl; + for(nit = neighbours.begin(); nit != neighbours.end(); nit++) + { + out << "Neighbour: " << (nit->second).id; + out << std::endl; + out << "-> LocalAddr: "; + out << inet_ntoa(nit->second.localAddr.sin_addr); + out << ":" << ntohs(nit->second.localAddr.sin_port) << std::endl; + out << "-> RemoteAddr: "; + out << inet_ntoa(nit->second.remoteAddr.sin_addr); + out << ":" << ntohs(nit->second.remoteAddr.sin_port) << std::endl; + out << " Last Contact: "; + out << cts - (nit->second.ts) << " sec ago"; + out << std::endl; + + out << " -->DiscFlags: 0x" << std::hex << nit->second.discFlags; + out << std::dec << std::endl; + + for(sit = (nit->second.neighbour_of).begin(); + sit != (nit->second.neighbour_of).end(); sit++) + { + out << "\tConnected via: " << (sit->first); + out << std::endl; + out << "\t\tLocalAddr: "; + out << inet_ntoa(sit->second.localAddr.sin_addr); + out <<":"<< ntohs(sit->second.remoteAddr.sin_port); + out << std::endl; + out << "\t\tRemoteAddr: "; + out << inet_ntoa(sit->second.remoteAddr.sin_addr); + out <<":"<< ntohs(sit->second.remoteAddr.sin_port); + + out << std::endl; + out << "\t\tLast Contact:"; + out << cts - (sit->second.ts) << " sec ago"; + out << std::endl; + out << "\t\tDiscFlags: 0x" << std::hex << (sit->second.discFlags); + out << std::dec << std::endl; + } + } + +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::idServers()" << std::endl; + std::cerr << out.str(); + std::cerr << std::endl; +#endif + + return 1; +} // tdelta -> trange. @@ -2131,99 +710,3 @@ int convertTRangeToTDelta(int trange) return (int) (pow(10.0, trange) - 1.5); // (int) xxx98.5 -> xxx98 } -// fn which updates: connect, c_ts, -// listen, l_ts, -// local_addr, server_addr, -// and discFlags. -int updateAutoServer(autoserver *as, RsDiscItem *di) -{ - int cts = time(NULL); - - - as->listen = (di->receive_tr != 0); - as->connect= (di->connect_tr != 0); - - /* convert [r|c]_tf to timestamps.... - * - * Conversion to a _tf.... - * - * - * */ - if (as->listen) - { - as->l_ts = cts - convertTRangeToTDelta(di->receive_tr); - } - - if (as->connect) - { - as->c_ts = cts - convertTRangeToTDelta(di->connect_tr); - - } - as->local_addr = di->laddr; - as->server_addr = di->saddr; - as->discFlags = di->discFlags; - - return 1; -} - - -static const int PQI_DISC_FLAGS_FIREWALLED = 0x0001; -static const int PQI_DISC_FLAGS_FORWARDED = 0x0002; -static const int PQI_DISC_FLAGS_LOCAL = 0x0004; - -int updateCertAvailabilityFlags(cert *c, unsigned long discFlags) -{ - if (c) - { - c->Firewalled(discFlags & PQI_DISC_FLAGS_FIREWALLED); - c->Forwarded(discFlags & PQI_DISC_FLAGS_FORWARDED); - - if (discFlags & PQI_DISC_FLAGS_FIREWALLED) - { - pqioutput(PQL_WARNING, pqidisczone, - "updateCertAvailabilityFlags() Setting Firewalled Flag = true"); - } - else - { - pqioutput(PQL_WARNING, pqidisczone, - "updateCertAvailabilityFlags() Setting Firewalled Flag = false"); - } - - if (discFlags & PQI_DISC_FLAGS_FORWARDED) - { - pqioutput(PQL_WARNING, pqidisczone, - "updateCertAvailabilityFlags() Setting Forwarded Flag = true"); - } - else - { - pqioutput(PQL_WARNING, pqidisczone, - "updateCertAvailabilityFlags() Setting Forwarded Flag = false"); - } - - return 1; - } - return 0; -} - - -unsigned long determineCertAvailabilityFlags(cert *c) -{ - unsigned long flags = 0; - if (c->Firewalled()) - { - flags |= PQI_DISC_FLAGS_FIREWALLED; - } - - if (c->Forwarded()) - { - flags |= PQI_DISC_FLAGS_FORWARDED; - } - - if (c->Local()) - { - flags |= PQI_DISC_FLAGS_LOCAL; - } - - return flags; -} - diff --git a/libretroshare/src/services/p3disc.h b/libretroshare/src/services/p3disc.h index cdcbc5671..4a3382042 100644 --- a/libretroshare/src/services/p3disc.h +++ b/libretroshare/src/services/p3disc.h @@ -39,6 +39,7 @@ class p3ConnectMgr; class p3AuthMgr; +#include "pqi/pqimonitor.h" #include "serialiser/rsdiscitems.h" #include "services/p3service.h" @@ -46,20 +47,14 @@ class autoserver { public: autoserver() - :id(NULL), ca(NULL), connect(false), c_ts(0), - listen(false), l_ts(0), discFlags(0) { return;} + :ts(0), discFlags(0) { return;} std::string id; - std::string ca; - bool connect; - unsigned int c_ts; // this is connect_tf converted to timestamp, 0 invalid. + struct sockaddr_in localAddr; + struct sockaddr_in remoteAddr; - bool listen; - unsigned int l_ts; // this is receive_tf converted to timestamp, 0 invalid. - - struct sockaddr_in local_addr; - struct sockaddr_in server_addr; - unsigned long discFlags; + time_t ts; + uint32_t discFlags; }; @@ -67,95 +62,69 @@ class autoneighbour: public autoserver { public: autoneighbour() - :autoserver(), local(false), active(false) {} + :autoserver(), authoritative(false) {} - bool local; - bool active; // meaning in ssl's list. - std::list neighbour_of; + bool authoritative; + bool validAddrs; + + std::map neighbour_of; }; +class p3AuthMgr; +class p3ConnectMgr; -class p3disc: public p3Service + +class p3disc: public p3Service, public pqiMonitor { public: - bool local_disc; - bool remote_disc; - //sslroot *sslbase; - - p3disc(p3AuthMgr *am, p3ConnectMgr *cm); -virtual ~p3disc(); - - // Overloaded from p3Service functions. -virtual int tick(); - // For Proxy Information. -std::list requestStunServers(); -std::list potentialproxy(cert *target); + p3disc(p3AuthMgr *am, p3ConnectMgr *cm); - // load and save configuration to sslroot. - int save_configuration(); - int load_configuration(); + /************* from pqiMonitor *******************/ +virtual void statusChange(const std::list &plist); + /************* from pqiMonitor *******************/ - int ts_lastcheck; +int tick(); - int idServers(); - - // Handle Local Discovery. - int localListen(); - int localSetup(); - - int lsock; // local discovery socket. - struct sockaddr_in laddr; // local addr - struct sockaddr_in baddr; // local broadcast addr. - struct sockaddr_in saddr; // pqi ssl server addr. - - // bonus configuration flags. - bool local_firewalled; - bool local_forwarded; + private: - // local message construction/destruction. - void *ldata; - int ldlen; - int ldlenmax; +void respondToPeer(std::string id); + /* Network Output */ +void sendOwnDetails(std::string to); +void sendPeerDetails(std::string to, std::string about); - bool std_port; // if we have bound to default. - int ts_nextlp; // -1 for never (if on default) + /* Network Input */ +int handleIncoming(); +void recvPeerOwnMsg(RsDiscItem *item); +void recvPeerFriendMsg(RsDiscReply *item); - // helper functions. - int setLocalAddress(struct sockaddr_in srvaddr); - int determineLocalNetAddr(); - int setupLocalPacket(int type, struct sockaddr_in *home, - struct sockaddr_in *server); - int localPing(struct sockaddr_in); - int localReply(struct sockaddr_in); - int addLocalNeighbour(struct sockaddr_in*, struct sockaddr_in*); + /* handle network shape */ +int addDiscoveryData(std::string fromId, std::string aboutId, + struct sockaddr_in laddr, struct sockaddr_in raddr, + uint32_t flags, time_t ts); - // remote discovery function. - int newRequests(); - int handleReplies(); +bool potentialproxies(std::string id, std::list proxyIds); +int idServers(); - int handleDiscoveryData(RsDiscReply *di); - int handleDiscoveryPing(RsDiscItem *di); - int sendDiscoveryReply(cert *); - int collectCerts(); - int distillData(); + /* data */ -#if 0 - //cert *checkDuplicateX509(X509 *x509); - std::list &getDiscovered(); + private: - // Main Storage - std::list ad_init; - std::list discovered; -#endif - std::list neighbours; + p3AuthMgr *mAuthMgr; + p3ConnectMgr *mConnMgr; + + bool mRemoteDisc; + bool mLocalDisc; + + std::map neighbours; - p3AuthMgr *mAuthMgr; - p3ConnectMgr *mConnMgr; }; + + + #endif // MRK_PQI_AUTODISC_H diff --git a/libretroshare/src/services/p3ranking.cc b/libretroshare/src/services/p3ranking.cc new file mode 100644 index 000000000..7ba59e8a3 --- /dev/null +++ b/libretroshare/src/services/p3ranking.cc @@ -0,0 +1,435 @@ +/* + * libretroshare/src/services p3ranking.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 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 "services/p3ranking.h" +#include "pqi/pqibin.h" +#include "pqi/p3authmgr.h" + +const uint32_t RANK_MAX_FWD_OFFSET = (60 * 60 * 24 * 2); /* 2 Days */ + +std::string generateRandomLinkId(); + +/***** + * TODO + * (1) Streaming. + * (2) Ranking. + * + */ + + +p3Ranking::p3Ranking(uint16_t subtype, CacheTransfer *cft, + std::string sourcedir, std::string storedir, + uint32_t storePeriod) + :CacheSource(subtype, true, sourcedir), + CacheStore(subtype, true, cft, storedir), + mStorePeriod(storePeriod) +{ + mOwnId = getAuthMgr()->OwnId(); + createDummyData(); + return; +} + +bool p3Ranking::loadLocalCache(const CacheData &data) +{ + + return true; +} + +int p3Ranking::loadCache(const CacheData &data) +{ + + return 1; +} + +void p3Ranking::loadRankFile(std::string filename, std::string src) +{ + +#if 0 + /* create the serialiser to load info */ + pqistreamer *streamer = createStreamer(filename, src, BIN_FLAGS_READABLE); + + time_t now = time(NULL); + time_t min = now - mStorePeriod; + time_t max = now + RANK_MAX_FWD_OFFSET; + + RsItem *item; + RsRankMsg *newMsg; + while(NULL != (item = streamer->GetItem())) + { + newMsg = (RsRankMsg *) item; + + /* check timestamp */ + if ((newMsg->timestamp < min) || (newMsg->timestamp > max)) + { + /* if outside range -> remove */ + delete newMsg; + } + else + { + addRankMsg(newMsg); + } + } +#endif +} + +void p3Ranking::publishMsgs() +{ + +#if 0 + /* create a serialiser */ + std::string file; + pqistreamer *stream = createStreamer(file, mOwnId, BIN_FLAGS_NO_DELETE | BIN_FLAGS_HASH_DATA); + + /* iterate through list */ + std::map::iterator it; + for(it = mData.begin(); it != mData.end(); it++) + { + if (it->second.ownTag) + { + /* write to serialiser */ + RsItem *item = it->second.comments[mOwnId]; + if (item) + stream->SendItem(item); + } + } + + CacheData data; + data.pid = mOwnId; + data.cid = CacheId(CacheSource::getCacheType(), 0); + data.name = file; + + refreshCache(data); +#endif +} + + + +void p3Ranking::addRankMsg(RsRankMsg *msg) +{ + /* find msg */ + std::string id = msg->PeerId(); + std::string rid = msg->rid; + + std::map::iterator it; + it = mData.find(rid); + if (it == mData.end()) + { + /* add a new one */ + RankGroup grp; + grp.rid = rid; + grp.ownTag = false; + + /******** LINK SPECIFIC ****/ + grp.link = msg->link; + grp.title = msg->title; + + mData[rid] = grp; + it = mData.find(rid); + } + + /* check for old comment */ + std::map::iterator cit; + cit = (it->second).comments.find(id); + if ((it->second).comments.end() != cit) + { + (it->second).comments.erase(cit); + } + + (it->second).comments[id] = msg; + + if (id == mOwnId) + { + it->second.ownTag = true; + mRepublish = true; + } + + reSortGroup(it->second); +} + + +/***************** Sorting ****************/ + +bool p3Ranking::setSortPeriod(uint32_t period) +{ + mViewPeriod = period; + return true; +} + +bool p3Ranking::setSortMethod(uint32_t type) +{ + mSortType = type; + return true; +} + +bool p3Ranking::clearPeerFilter() +{ + mPeerFilter.clear(); + return true; +} + +bool p3Ranking::setPeerFilter(std::list peers) +{ + mPeerFilter = peers; + return true; +} + +float p3Ranking::locked_calcRank(RankGroup &grp) /* returns 0->100 */ +{ + +#if 0 + /* where all the work is done */ + bool doScore = (mSortType == + bool doTime = (mSortType == + bool doFilter = (mPeerFilter.size() > 0); + float rank = 0; + + for(it = grp.comments.begin(); it != grp.comments.end(); it++) + { + + if (doFilter) + { + /* do first so we can discard */ + + + if (doScore) + if (mSortType +#endif + + return 100; +} + +void p3Ranking::reSortGroup(RankGroup &grp) +{ + std::string rid = grp.rid; + float rank = grp.rank; + + /* remove from existings rankings */ + std::multimap::iterator rit; + rit = mRankings.lower_bound(grp.rank); + for(; (rit != mRankings.end()) && (rit->first == grp.rank); rit++) + { + if (rit->second == rid) + { + mRankings.erase(rit); + break; + } + } + + /* add it back in */ + grp.rank = locked_calcRank(grp); + mRankings.insert( + std::pair(grp.rank, rid)); +} + +void p3Ranking::sortAllMsgs() +{ + /* iterate through list and re-score each one */ + std::map::iterator it; + + mRankings.clear(); + + for(it = mData.begin(); it != mData.end(); it++) + { + (it->second).rank = locked_calcRank(it->second); + if (it->second.rank > 0) + { + mRankings.insert( + std::pair + (it->second.rank, it->first)); + } + } +} + +/******** ACCESS *************/ + + /* get Ids */ +uint32_t p3Ranking::getRankingsCount() +{ + return mRankings.size(); +} + +float p3Ranking::getMaxRank() +{ + if (mRankings.size() == 0) + return 0; + + return mRankings.rbegin()->first; +} + +bool p3Ranking::getRankings(uint32_t first, uint32_t count, std::list &rids) +{ + uint32_t i = 0; + std::multimap::iterator rit; + for(rit = mRankings.begin(); (i < first) && (rit != mRankings.end()); rit++); + + i = 0; + for(; (i < count) && (rit != mRankings.end()); rit++) + { + rids.push_back(rit->second); + } + return true; +} + +bool p3Ranking::getRankDetails(std::string rid, RsRankDetails &details) +{ + /* get the details. */ + std::map::iterator it; + it = mData.find(rid); + if (mData.end() == it) + { + return false; + } + + details.rid = it->first; + details.link = (it->second).link; + details.title = (it->second).title; + details.rank = (it->second).rank; + details.ownTag = (it->second).ownTag; + + std::map::iterator cit; + for(cit = (it->second).comments.begin(); + cit != (it->second).comments.end(); cit++) + { + RsRankComment comm; + comm.id = (cit->second)->PeerId(); + comm.timestamp = (cit->second)->timestamp; + comm.comment = (cit->second)->comment; + + details.comments.push_back(comm); + } + + return true; +} + + +void p3Ranking::tick() +{ + if (mRepublish) + { + publishMsgs(); + mRepublish = false; + } +} + + + + +/***** NEW CONTENT *****/ +std::string p3Ranking::newRankMsg(std::wstring link, std::wstring title, std::wstring comment) +{ + /* generate an id */ + std::string rid = generateRandomLinkId(); + + RsRankMsg *msg = new RsRankMsg(); + + time_t now = time(NULL); + + msg->PeerId(mOwnId); + msg->rid = rid; + msg->title = title; + msg->timestamp = now; + msg->link = link; + msg->comment = comment; + + addRankMsg(msg); + + return rid; +} + +bool p3Ranking::updateComment(std::string rid, std::wstring comment) +{ + return true; +} + +pqistreamer *createStreamer(std::string file, std::string src, uint32_t bioflags) +{ + +#if 0 + RsSerialiser *rsSerialiser = new RsSerialiser(); + RsSerialType *serialType = new RsRankSerial(); /* TODO */ + + rsSerialiser->addSerialType(serialType); + + BinInterface *bio = BinFileInterface(file.c_str(), bioflags); + pqistreamer *streamer = new pqistreamer(rsSerialiser, src, bio, 0); + + return streamer; +#endif + return NULL; +} + +std::string generateRandomLinkId() +{ + std::ostringstream out; + out << std::hex; + + /* 4 bytes per random number: 4 x 4 = 16 bytes */ + for(int i = 0; i < 4; i++) + { + uint32_t rint = random(); + out << rint; + } + return out.str(); +} + + +void p3Ranking::createDummyData() +{ + RsRankMsg *msg = new RsRankMsg(); + + time_t now = time(NULL); + + msg->PeerId(mOwnId); + msg->rid = "0001"; + msg->title = L"Original Awesome Site!"; + msg->timestamp = now - 12345; + msg->link = L"http://www.retroshare.org"; + msg->comment = L"Retroshares Website"; + + addRankMsg(msg); + + msg = new RsRankMsg(); + msg->PeerId(mOwnId); + msg->rid = "0002"; + msg->title = L"Awesome Site!"; + msg->timestamp = now - 123; + msg->link = L"http://www.lunamutt.org"; + msg->comment = L"Lunamutt's Website"; + + addRankMsg(msg); + + msg = new RsRankMsg(); + msg->PeerId("ALTID"); + msg->rid = "0002"; + msg->title = L"Awesome Site!"; + msg->timestamp = now - 12345; + msg->link = L"http://www.lunamutt.org"; + msg->comment = L"Lunamutt's Website (TWO) How Long can this comment be!\n"; + msg->comment += L"What happens to the second line?\n"; + msg->comment += L"And a 3rd!"; + + addRankMsg(msg); +} + diff --git a/libretroshare/src/services/p3ranking.h b/libretroshare/src/services/p3ranking.h new file mode 100644 index 000000000..cc111212e --- /dev/null +++ b/libretroshare/src/services/p3ranking.h @@ -0,0 +1,158 @@ +/* + * libretroshare/src/services: p3ranking.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 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 P3_GENERIC_RANKING_HEADER +#define P3_GENERIC_RANKING_HEADER + +#include "dbase/cachestrapper.h" +#include "pqi/pqiservice.h" +#include "pqi/pqistreamer.h" +//#include "util/rsthreads.h" + +#include "serialiser/rsserial.h" + +#include "rsiface/rsrank.h" + +/* + * A Generic Ranking system. + * Each User provides one cache... + * + * can be overloaded for specific types + * (links, shares, photos etc) + */ + +class RsRankMsg: public RsItem +{ + public: + + //std::string peerId; /* From */ + std::string rid; /* Random Id */ + time_t timestamp; + std::wstring link; + std::wstring title; + std::wstring comment; + + RsRankMsg():RsItem(0) { return; } +virtual void clear() + { return; } +virtual std::ostream& print(std::ostream &out, uint16_t) + { return out; } + +}; + +class RsRankSerial: public RsSerialType +{ + public: + + RsRankSerial() + :RsSerialType(0,0,0) + { return; } + +}; + +/* group these together */ + +class RankGroup +{ + public: + + std::string rid; /* Random Id */ + std::wstring link; + std::wstring title; + float rank; + bool ownTag; + std::map comments; +}; + + +class p3Ranking: public CacheSource, public CacheStore +{ + public: + + p3Ranking(uint16_t subtype, CacheTransfer *cft, + std::string sourcedir, std::string storedir, + uint32_t storePeriod); + +/******************************* CACHE SOURCE / STORE Interface *********************/ + + /* overloaded functions from Cache Source */ +virtual bool loadLocalCache(const CacheData &data); + + /* overloaded functions from Cache Store */ +virtual int loadCache(const CacheData &data); + +/******************************* CACHE SOURCE / STORE Interface *********************/ + + public: + +/************* Extern Interface *******/ + + /* Set Sort Methods */ +virtual bool setSortPeriod(uint32_t period); +virtual bool setSortMethod(uint32_t type); +virtual bool clearPeerFilter(); +virtual bool setPeerFilter(std::list peers); + + /* get Ids */ +virtual uint32_t getRankingsCount(); +virtual float getMaxRank(); +virtual bool getRankings(uint32_t first, uint32_t count, std::list &rids); +virtual bool getRankDetails(std::string rid, RsRankDetails &details); + + /* Add New Comment / Msg */ +virtual std::string newRankMsg(std::wstring link, std::wstring title, std::wstring comment); +virtual bool updateComment(std::string rid, std::wstring comment); + + +void tick(); + +void loadRankFile(std::string filename, std::string src); +void addRankMsg(RsRankMsg *msg); +void publishMsgs(); +float locked_calcRank(RankGroup &grp); /* returns 0->100 */ +void reSortGroup(RankGroup &grp); +void sortAllMsgs(); +pqistreamer *createStreamer(std::string file, std::string src, uint32_t bioflags); + + private: + +void createDummyData(); + + bool mRepublish; + uint32_t mStorePeriod; + + std::string mOwnId; + + std::map mData; + std::multimap mRankings; + + /* Filter/Sort params */ + std::list mPeerFilter; + uint32_t mViewPeriod; + uint32_t mSortType; + +}; + +#endif