Fixed upnp issues

* Removed periodic Check and thread.
 * Added Shutdown.
 * switched to terminating background thread.
 * removed temporary lease.
 * A bit of a HACK - this class could be cleaned up significantly.

Adding the start of forums/channels.
 * Dummy Interface and Forum data (so GUI work can start)
 * rough p3distrib - needs a lot of work.

Added shutdown function to p3connmgr, to shutdown Upnp.



git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@493 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
drbob 2008-04-09 12:54:15 +00:00
parent 20c9e7d224
commit 94371600be
16 changed files with 2007 additions and 233 deletions

View file

@ -9,7 +9,10 @@ include $(RS_TOP_DIR)/scripts/config.mk
RSOBJ = p3service.o p3chatservice.o p3msgservice.o \
p3gamelauncher.o p3ranking.o p3disc.o \
p3photoservice.o
p3photoservice.o \
p3forums.o
# p3distrib.o
#TESTOBJ =

View file

@ -0,0 +1,976 @@
/*
* libretroshare/src/services: p3distrib.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".
*
*/
#include "services/p3distrib.h"
#include "pqi/pqibin.h"
//#include "pqi/pqiservice.h"
//#include "util/rsthreads.h"
/*
* Group Messages....
*
* Forums / Channels / Blogs...
*
*
* Plan.
*
* (1) First create basic structures .... algorithms.
*
* (2) integrate with Cache Source/Store for data transmission.
* (3) integrate with Serialiser for messages
* (4) bring over the final key parts from existing p3channel.
*
*****************************************************************
*
* Group Description:
*
* Master Public/Private Key: (Admin Key) used to control
* Group Name/Description/Icon.
* Filter Lists.
* Publish Keys.
*
* Publish Keys. (multiple possible)
* Filters: blacklist or whitelist.
* TimeStore Length ??? (could make it a minimum of this and system one)
*
* Everyone gets:
* Master Public Key.
* Publish Public Keys.
* blacklist, or whitelist filter. (Only useful for Non-Anonymous groups)
* Name, Desc,
* etc.
*
* Admins get Master Private Key.
* Publishers get Publish Private Key.
* - Channels only some get publish key.
* - Forums everyone gets publish private key.
*
* Create a Signing structure for Messages in general.
*
*/
p3GroupDistrib::p3GroupDistrib(uint16_t subtype,
CacheStrapper *cs, CacheTransfer *cft,
std::string sourcedir, std::string storedir,
uint32_t configId,
uint32_t storePeriod, uint32_t pubPeriod)
:CacheSource(subtype, true, cs, sourcedir),
CacheStore(subtype, true, cs, cft, storedir),
p3Config(configId),
mStorePeriod(storePeriod),
mPubPeriod(pubPeriod)
{
/* not much yet */
time_t now = time(NULL);
/* set this a little in the future -> so we can
* adjust the publish point if needed
*/
mNextPublishTime = now + mPubPeriod / 4;
return;
}
void p3GroupDistrib::tick()
{
time_t now = time(NULL);
bool toPublish;
{
RsStackMutex stack(distribMtx); /**** STACK LOCKED MUTEX ****/
toPublish = (now > mNextPublishTime);
}
if (toPublish)
{
publishPendingMsgs();
RsStackMutex stack(distribMtx); /**** STACK LOCKED MUTEX ****/
mNextPublishTime = now + mPubPeriod;
}
}
/***************************************************************************************/
/***************************************************************************************/
/********************** overloaded functions from Cache Store ******************/
/***************************************************************************************/
/***************************************************************************************/
int p3GroupDistrib::loadAnyCache(const CacheData &data, bool local)
{
/* if subtype = 0 -> FileGroup, else -> FileMsgs */
std::string file = data.path;
file += "/";
file += data.name;
if (data.cid.subid == 0)
{
loadFileGroups(file, data.pid, local);
}
else
{
loadFileMsgs(file, data.cid.subid, data.pid, local);
}
return true;
}
int p3GroupDistrib::loadCache(const CacheData &data)
{
return loadAnyCache(data, false);
}
bool p3GroupDistrib::loadLocalCache(const CacheData &data)
{
return loadAnyCache(data, true);
}
/***************************************************************************************/
/***************************************************************************************/
/********************** load Cache Files ***************************************/
/***************************************************************************************/
/***************************************************************************************/
/* No need for special treatment for 'own' groups.
* configuration should be loaded before cache files.
*/
void p3GroupDistrib::loadFileGroups(std::string filename, std::string src, bool local)
{
/* create the serialiser to load info */
BinInterface *bio = new BinFileInterface(filename.c_str(), BIN_FLAGS_READABLE);
pqistreamer *streamer = createStreamer(bio, src, 0);
RsItem *item;
RsDistribGrp *newGrp;
while(NULL != (item = streamer->GetItem()))
{
if (NULL == (newGrp = dynamic_cast<RsDistribGrp *>(item)))
{
/* wrong message type */
delete item;
continue;
}
loadGroup(newGrp);
}
delete streamer;
return;
}
void p3GroupDistrib::loadFileMsgs(std::string filename, uint16_t cacheSubId, std::string src, bool local)
{
time_t now = time(NULL);
time_t start = now;
time_t end = 0;
/* create the serialiser to load msgs */
BinInterface *bio = new BinFileInterface(filename.c_str(), BIN_FLAGS_READABLE);
pqistreamer *streamer = createStreamer(bio, src, 0);
RsItem *item;
RsDistribMsg *newMsg;
while(NULL != (item = streamer->GetItem()))
{
if (NULL == (newMsg = dynamic_cast<RsDistribMsg *>(item)))
{
/* wrong message type */
delete item;
continue;
}
if (local)
{
/* calc the range */
if (newMsg->timestamp < start)
start = newMsg->timestamp;
if (newMsg->timestamp > end)
end = newMsg->timestamp;
}
loadMsg(newMsg, src, local);
}
/* Check the Hash? */
delete streamer;
if (local)
{
GroupCache newCache;
newCache.filename = filename;
newCache.cacheSubId = cacheSubId;
newCache.start = start;
newCache.end = end;
distribMtx.lock(); /******************** LOCKED MUTEX ************/
mLocalCaches.push_back(newCache);
/******************** This probably ain't necessary *******************/
#if 0
/* adjust next Publish Time if needed */
if ((end < now) && (end + mPubPeriod > mNextPublishTime))
{
mNextPublishTime = end + mPubPeriod;
}
#endif
/******************** This probably ain't necessary *******************/
distribMtx.unlock(); /******************** UNLOCKED MUTEX ************/
}
return;
}
/*******************************
********************************
********************************
***** COMPLETED TO HERE ******
********************************
********************************
********************************/
/***************************************************************************************/
/***************************************************************************************/
/********************** load Cache Msgs ***************************************/
/***************************************************************************************/
/***************************************************************************************/
void p3GroupDistrib::loadGroup(RsDistribGrp *newGrp)
{
/* load groupInfo */
/* look for duplicate */
/* check signature */
/* add in */
/* */
}
void p3GroupDistrib::loadMsg(RsDistribMsg *msg, std::string src, bool local)
{
/****************** check the msg ******************/
/* Do the most likely checks to fail first....
*
* timestamp (too old)
* group (non existant)
* msg (already have it)
*
* -> then do the expensive Hash / signature checks.
*/
distribMtx.lock(); /******************** LOCKED MUTEX ************/
/* check timestamp */
time_t now = time(NULL);
time_t min = now - mStorePeriod;
time_t minPub = now - mStorePeriod / 2.0;
time_t max = now + GROUP_MAX_FWD_OFFSET;
distribMtx.unlock(); /******************** UNLOCKED MUTEX ************/
if ((msg->timestamp < min) || (msg->timestamp > max))
{
/* if outside range -> remove */
delete msg;
return;
}
distribMtx.lock(); /******************** LOCKED MUTEX ************/
/* find group */
std::map<std::string, GroupInfo>::iterator git;
if (mGroups.end() == (git = mGroups.find(msg->grpId)))
{
/* if not there -> remove */
distribMtx.unlock(); /******************** UNLOCKED MUTEX ************/
delete msg;
return;
}
/* check for duplicate message */
std::map<std::string, RsDistribMsg *>::iterator mit;
if ((git->second).msgs.end() != (git->second).msgs.find(msg->msgId))
{
distribMtx.unlock(); /******************** UNLOCKED MUTEX ************/
/* if already there -> remove */
delete msg;
return;
}
distribMtx.unlock(); /******************** UNLOCKED MUTEX ************/
/* save and reset hash/signatures */
std::string hash = msg->msgId;
std::string grpSign = msg->grpSignature;
std::string srcSign = msg->sourceSignature;
msg->msgId = "";
msg->grpSignature = "";
msg->sourceSignature = "";
std::string computedHash = HashRsItem(msg);
/* restore data */
msg->msgId = hash;
msg->grpSignature = grpSign;
msg->sourceSignature = srcSign;
if (computedHash != hash)
{
/* hash is wrong */
delete msg;
return;
}
/* calc group signature */
/* if fails -> remove */
/* check peer signature */
/* if !allowedAnon & anon -> remove */
/* if !allowedUnknown & unknown -> remove */
/****************** check the msg ******************/
/* accept message */
(git->second).msgs[msg->msgId] = msg;
if (local)
{
/* if from local -> already published */
/* All local loads - will also come in as Remote loads.
* but should be discarded because of duplicates
* (Local load must happen first!)
*/
//delete msg;
return;
}
if (msg->timestamp < minPub)
{
/* outside publishing range */
//delete msg;
return;
}
/* else if group = subscribed | listener -> publish */
toPublishMsg(msg);
}
/***************************************************************************************/
/***************************************************************************************/
/****************** create/mod Cache Content **********************************/
/***************************************************************************************/
/***************************************************************************************/
void p3GroupDistrib::toPublishMsg(RsDistribMsg *msg)
{
RsStackMutex stack(distribMtx); /****** STACK MUTEX LOCKED *******/
mPendingPublish.push_back(msg);
}
void p3GroupDistrib::locked_publishPendingMsgs()
{
/* get the next message id */
CacheData newCache;
newCache.pid = mOwnId;
newCache.cid.type = CacheSource::getCacheType();
newCache.cid.subid = determineCacheSubId(); // NOT fixed - should rotate.
/* create filename */
std::string path = CacheSource::getCacheDir();
std::ostringstream out;
out << "grpdist-t" << CacheSource::getCacheType() << "-msgs-" << time(NULL) << ".dist";
std::string tmpname = out.str();
std::string filename = path + "/" + tmpname;
BinInterface *bio = new BinFileInterface(filename.c_str(),
BIN_FLAGS_WRITEABLE | BIN_FLAGS_HASH_DATA);
pqistreamer *streamer = createStreamer(bio, mOwnId,
BIN_FLAGS_NO_DELETE);
RsStackMutex stack(distribMtx); /****** STACK MUTEX LOCKED *******/
std::list<RsDistribMsg *>::iterator it;
for(it = mPendingPublish.begin(); it != mPendingPublish.end(); it++)
{
streamer->SendItem(*it); /* doesnt delete it */
}
/* cleanup */
mPendingPublish.clear();
delete streamer;
/* Extract File Information from pqistreamer */
newCache.path = path;
newCache.name = tmpname;
newCache.hash = bio->gethash();
newCache.size = bio->bytecount();
newCache.recvd = time(NULL);
/* push file to CacheSource */
refreshCache(newCache);
/* flag to store config (saying we've published messages) */
IndicateConfigChanged(); /**** INDICATE CONFIG CHANGED! *****/
}
void p3GroupDistrib::publishDistribGroups()
{
/* set subid = 0 */
CacheData newCache;
newCache.pid = mOwnId;
newCache.cid.type = CacheSource::getCacheType();
newCache.cid.subid = 0;
/* create filename */
std::string path = CacheSource::getCacheDir();
std::ostringstream out;
out << "grpdist-t" << CacheSource::getCacheType() << "-grps-" << time(NULL) << ".dist";
std::string tmpname = out.str();
std::string filename = path + "/" + tmpname;
BinInterface *bio = new BinFileInterface(filename.c_str(),
BIN_FLAGS_WRITEABLE | BIN_FLAGS_HASH_DATA);
pqistreamer *streamer = createStreamer(bio, mOwnId, 0);
RsStackMutex stack(distribMtx); /****** STACK MUTEX LOCKED *******/
/* Iterate through all the Groups */
std::map<std::string, GroupInfo>::iterator it;
for(it = mGroups.begin(); it != mGroups.end(); it++)
{
/* if subscribed or listener -> do stuff */
/* extract public info to RsDistribGrp */
RsDistribGrp *grp = new RsDistribGrp();
/* store in Cache File */
streamer->SendItem(grp); /* deletes it */
}
/* Extract File Information from pqistreamer */
newCache.path = path;
newCache.name = tmpname;
newCache.hash = bio->gethash();
newCache.size = bio->bytecount();
newCache.recvd = time(NULL);
/* cleanup */
delete streamer;
/* push file to CacheSource */
refreshCache(newCache);
}
/* clearing old data */
void p3GroupDistrib::clear_local_caches(time_t now)
{
RsStackMutex stack(distribMtx); /****** STACK MUTEX LOCKED *******/
time_t cutoff = now - mStorePeriod;
std::list<GroupCache>::iterator it;
for(it = mLocalCaches.begin(); it != mLocalCaches.end();)
{
if (it->end < cutoff)
{
/* Call to CacheSource Function */
CacheId cid(CacheSource::getCacheType(), it->cacheSubId);
clearCache(cid);
it = mLocalCaches.erase(it);
}
else
{
it++;
}
}
}
/***************************************************************************************/
/***************************************************************************************/
/********************** Access Content ***************************************/
/***************************************************************************************/
/***************************************************************************************/
/* get Group Lists */
bool p3GroupDistrib::getAllGroupList(std::list<std::string> &grpids)
{
RsStackMutex stack(distribMtx); /************* STACK MUTEX ************/
std::map<std::string, GroupInfo>::iterator git;
for(git = mGroups.begin(); git != mGroups.end(); git++)
{
grpids.push_back(git->first);
}
return true;
}
bool p3GroupDistrib::getSubscribedGroupList(std::list<std::string> &grpids)
{
RsStackMutex stack(distribMtx); /************* STACK MUTEX ************/
std::map<std::string, GroupInfo>::iterator git;
for(git = mGroups.begin(); git != mGroups.end(); git++)
{
if (git->second.flags & RS_GRPDISTRIB_SUBSCRIBED)
{
grpids.push_back(git->first);
}
}
return true;
}
bool p3GroupDistrib::getPublishGroupList(std::list<std::string> &grpids)
{
RsStackMutex stack(distribMtx); /************* STACK MUTEX ************/
std::map<std::string, GroupInfo>::iterator git;
for(git = mGroups.begin(); git != mGroups.end(); git++)
{
if (git->second.flags & RS_GRPDISTRIB_PUBLISH)
{
grpids.push_back(git->first);
}
}
return true;
}
bool p3GroupDistrib::getPopularGroupList(uint32_t popMin, uint32_t popMax, std::list<std::string> &grpids)
{
RsStackMutex stack(distribMtx); /************* STACK MUTEX ************/
std::map<std::string, GroupInfo>::iterator git;
for(git = mGroups.begin(); git != mGroups.end(); git++)
{
if ((git->second.pop >= popMin) &&
(git->second.pop <= popMax))
{
grpids.push_back(git->first);
}
}
return true;
}
/* get Msg Lists */
bool p3GroupDistrib::getAllMsgList(std::string grpId, std::list<std::string> &msgIds)
{
RsStackMutex stack(distribMtx); /************* STACK MUTEX ************/
std::map<std::string, GroupInfo>::iterator git;
if (mGroups.end() == (git = mGroups.find(grpId)))
{
return false;
}
std::map<std::string, RsDistribMsg *>::iterator mit;
std::map<std::string, RsDistribMsg *> msgs;
for(mit = git->second.msgs.begin(); mit != git->second.msgs.end(); mit++)
{
msgIds.push_back(mit->first);
}
return true;
}
bool p3GroupDistrib::getTimePeriodMsgList(std::string grpId, uint32_t timeMin,
uint32_t timeMax, std::list<std::string> &msgIds)
{
RsStackMutex stack(distribMtx); /************* STACK MUTEX ************/
std::map<std::string, GroupInfo>::iterator git;
if (mGroups.end() == (git = mGroups.find(grpId)))
{
return false;
}
std::map<std::string, RsDistribMsg *>::iterator mit;
for(mit = git->second.msgs.begin(); mit != git->second.msgs.end(); mit++)
{
if ((mit->second->timestamp >= timeMin) &&
(mit->second->timestamp <= timeMax))
{
msgIds.push_back(mit->first);
}
}
return true;
}
GroupInfo *p3GroupDistrib::locked_getGroupInfo(std::string grpId)
{
/************* ALREADY LOCKED ************/
std::map<std::string, GroupInfo>::iterator git;
if (mGroups.end() == (git = mGroups.find(grpId)))
{
return NULL;
}
return &(git->second);
}
RsDistribMsg *p3GroupDistrib::locked_getGroupMsg(std::string grpId, std::string msgId)
{
/************* ALREADY LOCKED ************/
std::map<std::string, GroupInfo>::iterator git;
if (mGroups.end() == (git = mGroups.find(grpId)))
{
return NULL;
}
std::map<std::string, RsDistribMsg *>::iterator mit;
if (git->second.msgs.end() == (mit = git->second.msgs.find(msgId)))
{
return NULL;
}
return mit->second;
}
/**** These must be created in derived classes ****/
#if 0
/* get Group Details */
bool p3GroupDistrib::getGroupDetails(std::string grpId, RsExternalDistribGroup &grp)
{
RsStackMutex stack(distribMtx); /************* STACK MUTEX ************/
std::map<std::string, GroupInfo>::iterator git;
if (mGroups.end() == (git = mGroups.find(grpId)))
{
return false;
}
/* Fill in details */
return true;
}
/* get Msg */
bool p3GroupDistrib::getGroupMsgDetails(std::string grpId, std::string msgId, RsExternalDistribMsg &msg)
{
RsStackMutex stack(distribMtx); /************* STACK MUTEX ************/
std::map<std::string, GroupInfo>::iterator git;
if (mGroups.end() == (git = mGroups.find(grpId)))
{
return false;
}
std::map<std::string, RsDistribMsg *>::iterator mit;
if (git->second.msgs.end() == (mit = git->second.msgs.find(msgId)))
{
return false;
}
/* Fill in the message details */
return true;
}
#endif
/************************************* p3Config *************************************/
RsSerialiser *p3GroupDistrib::setupSerialiser()
{
RsSerialiser *rss = new RsSerialiser();
rss->addSerialType(new RsSerialDistrib());
rss->addSerialType(new RsConfigDistrib());
return rss;
}
std::list<RsItem *> p3GroupDistrib::saveList(bool &cleanup)
{
std::list<RsItem *> saveData;
/* store private information for OUR lists */
/* store information on subscribed lists */
/* store messages for pending Publication */
return saveData;
}
bool p3GroupDistrib::loadList(std::list<RsItem *> load)
{
std::list<RsItem *>::iterator lit;
for(lit = load.begin(); lit != load.end(); lit++)
{
/* decide what type it is */
}
return true;
}
/************************************* p3Config *************************************/
pqistreamer *p3GroupDistrib::createStreamer(BinInterface *bio, std::string src, uint32_t bioflags)
{
RsSerialiser *rsSerialiser = new RsSerialiser();
RsSerialType *serialType = new RsSerialDistrib(); /* TODO */
rsSerialiser->addSerialType(serialType);
pqistreamer *streamer = new pqistreamer(rsSerialiser, src, bio, bioflags);
return streamer;
}
std::string HashRsItem(RsItem *item)
{
/* calc/check hash (of serialised data) */
RsSerialType *serial = new RsSerialDistrib();
uint32_t size = serial->size(item);
RsRawItem *ri = new RsRawItem(0, size);
serial->serialise(item, ri->getRawData(), &size);
pqihash hash;
std::string computedHash;
hash.addData(ri->getRawData(), size);
hash.Complete(computedHash);
delete ri;
delete serial;
return computedHash;
}
/***************************************************************************************/
/***************************************************************************************/
/********************** Create Content ***************************************/
/***************************************************************************************/
/***************************************************************************************/
std::string p3GroupDistrib::createGroup(std::string name, uint32_t flags)
{
/* Create a Group */
GroupInfo grpInfo;
std::string grpId;
#ifdef GROUP_SIGNATURES
/* Create Key Set (Admin) */
EVP_PKEY *key_admin = EVP_PKEY_new();
mAuthMgr->generateKeyPair(key_admin, 0);
/* extract AdminKey Id -> groupId */
grpId = mAuthMgr->getKeyId(key_admin);
/* setup GroupInfo */
grpInfo.adminKey = key_admin;
#else
grpInfo.id = generateRandomId();
#endif
grpInfo.id = grpId;
grpInfo.flags = flags;
grpInfo.name = name;
/* generate a set of keys */
/* generate RsDistribGrp */
/* sign Grp (with date) */
/* store new GroupInfo */
return grpId;
}
std::string p3GroupDistrib::addPublishKey(std::string grpId, uint32_t keyflags, time_t startDate, time_t endDate)
{
/* Find the Group */
GroupInfo *grpInfo = locked_getGroupInfo(grpId);
std::string keyId;
if (!grpInfo)
{
return keyId;
}
/* if we don't have the admin key -> then we cannot add a key */
if (!(grpInfo->grpFlags & RS_GRPDISTRIB_ADMIN_KEY))
{
return keyId;
}
/* Create Key Set (Publish) */
EVP_PKEY *key_publish = EVP_PKEY_new();
mAuthMgr->generateKeyPair(key_publish, 0);
/* extract Key Id -> keyId */
keyId = mAuthMgr->getKeyId(key_publish);
/* setup RsKey */
RsKey *publishKey = new RsKey();
publishKey -> key = key_publish;
publishKey -> keyId = keyId;
publishKey -> startDate = startDate;
publishKey -> endDate = endDate;
/* setup data packet for signing */
/* sign key with Admin Key */
publishKey -> adminSignature = ...;
grpInfo.publishKeys.push_back(publishKey);
return keyId;
}
int p3channel::signRsKey(RsKey *pubkey, EVP_PKEY *signKey, std::string &signature)
{
/*
// 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();
mAuthMgr->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;
}
void p3GroupDistrib::publishMsg(RsDistribMsg *msg, bool personalSign)
{
/* extract grpId */
std::string grpId = msg->grpId;
/* ensure Group exists */
/* hash message */
/* sign message */
/* personal signature? */
/* Message now Complete */
/* Insert in Group */
/* add to PublishPending */
/* done */
return;
}
#if 0
/* Modify Group */
std::string p3GroupDistrib::modGroupDescription(std::string grpId, std::string description)
{
return;
}
std::string p3GroupDistrib::modGroupIcon(std::string grpId, PIXMAP icon)
{
return;
}
#endif

