Merged branch v0.5-GenericTunneling into trunk (Rev. 6284 to 6410).

- adds turtle router as a generic tunneling service
- made ftServer a client of the service. Now turtle file items are handled in ftServer
- added new client: p3MsgService to send/recv pgp-encrypted distant messages
- added new client: p3ChatService to perform private (AES-encrypted) distant chat through tunnels.
- The GUI is disabled for now, since it needs some polishing before being fully usable.



git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@6411 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
csoler 2013-06-06 19:58:30 +00:00
commit dc2521cf71
62 changed files with 5031 additions and 1989 deletions

View File

@ -47,6 +47,7 @@
#include "ft/ftsearch.h"
#include "ft/ftdatamultiplex.h"
#include "ft/ftextralist.h"
#include "ft/ftserver.h"
#include "turtle/p3turtle.h"
@ -102,6 +103,7 @@ ftController::ftController(CacheStrapper *cs, ftDataMultiplex *dm, std::string /
last_clean_time(0),
mDataplex(dm),
mTurtle(NULL),
mFtServer(NULL),
ctrlMutex("ftController"),
doneMutex("ftController"),
mFtActive(false),
@ -112,10 +114,9 @@ ftController::ftController(CacheStrapper *cs, ftDataMultiplex *dm, std::string /
/* TODO */
}
void ftController::setTurtleRouter(p3turtle *pt)
{
mTurtle = pt ;
}
void ftController::setTurtleRouter(p3turtle *pt) { mTurtle = pt ; }
void ftController::setFtServer(ftServer *ft) { mFtServer = ft ; }
void ftController::setFtSearchNExtra(ftSearch *search, ftExtraList *list)
{
mSearch = search;
@ -646,7 +647,7 @@ void ftController::locked_checkQueueElement(uint32_t pos)
_queue[pos]->mState = ftFileControl::DOWNLOADING ;
if(_queue[pos]->mFlags & RS_FILE_REQ_ANONYMOUS_ROUTING)
mTurtle->monitorFileTunnels(_queue[pos]->mName,_queue[pos]->mHash,_queue[pos]->mSize) ;
mTurtle->monitorTunnels(_queue[pos]->mHash,mFtServer) ;
}
if(pos >= _max_active_downloads && _queue[pos]->mState != ftFileControl::QUEUED && _queue[pos]->mState != ftFileControl::PAUSED)
@ -655,7 +656,7 @@ void ftController::locked_checkQueueElement(uint32_t pos)
_queue[pos]->mCreator->closeFile() ;
if(_queue[pos]->mFlags & RS_FILE_REQ_ANONYMOUS_ROUTING)
mTurtle->stopMonitoringFileTunnels(_queue[pos]->mHash) ;
mTurtle->stopMonitoringTunnels(_queue[pos]->mHash) ;
}
}
@ -899,7 +900,7 @@ bool ftController::completeFile(std::string hash)
mDownloads.erase(it);
if(flags & RS_FILE_REQ_ANONYMOUS_ROUTING)
mTurtle->stopMonitoringFileTunnels(hash_to_suppress) ;
mTurtle->stopMonitoringTunnels(hash_to_suppress) ;
} /******* UNLOCKED ********/
@ -1264,7 +1265,7 @@ bool ftController::FileRequest(const std::string& fname, const std::string& has
// We check that flags are consistent.
if(flags & RS_FILE_REQ_ANONYMOUS_ROUTING)
mTurtle->monitorFileTunnels(fname,hash,size) ;
mTurtle->monitorTunnels(hash,mFtServer) ;
bool assume_availability = flags & RS_FILE_REQ_CACHE ; // assume availability for cache files
@ -1365,7 +1366,7 @@ bool ftController::setChunkStrategy(const std::string& hash,FileChunksInfo::Chun
bool ftController::FileCancel(const std::string& hash)
{
rsTurtle->stopMonitoringFileTunnels(hash) ;
rsTurtle->stopMonitoringTunnels(hash) ;
#ifdef CONTROL_DEBUG
std::cerr << "ftController::FileCancel" << std::endl;

View File

@ -42,6 +42,7 @@ class ftFileCreator;
class ftTransferModule;
class ftFileProvider;
class ftSearch;
class ftServer;
class ftExtraList;
class ftDataMultiplex;
class p3turtle ;
@ -119,6 +120,7 @@ class ftController: public CacheTransfer, public RsThread, public pqiMonitor, pu
void setFtSearchNExtra(ftSearch *, ftExtraList *);
void setTurtleRouter(p3turtle *) ;
void setFtServer(ftServer *) ;
bool activate();
bool isActiveAndNoPending();
@ -234,6 +236,7 @@ class ftController: public CacheTransfer, public RsThread, public pqiMonitor, pu
ftDataMultiplex *mDataplex;
ftExtraList *mExtraList;
p3turtle *mTurtle ;
ftServer *mFtServer ;
RsMutex ctrlMutex;

View File

@ -1085,7 +1085,7 @@ bool ftDataMultiplex::locked_handleServerRequest(ftFileProvider *provider,
std::string peerId, std::string hash, uint64_t size,
uint64_t offset, uint32_t chunksize)
{
if(chunksize > std::min(size,uint64_t(10*1024*1024)))
if(chunksize > uint32_t(10*1024*1024))
{
std::cerr << "Warning: peer " << peerId << " is asking a large chunk (s=" << chunksize << ") for hash " << hash << ", filesize=" << size << ". This is unexpected." << std::endl ;
return false ;

View File

@ -153,6 +153,12 @@ bool ftFileProvider::getFileData(const std::string& peer_id,uint64_t offset, uin
* FIXME: Warning of comparison between unsigned and signed int?
*/
if(offset >= mSize)
{
std::cerr << "ftFileProvider::getFileData(): request (" << offset << ") exceeds file size (" << mSize << "! " << std::endl;
return false ;
}
uint32_t data_size = chunk_size;
uint64_t base_loc = offset;

View File

@ -28,8 +28,10 @@
#include "util/rsdebug.h"
#include "util/rsdir.h"
#include "retroshare/rstypes.h"
#include "retroshare/rspeers.h"
const int ftserverzone = 29539;
#include "ft/ftturtlefiletransferitem.h"
#include "ft/ftserver.h"
#include "ft/ftextralist.h"
#include "ft/ftfilesearch.h"
@ -153,6 +155,9 @@ void ftServer::connectToTurtleRouter(p3turtle *fts)
mTurtleRouter = fts ;
mFtController->setTurtleRouter(fts) ;
mFtController->setFtServer(this) ;
mTurtleRouter->registerTunnelService(this) ;
}
void ftServer::StartupThreads()
@ -450,6 +455,77 @@ bool ftServer::FileDetails(const std::string &hash, FileSearchFlags hintflags, F
return false;
}
RsTurtleGenericTunnelItem *ftServer::deserialiseItem(void *data,uint32_t size) const
{
uint32_t rstype = getRsItemId(data);
#ifdef SERVER_DEBUG
std::cerr << "p3turtle: deserialising packet: " << std::endl ;
#endif
#ifdef SERVER_DEBUG
if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || (RS_SERVICE_TYPE_TURTLE != getRsItemService(rstype)))
{
#ifdef SERVER_DEBUG
std::cerr << " Wrong type !!" << std::endl ;
#endif
return NULL; /* wrong type */
}
#endif
switch(getRsItemSubType(rstype))
{
case RS_TURTLE_SUBTYPE_FILE_REQUEST : return new RsTurtleFileRequestItem(data,size) ;
case RS_TURTLE_SUBTYPE_FILE_DATA : return new RsTurtleFileDataItem(data,size) ;
case RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST : return new RsTurtleFileMapRequestItem(data,size) ;
case RS_TURTLE_SUBTYPE_FILE_MAP : return new RsTurtleFileMapItem(data,size) ;
case RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST : return new RsTurtleFileCrcRequestItem(data,size) ;
case RS_TURTLE_SUBTYPE_FILE_CRC : return new RsTurtleFileCrcItem(data,size) ;
case RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST : return new RsTurtleChunkCrcRequestItem(data,size) ;
case RS_TURTLE_SUBTYPE_CHUNK_CRC : return new RsTurtleChunkCrcItem(data,size) ;
default:
return NULL ;
}
}
void ftServer::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir)
{
if(dir == RsTurtleGenericTunnelItem::DIRECTION_SERVER)
mFtController->addFileSource(hash,virtual_peer_id) ;
}
void ftServer::removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id)
{
mFtController->removeFileSource(hash,virtual_peer_id) ;
}
bool ftServer::handleTunnelRequest(const std::string& hash,const std::string& peer_id)
{
FileInfo info ;
bool res = FileDetails(hash, RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_SPEC_ONLY | RS_FILE_HINTS_DOWNLOAD, info);
#ifdef SERVER_DEBUG
std::cerr << "ftServer: performing local hash search for hash " << hash << std::endl;
if(res)
{
std::cerr << "Found hash: " << std::endl;
std::cerr << " hash = " << hash << std::endl;
std::cerr << " peer = " << peer_id << std::endl;
std::cerr << " flags = " << info.storage_permission_flags << std::endl;
std::cerr << " local = " << rsFiles->FileDetails(hash, RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_SPEC_ONLY | RS_FILE_HINTS_DOWNLOAD, info) << std::endl;
std::cerr << " groups= " ; for(std::list<std::string>::const_iterator it(info.parent_groups.begin());it!=info.parent_groups.end();++it) std::cerr << (*it) << ", " ; std::cerr << std::endl;
std::cerr << " clear = " << rsPeers->computePeerPermissionFlags(peer_id,info.storage_permission_flags,info.parent_groups) << std::endl;
}
#endif
// The call to computeHashPeerClearance() return a combination of RS_FILE_HINTS_NETWORK_WIDE and RS_FILE_HINTS_BROWSABLE
// This is an additional computation cost, but the way it's written here, it's only called when res is true.
//
res = res && (RS_FILE_HINTS_NETWORK_WIDE & rsPeers->computePeerPermissionFlags(peer_id,info.storage_permission_flags,info.parent_groups)) ;
return res ;
}
/***************************************************************/
/******************* ExtraFileList Access **********************/
/***************************************************************/
@ -809,7 +885,14 @@ bool ftServer::loadConfigMap(std::map<std::string, std::string> &/*configMap*/)
bool ftServer::sendDataRequest(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize)
{
if(mTurtleRouter->isTurtlePeer(peerId))
mTurtleRouter->sendDataRequest(peerId,hash,size,offset,chunksize) ;
{
RsTurtleFileRequestItem *item = new RsTurtleFileRequestItem ;
item->chunk_offset = offset ;
item->chunk_size = chunksize ;
mTurtleRouter->sendTurtleData(peerId,item) ;
}
else
{
/* create a packet */
@ -836,7 +919,10 @@ bool ftServer::sendDataRequest(const std::string& peerId, const std::string& has
bool ftServer::sendChunkMapRequest(const std::string& peerId,const std::string& hash,bool is_client)
{
if(mTurtleRouter->isTurtlePeer(peerId))
mTurtleRouter->sendChunkMapRequest(peerId,hash,is_client) ;
{
RsTurtleFileMapRequestItem *item = new RsTurtleFileMapRequestItem ;
mTurtleRouter->sendTurtleData(peerId,item) ;
}
else
{
/* create a packet */
@ -859,7 +945,11 @@ bool ftServer::sendChunkMapRequest(const std::string& peerId,const std::string&
bool ftServer::sendChunkMap(const std::string& peerId,const std::string& hash,const CompressedChunkMap& map,bool is_client)
{
if(mTurtleRouter->isTurtlePeer(peerId))
mTurtleRouter->sendChunkMap(peerId,hash,map,is_client) ;
{
RsTurtleFileMapItem *item = new RsTurtleFileMapItem ;
item->compressed_map = map ;
mTurtleRouter->sendTurtleData(peerId,item) ;
}
else
{
/* create a packet */
@ -882,7 +972,11 @@ bool ftServer::sendChunkMap(const std::string& peerId,const std::string& hash,co
bool ftServer::sendCRC32MapRequest(const std::string& peerId,const std::string& hash)
{
if(mTurtleRouter->isTurtlePeer(peerId))
mTurtleRouter->sendCRC32MapRequest(peerId,hash) ;
{
RsTurtleFileCrcRequestItem *item = new RsTurtleFileCrcRequestItem;
mTurtleRouter->sendTurtleData(peerId,item) ;
}
else
{
/* create a packet */
@ -903,7 +997,12 @@ bool ftServer::sendCRC32MapRequest(const std::string& peerId,const std::string&
bool ftServer::sendSingleChunkCRCRequest(const std::string& peerId,const std::string& hash,uint32_t chunk_number)
{
if(mTurtleRouter->isTurtlePeer(peerId))
mTurtleRouter->sendSingleChunkCRCRequest(peerId,hash,chunk_number) ;
{
RsTurtleChunkCrcRequestItem *item = new RsTurtleChunkCrcRequestItem;
item->chunk_number = chunk_number ;
mTurtleRouter->sendTurtleData(peerId,item) ;
}
else
{
/* create a packet */
@ -926,7 +1025,12 @@ bool ftServer::sendSingleChunkCRCRequest(const std::string& peerId,const std::st
bool ftServer::sendCRC32Map(const std::string& peerId,const std::string& hash,const CRC32Map& crcmap)
{
if(mTurtleRouter->isTurtlePeer(peerId))
mTurtleRouter->sendCRC32Map(peerId,hash,crcmap) ;
{
RsTurtleFileCrcItem *item = new RsTurtleFileCrcItem ;
item->crc_map = crcmap ;
mTurtleRouter->sendTurtleData(peerId,item) ;
}
else
{
/* create a packet */
@ -948,7 +1052,13 @@ bool ftServer::sendCRC32Map(const std::string& peerId,const std::string& hash,co
bool ftServer::sendSingleChunkCRC(const std::string& peerId,const std::string& hash,uint32_t chunk_number,const Sha1CheckSum& crc)
{
if(mTurtleRouter->isTurtlePeer(peerId))
mTurtleRouter->sendSingleChunkCRC(peerId,hash,chunk_number,crc) ;
{
RsTurtleChunkCrcItem *item = new RsTurtleChunkCrcItem;
item->chunk_number = chunk_number ;
item->check_sum = crc ;
mTurtleRouter->sendTurtleData(peerId,item) ;
}
else
{
/* create a packet */
@ -1003,7 +1113,23 @@ bool ftServer::sendData(const std::string& peerId, const std::string& hash, uint
/******** New Serialiser Type *******/
if(mTurtleRouter->isTurtlePeer(peerId))
mTurtleRouter->sendFileData(peerId,hash,size,baseoffset+offset,chunk,&(((uint8_t *) data)[offset])) ;
{
RsTurtleFileDataItem *item = new RsTurtleFileDataItem ;
item->chunk_offset = offset+baseoffset ;
item->chunk_size = chunk;
item->chunk_data = malloc(chunk) ;
if(item->chunk_data == NULL)
{
std::cerr << "p3turtle: Warning: failed malloc of " << chunk << " bytes for sending data packet." << std::endl ;
delete item;
return false;
}
memcpy(item->chunk_data,&(((uint8_t *) data)[offset]),chunk) ;
mTurtleRouter->sendTurtleData(peerId,item) ;
}
else
{
RsFileData *rfd = new RsFileData();
@ -1047,6 +1173,76 @@ bool ftServer::sendData(const std::string& peerId, const std::string& hash, uint
return true;
}
void ftServer::receiveTurtleData(RsTurtleGenericTunnelItem *i,
const std::string& hash,
const std::string& virtual_peer_id,
RsTurtleGenericTunnelItem::Direction direction)
{
switch(i->PacketSubType())
{
case RS_TURTLE_SUBTYPE_FILE_REQUEST:
{
RsTurtleFileRequestItem *item = dynamic_cast<RsTurtleFileRequestItem *>(i) ;
getMultiplexer()->recvDataRequest(virtual_peer_id,hash,0,item->chunk_offset,item->chunk_size) ;
}
break ;
case RS_TURTLE_SUBTYPE_FILE_DATA :
{
RsTurtleFileDataItem *item = dynamic_cast<RsTurtleFileDataItem *>(i) ;
getMultiplexer()->recvData(virtual_peer_id,hash,0,item->chunk_offset,item->chunk_size,item->chunk_data) ;
item->chunk_data = NULL ; // this prevents deletion in the destructor of RsFileDataItem, because data will be deleted
// down _ft_server->getMultiplexer()->recvData()...in ftTransferModule::recvFileData
}
break ;
case RS_TURTLE_SUBTYPE_FILE_MAP :
{
RsTurtleFileMapItem *item = dynamic_cast<RsTurtleFileMapItem *>(i) ;
getMultiplexer()->recvChunkMap(virtual_peer_id,hash,item->compressed_map,direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ;
}
break ;
case RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST:
{
RsTurtleFileMapRequestItem *item = dynamic_cast<RsTurtleFileMapRequestItem *>(i) ;
getMultiplexer()->recvChunkMapRequest(virtual_peer_id,hash,direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ;
}
break ;
case RS_TURTLE_SUBTYPE_FILE_CRC :
{
RsTurtleFileCrcItem *item = dynamic_cast<RsTurtleFileCrcItem *>(i) ;
getMultiplexer()->recvCRC32Map(virtual_peer_id,hash,item->crc_map) ;
}
break ;
case RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST:
{
getMultiplexer()->recvCRC32MapRequest(virtual_peer_id,hash) ;
}
break ;
case RS_TURTLE_SUBTYPE_CHUNK_CRC :
{
RsTurtleChunkCrcItem *item = dynamic_cast<RsTurtleChunkCrcItem *>(i) ;
getMultiplexer()->recvSingleChunkCRC(virtual_peer_id,hash,item->chunk_number,item->check_sum) ;
}
break ;
case RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST:
{
RsTurtleChunkCrcRequestItem *item = dynamic_cast<RsTurtleChunkCrcRequestItem *>(i) ;
getMultiplexer()->recvSingleChunkCRCRequest(virtual_peer_id,hash,item->chunk_number) ;
}
break ;
default:
std::cerr << "WARNING: Unknown packet type received: sub_id=" << reinterpret_cast<void*>(i->PacketSubType()) << ". Is somebody trying to poison you ?" << std::endl ;
}
}
/* NB: The rsCore lock must be activated before calling this.
* This Lock should be moved lower into the system...

View File

@ -44,6 +44,7 @@
#include <iostream>
#include "ft/ftdata.h"
#include "turtle/turtleclientservice.h"
#include "retroshare/rsfiles.h"
//#include "dbase/cachestrapper.h"
@ -72,142 +73,151 @@ class ftDwlQueue;
class p3PeerMgr;
class p3LinkMgr;
class ftServer: public RsFiles, public ftDataSend, public RsThread
class ftServer: public RsFiles, public ftDataSend, public RsTurtleClientService, public RsThread
{
public:
/***************************************************************/
/******************** Setup ************************************/
/***************************************************************/
/***************************************************************/
/******************** Setup ************************************/
/***************************************************************/
ftServer(p3PeerMgr *peerMgr, p3LinkMgr *linkMgr);
ftServer(p3PeerMgr *peerMgr, p3LinkMgr *linkMgr);
/* Assign important variables */
void setConfigDirectory(std::string path);
/* Assign important variables */
void setConfigDirectory(std::string path);
void setP3Interface(P3Interface *pqi);
void setP3Interface(P3Interface *pqi);
/* add Config Items (Extra, Controller) */
void addConfigComponents(p3ConfigMgr *mgr);
/* add Config Items (Extra, Controller) */
void addConfigComponents(p3ConfigMgr *mgr);
virtual CacheStrapper *getCacheStrapper();
virtual CacheTransfer *getCacheTransfer();
virtual CacheStrapper *getCacheStrapper();
virtual CacheTransfer *getCacheTransfer();
std::string OwnId();
std::string OwnId();
/* Final Setup (once everything is assigned) */
//void SetupFtServer();
void SetupFtServer(NotifyBase *cb);
void connectToTurtleRouter(p3turtle *p) ;
/* Final Setup (once everything is assigned) */
//void SetupFtServer();
void SetupFtServer(NotifyBase *cb);
void connectToTurtleRouter(p3turtle *p) ;
void StartupThreads();
void StopThreads();
void StartupThreads();
void StopThreads();
/* own thread */
virtual void run();
/* own thread */
virtual void run();
// Checks that the given hash is well formed. Used to chase
// string bugs.
static bool checkHash(const std::string& hash,std::string& error_string) ;
// Checks that the given hash is well formed. Used to chase
// string bugs.
static bool checkHash(const std::string& hash,std::string& error_string) ;
/***************************************************************/
/*************** Control Interface *****************************/
/************** (Implements RsFiles) ***************************/
/***************************************************************/
// Implements RsTurtleClientService
//
virtual bool handleTunnelRequest(const std::string& hash,const std::string& peer_id) ;
virtual void receiveTurtleData(RsTurtleGenericTunnelItem *item,const std::string& hash,const std::string& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction) ;
virtual RsTurtleGenericTunnelItem *deserialiseItem(void *data,uint32_t size) const ;
// member access
void addVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&,RsTurtleGenericTunnelItem::Direction dir) ;
void removeVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&) ;
ftDataMultiplex *getMultiplexer() const { return mFtDataplex ; }
ftController *getController() const { return mFtController ; }
/***************************************************************/
/*************** Control Interface *****************************/
/************** (Implements RsFiles) ***************************/
/***************************************************************/
/***
* Control of Downloads
***/
virtual bool alreadyHaveFile(const std::string& hash, FileInfo &info);
virtual bool FileRequest(const std::string& fname, const std::string& hash, uint64_t size, const std::string& dest, TransferRequestFlags flags, const std::list<std::string>& srcIds);
virtual bool FileCancel(const std::string& hash);
virtual bool FileControl(const std::string& hash, uint32_t flags);
virtual bool FileClearCompleted();
virtual bool setDestinationDirectory(const std::string& hash,const std::string& new_path) ;
virtual bool setDestinationName(const std::string& hash,const std::string& new_name) ;
virtual bool setChunkStrategy(const std::string& hash,FileChunksInfo::ChunkStrategy s) ;
virtual void setDefaultChunkStrategy(FileChunksInfo::ChunkStrategy) ;
virtual FileChunksInfo::ChunkStrategy defaultChunkStrategy() ;
virtual uint32_t freeDiskSpaceLimit() const ;
virtual void setFreeDiskSpaceLimit(uint32_t size_in_mb) ;
// member access
ftDataMultiplex *getMultiplexer() const { return mFtDataplex ; }
ftController *getController() const { return mFtController ; }
/***
* Control of Downloads
***/
virtual bool alreadyHaveFile(const std::string& hash, FileInfo &info);
virtual bool FileRequest(const std::string& fname, const std::string& hash, uint64_t size, const std::string& dest, TransferRequestFlags flags, const std::list<std::string>& srcIds);
virtual bool FileCancel(const std::string& hash);
virtual bool FileControl(const std::string& hash, uint32_t flags);
virtual bool FileClearCompleted();
virtual bool setDestinationDirectory(const std::string& hash,const std::string& new_path) ;
virtual bool setDestinationName(const std::string& hash,const std::string& new_name) ;
virtual bool setChunkStrategy(const std::string& hash,FileChunksInfo::ChunkStrategy s) ;
virtual void setDefaultChunkStrategy(FileChunksInfo::ChunkStrategy) ;
virtual FileChunksInfo::ChunkStrategy defaultChunkStrategy() ;
virtual uint32_t freeDiskSpaceLimit() const ;
virtual void setFreeDiskSpaceLimit(uint32_t size_in_mb) ;
/***
* Control of Downloads Priority.
***/
virtual uint32_t getMinPrioritizedTransfers() ;
virtual void setMinPrioritizedTransfers(uint32_t s) ;
virtual uint32_t getQueueSize() ;
virtual void setQueueSize(uint32_t s) ;
virtual bool changeQueuePosition(const std::string hash, QueueMove queue_mv);
virtual bool changeDownloadSpeed(const std::string hash, int speed);
virtual bool getDownloadSpeed(const std::string hash, int & speed);
virtual bool clearDownload(const std::string hash);
//virtual void getDwlDetails(std::list<DwlDetails> & details);
/***
* Control of Downloads Priority.
***/
virtual uint32_t getMinPrioritizedTransfers() ;
virtual void setMinPrioritizedTransfers(uint32_t s) ;
virtual uint32_t getQueueSize() ;
virtual void setQueueSize(uint32_t s) ;
virtual bool changeQueuePosition(const std::string hash, QueueMove queue_mv);
virtual bool changeDownloadSpeed(const std::string hash, int speed);
virtual bool getDownloadSpeed(const std::string hash, int & speed);
virtual bool clearDownload(const std::string hash);
//virtual void getDwlDetails(std::list<DwlDetails> & details);
/***
* Download/Upload Details
***/
virtual bool FileDownloads(std::list<std::string> &hashs);
virtual bool FileUploads(std::list<std::string> &hashs);
virtual bool FileDetails(const std::string &hash, FileSearchFlags hintflags, FileInfo &info);
virtual bool FileDownloadChunksDetails(const std::string& hash,FileChunksInfo& info) ;
virtual bool FileUploadChunksDetails(const std::string& hash,const std::string& peer_id,CompressedChunkMap& map) ;
/***
* Download/Upload Details
***/
virtual bool FileDownloads(std::list<std::string> &hashs);
virtual bool FileUploads(std::list<std::string> &hashs);
virtual bool FileDetails(const std::string &hash, FileSearchFlags hintflags, FileInfo &info);
virtual bool FileDownloadChunksDetails(const std::string& hash,FileChunksInfo& info) ;
virtual bool FileUploadChunksDetails(const std::string& hash,const std::string& peer_id,CompressedChunkMap& map) ;
/***
* Extra List Access
***/
virtual bool ExtraFileAdd(std::string fname, std::string hash, uint64_t size, uint32_t period, TransferRequestFlags flags);
virtual bool ExtraFileRemove(std::string hash, TransferRequestFlags flags);
virtual bool ExtraFileHash(std::string localpath, uint32_t period, TransferRequestFlags flags);
virtual bool ExtraFileStatus(std::string localpath, FileInfo &info);
virtual bool ExtraFileMove(std::string fname, std::string hash, uint64_t size, std::string destpath);
/***
* Extra List Access
***/
virtual bool ExtraFileAdd(std::string fname, std::string hash, uint64_t size, uint32_t period, TransferRequestFlags flags);
virtual bool ExtraFileRemove(std::string hash, TransferRequestFlags flags);
virtual bool ExtraFileHash(std::string localpath, uint32_t period, TransferRequestFlags flags);
virtual bool ExtraFileStatus(std::string localpath, FileInfo &info);
virtual bool ExtraFileMove(std::string fname, std::string hash, uint64_t size, std::string destpath);
/***
* Directory Listing / Search Interface
***/
virtual int RequestDirDetails(const std::string& uid, const std::string& path, DirDetails &details);
virtual int RequestDirDetails(void *ref, DirDetails &details, FileSearchFlags flags);
virtual uint32_t getType(void *ref,FileSearchFlags flags) ;
/***
* Directory Listing / Search Interface
***/
virtual int RequestDirDetails(const std::string& uid, const std::string& path, DirDetails &details);
virtual int RequestDirDetails(void *ref, DirDetails &details, FileSearchFlags flags);
virtual uint32_t getType(void *ref,FileSearchFlags flags) ;
virtual int SearchKeywords(std::list<std::string> keywords, std::list<DirDetails> &results,FileSearchFlags flags);
virtual int SearchKeywords(std::list<std::string> keywords, std::list<DirDetails> &results,FileSearchFlags flags,const std::string& peer_id);
virtual int SearchBoolExp(Expression * exp, std::list<DirDetails> &results,FileSearchFlags flags);
virtual int SearchBoolExp(Expression * exp, std::list<DirDetails> &results,FileSearchFlags flags,const std::string& peer_id);
virtual int SearchKeywords(std::list<std::string> keywords, std::list<DirDetails> &results,FileSearchFlags flags);
virtual int SearchKeywords(std::list<std::string> keywords, std::list<DirDetails> &results,FileSearchFlags flags,const std::string& peer_id);
virtual int SearchBoolExp(Expression * exp, std::list<DirDetails> &results,FileSearchFlags flags);
virtual int SearchBoolExp(Expression * exp, std::list<DirDetails> &results,FileSearchFlags flags,const std::string& peer_id);
/***
* Utility Functions
***/
virtual bool ConvertSharedFilePath(std::string path, std::string &fullpath);
virtual void ForceDirectoryCheck();
virtual void updateSinceGroupPermissionsChanged() ;
virtual bool InDirectoryCheck();
virtual bool CopyFile(const std::string& source, const std::string& dest);
/***
* Utility Functions
***/
virtual bool ConvertSharedFilePath(std::string path, std::string &fullpath);
virtual void ForceDirectoryCheck();
virtual void updateSinceGroupPermissionsChanged() ;
virtual bool InDirectoryCheck();
virtual bool CopyFile(const std::string& source, const std::string& dest);
/***
* Directory Handling
***/
virtual void setDownloadDirectory(std::string path);
virtual void setPartialsDirectory(std::string path);
virtual std::string getDownloadDirectory();
virtual std::string getPartialsDirectory();
/***
* Directory Handling
***/
virtual void setDownloadDirectory(std::string path);
virtual void setPartialsDirectory(std::string path);
virtual std::string getDownloadDirectory();
virtual std::string getPartialsDirectory();
virtual bool getSharedDirectories(std::list<SharedDirInfo> &dirs);
virtual bool setSharedDirectories(std::list<SharedDirInfo> &dirs);
virtual bool addSharedDirectory(const SharedDirInfo& dir);
virtual bool updateShareFlags(const SharedDirInfo& dir); // updates the flags. The directory should already exist !
virtual bool removeSharedDirectory(std::string dir);
virtual bool getSharedDirectories(std::list<SharedDirInfo> &dirs);
virtual bool setSharedDirectories(std::list<SharedDirInfo> &dirs);
virtual bool addSharedDirectory(const SharedDirInfo& dir);
virtual bool updateShareFlags(const SharedDirInfo& dir); // updates the flags. The directory should already exist !
virtual bool removeSharedDirectory(std::string dir);
virtual bool getShareDownloadDirectory();
virtual bool shareDownloadDirectory(bool share);
virtual bool getShareDownloadDirectory();
virtual bool shareDownloadDirectory(bool share);
virtual void setRememberHashFilesDuration(uint32_t days) ;
virtual uint32_t rememberHashFilesDuration() const ;
@ -217,84 +227,84 @@ virtual bool shareDownloadDirectory(bool share);
virtual void setWatchPeriod(int minutes) ;
virtual int watchPeriod() const ;
/***************************************************************/
/*************** Control Interface *****************************/
/***************************************************************/
/***************************************************************/
/*************** Control Interface *****************************/
/***************************************************************/
/***************************************************************/
/*************** Data Transfer Interface ***********************/
/***************************************************************/
public:
virtual bool sendData(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data);
virtual bool sendDataRequest(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize);
virtual bool sendChunkMapRequest(const std::string& peer_id,const std::string& hash,bool is_client) ;
virtual bool sendChunkMap(const std::string& peer_id,const std::string& hash,const CompressedChunkMap& cmap,bool is_client) ;
virtual bool sendCRC32MapRequest(const std::string&, const std::string&) ;
virtual bool sendCRC32Map(const std::string&, const std::string&, const CRC32Map&) ;
virtual bool sendSingleChunkCRCRequest(const std::string& peer_id,const std::string& hash,uint32_t chunk_number) ;
virtual bool sendSingleChunkCRC(const std::string& peer_id,const std::string& hash,uint32_t chunk_number,const Sha1CheckSum& crc) ;
/***************************************************************/
/*************** Data Transfer Interface ***********************/
/***************************************************************/
public:
virtual bool sendData(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data);
virtual bool sendDataRequest(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize);
virtual bool sendChunkMapRequest(const std::string& peer_id,const std::string& hash,bool is_client) ;
virtual bool sendChunkMap(const std::string& peer_id,const std::string& hash,const CompressedChunkMap& cmap,bool is_client) ;
virtual bool sendCRC32MapRequest(const std::string&, const std::string&) ;
virtual bool sendCRC32Map(const std::string&, const std::string&, const CRC32Map&) ;
virtual bool sendSingleChunkCRCRequest(const std::string& peer_id,const std::string& hash,uint32_t chunk_number) ;
virtual bool sendSingleChunkCRC(const std::string& peer_id,const std::string& hash,uint32_t chunk_number,const Sha1CheckSum& crc) ;
/*************** Internal Transfer Fns *************************/
virtual int tick();
/*************** Internal Transfer Fns *************************/
virtual int tick();
/* Configuration */
bool addConfiguration(p3ConfigMgr *cfgmgr);
bool ResumeTransfers();
/* Configuration */
bool addConfiguration(p3ConfigMgr *cfgmgr);
bool ResumeTransfers();
private:
bool handleInputQueues();
bool handleCacheData();
bool handleFileData();
private:
bool handleInputQueues();
bool handleCacheData();
bool handleFileData();
/******************* p3 Config Overload ************************/
/******************* p3 Config Overload ************************/
protected:
/* Key Functions to be overloaded for Full Configuration */
virtual RsSerialiser *setupSerialiser();
virtual bool saveList(bool &cleanup, std::list<RsItem *>&);
virtual bool loadList(std::list<RsItem *>& load);
/* Key Functions to be overloaded for Full Configuration */
virtual RsSerialiser *setupSerialiser();
virtual bool saveList(bool &cleanup, std::list<RsItem *>&);
virtual bool loadList(std::list<RsItem *>& load);
private:
bool loadConfigMap(std::map<std::string, std::string> &configMap);
/******************* p3 Config Overload ************************/
bool loadConfigMap(std::map<std::string, std::string> &configMap);
/******************* p3 Config Overload ************************/
/*************************** p3 Config Overload ********************/
/*************************** p3 Config Overload ********************/
private:
/**** INTERNAL FUNCTIONS ***/
//virtual int reScanDirs();
//virtual int check_dBUpdate();
/**** INTERNAL FUNCTIONS ***/
//virtual int reScanDirs();
//virtual int check_dBUpdate();
private:
/* no need for Mutex protection -
* as each component is protected independently.
*/
/* no need for Mutex protection -
* as each component is protected independently.
*/
P3Interface *mP3iface; /* XXX THIS NEEDS PROTECTION */
P3Interface *mP3iface; /* XXX THIS NEEDS PROTECTION */
p3PeerMgr *mPeerMgr;
p3LinkMgr *mLinkMgr;
ftCacheStrapper *mCacheStrapper;
ftFiStore *mFiStore;
ftFiMonitor *mFiMon;
p3PeerMgr *mPeerMgr;
p3LinkMgr *mLinkMgr;
ftController *mFtController;
ftExtraList *mFtExtra;
ftCacheStrapper *mCacheStrapper;
ftFiStore *mFiStore;
ftFiMonitor *mFiMon;
ftDataMultiplex *mFtDataplex;
p3turtle *mTurtleRouter ;
ftController *mFtController;
ftExtraList *mFtExtra;
ftDataMultiplex *mFtDataplex;
p3turtle *mTurtleRouter ;
ftFileSearch *mFtSearch;
ftFileSearch *mFtSearch;
ftDwlQueue *mFtDwlQueue;
ftDwlQueue *mFtDwlQueue;
RsMutex srvMutex;
std::string mConfigPath;
std::string mDownloadPath;
std::string mPartialsPath;
RsMutex srvMutex;
std::string mConfigPath;
std::string mDownloadPath;
std::string mPartialsPath;
};

View File

@ -0,0 +1,739 @@
/*
* libretroshare/src/services: ftturtlefiletransferitem.cc
*
* Services for RetroShare.
*
* Copyright 2013 by Cyril Soler
*
* 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 "csoler@users.sourceforge.net".
*
*/
#include <iostream>
#include <stdexcept>
#include <serialiser/itempriorities.h>
#include <ft/ftturtlefiletransferitem.h>
uint32_t RsTurtleFileRequestItem::serial_size()
{
uint32_t s = 0 ;
s += 8 ; // header
s += 4 ; // tunnel id
s += 8 ; // file offset
s += 4 ; // chunk size
return s ;
}
uint32_t RsTurtleFileDataItem::serial_size()
{
uint32_t s = 0 ;
s += 8 ; // header
s += 4 ; // tunnel id
s += 8 ; // file offset
s += 4 ; // chunk size
s += chunk_size ; // actual data size.
return s ;
}
uint32_t RsTurtleFileMapRequestItem::serial_size()
{
uint32_t s = 0 ;
s += 8 ; // header
s += 4 ; // tunnel id
s += 4 ; // direction
return s ;
}
uint32_t RsTurtleFileMapItem::serial_size()
{
uint32_t s = 0 ;
s += 8 ; // header
s += 4 ; // tunnel id
s += 4 ; // direction
s += 4 ; // compressed_map.size()
s += 4 * compressed_map._map.size() ;
return s ;
}
uint32_t RsTurtleFileCrcRequestItem::serial_size()
{
uint32_t s = 0 ;
s += 8 ; // header
s += 4 ; // tunnel id
return s ;
}
uint32_t RsTurtleChunkCrcItem::serial_size()
{
uint32_t s = 0 ;
s += 8 ; // header
s += 4 ; // tunnel id
s += 4 ; // chunk number
s += 20 ; // check_sum
return s ;
}
uint32_t RsTurtleChunkCrcRequestItem::serial_size()
{
uint32_t s = 0 ;
s += 8 ; // header
s += 4 ; // tunnel id
s += 4 ; // chunk number
return s ;
}
uint32_t RsTurtleFileCrcItem::serial_size()
{
uint32_t s = 0 ;
s += 8 ; // header
s += 4 ; // tunnel id
s += 4 ; // size of _map
s += 4 ; // size of _crcs
s += 4 * crc_map._crcs.size() ;
s += 4 * crc_map._ccmap._map.size() ;
return s ;
}
bool RsTurtleFileMapRequestItem::serialize(void *data,uint32_t& pktsize)
{
uint32_t tlvsize = serial_size();
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize);
/* skip the header */
offset += 8;
/* add mandatory parts first */
ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id);
ok &= setRawUInt32(data, tlvsize, &offset, direction);
if (offset != tlvsize)
{
ok = false;
#ifdef RSSERIAL_DEBUG
std::cerr << "RsFileConfigSerialiser::serialiseTransfer() Size Error! " << std::endl;
#endif
}
return ok;
}
bool RsTurtleFileMapItem::serialize(void *data,uint32_t& pktsize)
{
uint32_t tlvsize = serial_size();
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize);
/* skip the header */
offset += 8;
/* add mandatory parts first */
ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id);
ok &= setRawUInt32(data, tlvsize, &offset, direction);
ok &= setRawUInt32(data, tlvsize, &offset, compressed_map._map.size());
for(uint32_t i=0;i<compressed_map._map.size() && ok;++i)
ok &= setRawUInt32(data, tlvsize, &offset, compressed_map._map[i]);
if (offset != tlvsize)
{
ok = false;
#ifdef RSSERIAL_DEBUG
std::cerr << "RsFileConfigSerialiser::serialiseTransfer() Size Error! " << std::endl;
#endif
}
return ok;
}
bool RsTurtleFileCrcRequestItem::serialize(void *data,uint32_t& pktsize)
{
#ifdef P3TURTLE_DEBUG
std::cerr << "RsTurtleFileCrcRequestItem::serialize(): serializing packet:" << std::endl ;
print(std::cerr,2) ;
#endif
uint32_t tlvsize = serial_size();
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize);
/* skip the header */
offset += 8;
/* add mandatory parts first */
ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id);
if (offset != tlvsize)
{
ok = false;
std::cerr << "RsFileConfigSerialiser::serialiseTransfer() Size Error! " << std::endl;
}
return ok;
}
bool RsTurtleChunkCrcRequestItem::serialize(void *data,uint32_t& pktsize)
{
#ifdef P3TURTLE_DEBUG
std::cerr << "RsTurtleChunkCrcRequestItem::serialize(): serializing packet:" << std::endl ;
print(std::cerr,2) ;
#endif
uint32_t tlvsize = serial_size();
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize);
/* skip the header */
offset += 8;
/* add mandatory parts first */
ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id);
ok &= setRawUInt32(data, tlvsize, &offset, chunk_number);
if (offset != tlvsize)
{
ok = false;
std::cerr << "RsFileConfigSerialiser::serialiseTransfer() Size Error! " << std::endl;
}
return ok;
}
bool RsTurtleFileCrcItem::serialize(void *data,uint32_t& pktsize)
{
#ifdef P3TURTLE_DEBUG
std::cerr << "RsTurtleFileCrcItem::serialize(): serializing packet:" << std::endl ;
print(std::cerr,2) ;
#endif
uint32_t tlvsize = serial_size();
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize);
/* skip the header */
offset += 8;
/* add mandatory parts first */
ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id);
ok &= setRawUInt32(data, tlvsize, &offset, crc_map._ccmap._map.size());
ok &= setRawUInt32(data, tlvsize, &offset, crc_map._crcs.size());
for(uint32_t i=0;i<crc_map._ccmap._map.size() && ok;++i)
ok &= setRawUInt32(data, tlvsize, &offset, crc_map._ccmap._map[i]);
for(uint32_t i=0;i<crc_map._crcs.size() && ok;++i)
ok &= setRawUInt32(data, tlvsize, &offset, crc_map._crcs[i]);
if (offset != tlvsize)
{
ok = false;
std::cerr << "RsFileConfigSerialiser::serialiseTransfer() Size Error! " << std::endl;
}
return ok;
}
bool RsTurtleChunkCrcItem::serialize(void *data,uint32_t& pktsize)
{
#ifdef P3TURTLE_DEBUG
std::cerr << "RsTurtleChunkCrcRequestItem::serialize(): serializing packet:" << std::endl ;
print(std::cerr,2) ;
#endif
uint32_t tlvsize = serial_size();
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize);
/* skip the header */
offset += 8;
/* add mandatory parts first */
ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id);
ok &= setRawUInt32(data, tlvsize, &offset, chunk_number);
ok &= setRawUInt32(data, tlvsize, &offset, check_sum.fourbytes[0]);
ok &= setRawUInt32(data, tlvsize, &offset, check_sum.fourbytes[1]);
ok &= setRawUInt32(data, tlvsize, &offset, check_sum.fourbytes[2]);
ok &= setRawUInt32(data, tlvsize, &offset, check_sum.fourbytes[3]);
ok &= setRawUInt32(data, tlvsize, &offset, check_sum.fourbytes[4]);
if (offset != tlvsize)
{
ok = false;
std::cerr << "RsFileConfigSerialiser::serialiseTransfer() Size Error! " << std::endl;
}
return ok;
}
RsTurtleFileMapItem::RsTurtleFileMapItem(void *data,uint32_t pktsize)
: RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_MAP)
{
setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_MAP) ;
#ifdef P3TURTLE_DEBUG
std::cerr << " type = file map item" << std::endl ;
#endif
uint32_t offset = 8; // skip the header
/* add mandatory parts first */
bool ok = true ;
uint32_t s,d ;
ok &= getRawUInt32(data, pktsize, &offset, &tunnel_id);
ok &= getRawUInt32(data, pktsize, &offset, &d);
direction = d ;
ok &= getRawUInt32(data, pktsize, &offset, &s) ;
compressed_map._map.resize(s) ;
for(uint32_t i=0;i<s && ok;++i)
ok &= getRawUInt32(data, pktsize, &offset, &(compressed_map._map[i])) ;
#ifdef WINDOWS_SYS // No Exceptions in Windows compile. (drbobs).
#else
if (offset != pktsize)
throw std::runtime_error("Size error while deserializing.") ;
if (!ok)
throw std::runtime_error("Unknown error while deserializing.") ;
#endif
}
RsTurtleFileMapRequestItem::RsTurtleFileMapRequestItem(void *data,uint32_t pktsize)
: RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST)
{
setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_MAP_REQUEST) ;
#ifdef P3TURTLE_DEBUG
std::cerr << " type = file map request item" << std::endl ;
#endif
uint32_t offset = 8; // skip the header
/* add mandatory parts first */
bool ok = true ;
ok &= getRawUInt32(data, pktsize, &offset, &tunnel_id);
ok &= getRawUInt32(data, pktsize, &offset, &direction);
#ifdef WINDOWS_SYS // No Exceptions in Windows compile. (drbobs).
#else
if (offset != pktsize)
throw std::runtime_error("Size error while deserializing.") ;
if (!ok)
throw std::runtime_error("Unknown error while deserializing.") ;
#endif
}
RsTurtleFileCrcItem::RsTurtleFileCrcItem(void *data,uint32_t pktsize)
: RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_CRC)
{
setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_CRC) ;
#ifdef P3TURTLE_DEBUG
std::cerr << " type = file map item" << std::endl ;
#endif
uint32_t offset = 8; // skip the header
/* add mandatory parts first */
bool ok = true ;
uint32_t s1,s2 ;
ok &= getRawUInt32(data, pktsize, &offset, &tunnel_id);
ok &= getRawUInt32(data, pktsize, &offset, &s1) ;
ok &= getRawUInt32(data, pktsize, &offset, &s2) ;
crc_map._ccmap._map.resize(s1) ;
crc_map._crcs.resize(s2) ;
for(uint32_t i=0;i<s1 && ok;++i)
ok &= getRawUInt32(data, pktsize, &offset, &(crc_map._ccmap._map[i])) ;
for(uint32_t i=0;i<s2 && ok;++i)
ok &= getRawUInt32(data, pktsize, &offset, &(crc_map._crcs[i])) ;
#ifdef WINDOWS_SYS // No Exceptions in Windows compile. (drbobs).
#else
if (offset != pktsize)
throw std::runtime_error("Size error while deserializing.") ;
if (!ok)
throw std::runtime_error("Unknown error while deserializing.") ;
#endif
}
RsTurtleChunkCrcItem::RsTurtleChunkCrcItem(void *data,uint32_t pktsize)
: RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_CHUNK_CRC)
{
setPriorityLevel(QOS_PRIORITY_RS_TURTLE_CHUNK_CRC) ;
#ifdef P3TURTLE_DEBUG
std::cerr << " type = file map item" << std::endl ;
#endif
uint32_t offset = 8; // skip the header
/* add mandatory parts first */
bool ok = true ;
ok &= getRawUInt32(data, pktsize, &offset, &tunnel_id) ;
ok &= getRawUInt32(data, pktsize, &offset, &chunk_number) ;
ok &= getRawUInt32(data, pktsize, &offset, &check_sum.fourbytes[0]) ;
ok &= getRawUInt32(data, pktsize, &offset, &check_sum.fourbytes[1]) ;
ok &= getRawUInt32(data, pktsize, &offset, &check_sum.fourbytes[2]) ;
ok &= getRawUInt32(data, pktsize, &offset, &check_sum.fourbytes[3]) ;
ok &= getRawUInt32(data, pktsize, &offset, &check_sum.fourbytes[4]) ;
#ifdef WINDOWS_SYS // No Exceptions in Windows compile. (drbobs).
#else
if (offset != pktsize)
throw std::runtime_error("Size error while deserializing.") ;
if (!ok)
throw std::runtime_error("Unknown error while deserializing.") ;
#endif
}
RsTurtleFileCrcRequestItem::RsTurtleFileCrcRequestItem(void *data,uint32_t pktsize)
: RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST)
{
setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_CRC_REQUEST) ;
#ifdef P3TURTLE_DEBUG
std::cerr << " type = file map request item" << std::endl ;
#endif
uint32_t offset = 8; // skip the header
/* add mandatory parts first */
bool ok = true ;
ok &= getRawUInt32(data, pktsize, &offset, &tunnel_id);
#ifdef WINDOWS_SYS // No Exceptions in Windows compile. (drbobs).
#else
if (offset != pktsize)
throw std::runtime_error("Size error while deserializing.") ;
if (!ok)
throw std::runtime_error("Unknown error while deserializing.") ;
#endif
}
RsTurtleChunkCrcRequestItem::RsTurtleChunkCrcRequestItem(void *data,uint32_t pktsize)
: RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST)
{
setPriorityLevel(QOS_PRIORITY_RS_TURTLE_CHUNK_CRC_REQUEST) ;
#ifdef P3TURTLE_DEBUG
std::cerr << " type = file map item" << std::endl ;
#endif
uint32_t offset = 8; // skip the header
/* add mandatory parts first */
bool ok = true ;
ok &= getRawUInt32(data, pktsize, &offset, &tunnel_id) ;
ok &= getRawUInt32(data, pktsize, &offset, &chunk_number) ;
#ifdef WINDOWS_SYS // No Exceptions in Windows compile. (drbobs).
#else
if (offset != pktsize)
throw std::runtime_error("Size error while deserializing.") ;
if (!ok)
throw std::runtime_error("Unknown error while deserializing.") ;
#endif
}
bool RsTurtleFileRequestItem::serialize(void *data,uint32_t& pktsize)
{
uint32_t tlvsize = serial_size();
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize);
/* skip the header */
offset += 8;
/* add mandatory parts first */
ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id) ;
ok &= setRawUInt64(data, tlvsize, &offset, chunk_offset);
ok &= setRawUInt32(data, tlvsize, &offset, chunk_size);
if (offset != tlvsize)
{
ok = false;
#ifdef RSSERIAL_DEBUG
std::cerr << "RsTurtleTunnelOkItem::serialiseTransfer() Size Error! " << std::endl;
#endif
}
return ok;
}
RsTurtleFileRequestItem::RsTurtleFileRequestItem(void *data,uint32_t pktsize)
: RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_REQUEST)
{
setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_REQUEST) ;
#ifdef P3TURTLE_DEBUG
std::cerr << " type = file request" << std::endl ;
#endif
uint32_t offset = 8; // skip the header
uint32_t rssize = getRsItemSize(data);
/* add mandatory parts first */
bool ok = true ;
ok &= getRawUInt32(data, pktsize, &offset, &tunnel_id) ;
ok &= getRawUInt64(data, pktsize, &offset, &chunk_offset);
ok &= getRawUInt32(data, pktsize, &offset, &chunk_size);
#ifdef P3TURTLE_DEBUG
std::cerr << " tunnel_id=" << (void*)tunnel_id << ", chunk_offset=" << chunk_offset << ", chunk_size=" << chunk_size << std::endl ;
#endif
#ifdef WINDOWS_SYS // No Exceptions in Windows compile. (drbobs).
UNREFERENCED_LOCAL_VARIABLE(rssize);
#else
if (offset != rssize)
throw std::runtime_error("RsTurtleTunnelOkItem::() error while deserializing.") ;
if (!ok)
throw std::runtime_error("RsTurtleTunnelOkItem::() unknown error while deserializing.") ;
#endif
}
RsTurtleFileDataItem::~RsTurtleFileDataItem()
{
free(chunk_data) ;
}
RsTurtleFileDataItem::RsTurtleFileDataItem(void *data,uint32_t pktsize)
: RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_DATA)
{
setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_DATA) ;
#ifdef P3TURTLE_DEBUG
std::cerr << " type = file request" << std::endl ;
#endif
uint32_t offset = 8; // skip the header
uint32_t rssize = getRsItemSize(data);
/* add mandatory parts first */
bool ok = true ;
ok &= getRawUInt32(data, pktsize, &offset, &tunnel_id) ;
ok &= getRawUInt64(data, pktsize, &offset, &chunk_offset);
ok &= getRawUInt32(data, pktsize, &offset, &chunk_size);
chunk_data = (void*)malloc(chunk_size) ;
memcpy(chunk_data,(void*)((unsigned char*)data+offset),chunk_size) ;
offset += chunk_size ;
#ifdef P3TURTLE_DEBUG
std::cerr << " tunnel_id=" << (void*)tunnel_id << ", chunk_offset=" << chunk_offset << ", chunk_size=" << chunk_size << std::endl ;
#endif
#ifdef WINDOWS_SYS // No Exceptions in Windows compile. (drbobs).
UNREFERENCED_LOCAL_VARIABLE(rssize);
#else
if (offset != rssize)
throw std::runtime_error("RsTurtleFileDataItem::() error while deserializing.") ;
if (!ok)
throw std::runtime_error("RsTurtleFileDataItem::() unknown error while deserializing.") ;
#endif
}
bool RsTurtleFileDataItem::serialize(void *data,uint32_t& pktsize)
{
uint32_t tlvsize = serial_size();
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize);
/* skip the header */
offset += 8;
/* add mandatory parts first */
ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id) ;
ok &= setRawUInt64(data, tlvsize, &offset, chunk_offset);
ok &= setRawUInt32(data, tlvsize, &offset, chunk_size);
memcpy((void*)((unsigned char*)data+offset),chunk_data,chunk_size) ;
offset += chunk_size ;
if (offset != tlvsize)
{
ok = false;
#ifdef RSSERIAL_DEBUG
std::cerr << "RsTurtleTunnelOkItem::serialiseTransfer() Size Error! " << std::endl;
#endif
}
return ok;
}
std::ostream& RsTurtleFileRequestItem::print(std::ostream& o, uint16_t)
{
o << "File request item:" << std::endl ;
o << " tunnel id : " << std::hex << tunnel_id << std::dec << std::endl ;
o << " offset : " << chunk_offset << std::endl ;
o << " chunk size: " << chunk_size << std::endl ;
return o ;
}
std::ostream& RsTurtleFileDataItem::print(std::ostream& o, uint16_t)
{
o << "File request item:" << std::endl ;
o << " tunnel id : " << std::hex << tunnel_id << std::dec << std::endl ;
o << " offset : " << chunk_offset << std::endl ;
o << " chunk size: " << chunk_size << std::endl ;
o << " data : " << std::hex << chunk_data << std::dec << std::endl ;
return o ;
}
std::ostream& RsTurtleFileMapItem::print(std::ostream& o, uint16_t)
{
o << "File map item:" << std::endl ;
o << " tunnel id : " << std::hex << tunnel_id << std::dec << std::endl ;
o << " direction : " << direction << std::endl ;
o << " map : " ;
for(uint32_t i=0;i<compressed_map._map.size();++i)
o << std::hex << compressed_map._map[i] << std::dec << std::endl ;
return o ;
}
std::ostream& RsTurtleFileMapRequestItem::print(std::ostream& o, uint16_t)
{
o << "File map request item:" << std::endl ;
o << " tunnel id : " << std::hex << tunnel_id << std::dec << std::endl ;
o << " direction : " << direction << std::endl ;
return o ;
}
std::ostream& RsTurtleFileCrcItem::print(std::ostream& o, uint16_t)
{
o << "File CRC item:" << std::endl ;
o << " tunnel id : " << std::hex << tunnel_id << std::dec << std::endl ;
o << " map : " ;
for(uint32_t i=0;i<crc_map._ccmap._map.size();++i)
o << std::hex << crc_map._ccmap._map[i] << std::endl ;
o << " CRC : " ;
for(uint32_t i=0;i<crc_map._crcs.size();++i)
o << std::hex << crc_map._crcs[i] << std::dec << std::endl ;
return o ;
}
std::ostream& RsTurtleFileCrcRequestItem::print(std::ostream& o, uint16_t)
{
o << "File CRC request item:" << std::endl ;
o << " tunnel id : " << std::hex << tunnel_id << std::dec << std::endl ;
return o ;
}
std::ostream& RsTurtleChunkCrcRequestItem::print(std::ostream& o, uint16_t)
{
o << "Chunk CRC request item:" << std::endl ;
o << " tunnel id : " << std::hex << tunnel_id << std::dec << std::endl ;
o << " chunk num : " << chunk_number << std::endl ;
return o ;
}
std::ostream& RsTurtleChunkCrcItem::print(std::ostream& o, uint16_t)
{
o << "Chunk CRC request item:" << std::endl ;
o << " tunnel id : " << std::hex << tunnel_id << std::dec << std::endl ;
o << " chunk num : " << chunk_number << std::endl ;
o << " sha1 sum : " << check_sum.toStdString() << std::endl ;
return o ;
}

