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 *);