From 6435357c07dda285371e78bbb7709298174ab0e4 Mon Sep 17 00:00:00 2001 From: drbob Date: Fri, 25 Jan 2008 06:36:40 +0000 Subject: [PATCH] Commit of the new UDP Connection methods and the rewrite of the retroshare core networking stack. This check-in commits the changes to the pqi code, and provides the majority of the improvements. (1) Introduced new interfaces for DHT and UPnP abstraction: p3dhtmgr.h, p3upnpmgr.h (2) Introduces abstraction for Authentication: p3authmgr.h (3) New Connection Manager to coordinate networking code: p3connmgr.h (4) New Configuration Manager: p3cfgmgr.h This library has been significantly modified to support DHT synced connections to enable connections between Firewalled Friends. The connection code has been rewritten within a new framework, which should make extensions easier to code. Also removed significant amount of old code relating to Tunnels, Channels etc. This will be recycled later as higher level services that should not be part of the core networking library. git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@306 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- libretroshare/src/pqi/Makefile | 58 +- libretroshare/src/pqi/authxpgp.cc | 1771 +++++++++++++ libretroshare/src/pqi/authxpgp.h | 177 ++ libretroshare/src/pqi/conn_test.cc | 350 +++ libretroshare/src/pqi/dht_test.cc | 295 +++ libretroshare/src/pqi/p3authmgr.cc | 226 ++ libretroshare/src/pqi/p3authmgr.h | 164 ++ libretroshare/src/pqi/p3cfgmgr.cc | 242 ++ libretroshare/src/pqi/p3cfgmgr.h | 156 ++ libretroshare/src/pqi/p3channel.cc | 1322 ---------- libretroshare/src/pqi/p3channel.h | 314 --- libretroshare/src/pqi/p3connmgr.cc | 1823 +++++++++++++ libretroshare/src/pqi/p3connmgr.h | 285 ++ libretroshare/src/pqi/p3dhtmgr.cc | 1337 ++++++++++ libretroshare/src/pqi/p3dhtmgr.h | 211 ++ .../src/pqi/{pqistunner.h => p3upnpmgr.h} | 52 +- libretroshare/src/pqi/pqi_base.h | 16 +- libretroshare/src/pqi/pqiaddrstore.h | 22 - libretroshare/src/pqi/pqiarchive.cc | 6 + libretroshare/src/pqi/pqiarchive.h | 3 + libretroshare/src/pqi/pqibin.cc | 271 +- libretroshare/src/pqi/pqibin.h | 39 +- libretroshare/src/pqi/pqichannel.cc | 610 ----- libretroshare/src/pqi/pqichannel.h | 111 - libretroshare/src/pqi/pqihandler.h | 15 - libretroshare/src/pqi/pqihash.h | 85 + libretroshare/src/pqi/pqiindic.h | 4 +- .../pqi/{pqitunneltst.cc => pqilistener.h} | 28 +- libretroshare/src/pqi/pqiloopback.cc | 33 +- libretroshare/src/pqi/pqiloopback.h | 10 +- libretroshare/src/pqi/pqimon.cc | 124 - libretroshare/src/pqi/pqimonitor.cc | 83 + libretroshare/src/pqi/pqimonitor.h | 132 + libretroshare/src/pqi/pqinetwork.cc | 11 +- libretroshare/src/pqi/pqinetwork.h | 1 + libretroshare/src/pqi/pqiperson.cc | 263 +- libretroshare/src/pqi/pqiperson.h | 33 +- libretroshare/src/pqi/pqipersongrp.cc | 456 ++-- libretroshare/src/pqi/pqipersongrp.h | 104 +- libretroshare/src/pqi/pqiproxy.cc | 2337 ----------------- libretroshare/src/pqi/pqiproxy.h | 376 --- libretroshare/src/pqi/pqissl.cc | 977 +------ libretroshare/src/pqi/pqissl.h | 79 +- libretroshare/src/pqi/pqissllistener.cc | 29 +- libretroshare/src/pqi/pqissllistener.h | 25 +- libretroshare/src/pqi/pqisslpersongrp.cc | 95 + .../src/pqi/{pqimon.h => pqisslpersongrp.h} | 54 +- libretroshare/src/pqi/pqissludp.cc | 884 +------ libretroshare/src/pqi/pqissludp.h | 83 +- libretroshare/src/pqi/pqistunner.cc | 264 -- libretroshare/src/pqi/pqitunnel.cc | 403 --- libretroshare/src/pqi/pqitunnel.h | 168 -- libretroshare/src/pqi/pqitunnelproxy.cc | 389 --- libretroshare/src/pqi/pqitunnelproxy.h | 120 - libretroshare/src/pqi/pqitunnelproxyudp.cc | 162 -- libretroshare/src/pqi/pqitunnelproxyudp.h | 65 - libretroshare/src/pqi/pqitunneltst.h | 146 - libretroshare/src/pqi/pqiudpproxy.cc | 859 ------ libretroshare/src/pqi/pqiudpproxy.h | 287 -- libretroshare/src/pqi/tstdns.cc | 16 - libretroshare/src/pqi/tstmsg.cc | 100 - libretroshare/src/pqi/xpgpcert.cc | 13 + libretroshare/src/pqi/xpgpcert.h | 1 + 63 files changed, 8336 insertions(+), 10839 deletions(-) create mode 100644 libretroshare/src/pqi/authxpgp.cc create mode 100644 libretroshare/src/pqi/authxpgp.h create mode 100644 libretroshare/src/pqi/conn_test.cc create mode 100644 libretroshare/src/pqi/dht_test.cc create mode 100644 libretroshare/src/pqi/p3authmgr.cc create mode 100644 libretroshare/src/pqi/p3authmgr.h create mode 100644 libretroshare/src/pqi/p3cfgmgr.cc create mode 100644 libretroshare/src/pqi/p3cfgmgr.h delete mode 100644 libretroshare/src/pqi/p3channel.cc delete mode 100644 libretroshare/src/pqi/p3channel.h create mode 100644 libretroshare/src/pqi/p3connmgr.cc create mode 100644 libretroshare/src/pqi/p3connmgr.h create mode 100644 libretroshare/src/pqi/p3dhtmgr.cc create mode 100644 libretroshare/src/pqi/p3dhtmgr.h rename libretroshare/src/pqi/{pqistunner.h => p3upnpmgr.h} (51%) delete mode 100644 libretroshare/src/pqi/pqiaddrstore.h delete mode 100644 libretroshare/src/pqi/pqichannel.cc delete mode 100644 libretroshare/src/pqi/pqichannel.h create mode 100644 libretroshare/src/pqi/pqihash.h rename libretroshare/src/pqi/{pqitunneltst.cc => pqilistener.h} (57%) delete mode 100644 libretroshare/src/pqi/pqimon.cc create mode 100644 libretroshare/src/pqi/pqimonitor.cc create mode 100644 libretroshare/src/pqi/pqimonitor.h delete mode 100644 libretroshare/src/pqi/pqiproxy.cc delete mode 100644 libretroshare/src/pqi/pqiproxy.h create mode 100644 libretroshare/src/pqi/pqisslpersongrp.cc rename libretroshare/src/pqi/{pqimon.h => pqisslpersongrp.h} (51%) delete mode 100644 libretroshare/src/pqi/pqistunner.cc delete mode 100644 libretroshare/src/pqi/pqitunnel.cc delete mode 100644 libretroshare/src/pqi/pqitunnel.h delete mode 100644 libretroshare/src/pqi/pqitunnelproxy.cc delete mode 100644 libretroshare/src/pqi/pqitunnelproxy.h delete mode 100644 libretroshare/src/pqi/pqitunnelproxyudp.cc delete mode 100644 libretroshare/src/pqi/pqitunnelproxyudp.h delete mode 100644 libretroshare/src/pqi/pqitunneltst.h delete mode 100644 libretroshare/src/pqi/pqiudpproxy.cc delete mode 100644 libretroshare/src/pqi/pqiudpproxy.h delete mode 100644 libretroshare/src/pqi/tstdns.cc delete mode 100644 libretroshare/src/pqi/tstmsg.cc diff --git a/libretroshare/src/pqi/Makefile b/libretroshare/src/pqi/Makefile index e4256f436..5428cfb82 100644 --- a/libretroshare/src/pqi/Makefile +++ b/libretroshare/src/pqi/Makefile @@ -3,42 +3,40 @@ RS_TOP_DIR = .. include ../make.opt # All the executables that should be generated. -EXECS = # test_p3items - -BASE_OBJ = pqi_base.o \ - pqidebug.o pqisecurity.o pqinetwork.o \ - pqibin.o pqimon.o \ +EXECS = dht_test conn_test # test_p3items +BASE_OBJ = pqi_base.o pqidebug.o pqisecurity.o pqinetwork.o LOOP_OBJ = pqiloopback.o +STREAM_OBJ = pqistreamer.o pqiarchive.o pqibin.o +MGR_OBJ = pqimonitor.o p3dhtmgr.o p3connmgr.o p3cfgmgr.o p3authmgr.o +GRP_OBJ = pqiperson.o pqihandler.o pqiservice.o pqipersongrp.o ifdef PQI_USE_XPGP - SSL_OBJ = xpgpcert.o + SSL_OBJ = authxpgp.o +#xpgpcert.o # Disabled for release... EXECS += p3supernode else SSL_OBJ = sslcert.o endif -SSL_OBJ += pqissl.o pqissllistener.o -GRP_OBJ = pqiperson.o pqihandler.o pqiservice.o pqipersongrp.o -STREAM_OBJ = pqistreamer.o pqiarchive.o +SSL_OBJ += pqissl.o pqissllistener.o pqisslpersongrp.o +UDP_OBJ = pqissludp.o - -OLD_OBJ = pqipacket.o p3loopback.o pqi.o -TUNN_OBJ = pqitunnel.o pqitunneltst.o -DISC_OBJ = discItem.o p3disc.o -UDP_OBJ = pqistunner.o pqiudpproxy.o pqissludp.o pqitunnelproxyudp.o - -PRXY_OBJ = pqiproxy.o pqitunnelproxy.o -CHAN_OBJ = p3channel.o pqichannel.o -SN_OBJ = pqisupernode.o +# Old code - no longer used! +#OLD_OBJ = pqipacket.o p3loopback.o pqi.o +#TUNN_OBJ = pqitunnel.o pqitunneltst.o +#DISC_OBJ = discItem.o p3disc.o +#UDP_OBJ = pqistunner.o pqiudpproxy.o pqissludp.o pqitunnelproxyudp.o +#PRXY_OBJ = pqiproxy.o pqitunnelproxy.o +#CHAN_OBJ = p3channel.o pqichannel.o +#SN_OBJ = pqisupernode.o OBJ = $(BASE_OBJ) $(LOOP_OBJ) \ - $(GRP_OBJ) $(SSL_OBJ) $(STREAM_OBJ) - -# Disabling this part of pqi core - until we have the basic -# items replaced by the new serialiser..... -# $(TUNN_OBJ) $(DISC_OBJ) \ -# $(CHAN_OBJ) $(PRXY_OBJ) $(UDP_OBJ) + $(STREAM_OBJ) \ + $(MGR_OBJ) \ + $(SSL_OBJ) \ + $(UDP_OBJ) \ + $(GRP_OBJ) # Linux only parts. ifeq ($(OS),Linux) @@ -85,14 +83,20 @@ librs: $(OBJ) $(OBJ) : $(HDR) -p3supernode: p3supernode.o librs - $(CC) $(CFLAGS) -o p3supernode p3supernode.o $(RSLIBS) +#p3supernode: p3supernode.o librs +# $(CC) $(CFLAGS) -o p3supernode p3supernode.o $(RSLIBS) + +dht_test: dht_test.o librs + $(CC) $(CFLAGS) -o dht_test dht_test.o $(RSLIBS) + +conn_test: conn_test.o librs + $(CC) $(CFLAGS) -o conn_test conn_test.o $(RSLIBS) .cc.o: $(CC) $(CFLAGS) -c $< clean: - -/bin/rm $(OBJ) p3supernode.o + -/bin/rm $(OBJ) clobber: clean -/bin/rm $(EXECS) $(LIBPQIA) $(LIBPQISO) diff --git a/libretroshare/src/pqi/authxpgp.cc b/libretroshare/src/pqi/authxpgp.cc new file mode 100644 index 000000000..ddf779e93 --- /dev/null +++ b/libretroshare/src/pqi/authxpgp.cc @@ -0,0 +1,1771 @@ +/* + * libretroshare/src/pqi: authxpgp.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-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 "authxpgp.h" + +#include "pqinetwork.h" + +#include +#include +#include + +#include +#include + +/******************************** TRUST LVLS +xPGP_vfy.h:#define TRUST_SIGN_OWN 6 +xPGP_vfy.h:#define TRUST_SIGN_TRSTED 5 +xPGP_vfy.h:#define TRUST_SIGN_AUTHEN 4 +xPGP_vfy.h:#define TRUST_SIGN_BASIC 3 +xPGP_vfy.h:#define TRUST_SIGN_UNTRUSTED 2 +xPGP_vfy.h:#define TRUST_SIGN_UNKNOWN 1 +xPGP_vfy.h:#define TRUST_SIGN_NONE 0 +xPGP_vfy.h:#define TRUST_SIGN_BAD -1 +******************************************************/ + + +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ + +#define AUTHXPGP_DEBUG 1 + +// the single instance of this. +static AuthXPGP instance_sslroot; + +p3AuthMgr *getAuthMgr() +{ + return &instance_sslroot; +} + + +xpgpcert::xpgpcert(XPGP *xpgp, std::string pid) +{ + certificate = xpgp; + id = pid; + name = getX509CNString(xpgp->subject -> subject); + org = getX509OrgString(xpgp->subject -> subject); + location = getX509LocString(xpgp->subject -> subject); + email = ""; + + /* These should be filled in afterwards */ + fpr = pid; + + trustLvl = 0; + ownsign = false; + trusted = false; +} + + +AuthXPGP::AuthXPGP() + :init(0), sslctx(NULL), pkey(NULL) +{ +} + +bool AuthXPGP::active() +{ + return init; +} + +// args: server cert, server private key, trusted certificates. + +int AuthXPGP::InitAuth(const char *cert_file, const char *priv_key_file, + const char *passwd) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::InitAuth()"; + std::cerr << std::endl; +#endif + +static int initLib = 0; + if (!initLib) + { + initLib = 1; + SSL_load_error_strings(); + SSL_library_init(); + } + + + if (init == 1) + { + return 1; + } + + if ((cert_file == NULL) || + (priv_key_file == NULL) || + (passwd == NULL)) + { + fprintf(stderr, "sslroot::initssl() missing parameters!\n"); + return 0; + } + + + // XXX TODO + // actions_to_seed_PRNG(); + + std::cerr << "SSL Library Init!" << std::endl; + + // setup connection method + sslctx = SSL_CTX_new(PGPv1_method()); + + // setup cipher lists. + SSL_CTX_set_cipher_list(sslctx, "DEFAULT"); + + // certificates (Set Local Server Certificate). + FILE *ownfp = fopen(cert_file, "r"); + if (ownfp == NULL) + { + std::cerr << "Couldn't open Own Certificate!" << std::endl; + return -1; + } + + + + // get xPGP certificate. + XPGP *xpgp = PEM_read_XPGP(ownfp, NULL, NULL, NULL); + fclose(ownfp); + + if (xpgp == NULL) + { + return -1; + } + SSL_CTX_use_pgp_certificate(sslctx, xpgp); + + // get private key + FILE *pkfp = fopen(priv_key_file, "rb"); + if (pkfp == NULL) + { + std::cerr << "Couldn't Open PrivKey File!" << std::endl; + CloseAuth(); + return -1; + } + + pkey = PEM_read_PrivateKey(pkfp, NULL, NULL, (void *) passwd); + fclose(pkfp); + + if (pkey == NULL) + { + return -1; + } + SSL_CTX_use_pgp_PrivateKey(sslctx, pkey); + + if (1 != SSL_CTX_check_pgp_private_key(sslctx)) + { + std::cerr << "Issues With Private Key! - Doesn't match your Cert" << std::endl; + std::cerr << "Check your input key/certificate:" << std::endl; + std::cerr << priv_key_file << " & " << cert_file; + std::cerr << std::endl; + CloseAuth(); + return -1; + } + + // make keyring. + pgp_keyring = createPGPContext(xpgp, pkey); + SSL_CTX_set_XPGP_KEYRING(sslctx, pgp_keyring); + + + // Setup the certificate. (after keyring is made!). + if (!XPGP_check_valid_certificate(xpgp)) + { + /* bad certificate */ + CloseAuth(); + return -1; + } + + if (!getXPGPid(xpgp, mOwnId)) + { + /* bad certificate */ + CloseAuth(); + return -1; + } + + + // enable verification of certificates (PEER) + SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER | + SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); + + std::cerr << "SSL Verification Set" << std::endl; + + mOwnCert = new xpgpcert(xpgp, mOwnId); + + /* add to keyring */ + XPGP_add_certificate(pgp_keyring, mOwnCert->certificate); + mOwnCert->trustLvl = XPGP_auth_certificate(pgp_keyring, mOwnCert->certificate); + mOwnCert->trusted = true; + mOwnCert->ownsign = true; + + init = 1; + return 1; +} + + + +bool AuthXPGP::CloseAuth() +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::CloseAuth()"; + std::cerr << std::endl; +#endif + SSL_CTX_free(sslctx); + + // clean up private key.... + // remove certificates etc -> opposite of initssl. + init = 0; + return 1; +} + +/* Context handling */ +SSL_CTX *AuthXPGP::getCTX() +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::getCTX()"; + std::cerr << std::endl; +#endif + return sslctx; +} + +int AuthXPGP::setConfigDirectories(const char *cdir, const char *ndir) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::setConfigDirectories()"; + std::cerr << std::endl; +#endif + xpgpMtx.lock(); /***** LOCK *****/ + + mCertDir = cdir; + mNeighDir = ndir; + + xpgpMtx.unlock(); /**** UNLOCK ****/ + return 1; +} + +std::string AuthXPGP::OwnId() +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::OwnId()"; + std::cerr << std::endl; +#endif + xpgpMtx.lock(); /***** LOCK *****/ + + std::string id = mOwnId; + + xpgpMtx.unlock(); /**** UNLOCK ****/ + return id; +} + +bool AuthXPGP::getAllList(std::list &ids) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::getAllList()"; + std::cerr << std::endl; +#endif + xpgpMtx.lock(); /***** LOCK *****/ + + /* iterate through both lists */ + std::map::iterator it; + + for(it = mCerts.begin(); it != mCerts.end(); it++) + { + ids.push_back(it->first); + } + + xpgpMtx.unlock(); /**** UNLOCK ****/ + + return true; +} + +bool AuthXPGP::getAuthenticatedList(std::list &ids) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::getAuthenticatedList()"; + std::cerr << std::endl; +#endif + xpgpMtx.lock(); /***** LOCK *****/ + + /* iterate through both lists */ + std::map::iterator it; + + for(it = mCerts.begin(); it != mCerts.end(); it++) + { + if (it->second->trustLvl > TRUST_SIGN_BASIC) + { + ids.push_back(it->first); + } + } + + xpgpMtx.unlock(); /**** UNLOCK ****/ + + return true; +} + +bool AuthXPGP::getUnknownList(std::list &ids) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::getUnknownList()"; + std::cerr << std::endl; +#endif + xpgpMtx.lock(); /***** LOCK *****/ + + /* iterate through both lists */ + std::map::iterator it; + + for(it = mCerts.begin(); it != mCerts.end(); it++) + { + if (it->second->trustLvl <= TRUST_SIGN_BASIC) + { + ids.push_back(it->first); + } + } + + xpgpMtx.unlock(); /**** UNLOCK ****/ + + return true; +} + + /* silly question really - only valid certs get saved to map + * so if in map its okay + */ +bool AuthXPGP::isValid(std::string id) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::isValid() " << id; + std::cerr << std::endl; +#endif + xpgpMtx.lock(); /***** LOCK *****/ + + bool valid = (mCerts.end() != mCerts.find(id)); + + xpgpMtx.unlock(); /**** UNLOCK ****/ + + return valid; +} + +bool AuthXPGP::isAuthenticated(std::string id) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::isAuthenticated() " << id; + std::cerr << std::endl; +#endif + xpgpMtx.lock(); /***** LOCK *****/ + + xpgpcert *cert = NULL; + bool auth = false; + + if (locked_FindCert(id, &cert)) + { + auth = (cert->trustLvl > TRUST_SIGN_BASIC); + } + + xpgpMtx.unlock(); /**** UNLOCK ****/ + + return auth; +} + +std::string AuthXPGP::getName(std::string id) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::getName() " << id; + std::cerr << std::endl; +#endif + std::string name; + + xpgpMtx.lock(); /***** LOCK *****/ + + xpgpcert *cert = NULL; + if (id == mOwnId) + { + name = mOwnCert->name; + } + else if (locked_FindCert(id, &cert)) + { + name = cert->name; + } + + xpgpMtx.unlock(); /**** UNLOCK ****/ + + return name; +} + +bool AuthXPGP::getDetails(std::string id, pqiAuthDetails &details) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::getDetails() " << id; + std::cerr << std::endl; +#endif + xpgpMtx.lock(); /***** LOCK *****/ + + bool valid = false; + xpgpcert *cert = NULL; + if (id == mOwnId) + { + cert = mOwnCert; + valid = true; + } + else if (locked_FindCert(id, &cert)) + { + valid = true; + } + + if (valid) + { + /* fill details */ + details.id = cert->id; + details.name = cert->name; + details.email = cert->email; + details.location= cert->location; + details.org = cert->org; + + details.fpr = cert->fpr; + details.signers = cert->signers; + + details.trustLvl= cert->trustLvl; + details.ownsign = cert->ownsign; + details.trusted = cert->trusted; + } + + xpgpMtx.unlock(); /**** UNLOCK ****/ + + return valid; +} + + + /* Load/Save certificates */ + +bool AuthXPGP::LoadCertificateFromString(std::string pem, std::string &id) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::LoadCertificateFromString() " << id; + std::cerr << std::endl; +#endif + + XPGP *xpgp = loadXPGPFromPEM(pem); + if (!xpgp) + return false; + + return ProcessXPGP(xpgp, id); +} + +std::string AuthXPGP::SaveCertificateToString(std::string id) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::SaveCertificateToString() " << id; + std::cerr << std::endl; +#endif + + + xpgpMtx.lock(); /***** LOCK *****/ + + /* get the cert first */ + std::string certstr; + xpgpcert *cert = NULL; + bool valid = false; + + if (id == mOwnId) + { + cert = mOwnCert; + valid = true; + } + else if (locked_FindCert(id, &cert)) + { + valid = true; + } + + if (valid) + { + BIO *bp = BIO_new(BIO_s_mem()); + + PEM_write_bio_XPGP(bp, cert->certificate); + + /* translate the bp data to a string */ + char *data; + int len = BIO_get_mem_data(bp, &data); + for(int i = 0; i < len; i++) + { + certstr += data[i]; + } + + BIO_free(bp); + } + + xpgpMtx.unlock(); /**** UNLOCK ****/ + + return certstr; +} + + + +bool AuthXPGP::LoadCertificateFromFile(std::string filename, std::string &id) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::LoadCertificateFromFile() " << id; + std::cerr << std::endl; +#endif + + std::string nullhash; + + XPGP *xpgp = loadXPGPFromFile(filename.c_str(), nullhash); + if (!xpgp) + return false; + + return ProcessXPGP(xpgp, id); +} + +bool AuthXPGP::SaveCertificateToFile(std::string id, std::string filename) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::SaveCertificateToFile() " << 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 = saveXPGPToFile(cert->certificate, filename, hash); + } + + xpgpMtx.unlock(); /**** UNLOCK ****/ + return valid; +} + + /* Signatures */ +bool AuthXPGP::SignCertificate(std::string id) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::SignCertificate() " << id; + std::cerr << std::endl; +#endif + + xpgpMtx.lock(); /***** LOCK *****/ + + /* get the cert first */ + xpgpcert *cert = NULL; + xpgpcert *own = mOwnCert; + bool valid = false; + + if (locked_FindCert(id, &cert)) + { + XPGP_sign_certificate(pgp_keyring, cert->certificate, own->certificate); + + /* reevaluate the auth of the xpgp */ + cert->trustLvl = XPGP_auth_certificate(pgp_keyring, cert->certificate); + cert->ownsign = true; + valid = true; + } + + xpgpMtx.unlock(); /**** UNLOCK ****/ + return valid; +} + +bool AuthXPGP::TrustCertificate(std::string id, bool totrust) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::TrustCertificate() " << id; + std::cerr << std::endl; +#endif + + xpgpMtx.lock(); /***** LOCK *****/ + + /* get the cert first */ + xpgpcert *cert = NULL; + bool valid = false; + + if (locked_FindCert(id, &cert)) + { + + /* if trusted -> untrust */ + if (!totrust) + { + XPGP_signer_untrusted(pgp_keyring, cert->certificate); + cert->trusted = false; + } + else + { + /* if auth then we can trust them */ + if (XPGP_signer_trusted(pgp_keyring, cert->certificate)) + { + cert->trusted = true; + } + } + + /* reevaluate the auth of the xpgp */ + cert->trustLvl = XPGP_auth_certificate(pgp_keyring, cert->certificate); + valid = true; + } + + xpgpMtx.unlock(); /**** UNLOCK ****/ + return valid; +} + +bool AuthXPGP::RevokeCertificate(std::string id) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::RevokeCertificate() " << id; + std::cerr << std::endl; +#endif + + xpgpMtx.lock(); /***** LOCK *****/ + xpgpMtx.unlock(); /**** UNLOCK ****/ + + return false; +} + + +bool AuthXPGP::AuthCertificate(std::string id) +{ + +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::AuthCertificate() " << id; + std::cerr << std::endl; +#endif + + xpgpMtx.lock(); /***** LOCK *****/ + + /* get the cert first */ + xpgpcert *cert = NULL; + xpgpcert *own = mOwnCert; + bool valid = false; + + if (locked_FindCert(id, &cert)) + { + /* ADD IN LATER */ + //if (cert->trustLvl > TRUST_SIGN_BASIC) + //{ +#ifdef AUTHXPGP_DEBUG + // std::cerr << "AuthXPGP::AuthCertificate() Already Authed: " << id; + // std::cerr << std::endl; +#endif + //} + + if (0 < validateCertificateIsSignedByKey( + cert->certificate, own->certificate)) + { +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::AuthCertificate() Signed Already: " << id; + std::cerr << std::endl; +#endif + cert->ownsign=true; + } + else + { +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::AuthCertificate() Signing Cert: " << id; + std::cerr << std::endl; +#endif + /* sign certificate */ + XPGP_sign_certificate(pgp_keyring, cert->certificate, own->certificate); + + /* reevaluate the auth of the xpgp */ + cert->trustLvl = XPGP_auth_certificate(pgp_keyring, cert->certificate); + cert->ownsign = true; + } + valid = true; + } + + xpgpMtx.unlock(); /**** UNLOCK ****/ + return valid; +} + + + + /* Sign / Encrypt / Verify Data (TODO) */ + + + /**** NEW functions we've added ****/ + + + + + /**** AUX Functions ****/ +bool AuthXPGP::locked_FindCert(std::string id, xpgpcert **cert) +{ + std::map::iterator it; + + if (mCerts.end() != (it = mCerts.find(id))) + { + *cert = it->second; + return true; + } + return false; +} + + +XPGP *AuthXPGP::loadXPGPFromFile(std::string fname, std::string hash) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::LoadXPGPFromFile()"; + std::cerr << std::endl; +#endif + + // if there is a hash - check that the file matches it before loading. + XPGP *pc = NULL; + FILE *pcertfp = fopen(fname.c_str(), "rb"); + + // load certificates from file. + if (pcertfp == NULL) + { + std::cerr << "sslroot::loadcertificate() Bad File: " << fname; + std::cerr << " Cannot be Hashed!" << std::endl; + return NULL; + } + + /* We only check a signature's hash if + * we are loading from a configuration file. + * Therefore we saved the file and it should be identical. + * and a direct load + verify will work. + * + * If however it has been transported by email.... + * Then we might have to correct the data (strip out crap) + * from the configuration at the end. (XPGP load should work!) + */ + + if (hash.length() > 1) + { + + unsigned int signlen = EVP_PKEY_size(pkey); + unsigned char signature[signlen]; + + int maxsize = 20480; /* should be enough for about 50 signatures */ + int rbytes; + char inall[maxsize]; + if (0 == (rbytes = fread(inall, 1, maxsize, pcertfp))) + { + std::cerr << "Error Reading Peer Record!" << std::endl; + return NULL; + } + //std::cerr << "Read " << rbytes << std::endl; + + + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + + if (0 == EVP_SignInit_ex(mdctx, EVP_sha1(), NULL)) + { + std::cerr << "EVP_SignInit Failure!" << std::endl; + } + + if (0 == EVP_SignUpdate(mdctx, inall, rbytes)) + { + std::cerr << "EVP_SignUpdate Failure!" << std::endl; + } + + if (0 == EVP_SignFinal(mdctx, signature, &signlen, pkey)) + { + std::cerr << "EVP_SignFinal Failure!" << std::endl; + } + + EVP_MD_CTX_destroy(mdctx); + + bool same = true; + if (signlen != hash.length()) + { + std::cerr << "Different Length Signatures... "; + std::cerr << "Cannot Load Certificate!" << std::endl; + fclose(pcertfp); + return NULL; + } + + for(int i = 0; i < (signed) signlen; i++) + { + if (signature[i] != (unsigned char) hash[i]) + { + same = false; + std::cerr << "Invalid Signature... "; + std::cerr << "Cannot Load Certificate!" << std::endl; + fclose(pcertfp); + return NULL; + } + } + std::cerr << "Verified Signature for: " << fname; + std::cerr << std::endl; + } + else + { + std::cerr << "Not checking cert signature" << std::endl; + } + + fseek(pcertfp, 0, SEEK_SET); /* rewind */ + pc = PEM_read_XPGP(pcertfp, NULL, NULL, NULL); + fclose(pcertfp); + + if (pc != NULL) + { + // read a certificate. + std::cerr << "Loaded Certificate: " << pc -> name << std::endl; + } + else // (pc == NULL) + { + unsigned long err = ERR_get_error(); + std::cerr << "Read Failed .... CODE(" << err << ")" << std::endl; + std::cerr << ERR_error_string(err, NULL) << std::endl; + + return NULL; + } + return pc; +} + +bool AuthXPGP::saveXPGPToFile(XPGP *xpgp, std::string fname, std::string &hash) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::saveXPGPToFile()"; + std::cerr << std::endl; +#endif + + // load certificates from file. + FILE *setfp = fopen(fname.c_str(), "wb"); + if (setfp == NULL) + { + std::cerr << "sslroot::savecertificate() Bad File: " << fname; + std::cerr << " Cannot be Written!" << std::endl; + return false; + } + + std::cerr << "Writing out Cert...:" << xpgp->name << std::endl; + PEM_write_XPGP(setfp, xpgp); + + fclose(setfp); + + // then reopen to generate hash. + setfp = fopen(fname.c_str(), "rb"); + if (setfp == NULL) + { + std::cerr << "sslroot::savecertificate() Bad File: " << fname; + std::cerr << " Opened for ReHash!" << std::endl; + return false; + } + + unsigned int signlen = EVP_PKEY_size(pkey); + unsigned char signature[signlen]; + + int maxsize = 20480; + int rbytes; + char inall[maxsize]; + if (0 == (rbytes = fread(inall, 1, maxsize, setfp))) + { + std::cerr << "Error Writing Peer Record!" << std::endl; + return -1; + } + std::cerr << "Read " << rbytes << std::endl; + + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + + if (0 == EVP_SignInit_ex(mdctx, EVP_sha1(), NULL)) + { + std::cerr << "EVP_SignInit Failure!" << std::endl; + } + + if (0 == EVP_SignUpdate(mdctx, inall, rbytes)) + { + std::cerr << "EVP_SignUpdate Failure!" << std::endl; + } + + if (0 == EVP_SignFinal(mdctx, signature, &signlen, pkey)) + { + std::cerr << "EVP_SignFinal Failure!" << std::endl; + } + + std::cerr << "Saved Cert: " << xpgp->name; + std::cerr << std::endl; + + std::cerr << "Cert + Setting Signature is(" << signlen << "): "; + std::string signstr; + for(uint32_t i = 0; i < signlen; i++) + { + fprintf(stderr, "%02x", signature[i]); + signstr += signature[i]; + } + std::cerr << std::endl; + + hash = signstr; + fclose(setfp); + + EVP_MD_CTX_destroy(mdctx); + + return true; +} + + +XPGP *AuthXPGP::loadXPGPFromPEM(std::string pem) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::LoadXPGPFromPEM()"; + std::cerr << std::endl; +#endif + + /* Put the data into a mem BIO */ + char *certstr = strdup(pem.c_str()); + + BIO *bp = BIO_new_mem_buf(certstr, -1); + + XPGP *pc = PEM_read_bio_XPGP(bp, NULL, NULL, NULL); + + BIO_free(bp); + free(certstr); + + return pc; +} + +XPGP *AuthXPGP::loadXPGPFromDER(char *data, uint32_t len) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::LoadXPGPFromDER()"; + std::cerr << std::endl; +#endif + + /**** TODO ****/ + return NULL; +} + +bool AuthXPGP::ProcessXPGP(XPGP *xpgp, std::string &id) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::ProcessXPGP()"; + std::cerr << std::endl; +#endif + + /* extract id */ + std::string xpgpid; + + if (!XPGP_check_valid_certificate(xpgp)) + { + /* bad certificate */ + XPGP_free(xpgp); + return false; + } + + if (!getXPGPid(xpgp, xpgpid)) + { + /* bad certificate */ + XPGP_free(xpgp); + return false; + } + + xpgpcert *cert = NULL; + bool duplicate = false; + + xpgpMtx.lock(); /***** LOCK *****/ + + if (xpgpid == mOwnId) + { + cert = mOwnCert; + duplicate = true; + } + else if (locked_FindCert(xpgpid, &cert)) + { + duplicate = true; + } + + if (duplicate) + { + /* have a duplicate */ + /* check that they are exact */ + if (0 != XPGP_cmp(cert->certificate, xpgp)) + { + /* MAJOR ERROR */ + XPGP_free(xpgp); + xpgpMtx.unlock(); /**** UNLOCK ****/ + return false; + } + + /* transfer new signatures */ + XPGP_copy_known_signatures(pgp_keyring, cert->certificate, xpgp); + XPGP_free(xpgp); + + /* we accepted it! */ + id = xpgpid; + + /* update signers */ + cert->signers = getXPGPsigners(cert->certificate); + + xpgpMtx.unlock(); /**** UNLOCK ****/ + return true; + } + + xpgpMtx.unlock(); /**** UNLOCK ****/ + + /* if we get here -> its a new certificate */ + cert = new xpgpcert(xpgp, xpgpid); + + xpgpMtx.lock(); /***** LOCK *****/ + + /* add to keyring */ + XPGP_add_certificate(pgp_keyring, cert->certificate); + mCerts[xpgpid] = cert; + + cert -> trustLvl = XPGP_auth_certificate(pgp_keyring, cert->certificate); + if (cert -> trustLvl == TRUST_SIGN_TRSTED) + { + cert->trusted = true; + cert->ownsign = true; + } + else if (cert->trustLvl == TRUST_SIGN_OWN) + { + cert->ownsign = true; + } + + cert->signers = getXPGPsigners(xpgp); + + xpgpMtx.unlock(); /**** UNLOCK ****/ + + id = xpgpid; + + return true; +} + + +bool AuthXPGP::getXPGPid(XPGP *xpgp, std::string &xpgpid) +{ +#ifdef AUTHXPGP_DEBUG + std::cerr << "AuthXPGP::getXPGPid()"; + std::cerr << std::endl; +#endif + + xpgpid = ""; + if (xpgp == NULL) + { +#ifdef XPGP_DEBUG + std::cerr << "AuthXPGP::getXPGPid() NULL pointer"; + std::cerr << std::endl; +#endif + return false; + } + + // get the first signature.... + if (sk_XPGP_SIGNATURE_num(xpgp->signs) < 1) + { +#ifdef XPGP_DEBUG + std::cerr << "AuthXPGP::getXPGPid() ERROR: No Signature"; + std::cerr << std::endl; +#endif + return false; + } + XPGP_SIGNATURE *xpgpsign = sk_XPGP_SIGNATURE_value(xpgp->signs, 0); + + // Validate that it is a self signature. + // (Already Done - but not in this function) + + // get the signature from the cert, and copy to the array. + ASN1_BIT_STRING *signature = xpgpsign->signature; + int signlen = ASN1_STRING_length(signature); + if (signlen < CERTSIGNLEN) + { +#ifdef XPGP_DEBUG + std::cerr << "AuthXPGP::getXPGPid() ERROR: Short Signature"; + std::cerr << std::endl; +#endif + return false; + } + + // else copy in the first CERTSIGNLEN. + unsigned char *signdata = ASN1_STRING_data(signature); + + std::ostringstream id; + for(uint32_t i = 0; i < CERTSIGNLEN; i++) + { + id << std::hex << std::setw(2) << std::setfill('0') + << (uint16_t) (((uint8_t *) (signdata))[i]); + } + xpgpid = id.str(); + return true; +} + + +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ + +int pem_passwd_cb(char *buf, int size, int rwflag, void *password) +{ + strncpy(buf, (char *)(password), size); + buf[size - 1] = '\0'; + return(strlen(buf)); +} + +// Not dependent on sslroot. load, and detroys the XPGP memory. + +int LoadCheckXPGPandGetName(const char *cert_file, std::string &userName) +{ + /* This function loads the XPGP certificate from the file, + * and checks the certificate + */ + + FILE *tmpfp = fopen(cert_file, "r"); + if (tmpfp == NULL) + { + std::cerr << "sslroot::LoadCheckAndGetXPGPName()"; + std::cerr << " Failed to open Certificate File:" << cert_file; + std::cerr << std::endl; + return 0; + } + + // get xPGP certificate. + XPGP *xpgp = PEM_read_XPGP(tmpfp, NULL, NULL, NULL); + fclose(tmpfp); + + // check the certificate. + bool valid = false; + if (xpgp) + { + valid = XPGP_check_valid_certificate(xpgp); + } + + if (valid) + { + // extract the name. + userName = getX509CNString(xpgp->subject->subject); + } + + // clean up. + XPGP_free(xpgp); + + if (valid) + { + // happy! + return 1; + } + else + { + // something went wrong! + return 0; + } +} + +std::string getX509NameString(X509_NAME *name) +{ + std::string namestr; + for(int i = 0; i < X509_NAME_entry_count(name); i++) + { + X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i); + ASN1_STRING *entry_data = X509_NAME_ENTRY_get_data(entry); + ASN1_OBJECT *entry_obj = X509_NAME_ENTRY_get_object(entry); + + namestr += "\t"; + namestr += OBJ_nid2ln(OBJ_obj2nid(entry_obj)); + namestr += " : "; + + //namestr += entry_obj -> flags; + //namestr += entry_data -> length; + //namestr += entry_data -> type; + + //namestr += entry_data -> flags; + //entry -> set; + + if (entry_data -> data != NULL) + { + namestr += (char *) entry_data -> data; + } + else + { + namestr += "NULL"; + } + + if (i + 1 < X509_NAME_entry_count(name)) + { + namestr += "\n"; + } + + } + return namestr; +} + + +std::string getX509CNString(X509_NAME *name) +{ + std::string namestr; + for(int i = 0; i < X509_NAME_entry_count(name); i++) + { + X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i); + ASN1_STRING *entry_data = X509_NAME_ENTRY_get_data(entry); + ASN1_OBJECT *entry_obj = X509_NAME_ENTRY_get_object(entry); + + if (0 == strncmp("CN", OBJ_nid2sn(OBJ_obj2nid(entry_obj)), 2)) + { + if (entry_data -> data != NULL) + { + namestr += (char *) entry_data -> data; + } + else + { + namestr += "Unknown"; + } + return namestr; + } + } + return namestr; +} + + +std::string getX509TypeString(X509_NAME *name, char *type, int len) +{ + std::string namestr; + for(int i = 0; i < X509_NAME_entry_count(name); i++) + { + X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i); + ASN1_STRING *entry_data = X509_NAME_ENTRY_get_data(entry); + ASN1_OBJECT *entry_obj = X509_NAME_ENTRY_get_object(entry); + + if (0 == strncmp(type, OBJ_nid2sn(OBJ_obj2nid(entry_obj)), len)) + { + if (entry_data -> data != NULL) + { + namestr += (char *) entry_data -> data; + } + else + { + namestr += "Unknown"; + } + return namestr; + } + } + return namestr; +} + + +std::string getX509LocString(X509_NAME *name) +{ + return getX509TypeString(name, "L", 2); +} + +std::string getX509OrgString(X509_NAME *name) +{ + return getX509TypeString(name, "O", 2); +} + + +std::string getX509CountryString(X509_NAME *name) +{ + return getX509TypeString(name, "C", 2); +} + + +std::string getXPGPInfo(XPGP *cert) +{ + std::stringstream out; + long l; + int i,j; + + out << "XPGP Certificate:" << std::endl; + l=XPGP_get_version(cert); + out << " Version: " << l+1 << "(0x" << l << ")" << std::endl; + out << " Subject: " << std::endl; + out << " " << getX509NameString(cert -> subject -> subject); + out << std::endl; + out << std::endl; + out << " Signatures:" << std::endl; + + for(i = 0; i < sk_XPGP_SIGNATURE_num(cert->signs); i++) + { + out << "Sign[" << i << "] -> ["; + + XPGP_SIGNATURE *sig = sk_XPGP_SIGNATURE_value(cert->signs,i); + ASN1_BIT_STRING *signature = sig->signature; + int signlen = ASN1_STRING_length(signature); + unsigned char *signdata = ASN1_STRING_data(signature); + + /* only show the first 8 bytes */ + if (signlen > 8) + signlen = 8; + for(j=0;jissuer); + out << std::endl; + out << std::endl; + } + + return out.str(); +} + + + +std::string getXPGPAuthCode(XPGP *xpgp) +{ + /* get the self signature -> the first signature */ + + std::stringstream out; + if (1 > sk_XPGP_SIGNATURE_num(xpgp->signs)) + { + out.str(); + } + + XPGP_SIGNATURE *sig = sk_XPGP_SIGNATURE_value(xpgp->signs,0); + ASN1_BIT_STRING *signature = sig->signature; + int signlen = ASN1_STRING_length(signature); + unsigned char *signdata = ASN1_STRING_data(signature); + + /* extract the authcode from the signature */ + /* convert it to a string, inverse of 2 bytes of signdata */ + if (signlen > 2) + signlen = 2; + int j; + for(j=0;j getXPGPsigners(XPGP *cert) +{ + std::list signers; + int i; + + for(i = 0; i < sk_XPGP_SIGNATURE_num(cert->signs); i++) + { + XPGP_SIGNATURE *sig = sk_XPGP_SIGNATURE_value(cert->signs,i); + std::string str = getX509CNString(sig->issuer); + signers.push_back(str); + std::cerr << "XPGPsigners(" << i << ")" << str << std::endl; + } + return signers; +} + + + +/********** SSL ERROR STUFF ******************************************/ + +int printSSLError(SSL *ssl, int retval, int err, unsigned long err2, + std::ostream &out) +{ + std::string reason; + + std::string mainreason = std::string("UNKNOWN ERROR CODE"); + if (err == SSL_ERROR_NONE) + { + mainreason = std::string("SSL_ERROR_NONE"); + } + else if (err == SSL_ERROR_ZERO_RETURN) + { + mainreason = std::string("SSL_ERROR_ZERO_RETURN"); + } + else if (err == SSL_ERROR_WANT_READ) + { + mainreason = std::string("SSL_ERROR_WANT_READ"); + } + else if (err == SSL_ERROR_WANT_WRITE) + { + mainreason = std::string("SSL_ERROR_WANT_WRITE"); + } + else if (err == SSL_ERROR_WANT_CONNECT) + { + mainreason = std::string("SSL_ERROR_WANT_CONNECT"); + } + else if (err == SSL_ERROR_WANT_ACCEPT) + { + mainreason = std::string("SSL_ERROR_WANT_ACCEPT"); + } + else if (err == SSL_ERROR_WANT_X509_LOOKUP) + { + mainreason = std::string("SSL_ERROR_WANT_X509_LOOKUP"); + } + else if (err == SSL_ERROR_SYSCALL) + { + mainreason = std::string("SSL_ERROR_SYSCALL"); + } + else if (err == SSL_ERROR_SSL) + { + mainreason = std::string("SSL_ERROR_SSL"); + } + out << "RetVal(" << retval; + out << ") -> SSL Error: " << mainreason << std::endl; + out << "\t + ERR Error: " << ERR_error_string(err2, NULL) << std::endl; + return 1; +} + + +#if 0 + +int AuthXPGP::saveCertificates(const char *fname) +{ + // construct file name. + // + // create the file in memory - hash + sign. + // write out data to a file. + + std::string neighdir = certdir + "/" + neighbourdir + "/"; + std::string configname = certdir + "/"; + configname += fname; + + std::map::iterator mit; + + + std::string conftxt; + std::string empty(""); + unsigned int i; + + std::list::iterator it; + for(it = peercerts.begin(); it != peercerts.end(); it++) + { + std::string neighfile = neighdir + getCertName(*it) + ".pqi"; + savecertificate((*it), neighfile.c_str()); + conftxt += "CERT "; + conftxt += getCertName(*it); + conftxt += "\n"; + conftxt += (*it) -> Hash(); + conftxt += "\n"; + std::cerr << std::endl; + } + + // now work out signature of it all. This relies on the + // EVP library of openSSL..... We are going to use signing + // for the moment. + + unsigned int signlen = EVP_PKEY_size(pkey); + unsigned char signature[signlen]; + + //OpenSSL_add_all_digests(); + + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + + if (0 == EVP_SignInit_ex(mdctx, EVP_sha1(), NULL)) + { + std::cerr << "EVP_SignInit Failure!" << std::endl; + } + + if (0 == EVP_SignUpdate(mdctx, conftxt.c_str(), conftxt.length())) + { + std::cerr << "EVP_SignUpdate Failure!" << std::endl; + } + + + if (0 == EVP_SignFinal(mdctx, signature, &signlen, pkey)) + { + std::cerr << "EVP_SignFinal Failure!" << std::endl; + } + + std::cerr << "Conf Signature is(" << signlen << "): "; + for(i = 0; i < signlen; i++) + { + fprintf(stderr, "%02x", signature[i]); + conftxt += signature[i]; + } + std::cerr << std::endl; + + FILE *cfd = fopen(configname.c_str(), "wb"); + int wrec; + if (1 != (wrec = fwrite(conftxt.c_str(), conftxt.length(), 1, cfd))) + { + std::cerr << "Error writing: " << configname << std::endl; + std::cerr << "Wrote: " << wrec << "/" << 1 << " Records" << std::endl; + } + + EVP_MD_CTX_destroy(mdctx); + fclose(cfd); + + return 1; +} + +int sslroot::loadCertificates(const char *conf_fname) +{ + // open the configuration file. + // + // read in CERT + Hash. + + // construct file name. + // + // create the file in memory - hash + sign. + // write out data to a file. + + std::string neighdir = certdir + "/" + neighbourdir + "/"; + std::string configname = certdir + "/"; + configname += conf_fname; + + // save name for later save attempts. + certfile = conf_fname; + + std::string conftxt; + + unsigned int maxnamesize = 1024; + char name[maxnamesize]; + + int c; + unsigned int i; + + FILE *cfd = fopen(configname.c_str(), "rb"); + if (cfd == NULL) + { + std::cerr << "Unable to Load Configuration File!" << std::endl; + std::cerr << "File: " << configname << std::endl; + return -1; + } + + std::list fnames; + std::list hashes; + std::map::iterator mit; + std::map tmpsettings; + + unsigned int signlen = EVP_PKEY_size(pkey); + unsigned char conf_signature[signlen]; + char *ret = NULL; + + for(ret = fgets(name, maxnamesize, cfd); + ((ret != NULL) && (!strncmp(name, "CERT ", 5))); + ret = fgets(name, maxnamesize, cfd)) + { + for(i = 5; (name[i] != '\n') && (i < (unsigned) maxnamesize); i++); + + if (name[i] == '\n') + { + name[i] = '\0'; + } + + // so the name is first.... + std::string fname = &(name[5]); + + // now read the + std::string hash; + std::string signature; + + for(i = 0; i < signlen; i++) + { + if (EOF == (c = fgetc(cfd))) + { + std::cerr << "Error Reading Signature of: "; + std::cerr << fname; + std::cerr << std::endl; + std::cerr << "ABorting Load!"; + std::cerr << std::endl; + return -1; + } + unsigned char uc = (unsigned char) c; + signature += (unsigned char) uc; + } + if ('\n' != (c = fgetc(cfd))) + { + std::cerr << "Warning Mising seperator" << std::endl; + } + + std::cerr << "Read fname:" << fname << std::endl; + std::cerr << "Signature:" << std::endl; + for(i = 0; i < signlen; i++) + { + fprintf(stderr, "%02x", (unsigned char) signature[i]); + } + std::cerr << std::endl; + std::cerr << std::endl; + + // push back..... + fnames.push_back(fname); + hashes.push_back(signature); + + conftxt += "CERT "; + conftxt += fname; + conftxt += "\n"; + conftxt += signature; + conftxt += "\n"; + + // be sure to write over a bit... + name[0] = 'N'; + name[1] = 'O'; + } + + // string already waiting! + for(; ((ret != NULL) && (!strncmp(name, "OPT ", 4))); + ret = fgets(name, maxnamesize, cfd)) + { + for(i = 4; (name[i] != '\n') && (i < OPT_LEN); i++); + // terminate the string. + name[i] = '\0'; + + // so the name is first.... + std::string opt = &(name[4]); + + // now read the + std::string val; // cleaned up value. + std::string valsign; // value in the file. + for(i = 0; i < VAL_LEN; i++) + { + if (EOF == (c = fgetc(cfd))) + { + std::cerr << "Error Reading Value of: "; + std::cerr << opt; + std::cerr << std::endl; + std::cerr << "ABorting Load!"; + std::cerr << std::endl; + return -1; + } + // remove zeros on strings... + if (c != '\0') + { + val += (unsigned char) c; + } + valsign += (unsigned char) c; + } + if ('\n' != (c = fgetc(cfd))) + { + std::cerr << "Warning Mising seperator" << std::endl; + } + + std::cerr << "Read OPT:" << opt; + std::cerr << " Val:" << val << std::endl; + + // push back..... + tmpsettings[opt] = val; + + conftxt += "OPT "; + conftxt += opt; + conftxt += "\n"; + conftxt += valsign; + conftxt += "\n"; + + // be sure to write over a bit... + name[0] = 'N'; + name[1] = 'O'; + } + + // only read up to the first newline symbol.... + // continue... + for(i = 0; (name[i] != '\n') && (i < signlen); i++); + + //printf("Stepping over [%d] %0x\n", i, name[i]); + + + if (i != signlen) + { + for(i++; i < signlen; i++) + { + c = fgetc(cfd); + if (c == EOF) + { + std::cerr << "Error Reading Conf Signature:"; + std::cerr << std::endl; + return 1; + } + unsigned char uc = (unsigned char) c; + name[i] = uc; + } + } + + std::cerr << "Configuration File Signature: " << std::endl; + for(i = 0; i < signlen; i++) + { + fprintf(stderr, "%02x", (unsigned char) name[i]); + } + std::cerr << std::endl; + + + // when we get here - should have the final signature in the buffer. + // check. + // + // compare signatures. + // instead of verifying with the public key.... + // we'll sign it again - and compare .... FIX LATER... + + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + + if (0 == EVP_SignInit(mdctx, EVP_sha1())) + { + std::cerr << "EVP_SignInit Failure!" << std::endl; + } + + if (0 == EVP_SignUpdate(mdctx, conftxt.c_str(), conftxt.length())) + { + std::cerr << "EVP_SignUpdate Failure!" << std::endl; + } + + if (0 == EVP_SignFinal(mdctx, conf_signature, &signlen, pkey)) + { + std::cerr << "EVP_SignFinal Failure!" << std::endl; + } + + EVP_MD_CTX_destroy(mdctx); + fclose(cfd); + + std::cerr << "Recalced File Signature: " << std::endl; + for(i = 0; i < signlen; i++) + { + fprintf(stderr, "%02x", conf_signature[i]); + } + std::cerr << std::endl; + + bool same = true; + for(i = 0; i < signlen; i++) + { + if ((unsigned char) name[i] != conf_signature[i]) + { + same = false; + } + } + + if (same == false) + { + std::cerr << "ERROR VALIDATING CONFIGURATION!" << std::endl; + std::cerr << "PLEASE FIX!" << std::endl; + return -1; + } + std::list::iterator it; + std::list::iterator it2; + for(it = fnames.begin(), it2 = hashes.begin(); it != fnames.end(); it++, it2++) + { + std::string neighfile = neighdir + (*it) + ".pqi"; + cert *nc = loadcertificate(neighfile.c_str(), (*it2)); + if (nc != NULL) + { + if (0 > addCertificate(nc)) + { + // cleanup. + std::cerr << "Updated Certificate....but no"; + std::cerr << " need for addition"; + std::cerr << std::endl; + // X509_free(nc -> certificate); + //delete nc; + } + } + } + for(mit = tmpsettings.begin(); mit != tmpsettings.end(); mit++) + { + settings[mit -> first] = mit -> second; + } + return 1; +} + +#endif diff --git a/libretroshare/src/pqi/authxpgp.h b/libretroshare/src/pqi/authxpgp.h new file mode 100644 index 000000000..c98f061f6 --- /dev/null +++ b/libretroshare/src/pqi/authxpgp.h @@ -0,0 +1,177 @@ +/* + * libretroshare/src/pqi: authxpgp.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-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 MRK_AUTH_SSL_XPGP_HEADER +#define MRK_AUTH_SSL_XPGP_HEADER + +/* This is the trial XPGP version + * + * It has to be compiled against XPGP ssl version. + * this is only a hacked up version, merging + * (so both can operate in parallel will happen later) + * + */ + +#include +#include + +#include +#include + +#include "util/rsthreads.h" + +#include "pqi/pqi_base.h" +#include "pqi/pqinetwork.h" +#include "pqi/p3authmgr.h" + +class AuthXPGP; + + +class xpgpcert +{ + public: + xpgpcert(XPGP *xpgp, std::string id); + + /* certificate parameters */ + std::string id; + std::string name; + std::string location; + std::string org; + std::string email; + + std::string fpr; + std::list signers; + + /* Auth settings */ + + uint32_t trustLvl; + bool ownsign; + bool trusted; + + /* INTERNAL Parameters */ + XPGP *certificate; +}; + +class AuthXPGP: public p3AuthMgr +{ + public: + + /* Initialisation Functions (Unique) */ + AuthXPGP(); +virtual bool active(); +virtual int InitAuth(const char *srvr_cert, const char *priv_key, + const char *passwd); +virtual bool CloseAuth(); +virtual int setConfigDirectories(const char *cdir, const char *ndir); + + /*********** Overloaded Functions from p3AuthMgr **********/ + + /* get Certificate Ids */ + +virtual std::string OwnId(); +virtual bool getAllList(std::list &ids); +virtual bool getAuthenticatedList(std::list &ids); +virtual bool getUnknownList(std::list &ids); + + /* get Details from the Certificates */ + +virtual bool isValid(std::string id); +virtual bool isAuthenticated(std::string id); +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); + + /* Signatures */ + +virtual bool AuthCertificate(std::string uid); +virtual bool SignCertificate(std::string id); +virtual bool RevokeCertificate(std::string id); +virtual bool TrustCertificate(std::string id, bool trust); + + /* Sign / Encrypt / Verify Data (TODO) */ + + + /**** NEW functions we've added ****/ + + + /*********** Overloaded Functions from p3AuthMgr **********/ + + private: + + /* Helper Functions */ +SSL_CTX *getCTX(); + +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); + + /*********** LOCKED Functions ******/ +bool locked_FindCert(std::string id, xpgpcert **cert); + + + /* Data */ + RsMutex xpgpMtx; /**** LOCKING */ + + int init; + std::string mCertDir; + std::string mNeighDir; + + SSL_CTX *sslctx; + XPGP_KEYRING *pgp_keyring; + + std::string mOwnId; + xpgpcert *mOwnCert; + EVP_PKEY *pkey; + + std::map mCerts; + +}; + +/* Helper Functions */ +int printSSLError(SSL *ssl, int retval, int err, unsigned long err2, std::ostream &out); +std::string getX509NameString(X509_NAME *name); +std::string getX509CNString(X509_NAME *name); + +std::string getX509OrgString(X509_NAME *name); +std::string getX509LocString(X509_NAME *name); +std::string getX509CountryString(X509_NAME *name); + +std::list getXPGPsigners(XPGP *cert); +std::string getXPGPInfo(XPGP *cert); +std::string getXPGPAuthCode(XPGP *xpgp); + +int LoadCheckXPGPandGetName(const char *cert_file, std::string &userName); + + +#endif // MRK_SSL_XPGP_CERT_HEADER diff --git a/libretroshare/src/pqi/conn_test.cc b/libretroshare/src/pqi/conn_test.cc new file mode 100644 index 000000000..542a82a28 --- /dev/null +++ b/libretroshare/src/pqi/conn_test.cc @@ -0,0 +1,350 @@ + + +#include "pqi/p3connmgr.h" + + +/***** Test for the new DHT system *****/ + + +#include "util/rsnet.h" +#include "util/rsthreads.h" +#include "util/rsprint.h" +#include "pqi/p3dhtmgr.h" +#include "pqi/p3connmgr.h" +#include "pqi/pqisecurity.h" +#include "pqi/pqipersongrp.h" + +#include +#include + +#include "tcponudp/udpsorter.h" + +/***** Test Framework *****/ + +const int NumOfPeers = 10; +std::string peerIds[NumOfPeers] = + {"PEER01", + "PEER02", /* Always online, no notify */ + "PEER03", /* notify/online at 20sec */ + "PEER04", /* Always online, notify at 30 sec */ + "PEER05", + "PEER06", /* notify/online at 50sec */ + "PEER07", + "PEER08", + "PEER09", /* notify/online at 80sec */ + "PEER10"}; + +#define STUN_PORT 7777 + +std::string ownId = "OWNID-AAAA"; +time_t ownPublishTs; + +RsMutex frmMtx; +std::list searchIds; +std::list searchModes; + +std::map onlineMap; +std::map notifyMap; + +void initTestData() +{ + ownPublishTs = 0; + /* setup Peers that are online always */ + bool online; + uint32_t ts; + for(int i = 0; i < NumOfPeers; i++) + { + online = false; + if ((i == 1) || (i == 3)) + { + online = true; + } + onlineMap[peerIds[i]] = online; + + if ((i == 2) || (i == 3) || + (i == 5) || (i == 8)) + { + ts = i * 10; + notifyMap[ts] = peerIds[i]; + } + } +} + +void respondPublish() +{ + frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ + if (!ownPublishTs) + { + std::cerr << "Own ID first published!" << std::endl; + ownPublishTs = time(NULL); + } + frmMtx.unlock(); /* UNLOCK TEST FRAMEWORK MUTEX */ +} + +void respondSearch(p3DhtMgr *mgr, std::string id, uint32_t mode) +{ + std::cerr << "Checking for Search Results" << std::endl; + time_t now = time(NULL); + bool doNotify = false; + bool doOnline = false; + std::string notifyId; + + frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ + if ((mode == DHT_MODE_NOTIFY) && (ownPublishTs)) + { + /* */ + std::map::iterator it; + uint32_t delta_t = now - ownPublishTs; + it = notifyMap.begin(); + if (it != notifyMap.end()) + { + if (it->first <= delta_t) + { + notifyId = it->second; + onlineMap[notifyId] = true; + notifyMap.erase(it); + doNotify = true; + } + } + } + else if (mode == DHT_MODE_SEARCH) + { + + /* translate */ + std::map::iterator mit; + for(mit = onlineMap.begin(); (mit != onlineMap.end()) && + (RsUtil::HashId(mit->first, false) != id); mit++); + + if (mit != onlineMap.end()) + { + doOnline = mit->second; + } + } + + frmMtx.unlock(); /* UNLOCK TEST FRAMEWORK MUTEX */ + + uint32_t type = 0; + + struct sockaddr_in laddr; + inet_aton("10.0.0.129", &(laddr.sin_addr)); + laddr.sin_port = htons(7812); + laddr.sin_family = AF_INET; + + struct sockaddr_in raddr; + inet_aton("127.0.0.1", &(raddr.sin_addr)); + raddr.sin_port = htons(STUN_PORT); + raddr.sin_family = AF_INET; + + if (doNotify) + { + std::cerr << "Responding to Notify: id:" << notifyId << std::endl; + mgr->dhtResultNotify(RsUtil::HashId(notifyId, true)); + } + + if (doOnline) + { + std::cerr << "Responding to Search" << std::endl; + mgr->dhtResultSearch(id, laddr, raddr, type, ""); + } + +} + + +/***** Test Framework *****/ + +class DhtMgrTester: public p3DhtMgr +{ + + /* Implementation */ + public: + + DhtMgrTester(std::string id, pqiConnectCb *cb) + :p3DhtMgr(id, cb) + { + return; + } + + + + + + /* Blocking calls (only from thread) */ +virtual bool dhtPublish(std::string id, + struct sockaddr_in &laddr, struct sockaddr_in &raddr, + uint32_t type, std::string sign) +{ + std::cerr << "DhtMgrTester::dhtPublish() id: " << RsUtil::BinToHex(id); + std::cerr << " laddr: " << inet_ntoa(laddr.sin_addr) << " lport: " << ntohs(laddr.sin_port); + std::cerr << " raddr: " << inet_ntoa(raddr.sin_addr) << " rport: " << ntohs(raddr.sin_port); + std::cerr << " type: " << type << " sign: " << sign; + std::cerr << std::endl; + + respondPublish(); + + return true; +} + +virtual bool dhtNotify(std::string peerid, std::string ownid, std::string sign) +{ + std::cerr << "DhtMgrTester::dhtNotify() id: " << RsUtil::BinToHex(peerid) << ", ownId: " << RsUtil::BinToHex(ownId); + std::cerr << " sign: " << sign; + std::cerr << std::endl; + + return true; +} + +virtual bool dhtSearch(std::string id, uint32_t mode) +{ + std::cerr << "DhtMgrTester::dhtSearch(id: " << RsUtil::BinToHex(id) << ", mode: " << mode << ")" << std::endl; + + frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ + searchIds.push_back(id); + searchModes.push_back(mode); + frmMtx.unlock(); /* LOCK TEST FRAMEWORK MUTEX */ + + return true; +} + +}; + + +/* OVERLOAD THE ConnMgr - to insert peers */ +class p3TestConnMgr: public p3ConnectMgr +{ + public: + p3TestConnMgr(int mode) + :p3ConnectMgr(new p3DummyAuthMgr()), mTestMode(mode) { return; } + + protected: + /* must be virtual for testing */ +virtual void loadConfiguration() +{ + + /* setup own address */ + ownState.id = ownId; + ownState.name = "SELF NAME"; + ownState.localaddr.sin_family = AF_INET; + inet_aton("127.0.0.1", &(ownState.localaddr.sin_addr)); + ownState.localaddr.sin_port = htons(7812); + ownState.netMode = RS_NET_MODE_UDP; + ownState.visState = RS_VIS_STATE_STD; + + /* others not important */ + //ownState.state = 0; + //ownState.actions = 0; + + + if (mTestMode == 1) /* Add to Stun List */ + { + for(int i = 0; i < NumOfPeers; i++) + { + mStunList.push_back(peerIds[i]); + } + } + else if (mTestMode == 2) /* add to peers */ + { + /* add in as peers */ + //addPeer(); + for(int i = 0; i < NumOfPeers; i++) + { + if (i < 5) + { + mStunList.push_back(RsUtil::HashId(peerIds[i])); + } + else + { + addFriend(peerIds[i]); + } + } + } +} + + protected: + + uint32_t mTestMode; +}; + + +int main() +{ + time_t startTime = time(NULL); + /* setup system */ + initTestData(); + + /* setup a Stunner to respond to ConnMgr */ + + struct sockaddr_in saddr; + saddr.sin_family = AF_INET; + inet_aton("127.0.0.1", &(saddr.sin_addr)); + saddr.sin_port = htons(STUN_PORT); + UdpSorter stunner(saddr); /* starts a receiving thread */ + + p3TestConnMgr connMgr(2); + DhtMgrTester dhtTester(ownId, &connMgr); + + /* now add in some peers */ + connMgr.setDhtMgr(&dhtTester); + connMgr.setUpnpMgr(NULL); + + /************ ADD pqipersongrp as pqimonitor *****************/ + + SecurityPolicy *pol = secpolicy_create(); + unsigned long flags = 0; + pqipersongrp *pqipg = new pqipersongrpDummy(pol, flags); + + connMgr.addMonitor(pqipg); + + /************ ADD pqipersongrp as pqimonitor *****************/ + + + /* startup dht */ + std::cerr << "Starting up DhtTester()" << std::endl; + dhtTester.start(); + + /* wait for a little before switching on */ + sleep(1); + + std::cerr << "Switching on DhtTester()" << std::endl; + dhtTester.setDhtOn(true); + + /* wait loop */ + while(1) + { + sleep(1); + + connMgr.tick(); + pqipg->tick(); + + /* handle async search */ + frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ + + std::string id; + uint32_t mode; + bool doRespond = false; + if (searchIds.size() > 0) + { + id = searchIds.front(); + mode = searchModes.front(); + doRespond = true; + searchIds.pop_front(); + searchModes.pop_front(); + } + + frmMtx.unlock(); /* UNLOCK TEST FRAMEWORK MUTEX */ + + if (doRespond) + { + respondSearch(&dhtTester, id, mode); + } + } +}; + + + + + + + + + + diff --git a/libretroshare/src/pqi/dht_test.cc b/libretroshare/src/pqi/dht_test.cc new file mode 100644 index 000000000..450ee545f --- /dev/null +++ b/libretroshare/src/pqi/dht_test.cc @@ -0,0 +1,295 @@ + + +/***** Test for the new DHT system *****/ + + +#include "util/rsnet.h" +#include "util/rsthreads.h" +#include "util/rsprint.h" + +#include "pqi/p3dhtmgr.h" + +#include +#include + + +/***** Test Framework *****/ + +const int NumOfPeers = 10; +std::string peerIds[NumOfPeers] = + {"PEER01", + "PEER02", /* Always online, no notify */ + "PEER03", /* notify/online at 20sec */ + "PEER04", /* Always online, notify at 30 sec */ + "PEER05", + "PEER06", /* notify/online at 50sec */ + "PEER07", + "PEER08", + "PEER09", /* notify/online at 80sec */ + "PEER10"}; + +std::string ownId = "AAAA"; +time_t ownPublishTs; + +RsMutex frmMtx; +std::list searchIds; +std::list searchModes; + +std::map onlineMap; +std::map notifyMap; + +void initTestData() +{ + ownPublishTs = 0; + /* setup Peers that are online always */ + bool online; + uint32_t ts; + for(int i = 0; i < NumOfPeers; i++) + { + online = false; + if ((i == 1) || (i == 3)) + { + online = true; + } + onlineMap[peerIds[i]] = online; + + if ((i == 2) || (i == 3) || + (i == 5) || (i == 8)) + { + ts = i * 10; + notifyMap[ts] = peerIds[i]; + } + } +} + +void respondPublish() +{ + frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ + if (!ownPublishTs) + { + std::cerr << "Own ID first published!" << std::endl; + ownPublishTs = time(NULL); + } + frmMtx.unlock(); /* UNLOCK TEST FRAMEWORK MUTEX */ +} + +void respondSearch(p3DhtMgr *mgr, std::string id, uint32_t mode) +{ + std::cerr << "Checking for Search Results" << std::endl; + time_t now = time(NULL); + bool doNotify = false; + bool doOnline = false; + std::string notifyId; + + frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ + if ((mode == DHT_MODE_NOTIFY) && (ownPublishTs)) + { + /* */ + std::map::iterator it; + uint32_t delta_t = now - ownPublishTs; + it = notifyMap.begin(); + if (it != notifyMap.end()) + { + if (it->first <= delta_t) + { + notifyId = it->second; + onlineMap[notifyId] = true; + notifyMap.erase(it); + doNotify = true; + } + } + } + else if (mode == DHT_MODE_SEARCH) + { + /* translate */ + std::map::iterator mit; + for(mit = onlineMap.begin(); (mit != onlineMap.end()) && + (RsUtil::HashId(mit->first, false) != id); mit++); + + if (mit != onlineMap.end()) + { + doOnline = mit->second; + } + } + + frmMtx.unlock(); /* UNLOCK TEST FRAMEWORK MUTEX */ + + uint32_t type = 0; + + struct sockaddr_in laddr; + inet_aton("10.0.0.129", &(laddr.sin_addr)); + laddr.sin_port = htons(7812); + laddr.sin_family = AF_INET; + + struct sockaddr_in raddr; + inet_aton("10.0.0.19", &(raddr.sin_addr)); + raddr.sin_port = htons(7812); + raddr.sin_family = AF_INET; + + if (doNotify) + { + std::cerr << "Responding to Notify" << std::endl; + mgr->dhtResultNotify(RsUtil::HashId(notifyId, true)); + } + + if (doOnline) + { + std::cerr << "Responding to Search" << std::endl; + mgr->dhtResultSearch(id, laddr, raddr, type, ""); + } +} + + + + + + +/***** Test Framework *****/ + + + + +class DhtMgrTester: public p3DhtMgr +{ + + /* Implementation */ + public: + + DhtMgrTester(std::string id, pqiConnectCb *cb) + :p3DhtMgr(id, cb) + { + return; + } + + + /* Blocking calls (only from thread) */ +virtual bool dhtPublish(std::string id, + struct sockaddr_in &laddr, struct sockaddr_in &raddr, + uint32_t type, std::string sign) +{ + std::cerr << "DhtMgrTester::dhtPublish() id: " << RsUtil::BinToHex(id); + std::cerr << " laddr: " << inet_ntoa(laddr.sin_addr) << " lport: " << ntohs(laddr.sin_port); + std::cerr << " raddr: " << inet_ntoa(raddr.sin_addr) << " rport: " << ntohs(raddr.sin_port); + std::cerr << " type: " << type << " sign: " << sign; + std::cerr << std::endl; + + respondPublish(); + + return true; +} + +virtual bool dhtNotify(std::string peerid, std::string ownid, std::string sign) +{ + std::cerr << "DhtMgrTester::dhtNotify() id: " << RsUtil::BinToHex(peerid) << ", ownId: " << RsUtil::BinToHex(ownId); + std::cerr << " sign: " << sign; + std::cerr << std::endl; + + return true; +} + +virtual bool dhtSearch(std::string id, uint32_t mode) +{ + std::cerr << "DhtMgrTester::dhtSearch(id: " << RsUtil::BinToHex(id) << ", mode: " << mode << ")" << std::endl; + + frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ + searchIds.push_back(id); + searchModes.push_back(mode); + frmMtx.unlock(); /* LOCK TEST FRAMEWORK MUTEX */ + + return true; +} + +}; + +int main() +{ + time_t startTime = time(NULL); + bool haveOwnAddress = false; + /* setup system */ + initTestData(); + + pqiConnectCbDummy cbTester; + DhtMgrTester dhtTester(ownId, &cbTester); + + /* now add in some peers */ + + /* startup dht */ + std::cerr << "Starting up DhtTester()" << std::endl; + dhtTester.start(); + + /* wait for a little before switching on */ + sleep(1); + + std::cerr << "Switching on DhtTester()" << std::endl; + dhtTester.setDhtOn(true); + + std::cerr << "Adding a List of Peers" << std::endl; + for(int i = 0; i < NumOfPeers; i++) + { + dhtTester.findPeer(peerIds[i]); + } + + + /* wait loop */ + while(1) + { + std::cerr << "Main waiting..." << std::endl; + sleep(3); + + /* handle async search */ + frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ + + std::string id; + uint32_t mode; + bool doRespond = false; + if (searchIds.size() > 0) + { + id = searchIds.front(); + mode = searchModes.front(); + doRespond = true; + searchIds.pop_front(); + searchModes.pop_front(); + } + + frmMtx.unlock(); /* UNLOCK TEST FRAMEWORK MUTEX */ + + if (doRespond) + { + respondSearch(&dhtTester, id, mode); + } + + if (!haveOwnAddress) + { + if (time(NULL) - startTime > 20) + { + std::cerr << "Setting Own Address!" << std::endl; + haveOwnAddress = true; + + uint32_t type = DHT_ADDR_UDP; + + struct sockaddr_in laddr; + inet_aton("10.0.0.111", &(laddr.sin_addr)); + laddr.sin_port = htons(7812); + laddr.sin_family = AF_INET; + + struct sockaddr_in raddr; + inet_aton("10.0.0.11", &(raddr.sin_addr)); + raddr.sin_port = htons(7812); + raddr.sin_family = AF_INET; + + dhtTester.setExternalInterface(laddr, raddr, type); + } + } + + } +}; + + + + + + + + + + diff --git a/libretroshare/src/pqi/p3authmgr.cc b/libretroshare/src/pqi/p3authmgr.cc new file mode 100644 index 000000000..ee629b602 --- /dev/null +++ b/libretroshare/src/pqi/p3authmgr.cc @@ -0,0 +1,226 @@ +/* + * libretroshare/src/pqi: p3authmgr.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 "pqi/p3authmgr.h" + +pqiAuthDetails::pqiAuthDetails() + :trustLvl(0), ownsign(false), trusted(0) +{ + return; +} + +p3DummyAuthMgr::p3DummyAuthMgr() +{ + /* for the truely dummy option */ + mOwnId = "OWNID"; + + pqiAuthDetails ownDetails; + ownDetails.id = mOwnId; + ownDetails.name = "Youself"; + ownDetails.email = "me@me.com"; + ownDetails.location = "here"; + ownDetails.org = "me.com"; + + ownDetails.trustLvl = 6; + ownDetails.ownsign = true; + ownDetails.trusted = true; + + /* ignoring fpr and signers */ + + mPeerList[mOwnId] = ownDetails; + +} + +p3DummyAuthMgr::p3DummyAuthMgr(std::string ownId, std::list peers) +{ + mOwnId = ownId; + bool addedOwn = false; + + std::list::iterator it; + for(it = peers.begin(); it != peers.end(); it++) + { + mPeerList[it->id] = (*it); + if (it->id == ownId) + { + addedOwn = true; + } + } + if (!addedOwn) + { + pqiAuthDetails ownDetails; + ownDetails.id = mOwnId; + ownDetails.name = "Youself"; + ownDetails.email = "me@me.com"; + ownDetails.location = "here"; + ownDetails.org = "me.com"; + + ownDetails.trustLvl = 6; + ownDetails.ownsign = true; + ownDetails.trusted = true; + + /* ignoring fpr and signers */ + + mPeerList[mOwnId] = ownDetails; + } +} + +bool p3DummyAuthMgr:: active() +{ + return true; +} + +int p3DummyAuthMgr::InitAuth(const char *srvr_cert, const char *priv_key, + const char *passwd) +{ + return 1; +} + +bool p3DummyAuthMgr::CloseAuth() +{ + return true; +} + +int p3DummyAuthMgr::setConfigDirectories(const char *cdir, const char *ndir) +{ + return 1; +} + +std::string p3DummyAuthMgr::OwnId() +{ + return mOwnId; +} + +bool p3DummyAuthMgr::getAllList(std::list &ids) +{ + std::map::iterator it; + for(it = mPeerList.begin(); it != mPeerList.end(); it++) + { + ids.push_back(it->first); + } + return true; +} + +bool p3DummyAuthMgr::getAuthenticatedList(std::list &ids) +{ + std::map::iterator it; + for(it = mPeerList.begin(); it != mPeerList.end(); it++) + { + if (it->second.trustLvl > 3) + { + ids.push_back(it->first); + } + } + return true; +} + +bool p3DummyAuthMgr::getUnknownList(std::list &ids) +{ + std::map::iterator it; + for(it = mPeerList.begin(); it != mPeerList.end(); it++) + { + if (it->second.trustLvl <= 3) + { + ids.push_back(it->first); + } + } + return true; +} + +bool p3DummyAuthMgr::isValid(std::string id) +{ + std::map::iterator it; + return (mPeerList.end() != mPeerList.find(id)); +} + + +bool p3DummyAuthMgr::isAuthenticated(std::string id) +{ + std::map::iterator it; + if (mPeerList.end() != (it = mPeerList.find(id))) + { + return (it->second.trustLvl > 3); + } + return false; +} + +std::string p3DummyAuthMgr::getName(std::string id) +{ + std::map::iterator it; + if (mPeerList.end() != (it = mPeerList.find(id))) + { + return it->second.name; + } + std::string empty(""); + return empty; +} + +bool p3DummyAuthMgr::getDetails(std::string id, pqiAuthDetails &details) +{ + std::map::iterator it; + if (mPeerList.end() != (it = mPeerList.find(id))) + { + details = it->second; + return true; + } + return false; +} + +bool p3DummyAuthMgr::LoadCertificateFromString(std::string pem, std::string &id) +{ + return false; +} + +std::string p3DummyAuthMgr::SaveCertificateToString(std::string id) +{ + std::string dummy("CERT STRING"); + return dummy; +} + +bool p3DummyAuthMgr::LoadCertificateFromFile(std::string filename, std::string &id) +{ + return false; +} + +bool p3DummyAuthMgr::SaveCertificateToFile(std::string id, std::string filename) +{ + return false; +} + + /* Signatures */ +bool p3DummyAuthMgr::SignCertificate(std::string id) +{ + return false; +} + +bool p3DummyAuthMgr::RevokeCertificate(std::string id) +{ + return false; +} + +bool p3DummyAuthMgr::TrustCertificate(std::string id, bool trust) +{ + return false; +} + diff --git a/libretroshare/src/pqi/p3authmgr.h b/libretroshare/src/pqi/p3authmgr.h new file mode 100644 index 000000000..2f9bc53cf --- /dev/null +++ b/libretroshare/src/pqi/p3authmgr.h @@ -0,0 +1,164 @@ +/* + * libretroshare/src/pqi: p3authmgr.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 RS_GENERIC_AUTH_HEADER +#define RS_GENERIC_AUTH_HEADER + +#include +#include +#include + +/************** GENERIC AUTHENTICATION MANAGER *********** + * Provides a common interface for certificates. + * + * Initialisation must be done in derived classes + * + * Key features: + * everything indexed by std::string id; + * has auth perspective: authed / not authed - different to friends. + * load/save certificates as strings or files. + * + */ + +class p3AuthMgr; +extern p3AuthMgr *authMgr; + +p3AuthMgr *getAuthMgr(); + +class pqiAuthDetails +{ + public: + pqiAuthDetails(); + + std::string id; + std::string name; + std::string email; + std::string location; + std::string org; + + std::string fpr; /* fingerprint */ + std::list signers; + + uint32_t trustLvl; + + bool ownsign; + bool trusted; +}; + + +class p3AuthMgr +{ + public: + + /* initialisation -> done by derived classes */ +virtual bool active() = 0; +virtual int InitAuth(const char *srvr_cert, const char *priv_key, + const char *passwd) = 0; +virtual bool CloseAuth() = 0; +virtual int setConfigDirectories(const char *cdir, const char *ndir) = 0; + + /* get Certificate Ids */ + +virtual std::string OwnId() = 0; +virtual bool getAllList(std::list &ids) = 0; +virtual bool getAuthenticatedList(std::list &ids) = 0; +virtual bool getUnknownList(std::list &ids) = 0; + + /* get Details from the Certificates */ + +virtual bool isValid(std::string id) = 0; +virtual bool isAuthenticated(std::string id) = 0; +virtual std::string getName(std::string id) = 0; +virtual bool getDetails(std::string id, pqiAuthDetails &details) = 0; + + /* Load/Save certificates */ + +virtual bool LoadCertificateFromString(std::string pem, std::string &id) = 0; +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; + + /* Signatures */ +virtual bool AuthCertificate(std::string uid) = 0; +virtual bool SignCertificate(std::string id) = 0; +virtual bool RevokeCertificate(std::string id) = 0; +virtual bool TrustCertificate(std::string id, bool trust) = 0; + + /* Sign / Encrypt / Verify Data (TODO) */ +//virtual bool encryptData(std::string recipientId, std::string plaindata, std::string &result); + +}; + + +class p3DummyAuthMgr: public p3AuthMgr +{ + public: + + p3DummyAuthMgr(); + p3DummyAuthMgr(std::string ownId, std::list peers); + + /* initialisation -> done by derived classes */ +virtual bool active(); +virtual int InitAuth(const char *srvr_cert, const char *priv_key, + const char *passwd); +virtual bool CloseAuth(); +virtual int setConfigDirectories(const char *cdir, const char *ndir); + + /* get Certificate Ids */ + +virtual std::string OwnId(); +virtual bool getAllList(std::list &ids); +virtual bool getAuthenticatedList(std::list &ids); +virtual bool getUnknownList(std::list &ids); + + /* get Details from the Certificates */ + +virtual bool isValid(std::string id); +virtual bool isAuthenticated(std::string id); +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); + + /* Signatures */ + +virtual bool SignCertificate(std::string id); +virtual bool RevokeCertificate(std::string id); +virtual bool TrustCertificate(std::string id, bool trust); + + std::string mOwnId; + std::map mPeerList; +}; + +#endif + + + + diff --git a/libretroshare/src/pqi/p3cfgmgr.cc b/libretroshare/src/pqi/p3cfgmgr.cc new file mode 100644 index 000000000..3dd1d8859 --- /dev/null +++ b/libretroshare/src/pqi/p3cfgmgr.cc @@ -0,0 +1,242 @@ +/* + * libretroshare/src/pqi: p3cfgmgr.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 "pqi/p3cfgmgr.h" +#include "pqi/pqibin.h" +#include "pqi/pqiarchive.h" + + + + +p3ConfigMgr::p3ConfigMgr(std::string dir, std::string fname, std::string signame) + :basedir(dir), metafname(fname), metasigfname(signame) +{ + + +} + +void p3ConfigMgr::tick() +{ + bool toSave = false; + + /* iterate through and check if any have changed */ + std::map::iterator it; + for(it = configs.begin(); it != configs.end(); it++) + { + if (it->second->ConfInd.Changed(0)) + { + toSave = true; + } + } + + if (toSave) + { + saveConfiguration(); + } +} + + +void p3ConfigMgr::saveConfiguration() +{ + /* setup metaconfig */ + + std::map::iterator it; + for(it = configs.begin(); it != configs.end(); it++) + { + if (it->second->ConfInd.Changed(1)) + { + it->second->saveConfiguration(basedir); + } + /* save metaconfig */ + } + + /* sign the hash of the data */ + + + /* write signature to configuration */ +} + +void p3ConfigMgr::loadConfiguration() +{ + + + +} + +void p3ConfigMgr::addConfiguration(uint32_t type, pqiConfig *conf) +{ + configs[type] = conf; +} + + +p3Config::p3Config(uint32_t t, std::string name) +:pqiConfig(t, name) +{ + return; +} + +bool p3Config::loadConfiguration(std::string basedir, std::string &loadHash) +{ + std::list load; + std::list::iterator it; + + std::string fname = basedir; + if (fname != "") + fname += "/"; + fname += Filename(); + + BinFileInterface *bio = new BinFileInterface(fname.c_str(), + BIN_FLAGS_READABLE | BIN_FLAGS_HASH_DATA); + pqiarchive archive(setupSerialiser(), bio, BIN_FLAGS_READABLE); + RsItem *item = NULL; + + while(NULL != (item = archive.GetItem())) + { + load.push_back(item); + } + /* check hash */ + std::string hashstr = archive.gethash(); + + if (hashstr != loadHash) + { + /* bad load */ + for(it = load.begin(); it != load.end(); it++) + { + delete (*it); + } + return false; + } + + setHash(hashstr); + + /* else okay */ + return loadList(load); +} + + +bool p3Config::saveConfiguration(std::string basedir) +{ + bool toKeep; + std::list toSave = saveList(toKeep); + + std::string fname = basedir; + if (fname != "") + fname += "/"; + fname += Filename(); + + BinFileInterface *bio = new BinFileInterface(fname.c_str(), + BIN_FLAGS_WRITEABLE | BIN_FLAGS_HASH_DATA); + + uint32_t arch_flags = BIN_FLAGS_WRITEABLE; + if (toKeep) + arch_flags |= BIN_FLAGS_NO_DELETE; + + pqiarchive archive(setupSerialiser(), bio, arch_flags); + std::list::iterator it; + for(it = toSave.begin(); it != toSave.end(); it++) + { + archive.SendItem(*it); + } + + /* store the hash */ + setHash(archive.gethash()); + + /* else okay */ + return true; +} + + +/**************************** CONFIGURATION CLASSES ********************/ + +p3GeneralConfig::p3GeneralConfig() + :p3Config(CONFIG_TYPE_GENERAL, "gen.set") +{ + return; +} + + // General Configuration System +std::string p3GeneralConfig::getSetting(std::string opt) +{ + /* extract from config */ + std::map::iterator it; + if (settings.end() == (it = settings.find(opt))) + { + std::string nullstring; + return nullstring; + } + return it->second; +} + +void p3GeneralConfig::setSetting(std::string opt, std::string val) +{ + /* extract from config */ + std::map::iterator it; + if (settings.end() != (it = settings.find(opt))) + { + if (it->second == val) + { + /* no change */ + return; + } + } + + ConfInd.IndicateChanged(); + settings[opt] = val; + + return; +} + + +/* TODO ******/ + +RsSerialiser *p3GeneralConfig::setupSerialiser() +{ + RsSerialiser *rss = NULL; + return rss; +} + +std::list p3GeneralConfig::saveList(bool &cleanup) +{ + cleanup = false; + std::list savelist; + //RsGenConfItem *item = ... + std::map::iterator it; + for(it = settings.begin(); it != settings.end(); it++) + { + + + } + return savelist; +} + + +bool p3GeneralConfig::loadList(std::list load) +{ + /* add into settings */ + + return false; +} + diff --git a/libretroshare/src/pqi/p3cfgmgr.h b/libretroshare/src/pqi/p3cfgmgr.h new file mode 100644 index 000000000..cea392525 --- /dev/null +++ b/libretroshare/src/pqi/p3cfgmgr.h @@ -0,0 +1,156 @@ +/* + * libretroshare/src/pqi: p3cfgmgr.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_CONFIG_MGR_HEADER +#define P3_CONFIG_MGR_HEADER + +#include +#include + +#include "pqi/pqi_base.h" +#include "pqi/pqiindic.h" +#include "pqi/pqinetwork.h" + +/***** Configuration Management ***** + * + * we need to store: + * (1) Certificates. + * (2) List of Friends / Net Configuration + * (3) Stun List. / DHT peers. + * (4) general config. + * + * + * At top level we need: + * + * - type / filename / size / hash - + * and the file signed... + * + * + */ + +const uint32_t CONFIG_TYPE_GENERAL = 0x0001; +const uint32_t CONFIG_TYPE_STUNLIST = 0x0002; +const uint32_t CONFIG_TYPE_FSERVER = 0x0003; +const uint32_t CONFIG_TYPE_PEERS = 0x0004; + +class pqiConfig +{ + public: + pqiConfig(uint32_t t, std::string defaultname) + :ConfInd(2), type(t), filename(defaultname) + { + return; + } + +virtual bool loadConfiguration(std::string filename, std::string &load) = 0; +virtual bool saveConfiguration(std::string filename) = 0; + + Indicator ConfInd; + +uint32_t Type() { return type; } +std::string Filename() { return filename; } +std::string Hash() { return hash; } + + protected: +void setHash(std::string h) { hash = h; } + + private: + uint32_t type; + std::string filename; + std::string hash; +}; + + +class p3ConfigMgr +{ + public: + p3ConfigMgr(std::string bdir, std::string fname, std::string signame); + +void tick(); +void saveConfiguration(); +void loadConfiguration(); +void addConfiguration(uint32_t type, pqiConfig *conf); + + private: + +std::map configs; + +std::string basedir; +std::string metafname; +std::string metasigfname; + +}; + + +class p3Config: public pqiConfig +{ + public: + + p3Config(uint32_t t, std::string name); + +virtual bool loadConfiguration(std::string basedir, std::string &loadHash); +virtual bool saveConfiguration(std::string basedir); + + protected: + + /* Key Functions to be overloaded for Full Configuration */ +virtual RsSerialiser *setupSerialiser() = 0; +virtual std::list saveList(bool &cleanup) = 0; +virtual bool loadList(std::list load) = 0; + + +}; /* end of p3Config */ + + +class p3GeneralConfig: public p3Config +{ + public: + p3GeneralConfig(); + +// General Configuration System +std::string getSetting(std::string opt); +void setSetting(std::string opt, std::string val); + + protected: + + /* Key Functions to be overloaded for Full Configuration */ +virtual RsSerialiser *setupSerialiser(); +virtual std::list saveList(bool &cleanup); +virtual bool loadList(std::list load); + + private: + +std::map settings; +}; + + + + + + + +#endif // P3_CONFIG_MGR_HEADER diff --git a/libretroshare/src/pqi/p3channel.cc b/libretroshare/src/pqi/p3channel.cc deleted file mode 100644 index 7444aa9ea..000000000 --- a/libretroshare/src/pqi/p3channel.cc +++ /dev/null @@ -1,1322 +0,0 @@ -/* - * "$Id: p3channel.cc,v 1.8 2007-04-07 08:40:54 rmf24 Exp $" - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2004-2006 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 "pqi/p3channel.h" - -// for active local cert stuff. -#include "pqi/pqissl.h" - -#include -#include -#include - -#include -#include -#include "pqi/pqidebug.h" - -const int pqichannelzone = 3334; - -/* - * Compile Flag to generate Rnd messages frequently. - * - * PQI_CHANNEL_GENERATE_RND 1 - */ -#define PQI_CHANNEL_GENERATE_RND 1 - - - - // | Publisher Bit. - // v - // | Subscriber Bit - // | (download) - // v - // | Listen Bit - // | (reBroadcast) - // v - -const int P3Chan_Publisher_Bit = 0x040; // 0100 0000 -const int P3Chan_Subscriber_Bit = 0x020; // 0010 0000 -const int P3Chan_Listener_Bit = 0x010; // 0001 0000 -const int P3Chan_No_Bit = 0x000; // 0000 0000 - -const int P3Chan_Publisher = 0x050; // 0101 0000 -const int P3Chan_Subscriber = 0x030; // 0011 0000 -const int P3Chan_Listener = 0x010; // 0001 0000 -const int P3Chan_Other = 0x000; // 0000 0000 - -/**** - * This is our channel class. - * It performs various functions. - * 1) collect channel messages. - * 2) save/restore messages. - * 3) manage their downloads.... - * 4) rebroadcast messages. - * - * You need to be able to categorise the channels - * 1) Favourites. - * 2) Standard Subscription - * 3) Listen - * 4) Others. - * - * The first three groups will be maintained. - * - * Controllable how long lists are maintained. (1 week standard) - * - * Messages are rebroadcast, At a random interval (0 - 4 hours) after - * receiving the message. (and downloading it???) - * - * Maximum Download Cache per channel. - * - * Flag stuff to keep. - * - * Popularity rating on how much each is rebroadcast. - * - * There should be a couple of rating schemes to decide - * on how long something stays downloaded. - * - * 1) Time, Old stuff first. - * 2) Volume.... - * 3) Size. - * 4) Popularity. - * - */ - -#include -#include - -#include "pqi.h" - -#include "discItem.h" -#include "pqitunnel.h" - -/************************** -class channelSign -**************************/ -bool channelSign::operator<(const channelSign &s) const -{ - return (memcmp(sign, s.sign, CHAN_SIGN_SIZE) < 0); -} - -bool channelSign::operator==(const channelSign &s) const -{ - return (memcmp(sign, s.sign, CHAN_SIGN_SIZE) == 0); -} - -std::ostream &channelSign::print(std::ostream &out) const -{ - out << "channelSign :"; - for(int i = 0; i < CHAN_SIGN_SIZE; i++) - { - unsigned char n = ((unsigned char *) sign)[i]; - out << (unsigned int) n << ":"; - } - return out; -} - - -std::ostream &channelSign::printHex(std::ostream &out) const -{ - out << std::hex << "["; - for(int i = 0; i < CHAN_SIGN_SIZE; i++) - { - unsigned char n = ((unsigned char *) sign)[i]; - out << std::setw(2) << (unsigned int) n; - if (i < CHAN_SIGN_SIZE-1) - { - out << ":"; - } - else - { - out << "]"; - } - - } - out << std::dec; - return out; -} - -/************************** -class channelKey -**************************/ - -bool channelKey::operator<(const channelKey &s) const -{ - return (memcmp(sign, s.sign, CHAN_SIGN_SIZE) < 0); -} - -bool channelKey::operator==(const channelKey &s) const -{ - return (memcmp(sign, s.sign, CHAN_SIGN_SIZE) == 0); -} - - -std::ostream &channelKey::print(std::ostream &out) const -{ - out << "channelKey :"; - for(int i = 0; i < CHAN_SIGN_SIZE; i++) - { - unsigned char n = ((unsigned char *) sign)[i]; - out << (unsigned int) n << ":"; - } - return out; -} - - -channelKey::channelKey() - :key(NULL) -{ -} - - -channelKey::channelKey(EVP_PKEY *k) - :key(k) -{ - // work out sign. - calcSign(); -} - -int channelKey::setKey(EVP_PKEY *k) -{ - - { - std::ostringstream out; - out << "channelKey::setKey()"; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - } - - key = k; - calcSign(); - return 1; -} - -channelKey::~channelKey() -{ - if (key) - { - EVP_PKEY_free(key); - } -} - -int channelKey::load(const unsigned char *d, int len) -{ - const unsigned char *ptr = d; - - { - std::ostringstream out; - out << "channelKey::load(" << len << ") "; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - } - - RSA *rsa; - - if (NULL == (rsa = d2i_RSAPublicKey(NULL, &ptr, len))) - { - std::ostringstream out; - out << "channelKey::in() Failed to Load RSA Key."; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - - return -1; - } - - // get the signature - - - // read in using ssl stylee. - key = EVP_PKEY_new(); - - EVP_PKEY_assign_RSA(key, rsa); - - return calcSign(); -} - -int channelKey::calcSign() -{ - // The signature will be extracted from the - // public exponential. - - RSA *rsa = EVP_PKEY_get1_RSA(key); - int len = BN_num_bytes(rsa -> n); - unsigned char tmp[len]; - BN_bn2bin(rsa -> n, tmp); - - // copy first CHAN_SIGN_SIZE bytes... - if (len > CHAN_SIGN_SIZE) - { - len = CHAN_SIGN_SIZE; - } - - std::ostringstream out; - out << "channelKey::calcSign()"; - - for(int i = 0; i < len; i++) - { - sign[i] = tmp[i]; - unsigned char c = ((unsigned char *) sign)[i]; - out << (unsigned int) c; - if (i != len - 1) - out << ":"; - } - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - - RSA_free(rsa); - return 1; -} - - -int channelKey::out(unsigned char *data, int len) -{ - unsigned char *ptr = data; - - if (!key) - { - std::ostringstream out; - out << "channelKey::out() Key = NULL"; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - return -1; - } - - RSA *trsa = EVP_PKEY_get1_RSA(key); - int reqspace = i2d_RSAPublicKey(trsa, NULL); - - if (data == NULL) - { - std::ostringstream out; - out << "channelKey::out() Returning Size"; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - RSA_free(trsa); - return reqspace; - } - - if (len < reqspace) - { - std::ostringstream out; - out << "channelKey::out() not enough space"; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - RSA_free(trsa); - return -1; - } - - int val = i2d_RSAPublicKey(trsa, &ptr); - - // delete the rsa key. - RSA_free(trsa); - - return val; -} - - - -bool channelKey::valid() -{ - return (key != 0); -} - -EVP_PKEY *channelKey::getKey() const -{ - return key; -} - -channelSign channelKey::getSign() const -{ - std::ostringstream out; - out << "channelKey::getSign()"; - - channelSign s; - for(int i = 0; i < CHAN_SIGN_SIZE; i++) - { - s.sign[i] = sign[i]; - unsigned char c = ((unsigned char *) s.sign)[i]; - out << (unsigned int) c; - if (i != CHAN_SIGN_SIZE-1) - out << ":"; - } - - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - return s; -} - -/************************** -class channelMsg -**************************/ - -channelMsg::channelMsg(PQChanItem *in, TimeStamp now, TimeStamp reb) - :msg(in), receivedCount(1), recvTime(now), rebroadcast(false), - rbcTime(reb), downloaded(false), save(false) -{ - { - std::ostringstream out; - out << "channelMsg::channelMsg()"; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - } - return; -} - -/************************** -class pqichannel -**************************/ - -pqichannel::pqichannel(sslroot *s, channelKey *k, std::string title, int m) - :sroot(s), mode(m), channelTitle(title), ranking(0), key(k) {} - -// retrieving msgs. -int pqichannel::getMsgSummary(std::list &summary) -{ - if (msgByHash.size() == 0) - { - return 0; - } - std::map::const_iterator it; - PQChanItem::FileList::const_iterator flit; - - for(it = msgByHash.begin(); it != msgByHash.end(); it++) - { - chanMsgSummary ms; - PQChanItem *item = it -> second -> msg; - //ms.msg = item -> title; - ms.msg = item -> msg; - ms.mh = it -> first; - ms.nofiles = item -> files.size(); - - ms.totalsize = 0; - for(flit = item->files.begin(); flit != item->files.end(); flit++) - { - ms.totalsize += flit->size; - } - ms.recvd = it->second->recvTime; - - summary.push_back(ms); - } - return 1; -} - - -channelMsg *pqichannel::findMsg(MsgHash mh) -{ - std::map::const_iterator it; - it = msgByHash.find(mh); - if (it == msgByHash.end()) - { - return NULL; - } - return (it -> second); -} - - -int pqichannel::processMsg(PQChanItem *in) -{ - { - std::ostringstream out; - out << "pqichannel::processMsg()"; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - } - if (!checkPktSignature(in)) - { - std::ostringstream out; - out << "pqichannel::processMsg() Failed Signature Check!"; - out << std::endl; - out << "pqichannel::processMsg() Deleting Incoming Pkt."; - out << std::endl; - - std::cerr << out.str(); - delete in; - return -1; - } - - // get time stamp. - TimeStamp now = time(NULL); - MsgHash hash = getMsgHash(in); - std::map::iterator it; - - if (msgByHash.end() != (it = msgByHash.find(hash))) - { - // already there.... (check). - - // increment the counter. - it -> second -> receivedCount++; - - // discard. - std::ostringstream out; - out << "pqichannel::processMsg() Msg Already There! Received"; - out << it -> second -> receivedCount << " times" << std::endl; - out << "pqichannel::processMsg() Deleting Incoming Pkt."; - out << std::endl; - - std::cerr << out.str(); - - delete in; - return -1; - } - else - { - // new.... - // calc Rebroadcast time. - TimeStamp reb = now; - -#ifdef PQI_CHANNEL_GENERATE_RND - float secIn10min = 60 * 10; - int rndsec = (int) (rand() * secIn10min / RAND_MAX); -#else - float secIn4hrs = 60 * 4 * 60; - int rndsec = (int) (rand() * secIn4hrs / RAND_MAX); -#endif - reb += rndsec; - - // create channelMsg. - channelMsg *msg = new channelMsg(in, now, reb); - - // save it. - msgByHash[hash] = msg; - - std::ostringstream out; - out << "pqichannel::processMsg() Saved New Msg"; - out << std::endl; - - std::cerr << out.str(); - } - return 1; -} - - - // fill with outgoing -int pqichannel::reBroadcast(std::list &outgoing) -{ - { - std::ostringstream out; - out << "pqichannel::reBroadcast()"; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - } - TimeStamp now = time(NULL); - - // iterate through the messages. - // if the rebroadcast flag is unset, - // and the RBC is in the past.... - // add to the queue. - - std::map::iterator it; - for(it = msgByHash.begin(); it != msgByHash.end(); it++) - { - if ((!it -> second -> rebroadcast) && - (it -> second -> rbcTime < now)) - { - PQChanItem *nitem = it -> second -> msg -> clone(); - // reset address to everyone. - // XXX FIX. - for(int i = 0; i < 10; i++) - nitem -> cid.route[i] = 0; - - // add to list. - outgoing.push_back(nitem); - - std::ostringstream out; - out << "pqichannel::reBroadcast() Sending Msg"; - out << std::endl; - nitem->print(out); - out << std::endl; - - std::cerr << out.str(); - - // set flag. - it -> second -> rebroadcast = true; - } - else - { - std::ostringstream out; - if (it -> second -> rebroadcast) - { - out << "pqichannel::reBroadcast() Msg Already Rebroadcast"; - } - else - { - out << "pqichannel::reBroadcast() Not ready for rebroadcast"; - } - out << std::endl; - std::cerr << out.str(); - } - } - return 1; -} - -channelSign pqichannel::getSign() -{ - return key -> getSign(); -} - -channelKey *pqichannel::getKey() -{ - return key; -} - -/************************** -class pqichanneler -// specialisation with the private key, and output. - - **************************/ - -pqichanneler::pqichanneler(sslroot *s, - channelKey *priv, channelKey *pub, - std::string title) - :pqichannel(s, pub, title, P3Chan_Publisher), privkey(priv) {} - - -int pqichanneler::sendmsg(PQChanItem *msg) -{ - { - std::ostringstream out; - out << "pqichanneler::sendmsg()"; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - } - // Takes a partially constructed Msg, - // fills in the signature.... - // then all it has to do is pass it - // to the pqichannel which will handle the - // distribution. - - if ((!key -> valid()) || (!privkey -> valid())) - { - std::ostringstream out; - out << "pqichanneler::sendmsg() Keys Not Valid!"; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - delete msg; - return -1; - } - - // - msg -> certLen = key -> out(NULL, 0); - msg -> certDER = (unsigned char *) malloc(msg -> certLen); - key -> out(msg -> certDER, msg -> certLen); - msg -> signLen = 0; - - // some nasty complexity here. - // we are going to write it to a buffer (as is) - // and then chop out the bit we need to sign. - int tmpsize = msg -> PQChanItem::getSize(); - char *tmpspace = (char *) malloc(tmpsize); - if (tmpsize != msg -> out(tmpspace, tmpsize)) - { - std::ostringstream out; - out << "pqichanneler::sendmsg() msg -> out() Failure!"; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - delete msg; - return -1; - } - - char *sign = tmpspace + msg -> PQTunnel::getSize(); - tmpsize -= msg -> PQTunnel::getSize(); - - msg -> signLen = EVP_PKEY_size(privkey -> getKey()); - msg -> signature = (unsigned char *) malloc(msg->signLen); - - sroot -> signDigest(privkey -> getKey(), sign, tmpsize, - msg->signature, msg->signLen); - - // now we can free the tmp space. - free(tmpspace); - - return pqichannel::processMsg(msg); -} - -/************************** -class p3channel -// the Tunnel Service. - - **************************/ - -p3channel::p3channel(sslroot *r) - :PQTunnelService(PQI_TUNNEL_CHANNEL_ITEM_TYPE), sroot(r) -{ - { - std::ostringstream out; - out << "p3channel::p3channel()"; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - } - // configure... - load_configuration(); - return; -} - -p3channel::~p3channel() -{ - { - std::ostringstream out; - out << "p3channel::~p3channel()"; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - } - return; -} - -// The PQTunnelService interface. -int p3channel::receive(PQTunnel *i) -{ - { - std::ostringstream out; - out << "p3channel::receive()"; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - } - inpkts.push_back(i); - - std::ostringstream out; - out << "p3channel::receive() InQueue:" << inpkts.size() << std::endl; - out << "incoming packet: " << std::endl; - i -> print(out); - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - - return 1; -} - -PQTunnel *p3channel::send() -{ - std::ostringstream out; - out << "p3channel::send(" << outpkts.size() << ")" << std::endl; - - if (outpkts.size() < 1) - { - out << "------------------> No Packet" << std::endl; - pqioutput(PQL_DEBUG_ALL, pqichannelzone, out.str()); - return NULL; - } - PQTunnel *pkt = (PQTunnel *) outpkts.front(); - outpkts.pop_front(); - - out << "outgoing packet: " << std::endl; - pkt -> print(out); - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - - return pkt; -} - - - -int p3channel::tick() -{ - // regularly run reBroadcast. - pqioutput(PQL_DEBUG_ALL, pqichannelzone, - "p3channel::tick()"); - - handleIncoming(); - - if (ts_nextlp == 0) - { - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, - "p3channel::tick() ReBroadcast Cycle!"); - reBroadcast(); - min10Count++; - // hourly. - if (min10Count > 5) - { - min10Count = 0; - // prune - pruneOldMsgs(); - } - } - -#ifdef PQI_CHANNEL_GENERATE_RND - if (ts_nextlp % 300 == 0) - { - generateRandomMsg(); - printMsgs(); - reBroadcast(); - } -#endif - - - // ten minute counter. - if (--ts_nextlp < 0) - { - ts_nextlp = 600; - } - - return 1; -} - -// load and save configuration. -int p3channel::save_configuration() -{ - { - std::ostringstream out; - out << "p3channel::save_configuration()"; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - } - // save to an independent file. - return 1; -} - -int p3channel::load_configuration() -{ - { - std::ostringstream out; - out << "p3channel::load_configuration()"; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - } - // load from independent file. - return 1; -} - - -// retrieving channels. -pqichannel *p3channel::findChannel(channelSign s) -{ - std::map::const_iterator it; - it = channels.find(s); - if (it == channels.end()) - { - return NULL; - } - return (it -> second); -} - - -int p3channel::getChannelList(std::list &chans) -{ - if (channels.size() == 0) - { - return 0; - } - - std::map::const_iterator it; - for(it = channels.begin(); it != channels.end(); it++) - { - chans.push_back(it->second); - } - return 1; -} - - // maintainance. -int p3channel::pruneOldMsgs() -{ - std::ostringstream out; - out << "p3channel::pruneOldMsgs()"; - - std::map::iterator it; - int pcount = 0; - for(it = channels.begin(); it != channels.end(); it++, pcount++) - { - it -> second -> pruneOldMsgs(); - } - - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - return 1; -} - - - // maintainance. -int pqichannel::pruneOldMsgs() -{ - std::ostringstream out; - out << "p3channel::pruneOldMsgs()"; - - - std::map::iterator it, it2; - int i = 0; - int t = time(NULL); - for(it = msgByHash.begin(); it != msgByHash.end(); i++) - { - // still in Hours, - // but should change to days.... - float tpHr = (t - it->second->recvTime) / 3600.0; - float pop = (it->second->receivedCount) / (float) tpHr - tpHr / 2.0; - if ((pop > 0) || (tpHr < 7)) - { - // leave it.. - it++; - continue; - } - out << "Deleting->->-> Msg(" << i << ")" << std::endl; - out << "Msg(" << i << ") : " << it->second->msg->msg; - out << std::endl; - out << "Received Count -> " << it->second->receivedCount; - out << std::endl; - - out << "Time Since Arrival -> " << t - it->second->recvTime; - out << std::endl; - out << "Popularity: " << pop; - out << std::endl; - out << "ReB(" << it->second->rebroadcast; - out << ") TS: " << it->second->rbcTime; - out << " or RTS: " << it->second->rbcTime - time(NULL) << std::endl; - out << "Down(" << it->second->downloaded; - out << ") TS: " << it->second->dldTime; - out << " or RTS: " << it->second->dldTime - time(NULL) << std::endl; - - channelSign s = getChannelSign(it->second->msg); - MsgHash h = getMsgHash(it->second->msg); - - s.print(out); - out << std::endl; - h.print(out); - out << std::endl; - out << "<-<-<--------"; - - // very dubious.... will it work.?? - it2 = it; - it++; - msgByHash.erase(it2); - } - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - return 1; -} - -int p3channel::handleIncoming() -{ - { - std::ostringstream out; - out << "p3channel::handleIncoming()"; - pqioutput(PQL_DEBUG_ALL, pqichannelzone, out.str()); - } - // loop through all incoming pkts. - // send off to correct pqichannel. - - while(inpkts.size() > 0) - { - PQItem *in = inpkts.front(); - inpkts.pop_front(); - - { - std::ostringstream out; - out << "p3channel::handleIncoming() Handling Pkt"; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - } - - - PQChanItem *msg; - if (NULL==(msg=dynamic_cast(in))) - { - // error with the packet!. - - delete in; - continue; - } - // At this point we need to validate the signature. - bool validSign = true; - - // save the sign size, so we can blank it for a moment. - int signlen = msg -> signLen; - msg -> signLen = 0; - - // some nasty complexity here. - // we are going to write it to a buffer (as is) - // and then chop out the bit we need to sign. - int tmpsize = msg -> PQChanItem::getSize(); - char *tmpspace = (char *) malloc(tmpsize); - if (0 > msg -> out(tmpspace, tmpsize)) - { - std::ostringstream out; - out << "p3channel::handleIncoming() msg Failed out()"; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - validSign = false; - } - // this is okay even if out() fails. - char *signdata = tmpspace + msg -> PQTunnel::getSize(); - tmpsize -= msg -> PQTunnel::getSize(); - - // restore signLen before verifying signature. - msg -> signLen = signlen; - - // generate the key. - channelKey tmpkey; - if (validSign) - { - std::ostringstream out; - out << "p3channel::handleIncoming() loading key"; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - - validSign = (1 == tmpkey.load( - msg -> certDER, msg -> certLen)); - } - - if (validSign) - { - std::ostringstream out; - out << "p3channel::handleIncoming() verifying Digest"; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - - validSign = (1 == sroot -> verifyDigest( - tmpkey.getKey(), signdata, tmpsize, - msg->signature, msg->signLen)); - - } - - // now we can free the tmp space. - // tmpkey will free itself. - free(tmpspace); - - if (!validSign) - { - std::ostringstream out; - out << "p3channel::handleIncoming() Msg Failed Check!"; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - - // error somewhere along the way. - delete in; - continue; - } - - - // get the channel signature from the pkt. - channelSign sign = getChannelSign(msg); - std::map::iterator it; - if (channels.end() != (it=channels.find(sign))) - { - // add to that channel. - it -> second -> processMsg(msg); - } - else - { - // create a new channel. - channelKey *k = getChannelKey(msg); - - // Temporarily Make all Listeners... - pqichannel *npc = new pqichannel(sroot, k, - msg->title, P3Chan_Listener); - channels[sign] = npc; - npc -> processMsg(msg); - } - } - return 1; -} - -int p3channel::reBroadcast() -{ - { - std::ostringstream out; - out << "p3channel::reBroadcast()"; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - } - // - std::list outgoing; - std::map::iterator it; - for(it = channels.begin(); it != channels.end(); it++) - { - if (it -> second -> getMode() & P3Chan_Listener_Bit) - { - it -> second -> reBroadcast(outgoing); - } - } - - std::list::iterator tit; - for(tit = outgoing.begin(); tit!=outgoing.end();tit++) - { - outpkts.push_back(*tit); - } - return 1; -} - - -channelSign getChannelSign(PQChanItem *ci) -{ - std::ostringstream out; - channelSign s; - - out << "getChannelSign() "; - - channelKey tmpkey; - if (1 != tmpkey.load(ci -> certDER, ci -> certLen)) - { - out << "FAILED!"; - } - else - { - s = tmpkey.getSign(); - } - - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - return s; -} - - -channelKey *getChannelKey(PQChanItem *ci) -{ - std::ostringstream out; - out << "p3channel::getChannelKey()"; - - channelKey *k = new channelKey(); - if (0 > k -> load(ci -> certDER, ci -> certLen)) - { - out << "FAILED!" << std::endl; - delete k; - k = NULL; - } - else - { - channelSign s = getChannelSign(ci); - s.print(out); - } - - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - return k; -} - - -/* Helper function */ -MsgHash getMsgHash(PQChanItem *in) -{ - std::ostringstream out; - - MsgHash h; - int len = in -> signLen; - - out << "getMsgHash(" << len << ") "; - if (len > CHAN_SIGN_SIZE) - len = CHAN_SIGN_SIZE; - - for (int i = 0; i < len; i++) - { - h.sign[i] = in -> signature[i]; - unsigned char c = ((unsigned char *) h.sign)[i]; - out << (unsigned int) c; - if (i != len - 1) - out << ":"; - } - - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - - return h; -} - - -bool pqichannel::checkPktSignature(PQChanItem *in) -{ - { - std::ostringstream out; - out << "pqichannel::checkPktSignature"; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - } - return true; -} - - - -int p3channel::generateRandomMsg() -{ - { - std::ostringstream out; - out << "p3channel::generateRandomMsg()"; - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - } - // count how many publisher channels we have. - // generate Rnd with range (0 -> pchan) - // if 0 -> create a new pqichanneler. - // else select that one. - // - // using that pqichanneler, generate a message. - - std::map::iterator it; - int pcount = 0; - int i; - - for(it = channels.begin(); it != channels.end(); it++) - { - if (it -> second -> getMode() & P3Chan_Publisher_Bit) - { - pcount++; - } - } - - int rnd = (int) (rand() * (pcount + 1.0) / RAND_MAX); - pqichanneler *pc = NULL; - channelKey *pub = NULL; - channelKey *priv = NULL; - if (rnd == 0) - { - // create a new pqichanneler!. - pub = new channelKey(); - priv = new channelKey(); - generateRandomKeys(priv, pub); - - pc = new pqichanneler(sroot, priv, pub, "pqiChanneler"); - channelSign sign = pub -> getSign(); - channels[sign] = pc; - } - else - { - // select the chosen one. - i = 0; - for(it = channels.begin(); (i < rnd) && - (it != channels.end()); it++) - { - if (it -> second -> getMode() & - P3Chan_Publisher_Bit) - { - i++; - } - } - if (it != channels.end()) - { - pqichannel *c = it -> second; - pc = dynamic_cast(c); - } - } - - if (pc == NULL) - { - // failed this time! - return -1; - } - - pub = pc -> getKey(); - - // create a new message for the world. - PQChanItem *msg = new PQChanItem(); - -static int count = 0; - std::ostringstream out; - - cert *own = sroot -> getOwnCert(); - - out << "U:" << own -> Name() << " Says "; - out << "Hello World #" << count++; - msg -> msg = out.str(); - - /* now add in some files */ - int nfiles = (int) ((rand() * 5.0) / RAND_MAX); - for(i = 0; i < nfiles; i++) - { - PQChanItem::FileItem fi; - std::ostringstream out; - out << "file-" << count << "-" << nfiles; - out << "-" << "i" << ".dta"; - fi.name = out.str(); - fi.size = count * nfiles + i + 12354; - - msg -> files.push_back(fi); - } - - // keys and signing are handled in sendmsg(). - pc -> sendmsg(msg); - return 1; -} - - -int p3channel::generateRandomKeys(channelKey *priv, channelKey *pub) -{ - // sslroot will generate the pair... - // we need to split it into an pub/private. - - EVP_PKEY *keypair = EVP_PKEY_new(); - EVP_PKEY *pubkey = EVP_PKEY_new(); - sroot -> generateKeyPair(keypair, 0); - - RSA *rsa1 = EVP_PKEY_get1_RSA(keypair); - RSA *rsa2 = RSAPublicKey_dup(rsa1); - - { - std::ostringstream out; - out << "p3channel::generateRandomKeys()" << std::endl; - out << "Rsa1: " << (void *) rsa1 << " & Rsa2: "; - out << (void *) rsa2 << std::endl; - - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - } - - EVP_PKEY_assign_RSA(pubkey, rsa1); - RSA_free(rsa1); // decrement ref count! - - priv -> setKey(keypair); - pub -> setKey(pubkey); - - { - std::ostringstream out; - out << "p3channel::generateRandomKey(): "; - priv -> print(out); - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - } - return 1; -} - - - -int p3channel::printMsgs() -{ - std::ostringstream out; - out << "p3channel::printMsgs()"; - - std::map::iterator it; - int pcount = 0; - for(it = channels.begin(); it != channels.end(); it++, pcount++) - { - out << std::endl << "Channel[" << pcount << "] : "; - it->first.print(out); - out << std::endl; - it -> second -> print(out); - } - - pqioutput(PQL_DEBUG_BASIC, pqichannelzone, out.str()); - return 1; -} - - - -std::ostream &pqichannel::print(std::ostream &out) -{ - out << "pqichannel::print()------------------"; - std::map::iterator it; - int i = 0; - int t = time(NULL); - int oldmsgs = 0; - for(it = msgByHash.begin(); it != msgByHash.end(); it++, i++) - { - float tpHr = (t - it->second->recvTime) / 3600.0; - float pop = (it->second->receivedCount) / (float) tpHr - tpHr / 2.0; - if (pop < 0) - { - oldmsgs++; - out << "->->-> Skipped Old Msg(" << i << ")" << std::endl; - continue; - } - - out << "-------->->->" << std::endl; - out << "Msg(" << i << ") : " << it->second->msg->msg; - out << std::endl; - out << "Received Count -> " << it->second->receivedCount; - out << std::endl; - - out << "Time Since Arrival -> " << t - it->second->recvTime; - out << std::endl; - out << "Popularity: " << pop; - out << std::endl; - out << "ReB(" << it->second->rebroadcast; - out << ") TS: " << it->second->rbcTime; - out << " or RTS: " << it->second->rbcTime - time(NULL) << std::endl; - out << "Down(" << it->second->downloaded; - out << ") TS: " << it->second->dldTime; - out << " or RTS: " << it->second->dldTime - time(NULL) << std::endl; - - channelSign s = getChannelSign(it->second->msg); - MsgHash h = getMsgHash(it->second->msg); - - s.print(out); - out << std::endl; - h.print(out); - out << std::endl; - out << "<-<-<--------"; - } - out << ">>>> Total Skipped Msgs: " << oldmsgs << std::endl; - out << "-------------------------------------"; - return out; -} - - diff --git a/libretroshare/src/pqi/p3channel.h b/libretroshare/src/pqi/p3channel.h deleted file mode 100644 index 56015ab20..000000000 --- a/libretroshare/src/pqi/p3channel.h +++ /dev/null @@ -1,314 +0,0 @@ -/* - * "$Id: p3channel.h,v 1.6 2007-03-05 21:26:03 rmf24 Exp $" - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2004-2006 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - -#ifndef MRK_P3_CHANNEL_H -#define MRK_P3_CHANNEL_H - -#include "pqi/pqichannel.h" - -/**** - * This is our channel class. - * It performs various functions. - * 1) collect channel messages. - * 2) save/restore messages. - * 3) manage their downloads.... - * 4) rebroadcast messages. - * - * You need to be able to categorise the channels - * 1) Favourites. - * 2) Standard Subscription - * 3) Listen - * 4) Others. - * - * The first three groups will be maintained. - * - * Controllable how long lists are maintained. (1 week standard) - * - * Messages are rebroadcast, At a random interval (0 - 4 hours) after - * receiving the message. - * - * Popularity rating on how much each is rebroadcast. - * - * - * There should be a couple of rating schemes to decide - * on how long something stays downloaded. - * - * 1) Time, Old stuff first. - * 2) Volume.... - * 3) Size. - * 4) Popularity. - * - */ - -#include -#include -#include - -#include "pqi/pqi.h" - -/**************** PQI_USE_XPGP ******************/ -#if defined(PQI_USE_XPGP) - -#include "pqi/xpgpcert.h" - -#else /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - -#include "pqi/sslcert.h" - -#endif /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - -#include "pqi/discItem.h" -#include "pqi/pqitunnel.h" - -/* Size of these should match the RsInterface (for ease of use ) - 16 bytes */ - -//#define CHAN_SIGN_SIZE 16 - -class channelSign -{ - public: -bool operator<(const channelSign &s) const; -bool operator==(const channelSign &s) const; -std::ostream& print(std::ostream&) const; -std::ostream& printHex(std::ostream&) const; - char sign[CHAN_SIGN_SIZE]; - -}; - -typedef channelSign MsgHash; - -class channelKey -{ - public: - channelKey(EVP_PKEY *k); - channelKey(); -virtual ~channelKey(); - -bool valid(); -int load(const unsigned char *d, int len); -int setKey(EVP_PKEY *k); -int out(unsigned char *d, int len); - -bool operator<(const channelKey &k) const; -bool operator==(const channelKey &k) const; -std::ostream& print(std::ostream&) const; - -channelSign getSign() const; -EVP_PKEY * getKey() const; - - private: -int calcSign(); - - EVP_PKEY *key; - char sign[CHAN_SIGN_SIZE]; -}; - -typedef time_t TimeStamp; - -//class TimeStamp -//{ -// public: -// -// int yr, month, day, hour, min, sec; -//}; -// - -class chanMsgSummary -{ - public: - std::string msg; - MsgHash mh; - int nofiles; - int totalsize; - TimeStamp recvd; -}; - - - -// This is used For Msg + Info storage. -class channelMsg -{ - public: -channelMsg(PQChanItem *in, TimeStamp now, TimeStamp reb); - - PQChanItem *msg; - - int receivedCount; - TimeStamp recvTime; - - bool rebroadcast; - TimeStamp rbcTime; - - bool downloaded; - TimeStamp dldTime; - - bool save; -}; - -// a little helper function. -channelSign getChannelSign(PQChanItem *ci); -channelKey * getChannelKey(PQChanItem *ci); -MsgHash getMsgHash(PQChanItem *ci); - -class pqichannel -{ - public: - - pqichannel(sslroot *, channelKey *, std::string title, int mode); -virtual ~pqichannel() { return; } - - // retrieval. - -channelMsg *findMsg(MsgHash mh); -int getMsgSummary(std::list &summary); - - -int processMsg(PQChanItem *in); -int pruneOldMsgs(); - - // check packet signature (with channel key) - // check key matches ours. - // if we have it, increment the counter. - // else add in. - - // fill with outgoing -int reBroadcast(std::list &outgoing); - -channelSign getSign(); -channelKey *getKey(); - -int getMode() { return mode; } -std::string getName() { return channelTitle; } -float getRanking() { return ranking; } -int getMsgCount() { return msgByHash.size(); } - -std::ostream& print(std::ostream&); - - protected: -sslroot *sroot; - - private: - - // analysis functions -TimeStamp getCurrentTimeStamp(); -bool checkPktSignature(PQChanItem*); -//MsgHash getPktHash(PQChanItem*); - - int mode; // Fav, Sub, Listen, Other. - std::map msgByHash; - - std::string channelTitle; - float ranking; - - protected: // needed by pqichanneler. - channelKey *key; -}; - -// specialisation with the private key, and output. -class pqichanneler: public pqichannel -{ - public: - pqichanneler(sslroot *s, - channelKey *priv, channelKey *pub, - std::string title); - -virtual ~pqichanneler() { return; } - - // Takes a partially constructed Msg, - // fills in the signature.... - // then all it has to do is pass it - // to the pqichannel which will handle the - // distribution. -int sendmsg(PQChanItem *); - - private: - channelKey *privkey; -}; - - -class p3channel: public PQTunnelService -{ - public: - p3channel(sslroot *r); -virtual ~p3channel(); - - // PQTunnelService functions. -virtual int receive(PQTunnel *); -virtual PQTunnel *send(); - -virtual int tick(); - - // doesn't use the init functions. -virtual int receive(PQTunnelInit *i) { delete i; return 1; } -virtual PQTunnelInit *sendInit() { return NULL; } - - // End of PQTunnelService functions. - - // load and save configuration. - int save_configuration(); - int load_configuration(); - - // test functions. -int generateRandomMsg(); -int generateRandomKeys(channelKey *priv, channelKey *pub); - - // retrieval fns. -pqichannel *findChannel(channelSign s); -int getChannelList(std::list &chans); - - private: - - // so we need an interface for the data. - -int handleIncoming(); - -int printMsgs(); - - // first storage. - std::map channels; - - - // -int reBroadcast(); - // maintainance. -int pruneOldMsgs(); - - // counters. -int ts_nextlp; -int min10Count; - - std::list discovered; - sslroot *sroot; - - // Storage for incoming/outgoing. - std::list inpkts; - std::list outpkts; -}; - -#endif // MRK_P3_CHANNEL_H diff --git a/libretroshare/src/pqi/p3connmgr.cc b/libretroshare/src/pqi/p3connmgr.cc new file mode 100644 index 000000000..58201e02b --- /dev/null +++ b/libretroshare/src/pqi/p3connmgr.cc @@ -0,0 +1,1823 @@ +/* + * libretroshare/src/pqi: p3connmgr.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 "pqi/p3connmgr.h" +#include "tcponudp/tou.h" +#include "util/rsprint.h" + +/* Network setup States */ + +const uint32_t RS_NET_UNKNOWN = 0x0001; +const uint32_t RS_NET_UPNP_INIT = 0x0002; +const uint32_t RS_NET_UPNP_SETUP = 0x0003; +const uint32_t RS_NET_UDP_SETUP = 0x0004; +const uint32_t RS_NET_DONE = 0x0005; + + +/* Stun modes (TODO) */ +const uint32_t RS_STUN_DHT = 0x0001; +const uint32_t RS_STUN_DONE = 0x0002; +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), + mStunStatus(0), mStatusChanged(false) +{ + mUpnpAddrValid = false; + mStunAddrValid = false; + + /* setup basics of own state */ + if (am) + { + ownState.id = mAuthMgr->OwnId(); + ownState.name = mAuthMgr->getName(ownState.id); + } + + return; +} + +peerConnectAddress::peerConnectAddress() + :type(0), ts(0) +{ + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = 0; + addr.sin_port = 0; +} + + +peerAddrInfo::peerAddrInfo() + :found(false), type(0), ts(0) +{ + laddr.sin_family = AF_INET; + laddr.sin_addr.s_addr = 0; + laddr.sin_port = 0; + + raddr.sin_family = AF_INET; + raddr.sin_addr.s_addr = 0; + raddr.sin_port = 0; +} + +peerConnectState::peerConnectState() + :id("unknown"), name("nameless"), state(0), actions(0), + 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) +{ + lastaddr.sin_family = AF_INET; + lastaddr.sin_addr.s_addr = 0; + lastaddr.sin_port = 0; + + localaddr.sin_family = AF_INET; + localaddr.sin_addr.s_addr = 0; + localaddr.sin_port = 0; + + serveraddr.sin_family = AF_INET; + serveraddr.sin_addr.s_addr = 0; + serveraddr.sin_port = 0; + + return; +} + +/***** Framework / initial implementation for a connection manager. + * + * This needs a state machine for Initialisation. + * + * Network state: + * RS_NET_UNKNOWN + * RS_NET_EXT_UNKNOWN * forwarded port (but Unknown Ext IP) * + * RS_NET_EXT_KNOWN * forwarded port with known IP/Port. * + * + * RS_NET_UPNP_CHECK * checking for UPnP * + * RS_NET_UPNP_KNOWN * confirmed UPnP ext Ip/port * + * + * RS_NET_UDP_UNKNOWN * not Ext/UPnP - to determine Ext IP/Port * + * RS_NET_UDP_KNOWN * have Stunned for Ext Addr * + * + * Transitions: + * + * RS_NET_UNKNOWN -(config)-> RS_NET_EXT_UNKNOWN + * RS_NET_UNKNOWN -(config)-> RS_NET_UPNP_UNKNOWN + * RS_NET_UNKNOWN -(config)-> RS_NET_UDP_UNKNOWN + * + * RS_NET_EXT_UNKNOWN -(DHT(ip)/Stun)-> RS_NET_EXT_KNOWN + * + * RS_NET_UPNP_UNKNOWN -(Upnp)-> RS_NET_UPNP_KNOWN + * RS_NET_UPNP_UNKNOWN -(timout/Upnp)-> RS_NET_UDP_UNKNOWN + * + * RS_NET_UDP_UNKNOWN -(stun)-> RS_NET_UDP_KNOWN + * + * + * STUN state: + * RS_STUN_INIT * done nothing * + * RS_STUN_DHT * looking up peers * + * RS_STUN_DONE * found active peer and stunned * + * + * + * Steps. + ******************************************************************* + * (1) Startup. + * - UDP port setup. + * - DHT setup. + * - Get Stun Keys -> add to DHT. + * - Feedback from DHT -> ask UDP to stun. + * + * (1) determine Network mode. + * If external Port.... Done: + * (2) + ******************************************************************* + * Stable operation: + * (1) tick and check peers. + * (2) handle callback. + * (3) notify of new/failed connections. + * + * + */ + +void p3ConnectMgr::netStartup() +{ + /* startup stuff */ + + /* StunInit gets a list of peers, and asks the DHT to find them... + * This is needed for all systems so startup straight away + */ + + loadConfiguration(); + netDhtInit(); + netUdpInit(); + netStunInit(); + + /* decide which net setup mode we're going into + */ + + connMtx.lock(); /* LOCK MUTEX */ + + mNetInitTS = time(NULL); + + switch(ownState.netMode) + { + case RS_NET_MODE_UPNP: + mNetStatus = RS_NET_UPNP_INIT; + break; + + case RS_NET_MODE_EXT: /* v similar to UDP */ + case RS_NET_MODE_UDP: + default: + mNetStatus = RS_NET_UDP_SETUP; + break; + + } + connMtx.unlock(); /* UNLOCK MUTEX */ +} + + +void p3ConnectMgr::tick() +{ + netTick(); + tickMonitors(); + +} + +void p3ConnectMgr::netTick() +{ + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::netTick()" << std::endl; +#endif + + connMtx.lock(); /* LOCK MUTEX */ + + uint32_t netStatus = mNetStatus; + + connMtx.unlock(); /* UNLOCK MUTEX */ + + switch(netStatus) + { + case RS_NET_UNKNOWN: + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::netTick() STATUS: UNKNOWN" << std::endl; +#endif + /* RS_NET_UNKNOWN -(config)-> RS_NET_EXT_INIT + * RS_NET_UNKNOWN -(config)-> RS_NET_UPNP_INIT + * RS_NET_UNKNOWN -(config)-> RS_NET_UDP_INIT + */ + netStartup(); + break; + + case RS_NET_UPNP_INIT: +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::netTick() STATUS: UPNP_INIT" << std::endl; +#endif + netUpnpInit(); + break; + + case RS_NET_UPNP_SETUP: +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::netTick() STATUS: UPNP_SETUP" << std::endl; +#endif + netUpnpCheck(); + break; + + case RS_NET_UDP_SETUP: +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::netTick() STATUS: UDP_SETUP" << std::endl; +#endif + netUdpCheck(); + break; + + case RS_NET_DONE: +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::netTick() STATUS: DONE" << std::endl; +#endif + default: + break; + } + + return; +} + + +void p3ConnectMgr::netUdpInit() +{ + connMtx.lock(); /* LOCK MUTEX */ + + struct sockaddr_in iaddr = ownState.localaddr; + + connMtx.unlock(); /* UNLOCK MUTEX */ + + /* open our udp port */ + tou_init((struct sockaddr *) &iaddr, sizeof(iaddr)); +} + + +void p3ConnectMgr::netDhtInit() +{ + connMtx.lock(); /* LOCK MUTEX */ + + uint32_t vs = ownState.visState; + + connMtx.unlock(); /* UNLOCK MUTEX */ + + mDhtMgr->setDhtOn(!(vs & RS_VIS_STATE_NODHT)); +} + + +void p3ConnectMgr::netUpnpInit() +{ + uint16_t eport, iport; + + connMtx.lock(); /* LOCK MUTEX */ + + /* get the ports from the configuration */ + + mNetStatus = RS_NET_UPNP_SETUP; + + connMtx.unlock(); /* UNLOCK MUTEX */ + + mUpnpMgr->setInternalPort(iport); + mUpnpMgr->setExternalPort(eport); + + mUpnpMgr->enableUPnP(true); +} + +void p3ConnectMgr::netUpnpCheck() +{ + /* grab timestamp */ + connMtx.lock(); /* LOCK MUTEX */ + + time_t delta = time(NULL) - mNetInitTS; + + connMtx.unlock(); /* UNLOCK MUTEX */ + + struct sockaddr_in extAddr; + int upnpState = mUpnpMgr->getUPnPActive(); + + if ((upnpState < 0) || + ((upnpState == 0) && (delta > MAX_UPNP_INIT))) + { + /* fallback to UDP startup */ + connMtx.lock(); /* LOCK MUTEX */ + + mUpnpAddrValid = false; + mNetStatus = RS_NET_UDP_SETUP; + ownState.netMode = RS_NET_MODE_UDP; /* UPnP Failed us! */ + + connMtx.unlock(); /* UNLOCK MUTEX */ + } + else if ((upnpState > 0) && + mUpnpMgr->getExternalAddress(extAddr)) + { + /* switch to UDP startup */ + connMtx.lock(); /* LOCK MUTEX */ + + mUpnpAddrValid = true; + mUpnpExtAddr = extAddr; + mNetStatus = RS_NET_UDP_SETUP; + + connMtx.unlock(); /* UNLOCK MUTEX */ + } +} + +void p3ConnectMgr::netUdpCheck() +{ +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::netUdpCheck()" << std::endl; +#endif + if (stunCheck()) + { + bool extValid = false; + struct sockaddr_in extAddr; + uint32_t mode = 0; + + + + connMtx.lock(); /* LOCK MUTEX */ + + mNetStatus = RS_NET_DONE; + + /* get the addr from the configuration */ + struct sockaddr_in iaddr = ownState.localaddr; + + if (mUpnpAddrValid) + { + extValid = true; + extAddr = mUpnpExtAddr; + } + else if (mStunAddrValid) + { + extValid = true; + extAddr = mStunExtAddr; + } + + if (extValid) + { + ownState.serveraddr = extAddr; + mode = RS_NET_CONN_TCP_LOCAL | RS_NET_CONN_UDP_DHT_SYNC; + if ((ownState.netMode == RS_NET_MODE_UPNP) || + (ownState.netMode == RS_NET_MODE_EXT)) + { + mode |= RS_NET_CONN_TCP_EXTERNAL; + } + } + + connMtx.unlock(); /* UNLOCK MUTEX */ + + if (extValid) + { + mDhtMgr->setExternalInterface(iaddr, extAddr, mode); + } + else + { + mDhtMgr->setExternalInterface(iaddr, extAddr, RS_NET_MODE_ERROR); + } + } +} + + +/******************************* UDP MAINTAINANCE ******************************** + * Interaction with the UDP is mainly for determining the External Port. + * + */ + +bool p3ConnectMgr::udpInternalAddress(struct sockaddr_in iaddr) +{ + return false; +} + +bool p3ConnectMgr::udpExtAddressCheck() +{ + /* three possibilities: + * (1) not found yet. + * (2) Found! + * (3) bad udp (port switching). + */ + struct sockaddr_in addr; + socklen_t len = sizeof(addr); + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::udpExtAddressCheck()" << std::endl; +#endif + + if (tou_extaddr((struct sockaddr *) &addr, &len)) + { + /* update UDP information */ + connMtx.lock(); /* LOCK MUTEX */ + + mStunExtAddr = addr; + mStunAddrValid = true; + + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::udpExtAddressCheck() Got "; + std::cerr << " addr: " << inet_ntoa(mStunExtAddr.sin_addr); + std::cerr << " port: " << ntohs(mStunExtAddr.sin_port); + std::cerr << std::endl; +#endif + + + connMtx.unlock(); /* UNLOCK MUTEX */ + + return true; + } + return false; +} + +void p3ConnectMgr::udpStunPeer(std::string id, struct sockaddr_in &addr) +{ +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::udpStunPeer()" << std::endl; +#endif + /* add it into udp stun list */ + tou_stunpeer((struct sockaddr *) &addr, sizeof(addr), id.c_str()); +} + +/********************************** STUN SERVERS *********************************** + * We maintain a list of stun servers. This is initialised with a set of random keys. + * + * This is gradually rolled over with time. We update with friends/friends of friends, + * and the lists that they provide (part of AutoDisc). + * + * max 100 entries? + */ + +void p3ConnectMgr::netStunInit() +{ + stunInit(); +} + +void p3ConnectMgr::stunInit() +{ + + connMtx.lock(); /* LOCK MUTEX */ + + /* push stun list to DHT */ + std::list::iterator it; + for(it = mStunList.begin(); it != mStunList.end(); it++) + { + mDhtMgr->addStun(*it); + } + mStunStatus = RS_STUN_DHT; + + connMtx.unlock(); /* UNLOCK MUTEX */ +} + +bool p3ConnectMgr::stunCheck() +{ + /* check if we've got a Stun result */ + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::stunCheck()" << std::endl; +#endif + + + if (udpExtAddressCheck()) + { + /* set external UDP address */ + mDhtMgr->doneStun(); + + connMtx.lock(); /* LOCK MUTEX */ + + mStunStatus = RS_STUN_DONE; + + connMtx.unlock(); /* UNLOCK MUTEX */ + + return true; + } + return false; +} + +void p3ConnectMgr::stunStatus(std::string id, struct sockaddr_in addr, uint32_t flags) +{ + std::cerr << "p3ConnectMgr::stunStatus()"; + std::cerr << " id: " << RsUtil::BinToHex(id) << " addr: " << inet_ntoa(addr.sin_addr); + std::cerr << " port: " << ntohs(addr.sin_port); + std::cerr << std::endl; + + connMtx.lock(); /* LOCK MUTEX */ + + bool stillStunning = (mStunStatus == RS_STUN_DHT); + + connMtx.unlock(); /* UNLOCK MUTEX */ + + if (stillStunning) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::stunStatus() Sending to UDP" << std::endl; +#endif + /* push to the UDP */ + udpStunPeer(id, addr); + } + + /* push to the stunCollect */ + stunCollect(id, addr, flags); +} + +/* FLAGS + +ONLINE +EXT +UPNP +UDP +FRIEND +FRIEND_OF_FRIEND +OTHER + +*/ + +void p3ConnectMgr::stunCollect(std::string id, struct sockaddr_in addr, uint32_t flags) +{ + /* if peer is online - move to the top */ + connMtx.lock(); /* LOCK MUTEX */ + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::stunCollect() id: " << RsUtil::BinToHex(id) << std::endl; +#endif + + std::list::iterator it; + it = std::find(mStunList.begin(), mStunList.end(), id); + if (it == mStunList.end()) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::stunCollect() Id not in List" << std::endl; +#endif + /* add it in: + * if FRIEND / ONLINE or if list is short. + */ + if ((flags & RS_STUN_ONLINE) || (flags & RS_STUN_FRIEND) + || (mStunList.size() < RS_STUN_LIST_MIN)) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::stunCollect() Id added to Front" << std::endl; +#endif + /* push to the front */ + mStunList.push_front(id); + } + } + else + { + /* if they're online ... move to the front + */ + if (flags & RS_STUN_ONLINE) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::stunCollect() Id moved to Front" << std::endl; +#endif + /* move to front */ + mStunList.erase(it); + mStunList.push_front(id); + } + } + + connMtx.unlock(); /* UNLOCK MUTEX */ +} + +/******************************** Network Status ********************************* + * Configuration Loading / Saving. + */ + + +void p3ConnectMgr::addMonitor(pqiMonitor *mon) +{ + /* + */ + connMtx.lock(); /* LOCK MUTEX */ + connMtx.unlock(); /* UNLOCK MUTEX */ + std::list::iterator it; + it = std::find(clients.begin(), clients.end(), mon); + if (it != clients.end()) + { + return; + } + + mon->setConnectionMgr(this); + clients.push_back(mon); + return; +} + +void p3ConnectMgr::removeMonitor(pqiMonitor *mon) +{ + /* + */ + connMtx.lock(); /* LOCK MUTEX */ + connMtx.unlock(); /* UNLOCK MUTEX */ + std::list::iterator it; + it = std::find(clients.begin(), clients.end(), mon); + if (it == clients.end()) + { + return; + } + (*it)->setConnectionMgr(NULL); + clients.erase(it); + + return; +} + + +void p3ConnectMgr::tickMonitors() +{ + std::list actionList; + std::map::iterator it; + + if (mStatusChanged) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::tickMonitors() StatusChanged! List:" << std::endl; +#endif + connMtx.lock(); /* LOCK MUTEX */ + connMtx.unlock(); /* UNLOCK MUTEX */ + /* assemble list */ + for(it = mFriendList.begin(); it != mFriendList.end(); it++) + { + if (it->second.actions) + { + /* add in */ + pqipeer peer; + peer.id = it->second.id; + peer.name = it->second.name; + peer.state = it->second.state; + peer.actions = it->second.actions; + + /* reset action */ + it->second.actions = 0; + + actionList.push_back(peer); + +#ifdef CONN_DEBUG + std::cerr << "Friend: " << peer.name; + std::cerr << " Id: " << peer.id; + std::cerr << " State: " << peer.state; + if (peer.state & RS_PEER_S_FRIEND) + std::cerr << " S:RS_PEER_S_FRIEND"; + if (peer.state & RS_PEER_S_ONLINE) + std::cerr << " S:RS_PEER_S_ONLINE"; + if (peer.state & RS_PEER_S_CONNECTED) + std::cerr << " S:RS_PEER_S_CONNECTED"; + std::cerr << " Actions: " << peer.actions; + if (peer.actions & RS_PEER_NEW) + std::cerr << " A:RS_PEER_NEW"; + if (peer.actions & RS_PEER_MOVED) + std::cerr << " A:RS_PEER_MOVED"; + if (peer.actions & RS_PEER_CONNECTED) + std::cerr << " A:RS_PEER_CONNECTED"; + if (peer.actions & RS_PEER_DISCONNECTED) + std::cerr << " A:RS_PEER_DISCONNECTED"; + if (peer.actions & RS_PEER_CONNECT_REQ) + std::cerr << " A:RS_PEER_CONNECT_REQ"; + + std::cerr << std::endl; +#endif + } + } + /* do the Others as well! */ + for(it = mOthersList.begin(); it != mOthersList.end(); it++) + { + if (it->second.actions) + { + /* add in */ + pqipeer peer; + peer.id = it->second.id; + peer.name = it->second.name; + peer.state = it->second.state; + peer.actions = it->second.actions; + + /* reset action */ + it->second.actions = 0; + +#ifdef CONN_DEBUG + std::cerr << "Other: " << peer.name; + std::cerr << " Id: " << peer.id; + std::cerr << " State: " << peer.state; + if (peer.state & RS_PEER_S_FRIEND) + std::cerr << " S:RS_PEER_S_FRIEND"; + if (peer.state & RS_PEER_S_ONLINE) + std::cerr << " S:RS_PEER_S_ONLINE"; + if (peer.state & RS_PEER_S_CONNECTED) + std::cerr << " S:RS_PEER_S_CONNECTED"; + std::cerr << " Actions: " << peer.actions; + if (peer.actions & RS_PEER_NEW) + std::cerr << " A:RS_PEER_NEW"; + if (peer.actions & RS_PEER_MOVED) + std::cerr << " A:RS_PEER_MOVED"; + if (peer.actions & RS_PEER_CONNECTED) + std::cerr << " A:RS_PEER_CONNECTED"; + if (peer.actions & RS_PEER_DISCONNECTED) + std::cerr << " A:RS_PEER_DISCONNECTED"; + if (peer.actions & RS_PEER_CONNECT_REQ) + std::cerr << " A:RS_PEER_CONNECT_REQ"; + + std::cerr << std::endl; +#endif + + actionList.push_back(peer); + } + } + mStatusChanged = false; + +#ifdef CONN_DEBUG + std::cerr << "Sending to " << clients.size() << " monitorClients"; + std::cerr << std::endl; +#endif + + /* send to all monitors */ + std::list::iterator mit; + for(mit = clients.begin(); mit != clients.end(); mit++) + { + (*mit)->statusChange(actionList); + } + } +} + + +const std::string p3ConnectMgr::getOwnId() +{ + if (mAuthMgr) + { + return mAuthMgr->OwnId(); + } + else + { + std::string nullStr; + return nullStr; + } +} + + +bool p3ConnectMgr::getOwnNetStatus(peerConnectState &state) +{ + connMtx.lock(); /* LOCK MUTEX */ + connMtx.unlock(); /* UNLOCK MUTEX */ + state = ownState; + return true; +} + +bool p3ConnectMgr::isFriend(std::string id) +{ + connMtx.lock(); /* LOCK MUTEX */ + connMtx.unlock(); /* UNLOCK MUTEX */ + return (mFriendList.end() != mFriendList.find(id)); +} + +bool p3ConnectMgr::getFriendNetStatus(std::string id, peerConnectState &state) +{ + /* check for existing */ + std::map::iterator it; + connMtx.lock(); /* LOCK MUTEX */ + connMtx.unlock(); /* UNLOCK MUTEX */ + it = mFriendList.find(id); + if (it == mFriendList.end()) + { + return false; + } + + state = it->second; + return true; +} + + +bool p3ConnectMgr::getOthersNetStatus(std::string id, peerConnectState &state) +{ + /* check for existing */ + std::map::iterator it; + connMtx.lock(); /* LOCK MUTEX */ + connMtx.unlock(); /* UNLOCK MUTEX */ + it = mOthersList.find(id); + if (it == mOthersList.end()) + { + return false; + } + + state = it->second; + return true; +} + + +void p3ConnectMgr::getOnlineList(std::list &peers) +{ + /* check for existing */ + std::map::iterator it; + connMtx.lock(); /* LOCK MUTEX */ + connMtx.unlock(); /* UNLOCK MUTEX */ + for(it = mFriendList.begin(); it != mFriendList.end(); it++) + { + if (it->second.state & RS_PEER_S_ONLINE) + { + peers.push_back(it->first); + } + } + return; +} + +void p3ConnectMgr::getFriendList(std::list &peers) +{ + /* check for existing */ + std::map::iterator it; + connMtx.lock(); /* LOCK MUTEX */ + connMtx.unlock(); /* UNLOCK MUTEX */ + for(it = mFriendList.begin(); it != mFriendList.end(); it++) + { + peers.push_back(it->first); + } + return; +} + + +void p3ConnectMgr::getOthersList(std::list &peers) +{ + /* check for existing */ + std::map::iterator it; + connMtx.lock(); /* LOCK MUTEX */ + connMtx.unlock(); /* UNLOCK MUTEX */ + for(it = mOthersList.begin(); it != mOthersList.end(); it++) + { + peers.push_back(it->first); + } + return; +} + + + +bool p3ConnectMgr::connectAttempt(std::string id, struct sockaddr_in &addr, uint32_t &type) +{ + /* check for existing */ + std::map::iterator it; + connMtx.lock(); /* LOCK MUTEX */ + connMtx.unlock(); /* UNLOCK MUTEX */ + it = mFriendList.find(id); + if (it == mFriendList.end()) + { + return false; + } + + if (it->second.connAddrs.size() < 1) + { + return false; + } + + it->second.inConnAttempt = true; + it->second.currentConnAddr = it->second.connAddrs.front(); + it->second.connAddrs.pop_front(); + + addr = it->second.currentConnAddr.addr; + type = it->second.currentConnAddr.type; + + return true; +} + + +/**************************** + * Update state, + * trigger retry if necessary, + * + * remove from DHT? + * + */ + +bool p3ConnectMgr::connectResult(std::string id, bool success, uint32_t flags) +{ + /* check for existing */ + std::map::iterator it; + connMtx.lock(); /* LOCK MUTEX */ + connMtx.unlock(); /* UNLOCK MUTEX */ + it = mFriendList.find(id); + if (it == mFriendList.end()) + { + return false; + } + + it->second.inConnAttempt = false; + + if (success) + { + /* remove other attempts */ + it->second.connAddrs.clear(); + mDhtMgr->dropPeer(id); + + /* update address */ + + /* change state */ + it->second.state |= RS_PEER_S_CONNECTED; + it->second.actions |= RS_PEER_CONNECTED; + mStatusChanged = true; + + return true; + } + + /* if currently connected -> flag as failed */ + if (it->second.state & RS_PEER_S_CONNECTED) + { + it->second.state ^= RS_PEER_S_CONNECTED; + it->second.actions |= RS_PEER_DISCONNECTED; + + mDhtMgr->findPeer(id); + if (it->second.visState & RS_VIS_STATE_NODHT) + { + /* hidden from DHT world */ + } + else + { + mDhtMgr->findPeer(id); + } + + } + + + if (it->second.connAddrs.size() < 1) + { + return true; + } + + + it->second.actions |= RS_PEER_CONNECT_REQ; + mStatusChanged = true; + + return true; +} + + + + +/******************************** Feedback ...... ********************************* + * From various sources + */ + +void p3ConnectMgr::peerStatus(std::string id, + struct sockaddr_in laddr, struct sockaddr_in raddr, + uint32_t type, uint32_t mode, uint32_t source) +{ + std::cerr << "p3ConnectMgr::peerStatus()"; + std::cerr << " id: " << id; + std::cerr << " laddr: " << inet_ntoa(laddr.sin_addr); + std::cerr << " lport: " << ntohs(laddr.sin_port); + 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 << " source: " << source; + std::cerr << std::endl; + + /* look up the id */ + std::map::iterator it; + connMtx.lock(); /* LOCK MUTEX */ + connMtx.unlock(); /* UNLOCK MUTEX */ + bool isFriend = true; + it = mFriendList.find(id); + if (it == mFriendList.end()) + { + /* check Others list */ + isFriend = false; + it = mOthersList.find(id); + if (it == mOthersList.end()) + { + /* not found - ignore */ + std::cerr << "p3ConnectMgr::peerStatus() Peer Not Found - Ignore"; + std::cerr << std::endl; + return; + } + std::cerr << "p3ConnectMgr::peerStatus() Peer is in mOthersList"; + std::cerr << std::endl; + } + + + /* update the status */ + + peerAddrInfo details; + details.type = type; + details.found = true; + details.laddr = laddr; + details.raddr = raddr; + details.ts = time(NULL); + + /* if source is DHT */ + if (source == RS_CB_DHT) + { + /* DHT can tell us about + * 1) connect type (UDP/TCP/etc) + * 2) local/external address + */ + it->second.source = RS_CB_DHT; + it->second.dht = details; + } + else if (source == RS_CB_DISC) + { + /* DISC can tell us about + * 1) connect type (UDP/TCP/etc) + * 2) local/external addresses + */ + it->second.source = RS_CB_DISC; + it->second.disc = details; + } + else if (source == RS_CB_PERSON) + { + /* PERSON can tell us about + * 1) online / offline + * 2) connect address + */ + + it->second.source = RS_CB_PERSON; + it->second.peer = details; + } + + if (!isFriend) + { + return; + } + + /* if already connected -> done */ + if (it->second.state & RS_PEER_S_CONNECTED) + { + return; + } + + + /* are the addresses different? */ + + + time_t now = time(NULL); + /* add in attempts ... local(TCP), remote(TCP) + * udp must come from notify + */ + + /* if address is same -> try local */ + if ((!isValidNet(&(details.laddr.sin_addr))) && + (sameNet(&(ownState.localaddr.sin_addr), &(details.laddr.sin_addr)))) + + { + /* add the local address */ + peerConnectAddress pca; + pca.ts = now; + pca.type = RS_NET_CONN_TCP_LOCAL; + pca.addr = details.laddr; + + it->second.connAddrs.push_front(pca); + } + + if ((details.type & RS_NET_CONN_TCP_EXTERNAL) && + (!isValidNet(&(details.raddr.sin_addr)))) + + { + /* add the remote address */ + peerConnectAddress pca; + pca.ts = now; + pca.type = RS_NET_CONN_TCP_EXTERNAL; + pca.addr = details.raddr; + + it->second.connAddrs.push_front(pca); + } + + if (it->second.inConnAttempt) + { + /* -> it'll automatically use the addresses */ + return; + } + + /* start a connection attempt */ + it->second.actions |= RS_PEER_CONNECT_REQ; + mStatusChanged = true; +} + + +void p3ConnectMgr::peerConnectRequest(std::string id, uint32_t type) +{ + std::cerr << "p3ConnectMgr::peerConnectRequest()"; + std::cerr << " id: " << id; + std::cerr << " type: " << type; + std::cerr << std::endl; + + /* look up the id */ + std::map::iterator it; + connMtx.lock(); /* LOCK MUTEX */ + connMtx.unlock(); /* UNLOCK MUTEX */ + bool isFriend = true; + it = mFriendList.find(id); + if (it == mFriendList.end()) + { + /* check Others list */ + isFriend = false; + it = mOthersList.find(id); + if (it == mOthersList.end()) + { + /* not found - ignore */ + std::cerr << "p3ConnectMgr::peerStatus() Peer Not Found - Ignore"; + std::cerr << std::endl; + return; + } + std::cerr << "p3ConnectMgr::peerStatus() Peer is in mOthersList"; + std::cerr << std::endl; + } + + /* if already connected -> done */ + if (it->second.state & RS_PEER_S_CONNECTED) + { + return; + } + + time_t now = time(NULL); + /* this is a UDP connection request (DHT only for the moment!) */ + if (isValidNet(&(it->second.dht.raddr.sin_addr))) + + { + /* add the remote address */ + peerConnectAddress pca; + pca.ts = now; + pca.type = RS_NET_CONN_UDP_DHT_SYNC; + pca.addr = it->second.dht.raddr; + + /* add to the start of list -> so handled next! */ + //it->second.connAddrs.push_front(pca); + /* push to the back ... TCP ones should be tried first */ + it->second.connAddrs.push_back(pca); + } + + + if (it->second.inConnAttempt) + { + /* -> it'll automatically use the addresses */ + return; + } + + /* start a connection attempt */ + it->second.actions |= RS_PEER_CONNECT_REQ; + mStatusChanged = true; +} + + + + +//void p3ConnectMgr::stunStatus(std::string id, struct sockaddr_in addr) + +/*******************************************************************/ +/*******************************************************************/ + +bool p3ConnectMgr::addFriend(std::string id) +{ + /* so three possibilities + * (1) already exists as friend -> do nothing. + * (2) is in others list -> move over. + * (3) is non-existant -> create new one. + */ + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::addFriend() " << id; + std::cerr << std::endl; +#endif + + connMtx.lock(); /* LOCK MUTEX */ + + + std::map::iterator it; + if (mFriendList.end() != mFriendList.find(id)) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::addFriend() Already Exists"; + std::cerr << std::endl; +#endif + /* (1) already exists */ + + connMtx.unlock(); /* UNLOCK MUTEX */ + return true; + } + + /* check with the AuthMgr if its authorised */ + if (!mAuthMgr->isAuthenticated(id)) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::addFriend() Failed Authentication"; + std::cerr << std::endl; +#endif + /* no auth */ + + connMtx.unlock(); /* UNLOCK MUTEX */ + return false; + } + + /* check if it is in others */ + if (mOthersList.end() != (it = mOthersList.find(id))) + { + /* (2) in mOthersList -> move over */ +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::addFriend() Move from Others"; + std::cerr << std::endl; +#endif + + mFriendList[id] = it->second; + mOthersList.erase(it); + + it = mFriendList.find(id); + + /* setup state */ + it->second.state = RS_PEER_S_FRIEND; + it->second.actions = RS_PEER_NEW; + + mStatusChanged = true; + + /* add peer to DHT (if not dark) */ + if (it->second.visState & RS_VIS_STATE_NODHT) + { + /* hidden from DHT world */ + } + else + { + mDhtMgr->findPeer(id); + } + + connMtx.unlock(); /* UNLOCK MUTEX */ + return true; + } + + /* get details from AuthMgr */ + pqiAuthDetails detail; + if (!mAuthMgr->getDetails(id, detail)) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::addFriend() Failed to get Details"; + std::cerr << std::endl; +#endif + /* ERROR: no details */ + + connMtx.unlock(); /* UNLOCK MUTEX */ + return false; + } + + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::addFriend() Creating New Entry"; + std::cerr << std::endl; +#endif + + /* create a new entry */ + peerConnectState pstate; + + pstate.id = id; + pstate.name = detail.name; + + pstate.state = RS_PEER_S_FRIEND; + pstate.actions = RS_PEER_NEW; + pstate.visState = RS_VIS_STATE_STD; + pstate.netMode = RS_NET_MODE_UNKNOWN; + + /* addr & timestamps -> auto cleared */ + + mFriendList[id] = pstate; + + mStatusChanged = true; + + /* expect it to be a standard DHT */ + mDhtMgr->findPeer(id); + + connMtx.unlock(); /* UNLOCK MUTEX */ + + return true; +} + + +bool p3ConnectMgr::removeFriend(std::string id) +{ + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::removeFriend() " << id; + std::cerr << std::endl; +#endif + + mDhtMgr->dropPeer(id); + + connMtx.lock(); /* LOCK MUTEX */ + + /* move to othersList */ + bool success = false; + std::map::iterator it; + if (mFriendList.end() != (it = mFriendList.find(id))) + { + + peerConnectState peer = it->second; + + mFriendList.erase(it); + + peer.state &= (~RS_PEER_S_FRIEND); + peer.state &= (~RS_PEER_S_CONNECTED); + peer.state &= (~RS_PEER_S_ONLINE); + peer.actions = RS_PEER_MOVED; + peer.inConnAttempt = false; + mOthersList[id] = peer; + mStatusChanged = true; + + success = true; + } + + connMtx.unlock(); /* UNLOCK MUTEX */ + + return success; +} + + + +bool p3ConnectMgr::addNeighbour(std::string id) +{ + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::addNeighbour() " << id; + std::cerr << std::endl; +#endif + + /* so three possibilities + * (1) already exists as friend -> do nothing. + * (2) already in others list -> do nothing. + * (3) is non-existant -> create new one. + */ + + connMtx.lock(); /* LOCK MUTEX */ + + std::map::iterator it; + if (mFriendList.end() == mFriendList.find(id)) + { + /* (1) already exists */ + connMtx.unlock(); /* UNLOCK MUTEX */ + return false; + } + + if (mOthersList.end() == mOthersList.find(id)) + { + /* (2) already exists */ + connMtx.unlock(); /* UNLOCK MUTEX */ + return true; + } + + /* check with the AuthMgr if its valid */ + if (!mAuthMgr->isValid(id)) + { + /* no auth */ + connMtx.unlock(); /* UNLOCK MUTEX */ + return false; + } + + /* get details from AuthMgr */ + pqiAuthDetails detail; + if (!mAuthMgr->getDetails(id, detail)) + { + /* no details */ + connMtx.unlock(); /* UNLOCK MUTEX */ + return false; + } + + /* create a new entry */ + peerConnectState pstate; + + pstate.id = id; + pstate.name = detail.name; + + pstate.state = 0; + pstate.actions = 0; //RS_PEER_NEW; + pstate.visState = RS_VIS_STATE_STD; + pstate.netMode = RS_NET_MODE_UNKNOWN; + + /* addr & timestamps -> auto cleared */ + + mOthersList[id] = pstate; + + // Nothing to notify anyone about... as no new information + //mStatusChanged = true; + + connMtx.unlock(); /* UNLOCK MUTEX */ + + return true; +} + + +/*******************************************************************/ +/*******************************************************************/ + /*************** External Control ****************/ +bool p3ConnectMgr::retryConnect(std::string id) +{ + /* push addresses onto stack */ + std::cerr << "p3ConnectMgr::retryConnect()"; + std::cerr << " id: " << id; + std::cerr << std::endl; + + /* look up the id */ + std::map::iterator it; + connMtx.lock(); /* LOCK MUTEX */ + connMtx.unlock(); /* UNLOCK MUTEX */ + + if (mFriendList.end() == (it = mFriendList.find(id))) + { + std::cerr << "p3ConnectMgr::retryConnect() Peer is not Friend"; + std::cerr << std::endl; + return false; + } + + /* if already connected -> done */ + if (it->second.state & RS_PEER_S_CONNECTED) + { + std::cerr << "p3ConnectMgr::retryConnect() Peer Already Connected"; + std::cerr << std::endl; + return true; + } + + /* are the addresses different? */ + + time_t now = time(NULL); + std::list::iterator cit; + + /* add in attempts ... local(TCP), remote(TCP) + */ + + /* if address is same -> try local */ + if ((isValidNet(&(it->second.localaddr.sin_addr))) && + (sameNet(&(ownState.localaddr.sin_addr), + &(it->second.localaddr.sin_addr)))) + + { + std::cerr << "p3ConnectMgr::retryConnect() Local Address Valid: "; + std::cerr << inet_ntoa(it->second.localaddr.sin_addr); + std::cerr << ":" << ntohs(it->second.localaddr.sin_port); + std::cerr << std::endl; + + bool localExists = false; + if ((it->second.inConnAttempt) && + (it->second.currentConnAddr.type == RS_NET_CONN_TCP_LOCAL)) + { + localExists = true; + } + + for(cit = it->second.connAddrs.begin(); + (!localExists) && (cit != it->second.connAddrs.begin()); cit++) + { + if (cit->type == RS_NET_CONN_TCP_LOCAL) + { + localExists = true; + } + } + + /* check if there is a local one on there already */ + + if (!localExists) + { + std::cerr << "p3ConnectMgr::retryConnect() Adding Local Addr to Queue"; + std::cerr << std::endl; + + /* add the local address */ + peerConnectAddress pca; + pca.ts = now; + pca.type = RS_NET_CONN_TCP_LOCAL; + pca.addr = it->second.localaddr; + + it->second.connAddrs.push_front(pca); + } + else + { + std::cerr << "p3ConnectMgr::retryConnect() Local Addr already in Queue"; + std::cerr << std::endl; + } + } + + /* otherwise try external ... (should check flags) */ + if ((isValidNet(&(it->second.serveraddr.sin_addr))) && (1)) + // (it->second.netMode & RS_NET_CONN_TCP_EXTERNAL)) + { + std::cerr << "p3ConnectMgr::retryConnect() Ext Address Valid (+EXT Flag): "; + std::cerr << inet_ntoa(it->second.serveraddr.sin_addr); + std::cerr << ":" << ntohs(it->second.serveraddr.sin_port); + std::cerr << std::endl; + + + bool remoteExists = false; + if ((it->second.inConnAttempt) && + (it->second.currentConnAddr.type == RS_NET_CONN_TCP_EXTERNAL)) + { + remoteExists = true; + } + + for(cit = it->second.connAddrs.begin(); + (!remoteExists) && (cit != it->second.connAddrs.begin()); cit++) + { + if (cit->type == RS_NET_CONN_TCP_EXTERNAL) + { + remoteExists = true; + } + } + + /* check if there is a local one on there already */ + + if (!remoteExists) + { + std::cerr << "p3ConnectMgr::retryConnect() Adding Ext Addr to Queue"; + std::cerr << std::endl; + + /* add the remote address */ + peerConnectAddress pca; + pca.ts = now; + pca.type = RS_NET_CONN_TCP_EXTERNAL; + pca.addr = it->second.serveraddr; + + it->second.connAddrs.push_front(pca); + } + else + { + std::cerr << "p3ConnectMgr::retryConnect() Ext Addr already in Queue"; + std::cerr << std::endl; + } + } + + if (it->second.inConnAttempt) + { + /* -> it'll automatically use the addresses */ + return true; + } + + /* start a connection attempt */ + it->second.actions |= RS_PEER_CONNECT_REQ; + mStatusChanged = true; + + return true; +} + + + +bool p3ConnectMgr::setLocalAddress(std::string id, struct sockaddr_in addr) +{ + connMtx.lock(); /* LOCK MUTEX */ + connMtx.unlock(); /* UNLOCK MUTEX */ + if (id == mAuthMgr->OwnId()) + { + ownState.localaddr = addr; + return true; + } + + /* check if it is a friend */ + std::map::iterator it; + if (mFriendList.end() == (it = mFriendList.find(id))) + { + if (mOthersList.end() == (it = mOthersList.find(id))) + { + return false; + } + } + + /* "it" points to peer */ + it->second.localaddr = addr; + + return true; +} + +bool p3ConnectMgr::setExtAddress(std::string id, struct sockaddr_in addr) +{ + connMtx.lock(); /* LOCK MUTEX */ + connMtx.unlock(); /* UNLOCK MUTEX */ + if (id == mAuthMgr->OwnId()) + { + ownState.serveraddr = addr; + return true; + } + + /* check if it is a friend */ + std::map::iterator it; + if (mFriendList.end() == (it = mFriendList.find(id))) + { + if (mOthersList.end() == (it = mOthersList.find(id))) + { + return false; + } + } + + /* "it" points to peer */ + it->second.serveraddr = addr; + + return true; +} + +bool p3ConnectMgr::setNetworkMode(std::string id, uint32_t netMode) +{ + connMtx.lock(); /* LOCK MUTEX */ + connMtx.unlock(); /* UNLOCK MUTEX */ + return false; +} + +bool p3ConnectMgr::getUPnPState() +{ + return mUpnpMgr->getUPnPActive(); +} + +bool p3ConnectMgr::getUPnPEnabled() +{ + return mUpnpMgr->getUPnPEnabled(); +} + +bool p3ConnectMgr::getDHTEnabled() +{ + return mDhtMgr->getDhtOn(); +} + + +/*******************************************************************/ + +bool p3ConnectMgr::checkNetAddress() +{ + std::list addrs = getLocalInterfaces(); + std::list::iterator it; + + connMtx.lock(); /* LOCK MUTEX */ + connMtx.unlock(); /* UNLOCK MUTEX */ + bool found = false; + for(it = addrs.begin(); (!found) && (it != addrs.end()); it++) + { + if ((*it) == inet_ntoa(ownState.localaddr.sin_addr)) + { + found = true; + } + } + /* check that we didn't catch 0.0.0.0 - if so go for prefered */ + if ((found) && (ownState.localaddr.sin_addr.s_addr == 0)) + { + found = false; + } + + if (!found) + { + ownState.localaddr.sin_addr = getPreferredInterface(); + } + if ((isPrivateNet(&(ownState.localaddr.sin_addr))) || + (isLoopbackNet(&(ownState.localaddr.sin_addr)))) + { + /* firewalled */ + //own_cert -> Firewalled(true); + } + else + { + //own_cert -> Firewalled(false); + } + + int port = ntohs(ownState.localaddr.sin_port); + if ((port < PQI_MIN_PORT) || (port > PQI_MAX_PORT)) + { + ownState.localaddr.sin_port = htons(PQI_DEFAULT_PORT); + } + + /* if localaddr = serveraddr, then ensure that the ports + * are the same (modify server)... this mismatch can + * occur when the local port is changed.... + */ + + if (ownState.localaddr.sin_addr.s_addr == + ownState.serveraddr.sin_addr.s_addr) + { + ownState.serveraddr.sin_port = + ownState.localaddr.sin_port; + } + + // ensure that address family is set, otherwise windows Barfs. + ownState.localaddr.sin_family = AF_INET; + ownState.serveraddr.sin_family = AF_INET; + ownState.lastaddr.sin_family = AF_INET; + + return 1; +} + + +/************************* p3config functions **********************/ +/*******************************************************************/ + /* Key Functions to be overloaded for Full Configuration */ + +/**** TODO ****/ + +RsSerialiser *p3ConnectMgr::setupSerialiser() +{ + RsSerialiser *rss = new RsSerialiser(); + //rss->addSerialType(new RsConfigSerialiser()); + + return rss; +} + + +std::list p3ConnectMgr::saveList(bool &cleanup) +{ + /* create a list of current peers */ + std::list saveData; + cleanup = true; + connMtx.lock(); /* LOCK MUTEX */ + connMtx.unlock(); /* UNLOCK MUTEX */ + + return saveData; +} + +bool p3ConnectMgr::loadList(std::list load) +{ + /* load the list of peers */ + std::list::iterator it; + for(it = load.begin(); it != load.end(); it++) + { + + connMtx.lock(); /* LOCK MUTEX */ + connMtx.unlock(); /* UNLOCK MUTEX */ + delete (*it); + } + + return true; +} + +/*******************************************************************/ +#if 0 + +/******************************** Load/Save Config ********************************* + * Configuration Loading / Saving. + */ + + +void p3ConnectMgr::saveConfiguration() +{ + + return; +} + +void p3ConnectMgr::loadConfiguration() +{ + /* open the config file.... + * load: + * (1) a list of friends + * (2) a list of stun peers + */ + return; +} + + + std::string configFile = configMgr->getConfigDir(); + + configFile += "rsnet.state"; + + /* open file */ + while(NULL != (item = config.read())) + { + + switch(item->SubType()) + { + case OWN_CONFIG: + { + RsPeerConfigItem *peeritem = (RsPeerConfigItem *) item; + setupConfig(peeritem); + break; + } + case PEER_CONFIG: + { + RsPeerConfigItem *peeritem = (RsPeerConfigItem *) item; + addPeer(peeritem); + break; + } + case STUNLIST: + { + RsStunConfigItem *slitem = (RsStunConfigItem *) item; + + /* add to existing list */ + for(it = slitem.begin(); + it = slitem.end(); it++) + { + mStunList.push_back(*it); + } + break; + } + default: + break; + } + + delete item; + } + +} + + +void p3ConnectMgr::setupOwnNetConfig(RsPeerConfigItem *item) +{ + + return; +} + +#endif + diff --git a/libretroshare/src/pqi/p3connmgr.h b/libretroshare/src/pqi/p3connmgr.h new file mode 100644 index 000000000..71ad01a9e --- /dev/null +++ b/libretroshare/src/pqi/p3connmgr.h @@ -0,0 +1,285 @@ +/* + * libretroshare/src/pqi: p3connmgr.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 MRK_PQI_CONNECTION_MANAGER_HEADER +#define MRK_PQI_CONNECTION_MANAGER_HEADER + +#include "pqi/pqimonitor.h" +#include "pqi/p3dhtmgr.h" +#include "pqi/p3upnpmgr.h" +#include "pqi/p3authmgr.h" + +#include "pqi/p3cfgmgr.h" + +#include "util/rsthreads.h" + +const uint32_t RS_VIS_STATE_NODISC = 0x0001; +const uint32_t RS_VIS_STATE_NODHT = 0x0002; + +const uint32_t RS_VIS_STATE_STD = 0x0000; +const uint32_t RS_VIS_STATE_GRAY = RS_VIS_STATE_NODHT; +const uint32_t RS_VIS_STATE_DARK = RS_VIS_STATE_NODISC | RS_VIS_STATE_NODHT; +const uint32_t RS_VIS_STATE_BROWN = RS_VIS_STATE_NODISC; + +const uint32_t RS_NET_MODE_UNKNOWN = 0x0000; +const uint32_t RS_NET_MODE_EXT = 0x0001; +const uint32_t RS_NET_MODE_UPNP = 0x0002; +const uint32_t RS_NET_MODE_UDP = 0x0003; +const uint32_t RS_NET_MODE_ERROR = 0x0004; + + +/* order of attempts ... */ +const uint32_t RS_NET_CONN_TCP_ALL = 0x000f; +const uint32_t RS_NET_CONN_UDP_ALL = 0x00f0; + +const uint32_t RS_NET_CONN_TCP_LOCAL = 0x0001; +const uint32_t RS_NET_CONN_TCP_EXTERNAL = 0x0002; +const uint32_t RS_NET_CONN_UDP_DHT_SYNC = 0x0010; + + +class peerAddrInfo +{ + public: + peerAddrInfo(); /* init */ + + bool found; + uint32_t type; + struct sockaddr_in laddr, raddr; + time_t ts; +}; + +class peerConnectAddress +{ + public: + peerConnectAddress(); /* init */ + + struct sockaddr_in addr; + uint32_t type; + time_t ts; +}; + +class peerConnectState +{ + public: + peerConnectState(); /* init */ + + std::string id; + std::string name; + + uint32_t state; + uint32_t actions; + + uint32_t netMode; /* EXT / UPNP / UDP / INVALID */ + + /* Fix this up! */ + + // public for the moment. + struct sockaddr_in lastaddr, localaddr, serveraddr; + + /* determines how public this peer wants to be... + * + * STD = advertise to Peers / DHT checking etc + * GRAY = share with friends / but not DHT + * DARK = hidden from all + * BROWN? = hidden from friends / but on DHT + */ + + uint32_t visState; /* STD, GRAY, DARK */ + + uint32_t source; /* most current source */ + peerAddrInfo dht; + peerAddrInfo disc; + peerAddrInfo peer; + + /* a list of connect attempts to make (in order) */ + bool inConnAttempt; + time_t connAttemptTS; + peerConnectAddress currentConnAddr; + std::list connAddrs; + + + /* stuff here un-used at the moment */ + + + 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. +}; + + +class p3ConnectMgr: public pqiConnectCb, public p3Config +{ + public: + + p3ConnectMgr(p3AuthMgr *authMgr); + +void tick(); + + /*************** Setup ***************************/ +void setDhtMgr(p3DhtMgr *dmgr) { mDhtMgr = dmgr; } +void setUpnpMgr(p3UpnpMgr *umgr) { mUpnpMgr = umgr; } +bool checkNetAddress(); /* check our address is sensible */ + + /*************** External Control ****************/ +bool retryConnect(std::string id); + +bool getUPnPState(); +bool getUPnPEnabled(); +bool getDHTEnabled(); + +bool setLocalAddress(std::string id, struct sockaddr_in addr); +bool setExtAddress(std::string id, struct sockaddr_in addr); +bool setNetworkMode(std::string id, uint32_t netMode); + + /* add/remove friends */ +bool addFriend(std::string); +bool removeFriend(std::string); +bool addNeighbour(std::string); + + /*************** External Control ****************/ + + /* access to network details (called through Monitor) */ +const std::string getOwnId(); +bool getOwnNetStatus(peerConnectState &state); + +bool isFriend(std::string id); +bool getFriendNetStatus(std::string id, peerConnectState &state); +bool getOthersNetStatus(std::string id, peerConnectState &state); + +void getOnlineList(std::list &peers); +void getFriendList(std::list &peers); +void getOthersList(std::list &peers); + + + /**************** handle monitors *****************/ +void addMonitor(pqiMonitor *mon); +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); +virtual void peerConnectRequest(std::string id, uint32_t type); +virtual void stunStatus(std::string id, struct sockaddr_in addr, uint32_t flags); + + /****************** Connections *******************/ +bool connectAttempt(std::string id, struct sockaddr_in &addr, uint32_t &type); +bool connectResult(std::string id, bool success, uint32_t flags); + + +protected: + + /* Internal Functions */ +void netTick(); +void netStartup(); + + /* startup the bits */ +void netDhtInit(); +void netUdpInit(); +void netStunInit(); + + + + +void netInit(); + +void netExtInit(); +void netExtCheck(); + +void netUpnpInit(); +void netUpnpCheck(); + +void netUdpCheck(); + + /* Udp / Stun functions */ +bool udpInternalAddress(struct sockaddr_in iaddr); +bool udpExtAddressCheck(); +void udpStunPeer(std::string id, struct sockaddr_in &addr); + +void stunInit(); +bool stunCheck(); +void stunCollect(std::string id, struct sockaddr_in addr, uint32_t flags); + + /* monitor control */ +void tickMonitors(); + + + /* temporary for testing */ +virtual void loadConfiguration() { return; } + + protected: +/*****************************************************************/ +/*********************** p3config ******************************/ + /* Key Functions to be overloaded for Full Configuration */ + virtual RsSerialiser *setupSerialiser(); + virtual std::list saveList(bool &cleanup); + virtual bool loadList(std::list load); +/*****************************************************************/ + + +#if 0 + +void setupOwnNetConfig(RsPeerConfigItem *item); +void addPeer(RsPeerConfigItem *item); + +#endif + +private: + + p3AuthMgr *mAuthMgr; + p3DhtMgr *mDhtMgr; + p3UpnpMgr *mUpnpMgr; + + RsMutex connMtx; /* protects below */ + + time_t mNetInitTS; + uint32_t mNetStatus; + uint32_t mStunStatus; + bool mStatusChanged; + + std::list clients; + + + /* external Address determination */ + bool mUpnpAddrValid, mStunAddrValid; + struct sockaddr_in mUpnpExtAddr; + struct sockaddr_in mStunExtAddr; + + + /* these are protected for testing */ +protected: + +void addPeer(std::string id, std::string name); /* tmp fn */ + + peerConnectState ownState; + + std::list mStunList; + std::map mFriendList; + std::map mOthersList; +}; + +#endif // MRK_PQI_CONNECTION_MANAGER_HEADER diff --git a/libretroshare/src/pqi/p3dhtmgr.cc b/libretroshare/src/pqi/p3dhtmgr.cc new file mode 100644 index 000000000..6a7a70b0b --- /dev/null +++ b/libretroshare/src/pqi/p3dhtmgr.cc @@ -0,0 +1,1337 @@ +/* + * libretroshare/src/pqi: p3dhtmgr.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-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 "pqi/p3dhtmgr.h" +#include +#include +#include + +#include "util/rsprint.h" + +#define DHT_DEBUG 1 + + +/**** DHT State Variables **** + * TODO: + * (1) notify call in. + * (2) publish/search parameters. + * (3) callback. + * (4) example + * + */ + +/**** DHT State Variables ****/ + +#define DHT_STATE_OFF 0 +#define DHT_STATE_INIT 1 +#define DHT_STATE_CHECK_PEERS 2 +#define DHT_STATE_FIND_STUN 3 +#define DHT_STATE_ACTIVE 4 + +/* TIMEOUTS */ +#define DHT_SEARCH_PERIOD 600 /* 10 min */ +#define DHT_CHECK_PERIOD 60 //1800 /* 30 min */ +#define DHT_PUBLISH_PERIOD 1800 /* 30 min */ +#define DHT_NOTIFY_PERIOD 20 //120 /* 2 min - Notify Check period */ +#define DHT_RESTART_PERIOD 300 /* 5 min */ + +#define DHT_DEFAULT_PERIOD 600 /* Default period if no work to do */ +#define DHT_MIN_PERIOD 1 /* to ensure we don't get too many requests */ + +#define DHT_DEFAULT_WAITTIME 1 /* Std sleep break period */ + +/* TTLs for DHTs posts */ +#define DHT_TTL_PUBLISH DHT_PUBLISH_PERIOD +#define DHT_TTL_NOTIFY DHT_NOTIFY_PERIOD + + +void printDhtPeerEntry(dhtPeerEntry *ent, std::ostream &out); + +/* Interface class for DHT data */ + +dhtPeerEntry::dhtPeerEntry() + :state(DHT_PEER_INIT), lastTS(0), + notifyPending(0), notifyTS(0), + type(DHT_ADDR_INVALID) +{ + laddr.sin_addr.s_addr = 0; + laddr.sin_port = 0; + laddr.sin_family = 0; + + raddr.sin_addr.s_addr = 0; + raddr.sin_port = 0; + raddr.sin_family = 0; + + return; +} + +p3DhtMgr::p3DhtMgr(std::string id, pqiConnectCb *cb) + :connCb(cb), mStunRequired(true) +{ + /* setup own entry */ + dhtMtx.lock(); /* LOCK MUTEX */ + + ownEntry.id = id; + ownEntry.state = DHT_PEER_INIT; + ownEntry.type = DHT_ADDR_INVALID; + ownEntry.lastTS = 0; + + ownEntry.notifyPending = 0; + ownEntry.notifyTS = 0; + + ownEntry.hash1 = RsUtil::HashId(id, false); + ownEntry.hash2 = RsUtil::HashId(id, true); + + mDhtModifications = true; + mDhtOn = false; + mDhtState = DHT_STATE_OFF; + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + return; +} + +void p3DhtMgr::setDhtOn(bool on) +{ + dhtMtx.lock(); /* LOCK MUTEX */ + + mDhtModifications = true; + mDhtOn = on; + + dhtMtx.unlock(); /* UNLOCK MUTEX */ +} + +bool p3DhtMgr::getDhtOn() +{ + dhtMtx.lock(); /* LOCK MUTEX */ + + bool on = mDhtOn; + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + return on; +} + +bool p3DhtMgr::getDhtActive() +{ + dhtMtx.lock(); /* LOCK MUTEX */ + + bool act = dhtActive(); + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + return act; +} + +/******************************** PEER MANAGEMENT ********************************** + * + */ + /* set key data */ +bool p3DhtMgr::setExternalInterface( + struct sockaddr_in laddr, + struct sockaddr_in raddr, + uint32_t type) +{ + dhtMtx.lock(); /* LOCK MUTEX */ + + mDhtModifications = true; + ownEntry.laddr = laddr; + ownEntry.raddr = raddr; + ownEntry.type = type; + ownEntry.state = DHT_PEER_ADDR_KNOWN; /* will force republish */ + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::setExternalInterface()"; + std::cerr << " laddr: " << inet_ntoa(ownEntry.laddr.sin_addr); + std::cerr << " lport: " << ntohs(ownEntry.laddr.sin_port); + std::cerr << " raddr: " << inet_ntoa(ownEntry.raddr.sin_addr); + std::cerr << " rport: " << ntohs(ownEntry.raddr.sin_port); + std::cerr << " type: " << ownEntry.type; + std::cerr << " state: " << ownEntry.state; + std::cerr << std::endl; +#endif + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + return true; +} + + + /* add / remove peers */ +bool p3DhtMgr::findPeer(std::string id) +{ + dhtMtx.lock(); /* LOCK MUTEX */ + + mDhtModifications = true; + + std::map::iterator it; + it = peers.find(id); + if (it == peers.end()) + { + /* if they are not in the list -> add */ + dhtPeerEntry ent; + ent.id = id; + ent.state = DHT_PEER_INIT; + ent.type = DHT_ADDR_INVALID; + ent.lastTS = 0; + + ent.notifyPending = 0; + ent.notifyTS = 0; + + /* fill in hashes */ + ent.hash1 = RsUtil::HashId(id, false); + ent.hash2 = RsUtil::HashId(id, true); + + /* other fields don't matter */ + + peers[id] = ent; + } + else + { + /* ignore */ + } + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + return true; +} + +bool p3DhtMgr::dropPeer(std::string id) +{ + dhtMtx.lock(); /* LOCK MUTEX */ + + mDhtModifications = true; + + /* once we are connected ... don't worry about them anymore */ + std::map::iterator it; + it = peers.find(id); + if (it == peers.end()) + { + /* ignore */ + } + else + { + /* remove */ + peers.erase(it); + } + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + return true; +} + + /* post DHT key saying we should connect */ +bool p3DhtMgr::notifyPeer(std::string id) +{ + dhtMtx.lock(); /* LOCK MUTEX */ + + mDhtModifications = true; + + /* once we are connected ... don't worry about them anymore */ + std::map::iterator it; + it = peers.find(id); + bool ret = true; + if (it == peers.end()) + { + /* ignore */ + ret = false; + } + else + { + it->second.notifyPending = RS_CONNECT_ACTIVE; + it->second.notifyTS = time(NULL); + } + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + return ret; +} + + + /* extract current peer status */ +bool p3DhtMgr::getPeerStatus(std::string id, + struct sockaddr_in &laddr, + struct sockaddr_in &raddr, + uint32_t &type, uint32_t &state) +{ + dhtMtx.lock(); /* LOCK MUTEX */ + + std::map::iterator it; + it = peers.find(id); + + bool found = it != peers.end(); + if (found) + { + laddr = it->second.laddr; + raddr = it->second.raddr; + type = it->second.type; + state = it->second.type; + } + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + return found; +} + +/********************************* STUN HANDLING ********************************** + * add / cleanup / stun. + * + */ + + /* stun */ +bool p3DhtMgr::addStun(std::string id) +{ + dhtMtx.lock(); /* LOCK MUTEX */ + + mDhtModifications = true; + + std::list::iterator it; + it = std::find(stunIds.begin(), stunIds.end(), id); + if (it != stunIds.end()) + { + dhtMtx.unlock(); /* UNLOCK MUTEX */ + return false; + } + stunIds.push_back(id); + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + return true; +} + +bool p3DhtMgr::doneStun() +{ + dhtMtx.lock(); /* LOCK MUTEX */ + + mDhtModifications = true; + + /* clear up */ + stunIds.clear(); + + mStunRequired = false; + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + return true; +} + + +void p3DhtMgr::run() +{ + /* + * + */ + + while(1) + { + checkDHTStatus(); + + +#ifdef DHT_DEBUG + status(std::cerr); +#endif + + dhtMtx.lock(); /* LOCK MUTEX */ + + uint32_t dhtState = mDhtState; + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + int period = 60; /* default wait */ + switch(dhtState) + { + case DHT_STATE_INIT: +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::run() state = INIT -> wait" << std::endl; +#endif + period = 10; + break; + case DHT_STATE_CHECK_PEERS: +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::run() state = CHECK_PEERS -> do stuff" << std::endl; +#endif + checkPeerDHTKeys(); + checkStunState(); + period = DHT_MIN_PERIOD; + break; + case DHT_STATE_FIND_STUN: +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::run() state = FIND_STUN -> do stuff" << std::endl; +#endif + doStun(); + checkPeerDHTKeys(); /* keep on going - as we could be in this state for a while */ + checkStunState(); + period = DHT_MIN_PERIOD; + break; + case DHT_STATE_ACTIVE: + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::run() state = ACTIVE -> do stuff" << std::endl; +#endif + period = checkOwnDHTKeys(); +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::run() checkOwnDHTKeys() period: " << period << std::endl; +#endif + int tmpperiod = checkNotifyDHT(); +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::run() checkNotifyDHT() period: " << tmpperiod << std::endl; +#endif + int tmpperiod2 = checkPeerDHTKeys(); +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::run() checkPeerDHTKeys() period: " << tmpperiod2 << std::endl; +#endif + if (tmpperiod < period) + period = tmpperiod; + if (tmpperiod2 < period) + period = tmpperiod2; + } + break; + default: + case DHT_STATE_OFF: +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::run() state = OFF -> wait" << std::endl; +#endif + period = 60; + break; + } + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::run() sleeping for: " << period << std::endl; +#endif + + /* Breakable sleep loop */ + + bool toBreak = false; + int waittime = 1; + int i; + for(i = 0; i < period; i += waittime) + { + if (period-i > DHT_DEFAULT_WAITTIME) + { + waittime = DHT_DEFAULT_WAITTIME; + } + else + { + waittime = period-i; + } + + dhtMtx.lock(); /* LOCK MUTEX */ + + if (mDhtModifications) + { + mDhtModifications = false; + toBreak = true; + } + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + if (toBreak) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::run() breaking sleep" << std::endl; +#endif + + break; /* speed up config modifications */ + } + + + sleep(waittime); + } + } +} + + +int p3DhtMgr::checkOwnDHTKeys() +{ + int repubPeriod = 10000; + time_t now = time(NULL); + + /* in order of importance: + * (1) Check for Own Key publish. + * (2) Check for notification requests + * (3) Check for Peers + */ + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkOwnDHTKeys()" << std::endl; +#endif + + dhtMtx.lock(); /* LOCK MUTEX */ + + dhtPeerEntry peer = ownEntry; + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + /* publish ourselves if necessary */ + if (peer.state >= DHT_PEER_ADDR_KNOWN) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkOwnDHTKeys() OWN ADDR KNOWN" << std::endl; +#endif + if ((peer.state < DHT_PEER_PUBLISHED) || + (now - peer.lastTS > DHT_PUBLISH_PERIOD)) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkOwnDHTKeys() OWN ADDR REPUB" << std::endl; +#endif + /* publish own key */ + if (dhtPublish(peer.hash1, peer.laddr, peer.raddr, peer.type, "")) + { + dhtMtx.lock(); /* LOCK MUTEX */ + + ownEntry.lastTS = now; + ownEntry.state = DHT_PEER_PUBLISHED; + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + } + + /* restart immediately */ + repubPeriod = DHT_MIN_PERIOD; + return repubPeriod; + } + else + { + if (now - peer.lastTS < DHT_PUBLISH_PERIOD) + { + repubPeriod = DHT_PUBLISH_PERIOD - + (now - peer.lastTS); + } + else + { + repubPeriod = 10; + } +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkOwnDHTKeys() repub in: "; + std::cerr << repubPeriod << std::endl; +#endif + } + + + /* check for connect requests */ + if ((peer.state == DHT_PEER_PUBLISHED) && + (now - peer.notifyTS >= DHT_NOTIFY_PERIOD)) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkOwnDHTKeys() check for Notify (rep=0)"; + std::cerr << std::endl; +#endif + if (dhtSearch(peer.hash1, DHT_MODE_NOTIFY)) + { + dhtMtx.lock(); /* LOCK MUTEX */ + + ownEntry.notifyTS = now; + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + } + + /* restart immediately */ + repubPeriod = DHT_MIN_PERIOD; + return repubPeriod; + } + else + { + repubPeriod = DHT_NOTIFY_PERIOD - + (now - peer.notifyTS); +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkOwnDHTKeys() check Notify in: "; + std::cerr << repubPeriod << std::endl; +#endif + } + + } + else + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkOwnDHTKeys() PEER ADDR UNKNOWN" << std::endl; +#endif + repubPeriod = 10; + } + return repubPeriod; +} + + +int p3DhtMgr::checkPeerDHTKeys() +{ + /* now loop through the peers */ + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkPeerDHTKeys()" << std::endl; +#endif + + dhtMtx.lock(); /* LOCK MUTEX */ + + /* iterate through and find min time and suitable candidate */ + std::map::iterator it,pit; + time_t now = time(NULL); + uint32_t period = 0; + uint32_t repeatPeriod = 6000; + + pit = peers.end(); + time_t pTS = now; + + for(it = peers.begin(); it != peers.end(); it++) + { + time_t delta = now - it->second.lastTS; + if (it->second.state < DHT_PEER_FOUND) + { + period = DHT_SEARCH_PERIOD; + } + else /* (it->second.state == DHT_PEER_FOUND) */ + { + period = DHT_CHECK_PERIOD; + } +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkPeerDHTKeys() Peer: " << it->second.id; + std::cerr << " Period: " << period; + std::cerr << " Delta: " << delta; + std::cerr << std::endl; +#endif + + + if ((unsigned) delta >= period) + { + if (it->second.lastTS < pTS) + { + pit = it; + pTS = it->second.lastTS; + } + repeatPeriod = DHT_MIN_PERIOD; + } + else if (period - delta < repeatPeriod) + { + repeatPeriod = period - delta; + } + } + + /* now have - peer to handle, and period to next call */ + + if (pit == peers.end()) + { + dhtMtx.unlock(); /* UNLOCK MUTEX */ + return repeatPeriod; + } + + /* update timestamp */ + pit->second.lastTS = now; + if (pit->second.state == DHT_PEER_INIT) + { + pit->second.state = DHT_PEER_SEARCH; + } + + dhtPeerEntry peer = (pit->second); + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + /* now search for the peer */ + dhtSearch(peer.hash1, DHT_MODE_SEARCH); + + /* results come through callback */ + return repeatPeriod; +} + + +int p3DhtMgr::checkNotifyDHT() +{ +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkNotifyDHT()" << std::endl; +#endif + /* now loop through the peers */ + + dhtMtx.lock(); /* LOCK MUTEX */ + + /* iterate through and find min time and suitable candidate */ + std::map::iterator it; + time_t now = time(NULL); + int repeatPeriod = DHT_DEFAULT_PERIOD; + + /* find the first with a notify flag */ + for(it = peers.begin(); it != peers.end(); it++) + { + if ((it->second.state == DHT_PEER_FOUND) && + (it->second.notifyPending == RS_CONNECT_ACTIVE)) + { + break; + } + } + /* now have - peer to handle */ + if (it == peers.end()) + { + dhtMtx.unlock(); /* UNLOCK MUTEX */ + return repeatPeriod; + } + + /* update timestamp */ + it->second.notifyTS = now; + it->second.notifyPending = 0; + + dhtPeerEntry peer = (it->second); + dhtPeerEntry own = ownEntry; + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + /* publish notification (publish Our Id) + * We publish the connection attempt on peers hash, + * using our alternative hash.. + * */ + + if (dhtNotify(peer.hash1, own.hash2, "")) + { + /* feedback to say we started it! */ + connCb->peerConnectRequest(peer.id, RS_CONNECT_ACTIVE); + } + + + repeatPeriod = DHT_MIN_PERIOD; + return repeatPeriod; +} + + + +int p3DhtMgr::doStun() +{ +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::doStun()" << std::endl; +#endif + if (stunIds.size() < 1) + return 0; + + /* pop the front one */ + std::string activeStunId = stunIds.front(); + + stunIds.pop_front(); + /* Don't recycle -> otherwise can end in an infinite (pointless) loop! */ + //stunIds.push_back(activeStunId); + + /* look it up! */ + dhtSearch(activeStunId, DHT_MODE_SEARCH); + + return 1; +} + + + +int p3DhtMgr::checkStunState() +{ +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkStunState()" << std::endl; +#endif + dhtMtx.lock(); /* LOCK MUTEX */ + + /* now loop through the peers */ + if (!mStunRequired) + { + mDhtState = DHT_STATE_ACTIVE; + } + + if (mDhtState == DHT_STATE_CHECK_PEERS) + { + /* check that they have all be searched for */ + std::map::iterator it; + for(it = peers.begin(); it != peers.end(); it++) + { + if (it->second.state == DHT_PEER_INIT) + { + break; + } + } + + if (it == peers.end()) + { + /* we've checked all peers */ + mDhtState = DHT_STATE_FIND_STUN; + } + } + else if (mDhtState == DHT_STATE_FIND_STUN) + { + /* if we run out of stun peers -> just go to active */ + if (stunIds.size() < 1) + { + std::cerr << "WARNING: out of Stun Peers - without getting id" << std::endl; + mDhtState = DHT_STATE_ACTIVE; + } + } + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + return 1; +} + +void p3DhtMgr::checkDHTStatus() +{ + dhtMtx.lock(); /* LOCK MUTEX */ + + bool isActive = (mDhtState != DHT_STATE_OFF); + + bool toShutdown = false; + bool toStartup = false; + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkDhtStatus() mDhtState: " << mDhtState << std::endl; + std::cerr << "p3DhtMgr::checkDhtStatus() mDhtOn : " << mDhtOn << std::endl; +#endif + + if ((isActive) && (!mDhtOn)) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkDhtStatus() Active & !mDhtOn -> toShutdown" << std::endl; +#endif + toShutdown = true; + } + + if ((!isActive) && (mDhtOn)) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkDhtStatus() !Active & mDhtOn -> toStartup" << std::endl; +#endif + toStartup = true; + } + + /* restart if it has shutdown */ + if (isActive && mDhtOn) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkDhtStatus() Active & mDhtOn" << std::endl; +#endif + if (dhtActive()) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkDhtStatus() dhtActive() = true" << std::endl; +#endif + if (mDhtState == DHT_STATE_INIT) + { + mDhtState = DHT_STATE_CHECK_PEERS; +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkDhtStatus() Switching to CHECK PEERS" << std::endl; +#endif + } + } + else + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkDhtStatus() dhtActive() = false" << std::endl; +#endif + if (mDhtActiveTS - time(NULL) > DHT_RESTART_PERIOD) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkDhtStatus() restart Period..." << std::endl; +#endif + toShutdown = true; + toStartup = true; + } + } + } + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + if (toShutdown) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkDhtStatus() toShutdown = true -> shutdown()" << std::endl; +#endif + if (shutdown()) + { + clearDhtData(); + + dhtMtx.lock(); /* LOCK MUTEX */ + + mDhtState = DHT_STATE_OFF; +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkDhtStatus() mDhtState -> OFF" << std::endl; +#endif + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + } + } + + if (toStartup) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkDhtStatus() toStartup = true -> init()" << std::endl; +#endif + if (init()) + { + + dhtMtx.lock(); /* LOCK MUTEX */ + + mDhtState = DHT_STATE_INIT; + mDhtActiveTS = time(NULL); + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkDhtStatus() mDhtState -> INIT" << std::endl; +#endif + + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + } + } +} + +void p3DhtMgr::clearDhtData() +{ + std::cerr << "p3DhtMgr::clearDhtData() DUMMY FN" << std::endl; +} + + +/****************************** REAL DHT INTERFACE ********************************* + * publish/search/result. + * + * dummy implementation for testing. + */ + +int p3DhtMgr::status(std::ostream &out) +{ + dhtMtx.lock(); /* LOCK MUTEX */ + + out << "p3DhtMgr::status() ************************************" << std::endl; + out << "mDhtState: " << mDhtState << std::endl; + out << "mDhtOn : " << mDhtOn << std::endl; + out << "dhtActive: " << dhtActive() << std::endl; + + /* now own state */ + out << "OWN DETAILS -------------------------------------------" << std::endl; + printDhtPeerEntry(&ownEntry, out); + out << "OWN DETAILS END----------------------------------------" << std::endl; + + /* now peers states */ + std::map::iterator it; + out << "PEER DETAILS ------------------------------------------" << std::endl; + for(it = peers.begin(); it != peers.end(); it++) + { + printDhtPeerEntry(&(it->second), out); + } + out << "PEER DETAILS END---------------------------------------" << std::endl; + + /* now stun states */ + out << "STUN DETAILS ------------------------------------------" << std::endl; + out << "Available Stun Ids: " << stunIds.size() << std::endl; + out << "STUN DETAILS END---------------------------------------" << std::endl; + + + out << "p3DhtMgr::status() END ********************************" << std::endl; + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + return 0; +} + + + + + +bool p3DhtMgr::init() +{ + std::cerr << "p3DhtMgr::init() DUMMY FN" << std::endl; + return true; +} + +bool p3DhtMgr::shutdown() +{ + std::cerr << "p3DhtMgr::shutdown() DUMMY FN" << std::endl; + return true; +} + +bool p3DhtMgr::dhtActive() +{ + std::cerr << "p3DhtMgr::dhtActive() DUMMY FN" << std::endl; + return true; +} + +bool p3DhtMgr::publishDHT(std::string key, std::string value, uint32_t ttl) +{ + std::cerr << "p3DhtMgr::publishDHT() DUMMY FN" << std::endl; + return false; +} + +bool p3DhtMgr::searchDHT(std::string idhash) +{ + std::cerr << "p3DhtMgr::searchDHT() DUMMY FN" << std::endl; + return false; +} + + + + +/****************************** INTERMEDIATE DHT INTERFACE ********************************* + * publish/search/result. + * + * Take the 'real' parameters and create the key/value parameters for the real dht. + */ + + +bool p3DhtMgr::dhtPublish(std::string idhash, + struct sockaddr_in &laddr, struct sockaddr_in &raddr, + uint32_t type, std::string sign) +{ + /* ... goes and searches */ + std::cerr << "p3DhtMgr::dhtPublish()" << std::endl; + + /* Create a Value from addresses and type */ + + /* to store the ip address and flags */ + char valuearray[1024]; + snprintf(valuearray, 1024, "RSDHT:%02d: IPL=%s:%d, IPE=%s:%d, type=%04X,", + DHT_MODE_SEARCH, + inet_ntoa(laddr.sin_addr), + ntohs(laddr.sin_port), + inet_ntoa(raddr.sin_addr), + ntohs(raddr.sin_port), + type); + + std::string value = valuearray; + + /* call to the real DHT */ + return publishDHT(idhash, value, DHT_TTL_PUBLISH); +} + +bool p3DhtMgr::dhtNotify(std::string idhash, std::string ownIdHash, std::string sign) +{ + std::cerr << "p3DhtMgr::dhtNotify()" << std::endl; + + std::ostringstream value; + value << "RSDHT:" << std::setw(2) << std::setfill('0') << DHT_MODE_NOTIFY << ":"; + value << ownIdHash; + + /* call to the real DHT */ + return publishDHT(idhash, value.str(), DHT_TTL_NOTIFY); +} + +bool p3DhtMgr::dhtSearch(std::string idhash, uint32_t mode) +{ + std::cerr << "p3DhtMgr::dhtSearch()" << std::endl; + + /* call to the real DHT */ + return searchDHT(idhash); +} + + + + + +/****************************** DHT FEEDBACK INTERFACE ********************************* + * Two functions... + * (1) The interpretation function. + * (2) callback handling. + * + */ + +bool p3DhtMgr::resultDHT(std::string key, std::string value) +{ + /* so .... two possibilities. + * + * RSDHT:01: IPL ... IPE ... TYPE ... (advertising) + * RSDHT:02: HASH (connect request) + * + */ + + /* variables for dhtResult() call */ + struct sockaddr_in laddr; + struct sockaddr_in raddr; + std::string sign; + + + int32_t reqType; + uint32_t loc; + if (1 > sscanf(value.c_str(), "RSDHT:%d: %n", &reqType, &loc)) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::resultDHT() Not RSDHT msg -> discarding" << std::endl; +#endif + /* failed */ + return false; + } + + + dhtMtx.lock(); /* LOCK MUTEX */ + std::string ownhash = ownEntry.hash1; + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + switch(reqType) + { + case DHT_MODE_NOTIFY: + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::resultDHT() NOTIFY msg" << std::endl; +#endif + + if (ownhash != key) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::resultDHT() NOTIFY msg not for us -> discarding" << std::endl; +#endif + return false; + } + + /* get the hash */ + std::string notifyHash = value.substr(loc); +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::resultDHT() NOTIFY msg HASH:->" << notifyHash << "<-" << std::endl; +#endif + /* call out */ + dhtResultNotify(notifyHash); + + break; + } + + case DHT_MODE_SEARCH: + { + + if (ownhash == key) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::resultDHT() SEARCH msg is OWN PUBLISH -> discarding" << std::endl; +#endif + return false; + } + + uint32_t a1,b1,c1,d1,e1; + uint32_t a2,b2,c2,d2,e2; + uint32_t flags; + + if (sscanf(&((value.c_str())[loc]), " IPL=%d.%d.%d.%d:%d, IPE=%d.%d.%d.%d:%d, type=%x", + &a1, &b1, &c1, &d1, &e1, &a2, &b2, &c2, &d2, &e2, &flags) != 11) + { + /* failed to scan */ +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::resultDHT() SEARCH parse failed of:" << (&((value.c_str())[loc])); + std::cerr << std::endl; +#endif + return false; + } + + std::ostringstream out1; + out1 << a1 << "." << b1 << "." << c1 << "." << d1; + inet_aton(out1.str().c_str(), &(laddr.sin_addr)); + laddr.sin_port = htons(e1); + laddr.sin_family = AF_INET; + + std::ostringstream out2; + out2 << a2 << "." << b2 << "." << c2 << "." << d2; + inet_aton(out2.str().c_str(), &(raddr.sin_addr)); + raddr.sin_port = htons(e2); + raddr.sin_family = AF_INET; + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::resultDHT() SEARCH laddr: " << out1.str() << ":" << e1; + std::cerr << " raddr: " << out2.str() << ":" << e2; + std::cerr << " flags: " << flags; + std::cerr << std::endl; +#endif + + return dhtResultSearch(key, laddr, raddr, flags, sign); + + break; + } + + default: + + return false; + break; + } + + return false; +} + + + + + + +bool p3DhtMgr::dhtResultNotify(std::string idhash) +{ + dhtMtx.lock(); /* LOCK MUTEX */ + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::dhtResultNotify() from idhash: "; + std::cerr << RsUtil::BinToHex(idhash) << std::endl; +#endif + std::map::iterator it; + bool doNotify = false; + time_t now = time(NULL); + + /* if notify - we must match on the second hash */ + for(it = peers.begin(); (it != peers.end()) && ((it->second).hash2 != idhash); it++); + + /* update data */ + std::string peerid; + if (it != peers.end()) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::dhtResult() NOTIFY for id: " << it->first << std::endl; +#endif + /* delay callback -> if they are not found */ + it->second.notifyTS = now; + if (it->second.state != DHT_PEER_FOUND) + { + doNotify = false; + it->second.notifyPending = RS_CONNECT_PASSIVE; + /* flag for immediate search */ + mDhtModifications = true; /* no wait! */ + it->second.lastTS = 0; + } + else + { + doNotify = true; + it->second.notifyPending = 0; + peerid = (it->second).id; + } + } + else + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::dhtResult() unknown NOTIFY "; + std::cerr << RsUtil::BinToHex(idhash) << std::endl; +#endif + } + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + /* do callback */ + if (doNotify) + connCb->peerConnectRequest(peerid, RS_CONNECT_PASSIVE); + + return true; +} + + +bool p3DhtMgr::dhtResultSearch(std::string idhash, + struct sockaddr_in &laddr, struct sockaddr_in &raddr, + uint32_t type, std::string sign) +{ + dhtMtx.lock(); /* LOCK MUTEX */ + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::dhtResultSearch() for idhash: "; + std::cerr << RsUtil::BinToHex(idhash) << std::endl; +#endif + std::map::iterator it; + bool doCb = false; + bool doNotify = false; + bool doStun = false; + uint32_t stunFlags = 0; + time_t now = time(NULL); + + dhtPeerEntry ent; + + /* if search - we must match on the second hash */ + for(it = peers.begin(); (it != peers.end()) && ((it->second).hash1 != idhash); it++); + + /* update data */ + if (it != peers.end()) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::dhtResult() SEARCH for id: " << it->first << std::endl; +#endif + it->second.lastTS = now; + + /* has it changed??? */ + if ((it->second.state != DHT_PEER_FOUND) || + (0 != sockaddr_cmp(it->second.laddr,laddr)) || + (0 != sockaddr_cmp(it->second.raddr,raddr)) || + (it->second.type != type)) + { + it->second.state = DHT_PEER_FOUND; + it->second.laddr = laddr; + it->second.raddr = raddr; + it->second.type = type; + ent = it->second; + doCb = true; + } + + /* do we have a pending notify */ + if ((it->second.state == DHT_PEER_FOUND) && + (it->second.notifyPending == RS_CONNECT_PASSIVE)) + { + it->second.notifyPending = 0; + doNotify = true; + } + + /* if stun not happy yet - doStun aswell */ + if ((mDhtState != DHT_STATE_OFF) && + (mDhtState != DHT_STATE_ACTIVE)) + { + doStun = true; + stunFlags = RS_STUN_FRIEND | RS_STUN_ONLINE; + } + } + else + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::dhtResult() SEARCH(stun) for idhash: "; + std::cerr << RsUtil::BinToHex(idhash) << std::endl; +#endif + /* stun result? */ + doStun = true; + stunFlags = RS_STUN_ONLINE; + } + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + /* if changed - do callback */ + if (doCb) + { + connCb->peerStatus(ent.id, + ent.laddr, ent.raddr, + ent.type, 0, RS_CB_DHT); + //ent.type, RS_CB_LOCAL_ADDR | RS_CB_REMOTE_ADDR, RS_CB_DHT); + if (doNotify) + { + connCb->peerConnectRequest(ent.id, RS_CONNECT_PASSIVE); + } + } + + if (doStun) + { + connCb->stunStatus(idhash, raddr, stunFlags); + } + + return true; +} + + + +/******************************** AUX FUNCTIONS ********************************** + * + */ + +void printDhtPeerEntry(dhtPeerEntry *ent, std::ostream &out) +{ + + out << "DhtEntry: ID: " << ent->id; + out << " State: " << ent->state; + out << " lastTS: " << ent->lastTS; + out << " notifyPending: " << ent->notifyPending; + out << " notifyTS: " << ent->notifyTS; + out << std::endl; + out << " laddr: " << inet_ntoa(ent->laddr.sin_addr) << ":" << ntohs(ent->laddr.sin_port); + out << " raddr: " << inet_ntoa(ent->raddr.sin_addr) << ":" << ntohs(ent->raddr.sin_port); + out << " type: " << ent->type; + out << std::endl; + out << " hash1: " << RsUtil::BinToHex(ent->hash1); + out << std::endl; + out << " hash2: " << RsUtil::BinToHex(ent->hash2); + out << std::endl; + return; +} + + diff --git a/libretroshare/src/pqi/p3dhtmgr.h b/libretroshare/src/pqi/p3dhtmgr.h new file mode 100644 index 000000000..7c95bd958 --- /dev/null +++ b/libretroshare/src/pqi/p3dhtmgr.h @@ -0,0 +1,211 @@ +/* + * libretroshare/src/pqi: p3dhtmgr.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-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 MRK_P3_DHT_MANAGER_HEADER +#define MRK_P3_DHT_MANAGER_HEADER + +/* Interface class for DHT data */ + +#include +#include +#include "pqi/pqinetwork.h" + +#include "util/rsthreads.h" +#include "pqi/pqimonitor.h" + +/* All other #defs are in .cc */ +#define DHT_ADDR_INVALID 0xff +#define DHT_ADDR_TCP 0x01 +#define DHT_ADDR_UDP 0x02 + + +/* for DHT peer STATE */ +#define DHT_PEER_INIT 0 +#define DHT_PEER_SEARCH 1 +#define DHT_PEER_FOUND 2 + +/* for DHT peer STATE (ownEntry) */ +#define DHT_PEER_ADDR_KNOWN 3 +#define DHT_PEER_PUBLISHED 4 + +/* Interface with Real DHT Implementation */ +#define DHT_MODE_SEARCH 1 +#define DHT_MODE_PUBLISH 1 +#define DHT_MODE_NOTIFY 2 + + +class dhtPeerEntry +{ + public: + dhtPeerEntry(); + + std::string id; + uint32_t state; + time_t lastTS; + + uint32_t notifyPending; + time_t notifyTS; + + struct sockaddr_in laddr, raddr; + uint32_t type; /* ADDR_TYPE as defined above */ + + std::string hash1; /* SHA1 Hash of id */ + std::string hash2; /* SHA1 Hash of reverse Id */ +}; + +class p3DhtMgr: public RsThread +{ + /* + */ + public: + p3DhtMgr(std::string id, pqiConnectCb *cb); + + /********** External DHT Interface ************************ + * These Functions are the external interface + * for the DHT, and must be non-blocking and return quickly + */ + +void setDhtOn(bool on); +bool getDhtOn(); +bool getDhtActive(); + + /* set key data */ +bool setExternalInterface(struct sockaddr_in laddr, + struct sockaddr_in raddr, uint32_t type); + + /* add / remove peers */ +bool findPeer(std::string id); +bool dropPeer(std::string id); + + /* post DHT key saying we should connect (callback when done) */ +bool notifyPeer(std::string id); + + /* extract current peer status */ +bool getPeerStatus(std::string id, + struct sockaddr_in &laddr, struct sockaddr_in &raddr, + uint32_t &type, uint32_t &mode); + + /* stun */ +bool addStun(std::string id); +bool doneStun(); + + /********** Higher Level DHT Work Functions ************************ + * These functions translate from the strings/addresss to + * key/value pairs. + */ + public: + + /* results from DHT proper */ +virtual bool dhtResultNotify(std::string id); +virtual bool dhtResultSearch(std::string id, + struct sockaddr_in &laddr, struct sockaddr_in &raddr, + uint32_t type, std::string sign); + + protected: + + /* can block briefly (called only from thread) */ +virtual bool dhtPublish(std::string id, + struct sockaddr_in &laddr, + struct sockaddr_in &raddr, + uint32_t type, std::string sign); + +virtual bool dhtNotify(std::string peerid, std::string ownId, + std::string sign); +virtual bool dhtSearch(std::string id, uint32_t mode); + + + /********** Actual DHT Work Functions ************************ + * These involve a very simple LOW-LEVEL interface ... + * + * publish + * search + * result + * + */ + + public: + + /* Feedback callback (handled here) */ +virtual bool resultDHT(std::string key, std::string value); + + protected: + +virtual bool init(); +virtual bool shutdown(); +virtual bool dhtActive(); +virtual int status(std::ostream &out); + +virtual bool publishDHT(std::string key, std::string value, uint32_t ttl); +virtual bool searchDHT(std::string key); + + + + /********** Internal DHT Threading ************************ + * + */ + + public: + +virtual void run(); + + private: + + /* search scheduling */ +void checkDHTStatus(); +int checkStunState(); +int doStun(); +int checkPeerDHTKeys(); +int checkOwnDHTKeys(); +int checkNotifyDHT(); + +void clearDhtData(); + + + /* other feedback through callback */ + pqiConnectCb *connCb; + + /* protected by Mutex */ + RsMutex dhtMtx; + + bool mDhtOn; /* User desired state */ + bool mDhtModifications; /* any user requests? */ + + dhtPeerEntry ownEntry; + time_t ownNotifyTS; + std::map peers; + + std::list stunIds; + bool mStunRequired; + + uint32_t mDhtState; + time_t mDhtActiveTS; + +}; + + +#endif // MRK_P3_DHT_MANAGER_HEADER + + diff --git a/libretroshare/src/pqi/pqistunner.h b/libretroshare/src/pqi/p3upnpmgr.h similarity index 51% rename from libretroshare/src/pqi/pqistunner.h rename to libretroshare/src/pqi/p3upnpmgr.h index f96a7cce8..05a98cda7 100644 --- a/libretroshare/src/pqi/pqistunner.h +++ b/libretroshare/src/pqi/p3upnpmgr.h @@ -1,9 +1,9 @@ /* - * "$Id: pqistunner.h,v 1.2 2007-02-18 21:46:50 rmf24 Exp $" + * libretroshare/src/pqi: p3upnpmgr.h * * 3P/PQI network interface for RetroShare. * - * Copyright 2004-2006 by Robert Fernie. + * Copyright 2004-2007 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 @@ -24,45 +24,35 @@ */ +#ifndef MRK_P3_UPNP_MANAGER_H +#define MRK_P3_UPNP_MANAGER_H - - +/* platform independent networking... */ +#include "util/rsthreads.h" #include "pqi/pqinetwork.h" - -class pqistunner +class p3UpnpMgr: public RsThread { public: - pqistunner(struct sockaddr_in addr); +virtual ~p3UpnpMgr() { return; } -int setListenAddr(struct sockaddr_in addr); -int setuplisten(); + /* External Interface */ +virtual void enableUPnP(bool on) = 0; +virtual void shutdownUPnP() = 0; -int resetlisten(); +virtual bool getUPnPEnabled() = 0; +virtual bool getUPnPActive() = 0; -int stun(struct sockaddr_in stun_addr); - -bool response(void *stun_pkt, int size, struct sockaddr_in &addr); -int recvfrom(void *data, int *size, struct sockaddr_in &addr); -int reply(void *data, int size, struct sockaddr_in &addr); - - private: - -/************************** Basic Functionality ******************/ - -bool generate_stun_pkt(void *stun_pkt, int *len); -void * generate_stun_reply(struct sockaddr_in *stun_addr, int *len); - - - int sockfd; - bool active; - void *stunpkt; - unsigned int stunpktlen; - - struct sockaddr_in laddr, stun_addr; + /* the address that the listening port is on */ +virtual void setInternalPort(unsigned short iport_in) = 0; +virtual void setExternalPort(unsigned short eport_in) = 0; + + /* as determined by uPnP */ +virtual bool getInternalAddress(struct sockaddr_in &addr) = 0; +virtual bool getExternalAddress(struct sockaddr_in &addr) = 0; }; - +#endif /* MRK_P3_UPNP_MANAGER_H */ diff --git a/libretroshare/src/pqi/pqi_base.h b/libretroshare/src/pqi/pqi_base.h index fad229360..2835c82fd 100644 --- a/libretroshare/src/pqi/pqi_base.h +++ b/libretroshare/src/pqi/pqi_base.h @@ -279,18 +279,24 @@ virtual int notifyEvent(NetInterface *ni, int event) { return 0; } std::string peerId; }; + + +/**** Consts for pqiperson -> placed here for NetBinDummy usage() */ + +const uint32_t PQI_CONNECT_TCP = 0x0001; +const uint32_t PQI_CONNECT_UDP = 0x0002; + + /********************** Binary INTERFACE **************************** * This defines the binary interface used by Network/loopback/file * interfaces - * - * Flags are passed to BinInterfaces, and serialisers */ #define BIN_FLAGS_NO_CLOSE 0x0001 #define BIN_FLAGS_READABLE 0x0002 #define BIN_FLAGS_WRITEABLE 0x0004 #define BIN_FLAGS_NO_DELETE 0x0008 -#define BIN_FLAGS_HASHDATA 0x0010 +#define BIN_FLAGS_HASH_DATA 0x0010 class BinInterface { @@ -306,6 +312,8 @@ virtual int netstatus() = 0; virtual int isactive() = 0; virtual bool moretoread() = 0; virtual bool cansend() = 0; +virtual std::string gethash() = 0; + /* used by pqistreamer to limit transfers */ virtual bool bandwidthLimited() { return true; } }; @@ -340,7 +348,7 @@ virtual ~NetInterface() // virtual int tick() = 0; // Already defined for BinInterface. -virtual int connectattempt() = 0; +virtual int connect(struct sockaddr_in raddr) = 0; virtual int listen() = 0; virtual int stoplistening() = 0; virtual int disconnect() = 0; diff --git a/libretroshare/src/pqi/pqiaddrstore.h b/libretroshare/src/pqi/pqiaddrstore.h deleted file mode 100644 index f0dbe5039..000000000 --- a/libretroshare/src/pqi/pqiaddrstore.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef PQI_ADDR_STORE_H -#define PQI_ADDR_STORE_H - -#include "pqi/pqinetwork.h" - -#include - -class pqiAddrStore -{ - public: - virtual ~pqiAddrStore() { return; } - /* pqiAddrStore ... called prior to connect */ - virtual bool addrFriend(std::string id, struct sockaddr_in &addr, unsigned int &flags) = 0; -}; - - -/* implemented elsewhere, to provide pqi with AddrStore */ - -extern pqiAddrStore *getAddrStore(); - - -#endif /* PQI_ADDR_STORE_H */ diff --git a/libretroshare/src/pqi/pqiarchive.cc b/libretroshare/src/pqi/pqiarchive.cc index bc64f3af3..9c75c19bf 100644 --- a/libretroshare/src/pqi/pqiarchive.cc +++ b/libretroshare/src/pqi/pqiarchive.cc @@ -469,5 +469,11 @@ int pqiarchive::readPkt(RsItem **item_out, long *ts_out) return 1; } +/**** Hashing Functions ****/ +std::string pqiarchive::gethash() +{ + return bio->gethash(); +} + diff --git a/libretroshare/src/pqi/pqiarchive.h b/libretroshare/src/pqi/pqiarchive.h index 1ba6cdcb1..830bf3449 100644 --- a/libretroshare/src/pqi/pqiarchive.h +++ b/libretroshare/src/pqi/pqiarchive.h @@ -55,6 +55,9 @@ virtual int tick(); virtual int status(); virtual void setRealTime(bool r) { realTime = r; } + +std::string gethash(); + private: int writePkt(RsItem *item); int readPkt(RsItem **item_out, long *ts); diff --git a/libretroshare/src/pqi/pqibin.cc b/libretroshare/src/pqi/pqibin.cc index dd9e7ce60..6d45e8234 100644 --- a/libretroshare/src/pqi/pqibin.cc +++ b/libretroshare/src/pqi/pqibin.cc @@ -28,8 +28,8 @@ #include "pqi/pqibin.h" -BinFileInterface::BinFileInterface(char *fname, int flags) - :bin_flags(flags), buf(NULL) +BinFileInterface::BinFileInterface(const char *fname, int flags) + :bin_flags(flags), buf(NULL), hash(NULL) { /* if read + write - open r+ */ if ((bin_flags & BIN_FLAGS_READABLE) && @@ -75,6 +75,10 @@ BinFileInterface::BinFileInterface(char *fname, int flags) size = 0; } + if (bin_flags & BIN_FLAGS_HASH_DATA) + { + hash = new pqihash(); + } } @@ -95,6 +99,10 @@ int BinFileInterface::senddata(void *data, int len) { return -1; } + if (bin_flags & BIN_FLAGS_HASH_DATA) + { + hash->addData(data, len); + } return len; } @@ -107,15 +115,33 @@ int BinFileInterface::readdata(void *data, int len) { return -1; } + if (bin_flags & BIN_FLAGS_HASH_DATA) + { + hash->addData(data, len); + } return len; } +std::string BinFileInterface::gethash() +{ + std::string hashstr; + if (bin_flags & BIN_FLAGS_HASH_DATA) + { + hash->Complete(hashstr); + } + return hashstr; +} + BinMemInterface::BinMemInterface(int defsize, int flags) :bin_flags(flags), buf(NULL), size(defsize), - recvsize(0), readloc(0) + recvsize(0), readloc(0), hash(NULL) { buf = malloc(defsize); + if (bin_flags & BIN_FLAGS_HASH_DATA) + { + hash = new pqihash(); + } } BinMemInterface::~BinMemInterface() @@ -145,6 +171,10 @@ int BinMemInterface::senddata(void *data, int len) return -1; } memcpy((char *) buf + recvsize, data, len); + if (bin_flags & BIN_FLAGS_HASH_DATA) + { + hash->addData(data, len); + } recvsize += len; return len; } @@ -158,8 +188,243 @@ int BinMemInterface::readdata(void *data, int len) return -1; } memcpy(data, (char *) buf + readloc, len); + if (bin_flags & BIN_FLAGS_HASH_DATA) + { + hash->addData(data, len); + } readloc += len; return len; } + +std::string BinMemInterface::gethash() + { + std::string hashstr; + if (bin_flags & BIN_FLAGS_HASH_DATA) + { + hash->Complete(hashstr); + } + return hashstr; + } + + + +/**************************************************************************/ + + +void printNetBinID(std::ostream &out, std::string id, uint32_t t) +{ + out << "NetBinId(" << id << ","; + if (t == PQI_CONNECT_TCP) + { + out << "TCP)"; + } + else + { + out << "UDP)"; + } +} + + +/************************** NetBinDummy ****************************** + * A test framework, + * + */ + +#include "pqi/pqiperson.h" + +const uint32_t DEFAULT_DUMMY_DELTA = 5; + +NetBinDummy::NetBinDummy(PQInterface *parent, std::string id, uint32_t t) + :NetBinInterface(parent, id), type(t), dummyConnected(false), + toConnect(false), connectDelta(DEFAULT_DUMMY_DELTA) +{ + return; +} + + // Net Interface +int NetBinDummy::connect(struct sockaddr_in raddr) +{ + std::cerr << "NetBinDummy::connect("; + std::cerr << inet_ntoa(raddr.sin_addr) << ":"; + std::cerr << htons(raddr.sin_port); + std::cerr << ") "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + + std::cerr << "NetBinDummy::dummyConnect = true!"; + std::cerr << std::endl; + + if (type == PQI_CONNECT_TCP) + { + std::cerr << "NetBinDummy:: Not connecting TCP"; + std::cerr << std::endl; + if (parent()) + { + parent()->notifyEvent(this, CONNECT_FAILED); + } + } + else if (!dummyConnected) + { + toConnect = true; + connectTS = time(NULL) + connectDelta; + std::cerr << "NetBinDummy::toConnect = true, connect in: "; + std::cerr << connectDelta << " secs"; + std::cerr << std::endl; + } + else + { + std::cerr << "NetBinDummy:: Already Connected!"; + std::cerr << std::endl; + } + + return 1; +} + +int NetBinDummy::listen() +{ + std::cerr << "NetBinDummy::connect() "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + + return 1; +} + +int NetBinDummy::stoplistening() +{ + std::cerr << "NetBinDummy::stoplistening() "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + + return 1; +} + +int NetBinDummy::disconnect() +{ + std::cerr << "NetBinDummy::disconnect() "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + + std::cerr << "NetBinDummy::dummyConnect = false!"; + std::cerr << std::endl; + dummyConnected = false; + + if (parent()) + { + parent()->notifyEvent(this, CONNECT_FAILED); + } + + return 1; +} + +int NetBinDummy::reset() +{ + std::cerr << "NetBinDummy::reset() "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + + disconnect(); + + return 1; +} + + + // Bin Interface. +int NetBinDummy::tick() +{ + + if (toConnect) + { + if (connectTS < time(NULL)) + { + std::cerr << "NetBinDummy::tick() dummyConnected = true "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + dummyConnected = true; + toConnect = false; + if (parent()) + parent()->notifyEvent(this, CONNECT_SUCCESS); + } + else + { + std::cerr << "NetBinDummy::tick() toConnect "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + } + } + return 0; +} + +int NetBinDummy::senddata(void *data, int len) +{ + std::cerr << "NetBinDummy::senddata() "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + + if (dummyConnected) + return len; + return 0; +} + +int NetBinDummy::readdata(void *data, int len) +{ + std::cerr << "NetBinDummy::readdata() "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + + return 0; +} + +int NetBinDummy::netstatus() +{ + std::cerr << "NetBinDummy::netstatus() "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + + return 1; +} + +int NetBinDummy::isactive() +{ + std::cerr << "NetBinDummy::isactive() "; + printNetBinID(std::cerr, PeerId(), type); + if (dummyConnected) + std::cerr << " true "; + else + std::cerr << " false "; + std::cerr << std::endl; + + return dummyConnected; +} + +bool NetBinDummy::moretoread() +{ + std::cerr << "NetBinDummy::moretoread() "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + + return false; +} + +bool NetBinDummy::cansend() +{ + std::cerr << "NetBinDummy::cansend() "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + + return dummyConnected; +} + +std::string NetBinDummy::gethash() +{ + std::cerr << "NetBinDummy::gethash() "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + + return std::string(""); +} + + + + diff --git a/libretroshare/src/pqi/pqibin.h b/libretroshare/src/pqi/pqibin.h index 5096bf49f..ba9c22a63 100644 --- a/libretroshare/src/pqi/pqibin.h +++ b/libretroshare/src/pqi/pqibin.h @@ -29,11 +29,12 @@ #define PQI_BIN_INTERFACE_HEADER #include "pqi/pqi_base.h" +#include "pqi/pqihash.h" class BinFileInterface: public BinInterface { public: - BinFileInterface(char *fname, int flags); + BinFileInterface(const char *fname, int flags); virtual ~BinFileInterface(); virtual int tick() { return 1; } @@ -56,11 +57,13 @@ virtual bool moretoread() virtual bool cansend() { return (bin_flags | BIN_FLAGS_WRITEABLE); } +virtual std::string gethash(); private: int bin_flags; FILE *buf; int size; + pqihash *hash; }; @@ -93,6 +96,7 @@ virtual bool moretoread() } virtual bool cansend() { return (bin_flags | BIN_FLAGS_WRITEABLE); } +virtual std::string gethash(); private: int bin_flags; @@ -100,9 +104,42 @@ virtual bool cansend() { return (bin_flags | BIN_FLAGS_WRITEABLE); } int size; int recvsize; int readloc; + pqihash *hash; }; +class NetBinDummy: public NetBinInterface +{ +public: + NetBinDummy(PQInterface *parent, std::string id, uint32_t t); +virtual ~NetBinDummy() { return; } + + // Net Interface +virtual int connect(struct sockaddr_in raddr); +virtual int listen(); +virtual int stoplistening(); +virtual int disconnect(); +virtual int reset(); + + // Bin Interface. +virtual int tick(); + +virtual int senddata(void *data, int len); +virtual int readdata(void *data, int len); +virtual int netstatus(); +virtual int isactive(); +virtual bool moretoread(); +virtual bool cansend(); +virtual std::string gethash(); + + private: + uint32_t type; + bool dummyConnected; + bool toConnect; + uint32_t connectDelta; + time_t connectTS; +}; + #endif // PQI_BINARY_INTERFACES_HEADER diff --git a/libretroshare/src/pqi/pqichannel.cc b/libretroshare/src/pqi/pqichannel.cc deleted file mode 100644 index 4ccd4f430..000000000 --- a/libretroshare/src/pqi/pqichannel.cc +++ /dev/null @@ -1,610 +0,0 @@ -/* - * "$Id: pqichannel.cc,v 1.4 2007-02-18 21:46:49 rmf24 Exp $" - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2004-2006 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 "pqi/pqichannel.h" - -static const int pqicizone = 449; -#include "pqi/pqidebug.h" -#include - -const int PQChan_MsgType = 0x5601; -const int PQChan_NameType = 0x5602; -const int PQChan_HashType = 0x5604; -const int PQChan_TitleType = 0x5608; -const int PQChan_FileType = 0x5610; -const int PQChan_SizeType = 0x5620; -const int PQChan_ListType = 0x5640; - - -PQTunnel *createChannelItems(void *d, int n) -{ - pqioutput(PQL_DEBUG_BASIC, pqicizone, - "createChannelItems()"); - - return new PQChanItem(); -} - -PQChanItem::PQChanItem() - :PQTunnel(PQI_TUNNEL_CHANNEL_ITEM_TYPE), - certDER(NULL), certType(0), certLen(0), msg(""), - signature(NULL), signType(0), signLen(0) -{ - pqioutput(PQL_DEBUG_BASIC, pqicizone, - "PQChanItem::PQChanItem()"); - - return; -} - - -PQChanItem::~PQChanItem() -{ - pqioutput(PQL_DEBUG_BASIC, pqicizone, - "PQChanItem::~PQChanItem()"); - - clear(); - - return; -} - -PQChanItem *PQChanItem::clone() -{ - pqioutput(PQL_DEBUG_BASIC, pqicizone, - "PQChanItem::clone()"); - - PQChanItem *di = new PQChanItem(); - di -> copy(this); - return di; -} - -void PQChanItem::copy(const PQChanItem *di) -{ - pqioutput(PQL_DEBUG_BASIC, pqicizone, - "PQChanItem::copy()"); - - PQTunnel::copy(di); - - clear(); - - certType = di -> certType; - certLen = di -> certLen; - - // allocate memory and copy. - if (NULL == (certDER = (unsigned char *) malloc(certLen))) - { - pqioutput(PQL_DEBUG_BASIC, pqicizone, - "PQChanItem::in() Not enough Memory!"); - return; // cant be us. - } - - memcpy(certDER, di -> certDER, certLen); - - msg = di -> msg; - - files = di -> files; - - // only the signature to go!. - signType = di -> signType; - signLen = di -> signLen; - - // allocate memory and copy. - if (NULL == (signature = (unsigned char *) malloc(signLen))) - { - pqioutput(PQL_DEBUG_BASIC, pqicizone, - "PQChanItem::copy() Not enough Memory!"); - return; // cant be us. - } - - memcpy(signature, di -> signature, signLen); -} - - // Overloaded from PQTunnel. -const int PQChanItem::getSize() const -{ - // 8 bytes for cert + certLen; - // 8 bytes for msg + msgLen; - // 12 bytes for files + sum(file -> getSize()) - // 8 bytes for sign + signLen; - - int files_size = 0; - FileList::const_iterator it; - for(it = files.begin(); it != files.end(); it++) - { - files_size += it -> getSize(); - } - - return 8 + certLen + 8 + msg.length() + - 12 + files_size + 8 + signLen; -} - -int PQChanItem::out(void *data, const int size) const -{ - { - std::ostringstream out; - out << "PQChanItem::out() Data: " << data; - out << " Size: " << size << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqicizone, out.str()); - } - - if (size < PQChanItem::getSize()) - { - pqioutput(PQL_DEBUG_BASIC, pqicizone, - "PQChanItem::out() Packet Too Small!"); - return -1; - } - - // out is easy cos the getSize should be correct. - char *dta = (char *) data; - - // first we put down the certificate; - ((int *) dta)[0] = certType; - ((int *) dta)[1] = certLen; - dta += 8; // 4 bytes per int. - memcpy(dta, certDER, certLen); - dta += certLen; - - // now the message. - ((int *) dta)[0] = PQChan_MsgType; - ((int *) dta)[1] = msg.length(); - dta += 8; // 4 bytes per int. - memcpy(dta, msg.c_str(), msg.length()); - dta += msg.length(); - - // now list counter. - ((int *) dta)[0] = PQChan_ListType; - ((int *) dta)[1] = files.size(); - - // calc the length. - int files_size = 0; - FileList::const_iterator it; - for(it = files.begin(); it != files.end(); it++) - { - files_size += it -> getSize(); - } - - ((int *) dta)[2] = files_size; - dta += 12; // 4 bytes per int. - - // for each item of the list we need to put the data out. - for(it = files.begin(); it != files.end(); it++) - { - int fsize = it -> getSize(); - it -> out(dta, fsize); - dta += fsize; - } - - // finally the signature. - ((int *) dta)[0] = signType; - ((int *) dta)[1] = signLen; - dta += 8; // 4 bytes per int. - memcpy(dta, signature, signLen); - - return PQChanItem::getSize(); -} - - -void PQChanItem::clear() -{ - // first reset all our dataspaces. - if (certDER != NULL) - { - free(certDER); - certDER = NULL; - } - certLen = 0; - msg.clear(); - files.clear(); - if (signature != NULL) - { - free(signature); - signature = NULL; - } - signLen = 0; -} - - -int PQChanItem::in(const void *data, const int size) -{ - { - std::ostringstream out; - out << "PQChanItem::in() Data: " << data; - out << " Size: " << size << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqicizone, out.str()); - } - - clear(); - - int i; - int basesize = PQChanItem::getSize(); - if (size < basesize) - { - pqioutput(PQL_ALERT, pqicizone, - "PQChanItem::in() Not enough space for Class (Base)!"); - return -1; // cant be us. - } - - // now get certLen. - char *loc = ((char *) data); - certType = ((int *) loc)[0]; - certLen = ((int *) loc)[1]; - loc += 8; - // check size again. - if (size < (basesize = PQChanItem::getSize())) - { - pqioutput(PQL_ALERT, pqicizone, - "PQChanItem::in() Not enough space for Class (Cert)!"); - return -1; // cant be us. - } - - // allocate memory and copy. - if (NULL == (certDER = (unsigned char *) malloc(certLen))) - { - pqioutput(PQL_ALERT, pqicizone, - "PQChanItem::in() Not enough Memory!"); - return -1; // cant be us. - } - - memcpy(certDER, loc, certLen); - - loc += certLen; - - // now get msgSize. - if (((int *) loc)[0] != PQChan_MsgType) - { - pqioutput(PQL_ALERT, pqicizone, - "PQChanItem::in() Bad Msg Data Type!"); - return -1; // cant be us. - } - - int msize = ((int *) loc)[1]; - loc += 8; - - if (size < basesize + msize) - { - pqioutput(PQL_ALERT, pqicizone, - "PQChanItem::in() Not enough space for Class (Msg)!"); - return -1; // cant be us. - } - for(i = 0; i < msize; i++) - { - msg += loc[i]; - } - loc += msize; - - // now the files.... - // get total size... and check. - // now list counter. - - // now get msgSize. - if (((int *) loc)[0] != PQChan_ListType) - { - pqioutput(PQL_ALERT, pqicizone, - "PQChanItem::in() Bad List Data Type!"); - return -1; // cant be us. - } - - int fcount = ((int *) loc)[1]; - int fsize = ((int *) loc)[2]; - loc += 12; - - { - std::ostringstream out; - out << "PQChanItem::in() Size before Files: " << PQChanItem::getSize(); - out << " FileCount: " << fcount; - out << " FileSize: " << fsize; - pqioutput(PQL_DEBUG_BASIC, pqicizone, out.str()); - } - - // check the size again. - if (size < PQChanItem::getSize() + fsize) - { - pqioutput(PQL_ALERT, pqicizone, - "PQChanItem::in() Not enough space for Class (Files)!"); - return -1; // cant be us. - } - - // Loop through the the files. - int remain_fsize = fsize; - for(i = 0; i < fcount; i++) - { - FileItem file; - // loc, and the space left. - if (0 >= file.in(loc, remain_fsize)) - { - std::ostringstream out; - out << "PQChanItem::in() Not enough space for Class (File2)!"; - out << std::endl; - out << "\tWhen loading File #" << i+1 << " of " << fcount; - out << "\tCurrent Loc: " << loc << " Remaining: " << remain_fsize; - - pqioutput(PQL_ALERT, pqicizone, out.str()); - return -1; // cant be us. - } - - { - std::ostringstream out; - out << "PQChanItem::in() Loaded File #" << i+1; - out << " Loc: " << loc << " size: " << file.getSize(); - pqioutput(PQL_DEBUG_BASIC, pqicizone, out.str()); - } - - loc += file.getSize(); - remain_fsize -= file.getSize(); - - files.push_back(file); - } - - if (remain_fsize != 0) - { - std::ostringstream out; - out << "PQChanItem::in() Warning files size incorrect:"; - out << std::endl; - out << "Indicated Size: " << fsize << " Indicated Count:"; - out << fcount << std::endl; - out << "Real Size: " << fsize - remain_fsize; - pqioutput(PQL_ALERT, pqicizone, out.str()); - } - - // only the signature to go!. - signType = ((int *) loc)[0]; - signLen = ((int *) loc)[1]; - loc += 8; - // check size again. - if (size != PQChanItem::getSize()) - { - std::ostringstream out; - out << "PQChanItem::in() Size of Packet Incorrect!"; - out << std::endl; - out << "getSize(): " << PQChanItem::getSize(); - out << "data size: " << size; - - pqioutput(PQL_ALERT, pqicizone, out.str()); - - return -1; // cant be us. - } - - // allocate memory and copy. - if (NULL == (signature = (unsigned char *) malloc(signLen))) - { - pqioutput(PQL_ALERT, pqicizone, - "PQChanItem::in() Not enough Memory!"); - return -1; // cant be us. - } - - memcpy(signature, loc, signLen); - - loc += signLen; - - return PQChanItem::getSize(); -} - - - - - - -std::ostream &PQChanItem::print(std::ostream &out) -{ - out << "-------- PQChanItem" << std::endl; - PQItem::print(out); - - out << "Cert Type/Len: " << certType << "/"; - out << certLen << std::endl; - out << "Msg: " << msg << std::endl; - FileList::iterator it; - for(it = files.begin(); it != files.end(); it++) - { - it -> print(out); - } - out << "Sign Type/Len: " << signType << "/"; - out << signLen << std::endl; - - return out << "--------" << std::endl; -} - - -std::ostream &PQChanItem::FileItem::print(std::ostream &out) -{ - out << "-- PQChanItem::FileItem" << std::endl; - out << "Name: " << name << std::endl; - out << "Hash: " << hash << std::endl; - out << "Size: " << size << std::endl; - return out << "--" << std::endl; -} - - - // Overloaded from PQTunnel. -const int PQChanItem::FileItem::getSize() const -{ - // 8 bytes - // 8 bytes file + size; - // 8 bytes message + size; - // 8 bytes size; - - return 8 + 8 + name.length() + 8 + hash.length() + 8; -} - -int PQChanItem::FileItem::out(void *data, const int size) const -{ - { - std::ostringstream out; - out << "PQChanItem::FileItem::out() Data: " << data; - out << " Size: " << size << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqicizone, out.str()); - } - - if (size < PQChanItem::FileItem::getSize()) - { - pqioutput(PQL_DEBUG_BASIC, pqicizone, - "PQChanItem::FileItem::out() Packet Too Small!"); - return -1; - } - - // out is easy cos the getSize should be correct. - char *dta = (char *) data; - - // first we put down the total - ((int *) dta)[0] = PQChan_FileType; - ((int *) dta)[1] = PQChanItem::FileItem::getSize(); - dta += 8; // 4 bytes per int. - - ((int *) dta)[0] = PQChan_NameType; - ((int *) dta)[1] = name.length(); - dta += 8; // 4 bytes per int. - memcpy(dta, name.c_str(), name.length()); - dta += name.length(); - - ((int *) dta)[0] = PQChan_HashType; - ((int *) dta)[1] = hash.length(); - dta += 8; // 4 bytes per int. - memcpy(dta, hash.c_str(), hash.length()); - dta += hash.length(); - - ((int *) dta)[0] = PQChan_SizeType; - ((int *) dta)[1] = this -> size; - dta += 8; // 4 bytes per int. - - return PQChanItem::FileItem::getSize(); -} - - -void PQChanItem::FileItem::clear() -{ - // first reset all our dataspaces. - name.clear(); - hash.clear(); -} - - -int PQChanItem::FileItem::in(const void *data, const int size) -{ - { - std::ostringstream out; - out << "PQChanItem::FileItem::in() Data: " << data; - out << " Size: " << size << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqicizone, out.str()); - } - - clear(); - int i; - - int basesize = PQChanItem::FileItem::getSize(); - if (size < basesize) - { - pqioutput(PQL_ALERT, pqicizone, - "PQChanItem::FileItem::in() No space for Class (Base)!"); - return -1; // cant be us. - } - - - char *loc = ((char *) data); - if (((int *) loc)[0] != PQChan_FileType) - { - pqioutput(PQL_ALERT, pqicizone, - "PQChanItem::FileItem::in() Bad File Data Type!"); - return -1; // cant be us. - } - - int real_size = ((int *) loc)[1]; - if (size < real_size) - { - pqioutput(PQL_ALERT, pqicizone, - "PQChanItem::FileItem::in() No space for Class (TotalSize)!"); - return -1; // cant be us. - } - loc += 8; // 4 bytes per int. - - // now get name; - if (((int *) loc)[0] != PQChan_NameType) - { - pqioutput(PQL_ALERT, pqicizone, - "PQChanItem::FileItem::in() Bad Name Data Type!"); - return -1; // cant be us. - } - - int msize = ((int *) loc)[1]; - loc += 8; - - if (real_size < basesize + msize) - { - pqioutput(PQL_ALERT, pqicizone, - "PQChanItem::FileItem::in() No space for Class (Name)!"); - return -1; // cant be us. - } - for(i = 0; i < msize; i++) - { - name += loc[i]; - } - loc += msize; - - // now get hash; - if (((int *) loc)[0] != PQChan_HashType) - { - pqioutput(PQL_ALERT, pqicizone, - "PQChanItem::FileItem::in() Bad Hash Data Type!"); - return -1; // cant be us. - } - - int hsize = ((int *) loc)[1]; - loc += 8; - - if (real_size < basesize + msize + hsize) - { - pqioutput(PQL_ALERT, pqicizone, - "PQChanItem::FileItem::in() No space for Class (Hash)!"); - return -1; // cant be us. - } - for(i = 0; i < hsize; i++) - { - hash += loc[i]; - } - loc += hsize; - - // now get size. - if (((int *) loc)[0] != PQChan_SizeType) - { - pqioutput(PQL_ALERT, pqicizone, - "PQChanItem::FileItem::in() Bad Size Data Type!"); - return -1; // cant be us. - } - - this -> size = ((int *) loc)[1]; - loc += 8; - - // finally verify that the sizes are correct. - if (real_size != PQChanItem::FileItem::getSize()) - { - pqioutput(PQL_ALERT, pqicizone, - "PQChanItem::FileItem::in() Size Mismatch!"); - return -1; // cant be us. - } - - return PQChanItem::FileItem::getSize(); -} - - - diff --git a/libretroshare/src/pqi/pqichannel.h b/libretroshare/src/pqi/pqichannel.h deleted file mode 100644 index a44bd9ddb..000000000 --- a/libretroshare/src/pqi/pqichannel.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * "$Id: pqichannel.h,v 1.3 2007-02-18 21:46:49 rmf24 Exp $" - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2004-2006 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - -#ifndef MRK_PQI_CHANNELITEM_H -#define MRK_PQI_CHANNELITEM_H - -#include "pqi/pqitunnel.h" - -#define PQI_TUNNEL_CHANNEL_ITEM_TYPE 162 - -PQTunnel *createChannelItems(void *d, int n); - -class PQChanItem: public PQTunnel -{ - protected: - //PQChanItem(int st); - public: - PQChanItem(); - ~PQChanItem(); -virtual PQChanItem *clone(); -void copy(const PQChanItem *di); -void clear(); -virtual std::ostream &print(std::ostream &out); - - // Overloaded from PQTunnel. -virtual const int getSize() const; -virtual int out(void *data, const int size) const; -virtual int in(const void *data, const int size); - - - // So what data do we need. - // data load. - // - // 1) a Message. - // 2) a list of filenames/hashs/sizes. - // - // So you can different types - // of channels. - // - // 1) Clear Text Signed. - // -> name - // -> public key. - // -> data load - // -> signature. (of all) - // - // 2) Encrypted. - // -> name - // -> public key - // -> encrypted data load. - // -> signature (of all) - // - - class FileItem - { - public: - std::string name; - std::string hash; - long size; - - void clear(); - std::ostream &print(std::ostream &out); - - const int getSize() const; - int out(void *data, const int size) const; - int in(const void *data, const int size); - }; - - typedef std::list FileList; - - // Certificate/Key (containing Name) - unsigned char *certDER; - int certType; - int certLen; - - std::string msg; - std::string title; - FileList files; - - unsigned char *signature; - int signType; - int signLen; - - bool signValid; // not transmitted. -}; - - -#endif // MRK_PQI_CHANNELITEM_H diff --git a/libretroshare/src/pqi/pqihandler.h b/libretroshare/src/pqi/pqihandler.h index 483603bb3..f8ef9dae9 100644 --- a/libretroshare/src/pqi/pqihandler.h +++ b/libretroshare/src/pqi/pqihandler.h @@ -23,27 +23,12 @@ * */ - - #ifndef MRK_PQI_HANDLER_HEADER #define MRK_PQI_HANDLER_HEADER #include "pqi/pqi.h" #include "pqi/pqisecurity.h" -/**************** PQI_USE_XPGP ******************/ -#if defined(PQI_USE_XPGP) - -#include "pqi/xpgpcert.h" - -#else /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - -#include "pqi/sslcert.h" - -#endif /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - #include #include diff --git a/libretroshare/src/pqi/pqihash.h b/libretroshare/src/pqi/pqihash.h new file mode 100644 index 000000000..a2e5f9147 --- /dev/null +++ b/libretroshare/src/pqi/pqihash.h @@ -0,0 +1,85 @@ +/* + * libretroshare/src/pqi: pqihash.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 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 +#include +#include +#include + +class pqihash +{ + public: + pqihash() +{ + + sha_hash = new uint8_t[SHA_DIGEST_LENGTH]; + sha_ctx = new SHA_CTX; + SHA1_Init(sha_ctx); + doHash = true; +} + +void addData(void *data, uint32_t len) +{ + if (doHash) + { + SHA1_Update(sha_ctx, data, len); + } +} + +void Complete(std::string &hash) +{ + if (!doHash) + { + hash = endHash; + return; + } + + SHA1_Final(sha_hash, sha_ctx); + + std::ostringstream out; + for(int i = 0; i < SHA_DIGEST_LENGTH; i++) + { + out << std::setw(2) << std::setfill('0') << std::hex; + out << (unsigned int) (sha_hash[i]); + } + endHash = out.str(); + hash = endHash; + doHash = false; + + delete []sha_hash; + delete sha_ctx; + + return; +} + + private: + + bool doHash; + std::string endHash; + uint8_t *sha_hash; + SHA_CTX *sha_ctx; +}; + + diff --git a/libretroshare/src/pqi/pqiindic.h b/libretroshare/src/pqi/pqiindic.h index 2207d7538..3c036e3c5 100644 --- a/libretroshare/src/pqi/pqiindic.h +++ b/libretroshare/src/pqi/pqiindic.h @@ -36,7 +36,7 @@ class Indicator { public: - Indicator(int n = 0) + Indicator(int n = 1) :num(n), changeFlags(n) {IndicateChanged();} void IndicateChanged() { @@ -44,7 +44,7 @@ void IndicateChanged() changeFlags[i]=true; } -bool Changed(int idx) +bool Changed(int idx = 0) { /* catch overflow */ if (idx > num - 1) diff --git a/libretroshare/src/pqi/pqitunneltst.cc b/libretroshare/src/pqi/pqilistener.h similarity index 57% rename from libretroshare/src/pqi/pqitunneltst.cc rename to libretroshare/src/pqi/pqilistener.h index f73cb5435..5642ae2b1 100644 --- a/libretroshare/src/pqi/pqitunneltst.cc +++ b/libretroshare/src/pqi/pqilistener.h @@ -1,9 +1,9 @@ /* - * "$Id: pqitunneltst.cc,v 1.3 2007-02-18 21:46:50 rmf24 Exp $" + * libretroshare/src/pqi: pqilistener.h * * 3P/PQI network interface for RetroShare. * - * Copyright 2004-2006 by Robert Fernie. + * Copyright 2004-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 @@ -23,14 +23,26 @@ * */ +#ifndef MRK_PQI_GENERIC_LISTEN_HEADER +#define MRK_PQI_GENERIC_LISTEN_HEADER +// operating system specific network header. +#include "pqi/pqinetwork.h" - -#include "pqi/pqitunneltst.h" - -PQTunnel *createPQTStst(void *d, int n) +class pqilistener { - return new PQTunnelTst(); -} + public: + + pqilistener() { return; } +virtual ~pqilistener() { return; } + +virtual int tick() { return 1; } +virtual int status() { return 1; } +virtual int setListenAddr(struct sockaddr_in addr) { return 1; } +virtual int setuplisten() { return 1; } +virtual int resetlisten() { return 1; } + +}; +#endif // MRK_PQI_GENERIC_LISTEN_HEADER diff --git a/libretroshare/src/pqi/pqiloopback.cc b/libretroshare/src/pqi/pqiloopback.cc index 45a9e71be..c9be77373 100644 --- a/libretroshare/src/pqi/pqiloopback.cc +++ b/libretroshare/src/pqi/pqiloopback.cc @@ -1,9 +1,9 @@ /* - * "$Id: pqiloopback.cc,v 1.8 2007-02-19 20:08:30 rmf24 Exp $" + * libretroshare/src/pqi: pqiloopback.cc * * 3P/PQI network interface for RetroShare. * - * Copyright 2004-2006 by Robert Fernie. + * Copyright 2004-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 @@ -23,33 +23,12 @@ * */ - - - #include "pqi/pqi.h" #include "pqi/pqiloopback.h" -/**************** PQI_USE_XPGP ******************/ -#if defined(PQI_USE_XPGP) - -#include "pqi/xpgpcert.h" - -#else /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - -#include "pqi/sslcert.h" - -#endif /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - -// Test Interface (LoopBack) - - pqiloopback::pqiloopback(std::string id) :PQInterface(id) { - //std::cerr << "pqiloopback construction()" << std::endl; - // rates are irrelevant..... no B/W consumed. setMaxRate(true, 0); setMaxRate(false, 0); setRate(true, 0); @@ -65,9 +44,6 @@ pqiloopback::~pqiloopback() int pqiloopback::SendItem(RsItem *i) { - // contact Id should be correct already! - //i -> p = getContact(); - //i -> flags |= PQI_ITEM_FLAG_LOCAL; objs.push_back(i); return 1; } @@ -78,15 +54,12 @@ RsItem * pqiloopback::GetItem() { RsItem *pqi = objs.front(); objs.pop_front(); - // breaks the module, through ssl dependance. - // but necessary for running system.. - //pqi -> p = getSSLRoot() -> getOwnCert(); return pqi; } return NULL; } -// // PQI interface. +// PQI interface. int pqiloopback::tick() { return 0; diff --git a/libretroshare/src/pqi/pqiloopback.h b/libretroshare/src/pqi/pqiloopback.h index fb1b9b6d7..f79403609 100644 --- a/libretroshare/src/pqi/pqiloopback.h +++ b/libretroshare/src/pqi/pqiloopback.h @@ -1,9 +1,9 @@ /* - * "$Id: pqiloopback.h,v 1.5 2007-02-19 20:08:30 rmf24 Exp $" + * libretroshare/src/pqi: pqiloopback.h * * 3P/PQI network interface for RetroShare. * - * Copyright 2004-2006 by Robert Fernie. + * Copyright 2004-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 @@ -23,12 +23,9 @@ * */ - - #ifndef MRK_PQI_LOOPBACK_HEADER #define MRK_PQI_LOOPBACK_HEADER - // The standard data types and the search interface. #include "pqi/pqi.h" @@ -36,9 +33,6 @@ #include #include - -// Test Interface (LoopBack) -// public interface .... includes the whole p3interface. class pqiloopback: public PQInterface { public: diff --git a/libretroshare/src/pqi/pqimon.cc b/libretroshare/src/pqi/pqimon.cc deleted file mode 100644 index a6fb5bdc8..000000000 --- a/libretroshare/src/pqi/pqimon.cc +++ /dev/null @@ -1,124 +0,0 @@ -/* - * "$Id: pqimon.cc,v 1.2 2007-02-18 21:46:49 rmf24 Exp $" - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2004-2006 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". - * - */ - -/**************** PQI_USE_XPGP ******************/ -#if defined(PQI_USE_XPGP) - -#include "pqi/xpgpcert.h" - -#else /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - -#include "pqi/sslcert.h" - -#endif /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - -#include "pqi/pqimon.h" - - -pqimonitor::pqimonitor() { return; } -pqimonitor::~pqimonitor() { return; } - - -int pqimonitor::tick() -{ - - /* grab the sslroot - and check the state of the peers */ - sslroot *sslr = getSSLRoot(); - std::list &certlist = sslr->getCertList(); - std::list::iterator it; - std::list::iterator pit; - std::list::iterator cit; - - //std::cerr << "pqimonitor::tick() plist:" << plist.size() << " clist:" << certlist.size() << std::endl; - - bool ok = true; - if (plist.size() != certlist.size()) - { - ok = false; - } - - pit = plist.begin(); - for(it = certlist.begin(); (ok) && (it != certlist.end()); it++, pit++) - { - certsign sign; - if (!sslr->getcertsign(*it, sign)) - { - ok = false; - break; - } - - std::string id = convert_to_str(sign); - - if (id != pit->id) - { - ok = false; - break; - } - } - - if (!ok) - { - //std::cerr << "pqimonitor::tick() Updating plist" << std::endl; - /* copy the list */ - plist.clear(); - for(it = certlist.begin(); it != certlist.end(); it++) - { - /* list */ - certsign sign; - if (!sslr->getcertsign(*it, sign)) - { - std::cerr << "Major Error in pqimonitor!"; - std::cerr << std::endl; - exit(1); - } - - pqipeer peer; - peer.id = convert_to_str(sign); - peer.name = (*it)->Name(); - if ((*it)->Connected()) - { - peer.state = PQI_PEER_STATE_ONLINE; - } - else - { - peer.state = PQI_PEER_STATE_OFFLINE; - } - plist.push_back(peer); - } - - /* now notify clients */ - for(cit = clients.begin(); cit != clients.end(); cit++) - { - //std::cerr << "pqimonitor::tick() Calling Client" << std::endl; - (*cit)->monUpdate(plist); - } - } - return 0; /* don't make more work for anyone */ -} - - - diff --git a/libretroshare/src/pqi/pqimonitor.cc b/libretroshare/src/pqi/pqimonitor.cc new file mode 100644 index 000000000..51cc4a74d --- /dev/null +++ b/libretroshare/src/pqi/pqimonitor.cc @@ -0,0 +1,83 @@ +/* + * libretroshare/src/pqi: pqimonitor.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 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 "pqi/pqimonitor.h" +#include "pqi/pqinetwork.h" +#include "util/rsprint.h" + +/***** DUMMY Connect CB for testing *****/ + +#include + + +pqiConnectCbDummy::pqiConnectCbDummy() +{ + std::cerr << "pqiConnectCbDummy()" << std::endl; + return; +} + +pqiConnectCbDummy::~pqiConnectCbDummy() +{ + return; +} + +void pqiConnectCbDummy::peerStatus(std::string id, + struct sockaddr_in laddr, struct sockaddr_in raddr, + uint32_t type, uint32_t mode, uint32_t source) +{ + std::cerr << "pqiConnectCbDummy::peerStatus()"; + std::cerr << " id: " << id; + + std::cerr << " laddr: " << inet_ntoa(laddr.sin_addr); + std::cerr << " lport: " << ntohs(laddr.sin_port); + 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 << " source: " << source; + std::cerr << std::endl; +} + +void pqiConnectCbDummy::peerConnectRequest(std::string id, uint32_t type) +{ + std::cerr << "pqiConnectCbDummy::peerConnectRequest()"; + std::cerr << " id: " << id; + std::cerr << " type: " << type; + std::cerr << std::endl; +} + + + +void pqiConnectCbDummy::stunStatus(std::string id, struct sockaddr_in addr, uint32_t flags) +{ + std::cerr << "pqiConnectCbDummy::stunStatus()"; + std::cerr << " idhash: " << RsUtil::BinToHex(id) << " addr: " << inet_ntoa(addr.sin_addr); + std::cerr << " port: " << ntohs(addr.sin_port); + std::cerr << " flags: " << flags; + std::cerr << std::endl; +} + + diff --git a/libretroshare/src/pqi/pqimonitor.h b/libretroshare/src/pqi/pqimonitor.h new file mode 100644 index 000000000..0b5036282 --- /dev/null +++ b/libretroshare/src/pqi/pqimonitor.h @@ -0,0 +1,132 @@ +/* + * libretroshare/src/pqi: pqimonitor.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 PQI_MONITOR_H +#define PQI_MONITOR_H + +/**** Rough sketch of a Monitor class + * expect it to change significantly + * + */ + +#include +#include +#include + +/************** Define Type/Mode/Source ***************/ + + +/* STATE MASK */ +const uint32_t RS_PEER_STATE_MASK = 0x00ff; +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..*/ + +/* 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; + +/* Stun Status Flags */ +//const uint32_t RS_STUN_SRC_DHT = 0x0001; +//const uint32_t RS_STUN_SRC_PEER = 0x0002; +const uint32_t RS_STUN_ONLINE = 0x0010; +const uint32_t RS_STUN_FRIEND = 0x0020; + + + +#define RS_CONNECT_PASSIVE 1 +#define RS_CONNECT_ACTIVE 2 + +#define RS_CB_DHT 1 /* from dht */ +#define RS_CB_DISC 2 /* from peers */ +#define RS_CB_PERSON 3 /* from connection */ + + +class pqipeer +{ + public: +std::string id; +std::string name; +uint32_t state; +uint32_t actions; +}; + +class p3ConnectMgr; + +class pqiMonitor +{ + public: + pqiMonitor() :mConnMgr(NULL) { return; } +virtual ~pqiMonitor() { return; } + + void setConnectionMgr(p3ConnectMgr *cm) { mConnMgr = cm; } +virtual void statusChange(const std::list &plist) = 0; + +//virtual void peerStatus(std::string id, uint32_t mode) = 0; + + protected: + p3ConnectMgr *mConnMgr; +}; + + + + +class pqiConnectCb +{ + public: +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; + +virtual void peerConnectRequest(std::string id, uint32_t type) = 0; + +virtual void stunStatus(std::string id, struct sockaddr_in addr, uint32_t flags) = 0; +}; + + +/**** DUMMY CB FOR TESTING (just prints) ****/ +class pqiConnectCbDummy: public pqiConnectCb +{ + public: + pqiConnectCbDummy(); +virtual ~pqiConnectCbDummy(); +virtual void peerStatus(std::string id, + struct sockaddr_in laddr, struct sockaddr_in raddr, + uint32_t type, uint32_t mode, 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); +}; + +#endif // PQI_MONITOR_H + diff --git a/libretroshare/src/pqi/pqinetwork.cc b/libretroshare/src/pqi/pqinetwork.cc index a4344e61a..e0c54ef9b 100644 --- a/libretroshare/src/pqi/pqinetwork.cc +++ b/libretroshare/src/pqi/pqinetwork.cc @@ -436,6 +436,15 @@ in_addr_t pqi_inet_netof(struct in_addr addr) //return abit; } +int sockaddr_cmp(struct sockaddr_in &addr1, struct sockaddr_in &addr2 ) +{ + if (addr1.sin_family != addr2.sin_family) + return addr1.sin_family - addr2.sin_family; + if (addr1.sin_addr.s_addr != addr2.sin_addr.s_addr) + return (addr1.sin_addr.s_addr - addr2.sin_addr.s_addr); + if (addr1.sin_port != addr2.sin_port) + return (addr1.sin_port - addr2.sin_port); +} int inaddr_cmp(struct sockaddr_in addr1, struct sockaddr_in addr2 ) { @@ -660,7 +669,7 @@ bool isSameSubnet(struct in_addr *addr1, struct in_addr *addr2) bool LookupDNSAddr(std::string name, struct sockaddr_in &addr) { -#if 0 +#if 1 char service[100]; struct addrinfo hints_st; struct addrinfo *hints = &hints_st; diff --git a/libretroshare/src/pqi/pqinetwork.h b/libretroshare/src/pqi/pqinetwork.h index b87d92260..a86f6cd0e 100644 --- a/libretroshare/src/pqi/pqinetwork.h +++ b/libretroshare/src/pqi/pqinetwork.h @@ -102,6 +102,7 @@ extern int errno; /* Define extern errno, to duplicate unix behaviour */ std::ostream &showSocketError(std::ostream &out); std::string socket_errorType(int err); +int sockaddr_cmp(struct sockaddr_in &addr1, struct sockaddr_in &addr2 ); int inaddr_cmp(struct sockaddr_in addr1, struct sockaddr_in addr1 ); int inaddr_cmp(struct sockaddr_in addr1, unsigned long); diff --git a/libretroshare/src/pqi/pqiperson.cc b/libretroshare/src/pqi/pqiperson.cc index 095548d23..c555fdf9e 100644 --- a/libretroshare/src/pqi/pqiperson.cc +++ b/libretroshare/src/pqi/pqiperson.cc @@ -23,41 +23,22 @@ * */ - - #include "pqi/pqi.h" - -#include - #include "pqi/pqiperson.h" +#include "pqi/pqipersongrp.h" const int pqipersonzone = 82371; #include "pqi/pqidebug.h" #include -pqiperson::pqiperson(cert *c, std::string id) - :PQInterface(id), sslcert(c), active(false), activepqi(NULL), - inConnectAttempt(false), waittimes(0) +pqiperson::pqiperson(std::string id, pqipersongrp *pg) + :PQInterface(id), active(false), activepqi(NULL), + inConnectAttempt(false), waittimes(0), + pqipg(pg) { - sroot = getSSLRoot(); - // check certificate - -/**************** PQI_USE_XPGP ******************/ -#if defined(PQI_USE_XPGP) - sroot -> validateCertificateXPGP(sslcert); -#else /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - sroot -> validateCertificate(sslcert); -#endif /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - - if (!(sslcert -> Valid())) - { - std::cerr << "pqiperson::Warning Certificate Not Approved!"; - std::cerr << " pqiperson will not initialise...." << std::endl; - } + /* must check id! */ return; } @@ -65,13 +46,13 @@ pqiperson::pqiperson(cert *c, std::string id) pqiperson::~pqiperson() { // clean up the children. - std::list::iterator it = kids.begin(); - for(it = kids.begin(); it != kids.end(); ) + std::map::iterator it; + for(it = kids.begin(); it != kids.end(); it++) { - pqiconnect *pc = (*it); - it = kids.erase(it); + pqiconnect *pc = (it->second); delete pc; } + kids.clear(); } @@ -111,11 +92,6 @@ int pqiperson::status() return -1; } -cert * pqiperson::getContact() -{ - return sslcert; -} - // tick...... int pqiperson::tick() { @@ -123,7 +99,7 @@ int pqiperson::tick() { std::ostringstream out; - out << "pqiperson::tick() Cert: " << sslcert -> Name() << " "; + out << "pqiperson::tick() Id: " << PeerId() << " "; if (active) out << "***Active***"; else @@ -140,48 +116,19 @@ int pqiperson::tick() // tick the children. - std::list::iterator it; + std::map::iterator it; for(it = kids.begin(); it != kids.end(); it++) { - if (0 < (*it) -> tick()) + if (0 < (it->second) -> tick()) { activeTick = 1; } - out << "\tTicking Child: " << (*it) << std::endl; + out << "\tTicking Child: " << (it->first) << std::endl; } pqioutput(PQL_DEBUG_ALL, pqipersonzone, out.str()); } // end of pqioutput. - // use cert settings to control everything. - if (!active) - { - if ((sslcert -> WillConnect()) && (!inConnectAttempt)) - { - if (sslcert -> nc_timestamp < time(NULL)) - { - // calc the time til next connect. - sslcert -> nc_timestamp = time(NULL) + - connectWait(); - connectattempt(NULL); - } - } - if (sslcert -> Listening()) - { - if (!(sslcert -> WillListen())) - { - stoplistening(); - } - } - else - { - if (sslcert -> WillListen()) - { - listen(); - } - } - } - return activeTick; } @@ -192,7 +139,7 @@ int pqiperson::notifyEvent(NetInterface *ni, int newState) { { std::ostringstream out; - out << "pqiperson::notifyEvent() Cert: " << sslcert -> Name(); + out << "pqiperson::notifyEvent() Id: " << PeerId(); out << std::endl; out << "Message: " << newState << " from: " << ni << std::endl; @@ -201,7 +148,7 @@ int pqiperson::notifyEvent(NetInterface *ni, int newState) /* find the pqi, */ pqiconnect *pqi = NULL; - std::list::iterator it; + std::map::iterator it; /* start again */ int i = 0; @@ -211,15 +158,15 @@ int pqiperson::notifyEvent(NetInterface *ni, int newState) out << "pqiperson::connectattempt() Kid# "; out << i << " of " << kids.size(); out << std::endl; - out << " pqiconn: " << (*it); - out << " ni: " << (*it)->ni; + out << " type: " << (it->first); + out << " ni: " << (it->second)->ni; out << " in_ni: " << ni; pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str()); i++; - if ((*it)->thisNetInterface(ni)) + if ((it->second)->thisNetInterface(ni)) { - pqi = (*it); + pqi = (it->second); } } @@ -234,13 +181,16 @@ int pqiperson::notifyEvent(NetInterface *ni, int newState) { case CONNECT_RECEIVED: case CONNECT_SUCCESS: + + /* notify */ + if (pqipg) + pqipg->notifyConnect(PeerId(), true); + if ((active) && (activepqi != pqi)) // already connected - trouble { pqioutput(PQL_WARNING, pqipersonzone, "CONNECT_SUCCESS+active->trouble: shutdown EXISTING->switch to new one!"); - //pqi -> stoplistening(); - // This is the RESET that's killing the connections..... activepqi -> reset(); // this causes a recursive call back into this fn. @@ -256,20 +206,20 @@ int pqiperson::notifyEvent(NetInterface *ni, int newState) // mark as active. active = true; activepqi = pqi; - sslcert -> Connected(true); - sroot -> IndicateCertsChanged(); - connectSuccess(); inConnectAttempt = false; - // dont stop listening. - //stoplistening(); return 1; } break; case CONNECT_UNREACHABLE: case CONNECT_FIREWALLED: case CONNECT_FAILED: + + /* notify up */ + if (pqipg) + pqipg->notifyConnect(PeerId(), false); + if (active) { if (activepqi == pqi) @@ -278,8 +228,6 @@ int pqiperson::notifyEvent(NetInterface *ni, int newState) "CONNECT_FAILED->marking so!"); active = false; activepqi = NULL; - sslcert -> Connected(false); - sroot -> IndicateCertsChanged(); return 1; } else @@ -295,7 +243,7 @@ int pqiperson::notifyEvent(NetInterface *ni, int newState) pqioutput(PQL_WARNING, pqipersonzone, "CONNECT_FAILED+NOT active -> try connect again"); - connectattempt(pqi); + //connectattempt(pqi); return 1; } break; @@ -311,59 +259,33 @@ int pqiperson::reset() { { std::ostringstream out; - out << "pqiperson::reset() Cert: " << sslcert -> Name(); + out << "pqiperson::reset() Id: " << PeerId(); out << std::endl; pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str()); } - std::list::iterator it; + std::map::iterator it; for(it = kids.begin(); it != kids.end(); it++) { - (*it) -> reset(); + (it->second) -> reset(); } activepqi = NULL; active = false; - sslcert -> Listening(false); - sslcert -> Connected(false); - sroot -> IndicateCertsChanged(); - - // check auto setting at reset. - if (!sslcert -> Manual()) - autoconnect(true); return 1; } -int pqiperson::autoconnect(bool b) +int pqiperson::addChildInterface(uint32_t type, pqiconnect *pqi) { { std::ostringstream out; - out << "pqiperson::autoconnect() Cert: " << sslcert -> Name(); - out << " - " << (int) b << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str()); - } - - sslcert -> Manual(!b); - - sslcert -> WillConnect(b); - sslcert -> WillListen(b); - sroot -> IndicateCertsChanged(); - - return 1; -} - - -int pqiperson::addChildInterface(pqiconnect *pqi) -{ - { - std::ostringstream out; - out << "pqiperson::addChildInterface() : " << pqi; + out << "pqiperson::addChildInterface() : Id " << PeerId() << " " << type; out << std::endl; pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str()); } - kids.push_back(pqi); + kids[type] = pqi; return 1; } @@ -375,21 +297,19 @@ int pqiperson::listen() { { std::ostringstream out; - out << "pqiperson::listen() Cert: " << sslcert -> Name(); + out << "pqiperson::listen() Id: " << PeerId(); out << std::endl; pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str()); } if (!active) { - std::list::iterator it; + std::map::iterator it; for(it = kids.begin(); it != kids.end(); it++) { // set them all listening. - (*it) -> listen(); + (it->second) -> listen(); } - sslcert -> Listening(true); - sroot -> IndicateCertsChanged(); } return 1; } @@ -399,114 +319,53 @@ int pqiperson::stoplistening() { { std::ostringstream out; - out << "pqiperson::stoplistening() Cert: " << sslcert -> Name(); + out << "pqiperson::stoplistening() Id: " << PeerId(); out << std::endl; pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str()); } - std::list::iterator it; + std::map::iterator it; for(it = kids.begin(); it != kids.end(); it++) { // set them all listening. - (*it) -> stoplistening(); + (it->second) -> stoplistening(); } - sslcert -> Listening(false); - sroot -> IndicateCertsChanged(); - return 1; } -int pqiperson::connectattempt(pqiconnect *last) +int pqiperson::connect(uint32_t type, struct sockaddr_in raddr) { { std::ostringstream out; - out << "pqiperson::connectattempt() Cert: " << sslcert -> Name(); + out << "pqiperson::connect() Id: " << PeerId(); + out << " type: " << type; + out << " addr: " << inet_ntoa(raddr.sin_addr); + out << ":" << ntohs(raddr.sin_port); out << std::endl; pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str()); } - std::list::iterator it = kids.begin(); - int i = 0; - if (last != NULL) - { - // find the current connection. - for(; (it != kids.end()) && ((*it) != last); it++, i++); - - if (it != kids.end()) - { - std::ostringstream out; - out << "pqiperson::connectattempt() Last Cert#: "; - out << i << " of " << kids.size(); - out << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str()); - - - it++; - i++; - } - } - // now at the first one to try. - { - std::ostringstream out; - out << "pqiperson::connectattempt() Cert: " << sslcert -> Name(); - out << " Starting Attempts at Interface " << i << " of " << kids.size(); - out << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str()); - } - - // try to connect on the next one. - for(; (it != kids.end()) && (0 > (*it)->connectattempt()); it++, i++); - + std::map::iterator it; + + it = kids.find(type); if (it == kids.end()) { - std::ostringstream out; - out << "pqiperson::connectattempt() Cert: " << sslcert -> Name(); - out << " Failed on All Interfaces"; - out << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str()); - } - else - { - std::ostringstream out; - out << "pqiperson::connectattempt() Cert: " << sslcert -> Name(); - out << " attempt on pqiconnect #" << i << " suceeded"; - out << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str()); + std::ostringstream out; + out << "pqiperson::connect()"; + out << " missing pqiconnect"; + out << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str()); } + + (it->second)->connect(raddr); // flag if we started a new connectionAttempt. - inConnectAttempt = (it != kids.end()); + inConnectAttempt = true; return 1; } -// returns (in secs) the time til next connect attempt -// this is based on the -// -#define SEC_PER_LOG_UNIT 600 /* ten minutes? */ -#define MAX_WAITTIMES 10 /* ten minutes? */ - -int pqiperson::connectWait() -{ - int log_weight = (1 << waittimes); - // max wait of 2^10 = 1024 * X min (over a month) - // 10240 min = 1 day - waittimes++; - if (waittimes > MAX_WAITTIMES) - waittimes = MAX_WAITTIMES; - // make it linear instead!. - return waittimes * SEC_PER_LOG_UNIT; - //return log_weight * SEC_PER_LOG_UNIT; -} - -// called to reduce the waittimes, next time. -int pqiperson::connectSuccess() -{ - return waittimes = 0; -} - - float pqiperson::getRate(bool in) { // get the rate from the active one. @@ -520,10 +379,10 @@ void pqiperson::setMaxRate(bool in, float val) // set to all of them. (and us) PQInterface::setMaxRate(in, val); // clean up the children. - std::list::iterator it = kids.begin(); + std::map::iterator it; for(it = kids.begin(); it != kids.end(); it++) { - (*it) -> setMaxRate(in, val); + (it->second) -> setMaxRate(in, val); } } diff --git a/libretroshare/src/pqi/pqiperson.h b/libretroshare/src/pqi/pqiperson.h index 403ad8f05..7fac0bbb4 100644 --- a/libretroshare/src/pqi/pqiperson.h +++ b/libretroshare/src/pqi/pqiperson.h @@ -31,23 +31,9 @@ #include "pqi/pqi.h" -/**************** PQI_USE_XPGP ******************/ -#if defined(PQI_USE_XPGP) - -#include "pqi/xpgpcert.h" - -#else /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - -#include "pqi/sslcert.h" - -#endif /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - #include class pqiperson; -class sslroot; static const int CONNECT_RECEIVED = 1; static const int CONNECT_SUCCESS = 2; @@ -77,7 +63,7 @@ public: virtual ~pqiconnect() { return; } // presents a virtual NetInterface -> passes to ni. -virtual int connectattempt() { return ni -> connectattempt(); } +virtual int connect(struct sockaddr_in raddr) { return ni->connect(raddr); } virtual int listen() { return ni -> listen(); } virtual int stoplistening() { return ni -> stoplistening(); } virtual int reset() { return ni -> reset(); } @@ -104,19 +90,20 @@ protected: }; +class pqipersongrp; class pqiperson: public PQInterface { public: - pqiperson(cert *c, std::string id); + pqiperson(std::string id, pqipersongrp *ppg); virtual ~pqiperson(); // must clean up children. // control of the connection. int reset(); -int autoconnect(bool); +int connect(uint32_t type, struct sockaddr_in raddr); // add in connection method. -int addChildInterface(pqiconnect *pqi); +int addChildInterface(uint32_t type, pqiconnect *pqi); // The PQInterface interface. virtual int SendItem(RsItem *); @@ -124,7 +111,6 @@ virtual RsItem *GetItem(); virtual int status(); virtual int tick(); -virtual cert * getContact(); // overloaded callback function for the child - notify of a change. int notifyEvent(NetInterface *ni, int event); @@ -135,23 +121,18 @@ virtual void setMaxRate(bool in, float val); private: - std::list kids; - cert *sslcert; + std::map kids; bool active; pqiconnect *activepqi; bool inConnectAttempt; int waittimes; - sslroot *sroot; - private: /* Helper functions */ -int connectWait(); -int connectSuccess(); int listen(); int stoplistening(); -int connectattempt(pqiconnect *last); + pqipersongrp *pqipg; /* parent for callback */ }; diff --git a/libretroshare/src/pqi/pqipersongrp.cc b/libretroshare/src/pqi/pqipersongrp.cc index dc4a07af6..1a2faecb5 100644 --- a/libretroshare/src/pqi/pqipersongrp.cc +++ b/libretroshare/src/pqi/pqipersongrp.cc @@ -1,5 +1,5 @@ /* - * "$Id: pqipersongrp.cc,v 1.14 2007-02-19 20:08:30 rmf24 Exp $" + * libretroshare/src/pqi: pqipersongrp.cc * * 3P/PQI network interface for RetroShare. * @@ -23,22 +23,10 @@ * */ - - - #include "pqi/pqipersongrp.h" - -#include "pqi/pqissl.h" -#include "pqi/pqissllistener.h" - -#ifdef PQI_USE_PROXY - #include "pqi/pqiudpproxy.h" - #include "pqi/pqissludp.h" -#endif - -//#include "pqi/pqitunneltst.h" - +#include "pqi/p3connmgr.h" #include "pqi/pqidebug.h" + #include const int pqipersongrpzone = 354; @@ -101,87 +89,13 @@ int pqipersongrp::tickServiceSend() } - // inits -pqipersongrp::pqipersongrp(SecurityPolicy *glob, sslroot *sr, unsigned long flags) - :pqihandler(glob), sslr(sr), -#ifdef PQI_USE_PROXY - p3p(NULL), -#endif - initFlags(flags) + // init +pqipersongrp::pqipersongrp(SecurityPolicy *glob, unsigned long flags) + :pqihandler(glob), pqil(NULL), config(NULL), initFlags(flags) { - // add a p3proxy & p3disc. -#ifdef PQI_USE_PROXY - p3p = new p3udpproxy(p3d); -#endif - - if (!(sr -> active())) - { - pqioutput(PQL_ALERT, pqipersongrpzone, "sslroot not active... exiting!"); - exit(1); - } - - // make listen - Person *us = sr -> getOwnCert(); - if (us != NULL) - { - if (flags & PQIPERSON_NO_SSLLISTENER) - { - pqil = NULL; - } - else - { - pqil = new pqissllistener(us -> localaddr); - } -#ifdef PQI_USE_PROXY - pqiudpl = new pqiudplistener((p3udpproxy *) p3p, - us -> localaddr); -#endif - } - else - { - pqioutput(PQL_ALERT, pqipersongrpzone, "No Us! what are we!"); - exit(1); - } - - - // now we run through any certificates - // already made... and reactivate them. - std::list::iterator it; - std::list &clist = sr -> getCertList(); - for(it = clist.begin(); it != clist.end(); it++) - { - cert *c = (*it); - - c -> InUse(false); - c -> Listening(false); - c -> Connected(false); - - // make new - if (c -> Accepted()) - { - cert_accept(c); - } - } - - - // finally lets - - - // add in a tunneltest. - // register the packet creations. - //addService(new PQTStst()); - //registerTunnelType(PQI_TUNNEL_TST_TYPE, createPQTStst); - - -#ifdef PQI_USE_PROXY - addService(p3p); - registerTunnelType(PQI_TUNNEL_PROXY_TYPE, createPQTunnelProxy); - registerTunnelInitType(PQI_TUNNEL_PROXY_TYPE, createPQTunnelProxyInit); -#endif - - return; } + int pqipersongrp::tick() { /* could limit the ticking of listener / tunnels to 1/sec... @@ -192,9 +106,6 @@ int pqipersongrp::tick() { pqil -> tick(); } -#ifdef PQI_USE_PROXY - pqiudpl->tick(); -#endif int i = 0; if (tickServiceSend()) i = 1; @@ -206,166 +117,59 @@ int pqipersongrp::tick() return 1; } - int pqipersongrp::status() { if (pqil) { pqil -> status(); } -#ifdef PQI_USE_PROXY - //pqiudpl->status(); -#endif return pqihandler::status(); } - // control the connections. -int pqipersongrp::cert_accept(cert *a) +/* Initialise pqilistener */ +int pqipersongrp::init_listener() { - if (a -> InUse()) + /* extract our information from the p3ConnectMgr */ + if (initFlags & PQIPERSON_NO_LISTENER) { - pqioutput(PQL_DEBUG_BASIC, pqipersongrpzone, - "pqipersongrp::cert_accept() Cert in Use!"); - - return -1; - } - - { - std::ostringstream out; - out << "pqipersongrp::cert_accept() PeerId: " << a->PeerId(); - pqioutput(PQL_DEBUG_BASIC, pqipersongrpzone, out.str()); - } - - pqiperson *pqip = new pqiperson(a, a->PeerId()); - pqissl *pqis = new pqissl(a, pqil, pqip); - - /* construct the serialiser .... - * Needs: - * * FileItem - * * FileData - * * ServiceGeneric - */ - - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsFileItemSerialiser()); - rss->addSerialType(new RsCacheItemSerialiser()); - rss->addSerialType(new RsServiceSerialiser()); - - pqiconnect *pqisc = new pqiconnect(rss, pqis); - - pqip -> addChildInterface(pqisc); - -#ifdef PQI_USE_PROXY - pqiudpproxy *pqipxy = new pqiudpproxy(a, (p3udpproxy *) p3p, NULL); - pqissludp *pqius = new pqissludp(a, pqip, pqipxy); - pqiconnect *pqiusc = new pqiconnect(pqius); - - // add a ssl + proxy interface. - // Add Proxy First. - pqip -> addChildInterface(pqiusc); -#endif - - a -> InUse(true); - a -> Accepted(true); - - - // setup no behaviour. (no remote address) - - // attach to pqihandler - SearchModule *sm = new SearchModule(); - sm -> peerid = a->PeerId(); - sm -> pqi = pqip; - sm -> sp = secpolicy_create(); - - // reset it to start it working. - pqis -> reset(); - - - return AddSearchModule(sm); -} - -int pqipersongrp::cert_deny(cert *a) -{ - std::map::iterator it; - SearchModule *mod; - bool found = false; - - // if used find search module.... - if (a -> InUse()) - { - // find module. - for(it = mods.begin(); (!found) && (it != mods.end());it++) - { - mod = it -> second; - pqiperson *p = (pqiperson *) mod -> pqi; - if (a->PeerId() == p->PeerId()) - { - found = true; - } - } - if (found) - { - RemoveSearchModule(mod); - secpolicy_delete(mod -> sp); - pqiperson *p = (pqiperson *) mod -> pqi; - p -> reset(); - delete p; - a -> InUse(false); - } - } - a -> Accepted(false); - return 1; -} - -int pqipersongrp::cert_auto(cert *a, bool b) -{ - std::map::iterator it; - if (b) - { - cert_accept(a); - // find module. - for(it = mods.begin(); it != mods.end();it++) - { - SearchModule *mod = it -> second; - pqiperson *p = (pqiperson *) mod -> pqi; - if (a->PeerId() == p->PeerId()) - { - p -> autoconnect(b); - return 1; - } - } + pqil = NULL; } else { - a -> Manual(true); - cert_deny(a); + /* extract details from + */ + peerConnectState state; + mConnMgr->getOwnNetStatus(state); + + pqil = createListener(state.localaddr); } return 1; } - int pqipersongrp::restart_listener() { // stop it, // change the address. // restart. - cert *own = sslr -> getOwnCert(); if (pqil) { + peerConnectState state; + mConnMgr->getOwnNetStatus(state); + pqil -> resetlisten(); - pqil -> setListenAddr(own -> localaddr); + pqil -> setListenAddr(state.localaddr); pqil -> setuplisten(); } -#ifdef PQI_USE_PROXY - pqiudpl -> resetlisten(); - pqiudpl -> setListenAddr(own -> localaddr); - pqiudpl -> setuplisten(); -#endif return 1; } +int pqipersongrp::setConfig(p3GeneralConfig *cfg) +{ + config = cfg; +} + static const std::string pqih_ftr("PQIH_FTR"); int pqipersongrp::save_config() @@ -373,15 +177,21 @@ int pqipersongrp::save_config() char line[512]; sprintf(line, "%f %f %f %f", getMaxRate(true), getMaxRate(false), getMaxIndivRate(true), getMaxIndivRate(false)); - sslr -> setSetting(pqih_ftr, std::string(line)); + if (config) + { + config -> setSetting(pqih_ftr, std::string(line)); + } return 1; } - - int pqipersongrp::load_config() { - std::string line = sslr -> getSetting(pqih_ftr); + std::string line; + if (config) + { + line = config -> getSetting(pqih_ftr); + } + float mri, mro, miri, miro; if (4 == sscanf(line.c_str(), "%f %f %f %f", &mri, &mro, &miri, &miro)) @@ -406,3 +216,195 @@ int pqipersongrp::load_config() } +void pqipersongrp::statusChange(const std::list &plist) +{ + + /* iterate through, only worry about the friends */ + std::list::const_iterator it; + for(it = plist.begin(); it != plist.end(); it++) + { + if (it->state & RS_PEER_S_FRIEND) + { + /* now handle add/remove */ + if ((it->actions & RS_PEER_NEW) + || (it->actions & RS_PEER_MOVED)) + { + addPeer(it->id); + } + + if (it->actions & RS_PEER_CONNECT_REQ) + { + connectPeer(it->id); + } + } + else /* Not Friend */ + { + if (it->actions & RS_PEER_MOVED) + { + removePeer(it->id); + } + } + } +} + + + +int pqipersongrp::addPeer(std::string id) +{ + { + std::ostringstream out; + out << "pqipersongrp::addPeer() PeerId: " << id; + pqioutput(PQL_DEBUG_BASIC, pqipersongrpzone, out.str()); + } + + std::cerr << " pqipersongrp::addPeer() id: " << id; + std::cerr << std::endl; + + SearchModule *sm = NULL; + std::map::iterator it; + it = mods.find(id); + if (it != mods.end()) + { + pqioutput(PQL_DEBUG_BASIC, pqipersongrpzone, + "pqipersongrp::addPeer() Peer already in Use!"); + return -1; + } + + pqiperson *pqip = createPerson(id, pqil); + + // attach to pqihandler + sm = new SearchModule(); + sm -> peerid = id; + sm -> pqi = pqip; + sm -> sp = secpolicy_create(); + + // reset it to start it working. + pqip -> reset(); + + return AddSearchModule(sm); +} + + +int pqipersongrp::removePeer(std::string id) +{ + std::map::iterator it; + + std::cerr << " pqipersongrp::removePeer() id: " << id; + std::cerr << std::endl; + + it = mods.find(id); + if (it != mods.end()) + { + SearchModule *mod = it->second; + RemoveSearchModule(mod); + secpolicy_delete(mod -> sp); + pqiperson *p = (pqiperson *) mod -> pqi; + p -> reset(); + delete p; + mods.erase(it); + } + return 1; +} + +int pqipersongrp::connectPeer(std::string id) +{ + /* get status from p3connectMgr */ + std::cerr << " pqipersongrp::connectPeer() id: " << id << " does nothing yet! "; + std::cerr << std::endl; + + std::map::iterator it; + it = mods.find(id); + if (it == mods.end()) + { + return 0; + } + /* get the connect attempt details from the p3connmgr... */ + SearchModule *mod = it->second; + pqiperson *p = (pqiperson *) mod -> pqi; + + + /* get address from p3connmgr */ + if (!mConnMgr) + return 0; + + struct sockaddr_in addr; + uint32_t type; + + mConnMgr->connectAttempt(id, addr, type); + + uint32_t ptype; + if (type & RS_NET_CONN_TCP_ALL) + { + ptype = PQI_CONNECT_TCP; + } + else if (type & RS_NET_CONN_UDP_ALL) + { + ptype = PQI_CONNECT_UDP; + } + else + return 0; + + p->connect(ptype, addr); + + /* */ + return 1; +} + +bool pqipersongrp::notifyConnect(std::string id, bool success) +{ + if (mConnMgr) + mConnMgr->connectResult(id, success, 0); + + return (NULL != mConnMgr); +} + +/******************************** DUMMY Specific features ***************************/ + +#include "pqi/pqibin.h" + +pqilistener * pqipersongrpDummy::createListener(struct sockaddr_in laddr) +{ + pqilistener *listener = new pqilistener(); + return listener; +} + + +pqiperson * pqipersongrpDummy::createPerson(std::string id, pqilistener *listener) +{ + { + std::ostringstream out; + out << "pqipersongrpDummy::createPerson() PeerId: " << id; + pqioutput(PQL_DEBUG_BASIC, pqipersongrpzone, out.str()); + } + + pqiperson *pqip = new pqiperson(id, this); + + // TCP + NetBinDummy *d1 = new NetBinDummy(pqip, id, PQI_CONNECT_TCP); + + RsSerialiser *rss = new RsSerialiser(); + rss->addSerialType(new RsFileItemSerialiser()); + rss->addSerialType(new RsCacheItemSerialiser()); + rss->addSerialType(new RsServiceSerialiser()); + + pqiconnect *pqic = new pqiconnect(rss, d1); + + pqip -> addChildInterface(PQI_CONNECT_TCP, pqic); + + // UDP. + NetBinDummy *d2 = new NetBinDummy(pqip, id, PQI_CONNECT_UDP); + + RsSerialiser *rss2 = new RsSerialiser(); + rss2->addSerialType(new RsFileItemSerialiser()); + rss2->addSerialType(new RsCacheItemSerialiser()); + rss2->addSerialType(new RsServiceSerialiser()); + + pqiconnect *pqic2 = new pqiconnect(rss2, d2); + + pqip -> addChildInterface(PQI_CONNECT_UDP, pqic2); + + return pqip; +} + +/******************************** DUMMY Specific features ***************************/ + diff --git a/libretroshare/src/pqi/pqipersongrp.h b/libretroshare/src/pqi/pqipersongrp.h index a0d884998..9f3c577fc 100644 --- a/libretroshare/src/pqi/pqipersongrp.h +++ b/libretroshare/src/pqi/pqipersongrp.h @@ -1,9 +1,9 @@ /* - * "$Id: pqipersongrp.h,v 1.13 2007-02-18 21:46:49 rmf24 Exp $" + * libretroshare/src/pqi: pqipersongrp.h * * 3P/PQI network interface for RetroShare. * - * Copyright 2004-2006 by Robert Fernie. + * Copyright 2004-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 @@ -24,13 +24,15 @@ */ - #ifndef MRK_PQI_PERSON_HANDLER_HEADER #define MRK_PQI_PERSON_HANDLER_HEADER #include "pqi/pqihandler.h" #include "pqi/pqiperson.h" +#include "pqi/pqilistener.h" #include "pqi/pqiservice.h" +#include "pqi/pqimonitor.h" +#include "pqi/p3cfgmgr.h" // So this is a specific implementation @@ -40,61 +42,46 @@ // as an added bonus, we are going to // make this a pqitunnelserver, to which services can be attached. -#ifdef PQI_USE_PROXY - class p3proxy; - class pqiudplistener; -#endif - - -const unsigned long PQIPERSON_NO_SSLLISTENER = 0x0001; +const unsigned long PQIPERSON_NO_LISTENER = 0x0001; const unsigned long PQIPERSON_ALL_BW_LIMITED = 0x0010; -#ifdef PQI_USE_DISC - class p3disc; -#endif - -#ifdef PQI_USE_CHANNELS - class p3channel; -#endif - -class pqissllistener; - -class pqipersongrp: public pqihandler, public p3ServiceServer +class pqipersongrp: public pqihandler, public pqiMonitor, public p3ServiceServer { public: - pqipersongrp(SecurityPolicy *, sslroot *sr, unsigned long flags); - - // control the connections. -int cert_accept(cert *a); -int cert_deny(cert *a); -int cert_auto(cert *a, bool b); + pqipersongrp(SecurityPolicy *, unsigned long flags); + /*************************** Setup *************************/ + /* pqilistener */ +int init_listener(); int restart_listener(); +int setConfig(p3GeneralConfig *cfg); int save_config(); int load_config(); + /*************** pqiMonitor callback ***********************/ +virtual void statusChange(const std::list &plist); + + /******************* Peer Control **************************/ +virtual int addPeer(std::string id); /* can be overloaded for testing */ +int removePeer(std::string id); +int connectPeer(std::string id); + + /*** callback from children ****/ +bool notifyConnect(std::string id, bool success); + // tick interfaces. virtual int tick(); virtual int status(); - // + SearchInterface which should automatically handle stuff - - // acess to services. -#ifdef PQI_USE_DISC - p3disc *getP3Disc() { return p3d; } -#endif - -#ifdef PQI_USE_PROXY - p3proxy *getP3Proxy() { return p3p; } -#endif - -#ifdef PQI_USE_CHANNELS - p3channel *getP3Channel() { return p3c; } -#endif - protected: + + /********* FUNCTIONS to OVERLOAD for specialisation ********/ +virtual pqilistener *createListener(struct sockaddr_in laddr) = 0; +virtual pqiperson *createPerson(std::string id, pqilistener *listener) = 0; + /********* FUNCTIONS to OVERLOAD for specialisation ********/ + /* Overloaded RsItem Check * checks item->cid vs Person */ @@ -106,22 +93,25 @@ virtual int checkOutgoingRsItem(RsItem *item, int global) { return 1; } int tickServiceRecv(); int tickServiceSend(); - pqissllistener *pqil; - - sslroot *sslr; - -#ifdef PQI_USE_DISC - p3disc *p3d; -#endif - -#ifdef PQI_USE_PROXY - p3proxy *p3p; - pqiudplistener *pqiudpl; -#endif -#ifdef PQI_USE_CHANNELS - p3channel *p3c; -#endif + pqilistener *pqil; + p3GeneralConfig *config; unsigned long initFlags; }; +class pqipersongrpDummy: public pqipersongrp +{ + public: + pqipersongrpDummy(SecurityPolicy *pol, unsigned long flags) + :pqipersongrp(pol, flags) { return; } + + protected: + + /********* FUNCTIONS to OVERLOAD for specialisation ********/ +virtual pqilistener *createListener(struct sockaddr_in laddr); +virtual pqiperson *createPerson(std::string id, pqilistener *listener); + /********* FUNCTIONS to OVERLOAD for specialisation ********/ +}; + + + #endif // MRK_PQI_PERSON_HANDLER_HEADER diff --git a/libretroshare/src/pqi/pqiproxy.cc b/libretroshare/src/pqi/pqiproxy.cc deleted file mode 100644 index 25a63e160..000000000 --- a/libretroshare/src/pqi/pqiproxy.cc +++ /dev/null @@ -1,2337 +0,0 @@ -/* - * "$Id: pqiproxy.cc,v 1.10 2007-02-18 21:46:49 rmf24 Exp $" - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2004-2006 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 "pqi/pqiproxy.h" - -#include "pqi/pqipacket.h" -#include "pqi/pqitunnelproxy.h" - -#include "pqi/p3disc.h" - -#include -#include "pqi/pqidebug.h" - -const int pqiproxyzone = 1728; - - -static const unsigned long P3PROXY_CONNECT_TIMEOUT = 30; - -// PQTunnelService Overloading. -int p3proxy::receive(PQTunnel *in) -{ - { - std::ostringstream out; - out << "p3proxy::receive()"; - out << " Received PQTunnel Packet!" << std::endl; - in -> print(out); - pqioutput(PQL_DEBUG_ALL, pqiproxyzone, out.str()); - } - - PQTunnelProxy *pqtp = dynamic_cast(in); - if (pqtp == NULL) - { - delete in; - pqioutput(PQL_WARNING, pqiproxyzone, - "PQTunnel is Not a PQTunnelProxy Pkt...Deleting"); - return -1; - } - - - cert *from = (cert *) pqtp -> p; - - pqioutput(PQL_DEBUG_ALL,pqiproxyzone, "Finding Src"); - cert *src = findcert(pqtp -> src); - pqioutput(PQL_DEBUG_ALL,pqiproxyzone, "Finding Dest"); - cert *dest = findcert(pqtp -> dest); - - if (from != NULL) - { - std::ostringstream out; - out << "ProxyTunnel Pkt from: " << from -> Name() << std::endl; - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, out.str()); - } - - if (src != NULL) - { - std::ostringstream out; - out << "ProxyTunnel Pkt Src: " << src -> Name() << std::endl; - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, out.str()); - } - - if (dest != NULL) - { - std::ostringstream out; - out << "ProxyTunnel Pkt dest: " << dest -> Name() << std::endl; - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, out.str()); - } - - // if either is unknown... - if ((dest == NULL) || (src == NULL)) - { - // ignore/discard packet. - pqioutput(PQL_WARNING, pqiproxyzone, - "Unknown Source/Destination"); - delete pqtp; - return -1; - } - - // if they are in the wrong order. - // 1) dest == real source (we are proxy) - // 2) own = src (we are dest) - cert *own = sroot -> getOwnCert(); - if ((dest == (cert *) pqtp -> p) || (src == own)) - { - // swap them. - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "Swapping Dest/Src Order"); - cert *tmp = dest; - dest = src; - src = tmp; - } - - // check if we are a proxy - if (dest != own) - { - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "Packet Not Meant for us...."); - // forward onto the correct location. - // all we need to do is correct the cid, - // and filter.... - - if (isConnection(src, dest)) - { - std::ostringstream out; - out << "Proxy Packet Connection (" << src -> Name(); - out << " -> " << dest -> Name() << ") is Okay - Packet received" << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - - return receiveAsProxy(pqtp, src, dest); - } - - // delete packet... - { - pqioutput(PQL_WARNING, pqiproxyzone, - "No Connection/Packet Filtered -> deleting"); - delete pqtp; - return -1; - } - } - - // we are the destination. - - // search for it. - std::map::iterator it; - std::map::iterator pit; - - // first ensure that we have a connection. - if (connectionmap.end() == (it = connectionmap.find(src))) - { - pqioutput(PQL_WARNING, pqiproxyzone, - "Packet Reject Not Connected"); - // not connected.. reject. - delete pqtp; - return -1; - } - else - { - std::ostringstream out; - out << "Proxy Packet Over Connection (" << it->first->Name(); - out << " -> " << it -> second -> Name() << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - - if (proxymap.end() == (pit = proxymap.find(src))) - { - pqioutput(PQL_WARNING, pqiproxyzone, - "Packet Reject Not in ProxyMap"); - // no proxy. reject. - delete pqtp; - return -1; - } - else - { - std::ostringstream out; - out << "Proxy Found in ProxyMap"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - - if (it -> second != from) - { - std::ostringstream out; - out << "Packet Reject Mismatch Proxy : "; - out << it -> second -> Name() << " != "; - out << from -> Name(); - pqioutput(PQL_WARNING, pqiproxyzone, out.str()); - - // mismatch reject. - delete pqtp; - return -1; - } - - // done! - { - std::ostringstream out; - out << "Proxy Packet PASSES OK (" << src->Name(); - out << " -> " << from -> Name(); - out << " -> " << dest -> Name() << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - - return receiveAsDestination(pqtp, src, from, dest, pit -> second); -} - - -int p3proxy::receiveAsProxy(PQTunnelProxy *pqtp, cert *src, cert *dest) -{ - { - std::ostringstream out; - out << "p3proxy::receiveAsProxy()"; - out << " Received PQTunnel Packet!" << std::endl; - pqtp -> print(out); - pqioutput(PQL_DEBUG_ALL, pqiproxyzone, out.str()); - } - - if (isConnection(src, dest)) - { - std::ostringstream out; - out << "Proxy Packet Connection (" << src -> Name(); - out << " -> " << dest -> Name() << ") is Okay" << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - - if ((filter(pqtp))) - { - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "Packet Okay to Proxy, Sending Out"); - pqtp -> cid = dest -> cid; - // stick into the out queue. - outPkts.push_back(pqtp); - return 1; - } - else - { - pqioutput(PQL_WARNING, pqiproxyzone, - "Packet Fails Filter Test!"); - } - } - - // delete packet... - { - pqioutput(PQL_WARNING, pqiproxyzone, - "No Connection/Packet Filtered -> deleting"); - delete pqtp; - return -1; - } -} - - -int p3proxy::receiveAsDestination(PQTunnelProxy *pqtp, cert *src, cert *from, cert *dest, pqiproxy *pqip) -{ - { - std::ostringstream out; - out << "p3proxy::receiveAsDestination(" << src->Name(); - out << " -> " << from -> Name(); - out << " -> " << dest -> Name() << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - - // push_back to correct queue. - std::map >::iterator qit; - if (inqueue.end() == (qit = inqueue.find(pqip))) - { - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "p3proxy::receiveAsDestination() Packet Pushed Onto New Queue"); - // make a new list. - std::list nlist; - nlist.push_back(pqtp); - inqueue[pqip] = nlist; - return 1; - } - - // add to existing queue. - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "p3proxy::receiveAsDestination() Packet Pushed Onto Existing Queue"); - - (qit->second).push_back(pqtp); - return 1; -} - - -int p3proxy::receiveAsError(PQTunnelProxy* pqtp, cert *src, cert *from, cert *dest) -{ - { - std::ostringstream out; - out << "p3proxy::receiveAsError()"; - out << " Received Bad PQTunnel Packet!" << std::endl; - pqtp -> print(out); - pqioutput(PQL_ALERT, pqiproxyzone, out.str()); - delete pqtp; - } - return 1; -} - - -PQTunnel *p3proxy::send() -{ - pqioutput(PQL_DEBUG_ALL, pqiproxyzone, - "p3proxy::send()"); - - if (outPkts.size() < 1) - return NULL; - - PQTunnel *in = outPkts.front(); - outPkts.pop_front(); - - std::ostringstream out; - out << "Sending (1/" << outPkts.size() + 1 << "): " << std::endl; - in -> print(out); - pqioutput(PQL_DEBUG_ALL,pqiproxyzone,out.str()); - - return in; -} - -// decide if we let data through. -bool p3proxy::filter(PQTunnelProxy *in) -{ - pqioutput(PQL_WARNING,pqiproxyzone, - "p3proxy::filter() Not Implemented!"); - return true; -} - -int p3proxy::receive(PQTunnelInit *in) -{ - { - std::ostringstream out; - out << "p3proxy::receive()" << std::endl; - if (in == NULL) - { - out << "NULL Pkt!" << std::endl; - } - else - { - in -> print(out); - } - pqioutput(PQL_DEBUG_ALL,pqiproxyzone, out.str()); - } - - if (in == NULL) - return 1; - - // make sure it is a ProxyInit.... - PQTunnelProxyInit *pinit = NULL; - if (NULL == (pinit = dynamic_cast(in))) - { - // wrong type. - pqioutput(PQL_WARNING,pqiproxyzone, - "Not PQTunnelProxyInit Pkt Deleting"); - delete in; - return -1; - } - - cert *from = (cert *) pinit -> p; - - pqioutput(PQL_DEBUG_ALL,pqiproxyzone, "Finding Proxy"); - cert *proxy = findcert(pinit -> proxy); - pqioutput(PQL_DEBUG_ALL,pqiproxyzone, "Finding Src"); - cert *src = findcert(pinit -> src); - pqioutput(PQL_DEBUG_ALL,pqiproxyzone, "Finding Dest"); - cert *dest = findcert(pinit -> dest); - - if (from != NULL) - { - std::ostringstream out; - out << "ProxyInit Pkt from: " << from -> Name() << std::endl; - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, out.str()); - } - - if (src != NULL) - { - std::ostringstream out; - out << "ProxyInit Pkt Src: " << src -> Name() << std::endl; - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, out.str()); - } - - - if (proxy != NULL) - { - std::ostringstream out; - out << "ProxyInit Pkt proxy: " << proxy -> Name() << std::endl; - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, out.str()); - } - - - if (dest != NULL) - { - std::ostringstream out; - out << "ProxyInit Pkt dest: " << dest -> Name() << std::endl; - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, out.str()); - } - - if ((from == NULL) || (src == NULL) || - (proxy == NULL) || (dest == NULL)) - { - if (!from) - { - pqioutput(PQL_WARNING,pqiproxyzone, - "Sorry: from (IntRef) == NULL"); - } - - if (!src) - { - pqioutput(PQL_WARNING,pqiproxyzone, - "Sorry: src (SrcRef) == NULL"); - } - - if (!proxy) - { - pqioutput(PQL_WARNING,pqiproxyzone, - "Sorry: proxy (ProxyRef) == NULL"); - } - - if (!dest) - { - pqioutput(PQL_WARNING,pqiproxyzone, - "Sorry: dest (DestRef) == NULL"); - } - - pqioutput(PQL_WARNING,pqiproxyzone, - "deleting as: who are these people!"); - delete in; - return -1; - } - - // At this point we need to decide if we - // are the dest or the proxy. - cert *own = sroot -> getOwnCert(); - - // at this point we need to flip it around. - // if 1) we are end then: - if (src == own) - { - // we need to rotate dest/src, as we - // expect to be the destination, not source. - // so we flip them - src = dest; - dest = own; - } - // 2) if we are proxy... and it came from the destination. - else if (dest == from) - { - dest = src; - src = from; - } - - if (dest != own) - { - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "We are not the destination - so we should be proxy!"); - // this is meant for another..... - // we are the proxy. - if (proxy != own) - { - pqioutput(PQL_WARNING,pqiproxyzone, - "But we are not the specified Proxy! ERROR!"); - // error! - delete pinit; - return -1; - } - - // record connection possibility. - // pass on the packet if possible. - // if not return an endConnect. - - // check if we are connected to dest. - if (!dest -> Connected()) - { - pqioutput(PQL_WARNING,pqiproxyzone, - "We Are Not Connected to Destination: rtn End"); - // Return an end Connection, as we cannot connect!. - // just send back the same packet with mode changed. - pinit -> PQTunnelInit::mode = PQTunnelInit::End; - addOutInitPkt(pinit); - return 1; - } - - // we can pass it on. - // register as a potential connection. - PQTunnelProxyInit *pdup = pinit->clone(); - - // pass on the packet. - pinit -> cid = dest -> cid; - addOutInitPkt(pinit); - - // must pass before registration... - registerProxyConnection(src, proxy, dest, pdup); - - delete pdup; - - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "Proxy Pass-Through Not Completed"); - return 1; - } - - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "We are the End destination of the Proxy Pkt"); - - if (from != proxy) - { - // error this packet is not from - // the expected proxy.... kill. - pqioutput(PQL_WARNING,pqiproxyzone, - "But the Pkt Not from Proxy ERROR"); - delete pinit; - return -1; - } - - // if meant for us - // switch on the type. - // These Functions consume the packet, - switch(pinit -> PQTunnelInit::mode) - { - case PQTunnelInit::Request: - respondConnect(src, from, pinit); - break; - - case PQTunnelInit::Connect: - completeConnect(src, from, pinit); - break; - - case PQTunnelInit::End: - endConnect(src, from, pinit); - break; - default: - - pqioutput(PQL_WARNING,pqiproxyzone, - "Unknown Mode => defaulting to endConnect"); - endConnect(src, from, pinit); - break; - } - //delete pinit; - return 1; -} - -// Handling the Ones We can proxy. -int p3proxy::registerProxyConnection(cert *src, cert *proxy, - cert *dest, PQTunnelProxyInit *pinit) -{ - { - std::ostringstream out; - out << "p3proxy::registerProxyConnection() Checking Name() << ",P:" << proxy -> Name() << ">"; - out << ",D:" << dest -> Name() << ">"; - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, out.str()); - } - - cert *own = sroot -> getOwnCert(); - if (proxy != own) - { - // error..... - return -1; - } - - // get the reference. - std::map, int>::iterator cit1, cit2; - - std::pair ccdir(dest, src), ccrev(src, dest); - - cit1 = proxyconnect.find(ccdir); - cit2 = proxyconnect.find(ccrev); - - if (proxyconnect.end() != cit1) - { - std::ostringstream out; - out << "p3proxy::registerProxyConnection() Prev State(d,s):"; - out << cit1 -> second; - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, out.str()); - } - else - { - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "p3proxy::registerProxyConnection() No Prev (d,s) Pair"); - } - - if (proxyconnect.end() != cit2) - { - std::ostringstream out; - out << "p3proxy::registerProxyConnection() Prev State(s,d):"; - out << cit2 -> second; - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, out.str()); - } - else - { - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "p3proxy::registerProxyConnection() No Prev (s,d) Pair"); - } - - switch(pinit -> PQTunnelInit::mode) - { - case PQTunnelInit::Request: - // insert or override... the same. - proxyconnect[ccdir] = 1; - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "p3proxy::registerProxyConnection() Setting State -> 1"); - break; - - case PQTunnelInit::Connect: - if (cit1 != proxyconnect.end()) - { - if (cit1 -> second == 1) - { - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "p3proxy::registerProxyConnection() Switch 1 -> 2"); - - // advance - cit1 -> second = 2; - if (cit2 != proxyconnect.end()) - { - if (cit2 -> second == 2) - { - // complete! - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "p3proxy::registerProxyConnection() Connect Complete"); - /* call the function tp handle other goodies */ - connectionCompletedAsProxy(cit1->first.first, cit2->first.first); - - } - else - { - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "p3proxy::registerProxyConnection() Rev Connect todo"); - } - } - else - { - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "p3proxy::registerProxyConnection() No Rev Conn"); - } - } - else - { - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "p3proxy::registerProxyConnection() Cannot Ad -> 2"); - } - } - else - { - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "p3proxy::registerProxyConnection() Unknown Connect!"); - - } - break; - - case PQTunnelInit::End: - default: - // remove all the items. - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "p3proxy::registerProxyConnection() End: Cleaning up"); - if (cit1 != proxyconnect.end()) - { - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "p3proxy::registerProxyConnection() End: Removing Cit1"); - proxyconnect.erase(cit1); - } - if (proxyconnect.end() != (cit2 = proxyconnect.find(ccrev))) - { - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "p3proxy::registerProxyConnection() End: Removing Cit2"); - proxyconnect.erase(cit2); - } - break; - } - - return 1; - -} - -int p3proxy::isConnection(cert *src, cert *dest) -{ - if ((src == NULL) || (dest == NULL)) - { - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "p3proxy::isConnection() ERROR: NULL dest/src"); - return -1; - } - - { - std::ostringstream out; - out << "p3proxy::isConnection() Checking <"; - out << dest -> Name() << "," << src -> Name() << ">"; - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, out.str()); - } - - // get the reference. - std::map, int>::iterator cit1, cit2; - - std::pair ccdir(dest, src), ccrev(src, dest); - - cit1 = proxyconnect.find(ccdir); - cit2 = proxyconnect.find(ccrev); - if (proxyconnect.end() != cit1) - { - std::ostringstream out; - out << "p3proxy::isConnection() State(d,s):" << cit1 -> second; - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, out.str()); - } - else - { - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "p3proxy::isConnection() Unknown (d,s) Pair"); - } - - if (proxyconnect.end() != cit2) - { - std::ostringstream out; - out << "p3proxy::isConnection() State(s,d):" << cit2 -> second; - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, out.str()); - } - else - { - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "p3proxy::isConnection() Unknown (s,d) Pair"); - } - - - if ((proxyconnect.end() == cit1) || (proxyconnect.end() == cit2)) - { - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "p3proxy::isConnection() Unable to find pc pairs: return -1"); - // connection not established! - return -1; - } - - if ((cit1 -> second == 2) && (cit2 -> second == 2)) - { - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "p3proxy::isConnection() Connection Okay!"); - // connection complete. - return 1; - } - - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "p3proxy::isConnection() Incomplete Connection State!"); - return -1; -} - - - -int p3proxy::respondConnect(cert *other, cert *proxy, PQTunnelProxyInit *in) -{ - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "p3proxy::respondConnect()"); - // a couple of cases - // 1) random init from some other person - // wanting to create a proxyconnection. - // -check listening queue. - // 2) return init from someone. - // -check init queue. - - std::list::iterator lit; - std::map::iterator it, iit, rit, cit; - - iit = initmap.find(other); - rit = replymap.find(other); - cit = connectionmap.find(other); - lit = std::find(listenqueue.begin(), listenqueue.end(), other); - - if ((cit != connectionmap.end()) || (rit != replymap.end())) - { - // error, shouldn't receive this packet - // if in these maps. - // - // close connection / and return endConnect. - - in -> PQTunnelInit::mode = PQTunnelInit::End; - addOutInitPkt(in); - - // clean up. - if (iit != initmap.end()) - initmap.erase(iit); - if (rit != replymap.end()) - replymap.erase(rit); - if (cit != connectionmap.end()) - connectionmap.erase(cit); - - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "p3proxy::respondConnect() Bad State: in connect or reply state"); - - return -1; - } - - // if not in initmap, and we are listening for it. - // send out own init. - if ((iit == initmap.end()) && (lit != listenqueue.end())) - { - // have found a listen item. (with no current attempt) - // send reply - - PQTunnelProxyInit *pi = createProxyInit(other, proxy); - - { - std::ostringstream out; - out << "Generated Proxy Init:" << std::endl; - pi -> print(out); - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - - addOutInitPkt(pi); - - // addtotheInit list... as we are now in that state! - // should save the packet with the challenges. - initmap[other] = proxy; - passivemap[other] = true; - } - else - { - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "p3proxy::respondConnect() No Need to Send InitPkt!"); - } - - - // Find it again..... - if (initmap.end() == (it = initmap.find(other))) - { - // Not here... failed. - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "Error Not in InitMap/ListenQueue - Returning End."); - - in -> PQTunnelInit::mode = PQTunnelInit::End; - addOutInitPkt(in); - return -1; - } - else - { - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "Found It in InitMap!"); - } - - if (it -> second != proxy) - { - // Init for the wrong one, what should happen. - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "Error Init For the wrong one! - Returning End"); - in -> PQTunnelInit::mode = PQTunnelInit::End; - addOutInitPkt(in); - return -1; - } - else - { - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "Proxy Matches!"); - } - - - - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "Sending PQTunnelProxyInitConnect unfinished!"); - - in -> PQTunnelInit::mode = PQTunnelInit::Connect; - addOutInitPkt(in); - - // remove from initmap. - initmap.erase(it); - // add to replymap. - replymap[other] = proxy; - - return 1; -} - - -int p3proxy::completeConnect(cert *other, cert *proxy, PQTunnelProxyInit *in) -{ - { - std::ostringstream out; - out << "p3proxy::completeConnect()"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - - std::map::iterator iit, rit, cit; - - // check maps. - iit = initmap.find(other); - rit = replymap.find(other); - cit = connectionmap.find(other); - - // if not in the replymap ... error.... - if (replymap.end() == rit) - { - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "Not expecting Reply Pkt - Sending End"); - // Send Error. - - in -> PQTunnelInit::mode = PQTunnelInit::End; - addOutInitPkt(in); - - return -1; - } - - if (proxy != rit -> second) - { - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "Expect Reply from different Proxy - Sending End"); - // Send Error. - - in -> PQTunnelInit::mode = PQTunnelInit::End; - addOutInitPkt(in); - - return -1; - } - - // if in any other maps... error. - if ((iit != initmap.end()) || (cit != connectionmap.end())) - { - std::ostringstream out; - - out << "Found Target in other list! - Sending End"; - out << std::endl; - - if (iit != initmap.end()) - { - out << "Target in InitMap!" << std::endl; - initmap.erase(iit); - } - if (rit != replymap.end()) - { - out << "Target in ReplyMap (expected)!" << std::endl; - replymap.erase(rit); - } - if (cit != connectionmap.end()) - { - connectionmap.erase(cit); - out << "Target in ConnectionMap!" << std::endl; - } - - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone,out.str()); - - in -> PQTunnelInit::mode = PQTunnelInit::End; - addOutInitPkt(in); - - return -1; - } - - // remove cos the attempt has either failed or succeeded. - replymap.erase(rit); - - std::map::iterator pit; - if(proxymap.end() == (pit = proxymap.find(other))) - { - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "Couldn't Find PqiProxy"); - // Error. - return -1; - } - - // At this point we should check the correctness - // of the response to the challenge... - - // if okay, save -> and we are connected. - connectionmap[other] = proxy; - - // tell the pqiproxy that it can send. - - /* call the virtual fn */ - connectionCompletedAsPeer(proxy, other); - /* notify the pqiproxy */ - (pit -> second) -> connected(passivemap[other]); - - - { - std::ostringstream out; - out << "Proxy Connection Complete!" << std::endl; - out << "Destination: " << other -> Name() << std::endl; - out << "Proxy: " << proxy -> Name() << std::endl; - - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone,out.str()); - } - - // at this point we can remove it from the listenqueue. - std::list::iterator lit; - if (listenqueue.end() != (lit = std::find(listenqueue.begin(), - listenqueue.end(), other))) - { - listenqueue.erase(lit); - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "Removing Cert from listenqueue"); - } - - - // and from the connectqueue. - if (connectqueue.end() != (lit = std::find(connectqueue.begin(), - connectqueue.end(), other))) - { - connectqueue.erase(lit); - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "Removing Cert from connectqueue"); - } - - // also clear lastproxymap - std::map::iterator lpit; - lpit = lastproxymap.find(other); - if (lpit != lastproxymap.end()) - { - lastproxymap.erase(lpit); - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "Cleared Last Proxy Map"); - } - - std::map::iterator ctit; - ctit = connecttimemap.find(other); - if (ctit != connecttimemap.end()) - { - connecttimemap.erase(ctit); - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "Cleared Connect Time Map"); - } - // clean up if we make here. - delete in; - return 1; -} - -int p3proxy::endConnect(cert *other, cert *proxy, PQTunnelProxyInit *in) -{ - { - std::ostringstream out; - out << "p3proxy::endConnect()"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - - // if we get this..... delete all references - // but only ones that exactly match both the other and the proxy. - - - // This can be sent at any point, - // we need to check all the queues. - std::map::iterator it; - if ((connectionmap.end() != (it = connectionmap.find(other))) - && (it -> second == proxy)) - { - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "End Matches an Active Connection: Ending"); - connectionmap.erase(it); - // if here - we must tell it to disconnect. - std::map::iterator it2; - if (proxymap.end() != (it2 = proxymap.find(other))) - { - (it2 -> second) -> disconnected(); - } - } - - // clean up initmap. - if ((initmap.end() != (it = initmap.find(other))) - && (it -> second == proxy)) - { - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "End Matches an InitMap item: Erasing"); - initmap.erase(it); - } - - // clean up replymap. - if ((replymap.end() != (it = replymap.find(other))) - && (it -> second == proxy)) - { - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "End Matches an ReplyMap item: Erasing"); - replymap.erase(it); - } - - // clean up the packet. - delete in; - return 1; -} - - -PQTunnelInit *p3proxy::sendInit() -{ - { - std::ostringstream out; - out << "p3proxy::sendInit(" << outInitPkts.size() << ")"; - pqioutput(PQL_DEBUG_ALL, pqiproxyzone, out.str()); - } - if (outInitPkts.size() < 1) - return NULL; - - PQTunnelInit *in = outInitPkts.front(); - outInitPkts.pop_front(); - { - std::ostringstream out; - out << "p3proxy::sendInit Sending:"; - in -> print(out); - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - return in; -} - -/* to end a proxy connection - * this sends the packet, and can be called at any time - * as it doesn't check any queues.... - * - * This is used in a ::reset() of an active connection, - * but could be used at any point the connection needs to be ended. - */ - -int p3proxy::sendEndProxyConnectionPkt(cert *other, cert *proxy) -{ - PQTunnelProxyInit *pi = createProxyInit(other, proxy); - if (!pi) - { - std::ostringstream out; - out << "p3proxy::endProxyConnection()"; - out << " Cannot create Init(END) pkt"; - pqioutput(PQL_ALERT, pqiproxyzone, out.str()); - return -1; - } - - pi -> PQTunnelInit::mode = PQTunnelInit::End; - - { - std::ostringstream out; - out << "Ending Proxy Connection(us -> "; - out << proxy->Name() << " -> "; - out << other->Name() << std::endl; - - out << "Generated ProxyInit(END):" << std::endl; - pi -> print(out); - pqioutput(PQL_ALERT, pqiproxyzone, out.str()); - } - - addOutInitPkt(pi); - return 1; -} - - // interface to pqiproxy. -int p3proxy::attach(pqiproxy *p, cert *c) -{ - { - std::ostringstream out; - out << "p3proxy::attach()"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - proxymap[c] = p; - return 1; -} - -int p3proxy::detach(pqiproxy *p, cert *c) -{ - { - std::ostringstream out; - out << "p3proxy::detach()"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - // remove this proxy from all references. - // and send a disconnect to any current connections. - std::map::iterator it; - if (proxymap.end() == (it = proxymap.find(c))) - { - return -1; - } - - // remove from init/reply/connect queues. - reset(p,c); - - // stoplistening. - stoplistening(p,c); - - // remove from connect queue. - stopconnecting(p,c); - - proxymap.erase(it); - return 1; -} - -int p3proxy::connectattempt(pqiproxy *p, cert *c) -{ - { - std::ostringstream out; - out << "p3proxy::connectattempt(pqiproxy *p,c)"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - std::list::iterator it; - if (connectqueue.end() == (it = - std::find(connectqueue.begin(), connectqueue.end(), c))) - { - std::ostringstream out; - out << "p3proxy::connectattempt() added " << c -> Name(); - out << " to the connection queue"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - - connectqueue.push_back(c); - connecttimemap[c] = time(NULL); - } - - // also clear lastproxymap - std::map::iterator lpit; - lpit = lastproxymap.find(c); - if (lpit != lastproxymap.end()) - { - lastproxymap.erase(lpit); - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "p3proxy::connectattempt(p,c) Cleared Last Proxy Map"); - } - - return 1; -} - -int p3proxy::listen(pqiproxy *p, cert *c) -{ - { - std::ostringstream out; - out << "p3proxy::listen()"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - std::map::iterator it; - if (proxymap.end() == (it = proxymap.find(c))) - { - std::ostringstream out; - out << "p3proxy::listen() Error cert: " << c->Name() << " not in ProxyMap"; - pqioutput(PQL_ALERT, pqiproxyzone, out.str()); - return -1; - } - if (it -> second != p) - { - std::ostringstream out; - out << "p3proxy::listen() Error for cert: " << c->Name() << " PqiProxy don't match"; - pqioutput(PQL_ALERT, pqiproxyzone, out.str()); - return -1; - } - - /* check it's not there already. */ - std::list::iterator lit; - lit = std::find(listenqueue.begin(), listenqueue.end(), c); - if (lit == listenqueue.end()) - { - listenqueue.push_back(c); - } - else - { - std::ostringstream out; - out << "p3proxy::listen() Error cert: " << c->Name() << " already in listenqueue"; - pqioutput(PQL_ALERT, pqiproxyzone, out.str()); - } - - return 1; -} - -int p3proxy::stoplistening(pqiproxy *p, cert *c) -{ - std::list::iterator it; - it = std::find(listenqueue.begin(), listenqueue.end(), c); - if (it == listenqueue.end()) - { - std::ostringstream out; - out << "p3proxy::stoplistening() pqiproxy not found"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - return -1; - } - - // remove from the listen queue, - listenqueue.erase(it); - { - std::ostringstream out; - out << "p3proxy::stoplistening() pqiproxy removed from queue"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - return 1; -} - - -int p3proxy::stopconnecting(pqiproxy *p, cert *c) -{ - std::list::iterator it; - it = std::find(connectqueue.begin(), connectqueue.end(), c); - if (it == connectqueue.end()) - { - std::ostringstream out; - out << "p3proxy::stopconnecting() pqiproxy not found"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - return -1; - } - - // remove from the listen queue, - connectqueue.erase(it); - - { - std::ostringstream out; - out << "p3proxy::stopconnecting() pqiproxy removed from queue"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - - // also clear lastproxymap - std::map::iterator lpit; - lpit = lastproxymap.find(c); - if (lpit != lastproxymap.end()) - { - lastproxymap.erase(lpit); - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "p3proxy::connectattempt(p,c) Cleared Last Proxy Map"); - } - - // and the connecttime map. - std::map::iterator tit; - tit = connecttimemap.find(c); - if (tit != connecttimemap.end()) - { - connecttimemap.erase(tit); - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "p3proxy::connectattempt(p,c) Cleared Connect Time Map"); - } - return 1; -} - - -int p3proxy::reset(pqiproxy *p, cert *c) -{ - { - std::ostringstream out; - out << "p3proxy::reset()"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - - - std::map::iterator pit; - std::map::iterator iit, rit, cit; - - // remove from all except the connect/listen queues. - // clean init/passive map - iit = initmap.find(c); - if (iit != initmap.end()) - { - initmap.erase(iit); - } - - pit = passivemap.find(c); - if (pit != passivemap.end()) - { - passivemap.erase(pit); - } - - // replymap? - rit = replymap.find(c); - if (rit != replymap.end()) - { - replymap.erase(rit); - } - - // connectionmap? - cit = connectionmap.find(c); - if (cit != connectionmap.end()) - { - // if it found in here... send a disconnect packet!. - sendEndProxyConnectionPkt(cit->first, cit->second); - - // remove the connection. - connectionmap.erase(cit); - } - - /* also clear the lastproxymap */ - iit = lastproxymap.find(c); - if (iit != lastproxymap.end()) - { - lastproxymap.erase(iit); - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "p3proxy::reset() Cleared Last Proxy Map"); - } - - // finally, remove any packets from the incoming queue. - std::map >::iterator qit; - if (inqueue.end() == (qit = inqueue.find(p))) - { - std::ostringstream out; - out << "p3proxy::reset() no inQueue"; - pqioutput(PQL_DEBUG_ALL, pqiproxyzone, out.str()); - } - else - { - while((qit -> second).size() > 0) - { - // add to existing queue. - PQTunnelProxy *pqtp = (qit -> second).front(); - (qit -> second).pop_front(); - delete pqtp; - } - } - - /* if the certificate is active and listening, put back into the listening queue */ - if ((c->Accepted()) && (c->WillListen()) && (c->Listening())) - { - std::ostringstream out; - out << "p3proxy::reset() Putting " << c -> Name() << " back onto Listening Queue"; - pqioutput(PQL_WARNING, pqiproxyzone, out.str()); - - listen(p,c); - } - else - { - std::ostringstream out; - out << "p3proxy::reset() " << c -> Name() << " Left off Listening Queue"; - pqioutput(PQL_WARNING, pqiproxyzone, out.str()); - } - - return 1; -} - - -int p3proxy::outgoingpkt(pqiproxy *p, cert *c, void *d, int size) -{ - { - std::ostringstream out; - out << "p3proxy::outgoingpkt() For: " << c -> Name(); - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - // find the correct address. - // -> check the connectionmap. - std::map::iterator it; - if (connectionmap.end() == (it = connectionmap.find(c))) - { - std::ostringstream out; - out << "p3proxy::outgoingpkt() Failed to Find Connection"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - return -1; - } - - // create pqitunnel packet - PQTunnelProxy *pqtp = createProxyPkt(c, it -> second, 000101010, (const char *) d, size); - if (pqtp == NULL) - { - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "Failed to Create PQTunnelProxy"); - } - - { - std::ostringstream out; - out << "p3proxy::outgoingpkt() Sending off Via: "; - out << it -> second -> Name(); - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - - // send it off. - outPkts.push_back(pqtp); - - // how much that we've packaged up! - return size; -} - - -int p3proxy::incomingpkt(pqiproxy *p, void *d, int maxsize) -{ - { - std::ostringstream out; - out << "p3proxy::incomingpkt()"; - pqioutput(PQL_DEBUG_ALL, pqiproxyzone, out.str()); - } - // check the incoming queue. - std::map >::iterator qit; - if (inqueue.end() == (qit = inqueue.find(p))) - { - std::ostringstream out; - out << "p3proxy::incomingpkt() Missing Queue"; - pqioutput(PQL_DEBUG_ALL, pqiproxyzone, out.str()); - return -1; - } - - if ((qit -> second).size() < 1) - { - std::ostringstream out; - out << "p3proxy::incomingpkt() Empty Queue"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - return -1; - } - - - // add to existing queue. - PQTunnelProxy *pqtp = (qit -> second).front(); - if (maxsize < pqtp -> size) - { - // not enough space. - - std::ostringstream out; - out << "p3proxy::incomingpkt() Not Enough Space"; - out << "to Decode to pqiproxy"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - return -1; - } - - (qit -> second).pop_front(); - - int size = pqtp -> size; - // copy out the tunneled stuff. - memcpy(d, pqtp -> data, size); - - std::ostringstream out; - out << "p3proxy::incomingpkt() Decoding to pqiproxy. ("; - out << size << " bytes) From Packet:" << std::endl; - out << "Ptr: " << (void *) pqtp << " DataPtr: "; - out << (void *) pqtp -> data << std::endl; - pqtp -> print(out); - - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - - // decode into pqiproxy space. - // Need to Remove Tunnel Headers. - - // XXX Should Check Signature Here. - - delete pqtp; - return size; -} - -int p3proxy::connectattempt() -{ - { - std::ostringstream out; - out << "p3proxy::connectattempt()"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - // get the list of potential connections. - std::list::iterator it; - - std::list::iterator itc; - std::list plist; - std::map::iterator lpit; - - unsigned long ct = time(NULL); - - // find the certificates, that are active. - for(it = connectqueue.begin(); it != connectqueue.end();) - { - // If not currently querying, - if ((initmap.end() == initmap.find(*it)) && - (replymap.end() == replymap.find(*it))) - { - /* find last proxy - if there is one */ - lpit = lastproxymap.find(*it); - cert *lastproxy = NULL; - if (lpit != lastproxymap.end()) - { - lastproxy = lpit->second; - } - - if (0 < nextconnectattempt(*it, lastproxy)) - { - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "Successful Proxy Connect Attempt"); - it++; - } - else - { - /* clear the lastproxymap - either way (so it restarts) */ - lpit = lastproxymap.find(*it); - if (lpit != lastproxymap.end()) - { - lastproxymap.erase(lpit); - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "Cleared Last Proxy Map"); - } - else - { - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "Nothing in Last Proxy Map"); - } - - // check the connecttime map - std::map::iterator tit; - tit = connecttimemap.find(*it); - if ((tit == connecttimemap.end()) || - (tit->second + P3PROXY_CONNECT_TIMEOUT < ct)) - { - // remove from lists... - - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "Failed Proxy Connect Attempt"); - // notify the pqiproxy that it didn't connect. - std::map::iterator pit; - if (proxymap.end() != (pit = proxymap.find(*it))) - { - // notify. - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "Notify pqiproxy of failure"); - pit -> second -> disconnected(); - } - else - { - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "ERROR - Unknown pqiproxy"); - } - // delete connect attempt. - it = connectqueue.erase(it); - - // delete the connecttimemap. - connecttimemap.erase(tit); - } - else - { - it++; - } - - } - - } - else - { - it++; - } - } - return 1; -} - -int p3proxy::nextconnectattempt(cert *other, cert *lastproxy) -{ - { - std::ostringstream out; - out << "p3proxy::nextconnectattempt() for " << other -> Name(); - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - // get the list of potential connections. - - // check that it is in the connect queue. - if (connectqueue.end() == - std::find(connectqueue.begin(), connectqueue.end(), other)) - { - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "Missing from ConnectQueue, Cannot Connect"); - return -1; - } - - std::list::iterator it; - std::list plist = p3d -> potentialproxy(other); - - if (plist.size() == 0) - { - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "No Potential Proxies - Failed Connection Attempt"); - return -1; - } - else - { - for(it = plist.begin(); it != plist.end(); it++) - { - std::ostringstream out; - out << "Potential Proxy: " << (*it) -> Name(); - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - } - - bool next = false; - it = plist.begin(); - - /* start at start */ - if (lastproxy == NULL) - { - next = true; - } - - for(; (it != plist.end()) && (!next); it++) - { - if ((*it) == lastproxy) - { - next = true; - } - } - - if (it == plist.end()) - { - std::ostringstream out; - out << "Run out of Potential Proxies! :" << plist.size() << " in total!"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - return -1; - } - - - { - std::ostringstream out; - out << "Connection Attempt to: " << (*it) -> Name(); - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "p3proxy::nextconnectattempt() Don't Build Correct Packets Yet!"); - - // it points to the next proxy. - // send a proxy init. - PQTunnelProxyInit *pi = createProxyInit(other, (*it)); - - { - std::ostringstream out; - out << "Generated Proxy Init:" << std::endl; - pi -> print(out); - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - - addOutInitPkt(pi); - - // should save the packet with the challenges. - initmap[other] = *it; - /* save the last proxy, so we can continue next time */ - lastproxymap[other] = *it; - passivemap[other] = false; - return 1; -} - -int p3proxy::addOutInitPkt(PQTunnelInit *pkt) -{ - { - std::ostringstream out; - out << "AddOutInitPkt(" << (void *) pkt << ")" << std::endl; - pkt -> print(out); - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - outInitPkts.push_back(pkt); - return 1; -} - - - -int p3proxy::tick() -{ - { - std::ostringstream out; - out << "p3proxy::tick()"; - pqioutput(PQL_DEBUG_ALL, pqiproxyzone, out.str()); - } - // check for incoming. - processincoming(); - - // handle any new connections. - connectattempt(); - - status(); - return 1; -} - -int p3proxy::status() -{ - std::ostringstream out; - out << "p3proxy::status()"; - out << std::endl; - - /* show all the details - * in all of these container classes - */ - - if (proxymap.size() > 0) - { - out << std::endl; - out << "p3proxy::status() proxymap entries:"; - out << std::endl; - } - std::map::iterator cpit; - for(cpit = proxymap.begin(); cpit != proxymap.end(); ++cpit) - { - out << "\t" << cpit->first->Name(); - out << std::endl; - } - - if (listenqueue.size() > 0) - { - out << std::endl; - out << "p3proxy::status() listenqueue entries:"; - out << std::endl; - } - std::list::iterator it; - for(it = listenqueue.begin(); it != listenqueue.end(); ++it) - { - out << "\t" << (*it)->Name(); - out << std::endl; - } - - if (connectqueue.size() > 0) - { - out << std::endl; - out << "p3proxy::status() connectqueue entries:"; - out << std::endl; - } - for(it = connectqueue.begin(); it != connectqueue.end(); ++it) - { - out << "\t" << (*it)->Name(); - out << std::endl; - } - if (connecttimemap.size() > 0) - { - out << std::endl; - out << "p3proxy::status() connecttimemap entries:"; - out << std::endl; - } - std::map::iterator ctit; - int ct = time(NULL); - for(ctit = connecttimemap.begin(); ctit != connecttimemap.end(); ++ctit) - { - out << "\t" << ctit->first->Name() << " : " << ct - ctit->second << " sec ago"; - out << std::endl; - } - - std::map::iterator ccit; - if (lastproxymap.size() > 0) - { - out << std::endl; - out << "p3proxy::status() lastproxymap entries:"; - out << std::endl; - } - for(ccit = lastproxymap.begin(); - ccit != lastproxymap.end(); ++ccit) - { - out << "us -> " << ccit->second->Name(); - out << " -> " << ccit->first->Name(); - out << std::endl; - } - - if (initmap.size() > 0) - { - out << std::endl; - out << "p3proxy::status() initmap entries:"; - out << std::endl; - } - for(ccit = initmap.begin(); ccit != initmap.end(); ++ccit) - { - out << "us -> " << ccit->second->Name(); - out << " -> " << ccit->first->Name(); - out << std::endl; - } - - if (replymap.size() > 0) - { - out << std::endl; - out << "p3proxy::status() replymap entries:"; - out << std::endl; - } - for(ccit = replymap.begin(); ccit != replymap.end(); ++ccit) - { - out << "us -> " << ccit->second->Name(); - out << " -> " << ccit->first->Name(); - out << std::endl; - } - - if (connectionmap.size() > 0) - { - out << std::endl; - out << "p3proxy::status() connectionmap entries:"; - out << std::endl; - } - for(ccit = connectionmap.begin(); - ccit != connectionmap.end(); ++ccit) - { - out << "us -> " << ccit->second->Name(); - out << " -> " << ccit->first->Name(); - out << std::endl; - } - - if (passivemap.size() > 0) - { - out << std::endl; - out << "p3proxy::status() passivemap entries:"; - out << std::endl; - } - std::map::iterator pmit; - for(pmit = passivemap.begin(); pmit != passivemap.end(); ++pmit) - { - out << pmit->first->Name(); - out << " -> " << (void *) ccit->second; - out << std::endl; - } - - if (proxyconnect.size() > 0) - { - out << std::endl; - out << "p3proxy::status() proxyconnect entries:"; - out << std::endl; - } - std::map, int>::iterator pit; - for(pit = proxyconnect.begin(); pit != proxyconnect.end(); ++pit) - { - out << "pair< " << pit->first.first->Name(); - out << ", " << pit->first.second->Name(); - out << "> -> " << pit->second; - out << std::endl; - } - - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - - return 1; -} - - -int p3proxy::processincoming() -{ - { - std::ostringstream out; - out << "p3proxy::processincoming()"; - pqioutput(PQL_DEBUG_ALL, pqiproxyzone, out.str()); - } - // read packets. - // run the through the filters. - // - // catch any control packets. - // send notification. - // - // pack packets in correct queue. - return 1; -} - -int p3proxy::sendProxyInit(cert *c) -{ - { - std::ostringstream out; - out << "p3proxy::sendProxyInit()"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - // create a proxyInit packet. - // send it off. - return 1; -} - -/************************ PQI PROXY *************************/ - -pqipeerproxy::pqipeerproxy(cert *c, p3proxy *l, PQInterface *parent) - :pqiproxy(c, l), NetBinInterface(parent, c), active(false) -{ - { - std::ostringstream out; - out << "pqipeerproxy::pqipeerproxy()"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - - // register a potential proxy connection. - p3p -> attach(this, c); - - // create a temp pkt. - maxpktlen = pqipkt_maxsize(); - pkt = (void *) malloc(maxpktlen); - pktlen = pktn = 0; - - return; -} - -pqipeerproxy::~pqipeerproxy() -{ - { - std::ostringstream out; - out << "pqipeerproxy::~pqipeerproxy()"; - pqioutput(PQL_ALERT, pqiproxyzone, out.str()); - } - // remove references to us. - p3p -> detach(this, sslcert); - if (pkt) - free(pkt); - return; -} - - // pqiconnect Interface. -int pqipeerproxy::connectattempt() -{ - { - std::ostringstream out; - out << "pqipeerproxy::connectattempt()"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - - p3p -> connectattempt(this, sslcert); - - return 1; -} - -int pqipeerproxy::connected(bool cMode) -{ - { - std::ostringstream out; - out << "pqipeerproxy::connected()"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - active = true; - connect_mode = cMode; - if (parent()) - { - parent() -> notifyEvent(this, CONNECT_SUCCESS); - } - return 1; -} - - -int pqipeerproxy::listen() -{ - { - std::ostringstream out; - out << "pqipeerproxy::listen()"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - return p3p -> listen(this, sslcert); -} - -int pqipeerproxy::stoplistening() -{ - { - std::ostringstream out; - out << "pqipeerproxy::stoplistening()"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - return p3p -> stoplistening(this, sslcert); -} - -int pqipeerproxy::reset() -{ - { - std::ostringstream out; - out << "pqipeerproxy::reset()"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - p3p -> reset(this, sslcert); - /* also flag as inactive */ - active = false; - return 1; -} - -int pqipeerproxy::disconnected() -{ - { - std::ostringstream out; - out << "pqipeerproxy::disconnected()"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - active = false; - if (parent()) - { - parent() -> notifyEvent(this, CONNECT_FAILED); - } - return 1; -} - -// called when?? -int pqipeerproxy::disconnect() -{ - { - std::ostringstream out; - out << "pqipeerproxy::disconnect()"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - disconnected(); - return 1; -} - - - - // Overloaded from PQInterface -int pqipeerproxy::status() -{ - { - std::ostringstream out; - out << "pqipeerproxy::status()"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - return 1; -} - -int pqipeerproxy::tick() -{ - { - std::ostringstream out; - out << "pqipeerproxy::tick()"; - pqioutput(PQL_DEBUG_ALL, pqiproxyzone, out.str()); - } - //pqistreamer::tick(); - //more to do??? - - return 1; -} - -cert * pqipeerproxy::getContact() -{ - { - std::ostringstream out; - out << "pqipeerproxy::getContact()"; - pqioutput(PQL_DEBUG_ALL, pqiproxyzone, out.str()); - } - return sslcert; -} - - -// overloaded from pqistreamer..... -int pqipeerproxy::senddata(void *d, int n) -{ - { - std::ostringstream out; - out << "pqipeerproxy::senddata(" << d << "," << n << ")"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - return p3p -> outgoingpkt(this, sslcert, d, n); -} - -int pqipeerproxy::readdata(void* d, int n) -{ - { - std::ostringstream out; - out << "pqipeerproxy::readdata(" << d << "," << n << ")"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - - if (pktlen == 0) - { - if (!moretoread()) - { - std::ostringstream out; - out << "pqipeerproxy::readdata -> Nothing There"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - - return 0; - } - } - - std::ostringstream out; - out << "pqipeerproxy::readdata -> Data Used (" << pktn << "/"; - out << pktlen << ")" << std::endl; - - int size = pktlen - pktn; - if (size > n) - size = n; - - char *start = (char *) pkt; - start += pktn; - - memcpy(d, start, size); - - out << "pqipeerproxy::readdata -> Allowing "; - out << size << " bytes out" << std::endl; - - pktn += size; - if (pktn == pktlen) - { - // flag empty packet. - pktn = pktlen = 0; - out << "pqipeerproxy::readdata -> Finished the Packet!"; - } - - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - - return size; -} - -int pqipeerproxy::netstatus() -{ - { - std::ostringstream out; - out << "pqipeerproxy::netstatus() => Always True"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - return 1; -} - -int pqipeerproxy::isactive() -{ - { - std::ostringstream out; - out << "pqipeerproxy::isactive() => "; - - if (active) out << "True"; - else out << "False"; - - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - return active; -} - -bool pqipeerproxy::moretoread() -{ - { - std::ostringstream out; - out << "pqipeerproxy::moretoread()"; - pqioutput(PQL_DEBUG_ALL, pqiproxyzone, out.str()); - } - // if haven't finished the current packet, - // return true. - if ((pkt != NULL) && (pktlen != 0) && (pktn < pktlen)) - { - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, - "More to Read"); - return true; - } - - // else packet is empty. - int size = 0; - if (0 < (size = p3p -> incomingpkt(this, pkt, maxpktlen))) - { - // we've got some more. - std::stringstream out; - out << "pqipeerproxy::moretoread()"; - out << "Got Another Packet (" << size << " bytes)"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - - pktlen = size; - pktn = 0; - return true; - } - - pqioutput(PQL_DEBUG_ALL, pqiproxyzone, - "Nothing to Read"); - return false; -} - -bool pqipeerproxy::cansend() -{ - // cansend.... hard to catch - // if the data's being cached on the way... - // most likely to be locally. - - { - std::ostringstream out; - out << "pqipeerproxy::cansend Always returns 1"; - pqioutput(PQL_DEBUG_ALL, pqiproxyzone, out.str()); - } - - return 1; -} - - - // The interface to p3proxy. -int pqipeerproxy::notifyEvent(int type) -{ - { - std::ostringstream out; - out << "pqipeerproxy::notifyEvent(" << type << ")"; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - - switch(type) - { - case CONNECT_RECEIVED: - case CONNECT_SUCCESS: - active = true; - break; - - case CONNECT_FAILED: - default: - active = false; - break; - } - - // notify the parent. - if (parent()) - { - parent() -> notifyEvent(this, type); - } - return 1; -} - - -/********************** CERT SIGNS *************************/ - -cert *p3proxy::findcert(certsign &cs) -{ - pqioutput(PQL_DEBUG_BASIC,pqiproxyzone, - "p3proxy::findcert()"); - - cert *c = sroot -> findcertsign(cs); - return c; -} - -PQTunnelProxyInit *p3proxy::createProxyInit(cert *dest, cert *proxy) -{ - PQTunnelProxyInit *pi = new PQTunnelProxyInit(); - - { - std::ostringstream out; - out << "p3proxy::createProxyInit()" << std::endl; - out << "Dest: " << dest -> Name() << std::endl; - out << "Proxy: " << proxy -> Name() << std::endl; - out << "Src: " << (sroot -> getOwnCert()) -> Name(); - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - - - // Fill In certificates - if ((!sroot -> getcertsign(dest, pi -> dest)) || - (!sroot -> getcertsign(proxy, pi -> proxy)) || - (!sroot -> getcertsign(sroot -> getOwnCert(), pi -> src))) - { - delete pi; - return NULL; - } - - // fill in the challenge. - // with randoms; - int i; - for(i = 0; i < PQI_PROXY_CHALLENGE_SIZE; i++) - { - pi -> challenge[i] = (unsigned char) - (256.0*rand()/(RAND_MAX+1.0)); - } - - // ProxyInit Details. - cert *o = sroot -> getOwnCert(); - pi -> cid = proxy -> cid; // destination. - pi -> p = o; // from us. - - // Sign it..... XXX to do. - - - return pi; -} - - -PQTunnelProxy *p3proxy::createProxyPkt(cert *dest, cert *proxy, long nextseq, - const char *data, int size) -{ - PQTunnelProxy *pi = new PQTunnelProxy(); - cert *o = sroot -> getOwnCert(); - - { - std::ostringstream out; - out << "p3proxy::createProxyPkt()" << std::endl; - out << "Dest: " << dest -> Name() << std::endl; - out << "Proxy: " << proxy -> Name() << std::endl; - out << "Src: " << o -> Name() << std::endl; - out << "Seq: " << nextseq << std::endl; - out << "Data: " << (void *) data << std::endl; - out << "Size: " << size << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - } - - // Fill in Details.... - // PQItem - if ((!sroot -> getcertsign(dest, pi -> dest)) || - (!sroot -> getcertsign(o, pi -> src))) - { - std::ostringstream out; - out << "p3proxy::createProxyPkt()"; - out << " Error: Failed to Get Signatures..."; - pqioutput(PQL_DEBUG_BASIC, pqiproxyzone, out.str()); - - delete pi; - return NULL; - } - - // initialise packets. - pi -> sid = 0; // doesn't matter. - pi -> cid = proxy -> cid; // destination. - pi -> p = o; // from us; - pi -> seq = nextseq; - - // ProxyInit Details. - pi -> data = malloc(size); - memcpy(pi -> data, data, size); - pi -> size = size; - - // Sign Packet. - - return pi; -} - diff --git a/libretroshare/src/pqi/pqiproxy.h b/libretroshare/src/pqi/pqiproxy.h deleted file mode 100644 index 4df4827d0..000000000 --- a/libretroshare/src/pqi/pqiproxy.h +++ /dev/null @@ -1,376 +0,0 @@ -/* - * "$Id: pqiproxy.h,v 1.7 2007-02-18 21:46:49 rmf24 Exp $" - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2004-2006 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - -#ifndef MRK_PQI_PROXY_HEADER -#define MRK_PQI_PROXY_HEADER - - -#include - - -#include -#include -#include - -#include "pqi/pqi.h" - -#include "pqi/pqiperson.h" -#include "pqi/pqitunnel.h" -#include "pqi/pqitunnelproxy.h" - -class cert; - -class pqiproxy; -class pqifilter; - -class p3disc; - -// PQItem derived classes. -class PQTunnelInit; -class PQTunnelProxyInit; - -class PQTunnel; -class PQTunnelProxy; - -/* - * #ifdef PQI_USE_XPGP - * #include "xpgpcert.h" - */ - -class p3proxy : public PQTunnelService -{ - public: - - p3proxy(p3disc *p) - :PQTunnelService(PQI_TUNNEL_PROXY_TYPE), p3d(p) - { - sroot = getSSLRoot(); - return; - } - -virtual ~p3proxy() { return; } - - // PQTunnelService Overloading. -virtual int receive(PQTunnel *); -virtual PQTunnel * send(); - -virtual int receive(PQTunnelInit *); -virtual PQTunnelInit * sendInit(); - - // interface to pqiproxy. -int attach(pqiproxy *p, cert *c); -int detach(pqiproxy *p, cert *c); - -int listen(pqiproxy *p, cert *c); -int stoplistening(pqiproxy *p, cert *c); -int stopconnecting(pqiproxy *p, cert *c); - -int reset(pqiproxy *p, cert *c); - -int outgoingpkt(pqiproxy *p, cert *, void *d, int size); -int incomingpkt(pqiproxy *p, void *d, int maxsize); - -// overloaded from many sources. -virtual int tick(); - -int status(); - -int connectattempt(pqiproxy*, cert*); -int connectattempt(); -int nextconnectattempt(cert *, cert *); - - protected: - - // Fn to translate the sig to a cert. -bool filter(PQTunnelProxy *in); - -cert *findcert(certsign &cs); - -PQTunnelProxyInit *createProxyInit(cert *dest, cert *proxy); -PQTunnelProxy *createProxyPkt(cert *dest, cert *proxy, long nextseq, - const char *data, int size); - - // Register Connections for which we are the Proxy. - // (only channels registered this way can send proxy packets) -int registerProxyConnection(cert *src, cert *proxy, - cert *dest, PQTunnelProxyInit *pinit); - // indicates if a proxy connection has been established. -int isConnection(cert *src, cert *dest); - - // Init Proxy Connections. -int respondConnect(cert *o, cert *p, PQTunnelProxyInit *in); -int completeConnect(cert *o, cert *p, PQTunnelProxyInit *in); -int endConnect(cert *o, cert *p, PQTunnelProxyInit *in); - - // process incoming. -virtual int processincoming(); - - // Overload to provide alternative behaviour. - // These fns are called from receive(PQTunnel *); -virtual int connectionCompletedAsProxy(cert *n1, cert *n2) { return 1; } -virtual int connectionCompletedAsPeer(cert *proxy, cert *peer) { return 1; } - - - // Overload to provide alternative behaviour. - // These fns are called from receive(PQTunnel *); -virtual int receiveAsProxy(PQTunnelProxy* pqtp, cert *src, cert *dest); -virtual int receiveAsDestination(PQTunnelProxy* pqtp, - cert *src, cert *from, cert *dest, pqiproxy *pqip); - -virtual int receiveAsError(PQTunnelProxy* pqtp, cert *src, cert *from, cert *dest); - - // Proxy Control functions. -int sendProxyInit(cert *c); - - // Fn to send -int sendEndProxyConnectionPkt(cert *other, cert *proxy); - - bool active; - - // the registered proxies. - // All of these maps are - // indexed by the destination, not the proxy. - // which is the second cert is some cases. - - std::map proxymap; - std::list listenqueue; // the ones to listen for. - std::list connectqueue; // the ones to attempt to connect. - std::map initmap; // ones we sent init, wait for init. - std::map replymap; // ones that need a auth reply. - std::map connectionmap; - std::map lastproxymap; - std::map connecttimemap; // timeout map. - std::map passivemap; // who inited connection. - - // double direction map. - //std::map outmap; - std::map > inqueue; - - // filters. (remove bad packets/cache data). - std::list filters; - - // Map of the connections we are proxy for. - std::map, int> proxyconnect; - - p3disc *p3d; // needed to find proxies. - sslroot *sroot; // for certificate references. - - // input fn for details. -int addOutInitPkt(PQTunnelInit *pkt); - - std::list outPkts; - std::list outInitPkts; - -}; - - - -// pqiconnect, derives from pqistreamer/PQInterface. -// -// this class needs to provide. -// 1) read/write data. -// 2) connect functions. - -// base interface for pqiproxy.... -class pqiproxy -{ -public: - pqiproxy(cert *c, p3proxy *l) - :sslcert(c), p3p(l) { return; } -virtual ~pqiproxy() { return; } - - // The interface to p3proxy. -virtual int notifyEvent(int type) = 0; - - // notification from p3proxy. -virtual int connected(bool active) = 0; -virtual int disconnected() = 0; - - protected: - cert *sslcert; - p3proxy *p3p; -}; - - - -/* use a common peer as a proxy, to pass messages - * between proxied peers. - */ - -class pqipeerproxy: public pqiproxy, public NetBinInterface -{ -public: - pqipeerproxy(cert *c, p3proxy *l, PQInterface *parent); -virtual ~pqipeerproxy(); - - // Net Interface. -virtual int connectattempt(); -virtual int listen(); -virtual int stoplistening(); -virtual int reset(); -virtual int disconnect(); - - // Overloaded from PQInterface -virtual int status(); -virtual int tick(); -virtual cert * getContact(); - - // Bin Interface. -virtual int senddata(void*, int); -virtual int readdata(void*, int); -virtual int netstatus(); -virtual int isactive(); -virtual bool moretoread(); -virtual bool cansend(); - - // The interface to p3proxy. -virtual int notifyEvent(int type); - - // notification from p3proxy. -virtual int connected(bool active); -virtual int disconnected(); - -protected: - - /* data */ - //p3proxy *p3p; - - bool active; - int connect_mode; - - void *pkt; - int maxpktlen; - int pktlen; - int pktn; - -}; - - -/* Documenting the virtual (proxy) pqi interface. - * - * This is used to create proxy interface - * for people behind firewalls. - * - * There are two options for such an - * interface. - * 1) Encrypted Tunneling - This has the - * the advantage/disadvantage that it - * allows multiple layers of proxying, - * and very private. - * - * 2) Open Proxying - This lets people - * see the data, and allows restriction to one - * layer. This option allow the proxier, - * to collect the files passing through. - * (benefit for allowing proxying). - * - * As this option will less impact on the - * persons bandwidth, and give them some - * benefit, it'll be implemented first. - * - * The data will be saved in a cache, - * with a first in, first out policy, - * - * maybe show a window of cached files, - * and allow the user to save any from - * a list. - * - * So to do this we need - * i) a cache system. - * ii) extra message types to indicate - * proxied files, and searches etc. - * iii) a proxy server, to handle proxy messages. - * - * actually, this class will need to - * - * a proxy interface in someway or another. - * - * - * P1 PROXY P2 - * requests a - * proxy interface. - * ---------> - * end attempt <----- IF Not - * Available. - * - * else ---------------> Check for proxy/person auth - * end attempt <------ cancel ------- If Not Auth. - * - * else, if allowed. - * build proxy server. - * Build proxy <------ setup ---------- send okay - * server connection. - * - * pqissl. - * -> proxy interface. - * Send() - * return proxymsg locally - * pulled by proxy server. - * - * ps -> send proxy msg - * to correct pqissl. - * ----------> popped out to - * the proxy server. - * if file cache. - * redirect ------> recieved by pqissl. - * pulled by proxy server. - * - * proxy server - * - * all proxied information is - * going to be signed/or encrypted. - * - * very simple - that is the only - * necessary change. - * - * proxy msg. - * --------------------- - * type : init - * end - * msg (signed) - * tunnelled (includes init of ssl.) - * dest cert signature: - * - * encryption/signature mode. - * - * signature len: - * signature: - * - * data len: - * data - * - * - * - * - * - * is this the right place to add it? - * or is pqistreamer the answer. - * - */ - -#endif - diff --git a/libretroshare/src/pqi/pqissl.cc b/libretroshare/src/pqi/pqissl.cc index dcaca61c5..ffcaa5c31 100644 --- a/libretroshare/src/pqi/pqissl.cc +++ b/libretroshare/src/pqi/pqissl.cc @@ -85,25 +85,30 @@ static const int PQISSL_SSL_CONNECT_TIMEOUT = 30; * */ -pqissl::pqissl(cert *c, pqissllistener *l, PQInterface *parent) - //:NetBinInterface(parent, c), +pqissl::pqissl(pqissllistener *l, PQInterface *parent) :NetBinInterface(parent, parent->PeerId()), waiting(WAITING_NOT), active(false), certvalid(false), sslmode(PQISSL_ACTIVE), ssl_connection(NULL), sockfd(-1), - sslcert(c), sslccr(NULL), pqil(l), // no init for remote_addr. + pqil(l), // no init for remote_addr. readpkt(NULL), pktlen(0), attempt_ts(0), net_attempt(0), net_failure(0), net_unreachable(0), sameLAN(false), n_read_zero(0) { - sslccr = getSSLRoot(); + /* set address to zero */ + remote_addr.sin_addr.s_addr = 0; + remote_addr.sin_port = 0; + remote_addr.sin_family = AF_INET; + + sslroot *sslccr = getSSLRoot(); { std::ostringstream out; out << "pqissl for PeerId: " << PeerId(); pqioutput(PQL_ALERT, pqisslzone, out.str()); } + cert *sslcert = sslccr->findPeerId(PeerId()); // check certificate /**************** PQI_USE_XPGP ******************/ @@ -140,10 +145,13 @@ pqissl::pqissl(cert *c, pqissllistener *l, PQInterface *parent) /********** Implementation of NetInterface *************************/ -int pqissl::connectattempt() +int pqissl::connect(struct sockaddr_in raddr) { // reset failures net_failure = 0; + remote_addr = raddr; + remote_addr.sin_family = AF_INET; + return ConnectAttempt(); } @@ -152,7 +160,7 @@ int pqissl::listen() { if (pqil) { - return pqil -> addlistenaddr(sslcert, this); + return pqil -> addlistenaddr(PeerId(), this); } return 0; } @@ -161,7 +169,7 @@ int pqissl::stoplistening() { if (pqil) { - pqil -> removeListenPort(sslcert); + pqil -> removeListenPort(PeerId()); } return 1; } @@ -185,7 +193,7 @@ int pqissl::reset() * */ - out << "pqissl::reset():" << sslcert -> Name() << std::endl; + out << "pqissl::reset():" << PeerId() << std::endl; out << "pqissl::reset() State Before Reset:" << std::endl; out << "\tActive: " << (int) active << std::endl; @@ -261,8 +269,12 @@ int pqissl::status() { int alg; + sslroot *sslccr = getSSLRoot(); + cert *sslcert = sslccr->findPeerId(PeerId()); + std::ostringstream out; out << "pqissl::status()"; + if (active) { out << " active: " << std::endl; @@ -335,30 +347,9 @@ int pqissl::ConnectAttempt() "pqissl::ConnectAttempt() STATE = Not Waiting, starting connection"); sslmode = PQISSL_ACTIVE; /* we're starting this one */ - return Request_Proxy_Connection(); + return Initiate_Connection(); break; - case WAITING_PROXY_CONNECT: - - pqioutput(PQL_DEBUG_BASIC, pqisslzone, - "pqissl::ConnectAttempt() STATE = Proxy Wait."); - - return Check_Proxy_Connection(); - - break; - case WAITING_LOCAL_ADDR: - - pqioutput(PQL_DEBUG_BASIC, pqisslzone, - "pqissl::ConnectAttempt() STATE = Waiting Local Addr"); - - return Determine_Local_Address(); - - case WAITING_REMOTE_ADDR: - - pqioutput(PQL_DEBUG_BASIC, pqisslzone, - "pqissl::ConnectAttempt() STATE = Waiting Remote Addr"); - - return Determine_Remote_Address(); case WAITING_SOCK_CONNECT: @@ -388,7 +379,7 @@ int pqissl::ConnectAttempt() pqioutput(PQL_DEBUG_BASIC, pqisslzone, "pqissl::ConnectAttempt() Failed - Retrying"); - return Reattempt_Connection(); + return Failed_Connection(); break; @@ -404,80 +395,6 @@ int pqissl::ConnectAttempt() return -1; } -/****************************** REQUEST LOCAL ADDR ************************** - * Start Transaction. - * - * Specifics: - * TCP / UDP - * TCP - null interface. - * UDP - Proxy Connection and Exchange of Stunned addresses. - * - * X509 / XPGP - Same. - * - */ -int pqissl::Request_Proxy_Connection() -{ - waiting = WAITING_REMOTE_ADDR; - return Determine_Remote_Address(); -} - -int pqissl::Check_Proxy_Connection() -{ - waiting = WAITING_REMOTE_ADDR; - return Determine_Remote_Address(); -} - -int pqissl::Request_Local_Address() -{ - waiting = WAITING_REMOTE_ADDR; - return Determine_Remote_Address(); -} - -int pqissl::Determine_Local_Address() -{ - waiting = WAITING_REMOTE_ADDR; - return Determine_Remote_Address(); - return -1; -} - -/****************************** DETERMINE ADDR ****************************** - * Determine the Remote Address. - * - * Specifics: - * TCP / UDP - * TCP - check for which interface to use. - * UDP - start proxy request.... - * - * X509 / XPGP - Same. - * - */ - -int pqissl::Determine_Remote_Address() -{ - struct sockaddr_in addr; - pqioutput(PQL_DEBUG_BASIC, pqisslzone, - "pqissl::Determine_Remote_Address() Finding Interface"); - if (0 < connectInterface(addr)) - { - remote_addr = addr; - remote_addr.sin_family = AF_INET; - // jump unneccessary state. - waiting = WAITING_REMOTE_ADDR; - return Initiate_Connection(); - } - // cannot connect!. - pqioutput(PQL_DEBUG_BASIC, pqisslzone, - "pqissl::Request_Remote_Address() No Avail Interfaces"); - - // This is one of only place that notifies of failure... - if (parent()) - { - parent() -> notifyEvent(this, NET_CONNECT_UNREACHABLE); - } - //waiting = WAITING_NOT; - return -1; -} - /****************************** FAILED ATTEMPT ****************************** * Determine the Remote Address. @@ -491,15 +408,18 @@ int pqissl::Determine_Remote_Address() * */ -int pqissl::Reattempt_Connection() +int pqissl::Failed_Connection() { pqioutput(PQL_DEBUG_BASIC, pqisslzone, - "pqissl::ConnectAttempt() Failed - Retrying"); - // flag last attempt as a failure. - net_failure |= net_attempt; + "pqissl::ConnectAttempt() Failed - Notifying"); + + if (parent()) + { + parent() -> notifyEvent(this, NET_CONNECT_UNREACHABLE); + } waiting = WAITING_NOT; - return Request_Proxy_Connection(); /* start of the chain */ + return 1; } /****************************** MAKE CONNECTION ***************************** @@ -522,7 +442,7 @@ int pqissl::Initiate_Connection() pqioutput(PQL_DEBUG_BASIC, pqisslzone, "pqissl::Initiate_Connection() Attempting Outgoing Connection...."); - if (waiting != WAITING_REMOTE_ADDR) + if (waiting != WAITING_NOT) { pqioutput(PQL_WARNING, pqisslzone, "pqissl::Initiate_Connection() Already Attempt in Progress!"); @@ -596,7 +516,7 @@ int pqissl::Initiate_Connection() { std::ostringstream out; out << "Connecting to "; - out << sslcert -> Name() << " via "; + out << PeerId() << " via "; out << inet_ntoa(addr.sin_addr); out << ":" << ntohs(addr.sin_port); pqioutput(PQL_DEBUG_BASIC, pqisslzone, out.str()); @@ -622,7 +542,7 @@ int pqissl::Initiate_Connection() } else if ((errno == ENETUNREACH) || (errno == ETIMEDOUT)) { - out << "ENETUNREACHABLE: cert" << sslcert -> Name(); + out << "ENETUNREACHABLE: cert" << PeerId(); pqioutput(PQL_WARNING, pqisslzone, out.str()); // Then send unreachable message. @@ -788,7 +708,7 @@ int pqissl::Basic_Connection_Complete() std::ostringstream out; out << "pqissl::Basic_Connection_Complete()"; out << "TCP Connection Complete: cert: "; - out << sslcert -> Name(); + out << PeerId(); out << " on osock: " << sockfd; pqioutput(PQL_WARNING, pqisslzone, out.str()); } @@ -799,7 +719,7 @@ int pqissl::Basic_Connection_Complete() std::ostringstream out; out << "pqissl::Basic_Connection_Complete()"; - out << "EINPROGRESS: cert" << sslcert -> Name(); + out << "EINPROGRESS: cert" << PeerId(); pqioutput(PQL_WARNING, pqisslzone, out.str()); return 0; @@ -809,7 +729,7 @@ int pqissl::Basic_Connection_Complete() std::ostringstream out; out << "pqissl::Basic_Connection_Complete()"; out << "ENETUNREACH/ETIMEDOUT: cert"; - out << sslcert -> Name(); + out << PeerId(); pqioutput(PQL_WARNING, pqisslzone, out.str()); // Then send unreachable message. @@ -828,7 +748,7 @@ int pqissl::Basic_Connection_Complete() std::ostringstream out; out << "pqissl::Basic_Connection_Complete()"; out << "EHOSTUNREACH/EHOSTDOWN: cert"; - out << sslcert -> Name(); + out << PeerId(); pqioutput(PQL_WARNING, pqisslzone, out.str()); // Then send unreachable message. @@ -844,7 +764,7 @@ int pqissl::Basic_Connection_Complete() std::ostringstream out; out << "pqissl::Basic_Connection_Complete()"; out << "ECONNREFUSED: cert"; - out << sslcert -> Name(); + out << PeerId(); pqioutput(PQL_WARNING, pqisslzone, out.str()); // Then send unreachable message. @@ -887,6 +807,9 @@ int pqissl::Initiate_SSL_Connection() return err; } + sslroot *sslccr = getSSLRoot(); + + pqioutput(PQL_DEBUG_BASIC, pqisslzone, "pqissl::Initiate_SSL_Connection() Basic Connection Okay"); @@ -1011,6 +934,8 @@ int pqissl::Extract_Failed_SSL_Certificate() pqioutput(PQL_DEBUG_BASIC, pqisslzone, "pqissl::Extract_Failed_SSL_Certificate()"); + sslroot *sslccr = getSSLRoot(); + // Get the Peer Certificate.... /**************** PQI_USE_XPGP ******************/ #if defined(PQI_USE_XPGP) @@ -1078,6 +1003,9 @@ int pqissl::Authorise_SSL_Connection() waiting = WAITING_NOT; // Get the Peer Certificate.... + sslroot *sslccr = getSSLRoot(); + cert *sslcert = sslccr->findPeerId(PeerId()); + /**************** PQI_USE_XPGP ******************/ #if defined(PQI_USE_XPGP) XPGP *peercert = SSL_get_peer_pgp_certificate(ssl_connection); @@ -1169,15 +1097,6 @@ int pqissl::accept(SSL *ssl, int fd, struct sockaddr_in foreign_addr) // initiat switch(waiting) { - case WAITING_LOCAL_ADDR: - - pqioutput(PQL_DEBUG_BASIC, pqisslzone, - "pqissl::accept() STATE = Waiting Local Addr - Nothing to close"); - - case WAITING_REMOTE_ADDR: - - pqioutput(PQL_DEBUG_BASIC, pqisslzone, - "pqissl::accept() STATE = Waiting Remote Addr - Nothing to close"); case WAITING_SOCK_CONNECT: @@ -1247,6 +1166,7 @@ int pqissl::accept(SSL *ssl, int fd, struct sockaddr_in foreign_addr) // initiat remote_addr = foreign_addr; /* check whether it is on the same LAN */ + sslroot *sslccr = getSSLRoot(); cert *own = sslccr -> getOwnCert(); struct sockaddr_in own_laddr = own -> localaddr; @@ -1620,805 +1540,12 @@ bool pqissl::cansend() } +std::string pqissl::gethash() +{ + std::string dummyhash; + return dummyhash; +} /********** End of Implementation of BinInterface ******************/ - - - - - -/******************* PQI NET SSL INTERFACE CHOOSER ************************ - * PQI NET SSL - * - * This is the part that selects which network address the - * SSL connection will attempt to connect to. - * - */ - - -/********************* CHOOSE TARGET ********************/ -int pqissl::connectInterface(struct sockaddr_in &addr) -{ - // choose the interface to connect via. - // either local addr. (if same localnet) - // or server addr. (if not firewalled). - - // says local, local is valid, and matches a local address. - // sounds like a lot of work, but only happens max 1 per hour / ssl. - - // attempt to connect to localaddr. - // don't worry about the local flag -> try anyway. (set it afterwards) - // local server dns - //net_attempt; 0x01 0x02 0x04 - //net_failure; 0x01 0x02 0x04 - //net_unreachable; - - { - std::ostringstream out; - out << "pqissl::connectInterface() for: " << sslcert->Name(); - pqioutput(PQL_WARNING, pqisslzone, out.str()); - } - - if ((net_unreachable & PQISSL_LOCAL_FLAG) || - (net_failure & PQISSL_LOCAL_FLAG) || - !isValidNet(&(sslcert->localaddr.sin_addr))) - { - pqioutput(PQL_WARNING, pqisslzone, - "pqissl::connectInterface() Not Local"); - // not local... - net_failure |= PQISSL_LOCAL_FLAG; - sslcert -> Local(false); - } - else - { - pqioutput(PQL_WARNING, pqisslzone, - "pqissl::connectInterface() Using Local Address: "); - - - std::list addrs = getLocalInterfaces(); - std::list::iterator it; - for(it = addrs.begin(); it != addrs.end(); it++) - { - struct in_addr local; - inet_aton(it -> c_str(), &local); - if (sameNet(&local, &(sslcert -> localaddr.sin_addr))) - { - net_attempt = PQISSL_LOCAL_FLAG; - addr = sslcert -> localaddr; - return 1; - } - } - } - - // if we get here the local failed.... - if ((net_unreachable & PQISSL_REMOTE_FLAG) || - (net_failure & PQISSL_REMOTE_FLAG) || - !isValidNet(&(sslcert->serveraddr.sin_addr))) - { - std::ostringstream out; - out << "pqissl::connectInterface()"; - out << " Failure to Connect via SSL (u:"; - out << net_unreachable << ", f:"; - out << net_failure << ")"; - - pqioutput(PQL_WARNING, pqisslzone, out.str()); - - // fails server test. - net_failure |= PQISSL_REMOTE_FLAG; - // fall through... - } - else if ((sslcert->Firewalled()) && (!sslcert->Forwarded())) - { - // setup remote address - pqioutput(PQL_WARNING, pqisslzone, - "pqissl::connectInterface() Server Firewalled - set u"); - pqioutput(PQL_WARNING, pqisslzone, - "pqissl::connectInterface() Destination Unreachable"); - net_failure |= PQISSL_REMOTE_FLAG; - - - // shouldn't flag as unreachable - as if flags change, - // we want to connect! -> only failure.... - //net_unreachable |= PQISSL_REMOTE_FLAG; - - // dont' fall through... (name resolution wont help). - //return -1; - } - else - { - // setup remote address - pqioutput(PQL_WARNING, pqisslzone, - "pqissl::connectInterface() Using Server Address: "); - - net_attempt = PQISSL_REMOTE_FLAG; - addr = sslcert -> serveraddr; - return 1; - } - - /* Finally we attempt the dns name lookup thingy */ - pqioutput(PQL_WARNING, pqisslzone, - "pqissl::connectInterface() Attempting DNS Address lookup: "); - - - /* The initial attempt should have cached the dns request locally. - * This is made at ... - */ - if ((net_unreachable & PQISSL_DNS_FLAG) || - (net_failure & PQISSL_DNS_FLAG)) - { - - /* failed already */ - pqioutput(PQL_WARNING, pqisslzone, - "pqissl::connectInterface() DNS Address Failed Already"); - - } - else /* go for it! */ - { - /* we also set it to the server addr, as it's - * the best guess - */ - - if (sslcert->hasDHT()) - { - sslcert->serveraddr = sslcert->dhtaddr; - std::ostringstream out; - out << "pqissl::connectInterface() DHT:"; - out << " " << inet_ntoa(sslcert->serveraddr.sin_addr) << std::endl; - - net_attempt = PQISSL_DNS_FLAG; - addr = sslcert -> serveraddr; - - pqioutput(PQL_WARNING, pqisslzone, out.str()); - return 1; - } - -#if (0) /* DNS name resolution */ - if (sslcert->dynDNSaddr.length () > 0) - { - if (LookupDNSAddr(sslcert->dynDNSaddr, sslcert->serveraddr)) - { - /* success, load DNS */ - net_attempt = PQISSL_DNS_FLAG; - addr = sslcert -> serveraddr; - - std::ostringstream out; - out << "pqissl::connectInterface() DNS:" << sslcert->dynDNSaddr; - out << " " << inet_ntoa(sslcert->serveraddr.sin_addr) << std::endl; - - pqioutput(PQL_WARNING, pqisslzone, out.str()); - return 1; - } - } -#endif - - /* otherwise we failed */ - } - - pqioutput(PQL_WARNING, pqisslzone, - "pqissl::connectInterface() DNS Address Failed"); - /* the end of the road */ - net_failure |= PQISSL_DNS_FLAG; - waiting = WAITING_NOT; - return -1; -} - - -/************************ PQI NET SSL LISTENER **************************** - * PQI NET SSL LISTENER - * - * to be worked out - */ - - - -#if 0 /* NO LISTENER */ - -pqissllistener::pqissllistener(struct sockaddr_in addr) - :laddr(addr), active(false) -{ - sslccr = getSSLRoot(); - if (!(sslccr -> active())) - { - pqioutput(PQL_ALERT, pqisslzone, - "SSL-CTX-CERT-ROOT not initialised!"); - - exit(1); - } - - setuplisten(); - return; -} - -int pqissllistener::tick() -{ - status(); - // check listen port. - acceptconnection(); - return continueaccepts(); -} - -int pqissllistener::status() -{ - // print certificates we are listening for. - std::map::iterator it; - - std::ostringstream out; - out << "pqissllistener::status(): "; - out << " Listening (" << ntohs(laddr.sin_port) << ") for Certs:" << std::endl; - for(it = listenaddr.begin(); it != listenaddr.end(); it++) - { - sslccr -> printCertificate(it -> first, out); - } - pqioutput(PQL_DEBUG_ALL, pqisslzone, out.str()); - - return 1; -} - -int pqissllistener::addlistenaddr(cert *c, pqissl *acc) -{ - std::map::iterator it; - - std::ostringstream out; - - out << "Adding to Cert Listening Addresses:" << std::endl; - sslccr -> printCertificate(c, out); - out << "Current Certs:" << std::endl; - for(it = listenaddr.begin(); it != listenaddr.end(); it++) - { - sslccr -> printCertificate(it -> first, out); - if (sslccr -> compareCerts(c, it -> first) == 0) - { - out << "pqissllistener::addlistenaddr()"; - out << "Already listening for Certificate!"; - out << std::endl; - - pqioutput(PQL_DEBUG_ALERT, pqisslzone, out.str()); - return -1; - - } - } - - pqioutput(PQL_DEBUG_BASIC, pqisslzone, out.str()); - - // not there can accept it! - listenaddr[c] = acc; - return 1; -} - - - - -int pqissllistener::setuplisten() -{ - int err; - if (active) - return -1; - - lsock = socket(PF_INET, SOCK_STREAM, 0); -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - if (lsock < 0) - { - pqioutput(PQL_ALERT, pqisslzone, - "pqissllistener::setuplisten() Cannot Open Socket!"); - - return -1; - } - - err = fcntl(lsock, F_SETFL, O_NONBLOCK); - if (err < 0) - { - std::ostringstream out; - out << "Error: Cannot make socket NON-Blocking: "; - out << err << std::endl; - pqioutput(PQL_ERROR, pqisslzone, out.str()); - - return -1; - } - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#else //WINDOWS_SYS - if ((unsigned) lsock == INVALID_SOCKET) - { - std::ostringstream out; - out << "pqissllistener::setuplisten()"; - out << " Cannot Open Socket!" << std::endl; - out << "Socket Error:"; - out << socket_errorType(WSAGetLastError()) << std::endl; - pqioutput(PQL_ALERT, pqisslzone, out.str()); - - return -1; - } - - // Make nonblocking. - unsigned long int on = 1; - if (0 != (err = ioctlsocket(lsock, FIONBIO, &on))) - { - std::ostringstream out; - out << "pqissllistener::setuplisten()"; - out << "Error: Cannot make socket NON-Blocking: "; - out << err << std::endl; - out << "Socket Error:"; - out << socket_errorType(WSAGetLastError()) << std::endl; - pqioutput(PQL_ALERT, pqisslzone, out.str()); - - return -1; - } -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - // setup listening address. - - // fill in fconstant bits. - - laddr.sin_family = AF_INET; - - { - std::ostringstream out; - out << "pqissllistener::setuplisten()"; - out << "\tAddress Family: " << (int) laddr.sin_family; - out << std::endl; - out << "\tSetup Address: " << inet_ntoa(laddr.sin_addr); - out << std::endl; - out << "\tSetup Port: " << ntohs(laddr.sin_port); - - pqioutput(PQL_DEBUG_BASIC, pqisslzone, out.str()); - } - - if (0 != (err = bind(lsock, (struct sockaddr *) &laddr, sizeof(laddr)))) - { - std::ostringstream out; - out << "pqissllistener::setuplisten()"; - out << " Cannot Bind to Local Address!" << std::endl; - showSocketError(out); - pqioutput(PQL_ALERT, pqisslzone, out.str()); - - exit(1); - return -1; - } - else - { - pqioutput(PQL_DEBUG_BASIC, pqisslzone, - "pqissllistener::setuplisten() Bound to Address."); - } - - if (0 != (err = listen(lsock, 100))) - { - std::ostringstream out; - out << "pqissllistener::setuplisten()"; - out << "Error: Cannot Listen to Socket: "; - out << err << std::endl; - showSocketError(out); - pqioutput(PQL_ALERT, pqisslzone, out.str()); - - exit(1); - return -1; - } - else - { - pqioutput(PQL_DEBUG_BASIC, pqisslzone, - "pqissllistener::setuplisten() Listening to Socket"); - } - active = true; - return 1; -} - -int pqissllistener::setListenAddr(struct sockaddr_in addr) -{ - laddr = addr; - return 1; -} - -int pqissllistener::resetlisten() -{ - if (active) - { - // close ports etc. -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - shutdown(lsock, SHUT_RDWR); - close(lsock); -#else //WINDOWS_SYS - closesocket(lsock); -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - active = false; - return 1; - } - - return 0; -} - - -int pqissllistener::acceptconnection() -{ - if (!active) - return 0; - // check port for any socets... - pqioutput(PQL_DEBUG_ALL, pqisslzone, "pqissllistener::accepting()"); - - // These are local but temp variables... - // can't be arsed making them all the time. - addrlen = sizeof(raddr); - int fd = accept(lsock, (struct sockaddr *) &raddr, &addrlen); - int err = 0; - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - if (fd < 0) - { - pqioutput(PQL_DEBUG_ALL, pqisslzone, - "pqissllistener::acceptconnnection() Nothing to Accept!"); - return 0; - } - - err = fcntl(fd, F_SETFL, O_NONBLOCK); - if (err < 0) - { - std::ostringstream out; - out << "pqissllistener::acceptconnection()"; - out << "Error: Cannot make socket NON-Blocking: "; - out << err << std::endl; - pqioutput(PQL_ERROR, pqisslzone, out.str()); - - close(fd); - return -1; - } - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#else //WINDOWS_SYS - if ((unsigned) fd == INVALID_SOCKET) - { - pqioutput(PQL_DEBUG_ALL, pqisslzone, - "pqissllistener::acceptconnnection() Nothing to Accept!"); - return 0; - } - - // Make nonblocking. - unsigned long int on = 1; - if (0 != (err = ioctlsocket(fd, FIONBIO, &on))) - { - std::ostringstream out; - out << "pqissllistener::acceptconnection()"; - out << "Error: Cannot make socket NON-Blocking: "; - out << err << std::endl; - out << "Socket Error:"; - out << socket_errorType(WSAGetLastError()) << std::endl; - pqioutput(PQL_ALERT, pqisslzone, out.str()); - - closesocket(fd); - return 0; - } -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - { - std::ostringstream out; - out << "Accepted Connection from "; - out << inet_ntoa(raddr.sin_addr) << ":" << ntohs(raddr.sin_port); - pqioutput(PQL_DEBUG_BASIC, pqisslzone, out.str()); - } - - // Negotiate certificates. SSL stylee. - // Allow negotiations for secure transaction. - - SSL *ssl = SSL_new(sslccr -> getCTX()); - SSL_set_fd(ssl, fd); - - return continueSSL(ssl, true); // continue and save if incomplete. -} - -int pqissllistener::continueSSL(SSL *ssl, bool addin) -{ - // attempt the accept again. - int fd = SSL_get_fd(ssl); - int err = SSL_accept(ssl); - if (err <= 0) - { - int ssl_err = SSL_get_error(ssl, err); - int err_err = ERR_get_error(); - - { - std::ostringstream out; - out << "pqissllistener::continueSSL() "; - out << "Issues with SSL Accept(" << err << ")!" << std::endl; - printSSLError(ssl, err, ssl_err, err_err, out); - pqioutput(PQL_DEBUG_BASIC, pqisslzone, out.str()); - } - - if ((ssl_err == SSL_ERROR_WANT_READ) || - (ssl_err == SSL_ERROR_WANT_WRITE)) - { - std::ostringstream out; - out << "pqissllistener::continueSSL() "; - out << " Connection Not Complete!"; - out << std::endl; - - if (addin) - { - out << "pqissllistener::continueSSL() "; - out << "Adding SSL to incoming!"; - - // add to incomingqueue. - incoming_ssl.push_back(ssl); - } - - pqioutput(PQL_DEBUG_BASIC, pqisslzone, out.str()); - - // zero means still continuing.... - return 0; - } - - /* we have failed -> get certificate if possible */ - Extract_Failed_SSL_Certificate(ssl, &raddr); - - // other wise delete ssl connection. - // kill connection.... - // so it will be removed from cache. - SSL_shutdown(ssl); - - // close socket??? -/************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - shutdown(fd, SHUT_RDWR); - close(fd); -#else //WINDOWS_SYS - closesocket(fd); -#endif -/************************** WINDOWS/UNIX SPECIFIC PART ******************/ - // free connection. - SSL_free(ssl); - - std::ostringstream out; - out << "Read Error on the SSL Socket"; - out << std::endl; - out << "Shutting it down!" << std::endl; - pqioutput(PQL_WARNING, pqisslzone, out.str()); - - // failure -1, pending 0, sucess 1. - return -1; - } - - - // if it succeeds - - // Get the Peer Certificate.... -/**************** PQI_USE_XPGP ******************/ -#if defined(PQI_USE_XPGP) - XPGP *peercert = SSL_get_peer_pgp_certificate(ssl); -#else /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - X509 *peercert = SSL_get_peer_certificate(ssl); -#endif /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - - if (peercert == NULL) - { - pqioutput(PQL_WARNING, pqisslzone, - "pqissl::connectattempt() Peer Did Not Provide Cert!"); - - // delete ssl connection. - SSL_shutdown(ssl); - - // close socket??? -/************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - shutdown(fd, SHUT_RDWR); - close(fd); -#else //WINDOWS_SYS - closesocket(fd); -#endif -/************************** WINDOWS/UNIX SPECIFIC PART ******************/ - // free connection. - SSL_free(ssl); - - std::ostringstream out; - out << "Shutting it down!" << std::endl; - pqioutput(PQL_WARNING, pqisslzone, out.str()); - - // failure -1, pending 0, sucess 1. - return -1; - } - - - // save certificate... (and ip locations) -/**************** PQI_USE_XPGP ******************/ -#if defined(PQI_USE_XPGP) - cert *npc = sslccr -> registerCertificateXPGP(peercert, raddr, true); -#else /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - cert *npc = sslccr -> registerCertificate(peercert, raddr, true); -#endif /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - - bool found = false; - std::map::iterator it; - - if ((npc == NULL) || (npc -> Connected())) - { - // bad - shutdown. - } - else - { - std::ostringstream out; - - out << "pqissllistener::continueSSL()" << std::endl; - out << "checking: " << npc -> Name() << std::endl; - // check if cert is in our list..... - for(it = listenaddr.begin();(found!=true) && (it!=listenaddr.end());) - { - out << "\tagainst: " << it->first->Name() << std::endl; - if (sslccr -> compareCerts(it -> first, npc) == 0) - { - out << "\t\tMatch!"; - found = true; - } - else - { - it++; - } - } - - pqioutput(PQL_DEBUG_BASIC, pqisslzone, out.str()); - } - - if (found == false) - { - // kill connection.... - // so it will be removed from cache. - SSL_shutdown(ssl); - - // close socket??? -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - shutdown(fd, SHUT_RDWR); - close(fd); -#else //WINDOWS_SYS - closesocket(fd); -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - // free connection. - SSL_free(ssl); - - std::ostringstream out; - out << "No Matching Certificate/Already Connected"; - out << " for Connection:" << inet_ntoa(raddr.sin_addr); - out << std::endl; - out << "Shutting it down!" << std::endl; - pqioutput(PQL_WARNING, pqisslzone, out.str()); - return -1; - } - - pqissl *pqis = it -> second; - - // remove from the list of certificates. - listenaddr.erase(it); - - // timestamp - // done in sslroot... npc -> lr_timestamp = time(NULL); - - // hand off ssl conection. - pqis -> accept(ssl, fd); - return 1; -} - - -int pqissllistener::Extract_Failed_SSL_Certificate(SSL *ssl, struct sockaddr_in *inaddr) -{ - pqioutput(PQL_DEBUG_BASIC, pqisslzone, - "pqissllistener::Extract_Failed_SSL_Certificate()"); - - // Get the Peer Certificate.... -/**************** PQI_USE_XPGP ******************/ -#if defined(PQI_USE_XPGP) - XPGP *peercert = SSL_get_peer_pgp_certificate(ssl); -#else /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - X509 *peercert = SSL_get_peer_certificate(ssl); -#endif /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - - if (peercert == NULL) - { - pqioutput(PQL_WARNING, pqisslzone, - "pqissllistener::Extract_Failed_SSL_Certificate() Peer Didnt Give Cert"); - return -1; - } - - pqioutput(PQL_DEBUG_BASIC, pqisslzone, - "pqissllistener::Extract_Failed_SSL_Certificate() Have Peer Cert - Registering"); - - // save certificate... (and ip locations) - // false for outgoing.... -/**************** PQI_USE_XPGP ******************/ -#if defined(PQI_USE_XPGP) - cert *npc = sslccr -> registerCertificateXPGP(peercert, *inaddr, true); -#else /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - cert *npc = sslccr -> registerCertificate(peercert, *inaddr, true); -#endif /* X509 Certificates */ -/**************** PQI_USE_XPGP ******************/ - - return 1; -} - - -int pqissllistener::continueSocket(int fd, bool addin) -{ - // this does nothing, as sockets - // cannot (haven't) blocked yet! - return 0; -} - - -int pqissllistener::continueaccepts() -{ - - // for each of the incoming sockets.... call continue. - std::list::iterator it; - std::list::iterator its; - - for(it = incoming_skts.begin(); it != incoming_skts.end();) - { - if (continueSocket(*it, false)) - { - it = incoming_skts.erase(it); - } - else - { - it++; - } - } - - for(its = incoming_ssl.begin(); its != incoming_ssl.end();) - { - pqioutput(PQL_DEBUG_BASIC, pqisslzone, - "pqissllistener::continueaccepts() Continuing SSL"); - if (0 != continueSSL(*its, false)) - { - pqioutput(PQL_DEBUG_ALERT, pqisslzone, - "pqissllistener::continueaccepts() SSL Complete/Dead!"); - - its = incoming_ssl.erase(its); - } - else - { - its++; - } - } - return 1; -} - - - - -int pqissllistener::removeListenPort(cert *c) -{ - // check where the connection is coming from. - // if in list of acceptable addresses, - // - // check if in list. - std::map::iterator it; - for(it = listenaddr.begin();it!=listenaddr.end();it++) - { - if (sslccr -> compareCerts(it -> first, c) == 0) - { - listenaddr.erase(it); - - pqioutput(PQL_DEBUG_BASIC, pqisslzone, - "pqissllisten::removeListenPort() Success!"); - return 1; - } - } - - pqioutput(PQL_WARNING, pqisslzone, - "pqissllistener::removeListenPort() Failed to Find a Match"); - - return -1; -} - -#endif /* NO LISTENER */ diff --git a/libretroshare/src/pqi/pqissl.h b/libretroshare/src/pqi/pqissl.h index 63bc9f28d..000a37e50 100644 --- a/libretroshare/src/pqi/pqissl.h +++ b/libretroshare/src/pqi/pqissl.h @@ -49,13 +49,10 @@ #define WAITING_NOT 0 -#define WAITING_PROXY_CONNECT 1 -#define WAITING_LOCAL_ADDR 2 -#define WAITING_REMOTE_ADDR 3 -#define WAITING_SOCK_CONNECT 4 -#define WAITING_SSL_CONNECTION 5 -#define WAITING_SSL_AUTHORISE 6 -#define WAITING_FAIL_INTERFACE 7 +#define WAITING_SOCK_CONNECT 1 +#define WAITING_SSL_CONNECTION 2 +#define WAITING_SSL_AUTHORISE 3 +#define WAITING_FAIL_INTERFACE 4 #define PQISSL_PASSIVE 0x00 @@ -93,63 +90,14 @@ class cert; class pqissllistener; -#if 0 /* REMOVING pqissllistener */ - -class pqissllistener -{ - public: - - pqissllistener(struct sockaddr_in addr); - -int addlistenaddr(cert *c, pqissl *acc); -int removeListenPort(cert *c); - -int setListenAddr(struct sockaddr_in addr); -int setuplisten(); -int resetlisten(); - -int acceptconnection(); -int continueaccepts(); -int continueSSL(SSL *ssl, bool); -int continueSocket(int fd, bool); - -//int connectCertExchange(cert *); -// - - -int tick(); -int status(); - - private: - - // fn to get cert, anyway -int Extract_Failed_SSL_Certificate(SSL *ssl, struct sockaddr_in *inaddr); - - struct sockaddr_in raddr; - struct sockaddr_in laddr; - socklen_t addrlen; - - bool active; - int lsock; - cert *localcert; - std::map listenaddr; - std::list incoming_ssl; - std::list incoming_skts; - - sslroot *sslccr; -}; - - -#endif /* removing pqisllistener */ - class pqissl: public NetBinInterface { public: - pqissl(cert *c, pqissllistener *l, PQInterface *parent); + pqissl(pqissllistener *l, PQInterface *parent); virtual ~pqissl(); // NetInterface -virtual int connectattempt(); +virtual int connect(struct sockaddr_in raddr); virtual int listen(); virtual int stoplistening(); virtual int reset(); @@ -165,6 +113,7 @@ virtual int netstatus(); virtual int isactive(); virtual bool moretoread(); virtual bool cansend(); +virtual std::string gethash(); /* not used here */ virtual bool bandwidthLimited(); protected: @@ -177,14 +126,9 @@ protected: int ConnectAttempt(); int waiting; - // These first five fns are overloaded for udp/etc connections. -virtual int Reattempt_Connection(); -virtual int Request_Proxy_Connection(); -virtual int Check_Proxy_Connection(); -virtual int Request_Local_Address(); -virtual int Determine_Local_Address(); -virtual int Determine_Remote_Address(); +virtual int Failed_Connection(); + // These two fns are overloaded for udp/etc connections. virtual int Initiate_Connection(); virtual int Basic_Connection_Complete(); @@ -223,14 +167,9 @@ virtual int net_internal_fcntl_nonblock(int fd) { return unix_fcntl_nonblock(fd) SSL *ssl_connection; int sockfd; - cert *sslcert; - sslroot *sslccr; - pqissllistener *pqil; - struct sockaddr_in remote_addr; - void *readpkt; int pktlen; diff --git a/libretroshare/src/pqi/pqissllistener.cc b/libretroshare/src/pqi/pqissllistener.cc index d75aa65fb..7319c1ed4 100644 --- a/libretroshare/src/pqi/pqissllistener.cc +++ b/libretroshare/src/pqi/pqissllistener.cc @@ -503,19 +503,18 @@ pqissllistener::~pqissllistener() return; } -int pqissllistener::addlistenaddr(cert *c, pqissl *acc) +int pqissllistener::addlistenaddr(std::string id, pqissl *acc) { - std::map::iterator it; + std::map::iterator it; std::ostringstream out; - out << "Adding to Cert Listening Addresses:" << std::endl; - sslccr -> printCertificate(c, out); + out << "Adding to Cert Listening Addresses Id: " << id << std::endl; out << "Current Certs:" << std::endl; for(it = listenaddr.begin(); it != listenaddr.end(); it++) { - sslccr -> printCertificate(it -> first, out); - if (sslccr -> compareCerts(c, it -> first) == 0) + out << id << std::endl; + if (it -> first == id) { out << "pqissllistener::addlistenaddr()"; out << "Already listening for Certificate!"; @@ -530,20 +529,20 @@ int pqissllistener::addlistenaddr(cert *c, pqissl *acc) pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, out.str()); // not there can accept it! - listenaddr[c] = acc; + listenaddr[id] = acc; return 1; } -int pqissllistener::removeListenPort(cert *c) +int pqissllistener::removeListenPort(std::string id) { // check where the connection is coming from. // if in list of acceptable addresses, // // check if in list. - std::map::iterator it; + std::map::iterator it; for(it = listenaddr.begin();it!=listenaddr.end();it++) { - if (sslccr -> compareCerts(it -> first, c) == 0) + if (it->first == id) { listenaddr.erase(it); @@ -564,14 +563,14 @@ int pqissllistener::status() { pqissllistenbase::status(); // print certificates we are listening for. - std::map::iterator it; + std::map::iterator it; std::ostringstream out; out << "pqissllistener::status(): "; out << " Listening (" << ntohs(laddr.sin_port) << ") for Certs:" << std::endl; for(it = listenaddr.begin(); it != listenaddr.end(); it++) { - sslccr -> printCertificate(it -> first, out); + out << it -> first << std::endl; } pqioutput(PQL_DEBUG_ALL, pqissllistenzone, out.str()); @@ -612,7 +611,7 @@ int pqissllistener::completeConnection(int fd, SSL *ssl, struct sockaddr_in &rem /**************** PQI_USE_XPGP ******************/ bool found = false; - std::map::iterator it; + std::map::iterator it; // Let connected one through as well! if ((npc == NULL) || (npc -> Connected())) if (npc == NULL) @@ -633,8 +632,8 @@ int pqissllistener::completeConnection(int fd, SSL *ssl, struct sockaddr_in &rem // check if cert is in our list..... for(it = listenaddr.begin();(found!=true) && (it!=listenaddr.end());) { - out << "\tagainst: " << it->first->Name() << std::endl; - if (sslccr -> compareCerts(it -> first, npc) == 0) + out << "\tagainst: " << it->first << std::endl; + if (it -> first == npc->PeerId()) { out << "\t\tMatch!"; found = true; diff --git a/libretroshare/src/pqi/pqissllistener.h b/libretroshare/src/pqi/pqissllistener.h index 39e374147..a36da3416 100644 --- a/libretroshare/src/pqi/pqissllistener.h +++ b/libretroshare/src/pqi/pqissllistener.h @@ -37,6 +37,7 @@ #include #include "pqi/pqi_base.h" +#include "pqi/pqilistener.h" /**************** PQI_USE_XPGP ******************/ #if defined(PQI_USE_XPGP) @@ -53,23 +54,29 @@ class pqissl; class cert; -class pqissllistenbase +class pqissllistenbase: public pqilistener { public: + pqissllistenbase(struct sockaddr_in addr); virtual ~pqissllistenbase(); -int setListenAddr(struct sockaddr_in addr); -int setuplisten(); -int resetlisten(); +/*************************************/ +/* LISTENER INTERFACE **/ + +virtual int tick(); +virtual int status(); +virtual int setListenAddr(struct sockaddr_in addr); +virtual int setuplisten(); +virtual int resetlisten(); + +/*************************************/ int acceptconnection(); int continueaccepts(); int continueSSL(SSL *ssl, struct sockaddr_in remote_addr, bool); -virtual int tick(); -virtual int status(); virtual int completeConnection(int sockfd, SSL *in_connection, struct sockaddr_in &raddr) = 0; @@ -100,8 +107,8 @@ class pqissllistener: public pqissllistenbase pqissllistener(struct sockaddr_in addr); virtual ~pqissllistener(); -int addlistenaddr(cert *c, pqissl *acc); -int removeListenPort(cert *c); +int addlistenaddr(std::string id, pqissl *acc); +int removeListenPort(std::string id); //virtual int tick(); virtual int status(); @@ -110,7 +117,7 @@ virtual int completeConnection(int sockfd, SSL *in_connection, struct sockaddr_i private: - std::map listenaddr; + std::map listenaddr; }; diff --git a/libretroshare/src/pqi/pqisslpersongrp.cc b/libretroshare/src/pqi/pqisslpersongrp.cc new file mode 100644 index 000000000..b7fed9476 --- /dev/null +++ b/libretroshare/src/pqi/pqisslpersongrp.cc @@ -0,0 +1,95 @@ +/* + * libretroshare/src/pqi: pqisslpersongrp.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-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 "pqi/pqisslpersongrp.h" +#include "pqi/pqidebug.h" +#include + +const int pqipersongrpzone = 354; + +/********************************** SSL Specific features ***************************/ + +#include "pqi/pqissl.h" +#include "pqi/pqissllistener.h" + +#ifdef PQI_USE_PROXY + #include "pqi/pqissludp.h" +#endif + +pqilistener * pqisslpersongrp::createListener(struct sockaddr_in laddr) +{ + pqilistener *listener = new pqissllistener(laddr); + return listener; +} + +pqiperson * pqisslpersongrp::createPerson(std::string id, pqilistener *listener) +{ + { + std::ostringstream out; + out << "pqipersongrp::createPerson() PeerId: " << id; + pqioutput(PQL_DEBUG_BASIC, pqipersongrpzone, out.str()); + } + + pqiperson *pqip = new pqiperson(id, this); + pqissl *pqis = new pqissl((pqissllistener *) listener, pqip); + + /* construct the serialiser .... + * Needs: + * * FileItem + * * FileData + * * ServiceGeneric + */ + + RsSerialiser *rss = new RsSerialiser(); + rss->addSerialType(new RsFileItemSerialiser()); + rss->addSerialType(new RsCacheItemSerialiser()); + rss->addSerialType(new RsServiceSerialiser()); + + pqiconnect *pqisc = new pqiconnect(rss, pqis); + + pqip -> addChildInterface(PQI_CONNECT_TCP, pqisc); + +#ifdef PQI_USE_PROXY + pqissludp *pqius = new pqissludp(pqip); + + RsSerialiser *rss2 = new RsSerialiser(); + rss2->addSerialType(new RsFileItemSerialiser()); + rss2->addSerialType(new RsCacheItemSerialiser()); + rss2->addSerialType(new RsServiceSerialiser()); + + pqiconnect *pqiusc = new pqiconnect(rss2, pqius); + + // add a ssl + proxy interface. + // Add Proxy First. + pqip -> addChildInterface(PQI_CONNECT_UDP, pqiusc); +#endif + + return pqip; +} + + +/********************************** SSL Specific features ***************************/ + + diff --git a/libretroshare/src/pqi/pqimon.h b/libretroshare/src/pqi/pqisslpersongrp.h similarity index 51% rename from libretroshare/src/pqi/pqimon.h rename to libretroshare/src/pqi/pqisslpersongrp.h index 6f380d904..7cff11621 100644 --- a/libretroshare/src/pqi/pqimon.h +++ b/libretroshare/src/pqi/pqisslpersongrp.h @@ -1,9 +1,9 @@ /* - * "$Id: pqibin.h,v 1.2 2007-02-18 21:46:49 rmf24 Exp $" + * libretroshare/src/pqi: pqisslpersongrp.h * * 3P/PQI network interface for RetroShare. * - * Copyright 2004-2006 by Robert Fernie. + * Copyright 2004-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 @@ -23,50 +23,26 @@ * */ -#ifndef PQI_MONITOR_HEADER -#define PQI_MONITOR_HEADER - -/**** Rough sketch of a Monitor class - * expect it to change significantly - * - */ -const uint32_t PQI_PEER_STATE_OFFLINE = 0; -const uint32_t PQI_PEER_STATE_ONLINE = 1; +#ifndef MRK_PQI_SSL_PERSON_HANDLER_HEADER +#define MRK_PQI_SSL_PERSON_HANDLER_HEADER -class pqipeer +#include "pqi/pqipersongrp.h" + +class pqisslpersongrp: public pqipersongrp { public: -std::string id; -std::string name; -int state; -}; + pqisslpersongrp(SecurityPolicy *pol, unsigned long flags) + :pqipersongrp(pol, flags) { return; } -class pqimonclient -{ - public: + protected: - pqimonclient() { return; } -virtual ~pqimonclient() { return; } - -virtual void monUpdate(const std::list &plist) = 0; + /********* FUNCTIONS to OVERLOAD for specialisation ********/ +virtual pqilistener *createListener(struct sockaddr_in laddr); +virtual pqiperson *createPerson(std::string id, pqilistener *listener); + /********* FUNCTIONS to OVERLOAD for specialisation ********/ }; -class pqimonitor -{ -public: - pqimonitor(); - ~pqimonitor(); -int tick(); -int addClient(pqimonclient *cli) { clients.push_back(cli); return 1; } - -private: - std::list clients; - std::list plist; -}; - - - -#endif +#endif // MRK_PQI_SSL_PERSON_HANDLER_HEADER diff --git a/libretroshare/src/pqi/pqissludp.cc b/libretroshare/src/pqi/pqissludp.cc index da0c1d80b..3649d7edb 100644 --- a/libretroshare/src/pqi/pqissludp.cc +++ b/libretroshare/src/pqi/pqissludp.cc @@ -28,7 +28,6 @@ #include "pqi/pqissludp.h" -#include "pqi/pqiudpproxy.h" #include "pqi/pqinetwork.h" #include "tcponudp/tou.h" @@ -42,23 +41,6 @@ const int pqissludpzone = 3144; -static const int PQI_SSLUDP_STUN_TIMEOUT = 2; -static const int PQI_SSLUDP_STUN_ATTEMPTS = 15; - - /* we need a long timeout to give the local address - * discovery a chance. This must also allow for the - * time for the peer to check for a proxy connect (before lad starts). - * Remote = Check Time + 40 - */ -static const int PQI_SSLUDP_PROXY_CHECK_TIME = 29; -static const int PQI_SSLUDP_REMOTE_TIMEOUT = 70; - - /* we need a long timeout to give the udpproxy time - * to find proxies (at startup) - * this is only an emergency timeout anyway - */ -static const int PQI_SSLUDP_PROXY_TIMEOUT = 180; - /* a final timeout, to ensure this never blocks completely * 300 secs to complete udp/tcp/ssl connection. * This is long as the udp connect can take some time. @@ -67,13 +49,12 @@ static const int PQI_SSLUDP_CONNECT_TIMEOUT = 300; /********** PQI SSL UDP STUFF **************************************/ -pqissludp::pqissludp(cert *c, PQInterface *parent, pqiudpproxy *prxy) - :pqissl(c, NULL, parent), tou_bio(NULL), udpproxy(prxy), +pqissludp::pqissludp(PQInterface *parent) + :pqissl(NULL, parent), tou_bio(NULL), listen_checktime(0) { - sslmode = PQISSL_PASSIVE; - stun_addr.sin_addr.s_addr = 0; + attach(); return; } @@ -81,7 +62,7 @@ pqissludp::pqissludp(cert *c, PQInterface *parent, pqiudpproxy *prxy) pqissludp::~pqissludp() { pqioutput(PQL_ALERT, pqissludpzone, - "pqissludp::~pqissludp -> destroying pqissludp (+ pqiudproxy)"); + "pqissludp::~pqissludp -> destroying pqissludp"); /* must call reset from here, so that the * virtual functions will still work. @@ -93,11 +74,6 @@ pqissludp::~pqissludp() stoplistening(); /* remove from p3proxy listenqueue */ reset(); - if (udpproxy) - { - delete udpproxy; - } - if (tou_bio) // this should be in the reset? { BIO_free(tou_bio); @@ -107,67 +83,11 @@ pqissludp::~pqissludp() int pqissludp::reset() { - /* and reset the udpproxy */ - if (udpproxy) - { - udpproxy->reset(); - } /* reset for next time.*/ - stun_attempts = 0; return pqissl::reset(); } -void *pqissludp::generate_stun_pkt(struct sockaddr_in *stun_addr, int *len) -{ - /* just the header */ - void *stun_pkt = malloc(20); - ((uint16_t *) stun_pkt)[0] = 0x0001; - ((uint16_t *) stun_pkt)[1] = 0x0020; /* only header */ - /* transaction id - should be random */ - ((uint32_t *) stun_pkt)[1] = 0x0020; - ((uint32_t *) stun_pkt)[2] = 0x0121; - ((uint32_t *) stun_pkt)[3] = 0x0111; - ((uint32_t *) stun_pkt)[4] = 0x1010; - *len = 20; - return stun_pkt; -} - - -int pqissludp::getStunReturnedAddr(void *stun_pkt, int len, struct sockaddr_in *fw_addr) -{ - if (((uint16_t *) stun_pkt)[0] != 0x0101) - { - /* not a response */ - return 0; - } - - /* iterate through the packet */ - /* for now assume the address follows the header directly */ - fw_addr->sin_family = AF_INET; - fw_addr->sin_addr.s_addr = ((uint32_t *) stun_pkt)[6]; - fw_addr->sin_port = ((uint16_t *) stun_pkt)[11]; - - return 1; -} - - -// Udp Proxy service is started by the pqiudpproxy. -// connection is attempted by searching for common neighbours. -// Proxy Pkts are exchanged and an exchange of external addresses -// is done. these are passed to pqissludp, through a series -// of function calls. should all work perfectly. -// - -int pqissludp::Reattempt_Connection() -{ - pqioutput(PQL_DEBUG_BASIC, pqissludpzone, - "pqissludp::Reattempt_Connection() Failed Doing nothing"); - // notify the parent. - waiting = WAITING_NOT; - return -1; -} - /* <===================== UDP Difference *******************/ // The Proxy Version takes a few more step // @@ -175,16 +95,8 @@ int pqissludp::Reattempt_Connection() // and is set here. /* <===================== UDP Difference *******************/ -int pqissludp::attach(struct sockaddr_in &addr) +int pqissludp::attach() { - if (waiting != WAITING_PROXY_CONNECT) - { - pqioutput(PQL_WARNING, pqissludpzone, - "pqissludp::attach() not WAITING_PROXY_CONNECT"); - /* should be attached already! */ - return 1; - } - sockfd = tou_socket(0,0,0); if (0 > sockfd) { @@ -193,349 +105,15 @@ int pqissludp::attach(struct sockaddr_in &addr) return -1; } - /* just fix the address to start with */ - int err = -1; - int fails = 0; - while(0 > (err = tou_bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)))) - { - addr.sin_port = htons(ntohs(addr.sin_port) + 1); - - std::ostringstream out; - out << "pqissludp::attach() Changing udp bind address to: "; - out << inet_ntoa(addr.sin_addr) << ":" << ntohs(addr.sin_port); - pqioutput(PQL_WARNING, pqissludpzone, out.str()); - if (fails++ > 20) - { - pqioutput(PQL_WARNING, pqissludpzone, - "pqissludp::attach() Too many tou_bind attempts"); - net_internal_close(sockfd); - sockfd = -1; - return 0; - } - } - // setup remote address pqioutput(PQL_WARNING, pqissludpzone, - "pqissludp::attach() opening Local Udp Socket"); + "pqissludp::attach() Opened Local Udp Socket"); return 1; } -// find a suitable STUN client. -// This is choosen from a list of neighbours. (AutoDiscovery) -// and failing a suitable STUN, uses googles STUN servers. -// send out message. - -int pqissludp::Request_Proxy_Connection() -{ - /* to start the whole thing rolling we need, to be connected - * (this don't match the fn name) - */ - - /* so start a connection */ - waiting = WAITING_PROXY_CONNECT; - proxy_timeout = time(NULL) + PQI_SSLUDP_PROXY_TIMEOUT; - pqioutput(PQL_DEBUG_BASIC, pqissludpzone, - "pqissludp::Request_Proxy_Connection() connectattempt!"); - return udpproxy -> connectattempt(); -} - -int pqissludp::Check_Proxy_Connection() -{ - int mode; - if (udpproxy -> isConnected(mode)) - { - pqioutput(PQL_WARNING, pqissludpzone, - "pqissludp::Check_Proxy_Connection() isConnected!"); - sslmode = mode; - waiting = WAITING_PROXY_CONNECT; - /* This will switch into WAITING_LOCAL_ADDR */ - return Request_Local_Address(); - } - if (udpproxy -> hasFailed()) - { - pqioutput(PQL_WARNING, pqissludpzone, - "pqissludp::Check_Proxy_Connection() hasFailed!"); - - /* failure */ - if (parent()) - { - - /* only notify of failure, if its an active connect attempt. - * ie not if waiting == WAITING_NOT and we are listening... - */ - - if (waiting == WAITING_PROXY_CONNECT) - { - pqioutput(PQL_WARNING, pqissludpzone, - "pqissludp::Check_Proxy_Connection() notifying parent - hasFailed!"); - - udpproxy->reset(); - if (parent()) - { - parent() -> notifyEvent(this, NET_CONNECT_FAILED); - } - } - else - { - pqioutput(PQL_WARNING, pqissludpzone, - "pqissludp::Check_Proxy_Connection() listen - not Connected....Ignore"); - } - } - else - { - pqioutput(PQL_WARNING, pqissludpzone, - "pqissludp::Check_Proxy_Connection() no parent to notify - hasFailed!"); - } - waiting = WAITING_FAIL_INTERFACE; - return -1; - } - - /* finally a proxy timeout - shouldn't be needed, but you don't know.... - */ - if (waiting == WAITING_PROXY_CONNECT) - { - if (proxy_timeout < time(NULL)) - { - pqioutput(PQL_ALERT, pqissludpzone, - "pqissludp::Check_Proxy_Connection() Proxy Connect Timed Out!"); - - udpproxy->reset(); - if (parent()) - { - parent() -> notifyEvent(this, NET_CONNECT_FAILED); - } - waiting = WAITING_FAIL_INTERFACE; - return -1; - } - } - - return 0; -} - -int pqissludp::Request_Local_Address() -{ - // reset of stun_addr, restarts attempts. - if (stun_addr.sin_addr.s_addr == 0) - { - stun_attempts = 0; - } - - udpproxy->requestStunServer(stun_addr); - - /* check its valid */ - if (!isValidNet((&(stun_addr.sin_addr)))) - { - pqioutput(PQL_WARNING, pqissludpzone, - "pqissludp::Request_Local_Address() No StunServers!"); - - - /* must do this manually - as we don't know if ::reset() will send notification. - */ - - udpproxy->reset(); - if (sockfd > 0) /* might be valid - might not */ - { - net_internal_close(sockfd); - } - waiting = WAITING_FAIL_INTERFACE; - if (parent()) - { - // not enough stun attempts. FAILED (not UNREACHABLE) - parent() -> notifyEvent(this, NET_CONNECT_FAILED); - } - return -1; - } - - /* add +1 to get correct stun addr */ - stun_addr.sin_port = htons(ntohs(stun_addr.sin_port) + 1); - - /* - * send of pkt. - */ - - net_attempt = PQISSL_UDP_FLAG; - - pqioutput(PQL_WARNING, pqissludpzone, - "pqissludp::Request_Local_Address() Opening Local Socket"); - - /* only if the first time */ - if (waiting == WAITING_PROXY_CONNECT) - { - /* open socket. */ - local_addr = sslccr -> getOwnCert() -> localaddr; - if (0 > attach(local_addr)) - { - pqioutput(PQL_WARNING, pqissludpzone, - "pqissludp::Request_Local_Address() Failed to Attach"); - - udpproxy->reset(); - waiting = WAITING_FAIL_INTERFACE; - parent() -> notifyEvent(this, NET_CONNECT_FAILED); - return -1; - } - } - - /* then send packet */ - int len; - void *stun_pkt = generate_stun_pkt(&stun_addr, &len); - if (!tou_sendto(sockfd, stun_pkt, len, 0, - (const sockaddr *) &stun_addr, sizeof(stun_addr))) - { - pqioutput(PQL_WARNING, pqissludpzone, - "pqissludp::Request_Local_Address() Failed to Stun"); - free(stun_pkt); - return -1; - } - - { - std::ostringstream out; - out << "pqissludp::Request_Local_Address() Sent StunPkt to: "; - out << inet_ntoa(stun_addr.sin_addr); - out << ":" << ntohs(stun_addr.sin_port); - - pqioutput(PQL_WARNING, pqissludpzone, out.str()); - } - - free(stun_pkt); - waiting = WAITING_LOCAL_ADDR; - stun_timeout = time(NULL) + PQI_SSLUDP_STUN_TIMEOUT; - return 0; -} - - -int pqissludp::Determine_Local_Address() -{ - /* have we recieved anything from the Stun server? */ - /* now find the listenUdp port */ - struct sockaddr_in stun_addr_in; - socklen_t addrlen = sizeof(stun_addr_in); - int size = 1000; - char data[size]; - - pqioutput(PQL_DEBUG_BASIC, pqissludpzone, - "pqissludp::Determine_Local_Address() Waiting Local Addr - Can't do nothing,!"); - - size = tou_recvfrom(sockfd, data, size, 0, - (struct sockaddr *) &stun_addr_in, &addrlen); - - if (0 < size) - { - { - std::ostringstream out; - out << "pqissludp::Determine_Local_Address() Received + Decoding Stun Reply: " << size; - pqioutput(PQL_DEBUG_BASIC, pqissludpzone, out.str()); - } - - /* get the firewall_address out. - */ - - if (getStunReturnedAddr(data, size, &firewall_addr)) - { - std::ostringstream out; - out << "pqissludp::Listen_for_Proxy() Got ExtAddr: "; - out << inet_ntoa(firewall_addr.sin_addr) << ":"; - out << ntohs(firewall_addr.sin_port) << std::endl; - - pqioutput(PQL_DEBUG_BASIC, pqissludpzone, out.str()); - - /* initiate (or complete) a connection via the proxy */ - - /* now tell the udpproxy our address */ - udpproxy -> sendExternalAddress(firewall_addr); - waiting = WAITING_REMOTE_ADDR; - remote_timeout = time(NULL) + PQI_SSLUDP_REMOTE_TIMEOUT; - return Determine_Remote_Address(); - } - else - { - std::ostringstream out; - out << "pqissludp::Listen_for_Proxy() Failed to Get StunRtn Addr"; - pqioutput(PQL_DEBUG_BASIC, pqissludpzone, out.str()); - } - } - - // switched to time based timeout. - //if (stun_timeout++ > PQI_SSLUDP_STUN_TIMEOUT) - if (stun_timeout < time(NULL)) - { - /* too many times? */ - if (stun_attempts++ > PQI_SSLUDP_STUN_ATTEMPTS) - { - std::ostringstream out; - out << "pqissludp::Listen_for_Proxy() Too Many Stun Attempts"; - out << std::endl; - out << "Will notifyEvent(NET_CONNECT_UNREACHABLE)"; - out << std::endl; - pqioutput(PQL_ALERT, pqissludpzone, out.str()); - - reset(); - return -1; - } - - /* retry. - */ - return Request_Local_Address(); - } - return 0; -} - - -int pqissludp::Determine_Remote_Address() -{ - int ret; - int cMode; - if (waiting != WAITING_REMOTE_ADDR) - { - pqioutput(PQL_WARNING, pqissludpzone, - "pqissludp::Determine_Remote_Address() ERROR: waiting != REMOTE_ADDR!"); - return -1; - } - - if (0 > (ret = udpproxy -> gotRemoteAddress(remote_addr, cMode))) - { - pqioutput(PQL_WARNING, pqissludpzone, - "pqissludp::Determine_Remote_Address() FAILURE to Get Remote Address"); - - reset(); - waiting = WAITING_FAIL_INTERFACE; - return -1; - - } - if (ret == 0) - { - pqioutput(PQL_DEBUG_BASIC, pqissludpzone, - "pqissludp::Determine_Remote_Address() Remote Address Acquistion in progress"); - /* inprogress */ - - /* check if its timed out */ - if (remote_timeout < time(NULL)) - { - pqioutput(PQL_WARNING, pqissludpzone, - "pqissludp::Determine_Remote_Address() Timed out: NOTIFY of FAILURE"); - - reset(); - waiting = WAITING_FAIL_INTERFACE; - return -1; - } - return 0; - } - - /* success */ - - sslmode = cMode; /* set the connect mode */ - - std::ostringstream out; - out << "pqissludp::Determine_Remote_Address() Success:"; - out << "Remote Address: " << inet_ntoa(remote_addr.sin_addr) << ":"; - out << ntohs(remote_addr.sin_port); - out << " sslMode: " << (int) sslmode; - pqioutput(PQL_DEBUG_BASIC, pqissludpzone, out.str()); - - return Initiate_Connection(); -} - +// The Address determination is done centrally int pqissludp::Initiate_Connection() { @@ -545,7 +123,7 @@ int pqissludp::Initiate_Connection() pqioutput(PQL_DEBUG_BASIC, pqissludpzone, "pqissludp::Initiate_Connection() Attempting Outgoing Connection...."); - if (waiting != WAITING_REMOTE_ADDR) + if (waiting != WAITING_NOT) { pqioutput(PQL_WARNING, pqissludpzone, "pqissludp::Initiate_Connection() Already Attempt in Progress!"); @@ -580,7 +158,7 @@ int pqissludp::Initiate_Connection() { std::ostringstream out; out << "Connecting to "; - out << sslcert -> Name() << " via "; + out << PeerId() << " via "; out << inet_ntoa(remote_addr.sin_addr); out << ":" << ntohs(remote_addr.sin_port); pqioutput(PQL_DEBUG_BASIC, pqissludpzone, out.str()); @@ -611,7 +189,7 @@ int pqissludp::Initiate_Connection() } else if ((tou_err == ENETUNREACH) || (tou_err == ETIMEDOUT)) { - out << "ENETUNREACHABLE: cert" << sslcert -> Name(); + out << "ENETUNREACHABLE: cert" << PeerId(); out << std::endl; // Then send unreachable message. @@ -677,7 +255,7 @@ int pqissludp::Basic_Connection_Complete() std::ostringstream out; out << "pqissludp::Basic_Connection_Complete()"; - out << "EINPROGRESS: cert" << sslcert -> Name(); + out << "EINPROGRESS: cert" << PeerId(); pqioutput(PQL_WARNING, pqissludpzone, out.str()); } @@ -686,7 +264,7 @@ int pqissludp::Basic_Connection_Complete() std::ostringstream out; out << "pqissludp::Basic_Connection_Complete()"; out << "ENETUNREACH/ETIMEDOUT: cert"; - out << sslcert -> Name() << std::endl; + out << PeerId() << std::endl; net_unreachable |= net_attempt; @@ -763,22 +341,7 @@ int pqissludp::net_internal_fcntl_nonblock(int fd) int pqissludp::tick() { - /* check the udpproxy, if we should be listening */ - if ((waiting == WAITING_NOT) && (sslcert -> Listening())) - { - if (time(NULL) > listen_checktime) - { - listen_checktime = time(NULL) + - PQI_SSLUDP_PROXY_CHECK_TIME; - - /* check the Proxy anyway (every xxx secs) */ - Check_Proxy_Connection(); - } - - } - pqissl::tick(); - udpproxy->tick(); return 1; } @@ -787,20 +350,20 @@ int pqissludp::listen() { { std::ostringstream out; - out << "pqissludp::listen()"; + out << "pqissludp::listen() (NULLOP)"; pqioutput(PQL_ALERT, pqissludpzone, out.str()); } - return udpproxy->listen(); + return 1; //udpproxy->listen(); } int pqissludp::stoplistening() { { std::ostringstream out; - out << "pqissludp::stoplistening()"; + out << "pqissludp::stoplistening() (NULLOP)"; pqioutput(PQL_ALERT, pqissludpzone, out.str()); } - return udpproxy->stoplistening(); + return 1; //udpproxy->stoplistening(); } @@ -839,7 +402,7 @@ bool pqissludp::moretoread() std::ostringstream out; out << "pqissludp::moretoread() "; - out << "EAGAIN/EINPROGRESS: cert" << sslcert -> Name(); + out << "EAGAIN/EINPROGRESS: cert" << PeerId(); pqioutput(PQL_WARNING, pqissludpzone, out.str()); return 0; @@ -849,7 +412,7 @@ bool pqissludp::moretoread() std::ostringstream out; out << "pqissludp::moretoread() "; out << "ENETUNREACH/ETIMEDOUT: cert"; - out << sslcert -> Name(); + out << PeerId(); pqioutput(PQL_WARNING, pqissludpzone, out.str()); } @@ -858,7 +421,7 @@ bool pqissludp::moretoread() std::ostringstream out; out << "pqissludp::moretoread() "; out << "EBADF: cert"; - out << sslcert -> Name(); + out << PeerId(); pqioutput(PQL_WARNING, pqissludpzone, out.str()); } @@ -867,7 +430,7 @@ bool pqissludp::moretoread() std::ostringstream out; out << "pqissludp::moretoread() "; out << " Unknown ERROR: " << err << ": cert"; - out << sslcert -> Name(); + out << PeerId(); pqioutput(PQL_WARNING, pqissludpzone, out.str()); } @@ -898,410 +461,3 @@ bool pqissludp::cansend() -pqiudplistener::pqiudplistener(p3udpproxy *p, struct sockaddr_in addr) - :p3u(p), sockfd(-1), active(false), laststun(0), firstattempt(0), - lastattempt(0) -{ - pqioutput(PQL_DEBUG_BASIC, pqissludpzone, - "pqiudplistener::pqiudplistener()"); - - setListenAddr(addr); - setuplisten(); - - stunpkt = malloc(1024); /* 20 = size of a stun request */ - stunpktlen = 1024; -} - - -int pqiudplistener::setListenAddr(struct sockaddr_in addr) -{ - laddr = addr; - // increment the port by 1. (can't open on same) - laddr.sin_port = htons(ntohs(laddr.sin_port) + 1); - - return 1; -} - -int pqiudplistener::resetlisten() -{ - if (sockfd > -1) - { - /* close it down */ - tou_close(sockfd); - sockfd = -1; - } - active = false; - return 1; -} - -int pqiudplistener::setuplisten() -{ - sockfd = tou_socket(0,0,0); - if (0 == tou_bind(sockfd, (struct sockaddr *) &laddr, sizeof(laddr))) - { - active = true; - pqioutput(PQL_DEBUG_BASIC, pqissludpzone, "pqiudplistener::setuplisten Succeeded!"); - return 1; - } - active = false; - pqioutput(PQL_DEBUG_BASIC, pqissludpzone, "pqiudplistener::setuplisten Failed!"); - - std::cerr << "pqiudplistener failed to bind to :" << inet_ntoa(laddr.sin_addr); - std::cerr << ":" << ntohs(laddr.sin_port) << std::endl; - return 0; -} - -int pqiudplistener::status() -{ - - return 1; -} - -int pqiudplistener::tick() -{ - int dsize = 1024; - char data[dsize]; - struct sockaddr_in addr, pot_ext_addr; - - /* must check if address is okay. - */ - if (!active) - { - /* can't do much ... */ - return 1; - } - - serverStun(); - - if (recvfrom(data, &dsize, addr)) - { - if (response(data, dsize, pot_ext_addr)) - { - checkExtAddr(addr, data, dsize, pot_ext_addr); - } - else - { - reply(data, dsize, addr); - } - } - - return 1; -} - -const int MIN_STUN_PERIOD = 24 * 60 * 60; /* 1 day */ -const int MIN_STUN_GAP = 10; /* seconds. */ -const int MAX_STUN_ATTEMPTS = 60; /* 6 * 10 sec attempts */ -const int STUN_RETRY_PERIOD = 10; // * 60; /* 20 minutes */ - -int pqiudplistener::serverStun() -{ - pqioutput(PQL_DEBUG_BASIC, pqissludpzone, "pqiudplistener::serverStun()"); - /* get the list from p3disc() */ - int ts = time(NULL); - if (!firstattempt) firstattempt = ts; - - /* if not stunned */ - if ((!laststun) && (ts - firstattempt > MAX_STUN_ATTEMPTS)) - { - pqioutput(PQL_DEBUG_BASIC, pqissludpzone, "pqiudplistener::Stun Paused!"); - /* will fail until RETRY_PERIOD */ - if (ts - firstattempt > STUN_RETRY_PERIOD) - { - firstattempt = ts; - } - - return 0; - } - - if (ts - laststun < MIN_STUN_PERIOD) - { - pqioutput(PQL_DEBUG_BASIC, pqissludpzone, "pqiudplistener::Stun Paused! 2"); - return 0; - } - - if (ts - lastattempt < MIN_STUN_GAP) - { - pqioutput(PQL_DEBUG_BASIC, pqissludpzone, "pqiudplistener::Stun Paused! 3"); - return 0; - } - - lastattempt = ts; - - /* stun someone */ - if (!p3u -> requestStunServer(stun_addr)) - { - pqioutput(PQL_DEBUG_BASIC, pqissludpzone, - "pqiudplistener::serverStun() No Stun Server"); - /* failed, wait a bit */ - return 0; - } - - /* send out a stun packet -> save in the local variable */ - - int tmplen = stunpktlen; - bool done = generate_stun_pkt(stunpkt, &tmplen); - if (!done) - return 0; - - /* increment the port +1 */ - stun_addr.sin_port = htons(ntohs(stun_addr.sin_port) + 1); - /* and send it off */ - // int sentlen = - tou_sendto(sockfd, stunpkt, tmplen, 0, - (const struct sockaddr *) &stun_addr, sizeof(stun_addr)); - - std::ostringstream out; - out << "pqiudplistener::serverStun() Sent Stun Packet to:"; - out << inet_ntoa(stun_addr.sin_addr) << ":" << ntohs(stun_addr.sin_port); - pqioutput(PQL_DEBUG_BASIC, pqissludpzone, out.str()); - - return 1; -} - - - -bool pqiudplistener::response(void *stun_pkt, int size, struct sockaddr_in &addr) -{ - /* check what type it is */ - if (size < 28) - { - return false; - } - - if (((uint16_t *) stun_pkt)[0] != 0x0101) - { - /* not a response */ - return false; - } - - /* iterate through the packet */ - /* for now assume the address follows the header directly */ - /* all stay in netbyteorder! */ - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = ((uint32_t *) stun_pkt)[6]; - addr.sin_port = ((uint16_t *) stun_pkt)[11]; - - - std::ostringstream out; - out << "pqiudplistener::response() Recvd a Stun Response, ext_addr: "; - out << inet_ntoa(addr.sin_addr) << ":" << ntohs(addr.sin_port); - pqioutput(PQL_ALERT, pqissludpzone, out.str()); - - return true; - -} - -int pqiudplistener::checkExtAddr(struct sockaddr_in &src_addr, - void *data, int size, struct sockaddr_in &ext_addr) -{ - - /* display it */ - { - std::ostringstream out; - out << "pqiudplistener::checkExtAddr(): received Stun Pkt" << std::endl; - out << "\t\text_addr: "; - out << inet_ntoa(ext_addr.sin_addr) << ":" << ntohs(ext_addr.sin_port); - out << std::endl; - out << "\t\tsrc_addr: "; - out << inet_ntoa(src_addr.sin_addr) << ":" << ntohs(src_addr.sin_port); - pqioutput(PQL_WARNING, pqissludpzone, out.str()); - } - - /* decide if its better than the current external address */ - - cert *own = getSSLRoot() -> getOwnCert(); - - - /* if src is same network as local, or it is not external ... then ignore */ - if ((sameNet(&(src_addr.sin_addr), &(own->localaddr.sin_addr))) || - (!isExternalNet(&(src_addr.sin_addr)))) - { - std::ostringstream out; - out << "Cannot use returned StunAddr:"; - out << " srcAddr !Ext || sameNet(srcAddr, localAddr)"; - pqioutput(PQL_WARNING, pqissludpzone, out.str()); - return 0; - } - - /* if extAddr is not ext, then don't accept */ - if (!isExternalNet(&(ext_addr.sin_addr))) - { - std::ostringstream out; - out << "Cannot use returned StunAddr:"; - out << " returnedAddr is !External"; - pqioutput(PQL_WARNING, pqissludpzone, out.str()); - return 0; - } - - /* port is harder.... - * there are a couple of cases. - * --- NOT Firewalled --------------------- - * (1) ext = local, port should = local.port. - * --- Firewalled --------------------- - * (2) own->Forwarded(), keep old port number. - * (3) behind firewall -> port is irrelevent, can't connect. put 0. - */ - - /* default is case (3) */ - unsigned short server_port = 0; - /* incase they have actually forwarded a port, set it correct! */ - server_port = ntohs(ext_addr.sin_port) - 1; - - if (isValidNet(&(own->serveraddr.sin_addr))) - { - /* Final extra check.... - * if src Address is same network as current server addr... - * then its not far enough away - */ - - /*************************** - * ... but until network is well established we wont switch this - * rule on... - * - if (isSameNet(src_addr, own->serveraddr)) - { - std::ostringstream out; - out << "Cannot use returned StunAddr:"; - out << " sameNet(srcAddr, current srvAddr)"; - pqioutput(PQL_WARNING, pqissludpzone, out.str()); - return 0; - } - * - * - **************************/ - - /* port case (2) */ - if (own->Forwarded()) - { - /* this *MUST* have been set by the user, so - * keep the port number.... - */ - server_port = ntohs(own->serveraddr.sin_port); - - std::ostringstream out; - out << "We are marked as Forwarded(), using existing port: "; - out << server_port; - pqioutput(PQL_WARNING, pqissludpzone, out.str()); - } - } - - /* port case (1) */ - if (0 == inaddr_cmp(ext_addr, own->localaddr)) - { - server_port = ntohs(own->localaddr.sin_port); - { - std::ostringstream out; - out << "extAddr == localAddr, Not Firewalled() + using local port: "; - out << server_port; - pqioutput(PQL_WARNING, pqissludpzone, out.str()); - } - - /* if it is the same as local address -> then not firewalled */ - if (own->Firewalled()) - { - std::ostringstream out; - out << "We are currently Marked as Firewalled, changing to NotFirewalled()"; - own->Firewalled(false); - pqioutput(PQL_WARNING, pqissludpzone, out.str()); - } - } - - /* otherwise we will take the addr */ - own->serveraddr = ext_addr; - - /* set the port number finally */ - own->serveraddr.sin_port = htons(server_port); - - /* save timestamp of successful stun */ - laststun = time(NULL); - - return 1; -} - - -/************************** Basic Functionality ******************/ -int pqiudplistener::recvfrom(void *data, int *size, struct sockaddr_in &addr) -{ - /* check the socket */ - socklen_t addrlen = sizeof(addr); - - int rsize = tou_recvfrom(sockfd, data, *size, 0, (struct sockaddr *) &addr, &addrlen); - if (rsize > 0) - { - std::ostringstream out; - out << "pqiudplistener::recvfrom() Recved a Pkt from: "; - out << inet_ntoa(addr.sin_addr) << ":" << ntohs(addr.sin_port); - pqioutput(PQL_ALERT, pqissludpzone, out.str()); - - *size = rsize; - return 1; - } - return 0; -} - -int pqiudplistener::reply(void *data, int size, struct sockaddr_in &addr) -{ - /* so we design a new packet with the external address in it */ - int pktlen = 0; - void *pkt = generate_stun_reply(&addr, &pktlen); - - /* and send it off */ - int sentlen = tou_sendto(sockfd, pkt, pktlen, 0, - (const struct sockaddr *) &addr, sizeof(addr)); - - free(pkt); - - /* display status */ - std::ostringstream out; - out << "pqiudplistener::reply() Responding to a Stun Req, ext_addr: "; - out << inet_ntoa(addr.sin_addr) << ":" << ntohs(addr.sin_port); - pqioutput(PQL_ALERT, pqissludpzone, out.str()); - - return sentlen; -} - -bool pqiudplistener::generate_stun_pkt(void *stun_pkt, int *len) -{ - if (*len < 20) - { - return false; - } - - /* just the header */ - ((uint16_t *) stun_pkt)[0] = 0x0001; - ((uint16_t *) stun_pkt)[1] = 0x0020; /* only header */ - /* transaction id - should be random */ - ((uint32_t *) stun_pkt)[1] = 0x0020; - ((uint32_t *) stun_pkt)[2] = 0x0121; - ((uint32_t *) stun_pkt)[3] = 0x0111; - ((uint32_t *) stun_pkt)[4] = 0x1010; - *len = 20; - return true; -} - - -void *pqiudplistener::generate_stun_reply(struct sockaddr_in *stun_addr, int *len) -{ - /* just the header */ - void *stun_pkt = malloc(28); - ((uint16_t *) stun_pkt)[0] = 0x0101; - ((uint16_t *) stun_pkt)[1] = 0x0028; /* only header + 8 byte addr */ - /* transaction id - should be random */ - ((uint32_t *) stun_pkt)[1] = 0x0020; - ((uint32_t *) stun_pkt)[2] = 0x0121; - ((uint32_t *) stun_pkt)[3] = 0x0111; - ((uint32_t *) stun_pkt)[4] = 0x1010; - /* now add address - * 0 1 2 3 - * - * - */ - - ((uint32_t *) stun_pkt)[6] = stun_addr->sin_addr.s_addr; - ((uint16_t *) stun_pkt)[11] = stun_addr->sin_port; - - *len = 28; - return stun_pkt; -} - - diff --git a/libretroshare/src/pqi/pqissludp.h b/libretroshare/src/pqi/pqissludp.h index 1a3f0737b..6b779c742 100644 --- a/libretroshare/src/pqi/pqissludp.h +++ b/libretroshare/src/pqi/pqissludp.h @@ -38,12 +38,6 @@ #include "pqi/pqissl.h" -// function for discovering certificates. -//int connectForExchange(struct sockaddr_in addr); -// -// -// -// /* So pqissludp is the special firewall breaking protocol. * This class will implement the basics of streaming * ssl over udp using a tcponudp library.... @@ -51,59 +45,8 @@ */ class pqissludp; -class pqiudpproxy; -class p3udpproxy; class cert; -/* no such thing as a listener .... actually each one - * can receive connections..... its the stateless you see!. - * - * so pqiudplistener - * - * will be the support udp listener for proxy connections. - * this will be used by the p3proxy for external addresses. - */ - -class pqiudplistener -{ - public: - - pqiudplistener(p3udpproxy *p, struct sockaddr_in addr); - -int resetlisten(); -int setListenAddr(struct sockaddr_in addr); -int setuplisten(); - -int tick(); /* does below */ -int status(); - -int recvfrom(void *data, int *size, struct sockaddr_in &addr); -int reply(void *data, int size, struct sockaddr_in &addr); - - private: -int serverStun(); -bool response(void *data, int size, struct sockaddr_in &addr); -int checkExtAddr(struct sockaddr_in &src_addr, - void *data, int size, struct sockaddr_in &ext_addr); - -bool generate_stun_pkt(void *stun_pkt, int *len); -void *generate_stun_reply(struct sockaddr_in *stun_addr, int *len); - - p3udpproxy *p3u; - - int sockfd; - struct sockaddr_in laddr; - bool active; - - int laststun, firstattempt, lastattempt; - - /* last stun packet sent out */ - struct sockaddr_in stun_addr; - void *stunpkt; - int stunpktlen; -}; - - /* This provides a NetBinInterface, which is * primarily inherited from pqissl. * fns declared here are different -> all others are identical. @@ -112,7 +55,7 @@ void *generate_stun_reply(struct sockaddr_in *stun_addr, int *len); class pqissludp: public pqissl { public: - pqissludp(cert *c, PQInterface *parent, pqiudpproxy *prxy); + pqissludp(PQInterface *parent); virtual ~pqissludp(); // NetInterface. @@ -130,24 +73,13 @@ virtual bool cansend(); virtual bool bandwidthLimited() { return true; } // pqissludp specific. - // These three functions must - // be called to initiate a connection; - -int attach(sockaddr_in&); - // stun packet handling. -void *generate_stun_pkt(struct sockaddr_in *stun_addr, int *len); -int getStunReturnedAddr(void *pkt, int len, struct sockaddr_in *stun_addr); + // called to initiate a connection; +int attach(); protected: -virtual int Request_Proxy_Connection();// Overloaded -> all 7. -virtual int Check_Proxy_Connection(); -virtual int Request_Local_Address(); -virtual int Determine_Local_Address(); -virtual int Determine_Remote_Address(); virtual int Initiate_Connection(); virtual int Basic_Connection_Complete(); -virtual int Reattempt_Connection(); //protected internal fns that are overloaded for udp case. virtual int net_internal_close(int fd); @@ -157,16 +89,7 @@ virtual int net_internal_fcntl_nonblock(int fd); private: BIO *tou_bio; // specific to ssludp. - pqiudpproxy *udpproxy; - // are these needed at all?? - struct sockaddr_in local_addr; // ssludp - struct sockaddr_in firewall_addr; // ssludp - - - struct sockaddr_in stun_addr; //pqissl. - int stun_timeout; - int stun_attempts; int remote_timeout; int proxy_timeout; int udp_connect_timeout; diff --git a/libretroshare/src/pqi/pqistunner.cc b/libretroshare/src/pqi/pqistunner.cc deleted file mode 100644 index 1efbc82ea..000000000 --- a/libretroshare/src/pqi/pqistunner.cc +++ /dev/null @@ -1,264 +0,0 @@ -/* - * "$Id: pqistunner.cc,v 1.2 2007-02-18 21:46:50 rmf24 Exp $" - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2004-2006 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 "pqi/pqistunner.h" -#include "tcponudp/tou.h" - -#include "pqi/pqidebug.h" -#include - -const int pqistunzone = 13754; - - -pqistunner::pqistunner(struct sockaddr_in addr) - :sockfd(-1), active(false) -{ - pqioutput(PQL_ALERT, pqistunzone, - "pqistunner::pqistunner()"); - - setListenAddr(addr); - setuplisten(); - - stunpkt = malloc(1024); /* 20 = size of a stun request */ - stunpktlen = 1024; -} - - -int pqistunner::setListenAddr(struct sockaddr_in addr) -{ - laddr = addr; - // increment the port by 1. (can't open on same) - laddr.sin_port = htons(ntohs(laddr.sin_port) + 1); - - return 1; -} - -int pqistunner::resetlisten() -{ - if (sockfd > -1) - { - /* close it down */ - std::ostringstream out; - out << "pqistunner::resetlisten() Closed stun port"; - pqioutput(PQL_ALERT, pqistunzone, out.str()); - - tou_close(sockfd); - sockfd = -1; - } - active = false; - return 1; -} - -int pqistunner::setuplisten() -{ - sockfd = tou_socket(0,0,0); - if (0 == tou_bind(sockfd, (struct sockaddr *) &laddr, sizeof(laddr))) - { - active = true; - std::ostringstream out; - out << "pqistunner::setuplisten() Attached to Listen Address: "; - out << inet_ntoa(laddr.sin_addr) << ":" << ntohs(laddr.sin_port); - pqioutput(PQL_ALERT, pqistunzone, out.str()); - } - else - { - pqioutput(PQL_ALERT, pqistunzone, "pqistunner::setuplisten Failed!"); - } - return 1; -} - -int pqistunner::stun(struct sockaddr_in stun_addr) -{ - pqioutput(PQL_DEBUG_BASIC, pqistunzone, "pqistunner::stun()"); - - /* send out a stun packet -> save in the local variable */ - if (!active) - { - pqioutput(PQL_ALERT, pqistunzone, "pqistunner::stun() Not Active!"); - return 0; - } - - int tmplen = stunpktlen; - bool done = generate_stun_pkt(stunpkt, &tmplen); - if (!done) - { - pqioutput(PQL_ALERT, pqistunzone, "pqistunner::stun() Failed!"); - return 0; - } - - /* increment the port +1 */ - stun_addr.sin_port = htons(ntohs(stun_addr.sin_port) + 1); - /* and send it off */ - int sentlen = tou_sendto(sockfd, stunpkt, stunpktlen, 0, - (const struct sockaddr *) &stun_addr, sizeof(stun_addr)); - - std::ostringstream out; - out << "pqistunner::stun() Sent Stun Packet(" << sentlen << ") from:"; - out << inet_ntoa(laddr.sin_addr) << ":" << ntohs(laddr.sin_port); - out << " to:"; - out << inet_ntoa(stun_addr.sin_addr) << ":" << ntohs(stun_addr.sin_port); - pqioutput(PQL_ALERT, pqistunzone, out.str()); - - return 1; -} - - - -bool pqistunner::response(void *stun_pkt, int size, struct sockaddr_in &addr) -{ - /* check what type it is */ - if (size < 28) - { - return false; - } - - if (((uint16_t *) stun_pkt)[0] != 0x0101) - { - /* not a response */ - return false; - } - - /* iterate through the packet */ - /* for now assume the address follows the header directly */ - /* all stay in netbyteorder! */ - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = ((uint32_t *) stun_pkt)[6]; - addr.sin_port = ((uint16_t *) stun_pkt)[11]; - - - std::ostringstream out; - out << "pqistunner::response() Recvd a Stun Response, ext_addr: "; - out << inet_ntoa(addr.sin_addr) << ":" << ntohs(addr.sin_port); - pqioutput(PQL_ALERT, pqistunzone, out.str()); - - return true; - -} - - - -/************************** Basic Functionality ******************/ -int pqistunner::recvfrom(void *data, int *size, struct sockaddr_in &addr) -{ - if (!active) - { - pqioutput(PQL_ALERT, pqistunzone, "pqistunner::recvfrom() Not Active!"); - return 0; - } - - /* check the socket */ - socklen_t addrlen = sizeof(addr); - - int rsize = tou_recvfrom(sockfd, data, *size, 0, (struct sockaddr *) &addr, &addrlen); - if (rsize > 0) - { - std::ostringstream out; - out << "pqistunner::recvfrom() Recvd a Pkt on: "; - out << inet_ntoa(laddr.sin_addr) << ":" << ntohs(laddr.sin_port); - out << " from: "; - out << inet_ntoa(addr.sin_addr) << ":" << ntohs(addr.sin_port); - pqioutput(PQL_ALERT, pqistunzone, out.str()); - - *size = rsize; - return 1; - } - return 0; -} - -int pqistunner::reply(void *data, int size, struct sockaddr_in &addr) -{ - /* so we design a new packet with the external address in it */ - int pktlen = 0; - void *pkt = generate_stun_reply(&addr, &pktlen); - - /* and send it off */ - int sentlen = tou_sendto(sockfd, pkt, pktlen, 0, - (const struct sockaddr *) &addr, sizeof(addr)); - - { - std::ostringstream out; - out << "pqistunner::reply() Replying from: "; - out << inet_ntoa(laddr.sin_addr) << ":" << ntohs(laddr.sin_port); - out << " to: "; - out << inet_ntoa(addr.sin_addr) << ":" << ntohs(addr.sin_port); - pqioutput(PQL_ALERT, pqistunzone, out.str()); - } - - free(pkt); - - /* display status */ - - return sentlen; -} - -bool pqistunner::generate_stun_pkt(void *stun_pkt, int *len) -{ - if (*len < 20) - { - return false; - } - - /* just the header */ - ((uint16_t *) stun_pkt)[0] = 0x0001; - ((uint16_t *) stun_pkt)[1] = 0x0020; /* only header */ - /* transaction id - should be random */ - ((uint32_t *) stun_pkt)[1] = 0x0020; - ((uint32_t *) stun_pkt)[2] = 0x0121; - ((uint32_t *) stun_pkt)[3] = 0x0111; - ((uint32_t *) stun_pkt)[4] = 0x1010; - *len = 20; - return true; -} - - -void *pqistunner::generate_stun_reply(struct sockaddr_in *stun_addr, int *len) -{ - /* just the header */ - void *stun_pkt = malloc(28); - ((uint16_t *) stun_pkt)[0] = 0x0101; - ((uint16_t *) stun_pkt)[1] = 0x0028; /* only header + 8 byte addr */ - /* transaction id - should be random */ - ((uint32_t *) stun_pkt)[1] = 0x0020; - ((uint32_t *) stun_pkt)[2] = 0x0121; - ((uint32_t *) stun_pkt)[3] = 0x0111; - ((uint32_t *) stun_pkt)[4] = 0x1010; - /* now add address - * 0 1 2 3 - * - * - */ - - ((uint32_t *) stun_pkt)[6] = stun_addr->sin_addr.s_addr; - ((uint16_t *) stun_pkt)[11] = stun_addr->sin_port; - - *len = 28; - return stun_pkt; -} - - diff --git a/libretroshare/src/pqi/pqitunnel.cc b/libretroshare/src/pqi/pqitunnel.cc deleted file mode 100644 index 95fda7002..000000000 --- a/libretroshare/src/pqi/pqitunnel.cc +++ /dev/null @@ -1,403 +0,0 @@ -/* - * "$Id: pqitunnel.cc,v 1.4 2007-02-18 21:46:50 rmf24 Exp $" - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2004-2006 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 "pqi/pqitunnel.h" - -const int pqitunnelzone = 60478; -#include "pqi/pqidebug.h" -#include - - -PQTunnel::PQTunnel(int st) - :PQItem(PQI_ITEM_TYPE_TUNNELITEM, st) -{ - pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, - "PQTunnel::PQTunnel() Creation..."); - - return; -} - -PQTunnel::~PQTunnel() -{ -} - -// This is commented out - because -// it should never be cloned at this level! -// -//PQTunnel *PQTunnel::clone() -//{ -// pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, -// "PQTunnel::clone"); -// -// PQTunnel *t = new PQTunnel(subtype); -// t -> copy(this); -// return t; -//} - -void PQTunnel::copy(const PQTunnel *src) -{ - pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, - "PQTunnel::copy() : Only the Base!"); - PQItem::copy(src); -} - -std::ostream &PQTunnel::print(std::ostream &out) -{ - out << "-------- PQTunnel"; - PQItem::print(out); - - out << "PQTunnel size:" << getSize(); - out << "--------" << std::endl; - return out; -} - - -//const int PQTunnel::getSize() const -//{ -// return size; -//} -// -//const void *PQTunnel::getData() const -//{ -// return data; -//} -// -//int PQTunnel::out(void *dta, const int n) const -//{ -// pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, -// "PQTunnel::out()"); -// -// if ((dta == NULL) || (data == NULL)) -// { -// return -1; -// } -// if (size == 0) -// { -// return 0; -// } -// -// if (n < size) -// return -1; -// memcpy(dta, data, size); -// return size; -//} -// -//int PQTunnel::in(const void *dta, const int n) -//{ -// pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, -// "PQTunnel::in()"); -// -// if (data) -// { -// if (n != size) -// { -// free(data); -// data = malloc(n); -// size = n; -// } -// } -// else -// { -// data = malloc(n); -// size = n; -// } -// -// memcpy(data, dta, size); -// return 1; -//} - -PQTunnelInit::PQTunnelInit(int st) - :PQItem(PQI_ITEM_TYPE_TUNNELINITITEM, st), mode(Request) -{ - pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, - "PQTunnelInit::PQTunnelInit()"); - return; -} - -PQTunnelInit::~PQTunnelInit() -{ - return; -} - - -PQTunnelInit *PQTunnelInit::clone() -{ - pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, - "PQTunnelInit::clone()"); - - PQTunnelInit *ni = new PQTunnelInit(subtype); - ni -> copy(this); - return ni; -} - -void PQTunnelInit::copy(const PQTunnelInit *item) -{ - pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, - "PQTunnelInit::copy()"); - - PQItem::copy(item); - - mode = item -> mode; -} - -std::ostream &PQTunnelInit::print(std::ostream &out) -{ - out << "---- ---- PQTunnelInit" << std::endl; - PQItem::print(out); - out << "mode: "; - switch(mode) - { - case Request: - out << "Request" << std::endl; - break; - case Connect: - out << "Connect" << std::endl; - break; - case End: - out << "End" << std::endl; - break; - default: - out << "Unknown" << std::endl; - break; - } - - out << "---- ----" << std::endl; - - return out; -} - -const int PQTunnelInit::getSize() const -{ - return 4; -} - -int PQTunnelInit::out(void *data, const int size) const -{ - if (size < PQTunnelInit::getSize()) - return -1; - ((int *) data)[0] = (int) mode; - return PQTunnelInit::getSize(); -} - - -int PQTunnelInit::in(const void *data, const int size) -{ - if (size < PQTunnelInit::getSize()) - return -1; - mode = (InitMsg) ((int *) data)[0]; - return PQTunnelInit::getSize(); -} - -PQTunnelServer::PQTunnelServer() -{ - pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, - "PQTunnelServer::PQTunnelServer()"); - - rrit = services.begin(); - return; -} - -int PQTunnelServer::addService(PQTunnelService *ts) -{ - pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, - "PQTunnelServer::addService()"); - - std::map::iterator it; - it = services.find(ts -> getSubType()); - if (it != services.end()) - { - // it exists already! - return -1; - } - - services[ts -> getSubType()] = ts; - rrit = services.begin(); - return 1; -} - -int PQTunnelServer::incoming(PQItem *item) -{ - pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, - "PQTunnelServer::incoming()"); - - { - std::ostringstream out; - out << "PQTunnelServer::incoming() Service: "; - out << item -> subtype << std::endl; - out << "Item:" << std::endl; - item -> print(out); - out << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, out.str()); - } - - std::map::iterator it; - it = services.find(item -> subtype); - if (it == services.end()) - { - pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, - "PQTunnelServer::incoming() Service: No Service - deleting"); - - // delete it. - delete item; - - // it exists already! - return -1; - } - - switch(item -> type) - { - case PQI_ITEM_TYPE_TUNNELITEM: - { - std::ostringstream out; - out << "PQTunnelServer::incoming() Sending to"; - out << it -> second << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, out.str()); - - return (it->second) -> receive((PQTunnel *) item); - } - break; - case PQI_ITEM_TYPE_TUNNELINITITEM: - { - std::ostringstream out; - out << "PQTunnelServer::incoming() Sending to"; - out << it -> second << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, out.str()); - - return (it->second) -> receive((PQTunnelInit *) item); - } - break; - default: - break; - } - delete item; - return -1; -} - - - -PQItem *PQTunnelServer::outgoing() -{ - pqioutput(PQL_DEBUG_ALL, pqitunnelzone, - "PQTunnelServer::outgoing()"); - - if (rrit != services.end()) - { - rrit++; - } - else - { - rrit = services.begin(); - } - - std::map::iterator sit = rrit; - // run to the end. - PQItem *item; - - // run through to the end, - for(;rrit != services.end();rrit++) - { - // send out init items first. - if (NULL != (item = (rrit -> second) -> sendInit())) - { - std::ostringstream out; - out << "PQTunnelServer::outgoing() Got InitItem From:"; - out << rrit -> second << std::endl; - - item -> print(out); - out << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, out.str()); - return item; - } - if (NULL != (item = (rrit -> second) -> send())) - { - std::ostringstream out; - out << "PQTunnelServer::outgoing() Got Item From:"; - out << rrit -> second << std::endl; - - item -> print(out); - out << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, out.str()); - return item; - } - } - - // from the beginning to where we started. - for(rrit = services.begin();rrit != sit; rrit++) - { - if (NULL != (item = (rrit -> second) -> sendInit())) - { - std::ostringstream out; - out << "PQTunnelServer::outgoing() Got InitItem From:"; - out << rrit -> second << std::endl; - - item -> print(out); - out << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, out.str()); - return item; - } - if (NULL != (item = (rrit -> second) -> send())) - { - std::ostringstream out; - out << "PQTunnelServer::outgoing() Got Item From:"; - out << rrit -> second << std::endl; - - item -> print(out); - out << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, out.str()); - return item; - } - } - return NULL; -} - - - -int PQTunnelServer::tick() -{ - pqioutput(PQL_DEBUG_ALL, pqitunnelzone, - "PQTunnelServer::tick()"); - - std::map::iterator it; - - // from the beginning to where we started. - for(it = services.begin();it != services.end(); it++) - { - std::ostringstream out; - out << "PQTunnelServer::service id:" << it -> first; - out << " -> Service: " << it -> second; - out << std::endl; - pqioutput(PQL_DEBUG_ALL, pqitunnelzone, out.str()); - - // now we should actually tick the service. - (it -> second) -> tick(); - } - return 1; -} - - - diff --git a/libretroshare/src/pqi/pqitunnel.h b/libretroshare/src/pqi/pqitunnel.h deleted file mode 100644 index b1e57d3e9..000000000 --- a/libretroshare/src/pqi/pqitunnel.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * "$Id: pqitunnel.h,v 1.3 2007-02-18 21:46:50 rmf24 Exp $" - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2004-2006 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 PQI_TUNNEL_HEADER -#define PQI_TUNNEL_HEADER - -#include "pqi/pqi_base.h" - -// PQI Tunnel, this is a raw tunnel of data. -// The bottom layer on which other services -// can run on. -// -// these packets get passed through the -// server, to a service that is registered. -// -// example services: -// proxytunnel. -> p3proxy. -// sockettunnel -// -> either broadcast (attach to -// open socket instead -// of broadcast address) -// -> or requested/signon. -// -// games, -// voice -// video -// - -class PQTunnel: public PQItem -{ - // private copy constructor... prevent copying... - PQTunnel(const PQTunnel &) {return; } -protected: - PQTunnel(int st); // initialise with subtypes. -public: -virtual ~PQTunnel(); - - // copy functions. -//virtual PQTunnel *clone() = 0; -void copy(const PQTunnel *src); - -// These will be made pure virtual. -virtual const int getSize() const { return 0; } -virtual int out(void *data, const int size) const { return 0;} -virtual int in(const void *data, const int size) { return 0;} - // an overloaded - // fn that will - // mean the building - // fns will be attached. - // to the class. and - // dont have to - -virtual std::ostream &print(std::ostream &out); - -// int size; -// void *data; -}; - - - - -class PQTunnelInit: public PQItem -{ - // private copy constructor... prevent copying... - PQTunnelInit(const PQTunnelInit &) {return; } -protected: - PQTunnelInit(int st); // initialise with subtypes. -public: -virtual ~PQTunnelInit(); - - // copy functions. -virtual PQTunnelInit *clone(); -void copy(const PQTunnelInit *src); - -std::ostream &print(std::ostream &out); - - // These are overloaded from PQTunnelInit. - // these should be able to construct + destruct - // the whole packet from here. - virtual const int getSize() const; - virtual int out(void *data, const int size) const; // write - virtual int in(const void *data, const int size); // read, - - enum InitMsg { Request, Connect, End }; - InitMsg mode; -}; - - -class PQTunnelService -{ - protected: - - PQTunnelService(int s) // our type of packets. - :subtype(s) { return; } - -virtual ~PQTunnelService() { return; } - - public: - // -virtual int receive(PQTunnel *) = 0; -virtual PQTunnel * send() = 0; - -virtual int receive(PQTunnelInit *) = 0; -virtual PQTunnelInit * sendInit() = 0; - -int getSubType() { return subtype; } - -virtual int tick() { return 1; } - - private: - int subtype; -}; - -#include - - -class PQTunnelServer -{ -public: - PQTunnelServer(); - -int addService(PQTunnelService *); - -int incoming(PQItem *); -PQItem *outgoing(); - -int tick(); - -private: - -std::map services; -std::map::iterator rrit; - -}; - - - - - - - - - -#endif // PQI_TUNNEL_HEADER diff --git a/libretroshare/src/pqi/pqitunnelproxy.cc b/libretroshare/src/pqi/pqitunnelproxy.cc deleted file mode 100644 index c7f49ad02..000000000 --- a/libretroshare/src/pqi/pqitunnelproxy.cc +++ /dev/null @@ -1,389 +0,0 @@ -/* - * "$Id: pqitunnelproxy.cc,v 1.4 2007-02-18 21:46:50 rmf24 Exp $" - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2004-2006 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 "pqi/pqitunnelproxy.h" - -PQTunnel *createPQTunnelProxy(void *d, int n) -{ - return new PQTunnelProxy(); -} - - -PQTunnelInit *createPQTunnelProxyInit(void *d, int n) -{ - return new PQTunnelProxyInit(); -} - - -PQTunnelProxy::PQTunnelProxy() -:PQTunnel(PQI_TUNNEL_PROXY_TYPE), seq(0), size(0), data(NULL) -{ - return; -} - -PQTunnelProxy::~PQTunnelProxy() -{ - if (data) - free(data); -} - - - // copy functions. -PQTunnelProxy *PQTunnelProxy::clone() -{ - PQTunnelProxy *item = new PQTunnelProxy(); - item -> copy(this); - return item; -} - - - -void PQTunnelProxy::copy(const PQTunnelProxy *item) -{ - // copy parents. - PQTunnel::copy(item); - - if (data) - free(data); - size = 0; - size = item -> PQTunnelProxy::getSize() - PQTunnelProxy::getSize(); - data = malloc(size); - - seq = item -> seq; - src = item -> src; - dest = item -> dest; - //proxy = item -> proxy; - - memcpy(data, item -> data, size); - memcpy(sign, item -> sign, PQI_TUNNEL_SIGN_SIZE); -} - - -int PQTunnelProxy::out(void *dta, const int n) const -{ - //std::cerr << "PQTunnelProxy::out()" << std::endl; - if (n < PQTunnelProxy::getSize()) - { - std::cerr << "PQTunnelProxy::out() Failed 1" << std::endl; - return -1; - } - - if (PQTunnel::getSize() != PQTunnel::out(dta, n)) - { - std::cerr << "PQTunnelProxy::out() Failed 2" << std::endl; - return -1; - } - - if (n < PQTunnelProxy::getSize()) - return -1; - char *ptr = (char *) dta; - ptr += PQTunnel::getSize(); - - - memcpy(ptr, &seq, 4); - ptr += 4; - memcpy(ptr, src.data, CERTSIGNLEN); - ptr += CERTSIGNLEN; - memcpy(ptr, dest.data, CERTSIGNLEN); - ptr += CERTSIGNLEN; - - memcpy(ptr, data, size); - ptr += size; - - memcpy(ptr, sign, PQI_TUNNEL_SIGN_SIZE); - ptr += PQI_TUNNEL_SIGN_SIZE; - - return PQTunnelProxy::getSize(); -} - -// The Size -int PQTunnelProxy::in(const void *dta, const int n) -{ - //std::cerr << "PQTunnelProxy::in()" << std::endl; - - if ((dta == NULL) || (n < PQTunnelProxy::getSize())) - { - std::cerr << "PQTunnelProxy::in() Failed 1" << std::endl; - if (dta == NULL) - std::cerr << "PQTunnelProxy::in() dta==NULL" << std::endl; - std::cerr << "PQTunnelProxy::in() is? n: " << n << " < "; - std::cerr << PQTunnelProxy::getSize() << std::endl; - if (n < PQTunnelProxy::getSize()) - std::cerr << "PQTunnelProxy::in() not Enough Space" << std::endl; - - return -1; - } - - if (PQTunnel::getSize() != PQTunnel::in(dta, n)) - { - std::cerr << "PQTunnelProxy::in() Failed 2" << std::endl; - return -1; - } - - // range check size. - if (data) - { - if (n != PQTunnelProxy::getSize()) - { - free(data); - size = 0; - size = n - PQTunnelProxy::getSize(); - data = malloc(size); - } - } - else - { - size = 0; - size = n - PQTunnelProxy::getSize(); - data = malloc(size); - } - - char *ptr = (char *) dta; - ptr += PQTunnel::getSize(); - - memcpy(&seq, ptr, 4); - ptr += 4; - memcpy(src.data, ptr, CERTSIGNLEN); - ptr += CERTSIGNLEN; - memcpy(dest.data, ptr, CERTSIGNLEN); - ptr += CERTSIGNLEN; - - memcpy(data, ptr, size); - ptr += size; - - memcpy(sign, ptr, PQI_TUNNEL_SIGN_SIZE); - ptr += PQI_TUNNEL_SIGN_SIZE; - - return PQTunnelProxy::getSize(); -} - -const int PQTunnelProxy::getSize() const -{ - //std::cerr << "PQTunnelProxy::getSize()" << std::endl; - return PQTunnel::getSize() + sizeof(long) + - CERTSIGNLEN * 2 + - + size + PQI_TUNNEL_SIGN_SIZE; -} - - -#include "pqipacket.h" - -std::ostream &PQTunnelProxy::print(std::ostream &out) -{ - out << "-------- PQTunnelProxy" << std::endl; - PQItem::print(out); - - out << "-------- -------- Tunnelling" << std::endl; - PQItem *pkt = NULL; - if ((data == NULL) || (size == 0)) - { - out << "NULL Pkt" << std::endl; - } - else if (pqipkt_check(data, size)) - { - pkt = pqipkt_create(data); - } - - if (pkt == NULL) - { - out << "Unknown Packet Type" << std::endl; - } - else - { - pkt -> print(out); - delete pkt; - } - out << "-------- -------- " << std::endl; - return out << "-------- PQTunnelProxy" << std::endl; -} - - - -PQTunnelProxyInit::PQTunnelProxyInit() - :PQTunnelInit(PQI_TUNNEL_PROXY_TYPE), seq(0) -{ - return; -} - -PQTunnelProxyInit::~PQTunnelProxyInit() -{ - return; -} - -PQTunnelProxyInit *PQTunnelProxyInit::clone() -{ - PQTunnelProxyInit *ni = new PQTunnelProxyInit(); - ni -> copy(this); - return ni; -} - -void PQTunnelProxyInit::copy(const PQTunnelProxyInit *item) -{ - PQTunnelInit::copy(item); - - mode = item -> mode; - seq = item -> seq; - src = item -> src; - dest = item -> dest; - proxy = item -> proxy; - memcpy(challenge, item -> challenge, CERTSIGNLEN); - memcpy(sign, item -> sign, PQI_TUNNEL_SIGN_SIZE); - -} - - -std::ostream &PQTunnelProxyInit::print(std::ostream &out) -{ - out << "-----------------PQTunnelProxyInit" << std::endl; - PQTunnelInit::print(out); - out << "Mode: " << mode << std::endl; - out << "Seq: " << seq << std::endl; - - out << std::hex; - out << "Src: "; - int i; - for(i = 0; i < CERTSIGNLEN; i++) - { - out << ":" << (unsigned int) src.data[i]; - } - out << std::endl; - - out << "Proxy: "; - for(i = 0; i < CERTSIGNLEN; i++) - { - out << ":" << (unsigned int) proxy.data[i]; - } - out << std::endl; - - out << "Dest: "; - for(i = 0; i < CERTSIGNLEN; i++) - { - out << ":" << (unsigned int) dest.data[i]; - } - out << std::endl; - out << std::dec; - - out << "-----------------PQTunnelProxyInit" << std::endl; - - return out; -} - - -int PQTunnelProxyInit::out(void *dta, const int n) const -{ - //std::cerr << "PQTunnelProxyInit::out()" << std::endl; - if (n < PQTunnelProxyInit::getSize()) - { - std::cerr << "PQTunnelProxyInit::out() Failed 1" << std::endl; - return -1; - } - - if (PQTunnelInit::getSize() != PQTunnelInit::out(dta, n)) - { - std::cerr << "PQTunnelProxyInit::out() Failed 2" << std::endl; - return -1; - } - - - char *ptr = (char *) dta; - ptr += PQTunnelInit::getSize(); - - memcpy(ptr, &seq, 4); - ptr += 4; - memcpy(ptr, &mode, 4); - ptr += 4; - memcpy(ptr, src.data, CERTSIGNLEN); - ptr += CERTSIGNLEN; - memcpy(ptr, proxy.data, CERTSIGNLEN); - ptr += CERTSIGNLEN; - memcpy(ptr, dest.data, CERTSIGNLEN); - ptr += CERTSIGNLEN; - - memcpy(ptr, challenge, PQI_PROXY_CHALLENGE_SIZE); - ptr += PQI_PROXY_CHALLENGE_SIZE; - - memcpy(ptr, sign, PQI_TUNNEL_SIGN_SIZE); - ptr += PQI_TUNNEL_SIGN_SIZE; - - return PQTunnelProxyInit::getSize(); -} - - -int PQTunnelProxyInit::in(const void *dta, const int n) -{ - //std::cerr << "PQTunnelProxyInit::in()" << std::endl; - - if ((dta == NULL) || (n < PQTunnelProxyInit::getSize())) - { - std::cerr << "PQTunnelProxyInit::in() Failed 1" << std::endl; - - return -1; - } - - if (PQTunnelInit::getSize() != PQTunnelInit::in(dta, n)) - { - std::cerr << "PQTunnelProxyInit::in() Failed 2" << std::endl; - return -1; - } - - char *ptr = (char *) dta; - ptr += PQTunnelInit::getSize(); - - memcpy(&seq, ptr, 4); - ptr += 4; - memcpy(&mode, ptr, 4); - ptr += 4; - memcpy(src.data, ptr, CERTSIGNLEN); - ptr += CERTSIGNLEN; - memcpy(proxy.data, ptr, CERTSIGNLEN); - ptr += CERTSIGNLEN; - memcpy(dest.data, ptr, CERTSIGNLEN); - ptr += CERTSIGNLEN; - - memcpy(challenge, ptr, PQI_PROXY_CHALLENGE_SIZE); - ptr += PQI_PROXY_CHALLENGE_SIZE; - - memcpy(sign, ptr, PQI_TUNNEL_SIGN_SIZE); - ptr += PQI_TUNNEL_SIGN_SIZE; - - return PQTunnelProxyInit::getSize(); -} - - - -const int PQTunnelProxyInit::getSize() const -{ - //std::cerr << "PQTunnelProxyInit::getSize()" << std::endl; - - return PQTunnelInit::getSize() + - 2 * sizeof(long) + - 3 * CERTSIGNLEN + - PQI_PROXY_CHALLENGE_SIZE + - PQI_TUNNEL_SIGN_SIZE; -} - diff --git a/libretroshare/src/pqi/pqitunnelproxy.h b/libretroshare/src/pqi/pqitunnelproxy.h deleted file mode 100644 index 05a650a48..000000000 --- a/libretroshare/src/pqi/pqitunnelproxy.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * "$Id: pqitunnelproxy.h,v 1.3 2007-02-18 21:46:50 rmf24 Exp $" - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2004-2006 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 PQI_TUNNEL_PROXY_HEADER -#define PQI_TUNNEL_PROXY_HEADER - -#include "pqi/pqitunnel.h" - -#define PQI_TUNNEL_PROXY_TYPE 0x0024 - -#define PQI_TUNNEL_SIGN_SIZE 256 -#define PQI_TUNNEL_SHRT_SIGN_SIZE 16 -#define PQI_PROXY_CHALLENGE_SIZE 1024 - -// mode types... -#define PQI_TI_REQUEST 0x01 -#define PQI_TI_CONNECT 0x02 -#define PQI_TI_END 0x03 - -PQTunnel *createPQTunnelProxy(void *d, int n); -PQTunnelInit *createPQTunnelProxyInit(void *d, int n); -// defined at the end of header. - -class PQTunnelProxyInit: public PQTunnelInit -{ - // private copy constructor... prevent copying... - PQTunnelProxyInit(const PQTunnelProxyInit &) - :PQTunnelInit(PQI_TUNNEL_PROXY_TYPE) - {return; } - -public: - PQTunnelProxyInit(); -virtual ~PQTunnelProxyInit(); - - // copy functions. -virtual PQTunnelProxyInit *clone(); -void copy(const PQTunnelProxyInit *src); - - // These are overloaded from PQTunnelInit. -virtual const int getSize() const; -virtual int out(void *data, const int size) const; // write -virtual int in(const void *data, const int size); // read, - -std::ostream &print(std::ostream &out); - - long seq; - - int mode; - - // source - certsign src; - certsign proxy; - certsign dest; - - unsigned char challenge[PQI_PROXY_CHALLENGE_SIZE]; - unsigned char sign[PQI_TUNNEL_SIGN_SIZE]; - -}; - -// Data Via Proxy. - -class PQTunnelProxy: public PQTunnel -{ - // private copy constructor... prevent copying... - PQTunnelProxy(const PQTunnelProxy &) - :PQTunnel(PQI_TUNNEL_PROXY_TYPE) - {return; } - -public: - PQTunnelProxy(); -virtual ~PQTunnelProxy(); - - // copy functions. -virtual PQTunnelProxy *clone(); -void copy(const PQTunnelProxy *src); - -virtual const int getSize() const; -virtual int out(void *data, const int size) const; // write -virtual int in(const void *data, const int size); // read, - -std::ostream &print(std::ostream &out); - -//private: - // full redefinition of the data space. - - long seq; - - certsign src, dest; - - int size; - void *data; - - unsigned char sign[PQI_TUNNEL_SIGN_SIZE]; -}; - -#endif // PQI_TUNNEL_HEADER diff --git a/libretroshare/src/pqi/pqitunnelproxyudp.cc b/libretroshare/src/pqi/pqitunnelproxyudp.cc deleted file mode 100644 index 1a21bfabd..000000000 --- a/libretroshare/src/pqi/pqitunnelproxyudp.cc +++ /dev/null @@ -1,162 +0,0 @@ -/* - * "$Id: pqitunnelproxyudp.cc,v 1.3 2007-02-18 21:46:50 rmf24 Exp $" - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2004-2006 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 "pqi/pqitunnelproxyudp.h" - -PQProxyUdp::PQProxyUdp() - :type(0), ksize(0), key(NULL), connectMode(0) - { - return; - } - -PQProxyUdp::PQProxyUdp(void *data, int n) - :ksize(0), key(NULL), connectMode(0) - { - in(data, n); - } - - // construct from info. -PQProxyUdp::PQProxyUdp(struct sockaddr_in *proxyaddr, void *ikey, int n) - :type(PQI_TPUDP_TYPE_1), paddr(*proxyaddr), ksize(n), key(NULL), - connectMode(0) - - { - key = malloc(ksize); - memcpy(key, ikey, ksize); - } - -PQProxyUdp::PQProxyUdp(struct sockaddr_in *neighaddr, - struct sockaddr_in *peeraddr, int cMode) - :type(PQI_TPUDP_TYPE_2), - naddr(*neighaddr), - paddr(*peeraddr), - ksize(0), key(NULL), connectMode(cMode) - { - return; - } - -PQProxyUdp::~PQProxyUdp() -{ - if (key) - { - ksize = 0; - free(key); - } -} - -const int PQProxyUdp::getSize() const -{ - return sizeof(int) + 2 * sizeof(struct sockaddr_in) - + sizeof(int) + ksize; -} - -int PQProxyUdp::out(void *dta, const int n) const // write -{ - if (n < getSize()) - return -1; - - char *loc = (char *) dta; // so we can count bytes - int cs = sizeof(int); - memcpy(loc, &type, cs); - loc += cs; - cs = sizeof(struct sockaddr_in); - memcpy(loc, &naddr, cs); - loc += cs; - memcpy(loc, &paddr, cs); - loc += cs; - - /* add in ConnectMode */ - cs = sizeof(int); - memcpy(loc, &connectMode, cs); - loc += cs; - - if (ksize) - { - memcpy(loc, key, ksize); - } - loc += ksize; - - return getSize(); -} - -int PQProxyUdp::in(const void *dta, const int n) // read, -{ - if (key) - { - ksize = 0; - free(key); - key = NULL; - } - - if (n < getSize()) /* smaller than min ksize */ - { - std::cerr << "PQTunnelProxy::in() Failed (n < getSize())" << std::endl; - return -1; - } - - char *loc = (char *) dta; - int cs = sizeof(int); - memcpy(&type, loc, cs); - loc += cs; - cs = sizeof(struct sockaddr_in); - memcpy(&naddr, loc, cs); - loc += cs; - memcpy(&paddr, loc, cs); - loc += cs; - - /* get in ConnectMode */ - cs = sizeof(int); - memcpy(&connectMode,loc, cs); - loc += cs; - - ksize = 0; - ksize = n - getSize(); - if (ksize) - { - key = malloc(ksize); - memcpy(key, loc, ksize); - } - return getSize(); /* should be equal to n */ -} - - -std::ostream &PQProxyUdp::print(std::ostream &out) -{ - out << "-------- PQProxyUdp" << std::endl; - out << "Type: " << type << std::endl; - out << "naddr: " << inet_ntoa(naddr.sin_addr) << ":"; - out << ntohs(naddr.sin_port) << std::endl; - out << "paddr: " << inet_ntoa(paddr.sin_addr) << ":"; - out << ntohs(paddr.sin_port) << std::endl; - out << "ConnectMode: " << connectMode << std::endl; - out << "KeySize: " << ksize << std::endl; - return out << "-------- PQProxyUdp" << std::endl; -} - - diff --git a/libretroshare/src/pqi/pqitunnelproxyudp.h b/libretroshare/src/pqi/pqitunnelproxyudp.h deleted file mode 100644 index 09ba238b3..000000000 --- a/libretroshare/src/pqi/pqitunnelproxyudp.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * "$Id: pqitunnelproxyudp.h,v 1.3 2007-02-18 21:46:50 rmf24 Exp $" - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2004-2006 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 PQI_TUNNEL_PROXY_UDP_HEADER -#define PQI_TUNNEL_PROXY_UDP_HEADER - -#include "pqi/pqitunnel.h" - -#define PQI_TPUDP_TYPE_1 0x0001 -#define PQI_TPUDP_TYPE_2 0x0002 - -class PQProxyUdp -{ -public: - // construct from data. - PQProxyUdp(void *data, int size); - PQProxyUdp(); - - // construct from info. - PQProxyUdp(struct sockaddr_in *proxyaddr, void *key, int size); - PQProxyUdp(struct sockaddr_in *neighaddr, - struct sockaddr_in *peeraddr, int cMode); - -virtual ~PQProxyUdp(); - - // no copy functions. - -virtual const int getSize() const; -virtual int out(void *data, const int size) const; // write -virtual int in(const void *data, const int size); // read, - -std::ostream &print(std::ostream &out); - - int type; - struct sockaddr_in naddr, paddr; - int ksize; - void *key; - int connectMode; -}; - -#endif // PQI_TUNNEL_PROXY_UDP_HEADER diff --git a/libretroshare/src/pqi/pqitunneltst.h b/libretroshare/src/pqi/pqitunneltst.h deleted file mode 100644 index e53b928b1..000000000 --- a/libretroshare/src/pqi/pqitunneltst.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * "$Id: pqitunneltst.h,v 1.4 2007-02-18 21:46:50 rmf24 Exp $" - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2004-2006 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 PQI_TUNNEL_TST_HEADER -#define PQI_TUNNEL_TST_HEADER - -#include "pqi/pqitunnel.h" - -#define PQI_TUNNEL_TST_TYPE 0x0265 - - -#define pqitunnelzone 71849 -#include "pqi/pqidebug.h" -#include - - -PQTunnel *createPQTStst(void *d, int n); - - -class PQTunnelTst: public PQTunnel -{ -public: - PQTunnelTst() - :PQTunnel(PQI_TUNNEL_TST_TYPE) - { - pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, - "PQTunnelTst::PQTunnelTst()"); - return; - } - -virtual ~PQTunnelTst() -{ - pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, - "PQTunnelTst::~PQTunnelTst()"); - return; -} - -virtual PQTunnelTst *clone() -{ - PQTunnelTst *pqt = new PQTunnelTst(); - // getData() no longer exists. - //pqt -> in(getData(), getSize()); - return pqt; -} - - -virtual std::ostream &print(std::ostream &out) -{ - out << "----------------" << std::endl; - out << "PQTunnelTst" << std::endl; - // getData() no longer exists. - // out << "Msg:" << (char *) getData() << std::endl; - PQTunnel::print(out); - out << "----------------" << std::endl; - return out; -} - -}; - - -class PQTStst: public PQTunnelService -{ -public: - PQTStst() :PQTunnelService(PQI_TUNNEL_TST_TYPE) - { - pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, - "PQTStst::PQTStst()"); - - ts = time(NULL); - return; - } - -int receive(PQTunnel *item) -{ - pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, - "PQTStst::receive()"); - - PQTunnelTst *tst = (PQTunnelTst *) item; - std::cerr << "PQTStst::receive()...." << std::endl; - tst -> print(std::cerr); - delete item; - return 1; -} - -PQTunnel *send() -{ - if (time(NULL) - ts > 100.0 * rand()/(RAND_MAX + 1.0) ) - { - pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, - "PQTStst::send() Sending Test Packet!"); - // make an item. - PQTunnelTst *tst = new PQTunnelTst(); - std::string msg = "Hello"; - tst -> in(msg.c_str(), msg.length()); - ts = time(NULL); - return tst; - } - return NULL; -} - -int receive(PQTunnelInit *item) -{ - pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, - "PQTStst::receive() Cleaning PQTunnelInit"); - delete item; - return 1; -} - -PQTunnelInit *sendInit() -{ - pqioutput(PQL_DEBUG_BASIC, pqitunnelzone, - "PQTStst::sendInit() returning NULL"); - return NULL; -} - - private: - long ts; -}; - - - -#endif // PQI_TUNNEL_TST_HEADER diff --git a/libretroshare/src/pqi/pqiudpproxy.cc b/libretroshare/src/pqi/pqiudpproxy.cc deleted file mode 100644 index 593c7c361..000000000 --- a/libretroshare/src/pqi/pqiudpproxy.cc +++ /dev/null @@ -1,859 +0,0 @@ -/* - * "$Id: pqiudpproxy.cc,v 1.7 2007-02-18 21:46:50 rmf24 Exp $" - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2004-2006 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 "pqi/pqiudpproxy.h" -#include "pqi/pqitunnelproxyudp.h" -#include "pqi/pqissludp.h" -#include "pqi/p3disc.h" - -#include -#include "pqi/pqidebug.h" - -#include "tcponudp/tou.h" - -const int pqiudpproxyzone = 6846; - -class udpAddrPair -{ -public: - udpAddrPair(cert *n1, cert *n2, int fd); - ~udpAddrPair(); - - int match(cert *src, cert *peer, struct sockaddr_in &addr); - bool bothMatched(); - - cert *cert1, *cert2; - int m1count, m2count; - bool matched1, matched2; - struct sockaddr_in addr1, addr2; - char *key1, *key2; - int keysize1, keysize2; - int sockfd; -}; - - -udpAddrPair:: udpAddrPair(cert *n1, cert *n2, int fd) - :cert1(n1), cert2(n2), - matched1(false), matched2(false), - key1(NULL), key2(NULL), - keysize1(0), keysize2(0), sockfd(fd) -{ - - /* choose a random number 20 - 100 */ - keysize1 = 20 + (int) (80.0 * (rand() / (RAND_MAX + 1.0))); - keysize2 = 20 + (int) (80.0 * (rand() / (RAND_MAX + 1.0))); - int i; - - /* generate keys */ - key1 = (char *) malloc(keysize1); - key2 = (char *) malloc(keysize2); - for(i = 0; i < keysize1; i++) - { - key1[i] = (char) (256.0 * (rand() / (RAND_MAX + 1.0))); - } - for(i = 0; i < keysize2; i++) - { - key2[i] = (char) (256.0 * (rand() / (RAND_MAX + 1.0))); - } - /* done! */ -} - -udpAddrPair::~udpAddrPair() -{ - free(key1); - free(key2); -} - -int udpAddrPair::match(cert *src, cert *peer, struct sockaddr_in &addr) -{ - if ((src == cert1) && (peer == cert2)) - { - /* matched 1 */ - matched1 = true; - m1count++; - addr1 = addr; - - std::ostringstream out; - out << "udpAddrPair::match() Matched Cert 1" << std::endl; - out << "FROM: " << inet_ntoa(addr.sin_addr) << ":"; - out << ntohs(addr.sin_port) << " count: " << m1count; - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - return true; - - } - - if ((src == cert2) && (peer == cert1 )) - { - matched2 = true; - m2count++; - addr2 = addr; - - std::ostringstream out; - out << "udpAddrPair::match() Matched Key 2" << std::endl; - out << "FROM: " << inet_ntoa(addr.sin_addr) << ":"; - out << ntohs(addr.sin_port) << " count: " << m1count; - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - return true; - } - - pqioutput(PQL_DEBUG_ALL, pqiudpproxyzone, "not matched"); - return false; -} - -bool udpAddrPair::bothMatched() -{ - return (matched1 && matched2); -} - - - p3udpproxy::p3udpproxy(p3disc *p) - :p3proxy(p) -{ - /* if we have a udp_server, - * setup a listener. - */ - - /* check that the sslcert flags are good. */ - //if ((sslcert->isFirewalled() && sslcert->isForwarded() || - // (!(sslcert->isFirewalled()))) - { - /* then check address */ - /* attempt to setup a udp port to listen... - */ - struct sockaddr_in *addr = &(getSSLRoot()->getOwnCert()->localaddr); - { - std::ostringstream out; - out << "p3udpproxy::p3udpproxy()"; - out << " Creating a UDP Listening port:"; - out << inet_ntoa(addr->sin_addr) << ":" << ntohs(addr->sin_port); - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - } - - int sockfd = tou_socket(0,0,0); - tou_bind(sockfd, (struct sockaddr *) addr, - sizeof(struct sockaddr_in)); - - tou_listen(sockfd, 1); - tou_extaddr(sockfd, (struct sockaddr *) addr, - sizeof(struct sockaddr_in)); - } - - return; -} - -p3udpproxy::~p3udpproxy() -{ - /* should clean up! */ - return; -} - - -// PQTunnelService Overloading. -// -// Major overloaded function. -// -// The receive function now has two distinct roles. -// 1) Proxy role: receive Ext Addresses (in an established connection) -// -> when multiple recieved, return address pair to initiate -// -> transaction. -// -// The generic (p3proxy) recieve should split the -// packet depending on if we are proxy, or end destination. -// -// expects to recieve -// 1) if we are the proxy ... add address to the -// waiting pairs. -// -// if have both -> respond. -// -// 2) if receive as destination, and they've -// sent the addr pair, then we can -// commence the connection. - - - /* only two types of packets are expected over the - * proxy connection...... - * 1) ProxyAddress + Key. - * 2) discovered addresses. - * - * This information comes from the Proxy for us. - * and is encapsulated in a PQProxyUdp packet. - */ - -int p3udpproxy::receiveAsProxy(PQTunnelProxy* pqtp, cert *src, cert *dest) -{ - /* if connected (checked already!) */ - { - std::ostringstream out; - out << "p3udpproxy::receiveAsProxy()"; - out << " Received PQTunnel Packet! - Yet to do anything!" << std::endl; - pqtp -> print(out); - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - } - - /* add to waiting */ - PQProxyUdp udppkt; - if (pqtp->size != udppkt.in(pqtp->data, pqtp->size)) - { - delete pqtp; - pqioutput(PQL_WARNING, pqiudpproxyzone, - "PQTunnel is Not a PQProxyUdp Pkt...Deleting"); - return -1; - } - - if ((cert *) pqtp->p != src) - { - // error - std::ostringstream out; - out << "p3udpproxy::receiveAsProxy() ERROR pqtp->p != src"; - pqioutput(PQL_ALERT, pqiudpproxyzone, out.str()); - return -1; - } - - // order very important.... packet from src, for connection to dest!. - checkUdpPacket(&udppkt, src, dest); - - /* cleanup */ - delete pqtp; - return 1; -} - -int p3udpproxy::receiveAsError(PQTunnelProxy* pqtp, cert *src, cert *from, cert *dest) -{ - /* don't do much */ - return 1; -} - -int p3udpproxy::receiveAsDestination(PQTunnelProxy* pqtp, cert *src, cert *from, cert *dest, pqiproxy *pqip) - - -{ - { - std::ostringstream out; - out << "p3udpproxy::receiveAsDestination("; - out << src -> Name(); - out << " -> " << from -> Name(); - out << " -> " << dest -> Name() << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - } - - PQProxyUdp udppkt; - if (pqtp->size != udppkt.in(pqtp->data, pqtp->size)) - { - delete pqtp; - pqioutput(PQL_WARNING, pqiudpproxyzone, - "PQTunnel is Not a PQProxyUdp Pkt...Deleting"); - return -1; - } - - // inform the pqiudpproxy - pqiudpproxy *udpproxy = dynamic_cast(pqip); - if (udpproxy == NULL) - { - std::ostringstream out; - out << "pqiproxy -> NOT a pqiudpproxy....Trouble"; - pqioutput(PQL_WARNING, pqiudpproxyzone, out.str()); - - // mismatch reject. - delete pqtp; - return -1; - } - - if (udppkt.type != PQI_TPUDP_TYPE_2) - { - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, - "Unknown Proxy Packet"); - delete pqtp; - return -1; - } - - - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, - "Packet -> Discovered Address"); - udpproxy->discoveredaddresses(&(udppkt.naddr), &(udppkt.paddr), - udppkt.connectMode); - - /* we have now completed that proxy connection. - * shut it down - */ - - delete pqtp; - return 1; -} - -/* This is called by the pqiudpproxy, when an address should - * be transmitted..... - */ - -int p3udpproxy::sendExternalAddress(pqiudpproxy *pqip, - struct sockaddr_in &ext_addr) -{ - // first find the certs. - cert *dest = pqip -> getContact(); - cert *own = sroot -> getOwnCert(); - - std::map::iterator it; - it = connectionmap.find(dest); - /* check certs for basic safety */ - if (it == connectionmap.end()) - { - /* cannot */ - return -1; - } - cert *prxy = it -> second; - - std::ostringstream out; - out << "p3udpproxy::sendExternalAddress():"; - out << " & " << inet_ntoa(ext_addr.sin_addr); - out << ":" << ntohs(ext_addr.sin_port); - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - - PQProxyUdp *udppkt = new PQProxyUdp(&ext_addr, &ext_addr, sizeof(ext_addr)); - - /* now pack them in PQTunnelProxy pkts */ - PQTunnelProxy *tp1 = createProxyUdpPkt(dest, prxy, own, udppkt); - delete udppkt; - - /* send them off */ - outPkts.push_back(tp1); - return 1; -} - - - -int p3udpproxy::connectionCompletedAsProxy(cert *n1, cert *n2) -{ - /* As the proxy, we do nothing at the completion of the connection - * except wait for the two external addresses to be forwarded to us - * (this is handled in receiveAsProxy()). - */ - - { - std::ostringstream out; - out << "p3udpproxy::completeConnectAsProxy()"; - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - } - - /* generate keys */ - udpAddrPair *uc = new udpAddrPair(n1, n2, 1); /* sockfd - legacy = 1? */ - - /* save keys in list */ - keysWaiting.push_back(uc); - return 1; -} - - -int p3udpproxy::checkUdpPacket(PQProxyUdp *pkt, cert *src, cert *dest) -{ - { - std::ostringstream out; - out << "p3udpproxy::checkUdpPacket()"; - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - } - - /* only if we are the proxy */ - struct sockaddr_in ext_addr = pkt->paddr; - - /* the packet should just contain the key */ - std::list::iterator it; - for(it = keysWaiting.begin(); it != keysWaiting.end(); it++) - { - if ((*it) -> match(src, dest, ext_addr)) - { - std::ostringstream out; - out << "p3udpproxy::checkUdpPacket() Matched Key!"; - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - } - else - { - // only way to continue loop! - continue; - } - - if ((*it) -> bothMatched()) - { - udpAddrPair *uc = (*it); - - std::ostringstream out; - out << "p3udpproxy::checkUdpPacket() Both Keys Matched!"; - out << "p3udpproxy::checkUdpPacket() Sending addresses: "; - out << inet_ntoa(uc->addr1.sin_addr) << ":"; - out << ntohs(uc->addr1.sin_port); - out << " & " << inet_ntoa(uc->addr2.sin_addr); - out << ":" << ntohs(uc->addr2.sin_port); - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - - - /* remove packet, and send addresses to both! - * Arbitarily decide which is active (one with addr1) - */ - PQProxyUdp *p1 = new PQProxyUdp( - &(uc->addr1), &(uc->addr2), 1); - PQProxyUdp *p2 = new PQProxyUdp( - &(uc->addr2), &(uc->addr1), 0); - - - /* now pack them in PQTunnelProxy pkts */ - PQTunnelProxy *tp1 = createProxyUdpPkt(uc->cert1, NULL, uc->cert2, p1); - PQTunnelProxy *tp2 = createProxyUdpPkt(uc->cert2, NULL, uc->cert1, p2); - - delete p1; - delete p2; - - /* send them off */ - outPkts.push_back(tp1); - outPkts.push_back(tp2); - - /* remove */ - it = keysWaiting.erase(it); - - } - /* if we matched -> then good! */ - return 1; - } - - { - std::ostringstream out; - out << "p3udpproxy::checkUdpPacket() FAILED to Match Incoming UdpPkt"; - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - } - - return 0; -} - -int p3udpproxy::reset(pqiproxy *p, cert *c) -{ - { - std::ostringstream out; - out << "p3udpproxy::reset()"; - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - } - // restart. - // remove from keysWaiting ??? - return p3proxy::reset(p,c); -} - - -int p3udpproxy::outgoingpkt(pqiproxy *p, cert *c, void *d, int size) -{ - { - std::ostringstream out; - out << "p3udpproxy::outgoingpkt() For: " << c -> Name(); - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - } - /* fails in udpproxy */ - return 0; -} - - -int p3udpproxy::incomingpkt(pqiproxy *p, void *d, int maxsize) -{ - { - std::ostringstream out; - out << "p3udpproxy::incomingpkt()"; - pqioutput(PQL_DEBUG_ALL, pqiudpproxyzone, out.str()); - } - /* fails in udpproxy */ - return 0; -} - - -int p3udpproxy::status() -{ - { - std::ostringstream out; - out << "p3udpproxy::status()"; - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - } - p3proxy::status(); - return 1; -} - - -int p3udpproxy::processincoming() -{ - { - std::ostringstream out; - out << "p3udpproxy::processincoming()"; - pqioutput(PQL_DEBUG_ALL, pqiudpproxyzone, out.str()); - } - - return 1; -} - - -/* this is only called by the proxy */ -PQTunnelProxy *p3udpproxy::createProxyUdpPkt(cert *dest, cert *prxy, cert *src, PQProxyUdp *uap) -{ - PQTunnelProxy *pi = new PQTunnelProxy(); - cert *o = sroot -> getOwnCert(); - - { - std::ostringstream out; - out << "p3udpproxy::createProxyUdpPkt()" << std::endl; - out << "Dest: " << dest -> Name() << std::endl; - if (!prxy) - { - out << "Proxy: US!" << std::endl; - } - else - { - out << "Proxy: " << prxy -> Name() << std::endl; - } - out << "Src: " << src -> Name() << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - } - - // Fill in Details.... - // only src = peer to fill in . - if (!sroot -> getcertsign(src, pi -> src)) - { - std::ostringstream out; - out << "p3proxy::createProxyPkt()"; - out << " Error: Failed to Get Signature 1..."; - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - - delete pi; - return NULL; - } - if (!sroot -> getcertsign(dest, pi -> dest)) - { - std::ostringstream out; - out << "p3proxy::createProxyPkt()"; - out << " Error: Failed to Get Signature 2..."; - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - - delete pi; - return NULL; - } - - // initialise packets. - pi -> sid = 0; // doesn't matter. - pi -> seq = 0; - - /* HACK HERE */ - if (prxy == NULL) /* then we are the proxy */ - { - /* send on */ - pi -> cid = dest -> cid; // destination. - pi -> p = o; // from us; - } - else - { - pi -> cid = prxy -> cid; // send to proxy. - pi -> p = o; // from us; - } - - - // ProxyInit Details. - pi -> size = uap -> getSize(); - pi -> data = malloc(pi->size); - uap->out(pi->data, pi->size); - // Sign Packet. - - return pi; -} - - -/************************ PQI PROXY *************************/ - -#define PUP_CLOSED 0 -#define PUP_WAITING_PROXY 1 -#define PUP_PROXY_CONNECT 2 -#define PUP_WAITING_DISC 3 -#define PUP_WAITING_UDP 4 -#define PUP_WAITING_SSL 5 -#define PUP_CONNECTED 6 - -pqiudpproxy::pqiudpproxy(cert *c, p3udpproxy *l, PQInterface *p) - :pqipeerproxy(c, l, p), state(PUP_CLOSED) -{ - { - std::ostringstream out; - out << "pqiudpproxy::pqiudpproxy()"; - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - } - - return; -} - -pqiudpproxy::~pqiudpproxy() -{ - { - std::ostringstream out; - out << "pqiudpproxy::~pqiudpproxy()"; - //pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - pqioutput(PQL_ALERT, pqiudpproxyzone, out.str()); - } - state = PUP_CLOSED; - return; -} - - // pqiconnect Interface. -int pqiudpproxy::connectattempt() // as pqiproxy/ -{ - { - std::ostringstream out; - out << "pqiudpproxy::connectattempt()"; - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - } - state = PUP_WAITING_PROXY; - return pqipeerproxy::connectattempt(); -} - - -int pqiudpproxy::listen() -{ - { - std::ostringstream out; - out << "pqiudpproxy::listen()"; - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - } - state = PUP_WAITING_PROXY; - return pqipeerproxy::listen(); -} - - -int pqiudpproxy::stoplistening() -{ - //state = PUP_WAITING_PROXY; - return pqipeerproxy::stoplistening(); -} - -int pqiudpproxy::disconnected() -{ - pqipeerproxy::disconnected(); - state = PUP_CLOSED; - reset(); - return 1; -} - -/* pqiproxy interface */ -int pqiudpproxy::connected(bool act) -{ - { - std::ostringstream out; - out << "pqiudpproxy::connected() - Set State!"; - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - } - state = PUP_PROXY_CONNECT; - return pqipeerproxy::connected(act); -} - -// called by the p3udpproxy .... means attempt failed.... -int pqiudpproxy::disconnect() -{ - { - std::ostringstream out; - out << "pqiudpproxy::disconnect()"; - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - } - /* if we haven't got remote address yet! */ - if (state < PUP_WAITING_SSL) - { - disconnected(); - } - /* else is okay */ - return 1; -} - - -int pqiudpproxy::reset() -{ - { - std::ostringstream out; - out << "pqiudpproxy::reset()"; - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - } - pqipeerproxy::reset(); - state = PUP_CLOSED; - return 1; -} - - - - // Overloaded from PQInterface -int pqiudpproxy::status() -{ - { - std::ostringstream out; - out << "pqiudpproxy::status() state = " << state; - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - } - pqipeerproxy::status(); - return 1; -} - - - -int pqiudpproxy::tick() -{ - { - std::ostringstream out; - out << "pqiudpproxy::tick()"; - pqioutput(PQL_DEBUG_ALL, pqiudpproxyzone, out.str()); - } - - if (state == PUP_CLOSED) /* silent state */ - { - - } - else if (state == PUP_WAITING_PROXY) /* just started connection */ - { - //state = PUP_WAITING_DISC; - } - else if (state == PUP_PROXY_CONNECT) - { - //state = PUP_WAITING_DISC; - } - else if (state == PUP_WAITING_DISC) - { - //state = PUP_WAITING_DISC; - } - else if (state == PUP_WAITING_SSL) - { - - } - - pqipeerproxy::tick(); - return 1; -} - -int pqiudpproxy::notifyEvent(int type) -{ - { - std::ostringstream out; - out << "pqiudpproxy::notifyEvent(" << type << ")"; - pqioutput(PQL_DEBUG_BASIC, pqiudpproxyzone, out.str()); - } - return pqipeerproxy::notifyEvent(type); -} - - -int p3udpproxy::requestStunServer(struct sockaddr_in &addr) -{ - if (potentials.size() == 0) - { - potentials = p3d -> requestStunServers(); - } - - if (potentials.size() > 0) - { - /* pop the first one off and return it */ - addr = potentials.front(); - potentials.pop_front(); - return 1; - } - - return 0; -} - -/* The pqissludp interface is below, in order of execution - */ - -bool pqiudpproxy::isConnected(int &mode) -{ - if (isactive()) - { - mode = connect_mode; - return true; - } - return false; -} - - -bool pqiudpproxy::hasFailed() -{ - return (state == PUP_CLOSED); -} - -int pqiudpproxy::requestStunServer(struct sockaddr_in &addr) -{ - return ((p3udpproxy *) p3p) -> requestStunServer(addr); -} - - // notification from pqissludp. -bool pqiudpproxy::sendExternalAddress(struct sockaddr_in &ext_addr) -{ - return ((p3udpproxy *) p3p) -> - sendExternalAddress(this, ext_addr); -} - -// -int pqiudpproxy::discoveredaddresses(struct sockaddr_in *our_addr, - struct sockaddr_in *peer, int cMode) -{ - /* we have our own address!, and peers address */ - { - std::ostringstream out; - out << "pqiudpproxy::discoveredaddresses() Connect"; - out << std::endl; - out << "Our Address: " << inet_ntoa(our_addr->sin_addr) << ":"; - out << ntohs(our_addr->sin_port); - out << std::endl; - out << " Peers Address: " << inet_ntoa(peer->sin_addr) << ":"; - out << ntohs(peer->sin_port); - - pqioutput(PQL_ALERT, pqiudpproxyzone, out.str()); - } - - remote_addr = *peer; - if (cMode) - { - connectMode = 1; /* active */ - } - else - { - connectMode = 0; /* passive */ - } - state = PUP_WAITING_UDP; - - // shutdown the proxy Connection. - // by calling the pqipeerproxy::reset(). - pqipeerproxy::reset(); - - pqioutput(PQL_ALERT, pqiudpproxyzone, - "sent pqipeerproxy::reset() should shutdown proxy connect"); - return 1; -} - - // poll by pqissludp for state completion. -bool pqiudpproxy::gotRemoteAddress(struct sockaddr_in &raddr, int &cMode) -{ - if (state == PUP_WAITING_UDP) - { - raddr = remote_addr; - cMode = connectMode; - return true; - } - return false; -} - - - diff --git a/libretroshare/src/pqi/pqiudpproxy.h b/libretroshare/src/pqi/pqiudpproxy.h deleted file mode 100644 index 5c3e66cef..000000000 --- a/libretroshare/src/pqi/pqiudpproxy.h +++ /dev/null @@ -1,287 +0,0 @@ -/* - * "$Id: pqiudpproxy.h,v 1.6 2007-02-18 21:46:50 rmf24 Exp $" - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2004-2006 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - -#ifndef MRK_PQI_UDP_PROXY_HEADER -#define MRK_PQI_UDP_PROXY_HEADER - - -#include - - -#include -#include -#include - -#include "pqi/pqiproxy.h" - -class pqiudpproxy; -class udpAddrPair; -class pqissludp; -class PQProxyUdp; - -class p3udpproxy: public p3proxy -{ - public: - p3udpproxy(p3disc *p); -virtual ~p3udpproxy(); - - // New udp functions. - // this first one will be called from - // inside p3proxy, at the appropriate time. - int checkUdpPacket(PQProxyUdp *, cert *src, cert *peer); - - - // PQTunnelService Overloading. (none) - // Overloaded from p3proxy. - // receive now plays role of - // collecting address packets. - - // interface to pqiproxy. -//int attach(pqiproxy *p, cert *c); -//int detach(pqiproxy *p, cert *c); - -//int listen(pqiproxy *p, cert *c); -//int stoplistening(pqiproxy *p, cert *c); - -int reset(pqiproxy *p, cert *c); - -virtual int outgoingpkt(pqiproxy *p, cert *, void *d, int size); -virtual int incomingpkt(pqiproxy *p, void *d, int maxsize); - -int requestStunServer(struct sockaddr_in &addr); -int sendExternalAddress(pqiudpproxy *pqip, - struct sockaddr_in &ext_addr); - - -// overloaded from many sources. -//virtual int tick(); - -int status(); - -//int connectattempt(pqiproxy*, cert*); -//int connectattempt(); -//int nextconnectattempt(cert *, cert *); - - protected: /* interface not clean enough for private */ - - // overload connection Completion. -virtual int connectionCompletedAsProxy(cert*, cert*); -//virtual int connectionCompletedAsPeer(cert*, cert*); - - // overload receiving Tunnel Data. -virtual int receiveAsProxy(PQTunnelProxy *pqtp, cert *src, cert *dest); -virtual int receiveAsDestination(PQTunnelProxy *pqtp, - cert *src, cert *from, cert *dest, pqiproxy *pqip); -virtual int receiveAsError(PQTunnelProxy *pqtp, cert *src, cert *from, cert *dest); - -virtual int processincoming(); - - - PQTunnelProxy *createProxyUdpPkt(cert *dest, cert *prxy, cert *src, PQProxyUdp *uap); - - std::list keysWaiting; - std::list potentials; // stun addresses. -}; - - -// pqiconnect, derives from pqistreamer/PQInterface. -// -// pqiproxy provide. -// 1) read/write data. -// 2) connect functions. -// -// pqiudpproxy provides the -// linking, and redirects -// the sending the udpssl layer below. -// -// small extensions to the pqiproxy interface -// are required. - -class pqiudpproxy: public pqipeerproxy -{ -public: - pqiudpproxy(cert *c, p3udpproxy *l, PQInterface *parent); -virtual ~pqiudpproxy(); - - // Net Interface. -virtual int connectattempt(); -virtual int listen(); -virtual int stoplistening(); -virtual int reset(); -virtual int disconnect(); - -// PQInterface -virtual int tick(); -virtual int status(); - - // Bin Interface disabled. -virtual int senddata(void*, int) { return 0; } -virtual int readdata(void*, int) { return 0; } -virtual int netstatus() { return 0; } -//virtual int isactive(); -> same as peer. -virtual bool moretoread() { return false; } - - // The interface to p3proxy. -virtual int notifyEvent(int type); - // unneeded notification. - - // notification from p3proxy. -virtual int connected(bool active); -virtual int disconnected(); - - // Below is the pqissludp interface to us. - // in order of execution..... - - // poll by pqissludp for state completion. -bool isConnected(int &mode); -bool hasFailed(); - - // requests from pqissludp layer. -int requestStunServer(struct sockaddr_in &addr); - // notification from pqissludp. -bool sendExternalAddress(struct sockaddr_in &ext_addr); - - // notification of external address exchange! -virtual int discoveredaddresses(struct sockaddr_in *our_addr, - struct sockaddr_in *peer, int cMode); - - // poll by pqissludp for state completion. -bool gotRemoteAddress(struct sockaddr_in &remote_addr, int &cMode); - -private: - int state; - struct sockaddr_in ext_addr; - struct sockaddr_in remote_addr; - int connectMode; /* sent with the remote addresses */ -}; - -/* Documenting the virtual (proxy) pqi interface. - * - * This is used to create proxy interface - * for people behind firewalls. - * - * P1 PROXY P2 - * requests a - * proxy interface. - * ---------> - * end attempt <----- IF Not - * Available. - * - * else ---------------> Check for proxy/person auth - * end attempt <------ cancel ------- If Not Auth. - * - * else, if allowed. - * build proxy server. - * Build proxy <------ setup ---------- send okay - * server connection. - * - * Determine Local - * External Addr - * Determine Local - * External Addr - * - * send ext addr -------> - * collect addresses. - * <---------- send ext addr -------> - * complete proxy part. - * <-------- send addresses -------> - * - * - * Initiate Udp Connection. --------------------> Initiate Udp Connection. - * <-------------------------------- - * - * - * So the initial stuff is the same..... - * but there is no pipe at the end - * just the exchange of addresses. - * - * there is a udp listener on the same address - * as the ssllistener (just udp). This port - * will be used by the stunServer, and will supply - * external addresses to clients that request them. - * - * - * Order of udp connection: - * (1) establish a proxy connection. - * (2) determine external address. - * (3) send external address to proxy. - * (4) recieve address pair - * (5) initiate a udp connection. - * - * Each udpproxy must stun to get their connection addr. - * this might end up with lots of stuns? - * does that matter? - * - * pqissl. - * -> proxy interface. - * Send() - * return proxymsg locally - * pulled by proxy server. - * - * ps -> send proxy msg - * to correct pqissl. - * ----------> popped out to - * the proxy server. - * if file cache. - * redirect ------> recieved by pqissl. - * pulled by proxy server. - * - * proxy server - * - * all proxied information is - * going to be signed/or encrypted. - * - * very simple - that is the only - * necessary change. - * - * proxy msg. - * --------------------- - * type : init - * end - * msg (signed) - * tunnelled (includes init of ssl.) - * dest cert signature: - * - * encryption/signature mode. - * - * signature len: - * signature: - * - * data len: - * data - * - * - * - * - * - * is this the right place to add it? - * or is pqistreamer the answer. - * - */ - -#endif - diff --git a/libretroshare/src/pqi/tstdns.cc b/libretroshare/src/pqi/tstdns.cc deleted file mode 100644 index 22cb472c8..000000000 --- a/libretroshare/src/pqi/tstdns.cc +++ /dev/null @@ -1,16 +0,0 @@ - -#include "pqi/pqinetwork.h" - -int main() -{ - struct sockaddr_in addr; - addr.sin_port = htons(1101); - - LookupDNSAddr("www.google.com", addr); - LookupDNSAddr("10.0.0.19", addr); - LookupDNSAddr("localhost", addr); - LookupDNSAddr("nameless", addr); - - return 1; -} - diff --git a/libretroshare/src/pqi/tstmsg.cc b/libretroshare/src/pqi/tstmsg.cc deleted file mode 100644 index a1f659dc9..000000000 --- a/libretroshare/src/pqi/tstmsg.cc +++ /dev/null @@ -1,100 +0,0 @@ - -#include "pqi/pqipacket.h" -#include "pqi/pqi.h" - -#include -#include -#include - -int checkMsg(PQItem *item); - -int main() -{ - - MsgItem *item = new MsgItem(); - - item -> sendTime = 0x10203040; - item -> msg = "asdfghjklwertyuisdfghjkasdfghewrtyefrghfghdfghjklghjkdfghjdfghjdfghjdfghjdghjsdghdfghjdfghdfghdfghjdfghdfghjdfghjfghjdfghjdfghjfghjfghjfghjdfghj"; - item -> msg += " asdfghjklwertyuisdfghjkasdfghewrtyefrghfghdfghjklghjkdfghjdfghjdfghjdfghjdghjsdghdfghjdfghdfghdfghjdfghdfghjdfghjfghjdfghjdfghjfghjfghjfghjdfghj"; - item -> msg += " asdfghjklwertyuisdfghjkasdfghewrtyefrghfghdfghjklghjkdfghjdfghjdfghjdfghjdghjsdghdfghjdfghdfghdfghjdfghdfghjdfghjfghjdfghjdfghjfghjfghjfghjdfghj"; - - MsgFileItem mfi; - mfi.name = "A"; - mfi.hash = "B"; - mfi.size = 0xFFFFFFFF; - item -> files.push_back(mfi); - - mfi.name = "safjhlsafhlsa kfjdhlsa kjfh klsajhf lkjsahflkjhsafkljhsafkjhsafjkhsakfjhksjfhkla sjhf klsjhf kl"; - mfi.hash = "ia dfjsakfjhsalkfjhlsajkfhlhjksf ljksafhlkjsahflkjsahfl kjsahfl jkhsafl kjhsafkl jhsa fkljh "; - mfi.size = 0xFFFFFFFF; - item -> files.push_back(mfi); - - item -> title = "sadf"; - item -> header = "To you from me"; - - - /* fill it up with rubbish */ - checkMsg(item); - - ChatItem *item2 = new ChatItem(); - item2 -> msg = "A Short Message"; - checkMsg(item2); - - ChatItem *item3 = new ChatItem(); - item3 -> msg = "asdfjkhfjhl sajkfhjksahfkl jahs fjklhsakfj hsajk fh klajs hfklja hsfjkhsa kf hksjdfhksajhf klsajhfkl jhdsafkl jhsklfj hksfjh lksajf klsjhfkjsaf sah f;lksahfk; jshfl kjsahfl; kjhsa flkjhsal kfjh s;akfjhsakfjh ljksl kjsahf ;jksal;sajkfhowiher ;oi28y540832qy5h4rlkjqwhrp928y52hrl;kwajhr2098y54 25hujh 32u5h3 285y 319485yh 315jh3 1495y 13295y15ui1 h51o h51ou5A Short Message"; - checkMsg(item3); - - - - return 1; -} - -int checkMsg(PQItem *item) -{ - int i, j; - - std::cerr << "Input MsgItem: " << std::endl; - item -> print(std::cerr); - - /* stream it */ - std::cerr << "Streaming..." << std::endl; - - void *pkt = pqipkt_makepkt(item); - - if (!pkt) - { - std::cerr << "Pkt creation failed!" << std::endl; - return 1; - } - - /* print out packet */ - int size = pqipkt_rawlen(pkt); - - std::cerr << "Pkt Dump(" << size << ")" << std::endl; - std::ostringstream out; - for(i = 0; i < size;) - { - for(j = 0; (i + j < size) && (j < 8); j++) - { - unsigned char n = ((unsigned char *) pkt)[i+j]; - out << std::setw(2) << std::hex << (unsigned int) n << ":"; - } - i += j; - out << std::endl; - } - std::cerr << out.str(); - - /* stream back */ - PQItem *i2 = pqipkt_create(pkt); - - std::cerr << "Output MsgItem: " << std::endl; - i2 -> print(std::cerr); - - return 1; - -} - - - - - diff --git a/libretroshare/src/pqi/xpgpcert.cc b/libretroshare/src/pqi/xpgpcert.cc index 710491874..9449c5960 100644 --- a/libretroshare/src/pqi/xpgpcert.cc +++ b/libretroshare/src/pqi/xpgpcert.cc @@ -1932,6 +1932,19 @@ bool certsign::operator==(const certsign &ref) const /* Fns for relating cert signatures to structures */ +cert *sslroot::findPeerId(std::string id) +{ + certsign sign; + if (!convert_to_certsign(id, sign)) + { + pqioutput(PQL_WARNING, pqisslrootzone, + "sslroot::findPeerId() ERROR: Failed to Convert to certsign"); + return NULL; + } + + return findcertsign(sign); +} + cert *sslroot::findcertsign(certsign &sign) { std::map::iterator it; diff --git a/libretroshare/src/pqi/xpgpcert.h b/libretroshare/src/pqi/xpgpcert.h index 41bedf32f..b419cd655 100644 --- a/libretroshare/src/pqi/xpgpcert.h +++ b/libretroshare/src/pqi/xpgpcert.h @@ -181,6 +181,7 @@ void setSetting(std::string opt, std::string val); /* Fns for relating cert signatures to structures */ +cert *findPeerId(std::string id); cert *findcertsign(certsign &sign); int getcertsign(cert *c, certsign &sign); int addtosignmap(cert *);