View File

@ -0,0 +1,168 @@
/*
* libretroshare/src/services: ftturtlefiletransferitem.h
*
* Services for RetroShare.
*
* Copyright 2013 by Cyril Soler
*
* 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 "csoler@users.sourceforge.net".
*
*/
#include <stdint.h>
#include <turtle/rsturtleitem.h>
/***********************************************************************************/
/* Turtle File Transfer item classes */
/***********************************************************************************/
class RsTurtleFileRequestItem: public RsTurtleGenericTunnelItem
{
public:
RsTurtleFileRequestItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_REQUEST) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_REQUEST);}
RsTurtleFileRequestItem(void *data,uint32_t size) ; // deserialization
virtual bool shouldStampTunnel() const { return false ; }
virtual Direction travelingDirection() const { return DIRECTION_SERVER ; }
uint64_t chunk_offset ;
uint32_t chunk_size ;
virtual std::ostream& print(std::ostream& o, uint16_t) ;
protected:
virtual bool serialize(void *data,uint32_t& size) ;
virtual uint32_t serial_size() ;
};
class RsTurtleFileDataItem: public RsTurtleGenericTunnelItem
{
public:
RsTurtleFileDataItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_DATA) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_DATA) ;}
~RsTurtleFileDataItem() ;
RsTurtleFileDataItem(void *data,uint32_t size) ; // deserialization
virtual bool shouldStampTunnel() const { return true ; }
virtual Direction travelingDirection() const { return DIRECTION_CLIENT ; }
uint64_t chunk_offset ; // offset in the file
uint32_t chunk_size ; // size of the file chunk
void *chunk_data ; // actual data.
virtual std::ostream& print(std::ostream& o, uint16_t) ;
virtual bool serialize(void *data,uint32_t& size) ;
virtual uint32_t serial_size() ;
};
class RsTurtleFileMapRequestItem: public RsTurtleGenericTunnelItem
{
public:
RsTurtleFileMapRequestItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_MAP_REQUEST) ;}
RsTurtleFileMapRequestItem(void *data,uint32_t size) ; // deserialization
virtual bool shouldStampTunnel() const { return false ; }
virtual std::ostream& print(std::ostream& o, uint16_t) ;
virtual bool serialize(void *data,uint32_t& size) ;
virtual uint32_t serial_size() ;
};
class RsTurtleFileMapItem: public RsTurtleGenericTunnelItem
{
public:
RsTurtleFileMapItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_MAP) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_MAP) ;}
RsTurtleFileMapItem(void *data,uint32_t size) ; // deserialization
virtual bool shouldStampTunnel() const { return false ; }
CompressedChunkMap compressed_map ; // Map info for the file in compressed format. Each *bit* in the array uint's says "I have" or "I don't have"
// by default, we suppose the peer has all the chunks. This info will thus be and-ed
// with the default file map for this source.
virtual std::ostream& print(std::ostream& o, uint16_t) ;
virtual bool serialize(void *data,uint32_t& size) ;
virtual uint32_t serial_size() ;
};
class RsTurtleFileCrcRequestItem: public RsTurtleGenericTunnelItem
{
public:
RsTurtleFileCrcRequestItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST) { setPriorityLevel(QOS_PRIORITY_RS_FILE_CRC_REQUEST);}
RsTurtleFileCrcRequestItem(void *data,uint32_t size) ; // deserialization
virtual bool shouldStampTunnel() const { return false ; }
virtual Direction travelingDirection() const { return DIRECTION_SERVER ; }
virtual std::ostream& print(std::ostream& o, uint16_t) ;
virtual bool serialize(void *data,uint32_t& size) ;
virtual uint32_t serial_size() ;
};
class RsTurtleChunkCrcRequestItem: public RsTurtleGenericTunnelItem
{
public:
RsTurtleChunkCrcRequestItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST) { setPriorityLevel(QOS_PRIORITY_RS_CHUNK_CRC_REQUEST);}
RsTurtleChunkCrcRequestItem(void *data,uint32_t size) ; // deserialization
virtual bool shouldStampTunnel() const { return false ; }
virtual Direction travelingDirection() const { return DIRECTION_SERVER ; }
uint32_t chunk_number ; // id of the chunk to CRC.
virtual std::ostream& print(std::ostream& o, uint16_t) ;
virtual bool serialize(void *data,uint32_t& size) ;
virtual uint32_t serial_size() ;
};
class RsTurtleFileCrcItem: public RsTurtleGenericTunnelItem
{
public:
RsTurtleFileCrcItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_CRC) { setPriorityLevel(QOS_PRIORITY_RS_FILE_CRC);}
RsTurtleFileCrcItem(void *data,uint32_t size) ; // deserialization
virtual bool shouldStampTunnel() const { return true ; }
virtual Direction travelingDirection() const { return DIRECTION_CLIENT ; }
CRC32Map crc_map ;// Map info for the file in compressed format. Each *bit* in the array uint's says "I have" or "I don't have"
// by default, we suppose the peer has all the chunks. This info will thus be and-ed
// with the default file map for this source.
virtual std::ostream& print(std::ostream& o, uint16_t) ;
virtual bool serialize(void *data,uint32_t& size) ;
virtual uint32_t serial_size() ;
};
class RsTurtleChunkCrcItem: public RsTurtleGenericTunnelItem
{
public:
RsTurtleChunkCrcItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_CHUNK_CRC) { setPriorityLevel(QOS_PRIORITY_RS_CHUNK_CRC);}
RsTurtleChunkCrcItem(void *data,uint32_t size) ; // deserialization
virtual bool shouldStampTunnel() const { return true ; }
virtual Direction travelingDirection() const { return DIRECTION_CLIENT ; }
uint32_t chunk_number ;
Sha1CheckSum check_sum ;
virtual std::ostream& print(std::ostream& o, uint16_t) ;
virtual bool serialize(void *data,uint32_t& size) ;
virtual uint32_t serial_size() ;
};

View File

@ -306,12 +306,14 @@ HEADERS += ft/ftchunkmap.h \
ft/ftfilesearch.h \
ft/ftsearch.h \
ft/ftserver.h \
ft/fttransfermodule.h
ft/fttransfermodule.h \
ft/ftturtlefiletransferitem.h
HEADERS += pqi/authssl.h \
pqi/authgpg.h \
pgp/pgphandler.h \
pgp/pgpkeyutil.h \
pgp/rsaes.h \
pgp/rscertificate.h \
pqi/p3cfgmgr.h \
pqi/p3peermgr.h \
@ -446,6 +448,7 @@ SOURCES += ft/ftchunkmap.cc \
ft/ftfilesearch.cc \
ft/ftserver.cc \
ft/fttransfermodule.cc \
ft/ftturtlefiletransferitem.cc
SOURCES += pqi/authgpg.cc \
pqi/authssl.cc \
@ -565,6 +568,7 @@ SOURCES += util/folderiterator.cc \
util/rsthreads.cc \
util/rsversion.cc \
util/rswin.cc \
util/rsaes.cc \
util/rsrandom.cc \
util/rstickevent.cc \

View File