View file

@ -0,0 +1,375 @@
/*
* libretroshare/src/services: p3distrib.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 P3_GENERIC_DISTRIB_HEADER
#define P3_GENERIC_DISTRIB_HEADER
#include "pqi/pqi.h"
#include "pqi/pqistreamer.h"
#include "pqi/p3cfgmgr.h"
#include "services/p3service.h"
#include "dbase/cachestrapper.h"
//#include "util/rsthreads.h"
/*
* Group Messages....
*
* Forums / Channels / Blogs...
*
*
* Plan.
*
* (1) First create basic structures .... algorithms.
*
* (2) integrate with Cache Source/Store for data transmission.
* (3) integrate with Serialiser for messages
* (4) bring over the final key parts from existing p3channel.
*
*****************************************************************
*
* Group Description:
*
* Master Public/Private Key: (Admin Key) used to control
* Group Name/Description/Icon.
* Filter Lists.
* Publish Keys.
*
* Publish Keys. (multiple possible)
* Filters: blacklist or whitelist.
* TimeStore Length ??? (could make it a minimum of this and system one)
*
* Everyone gets:
* Master Public Key.
* Publish Public Keys.
* blacklist, or whitelist filter. (Only useful for Non-Anonymous groups)
* Name, Desc,
* etc.
*
* Admins get Master Private Key.
* Publishers get Publish Private Key.
* - Channels only some get publish key.
* - Forums everyone gets publish private key.
*
* Create a Signing structure for Messages in general.
*
*/
/* Our Mode for the Group */
const uint32_t RS_GRPDISTRIB_SUBSCRIBED = 0x0001;
const uint32_t RS_GRPDISTRIB_PUBLISH = 0x0002;
/* Group Type */
const uint32_t RS_DISTRIB_PRIVATE = 0x0001; /* retain Private Key ( Default ) */
const uint32_t RS_DISTRIB_PUBLIC = 0x0002; /* share All Keys */
const uint32_t RS_DISTRIB_ENCRYPTED = 0x0004; /* encrypt Msgs */
class RsSignature
{
public:
uint32_t type; /* MASTER, PUBLISH, PERSONAL */
std::string signerId;
std::string signature;
};
class RsAuthMsg
{
public:
RsItem *msg;
std::string hash;
std::map<std::string, RsSignature> signs;
};
class RsKey
{
public:
uint32_t type; /* PUBLIC, PRIVATE */
uint32_t type2; /* MASTER, PUBLISH, PERSONAL (not sent) */
EVP_PKEY *key;
};
const uint32_t GROUP_MAX_FWD_OFFSET = (60 * 60 * 24 * 2); /* 2 Days */
/************* The Messages that are serialised ****************/
class RsDistribMsg: public RsItem
{
public:
RsDistribMsg(); //uint16_t type);
virtual void clear();
virtual std::ostream& print(std::ostream&, uint16_t);
std::string grpId;
std::string headId; /* head of the thread */
std::string parentId; /* parent id */
time_t timestamp;
/* This data is not Hashed (set to zero - before hash calced) */
std::string msgId; /* SHA1 Hash */
std::string grpSignature; /* sign of msgId */
std::string sourceSignature; /* sign of msgId */
};
class RsDistribGrp: public RsItem
{
public:
RsDistribGrp(); //uint16_t type);
virtual void clear();
virtual std::ostream& print(std::ostream&, uint16_t);
RsKey rsKey;
};
class RsConfigDistrib: public RsSerialType
{
public:
RsConfigDistrib();
};
class RsSerialDistrib: public RsSerialType
{
public:
RsSerialDistrib();
};
/************* The Messages that are serialised ****************/
//class PIXMAP;
class GroupInfo
{
public:
std::string grpId;
std::string grpName;
std::string grpDesc;
std::string category;
//PIXMAP *GroupIcon;
//RSA_KEY privateKey;
//RSA_KEY publicKey;
bool publisher, allowAnon, allowUnknown;
bool subscribed, listener;
uint32_t type;
uint32_t pop;
uint32_t flags;
std::list<std::string> sources;
std::map<std::string, RsDistribMsg *> msgs;
};
class GroupCache
{
public:
std::string filename;
time_t start, end;
uint16_t cacheSubId;
};
class p3GroupDistrib: public CacheSource, public CacheStore, public p3Config
{
public:
p3GroupDistrib(uint16_t subtype,
CacheStrapper *cs, CacheTransfer *cft,
std::string sourcedir, std::string storedir,
uint32_t configId,
uint32_t storePeriod, uint32_t pubPeriod);
/***************************************************************************************/
/******************************* CACHE SOURCE / STORE Interface ************************/
/***************************************************************************************/
/* TO FINISH */
public:
virtual bool loadLocalCache(const CacheData &data); /* overloaded from Cache Source */
virtual int loadCache(const CacheData &data); /* overloaded from Cache Store */
private:
/* top level load */
int loadAnyCache(const CacheData &data, bool local);
/* load cache files */
void loadFileGroups(std::string filename, std::string src, bool local);
void loadFileMsgs(std::string filename, uint16_t cacheSubId, std::string src, bool local);
/* load cache msgs */
void loadMsg(RsDistribMsg *msg, std::string src, bool local);
void loadGroup(RsDistribGrp *newGrp);
/***************************************************************************************/
/***************************************************************************************/
/***************************************************************************************/
/**************************** Create Content *******************************************/
/***************************************************************************************/
/* TO FINISH */
public:
std::string createGroup(std::string name, uint32_t flags);
//std::string modGroupDescription(std::string grpId, std::string discription);
//std::string modGroupIcon(std::string grpId, PIXMAP *icon);
void publishMsg(RsDistribMsg *msg, bool personalSign);
/***************************************************************************************/
/***************************************************************************************/
/***************************************************************************************/
/****************************** Access Content ***************************************/
/***************************************************************************************/
public:
/* get Group Lists */
bool getAllGroupList(std::list<std::string> &grpids);
bool getSubscribedGroupList(std::list<std::string> &grpids);
bool getPublishGroupList(std::list<std::string> &grpids);
bool getPopularGroupList(uint32_t popMin, uint32_t popMax, std::list<std::string> &grpids);
/* get Msg Lists */
bool getAllMsgList(std::string grpId, std::list<std::string> &msgIds);
bool getTimePeriodMsgList(std::string grpId, uint32_t timeMin,
uint32_t timeMax, std::list<std::string> &msgIds);
RsDistribMsg *locked_getGroupMsg(std::string grpId, std::string msgId);
/* TO FINISH DEFINITIONS */
/* get Details */
//bool getGroupDetails(std::string grpId, RsExternalDistribGroup &grp);
//bool getGroupMsgDetails(std::string grpId, std::string msgId, RsExternalDistribMsg &msg);
/* Filter Messages */
/***************************************************************************************/
/***************************************************************************************/
/***************************************************************************************/
/********************************* p3Config ********************************************/
/***************************************************************************************/
/* TO FINISH */
protected:
virtual RsSerialiser *setupSerialiser();
virtual std::list<RsItem *> saveList(bool &cleanup);
virtual bool loadList(std::list<RsItem *> load);
/***************************************************************************************/
/***************************************************************************************/
/* TO FINISH */
public:
void tick();
/***************************************************************************************/
/**************************** Publish Content ******************************************/
/***************************************************************************************/
/* TO FINISH */
protected:
/* create/mod cache content */
void toPublishMsg(RsDistribMsg *msg);
void publishPendingMsgs();
void publishDistribGroups();
void clear_local_caches(time_t now);
void locked_publishPendingMsgs();
uint16_t determineCacheSubId();
/***************************************************************************************/
/***************************************************************************************/
/***************************************************************************************/
/***************************** Utility Functions ***************************************/
/***************************************************************************************/
/* TO FINISH */
/* utilities */
pqistreamer *createStreamer(BinInterface *bio, std::string src, uint32_t bioflags);
std::string HashRsItem(const RsItem *item);
/***************************************************************************************/
/***************************************************************************************/
/* key cache functions - we use .... (not overloaded)
*/
private:
/* storage */
RsMutex distribMtx; /* Protects All Data Below */
std::string mOwnId;
std::list<GroupCache> mLocalCaches;
std::map<std::string, GroupInfo> mGroups;
uint32_t mStorePeriod, mPubPeriod;
time_t mNextPublishTime;
std::list<RsDistribMsg *> mPendingPublish;
};
/***************************************************************************************/
/***************************************************************************************/
/*
* Structure of the Storage:
*
* map<std::string(id) -> GroupInfo>
*
*
*
*
*/
/***************************************************************************************/
/***************************************************************************************/
#endif // P3_GENERIC_DISTRIB_HEADER

