mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
2230 lines
53 KiB
C++
2230 lines
53 KiB
C++
|
/*
|
||
|
* libretroshare/src/services: p3disc.cc
|
||
|
*
|
||
|
* Services 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 "services/p3disc.h"
|
||
|
|
||
|
// for active local cert stuff.
|
||
|
#include "pqi/pqissl.h"
|
||
|
|
||
|
#include <iostream>
|
||
|
#include <errno.h>
|
||
|
#include <cmath>
|
||
|
|
||
|
const uint32_t AUTODISC_LDI_SUBTYPE_PING = 0x01;
|
||
|
const uint32_t AUTODISC_LDI_SUBTYPE_RPLY = 0x02;
|
||
|
|
||
|
#include <sstream>
|
||
|
#include "pqi/pqidebug.h"
|
||
|
|
||
|
const int pqidisczone = 2482;
|
||
|
|
||
|
|
||
|
static int updateAutoServer(autoserver *as, RsDiscItem *di);
|
||
|
static int convertTDeltaToTRange(double tdelta);
|
||
|
static int convertTRangeToTDelta(int trange);
|
||
|
static int updateCertAvailabilityFlags(cert *c, unsigned long discFlags);
|
||
|
static unsigned long determineCertAvailabilityFlags(cert *c);
|
||
|
|
||
|
// Operating System specific includes.
|
||
|
#include "pqi/pqinetwork.h"
|
||
|
|
||
|
p3disc::p3disc(sslroot *r)
|
||
|
:p3Service(RS_SERVICE_TYPE_DISC), sroot(r)
|
||
|
{
|
||
|
addSerialType(new RsDiscSerialiser());
|
||
|
|
||
|
ldata = NULL;
|
||
|
ldlenmax = 1024;
|
||
|
|
||
|
local_disc = false; //true;
|
||
|
remote_disc = true;
|
||
|
|
||
|
// set last check to current time, this prevents queued.
|
||
|
// messages at the start! (actually shouldn't matter - as they aren't connected).
|
||
|
ts_lastcheck = time(NULL); // 0;
|
||
|
|
||
|
// configure...
|
||
|
load_configuration();
|
||
|
localSetup();
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
p3disc::~p3disc()
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
int p3disc::tick()
|
||
|
{
|
||
|
pqioutput(PQL_DEBUG_ALL, pqidisczone,
|
||
|
"p3disc::tick()");
|
||
|
|
||
|
if (local_disc)
|
||
|
{
|
||
|
if (ts_nextlp == 0)
|
||
|
{
|
||
|
pqioutput(PQL_DEBUG_ALL, pqidisczone,
|
||
|
"Local Discovery On!");
|
||
|
localPing(baddr);
|
||
|
localListen();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pqioutput(PQL_DEBUG_ALL, pqidisczone,
|
||
|
"Local Discovery Off!");
|
||
|
}
|
||
|
|
||
|
// ten minute counter.
|
||
|
if (--ts_nextlp < 0)
|
||
|
{
|
||
|
ts_nextlp = 600;
|
||
|
}
|
||
|
|
||
|
if (ts_nextlp % 300 == 0)
|
||
|
idServers();
|
||
|
|
||
|
|
||
|
/* remote discovery can run infrequently....
|
||
|
* this is a good idea, as it ensures that
|
||
|
* multiple Pings aren't sent to neighbours....
|
||
|
*
|
||
|
* only run every 5 seconds.
|
||
|
*/
|
||
|
|
||
|
if (ts_nextlp % 5 != 0)
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
// important bit
|
||
|
int nr = handleReplies(); // discards packets if not running.
|
||
|
if (remote_disc)
|
||
|
{
|
||
|
pqioutput(PQL_DEBUG_ALL, pqidisczone,
|
||
|
"Remote Discovery On!");
|
||
|
newRequests();
|
||
|
if ((sroot -> collectedCerts()) || (nr > 0))
|
||
|
{
|
||
|
distillData();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pqioutput(PQL_DEBUG_ALL, pqidisczone,
|
||
|
"Remote Discovery Off!");
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int local_disc_def_port = 7770;
|
||
|
static int local_disc_secondary_port = 7870;
|
||
|
|
||
|
int p3disc::setLocalAddress(struct sockaddr_in srvaddr)
|
||
|
{
|
||
|
saddr = srvaddr;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
int p3disc::determineLocalNetAddr()
|
||
|
{
|
||
|
// laddr filled in by load_configuration.
|
||
|
laddr.sin_port = htons(local_disc_def_port);
|
||
|
|
||
|
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||
|
#ifndef WINDOWS_SYS // ie UNIX
|
||
|
// broadcast address.
|
||
|
baddr.sin_family = AF_INET;
|
||
|
inet_aton("0.0.0.0", &(baddr.sin_addr));
|
||
|
baddr.sin_port = htons(local_disc_def_port);
|
||
|
#else // WIN
|
||
|
|
||
|
baddr. sin_family = AF_INET;
|
||
|
|
||
|
// So as recommended on this site.. will use |+& to calc it.
|
||
|
unsigned long netmask = inet_addr("255.255.255.0");
|
||
|
unsigned long netaddr = saddr.sin_addr.s_addr & netmask;
|
||
|
baddr.sin_addr.s_addr = netaddr | (~netmask);
|
||
|
|
||
|
// direct works!
|
||
|
//baddr.sin_addr.s_addr = inet_addr("10.0.0.59");
|
||
|
//baddr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||
|
// broadcast!
|
||
|
baddr.sin_addr.s_addr = INADDR_BROADCAST;
|
||
|
baddr.sin_port = htons(local_disc_def_port);
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#endif
|
||
|
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||
|
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "p3disc::determineLocalNetAddr() baddr: ";
|
||
|
out << inet_ntoa(baddr.sin_addr) << std::endl;
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int p3disc::setupLocalPacket(int type, struct sockaddr_in *home,
|
||
|
struct sockaddr_in *server)
|
||
|
{
|
||
|
if (ldata == NULL)
|
||
|
{
|
||
|
ldata = malloc(ldlenmax);
|
||
|
}
|
||
|
|
||
|
// setup packet.
|
||
|
// 8 bytes - tag
|
||
|
((char *) ldata)[0] = 'P';
|
||
|
((char *) ldata)[1] = 'Q';
|
||
|
((char *) ldata)[2] = 'I';
|
||
|
((char *) ldata)[3] = 'L';
|
||
|
if (type == AUTODISC_LDI_SUBTYPE_PING)
|
||
|
{
|
||
|
((char *) ldata)[4] = 'D';
|
||
|
((char *) ldata)[5] = 'I';
|
||
|
((char *) ldata)[6] = 'S';
|
||
|
((char *) ldata)[7] = 'C';
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
((char *) ldata)[4] = 'R';
|
||
|
((char *) ldata)[5] = 'P';
|
||
|
((char *) ldata)[6] = 'L';
|
||
|
((char *) ldata)[7] = 'Y';
|
||
|
}
|
||
|
|
||
|
// sockaddr copy.
|
||
|
ldlen = 8;
|
||
|
for(unsigned int i = 0; i < sizeof(*home); i++)
|
||
|
{
|
||
|
((char *) ldata)[ldlen + i] = ((char *) home)[i];
|
||
|
}
|
||
|
|
||
|
ldlen += sizeof(*home);
|
||
|
for(unsigned int i = 0; i < sizeof(*server); i++)
|
||
|
{
|
||
|
((char *) ldata)[ldlen + i] = ((char *) server)[i];
|
||
|
}
|
||
|
ldlen += sizeof(*server);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
int p3disc::localSetup()
|
||
|
{
|
||
|
|
||
|
if (!local_disc)
|
||
|
{
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone,
|
||
|
"p3disc::localSetup() Warning local_disc OFF!");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
//First we must attempt to open the default socket
|
||
|
determineLocalNetAddr();
|
||
|
|
||
|
int err = 0;
|
||
|
|
||
|
lsock = socket(PF_INET, SOCK_DGRAM, 0);
|
||
|
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||
|
#ifndef WINDOWS_SYS // ie UNIX
|
||
|
|
||
|
if (lsock < 0)
|
||
|
{
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone,
|
||
|
"p3disc::localSetup() Cannot open UDP socket!");
|
||
|
local_disc = false;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
err = fcntl(lsock, F_SETFL, O_NONBLOCK);
|
||
|
if (err < 0)
|
||
|
{
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone,
|
||
|
"p3disc::localSetup() Error: Cannot make socket NON-Blocking: ");
|
||
|
|
||
|
local_disc = false;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
int on = 1;
|
||
|
if(0 != (err =setsockopt(lsock, SOL_SOCKET, SO_BROADCAST,(void *) &on, sizeof(on))))
|
||
|
{
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone,
|
||
|
"p3disc::localSetup() Error: Cannot make socket Broadcast: ");
|
||
|
local_disc = false;
|
||
|
return -1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone,
|
||
|
"p3disc::localSetup() Broadcast Flag Set!");
|
||
|
}
|
||
|
|
||
|
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||
|
#else //WINDOWS_SYS
|
||
|
|
||
|
if (lsock == INVALID_SOCKET)
|
||
|
{
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone,
|
||
|
"p3disc::localSetup() Cannot open UDP socket!");
|
||
|
local_disc = false;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
unsigned long int on = 1;
|
||
|
if (0 != (err = ioctlsocket(lsock, FIONBIO, &on)))
|
||
|
{
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone,
|
||
|
"p3disc::localSetup() Error: Cannot make socket NON-Blocking: ");
|
||
|
local_disc = false;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
on = 1;
|
||
|
if(0 != (err=setsockopt(lsock, SOL_SOCKET, SO_BROADCAST,(char *) &on, sizeof(on))))
|
||
|
{
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone,
|
||
|
"p3disc::localSetup() Error: Cannot make socket Broadcast: ");
|
||
|
|
||
|
local_disc = false;
|
||
|
return -1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone,
|
||
|
"p3disc::localSetup() Broadcast Flag Set!");
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||
|
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "p3disc::localSetup()" << std::endl;
|
||
|
out << "\tSetup Family: " << laddr.sin_family;
|
||
|
out << std::endl;
|
||
|
out << "\tSetup Address: " << inet_ntoa(laddr.sin_addr);
|
||
|
out << std::endl;
|
||
|
out << "\tSetup Port: " << ntohs(laddr.sin_port) << std::endl;
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
}
|
||
|
|
||
|
if (0 != (err = bind(lsock, (struct sockaddr *) &laddr, sizeof(laddr))))
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "p3disc::localSetup()";
|
||
|
out << " Cannot Bind to Default Address!" << std::endl;
|
||
|
showSocketError(out);
|
||
|
out << std::endl;
|
||
|
out << " Trying Secondary Address." << std::endl;
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// ifsucessful then call localPing
|
||
|
// set ts to -1 and don't worry about outgoing until
|
||
|
// we receive a packet
|
||
|
std::ostringstream out;
|
||
|
out << "p3disc::localSetup()" << std::endl;
|
||
|
out << " Bound to Address." << std::endl;
|
||
|
out << "\tSetup Address: " << inet_ntoa(laddr.sin_addr);
|
||
|
out << std::endl;
|
||
|
out << "\tSetup Port: " << ntohs(laddr.sin_port) << std::endl;
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
|
||
|
ts_nextlp = -1;
|
||
|
ts_nextlp = 10;
|
||
|
localPing(baddr);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
laddr.sin_port = htons(local_disc_secondary_port);
|
||
|
if (0 != (err = bind(lsock, (struct sockaddr *) &laddr, sizeof(laddr))))
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "p3disc::localSetup()";
|
||
|
out << " Cannot Bind to Secondary Address!" << std::endl;
|
||
|
showSocketError(out);
|
||
|
out << std::endl;
|
||
|
out << " Giving Up!" << std::endl;
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
local_disc = false;
|
||
|
return -1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "p3disc::localSetup()" << std::endl;
|
||
|
out << " Bound to Secondary Address." << std::endl;
|
||
|
out << "\tSetup Address: " << inet_ntoa(laddr.sin_addr);
|
||
|
out << std::endl;
|
||
|
out << "\tSetup Port: " << ntohs(laddr.sin_port) << std::endl;
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
|
||
|
ts_nextlp = 10;
|
||
|
localPing(baddr);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
// else we open a random port and set the timer
|
||
|
// ie - don't bind to a port.....
|
||
|
ts_nextlp = 10; // ping every 10 minutes.
|
||
|
localPing(baddr);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int p3disc::localPing(struct sockaddr_in reply_to)
|
||
|
{
|
||
|
//This function sends a meessage out containing both cert
|
||
|
// and server address, as well as the ping address (if not standard)
|
||
|
|
||
|
// so we send a packet out to that address
|
||
|
// (most likely broadcast address).
|
||
|
|
||
|
// setup up the data for connection.
|
||
|
setupLocalPacket(AUTODISC_LDI_SUBTYPE_PING,&laddr, &saddr);
|
||
|
|
||
|
// Cast to char for windows benefit.
|
||
|
int len = sendto(lsock, (char *) ldata, ldlen, 0, (struct sockaddr *) &reply_to, sizeof(reply_to));
|
||
|
if (len != ldlen)
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "p3disc::localPing()";
|
||
|
out << " Failed to send Packet." << std::endl;
|
||
|
out << "Sent (" << len << "/" << ldlen;
|
||
|
out << std::endl;
|
||
|
out << "Addr:" << inet_ntoa(reply_to.sin_addr) << std::endl;
|
||
|
out << "Port:" << ntohs(reply_to.sin_port) << std::endl;
|
||
|
out << std::endl;
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "p3disc::localPing() Success!" << std::endl;
|
||
|
out << "Sent To Addr:" << inet_ntoa(reply_to.sin_addr) << std::endl;
|
||
|
out << "Sent To Port:" << ntohs(reply_to.sin_port) << std::endl;
|
||
|
out << "Message Size: " << len << std::endl;
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int p3disc::localReply(struct sockaddr_in reply_to)
|
||
|
{
|
||
|
//This function sends a meessage out containing both cert
|
||
|
// and server address, as well as the ping address (if not standard)
|
||
|
|
||
|
// so we send a packet out to that address
|
||
|
// (most likely broadcast address).
|
||
|
|
||
|
// setup up the data for connection.
|
||
|
setupLocalPacket(AUTODISC_LDI_SUBTYPE_RPLY,&laddr, &saddr);
|
||
|
|
||
|
// Cast to char for windows benefit.
|
||
|
int len = sendto(lsock, (char *) ldata, ldlen, 0, (struct sockaddr *) &reply_to, sizeof(reply_to));
|
||
|
if (len != ldlen)
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "p3disc::localPing()";
|
||
|
out << " Failed to send Packet." << std::endl;
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
int p3disc::localListen()
|
||
|
{
|
||
|
//This function listens to the ping address.
|
||
|
//For each reply, store the result in the structure and mark as local
|
||
|
struct sockaddr_in addr;
|
||
|
struct sockaddr_in neighbour;
|
||
|
struct sockaddr_in server;
|
||
|
socklen_t alen = sizeof(addr);
|
||
|
int nlen = sizeof(neighbour);
|
||
|
int len;
|
||
|
int size = 0;
|
||
|
|
||
|
while(0 < (size = recvfrom(lsock, (char *) ldata, ldlen, 0,
|
||
|
(struct sockaddr *) &addr, &alen)))
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "Recved Message" << std::endl;
|
||
|
out << "From Addr:" << inet_ntoa(addr.sin_addr) << std::endl;
|
||
|
out << "From Port:" << ntohs(addr.sin_port) << std::endl;
|
||
|
out << "Message Size: " << size << std::endl;
|
||
|
|
||
|
for(int i = 0; i < 8; i++)
|
||
|
{
|
||
|
out << ((char *) ldata)[i];
|
||
|
}
|
||
|
out << std::endl;
|
||
|
|
||
|
len = 8;
|
||
|
// sockaddr copy.
|
||
|
for(int i = 0; i < nlen; i++)
|
||
|
{
|
||
|
((char *) &neighbour)[i] = ((char *) ldata)[len + i];
|
||
|
}
|
||
|
len += nlen;
|
||
|
for(int i = 0; i < nlen; i++)
|
||
|
{
|
||
|
((char *) &server)[i] = ((char *) ldata)[len + i];
|
||
|
}
|
||
|
len += nlen;
|
||
|
|
||
|
|
||
|
out << "Neighbour Addr:" << inet_ntoa(neighbour.sin_addr) << std::endl;
|
||
|
out << "Neighbour Port:" << ntohs(neighbour.sin_port) << std::endl;
|
||
|
out << "Server Addr:" << inet_ntoa(server.sin_addr) << std::endl;
|
||
|
out << "Server Port:" << ntohs(server.sin_port) << std::endl;
|
||
|
|
||
|
if ((laddr.sin_addr.s_addr == neighbour.sin_addr.s_addr) &&
|
||
|
(laddr.sin_port == neighbour.sin_port))
|
||
|
{
|
||
|
// Then We Sent it!!!!
|
||
|
// ignore..
|
||
|
out << "Found Self! Addr - " << inet_ntoa(neighbour.sin_addr);
|
||
|
out << ":" << ntohs(neighbour.sin_port) << std::endl;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ('D' == (((char *) ldata)[4])) // Then Ping.
|
||
|
{
|
||
|
// reply.
|
||
|
localReply(neighbour);
|
||
|
}
|
||
|
|
||
|
addLocalNeighbour(&neighbour, &server);
|
||
|
}
|
||
|
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
}
|
||
|
|
||
|
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||
|
#ifndef WINDOWS_SYS // ie UNIX
|
||
|
|
||
|
if ((size < 0) && (errno != EAGAIN))
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "Error Recieving Message" << std::endl;
|
||
|
out << "Errno: " << errno << std::endl;
|
||
|
out << socket_errorType(errno) << std::endl;
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
}
|
||
|
|
||
|
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||
|
#else // WINDOWS_SYS
|
||
|
|
||
|
if (size == SOCKET_ERROR)
|
||
|
{
|
||
|
int err = WSAGetLastError();
|
||
|
if (err != WSAEWOULDBLOCK)
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "Error Recieving Message" << std::endl;
|
||
|
out << "WSE: " << err << std::endl;
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
// This needs to be fixed up....
|
||
|
// Local dicsovery disabled for the moment....
|
||
|
|
||
|
int p3disc::addLocalNeighbour(struct sockaddr_in *n, struct sockaddr_in *s)
|
||
|
{
|
||
|
std::list<autoneighbour *>::iterator it;
|
||
|
for(it = neighbours.begin(); it != neighbours.end(); it++)
|
||
|
{
|
||
|
// if the server address matches one already!
|
||
|
// make sure its flags as local and return.
|
||
|
if (0 == memcmp((char *) &((*it) -> server_addr), (char *) s, sizeof(*s)))
|
||
|
{
|
||
|
(*it) -> local = true;
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
// else add it in!
|
||
|
autoneighbour *ln = new autoneighbour();
|
||
|
ln -> server_addr = (*s);
|
||
|
ln -> local = true;
|
||
|
ln -> id = NULL; // null cert
|
||
|
|
||
|
std::string nname = "Local Neighbour (";
|
||
|
nname += inet_ntoa(ln -> server_addr.sin_addr);
|
||
|
nname += ")";
|
||
|
|
||
|
//ln -> id -> Name(nname);
|
||
|
|
||
|
// now we call the dummy connect...
|
||
|
// this will only be done once per local neighbour.
|
||
|
// connectForExchange(ln -> server_addr);
|
||
|
|
||
|
neighbours.push_back(ln);
|
||
|
// update dicovered.
|
||
|
distillData();
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Code Fragment that might be useful when local is patched up....
|
||
|
/****************************************************
|
||
|
int p3disc::distillLocalData()
|
||
|
{
|
||
|
// This transforms the autoneighbour tree into
|
||
|
// a list of certificates with the best guess settings.
|
||
|
|
||
|
discovered.clear();
|
||
|
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, "p3disc::distillData()");
|
||
|
|
||
|
std::list<autoneighbour *>::iterator it;
|
||
|
std::list<autoneighbour *>::iterator it2;
|
||
|
|
||
|
// Now check for local -> remote duplicates....
|
||
|
for(it = neighbours.begin(); it != neighbours.end();)
|
||
|
{
|
||
|
cert *c = (cert *) ((*it) -> id);
|
||
|
if (((*it) -> local) && (c == NULL))
|
||
|
{
|
||
|
// potentially a duplicate.
|
||
|
bool found = false;
|
||
|
for(it2 = neighbours.begin(); it2 != neighbours.end(); it2++)
|
||
|
{
|
||
|
// if address is the same -> remove first version.
|
||
|
if ((it != it2) && (0 == memcmp((char *) &((*it) -> addr),
|
||
|
(char *) &((*it2) -> addr),
|
||
|
sizeof(struct sockaddr))))
|
||
|
{
|
||
|
(*it2) -> local = true;
|
||
|
found = true;
|
||
|
}
|
||
|
}
|
||
|
if (found == true)
|
||
|
{
|
||
|
// remove the certless local.
|
||
|
it = neighbours.erase(it);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
it++;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
it++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
******************************************/
|
||
|
|
||
|
|
||
|
int p3disc::idServers()
|
||
|
{
|
||
|
std::list<autoneighbour *>::iterator it;
|
||
|
std::list<autoserver *>::iterator nit;
|
||
|
int cts = time(NULL);
|
||
|
|
||
|
std::ostringstream out;
|
||
|
out << "::::AutoDiscovery Neighbours::::" << std::endl;
|
||
|
for(it = neighbours.begin(); it != neighbours.end(); it++)
|
||
|
{
|
||
|
if ((*it) -> local)
|
||
|
{
|
||
|
out << "Local Neighbour: ";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
out << "Friend of a friend: ";
|
||
|
}
|
||
|
cert *c = (cert *) ((*it) -> id);
|
||
|
|
||
|
if (c != NULL)
|
||
|
{
|
||
|
if (c -> certificate != NULL)
|
||
|
{
|
||
|
out << c -> certificate -> name;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
out << c -> Name();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
out << "UnIdentified";
|
||
|
}
|
||
|
|
||
|
out << std::endl;
|
||
|
out << "BG LocalAddr: ";
|
||
|
out << inet_ntoa((*it) -> local_addr.sin_addr);
|
||
|
out << ":" << ntohs((*it) -> local_addr.sin_port) << std::endl;
|
||
|
out << "BG Server: ";
|
||
|
out << inet_ntoa((*it) -> server_addr.sin_addr);
|
||
|
out << ":" << ntohs((*it) -> server_addr.sin_port) << std::endl;
|
||
|
out << " Listen TR: ";
|
||
|
if (((*it) -> listen) && ((*it) -> l_ts))
|
||
|
{
|
||
|
out << cts - (*it) -> l_ts << " sec ago";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
out << "Never";
|
||
|
}
|
||
|
out << " ";
|
||
|
|
||
|
out << "Connect TR: ";
|
||
|
if (((*it) -> connect) && ((*it) -> c_ts))
|
||
|
{
|
||
|
out << cts - (*it) -> c_ts << " sec ago";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
out << "Never";
|
||
|
}
|
||
|
|
||
|
if ((*it) -> active)
|
||
|
{
|
||
|
out << " Active!!!";
|
||
|
}
|
||
|
out << std::endl;
|
||
|
|
||
|
out << " -->DiscFlags: 0x" << std::hex << (*it)->discFlags;
|
||
|
out << std::dec << std::endl;
|
||
|
|
||
|
for(nit = ((*it) -> neighbour_of).begin();
|
||
|
nit != ((*it) -> neighbour_of).end(); nit++)
|
||
|
{
|
||
|
out << "\tConnected via: ";
|
||
|
if ((*nit) -> id != NULL)
|
||
|
{
|
||
|
out << ((*nit) ->id) -> Name() << "(";
|
||
|
out << inet_ntoa(((*nit) -> id) -> lastaddr.sin_addr);
|
||
|
out << ":" << ntohs(((*nit) -> id) -> lastaddr.sin_port);
|
||
|
out << ")";
|
||
|
}
|
||
|
out << std::endl;
|
||
|
out << "\t\tServer: ";
|
||
|
out << inet_ntoa((*nit) -> server_addr.sin_addr);
|
||
|
out <<":"<< ntohs((*nit) -> server_addr.sin_port);
|
||
|
out << std::endl;
|
||
|
out << "\t\tLocalAddr: ";
|
||
|
out << inet_ntoa((*nit) -> local_addr.sin_addr);
|
||
|
out <<":"<< ntohs((*nit) -> local_addr.sin_port);
|
||
|
|
||
|
out << std::endl;
|
||
|
if ((*nit) -> listen)
|
||
|
{
|
||
|
out << "\t\tListen TR:";
|
||
|
out << cts - (*nit) -> l_ts << " sec ago";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
out << "\t\tNever Received!";
|
||
|
}
|
||
|
out << std::endl;
|
||
|
if ((*nit) -> connect)
|
||
|
{
|
||
|
out << "\t\tConnect TR:";
|
||
|
out << cts - (*nit) -> c_ts << " sec ago";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
out << "\t\tNever Connected!";
|
||
|
}
|
||
|
out << std::endl;
|
||
|
out << "\t\tDiscFlags: 0x" << std::hex << (*nit)->discFlags;
|
||
|
out << std::dec << std::endl;
|
||
|
}
|
||
|
}
|
||
|
pqioutput(PQL_WARNING, pqidisczone, out.str());
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
int p3disc::newRequests()
|
||
|
{
|
||
|
// Check the timestamp against the list of certs.
|
||
|
// If any are newer and currently active, then
|
||
|
// send out Discovery Request.
|
||
|
// This initiates the p3disc procedure.
|
||
|
|
||
|
if (!remote_disc)
|
||
|
{
|
||
|
pqioutput(PQL_DEBUG_ALL, pqidisczone,
|
||
|
"p3disc::newRequests() Remote Discovery is turned off");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
pqioutput(PQL_DEBUG_ALL, pqidisczone,
|
||
|
"p3disc::newRequests() checkin for new neighbours");
|
||
|
|
||
|
// Perform operation on the cert list.
|
||
|
std::list<cert *>::iterator it;
|
||
|
// Temp variable
|
||
|
std::list<cert *> &certlist = sroot -> getCertList();
|
||
|
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "Checking CertList!" << std::endl;
|
||
|
out << "last_check: " << ts_lastcheck;
|
||
|
out << " time(): " << time(NULL);
|
||
|
pqioutput(PQL_DEBUG_ALL, pqidisczone, out.str());
|
||
|
}
|
||
|
|
||
|
for(it = certlist.begin(); it != certlist.end(); it++)
|
||
|
{
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "Cert: " << (*it) -> Name();
|
||
|
out << " lc_ts: " << (*it) -> lc_timestamp;
|
||
|
out << " lr_ts: " << (*it) -> lr_timestamp;
|
||
|
pqioutput(PQL_DEBUG_ALL, pqidisczone, out.str());
|
||
|
}
|
||
|
|
||
|
// This should be Connected(), rather than Accepted().
|
||
|
// should reply with all Accepted(), but only send to all connected().
|
||
|
// if (((*it) -> Accepted()) &&
|
||
|
//
|
||
|
// need >= to ensure that it will happen,
|
||
|
// about 1 in 5 chance of multiple newRequests if called every 5 secs.
|
||
|
// can live with this. (else switch to fractional seconds).
|
||
|
|
||
|
if (((*it) -> Connected()) &&
|
||
|
(((*it) -> lc_timestamp >= ts_lastcheck)
|
||
|
|| ((*it) -> lr_timestamp >= ts_lastcheck)))
|
||
|
{
|
||
|
|
||
|
// also must not have already sent message.
|
||
|
// (unless reconnection?)
|
||
|
// actually - this should occur, even if last
|
||
|
// exchange not complete.
|
||
|
// reconnect
|
||
|
|
||
|
/*****************************************************************************
|
||
|
* No more need for ad_init silliness....
|
||
|
*
|
||
|
//if (ad_init.end() ==
|
||
|
// find(ad_init.begin(),ad_init.end(),*it))
|
||
|
// infact - we need the opposite behaviour.
|
||
|
// remove if in the init list.
|
||
|
|
||
|
std::list<cert *>::iterator it2;
|
||
|
if (ad_init.end() !=
|
||
|
(it2 = find(ad_init.begin(),ad_init.end(),*it)))
|
||
|
{
|
||
|
ad_init.erase(it2);
|
||
|
}
|
||
|
*
|
||
|
*
|
||
|
*
|
||
|
****************************************************************************/
|
||
|
|
||
|
|
||
|
{
|
||
|
// Then send message.
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "p3disc::newRequests()";
|
||
|
out << "Constructing a Message!" << std::endl;
|
||
|
out << "Sending to: " << (*it) -> Name();
|
||
|
out << " lc_ts: " << (*it) -> lc_timestamp;
|
||
|
out << " lr_ts: " << (*it) -> lr_timestamp;
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
}
|
||
|
|
||
|
// Construct a message
|
||
|
RsDiscItem *di = new RsDiscItem();
|
||
|
|
||
|
// get our details.....
|
||
|
cert *own = sroot -> getOwnCert();
|
||
|
|
||
|
// Fill the message
|
||
|
di -> PeerId((*it) -> PeerId());
|
||
|
di -> laddr = own -> localaddr;
|
||
|
di -> saddr = own -> serveraddr;
|
||
|
|
||
|
// if we are firewalled..... (and no forwarding...)
|
||
|
// set received as impossible.
|
||
|
if (own -> Firewalled() && (!(own -> Forwarded())))
|
||
|
di -> receive_tr = 0; /* invalid */
|
||
|
else
|
||
|
di -> receive_tr = 1; /* zero time */
|
||
|
|
||
|
di -> connect_tr = 1; /* zero time */
|
||
|
di -> discFlags = determineCertAvailabilityFlags(own);
|
||
|
|
||
|
// Send off message
|
||
|
sendItem(di);
|
||
|
|
||
|
/*****************************************************************************
|
||
|
* No more need for ad_init silliness....
|
||
|
// push onto init list.
|
||
|
ad_init.push_back(*it);
|
||
|
*
|
||
|
****************************************************************************/
|
||
|
|
||
|
// Finally we should also advertise the
|
||
|
// new connection to our neighbours????
|
||
|
// SHOULD DO - NOT YET.
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
ts_lastcheck = time(NULL);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int p3disc::handleReplies()
|
||
|
{
|
||
|
RsItem *item = NULL;
|
||
|
pqioutput(PQL_DEBUG_ALL, pqidisczone, "p3disc::handleReplies()");
|
||
|
|
||
|
// if off discard item.
|
||
|
if (!remote_disc)
|
||
|
{
|
||
|
while(NULL != (item = recvItem()))
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "p3disc::handleReplies()";
|
||
|
out << " Deleting - Cos RemoteDisc Off!" << std::endl;
|
||
|
|
||
|
item -> print(out);
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
|
||
|
delete item;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int nhandled = 0;
|
||
|
// While messages read
|
||
|
while(NULL != (item = recvItem()))
|
||
|
{
|
||
|
RsDiscItem *di = NULL;
|
||
|
RsDiscReply *dri = NULL;
|
||
|
|
||
|
if (NULL == (di = dynamic_cast<RsDiscItem *> (item)))
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "p3disc::handleReplies()";
|
||
|
out << "Deleting Non RsDiscItem Msg" << std::endl;
|
||
|
item -> print(out);
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
|
||
|
// delete and continue to next loop.
|
||
|
delete item;
|
||
|
|
||
|
continue;
|
||
|
}
|
||
|
nhandled++;
|
||
|
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "p3disc::handleReplies()";
|
||
|
out << " Received Message!" << std::endl;
|
||
|
di -> print(out);
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
}
|
||
|
|
||
|
|
||
|
// if discovery reply then respondif haven't already.
|
||
|
if (NULL != (dri = dynamic_cast<RsDiscReply *> (di)))
|
||
|
{
|
||
|
|
||
|
// add to data tree.
|
||
|
handleDiscoveryData(dri);
|
||
|
}
|
||
|
else /* Ping */
|
||
|
{
|
||
|
handleDiscoveryPing(di);
|
||
|
|
||
|
/* find the certificate */
|
||
|
certsign sign;
|
||
|
convert_to_certsign(di->PeerId(), sign);
|
||
|
cert *peer = getSSLRoot() -> findcertsign(sign);
|
||
|
if (peer)
|
||
|
{
|
||
|
sendDiscoveryReply(peer);
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone,
|
||
|
"After Reply to Ping");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pqioutput(PQL_ALERT, pqidisczone,
|
||
|
"Failed to Match disc Ping ID");
|
||
|
}
|
||
|
}
|
||
|
delete di;
|
||
|
}
|
||
|
return nhandled;
|
||
|
}
|
||
|
|
||
|
int p3disc::sendDiscoveryReply(cert *p)
|
||
|
{
|
||
|
if (!remote_disc)
|
||
|
return -1;
|
||
|
|
||
|
// So to send a discovery reply .... we need to....
|
||
|
// 1) generate a list of our neighbours.....
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone,
|
||
|
"p3disc::sendDiscoveryReply() Generating Messages!");
|
||
|
|
||
|
std::list<cert *>::iterator it;
|
||
|
// Temp variable
|
||
|
std::list<cert *> &certlist = sroot -> getCertList();
|
||
|
int good_certs = 0;
|
||
|
int cts = time(NULL);
|
||
|
|
||
|
for(it = certlist.begin(); it != certlist.end(); it++)
|
||
|
{
|
||
|
// if accepted and has connected (soon)
|
||
|
if ((*it) -> Accepted())
|
||
|
{
|
||
|
good_certs++;
|
||
|
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "p3disc::sendDiscoveryReply()";
|
||
|
out << " Found Neighbour Cert!" << std::endl;
|
||
|
out << "Encoding: "<<(*it)->Name() << std::endl;
|
||
|
out << "Encoding(2): "<<(*it)->certificate->name << std::endl;
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
}
|
||
|
|
||
|
// Construct a message
|
||
|
RsDiscReply *di = new RsDiscReply();
|
||
|
|
||
|
// Fill the message
|
||
|
// Set Target as input cert.
|
||
|
di -> PeerId(p -> PeerId());
|
||
|
|
||
|
// set the server address.
|
||
|
di -> laddr = (*it) -> localaddr;
|
||
|
di -> saddr = (*it) -> serveraddr;
|
||
|
|
||
|
// set the timeframe since last connection.
|
||
|
if ((*it) -> lr_timestamp <= 0)
|
||
|
{
|
||
|
di -> receive_tr = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
di -> receive_tr = convertTDeltaToTRange(cts - (*it) -> lr_timestamp);
|
||
|
}
|
||
|
|
||
|
if ((*it) -> lc_timestamp <= 0)
|
||
|
{
|
||
|
di -> connect_tr = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
di -> connect_tr = convertTDeltaToTRange(cts - (*it) -> lc_timestamp);
|
||
|
}
|
||
|
di -> discFlags = determineCertAvailabilityFlags(*it);
|
||
|
|
||
|
// actually ned to copy certificate to array
|
||
|
// for proper cert stuff.
|
||
|
|
||
|
/**************** PQI_USE_XPGP ******************/
|
||
|
#if defined(PQI_USE_XPGP)
|
||
|
int len = i2d_XPGP((*it) -> certificate, (unsigned char **) &(di -> certDER.bin_data));
|
||
|
#else /* X509 Certificates */
|
||
|
/**************** PQI_USE_XPGP ******************/
|
||
|
int len = i2d_X509((*it) -> certificate, (unsigned char **) &(di -> certDER.bin_data));
|
||
|
#endif /* X509 Certificates */
|
||
|
/**************** PQI_USE_XPGP ******************/
|
||
|
if (len > 0)
|
||
|
{
|
||
|
di -> certDER.bin_len = len;
|
||
|
std::ostringstream out;
|
||
|
out << "Cert Encoded(" << len << ")" << std::endl;
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, "Failed to Encode Cert");
|
||
|
di -> certDER.bin_len = 0;
|
||
|
}
|
||
|
|
||
|
// Send off message
|
||
|
sendItem(di);
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, "Sent DI Message");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "p3disc::sendDiscoveryReply()";
|
||
|
out << "Not Sending Cert: " << std::endl;
|
||
|
out << (*it) -> Name() << std::endl;
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "p3disc::sendDiscoveryReply()";
|
||
|
out << "Found " << good_certs << " Certs" << std::endl;
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
int p3disc::handleDiscoveryPing(RsDiscItem *di)
|
||
|
{
|
||
|
std::list<autoneighbour *>::iterator it;
|
||
|
|
||
|
// as already connected.... certificate available.
|
||
|
certsign sign;
|
||
|
convert_to_certsign(di->PeerId(), sign);
|
||
|
cert *c = getSSLRoot() -> findcertsign(sign);
|
||
|
|
||
|
if (c == NULL)
|
||
|
return -1;
|
||
|
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "p3disc::handleDiscoveryPing()" << std::endl;
|
||
|
di -> print(out);
|
||
|
out << "RECEIVED Self Describing RsDiscItem!";
|
||
|
out << std::endl;
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
}
|
||
|
|
||
|
// The first check is whether this packet came from
|
||
|
// the cert in the reply.
|
||
|
|
||
|
// Local address is always right!
|
||
|
// No User control anyway!
|
||
|
c -> localaddr = di -> laddr;
|
||
|
|
||
|
// The Rest of this should only be set
|
||
|
// if we are in autoconnect mode.....
|
||
|
// else should be done manually.
|
||
|
// ----> Think we should do this always (is disc from then)
|
||
|
/****************************
|
||
|
if (!(c -> Manual()))
|
||
|
****************************/
|
||
|
{
|
||
|
|
||
|
// if the connect addr isn't valid.
|
||
|
if (!isValidNet(&(c -> lastaddr.sin_addr)))
|
||
|
{
|
||
|
// set it all
|
||
|
c -> serveraddr = di -> saddr;
|
||
|
pqioutput(PQL_WARNING, pqidisczone,
|
||
|
"lastaddr !Valid -> serveraddr=di->saddr");
|
||
|
}
|
||
|
// if the connect addr == dispkt.local
|
||
|
else if (0 == inaddr_cmp(c -> lastaddr, di -> laddr))
|
||
|
{
|
||
|
// set it all
|
||
|
c -> serveraddr = di -> saddr;
|
||
|
c -> Local(true);
|
||
|
pqioutput(PQL_WARNING, pqidisczone,
|
||
|
"lastaddr=di->laddr -> Local & serveraddr=di->saddr");
|
||
|
}
|
||
|
else if (0 == inaddr_cmp(c -> lastaddr, di -> saddr))
|
||
|
{
|
||
|
pqioutput(PQL_WARNING, pqidisczone,
|
||
|
"lastaddr=di->saddr -> !Local & serveraddr=di->saddr");
|
||
|
c -> serveraddr = di -> saddr;
|
||
|
c -> Local(false);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pqioutput(PQL_WARNING, pqidisczone,
|
||
|
"lastaddr!=(di->laddr|di->saddr) -> !Local,serveraddr left");
|
||
|
c -> Local(false);
|
||
|
}
|
||
|
|
||
|
updateCertAvailabilityFlags(c, di->discFlags);
|
||
|
|
||
|
}
|
||
|
/****************************
|
||
|
else
|
||
|
{
|
||
|
pqioutput(PQL_WARNING, pqidisczone,
|
||
|
"peer is Manual -> leaving server settings");
|
||
|
if (0 == inaddr_cmp(c -> lastaddr, di -> laddr))
|
||
|
{
|
||
|
pqioutput(PQL_WARNING, pqidisczone,
|
||
|
"c->lastaddr=di->laddr -> local");
|
||
|
c -> Local(true);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pqioutput(PQL_WARNING, pqidisczone,
|
||
|
"c->lastaddr!=di->laddr -> !local");
|
||
|
c -> Local(false);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
****************************/
|
||
|
|
||
|
// Now add it into the system.
|
||
|
// check if it exists already......
|
||
|
for(it = neighbours.begin(); it != neighbours.end(); it++)
|
||
|
{
|
||
|
cert *c2 = (cert *) (*it) -> id;
|
||
|
/**************** PQI_USE_XPGP ******************/
|
||
|
#if defined(PQI_USE_XPGP)
|
||
|
if ((c2 != NULL) && (0 == XPGP_cmp(
|
||
|
c -> certificate, c2 -> certificate)))
|
||
|
#else /* X509 Certificates */
|
||
|
/**************** PQI_USE_XPGP ******************/
|
||
|
if ((c2 != NULL) && (0 == X509_cmp(
|
||
|
c -> certificate, c2 -> certificate)))
|
||
|
#endif /* X509 Certificates */
|
||
|
/**************** PQI_USE_XPGP ******************/
|
||
|
{
|
||
|
// matching....
|
||
|
// update it....;
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, "Updating Certificate (AN)!");
|
||
|
|
||
|
(*it)-> local = c -> Local();
|
||
|
updateAutoServer((*it), di);
|
||
|
|
||
|
/* now look through the neighbours_of */
|
||
|
std::list<autoserver *>::iterator nit;
|
||
|
for(nit = ((*it) -> neighbour_of).begin();
|
||
|
nit != ((*it) -> neighbour_of).end(); nit++)
|
||
|
{
|
||
|
|
||
|
/* check if we already have a autoserver.... */
|
||
|
if ((*it)->id == (*nit)->id)
|
||
|
{
|
||
|
/* we already have one */
|
||
|
// update it....;
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone,
|
||
|
"Updating Certificate (AS)!");
|
||
|
|
||
|
updateAutoServer(*nit, di);
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone,
|
||
|
"Adding Certificate (AS)!");
|
||
|
|
||
|
/* if we get here, we need to add an autoserver */
|
||
|
autoserver *as = new autoserver();
|
||
|
as -> id = c;
|
||
|
updateAutoServer(as, di);
|
||
|
(*it) -> neighbour_of.push_back(as);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// if get here must add a autoneighbour + an autoserver.
|
||
|
|
||
|
autoneighbour *an = new autoneighbour();
|
||
|
an -> id = c;
|
||
|
an -> local = c -> Local();
|
||
|
updateAutoServer(an, di);
|
||
|
|
||
|
// add autoserver to an.
|
||
|
autoserver *as = new autoserver();
|
||
|
as -> id = c;
|
||
|
updateAutoServer(as, di);
|
||
|
|
||
|
an -> neighbour_of.push_back(as);
|
||
|
neighbours.push_back(an);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
int p3disc::handleDiscoveryData(RsDiscReply *di)
|
||
|
{
|
||
|
std::list<autoneighbour *>::iterator it;
|
||
|
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "p3disc::handleDiscoveryData()" << std::endl;
|
||
|
di -> print(out);
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
}
|
||
|
|
||
|
|
||
|
certsign sign;
|
||
|
convert_to_certsign(di->PeerId(), sign);
|
||
|
cert *di_peer = getSSLRoot() -> findcertsign(sign);
|
||
|
if (!di_peer)
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "p3disc::handleDiscoveryData() BAD Id" << std::endl;
|
||
|
di -> print(out);
|
||
|
pqioutput(PQL_ALERT, pqidisczone, out.str());
|
||
|
delete di;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* WIN/LINUX Difference.
|
||
|
*/
|
||
|
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||
|
#ifndef WINDOWS_SYS // ie UNIX
|
||
|
const unsigned char *certptr = (const unsigned char *) di -> certDER.bin_data;
|
||
|
#else
|
||
|
unsigned char *certptr = (unsigned char *) di -> certDER.bin_data;
|
||
|
#endif
|
||
|
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||
|
|
||
|
|
||
|
// load up the certificate.....
|
||
|
/**************** PQI_USE_XPGP ******************/
|
||
|
#if defined(PQI_USE_XPGP)
|
||
|
|
||
|
XPGP *tmp = NULL;
|
||
|
XPGP *xpgp = d2i_XPGP(&tmp, (unsigned char **) &certptr, di -> certDER.bin_len);
|
||
|
if (xpgp == NULL)
|
||
|
return -1;
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "p3disc::handleDiscoveryData()" << std::endl;
|
||
|
out << "certificate name: " << xpgp -> name << std::endl;
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
}
|
||
|
|
||
|
// if a duplicate with ad/or sslroot;
|
||
|
cert *c = sroot -> makeCertificateXPGP(xpgp);
|
||
|
if (c == NULL)
|
||
|
{
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone,
|
||
|
"Failed to Create Certificate");
|
||
|
// delete the cert.
|
||
|
XPGP_free(xpgp);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
#else /* X509 Certificates */
|
||
|
/**************** PQI_USE_XPGP ******************/
|
||
|
|
||
|
X509 *tmp = NULL;
|
||
|
X509 *x509 = d2i_X509(&tmp, &certptr, di -> certLen);
|
||
|
if (x509 == NULL)
|
||
|
return -1;
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "p3disc::handleDiscoveryData()" << std::endl;
|
||
|
out << "certificate name: " << x509 -> name << std::endl;
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
}
|
||
|
|
||
|
// if a duplicate with ad/or sslroot;
|
||
|
cert *c = sroot -> makeCertificate(x509);
|
||
|
if (c == NULL)
|
||
|
{
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone,
|
||
|
"Failed to Create Certificate");
|
||
|
// delete the cert.
|
||
|
X509_free(x509);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
#endif /* X509 Certificates */
|
||
|
/**************** PQI_USE_XPGP ******************/
|
||
|
|
||
|
|
||
|
// So have new/existing cert;
|
||
|
// check if it exists already......
|
||
|
for(it = neighbours.begin(); it != neighbours.end(); it++)
|
||
|
{
|
||
|
cert *c2 = (cert *) (*it) -> id;
|
||
|
|
||
|
/**************** PQI_USE_XPGP ******************/
|
||
|
#if defined(PQI_USE_XPGP)
|
||
|
if ((c2 != NULL) && (0 == XPGP_cmp(
|
||
|
c -> certificate, c2 -> certificate)))
|
||
|
#else /* X509 Certificates */
|
||
|
/**************** PQI_USE_XPGP ******************/
|
||
|
if ((c2 != NULL) && (0 == X509_cmp(
|
||
|
c -> certificate, c2 -> certificate)))
|
||
|
#endif /* X509 Certificates */
|
||
|
/**************** PQI_USE_XPGP ******************/
|
||
|
{
|
||
|
// matching.... check neighbours of....
|
||
|
// for the source of the message.
|
||
|
|
||
|
std::list<autoserver *>::iterator nit;
|
||
|
for(nit = ((*it) -> neighbour_of).begin();
|
||
|
nit != ((*it) -> neighbour_of).end(); nit++)
|
||
|
{
|
||
|
|
||
|
|
||
|
/**************** PQI_USE_XPGP ******************/
|
||
|
#if defined(PQI_USE_XPGP)
|
||
|
if (0 == XPGP_cmp(
|
||
|
#else /* X509 Certificates */
|
||
|
/**************** PQI_USE_XPGP ******************/
|
||
|
if (0 == X509_cmp(
|
||
|
#endif /* X509 Certificates */
|
||
|
/**************** PQI_USE_XPGP ******************/
|
||
|
((cert *) (*nit) -> id) -> certificate,
|
||
|
di_peer -> certificate))
|
||
|
{
|
||
|
|
||
|
// update it....;
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone,
|
||
|
"Updating Certificate!");
|
||
|
|
||
|
updateAutoServer(*nit, di);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// if we get to here - add neighbour of info.
|
||
|
autoserver *as = new autoserver();
|
||
|
as -> id = di_peer;
|
||
|
|
||
|
// add in some more ....as -> addr = (di -> );
|
||
|
|
||
|
updateAutoServer(as, di);
|
||
|
|
||
|
(*it) -> neighbour_of.push_back(as);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// if get here must add a autoneighbour + autoserver.
|
||
|
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "p3disc::handleDiscoveryData()" << std::endl;
|
||
|
out << "Adding New AutoNeighbour:" << c -> Name() << std::endl;
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
}
|
||
|
|
||
|
autoneighbour *an = new autoneighbour();
|
||
|
an -> id = c;
|
||
|
// initial guess.
|
||
|
an -> local_addr = di -> laddr;
|
||
|
an -> server_addr = di -> saddr;
|
||
|
an -> local = false;
|
||
|
|
||
|
autoserver *as = new autoserver();
|
||
|
as -> id = di_peer;
|
||
|
|
||
|
updateAutoServer(as, di);
|
||
|
|
||
|
an -> neighbour_of.push_back(as);
|
||
|
|
||
|
neighbours.push_back(an);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int p3disc::collectCerts()
|
||
|
{
|
||
|
|
||
|
// First get any extras from the CollectedCerts Queue.
|
||
|
// if the cert matches an existing one.... update + discard
|
||
|
// else add in....
|
||
|
|
||
|
std::list<autoneighbour *>::iterator it;
|
||
|
std::list<autoneighbour *>::iterator it2;
|
||
|
|
||
|
cert *nc;
|
||
|
while(NULL != (nc = sroot -> getCollectedCert()))
|
||
|
{
|
||
|
// check for matching certs.
|
||
|
bool found = false;
|
||
|
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "p3disc::collectCert: " << std::endl;
|
||
|
out << "Name: " << nc -> Name() << std::endl;
|
||
|
out << "CN: " << nc -> certificate -> name << std::endl;
|
||
|
|
||
|
out << " From: ";
|
||
|
out << inet_ntoa(nc -> lastaddr.sin_addr);
|
||
|
out << ":" << ntohs(nc -> lastaddr.sin_port) << std::endl;
|
||
|
out << " Local: ";
|
||
|
out << inet_ntoa(nc -> localaddr.sin_addr);
|
||
|
out << ":" << ntohs(nc -> localaddr.sin_port) << std::endl;
|
||
|
out << " Server: ";
|
||
|
out << inet_ntoa(nc -> serveraddr.sin_addr);
|
||
|
out << ":" << ntohs(nc -> serveraddr.sin_port) << std::endl;
|
||
|
out << " Listen TS:";
|
||
|
out << nc -> lr_timestamp << " ";
|
||
|
out << "Connect TR:";
|
||
|
out << nc -> lc_timestamp << std::endl;
|
||
|
out << std::endl;
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
}
|
||
|
|
||
|
|
||
|
for(it = neighbours.begin(); (!found) && (it != neighbours.end()); it++)
|
||
|
{
|
||
|
cert *c = (cert *) ((*it) -> id);
|
||
|
/**************** PQI_USE_XPGP ******************/
|
||
|
#if defined(PQI_USE_XPGP)
|
||
|
if ((c != NULL) &&
|
||
|
(0 == XPGP_cmp(c -> certificate, nc -> certificate)))
|
||
|
#else /* X509 Certificates */
|
||
|
/**************** PQI_USE_XPGP ******************/
|
||
|
if ((c != NULL) &&
|
||
|
(0 == X509_cmp(c -> certificate, nc -> certificate)))
|
||
|
#endif /* X509 Certificates */
|
||
|
/**************** PQI_USE_XPGP ******************/
|
||
|
{
|
||
|
/* addresses handled already ....
|
||
|
* by sslroot. (more intelligent decisions).
|
||
|
* update timestamps so we don't overwrite
|
||
|
* the uptodate cert data.
|
||
|
*/
|
||
|
|
||
|
found = true;
|
||
|
if ((nc -> lc_timestamp > 0) &&
|
||
|
((unsigned) nc -> lc_timestamp > (*it) -> c_ts))
|
||
|
{
|
||
|
// connect.... timestamp
|
||
|
(*it) -> connect = true;
|
||
|
(*it) -> c_ts = nc -> lc_timestamp;
|
||
|
// don't make this decision here.
|
||
|
//(*it) -> server_addr = nc -> lastaddr;
|
||
|
}
|
||
|
|
||
|
if ((nc -> lr_timestamp > 0) &&
|
||
|
((unsigned) nc -> lr_timestamp > (*it) -> l_ts))
|
||
|
{
|
||
|
// received.... timestamp
|
||
|
(*it) -> listen = true;
|
||
|
(*it) -> l_ts = nc -> lr_timestamp;
|
||
|
}
|
||
|
|
||
|
if ((c != nc) ||
|
||
|
(c -> certificate != nc -> certificate))
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "Warning Dup/Diff Mem ";
|
||
|
out << " Found in p3Disc!";
|
||
|
out << std::endl;
|
||
|
pqioutput(PQL_ALERT, pqidisczone, out.str());
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (!found)
|
||
|
{
|
||
|
// add into the list.....
|
||
|
autoneighbour *an = new autoneighbour();
|
||
|
an -> id = nc;
|
||
|
|
||
|
// initial guess.
|
||
|
an -> local_addr = nc -> localaddr;
|
||
|
an -> server_addr = nc -> serveraddr;
|
||
|
an -> local = false;
|
||
|
|
||
|
if (nc -> lc_timestamp > 0)
|
||
|
{
|
||
|
an -> c_ts = nc -> lc_timestamp;
|
||
|
an -> connect = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
an -> c_ts = 0;
|
||
|
an -> connect = false;
|
||
|
}
|
||
|
|
||
|
if (nc -> lr_timestamp > 0)
|
||
|
{
|
||
|
an -> l_ts = nc -> lr_timestamp;
|
||
|
an -> listen = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
an -> l_ts = 0;
|
||
|
an -> listen = false;
|
||
|
}
|
||
|
|
||
|
neighbours.push_back(an);
|
||
|
}
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int p3disc::distillData()
|
||
|
{
|
||
|
// This transforms the autoneighbour tree into
|
||
|
// a list of certificates with the best guess settings.
|
||
|
|
||
|
// get any extra. from sslroot.
|
||
|
collectCerts();
|
||
|
|
||
|
discovered.clear();
|
||
|
|
||
|
std::ostringstream out;
|
||
|
out << "p3disc::distillData()" << std::endl;
|
||
|
|
||
|
std::list<autoneighbour *>::iterator it;
|
||
|
std::list<autoneighbour *>::iterator it2;
|
||
|
std::list<autoserver *>::iterator nit;
|
||
|
cert *own = sroot -> getOwnCert();
|
||
|
|
||
|
for(it = neighbours.begin(); it != neighbours.end(); it++)
|
||
|
{
|
||
|
/* for the moment this is going to be a simplistic
|
||
|
* (and non-fault tolerent design)....
|
||
|
* we will take the most up-to-date values.... from the friends of neighbours.
|
||
|
*
|
||
|
* if these are more up-to-date than both the
|
||
|
* (1) neighbour (*it) and
|
||
|
* (2) the actual certificate and
|
||
|
* (3) we are not connected... then
|
||
|
*
|
||
|
* (a) we update the addresses and timestamps on the neighbour.
|
||
|
* (b) addresses on the certificate.
|
||
|
*
|
||
|
* Therefore
|
||
|
* cert has (1) our connect times, (2) best guess server.
|
||
|
* neighbour has uptodate times/servers from last distill.
|
||
|
*
|
||
|
* NOTE this requires a better algorithm.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
unsigned int mr_connect = 0;
|
||
|
unsigned int mr_listen = 0;
|
||
|
|
||
|
unsigned int mr_both = 0; /* connect or receive */
|
||
|
/* three fields below match most recent (of either) */
|
||
|
struct sockaddr_in mr_server;
|
||
|
struct sockaddr_in mr_local;
|
||
|
unsigned int mr_flags = 0;
|
||
|
|
||
|
/* if we find a neighbour_of, which is the same cert.
|
||
|
* then we have the definitive answer already
|
||
|
* (and it has been installed)
|
||
|
*/
|
||
|
|
||
|
bool haveDefinitive = false;
|
||
|
|
||
|
cert *c = (cert *) (*it) -> id;
|
||
|
for(nit = ((*it) -> neighbour_of).begin();
|
||
|
nit != ((*it) -> neighbour_of).end(); nit++)
|
||
|
{
|
||
|
out << "\tDistill Connected via: ";
|
||
|
if ((*nit) -> id != NULL)
|
||
|
{
|
||
|
out << ((*nit) ->id) -> Name();
|
||
|
}
|
||
|
out << std::endl;
|
||
|
out << "\t\tServer: ";
|
||
|
out << inet_ntoa((*nit)->server_addr.sin_addr);
|
||
|
out << ":" << ntohs((*nit)->server_addr.sin_port);
|
||
|
out << std::endl;
|
||
|
if ((*nit)->id == (*it)->id)
|
||
|
{
|
||
|
haveDefinitive = true;
|
||
|
out << "\t\tIs Definitive Answer!";
|
||
|
out << std::endl;
|
||
|
}
|
||
|
|
||
|
if ((*nit) -> listen)
|
||
|
{
|
||
|
if ((*nit)->l_ts > mr_listen)
|
||
|
{
|
||
|
mr_listen = (*nit)->l_ts;
|
||
|
if (mr_listen > mr_both)
|
||
|
{
|
||
|
mr_both = mr_listen;
|
||
|
mr_server = (*nit) -> server_addr;
|
||
|
mr_local = (*nit) -> local_addr;
|
||
|
mr_flags = (*nit) -> discFlags;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ((*nit) -> connect)
|
||
|
{
|
||
|
if ((*nit) -> c_ts > mr_connect)
|
||
|
{
|
||
|
mr_connect = (*nit)->c_ts;
|
||
|
if (mr_connect > mr_both)
|
||
|
{
|
||
|
mr_both = mr_connect;
|
||
|
mr_server = (*nit) -> server_addr;
|
||
|
mr_local = (*nit) -> local_addr;
|
||
|
mr_flags = (*nit) -> discFlags;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ((c == own) || (haveDefinitive))
|
||
|
{
|
||
|
out << c -> Name();
|
||
|
out << ": Is Own or Definitive: no Update...";
|
||
|
out << std::endl;
|
||
|
|
||
|
discovered.push_back(c);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ((mr_both > (*it)-> c_ts) && (mr_both > (*it)-> l_ts))
|
||
|
{
|
||
|
(*it) -> server_addr = mr_server;
|
||
|
(*it) -> local_addr = mr_local;
|
||
|
(*it) -> discFlags = mr_flags;
|
||
|
|
||
|
}
|
||
|
|
||
|
/* now we can check against (*it) */
|
||
|
if ((!(*it)->listen) || ((*it)-> l_ts < mr_listen))
|
||
|
{
|
||
|
(*it) -> listen = true;
|
||
|
(*it)-> l_ts = mr_listen;
|
||
|
}
|
||
|
|
||
|
if ((!(*it)->connect) || ((*it)-> c_ts < mr_connect))
|
||
|
{
|
||
|
(*it) -> connect = true;
|
||
|
(*it)-> c_ts = mr_connect;
|
||
|
}
|
||
|
|
||
|
/* XXX fixme ***/
|
||
|
// Finally we can update the certificate, if auto
|
||
|
// is selected.... or not in use.
|
||
|
if (!(c -> Connected()))
|
||
|
{
|
||
|
out << "Checking: " << c -> Name() << std::endl;
|
||
|
|
||
|
// if empty local
|
||
|
if (0 == inaddr_cmp(c -> localaddr, INADDR_ANY))
|
||
|
{
|
||
|
out << "\tUpdating NULL Local Addr:" << std::endl;
|
||
|
out << "\t\tOld: ";
|
||
|
out << inet_ntoa(c->localaddr.sin_addr);
|
||
|
out << ":" << ntohs(c->localaddr.sin_port);
|
||
|
c -> localaddr = (*it) -> local_addr;
|
||
|
out << "\t\tNew: ";
|
||
|
out << inet_ntoa(c->localaddr.sin_addr);
|
||
|
out << ":" << ntohs(c->localaddr.sin_port);
|
||
|
}
|
||
|
|
||
|
// if empty server .....
|
||
|
if (0 == inaddr_cmp(c -> serveraddr, INADDR_ANY))
|
||
|
{
|
||
|
out << "\tUpdating NULL Serv Addr:" << std::endl;
|
||
|
out << "\t\tOld: ";
|
||
|
out << inet_ntoa(c->serveraddr.sin_addr);
|
||
|
out << ":" << ntohs(c->serveraddr.sin_port);
|
||
|
c -> serveraddr = (*it) -> server_addr;
|
||
|
out << "\t\tNew: ";
|
||
|
out << inet_ntoa(c->serveraddr.sin_addr);
|
||
|
out << ":" << ntohs(c->serveraddr.sin_port);
|
||
|
}
|
||
|
// if local (second as should catch empty)
|
||
|
else if ((0 == inaddr_cmp((*it) -> server_addr,
|
||
|
c -> localaddr)))
|
||
|
//&& (inaddr_local(c -> localaddr))
|
||
|
{
|
||
|
out << "\tMaking Local..." << std::endl;
|
||
|
c -> Local(true);
|
||
|
}
|
||
|
|
||
|
// Finally the key update ....
|
||
|
// check only against the latest data....
|
||
|
|
||
|
if (mr_both)
|
||
|
{
|
||
|
//
|
||
|
unsigned int cert_both = c -> lc_timestamp;
|
||
|
if (cert_both < (unsigned) c -> lr_timestamp)
|
||
|
{
|
||
|
cert_both = c -> lr_timestamp;
|
||
|
}
|
||
|
|
||
|
int log_delta = -1; /* invalid log */
|
||
|
if (mr_both > cert_both)
|
||
|
{
|
||
|
log_delta = (int) log10((double) (mr_both - cert_both));
|
||
|
}
|
||
|
|
||
|
/* if a peer has connected more recently than us */
|
||
|
if (log_delta > 3) // or > 10000 (secs), or ~3 hours.
|
||
|
{
|
||
|
out << "\tUpdating OLD Addresses:" << std::endl;
|
||
|
out << "\t\tOld Local: ";
|
||
|
out << inet_ntoa(c->serveraddr.sin_addr);
|
||
|
out << ":" << ntohs(c->serveraddr.sin_port);
|
||
|
out << std::endl;
|
||
|
out << "\t\tOld Server: ";
|
||
|
out << inet_ntoa(c->serveraddr.sin_addr);
|
||
|
out << ":" << ntohs(c->serveraddr.sin_port);
|
||
|
out << std::endl;
|
||
|
if (c->Firewalled())
|
||
|
{
|
||
|
out << "\t\tFireWalled/";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
out << "\t\tNot FireWalled/";
|
||
|
}
|
||
|
if (c->Forwarded())
|
||
|
{
|
||
|
out << "Forwarded";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
out << "Not Forwarded";
|
||
|
}
|
||
|
out << std::endl;
|
||
|
|
||
|
if (0!=inaddr_cmp(mr_server, INADDR_ANY))
|
||
|
{
|
||
|
c -> serveraddr = mr_server;
|
||
|
}
|
||
|
|
||
|
if (0!=inaddr_cmp(mr_local, INADDR_ANY))
|
||
|
{
|
||
|
c -> localaddr = mr_local;
|
||
|
}
|
||
|
|
||
|
updateCertAvailabilityFlags(c, mr_flags);
|
||
|
|
||
|
out << "\t\tNew: ";
|
||
|
out << inet_ntoa(c->serveraddr.sin_addr);
|
||
|
out << ":" << ntohs(c->serveraddr.sin_port);
|
||
|
out << "\t\tNew Local: ";
|
||
|
out << inet_ntoa(c->serveraddr.sin_addr);
|
||
|
out << ":" << ntohs(c->serveraddr.sin_port);
|
||
|
out << std::endl;
|
||
|
out << "\t\tNew Server: ";
|
||
|
out << inet_ntoa(c->serveraddr.sin_addr);
|
||
|
out << ":" << ntohs(c->serveraddr.sin_port);
|
||
|
out << std::endl;
|
||
|
if (c->Firewalled())
|
||
|
{
|
||
|
out << "\t\tFireWalled/";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
out << "\t\tNot FireWalled/";
|
||
|
}
|
||
|
if (c->Forwarded())
|
||
|
{
|
||
|
out << "Forwarded";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
out << "Not Forwarded";
|
||
|
}
|
||
|
out << std::endl;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
discovered.push_back(c);
|
||
|
}
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str());
|
||
|
idServers();
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
std::list<cert *> &p3disc::getDiscovered()
|
||
|
{
|
||
|
return discovered;
|
||
|
}
|
||
|
|
||
|
static const std::string pqi_adflags("PQI_ADFLAGS");
|
||
|
|
||
|
int p3disc::save_configuration()
|
||
|
{
|
||
|
if (sroot == NULL)
|
||
|
return -1;
|
||
|
|
||
|
std::string localflags;
|
||
|
if (local_disc)
|
||
|
localflags += "L";
|
||
|
if (remote_disc)
|
||
|
localflags += "R";
|
||
|
sroot -> setSetting(pqi_adflags, localflags);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
// load configuration from sslcert -> owncert()
|
||
|
// instead of from the configuration files.
|
||
|
|
||
|
int p3disc::load_configuration()
|
||
|
{
|
||
|
unsigned int i = 0;
|
||
|
|
||
|
if (sroot == NULL)
|
||
|
return -1;
|
||
|
|
||
|
Person *p = sroot -> getOwnCert();
|
||
|
if (p == NULL)
|
||
|
return -1;
|
||
|
laddr = p -> localaddr;
|
||
|
//laddr.sin_family = AF_INET;
|
||
|
|
||
|
saddr = p -> serveraddr;
|
||
|
local_firewalled = p -> Firewalled();
|
||
|
local_forwarded = p -> Forwarded();
|
||
|
|
||
|
std::string localflags = sroot -> getSetting(pqi_adflags);
|
||
|
// initially drop out gracefully.
|
||
|
if (localflags.length() == 0)
|
||
|
return 1;
|
||
|
if (i < localflags.length())
|
||
|
if (local_disc = ('L' == localflags[i]))
|
||
|
i++;
|
||
|
if (i < localflags.length())
|
||
|
if (remote_disc = ('R' == localflags[i]))
|
||
|
i++;
|
||
|
// temp turn on!
|
||
|
local_disc = false; // true;
|
||
|
remote_disc = true;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
std::list<cert *> p3disc::potentialproxy(cert *target)
|
||
|
{
|
||
|
std::list<cert *> certs;
|
||
|
// search the discovery tree for proxies for target.
|
||
|
|
||
|
std::list<autoneighbour *>::iterator it;
|
||
|
std::list<autoserver *>::iterator nit;
|
||
|
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone,
|
||
|
"p3disc::potentialproxy()");
|
||
|
|
||
|
for(it = neighbours.begin(); it != neighbours.end(); it++)
|
||
|
{
|
||
|
cert *c = (cert *) (*it) -> id;
|
||
|
if (c == target)
|
||
|
{
|
||
|
// found target.
|
||
|
for(nit = ((*it) -> neighbour_of).begin();
|
||
|
nit != ((*it) -> neighbour_of).end(); nit++)
|
||
|
{
|
||
|
/* can't use target as proxy */
|
||
|
cert *pp = (cert *) (*nit)->id;
|
||
|
if ((pp -> Connected()) && (target != pp))
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "Potential Proxy: ";
|
||
|
out << pp -> Name();
|
||
|
certs.push_back(pp);
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone,
|
||
|
out.str());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return certs;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pqioutput(PQL_DEBUG_BASIC, pqidisczone,
|
||
|
"p3disc::potentialproxy() No proxies found");
|
||
|
// empty list.
|
||
|
return certs;
|
||
|
}
|
||
|
|
||
|
std::list<struct sockaddr_in> p3disc::requestStunServers()
|
||
|
{
|
||
|
|
||
|
/* loop through all the possibilities
|
||
|
*
|
||
|
* find the ones which aren't firewalled.
|
||
|
*
|
||
|
* get their addresses.
|
||
|
*/
|
||
|
cert *own = sroot -> getOwnCert();
|
||
|
|
||
|
std::list<struct sockaddr_in> stunList;
|
||
|
|
||
|
std::list<autoneighbour *>::iterator it;
|
||
|
for(it = neighbours.begin(); it != neighbours.end(); it++)
|
||
|
{
|
||
|
cert *c = (cert *) (*it) -> id;
|
||
|
|
||
|
/* if flags are correct, and the address looks
|
||
|
* valid.
|
||
|
*/
|
||
|
|
||
|
/* switch on Local Stun for testing */
|
||
|
/*
|
||
|
* #define STUN_ALLOW_LOCAL_NET 1
|
||
|
*/
|
||
|
|
||
|
|
||
|
#ifdef STUN_ALLOW_LOCAL_NET
|
||
|
bool isExtern = true;
|
||
|
#else
|
||
|
bool isExtern = (!c->Firewalled()) ||
|
||
|
(c->Firewalled() && c->Forwarded());
|
||
|
#endif
|
||
|
|
||
|
if (isExtern)
|
||
|
{
|
||
|
// second level of checks.
|
||
|
// if we will connect, and haven't -> they are probably
|
||
|
// offline.
|
||
|
if (c->Accepted() && (!c->Connected()))
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "Offline Friend: ";
|
||
|
out << c -> Name();
|
||
|
out << " not available for Stun";
|
||
|
pqioutput(PQL_DEBUG_ALERT, pqidisczone, out.str());
|
||
|
isExtern = false;
|
||
|
}
|
||
|
|
||
|
// and address looks good.
|
||
|
//
|
||
|
// and not in our subnet (external to us)
|
||
|
}
|
||
|
|
||
|
|
||
|
if (isExtern)
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "Potential Stun Server: ";
|
||
|
out << c -> Name();
|
||
|
out << std::endl;
|
||
|
out << " ServerAddr: " << inet_ntoa(c->serveraddr.sin_addr);
|
||
|
out << " : " << ntohs(c->serveraddr.sin_port);
|
||
|
out << std::endl;
|
||
|
out << " LocalAddr: " << inet_ntoa(c->localaddr.sin_addr);
|
||
|
out << " : " << ntohs(c->localaddr.sin_port);
|
||
|
out << std::endl;
|
||
|
|
||
|
#ifdef STUN_ALLOW_LOCAL_NET
|
||
|
if (isValidNet(&(c->serveraddr.sin_addr)) &&
|
||
|
(!sameNet(&(own->serveraddr.sin_addr), &(c->serveraddr.sin_addr))))
|
||
|
#else
|
||
|
if ((isValidNet(&(c->serveraddr.sin_addr))) &&
|
||
|
(!isPrivateNet(&(c->serveraddr.sin_addr))) &&
|
||
|
(!sameNet(&(own->localaddr.sin_addr), &(c->serveraddr.sin_addr))) &&
|
||
|
(!sameNet(&(own->serveraddr.sin_addr), &(c->serveraddr.sin_addr))))
|
||
|
#endif
|
||
|
{
|
||
|
out << " -- Chose Server Address";
|
||
|
out << std::endl;
|
||
|
stunList.push_back(c->serveraddr);
|
||
|
}
|
||
|
#ifdef STUN_ALLOW_LOCAL_NET
|
||
|
else if (isValidNet(&(c->localaddr.sin_addr)))
|
||
|
#else
|
||
|
else if ((!c->Firewalled()) &&
|
||
|
(isValidNet(&(c->localaddr.sin_addr))) &&
|
||
|
(!isPrivateNet(&(c->localaddr.sin_addr))) &&
|
||
|
(!sameNet(&(own->localaddr.sin_addr), &(c->localaddr.sin_addr))))
|
||
|
#endif
|
||
|
{
|
||
|
out << " -- Chose Local Address";
|
||
|
out << std::endl;
|
||
|
stunList.push_back(c->localaddr);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
out << "<=> Invalid / Private Addresses";
|
||
|
out << std::endl;
|
||
|
}
|
||
|
pqioutput(PQL_DEBUG_ALERT, pqidisczone, out.str());
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
std::ostringstream out;
|
||
|
out << "Non-Stun Neighbour: ";
|
||
|
out << c -> Name();
|
||
|
pqioutput(PQL_DEBUG_ALERT, pqidisczone, out.str());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return stunList;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// tdelta -> trange.
|
||
|
// -inf...<0 0 (invalid)
|
||
|
// 0.. <9 1
|
||
|
// 9...<99 2
|
||
|
// 99...<999 3
|
||
|
// 999...<9999 4
|
||
|
// etc...
|
||
|
|
||
|
int convertTDeltaToTRange(double tdelta)
|
||
|
{
|
||
|
if (tdelta < 0)
|
||
|
return 0;
|
||
|
int trange = 1 + (int) log10(tdelta + 1.0);
|
||
|
return trange;
|
||
|
|
||
|
}
|
||
|
|
||
|
// trange -> tdelta
|
||
|
// -inf...0 -1 (invalid)
|
||
|
// 1 8
|
||
|
// 2 98
|
||
|
// 3 998
|
||
|
// 4 9998
|
||
|
// etc...
|
||
|
|
||
|
int convertTRangeToTDelta(int trange)
|
||
|
{
|
||
|
if (trange <= 0)
|
||
|
return -1;
|
||
|
|
||
|
return (int) (pow(10.0, trange) - 1.5); // (int) xxx98.5 -> xxx98
|
||
|
}
|
||
|
|
||
|
// fn which updates: connect, c_ts,
|
||
|
// listen, l_ts,
|
||
|
// local_addr, server_addr,
|
||
|
// and discFlags.
|
||
|
int updateAutoServer(autoserver *as, RsDiscItem *di)
|
||
|
{
|
||
|
int cts = time(NULL);
|
||
|
|
||
|
|
||
|
as->listen = (di->receive_tr != 0);
|
||
|
as->connect= (di->connect_tr != 0);
|
||
|
|
||
|
/* convert [r|c]_tf to timestamps....
|
||
|
*
|
||
|
* Conversion to a _tf....
|
||
|
*
|
||
|
*
|
||
|
* */
|
||
|
if (as->listen)
|
||
|
{
|
||
|
as->l_ts = cts - convertTRangeToTDelta(di->receive_tr);
|
||
|
}
|
||
|
|
||
|
if (as->connect)
|
||
|
{
|
||
|
as->c_ts = cts - convertTRangeToTDelta(di->connect_tr);
|
||
|
|
||
|
}
|
||
|
as->local_addr = di->laddr;
|
||
|
as->server_addr = di->saddr;
|
||
|
as->discFlags = di->discFlags;
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
static const int PQI_DISC_FLAGS_FIREWALLED = 0x0001;
|
||
|
static const int PQI_DISC_FLAGS_FORWARDED = 0x0002;
|
||
|
static const int PQI_DISC_FLAGS_LOCAL = 0x0004;
|
||
|
|
||
|
int updateCertAvailabilityFlags(cert *c, unsigned long discFlags)
|
||
|
{
|
||
|
if (c)
|
||
|
{
|
||
|
c->Firewalled(discFlags & PQI_DISC_FLAGS_FIREWALLED);
|
||
|
c->Forwarded(discFlags & PQI_DISC_FLAGS_FORWARDED);
|
||
|
|
||
|
if (discFlags & PQI_DISC_FLAGS_FIREWALLED)
|
||
|
{
|
||
|
pqioutput(PQL_WARNING, pqidisczone,
|
||
|
"updateCertAvailabilityFlags() Setting Firewalled Flag = true");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pqioutput(PQL_WARNING, pqidisczone,
|
||
|
"updateCertAvailabilityFlags() Setting Firewalled Flag = false");
|
||
|
}
|
||
|
|
||
|
if (discFlags & PQI_DISC_FLAGS_FORWARDED)
|
||
|
{
|
||
|
pqioutput(PQL_WARNING, pqidisczone,
|
||
|
"updateCertAvailabilityFlags() Setting Forwarded Flag = true");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pqioutput(PQL_WARNING, pqidisczone,
|
||
|
"updateCertAvailabilityFlags() Setting Forwarded Flag = false");
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
unsigned long determineCertAvailabilityFlags(cert *c)
|
||
|
{
|
||
|
unsigned long flags = 0;
|
||
|
if (c->Firewalled())
|
||
|
{
|
||
|
flags |= PQI_DISC_FLAGS_FIREWALLED;
|
||
|
}
|
||
|
|
||
|
if (c->Forwarded())
|
||
|
{
|
||
|
flags |= PQI_DISC_FLAGS_FORWARDED;
|
||
|
}
|
||
|
|
||
|
if (c->Local())
|
||
|
{
|
||
|
flags |= PQI_DISC_FLAGS_LOCAL;
|
||
|
}
|
||
|
|
||
|
return flags;
|
||
|
}
|
||
|
|