@ -943,7 +943,37 @@ bool PGPHandler::addOrMergeKey(ops_keyring_t *keyring,std::map<std::string,PGPCe
return ret ;
}
// bool PGPHandler::encryptTextToString(const PGPIdType& key_id,const std::string& text,std::string& outstring)
// {
// RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures.
//
// const ops_keydata_t *public_key = getPublicKey(key_id) ;
//
// if(public_key == NULL)
// {
// std::cerr << "Cannot get public key of id " << key_id.toStdString() << std::endl;
// return false ;
// }
//
// if(public_key->type != OPS_PTAG_CT_PUBLIC_KEY)
// {
// std::cerr << "PGPHandler::encryptTextToFile(): ERROR: supplied id did not return a public key!" << std::endl;
// return false ;
// }
//
// ops_create_info_t *info;
// ops_memory_t *buf = NULL ;
// ops_setup_memory_write(&info, &buf, 0);
//
// ops_encrypt_stream(info, public_key, NULL, ops_false, ops_true);
// ops_write(text.c_str(), text.length(), info);
// ops_writer_close(info);
//
// outstring = std::string((char *)ops_memory_get_data(buf),ops_memory_get_length(buf)) ;
// ops_create_info_delete(info);
//
// return true ;
// }
bool PGPHandler::encryptTextToFile(const PGPIdType& key_id,const std::string& text,const std::string& outfile)
{
RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures.
@ -978,6 +1008,73 @@ bool PGPHandler::encryptTextToFile(const PGPIdType& key_id,const std::string& te
return true ;
}
bool PGPHandler::encryptDataBin(const PGPIdType& key_id,const void *data, const uint32_t len, unsigned char *encrypted_data, unsigned int *encrypted_data_len)
{
RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures.
const ops_keydata_t *public_key = locked_getPublicKey(key_id,true) ;
if(public_key == NULL)
{
std::cerr << "Cannot get public key of id " << key_id.toStdString() << std::endl;
return false ;
}
if(public_key->type != OPS_PTAG_CT_PUBLIC_KEY)
{
std::cerr << "PGPHandler::encryptTextToFile(): ERROR: supplied id did not return a public key!" << std::endl;
return false ;
}
ops_create_info_t *info;
ops_memory_t *buf = NULL ;
ops_setup_memory_write(&info, &buf, 0);
ops_encrypt_stream(info, public_key, NULL, ops_false, ops_false);
ops_write(data,len,info);
ops_writer_close(info);
ops_create_info_delete(info);
int tlen = ops_memory_get_length(buf) ;
bool res ;
if( (int)*encrypted_data_len >= tlen)
{
memcpy(encrypted_data,ops_memory_get_data(buf),tlen) ;
*encrypted_data_len = tlen ;
res = true ;
}
else
{
std::cerr << "Not enough room to fit encrypted data. Size given=" << *encrypted_data_len << ", required=" << tlen << std::endl;
res = false ;
}
ops_memory_release(buf) ;
free(buf) ;
return res ;
}
bool PGPHandler::decryptDataBin(const PGPIdType& key_id,const void *encrypted_data, const uint32_t encrypted_len, unsigned char *data, unsigned int *data_len)
{
int out_length ;
unsigned char *out ;
ops_boolean_t res = ops_decrypt_memory((const unsigned char *)encrypted_data,encrypted_len,&out,&out_length,_secring,ops_false,cb_get_passphrase) ;
if(*data_len < out_length)
{
std::cerr << "Not enough room to store decrypted data! Please give more."<< std::endl;
return false ;
}
*data_len = out_length ;
memcpy(data,out,out_length) ;
free(out) ;
return (bool)res ;
}
bool PGPHandler::decryptTextFromFile(const PGPIdType&,std::string& text,const std::string& inputfile)
{
RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures.
@ -1054,10 +1151,21 @@ bool PGPHandler::SignDataBin(const PGPIdType& id,const void *data, const uint32_
if(!memres)
return false ;
uint32_t tlen = std::min(*signlen,(uint32_t)ops_memory_get_length(memres)) ;
bool res ;
uint32_t slen = (uint32_t)ops_memory_get_length(memres);
memcpy(sign,ops_memory_get_data(memres),tlen) ;
*signlen = tlen ;
if(*signlen >= slen)
{
*signlen = slen ;
memcpy(sign,ops_memory_get_data(memres),*signlen) ;
res = true ;
}
else
{
std::cerr << "(EE) memory chunk is not large enough for signature packet. Requred size: " << slen << " bytes." << std::endl;
res = false ;
}
ops_memory_release(memres) ;
free(memres) ;
@ -1073,7 +1181,7 @@ bool PGPHandler::SignDataBin(const PGPIdType& id,const void *data, const uint32_
hexdump( (unsigned char *)sign,*signlen) ;
std::cerr << std::endl;
#endif
return true ;
return res ;
}
bool PGPHandler::privateSignCertificate(const PGPIdType& ownId,const PGPIdType& id_of_key_to_sign)

View File

@ -94,8 +94,15 @@ class PGPHandler
bool VerifySignBin(const void *data, uint32_t data_len, unsigned char *sign, unsigned int sign_len, const PGPFingerprintType& withfingerprint) ;
bool privateSignCertificate(const PGPIdType& own_id,const PGPIdType& id_of_key_to_sign) ;
// The client should supply a memory chunk to store the data. The length will be updated to the real length of the data.
//
bool encryptDataBin(const PGPIdType& key_id,const void *data, const uint32_t len, unsigned char *encrypted_data, unsigned int *encrypted_data_len) ;
bool decryptDataBin(const PGPIdType& key_id,const void *data, const uint32_t len, unsigned char *decrypted_data, unsigned int *decrypted_data_len) ;
bool encryptTextToFile(const PGPIdType& key_id,const std::string& text,const std::string& outfile) ;
bool decryptTextFromFile(const PGPIdType& key_id,std::string& text,const std::string& inputfile) ;
bool decryptTextFromFile(const PGPIdType& key_id,std::string& text,const std::string& encrypted_inputfile) ;
//bool encryptTextToString(const PGPIdType& key_id,const std::string& text,std::string& outstring) ;
//bool decryptTextFromString(const PGPIdType& key_id,const std::string& encrypted_text,std::string& outstring) ;
bool getKeyFingerprint(const PGPIdType& id,PGPFingerprintType& fp) const ;
void setAcceptConnexion(const PGPIdType&,bool) ;

View File

@ -70,11 +70,21 @@ bool AuthGPG::removeKeysFromPGPKeyring(const std::list<std::string>& pgp_ids,std
return PGPHandler::removeKeysFromPGPKeyring(pids,backup_file,error_code) ;
}
// bool AuthGPG::decryptTextFromString(std::string& encrypted_text,std::string& output)
// {
// return PGPHandler::decryptTextFromString(mOwnGpgId,encrypted_text,output) ;
// }
bool AuthGPG::encryptTextToFile(const std::string& text,const std::string& outfile)
{
return PGPHandler::encryptTextToFile(mOwnGpgId,text,outfile) ;
}
// bool AuthGPG::encryptTextToString(const std::string& pgp_id,const std::string& text,std::string& outstr)
// {
// return PGPHandler::encryptTextToString(PGPIdType(pgp_id),text,outstr) ;
// }
std::string pgp_pwd_callback(void * /*hook*/, const char *uid_hint, const char * /*passphrase_info*/, int prev_was_bad)
{
#define GPG_DEBUG2
@ -640,6 +650,15 @@ bool AuthGPG::TrustCertificate(const std::string &id, int trustlvl)
return privateTrustCertificate(id, trustlvl) ;
}
bool AuthGPG::encryptDataBin(const std::string& pgp_id,const void *data, unsigned int datalen, unsigned char *sign, unsigned int *signlen)
{
return PGPHandler::encryptDataBin(PGPIdType(pgp_id),data,datalen,sign,signlen) ;
}
bool AuthGPG::decryptDataBin(const void *data, unsigned int datalen, unsigned char *sign, unsigned int *signlen)
{
return PGPHandler::decryptDataBin(mOwnGpgId,data,datalen,sign,signlen) ;
}
bool AuthGPG::SignDataBin(const void *data, unsigned int datalen, unsigned char *sign, unsigned int *signlen)
{
return DoOwnSignature(data, datalen, sign, signlen);

View File

@ -217,9 +217,15 @@ class AuthGPG: public p3Config, public RsThread, public PGPHandler
virtual bool SignDataBin(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen);
virtual bool VerifySignBin(const void*, uint32_t, unsigned char*, unsigned int, const std::string &withfingerprint);
virtual bool encryptDataBin(const std::string& pgp_id,const void *data, const uint32_t len, unsigned char *encr, unsigned int *encrlen);
virtual bool decryptDataBin(const void *data, const uint32_t len, unsigned char *decr, unsigned int *decrlen);
virtual bool decryptTextFromFile( std::string& text,const std::string& filename);
virtual bool encryptTextToFile (const std::string& text,const std::string& filename);
// virtual bool decryptTextFromString( std::string& encrypted_text,std::string& clear_string);
// virtual bool encryptTextToString (const std::string& pgp_id,const std::string& clear_text,std::string& encrypted_string);
bool getGPGFilteredList(std::list<std::string>& list,bool (*filter)(const PGPCertificateInfo&) = NULL) ;
//END of PGP public functions

View File

@ -58,6 +58,7 @@
#define RS_MSG_USER_REQUEST 0x0400 /* user request */
#define RS_MSG_FRIEND_RECOMMENDATION 0x0800 /* friend recommendation */
#define RS_MSG_SYSTEM (RS_MSG_USER_REQUEST | RS_MSG_FRIEND_RECOMMENDATION)
#define RS_MSG_ENCRYPTED 0x1000 /* message is encrypted */
#define RS_CHAT_LOBBY_EVENT_PEER_LEFT 0x01
#define RS_CHAT_LOBBY_EVENT_PEER_STATUS 0x02
@ -99,6 +100,7 @@ class MessageInfo
std::wstring attach_title;
std::wstring attach_comment;
std::list<FileInfo> files;
std::map<std::string,std::string> encryption_keys ; // for concerned ids only the public pgp key id to encrypt the message with.
int size; /* total of files */
int count; /* file count */
@ -144,6 +146,16 @@ public:
#define RS_CHAT_PRIVATE 0x0002
#define RS_CHAT_AVATAR_AVAILABLE 0x0004
#define RS_DISTANT_CHAT_STATUS_UNKNOWN 0x0000
#define RS_DISTANT_CHAT_STATUS_TUNNEL_DN 0x0001
#define RS_DISTANT_CHAT_STATUS_TUNNEL_OK 0x0002
#define RS_DISTANT_CHAT_STATUS_CAN_TALK 0x0003
#define RS_DISTANT_CHAT_ERROR_NO_ERROR 0x0000
#define RS_DISTANT_CHAT_ERROR_DECRYPTION_FAILED 0x0001
#define RS_DISTANT_CHAT_ERROR_SIGNATURE_MISMATCH 0x0002
#define RS_DISTANT_CHAT_ERROR_UNKNOWN_KEY 0x0003
class ChatInfo
{
public:
@ -195,6 +207,14 @@ class ChatLobbyInfo
time_t last_activity ; // last recorded activity. Useful for removing dead lobbies.
};
struct DistantChatInviteInfo
{
std::string hash ; // hash to contact the invite and refer to it.
std::string encrypted_radix64_string ; // encrypted radix string used to for the chat link
std::string destination_pgp_id ; // pgp is of the destination of the chat link
time_t time_of_validity ; // time when te invite becomes unusable
};
std::ostream &operator<<(std::ostream &out, const MessageInfo &info);
std::ostream &operator<<(std::ostream &out, const ChatInfo &info);
@ -203,6 +223,14 @@ bool operator==(const ChatInfo&, const ChatInfo&);
class RsMsgs;
extern RsMsgs *rsMsgs;
struct DistantOfflineMessengingInvite
{
std::string issuer_pgp_id ;
std::string hash ;
time_t time_of_validity ;
};
class RsMsgs
{
public:
@ -211,11 +239,13 @@ class RsMsgs
virtual ~RsMsgs() { return; }
/****************************************/
/* Message Items */
/* Message Items */
/****************************************/
virtual bool getMessageSummaries(std::list<MsgInfoSummary> &msgList) = 0;
virtual bool getMessage(const std::string &mId, MessageInfo &msg) = 0;
virtual void getMessageCount(unsigned int *pnInbox, unsigned int *pnInboxNew, unsigned int *pnOutbox, unsigned int *pnDraftbox, unsigned int *pnSentbox, unsigned int *pnTrashbox) = 0;
virtual bool decryptMessage(const std::string& mId) = 0 ;
virtual bool MessageSend(MessageInfo &info) = 0;
virtual bool SystemMessage(const std::wstring &title, const std::wstring &message, uint32_t systemFlag) = 0;
@ -241,8 +271,14 @@ virtual bool setMessageTag(const std::string &msgId, uint32_t tagId, bool set) =
virtual bool resetMessageStandardTagTypes(MsgTagType& tags) = 0;
/* private distant messages */
virtual bool createDistantOfflineMessengingInvite(time_t validity_time_stamp, std::string& hash)=0 ;
virtual bool getDistantOfflineMessengingInvites(std::vector<DistantOfflineMessengingInvite>& invites) = 0 ;
/****************************************/
/* Chat */
/****************************************/
/* Chat */
virtual bool sendPublicChat(const std::wstring& msg) = 0;
virtual bool sendPrivateChat(const std::string& id, const std::wstring& msg) = 0;
virtual int getPublicChatQueueCount() = 0;
@ -265,6 +301,10 @@ virtual void getAvatarData(const std::string& pid,unsigned char *& data,int& siz
virtual void setOwnAvatarData(const unsigned char *data,int size) = 0 ;
virtual void getOwnAvatarData(unsigned char *& data,int& size) = 0 ;
/****************************************/
/* Chat lobbies */
/****************************************/
virtual bool joinVisibleChatLobby(const ChatLobbyId& lobby_id) = 0 ;
virtual bool isLobbyId(const std::string& virtual_peer_id,ChatLobbyId& lobby_id) = 0;
virtual bool getVirtualPeerId(const ChatLobbyId& lobby_id,std::string& vpid) = 0;
@ -282,6 +322,13 @@ virtual bool getDefaultNickNameForChatLobby(std::string& nick) = 0 ;
virtual ChatLobbyId createChatLobby(const std::string& lobby_name,const std::string& lobby_topic,const std::list<std::string>& invited_friends,uint32_t lobby_privacy_type) = 0 ;
/****************************************/
/* Distant chat */
/****************************************/
virtual bool createDistantChatInvite(const std::string& pgp_id,time_t time_of_validity,std::string& encrypted_string) = 0 ;
virtual bool getDistantChatInviteList(std::vector<DistantChatInviteInfo>& invites) = 0;
virtual bool initiateDistantChatConnexion(const std::string& encrypted_string,std::string& hash,uint32_t& error_code) = 0;
virtual bool getDistantChatStatus(const std::string& hash,uint32_t& status,std::string& pgp_id) = 0;
};

View File

@ -34,6 +34,7 @@
#include <vector>
class LinearizedExpression ;
class RsTurtleClientService ;
class RsTurtle;
extern RsTurtle *rsTurtle ;
@ -83,8 +84,6 @@ class TurtleTrafficStatisticsInfo
class RsTurtle
{
public:
enum FileSharingStrategy { SHARE_ENTIRE_NETWORK, SHARE_FRIENDS_ONLY } ;
RsTurtle() {}
virtual ~RsTurtle() {}
@ -103,23 +102,27 @@ class RsTurtle
virtual TurtleRequestId turtleSearch(const std::string& match_string) = 0 ;
virtual TurtleRequestId turtleSearch(const LinearizedExpression& expr) = 0 ;
// Sets the file sharing strategy. It concerns all local files. It would
// be better to handle this for each file, of course.
void setFileSharingStrategy(FileSharingStrategy f) { _sharing_strategy = f ; }
// Initiates tunnel handling for the given file hash. tunnels. Launches
// an exception if an error occurs during the initialization process. The
// turtle router itself does not initiate downloads, it only maintains
// tunnels for the given hash. The download should be driven by the file
// transfer module by calling ftServer::FileRequest().
//
virtual void monitorFileTunnels(const std::string& name,const std::string& file_hash,uint64_t size) = 0 ;
virtual void monitorTunnels(const std::string& file_hash,RsTurtleClientService *client_service) = 0 ;
// Tells the turtle router to stop handling tunnels for the given file hash. Traditionally this should
// be called after calling ftServer::fileCancel().
//
virtual void stopMonitoringFileTunnels(const std::string& file_hash) = 0 ;
virtual void stopMonitoringTunnels(const std::string& file_hash) = 0 ;
/// Adds a client tunnel service. This means that the service will be added
/// to the list of services that might respond to tunnel requests.
/// Example tunnel services include:
///
/// p3ChatService: tunnels correspond to private distant chatting
/// ftServer : tunnels correspond to file data transfer
///
virtual void registerTunnelService(RsTurtleClientService *service) = 0;
// Get info from the turtle router. I use std strings to hide the internal structs.
//
@ -136,8 +139,6 @@ class RsTurtle
// Hardcore handles
virtual void setMaxTRForwardRate(int max_tr_up_rate) = 0 ;
virtual int getMaxTRForwardRate() const = 0 ;
protected:
FileSharingStrategy _sharing_strategy ;
};
#endif

View File

@ -96,6 +96,20 @@ bool p3Msgs::MessageSend(MessageInfo &info)
return mMsgSrv->MessageSend(info);
}
bool p3Msgs::decryptMessage(const std::string& mId)
{
return mMsgSrv->decryptMessage(mId);
}
bool p3Msgs::createDistantOfflineMessengingInvite(time_t ts, std::string& hash)
{
return mMsgSrv->createDistantOfflineMessengingInvite(ts,hash) ;
}
bool p3Msgs::getDistantOfflineMessengingInvites(std::vector<DistantOfflineMessengingInvite>& invites)
{
return mMsgSrv->getDistantOfflineMessengingInvites(invites);
}
bool p3Msgs::SystemMessage(const std::wstring &title, const std::wstring &message, uint32_t systemFlag)
{
return mMsgSrv->SystemMessage(title, message, systemFlag);
@ -330,5 +344,20 @@ void p3Msgs::getPendingChatLobbyInvites(std::list<ChatLobbyInvite>& invites)
{
mChatSrv->getPendingChatLobbyInvites(invites) ;
}
bool p3Msgs::createDistantChatInvite(const std::string& pgp_id,time_t time_of_validity,std::string& encrypted_string)
{
return mChatSrv->createDistantChatInvite(pgp_id,time_of_validity,encrypted_string) ;
}
bool p3Msgs::getDistantChatInviteList(std::vector<DistantChatInviteInfo>& invites)
{
return mChatSrv->getDistantChatInviteList(invites) ;
}
bool p3Msgs::initiateDistantChatConnexion(const std::string& encrypted_str,std::string& hash,uint32_t& error_code)
{
return mChatSrv->initiateDistantChatConnexion(encrypted_str,hash,error_code) ;
}
bool p3Msgs::getDistantChatStatus(const std::string& hash,uint32_t& status,std::string& pgp_id)
{
return mChatSrv->getDistantChatStatus(hash,status,pgp_id) ;
}

View File

@ -58,6 +58,7 @@ class p3Msgs: public RsMsgs
virtual void getMessageCount(unsigned int *pnInbox, unsigned int *pnInboxNew, unsigned int *pnOutbox, unsigned int *pnDraftbox, unsigned int *pnSentbox, unsigned int *pnTrashbox);
virtual bool MessageSend(MessageInfo &info);
virtual bool decryptMessage(const std::string& mid);
virtual bool SystemMessage(const std::wstring &title, const std::wstring &message, uint32_t systemFlag);
virtual bool MessageToDraft(MessageInfo &info, const std::string &msgParentId);
virtual bool MessageToTrash(const std::string &mid, bool bTrash);
@ -78,6 +79,9 @@ class p3Msgs: public RsMsgs
virtual bool resetMessageStandardTagTypes(MsgTagType& tags);
virtual bool createDistantOfflineMessengingInvite(time_t, std::string&) ;
virtual bool getDistantOfflineMessengingInvites(std::vector<DistantOfflineMessengingInvite>&);
/*!
* gets avatar from peer, image data in jpeg format
*/
@ -183,6 +187,11 @@ class p3Msgs: public RsMsgs
virtual bool getDefaultNickNameForChatLobby(std::string& nick) ;
virtual ChatLobbyId createChatLobby(const std::string& lobby_name,const std::string& lobby_topic,const std::list<std::string>& invited_friends,uint32_t privacy_type) ;
virtual bool createDistantChatInvite(const std::string& pgp_id,time_t time_of_validity,std::string& encrypted_string) ;
virtual bool getDistantChatInviteList(std::vector<DistantChatInviteInfo>& invites);
virtual bool initiateDistantChatConnexion(const std::string& encrypted_string,std::string& hash,uint32_t& error_code) ;
virtual bool getDistantChatStatus(const std::string& hash,uint32_t& status,std::string& pgp_id) ;
private:
p3MsgService *mMsgSrv;

View File

@ -2230,10 +2230,13 @@ int RsServer::StartupRetroShare()
mConnMgr->setP3tunnel(tn);
#endif
p3turtle *tr = new p3turtle(mLinkMgr,ftserver) ;
p3turtle *tr = new p3turtle(mLinkMgr) ;
rsTurtle = tr ;
pqih -> addService(tr);
ftserver->connectToTurtleRouter(tr) ;
chatSrv->connectToTurtleRouter(tr) ;
msgSrv->connectToTurtleRouter(tr) ;
pqih -> addService(ad);
pqih -> addService(msgSrv);

View File

@ -23,6 +23,10 @@
*
*/
#pragma once
#include <stdint.h>
// This file centralises QoS priorities for all transfer RsItems.
//
const uint8_t QOS_PRIORITY_UNKNOWN = 0 ;
@ -45,6 +49,7 @@ const uint8_t QOS_PRIORITY_RS_TURTLE_CHUNK_CRC = 5 ;
const uint8_t QOS_PRIORITY_RS_TURTLE_FILE_MAP = 3 ;
const uint8_t QOS_PRIORITY_RS_TURTLE_GENERIC_ITEM = 3 ;
const uint8_t QOS_PRIORITY_RS_TURTLE_FORWARD_FILE_DATA= 3 ;
const uint8_t QOS_PRIORITY_RS_TURTLE_GENERIC_DATA = 5 ;
// File transfer
//

View File

@ -188,6 +188,30 @@ std::ostream& RsPrivateChatMsgConfigItem::print(std::ostream &out, uint16_t inde
printRsItemEnd(out, "RsPrivateChatMsgConfigItem", indent);
return out;
}
std::ostream& RsPrivateChatDistantInviteConfigItem::print(std::ostream &out, uint16_t indent)
{
printRsItemBase(out, "RsPrivateChatDistantInviteConfigItem", indent);
uint16_t int_Indent = indent + 2;
printIndent(out, int_Indent);
out << "radix string: " << encrypted_radix64_string << std::endl;
printIndent(out, int_Indent);
out << "hash: " << hash << std::endl;
printIndent(out, int_Indent);
out << "destination pgp_id: " << destination_pgp_id << std::endl;
printIndent(out, int_Indent);
out << "time of validity: " << time_of_validity << std::endl;
printIndent(out, int_Indent);
out << "time of last hit: " << last_hit_time << std::endl;
printRsItemEnd(out, "RsPrivateChatDistantInviteConfigItem", indent);
return out;
}
std::ostream& RsChatStatusItem::print(std::ostream &out, uint16_t indent)
{
@ -195,7 +219,7 @@ std::ostream& RsChatStatusItem::print(std::ostream &out, uint16_t indent)
uint16_t int_Indent = indent + 2;
printIndent(out, int_Indent);
out << "Status string: " << status_string << std::endl;
out << "Flags : " << (void*)flags << std::endl;
out << "Flags : " << std::hex << flags << std::dec << std::endl;
printRsItemEnd(out, "RsChatStatusItem", indent);
return out;
@ -245,6 +269,7 @@ RsItem *RsChatSerialiser::deserialise(void *data, uint32_t *pktsize)
{
case RS_PKT_SUBTYPE_DEFAULT: return new RsChatMsgItem(data,*pktsize) ;
case RS_PKT_SUBTYPE_PRIVATECHATMSG_CONFIG: return new RsPrivateChatMsgConfigItem(data,*pktsize) ;
case RS_PKT_SUBTYPE_DISTANT_INVITE_CONFIG: return new RsPrivateChatDistantInviteConfigItem(data,*pktsize) ;
case RS_PKT_SUBTYPE_CHAT_STATUS: return new RsChatStatusItem(data,*pktsize) ;
case RS_PKT_SUBTYPE_CHAT_AVATAR: return new RsChatAvatarItem(data,*pktsize) ;
case RS_PKT_SUBTYPE_CHAT_LOBBY_MSG: return new RsChatLobbyMsgItem(data,*pktsize) ;
@ -387,7 +412,18 @@ uint32_t RsPrivateChatMsgConfigItem::serial_size()
return s;
}
uint32_t RsPrivateChatDistantInviteConfigItem::serial_size()
{
uint32_t s = 8; /* header */
s += GetTlvStringSize(hash);
s += GetTlvStringSize(encrypted_radix64_string);
s += GetTlvStringSize(destination_pgp_id);
s += 16; /* aes_key */
s += 4; /* time_of_validity */
s += 4; /* last_hit_time */
return s;
}
uint32_t RsChatStatusItem::serial_size()
{
uint32_t s = 8; /* header */
@ -780,7 +816,49 @@ bool RsPrivateChatMsgConfigItem::serialise(void *data, uint32_t& pktsize)
return ok;
}
bool RsPrivateChatDistantInviteConfigItem::serialise(void *data, uint32_t& pktsize)
{
uint32_t tlvsize = serial_size() ;
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data, tlvsize, PacketId(), tlvsize);
#ifdef CHAT_DEBUG
std::cerr << "RsChatSerialiser::serialiseItem() Header: " << ok << std::endl;
std::cerr << "RsChatSerialiser::serialiseItem() Size: " << tlvsize << std::endl;
#endif
/* skip the header */
offset += 8;
/* add mandatory parts first */
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_KEY, hash);
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_LINK, encrypted_radix64_string);
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GPGID, destination_pgp_id);
memcpy(&((unsigned char *)data)[offset],aes_key,16) ;
offset += 16 ;
ok &= setRawUInt32(data, tlvsize, &offset, time_of_validity);
ok &= setRawUInt32(data, tlvsize, &offset, last_hit_time);
if (offset != tlvsize)
{
ok = false;
#ifdef CHAT_DEBUG
std::cerr << "RsChatSerialiser::serialiseItem() Size Error! " << std::endl;
#endif
}
return ok;
}
bool RsChatStatusItem::serialise(void *data, uint32_t& pktsize)
{
uint32_t tlvsize = serial_size() ;
@ -1122,6 +1200,32 @@ RsPrivateChatMsgConfigItem::RsPrivateChatMsgConfigItem(void *data,uint32_t /*siz
ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_MSG, message);
ok &= getRawUInt32(data, rssize, &offset, &recvTime);
#ifdef CHAT_DEBUG
std::cerr << "Building new chat msg config item." << std::endl ;
#endif
if (offset != rssize)
std::cerr << "Size error while deserializing." << std::endl ;
if (!ok)
std::cerr << "Unknown error while deserializing." << std::endl ;
}
RsPrivateChatDistantInviteConfigItem::RsPrivateChatDistantInviteConfigItem(void *data,uint32_t /*size*/)
: RsChatItem(RS_PKT_SUBTYPE_DISTANT_INVITE_CONFIG)
{
uint32_t offset = 8; // skip the header
uint32_t rssize = getRsItemSize(data);
bool ok = true ;
/* get mandatory parts first */
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_KEY, hash);
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_LINK, encrypted_radix64_string);
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_GPGID, destination_pgp_id);
memcpy(aes_key,&((unsigned char*)data)[offset],16) ;
offset += 16 ;
ok &= getRawUInt32(data, rssize, &offset, &time_of_validity);
ok &= getRawUInt32(data, rssize, &offset, &last_hit_time);
#ifdef CHAT_DEBUG
std::cerr << "Building new chat msg config item." << std::endl ;
#endif
@ -1278,6 +1382,26 @@ void RsMsgTagType::clear()
}
void RsPublicMsgInviteConfigItem::clear()
{
hash.clear() ;
time_stamp = 0 ;
}
std::ostream& RsPublicMsgInviteConfigItem::print(std::ostream &out, uint16_t indent)
{
printRsItemBase(out, "RsPublicMsgInviteConfigItem", indent);
uint16_t int_Indent = indent + 2;
printIndent(out, int_Indent);
out << "hash : " << hash << std::endl;
printIndent(out, int_Indent);
out << "timt : " << time_stamp << std::endl;
printRsItemEnd(out, "RsPublicMsgInviteConfigItem", indent);
return out;
}
void RsMsgTags::clear()
{
msgId = 0;
@ -1476,7 +1600,15 @@ RsMsgItem *RsMsgSerialiser::deserialiseMsgItem(void *data, uint32_t *pktsize)
return item;
}
uint32_t RsMsgSerialiser::sizePublicMsgInviteConfigItem(RsPublicMsgInviteConfigItem* item)
{
uint32_t s = 8; /* header */
s += GetTlvStringSize(item->hash);
s += 4; /* time_stamp */
return s;
}
uint32_t RsMsgSerialiser::sizeTagItem(RsMsgTagType* item)
{
@ -1489,6 +1621,44 @@ uint32_t RsMsgSerialiser::sizeTagItem(RsMsgTagType* item)
return s;
}
bool RsMsgSerialiser::serialisePublicMsgInviteConfigItem(RsPublicMsgInviteConfigItem *item, void *data, uint32_t* pktsize)
{
uint32_t tlvsize = sizePublicMsgInviteConfigItem(item);
uint32_t offset = 0;
if (*pktsize < tlvsize)
return false; /* not enough space */
*pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize);
#ifdef RSSERIAL_DEBUG
std::cerr << "RsMsgSerialiser::serialiseMsgTagItem() Header: " << ok << std::endl;
std::cerr << "RsMsgSerialiser::serialiseMsgTagItem() Size: " << tlvsize << std::endl;
#endif
/* skip the header */
offset += 8;
/* add mandatory parts first */
ok &= SetTlvString(data,tlvsize,&offset, TLV_TYPE_STR_HASH_SHA1, item->hash);
ok &= setRawUInt32(data,tlvsize,&offset, item->time_stamp);
if (offset != tlvsize)
{
ok = false;
#ifdef RSSERIAL_DEBUG
std::cerr << "RsMsgSerialiser::serialiseMsgTagItem() Size Error! " << std::endl;
#endif
}
return ok;
}
bool RsMsgSerialiser::serialiseTagItem(RsMsgTagType *item, void *data, uint32_t* pktsize)
{
@ -1528,6 +1698,59 @@ bool RsMsgSerialiser::serialiseTagItem(RsMsgTagType *item, void *data, uint32_t*
return ok;
}
RsPublicMsgInviteConfigItem* RsMsgSerialiser::deserialisePublicMsgInviteConfigItem(void *data,uint32_t* pktsize)
{
/* get the type and size */
uint32_t rstype = getRsItemId(data);
uint32_t rssize = getRsItemSize(data);
uint32_t offset = 0;
if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) ||
(RS_SERVICE_TYPE_MSG != getRsItemService(rstype)) ||
(RS_PKT_SUBTYPE_MSG_INVITE != getRsItemSubType(rstype)))
{
return NULL; /* wrong type */
}
if (*pktsize < rssize) /* check size */
return NULL; /* not enough data */
/* set the packet length */
*pktsize = rssize;
bool ok = true;
/* ready to load */
RsPublicMsgInviteConfigItem *item = new RsPublicMsgInviteConfigItem();
item->clear();
/* skip the header */
offset += 8;
/* get mandatory parts first */
ok &= GetTlvString(data,rssize,&offset,TLV_TYPE_STR_HASH_SHA1,item->hash);
uint32_t ts ;
ok &= getRawUInt32(data, rssize, &offset, &ts) ;
item->time_stamp = ts ;
if (offset != rssize)
{
/* error */
delete item;
return NULL;
}
if (!ok)
{
delete item;
return NULL;
}
return item;
}
RsMsgTagType* RsMsgSerialiser::deserialiseTagItem(void *data,uint32_t* pktsize)
{
@ -2006,7 +2229,7 @@ bool RsMsgSerialiser::serialise(RsItem *i, void *data, uint32_t *pktsize)
RsMsgParentId* msp;
RsMsgTagType *mtt;
RsMsgTags *mts;
RsPublicMsgInviteConfigItem *mtu;
if (NULL != (mi = dynamic_cast<RsMsgItem *>(i)))
{
@ -2028,6 +2251,10 @@ bool RsMsgSerialiser::serialise(RsItem *i, void *data, uint32_t *pktsize)
{
return serialiseMsgTagItem(mts, data, pktsize);
}
else if (NULL != (mtu = dynamic_cast<RsPublicMsgInviteConfigItem *>(i)))
{
return serialisePublicMsgInviteConfigItem(mtu, data, pktsize);
}
return false;
}
@ -2061,6 +2288,9 @@ RsItem* RsMsgSerialiser::deserialise(void *data, uint32_t *pktsize)
case RS_PKT_SUBTYPE_MSG_TAG_TYPE:
return deserialiseTagItem(data, pktsize);
break;
case RS_PKT_SUBTYPE_MSG_INVITE:
return deserialisePublicMsgInviteConfigItem(data, pktsize);
break;
case RS_PKT_SUBTYPE_MSG_TAGS:
return deserialiseMsgTagItem(data, pktsize);
break;

View File

@ -64,12 +64,14 @@ const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE = 0x0F ;
const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_EVENT = 0x10 ;
const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_deprecated2 = 0x11 ; // to be removed (deprecated since 02 Dec. 2012)
const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_LIST = 0x12 ;
const uint8_t RS_PKT_SUBTYPE_DISTANT_INVITE_CONFIG = 0x13 ;
// for defining tags themselves and msg tags
const uint8_t RS_PKT_SUBTYPE_MSG_TAG_TYPE = 0x03;
const uint8_t RS_PKT_SUBTYPE_MSG_TAGS = 0x04;
const uint8_t RS_PKT_SUBTYPE_MSG_SRC_TAG = 0x05;
const uint8_t RS_PKT_SUBTYPE_MSG_PARENT_TAG = 0x06;
const uint8_t RS_PKT_SUBTYPE_MSG_INVITE = 0x07;
typedef uint64_t ChatLobbyId ;
typedef uint64_t ChatLobbyMsgId ;
@ -314,6 +316,27 @@ class RsPrivateChatMsgConfigItem: public RsChatItem
std::wstring message;
uint32_t recvTime;
};
class RsPrivateChatDistantInviteConfigItem: public RsChatItem
{
public:
RsPrivateChatDistantInviteConfigItem() :RsChatItem(RS_PKT_SUBTYPE_DISTANT_INVITE_CONFIG) {}
RsPrivateChatDistantInviteConfigItem(void *data,uint32_t size) ; // deserialization
virtual ~RsPrivateChatDistantInviteConfigItem() {}
virtual void clear() {}
virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
virtual bool serialise(void *data,uint32_t& size) ; // Isn't it better that items can serialize themselves ?
virtual uint32_t serial_size() ; // deserialise is handled using a constructor
unsigned char aes_key[16] ;
std::string hash ;
std::string encrypted_radix64_string ;
std::string destination_pgp_id ;
uint32_t time_of_validity ;
uint32_t last_hit_time ;
};
// This class contains activity info for the sending peer: active, idle, typing, etc.
//
@ -384,6 +407,9 @@ const uint32_t RS_MSG_FLAGS_PARTIAL = 0x0400;
const uint32_t RS_MSG_FLAGS_USER_REQUEST = 0x0800;
const uint32_t RS_MSG_FLAGS_FRIEND_RECOMMENDATION = 0x1000;
const uint32_t RS_MSG_FLAGS_SYSTEM = RS_MSG_FLAGS_USER_REQUEST | RS_MSG_FLAGS_FRIEND_RECOMMENDATION;
const uint32_t RS_MSG_FLAGS_RETURN_RECEPT = 0x2000;
const uint32_t RS_MSG_FLAGS_ENCRYPTED = 0x4000;
const uint32_t RS_MSG_FLAGS_DISTANT = 0x8000;
class RsMsgItem: public RsItem
{
@ -474,6 +500,24 @@ public:
std::string srcId;
};
class RsPublicMsgInviteConfigItem : public RsItem
{
public:
RsPublicMsgInviteConfigItem()
: RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_MSG,
RS_PKT_SUBTYPE_MSG_INVITE)
{ return;}
std::ostream &print(std::ostream &out, uint16_t indent = 0);
virtual ~RsPublicMsgInviteConfigItem() {}
virtual void clear();
std::string hash ;
time_t time_stamp ;
};
class RsMsgParentId : public RsItem
{
@ -498,45 +542,48 @@ public:
class RsMsgSerialiser: public RsSerialType
{
public:
RsMsgSerialiser(bool bConfiguration = false)
:RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_MSG), m_bConfiguration (bConfiguration)
{ return; }
RsMsgSerialiser(uint16_t type)
:RsSerialType(RS_PKT_VERSION_SERVICE, type), m_bConfiguration (false)
{ return; }
virtual ~RsMsgSerialiser() { return; }
virtual uint32_t size(RsItem *);
virtual bool serialise (RsItem *item, void *data, uint32_t *size);
virtual RsItem * deserialise(void *data, uint32_t *size);
RsMsgSerialiser(bool bConfiguration = false)
:RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_MSG), m_bConfiguration (bConfiguration)
{ return; }
RsMsgSerialiser(uint16_t type)
:RsSerialType(RS_PKT_VERSION_SERVICE, type), m_bConfiguration (false)
{ return; }
virtual ~RsMsgSerialiser() { return; }
virtual uint32_t size(RsItem *);
virtual bool serialise (RsItem *item, void *data, uint32_t *size);
virtual RsItem * deserialise(void *data, uint32_t *size);
private:
virtual uint32_t sizeMsgItem(RsMsgItem *);
virtual bool serialiseMsgItem (RsMsgItem *item, void *data, uint32_t *size);
virtual RsMsgItem *deserialiseMsgItem(void *data, uint32_t *size);
virtual uint32_t sizeMsgItem(RsMsgItem *);
virtual bool serialiseMsgItem (RsMsgItem *item, void *data, uint32_t *size);
virtual RsMsgItem *deserialiseMsgItem(void *data, uint32_t *size);
virtual uint32_t sizeTagItem(RsMsgTagType *);
virtual bool serialiseTagItem (RsMsgTagType *item, void *data, uint32_t *size);
virtual RsMsgTagType *deserialiseTagItem(void *data, uint32_t *size);
virtual uint32_t sizeTagItem(RsMsgTagType *);
virtual bool serialiseTagItem (RsMsgTagType *item, void *data, uint32_t *size);
virtual RsMsgTagType *deserialiseTagItem(void *data, uint32_t *size);
virtual uint32_t sizeMsgTagItem(RsMsgTags *);
virtual bool serialiseMsgTagItem (RsMsgTags *item, void *data, uint32_t *size);
virtual RsMsgTags *deserialiseMsgTagItem(void *data, uint32_t *size);
virtual uint32_t sizeMsgTagItem(RsMsgTags *);
virtual bool serialiseMsgTagItem (RsMsgTags *item, void *data, uint32_t *size);
virtual RsMsgTags *deserialiseMsgTagItem(void *data, uint32_t *size);
virtual uint32_t sizeMsgSrcIdItem(RsMsgSrcId *);
virtual bool serialiseMsgSrcIdItem (RsMsgSrcId *item, void *data, uint32_t *size);
virtual RsMsgSrcId *deserialiseMsgSrcIdItem(void *data, uint32_t *size);
virtual uint32_t sizeMsgSrcIdItem(RsMsgSrcId *);
virtual bool serialiseMsgSrcIdItem (RsMsgSrcId *item, void *data, uint32_t *size);
virtual RsMsgSrcId *deserialiseMsgSrcIdItem(void *data, uint32_t *size);
virtual uint32_t sizeMsgParentIdItem(RsMsgParentId *);
virtual bool serialiseMsgParentIdItem (RsMsgParentId *item, void *data, uint32_t *size);
virtual RsMsgParentId *deserialiseMsgParentIdItem(void *data, uint32_t *size);
virtual uint32_t sizeMsgParentIdItem(RsMsgParentId *);
virtual bool serialiseMsgParentIdItem (RsMsgParentId *item, void *data, uint32_t *size);
virtual RsMsgParentId *deserialiseMsgParentIdItem(void *data, uint32_t *size);
virtual uint32_t sizePublicMsgInviteConfigItem(RsPublicMsgInviteConfigItem *) ;
virtual bool serialisePublicMsgInviteConfigItem(RsPublicMsgInviteConfigItem *item, void *data, uint32_t *size);
virtual RsPublicMsgInviteConfigItem *deserialisePublicMsgInviteConfigItem(void *data, uint32_t *size);
bool m_bConfiguration; // is set to true for saving configuration (enables serialising msgId)
bool m_bConfiguration; // is set to true for saving configuration (enables serialising msgId)
};
/**************************************************************************/