View file

@ -0,0 +1,216 @@
/*
* libretroshare/src/services: rsforums.cc
*
* RetroShare C++ Interface.
*
* Copyright 2007-2008 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include "services/p3forums.h"
std::ostream &operator<<(std::ostream &out, const ForumInfo &info)
{
std::string name(info.forumName.begin(), info.forumName.end());
std::string desc(info.forumDesc.begin(), info.forumDesc.end());
out << "ForumInfo:";
out << std::endl;
out << "ForumId: " << info.forumId << std::endl;
out << "ForumName: " << name << std::endl;
out << "ForumDesc: " << desc << std::endl;
out << "ForumFlags: " << info.forumFlags << std::endl;
out << "Pop: " << info.pop << std::endl;
out << "LastPost: " << info.lastPost << std::endl;
return out;
}
std::ostream &operator<<(std::ostream &out, const ThreadInfoSummary &info)
{
out << "ThreadInfoSummary:";
out << std::endl;
//out << "ForumId: " << forumId << std::endl;
//out << "ThreadId: " << threadId << std::endl;
return out;
}
std::ostream &operator<<(std::ostream &out, const ForumMsgInfo &info)
{
out << "ForumMsgInfo:";
out << std::endl;
//out << "ForumId: " << forumId << std::endl;
//out << "ThreadId: " << threadId << std::endl;
return out;
}
RsForums *rsForums = NULL;
p3Forums::p3Forums()
:mForumsChanged(false)
{
loadDummyData();
return;
}
p3Forums::~p3Forums()
{
return;
}
/****************************************/
bool p3Forums::forumsChanged(std::list<std::string> &forumIds)
{
bool changed = mForumsChanged;
mForumsChanged = false;
return changed;
}
bool p3Forums::getForumList(std::list<ForumInfo> &forumList)
{
std::list<ForumInfo>::iterator it;
for(it = mForums.begin(); it != mForums.end(); it++)
{
forumList.push_back(*it);
}
return true;
}
bool p3Forums::getForumThreadList(std::string fId, std::list<ThreadInfoSummary> &msgs)
{
return true;
}
bool p3Forums::getForumThreadMsgList(std::string fId, std::string tId, std::list<ThreadInfoSummary> &msgs)
{
return true;
}
bool p3Forums::getForumMessage(std::string fId, std::string mId, ForumMsgInfo &msg)
{
return true;
}
bool p3Forums::ForumMessageSend(ForumMsgInfo &info)
{
return true;
}
/****************************************/
void p3Forums::loadDummyData()
{
ForumInfo fi;
time_t now = time(NULL);
fi.forumId = "FID1234";
fi.forumName = L"Forum 1";
fi.forumDesc = L"Forum 1";
fi.forumFlags = RS_FORUM_ADMIN;
fi.pop = 2;
fi.lastPost = now - 123;
mForums.push_back(fi);
fi.forumId = "FID2345";
fi.forumName = L"Forum 2";
fi.forumDesc = L"Forum 2";
fi.forumFlags = RS_FORUM_SUBSCRIBED;
fi.pop = 3;
fi.lastPost = now - 1234;
mForums.push_back(fi);
fi.forumId = "FID3456";
fi.forumName = L"Forum 3";
fi.forumDesc = L"Forum 3";
fi.forumFlags = 0;
fi.pop = 3;
fi.lastPost = now - 1234;
mForums.push_back(fi);
fi.forumId = "FID4567";
fi.forumName = L"Forum 4";
fi.forumDesc = L"Forum 4";
fi.forumFlags = 0;
fi.pop = 5;
fi.lastPost = now - 1234;
mForums.push_back(fi);
fi.forumId = "FID5678";
fi.forumName = L"Forum 5";
fi.forumDesc = L"Forum 5";
fi.forumFlags = 0;
fi.pop = 1;
fi.lastPost = now - 1234;
mForums.push_back(fi);
fi.forumId = "FID6789";
fi.forumName = L"Forum 6";
fi.forumDesc = L"Forum 6";
fi.forumFlags = 0;
fi.pop = 2;
fi.lastPost = now - 1234;
mForums.push_back(fi);
fi.forumId = "FID7890";
fi.forumName = L"Forum 7";
fi.forumDesc = L"Forum 7";
fi.forumFlags = 0;
fi.pop = 4;
fi.lastPost = now - 1234;
mForums.push_back(fi);
fi.forumId = "FID8901";
fi.forumName = L"Forum 8";
fi.forumDesc = L"Forum 8";
fi.forumFlags = 0;
fi.pop = 3;
fi.lastPost = now - 1234;
mForums.push_back(fi);
fi.forumId = "FID9012";
fi.forumName = L"Forum 9";
fi.forumDesc = L"Forum 9";
fi.forumFlags = 0;
fi.pop = 2;
fi.lastPost = now - 1234;
mForums.push_back(fi);
fi.forumId = "FID9123";
fi.forumName = L"Forum 10";
fi.forumDesc = L"Forum 10";
fi.forumFlags = 0;
fi.pop = 1;
fi.lastPost = now - 1234;
mForums.push_back(fi);
mForumsChanged = true;
}

View file

@ -0,0 +1,60 @@
#ifndef RS_P3_FORUMS_INTERFACE_H
#define RS_P3_FORUMS_INTERFACE_H
/*
* libretroshare/src/services: p3forums.h
*
* RetroShare C++ Interface.
*
* 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 "rsiface/rsforums.h"
class p3Forums: public RsForums
{
public:
p3Forums();
virtual ~p3Forums();
/****************************************/
/********* rsForums Interface ***********/
virtual bool forumsChanged(std::list<std::string> &forumIds);
virtual bool getForumList(std::list<ForumInfo> &forumList);
virtual bool getForumThreadList(std::string fId, std::list<ThreadInfoSummary> &msgs);
virtual bool getForumThreadMsgList(std::string fId, std::string tId, std::list<ThreadInfoSummary> &msgs);
virtual bool getForumMessage(std::string fId, std::string mId, ForumMsgInfo &msg);
virtual bool ForumMessageSend(ForumMsgInfo &info);
/****************************************/
private:
void loadDummyData();
std::list<ForumInfo> mForums;
bool mForumsChanged;
};
#endif