View File

@ -24,11 +24,18 @@
*/
#include <math.h>
#include "openssl/rand.h"
#include "pgp/rscertificate.h"
#include "pqi/authgpg.h"
#include "util/rsdir.h"
#include "util/radix64.h"
#include "util/rsaes.h"
#include "util/rsrandom.h"
#include "util/rsstring.h"
#include "turtle/p3turtle.h"
#include "retroshare/rsiface.h"
#include "retroshare/rspeers.h"
#include "retroshare/rsstatus.h"
#include "pqi/pqibin.h"
#include "pqi/pqinotify.h"
#include "pqi/pqistore.h"
@ -40,6 +47,7 @@
/****
* #define CHAT_DEBUG 1
* #define DEBUG_DISTANT_CHAT 1
****/
static const int CONNECTION_CHALLENGE_MAX_COUNT = 20 ; // sends a connexion challenge every 20 messages
@ -52,18 +60,30 @@ static const time_t MAX_DELAY_BETWEEN_LOBBY_KEEP_ALIVE = 120 ; // send keep al
static const time_t MAX_KEEP_PUBLIC_LOBBY_RECORD = 60 ; // keep inactive lobbies records for 60 secs max.
static const time_t MIN_DELAY_BETWEEN_PUBLIC_LOBBY_REQ = 20 ; // don't ask for lobby list more than once every 30 secs.
static const time_t DISTANT_CHAT_CLEANING_PERIOD = 60 ; // don't ask for lobby list more than once every 30 secs.
static const uint32_t DISTANT_CHAT_AES_KEY_SIZE = 16 ; // size of AES encryption key for distant chat.
static const uint32_t DISTANT_CHAT_HASH_SIZE = 20 ; // This is sha1 size in bytes.
p3ChatService::p3ChatService(p3LinkMgr *lm, p3HistoryMgr *historyMgr)
:p3Service(RS_SERVICE_TYPE_CHAT), p3Config(CONFIG_TYPE_CHAT), mChatMtx("p3ChatService"), mLinkMgr(lm) , mHistoryMgr(historyMgr)
{
addSerialType(new RsChatSerialiser());
_serializer = new RsChatSerialiser() ;
_own_avatar = NULL ;
_custom_status_string = "" ;
_time_shift_average = 0.0f ;
_default_nick_name = rsPeers->getPeerName(rsPeers->getOwnId());
_should_reset_lobby_counts = false ;
mTurtle = NULL ;
last_visible_lobby_info_request_time = 0 ;
addSerialType(_serializer) ;
}
void p3ChatService::connectToTurtleRouter(p3turtle *tr)
{
mTurtle = tr ;
tr->registerTunnelService(this) ;
}
int p3ChatService::tick()
@ -71,15 +91,21 @@ int p3ChatService::tick()
if(receivedItems())
receiveChatQueue();
static time_t last_clean_time = 0 ;
static time_t last_clean_time_lobby = 0 ;
static time_t last_clean_time_dchat = 0 ;
time_t now = time(NULL) ;
if(last_clean_time + LOBBY_CACHE_CLEANING_PERIOD < now)
if(last_clean_time_lobby + LOBBY_CACHE_CLEANING_PERIOD < now)
{
cleanLobbyCaches() ;
last_clean_time = now ;
last_clean_time_lobby = now ;
}
if(last_clean_time_dchat + DISTANT_CHAT_CLEANING_PERIOD < now)
{
cleanDistantChatInvites() ;
last_clean_time_dchat = now ;
}
return 0;
}
@ -221,10 +247,27 @@ void p3ChatService::sendStatusString( const std::string& id , const std::string&
std::cerr << "sending chat status packet:" << std::endl ;
cs->print(std::cerr) ;
#endif
sendItem(cs);
sendPrivateChatItem(cs);
}
}
void p3ChatService::sendPrivateChatItem(RsChatItem *item)
{
bool found = false ;
{
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
if(_distant_chat_peers.find(item->PeerId()) != _distant_chat_peers.end())
found = true ;
}
if(found)
sendTurtleData(item) ;
else
sendItem(item) ;
}
void p3ChatService::checkSizeAndSendMessage_deprecated(RsChatMsgItem *msg)
{
// We check the message item, and possibly split it into multiple messages, if the message is too big.
@ -248,9 +291,9 @@ void p3ChatService::checkSizeAndSendMessage_deprecated(RsChatMsgItem *msg)
// Indicate that the message is to be continued.
//
item->chatFlags |= RS_CHAT_FLAG_PARTIAL_MESSAGE ;
sendItem(item) ;
sendPrivateChatItem(item) ;
}
sendItem(msg) ;
sendPrivateChatItem(msg) ;
}
// This function should be used for all types of chat messages. But this requires a non backward compatible change in
// chat protocol. To be done for version 0.6
@ -374,6 +417,18 @@ bool p3ChatService::isLobbyId(const std::string& id,ChatLobbyId& lobby_id)
return false ;
}
bool p3ChatService::isOnline(const std::string& id)
{
// check if the id is a tunnel id or a peer id.
uint32_t status ;
std::string pgp_id ;
if(!getDistantChatStatus(id,status,pgp_id))
return mLinkMgr->isOnline(id) ;
return true ;
}
bool p3ChatService::sendPrivateChat(const std::string &id, const std::wstring &msg)
{
@ -398,7 +453,8 @@ bool p3ChatService::sendPrivateChat(const std::string &id, const std::wstrin
ci->recvTime = ci->sendTime;
ci->message = msg;
if (!mLinkMgr->isOnline(id)) {
if(!isOnline(id))
{
/* peer is offline, add to outgoing list */
{
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
@ -471,7 +527,7 @@ bool p3ChatService::sendPrivateChat(const std::string &id, const std::wstrin
#endif
RsChatStatusItem *cs = makeOwnCustomStateStringItem() ;
cs->PeerId(id) ;
sendItem(cs) ;
sendPrivateChatItem(cs) ;
}
return true;
@ -608,20 +664,24 @@ void p3ChatService::receiveChatQueue()
RsItem *item ;
while(NULL != (item=recvItem()))
{
#ifdef CHAT_DEBUG
std::cerr << "p3ChatService::receiveChatQueue() Item:" << (void*)item << std::endl ;
#endif
// RsChatMsgItems needs dynamic_cast, since they have derived siblings.
//
RsChatMsgItem *ci = dynamic_cast<RsChatMsgItem*>(item) ;
if(ci != NULL)
{
if(! handleRecvChatMsgItem(ci))
delete ci ;
handleIncomingItem(item) ;
}
continue ; // don't delete! It's handled by handleRecvChatMsgItem in some specific cases only.
}
void p3ChatService::handleIncomingItem(RsItem *item)
{
#ifdef CHAT_DEBUG
std::cerr << "p3ChatService::receiveChatQueue() Item:" << (void*)item << std::endl ;
#endif
// RsChatMsgItems needs dynamic_cast, since they have derived siblings.
//
RsChatMsgItem *ci = dynamic_cast<RsChatMsgItem*>(item) ;
if(ci != NULL)
{
if(! handleRecvChatMsgItem(ci))
delete ci ;
return ; // don't delete! It's handled by handleRecvChatMsgItem in some specific cases only.
}
switch(item->PacketSubType())
{
@ -647,7 +707,6 @@ void p3ChatService::receiveChatQueue()
}
}
delete item ;
}
}
void p3ChatService::handleRecvChatLobbyListRequest(RsChatLobbyListRequestItem *clr)
@ -1479,17 +1538,19 @@ void p3ChatService::getOwnAvatarJpegData(unsigned char *& data,int& size)
std::string p3ChatService::getCustomStateString(const std::string& peer_id)
{
// should be a Mutex here.
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
std::map<std::string,StateStringInfo>::iterator it = _state_strings.find(peer_id) ;
// has it. Return it strait away.
//
if(it!=_state_strings.end())
{
it->second._peer_is_new = false ;
return it->second._custom_status_string ;
// should be a Mutex here.
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
std::map<std::string,StateStringInfo>::iterator it = _state_strings.find(peer_id) ;
// has it. Return it strait away.
//
if(it!=_state_strings.end())
{
it->second._peer_is_new = false ;
return it->second._custom_status_string ;
}
}
sendCustomStateRequest(peer_id);
@ -1498,33 +1559,35 @@ std::string p3ChatService::getCustomStateString(const std::string& peer_id)
void p3ChatService::getAvatarJpegData(const std::string& peer_id,unsigned char *& data,int& size)
{
// should be a Mutex here.
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
std::map<std::string,AvatarInfo *>::const_iterator it = _avatars.find(peer_id) ;
#ifdef CHAT_DEBUG
std::cerr << "p3chatservice:: avatar for peer " << peer_id << " requested from above. " << std::endl ;
#endif
// has avatar. Return it straight away.
//
if(it!=_avatars.end())
{
uint32_t s=0 ;
it->second->toUnsignedChar(data,s) ;
size = s ;
it->second->_peer_is_new = false ;
#ifdef CHAT_DEBUG
std::cerr << "Already has avatar. Returning it" << std::endl ;
#endif
return ;
} else {
#ifdef CHAT_DEBUG
std::cerr << "No avatar for this peer. Requesting it by sending request packet." << std::endl ;
#endif
}
// should be a Mutex here.
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
sendAvatarRequest(peer_id);
std::map<std::string,AvatarInfo *>::const_iterator it = _avatars.find(peer_id) ;
#ifdef CHAT_DEBUG
std::cerr << "p3chatservice:: avatar for peer " << peer_id << " requested from above. " << std::endl ;
#endif
// has avatar. Return it straight away.
//
if(it!=_avatars.end())
{
uint32_t s=0 ;
it->second->toUnsignedChar(data,s) ;
size = s ;
it->second->_peer_is_new = false ;
#ifdef CHAT_DEBUG
std::cerr << "Already has avatar. Returning it" << std::endl ;
#endif
return ;
} else {
#ifdef CHAT_DEBUG
std::cerr << "No avatar for this peer. Requesting it by sending request packet." << std::endl ;
#endif
}
}
sendAvatarRequest(peer_id);
}
void p3ChatService::sendAvatarRequest(const std::string& peer_id)
@ -1543,7 +1606,7 @@ void p3ChatService::sendAvatarRequest(const std::string& peer_id)
std::cerr << std::endl;
#endif
sendItem(ci);
sendPrivateChatItem(ci);
}
void p3ChatService::sendCustomStateRequest(const std::string& peer_id){
@ -1559,7 +1622,7 @@ void p3ChatService::sendCustomStateRequest(const std::string& peer_id){
std::cerr << std::endl;
#endif
sendItem(cs);
sendPrivateChatItem(cs);
}
RsChatStatusItem *p3ChatService::makeOwnCustomStateStringItem()
@ -1601,7 +1664,7 @@ void p3ChatService::sendAvatarJpegData(const std::string& peer_id)
std::cerr << std::endl;
#endif
sendItem(ci) ;
sendPrivateChatItem(ci) ;
}
else {
#ifdef CHAT_DEBUG
@ -1619,7 +1682,7 @@ std::cerr << "p3chatservice: sending requested status string for peer " << peer_
RsChatStatusItem *cs = makeOwnCustomStateStringItem();
cs->PeerId(peer_id);
sendItem(cs);
sendPrivateChatItem(cs);
}
bool p3ChatService::loadList(std::list<RsItem*>& load)
@ -1683,6 +1746,24 @@ bool p3ChatService::loadList(std::list<RsItem*>& load)
continue;
}
RsPrivateChatDistantInviteConfigItem *ditem = NULL ;
if(NULL != (ditem = dynamic_cast<RsPrivateChatDistantInviteConfigItem *>(*it)))
{
DistantChatInvite invite ;
memcpy(invite.aes_key,ditem->aes_key,DISTANT_CHAT_AES_KEY_SIZE) ;
invite.encrypted_radix64_string = ditem->encrypted_radix64_string ;
invite.destination_pgp_id = ditem->destination_pgp_id ;
invite.time_of_validity = ditem->time_of_validity ;
invite.last_hit_time = ditem->last_hit_time ;
_distant_chat_invites[ditem->hash] = invite ;
delete *it ;
continue ;
}
RsConfigKeyValueSet *vitem = NULL ;
if(NULL != (vitem = dynamic_cast<RsConfigKeyValueSet*>(*it)))
@ -1746,6 +1827,21 @@ bool p3ChatService::saveList(bool& cleanup, std::list<RsItem*>& list)
list.push_back(ci);
}
/* save ongoing distant chat invites */
for(std::map<TurtleFileHash,DistantChatInvite>::const_iterator it(_distant_chat_invites.begin());it!=_distant_chat_invites.end();++it)
{
RsPrivateChatDistantInviteConfigItem *ei = new RsPrivateChatDistantInviteConfigItem ;
ei->hash = it->first ;
memcpy(ei->aes_key,it->second.aes_key,DISTANT_CHAT_AES_KEY_SIZE) ;
ei->encrypted_radix64_string = it->second.encrypted_radix64_string ;
ei->destination_pgp_id = it->second.destination_pgp_id ;
ei->time_of_validity = it->second.time_of_validity ;
ei->last_hit_time = it->second.last_hit_time ;
list.push_back(ei) ;
}
RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ;
RsTlvKeyValue kv;
kv.key = "DEFAULT_NICK_NAME" ;
@ -1780,10 +1876,14 @@ void p3ChatService::statusChange(const std::list<pqipeer> &plist)
for (it = plist.begin(); it != plist.end(); it++) {
if (it->state & RS_PEER_S_FRIEND) {
if (it->actions & RS_PEER_CONNECTED) {
/* send the saved outgoing messages */
bool changed = false;
if (privateOutgoingList.size()) {
std::vector<RsChatMsgItem*> to_send ;
if (privateOutgoingList.size())
{
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
std::string ownId = mLinkMgr->getOwnId();
@ -1795,7 +1895,7 @@ void p3ChatService::statusChange(const std::list<pqipeer> &plist)
if (c->PeerId() == it->id) {
mHistoryMgr->addMessage(false, c->PeerId(), ownId, c);
checkSizeAndSendMessage_deprecated(c); // delete item
to_send.push_back(c) ;
changed = true;
@ -1808,6 +1908,9 @@ void p3ChatService::statusChange(const std::list<pqipeer> &plist)
}
} /* UNLOCKED */
for(uint32_t i=0;i<to_send.size();++i)
checkSizeAndSendMessage_deprecated(to_send[i]); // delete item
if (changed) {
rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_PRIVATE_OUTGOING_CHAT, NOTIFY_TYPE_DEL);
@ -2745,4 +2848,534 @@ void p3ChatService::cleanLobbyCaches()
sendConnectionChallenge(*it) ;
}
bool p3ChatService::handleTunnelRequest(const std::string& hash,const std::string& peer_id)
{
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
std::map<TurtleFileHash,DistantChatInvite>::iterator it = _distant_chat_invites.find(hash) ;
#ifdef DEBUG_DISTANT_CHAT
std::cerr << "p3ChatService::handleTunnelRequest: received tunnel request for hash " << hash << std::endl;
#endif
if(it == _distant_chat_invites.end())
return false ;
it->second.last_hit_time = time(NULL) ;
return true ;
}
void p3ChatService::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir)
{
#ifdef DEBUG_DISTANT_CHAT
std::cerr << "p3ChatService:: adding new virtual peer " << virtual_peer_id << " for hash " << hash << std::endl;
#endif
time_t now = time(NULL) ;
if(dir == RsTurtleGenericTunnelItem::DIRECTION_SERVER)
{
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
#ifdef DEBUG_DISTANT_CHAT
std::cerr << " Side is in direction to server." << std::endl;
#endif
std::map<TurtleFileHash,DistantChatPeerInfo>::iterator it = _distant_chat_peers.find(hash) ;
if(it == _distant_chat_peers.end())
{
std::cerr << "(EE) Cannot add virtual peer for hash " << hash << ": no chat invite found for that hash." << std::endl;
return ;
}
it->second.last_contact = now ;
it->second.status = RS_DISTANT_CHAT_STATUS_TUNNEL_OK ;
it->second.virtual_peer_id = virtual_peer_id ;
#ifdef DEBUG_DISTANT_CHAT
std::cerr << "(II) Adding virtual peer " << virtual_peer_id << " for chat hash " << hash << std::endl;
#endif
}
if(dir == RsTurtleGenericTunnelItem::DIRECTION_CLIENT)
{
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
#ifdef DEBUG_DISTANT_CHAT
std::cerr << " Side is in direction to client." << std::endl;
std::cerr << " Initing encryption parameters from existing distant chat invites." << std::endl;
#endif
std::map<TurtleFileHash,DistantChatInvite>::iterator it = _distant_chat_invites.find(hash) ;
if(it == _distant_chat_invites.end())
{
std::cerr << "(EE) Cannot find distant chat invite for hash " << hash << ": no chat invite found for that hash." << std::endl;
return ;
}
DistantChatPeerInfo info ;
info.last_contact = now ;
info.status = RS_DISTANT_CHAT_STATUS_TUNNEL_OK ;
info.virtual_peer_id = virtual_peer_id ;
info.pgp_id = it->second.destination_pgp_id ;
memcpy(info.aes_key,it->second.aes_key,DISTANT_CHAT_AES_KEY_SIZE) ;
_distant_chat_peers[hash] = info ;
it->second.last_hit_time = now ;
}
rsicontrol->getNotify().notifyChatStatus(hash,"tunnel is up again!",true) ;
rsicontrol->getNotify().notifyPeerStatusChanged(hash,RS_STATUS_ONLINE) ;
getPqiNotify()->AddPopupMessage(RS_POPUP_CHAT, hash, "Distant peer", "Conversation starts...");
}
void p3ChatService::removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id)
{
{
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
std::map<std::string,DistantChatPeerInfo>::iterator it = _distant_chat_peers.find(hash) ;
if(it == _distant_chat_peers.end())
{
std::cerr << "(EE) Cannot remove virtual peer " << virtual_peer_id << ": not found in chat list!!" << std::endl;
return ;
}
it->second.status = RS_DISTANT_CHAT_STATUS_TUNNEL_DN ;
}
rsicontrol->getNotify().notifyChatStatus(hash,"tunnel is down...",true) ;
rsicontrol->getNotify().notifyPeerStatusChanged(hash,RS_STATUS_OFFLINE) ;
}
#ifdef DEBUG_DISTANT_CHAT
static void printBinaryData(void *data,uint32_t size)
{
static const char outl[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' } ;
for(uint32_t j = 0; j < size; j++)
{
std::cerr << outl[ ( ((uint8_t*)data)[j]>>4) ] ;
std::cerr << outl[ ((uint8_t*)data)[j] & 0xf ] ;
}
}
#endif
void p3ChatService::receiveTurtleData( RsTurtleGenericTunnelItem *gitem,const std::string& hash,
const std::string& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction)
{
#ifdef DEBUG_DISTANT_CHAT
std::cerr << "p3ChatService::receiveTurtleData(): Received turtle data. " << std::endl;
std::cerr << " hash = " << hash << std::endl;
std::cerr << " vpid = " << virtual_peer_id << std::endl;
std::cerr << " dir = " << virtual_peer_id << std::endl;
#endif
RsTurtleGenericDataItem *item = dynamic_cast<RsTurtleGenericDataItem*>(gitem) ;
if(item == NULL)
{
std::cerr << "(EE) item is not a data item. That is an error." << std::endl;
return ;
}
#ifdef DEBUG_DISTANT_CHAT
std::cerr << " size = " << item->data_size << std::endl;
std::cerr << " data = " << (void*)item->data_bytes << std::endl;
std::cerr << " IV = " << std::hex << *(uint64_t*)item->data_bytes << std::dec << std::endl;
std::cerr << " data = " ;
printBinaryData(item->data_bytes,item->data_size) ;
std::cerr << std::endl;
#endif
uint8_t aes_key[DISTANT_CHAT_AES_KEY_SIZE] ;
{
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
std::map<std::string,DistantChatPeerInfo>::iterator it = _distant_chat_peers.find(hash) ;
if(it == _distant_chat_peers.end())
{
std::cerr << "(EE) item is not coming out of a registered tunnel. Weird. hash=" << hash << ", peer id = " << virtual_peer_id << std::endl;
return ;
}
it->second.last_contact = time(NULL) ;
memcpy(aes_key,it->second.aes_key,DISTANT_CHAT_AES_KEY_SIZE) ;
it->second.status = RS_DISTANT_CHAT_STATUS_CAN_TALK ;
}
// Call the AES crypto module
// - the IV is the first 8 bytes of item->data_bytes
if(item->data_size < 8)
{
std::cerr << "(EE) item encrypted data stream is too small: size = " << item->data_size << std::endl;
return ;
}
uint32_t decrypted_size = RsAES::get_buffer_size(item->data_size-8);
uint8_t *decrypted_data = new uint8_t[decrypted_size];
#ifdef DEBUG_DISTANT_CHAT
std::cerr << " Using IV: " << std::hex << *(uint64_t*)item->data_bytes << std::dec << std::endl;
std::cerr << " Decrypted buffer size: " << decrypted_size << std::endl;
std::cerr << " key : " ; printBinaryData(aes_key,16) ; std::cerr << std::endl;
std::cerr << " data : " ; printBinaryData(item->data_bytes,item->data_size) ; std::cerr << std::endl;
#endif
if(!RsAES::aes_decrypt_8_16((uint8_t*)item->data_bytes+8,item->data_size-8,aes_key,(uint8_t*)item->data_bytes,decrypted_data,decrypted_size))
{
std::cerr << "(EE) packet decryption failed." << std::endl;
delete[] decrypted_data ;
return ;
}
#ifdef DEBUG_DISTANT_CHAT
std::cerr << "(II) Decrypted data: size=" << decrypted_size << std::endl;
#endif
// Now try deserialise the decrypted data to make an RsItem out of it.
//
RsItem *citem = _serializer->deserialise(decrypted_data,&decrypted_size) ;
delete[] decrypted_data ;
if(citem == NULL)
{
std::cerr << "(EE) item could not be de-serialized. That is an error." << std::endl;
return ;
}
// Setup the virtual peer to be the origin, and pass it on.
//
citem->PeerId(hash) ;
handleIncomingItem(citem) ; // Treats the item, and deletes it
}
void p3ChatService::sendTurtleData(RsChatItem *item)
{
#ifdef DEBUG_DISTANT_CHAT
std::cerr << "p3ChatService::sendTurtleData(): try sending item " << (void*)item << " to tunnel " << item->PeerId() << std::endl;
#endif
uint32_t rssize = item->serial_size();
uint8_t *buff = new uint8_t[rssize] ;
if(!item->serialise(buff,rssize))
{
std::cerr << "(EE) p3ChatService::sendTurtleData(): Could not serialise item!" << std::endl;
delete[] buff ;
return ;
}
#ifdef DEBUG_DISTANT_CHAT
std::cerr << " Serialized item has size " << rssize << std::endl;
#endif
uint8_t aes_key[DISTANT_CHAT_AES_KEY_SIZE] ;
std::string virtual_peer_id ;
{
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
std::map<std::string,DistantChatPeerInfo>::iterator it = _distant_chat_peers.find(item->PeerId()) ;
if(it == _distant_chat_peers.end())
{
std::cerr << "(EE) item is not coming out of a registered tunnel. Weird. peer id = " << virtual_peer_id << std::endl;
delete[] buff ;
return ;
}
it->second.last_contact = time(NULL) ;
virtual_peer_id = it->second.virtual_peer_id ;
memcpy(aes_key,it->second.aes_key,DISTANT_CHAT_AES_KEY_SIZE) ;
}
#ifdef DEBUG_DISTANT_CHAT
std::cerr << "p3ChatService::sendTurtleData(): tunnel found. Encrypting data." << std::endl;
#endif
// Now encrypt this data using AES.
//
uint8_t *encrypted_data = new uint8_t[RsAES::get_buffer_size(rssize)];
uint32_t encrypted_size = RsAES::get_buffer_size(rssize);
uint64_t IV = RSRandom::random_u64() ; // make a random 8 bytes IV
#ifdef DEBUG_DISTANT_CHAT
std::cerr << " Using IV: " << std::hex << IV << std::dec << std::endl;
std::cerr << " Using Key: " ; printBinaryData(aes_key,16) ; std::cerr << std::endl;
#endif
if(!RsAES::aes_crypt_8_16(buff,rssize,aes_key,(uint8_t*)&IV,encrypted_data,encrypted_size))
{
std::cerr << "(EE) packet encryption failed." << std::endl;
delete[] encrypted_data ;
delete[] buff ;
return ;
}
delete[] buff ;
// make a TurtleGenericData item out of it:
//
RsTurtleGenericDataItem *gitem = new RsTurtleGenericDataItem ;
gitem->data_size = encrypted_size + 8 ;
gitem->data_bytes = malloc(gitem->data_size) ;
memcpy(gitem->data_bytes ,&IV,8) ;
memcpy(gitem->data_bytes+8,encrypted_data,encrypted_size) ;
delete[] encrypted_data ;
delete item ;
#ifdef DEBUG_DISTANT_CHAT
std::cerr << "p3ChatService::sendTurtleData(): Sending through virtual peer: " << virtual_peer_id << std::endl;
std::cerr << " gitem->data_size = " << gitem->data_size << std::endl;
std::cerr << " data = " ;
printBinaryData(gitem->data_bytes,gitem->data_size) ;
std::cerr << std::endl;
#endif
mTurtle->sendTurtleData(virtual_peer_id,gitem) ;
}
bool p3ChatService::createDistantChatInvite(const std::string& pgp_id,time_t time_of_validity,std::string& encrypted_radix64_string)
{
// create the invite
time_t now = time(NULL) ;
DistantChatInvite invite ;
invite.time_of_validity = now + time_of_validity ;
invite.last_hit_time = now ;
RAND_bytes( (unsigned char *)&invite.aes_key[0],DISTANT_CHAT_AES_KEY_SIZE ) ; // generate a random AES encryption key
// Create a random hash for that invite.
//
unsigned char hash_bytes[DISTANT_CHAT_HASH_SIZE] ;
RAND_bytes( hash_bytes, DISTANT_CHAT_HASH_SIZE) ;
std::string hash = t_RsGenericIdType<DISTANT_CHAT_HASH_SIZE>(hash_bytes).toStdString(false) ;
#ifdef DEBUG_DISTANT_CHAT
std::cerr << "Created new distant chat invite: " << std::endl;
std::cerr << " validity time stamp = " << invite.time_of_validity << std::endl;
std::cerr << " hash = " << hash << std::endl;
std::cerr << " encryption key = " ;
static const char outl[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' } ;
for(uint32_t j = 0; j < 16; j++) { std::cerr << outl[ (invite.aes_key[j]>>4) ] ; std::cerr << outl[ invite.aes_key[j] & 0xf ] ; }
std::cerr << std::endl;
#endif
// Now encrypt the data to create the link info. We need
//
// [E] - the hash
// [E] - the aes key
// [E] - the signature
// - pgp id
// - timestamp
//
// The link will be
//
// retroshare://chat?time_stamp=3243242&private_data=[radix64 string]
uint32_t header_size = DISTANT_CHAT_AES_KEY_SIZE + DISTANT_CHAT_HASH_SIZE + KEY_ID_SIZE;
unsigned char *data = new unsigned char[header_size+400] ;
PGPIdType OwnId(AuthGPG::getAuthGPG()->getGPGOwnId());
memcpy(data ,hash_bytes ,DISTANT_CHAT_HASH_SIZE) ;
memcpy(data+DISTANT_CHAT_HASH_SIZE ,invite.aes_key ,DISTANT_CHAT_AES_KEY_SIZE) ;
memcpy(data+DISTANT_CHAT_HASH_SIZE+DISTANT_CHAT_AES_KEY_SIZE,OwnId.toByteArray(),KEY_ID_SIZE) ;
#ifdef DEBUG_DISTANT_CHAT
std::cerr << "Performing signature " << std::endl;
#endif
uint32_t signlen = 400;
if(!AuthGPG::getAuthGPG()->SignDataBin(data,header_size,data+header_size,&signlen))
return false ;
#ifdef DEBUG_DISTANT_CHAT
std::cerr << "Signature length = " << signlen << std::endl;
#endif
// Then encrypt the whole data into a single string.
unsigned char *encrypted_data = new unsigned char[2000] ;
uint32_t encrypted_size = 2000 ;
if(!AuthGPG::getAuthGPG()->encryptDataBin(pgp_id,(unsigned char *)data,signlen+header_size,encrypted_data,&encrypted_size))
return false ;
#ifdef DEBUG_DISTANT_CHAT
std::cerr << "Encrypted data size: " << encrypted_size << std::endl;
#endif
Radix64::encode((const char *)encrypted_data,encrypted_size,invite.encrypted_radix64_string) ;
invite.destination_pgp_id = pgp_id ;
{
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
_distant_chat_invites[hash] = invite ;
}
encrypted_radix64_string = invite.encrypted_radix64_string ;
#ifdef DEBUG_DISTANT_CHAT
std::cerr << "Encrypted radix64 string: " << invite.encrypted_radix64_string << std::endl;
#endif
IndicateConfigChanged();
return true ;
}
bool p3ChatService::initiateDistantChatConnexion(const std::string& encrypted_str,std::string& hash,uint32_t& error_code)
{
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
// Un-radix the string.
//
char *encrypted_data_bin = NULL ;
size_t encrypted_data_len ;
Radix64::decode(encrypted_str,encrypted_data_bin,encrypted_data_len) ;
// Decrypt it.
//
uint32_t data_size = encrypted_data_len+1000;
unsigned char *data = new unsigned char[data_size] ;
if(!AuthGPG::getAuthGPG()->decryptDataBin((unsigned char *)encrypted_data_bin,encrypted_data_len,data,&data_size))
{
error_code = RS_DISTANT_CHAT_ERROR_DECRYPTION_FAILED ;
return false ;
}
delete[] encrypted_data_bin ;
#ifdef DEBUG_DISTANT_CHAT
std::cerr << "Chat invite was successfuly decrypted!" << std::endl;
#endif
uint32_t header_size = DISTANT_CHAT_HASH_SIZE + DISTANT_CHAT_AES_KEY_SIZE + KEY_ID_SIZE ;
PGPIdType pgp_id( data + DISTANT_CHAT_HASH_SIZE + DISTANT_CHAT_AES_KEY_SIZE ) ;
#ifdef DEBUG_DISTANT_CHAT
std::cerr << "Got this PGP id: " << pgp_id.toStdString() << std::endl;
#endif
PGPFingerprintType fingerprint ;
if(!AuthGPG::getAuthGPG()->getKeyFingerprint(pgp_id,fingerprint))
{
error_code = RS_DISTANT_CHAT_ERROR_UNKNOWN_KEY ;
return false ;
}
if(!AuthGPG::getAuthGPG()->VerifySignBin(data,header_size,data+header_size,data_size-header_size,fingerprint.toStdString()))
{
error_code = RS_DISTANT_CHAT_ERROR_SIGNATURE_MISMATCH ;
return false ;
}
#ifdef DEBUG_DISTANT_CHAT
std::cerr << "Signature successfuly verified!" << std::endl;
#endif
hash = t_RsGenericIdType<DISTANT_CHAT_HASH_SIZE>(data).toStdString(false) ;
DistantChatPeerInfo info ;
info.last_contact = time(NULL) ;
info.status = RS_DISTANT_CHAT_STATUS_TUNNEL_DN ;
info.pgp_id = pgp_id.toStdString() ;
memcpy(info.aes_key,data+DISTANT_CHAT_HASH_SIZE,DISTANT_CHAT_AES_KEY_SIZE) ;
_distant_chat_peers[hash] = info ;
delete[] data ;
// Now ask the turtle router to manage a tunnel for that hash.
#ifdef DEBUG_DISTANT_CHAT
std::cerr << "Asking turtle router to monitor tunnels for hash " << hash << std::endl;
#endif
mTurtle->monitorTunnels(hash,this) ;
// And notify about chatting.
error_code = RS_DISTANT_CHAT_ERROR_NO_ERROR ;
return true ;
}
void p3ChatService::cleanDistantChatInvites()
{
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
time_t now = time(NULL) ;
#ifdef DEBUG_DISTANT_CHAT
std::cerr << "p3ChatService::cleanDistantChatInvites: " << std::endl;
#endif
for(std::map<TurtleFileHash,DistantChatInvite>::iterator it(_distant_chat_invites.begin());it!=_distant_chat_invites.end(); )
if(it->second.time_of_validity < now)
{
#ifdef DEBUG_DISTANT_CHAT
std::cerr << " Removing hash " << it->first << std::endl;
#endif
std::map<TurtleFileHash,DistantChatInvite>::iterator tmp(it) ;
++it ;
_distant_chat_invites.erase(tmp) ;
}
else
{
#ifdef DEBUG_DISTANT_CHAT
std::cerr << " Keeping hash " << it->first << std::endl;
#endif
++it ;
}
}
bool p3ChatService::getDistantChatInviteList(std::vector<DistantChatInviteInfo>& invites)
{
invites.clear() ;
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
for(std::map<std::string,DistantChatInvite>::const_iterator it(_distant_chat_invites.begin());it!=_distant_chat_invites.end();++it)
{
DistantChatInviteInfo info ;
info.hash = it->first ;
info.encrypted_radix64_string = it->second.encrypted_radix64_string ;
info.time_of_validity = it->second.time_of_validity ;
info.destination_pgp_id = it->second.destination_pgp_id ;
invites.push_back(info);
}
return true ;
}
bool p3ChatService::getDistantChatStatus(const std::string& hash,uint32_t& status,std::string& pgp_id)
{
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
std::map<TurtleFileHash,DistantChatPeerInfo>::const_iterator it = _distant_chat_peers.find(hash) ;
if(it == _distant_chat_peers.end())
return false ;
status = it->second.status ;
pgp_id = it->second.pgp_id ;
return true ;
}

View File

@ -33,10 +33,13 @@
#include "serialiser/rsmsgitems.h"
#include "services/p3service.h"
#include "pgp/pgphandler.h"
#include "turtle/turtleclientservice.h"
#include "retroshare/rsmsgs.h"
class p3LinkMgr;
class p3HistoryMgr;
class p3turtle ;
//!The basic Chat service.
/**
@ -45,7 +48,7 @@ class p3HistoryMgr;
* This service uses rsnotify (callbacks librs clients (e.g. rs-gui))
* @see NotifyBase
*/
class p3ChatService: public p3Service, public p3Config, public pqiMonitor
class p3ChatService: public p3Service, public p3Config, public pqiMonitor, public RsTurtleClientService
{
public:
p3ChatService(p3LinkMgr *cm, p3HistoryMgr *historyMgr);
@ -183,6 +186,7 @@ class p3ChatService: public p3Service, public p3Config, public pqiMonitor
virtual void saveDone();
virtual bool loadList(std::list<RsItem*>& load) ;
bool isOnline(const std::string& id) ;
private:
RsMutex mChatMtx;
@ -191,6 +195,7 @@ class p3ChatService: public p3Service, public p3Config, public pqiMonitor
// Receive chat queue
void receiveChatQueue();
void handleIncomingItem(RsItem *); // called by the former, and turtle handler for incoming encrypted items
void initRsChatInfo(RsChatMsgItem *c, ChatInfo &i);
@ -289,9 +294,69 @@ class p3ChatService: public p3Service, public p3Config, public pqiMonitor
std::map<std::string,ChatLobbyId> _lobby_ids ;
std::string _default_nick_name ;
float _time_shift_average ;
time_t last_lobby_challenge_time ; // prevents bruteforce attack
time_t last_lobby_challenge_time ; // prevents bruteforce attack
time_t last_visible_lobby_info_request_time ; // allows to ask for updates
bool _should_reset_lobby_counts ;
RsChatSerialiser *_serializer ;
// ===========================================================//
// Members related to anonymous distant chat. //
// ===========================================================//
public:
void connectToTurtleRouter(p3turtle *) ;
// Creates the invite if the public key of the distant peer is available.
// Om success, stores the invite in the map above, so that we can respond to tunnel requests.
//
bool createDistantChatInvite(const std::string& pgp_id,time_t time_of_validity,TurtleFileHash& hash) ;
bool getDistantChatInviteList(std::vector<DistantChatInviteInfo>& invites) ;
bool initiateDistantChatConnexion(const std::string& encrypted_string,std::string& hash,uint32_t& error_code) ;
virtual bool getDistantChatStatus(const std::string& hash,uint32_t& status,std::string& pgp_id) ;
private:
struct DistantChatInvite
{
unsigned char aes_key[16] ;
std::string encrypted_radix64_string ;
std::string destination_pgp_id ;
time_t time_of_validity ;
time_t last_hit_time ;
};
struct DistantChatPeerInfo
{
time_t last_contact ; // used to send keep alive packets
unsigned char aes_key[16] ; // key to encrypt packets
uint32_t status ; // info: do we have a tunnel ?
std::string virtual_peer_id; // given by the turtle router. Identifies the tunnel.
std::string pgp_id ; // pgp id of the peer we're talking to.
};
// This map contains the ongoing invites. This is the list where to look to
// handle tunnel requests.
//
std::map<TurtleFileHash,DistantChatInvite> _distant_chat_invites ;
// This maps contains the current peers to talk to with distant chat.
//
std::map<std::string,DistantChatPeerInfo> _distant_chat_peers ;
// Overloaded from RsTurtleClientService
virtual bool handleTunnelRequest(const std::string& hash,const std::string& peer_id) ;
virtual void receiveTurtleData(RsTurtleGenericTunnelItem *item,const std::string& hash,const std::string& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction) ;
void addVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&,RsTurtleGenericTunnelItem::Direction dir) ;
void removeVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&) ;
// Utility functions
void cleanDistantChatInvites() ;
void sendTurtleData(RsChatItem *) ;
void sendPrivateChatItem(RsChatItem *) ;
p3turtle *mTurtle ;
};
class p3ChatService::StateStringInfo

View File

@ -25,23 +25,34 @@
#include "retroshare/rsiface.h"
#include "retroshare/rspeers.h"
#include "pqi/pqibin.h"
#include "pqi/pqiarchive.h"
#include "pqi/p3linkmgr.h"
#include "pqi/authgpg.h"
#include "services/p3msgservice.h"
#include "pgp/pgpkeyutil.h"
#include "pqi/pqinotify.h"
#include "util/rsdebug.h"
#include "util/rsdir.h"
#include "util/rsstring.h"
#include "util/radix64.h"
#include "util/rsrandom.h"
#include <iomanip>
#include <map>
//#define DEBUG_DISTANT_MSG
const int msgservicezone = 54319;
static const uint32_t RS_DISTANT_MSG_STATUS_TUNNEL_OK = 0x0001 ;
static const uint32_t RS_DISTANT_MSG_STATUS_TUNNEL_DN = 0x0000 ;
static const uint32_t DISTANT_MSG_HASH_SIZE = 20 ;
/* Another little hack ..... unique message Ids
* will be handled in this class.....
* These are unique within this run of the server,
@ -58,7 +69,8 @@ p3MsgService::p3MsgService(p3LinkMgr *lm)
:p3Service(RS_SERVICE_TYPE_MSG), p3Config(CONFIG_TYPE_MSGS),
mLinkMgr(lm), mMsgMtx("p3MsgService"), mMsgUniqueId(time(NULL))
{
addSerialType(new RsMsgSerialiser());
_serialiser = new RsMsgSerialiser();
addSerialType(_serialiser);
/* Initialize standard tag types */
if(lm)
@ -81,6 +93,15 @@ int p3MsgService::tick()
*/
incomingMsgs();
static time_t last_management_time = 0 ;
time_t now = time(NULL) ;
if(now > last_management_time + 5)
{
manageDistantPeers() ;
last_management_time = now ;
}
//checkOutgoingMessages();
return 0;
@ -107,7 +128,7 @@ void p3MsgService::processMsg(RsMsgItem *mi, bool incoming)
{
/* from a peer */
mi->msgFlags &= RS_MSG_FLAGS_SYSTEM; // remove flags
mi->msgFlags &= (RS_MSG_FLAGS_ENCRYPTED | RS_MSG_FLAGS_SYSTEM); // remove flags except those
mi->msgFlags |= RS_MSG_FLAGS_NEW;
pqiNotify *notify = getPqiNotify();
@ -187,22 +208,27 @@ int p3MsgService::incomingMsgs()
{
RsMsgItem *mi;
int i = 0;
bool changed = false ;
while((mi = (RsMsgItem *) recvItem()) != NULL)
{
changed = true ;
++i;
handleIncomingItem(mi) ;
++i ;
}
if(checkAndRebuildPartialMessage(mi)) // only returns true when a msg is complete.
{
processMsg(mi, true);
}
return i;
}
void p3MsgService::handleIncomingItem(RsMsgItem *mi)
{
bool changed = false ;
if(checkAndRebuildPartialMessage(mi)) // only returns true when a msg is complete.
{
processMsg(mi, true);
changed = true ;
}
if(changed)
rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_MOD);
return 1;
}
void p3MsgService::statusChange(const std::list<pqipeer> &/*plist*/)
@ -233,10 +259,18 @@ void p3MsgService::checkSizeAndSendMessage(RsMsgItem *msg)
// Indicate that the message is to be continued.
//
item->msgFlags |= RS_MSG_FLAGS_PARTIAL ;
sendItem(item) ;
if(msg->msgFlags & RS_MSG_FLAGS_DISTANT)
sendPrivateMsgItem(msg) ;
else
sendItem(item) ;
}
std::cerr << " Chopped off msg of size " << msg->message.size() << std::endl;
sendItem(msg) ;
if(msg->msgFlags & RS_MSG_FLAGS_DISTANT)
sendPrivateMsgItem(msg) ;
else
sendItem(msg) ;
}
int p3MsgService::checkOutgoingMessages()
@ -247,6 +281,7 @@ int p3MsgService::checkOutgoingMessages()
*/
bool changed = false ;
std::list<RsMsgItem*> output_queue ;
{
const std::string ownId = mLinkMgr->getOwnId();
@ -264,18 +299,8 @@ int p3MsgService::checkOutgoingMessages()
/* find the certificate */
std::string pid = mit->second->PeerId();
bool toSend = false;
if (mLinkMgr->isOnline(pid))
{
toSend = true;
}
else if (pid == ownId) /* FEEDBACK Msg to Ourselves */
{
toSend = true;
}
if (toSend)
if(mit->second->msgFlags & RS_MSG_FLAGS_DISTANT || mLinkMgr->isOnline(pid) || pid == ownId) /* FEEDBACK Msg to Ourselves */
{
/* send msg */
pqioutput(PQL_DEBUG_BASIC, msgservicezone,
@ -283,7 +308,7 @@ int p3MsgService::checkOutgoingMessages()
/* remove the pending flag */
(mit->second)->msgFlags &= ~RS_MSG_FLAGS_PENDING;
checkSizeAndSendMessage(mit->second) ;
output_queue.push_back(mit->second) ;
toErase.push_back(mit->first);
changed = true ;
@ -317,6 +342,9 @@ int p3MsgService::checkOutgoingMessages()
}
}
for(std::list<RsMsgItem*>::const_iterator it(output_queue.begin());it!=output_queue.end();++it)
checkSizeAndSendMessage(*it) ;
if(changed)
rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_MOD);
@ -357,6 +385,14 @@ bool p3MsgService::saveList(bool& cleanup, std::list<RsItem*>& itemList)
for(mit4 = mParentId.begin(); mit4 != mParentId.end(); mit4++)
itemList.push_back(mit4->second);
for(std::map<std::string,DistantMessengingInvite>::const_iterator it(_messenging_invites.begin());it!=_messenging_invites.end();++it)
{
RsPublicMsgInviteConfigItem *item = new RsPublicMsgInviteConfigItem ;
item->hash = it->first ;
item->time_stamp = it->second.time_of_validity ;
itemList.push_back(item) ;
}
return true;
}
@ -421,6 +457,7 @@ bool p3MsgService::loadList(std::list<RsItem*>& load)
RsMsgTags* mti;
RsMsgSrcId* msi;
RsMsgParentId* msp;
RsPublicMsgInviteConfigItem* msv;
std::list<RsMsgItem*> items;
std::list<RsItem*>::iterator it;
@ -442,18 +479,18 @@ bool p3MsgService::loadList(std::list<RsItem*>& load)
items.push_back(mitem);
}
else if(NULL != (mtt = dynamic_cast<RsMsgTagType *>(*it)))
{
// delete standard tags as they are now save in config
if(mTags.end() == (tagIt = mTags.find(mtt->tagId)))
{
mTags.insert(std::pair<uint32_t, RsMsgTagType* >(mtt->tagId, mtt));
}
else
{
delete mTags[mtt->tagId];
mTags.erase(tagIt);
mTags.insert(std::pair<uint32_t, RsMsgTagType* >(mtt->tagId, mtt));
}
{
// delete standard tags as they are now save in config
if(mTags.end() == (tagIt = mTags.find(mtt->tagId)))
{
mTags.insert(std::pair<uint32_t, RsMsgTagType* >(mtt->tagId, mtt));
}
else
{
delete mTags[mtt->tagId];
mTags.erase(tagIt);
mTags.insert(std::pair<uint32_t, RsMsgTagType* >(mtt->tagId, mtt));
}
}
else if(NULL != (mti = dynamic_cast<RsMsgTags *>(*it)))
@ -469,6 +506,10 @@ bool p3MsgService::loadList(std::list<RsItem*>& load)
{
mParentId.insert(std::pair<uint32_t, RsMsgParentId*>(msp->msgId, msp));
}
else if(NULL != (msv = dynamic_cast<RsPublicMsgInviteConfigItem *>(*it)))
{
_messenging_invites[msv->hash].time_of_validity = msv->time_stamp ;
}
}
// sort items into lists
@ -1357,6 +1398,10 @@ void p3MsgService::initRsMI(RsMsgItem *msg, MessageInfo &mi)
{
mi.msgflags |= RS_MSG_NEW;
}
if (msg->msgFlags & RS_MSG_FLAGS_ENCRYPTED)
mi.msgflags |= RS_MSG_ENCRYPTED ;
if (msg->msgFlags & RS_MSG_FLAGS_TRASH)
{
mi.msgflags |= RS_MSG_TRASH;
@ -1442,6 +1487,9 @@ void p3MsgService::initRsMIS(RsMsgItem *msg, MsgInfoSummary &mis)
{
mis.msgflags = 0;
if (msg->msgFlags & RS_MSG_FLAGS_ENCRYPTED)
mis.msgflags |= RS_MSG_ENCRYPTED ;
/* translate flags, if we sent it... outgoing */
if ((msg->msgFlags & RS_MSG_FLAGS_OUTGOING)
/*|| (msg->PeerId() == mLinkMgr->getOwnId())*/)
@ -1513,7 +1561,8 @@ RsMsgItem *p3MsgService::initMIRsMsg(MessageInfo &info, const std::string &to)
msg -> recvTime = 0;
msg -> subject = info.title;
msg -> message = info.msg;
msg -> message = info.msg;
std::list<std::string>::iterator pit;
for(pit = info.msgto.begin(); pit != info.msgto.end(); pit++)
@ -1538,6 +1587,10 @@ RsMsgItem *p3MsgService::initMIRsMsg(MessageInfo &info, const std::string &to)
msg -> attachment.title = info.attach_title;
msg -> attachment.comment = info.attach_comment;
RsPeerDetails details ;
if(!rsPeers->getPeerDetails(to,details))
msg->msgFlags |= RS_MSG_FLAGS_DISTANT;
std::list<FileInfo>::iterator it;
for(it = info.files.begin(); it != info.files.end(); it++)
{
@ -1550,15 +1603,428 @@ RsMsgItem *p3MsgService::initMIRsMsg(MessageInfo &info, const std::string &to)
/* translate flags from outside */
if (info.msgflags & RS_MSG_USER_REQUEST)
{
msg->msgFlags |= RS_MSG_FLAGS_USER_REQUEST;
}
if (info.msgflags & RS_MSG_FRIEND_RECOMMENDATION)
{
msg->msgFlags |= RS_MSG_FLAGS_FRIEND_RECOMMENDATION;
}
//std::cerr << "p3MsgService::initMIRsMsg()" << std::endl;
if (info.msgflags & RS_MSG_FRIEND_RECOMMENDATION)
msg->msgFlags |= RS_MSG_FLAGS_FRIEND_RECOMMENDATION;
// See if we need to encrypt this message. If so, we replace the msg text
// by the whole message serialized and binary encrypted, so as to obfuscate
// all its content.
//
bool enc_ok = false ;
if(info.encryption_keys.find(to) != info.encryption_keys.end())
encryptMessage(info.encryption_keys[to],msg) ;
//std::cerr << "p3MsgService::initMIRsMsg()" << std::endl;
//msg->print(std::cerr);
return msg;
}
bool p3MsgService::encryptMessage(const std::string& pgp_id,RsMsgItem *item)
{
#ifdef DEBUG_DISTANT_MSG
std::cerr << "Encrypting message with public key " << pgp_id << " in place." << std::endl;
#endif
// 1 - serialise the whole message item into a binary chunk.
//
uint32_t rssize = _serialiser->size(item) ;
unsigned char *data = new unsigned char[rssize] ;
if(!_serialiser->serialise(item,data,&rssize))
{
std::cerr << "(EE) p3MsgService::sendTurtleData(): Serialization error." << std::endl;
delete[] data ;
return false;
}
// 2 - pgp-encrypt the chunk with the user-supplied public key.
//
uint32_t encrypted_size = rssize + 1000 ;
unsigned char *encrypted_data = new unsigned char[encrypted_size] ;
if(!AuthGPG::getAuthGPG()->encryptDataBin(pgp_id,data,rssize,encrypted_data,&encrypted_size))
{
delete[] data ;
delete[] encrypted_data ;
std::cerr << "Encryption failed!" << std::endl;
return false;
}
delete[] data ;
// Now turn the binary encrypted chunk into a readable radix string.
//
std::string armoured_data ;
Radix64::encode((char *)encrypted_data,encrypted_size,armoured_data) ;
delete[] encrypted_data ;
std::wstring encrypted_msg ;
if(!librs::util::ConvertUtf8ToUtf16(armoured_data,encrypted_msg))
return false;
// wipe the item clean and replace the message by the encrypted data.
item->message = encrypted_msg ;
item->subject = L"" ;
item->msgcc.ids.clear() ;
item->msgbcc.ids.clear() ;
item->msgto.ids.clear() ;
item->msgFlags |= RS_MSG_FLAGS_ENCRYPTED ;
item->attachment.TlvClear() ;
return true ;
}
bool p3MsgService::decryptMessage(const std::string& mId)
{
uint32_t msgId = atoi(mId.c_str());
std::string encrypted_string ;
{
RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/
std::map<uint32_t, RsMsgItem *>::iterator mit = imsg.find(msgId);
if(mit == imsg.end() || !librs::util::ConvertUtf16ToUtf8(mit->second->message,encrypted_string))
return false;
}
char *encrypted_data ;
size_t encrypted_size ;
Radix64::decode(encrypted_string,encrypted_data,encrypted_size) ;
uint32_t decrypted_size = encrypted_size + 500 ;
unsigned char *decrypted_data = new unsigned char[decrypted_size] ;
if(!AuthGPG::getAuthGPG()->decryptDataBin(encrypted_data,encrypted_size,decrypted_data,&decrypted_size))
{
delete[] encrypted_data ;
delete[] decrypted_data ;
std::cerr << "decryption failed!" << std::endl;
return false;
}
RsMsgItem *item = dynamic_cast<RsMsgItem*>(_serialiser->deserialise(decrypted_data,&decrypted_size)) ;
if(item == NULL)
return false ;
{
RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/
*imsg[msgId] = *item ;
}
delete item ;
IndicateConfigChanged() ;
return true ;
}
void p3MsgService::connectToTurtleRouter(p3turtle *pt)
{
mTurtle = pt ;
pt->registerTunnelService(this) ;
}
bool p3MsgService::createDistantOfflineMessengingInvite(time_t time_of_validity,TurtleFileHash& hash)
{
unsigned char hash_bytes[DISTANT_MSG_HASH_SIZE] ;
RSRandom::random_bytes( hash_bytes, DISTANT_MSG_HASH_SIZE) ;
hash = t_RsGenericIdType<DISTANT_MSG_HASH_SIZE>(hash_bytes).toStdString(false) ;
DistantMessengingInvite invite ;
invite.time_of_validity = time_of_validity + time(NULL);
{
RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/
_messenging_invites[hash] = invite ;
}
IndicateConfigChanged() ;
return true ;
}
bool p3MsgService::getDistantOfflineMessengingInvites(std::vector<DistantOfflineMessengingInvite>& invites)
{
RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/
for(std::map<std::string,DistantMessengingInvite>::const_iterator it(_messenging_invites.begin());it!=_messenging_invites.end();++it)
{
DistantOfflineMessengingInvite invite ;
invite.hash = it->first ;
invite.issuer_pgp_id = AuthGPG::getAuthGPG()->getGPGOwnId() ;
invite.time_of_validity = it->second.time_of_validity ;
invites.push_back(invite) ;
#ifdef DEBUG_DISTANT_MSG
std::cerr << " adding invite with hash " << invite.hash << std::endl;
#endif
}
return true ;
}
bool p3MsgService::handleTunnelRequest(const std::string& hash,const std::string& peer_id)
{
#ifdef DEBUG_DISTANT_MSG
std::cerr << "p3MsgService::handleTunnelRequest: received TR for hash " << hash << std::endl;
#endif
RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/
std::map<std::string,DistantMessengingInvite>::const_iterator it = _messenging_invites.find(hash) ;
#ifdef DEBUG_DISTANT_MSG
if(it != _messenging_invites.end())
std::cerr << "Responding OK!" << std::endl;
#endif
return it != _messenging_invites.end() ;
}
void p3MsgService::manageDistantPeers()
{
// now possibly flush pending messages
#ifdef DEBUG_DISTANT_MSG
std::cerr << "p3MsgService::manageDistantPeers()" << std::endl;
#endif
std::vector<std::pair<std::string,RsMsgItem*> > to_send ;
{
RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/
for(std::map<std::string,DistantMessengingContact>::iterator it(_messenging_contacts.begin());it!=_messenging_contacts.end();++it)
if(it->second.status == RS_DISTANT_MSG_STATUS_TUNNEL_OK)
{
for(uint32_t i=0;i<it->second.pending_messages.size();++i)
to_send.push_back(std::pair<std::string,RsMsgItem*>(it->first,it->second.pending_messages[i])) ;
it->second.pending_messages.clear() ;
}
}
for(uint32_t i=0;i<to_send.size();++i)
{
#ifdef DEBUG_DISTANT_MSG
std::cerr << " Flushing msg " << to_send[i].second->msgId << std::endl;
#endif
sendTurtleData(to_send[i].first,to_send[i].second) ;
}
time_t now = time(NULL) ;
{
RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/
// clean dead invites.
//
for(std::map<std::string,DistantMessengingInvite>::iterator it(_messenging_invites.begin());it!=_messenging_invites.end();)
if(it->second.time_of_validity < now)
{
#ifdef DEBUG_DISTANT_MSG
std::cerr << " Removing outdated invite " << it->second.time_of_validity << ", hash=" << it->first << std::endl;
#endif
std::map<std::string,DistantMessengingInvite>::iterator tmp(it) ;
++tmp ;
_messenging_invites.erase(it) ;
it = tmp ;
}
else
++it ;
// clean dead contacts.
//
for(std::map<std::string,DistantMessengingContact>::iterator it(_messenging_contacts.begin());it!=_messenging_contacts.end();)
if(it->second.pending_messages.empty() && it->second.status == RS_DISTANT_MSG_STATUS_TUNNEL_DN)
{
#ifdef DEBUG_DISTANT_MSG
std::cerr << " Removing dead contact with no pending msgs and dead tunnel. hash=" << it->first << std::endl;
#endif
std::map<std::string,DistantMessengingContact>::iterator tmp(it) ;
++tmp ;
_messenging_contacts.erase(it) ;
it = tmp ;
}
else
++it ;
}
}
void p3MsgService::addVirtualPeer(const TurtleFileHash& hash, const TurtleVirtualPeerId& vpid,RsTurtleGenericTunnelItem::Direction dir)
{
RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/
// A new tunnel has been created. We need to flush pending messages for the corresponding peer.
//std::map<std::string,DistantMessengingContact>::const_iterator it = _messenging_contacts.find(hash) ;
DistantMessengingContact& contact(_messenging_contacts[hash]) ; // possibly creates it.
contact.virtual_peer_id = vpid ;
contact.last_hit_time = time(NULL) ;
contact.status = RS_DISTANT_MSG_STATUS_TUNNEL_OK ;
#ifdef DEBUG_DISTANT_MSG
std::cerr << "p3MsgService::addVirtualPeer(): adding virtual peer " << vpid << " for hash " << hash << std::endl;
#endif
}
void p3MsgService::removeVirtualPeer(const TurtleFileHash& hash, const TurtleVirtualPeerId& vpid)
{
RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/
// A new tunnel has been created. We need to flush pending messages for the corresponding peer.
//std::map<std::string,DistantMessengingContact>::const_iterator it = _messenging_contacts.find(hash) ;
DistantMessengingContact& contact(_messenging_contacts[hash]) ; // possibly creates it.
contact.status = RS_DISTANT_MSG_STATUS_TUNNEL_DN ;
contact.virtual_peer_id.clear() ;
}
#ifdef DEBUG_DISTANT_MSG
static void printBinaryData(void *data,uint32_t size)
{
static const char outl[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' } ;
for(uint32_t j = 0; j < size; j++)
{
std::cerr << outl[ ( ((uint8_t*)data)[j]>>4) ] ;
std::cerr << outl[ ((uint8_t*)data)[j] & 0xf ] ;
}
}
#endif
void p3MsgService::sendTurtleData(const std::string& hash,RsMsgItem *msgitem)
{
// The item is serialized and turned into a generic turtle item.
uint32_t rssize = _serialiser->size(msgitem) ;
unsigned char *data = new unsigned char[rssize] ;
if(!_serialiser->serialise(msgitem,data,&rssize))
{
std::cerr << "(EE) p3MsgService::sendTurtleData(): Serialization error." << std::endl;
delete[] data ;
return ;
}
RsTurtleGenericDataItem *item = new RsTurtleGenericDataItem ;
item->data_bytes = malloc(rssize) ;
item->data_size = rssize ;
memcpy(item->data_bytes,data,rssize) ;
delete[] data ;
#ifdef DEBUG_DISTANT_MSG
printBinaryData(item->data_bytes,item->data_size) ;
std::cerr << std::endl;
#endif
// do we have a working tunnel for that hash ?
// If not, put on the contact's waiting list.
std::string virtual_peer_id ;
{
RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/
std::map<std::string,DistantMessengingContact>::const_iterator it = _messenging_contacts.find(hash) ;
if(it == _messenging_contacts.end())
{
std::cerr << "(EE) p3MsgService::sendTurtleData(): Can't find hash " << hash << " in recorded contact list." << std::endl;
delete[] data ;
return ;
}
if(!it->second.status == RS_DISTANT_MSG_STATUS_TUNNEL_OK)
{
std::cerr << "p3MsgService::sendTurtleData(): tunnel is not ok. Putting items on waiting list." << std::endl;
return ;
}
virtual_peer_id = it->second.virtual_peer_id ;
}
#ifdef DEBUG_DISTANT_MSG
std::cerr << "p3MsgService::sendTurtleData(): Sending through virtual peer: " << virtual_peer_id << std::endl;
std::cerr << " item->data_size = " << item->data_size << std::endl;
std::cerr << " data = " ;
#endif
mTurtle->sendTurtleData(virtual_peer_id,item) ;
}
void p3MsgService::receiveTurtleData(RsTurtleGenericTunnelItem *gitem,const std::string& hash,
const std::string& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction)
{
RsTurtleGenericDataItem *item = dynamic_cast<RsTurtleGenericDataItem*>(gitem) ;
if(item == NULL)
{
std::cerr << "(EE) p3MsgService::receiveTurtleData(): item is not a data item. That is an error." << std::endl;
return ;
}
#ifdef DEBUG_DISTANT_MSG
std::cerr << "p3MsgService::sendTurtleData(): Receiving through virtual peer: " << virtual_peer_id << std::endl;
std::cerr << " gitem->data_size = " << item->data_size << std::endl;
std::cerr << " data = " ;
printBinaryData(item->data_bytes,item->data_size) ;
std::cerr << std::endl;
#endif
{
RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/
std::map<std::string,DistantMessengingContact>::iterator it = _messenging_contacts.find(hash) ;
if(it == _messenging_contacts.end())
{
std::cerr << "(EE) p3MsgService::sendTurtleData(): Can't find hash " << hash << " in recorded contact list." << std::endl;
return ;
}
it->second.status = RS_DISTANT_MSG_STATUS_TUNNEL_OK ;
it->second.last_hit_time = time(NULL) ;
}
RsItem *itm = _serialiser->deserialise(item->data_bytes,&item->data_size) ;
RsMsgItem *mitm = dynamic_cast<RsMsgItem*>(itm) ;
if(mitm != NULL)
{
mitm->PeerId(hash) ;
handleIncomingItem(mitm) ;
}
else
{
std::cerr << "(EE) p3MsgService::receiveTurtleData(): received item is not a RsMsgItem!!" << std::endl;
delete itm ;
}
}
void p3MsgService::sendPrivateMsgItem(RsMsgItem *msgitem)
{
#ifdef DEBUG_DISTANT_MSG
std::cerr << "p3MsgService::sendDistanteMsgItem(): sending distant msg item to peer " << msgitem->PeerId() << std::endl;
std::cerr << " asking for tunnels" << std::endl;
std::cerr << " recording msg info" << std::endl;
#endif
const std::string& hash = msgitem->PeerId() ;
rsTurtle->monitorTunnels(hash,this) ; // create a tunnel for it, and put the msg on the waiting list.
{
RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/
// allocate a new contact. If it does not exist, set its tunnel state to DN
//
std::map<std::string,DistantMessengingContact>::iterator it = _messenging_contacts.find(hash) ;
DistantMessengingContact& contact( _messenging_contacts[hash] ) ;
if(it == _messenging_contacts.end())
it->second.status = RS_DISTANT_MSG_STATUS_TUNNEL_DN ;
contact.pending_messages.push_back(msgitem) ; // record the msg to be sent.
}
}

View File

@ -42,10 +42,12 @@
#include "services/p3service.h"
#include "serialiser/rsmsgitems.h"
#include "util/rsthreads.h"
#include "turtle/p3turtle.h"
#include "turtle/turtleclientservice.h"
class p3LinkMgr;
class p3MsgService: public p3Service, public p3Config, public pqiMonitor
class p3MsgService: public p3Service, public p3Config, public pqiMonitor, public RsTurtleClientService
{
public:
p3MsgService(p3LinkMgr *lm);
@ -55,6 +57,7 @@ bool getMessageSummaries(std::list<MsgInfoSummary> &msgList);
bool getMessage(const std::string &mid, MessageInfo &msg);
void getMessageCount(unsigned int *pnInbox, unsigned int *pnInboxNew, unsigned int *pnOutbox, unsigned int *pnDraftbox, unsigned int *pnSentbox, unsigned int *pnTrashbox);
bool decryptMessage(const std::string& mid) ;
bool removeMsgId(const std::string &mid);
bool markMsgIdRead(const std::string &mid, bool bUnreadByUser);
bool setMsgFlag(const std::string &mid, uint32_t flag, uint32_t mask);
@ -97,7 +100,51 @@ virtual void statusChange(const std::list<pqipeer> &plist);
int checkOutgoingMessages();
/*** Overloaded from pqiMonitor ***/
/*** overloaded from p3turtle ***/
void connectToTurtleRouter(p3turtle *) ;
struct DistantMessengingInvite
{
time_t time_of_validity ;
};
struct DistantMessengingContact
{
time_t last_hit_time ;
std::string virtual_peer_id ;
uint32_t status ;
std::vector<RsMsgItem*> pending_messages ;
};
bool createDistantOfflineMessengingInvite(time_t time_of_validity,TurtleFileHash& hash) ;
bool getDistantOfflineMessengingInvites(std::vector<DistantOfflineMessengingInvite>& invites) ;
void sendPrivateMsgItem(RsMsgItem *) ;
private:
// This maps contains the current invitations to respond to.
//
std::map<std::string,DistantMessengingInvite> _messenging_invites ;
// This contains the ongoing tunnel handling contacts.
//
std::map<std::string,DistantMessengingContact> _messenging_contacts ;
// Overloaded from RsTurtleClientService
virtual bool handleTunnelRequest(const std::string& hash,const std::string& peer_id) ;
virtual void receiveTurtleData(RsTurtleGenericTunnelItem *item,const std::string& hash,const std::string& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction) ;
void addVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&,RsTurtleGenericTunnelItem::Direction dir) ;
void removeVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&) ;
// Utility functions
bool encryptMessage(const std::string& pgp_id,RsMsgItem *msg) ;
void manageDistantPeers() ;
void sendTurtleData(const std::string& hash,RsMsgItem *) ;
void handleIncomingItem(RsMsgItem *) ;
p3turtle *mTurtle ;
uint32_t getNewUniqueMsgId();
int sendMessage(RsMsgItem *item);
@ -118,6 +165,7 @@ void initStandardTagTypes();
/* Mutex Required for stuff below */
RsMutex mMsgMtx;
RsMsgSerialiser *_serialiser ;
/* stored list of messages */
std::map<uint32_t, RsMsgItem *> imsg;

View File

@ -4,7 +4,7 @@ class MonitoredTurtleRouter: public p3turtle
{
public:
MonitoredTurtleRouter(p3LinkMgr *lmgr,ftServer *fts)
: p3turtle(lmgr,fts)
: p3turtle(lmgr)
{
}

View File

@ -172,7 +172,7 @@ void PeerNode::provideFileHash(const std::string& hash)
void PeerNode::manageFileHash(const std::string& hash)
{
_managed_hashes.insert(hash) ;
_turtle->monitorFileTunnels("file 1",hash,10000) ;
_turtle->monitorTunnels(hash,_ftserver) ;
}
void PeerNode::getTrafficInfo(NodeTrafficInfo& info)

View File

@ -47,6 +47,7 @@ class PeerNode
private:
p3ServiceServer *_service_server ;
MonitoredTurtleRouter *_turtle ;
ftServer *_ftserver ;
std::string _id ;
std::set<TurtleFileHash> _provided_hashes ;

View File

@ -9,8 +9,8 @@ OPS_TOP_DIR = ../../../../openpgpsdk/src
include $(RS_TOP_DIR)/tests/scripts/config.mk
###############################################################
TESTOBJ = dirtest.o sha1_test.o
TESTS = dirtest sha1_test
TESTOBJ = dirtest.o sha1_test.o aes_test.o dchat_decrypt.o
TESTS = dirtest sha1_test aes_test dchat_decrypt
all: tests
@ -18,6 +18,10 @@ sha1_test: sha1_test.o
$(CC) $(CFLAGS) -o sha1_test sha1_test.o $(LIBS)
dirtest: dirtest.o
$(CC) $(CFLAGS) -o dirtest dirtest.o $(LIBS)
dirtest: aes_test.o
$(CC) $(CFLAGS) -o aes_test aes_test.o $(LIBS)
dchat_decrypt: dchat_decrypt.o
$(CC) $(CFLAGS) -o dchat_decrypt dchat_decrypt.o $(LIBS)
###############################################################
include $(RS_TOP_DIR)/tests/scripts/rules.mk

View File

@ -0,0 +1,115 @@
/*
* "$Id: dirtest.cc,v 1.1 2007-02-19 20:08:30 rmf24 Exp $"
*
* RetroShare C++ Interface.
*
* Copyright 2012-2012 by Cyril Soler
*
* 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 "util/rsaes.h"
#include "util/utest.h"
#include <common/argstream.h>
#include <iostream>
#include <list>
#include <string>
#include <stdio.h>
void printHelp(int argc,char *argv[])
{
std::cerr << argv[0] << ": tests AES encryption/decryption functions." << std::endl;
std::cerr << "Usage: " << argv[0] << std::endl ;
}
void printHex(unsigned char *data,uint32_t length)
{
static const char outh[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' } ;
static const char outl[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' } ;
for(uint32_t j = 0; j < length; j++)
{
std::cerr << outh[ (data[j]>>4) ] ;
std::cerr << outh[ data[j] & 0xf ] ;
}
}
INITTEST() ;
int main(int argc,char *argv[])
{
std::string inputfile ;
argstream as(argc,argv) ;
as >> help() ;
as.defaultErrorHandling() ;
std::cerr << "Testing AES crypt" << std::endl;
std::string source_string = "This is a very secret string, but ultimately it will always be decyphered" ;
std::cerr << "Input string: length=" << source_string.length() << ", s=\"" << source_string << "\"" << std::endl;
unsigned char key_data[16] ;
unsigned char salt[8] ;
for(int i=0;i<16;++i)
key_data[i] = lrand48() & 0xff ;
std::cerr << "Key: " ; printHex(key_data,16);
std::cerr << std::endl;
for(int i=5;i<source_string.length();++i)
{
for(int j=0;j<8;++j)
salt[j] = lrand48() & 0xff ;
std::string S(source_string.c_str(),i) ;
unsigned char output_data[S.size() + 16] ;
uint32_t output_data_length = S.size() + 16 ;
CHECK(RsAES::aes_crypt_8_16( (const uint8_t*)S.c_str(),S.length(),key_data,salt,output_data,output_data_length)) ;
std::cerr << "Round " << i << " salt=" ;
printHex(salt,8) ;
std::cerr << ": real_length = " << S.length() << ", output_length = " << output_data_length << ", encrypted string = " ;
printHex(output_data,output_data_length) ;
std::cerr << std::endl;
unsigned char output_data2[output_data_length + 16] ;
uint32_t output_data_length2 = output_data_length + 16 ;
CHECK(RsAES::aes_decrypt_8_16(output_data,output_data_length,key_data,salt,output_data2,output_data_length2)) ;
std::cerr << " output_length = " << output_data_length2 << ", decrypted string = " ;
printHex(output_data2,output_data_length2) ;
std::cerr << std::endl;
CHECK(std::string( (const char *)output_data2,output_data_length2) == S) ;
}
FINALREPORT("AESTest") ;
return TESTRESULT() ;
}

File diff suppressed because it is too large Load Diff

View File

@ -150,6 +150,7 @@
#include "ft/ftsearch.h"
#include "retroshare/rsturtle.h"
#include "rsturtleitem.h"
#include "turtleclientservice.h"
#include "turtlestatistics.h"
//#define TUNNEL_STATISTICS
@ -191,15 +192,14 @@ class TurtleTunnel
// This class keeps trace of the activity for the file hashes the turtle router is asked to monitor.
//
class TurtleFileHashInfo
class TurtleHashInfo
{
public:
std::vector<TurtleTunnelId> tunnels ; // list of active tunnel ids for this file hash
TurtleRequestId last_request ; // last request for the tunnels of this hash
TurtleFileName name ;
time_t last_digg_time ;
uint64_t size ;
time_t last_digg_time ; // last time the tunnel digging happenned.
RsTurtleClientService *service ; // client service to which items should be sent. Never NULL.
};
// Subclassing:
@ -216,22 +216,25 @@ class TurtleFileHashInfo
class p3turtle: public p3Service, public RsTurtle, public p3Config
{
public:
p3turtle(p3LinkMgr *lm,ftServer *m);
p3turtle(p3LinkMgr *lm) ;
// Enables/disable the service. Still ticks, but does nothing. Default is true.
//
virtual void setEnabled(bool) ;
virtual bool enabled() const ;
// This is temporary, used by Operating Mode.
// This is temporary, used by Operating Mode.
// Turtle operates when both enabled() && sessionEnabled() are true.
virtual void setSessionEnabled(bool);
virtual bool sessionEnabled() const;
virtual void setSessionEnabled(bool);
virtual bool sessionEnabled() const;
// Lauches a search request through the pipes, and immediately returns
// the request id, which will be further used by the gui to store results
// as they come back.
//
// Eventually, search requests should be handled by client services. We will therefore
// remove the specific file search packets from the turtle router.
//
virtual TurtleSearchRequestId turtleSearch(const std::string& string_to_match) ;
virtual TurtleSearchRequestId turtleSearch(const LinearizedExpression& expr) ;
@ -247,12 +250,21 @@ class p3turtle: public p3Service, public RsTurtle, public p3Config
// This function should be called in addition to ftServer::FileRequest() so that the turtle router
// automatically provide tunnels for the file to download.
//
virtual void monitorFileTunnels(const std::string& name,const std::string& file_hash,uint64_t size) ;
virtual void monitorTunnels(const std::string& file_hash,RsTurtleClientService *client_service) ;
/// This should be called when canceling a file download, so that the turtle router stops
/// handling tunnels for this file.
///
virtual void stopMonitoringFileTunnels(const std::string& file_hash) ;
virtual void stopMonitoringTunnels(const std::string& file_hash) ;
/// Adds a client tunnel service. This means that the service will be added
/// to the list of services that might respond to tunnel requests.
/// Example tunnel services include:
///
/// p3ChatService: tunnels correspond to private distant chatting
/// ftServer : tunnels correspond to file data transfer
///
virtual void registerTunnelService(RsTurtleClientService *service) ;
/// get info about tunnels
virtual void getInfo(std::vector<std::vector<std::string> >&,
@ -277,7 +289,7 @@ class p3turtle: public p3Service, public RsTurtle, public p3Config
virtual bool saveList(bool& cleanup, std::list<RsItem*>&) ;
virtual bool loadList(std::list<RsItem*>& /*load*/) ;
/************* Communication with ftserver *******************/
/************* Communication with clients *******************/
/// Does the turtle router manages tunnels to this peer ? (this is not a
/// real id, but a fake one, that the turtle router is capable of connecting with a tunnel id).
virtual bool isTurtlePeer(const std::string& peer_id) const ;
@ -296,28 +308,7 @@ class p3turtle: public p3Service, public RsTurtle, public p3Config
void getVirtualPeersList(std::list<pqipeer>& list) ;
/// Send a data request into the correct tunnel for the given file hash
void sendDataRequest(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize) ;
/// Send file data into the correct tunnel for the given file hash
void sendFileData(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t baseoffset, uint32_t chunksize, void *data) ;
/// Send a request for the chunk map of this file to the given peer
void sendChunkMapRequest(const std::string& peerId, const std::string& hash,bool is_client) ;
/// Send a chunk map of this file to the given peer
void sendChunkMap(const std::string& peerId, const std::string& hash,const CompressedChunkMap& cmap,bool is_client) ;
/// Send a request for the crc32 map of this file to the given peer
void sendCRC32MapRequest(const std::string& peerId, const std::string& hash) ;
/// Send a crc32 map of this file to the given peer
void sendCRC32Map(const std::string& peerId, const std::string& hash,const CRC32Map& cmap) ;
/// Send a request for the CRC of a single chunk of this file to the given peer
void sendSingleChunkCRCRequest(const std::string& peerId, const std::string& hash,uint32_t chunk_number) ;
/// Send a crc32 map of this file to the given peer
void sendSingleChunkCRC(const std::string& peerId, const std::string& hash,uint32_t chunk_number,const Sha1CheckSum& sum) ;
void sendTurtleData(const std::string& virtual_peer_id, RsTurtleGenericTunnelItem *item) ;
private:
//--------------------------- Admin/Helper functions -------------------------//
@ -360,18 +351,14 @@ class p3turtle: public p3Service, public RsTurtle, public p3Config
void routeGenericTunnelItem(RsTurtleGenericTunnelItem *item) ;
/// specific routing functions for handling particular packets.
void handleRecvGenericTunnelItem(RsTurtleGenericTunnelItem *item);
bool getTunnelServiceInfo(TurtleTunnelId, std::string& virtual_peer_id, std::string& hash, RsTurtleClientService*&) ;
// following functions should go to ftServer
void handleSearchRequest(RsTurtleSearchRequestItem *item);
void handleSearchResult(RsTurtleSearchResultItem *item);
void handleTunnelRequest(RsTurtleOpenTunnelItem *item);
void handleTunnelResult(RsTurtleTunnelOkItem *item);
void handleRecvFileRequest(RsTurtleFileRequestItem *item);
void handleRecvFileData(RsTurtleFileDataItem *item);
void handleRecvFileMapRequest(RsTurtleFileMapRequestItem*);
void handleRecvFileMap(RsTurtleFileMapItem*);
void handleRecvFileCRC32MapRequest(RsTurtleFileCrcRequestItem*);
void handleRecvFileCRC32Map(RsTurtleFileCrcItem*);
void handleRecvChunkCRCRequest(RsTurtleChunkCrcRequestItem*);
void handleRecvChunkCRC(RsTurtleChunkCrcItem*);
//------ Functions connecting the turtle router to other components.----------//
@ -382,14 +369,13 @@ class p3turtle: public p3Service, public RsTurtle, public p3Config
void returnSearchResult(RsTurtleSearchResultItem *item) ;
/// Returns true if the file with given hash is hosted locally, and accessible in anonymous mode the supplied peer.
virtual bool performLocalHashSearch(const TurtleFileHash& hash,const std::string& client_peer_id,FileInfo& info) ;
virtual bool performLocalHashSearch(const TurtleFileHash& hash,const std::string& client_peer_id,RsTurtleClientService *& service);
//--------------------------- Local variables --------------------------------//
/* data */
p3LinkMgr *mLinkMgr;
ftServer *_ft_server ;
ftController *_ft_controller ;
RsTurtleSerialiser *_serialiser ;
mutable RsMutex mTurtleMtx;
@ -400,10 +386,10 @@ class p3turtle: public p3Service, public RsTurtle, public p3Config
std::map<TurtleTunnelRequestId,TurtleRequestInfo> _tunnel_requests_origins ;
/// stores adequate tunnels for each file hash locally managed
std::map<TurtleFileHash,TurtleFileHashInfo> _incoming_file_hashes ;
std::map<TurtleFileHash,TurtleHashInfo> _incoming_file_hashes ;
/// stores file info for each file we provide.
std::map<TurtleFileHash,FileInfo> _outgoing_file_hashes ;
std::map<TurtleFileHash,RsTurtleClientService *> _outgoing_file_hashes ;
/// local tunnels, stored by ids (Either transiting or ending).
std::map<TurtleTunnelId,TurtleTunnel > _local_tunnels ;
@ -414,6 +400,9 @@ class p3turtle: public p3Service, public RsTurtle, public p3Config
/// Hashes marked to be deleted.
std::vector<TurtleFileHash> _hashes_to_remove ;
/// List of client services that have regitered.
std::list<RsTurtleClientService*> _registered_services ;
time_t _last_clean_time ;
time_t _last_tunnel_management_time ;
time_t _last_tunnel_campaign_time ;

View File

@ -4,6 +4,7 @@
#include <iostream>
#include "turtletypes.h"
#include "rsturtleitem.h"
#include "turtleclientservice.h"
//#define P3TURTLE_DEBUG
// -----------------------------------------------------------------------------------//
@ -90,98 +91,14 @@ uint32_t RsTurtleTunnelOkItem::serial_size()
return s ;
}
uint32_t RsTurtleFileRequestItem::serial_size()
uint32_t RsTurtleGenericDataItem::serial_size()
{
uint32_t s = 0 ;
s += 8 ; // header
s += 4 ; // tunnel id
s += 8 ; // file offset
s += 4 ; // chunk size
return s ;
}
uint32_t RsTurtleFileDataItem::serial_size()
{
uint32_t s = 0 ;
s += 8 ; // header
s += 4 ; // tunnel id
s += 8 ; // file offset
s += 4 ; // chunk size
s += chunk_size ; // actual data size.
return s ;
}
uint32_t RsTurtleFileMapRequestItem::serial_size()
{
uint32_t s = 0 ;
s += 8 ; // header
s += 4 ; // tunnel id
s += 4 ; // direction
return s ;
}
uint32_t RsTurtleFileMapItem::serial_size()
{
uint32_t s = 0 ;
s += 8 ; // header
s += 4 ; // tunnel id
s += 4 ; // direction
s += 4 ; // compressed_map.size()
s += 4 * compressed_map._map.size() ;
return s ;
}
uint32_t RsTurtleFileCrcRequestItem::serial_size()
{
uint32_t s = 0 ;
s += 8 ; // header
s += 4 ; // tunnel id
return s ;
}
uint32_t RsTurtleChunkCrcItem::serial_size()
{
uint32_t s = 0 ;
s += 8 ; // header
s += 4 ; // tunnel id
s += 4 ; // chunk number
s += 20 ; // check_sum
return s ;
}
uint32_t RsTurtleChunkCrcRequestItem::serial_size()
{
uint32_t s = 0 ;
s += 8 ; // header
s += 4 ; // tunnel id
s += 4 ; // chunk number
return s ;
}
uint32_t RsTurtleFileCrcItem::serial_size()
{
uint32_t s = 0 ;
s += 8 ; // header
s += 4 ; // tunnel id
s += 4 ; // size of _map
s += 4 ; // size of _crcs
s += 4 * crc_map._crcs.size() ;
s += 4 * crc_map._ccmap._map.size() ;
s += 4 ; // data size
s += data_size ; // data
return s ;
}
@ -216,19 +133,21 @@ RsItem *RsTurtleSerialiser::deserialise(void *data, uint32_t *size)
case RS_TURTLE_SUBTYPE_SEARCH_RESULT : return new RsTurtleSearchResultItem(data,*size) ;
case RS_TURTLE_SUBTYPE_OPEN_TUNNEL : return new RsTurtleOpenTunnelItem(data,*size) ;
case RS_TURTLE_SUBTYPE_TUNNEL_OK : return new RsTurtleTunnelOkItem(data,*size) ;
case RS_TURTLE_SUBTYPE_FILE_REQUEST : return new RsTurtleFileRequestItem(data,*size) ;
case RS_TURTLE_SUBTYPE_FILE_DATA : return new RsTurtleFileDataItem(data,*size) ;
case RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST : return new RsTurtleFileMapRequestItem(data,*size) ;
case RS_TURTLE_SUBTYPE_FILE_MAP : return new RsTurtleFileMapItem(data,*size) ;
case RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST : return new RsTurtleFileCrcRequestItem(data,*size) ;
case RS_TURTLE_SUBTYPE_FILE_CRC : return new RsTurtleFileCrcItem(data,*size) ;
case RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST : return new RsTurtleChunkCrcRequestItem(data,*size) ;
case RS_TURTLE_SUBTYPE_CHUNK_CRC : return new RsTurtleChunkCrcItem(data,*size) ;
case RS_TURTLE_SUBTYPE_GENERIC_DATA : return new RsTurtleGenericDataItem(data,*size) ;
default:
std::cerr << "Unknown packet type in RsTurtle!" << std::endl ;
return NULL ;
break ;
}
// now try all client services
//
RsItem *item = NULL ;
for(uint32_t i=0;i<_client_services.size();++i)
if((item = _client_services[i]->deserialiseItem(data,*size)) != NULL)
return item ;
std::cerr << "Unknown packet type in RsTurtle (not even handled by client services)!" << std::endl ;
return NULL ;
#ifndef WINDOWS_SYS
}
catch(std::exception& e)
@ -240,224 +159,6 @@ RsItem *RsTurtleSerialiser::deserialise(void *data, uint32_t *size)
}
bool RsTurtleFileMapRequestItem::serialize(void *data,uint32_t& pktsize)
{
uint32_t tlvsize = serial_size();
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize);
/* skip the header */
offset += 8;
/* add mandatory parts first */
ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id);
ok &= setRawUInt32(data, tlvsize, &offset, direction);
if (offset != tlvsize)
{
ok = false;
#ifdef RSSERIAL_DEBUG
std::cerr << "RsFileConfigSerialiser::serialiseTransfer() Size Error! " << std::endl;
#endif
}
return ok;
}
bool RsTurtleFileMapItem::serialize(void *data,uint32_t& pktsize)
{
uint32_t tlvsize = serial_size();
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize);
/* skip the header */
offset += 8;
/* add mandatory parts first */
ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id);
ok &= setRawUInt32(data, tlvsize, &offset, direction);
ok &= setRawUInt32(data, tlvsize, &offset, compressed_map._map.size());
for(uint32_t i=0;i<compressed_map._map.size() && ok;++i)
ok &= setRawUInt32(data, tlvsize, &offset, compressed_map._map[i]);
if (offset != tlvsize)
{
ok = false;
#ifdef RSSERIAL_DEBUG
std::cerr << "RsFileConfigSerialiser::serialiseTransfer() Size Error! " << std::endl;
#endif
}
return ok;
}
bool RsTurtleFileCrcRequestItem::serialize(void *data,uint32_t& pktsize)
{
#ifdef P3TURTLE_DEBUG
std::cerr << "RsTurtleFileCrcRequestItem::serialize(): serializing packet:" << std::endl ;
print(std::cerr,2) ;
#endif
uint32_t tlvsize = serial_size();
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize);
/* skip the header */
offset += 8;
/* add mandatory parts first */
ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id);
if (offset != tlvsize)
{
ok = false;
std::cerr << "RsFileConfigSerialiser::serialiseTransfer() Size Error! " << std::endl;
}
return ok;
}
bool RsTurtleChunkCrcRequestItem::serialize(void *data,uint32_t& pktsize)
{
#ifdef P3TURTLE_DEBUG
std::cerr << "RsTurtleChunkCrcRequestItem::serialize(): serializing packet:" << std::endl ;
print(std::cerr,2) ;
#endif
uint32_t tlvsize = serial_size();
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize);
/* skip the header */
offset += 8;
/* add mandatory parts first */
ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id);
ok &= setRawUInt32(data, tlvsize, &offset, chunk_number);
if (offset != tlvsize)
{
ok = false;
std::cerr << "RsFileConfigSerialiser::serialiseTransfer() Size Error! " << std::endl;
}
return ok;
}
bool RsTurtleFileCrcItem::serialize(void *data,uint32_t& pktsize)
{
#ifdef P3TURTLE_DEBUG
std::cerr << "RsTurtleFileCrcItem::serialize(): serializing packet:" << std::endl ;
print(std::cerr,2) ;
#endif
uint32_t tlvsize = serial_size();
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize);
/* skip the header */
offset += 8;
/* add mandatory parts first */
ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id);
ok &= setRawUInt32(data, tlvsize, &offset, crc_map._ccmap._map.size());
ok &= setRawUInt32(data, tlvsize, &offset, crc_map._crcs.size());
for(uint32_t i=0;i<crc_map._ccmap._map.size() && ok;++i)
ok &= setRawUInt32(data, tlvsize, &offset, crc_map._ccmap._map[i]);
for(uint32_t i=0;i<crc_map._crcs.size() && ok;++i)
ok &= setRawUInt32(data, tlvsize, &offset, crc_map._crcs[i]);
if (offset != tlvsize)
{
ok = false;
std::cerr << "RsFileConfigSerialiser::serialiseTransfer() Size Error! " << std::endl;
}
return ok;
}
bool RsTurtleChunkCrcItem::serialize(void *data,uint32_t& pktsize)
{
#ifdef P3TURTLE_DEBUG
std::cerr << "RsTurtleChunkCrcRequestItem::serialize(): serializing packet:" << std::endl ;
print(std::cerr,2) ;
#endif
uint32_t tlvsize = serial_size();
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize);
/* skip the header */
offset += 8;
/* add mandatory parts first */
ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id);
ok &= setRawUInt32(data, tlvsize, &offset, chunk_number);
ok &= setRawUInt32(data, tlvsize, &offset, check_sum.fourbytes[0]);
ok &= setRawUInt32(data, tlvsize, &offset, check_sum.fourbytes[1]);
ok &= setRawUInt32(data, tlvsize, &offset, check_sum.fourbytes[2]);
ok &= setRawUInt32(data, tlvsize, &offset, check_sum.fourbytes[3]);
ok &= setRawUInt32(data, tlvsize, &offset, check_sum.fourbytes[4]);
if (offset != tlvsize)
{
ok = false;
std::cerr << "RsFileConfigSerialiser::serialiseTransfer() Size Error! " << std::endl;
}
return ok;
}
bool RsTurtleStringSearchRequestItem::serialize(void *data,uint32_t& pktsize)
{
uint32_t tlvsize = serial_size();
@ -648,169 +349,6 @@ bool RsTurtleSearchResultItem::serialize(void *data,uint32_t& pktsize)
return ok;
}
RsTurtleFileMapItem::RsTurtleFileMapItem(void *data,uint32_t pktsize)
: RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_MAP)
{
setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_MAP) ;
#ifdef P3TURTLE_DEBUG
std::cerr << " type = file map item" << std::endl ;
#endif
uint32_t offset = 8; // skip the header
/* add mandatory parts first */
bool ok = true ;
uint32_t s,d ;
ok &= getRawUInt32(data, pktsize, &offset, &tunnel_id);
ok &= getRawUInt32(data, pktsize, &offset, &d);
direction = d ;
ok &= getRawUInt32(data, pktsize, &offset, &s) ;
compressed_map._map.resize(s) ;
for(uint32_t i=0;i<s && ok;++i)
ok &= getRawUInt32(data, pktsize, &offset, &(compressed_map._map[i])) ;
#ifdef WINDOWS_SYS // No Exceptions in Windows compile. (drbobs).
#else
if (offset != pktsize)
throw std::runtime_error("Size error while deserializing.") ;
if (!ok)
throw std::runtime_error("Unknown error while deserializing.") ;
#endif
}
RsTurtleFileMapRequestItem::RsTurtleFileMapRequestItem(void *data,uint32_t pktsize)
: RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST)
{
setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_MAP_REQUEST) ;
#ifdef P3TURTLE_DEBUG
std::cerr << " type = file map request item" << std::endl ;
#endif
uint32_t offset = 8; // skip the header
/* add mandatory parts first */
bool ok = true ;
ok &= getRawUInt32(data, pktsize, &offset, &tunnel_id);
ok &= getRawUInt32(data, pktsize, &offset, &direction);
#ifdef WINDOWS_SYS // No Exceptions in Windows compile. (drbobs).
#else
if (offset != pktsize)
throw std::runtime_error("Size error while deserializing.") ;
if (!ok)
throw std::runtime_error("Unknown error while deserializing.") ;
#endif
}
RsTurtleFileCrcItem::RsTurtleFileCrcItem(void *data,uint32_t pktsize)
: RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_CRC)
{
setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_CRC) ;
#ifdef P3TURTLE_DEBUG
std::cerr << " type = file map item" << std::endl ;
#endif
uint32_t offset = 8; // skip the header
/* add mandatory parts first */
bool ok = true ;
uint32_t s1,s2 ;
ok &= getRawUInt32(data, pktsize, &offset, &tunnel_id);
ok &= getRawUInt32(data, pktsize, &offset, &s1) ;
ok &= getRawUInt32(data, pktsize, &offset, &s2) ;
crc_map._ccmap._map.resize(s1) ;
crc_map._crcs.resize(s2) ;
for(uint32_t i=0;i<s1 && ok;++i)
ok &= getRawUInt32(data, pktsize, &offset, &(crc_map._ccmap._map[i])) ;
for(uint32_t i=0;i<s2 && ok;++i)
ok &= getRawUInt32(data, pktsize, &offset, &(crc_map._crcs[i])) ;
#ifdef WINDOWS_SYS // No Exceptions in Windows compile. (drbobs).
#else
if (offset != pktsize)
throw std::runtime_error("Size error while deserializing.") ;
if (!ok)
throw std::runtime_error("Unknown error while deserializing.") ;
#endif
}
RsTurtleChunkCrcItem::RsTurtleChunkCrcItem(void *data,uint32_t pktsize)
: RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_CHUNK_CRC)
{
setPriorityLevel(QOS_PRIORITY_RS_TURTLE_CHUNK_CRC) ;
#ifdef P3TURTLE_DEBUG
std::cerr << " type = file map item" << std::endl ;
#endif
uint32_t offset = 8; // skip the header
/* add mandatory parts first */
bool ok = true ;
ok &= getRawUInt32(data, pktsize, &offset, &tunnel_id) ;
ok &= getRawUInt32(data, pktsize, &offset, &chunk_number) ;
ok &= getRawUInt32(data, pktsize, &offset, &check_sum.fourbytes[0]) ;
ok &= getRawUInt32(data, pktsize, &offset, &check_sum.fourbytes[1]) ;
ok &= getRawUInt32(data, pktsize, &offset, &check_sum.fourbytes[2]) ;
ok &= getRawUInt32(data, pktsize, &offset, &check_sum.fourbytes[3]) ;
ok &= getRawUInt32(data, pktsize, &offset, &check_sum.fourbytes[4]) ;
#ifdef WINDOWS_SYS // No Exceptions in Windows compile. (drbobs).
#else
if (offset != pktsize)
throw std::runtime_error("Size error while deserializing.") ;
if (!ok)
throw std::runtime_error("Unknown error while deserializing.") ;
#endif
}
RsTurtleFileCrcRequestItem::RsTurtleFileCrcRequestItem(void *data,uint32_t pktsize)
: RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST)
{
setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_CRC_REQUEST) ;
#ifdef P3TURTLE_DEBUG
std::cerr << " type = file map request item" << std::endl ;
#endif
uint32_t offset = 8; // skip the header
/* add mandatory parts first */
bool ok = true ;
ok &= getRawUInt32(data, pktsize, &offset, &tunnel_id);
#ifdef WINDOWS_SYS // No Exceptions in Windows compile. (drbobs).
#else
if (offset != pktsize)
throw std::runtime_error("Size error while deserializing.") ;
if (!ok)
throw std::runtime_error("Unknown error while deserializing.") ;
#endif
}
RsTurtleChunkCrcRequestItem::RsTurtleChunkCrcRequestItem(void *data,uint32_t pktsize)
: RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST)
{
setPriorityLevel(QOS_PRIORITY_RS_TURTLE_CHUNK_CRC_REQUEST) ;
#ifdef P3TURTLE_DEBUG
std::cerr << " type = file map item" << std::endl ;
#endif
uint32_t offset = 8; // skip the header
/* add mandatory parts first */
bool ok = true ;
ok &= getRawUInt32(data, pktsize, &offset, &tunnel_id) ;
ok &= getRawUInt32(data, pktsize, &offset, &chunk_number) ;
#ifdef WINDOWS_SYS // No Exceptions in Windows compile. (drbobs).
#else
if (offset != pktsize)
throw std::runtime_error("Size error while deserializing.") ;
if (!ok)
throw std::runtime_error("Unknown error while deserializing.") ;
#endif
}
RsTurtleSearchResultItem::RsTurtleSearchResultItem(void *data,uint32_t pktsize)
: RsTurtleItem(RS_TURTLE_SUBTYPE_SEARCH_RESULT)
{
@ -983,46 +521,12 @@ RsTurtleTunnelOkItem::RsTurtleTunnelOkItem(void *data,uint32_t pktsize)
#endif
}
bool RsTurtleFileRequestItem::serialize(void *data,uint32_t& pktsize)
RsTurtleGenericDataItem::RsTurtleGenericDataItem(void *data,uint32_t pktsize)
: RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_GENERIC_DATA)
{
uint32_t tlvsize = serial_size();
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize);
/* skip the header */
offset += 8;
/* add mandatory parts first */
ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id) ;
ok &= setRawUInt64(data, tlvsize, &offset, chunk_offset);
ok &= setRawUInt32(data, tlvsize, &offset, chunk_size);
if (offset != tlvsize)
{
ok = false;
#ifdef RSSERIAL_DEBUG
std::cerr << "RsTurtleTunnelOkItem::serialiseTransfer() Size Error! " << std::endl;
#endif
}
return ok;
}
RsTurtleFileRequestItem::RsTurtleFileRequestItem(void *data,uint32_t pktsize)
: RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_REQUEST)
{
setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_REQUEST) ;
setPriorityLevel(QOS_PRIORITY_RS_TURTLE_GENERIC_DATA) ;
#ifdef P3TURTLE_DEBUG
std::cerr << " type = file request" << std::endl ;
std::cerr << " type = tunnel ok" << std::endl ;
#endif
uint32_t offset = 8; // skip the header
uint32_t rssize = getRsItemSize(data);
@ -1030,12 +534,24 @@ RsTurtleFileRequestItem::RsTurtleFileRequestItem(void *data,uint32_t pktsize)
/* add mandatory parts first */
bool ok = true ;
ok &= getRawUInt32(data, pktsize, &offset, &tunnel_id) ;
ok &= getRawUInt64(data, pktsize, &offset, &chunk_offset);
ok &= getRawUInt32(data, pktsize, &offset, &chunk_size);
ok &= getRawUInt32(data, pktsize, &offset, &data_size);
#ifdef P3TURTLE_DEBUG
std::cerr << " tunnel_id=" << (void*)tunnel_id << ", chunk_offset=" << chunk_offset << ", chunk_size=" << chunk_size << std::endl ;
std::cerr << " request_id=" << (void*)request_id << ", tunnel_id=" << (void*)tunnel_id << std::endl ;
#endif
data_bytes = malloc(data_size) ;
if(data_bytes != NULL)
{
memcpy(data_bytes,data+offset,data_size) ;
offset += data_size ;
}
else
{
std::cerr << "(EE) RsTurtleGenericDataItem: Error. Cannot allocate data for a size of " << data_size << " bytes." <<std::endl;
offset = 0 ; // generate an error
}
#ifdef WINDOWS_SYS // No Exceptions in Windows compile. (drbobs).
UNREFERENCED_LOCAL_VARIABLE(rssize);
@ -1046,48 +562,8 @@ RsTurtleFileRequestItem::RsTurtleFileRequestItem(void *data,uint32_t pktsize)
throw std::runtime_error("RsTurtleTunnelOkItem::() unknown error while deserializing.") ;
#endif
}
RsTurtleFileDataItem::~RsTurtleFileDataItem()
{
free(chunk_data) ;
}
RsTurtleFileDataItem::RsTurtleFileDataItem(void *data,uint32_t pktsize)
: RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_DATA)
{
setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_DATA) ;
#ifdef P3TURTLE_DEBUG
std::cerr << " type = file request" << std::endl ;
#endif
uint32_t offset = 8; // skip the header
uint32_t rssize = getRsItemSize(data);
/* add mandatory parts first */
bool ok = true ;
ok &= getRawUInt32(data, pktsize, &offset, &tunnel_id) ;
ok &= getRawUInt64(data, pktsize, &offset, &chunk_offset);
ok &= getRawUInt32(data, pktsize, &offset, &chunk_size);
chunk_data = (void*)malloc(chunk_size) ;
memcpy(chunk_data,(void*)((unsigned char*)data+offset),chunk_size) ;
offset += chunk_size ;
#ifdef P3TURTLE_DEBUG
std::cerr << " tunnel_id=" << (void*)tunnel_id << ", chunk_offset=" << chunk_offset << ", chunk_size=" << chunk_size << std::endl ;
#endif
#ifdef WINDOWS_SYS // No Exceptions in Windows compile. (drbobs).
UNREFERENCED_LOCAL_VARIABLE(rssize);
#else
if (offset != rssize)
throw std::runtime_error("RsTurtleFileDataItem::() error while deserializing.") ;
if (!ok)
throw std::runtime_error("RsTurtleFileDataItem::() unknown error while deserializing.") ;
#endif
}
bool RsTurtleFileDataItem::serialize(void *data,uint32_t& pktsize)
bool RsTurtleGenericDataItem::serialize(void *data,uint32_t& pktsize)
{
uint32_t tlvsize = serial_size();
uint32_t offset = 0;
@ -1106,12 +582,11 @@ bool RsTurtleFileDataItem::serialize(void *data,uint32_t& pktsize)
/* add mandatory parts first */
ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id) ;
ok &= setRawUInt64(data, tlvsize, &offset, chunk_offset);
ok &= setRawUInt32(data, tlvsize, &offset, chunk_size);
ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id);
ok &= setRawUInt32(data, tlvsize, &offset, data_size);
memcpy((void*)((unsigned char*)data+offset),chunk_data,chunk_size) ;
offset += chunk_size ;
memcpy(data+offset,data_bytes,data_size) ;
offset += data_size ;
if (offset != tlvsize)
{
@ -1190,95 +665,13 @@ std::ostream& RsTurtleTunnelOkItem::print(std::ostream& o, uint16_t)
return o ;
}
std::ostream& RsTurtleFileRequestItem::print(std::ostream& o, uint16_t)
std::ostream& RsTurtleGenericDataItem::print(std::ostream& o, uint16_t)
{
o << "File request item:" << std::endl ;
o << "Generic Data item:" << std::endl ;
o << " tunnel id : " << std::hex << tunnel_id << std::dec << std::endl ;
o << " offset : " << chunk_offset << std::endl ;
o << " chunk size: " << chunk_size << std::endl ;
o << " Peer id : " << PeerId() << std::endl ;
o << " data size : " << data_size << std::endl ;
o << " data bytes: " << std::hex << (void*)data_bytes << std::dec << std::endl ;
return o ;
}
std::ostream& RsTurtleFileDataItem::print(std::ostream& o, uint16_t)
{
o << "File request item:" << std::endl ;
o << " tunnel id : " << std::hex << tunnel_id << std::dec << std::endl ;
o << " offset : " << chunk_offset << std::endl ;
o << " chunk size: " << chunk_size << std::endl ;
o << " data : " << std::hex << chunk_data << std::dec << std::endl ;
return o ;
}
std::ostream& RsTurtleFileMapItem::print(std::ostream& o, uint16_t)
{
o << "File map item:" << std::endl ;
o << " tunnel id : " << std::hex << tunnel_id << std::dec << std::endl ;
o << " direction : " << direction << std::endl ;
o << " map : " ;
for(uint32_t i=0;i<compressed_map._map.size();++i)
o << std::hex << compressed_map._map[i] << std::dec << std::endl ;
return o ;
}
std::ostream& RsTurtleFileMapRequestItem::print(std::ostream& o, uint16_t)
{
o << "File map request item:" << std::endl ;
o << " tunnel id : " << std::hex << tunnel_id << std::dec << std::endl ;
o << " direction : " << direction << std::endl ;
return o ;
}
std::ostream& RsTurtleFileCrcItem::print(std::ostream& o, uint16_t)
{
o << "File CRC item:" << std::endl ;
o << " tunnel id : " << std::hex << tunnel_id << std::dec << std::endl ;
o << " map : " ;
for(uint32_t i=0;i<crc_map._ccmap._map.size();++i)
o << std::hex << crc_map._ccmap._map[i] << std::endl ;
o << " CRC : " ;
for(uint32_t i=0;i<crc_map._crcs.size();++i)
o << std::hex << crc_map._crcs[i] << std::dec << std::endl ;
return o ;
}
std::ostream& RsTurtleFileCrcRequestItem::print(std::ostream& o, uint16_t)
{
o << "File CRC request item:" << std::endl ;
o << " tunnel id : " << std::hex << tunnel_id << std::dec << std::endl ;
return o ;
}
std::ostream& RsTurtleChunkCrcRequestItem::print(std::ostream& o, uint16_t)
{
o << "Chunk CRC request item:" << std::endl ;
o << " tunnel id : " << std::hex << tunnel_id << std::dec << std::endl ;
o << " chunk num : " << chunk_number << std::endl ;
return o ;
}
std::ostream& RsTurtleChunkCrcItem::print(std::ostream& o, uint16_t)
{
o << "Chunk CRC request item:" << std::endl ;
o << " tunnel id : " << std::hex << tunnel_id << std::dec << std::endl ;
o << " chunk num : " << chunk_number << std::endl ;
o << " sha1 sum : " << check_sum.toStdString() << std::endl ;
return o ;
}

View File

@ -18,6 +18,7 @@ const uint8_t RS_TURTLE_SUBTYPE_TUNNEL_CLOSED = 0x06 ;
const uint8_t RS_TURTLE_SUBTYPE_FILE_REQUEST = 0x07 ;
const uint8_t RS_TURTLE_SUBTYPE_FILE_DATA = 0x08 ;
const uint8_t RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST = 0x09 ;
const uint8_t RS_TURTLE_SUBTYPE_GENERIC_DATA = 0x0a ;
const uint8_t RS_TURTLE_SUBTYPE_FILE_MAP = 0x10 ;
const uint8_t RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST = 0x11 ;
const uint8_t RS_TURTLE_SUBTYPE_FILE_CRC = 0x12 ;
@ -171,32 +172,39 @@ class RsTurtleGenericTunnelItem: public RsTurtleItem
/// All tunnels derived from RsTurtleGenericTunnelItem should have a tunnel id to
/// indicate which tunnel they are travelling through.
virtual TurtleTunnelId tunnelId() const = 0 ;
virtual TurtleTunnelId tunnelId() const { return tunnel_id ; }
/// Indicate weither the packet is a client packet (goign back to the
/// client) or a server packet (going to the server. Typically file
/// requests are server packets, whereas file data are client packets.
virtual Direction travelingDirection() const = 0 ;
virtual Direction travelingDirection() const { return direction ; }
virtual void setTravelingDirection(Direction d) { direction = d; }
Direction direction ; // This does not need to be serialised. It's only used by the client services, optionnally,
// and is set by the turtle router according to which direction the item travels.
uint32_t tunnel_id ; // Id of the tunnel to travel through
};
/***********************************************************************************/
/* Turtle File Transfer item classes */
/* Specific Turtle Transfer items */
/***********************************************************************************/
class RsTurtleFileRequestItem: public RsTurtleGenericTunnelItem
// This item can be used by any service to pass-on arbitrary data into a tunnel.
//
class RsTurtleGenericDataItem: public RsTurtleGenericTunnelItem
{
public:
RsTurtleFileRequestItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_REQUEST) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_REQUEST);}
RsTurtleFileRequestItem(void *data,uint32_t size) ; // deserialization
RsTurtleGenericDataItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_GENERIC_DATA) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_REQUEST);}
RsTurtleGenericDataItem(void *data,uint32_t size) ; // deserialization
virtual bool shouldStampTunnel() const { return false ; }
virtual TurtleTunnelId tunnelId() const { return tunnel_id ; }
virtual Direction travelingDirection() const { return DIRECTION_SERVER ; }
virtual ~RsTurtleGenericDataItem() { if(data_bytes != NULL) free(data_bytes) ; }
uint32_t tunnel_id ; // id of the tunnel to travel through
uint64_t chunk_offset ;
uint32_t chunk_size ;
virtual bool shouldStampTunnel() const { return true ; }
uint32_t data_size ;
void *data_bytes ;
virtual std::ostream& print(std::ostream& o, uint16_t) ;
protected:
@ -204,154 +212,6 @@ class RsTurtleFileRequestItem: public RsTurtleGenericTunnelItem
virtual uint32_t serial_size() ;
};
class RsTurtleFileDataItem: public RsTurtleGenericTunnelItem
{
public:
RsTurtleFileDataItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_DATA) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_DATA) ;}
~RsTurtleFileDataItem() ;
RsTurtleFileDataItem(void *data,uint32_t size) ; // deserialization
virtual bool shouldStampTunnel() const { return true ; }
virtual TurtleTunnelId tunnelId() const { return tunnel_id ; }
virtual Direction travelingDirection() const { return DIRECTION_CLIENT ; }
uint32_t tunnel_id ; // id of the tunnel to travel through
uint64_t chunk_offset ; // offset in the file
uint32_t chunk_size ; // size of the file chunk
void *chunk_data ; // actual data.
virtual std::ostream& print(std::ostream& o, uint16_t) ;
virtual bool serialize(void *data,uint32_t& size) ;
virtual uint32_t serial_size() ;
};
class RsTurtleFileMapRequestItem: public RsTurtleGenericTunnelItem
{
public:
RsTurtleFileMapRequestItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_MAP_REQUEST) ;}
RsTurtleFileMapRequestItem(void *data,uint32_t size) ; // deserialization
virtual bool shouldStampTunnel() const { return false ; }
virtual TurtleTunnelId tunnelId() const { return tunnel_id ; }
virtual Direction travelingDirection() const { return direction ; }
Direction direction ; // travel direction for this packet (server/client)
uint32_t tunnel_id ; // id of the tunnel to travel through. Also used for identifying the file source
// this info from the file size, but this allows a security check.
virtual std::ostream& print(std::ostream& o, uint16_t) ;
virtual bool serialize(void *data,uint32_t& size) ;
virtual uint32_t serial_size() ;
};
class RsTurtleFileMapItem: public RsTurtleGenericTunnelItem
{
public:
RsTurtleFileMapItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_MAP) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_MAP) ;}
RsTurtleFileMapItem(void *data,uint32_t size) ; // deserialization
virtual bool shouldStampTunnel() const { return false ; }
virtual TurtleTunnelId tunnelId() const { return tunnel_id ; }
virtual Direction travelingDirection() const { return direction ; }
Direction direction ; // travel direction for this packet (server/client)
uint32_t tunnel_id ; // id of the tunnel to travel through. Also used for identifying the file source
// this info from the file size, but this allows a security check.
CompressedChunkMap compressed_map ; // Map info for the file in compressed format. Each *bit* in the array uint's says "I have" or "I don't have"
// by default, we suppose the peer has all the chunks. This info will thus be and-ed
// with the default file map for this source.
virtual std::ostream& print(std::ostream& o, uint16_t) ;
virtual bool serialize(void *data,uint32_t& size) ;
virtual uint32_t serial_size() ;
};
class RsTurtleFileCrcRequestItem: public RsTurtleGenericTunnelItem
{
public:
RsTurtleFileCrcRequestItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST) { setPriorityLevel(QOS_PRIORITY_RS_FILE_CRC_REQUEST);}
RsTurtleFileCrcRequestItem(void *data,uint32_t size) ; // deserialization
virtual bool shouldStampTunnel() const { return false ; }
virtual TurtleTunnelId tunnelId() const { return tunnel_id ; }
virtual Direction travelingDirection() const { return DIRECTION_SERVER ; }
uint32_t tunnel_id ; // id of the tunnel to travel through. Also used for identifying the file source
// this info from the file size, but this allows a security check.
virtual std::ostream& print(std::ostream& o, uint16_t) ;
virtual bool serialize(void *data,uint32_t& size) ;
virtual uint32_t serial_size() ;
};
class RsTurtleChunkCrcRequestItem: public RsTurtleGenericTunnelItem
{
public:
RsTurtleChunkCrcRequestItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST) { setPriorityLevel(QOS_PRIORITY_RS_CHUNK_CRC_REQUEST);}
RsTurtleChunkCrcRequestItem(void *data,uint32_t size) ; // deserialization
virtual bool shouldStampTunnel() const { return false ; }
virtual TurtleTunnelId tunnelId() const { return tunnel_id ; }
virtual Direction travelingDirection() const { return DIRECTION_SERVER ; }
uint32_t tunnel_id ; // id of the tunnel to travel through. Also used for identifying the file source
// this info from the file size, but this allows a security check.
uint32_t chunk_number ; // id of the chunk to CRC.
virtual std::ostream& print(std::ostream& o, uint16_t) ;
virtual bool serialize(void *data,uint32_t& size) ;
virtual uint32_t serial_size() ;
};
class RsTurtleFileCrcItem: public RsTurtleGenericTunnelItem
{
public:
RsTurtleFileCrcItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_CRC) { setPriorityLevel(QOS_PRIORITY_RS_FILE_CRC);}
RsTurtleFileCrcItem(void *data,uint32_t size) ; // deserialization
virtual bool shouldStampTunnel() const { return true ; }
virtual TurtleTunnelId tunnelId() const { return tunnel_id ; }
virtual Direction travelingDirection() const { return DIRECTION_CLIENT ; }
uint32_t tunnel_id ; // id of the tunnel to travel through. Also used for identifying the file source
// this info from the file size, but this allows a security check.
CRC32Map crc_map ;// Map info for the file in compressed format. Each *bit* in the array uint's says "I have" or "I don't have"
// by default, we suppose the peer has all the chunks. This info will thus be and-ed
// with the default file map for this source.
virtual std::ostream& print(std::ostream& o, uint16_t) ;
virtual bool serialize(void *data,uint32_t& size) ;
virtual uint32_t serial_size() ;
};
class RsTurtleChunkCrcItem: public RsTurtleGenericTunnelItem
{
public:
RsTurtleChunkCrcItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_CHUNK_CRC) { setPriorityLevel(QOS_PRIORITY_RS_CHUNK_CRC);}
RsTurtleChunkCrcItem(void *data,uint32_t size) ; // deserialization
virtual bool shouldStampTunnel() const { return true ; }
virtual TurtleTunnelId tunnelId() const { return tunnel_id ; }
virtual Direction travelingDirection() const { return DIRECTION_CLIENT ; }
uint32_t tunnel_id ; // id of the tunnel to travel through. Also used for identifying the file source
// this info from the file size, but this allows a security check.
uint32_t chunk_number ;
Sha1CheckSum check_sum ;
virtual std::ostream& print(std::ostream& o, uint16_t) ;
virtual bool serialize(void *data,uint32_t& size) ;
virtual uint32_t serial_size() ;
};
/***********************************************************************************/
/* Turtle Serialiser class */
/***********************************************************************************/
@ -370,5 +230,14 @@ class RsTurtleSerialiser: public RsSerialType
return dynamic_cast<RsTurtleItem *>(item)->serialize(data,*size) ;
}
virtual RsItem *deserialise (void *data, uint32_t *size) ;
// This is used by the turtle router to add services to its serialiser.
// Client services are only used for deserialising, since the serialisation is
// performed using the overloaded virtual functions above.
//
void registerClientService(RsTurtleClientService *service) { _client_services.push_back(service) ; }
private:
std::vector<RsTurtleClientService *> _client_services ;
};

View File

@ -0,0 +1,86 @@
/*
* libretroshare/src/services: turtleclientservice.h
*
* Services for RetroShare.
*
* Copyright 2013 by Cyril Soler
*
* 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 "csoler@users.sourceforge.net".
*
*/
// This class is the parent class for any service that will use the turtle router to distribute its packets.
// Typical representative clients include:
//
// p3ChatService: opens tunnels to distant peers for chatting
// ftServer: searches and open tunnels to distant sources for file transfer
//
#pragma once
#include <string>
#include <stdlib.h>
#include <serialiser/rsserial.h>
#include <turtle/rsturtleitem.h>
class RsItem ;
class RsTurtleClientService
{
public:
// Handling of tunnel request for the given hash. Most of the time, it's a search in a predefined list.
// The output info_string is used by the turtle router to display info about tunnels it manages. It is
// not passed to the tunnel.
virtual bool handleTunnelRequest(const std::string& hash,const std::string& peer_id) { return false ; }
// This method is called by the turtle router to send data that comes out of a turtle tunnel.
// The turtle router stays responsible for the memory management of data. Most of the time the
// data chunk is a serialized item to be de-serialized by the client service.
//
// Parameters:
// virtual_peer_id : name of the tunnel that sent the data
// data : memory chunk for the data
// size : size of data
// item->direction : direction of travel:
// RsTurtleGenericTunnelItem::DIRECTION_CLIENT: the service is acting as a client
// RsTurtleGenericTunnelItem::DIRECTION_CLIENT: the service is acting as a server
//
// Most of the time this parameter is not used by services, except when some info (such as chunk maps, chat items, etc) go
// both ways, and their nature cannot suffice to determine where they should be handled.
//
// By default (if not overloaded), the method will just free the data, as any subclass should do as well.
// Note: p3turtle stays owner of the item, so the client should not delete it!
//
virtual void receiveTurtleData(RsTurtleGenericTunnelItem *item,const std::string& hash,const std::string& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction)
{
std::cerr << "!!!!!! Received Data from turtle router, but the client service is not handling it !!!!!!!!!!" << std::endl ;
}
// Method for deserialising specific items of the client service. The
// method has a default behavior of not doing anything, since most client
// services might only use the generic item already provided by the turtle
// router: RsTurtleGenericDataItem
virtual RsTurtleGenericTunnelItem *deserialiseItem(void *data, uint32_t size) const { return NULL ; }
// These methods are called by the turtle router to add/remove virtual peers when tunnels are created/deleted
//
virtual void addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir) = 0 ;
virtual void removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) = 0 ;
};

View File

@ -0,0 +1,138 @@
/*
* libretroshare/src/utils: rsaes.cc
*
* AES crptography for RetroShare.
*
* Copyright 2013 by Cyril Soler
*
* 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 "csoler@users.sourceforge.net".
*
*/
#include <iostream>
#include <openssl/evp.h>
#include <openssl/aes.h>
#include "rsaes.h"
uint32_t RsAES::get_buffer_size(uint32_t n)
{
return n + AES_BLOCK_SIZE ;
}
bool RsAES::aes_crypt_8_16(const uint8_t *input_data,uint32_t input_data_length,uint8_t key_data[16],uint8_t salt[8],uint8_t *output_data,uint32_t& output_data_length)
{
int nrounds = 5;
uint8_t key[32], iv[32];
/*
* Gen key & IV for AES 256 CBC mode. A SHA1 digest is used to hash the supplied key material.
* nrounds is the number of times the we hash the material. More rounds are more secure but
* slower.
*/
int i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), salt, key_data, 16, nrounds, key, iv);
if (i != 32)
{
printf("Key size is %d bits - should be 256 bits\n", i);
return false ;
}
EVP_CIPHER_CTX e_ctx ;
EVP_CIPHER_CTX_init(&e_ctx);
EVP_EncryptInit_ex(&e_ctx, EVP_aes_256_cbc(), NULL, key, iv);
/* max ciphertext len for a n bytes of plaintext is n + AES_BLOCK_SIZE -1 bytes */
int c_len = input_data_length + AES_BLOCK_SIZE ;
int f_len = 0;
if(output_data_length < (uint32_t)c_len)
return false ;
/* update ciphertext, c_len is filled with the length of ciphertext generated,
*len is the size of plaintext in bytes */
if(!EVP_EncryptUpdate(&e_ctx, output_data, &c_len, input_data, input_data_length))
{
std::cerr << "RsAES: decryption failed at end. Check padding." << std::endl;
return false ;
}
/* update ciphertext with the final remaining bytes */
if(!EVP_EncryptFinal_ex(&e_ctx, output_data+c_len, &f_len))
{
std::cerr << "RsAES: decryption failed at end. Check padding." << std::endl;
return false ;
}
output_data_length = c_len + f_len;
return true;
}
bool RsAES::aes_decrypt_8_16(const uint8_t *input_data,uint32_t input_data_length,uint8_t key_data[16],uint8_t salt[8],uint8_t *output_data,uint32_t& output_data_length)
{
int nrounds = 5;
uint8_t key[32], iv[32];
/*
* Gen key & IV for AES 256 CBC mode. A SHA1 digest is used to hash the supplied key material.
* nrounds is the number of times the we hash the material. More rounds are more secure but
* slower.
*/
int i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), salt, key_data, 16, nrounds, key, iv);
if (i != 32)
{
printf("Key size is %d bits - should be 256 bits\n", i);
return false ;
}
EVP_CIPHER_CTX e_ctx ;
EVP_CIPHER_CTX_init(&e_ctx);
EVP_DecryptInit_ex(&e_ctx, EVP_aes_256_cbc(), NULL, key, iv);
/* max ciphertext len for a n bytes of plaintext is n + AES_BLOCK_SIZE -1 bytes */
int c_len = input_data_length + AES_BLOCK_SIZE ;
int f_len = 0;
if(output_data_length < (uint32_t)c_len)
return false ;
output_data_length = c_len ;
/* update ciphertext, c_len is filled with the length of ciphertext generated,
*len is the size of plaintext in bytes */
if(! EVP_DecryptUpdate(&e_ctx, output_data, &c_len, input_data, input_data_length))
{
std::cerr << "RsAES: decryption failed." << std::endl;
return false ;
}
/* update ciphertext with the final remaining bytes */
if(!EVP_DecryptFinal_ex(&e_ctx, output_data+c_len, &f_len))
{
std::cerr << "RsAES: decryption failed at end. Check padding." << std::endl;
return false ;
}
output_data_length = c_len + f_len;
return true;
}

View File

@ -0,0 +1,47 @@
/*
* libretroshare/src/utils: rsaescrypt.h
*
* AES crptography for RetroShare.
*
* Copyright 2013 by Cyril Soler
*
* 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 "csoler@users.sourceforge.net".
*
*/
#include <stdint.h>
class RsAES
{
public:
// Crypt/decrypt data using a 16 bytes key and a 8 bytes salt.
//
// output_data allocation is left to the client. The size should be at least RsAES::get_buffer_size(input_data_length)
//
// Return value:
// true: encryption/decryption ok
//
// false: encryption/decryption went bad. Check buffer size.
//
static bool aes_crypt_8_16(const uint8_t *input_data,uint32_t input_data_length,uint8_t key[16],uint8_t salt[8],uint8_t *output_data,uint32_t& output_data_length) ;
static bool aes_decrypt_8_16(const uint8_t *input_data,uint32_t input_data_length,uint8_t key[16],uint8_t salt[8],uint8_t *output_data,uint32_t& output_data_length) ;
// computes the safe buffer size to store encrypted/decrypted data for the given input stream size
//
static uint32_t get_buffer_size(uint32_t size) ;
};

View File

@ -51,6 +51,10 @@ bool RSRandom::seed(uint32_t s)
return true ;
}
void RSRandom::random_bytes(unsigned char *data,uint32_t size)
{
RAND_bytes(data,size) ;
}
void RSRandom::locked_next_state()
{
#ifdef RSRANDOM_USE_SSL

View File

@ -46,6 +46,7 @@ class RSRandom
static bool seed(uint32_t s) ;
static std::string random_alphaNumericString(uint32_t length) ;
static void random_bytes(unsigned char *data,uint32_t length) ;
private:
static RsMutex rndMtx ;

View File

@ -49,8 +49,8 @@ AudioPopupChatDialog::AudioPopupChatDialog(QWidget *parent)
connect(audioListenToggleButton, SIGNAL(clicked()), this , SLOT(toggleAudioListen()));
connect(audioMuteCaptureToggleButton, SIGNAL(clicked()), this , SLOT(toggleAudioMuteCapture()));
addButton(audioListenToggleButton) ;
addButton(audioMuteCaptureToggleButton) ;
addChatBarWidget(audioListenToggleButton) ;
addChatBarWidget(audioMuteCaptureToggleButton) ;
//ui.chatWidget->resetStatusBar();

View File

@ -0,0 +1,226 @@
/****************************************************************
* RetroShare is distributed under the following license:
*
* Copyright (C) 2013 Cyril Soler
*
* This program is free software; you can redistribute it and/or
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
****************************************************************/
#include <iostream>
#include <QMessageBox>
#include <QTimer>
#include <retroshare/rsmsgs.h>
#include <retroshare/rspeers.h>
#include "CreateMsgLinkDialog.h"
#include <gui/common/FriendSelectionWidget.h>
#include <gui/RetroShareLink.h>
CreateMsgLinkDialog::CreateMsgLinkDialog(QWidget *parent)
:QDialog(NULL, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint)
{
/* Invoke the Qt Designer generated object setup routine */
setupUi(this);
setAttribute(Qt::WA_DeleteOnClose, false);
_info_GB->layout()->addWidget( _gpg_selection = new FriendSelectionWidget(this) ) ;
QObject::connect(_link_type_CB,SIGNAL(currentIndexChanged(int)),this,SLOT(update())) ;
QObject::connect(_create_link_PB,SIGNAL(clicked()),this,SLOT(createLink())) ;
QObject::connect(_create_new_PB,SIGNAL(toggled(bool)),this,SLOT(toggleCreateLink(bool))) ;
QObject::connect(_existing_links_LW,SIGNAL(currentRowChanged(int)),this,SLOT(updateCurrentRow(int))) ;
_gpg_selection->setModus(FriendSelectionWidget::MODUS_SINGLE) ;
_gpg_selection->setShowType(FriendSelectionWidget::SHOW_NON_FRIEND_GPG | FriendSelectionWidget::SHOW_GPG) ;
_gpg_selection->setHeaderText(QObject::tr("Select who can contact you:")) ;
_gpg_selection->start() ;
toggleCreateLink(false) ;
update() ;
updateCurrentRow(-1) ;
}
void CreateMsgLinkDialog::updateCurrentRow(int r)
{
if(r < 0)
{
_current_link_type_LE->setText("") ;
_current_link_dst_LE->setText("") ;
_current_link_date_DE->setDateTime(QDateTime::fromMSecsSinceEpoch(0)) ;
return ;
}
QUrl text = _existing_links_LW->item(r)->data(Qt::UserRole).toUrl() ;
std::cerr << "Parsing link : " << text.toString().toStdString() << std::endl;
RetroShareLink link(text) ;
if( link.type() == RetroShareLink::TYPE_PRIVATE_CHAT )
_current_link_type_LE->setText( tr("Private chat invite") ) ;
else
_current_link_type_LE->setText( tr("Public message invite") ) ;
_current_link_dst_LE->setText(link.GPGId()) ;
_current_link_date_DE->setDateTime(QDateTime::fromMSecsSinceEpoch(link.timeStamp() * 1000 )) ;
}
void CreateMsgLinkDialog::toggleCreateLink(bool b)
{
_new_link_F->setHidden(!b) ;
}
void CreateMsgLinkDialog::update()
{
if(_link_type_CB->currentIndex() == 0)
{
QString s ;
s += "A private chat invite allows a specific peer to contact you using encrypted private chat. You need to select a destination peer from your PGP keyring before creating the link. The link contains the encryption code and your PGP signature, so that the peer can authenticate you." ;
_info_TB->setHtml(s) ;
_gpg_selection->setHidden(false) ;
}
else
{
QString s ;
s += "A public message link allows any peer in the nearby network to send a private message to you. The message is encrypted and only you can read it." ;
_info_TB->setHtml(s) ;
_gpg_selection->setHidden(true) ;
}
std::vector<DistantChatInviteInfo> invites ;
rsMsgs->getDistantChatInviteList(invites) ;
_existing_links_LW->clear() ;
for(uint32_t i=0;i<invites.size();++i)
{
RetroShareLink link ;
if(!link.createPrivateChatInvite(invites[i].time_of_validity,QString::fromStdString(invites[i].destination_pgp_id),QString::fromStdString(invites[i].encrypted_radix64_string)));
std::cerr << "Cannot create link." << std::endl;
QListWidgetItem *item = new QListWidgetItem;
item->setData(Qt::DisplayRole,tr("Private chat invite to ")+QString::fromStdString(invites[i].destination_pgp_id)) ;
item->setData(Qt::UserRole,link.toString()) ;
_existing_links_LW->insertItem(0,item) ;
}
std::vector<DistantOfflineMessengingInvite> invites2 ;
rsMsgs->getDistantOfflineMessengingInvites(invites2) ;
for(uint32_t i=0;i<invites2.size();++i)
{
RetroShareLink link ;
if(!link.createPublicMsgInvite(invites2[i].time_of_validity,QString::fromStdString(invites2[i].issuer_pgp_id),QString::fromStdString(invites2[i].hash)))
std::cerr << "Cannot create link." << std::endl;
else
{
QListWidgetItem *item = new QListWidgetItem;
item->setData(Qt::DisplayRole,tr("Public message link")) ;
item->setData(Qt::UserRole,link.toString()) ;
_existing_links_LW->insertItem(0,item) ;
}
}
}
time_t CreateMsgLinkDialog::computeValidityDuration() const
{
time_t unit ;
switch(_validity_time_CB->currentIndex())
{
default:
case 0: unit = 3600 ;
break ;
case 1: unit = 3600*24 ;
break ;
case 2: unit = 3600*24*7 ;
break ;
case 3: unit = 3600*24*30 ;
break ;
case 4: unit = 3600*24*365 ;
break ;
}
return unit * _validity_time_SB->value() ;
}
void CreateMsgLinkDialog::createLink()
{
std::cerr << "Creating link!" << std::endl;
if(_link_type_CB->currentIndex() == 0)
{
time_t validity_duration = computeValidityDuration() ;
FriendSelectionWidget::IdType type ;
std::string current_pgp_id = _gpg_selection->selectedId(type) ;
std::string encrypted_string ;
bool res = rsMsgs->createDistantChatInvite(current_pgp_id,validity_duration,encrypted_string) ;
RetroShareLink link ;
if(!link.createPrivateChatInvite(validity_duration + time(NULL),QString::fromStdString(current_pgp_id),QString::fromStdString(encrypted_string)) )
std::cerr << "Cannot create link." << std::endl;
QList<RetroShareLink> links ;
links.push_back(link) ;
RSLinkClipboard::copyLinks(links) ;
if(!res)
QMessageBox::critical(NULL,tr("Private chat invite creation failed"),tr("The creation of the chat invite failed")) ;
else
QMessageBox::information(NULL,tr("Private chat invite created"),tr("Your new chat invite has been copied to clipboard. You can now paste it as a Retroshare link.")) ;
}
else
{
time_t validity_duration = computeValidityDuration() ;
std::string hash;
std::string issuer_pgp_id = rsPeers->getGPGOwnId() ;
bool res = rsMsgs->createDistantOfflineMessengingInvite(validity_duration,hash) ;
RetroShareLink link ;
if(!link.createPublicMsgInvite(validity_duration + time(NULL),QString::fromStdString(issuer_pgp_id),QString::fromStdString(hash)) )
{
std::cerr << "Cannot create link." << std::endl;
return ;
}
QList<RetroShareLink> links ;
links.push_back(link) ;
RSLinkClipboard::copyLinks(links) ;
if(!res)
QMessageBox::critical(NULL,tr("Messenging invite creation failed"),tr("The creation of the messenging invite failed")) ;
else
QMessageBox::information(NULL,tr("Messenging invite created"),tr("Your new messenging chat invite has been copied to clipboard. You can now paste it as a Retroshare link.")) ;
}
QTimer::singleShot(100,this,SLOT(update())) ;
}

View File

@ -0,0 +1,53 @@
/****************************************************************
* RetroShare is distributed under the following license:
*
* Copyright (C) 2008 Robert Fernie
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
******************************************************************/
#pragma once
#include "ui_CreateMsgLinkDialog.h"
class FriendSelectionWidget ;
class CreateMsgLinkDialog : public QDialog, public Ui::CreateMsgLinkDialog
{
Q_OBJECT
public:
CreateMsgLinkDialog(QWidget *parent = NULL);
virtual ~CreateMsgLinkDialog() {}
private slots:
/* actions to take.... */
void createLink();
void update() ;
void toggleCreateLink(bool) ;
void updateCurrentRow(int) ;
private:
time_t computeValidityDuration() const ;
/** Qt Designer generated object */
FriendSelectionWidget *_gpg_selection ;
};

View File

@ -0,0 +1,220 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CreateMsgLinkDialog</class>
<widget class="QDialog" name="CreateMsgLinkDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>565</width>
<height>465</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QListWidget" name="_existing_links_LW">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Valid until:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Type:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_7">
<property name="text">
<string>Usable by:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QDateTimeEdit" name="_current_link_date_DE"/>
</item>
<item>
<widget class="QLineEdit" name="_current_link_type_LE"/>
</item>
<item>
<widget class="QLineEdit" name="_current_link_dst_LE"/>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>Copy to clipboard</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="_create_new_PB">
<property name="text">
<string>Create new</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QFrame" name="_new_link_F">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Invite type:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="_link_type_CB">
<item>
<property name="text">
<string>Private chat</string>
</property>
</item>
<item>
<property name="text">
<string>Public message</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Validity time :</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="_validity_time_SB">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>30</number>
</property>
<property name="value">
<number>5</number>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="_validity_time_CB">
<item>
<property name="text">
<string>hour</string>
</property>
</item>
<item>
<property name="text">
<string>day</string>
</property>
</item>
<item>
<property name="text">
<string>week</string>
</property>
</item>
<item>
<property name="text">
<string>month</string>
</property>
</item>
<item>
<property name="text">
<string>year</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QPushButton" name="_create_link_PB">
<property name="text">
<string>Create!</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="_info_GB">
<property name="title">
<string>Information</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextBrowser" name="_info_TB"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -23,6 +23,7 @@
#include <QShortcut>
#include <QTimer>
#include <QDateTime>
#include <QMessageBox>
#include <QKeyEvent>
#include "MessagesDialog.h"
@ -118,8 +119,8 @@ MessagesDialog::MessagesDialog(QWidget *parent)
inChange = false;
lockUpdate = 0;
connect(ui.messagestreeView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(messageslistWidgetCostumPopupMenu(QPoint)));
connect(ui.listWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(folderlistWidgetCostumPopupMenu(QPoint)));
connect(ui.messagestreeView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(messageslistWidgetCustomPopupMenu(QPoint)));
connect(ui.listWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(folderlistWidgetCustomPopupMenu(QPoint)));
connect(ui.messagestreeView, SIGNAL(clicked(const QModelIndex&)) , this, SLOT(clicked(const QModelIndex&)));
connect(ui.messagestreeView, SIGNAL(doubleClicked(const QModelIndex&)) , this, SLOT(doubleClicked(const QModelIndex&)));
connect(ui.listWidget, SIGNAL(currentRowChanged(int)), this, SLOT(changeBox(int)));
@ -507,7 +508,7 @@ bool MessagesDialog::hasMessageStar(int nRow)
return item->data(ROLE_MSGFLAGS).toInt() & RS_MSG_STAR;
}
void MessagesDialog::messageslistWidgetCostumPopupMenu( QPoint /*point*/ )
void MessagesDialog::messageslistWidgetCustomPopupMenu( QPoint /*point*/ )
{
std::string cid;
std::string mid;
@ -587,6 +588,9 @@ void MessagesDialog::messageslistWidgetCostumPopupMenu( QPoint /*point*/ )
action->setDisabled(true);
}
if(nCount==1 && (msgInfo.msgflags & RS_MSG_ENCRYPTED))
action = contextMnu.addAction(QIcon(IMAGE_SYSTEM), tr("Decrypt Message"), this, SLOT(decryptSelectedMsg()));
int listrow = ui.listWidget->currentRow();
if (listrow == ROW_TRASHBOX) {
action = contextMnu.addAction(tr("Undelete"), this, SLOT(undeletemessage()));
@ -605,7 +609,7 @@ void MessagesDialog::messageslistWidgetCostumPopupMenu( QPoint /*point*/ )
contextMnu.exec(QCursor::pos());
}
void MessagesDialog::folderlistWidgetCostumPopupMenu(QPoint /*point*/)
void MessagesDialog::folderlistWidgetCustomPopupMenu(QPoint /*point*/)
{
if (ui.listWidget->currentRow() != ROW_TRASHBOX) {
/* Context menu only neede for trash box */
@ -1112,7 +1116,11 @@ void MessagesDialog::insertMessages()
}
// Subject
text = QString::fromStdWString(it->title);
if(it->msgflags & RS_MSG_ENCRYPTED)
text = tr("Encrypted message. Right-click to decrypt it.") ;
else
text = QString::fromStdWString(it->title);
item[COLUMN_SUBJECT]->setText(text);
item[COLUMN_SUBJECT]->setData(text + dateString, ROLE_SORT);
@ -1464,6 +1472,28 @@ void MessagesDialog::insertMsgTxtAndFiles(QModelIndex Index, bool bSetToRead)
updateInterface();
}
void MessagesDialog::decryptSelectedMsg()
{
MessageInfo msgInfo;
if (!rsMsgs->getMessage(mCurrMsgId, msgInfo))
return ;
if(!msgInfo.msgflags & RS_MSG_ENCRYPTED)
{
std::cerr << "This message is not encrypted! Cannot decrypt!" << std::endl;
return ;
}
if(!rsMsgs->decryptMessage(mCurrMsgId) )
QMessageBox::warning(NULL,tr("Decryption failed!"),tr("This message could not be decrypted.")) ;
//setMsgAsReadUnread(currentIndex.row(), true);
updateMessageSummaryList();
insertMessages();
insertMsgTxtAndFiles();
}
bool MessagesDialog::getCurrentMsg(std::string &cid, std::string &mid)
{
QModelIndex currentIndex = ui.messagestreeView->currentIndex();

View File

@ -60,8 +60,9 @@ public slots:
private slots:
/** Create the context popup menu and it's submenus */
void messageslistWidgetCostumPopupMenu( QPoint point );
void folderlistWidgetCostumPopupMenu(QPoint);
void messageslistWidgetCustomPopupMenu( QPoint point );
void folderlistWidgetCustomPopupMenu(QPoint);
void decryptSelectedMsg() ;
void changeBox(int newrow);
void changeQuickView(int newrow);

View File

@ -28,6 +28,7 @@
#include <retroshare/rsiface.h>
#include <retroshare/rspeers.h>
#include <retroshare/rsdisc.h>
#include <retroshare/rsmsgs.h>
#include "common/vmessagebox.h"
#include "common/RSTreeWidgetItem.h"
@ -230,7 +231,10 @@ void NetworkDialog::connecttreeWidgetCostumPopupMenu( QPoint /*point*/ )
contextMnu->addAction(QIcon(IMAGE_PEERDETAILS), tr("Peer details..."), this, SLOT(peerdetails()));
contextMnu->addAction(QIcon(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copyLink()));
contextMnu->addSeparator() ;
#ifdef ENABLE_DISTANT_CHAT_AND_MSGS
contextMnu->addAction(QIcon(IMAGE_COPYLINK), tr("Create a distant chat invitation..."), this, SLOT(createChatLink()));
contextMnu->addSeparator() ;
#endif
contextMnu->addAction(QIcon(IMAGE_CLEAN_UNUSED), tr("Remove unused keys..."), this, SLOT(removeUnusedKeys()));
contextMnu->exec(QCursor::pos());
@ -330,6 +334,19 @@ void NetworkDialog::makeFriend()
ConfCertDialog::showIt(getCurrentNeighbour()->text(COLUMN_PEERID).toStdString(), ConfCertDialog::PageTrust);
}
void NetworkDialog::createChatLink()
{
std::string pgp_id = getCurrentNeighbour()->text(COLUMN_PEERID).toStdString() ;
std::cerr << "Creating chat link for pgp id " << pgp_id << std::endl;
std::string hash,estr ;
rsMsgs->createDistantChatInvite(pgp_id,time(NULL)+3600,estr) ;
std::cerr << "Created invite:" << std::endl;
std::cerr << " estr = " << estr << std::endl;
}
/** Shows Peer Information/Auth Dialog */
void NetworkDialog::peerdetails()
{

View File

@ -69,6 +69,7 @@ private slots:
void removeUnusedKeys() ;
void makeFriend() ;
void denyFriend() ;
void createChatLink() ;
void deleteCert() ;
void peerdetails();
void copyLink();

View File

@ -71,7 +71,7 @@ static NewsFeed *instance = NULL;
/** Constructor */
NewsFeed::NewsFeed(QWidget *parent)
: MainPage (parent)
: RsAutoUpdatePage(1000,parent)
{
/* Invoke the Qt Designer generated object setup routine */
setupUi(this);
@ -83,9 +83,9 @@ NewsFeed::NewsFeed(QWidget *parent)
connect(removeAllButton, SIGNAL(clicked()), this, SLOT(removeAll()));
connect(feedOptionsButton, SIGNAL(clicked()), this, SLOT(feedoptions()));
QTimer *timer = new QTimer(this);
timer->connect(timer, SIGNAL(timeout()), this, SLOT(updateFeed()));
timer->start(1000);
// QTimer *timer = new QTimer(this);
// timer->connect(timer, SIGNAL(timeout()), this, SLOT(updateFeed()));
// timer->start(1000);
}
NewsFeed::~NewsFeed()
@ -95,7 +95,7 @@ NewsFeed::~NewsFeed()
}
}
void NewsFeed::updateFeed()
void NewsFeed::updateDisplay()
{
if (!rsNotify)
return;

View File

@ -26,6 +26,7 @@
#include "ui_NewsFeed.h"
#include "gui/feeds/FeedHolder.h"
#include <retroshare-gui/RsAutoUpdatePage.h>
class RsFeedItem;
class ForumNewItem;
@ -33,7 +34,7 @@ class ChanMsgItem;
class ChatMsgItem;
class FeedNotify;
class NewsFeed : public MainPage, public FeedHolder, private Ui::NewsFeed
class NewsFeed : public RsAutoUpdatePage, public FeedHolder, private Ui::NewsFeed
{
Q_OBJECT
@ -52,6 +53,7 @@ public:
static void testFeeds(uint notifyFlags);
static void testFeed(FeedNotify *feedNotify);
virtual void updateDisplay();
signals:
void newsFeedChanged(int count);
@ -59,7 +61,6 @@ private slots:
// void toggleChanMsgItems(bool on);
void feedoptions();
void updateFeed();
void removeAll();
void itemDestroyed(QObject*);

View File

@ -41,6 +41,7 @@
#include "gui/connect/ConfCertDialog.h"
#include <retroshare/rsfiles.h>
#include <retroshare/rsmsgs.h>
#include <retroshare/rspeers.h>
#include <retroshare/rsforums.h>
#include <retroshare/rschannels.h>
@ -55,7 +56,9 @@
#define HOST_MESSAGE "message"
#define HOST_SEARCH "search"
#define HOST_CERTIFICATE "certificate"
#define HOST_REGEXP "file|person|forum|channel|search|message|certificate"
#define HOST_PUBLIC_MSG "public_msg"
#define HOST_PRIVATE_CHAT "private_chat"
#define HOST_REGEXP "file|person|forum|channel|search|message|certificate|private_chat|public_msg"
#define FILE_NAME "name"
#define FILE_SIZE "size"
@ -87,6 +90,14 @@
#define CERTIFICATE_EXT_IPPORT "extipp"
#define CERTIFICATE_LOC_IPPORT "locipp"
#define PRIVATE_CHAT_TIME_STAMP "time_stamp"
#define PRIVATE_CHAT_STRING "encrypted_data"
#define PRIVATE_CHAT_GPG_ID "gpgid"
#define PUBLIC_MSG_TIME_STAMP "time_stamp"
#define PUBLIC_MSG_SRC_PGP_ID "gpgid"
#define PUBLIC_MSG_HASH "hash"
RetroShareLink::RetroShareLink(const QUrl& url)
{
fromUrl(url);
@ -107,7 +118,8 @@ void RetroShareLink::fromString(const QString& url)
#endif
if ((url.startsWith(QString(RSLINK_SCHEME) + "://" + QString(HOST_FILE)) && url.count("|") == 3) ||
(url.startsWith(QString(RSLINK_SCHEME) + "://" + QString(HOST_PERSON)) && url.count("|") == 2)) {
(url.startsWith(QString(RSLINK_SCHEME) + "://" + QString(HOST_PERSON)) && url.count("|") == 2))
{
/* Old link, we try it */
QStringList list = url.split ("|");
@ -158,6 +170,7 @@ void RetroShareLink::fromUrl(const QUrl& url)
if (url.scheme() != RSLINK_SCHEME) {
/* No RetroShare-Link */
std::cerr << "Not a RS link: scheme=" << url.scheme().toStdString() << std::endl;
return;
}
@ -181,6 +194,29 @@ void RetroShareLink::fromUrl(const QUrl& url)
}
}
if(url.host() == HOST_PRIVATE_CHAT)
{
bool ok ;
_type = TYPE_PRIVATE_CHAT ;
_time_stamp = url.queryItemValue(PRIVATE_CHAT_TIME_STAMP).toUInt(&ok) ;
_encrypted_chat_info = url.queryItemValue(PRIVATE_CHAT_STRING) ;
_GPGid = url.queryItemValue(PRIVATE_CHAT_GPG_ID) ;
check() ;
return;
}
if(url.host() == HOST_PUBLIC_MSG)
{
bool ok ;
_type = TYPE_PUBLIC_MSG ;
_hash = url.queryItemValue(PUBLIC_MSG_HASH) ;
_time_stamp = url.queryItemValue(PUBLIC_MSG_TIME_STAMP).toUInt(&ok) ;
_GPGid = url.queryItemValue(PUBLIC_MSG_SRC_PGP_ID) ;
check() ;
return;
}
if (url.host() == HOST_EXTRAFILE) {
bool ok ;
@ -299,6 +335,32 @@ bool RetroShareLink::createFile(const QString& name, uint64_t size, const QStrin
return valid();
}
bool RetroShareLink::createPrivateChatInvite(time_t time_stamp,const QString& gpg_id,const QString& encrypted_chat_info)
{
clear() ;
_type = TYPE_PRIVATE_CHAT ;
_time_stamp = time_stamp ;
_encrypted_chat_info = encrypted_chat_info ;
_GPGid = gpg_id ;
check() ;
return valid() ;
}
bool RetroShareLink::createPublicMsgInvite(time_t time_stamp,const QString& issuer_pgp_id,const QString& hash)
{
clear() ;
_type = TYPE_PUBLIC_MSG ;
_time_stamp = time_stamp ;
_hash = hash ;
_GPGid = issuer_pgp_id ;
check() ;
return valid() ;
}
bool RetroShareLink::createPerson(const std::string& id)
{
clear();
@ -491,78 +553,93 @@ void RetroShareLink::clear()
_hash = "" ;
_size = 0 ;
_name = "" ;
_GPGid = "" ;
_time_stamp = 0 ;
_encrypted_chat_info = "" ;
}
void RetroShareLink::check()
{
_valid = true;
switch (_type) {
case TYPE_UNKNOWN:
_valid = false;
break;
case TYPE_EXTRAFILE:
if(!checkSSLId(_SSLid))
_valid = false; // no break! We also test file stuff below.
case TYPE_FILE:
if(_size > (((uint64_t)1)<<40)) // 1TB. Who has such large files?
switch (_type)
{
case TYPE_UNKNOWN:
_valid = false;
break;
case TYPE_EXTRAFILE:
if(!checkSSLId(_SSLid))
_valid = false; // no break! We also test file stuff below.
case TYPE_FILE:
if(_size > (((uint64_t)1)<<40)) // 1TB. Who has such large files?
_valid = false;
if(!checkName(_name))
_valid = false;
if(!checkName(_name))
_valid = false;
if(!checkHash(_hash))
_valid = false;
break;
case TYPE_PERSON:
if(_size != 0)
_valid = false;
if(!checkHash(_hash))
_valid = false;
break;
if(_name.isEmpty())
_valid = false;
case TYPE_PRIVATE_CHAT:
if(!checkRadix64(_encrypted_chat_info)) _valid = false ;
if(!checkPGPId(_GPGid)) _valid = false ;
break ;
if(_hash.isEmpty())
_valid = false;
break;
case TYPE_FORUM:
if(_size != 0)
_valid = false;
case TYPE_PUBLIC_MSG:
if(!checkHash(_hash)) _valid = false ;
if(!checkPGPId(_GPGid)) _valid = false ;
break ;
if(_name.isEmpty())
_valid = false;
case TYPE_PERSON:
if(_size != 0)
_valid = false;
if(_hash.isEmpty())
_valid = false;
break;
case TYPE_CHANNEL:
if(_size != 0)
_valid = false;
if(_name.isEmpty())
_valid = false;
if(_name.isEmpty())
_valid = false;
if(_hash.isEmpty())
_valid = false;
break;
case TYPE_FORUM:
if(_size != 0)
_valid = false;
if(_hash.isEmpty())
_valid = false;
break;
case TYPE_SEARCH:
if(_size != 0)
_valid = false;
if(_name.isEmpty())
_valid = false;
if(_name.isEmpty())
_valid = false;
if(_hash.isEmpty())
_valid = false;
break;
case TYPE_CHANNEL:
if(_size != 0)
_valid = false;
if(!_hash.isEmpty())
_valid = false;
break;
case TYPE_MESSAGE:
if(_size != 0)
_valid = false;
if(_name.isEmpty())
_valid = false;
if(_hash.isEmpty())
_valid = false;
break;
case TYPE_CERTIFICATE:
break;
if(_hash.isEmpty())
_valid = false;
break;
case TYPE_SEARCH:
if(_size != 0)
_valid = false;
if(_name.isEmpty())
_valid = false;
if(!_hash.isEmpty())
_valid = false;
break;
case TYPE_MESSAGE:
if(_size != 0)
_valid = false;
if(_hash.isEmpty())
_valid = false;
break;
case TYPE_CERTIFICATE:
break;
}
if (!_valid) {
@ -579,6 +656,22 @@ QString RetroShareLink::title() const
switch (_type) {
case TYPE_UNKNOWN:
break;
case TYPE_PUBLIC_MSG:
{
RsPeerDetails detail;
rsPeers->getPeerDetails(_GPGid.toStdString(), detail) ;
return QString("Click to send a private message to %1 (%2).").arg(QString::fromStdString(detail.name)).arg(_GPGid) ;
}
case TYPE_PRIVATE_CHAT:
{
RsPeerDetails detail;
rsPeers->getPeerDetails(_GPGid.toStdString(), detail) ;
if (_GPGid.toStdString() == rsPeers->getGPGOwnId())
return QString("Click to open a private chat canal to %1 (%2).").arg(QString::fromStdString(detail.name)).arg(_GPGid) ;
else
return QString("This is a private chat invite for %1 (%2). You can't use it.").arg(QString::fromStdString(detail.name)).arg(_GPGid) ;
}
case TYPE_EXTRAFILE:
return QString("%1 (%2, Extra - Source included)").arg(hash()).arg(misc::friendlyUnit(size()));
case TYPE_FILE:
@ -619,6 +712,29 @@ QString RetroShareLink::toString() const
return url.toString();
}
case TYPE_PRIVATE_CHAT:
{
QUrl url;
url.setScheme(RSLINK_SCHEME) ;
url.setHost(HOST_PRIVATE_CHAT) ;
url.addQueryItem(PRIVATE_CHAT_TIME_STAMP,QString::number(_time_stamp)) ;
url.addQueryItem(PRIVATE_CHAT_GPG_ID,_GPGid) ;
url.addQueryItem(PRIVATE_CHAT_STRING,_encrypted_chat_info) ;
return url.toString() ;
}
case TYPE_PUBLIC_MSG:
{
QUrl url;
url.setScheme(RSLINK_SCHEME) ;
url.setHost(HOST_PUBLIC_MSG) ;
url.addQueryItem(PUBLIC_MSG_TIME_STAMP,QString::number(_time_stamp)) ;
url.addQueryItem(PUBLIC_MSG_HASH,_hash) ;
url.addQueryItem(PUBLIC_MSG_SRC_PGP_ID,_GPGid) ;
return url.toString() ;
}
case TYPE_EXTRAFILE:
{
QUrl url;
@ -724,6 +840,14 @@ QString RetroShareLink::niceName() const
return PeerDefs::rsid(name().toUtf8().constData(), hash().toStdString());
}
if(type() == TYPE_PRIVATE_CHAT) {
return QString("Private chat invite (Valid only for key %1)").arg(_GPGid);
}
if(type() == TYPE_PUBLIC_MSG) {
RsPeerDetails detail;
rsPeers->getPeerDetails(_GPGid.toStdString(), detail) ;
return QString("Click this link to send a private message to %1 (%2)").arg(QString::fromStdString(detail.name)).arg(_GPGid) ;
}
if(type() == TYPE_CERTIFICATE) {
if (_location.isEmpty()) {
return QString("RetroShare Certificate (%1)").arg(_name);
@ -814,6 +938,41 @@ bool RetroShareLink::checkSSLId(const QString& ssl_id)
return true ;
}
bool RetroShareLink::checkPGPId(const QString& pgp_id)
{
if(pgp_id.length() != 16)
return false ;
QByteArray qb(pgp_id.toAscii()) ;
for(int i=0;i<qb.length();++i)
{
unsigned char b(qb[i]) ;
if(!((b>47 && b<58) || (b>64 && b<71)))
return false ;
}
return true ;
}
bool RetroShareLink::checkRadix64(const QString& s)
{
QByteArray qb(s.toAscii()) ;
for(int i=0;i<qb.length();++i)
{
unsigned char b(qb[i]) ;
if(!( (b > 46 && b < 58) || (b > 64 && b < 91) || (b > 96 && b < 123) || b=='+' || b=='='))
{
std::cerr << "Character not allowed in radix: " << b << std::endl;
return false;
}
}
std::cerr << "Radix check: passed" << std::endl;
return true ;
}
bool RetroShareLink::checkHash(const QString& hash)
{
if(hash.length() != 40)
@ -1028,6 +1187,58 @@ static void processList(const QStringList &list, const QString &textSingular, co
}
break ;
case TYPE_PUBLIC_MSG:
{
std::cerr << "Opening a public msg window " << std::endl;
std::cerr << " time_stamp = " << link._time_stamp << std::endl;
std::cerr << " hash = " << link._hash.toStdString() << std::endl;
std::cerr << " Issuer Id = " << link._GPGid.toStdString() << std::endl;
if(link._time_stamp < time(NULL))
{
QMessageBox::information(NULL,QObject::tr("Messenging link is expired"),QObject::tr("This Messenging link is expired. The destination peer will not receive it.")) ;
break ;
}
MessageComposer::msgDistantPeer(link._hash.toStdString(),link._GPGid.toStdString()) ;
}
break ;
case TYPE_PRIVATE_CHAT:
{
std::cerr << "Opening a private chat window " << std::endl;
std::cerr << " time_stamp = " << link._time_stamp << std::endl;
std::cerr << " enc-string = " << link._encrypted_chat_info.toStdString() << std::endl;
std::cerr << " PGP Id = " << link._GPGid.toStdString() << std::endl;
if(link._time_stamp < time(NULL))
{
QMessageBox::information(NULL,QObject::tr("Chat link is expired"),QObject::tr("This chat link is expired. The destination peer will not answer.")) ;
break ;
}
if(link._GPGid.toStdString() != rsPeers->getGPGOwnId())
{
QMessageBox::information(NULL,QObject::tr("Chat link cannot be decrypted"),QObject::tr("This chat link is encrypted with a key that is not yours. You can't used it. Key ID = ")+link._GPGid) ;
break ;
}
std::string hash ;
uint32_t error_code ;
if(!rsMsgs->initiateDistantChatConnexion(link._encrypted_chat_info.toStdString(),hash,error_code))
{
QString error_msg ;
switch(error_code)
{
default:
case RS_DISTANT_CHAT_ERROR_DECRYPTION_FAILED: error_msg = QObject::tr("The link could not be decrypted.") ; break ;
case RS_DISTANT_CHAT_ERROR_SIGNATURE_MISMATCH: error_msg = QObject::tr("The link signature cannot be checked.") ; break ;
case RS_DISTANT_CHAT_ERROR_UNKNOWN_KEY: error_msg = QObject::tr("The link is signed by an unknown key.") ; break ;
}
QMessageBox::information(NULL,QObject::tr("Chat connexion is not possible"),error_msg) ;
}
}
break ;
case TYPE_FILE:
case TYPE_EXTRAFILE:
{

View File

@ -52,7 +52,18 @@
class RetroShareLink
{
public:
enum enumType { TYPE_UNKNOWN, TYPE_FILE, TYPE_PERSON, TYPE_FORUM, TYPE_CHANNEL, TYPE_SEARCH, TYPE_MESSAGE, TYPE_CERTIFICATE,TYPE_EXTRAFILE };
enum enumType { TYPE_UNKNOWN = 0x00,
TYPE_FILE = 0x01,
TYPE_PERSON = 0x02,
TYPE_FORUM = 0x03,
TYPE_CHANNEL = 0x04,
TYPE_SEARCH = 0x05,
TYPE_MESSAGE = 0x06,
TYPE_CERTIFICATE = 0x07,
TYPE_EXTRAFILE = 0x08,
TYPE_PRIVATE_CHAT = 0x09,
TYPE_PUBLIC_MSG = 0x0a
};
public:
RetroShareLink();
@ -67,6 +78,8 @@ class RetroShareLink
bool createSearch(const QString& keywords);
bool createMessage(const std::string& peerId, const QString& subject);
bool createCertificate(const std::string& ssl_or_gpg_id) ;
bool createPrivateChatInvite(time_t time_stamp,const QString& gpg_id,const QString& encrypted_chat_info) ;
bool createPublicMsgInvite(time_t time_stamp,const QString& pgp_id,const QString& hash) ;
bool createUnknwonSslCertificate(const std::string& sslId, const std::string& gpgId = "") ;
enumType type() const {return _type; }
@ -83,6 +96,8 @@ class RetroShareLink
const QString& localIPAndPort() const { return _loc_ip_port ; }
const QString& externalIPAndPort() const { return _ext_ip_port ; }
const QString& location() const { return _location ; }
const time_t timeStamp() const { return _time_stamp ; }
const QString& encryptedPrivateChatInfo() const { return _encrypted_chat_info ; }
QString title() const;
unsigned int subType() const { return _subType; }
@ -118,8 +133,10 @@ class RetroShareLink
void clear();
void check();
static bool checkHash(const QString& hash);
static bool checkRadix64(const QString& s);
static bool checkName(const QString& name);
static bool checkSSLId(const QString& name);
static bool checkPGPId(const QString& name);
bool _valid;
enumType _type;
@ -135,6 +152,9 @@ class RetroShareLink
QString _location ; // location
QString _ext_ip_port ;
QString _loc_ip_port ;
QString _encrypted_chat_info ; // encrypted data string for the recipient of a chat invite
time_t _time_stamp ; // time stamp at which the link will expire.
unsigned int _subType; // for general use as sub type for _type (RSLINK_SUBTYPE_...)
};

View File

@ -26,6 +26,7 @@
#include "ChatDialog.h"
#include "gui/common/PeerDefs.h"
#include "PopupChatDialog.h"
#include "PopupDistantChatDialog.h"
#include "ChatLobbyDialog.h"
#include "PopupChatWindow.h"
#include "gui/settings/rsharesettings.h"
@ -91,11 +92,19 @@ void ChatDialog::init(const std::string &peerId, const QString &title)
ChatDialog *cd = getExistingChat(peerId);
if (cd == NULL) {
ChatLobbyId lobby_id;
ChatLobbyId lobby_id = 0;
bool distant_peer = false ;
if (rsMsgs->isLobbyId(peerId, lobby_id)) {
chatflags = RS_CHAT_OPEN | RS_CHAT_FOCUS; // use own flags
}
uint32_t distant_peer_status ;
std::string distant_chat_pgp_id ;
if(rsMsgs->getDistantChatStatus(peerId,distant_peer_status,distant_chat_pgp_id))
chatflags = RS_CHAT_OPEN | RS_CHAT_FOCUS; // use own flags
if (chatflags & RS_CHAT_OPEN) {
if (lobby_id) {
std::list<ChatLobbyInfo> linfos;
@ -108,6 +117,12 @@ void ChatDialog::init(const std::string &peerId, const QString &title)
cd->init(peerId, QString::fromUtf8((*it).lobby_name.c_str()));
}
}
} else if(distant_peer_status > 0) {
cd = new PopupDistantChatDialog();
chatDialogs[peerId] = cd;
std::string peer_name = rsPeers->getGPGName(distant_chat_pgp_id) ;
cd->init(peerId, tr("Talking to ")+QString::fromStdString(peer_name)+" (PGP id="+QString::fromStdString(distant_chat_pgp_id)+")") ;
} else {
RsPeerDetails sslDetails;
if (rsPeers->getPeerDetails(peerId, sslDetails)) {

View File

@ -78,7 +78,7 @@ ChatLobbyDialog::ChatLobbyDialog(const ChatLobbyId& lid, QWidget *parent, Qt::WF
connect(inviteFriendsButton, SIGNAL(clicked()), this , SLOT(inviteFriends()));
getChatWidget()->addChatButton(inviteFriendsButton) ;
getChatWidget()->addChatBarWidget(inviteFriendsButton) ;
unsubscribeButton = new QPushButton ;
unsubscribeButton->setMinimumSize(QSize(28,28)) ;
@ -95,7 +95,7 @@ ChatLobbyDialog::ChatLobbyDialog(const ChatLobbyId& lid, QWidget *parent, Qt::WF
connect(unsubscribeButton, SIGNAL(clicked()), this , SLOT(leaveLobby()));
getChatWidget()->addChatButton(unsubscribeButton) ;
getChatWidget()->addChatBarWidget(unsubscribeButton) ;
}
void ChatLobbyDialog::leaveLobby()

View File

@ -36,6 +36,7 @@
#include "ui_ChatWidget.h"
#include "gui/notifyqt.h"
#include "gui/RetroShareLink.h"
#include "gui/CreateMsgLinkDialog.h"
#include "gui/settings/rsharesettings.h"
#include "gui/settings/RsharePeerSettings.h"
#include "gui/im_history/ImHistoryBrowser.h"
@ -139,9 +140,9 @@ void ChatWidget::setDefaultExtraFileFlags(TransferRequestFlags fl)
ui->hashBox->setDefaultTransferRequestFlags(fl) ;
}
void ChatWidget::addChatButton(QPushButton *button)
void ChatWidget::addChatBarWidget(QWidget *w)
{
ui->toolBarFrame->layout()->addWidget(button) ;
ui->toolBarFrame->layout()->addWidget(w) ;
}
void ChatWidget::init(const std::string &peerId, const QString &title)
@ -548,11 +549,22 @@ void ChatWidget::contextMenu(QPoint point)
QAction *action = contextMnu->addAction(QIcon(":/images/pasterslink.png"), tr("Paste RetroShare Link"), this, SLOT(pasteLink()));
action->setDisabled(RSLinkClipboard::empty());
contextMnu->addAction(QIcon(":/images/pasterslink.png"), tr("Paste my certificate link"), this, SLOT(pasteOwnCertificateLink()));
#ifdef ENABLE_DISTANT_CHAT_AND_MSGS
contextMnu->addAction(QIcon(":/images/pasterslink.png"), tr("Paste/Create private chat or Message link..."), this, SLOT(pasteCreateMsgLink()));
#endif
contextMnu->exec(QCursor::pos());
delete(contextMnu);
}
void ChatWidget::pasteCreateMsgLink()
{
CreateMsgLinkDialog dialog ;
dialog.exec() ;
ui->chatTextEdit->insertHtml(RSLinkClipboard::toHtml());
}
void ChatWidget::contextMenuTextBrowser(QPoint point)
{
QMatrix matrix;

View File

@ -47,7 +47,6 @@ class ChatWidget : public QWidget
public:
enum enumChatType { TYPE_NORMAL, TYPE_HISTORY, TYPE_OFFLINE, TYPE_SYSTEM };
public:
explicit ChatWidget(QWidget *parent = 0);
~ChatWidget();
@ -74,13 +73,14 @@ public:
bool setStyle();
const RSStyle *getStyle() { return &style; }
void addChatButton(QPushButton *button) ;
void addChatBarWidget(QWidget *w) ;
bool isActive();
void setDefaultExtraFileFlags(TransferRequestFlags f) ;
void pasteText(const QString&);
private slots:
void pasteCreateMsgLink() ;
void clearChatHistory();
void deleteChatHistory();
void messageHistory();

View File

@ -141,9 +141,9 @@ void PopupChatDialog::addIncomingChatMsg(const ChatInfo& info)
}
}
void PopupChatDialog::addButton(QPushButton *button)
void PopupChatDialog::addChatBarWidget(QWidget *w)
{
getChatWidget()->addChatButton(button) ;
getChatWidget()->addChatBarWidget(w) ;
}
void PopupChatDialog::onChatChanged(int list, int type)

View File

@ -57,7 +57,7 @@ protected:
void processSettings(bool load);
// used by plugins
void addButton(QPushButton *button) ;
void addChatBarWidget(QWidget *w) ;
protected:
virtual void addIncomingChatMsg(const ChatInfo& info);

View File

@ -0,0 +1,98 @@
/****************************************************************
* RetroShare is distributed under the following license:
*
* Copyright (C) 2013, Cyril Soler
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
****************************************************************/
#include <QTimer>
#include "PopupDistantChatDialog.h"
#define IMAGE_RED_LED ":/images/redled.png"
#define IMAGE_YEL_LED ":/images/yellowled.png"
#define IMAGE_GRN_LED ":/images/greenled.png"
#define IMAGE_GRY_LED ":/images/grayled.png"
PopupDistantChatDialog::~PopupDistantChatDialog()
{
delete _tunnel_check_timer ;
}
PopupDistantChatDialog::PopupDistantChatDialog(QWidget *parent, Qt::WFlags flags)
: PopupChatDialog(parent,flags)
{
_tunnel_check_timer = new QTimer;
_tunnel_check_timer->setInterval(1000) ;
QObject::connect(_tunnel_check_timer,SIGNAL(timeout()),this,SLOT(checkTunnel())) ;
_tunnel_check_timer->start() ;
_status_label = new QLabel ;
addChatBarWidget(_status_label) ;
checkTunnel() ;
}
void PopupDistantChatDialog::init(const std::string& hash,const QString & title)
{
_hash = hash ;
PopupChatDialog::init(hash,title) ;
}
void PopupDistantChatDialog::checkTunnel()
{
if(!isVisible())
return ;
std::cerr << "Checking tunnel..." ;
// make sure about the tunnel status
//
uint32_t status= RS_DISTANT_CHAT_STATUS_UNKNOWN;
std::string pgp_id ;
rsMsgs->getDistantChatStatus(_hash,status,pgp_id) ;
switch(status)
{
case RS_DISTANT_CHAT_STATUS_UNKNOWN: std::cerr << "Unknown hash. Error!" << std::endl;
_status_label->setPixmap(QPixmap(IMAGE_GRY_LED)) ;
_status_label->setToolTip(tr("Hash error")) ;
break ;
case RS_DISTANT_CHAT_STATUS_TUNNEL_DN: std::cerr << "Tunnel asked. Waiting for reponse. " << std::endl;
_status_label->setPixmap(QPixmap(IMAGE_RED_LED)) ;
_status_label->setToolTip(tr("Tunnel is broken")) ;
break ;
case RS_DISTANT_CHAT_STATUS_TUNNEL_OK: std::cerr << "Tunnel is ok. " << std::endl;
_status_label->setPixmap(QPixmap(IMAGE_YEL_LED)) ;
_status_label->setToolTip(tr("Tunnel established")) ;
break ;
case RS_DISTANT_CHAT_STATUS_CAN_TALK: std::cerr << "Tunnel is ok and works. You can talk!" << std::endl;
_status_label->setPixmap(QPixmap(IMAGE_GRN_LED)) ;
_status_label->setToolTip(tr("Tunnel is working")) ;
break ;
}
}

View File

@ -0,0 +1,53 @@
/****************************************************************
* RetroShare is distributed under the following license:
*
* Copyright (C) 2013, Cyril Soler
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
****************************************************************/
#pragma once
#include "PopupChatDialog.h"
class QTimer ;
class PopupDistantChatDialog: public PopupChatDialog
{
Q_OBJECT
friend class ChatDialog;
public slots:
void checkTunnel() ;
protected:
/** Default constructor */
PopupDistantChatDialog(QWidget *parent = 0, Qt::WFlags flags = 0);
/** Default destructor */
virtual ~PopupDistantChatDialog();
virtual void init(const std::string& _hash, const QString &title);
virtual void updateStatus(int /*status*/) {}
QTimer *_tunnel_check_timer ;
std::string _hash ;
std::string _virtual_peer_id ;
QLabel *_status_label ;
};

View File

@ -352,6 +352,22 @@ void MessageComposer::processSettings(bool bLoad)
Settings->endGroup();
}
/*static*/ void MessageComposer::msgDistantPeer(const std::string& hash,const std::string& pgp_id)
{
// std::cerr << "MessageComposer::msgfriend()" << std::endl;
/* create a message */
MessageComposer *pMsgDialog = MessageComposer::newMsg();
if (pMsgDialog == NULL)
return;
pMsgDialog->addRecipient(TO, hash,pgp_id) ;
pMsgDialog->show();
/* window will destroy itself! */
}
/*static*/ void MessageComposer::msgFriend(const std::string &id, bool group)
{
@ -1219,7 +1235,7 @@ bool MessageComposer::sendMessage_internal(bool bDraftbox)
}
}
} else {
if (std::find(peers.begin(), peers.end(), id) == peers.end()) {
if (_distant_peers.find(id)==_distant_peers.end() && std::find(peers.begin(), peers.end(), id) == peers.end()) {
// no friend
continue;
}
@ -1269,6 +1285,7 @@ bool MessageComposer::sendMessage_internal(bool bDraftbox)
QMessageBox::warning(this, tr("RetroShare"), tr("Please insert at least one recipient."), QMessageBox::Ok);
return false; // Don't send with no recipient
}
mi.encryption_keys = _distant_peers ;
if (rsMsgs->MessageSend(mi) == false) {
return false;
@ -1402,7 +1419,13 @@ void MessageComposer::setRecipientToRow(int row, enumType type, std::string id,
}
} else {
RsPeerDetails details;
if (rsPeers->getPeerDetails(id, details)) {
if(_distant_peers.find(id) != _distant_peers.end())
{
name = tr("Distant peer (PGP key: %1)").arg(QString::fromStdString(_distant_peers[id])) ;
icon = QIcon(StatusDefs::imageUser(RS_STATUS_ONLINE));
}
else if (rsPeers->getPeerDetails(id, details))
{
name = PeerDefs::nameWithLocation(details);
StatusInfo peerStatusInfo;
@ -1546,6 +1569,32 @@ void MessageComposer::editingRecipientFinished()
lineEdit->setText(text);
}
void MessageComposer::addRecipient(enumType type, const std::string& hash,const std::string& pgp_id)
{
_distant_peers[hash] = pgp_id ;
int rowCount = ui.recipientWidget->rowCount();
int row;
for (row = 0; row < rowCount; row++)
{
enumType rowType;
std::string rowId;
bool rowGroup;
if (getRecipientFromRow(row, rowType, rowId, rowGroup) == true)
{
if (rowId.empty()) // use row
break;
if (rowId == hash && rowType == type) // existing row
break;
}
else // use row
break;
}
setRecipientToRow(row, type, hash, false);
}
void MessageComposer::addRecipient(enumType type, const std::string &id, bool group)
{
std::list<std::string> sslIds;

View File

@ -49,6 +49,8 @@ public:
~MessageComposer();
static void msgFriend(const std::string &id, bool group);
static void msgDistantPeer(const std::string& hash,const std::string& pgp_id) ;
static QString recommendMessage();
static void recommendFriend(const std::list <std::string> &sslIds, const std::string &to = "", const QString &msg = "", bool autoSend = false);
static void sendConnectAttemptMsg(const std::string &gpgId, const std::string &sslId, const QString &sslName);
@ -65,6 +67,7 @@ public:
void setQuotedMsg(const QString &msg, const QString &header);
void setMsgText(const QString &msg, bool asHtml = false);
void addRecipient(enumType type, const std::string &id, bool group);
void addRecipient(enumType type, const std::string &hash, const std::string& pgp_id) ;
public slots:
/* actions to take.... */
@ -217,6 +220,7 @@ private:
Ui::MessageComposer ui;
std::list<FileInfo> _recList ;
std::map<std::string,std::string> _distant_peers ; // pairs (hash,pgp_id)
};
#endif

View File

@ -275,6 +275,7 @@ HEADERS += rshare.h \
gui/TurtleRouterStatistics.h \
gui/AboutDialog.h \
gui/ForumsDialog.h \
gui/CreateMsgLinkDialog.h \
gui/forums/ForumDetails.h \
gui/forums/EditForumDetails.h \
gui/forums/CreateForum.h \
@ -333,6 +334,7 @@ HEADERS += rshare.h \
gui/profile/StatusMessage.h \
gui/chat/PopupChatWindow.h \
gui/chat/PopupChatDialog.h \
gui/chat/PopupDistantChatDialog.h \
gui/chat/ChatTabWidget.h \
gui/chat/ChatWidget.h \
gui/chat/ChatDialog.h \
@ -471,6 +473,7 @@ FORMS += gui/StartDialog.ui \
gui/MainWindow.ui \
gui/TurtleRouterDialog.ui \
gui/TurtleRouterStatistics.ui \
gui/CreateMsgLinkDialog.ui \
gui/forums/CreateForum.ui \
gui/forums/CreateForumMsg.ui \
gui/forums/ForumDetails.ui \
@ -580,6 +583,7 @@ SOURCES += main.cpp \
gui/TurtleRouterStatistics.cpp \
gui/MainWindow.cpp \
gui/ForumsDialog.cpp \
gui/CreateMsgLinkDialog.cpp \
gui/forums/ForumDetails.cpp \
gui/forums/EditForumDetails.cpp \
gui/forums/CreateForum.cpp \
@ -642,6 +646,7 @@ SOURCES += main.cpp \
gui/channels/ChannelUserNotify.cpp \
gui/chat/PopupChatWindow.cpp \
gui/chat/PopupChatDialog.cpp \
gui/chat/PopupDistantChatDialog.cpp \
gui/chat/ChatTabWidget.cpp \
gui/chat/ChatWidget.cpp \
gui/chat/ChatDialog.cpp \