Merge pull request #1829 from G10h4ck/rsfiles_links

RsFiles links support in libretroshare + a bunch of fixes
This commit is contained in:
G10h4ck 2020-04-20 17:12:04 +02:00 committed by GitHub
commit 2b44492cb6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
77 changed files with 2949 additions and 1667 deletions

View File

@ -12,13 +12,17 @@ build-and-test:
script:
- >
if [ -n "$CI_MERGE_REQUEST_ID" ]; then
MR_ARGS="--build-arg REPO_URL=$CI_MERGE_REQUEST_SOURCE_PROJECT_URL" ;
MR_ARGS="$MR_ARGS --build-arg REPO_BRANCH=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME" ;
export MR_ARGS ;
fi
REPO_ARGS="--build-arg REPO_URL=$CI_MERGE_REQUEST_SOURCE_PROJECT_URL" ;
REPO_ARGS="$REPO_ARGS --build-arg REPO_BRANCH=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME" ;
else
REPO_ARGS="--build-arg REPO_URL=$CI_REPOSITORY_URL" ;
REPO_ARGS="$REPO_ARGS --build-arg REPO_BRANCH=$CI_COMMIT_BRANCH" ;
fi ;
export REPO_ARGS ;
echo REPO_ARGS=$REPO_ARGS ;
- mkdir Dockercontext
- >
docker build -t retroshare:testing $MR_ARGS
docker build -t retroshare:testing $REPO_ARGS
--file $CI_PROJECT_DIR/build_scripts/GitlabCI/gitlabCI.Dockerfile
Dockercontext
- >

View File

@ -19,7 +19,7 @@
# SPDX-FileCopyrightText: Retroshare Team <contact@retroshare.cc>
# SPDX-License-Identifier: LGPL-3.0-or-later
CONFIG += c++11
CONFIG += c++14
!include("retroshare.pri"): error("Could not include file retroshare.pri")

View File

@ -7,7 +7,8 @@ ARG REPO_BRANCH=master
RUN \
cd RetroShare && git remote add testing $REPO_URL && \
git fetch --tags testing $REPO_BRANCH && \
git reset --hard testing/$REPO_BRANCH
git reset --hard testing/$REPO_BRANCH && \
git --no-pager log --max-count 1
RUN \
mkdir RetroShare-build && cd RetroShare-build && \
qmake ../RetroShare CONFIG+=no_retroshare_gui \

View File

@ -44,7 +44,7 @@ $%inputParamsDeserialization%$
const std::weak_ptr<rb::Service> weakService(mService);
const std::weak_ptr<rb::Session> weakSession(session);
$%callbackName%$ = [this, weakService, weakSession]($%callbackParams%$)
$%callbackName%$ = [weakService, weakSession]($%callbackParams%$)
{
auto session = weakSession.lock();
if(!session || session->is_closed()) return;

View File

@ -221,7 +221,8 @@ bool DistributedChatService::checkSignature(RsChatLobbyBouncingObject *obj,const
mGixs->requestKey(obj->signature.keyId,peer_list,RsIdentityUsage(RS_SERVICE_TYPE_CHAT,RsIdentityUsage::CHAT_LOBBY_MSG_VALIDATION,RsGxsGroupId(),RsGxsMessageId(),obj->lobby_id));
uint32_t size = RsChatSerialiser(RsServiceSerializer::SERIALIZATION_FLAG_SIGNATURE).size(dynamic_cast<RsItem*>(obj)) ;
uint32_t size = RsChatSerialiser(RsSerializationFlags::SIGNATURE)
.size(dynamic_cast<RsItem*>(obj));
RsTemporaryMemory memory(size) ;
#ifdef DEBUG_CHAT_LOBBIES
@ -229,7 +230,8 @@ bool DistributedChatService::checkSignature(RsChatLobbyBouncingObject *obj,const
std::cerr << " signature id: " << obj->signature.keyId << std::endl;
#endif
if(!RsChatSerialiser(RsServiceSerializer::SERIALIZATION_FLAG_SIGNATURE).serialise(dynamic_cast<RsItem*>(obj),memory,&size))
if( !RsChatSerialiser(RsSerializationFlags::SIGNATURE)
.serialise(dynamic_cast<RsItem*>(obj),memory,&size) )
{
std::cerr << " (EE) Cannot serialise message item. " << std::endl;
return false ;
@ -1003,10 +1005,12 @@ bool DistributedChatService::locked_initLobbyBouncableObject(const ChatLobbyId&
// now sign the object, if the lobby expects it
uint32_t size = RsChatSerialiser(RsServiceSerializer::SERIALIZATION_FLAG_SIGNATURE).size(dynamic_cast<RsItem*>(&item)) ;
uint32_t size = RsChatSerialiser(RsSerializationFlags::SIGNATURE)
.size(dynamic_cast<RsItem*>(&item));
RsTemporaryMemory memory(size) ;
if(!RsChatSerialiser(RsServiceSerializer::SERIALIZATION_FLAG_SIGNATURE).serialise(dynamic_cast<RsItem*>(&item),memory,&size))
if( !RsChatSerialiser(RsSerializationFlags::SIGNATURE)
.serialise(dynamic_cast<RsItem*>(&item),memory,&size) )
{
std::cerr << "(EE) Cannot sign message item. " << std::endl;
return false ;

View File

@ -70,23 +70,14 @@ void RsChatMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGeneric
/*************************************************************************/
RsChatAvatarItem::~RsChatAvatarItem()
{
if(image_data != NULL)
{
free(image_data) ;
image_data = NULL ;
}
}
void RsChatLobbyBouncingObject::serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx)
{
RsTypeSerializer::serial_process(j,ctx,lobby_id,"lobby_id") ;
RsTypeSerializer::serial_process(j,ctx,msg_id ,"msg_id") ;
RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_NAME,nick,"nick") ;
if(!(ctx.mFlags & RsServiceSerializer::SERIALIZATION_FLAG_SIGNATURE))
RsTypeSerializer::serial_process<RsTlvItem>(j,ctx,signature,"signature") ;
if(!(ctx.mFlags & RsSerializationFlags::SIGNATURE))
RS_SERIAL_PROCESS(signature);
}
void RsChatLobbyMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)

View File

@ -346,14 +346,20 @@ class RsChatStatusItem: public RsChatItem
//
class RsChatAvatarItem: public RsChatItem
{
public:
RsChatAvatarItem() :RsChatItem(RS_PKT_SUBTYPE_CHAT_AVATAR) {setPriorityLevel(QOS_PRIORITY_RS_CHAT_AVATAR_ITEM) ;}
public:
RsChatAvatarItem():
RsChatItem(RS_PKT_SUBTYPE_CHAT_AVATAR),
image_size(0), image_data(nullptr)
{ setPriorityLevel(QOS_PRIORITY_RS_CHAT_AVATAR_ITEM); }
virtual ~RsChatAvatarItem() ;
void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx);
~RsChatAvatarItem() override { free(image_data); }
uint32_t image_size ; // size of data in bytes
unsigned char *image_data ; // image
void serial_process(
RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx) override;
uint32_t image_size; /// size of data in bytes
unsigned char* image_data ; /// image data
};
@ -369,9 +375,8 @@ struct PrivateOugoingMapItem : RsChatItem
struct RsChatSerialiser : RsServiceSerializer
{
RsChatSerialiser(SerializationFlags flags = SERIALIZATION_FLAG_NONE) :
RsServiceSerializer( RS_SERVICE_TYPE_CHAT,
RsGenericSerializer::FORMAT_BINARY, flags ) {}
RsChatSerialiser(RsSerializationFlags flags = RsSerializationFlags::NONE):
RsServiceSerializer(RS_SERVICE_TYPE_CHAT, flags) {}
virtual RsItem *create_item(uint16_t service_id,uint8_t item_sub_id) const;
};

View File

@ -3,7 +3,9 @@
* *
* libretroshare: retroshare core library *
* *
* Copyright 2018 by Retroshare Team <retroshare.project@gmail.com> *
* Copyright (C) 2018 Retroshare Team <contact@retroshare.cc> *
* Copyright (C) 2020 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2020 Asociación Civil Altermundi <info@altermundi.net> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
@ -20,40 +22,100 @@
* *
******************************************************************************/
#include <iomanip>
#include <util/radix64.h>
#include <util/rsdir.h>
#include "util/radix64.h"
#include "util/rsbase64.h"
#include "util/rsdir.h"
#include "retroshare/rsfiles.h"
#include "file_sharing_defaults.h"
#include "filelist_io.h"
#include "file_tree.h"
#include "serialiser/rstypeserializer.h"
std::string FileTreeImpl::toRadix64() const
void RsFileTree::DirData::serial_process(
RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx )
{
unsigned char *buff = NULL ;
uint32_t size = 0 ;
serialise(buff,size) ;
std::string res ;
Radix64::encode(buff,size,res) ;
free(buff) ;
return res ;
RS_SERIAL_PROCESS(name);
RS_SERIAL_PROCESS(subdirs);
RS_SERIAL_PROCESS(subfiles);
}
FileTree *FileTree::create(const std::string& radix64_string)
void RsFileTree::FileData::serial_process(
RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx )
{
FileTreeImpl *ft = new FileTreeImpl ;
RS_SERIAL_PROCESS(name);
RS_SERIAL_PROCESS(size);
RS_SERIAL_PROCESS(hash);
}
/*static*/ std::tuple<std::unique_ptr<RsFileTree>, std::error_condition>
RsFileTree::fromBase64(const std::string& base64)
{
const auto failure = [](std::error_condition ec)
{ return std::make_tuple(nullptr, ec); };
if(base64.empty()) return failure(std::errc::invalid_argument);
std::error_condition ec;
std::vector<uint8_t> mem;
if( (ec = RsBase64::decode(base64, mem)) ) return failure(ec);
RsGenericSerializer::SerializeContext ctx(
mem.data(), static_cast<uint32_t>(mem.size()),
RsSerializationFlags::INTEGER_VLQ );
std::unique_ptr<RsFileTree> ft(new RsFileTree);
ft->serial_process(
RsGenericSerializer::SerializeJob::DESERIALIZE, ctx);
if(ctx.mOk) return std::make_tuple(std::move(ft), std::error_condition());
return failure(std::errc::invalid_argument);
}
std::string RsFileTree::toBase64() const
{
RsGenericSerializer::SerializeContext ctx;
ctx.mFlags = RsSerializationFlags::INTEGER_VLQ;
RsFileTree* ncThis = const_cast<RsFileTree*>(this);
ncThis->serial_process(
RsGenericSerializer::SerializeJob::SIZE_ESTIMATE, ctx );
std::vector<uint8_t> buf(ctx.mOffset);
ctx.mSize = ctx.mOffset; ctx.mOffset = 0; ctx.mData = buf.data();
ncThis->serial_process(
RsGenericSerializer::SerializeJob::SERIALIZE, ctx );
std::string result;
RsBase64::encode(ctx.mData, ctx.mSize, result, false, true);
return result;
}
std::string RsFileTree::toRadix64() const
{
unsigned char* buff = nullptr;
uint32_t size = 0;
serialise(buff, size);
std::string res;
Radix64::encode(buff,size,res);
free(buff);
return res;
}
std::unique_ptr<RsFileTree> RsFileTree::fromRadix64(
const std::string& radix64_string )
{
std::unique_ptr<RsFileTree> ft(new RsFileTree);
std::vector<uint8_t> mem = Radix64::decode(radix64_string);
ft->deserialise(mem.data(),mem.size()) ;
return ft ;
if(ft->deserialise(mem.data(), static_cast<uint32_t>(mem.size())))
return ft;
return nullptr;
}
void FileTreeImpl::recurs_buildFileTree(FileTreeImpl& ft,uint32_t index,const DirDetails& dd,bool remote,bool remove_top_dirs)
void RsFileTree::recurs_buildFileTree(
RsFileTree& ft, uint32_t index, const DirDetails& dd, bool remote,
bool remove_top_dirs )
{
RsDbg() << __PRETTY_FUNCTION__ << " index: " << index << std::endl;
if(ft.mDirs.size() <= index)
ft.mDirs.resize(index+1) ;
@ -67,14 +129,14 @@ void FileTreeImpl::recurs_buildFileTree(FileTreeImpl& ft,uint32_t index,const Di
DirDetails dd2 ;
FileSearchFlags flags = remote?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL ;
FileSearchFlags flags = remote ? RS_FILE_HINTS_REMOTE : RS_FILE_HINTS_LOCAL;
for(uint32_t i=0;i<dd.children.size();++i)
if(rsFiles->RequestDirDetails(dd.children[i].ref,dd2,flags))
{
if(dd.children[i].type == DIR_TYPE_FILE)
{
FileTree::FileData f ;
FileData f ;
f.name = dd2.name ;
f.size = dd2.count ;
f.hash = dd2.hash ;
@ -97,33 +159,50 @@ void FileTreeImpl::recurs_buildFileTree(FileTreeImpl& ft,uint32_t index,const Di
std::cerr << "(EE) Cannot request dir details for pointer " << dd.children[i].ref << std::endl;
}
bool FileTreeImpl::getDirectoryContent(uint32_t index,std::string& name,std::vector<uint32_t>& subdirs,std::vector<FileData>& subfiles) const
bool RsFileTree::getDirectoryContent(
std::string& name, std::vector<uint64_t>& subdirs,
std::vector<FileData>& subfiles, uint64_t index_p ) const
{
if(index >= mDirs.size())
return false ;
// Avoid warnings on Android armv7
using sz_t = std::vector<FileData>::size_type;
sz_t index = static_cast<sz_t>(index_p);
if(index >= mDirs.size()) return false;
name = mDirs[index].name;
subdirs = mDirs[index].subdirs ;
subfiles.clear() ;
for(uint32_t i=0;i<mDirs[index].subfiles.size();++i)
subfiles.push_back(mFiles[mDirs[index].subfiles[i]]);
for(sz_t i=0; i < mDirs[index].subfiles.size(); ++i)
subfiles.push_back(mFiles[static_cast<sz_t>(mDirs[index].subfiles[i])]);
return true ;
return true;
}
FileTree *FileTree::create(const DirDetails& dd, bool remote,bool remove_top_dirs)
std::unique_ptr<RsFileTree> RsFileTree::fromDirDetails(
const DirDetails& dd, bool remote ,bool remove_top_dirs )
{
FileTreeImpl *ft = new FileTreeImpl ;
std::unique_ptr<RsFileTree>ft(new RsFileTree);
if(dd.type == DIR_TYPE_FILE)
{
FileData fd;
fd.name = dd.name; fd.hash = dd.hash; fd.size = dd.count;
ft->mFiles.push_back(fd);
ft->mTotalFiles = 1;
ft->mTotalSize = fd.size;
FileTreeImpl::recurs_buildFileTree(*ft,0,dd,remote,remove_top_dirs) ;
return ft ;
DirData dd;
dd.name = "/";
dd.subfiles.push_back(0);
ft->mDirs.push_back(dd);
}
else recurs_buildFileTree(*ft, 0, dd, remote, remove_top_dirs );
return ft;
}
typedef FileListIO::read_error read_error ;
bool FileTreeImpl::deserialise(unsigned char *buffer,uint32_t buffer_size)
bool RsFileTree::deserialise(unsigned char *buffer,uint32_t buffer_size)
{
uint32_t buffer_offset = 0 ;
@ -218,7 +297,7 @@ bool FileTreeImpl::deserialise(unsigned char *buffer,uint32_t buffer_size)
return true ;
}
bool FileTreeImpl::serialise(unsigned char *& buffer,uint32_t& buffer_size) const
bool RsFileTree::serialise(unsigned char *& buffer,uint32_t& buffer_size) const
{
buffer = 0 ;
uint32_t buffer_offset = 0 ;
@ -234,7 +313,11 @@ bool FileTreeImpl::serialise(unsigned char *& buffer,uint32_t& buffer_size) cons
{
// Write some header
if(!FileListIO::writeField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_DIRECTORY_VERSION,(uint32_t) FILE_LIST_IO_LOCAL_DIRECTORY_TREE_VERSION_0001)) throw std::runtime_error("Write error") ;
if(!FileListIO::writeField(
buffer, buffer_size, buffer_offset,
FILE_LIST_IO_TAG_LOCAL_DIRECTORY_VERSION,
(uint32_t) FILE_LIST_IO_LOCAL_DIRECTORY_TREE_VERSION_0001 ) )
throw std::runtime_error("Write error") ;
if(!FileListIO::writeField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_RAW_NUMBER,(uint32_t) mFiles.size())) throw std::runtime_error("Write error") ;
if(!FileListIO::writeField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_RAW_NUMBER,(uint32_t) mDirs.size())) throw std::runtime_error("Write error") ;
@ -292,28 +375,4 @@ bool FileTreeImpl::serialise(unsigned char *& buffer,uint32_t& buffer_size) cons
}
}
void FileTreeImpl::print() const
{
std::cerr << "File hierarchy: name=" << mDirs[0].name << " size=" << mTotalSize << std::endl;
recurs_print(0," ") ;
}
void FileTreeImpl::recurs_print(uint32_t index,const std::string& indent) const
{
if(index >= mDirs.size())
{
std::cerr << "(EE) inconsistent FileTree structure" << std::endl;
return;
}
std::cerr << indent << mDirs[index].name << std::endl;
for(uint32_t i=0;i<mDirs[index].subdirs.size();++i)
recurs_print(mDirs[index].subdirs[i],indent+" ") ;
for(uint32_t i=0;i<mDirs[index].subfiles.size();++i)
{
const FileData& fd(mFiles[mDirs[index].subfiles[i]]) ;
std::cerr << indent << " " << fd.hash << " " << std::setprecision(8) << fd.size << " " << fd.name << std::endl;
}
}
RsFileTree::~RsFileTree() = default;

View File

@ -38,7 +38,7 @@
#include "util/rsdiscspace.h"
#include "util/rsmemory.h"
#include "util/rstime.h"
#include "util/cxx17retrocompat.h"
#include "ft/ftcontroller.h"
#include "ft/ftfilecreator.h"
@ -923,10 +923,15 @@ bool ftController::alreadyHaveFile(const RsFileHash& hash, FileInfo &info)
return false ;
}
bool ftController::FileRequest(const std::string& fname, const RsFileHash& hash,
uint64_t size, const std::string& dest, TransferRequestFlags flags,
const std::list<RsPeerId> &_srcIds, uint16_t state)
bool ftController::FileRequest(
const std::string& fname, const RsFileHash& hash, uint64_t size,
const std::string& dest, TransferRequestFlags flags,
const std::list<RsPeerId> &_srcIds, uint16_t state )
{
/* TODO: To support collections faithfully we need to be able to save
* the same file to multiple locations, both if already downloaded or
* incomplete */
std::list<RsPeerId> srcIds(_srcIds) ;
/* check if we have the file */
@ -965,8 +970,9 @@ bool ftController::FileRequest(const std::string& fname, const RsFileHash& hash
// create void file with the target name.
FILE *f = RsDirUtil::rs_fopen(destination.c_str(),"w") ;
if(f == NULL)
std::cerr << "Could not open file " << destination << " for writting." << std::endl ;
if(!f)
RsErr() << __PRETTY_FUNCTION__ << " Could not write file "
<< destination << std::endl;
else
fclose(f) ;
@ -979,12 +985,13 @@ bool ftController::FileRequest(const std::string& fname, const RsFileHash& hash
//
if(size >= 1024ull*1024ull*((1ull << 32) - 1))
{
std::cerr << "FileRequest Error: unexpected size. This is probably a bug." << std::endl;
std::cerr << " name = " << fname << std::endl ;
std::cerr << " flags = " << flags << std::endl ;
std::cerr << " dest = " << dest << std::endl ;
std::cerr << " size = " << size << std::endl ;
return false ;
RsErr() << __PRETTY_FUNCTION__
<< " unexpected size. This is probably a bug."
<< " name = " << fname
<< " flags = " << flags
<< " dest = " << dest
<< " size = " << size << std::endl;
return false;
}
/* If file transfer is not enabled ....
@ -1004,8 +1011,8 @@ bool ftController::FileRequest(const std::string& fname, const RsFileHash& hash
}
}
// remove the sources from the list, if they don't have clearance for direct transfer. This happens only for non cache files.
//
/* remove the sources from the list, if they don't have clearance for direct
* transfer. This happens only for non cache files. */
for(std::list<RsPeerId>::iterator it = srcIds.begin(); it != srcIds.end(); )
{
bool bAllowDirectDL = false;
@ -1052,11 +1059,10 @@ bool ftController::FileRequest(const std::string& fname, const RsFileHash& hash
* This is important as some guis request duplicate files regularly.
*/
{
RsStackMutex stack(ctrlMutex); /******* LOCKED ********/
std::map<RsFileHash, ftFileControl*>::const_iterator dit = mDownloads.find(hash);
{
RS_STACK_MUTEX(ctrlMutex);
auto dit = std::as_const(mDownloads).find(hash);
if (dit != mDownloads.end())
{
/* we already have it! */
@ -1110,7 +1116,7 @@ bool ftController::FileRequest(const std::string& fname, const RsFileHash& hash
return true;
}
} /******* UNLOCKED ********/
} // RS_STACK_MUTEX(ctrlMutex); unlocked
if(mSearch && !(flags & RS_FILE_REQ_NO_SEARCH))

View File

@ -20,6 +20,9 @@
* *
*******************************************************************************/
#include <algorithm>
#include <iostream>
#include "crypto/chacha20.h"
//const int ftserverzone = 29539;
@ -40,18 +43,16 @@
#include "retroshare/rstypes.h"
#include "retroshare/rspeers.h"
#include "retroshare/rsinit.h"
#include "util/cxx17retrocompat.h"
#include "rsitems/rsfiletransferitems.h"
#include "rsitems/rsserviceids.h"
#include "util/rsmemory.h"
#include "rsserver/p3face.h"
#include "turtle/p3turtle.h"
#include "util/rsurl.h"
#include "util/rsdebug.h"
#include "util/rsdir.h"
#include "util/rsprint.h"
#include <iostream>
#include "util/rstime.h"
#ifdef RS_DEEP_FILES_INDEX
@ -66,6 +67,18 @@
#define FTSERVER_DEBUG() std::cerr << time(NULL) << " : FILE_SERVER : " << __FUNCTION__ << " : "
#define FTSERVER_ERROR() std::cerr << "(EE) FILE_SERVER ERROR : "
/*static*/ const RsFilesErrorCategory RsFilesErrorCategory::instance;
/*static*/ const std::string RsFiles::DEFAULT_FILES_BASE_URL =
"retroshare:///files";
/*static*/ const std::string RsFiles::FILES_URL_COUNT_FIELD = "filesCount";
/*static*/ const std::string RsFiles::FILES_URL_DATA_FIELD = "filesData";
// Use a 5 character word so there is no mistake it isn't base64 as 5%4=1
/*static*/ const std::string RsFiles::FILES_URL_FAGMENT_FORWARD = "fragm";
/*static*/ const std::string RsFiles::FILES_URL_NAME_FIELD = "filesName";
/*static*/ const std::string RsFiles::FILES_URL_SIZE_FIELD = "filesSize";
static const rstime_t FILE_TRANSFER_LOW_PRIORITY_TASKS_PERIOD = 5 ; // low priority tasks handling every 5 seconds
static const rstime_t FILE_TRANSFER_MAX_DELAY_BEFORE_DROP_USAGE_RECORD = 10 ; // keep usage records for 10 secs at most.
@ -283,7 +296,10 @@ bool ftServer::alreadyHaveFile(const RsFileHash& hash, FileInfo &info)
return mFileDatabase->search(hash, RS_FILE_HINTS_LOCAL, info);
}
bool ftServer::FileRequest(const std::string& fname, const RsFileHash& hash, uint64_t size, const std::string& dest, TransferRequestFlags flags, const std::list<RsPeerId>& srcIds)
bool ftServer::FileRequest(
const std::string& fname, const RsFileHash& hash, uint64_t size,
const std::string& dest, TransferRequestFlags flags,
const std::list<RsPeerId>& srcIds )
{
#ifdef SERVER_DEBUG
FTSERVER_DEBUG() << "Requesting " << fname << std::endl ;
@ -295,6 +311,93 @@ bool ftServer::FileRequest(const std::string& fname, const RsFileHash& hash, uin
return true ;
}
std::error_condition ftServer::requestFiles(
const RsFileTree& collection, const std::string& destPath,
const std::vector<RsPeerId>& srcIds, FileRequestFlags flags )
{
constexpr auto fname = __PRETTY_FUNCTION__;
const auto dirsCount = collection.mDirs.size();
const auto filesCount = collection.mFiles.size();
Dbg2() << fname << " dirsCount: " << dirsCount
<< " filesCount: " << filesCount << std::endl;
if(!dirsCount)
{
RsErr() << fname << " Directories list empty in collection "
<< std::endl;
return std::errc::not_a_directory;
}
if(!filesCount)
{
RsErr() << fname << " Files list empty in collection " << std::endl;
return std::errc::invalid_argument;
}
if(filesCount != collection.mTotalFiles)
{
RsErr() << fname << " Files count mismatch" << std::endl;
return std::errc::invalid_argument;
}
std::string basePath = destPath.empty() ? getDownloadDirectory() : destPath;
// Track how many time a directory have been explored
std::vector<uint32_t> dirsSeenCnt(dirsCount, 0);
// <directory handle, parent path>
using StackEntry = std::tuple<uint64_t, std::string>;
std::deque<StackEntry> dStack = { std::make_tuple(0, basePath) };
const auto exploreDir = [&](const StackEntry& se)-> std::error_condition
{
uint64_t dirHandle; std::string parentPath;
std::tie(dirHandle, parentPath) = se;
const auto& dirData = collection.mDirs[dirHandle];
auto& seenTimes = dirsSeenCnt[dirHandle];
std::string dirPath = RsDirUtil::makePath(parentPath, dirData.name);
/* This check is not perfect but is cheap and interrupt loop exploration
* before it becomes pathological */
if(seenTimes++ > dirsCount)
{
RsErr() << fname << " loop detected! dir: "
<< dirHandle << " \"" << dirPath
<< "\" explored too many times" << std::endl;
return std::errc::too_many_symbolic_link_levels;
}
for(auto fHandle: dirData.subfiles)
{
if(fHandle >= filesCount) return std::errc::argument_out_of_domain;
const RsFileTree::FileData& fData = collection.mFiles[fHandle];
bool fr =
FileRequest( fData.name, fData.hash, fData.size,
dirPath,
TransferRequestFlags::fromEFT<FileRequestFlags>(flags),
std::list<RsPeerId>(srcIds.begin(), srcIds.end()) );
Dbg2() << fname << " requested: " << fr << " "
<< fData.hash << " -> " << dirPath << std::endl;
}
for(auto dHandle: dirData.subdirs)
dStack.push_back(std::make_tuple(dHandle, dirPath));
return std::error_condition();
};
while(!dStack.empty())
{
if(std::error_condition ec = exploreDir(dStack.front())) return ec;
dStack.pop_front();
}
return std::error_condition();
}
bool ftServer::activateTunnels(const RsFileHash& hash,uint32_t encryption_policy,TransferRequestFlags flags,bool onoff)
{
RsFileHash hash_of_hash ;
@ -740,7 +843,7 @@ bool ftServer::findChildPointer(void *ref, int row, void *& result, FileSearchFl
}
bool ftServer::requestDirDetails(
DirDetails &details, std::uintptr_t handle, FileSearchFlags flags )
DirDetails &details, uint64_t handle, FileSearchFlags flags )
{ return RequestDirDetails(reinterpret_cast<void*>(handle), details, flags); }
int ftServer::RequestDirDetails(void *ref, DirDetails &details, FileSearchFlags flags)
@ -1872,15 +1975,16 @@ void ftServer::ftReceiveSearchResult(RsTurtleFTSearchResultItem *item)
hasCallback = true;
std::vector<TurtleFileInfoV2> cRes;
for( const auto& tfiold : item->result)
cRes.push_back(tfiold);
for(auto& res: std::as_const(item->result))
cRes.push_back(TurtleFileInfoV2(res));
cbpt->second.first(cRes);
}
} // end RS_STACK_MUTEX(mSearchCallbacksMapMutex);
if(!hasCallback)
RsServer::notify()->notifyTurtleSearchResult(item->PeerId(),item->request_id, item->result );
RsServer::notify()->notifyTurtleSearchResult(
item->PeerId(), item->request_id, item->result );
}
bool ftServer::receiveSearchRequest(
@ -2101,3 +2205,144 @@ RsFileItem::RsFileItem(RsFileItemType subtype) :
void RsFileSearchRequestItem::clear() { queryString.clear(); }
void RsFileSearchResultItem::clear() { mResults.clear(); }
std::error_condition RsFilesErrorCategory::default_error_condition(int ev)
const noexcept
{
switch(static_cast<RsFilesErrorNum>(ev))
{
case RsFilesErrorNum::FILES_HANDLE_NOT_FOUND:
return std::errc::invalid_argument;
default:
return std::error_condition(ev, *this);
}
}
std::error_condition ftServer::dirDetailsToLink(
std::string& link,
const DirDetails& dirDetails, bool fragSneak, const std::string& baseUrl )
{
std::unique_ptr<RsFileTree> tFileTree =
RsFileTree::fromDirDetails(dirDetails, false);
if(!tFileTree) return std::errc::invalid_argument;
link = tFileTree->toBase64();
if(!baseUrl.empty())
{
RsUrl tUrl(baseUrl);
tUrl.setQueryKV(FILES_URL_COUNT_FIELD,
std::to_string(tFileTree->mTotalFiles) )
.setQueryKV(FILES_URL_NAME_FIELD, dirDetails.name)
.setQueryKV( FILES_URL_SIZE_FIELD,
std::to_string(tFileTree->mTotalSize) );
if(fragSneak)
tUrl.setQueryKV(FILES_URL_DATA_FIELD, FILES_URL_FAGMENT_FORWARD)
.setFragment(link);
else tUrl.setQueryKV(FILES_URL_DATA_FIELD, link);
link = tUrl.toString();
}
return std::error_condition();
}
std::error_condition ftServer::exportCollectionLink(
std::string& link, uint64_t handle, bool fragSneak,
const std::string& baseUrl )
{
DirDetails tDirDet;
if(!requestDirDetails(tDirDet, handle))
return RsFilesErrorNum::FILES_HANDLE_NOT_FOUND;
return dirDetailsToLink(link, tDirDet, fragSneak, baseUrl);
}
/// @see RsFiles
std::error_condition ftServer::exportFileLink(
std::string& link, const RsFileHash& fileHash, uint64_t fileSize,
const std::string& fileName, bool fragSneak, const std::string& baseUrl )
{
if(fileHash.isNull() || !fileSize || fileName.empty())
return std::errc::invalid_argument;
DirDetails tDirDet;
tDirDet.type = DIR_TYPE_FILE;
tDirDet.name = fileName;
tDirDet.hash = fileHash;
tDirDet.count = fileSize;
return dirDetailsToLink(link, tDirDet, fragSneak, baseUrl);
}
std::error_condition ftServer::parseFilesLink(
const std::string& link, RsFileTree& collection )
{
RsUrl tUrl(link);
{
/* Handle retrocompatibility with old stile single file links
* retroshare://file?name=$FILE_NAME&size=$FILE_SIZE&hash=$FILE_HASH
*/
if( tUrl.scheme() == "retroshare" && tUrl.host() == "file"
&& tUrl.hasQueryK("name") && !tUrl.getQueryV("name")->empty()
&& tUrl.hasQueryK("size") && !tUrl.getQueryV("size")->empty()
&& tUrl.hasQueryK("hash") && !tUrl.getQueryV("hash")->empty() )
{
DirDetails dt;
dt.type = DIR_TYPE_FILE;
dt.hash = RsFileHash(*tUrl.getQueryV("hash"));
dt.name = *tUrl.getQueryV("name");
try
{
dt.count = std::stoull(*tUrl.getQueryV("size"));
std::unique_ptr<RsFileTree> ft;
if( !dt.hash.isNull() &&
(ft = RsFileTree::fromDirDetails(dt, true)) )
{
collection = *ft;
return std::error_condition();
}
}
catch (...) {}
}
}
{
/* Handle retrocompatibility with old stile collection links
* retroshare://collection?name=$NAME&size=$SIZE&radix=$RADIX&files=$COUNT
*/
if( tUrl.scheme() == "retroshare" && tUrl.host() == "collection"
&& tUrl.hasQueryK("name") && !tUrl.getQueryV("name")->empty()
&& tUrl.hasQueryK("size") && !tUrl.getQueryV("size")->empty()
&& tUrl.hasQueryK("radix") && !tUrl.getQueryV("radix")->empty()
&& tUrl.hasQueryK("files") && !tUrl.getQueryV("files")->empty() )
{
try
{
// Don't need the values just check they are valid numbers
std::stoull(*tUrl.getQueryV("size"));
std::stoull(*tUrl.getQueryV("files"));
auto ft = RsFileTree::fromRadix64(*tUrl.getQueryV("radix"));
if(ft)
{
collection = *ft;
return std::error_condition();
}
}
catch (...) {}
}
}
// Finaly handle the new files link format
rs_view_ptr<const std::string> radixPtr =
tUrl.getQueryV(FILES_URL_DATA_FIELD);
if(!radixPtr) radixPtr = &link;
else if(*radixPtr == FILES_URL_FAGMENT_FORWARD) radixPtr = &tUrl.fragment();
std::unique_ptr<RsFileTree> tft; std::error_condition ec;
std::tie(tft, ec) = RsFileTree::fromBase64(*radixPtr);
if(tft) collection = *tft;
return ec;
}

View File

@ -207,14 +207,39 @@ public:
virtual uint32_t filePermDirectDL() ;
/// @see RsFiles
virtual bool turtleSearchRequest(
std::error_condition requestFiles(
const RsFileTree& collection,
const std::string& destPath = "",
const std::vector<RsPeerId>& srcIds = std::vector<RsPeerId>(),
FileRequestFlags flags = FileRequestFlags::ANONYMOUS_ROUTING
) override;
/// @see RsFiles
bool turtleSearchRequest(
const std::string& matchString,
const std::function<void (const std::vector<TurtleFileInfoV2>& results)>& multiCallback,
rstime_t maxWait = 300 );
rstime_t maxWait = 300 ) override;
virtual TurtleSearchRequestId turtleSearch(const std::string& string_to_match) ;
virtual TurtleSearchRequestId turtleSearch(const RsRegularExpression::LinearizedExpression& expr) ;
/// @see RsFiles
std::error_condition exportCollectionLink(
std::string& link, uint64_t handle, bool fragSneak = false,
const std::string& baseUrl = RsFiles::DEFAULT_FILES_BASE_URL
) override;
/// @see RsFiles
std::error_condition exportFileLink(
std::string& link, const RsFileHash& fileHash, uint64_t fileSize,
const std::string& fileName, bool fragSneak = false,
const std::string& baseUrl = RsFiles::DEFAULT_FILES_BASE_URL
) override;
/// @see RsFiles
std::error_condition parseFilesLink(
const std::string& link, RsFileTree& collection ) override;
/***
* Control of Downloads Priority.
***/
@ -254,7 +279,7 @@ public:
/// @see RsFiles::RequestDirDetails
virtual bool requestDirDetails(
DirDetails &details, std::uintptr_t handle = 0,
DirDetails &details, uint64_t handle = 0,
FileSearchFlags flags = RS_FILE_HINTS_LOCAL );
virtual bool findChildPointer(void *ref, int row, void *& result, FileSearchFlags flags) ;
@ -365,11 +390,11 @@ protected:
bool findEncryptedHash(const RsPeerId& virtual_peer_id, RsFileHash& encrypted_hash);
bool checkUploadLimit(const RsPeerId& pid,const RsFileHash& hash);
private:
/**** INTERNAL FUNCTIONS ***/
//virtual int reScanDirs();
//virtual int check_dBUpdate();
std::error_condition dirDetailsToLink(
std::string& link,
const DirDetails& dirDetails, bool fragSneak,
const std::string& baseUrl );
private:

View File

@ -75,8 +75,8 @@ void RsDiscPgpKeyItem::clear()
{
pgpKeyId.clear();
free(bin_data);
bin_data = nullptr;
bin_len=0;
bin_data = nullptr;
bin_len = 0;
}
void RsDiscContactItem::clear()

View File

@ -84,17 +84,23 @@ class RsDiscPgpKeyItem: public RsDiscItem
{
public:
RsDiscPgpKeyItem() : RsDiscItem(RsGossipDiscoveryItemType::PGP_CERT_BINARY)
RsDiscPgpKeyItem() :
RsDiscItem(RsGossipDiscoveryItemType::PGP_CERT_BINARY),
bin_data(nullptr), bin_len(0)
{ setPriorityLevel(QOS_PRIORITY_RS_DISC_PGP_CERT); }
virtual ~RsDiscPgpKeyItem() { delete[](bin_data);bin_data=nullptr;bin_len=0;}
~RsDiscPgpKeyItem() override { free(bin_data); }
void clear() override;
void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx) override;
RsPgpId pgpKeyId; // duplicate information for practical reasons
unsigned char *bin_data; // binry key data allocated with new unsigned char[]
uint32_t bin_len;
void serial_process(
RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx ) override;
/// duplicate information for practical reasons
RsPgpId pgpKeyId;
unsigned char* bin_data;
uint32_t bin_len;
};
class RS_DEPRECATED_FOR(RsDiscPgpKeyItem) RsDiscPgpCertItem: public RsDiscItem

View File

@ -108,14 +108,6 @@ p3discovery2::p3discovery2(
// Add self into PGP FriendList.
mFriendList[AuthGPG::getAuthGPG()->getGPGOwnId()] = DiscPgpInfo();
if(rsEvents)
rsEvents->registerEventsHandler(
RsEventType::GOSSIP_DISCOVERY,
[this](std::shared_ptr<const RsEvent> event)
{
rsEventsHandler(*event);
}, mRsEventsHandle ); // mRsEventsHandle is zeroed in initializer list
}
@ -1284,11 +1276,6 @@ bool p3discovery2::setPeerVersion(const RsPeerId &peerId, const std::string &ver
return true;
}
void p3discovery2::rsEventsHandler(const RsEvent& event)
{
Dbg3() << __PRETTY_FUNCTION__ << " " << static_cast<uint32_t>(event.mType) << std::endl;
}
/*************************************************************************************/
/* AuthGPGService */

View File

@ -99,12 +99,10 @@ void RsGRouterGenericDataItem::serial_process(RsGenericSerializer::SerializeJob
RsTypeSerializer::serial_process (j,ctx,destination_key,"destination_key") ;
RsTypeSerializer::serial_process<uint32_t>(j,ctx,service_id,"service_id") ;
RsTypeSerializer::TlvMemBlock_proxy prox(data_bytes,data_size) ;
RsTypeSerializer::RawMemoryWrapper prox(data_bytes, data_size);
RsTypeSerializer::serial_process(j, ctx, prox, "data");
RsTypeSerializer::serial_process(j,ctx,prox,"data") ;
if(ctx.mFlags & RsGenericSerializer::SERIALIZATION_FLAG_SIGNATURE)
return ;
if(!!(ctx.mFlags & RsSerializationFlags::SIGNATURE)) return;
RsTypeSerializer::serial_process<RsTlvItem>(j,ctx,signature,"signature") ;
RsTypeSerializer::serial_process<uint32_t>(j,ctx,duplication_factor,"duplication_factor") ;
@ -133,8 +131,7 @@ void RsGRouterSignedReceiptItem::serial_process(RsGenericSerializer::SerializeJo
RsTypeSerializer::serial_process<uint32_t> (j,ctx,service_id,"service_id") ;
RsTypeSerializer::serial_process (j,ctx,data_hash,"data_hash") ;
if(ctx.mFlags & RsGenericSerializer::SERIALIZATION_FLAG_SIGNATURE)
return ;
if(!!(ctx.mFlags & RsSerializationFlags::SIGNATURE)) return;
RsTypeSerializer::serial_process<RsTlvItem>(j,ctx,signature,"signature") ;
}

View File

@ -286,7 +286,9 @@ class RsGRouterRoutingInfoItem: public RsGRouterItem, public GRouterRoutingInfo,
class RsGRouterSerialiser: public RsServiceSerializer
{
public:
explicit RsGRouterSerialiser(SerializationFlags flags = SERIALIZATION_FLAG_NONE) : RsServiceSerializer(RS_SERVICE_TYPE_GROUTER,RsGenericSerializer::FORMAT_BINARY,flags) {}
explicit RsGRouterSerialiser(
RsSerializationFlags flags = RsSerializationFlags::NONE ):
RsServiceSerializer(RS_SERVICE_TYPE_GROUTER, flags) {}
virtual RsItem *create_item(uint16_t service,uint8_t subtype) const ;
};

View File

@ -1658,7 +1658,9 @@ void p3GRouter::handleIncomingReceiptItem(const RsGRouterSignedReceiptItem *rece
Sha1CheckSum p3GRouter::computeDataItemHash(const RsGRouterGenericDataItem *data_item)
{
RsGRouterSerialiser signature_serializer(RsGenericSerializer::SERIALIZATION_FLAG_SIGNATURE | RsGenericSerializer::SERIALIZATION_FLAG_SKIP_HEADER);
RsGRouterSerialiser signature_serializer(
RsSerializationFlags::SIGNATURE |
RsSerializationFlags::SKIP_HEADER );
uint32_t signed_data_size = signature_serializer.size(const_cast<RsGRouterGenericDataItem*>(data_item));
uint32_t total_size = signed_data_size + data_item->signature.TlvSize() ;
@ -2034,7 +2036,9 @@ bool p3GRouter::signDataItem(RsGRouterAbstractMsgItem *item,const RsGxsId& signi
std::cerr << " Key ID = " << signing_id << std::endl;
std::cerr << " Getting key material..." << std::endl;
//#endif
RsGRouterSerialiser signature_serializer(RsGenericSerializer::SERIALIZATION_FLAG_SIGNATURE | RsGenericSerializer::SERIALIZATION_FLAG_SKIP_HEADER) ;
RsGRouterSerialiser signature_serializer(
RsSerializationFlags::SIGNATURE |
RsSerializationFlags::SKIP_HEADER );
uint32_t data_size = signature_serializer.size(item) ;
RsTemporaryMemory data(data_size) ;
@ -2092,8 +2096,8 @@ bool p3GRouter::verifySignedDataItem(const RsGRouterAbstractMsgItem *item,const
}
RsGRouterSerialiser signature_serializer(
RsGenericSerializer::SERIALIZATION_FLAG_SIGNATURE |
RsGenericSerializer::SERIALIZATION_FLAG_SKIP_HEADER );
RsSerializationFlags::SIGNATURE |
RsSerializationFlags::SKIP_HEADER );
uint32_t data_size = signature_serializer.size(const_cast<RsGRouterAbstractMsgItem*>(item)); // the const cast shouldn't be necessary if size() took a const.
RsTemporaryMemory data(data_size);

View File

@ -1969,3 +1969,5 @@ bool RsGxsDataAccess::checkMsgFilter(
return true;
}
GxsGroupStatistic::~GxsGroupStatistic() = default;
GxsServiceStatistic::~GxsServiceStatistic() = default;

View File

@ -78,10 +78,10 @@ JsonApiServer::corsOptionsHeaders =
#define INITIALIZE_API_CALL_JSON_CONTEXT \
RsGenericSerializer::SerializeContext cReq( \
nullptr, 0, \
RsGenericSerializer::SERIALIZATION_FLAG_YIELDING ); \
RsSerializationFlags::YIELDING ); \
RsJson& jReq(cReq.mJson); \
if(session->get_request()->get_method() == "GET") \
{ \
{ \
const std::string jrqp(session->get_request()->get_query_parameter("jsonData")); \
jReq.Parse(jrqp.c_str(), jrqp.size()); \
} \
@ -352,7 +352,7 @@ JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config"),
rsEvents, "rsEvents", cAns, session ) )
return;
RsEventType eventType = RsEventType::NONE;
RsEventType eventType = RsEventType::__NONE;
// deserialize input parameters from JSON
{
@ -395,7 +395,8 @@ JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config"),
} );
};
bool retval = rsEvents->registerEventsHandler(eventType,multiCallback, hId);
std::error_condition retval = rsEvents->registerEventsHandler(
multiCallback, hId, eventType );
{
RsGenericSerializer::SerializeContext& ctx(cAns);

View File

@ -151,8 +151,6 @@ protected:
/// @see RsThread
void onStopRequested() override;
static const RsJsonApiErrorCategory sErrorCategory;
static std::error_condition badApiCredientalsFormat(
const std::string& user, const std::string& passwd );

View File

@ -45,7 +45,6 @@ file_lists {
file_sharing/directory_updater.h \
file_sharing/rsfilelistitems.h \
file_sharing/dir_hierarchy.h \
file_sharing/file_tree.h \
file_sharing/file_sharing_defaults.h
SOURCES *= file_sharing/p3filelists.cc \
@ -481,6 +480,8 @@ HEADERS += util/folderiterator.h \
util/dnsresolver.h \
util/radix32.h \
util/radix64.h \
util/rsbase64.h \
util/rsendian.h \
util/rsinitedptr.h \
util/rsprint.h \
util/rsstring.h \
@ -494,7 +495,8 @@ HEADERS += util/folderiterator.h \
util/rstime.h \
util/stacktrace.h \
util/rsdeprecate.h \
util/cxx11retrocompat.h \
util/cxx11retrocompat.h \
util/cxx14retrocompat.h \
util/cxx17retrocompat.h \
util/rsurl.h \
util/rserrno.h
@ -637,6 +639,7 @@ SOURCES += util/folderiterator.cc \
util/rsrecogn.cc \
util/rstime.cc \
util/rsurl.cc \
util/rsbase64.cc \
util/rserrno.cc
equals(RS_UPNP_LIB, miniupnpc) {

View File

@ -630,50 +630,61 @@ std::string PGPHandler::SaveCertificateToString(const RsPgpId& id,bool include_s
return makeRadixEncodedPGPKey(key,include_signatures) ;
}
bool PGPHandler::exportPublicKey(const RsPgpId& id,unsigned char *& mem_block,size_t& mem_size,bool armoured,bool include_signatures) const
bool PGPHandler::exportPublicKey(
const RsPgpId& id,
unsigned char*& mem_block, size_t& mem_size,
bool armoured, bool include_signatures ) const
{
RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures.
const ops_keydata_t *key = locked_getPublicKey(id,false) ;
mem_block = NULL ;
mem_block = nullptr; mem_size = 0; // clear just in case
if(armoured)
{
std::cerr << __PRETTY_FUNCTION__ << ": should not be used with armoured=true, because there's a bug in the armoured export of OPS" << std::endl;
return false ;
RsErr() << __PRETTY_FUNCTION__ << " should not be used with "
<< "armoured=true, because there's a bug in the armoured export"
<< " of OPS" << std::endl;
print_stacktrace();
return false;
}
if(key == NULL)
RS_STACK_MUTEX(pgphandlerMtx);
const ops_keydata_t* key = locked_getPublicKey(id,false);
if(!key)
{
std::cerr << "Cannot output key " << id.toStdString() << ": not found in keyring." << std::endl;
return false ;
RsErr() << __PRETTY_FUNCTION__ << " key id: " << id
<< " not found in keyring." << std::endl;
return false;
}
ops_create_info_t* cinfo;
ops_memory_t *buf = NULL ;
ops_setup_memory_write(&cinfo, &buf, 0);
ops_create_info_t* cinfo;
ops_memory_t *buf = nullptr;
ops_setup_memory_write(&cinfo, &buf, 0);
if(ops_write_transferable_public_key_from_packet_data(key,armoured,cinfo) != ops_true)
if(ops_write_transferable_public_key_from_packet_data(
key, armoured, cinfo ) != ops_true)
{
std::cerr << "ERROR: This key cannot be processed by RetroShare because\nDSA certificates are not yet handled." << std::endl;
return false ;
RsErr() << __PRETTY_FUNCTION__ << " This key id " << id
<< " cannot be processed by RetroShare because DSA certificates"
<< " support is not implemented yet." << std::endl;
return false;
}
ops_writer_close(cinfo) ;
ops_writer_close(cinfo);
mem_block = new unsigned char[ops_memory_get_length(buf)] ;
mem_size = ops_memory_get_length(buf) ;
memcpy(mem_block,ops_memory_get_data(buf),mem_size) ;
mem_size = ops_memory_get_length(buf);
mem_block = reinterpret_cast<unsigned char*>(malloc(mem_size));
memcpy(mem_block,ops_memory_get_data(buf),mem_size);
ops_teardown_memory_write(cinfo,buf);
ops_teardown_memory_write(cinfo,buf);
if(!include_signatures)
{
size_t new_size ;
PGPKeyManagement::findLengthOfMinimalKey(mem_block,mem_size,new_size) ;
mem_size = new_size ;
size_t new_size;
PGPKeyManagement::findLengthOfMinimalKey(mem_block, mem_size, new_size);
mem_size = new_size;
}
return true ;
return true;
}
bool PGPHandler::exportGPGKeyPair(const std::string& filename,const RsPgpId& exported_key_id) const

View File

@ -107,7 +107,11 @@ public:
bool LoadCertificateFromBinaryData(const unsigned char *bin_data,uint32_t bin_data_len, RsPgpId& gpg_id, std::string& error_string);
std::string SaveCertificateToString(const RsPgpId& id,bool include_signatures) const ;
bool exportPublicKey(const RsPgpId& id,unsigned char *& mem,size_t& mem_size,bool armoured,bool include_signatures) const ;
/** The caller is in charge of freeing `mem` once finished */
bool exportPublicKey( const RsPgpId& id,
unsigned char*& mem, size_t& mem_size,
bool armoured, bool include_signatures) const;
bool parseSignature(unsigned char *sign, unsigned int signlen,RsPgpId& issuer_id) ;
bool SignDataBin(const RsPgpId& id, const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen, bool make_raw_signature=false, std::string reason = "") ;

View File

@ -3,7 +3,9 @@
* *
* libretroshare: retroshare core library *
* *
* Copyright (C) 2019 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2019-2020 Retroshare Team <contact@retroshare.cc> *
* Copyright (C) 2019-2020 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2020 Asociación Civil Altermundi <info@altermundi.net> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
@ -50,7 +52,7 @@ extern RsEvents* rsEvents;
*/
enum class RsEventType : uint32_t
{
NONE = 0, /// Used to detect uninitialized event
__NONE = 0, /// Used internally to detect invalid event type passed
/// @see RsBroadcastDiscovery
BROADCAST_DISCOVERY = 1,
@ -64,7 +66,7 @@ enum class RsEventType : uint32_t
/// @see pqissl
PEER_CONNECTION = 4,
/// @see RsGxsChanges // this one is used in RsGxsBroadcast
/// @see RsGxsChanges, used also in @see RsGxsBroadcast
GXS_CHANGES = 5,
/// Emitted when a peer state changes, @see RsPeers
@ -95,11 +97,62 @@ enum class RsEventType : uint32_t
FILE_TRANSFER = 14,
/// @see RsMsgs
CHAT_MESSAGE = 15,
CHAT_MESSAGE = 15,
MAX /// Used to detect invalid event type passed
__MAX /// Used internally, keep last
};
enum class RsEventsErrorNum : int32_t
{
EVENT_TYPE_UNDEFINED = 3004,
EVENT_TYPE_OUT_OF_RANGE = 3005,
INVALID_HANDLER_ID = 3006,
NULL_EVENT_POINTER = 3007
};
struct RsEventsErrorCategory: std::error_category
{
const char* name() const noexcept override
{ return "RetroShare Events"; }
std::string message(int ev) const override
{
switch (static_cast<RsEventsErrorNum>(ev))
{
case RsEventsErrorNum::EVENT_TYPE_UNDEFINED:
return "Undefined event type";
case RsEventsErrorNum::EVENT_TYPE_OUT_OF_RANGE:
return "Event type out of range";
case RsEventsErrorNum::INVALID_HANDLER_ID:
return "Invalid handler id";
default:
return "Error message for error: " + std::to_string(ev) +
" not available in category: " + name();
}
}
std::error_condition default_error_condition(int ev) const noexcept override;
const static RsEventsErrorCategory instance;
};
namespace std
{
/** Register RsJsonApiErrorNum as an error condition enum, must be in std
* namespace */
template<> struct is_error_condition_enum<RsEventsErrorNum> : true_type {};
}
/** Provide RsEventsErrorNum conversion to std::error_condition, must be in
* same namespace of RsJsonApiErrorNum */
inline std::error_condition make_error_condition(RsEventsErrorNum e) noexcept
{
return std::error_condition(
static_cast<int>(e), RsEventsErrorCategory::instance );
};
/**
* This struct is not meant to be used directly, you should create events type
* deriving from it.
@ -107,7 +160,7 @@ enum class RsEventType : uint32_t
struct RsEvent : RsSerializable
{
protected:
RsEvent(RsEventType type) :
explicit RsEvent(RsEventType type) :
mType(type), mTimePoint(std::chrono::system_clock::now()) {}
RsEvent() = delete;
@ -144,12 +197,10 @@ public:
* @param[in] event
* @param[out] errorMessage Optional storage for error messsage, meaningful
* only on failure.
* @return False on error, true otherwise.
* @return Success or error details.
*/
virtual bool postEvent(
std::shared_ptr<const RsEvent> event,
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
) = 0;
virtual std::error_condition postEvent(
std::shared_ptr<const RsEvent> event ) = 0;
/**
* @brief Send event directly to handlers. Blocking API
@ -157,12 +208,10 @@ public:
* @param[in] event
* @param[out] errorMessage Optional storage for error messsage, meaningful
* only on failure.
* @return False on error, true otherwise.
* @return Success or error details.
*/
virtual bool sendEvent(
std::shared_ptr<const RsEvent> event,
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
) = 0;
virtual std::error_condition sendEvent(
std::shared_ptr<const RsEvent> event ) = 0;
/**
* @brief Generate unique handler identifier
@ -174,8 +223,9 @@ public:
* @brief Register events handler
* Every time an event is dispatced the registered events handlers will get
* their method handleEvent called with the event passed as paramether.
* @attention Callbacks must not fiddle internally with methods of this
* class otherwise a deadlock will happen.
* @jsonapi{development,manualwrapper}
* @param eventType Type of event for which the callback is called
* @param multiCallback Function that will be called each time an event
* is dispatched.
* @param[inout] hId Optional storage for handler id, useful to
@ -183,21 +233,23 @@ public:
* value may be provided to the function call but
* must habe been generated with
* @see generateUniqueHandlerId()
* @return False on error, true otherwise.
* @param[in] eventType Optional type of event for which the callback is
* called, if __NONE is passed multiCallback is
* called for every events without filtering.
* @return Success or error details.
*/
virtual bool registerEventsHandler(
RsEventType eventType,
virtual std::error_condition registerEventsHandler(
std::function<void(std::shared_ptr<const RsEvent>)> multiCallback,
RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0)
) = 0;
RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0),
RsEventType eventType = RsEventType::__NONE ) = 0;
/**
* @brief Unregister event handler
* @param[in] hId Id of the event handler to unregister
* @return True if the handler id has been found, false otherwise.
* @return Success or error details.
*/
virtual bool unregisterEventsHandler(RsEventsHandlerId_t hId) = 0;
virtual std::error_condition unregisterEventsHandler(
RsEventsHandlerId_t hId ) = 0;
virtual ~RsEvents();
};

View File

@ -4,7 +4,8 @@
* libretroshare: retroshare core library *
* *
* Copyright (C) 2008 Robert Fernie <retroshare@lunamutt.com> *
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2018-2020 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2019-2020 Asociación Civil Altermundi <info@altermundi.net> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
@ -28,12 +29,14 @@
#include <functional>
#include <chrono>
#include <cstdint>
#include <system_error>
#include "rstypes.h"
#include "serialiser/rsserializable.h"
#include "rsturtle.h"
#include "util/rstime.h"
#include "retroshare/rsevents.h"
#include "util/rsmemory.h"
class RsFiles;
@ -43,6 +46,50 @@ class RsFiles;
*/
extern RsFiles* rsFiles;
enum class RsFilesErrorNum : int32_t
{
FILES_HANDLE_NOT_FOUND = 2004,
};
struct RsFilesErrorCategory: std::error_category
{
const char* name() const noexcept override
{ return "RetroShare Files"; }
std::string message(int ev) const override
{
switch (static_cast<RsFilesErrorNum>(ev))
{
case RsFilesErrorNum::FILES_HANDLE_NOT_FOUND:
return "Files handle not found";
default:
return "Error message for error: " + std::to_string(ev) +
" not available in category: " + name();
}
}
std::error_condition default_error_condition(int ev) const noexcept override;
const static RsFilesErrorCategory instance;
};
namespace std
{
/** Register RsFilesErrorNum as an error condition enum, must be in std
* namespace */
template<> struct is_error_condition_enum<RsFilesErrorNum> : true_type {};
}
/** Provide RsJsonApiErrorNum conversion to std::error_condition, must be in
* same namespace of RsJsonApiErrorNum */
inline std::error_condition make_error_condition(RsFilesErrorNum e) noexcept
{
return std::error_condition(
static_cast<int>(e), RsFilesErrorCategory::instance );
};
namespace RsRegularExpression { class Expression; }
/* These are used mainly by ftController at the moment */
@ -96,8 +143,28 @@ const FileSearchFlags RS_FILE_HINTS_BROWSABLE ( 0x00000100 );// bro
const FileSearchFlags RS_FILE_HINTS_SEARCHABLE ( 0x00000200 );// can be searched anonymously
const FileSearchFlags RS_FILE_HINTS_PERMISSION_MASK ( 0x00000380 );// OR of the last tree flags. Used to filter out.
// Flags used when requesting a transfer
//
/** Flags used when requesting a new file transfer */
enum class FileRequestFlags: uint32_t
{
/// Enable requesting file via turtle routing.
ANONYMOUS_ROUTING = 0x00000040,
/// Asks (TODO: or enforce?) for end-to-end encryption of file trasfer
ENCRYPTED = 0x00000080,
/// Asks (TODO: or enforce?) no end-to-end encryption of file trasfer
UNENCRYPTED = 0x00000100,
/// Start trasfer very slow
SLOW = 0x00002000,
/// Disable searching for potential direct sources
NO_DIRECT_SEARCH = 0x02000000
};
RS_REGISTER_ENUM_FLAGS_TYPE(FileRequestFlags)
/// @deprecated Flags used when requesting a transfer
/// @see FileRequestFlags instead
const TransferRequestFlags RS_FILE_REQ_ANONYMOUS_ROUTING ( 0x00000040 ); // Use to ask turtle router to download the file.
const TransferRequestFlags RS_FILE_REQ_ENCRYPTED ( 0x00000080 ); // Asks for end-to-end encryption of file at the level of ftServer
const TransferRequestFlags RS_FILE_REQ_UNENCRYPTED ( 0x00000100 ); // Asks for no end-to-end encryption of file at the level of ftServer
@ -111,10 +178,6 @@ const TransferRequestFlags RS_FILE_REQ_NO_SEARCH ( 0x02000000 ); // di
// const uint32_t RS_FILE_HINTS_SHARE_FLAGS_MASK = RS_FILE_HINTS_NETWORK_WIDE_OTHERS | RS_FILE_HINTS_BROWSABLE_OTHERS
// | RS_FILE_HINTS_NETWORK_WIDE_GROUPS | RS_FILE_HINTS_BROWSABLE_GROUPS ;
/* Callback Codes */
const uint32_t RS_FILE_EXTRA_DELETE = 0x0010;
enum class RsSharedDirectoriesEventCode: uint8_t {
UNKNOWN = 0x00,
STARTING_DIRECTORY_SWEEP = 0x01, // (void)
@ -202,36 +265,117 @@ struct SharedDirStats
uint64_t total_shared_size ;
};
// This class represents a tree of directories and files, only with their names size and hash. It is used to create collection links in the GUI
// and to transmit directory information between services. This class is independent from the existing FileHierarchy classes used in storage because
// we need a very copact serialization and storage size since we create links with it. Besides, we cannot afford to risk the leak of other local information
// by using the orignal classes.
class FileTree
/** This class represents a tree of directories and files, only with their names
* size and hash. It is used to create collection links in the GUI and to
* transmit directory information between services. This class is independent
* from the existing FileHierarchy classes used in storage because we need a
* very copact serialization and storage size since we create links with it.
* Besides, we cannot afford to risk the leak of other local information
* by using the orignal classes.
*/
struct RsFileTree : RsSerializable
{
public:
virtual ~FileTree() {}
RsFileTree() : mTotalFiles(0), mTotalSize(0) {}
static FileTree *create(const DirDetails& dd, bool remote, bool remove_top_dirs = true) ;
static FileTree *create(const std::string& radix64_string) ;
/**
* @brief Create a RsFileTree from directory details
* @param dd directory or file details
* @param remote
* @param remove_top_dirs
* @return pointer to the created file-tree
*/
static std::unique_ptr<RsFileTree> fromDirDetails(
const DirDetails& dd, bool remote, bool remove_top_dirs = true );
virtual std::string toRadix64() const =0 ;
/**
* @brief Create a RsFileTree from Base64 representation
* @param base64 base64 or base64url string representation of the file-tree
* @return pointer to the parsed file-tree on success, nullptr plus error
* details on failure
*/
static std::tuple<std::unique_ptr<RsFileTree>, std::error_condition>
fromBase64(const std::string& base64);
// These methods allow the user to browse the hierarchy
/** @brief Convert to base64 representetion */
std::string toBase64() const;
struct FileData {
std::string name ;
uint64_t size ;
RsFileHash hash ;
/// @see RsSerializable
virtual void serial_process(
RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx )
{
RS_SERIAL_PROCESS(mFiles);
RS_SERIAL_PROCESS(mDirs);
RS_SERIAL_PROCESS(mTotalFiles);
RS_SERIAL_PROCESS(mTotalSize);
}
struct FileData: RsSerializable
{
std::string name;
uint64_t size;
RsFileHash hash;
void serial_process(
RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx ) override;
};
virtual uint32_t root() const { return 0;}
virtual bool getDirectoryContent(uint32_t index,std::string& name,std::vector<uint32_t>& subdirs,std::vector<FileData>& subfiles) const = 0;
/// Allow browsing the hierarchy
bool getDirectoryContent(
std::string& name, std::vector<uint64_t>& subdirs,
std::vector<FileData>& subfiles, uint64_t handle = 0 ) const;
virtual void print() const=0;
struct DirData: RsSerializable
{
std::string name;
std::vector<uint64_t> subdirs;
std::vector<uint64_t> subfiles;
uint32_t mTotalFiles ;
uint64_t mTotalSize ;
void serial_process(
RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx ) override;
};
static void recurs_buildFileTree(
RsFileTree& ft, uint32_t index, const DirDetails& dd, bool remote,
bool remove_top_dirs );
std::vector<FileData> mFiles;
std::vector<DirData> mDirs;
uint32_t mTotalFiles;
uint64_t mTotalSize;
virtual ~RsFileTree();
/**
* @brief Create a RsFileTree from Radix64 representation
* @deprecated kept for retrocompatibility with RetroShare-gui
* The format is not compatible with the new methods
* @param radix64_string
* @return nullptr if on failure, pointer to the created FileTree on success
*/
RS_DEPRECATED_FOR(fromBase64)
static std::unique_ptr<RsFileTree> fromRadix64(
const std::string& radix64_string );
/** @brief Convert to radix64 representetion
* @deprecated kept for retrocompatibility with RetroShare-gui
* The format is not compatible with the new methods
*/
RS_DEPRECATED_FOR(toBase64)
std::string toRadix64() const;
private:
/** @deprecated kept for retrocompatibility with RetroShare-gui */
RS_DEPRECATED_FOR(serial_process)
bool serialise(unsigned char *& data,uint32_t& data_size) const;
/** @deprecated kept for retrocompatibility with RetroShare-gui */
RS_DEPRECATED_FOR(serial_process)
bool deserialise(unsigned char* data, uint32_t data_size);
};
struct BannedFileEntry : RsSerializable
@ -258,12 +402,12 @@ struct TurtleFileInfoV2 : RsSerializable
{
TurtleFileInfoV2() : fSize(0), fWeight(0) {}
TurtleFileInfoV2(const TurtleFileInfo& oldInfo) :
explicit TurtleFileInfoV2(const TurtleFileInfo& oldInfo) :
fSize(oldInfo.size), fHash(oldInfo.hash), fName(oldInfo.name),
fWeight(0) {}
#ifdef RS_DEEP_FILES_INDEX
TurtleFileInfoV2(const DeepFilesSearchResult& dRes);
explicit TurtleFileInfoV2(const DeepFilesSearchResult& dRes);
#endif // def RS_DEEP_FILES_INDEX
uint64_t fSize; /// File size
@ -301,9 +445,6 @@ struct TurtleFileInfoV2 : RsSerializable
class RsFiles
{
public:
RsFiles() {}
virtual ~RsFiles() {}
/**
* @brief Provides file data for the GUI, media streaming or API clients.
* It may return unverified chunks. This allows streaming without having to
@ -344,10 +485,10 @@ public:
/**
* @brief Initiate downloading of a file
* @jsonapi{development}
* @param[in] fileName
* @param[in] hash
* @param[in] size
* @param[in] destPath in not empty specify a destination path
* @param[in] fileName file name
* @param[in] hash file hash
* @param[in] size file size
* @param[in] destPath optional specify the destination directory
* @param[in] flags you usually want RS_FILE_REQ_ANONYMOUS_ROUTING
* @param[in] srcIds eventually specify known sources
* @return false if we already have the file, true otherwhise
@ -357,6 +498,25 @@ public:
const std::string& destPath, TransferRequestFlags flags,
const std::list<RsPeerId>& srcIds ) = 0;
/**
* @brief Initiate download of a files collection
* @jsonapi{development}
* An usually useful companion method of this is @see parseFilesLink()
* @param[in] collection collection of files to download
* @param[in] destPath optional base path on which to download the
* collection, if left empty the default download directory will be used
* @param[in] srcIds optional peers id known as direct source of the
* collection
* @param[in] flags optional flags to fine tune search and download
* algorithm
* @return success or error details.
*/
virtual std::error_condition requestFiles(
const RsFileTree& collection,
const std::string& destPath = "",
const std::vector<RsPeerId>& srcIds = std::vector<RsPeerId>(),
FileRequestFlags flags = FileRequestFlags::ANONYMOUS_ROUTING ) = 0;
/**
* @brief Cancel file downloading
* @jsonapi{development}
@ -575,7 +735,7 @@ public:
* @return false if error occurred, true otherwise
*/
virtual bool requestDirDetails(
DirDetails &details, std::uintptr_t handle = 0,
DirDetails &details, uint64_t handle = 0,
FileSearchFlags flags = RS_FILE_HINTS_LOCAL ) = 0;
/***
@ -584,8 +744,9 @@ public:
/**
* Kept for retrocompatibility, it was originally written for easier
* interaction with Qt. As soon as you can, you should prefer to use the
* version of this methodn which take `std::uintptr_t handle` as paramether.
* version of this method which take `uint64_t handle` as paramether.
*/
RS_DEPRECATED_FOR(requestDirDetails)
virtual int RequestDirDetails(
void* handle, DirDetails& details, FileSearchFlags flags ) = 0;
@ -726,6 +887,76 @@ public:
*/
virtual bool removeSharedDirectory(std::string dir) = 0;
/// Default base URL used for files links @see exportFilesLink
static const std::string DEFAULT_FILES_BASE_URL;
/** Link query field used to store collection files count
* @see exportFilesLink */
static const std::string FILES_URL_COUNT_FIELD;
/// Link query field used to store collection data @see exportFilesLink
static const std::string FILES_URL_DATA_FIELD;
/** Link query FILES_URL_DATA_FIELD field value used to instruct the parser
* to look for the data into the link fragment
* @see exportFilesLink and parseFilesLink */
static const std::string FILES_URL_FAGMENT_FORWARD;
/// Link query field used to store collection name @see exportFilesLink
static const std::string FILES_URL_NAME_FIELD;
/// Link query field used to store collection size @see exportFilesLink
static const std::string FILES_URL_SIZE_FIELD;
/**
* @brief Export link to a collection of files
* @jsonapi{development}
* @param[out] link storage for the generated link
* @param[in] handle directory RetroShare handle
* @param[in] fragSneak when true the file data is sneaked into fragment
* instead of FILES_URL_DATA_FIELD query field, this way if using an
* http[s] link to pass around a disguised file link a misconfigured host
* attempting to visit that link with a web browser will not send the file
* data to the server thus protecting at least some of the privacy of the
* user even in a misconfiguration scenario.
* @param[in] baseUrl URL into which to sneak in the RetroShare file link
* base64, this is primarly useful to induce applications into making the
* link clickable, or to disguise the RetroShare link into a "normal"
* looking web link. If empty the collection data link will be outputted in
* plain base64 format.
* @return error information if some error occurred, 0/SUCCESS otherwise
*/
virtual std::error_condition exportCollectionLink(
std::string& link, uint64_t handle, bool fragSneak = false,
const std::string& baseUrl = RsFiles::DEFAULT_FILES_BASE_URL ) = 0;
/**
* @brief Export link to a file
* @jsonapi{development}
* @param[out] link @see exportCollectionLink
* @param[in] fileHash hash of the file
* @param[in] fileSize size of the file
* @param[in] fileName name of the file
* @param[in] fragSneak @see exportCollectionLink
* @param[in] baseUrl @see exportCollectionLink
* @return error @see exportCollectionLink
*/
virtual std::error_condition exportFileLink(
std::string& link, const RsFileHash& fileHash, uint64_t fileSize,
const std::string& fileName, bool fragSneak = false,
const std::string& baseUrl = RsFiles::DEFAULT_FILES_BASE_URL ) = 0;
/**
* @brief Parse RetroShare files link
* @jsonapi{development}
* Support also old RetroShare-gui file and collections links format.
* @param[in] link files link either in base64 or URL format
* @param[out] collection storage for parsed files link
* @return error information if some error occurred, 0/SUCCESS otherwise
*/
virtual std::error_condition parseFilesLink(
const std::string& link, RsFileTree& collection ) = 0;
/**
* @brief Get list of ignored file name prefixes and suffixes
* @param[out] ignoredPrefixes storage for ingored prefixes
@ -757,4 +988,6 @@ public:
virtual bool ignoreDuplicates() = 0;
virtual void setIgnoreDuplicates(bool ignore) = 0;
virtual ~RsFiles() = default;
};

View File

@ -24,6 +24,7 @@
#include <type_traits>
#include <ostream>
#include <bitset>
/** Check if given type is a scoped enum */
template<typename E>
@ -128,13 +129,7 @@ typename std::enable_if<Rs__BitFlagsOps<EFT>::enabled, std::ostream>::type&
operator <<(std::ostream& stream, EFT flags)
{
using u_t = typename std::underlying_type<EFT>::type;
for(int i = sizeof(u_t); i>=0; --i)
{
stream << (flags & ( 1 << i ) ? "1" : "0");
if( i % 8 == 0 ) stream << " ";
}
return stream;
return stream << std::bitset<sizeof(u_t)>(static_cast<u_t>(flags));
}
#include <cstdint>
@ -170,6 +165,7 @@ template<int n> class RS_DEPRECATED_FOR(RS_REGISTER_ENUM_FLAGS_TYPE) t_RsFlags32
inline t_RsFlags32() : _bits(0) {}
inline explicit t_RsFlags32(uint32_t N) : _bits(N) {} // allows initialization from a set of uint32_t
inline t_RsFlags32<n> operator| (const t_RsFlags32<n>& f) const { return t_RsFlags32<n>(_bits | f._bits) ; }
inline t_RsFlags32<n> operator^ (const t_RsFlags32<n>& f) const { return t_RsFlags32<n>(_bits ^ f._bits) ; }
inline t_RsFlags32<n> operator* (const t_RsFlags32<n>& f) const { return t_RsFlags32<n>(_bits & f._bits) ; }
@ -187,6 +183,19 @@ template<int n> class RS_DEPRECATED_FOR(RS_REGISTER_ENUM_FLAGS_TYPE) t_RsFlags32
//inline explicit operator bool() const { return _bits>0; }
inline uint32_t toUInt32() const { return _bits ; }
/// Easier porting to new flag system
template<typename EFT> inline
typename std::enable_if<(Rs__BitFlagsOps<EFT>::enabled &&
sizeof(EFT) >= sizeof(uint32_t) ), EFT>::type
toEFT() { return static_cast<EFT>(_bits); }
/// Easier porting to new flag system
template<typename EFT>
static inline typename std::enable_if<
Rs__BitFlagsOps<EFT>::enabled &&
sizeof(EFT) <= sizeof(uint32_t), t_RsFlags32>::type
fromEFT(EFT e) { return t_RsFlags32(static_cast<uint32_t>(e)); }
void clear() { _bits = 0 ; }
friend std::ostream& operator<<(std::ostream& o,const t_RsFlags32<n>& f) // friendly print with 0 and I
@ -199,8 +208,10 @@ template<int n> class RS_DEPRECATED_FOR(RS_REGISTER_ENUM_FLAGS_TYPE) t_RsFlags32
}
return o ;
}
private:
uint32_t _bits ;
private:
friend struct RsTypeSerializer;
uint32_t _bits;
};
#define FLAGS_TAG_TRANSFER_REQS 0x4228af
@ -210,9 +221,9 @@ template<int n> class RS_DEPRECATED_FOR(RS_REGISTER_ENUM_FLAGS_TYPE) t_RsFlags32
#define FLAGS_TAG_SERVICE_CHAT 0x839042
#define FLAGS_TAG_SERIALIZER 0xa0338d
// Flags for requesting transfers, ask for turtle, cache, speed, etc.
//
typedef t_RsFlags32<FLAGS_TAG_TRANSFER_REQS> TransferRequestFlags ;
/// @deprecated Flags for requesting transfers, ask for turtle, cache, speed, etc.
RS_DEPRECATED_FOR(FileRequestFlags)
typedef t_RsFlags32<FLAGS_TAG_TRANSFER_REQS> TransferRequestFlags;
// Flags for file storage. Mainly permissions like BROWSABLE/NETWORK_WIDE for groups and peers.
//
@ -230,7 +241,3 @@ typedef t_RsFlags32<FLAGS_TAG_SERVICE_PERM > ServicePermissionFlags ;
//
typedef t_RsFlags32<FLAGS_TAG_SERVICE_CHAT > ChatLobbyFlags ;
// Flags for serializer
//
typedef t_RsFlags32<FLAGS_TAG_SERIALIZER > SerializationFlags ;

View File

@ -4,7 +4,8 @@
* libretroshare: retroshare core library *
* *
* Copyright (C) 2012 Robert Fernie <retroshare@lunamutt.com> *
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2018-2020 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2019-2020 Asociación Civil Altermundi <info@altermundi.net> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
@ -283,26 +284,6 @@ public:
*/
virtual bool ExtraFileRemove(const RsFileHash& hash) = 0;
/**
* @brief Get auto-download option value for given channel
* @jsonapi{development}
* @param[in] channelId channel id
* @param[out] enabled storage for the auto-download option value
* @return false if something failed, true otherwhise
*/
virtual bool getChannelAutoDownload(
const RsGxsGroupId& channelId, bool& enabled ) = 0;
/**
* @brief Get download directory for the given channel
* @jsonapi{development}
* @param[in] channelId id of the channel
* @param[out] directory reference to string where to store the path
* @return false on error, true otherwise
*/
virtual bool getChannelDownloadDirectory( const RsGxsGroupId& channelId,
std::string& directory ) = 0;
/**
* @brief Get channels summaries list. Blocking API.
* @jsonapi{development}
@ -331,13 +312,15 @@ public:
* @param[out] comments storage for the comments
* @return false if something failed, true otherwhise
*/
virtual bool getChannelAllContent(const RsGxsGroupId& channelId,
virtual bool getChannelAllContent( const RsGxsGroupId& channelId,
std::vector<RsGxsChannelPost>& posts,
std::vector<RsGxsComment>& comments ) = 0;
/**
* @brief Get channel messages and comments corresponding to the given message ID list. If the list is empty, nothing is returned. Since
* comments are themselves messages, it is possible to get comments only by only supplying their message IDs.
* @brief Get channel messages and comments corresponding to the given IDs.
* If the set is empty, nothing is returned.
* @note Since comments are internally themselves messages, it is possible
* to get comments only by supplying their IDs.
* @jsonapi{development}
* @param[in] channelId id of the channel of which the content is requested
* @param[in] contentsIds ids of requested contents
@ -345,8 +328,8 @@ public:
* @param[out] comments storage for the comments
* @return false if something failed, true otherwhise
*/
virtual bool getChannelContent(const RsGxsGroupId& channelId,
const std::set<RsGxsMessageId>& contentIds,
virtual bool getChannelContent( const RsGxsGroupId& channelId,
const std::set<RsGxsMessageId>& contentsIds,
std::vector<RsGxsChannelPost>& posts,
std::vector<RsGxsComment>& comments ) = 0;
@ -369,16 +352,6 @@ public:
*/
virtual bool markRead(const RsGxsGrpMsgIdPair& postId, bool read) = 0;
/**
* @brief Enable or disable auto-download for given channel. Blocking API
* @jsonapi{development}
* @param[in] channelId channel id
* @param[in] enable true to enable, false to disable
* @return false if something failed, true otherwhise
*/
virtual bool setChannelAutoDownload(
const RsGxsGroupId& channelId, bool enable ) = 0;
/**
* @brief Share channel publishing key
* This can be used to authorize other peers to post on the channel
@ -390,16 +363,6 @@ public:
virtual bool shareChannelKeys(
const RsGxsGroupId& channelId, const std::set<RsPeerId>& peers ) = 0;
/**
* @brief Set download directory for the given channel. Blocking API.
* @jsonapi{development}
* @param[in] channelId id of the channel
* @param[in] directory path
* @return false on error, true otherwise
*/
virtual bool setChannelDownloadDirectory(
const RsGxsGroupId& channelId, const std::string& directory) = 0;
/**
* @brief Subscrbe to a channel. Blocking API
* @jsonapi{development}
@ -525,8 +488,62 @@ public:
std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0;
/* Following functions are deprecated as they expose internal functioning
* semantic, instead of a safe to use API */
/* Following functions are deprecated and should not be considered a safe to
* use API */
/**
* @brief Get auto-download option value for given channel
* @jsonapi{development}
* @deprecated This feature rely on very buggy code, the returned value is
* not reliable @see setChannelAutoDownload().
* @param[in] channelId channel id
* @param[out] enabled storage for the auto-download option value
* @return false if something failed, true otherwhise
*/
RS_DEPRECATED
virtual bool getChannelAutoDownload(
const RsGxsGroupId& channelId, bool& enabled ) = 0;
/**
* @brief Enable or disable auto-download for given channel. Blocking API
* @jsonapi{development}
* @deprecated This feature rely on very buggy code, when enabled the
* channel service start flooding erratically log with error messages,
* apparently without more dangerous consequences. Still those messages
* hints that something out of control is happening under the hood, use at
* your own risk. A safe alternative to this method can easly implemented
* at API client level instead.
* @param[in] channelId channel id
* @param[in] enable true to enable, false to disable
* @return false if something failed, true otherwhise
*/
RS_DEPRECATED
virtual bool setChannelAutoDownload(
const RsGxsGroupId& channelId, bool enable ) = 0;
/**
* @brief Get download directory for the given channel
* @jsonapi{development}
* @deprecated @see setChannelAutoDownload()
* @param[in] channelId id of the channel
* @param[out] directory reference to string where to store the path
* @return false on error, true otherwise
*/
RS_DEPRECATED
virtual bool getChannelDownloadDirectory( const RsGxsGroupId& channelId,
std::string& directory ) = 0;
/**
* @brief Set download directory for the given channel. Blocking API.
* @jsonapi{development}
* @deprecated @see setChannelAutoDownload()
* @param[in] channelId id of the channel
* @param[in] directory path
* @return false on error, true otherwise
*/
RS_DEPRECATED
virtual bool setChannelDownloadDirectory(
const RsGxsGroupId& channelId, const std::string& directory) = 0;
/**
* @brief Create channel. Blocking API.

View File

@ -305,10 +305,10 @@ public:
static const std::string FORUM_URL_DATA_FIELD;
/** Link query field used to store forum message title
* @see exportChannelLink */
* @see exportForumLink */
static const std::string FORUM_URL_MSG_TITLE_FIELD;
/// Link query field used to store forum message id @see exportChannelLink
/// Link query field used to store forum message id @see exportForumLink
static const std::string FORUM_URL_MSG_ID_FIELD;
/**

View File

@ -3,8 +3,8 @@
* *
* libretroshare: retroshare core library *
* *
* Copyright 2011 by Christopher Evi-Parker *
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2011 Christopher Evi-Parker *
* Copyright (C) 2018-2020 Gioacchino Mazzurco <gio@eigenlab.org> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
@ -30,6 +30,7 @@
#include "retroshare/rsreputations.h"
#include "rsgxsflags.h"
#include "util/rsdeprecate.h"
#include "util/rsdebug.h"
/*!
* This class only make method of internal members visible tu upper level to
@ -46,7 +47,7 @@
enum class TokenRequestType: uint8_t
{
UNDEFINED = 0x00,
__NONE = 0x00, /// Used to detect uninitialized
GROUP_DATA = 0x01,
GROUP_META = 0x02,
POSTS = 0x03,
@ -55,6 +56,7 @@ enum class TokenRequestType: uint8_t
GROUP_STATISTICS = 0x06,
SERVICE_STATISTICS = 0x07,
NO_KILL_TYPE = 0x08,
__MAX /// Used to detect out of range
};
class RsGxsIfaceHelper
@ -64,10 +66,11 @@ public:
* @param gxs handle to RsGenExchange instance of service (Usually the
* service class itself)
*/
RsGxsIfaceHelper(RsGxsIface& gxs) :
mGxs(gxs), mTokenService(*gxs.getTokenService()),mMtx("GxsIfaceHelper") {}
explicit RsGxsIfaceHelper(RsGxsIface& gxs) :
mGxs(gxs), mTokenService(*gxs.getTokenService()), mMtx("GxsIfaceHelper")
{}
~RsGxsIfaceHelper(){}
~RsGxsIfaceHelper() = default;
/*!
* Gxs services should call this for automatic handling of
@ -444,9 +447,9 @@ protected:
uint32_t token,
std::chrono::milliseconds maxWait = std::chrono::milliseconds(20000),
std::chrono::milliseconds checkEvery = std::chrono::milliseconds(100),
bool auto_delete_if_unsuccessful=true)
bool auto_delete_if_unsuccessful=true)
{
#if defined(__ANDROID__) && (__ANDROID_API__ < 24)
#if defined(__ANDROID__) && (__ANDROID_API__ < 24)
auto wkStartime = std::chrono::steady_clock::now();
int maxWorkAroundCnt = 10;
LLwaitTokenBeginLabel:
@ -454,13 +457,14 @@ LLwaitTokenBeginLabel:
auto timeout = std::chrono::steady_clock::now() + maxWait;
auto st = requestStatus(token);
while( !(st == RsTokenService::FAILED || st >= RsTokenService::COMPLETE) && std::chrono::steady_clock::now() < timeout )
while( !(st == RsTokenService::FAILED || st >= RsTokenService::COMPLETE)
&& std::chrono::steady_clock::now() < timeout )
{
std::this_thread::sleep_for(checkEvery);
st = requestStatus(token);
}
if(st != RsTokenService::COMPLETE && auto_delete_if_unsuccessful)
cancelRequest(token);
if(st != RsTokenService::COMPLETE && auto_delete_if_unsuccessful)
cancelRequest(token);
#if defined(__ANDROID__) && (__ANDROID_API__ < 24)
/* Work around for very slow/old android devices, we don't expect this
@ -487,35 +491,39 @@ LLwaitTokenBeginLabel:
#endif
{
RS_STACK_MUTEX(mMtx);
RS_STACK_MUTEX(mMtx);
mActiveTokens.erase(token);
}
}
return st;
}
return st;
}
private:
RsGxsIface& mGxs;
RsTokenService& mTokenService;
RsMutex mMtx;
RsMutex mMtx;
std::map<uint32_t,TokenRequestType> mActiveTokens;
std::map<uint32_t,TokenRequestType> mActiveTokens;
void locked_dumpTokens()
{
uint16_t service_id = mGxs.serviceType();
void locked_dumpTokens()
{
const uint16_t service_id = mGxs.serviceType();
const auto countSize = static_cast<size_t>(TokenRequestType::__MAX);
uint32_t count[countSize] = {0};
uint32_t count[7] = {0};
RsDbg() << __PRETTY_FUNCTION__ << "Service 0x" << std::hex << service_id
<< " (" << rsServiceControl->getServiceName(
RsServiceInfo::RsServiceInfoUIn16ToFullServiceId(service_id) )
<< ") this=0x" << static_cast<void*>(this)
<< ") Active tokens (per type): ";
RsDbg() << "Service " << std::hex << service_id << std::dec
<< " (" << rsServiceControl->getServiceName(RsServiceInfo::RsServiceInfoUIn16ToFullServiceId(service_id))
<< ") this=" << std::hex << (void*)this << std::dec << ") Active tokens (per type): " ;
// let's count how many token of each type we've got.
for(auto& it: mActiveTokens) ++count[static_cast<size_t>(it.second)];
for(auto& it: mActiveTokens) // let's count how many token of each type we've got.
++count[static_cast<int>(it.second)];
for(uint32_t i=0; i < countSize; ++i)
RsDbg().uStream() /* << i << ":" */ << count[i] << " ";
RsDbg().uStream() << std::endl;
}
for(uint32_t i=0;i<7;++i)
std::cerr << std::dec /* << i << ":" */ << count[i] << " ";
std::cerr << std::endl;
}
RS_SET_CONTEXT_DEBUG_LEVEL(1)
};

View File

@ -193,55 +193,50 @@ struct RsMsgMetaData : RsSerializable
struct RsGxsGenericMsgData
{
virtual ~RsGxsGenericMsgData() = default; // making the type polymorphic
virtual ~RsGxsGenericMsgData() = default; // making the type polymorphic
RsMsgMetaData mMeta;
};
class GxsGroupStatistic
struct GxsGroupStatistic : RsSerializable
{
public:
GxsGroupStatistic()
GxsGroupStatistic() :
mNumMsgs(0), mTotalSizeOfMsgs(0), mNumThreadMsgsNew(0),
mNumThreadMsgsUnread(0), mNumChildMsgsNew(0), mNumChildMsgsUnread(0) {}
/// @see RsSerializable
void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx ) override
{
mNumMsgs = 0;
mTotalSizeOfMsgs = 0;
mNumThreadMsgsNew = 0;
mNumThreadMsgsUnread = 0;
mNumChildMsgsNew = 0;
mNumChildMsgsUnread = 0;
RS_SERIAL_PROCESS(mGrpId);
RS_SERIAL_PROCESS(mNumMsgs);
RS_SERIAL_PROCESS(mTotalSizeOfMsgs);
RS_SERIAL_PROCESS(mNumThreadMsgsNew);
RS_SERIAL_PROCESS(mNumThreadMsgsUnread);
RS_SERIAL_PROCESS(mNumChildMsgsNew);
RS_SERIAL_PROCESS(mNumChildMsgsUnread);
}
public:
/// number of message
RsGxsGroupId mGrpId;
uint32_t mNumMsgs; // from the database
RsGxsGroupId mGrpId;
uint32_t mNumMsgs; /// number of message, from the database
uint32_t mTotalSizeOfMsgs;
uint32_t mNumThreadMsgsNew;
uint32_t mNumThreadMsgsUnread;
uint32_t mNumChildMsgsNew;
uint32_t mNumChildMsgsUnread;
uint32_t mNumChildMsgsUnread;
~GxsGroupStatistic() override;
};
class GxsServiceStatistic
struct GxsServiceStatistic : RsSerializable
{
public:
GxsServiceStatistic()
{
mNumMsgs = 0;
mNumGrps = 0;
mSizeOfMsgs = 0;
mSizeOfGrps = 0;
mNumGrpsSubscribed = 0;
mNumThreadMsgsNew = 0;
mNumThreadMsgsUnread = 0;
mNumChildMsgsNew = 0;
mNumChildMsgsUnread = 0;
mSizeStore = 0;
}
GxsServiceStatistic() :
mNumMsgs(0), mNumGrps(0), mSizeOfMsgs(0), mSizeOfGrps(0),
mNumGrpsSubscribed(0), mNumThreadMsgsNew(0), mNumThreadMsgsUnread(0),
mNumChildMsgsNew(0), mNumChildMsgsUnread(0), mSizeStore(0) {}
public:
uint32_t mNumMsgs;
uint32_t mNumGrps;
uint32_t mSizeOfMsgs;
@ -252,32 +247,35 @@ public:
uint32_t mNumChildMsgsNew;
uint32_t mNumChildMsgsUnread;
uint32_t mSizeStore;
/// @see RsSerializable
void serial_process( RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx ) override
{
RS_SERIAL_PROCESS(mNumMsgs);
RS_SERIAL_PROCESS(mNumGrps);
RS_SERIAL_PROCESS(mSizeOfMsgs);
RS_SERIAL_PROCESS(mSizeOfGrps);
RS_SERIAL_PROCESS(mNumGrpsSubscribed);
RS_SERIAL_PROCESS(mNumThreadMsgsNew);
RS_SERIAL_PROCESS(mNumThreadMsgsUnread);
RS_SERIAL_PROCESS(mNumChildMsgsNew);
RS_SERIAL_PROCESS(mNumChildMsgsUnread);
RS_SERIAL_PROCESS(mSizeStore);
}
~GxsServiceStatistic() override;
};
class UpdateItem
{
public:
virtual ~UpdateItem() { }
};
class StringUpdateItem : public UpdateItem
{
public:
StringUpdateItem(const std::string update) : mUpdate(update) {}
const std::string& getUpdate() const { return mUpdate; }
private:
std::string mUpdate;
};
class RsGxsGroupUpdateMeta
class RS_DEPRECATED RsGxsGroupUpdateMeta
{
public:
// expand as support is added for other utypes
enum UpdateType { DESCRIPTION, NAME };
RsGxsGroupUpdateMeta(const RsGxsGroupId& groupId) : mGroupId(groupId) {}
explicit RsGxsGroupUpdateMeta(const RsGxsGroupId& groupId):
mGroupId(groupId) {}
typedef std::map<UpdateType, std::string> GxsMetaUpdate;

View File

@ -37,7 +37,7 @@
#include "serialiser/rstypeserializer.h"
#include "util/rsdeprecate.h"
struct RsIdentity;
class RsIdentity;
/**
* Pointer to global instance of RsIdentity service implementation

View File

@ -1,7 +1,7 @@
/*
* RetroShare JSON API public header
*
* Copyright (C) 2018-2020 Gioacchino Mazzurco <gio.eigenlab.org>
* Copyright (C) 2018-2020 Gioacchino Mazzurco <gio@eigenlab.org>
* Copyright (C) 2019 Cyril Soler <csoler@users.sourceforge.net>
* Copyright (C) 2020 Asociación Civil Altermundi <info@altermundi.net>
*

View File

@ -3,7 +3,9 @@
* *
* libretroshare: retroshare core library *
* *
* Copyright 2004-2008 by Robert Fernie <retroshare@lunamutt.com> *
* Copyright (C) 2004-2008 by Robert Fernie <retroshare@lunamutt.com> *
* Copyright (C) 2018-2020 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2020 Asociación Civil Altermundi <info@altermundi.net> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
@ -468,7 +470,7 @@ struct RsGroupInfo : RsSerializable
struct RsPeerStateChangedEvent : RsEvent
{
/// @param[in] sslId is of the peer which changed state
RsPeerStateChangedEvent(RsPeerId sslId);
explicit RsPeerStateChangedEvent(RsPeerId sslId);
/// Storage fot the id of the peer that changed state
RsPeerId mSslId;
@ -605,7 +607,15 @@ public:
virtual bool getAssociatedSSLIds(const RsPgpId& gpg_id, std::list<RsPeerId>& ids) = 0;
virtual bool gpgSignData(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen, std::string reason = "") = 0;
virtual RsPgpId pgpIdFromFingerprint(const RsPgpFingerprint& fpr) = 0;
/**
* @brief Convert PGP fingerprint to PGP id
* @jsonapi{development}
* Helper method useful while we port the whole RetroShare codebase from
* RsPgpId to RsPgpFingerprint
* @param[in] fpr PGP fingerprint to convert
* @return PGP id corresponding to the fingerprint
*/
virtual RsPgpId pgpIdFromFingerprint(const RsPgpFingerprint& fpr) = 0;
// Note: the two methods below could be unified. The fact that one of them can take an optional RsPeerDetails struct as parameter
// seems quite inconsistent.
@ -803,7 +813,7 @@ public:
ServicePermissionFlags flags = RS_NODE_PERM_DEFAULT ) = 0;
/* Auth Stuff */
RS_DEPRECATED /// This function doesn't provide meaningful error reporting
virtual std::string getPGPKey(const RsPgpId& pgp_id,bool include_signatures) = 0;
virtual bool GetPGPBase64StringAndCheckSum(const RsPgpId& gpg_id,std::string& gpg_base64_string,std::string& gpg_base64_checksum) = 0;

View File

@ -201,7 +201,8 @@ struct FileInfo : RsSerializable
std::string path;
std::string fname;
RsFileHash hash;
std::string ext;
RS_DEPRECATED std::string ext; /// @deprecated unused
uint64_t size;
uint64_t avail; /// how much we have
@ -303,10 +304,16 @@ struct DirDetails : RsSerializable
type(DIR_TYPE_UNKNOWN), count(0), mtime(0), max_mtime(0) {}
/* G10h4ck do we still need to keep this as void* instead of uint64_t for
* retroshare-gui sake? */
void* parent;
int prow; /* parent row */
/* G10h4ck do we still need to keep this as void* instead of uint64_t for
* retroshare-gui sake? */
void* ref;
uint8_t type;
RsPeerId id;
std::string name;
@ -322,36 +329,18 @@ struct DirDetails : RsSerializable
/// @see RsSerializable
void serial_process(RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx)
RsGenericSerializer::SerializeContext& ctx) override
{
#if defined(__GNUC__) && !defined(__clang__)
# pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif // defined(__GNUC__) && !defined(__clang__)
/* Enforce serialization as uint64_t because void* changes size
* depending (usually 4 bytes on 32bit arch and 8 bytes on 64bit archs)
*/
uint64_t handle = reinterpret_cast<uint64_t>(ref);
RS_SERIAL_PROCESS(handle);
ref = reinterpret_cast<void*>(handle);
// (Cyril) We have to do this because on some systems (MacOS) uintptr_t is unsigned long which is not well defined. It is always
// preferable to force type serialization to the correct size rather than letting the compiler choose for us.
// /!\ This structure cannot be sent over the network. The serialization would be inconsistent.
if(sizeof(ref) == 4)
{
std::uint32_t& handle(reinterpret_cast<std::uint32_t&>(ref));
RS_SERIAL_PROCESS(handle);
std::uint32_t& parentHandle(reinterpret_cast<std::uint32_t&>(parent));
RS_SERIAL_PROCESS(parentHandle);
}
else if(sizeof(ref) == 8)
{
std::uint64_t& handle(reinterpret_cast<std::uint64_t&>(ref));
RS_SERIAL_PROCESS(handle);
std::uint64_t& parentHandle(reinterpret_cast<std::uint64_t&>(parent));
RS_SERIAL_PROCESS(parentHandle);
}
else
std::cerr << __PRETTY_FUNCTION__ << ": cannot serialize raw pointer of size " << sizeof(ref) << std::endl;
#if defined(__GNUC__) && !defined(__clang__)
# pragma GCC diagnostic pop
#endif // defined(__GNUC__) && !defined(__clang__)
uint64_t parentHandle = reinterpret_cast<uint64_t>(parent);
RS_SERIAL_PROCESS(parentHandle);
parent = reinterpret_cast<void*>(parentHandle);
RS_SERIAL_PROCESS(prow);
RS_SERIAL_PROCESS(type);
@ -366,6 +355,8 @@ struct DirDetails : RsSerializable
RS_SERIAL_PROCESS(children);
RS_SERIAL_PROCESS(parent_groups);
}
~DirDetails() override = default;
};
class FileDetail

View File

@ -45,11 +45,12 @@ struct RsItem : RsMemoryManagement::SmallObject, RsSerializable
/// TODO: Do this make sense with the new serialization system?
virtual void clear() = 0;
/// @deprecated use << ostream operator instead
RS_DEPRECATED_FOR("<< ostream operator")
virtual std::ostream &print(std::ostream &out, uint16_t /* indent */ = 0)
{
RsGenericSerializer::SerializeContext ctx(
NULL, 0, RsGenericSerializer::FORMAT_BINARY,
RsGenericSerializer::SERIALIZATION_FLAG_NONE );
nullptr, 0, RsSerializationFlags::NONE );
serial_process(RsGenericSerializer::PRINT,ctx);
return out;
}

View File

@ -147,8 +147,8 @@ void RsMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSeri
RsTypeSerializer::serial_process<RsTlvItem>(j,ctx,attachment,"attachment");
if(ctx.mFlags & RsServiceSerializer::SERIALIZATION_FLAG_CONFIG)
RsTypeSerializer::serial_process<uint32_t>(j,ctx,msgId,"msgId");
if(!!(ctx.mFlags & RsSerializationFlags::CONFIG))
RS_SERIAL_PROCESS(msgId);
}
void RsMsgTagType::clear()

View File

@ -19,8 +19,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#ifndef RS_MSG_ITEMS_H
#define RS_MSG_ITEMS_H
#pragma once
#include <map>
@ -33,10 +32,6 @@
#include "serialiser/rstlvfileitem.h"
#include "grouter/grouteritems.h"
#if 0
#include "serialiser/rstlvtypes.h"
#include "serialiser/rstlvfileitem.h"
#endif
/**************************************************************************/
@ -218,17 +213,12 @@ class RsMsgParentId : public RsMessageItem
class RsMsgSerialiser: public RsServiceSerializer
{
public:
RsMsgSerialiser(SerializationFlags flags = RsServiceSerializer::SERIALIZATION_FLAG_NONE)
:RsServiceSerializer(RS_SERVICE_TYPE_MSG,RsGenericSerializer::FORMAT_BINARY,flags){}
public:
RsMsgSerialiser(
RsSerializationFlags flags = RsSerializationFlags::NONE ):
RsServiceSerializer(RS_SERVICE_TYPE_MSG, flags){}
virtual ~RsMsgSerialiser() {}
RsItem* create_item(uint16_t service,uint8_t type) const override;
virtual RsItem *create_item(uint16_t service,uint8_t type) const ;
~RsMsgSerialiser() override = default;
};
/**************************************************************************/
#endif /* RS_MSG_ITEMS_H */

View File

@ -3,8 +3,9 @@
* *
* libretroshare: retroshare core library *
* *
* Copyright 2004-2008 by Robert Fernie <retroshare@lunamutt.com> *
* Copyright (C) 2015-2018 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2004-2008 Robert Fernie <retroshare@lunamutt.com> *
* Copyright (C) 2015-2020 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2020 Asociación Civil Altermundi <info@altermundi.net> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
@ -20,7 +21,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#include "util/radix64.h"
#include "pgp/pgpkeyutil.h"
#include "rsserver/p3peers.h"
@ -35,7 +36,8 @@
#include "retroshare/rsinit.h"
#include "retroshare/rsfiles.h"
#include "util/rsurl.h"
#include "util/radix64.h"
#include "util/rsbase64.h"
#include "pgp/rscertificate.h"
#include <iostream>
@ -1095,51 +1097,59 @@ bool p3Peers::setProxyServer(const uint32_t type, const std::string &addr_str, c
std::string p3Peers::getPGPKey(const RsPgpId& pgp_id,bool include_signatures)
{
unsigned char *mem_block = NULL;
rs_owner_ptr<unsigned char> mem_block = nullptr;
size_t mem_block_size = 0;
if( !AuthGPG::getAuthGPG()->exportPublicKey(
RsPgpId(pgp_id), mem_block, mem_block_size,
false, include_signatures ) )
{
std::cerr << "Cannot output certificate for id \"" << pgp_id
<< "\". Sorry." << std::endl;
return "" ;
RsErr() << __PRETTY_FUNCTION__
<< " Failure retriving certificate for id " << pgp_id
<< std::endl;
return "";
}
RsPeerDetails Detail;
if(!getGPGDetails(pgp_id,Detail)) return "";
RsPeerDetails details;
if(!getGPGDetails(pgp_id, details)) return "";
RsCertificate cert( Detail,mem_block,mem_block_size );
delete[] mem_block ;
auto certPtr =
RsCertificate::fromMemoryBlock(details, mem_block, mem_block_size);
return cert.armouredPGPKey();
free(mem_block);
if(certPtr) return certPtr->armouredPGPKey();
return "";
}
bool p3Peers::GetPGPBase64StringAndCheckSum( const RsPgpId& gpg_id,
std::string& gpg_base64_string,
std::string& gpg_base64_checksum)
bool p3Peers::GetPGPBase64StringAndCheckSum(
const RsPgpId& gpg_id,
std::string& gpg_base64_string, std::string& gpg_base64_checksum )
{
gpg_base64_string = "" ;
gpg_base64_checksum = "" ;
unsigned char *mem_block ;
size_t mem_block_size ;
rs_owner_ptr<unsigned char> mem_block = nullptr;
size_t mem_block_size = 0;
if(!AuthGPG::getAuthGPG()->exportPublicKey(
gpg_id,mem_block,mem_block_size,false,false ))
return false;
if(!AuthGPG::getAuthGPG()->exportPublicKey(gpg_id,mem_block,mem_block_size,false,false))
return false ;
RsBase64::encode(mem_block, mem_block_size, gpg_base64_string, true, false);
Radix64::encode(mem_block,mem_block_size,gpg_base64_string) ;
uint32_t crc = PGPKeyManagement::compute24bitsCRC(mem_block,mem_block_size);
uint32_t crc = PGPKeyManagement::compute24bitsCRC((unsigned char *)mem_block,mem_block_size) ;
free(mem_block);
unsigned char tmp[3] = { uint8_t((crc >> 16) & 0xff), uint8_t((crc >> 8) & 0xff), uint8_t(crc & 0xff) } ;
Radix64::encode(tmp,3,gpg_base64_checksum) ;
unsigned char tmp[3] = {
uint8_t((crc >> 16) & 0xff),
uint8_t((crc >> 8) & 0xff),
uint8_t(crc & 0xff) } ;
RsBase64::encode(tmp, 3, gpg_base64_checksum, true, false);
delete[] mem_block ;
return true ;
return true;
}
enum class RsShortInviteFieldType : uint8_t

View File

@ -141,7 +141,8 @@ public:
virtual std::string GetRetroshareInvite(
const RsPeerId& ssl_id = RsPeerId(),
bool include_signatures = false, bool includeExtraLocators = true );
virtual std::string getPGPKey(const RsPgpId& pgp_id,bool include_signatures);
RS_DEPRECATED /// @see RsPeers
std::string getPGPKey(const RsPgpId& pgp_id,bool include_signatures) override;
virtual bool GetPGPBase64StringAndCheckSum(const RsPgpId& gpg_id,std::string& gpg_base64_string,std::string& gpg_base64_checksum);

View File

@ -125,9 +125,7 @@ RsItem::RsItem(uint8_t ver, uint8_t cls, uint8_t t, uint8_t subtype)
type = (ver << 24) + (cls << 16) + (t << 8) + subtype;
}
RsItem::~RsItem()
{
}
RsItem::~RsItem() = default;
void RsItem::print_string(std::string &out, uint16_t indent)
{
@ -243,10 +241,7 @@ uint32_t RsSerialType::PacketId() const
RsSerialiser::RsSerialiser()
{
return;
}
RsSerialiser::RsSerialiser() = default;
RsSerialiser::~RsSerialiser()
@ -559,17 +554,7 @@ std::ostream &RsRawItem::print(std::ostream &out, uint16_t indent)
return out;
}
uint32_t getRsPktMaxSize()
{
//return 65535; /* 2^16 (old artifical low size) */
//return 1048575; /* 2^20 -1 (Too Big! - must remove fixed static buffers first) */
/* Remember that every pqistreamer allocates an input buffer of this size!
* So don't make it too big!
*/
return 262143; /* 2^18 -1 */
}
uint32_t getRsPktMaxSize() { return RsSerialiser::MAX_SERIAL_SIZE; }
uint32_t getRsPktBaseSize()
{

View File

@ -19,16 +19,16 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#ifndef RS_BASE_SERIALISER_H
#define RS_BASE_SERIALISER_H
#pragma once
#include <stdlib.h>
#include <string.h>
#include <cstring>
#include <map>
#include <string>
#include <iosfwd>
#include <stdlib.h>
#include <stdint.h>
#include <cstdlib>
#include <cstdint>
#include "util/rsdeprecate.h"
/*******************************************************************
* This is the Top-Level serialiser/deserialise,
@ -66,7 +66,11 @@ class RsSerialType ;
class RsSerialiser
{
public:
public:
/** Remember that every pqistreamer allocates an input buffer of this size!
* So don't make it too big! */
static constexpr uint32_t MAX_SERIAL_SIZE = 262143; /* 2^18 -1 */
RsSerialiser();
~RsSerialiser();
bool addSerialType(RsSerialType *type);
@ -76,7 +80,7 @@ class RsSerialiser
RsItem * deserialise(void *data, uint32_t *size);
private:
private:
std::map<uint32_t, RsSerialType *> serialisers;
};
@ -95,6 +99,8 @@ uint16_t getRsItemService(uint32_t type);
/* size constants */
uint32_t getRsPktBaseSize();
RS_DEPRECATED_FOR(RsSerialiser::MAX_SERIAL_SIZE)
uint32_t getRsPktMaxSize();
@ -106,5 +112,3 @@ std::ostream &printRsItemEnd(std::ostream &o, std::string n, uint16_t i);
/* defined in rstlvtypes.cc - redeclared here for ease */
std::ostream &printIndent(std::ostream &out, uint16_t indent);
/* Wrapper class for data that is serialised somewhere else */
#endif /* RS_BASE_SERIALISER_H */

View File

@ -4,6 +4,8 @@
* libretroshare: retroshare core library *
* *
* Copyright (C) 2016 Cyril Soler <csoler@users.sourceforge.net> *
* Copyright (C) 2020 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2020 Asociación Civil Altermundi <info@altermundi.net> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
@ -18,23 +20,17 @@
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
******************************************************************************/
#include <typeinfo>
#include "rsitems/rsitem.h"
#include "util/rsprint.h"
#include "serialiser/rsserializer.h"
#include "serialiser/rstypeserializer.h"
#include "util/stacktrace.h"
#include "util/rsdebug.h"
const SerializationFlags RsGenericSerializer::SERIALIZATION_FLAG_NONE ( 0x0000 );
const SerializationFlags RsGenericSerializer::SERIALIZATION_FLAG_CONFIG ( 0x0001 );
const SerializationFlags RsGenericSerializer::SERIALIZATION_FLAG_SIGNATURE ( 0x0002 );
const SerializationFlags RsGenericSerializer::SERIALIZATION_FLAG_SKIP_HEADER ( 0x0004 );
const SerializationFlags RsGenericSerializer::SERIALIZATION_FLAG_YIELDING ( 0x0008 );
RsItem *RsServiceSerializer::deserialise(void *data, uint32_t *size)
{
if(!data || !size || !*size)
@ -47,11 +43,13 @@ RsItem *RsServiceSerializer::deserialise(void *data, uint32_t *size)
return nullptr;
}
if(mFlags & SERIALIZATION_FLAG_SKIP_HEADER)
{
std::cerr << "(EE) Cannot deserialise item with flags SERIALIZATION_FLAG_SKIP_HEADER. Check your code!" << std::endl;
return NULL ;
}
if(!!(mFlags & RsSerializationFlags::SKIP_HEADER))
{
RsErr() << __PRETTY_FUNCTION__ << " Cannot deserialise item with flag "
<< "SKIP_HEADER. Check your code!" << std::endl;
print_stacktrace();
return nullptr;
}
uint32_t rstype = getRsItemId(const_cast<void*>((const void*)data)) ;
@ -64,7 +62,9 @@ RsItem *RsServiceSerializer::deserialise(void *data, uint32_t *size)
return NULL ;
}
SerializeContext ctx(const_cast<uint8_t*>(static_cast<uint8_t*>(data)),*size,mFormat,mFlags);
SerializeContext ctx(
const_cast<uint8_t*>(static_cast<uint8_t*>(data)), *size,
mFlags );
ctx.mOffset = 8 ;
item->serial_process(RsGenericSerializer::DESERIALIZE, ctx) ;
@ -85,11 +85,13 @@ RsItem *RsServiceSerializer::deserialise(void *data, uint32_t *size)
}
RsItem *RsConfigSerializer::deserialise(void *data, uint32_t *size)
{
if(mFlags & SERIALIZATION_FLAG_SKIP_HEADER)
{
std::cerr << "(EE) Cannot deserialise item with flags SERIALIZATION_FLAG_SKIP_HEADER. Check your code!" << std::endl;
return NULL ;
}
if(!!(mFlags & RsSerializationFlags::SKIP_HEADER))
{
RsErr() << __PRETTY_FUNCTION__ << " Cannot deserialise item with flag "
<< "SKIP_HEADER. Check your code!" << std::endl;
print_stacktrace();
return nullptr;
}
uint32_t rstype = getRsItemId(const_cast<void*>((const void*)data)) ;
@ -102,7 +104,9 @@ RsItem *RsConfigSerializer::deserialise(void *data, uint32_t *size)
return NULL ;
}
SerializeContext ctx(const_cast<uint8_t*>(static_cast<uint8_t*>(data)),*size,mFormat,mFlags);
SerializeContext ctx(
const_cast<uint8_t*>(static_cast<uint8_t*>(data)), *size,
mFlags );
ctx.mOffset = 8 ;
item->serial_process(DESERIALIZE, ctx) ;
@ -121,50 +125,44 @@ RsItem *RsConfigSerializer::deserialise(void *data, uint32_t *size)
delete item ;
return NULL ;
}
bool RsGenericSerializer::serialise(RsItem *item,void *data,uint32_t *size)
bool RsGenericSerializer::serialise(RsItem* item, void* data, uint32_t* size)
{
SerializeContext ctx(static_cast<uint8_t*>(data),0,mFormat,mFlags);
uint32_t tlvsize = this->size(item);
uint32_t tlvsize = this->size(item) ;
constexpr auto fName = __PRETTY_FUNCTION__;
const auto failure = [=](std::error_condition ec)
{
RsErr() << fName << " " << ec << std::endl;
print_stacktrace();
return false;
};
if(tlvsize > *size)
throw std::runtime_error("Cannot serialise: not enough room.") ;
if(tlvsize > *size) return failure(std::errc::no_buffer_space);
SerializeContext ctx(static_cast<uint8_t*>(data), tlvsize, mFlags);
if(mFlags & SERIALIZATION_FLAG_SKIP_HEADER)
ctx.mOffset = 0;
else
if(!(mFlags & RsSerializationFlags::SKIP_HEADER))
{
if(!setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize))
{
std::cerr << "RsSerializer::serialise_item(): ERROR. Not enough size!" << std::endl;
return false ;
}
return failure(std::errc::no_buffer_space);
ctx.mOffset = 8;
}
ctx.mSize = tlvsize;
item->serial_process(RsGenericSerializer::SERIALIZE,ctx);
item->serial_process(RsGenericSerializer::SERIALIZE,ctx) ;
if(ctx.mSize != ctx.mOffset) return failure(std::errc::message_size);
if(ctx.mSize != ctx.mOffset)
{
std::cerr << "RsSerializer::serialise(): ERROR. offset does not match expected size!" << std::endl;
return false ;
}
*size = ctx.mOffset ;
return true ;
*size = ctx.mOffset;
return true;
}
uint32_t RsGenericSerializer::size(RsItem *item)
{
SerializeContext ctx(NULL,0,mFormat,mFlags);
SerializeContext ctx(nullptr, 0, mFlags);
if(mFlags & SERIALIZATION_FLAG_SKIP_HEADER)
ctx.mOffset = 0;
else
ctx.mOffset = 8 ; // header size
if(!!(mFlags & RsSerializationFlags::SKIP_HEADER)) ctx.mOffset = 0;
else ctx.mOffset = 8; // header size
item->serial_process(SIZE_ESTIMATE, ctx) ;
return ctx.mOffset ;
@ -172,7 +170,7 @@ uint32_t RsGenericSerializer::size(RsItem *item)
void RsGenericSerializer::print(RsItem *item)
{
SerializeContext ctx(NULL,0,mFormat,mFlags);
SerializeContext ctx(nullptr, 0, mFlags);
std::cerr << "***** RsItem class: \"" << typeid(*item).name() << "\" *****" << std::endl;
item->serial_process(PRINT, ctx) ;
@ -255,7 +253,7 @@ RsItem *RsRawSerialiser::deserialise(void *data, uint32_t *pktsize)
RsGenericSerializer::SerializeContext::SerializeContext(
uint8_t* data, uint32_t size, SerializationFlags flags,
uint8_t* data, uint32_t size, RsSerializationFlags flags,
RsJson::AllocatorType* allocator ) :
mData(data), mSize(size), mOffset(0), mOk(true), mFlags(flags),
mJson(rapidjson::kObjectType, allocator)
@ -264,20 +262,23 @@ RsGenericSerializer::SerializeContext::SerializeContext(
{
if(size == 0)
{
std::cerr << __PRETTY_FUNCTION__ << " data passed without "
<< "size! This make no sense report to developers!"
<< std::endl;
RsFatal() << __PRETTY_FUNCTION__ << " data passed without "
<< "size! This make no sense report to developers!"
<< std::endl;
print_stacktrace();
exit(-EINVAL);
}
if(flags & SERIALIZATION_FLAG_YIELDING)
if(!!(flags & RsSerializationFlags::YIELDING))
{
std::cerr << __PRETTY_FUNCTION__ << " Attempt to create a "
RsFatal() << __PRETTY_FUNCTION__
<< " Attempt to create a "
<< "binary serialization context with "
<< "SERIALIZATION_FLAG_YIELDING! "
<< "This make no sense report to developers!"
<< std::endl;
print_stacktrace();
exit(-EINVAL);
}
}
}

View File

@ -192,6 +192,39 @@ class RsRawSerialiser: public RsSerialType
virtual RsItem * deserialise(void *data, uint32_t *size);
};
/** These are convenience flags to be used by the items when processing the
* data. The names of the flags are not very important. What matters is that
* the serial_process() method of each item correctly deals with the data
* when it sees the flags, if the serialiser sets them.
* By default the flags are not set and shouldn't be handled.
* When deriving a new serializer, the user can set his own flags, using
* compatible values
*/
enum class RsSerializationFlags
{
NONE = 0,
CONFIG = 1,
SIGNATURE = 2,
SKIP_HEADER = 4,
/** Used for JSON deserialization in JSON API, it causes the deserialization
* to continue even if some field is missing (or incorrect), this way the
* API is more user friendly as some methods need just part of the structs
* they take as parameters. */
YIELDING = 8,
/** When set integers typer are serialized/deserialized in Variable Length
* Quantity mode
* @see https://en.wikipedia.org/wiki/Variable-length_quantity
* This type of encoding is efficent when absoulte value is usually much
* smaller then the maximum representable with the original type.
* This encoding is also capable of representing big values at expences of a
* one more byte used.
*/
INTEGER_VLQ = 16
};
RS_REGISTER_ENUM_FLAGS_TYPE(RsSerializationFlags);
/// Top class for all services and config serializers.
struct RsGenericSerializer : RsSerialType
{
@ -200,63 +233,28 @@ struct RsGenericSerializer : RsSerialType
SIZE_ESTIMATE = 0x01,
SERIALIZE = 0x02,
DESERIALIZE = 0x03,
PRINT = 0x04,
PRINT = 0x04, /// @deprecated use rsdebug.h << operator instead
TO_JSON,
FROM_JSON
} SerializeJob;
/** @deprecated use SerializeJob instead */
RS_DEPRECATED typedef enum
{
FORMAT_BINARY = 0x01,
FORMAT_JSON = 0x02
} SerializationFormat;
struct SerializeContext
{
/** Allow shared allocator usage to avoid costly JSON deepcopy for
* nested RsSerializable */
SerializeContext(
uint8_t* data = nullptr, uint32_t size = 0,
SerializationFlags flags = SERIALIZATION_FLAG_NONE,
RsSerializationFlags flags = RsSerializationFlags::NONE,
RsJson::AllocatorType* allocator = nullptr);
RS_DEPRECATED SerializeContext(
uint8_t *data, uint32_t size, SerializationFormat format,
SerializationFlags flags,
RsJson::AllocatorType* allocator = nullptr) :
mData(data), mSize(size), mOffset(0), mOk(true), mFormat(format),
mFlags(flags), mJson(rapidjson::kObjectType, allocator) {}
unsigned char *mData;
uint32_t mSize;
uint32_t mOffset;
bool mOk;
RS_DEPRECATED SerializationFormat mFormat;
SerializationFlags mFlags;
RsSerializationFlags mFlags;
RsJson mJson;
};
/** These are convenience flags to be used by the items when processing the
* data. The names of the flags are not very important. What matters is that
* the serial_process() method of each item correctly deals with the data
* when it sees the flags, if the serialiser sets them.
* By default the flags are not set and shouldn't be handled.
* When deriving a new serializer, the user can set his own flags, using
* compatible values
*/
static const SerializationFlags SERIALIZATION_FLAG_NONE; // 0x0000
static const SerializationFlags SERIALIZATION_FLAG_CONFIG; // 0x0001
static const SerializationFlags SERIALIZATION_FLAG_SIGNATURE; // 0x0002
static const SerializationFlags SERIALIZATION_FLAG_SKIP_HEADER; // 0x0004
/** Used for JSON deserialization in JSON API, it causes the deserialization
* to continue even if some field is missing (or incorrect), this way the
* API is more user friendly as some methods need just part of the structs
* they take as parameters. */
static const SerializationFlags SERIALIZATION_FLAG_YIELDING; // 0x0008
/**
* The following functions overload RsSerialType.
* They *should not* need to be further overloaded.
@ -269,18 +267,15 @@ struct RsGenericSerializer : RsSerialType
protected:
RsGenericSerializer(
uint8_t serial_class, uint8_t serial_type,
SerializationFormat format, SerializationFlags flags ) :
RsSerializationFlags flags ):
RsSerialType( RS_PKT_VERSION1, serial_class, serial_type),
mFormat(format), mFlags(flags) {}
RsGenericSerializer(
uint16_t service, SerializationFormat format,
SerializationFlags flags ) :
RsSerialType( RS_PKT_VERSION_SERVICE, service ), mFormat(format),
mFlags(flags) {}
SerializationFormat mFormat;
SerializationFlags mFlags;
RsGenericSerializer(
uint16_t service, RsSerializationFlags flags ):
RsSerialType( RS_PKT_VERSION_SERVICE, service ), mFlags(flags) {}
RsSerializationFlags mFlags;
};
@ -290,9 +285,9 @@ protected:
struct RsServiceSerializer : RsGenericSerializer
{
RsServiceSerializer(
uint16_t service_id, SerializationFormat format = FORMAT_BINARY,
SerializationFlags flags = SERIALIZATION_FLAG_NONE ) :
RsGenericSerializer(service_id, format, flags) {}
uint16_t service_id,
RsSerializationFlags flags = RsSerializationFlags::NONE ) :
RsGenericSerializer(service_id, flags) {}
/*! should be overloaded to create the correct type of item depending on the
* data */
@ -309,11 +304,10 @@ struct RsServiceSerializer : RsGenericSerializer
*/
struct RsConfigSerializer : RsGenericSerializer
{
RsConfigSerializer(uint8_t config_class,
uint8_t config_type,
SerializationFormat format = FORMAT_BINARY,
SerializationFlags flags = SERIALIZATION_FLAG_NONE) :
RsGenericSerializer(config_class,config_type,format,flags) {}
RsConfigSerializer(
uint8_t config_class, uint8_t config_type,
RsSerializationFlags flags = RsSerializationFlags::NONE ) :
RsGenericSerializer(config_class, config_type, flags) {}
/*! should be overloaded to create the correct type of item depending on the
* data */

View File

@ -4,7 +4,8 @@
* libretroshare: retroshare core library *
* *
* Copyright (C) 2017 Cyril Soler <csoler@users.sourceforge.net> *
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2018-2020 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2020 Asociación Civil Altermundi <info@altermundi.net> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
@ -25,7 +26,7 @@
#include "serialiser/rsbaseserial.h"
#include "serialiser/rstlvkeys.h"
#include "serialiser/rsserializable.h"
#include "util/radix64.h"
#include "util/rsbase64.h"
#include "util/rsprint.h"
#include "util/rstime.h"
@ -34,8 +35,6 @@
#include <typeinfo> // for typeid
#include <rapidjson/prettywriter.h>
static constexpr uint32_t MAX_SERIALIZED_CHUNK_SIZE = 10*1024*1024 ; // 10 MB.
#ifdef RSSERIAL_DEBUG
# define SAFE_GET_JSON_V() \
const char* mName = memberName.c_str(); \
@ -56,32 +55,10 @@ static constexpr uint32_t MAX_SERIALIZED_CHUNK_SIZE = 10*1024*1024 ; // 10 MB.
rapidjson::Value& v = jDoc[mName]
#endif // ifdef RSSERIAL_DEBUG
//============================================================================//
// std::string //
//============================================================================//
template<> uint32_t RsTypeSerializer::serial_size(const std::string& str)
{
return getRawStringSize(str);
}
template<> bool RsTypeSerializer::serialize( uint8_t data[], uint32_t size,
uint32_t& offset,
const std::string& str )
{
return setRawString(data, size, &offset, str);
}
template<> bool RsTypeSerializer::deserialize( const uint8_t data[],
uint32_t size, uint32_t &offset,
std::string& str )
{
return getRawString(data, size, &offset, str);
}
template<> void RsTypeSerializer::print_data( const std::string& n,
const std::string& str )
{
std::cerr << " [std::string] " << n << ": " << str << std::endl;
}
template<> /*static*/
bool RsTypeSerializer::to_JSON( const std::string& membername,
const std::string& member, RsJson& jDoc )
@ -112,135 +89,11 @@ bool RsTypeSerializer::from_JSON( const std::string& memberName,
return ret;
}
//============================================================================//
// Integer types //
// Integral types //
//============================================================================//
template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const bool& member)
{
return setRawUInt8(data,size,&offset,member);
}
template<> bool RsTypeSerializer::serialize(uint8_t /*data*/[], uint32_t /*size*/, uint32_t& /*offset*/, const int32_t& /*member*/)
{
std::cerr << __PRETTY_FUNCTION__ << " Not implemented!" << std::endl;
print_stacktrace();
return false;
}
template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const uint8_t& member)
{
return setRawUInt8(data,size,&offset,member);
}
template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const uint16_t& member)
{
return setRawUInt16(data,size,&offset,member);
}
template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const uint32_t& member)
{
return setRawUInt32(data,size,&offset,member);
}
template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const uint64_t& member)
{
return setRawUInt64(data,size,&offset,member);
}
template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const rstime_t& member)
{
return setRawTimeT(data,size,&offset,member);
}
template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, bool& member)
{
uint8_t m;
bool ok = getRawUInt8(data,size,&offset,&m);
member = m;
return ok;
}
template<> bool RsTypeSerializer::deserialize(const uint8_t /*data*/[], uint32_t /*size*/, uint32_t& /*offset*/, int32_t& /*member*/)
{
std::cerr << __PRETTY_FUNCTION__ << " Not implemented!" << std::endl;
print_stacktrace();
return false;
}
template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, uint8_t& member)
{
return getRawUInt8(data,size,&offset,&member);
}
template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, uint16_t& member)
{
return getRawUInt16(data,size,&offset,&member);
}
template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, uint32_t& member)
{
return getRawUInt32(data,size,&offset,&member);
}
template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, uint64_t& member)
{
return getRawUInt64(data,size,&offset,&member);
}
template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, rstime_t& member)
{
return getRawTimeT(data,size,&offset,member);
}
template<> uint32_t RsTypeSerializer::serial_size(const bool& /* member*/)
{
return 1;
}
template<> uint32_t RsTypeSerializer::serial_size(const int32_t& /* member*/)
{
std::cerr << __PRETTY_FUNCTION__ << " Not implemented!" << std::endl;
print_stacktrace();
return 0;
}
template<> uint32_t RsTypeSerializer::serial_size(const uint8_t& /* member*/)
{
return 1;
}
template<> uint32_t RsTypeSerializer::serial_size(const uint16_t& /* member*/)
{
return 2;
}
template<> uint32_t RsTypeSerializer::serial_size(const uint32_t& /* member*/)
{
return 4;
}
template<> uint32_t RsTypeSerializer::serial_size(const uint64_t& /* member*/)
{
return 8;
}
template<> uint32_t RsTypeSerializer::serial_size(const rstime_t& /* member*/)
{
return 8;
}
template<> void RsTypeSerializer::print_data(const std::string& n, const bool & V)
{
std::cerr << " [bool ] " << n << ": " << V << std::endl;
}
template<> void RsTypeSerializer::print_data(const std::string& n, const int32_t& V)
{
std::cerr << " [int32_t ] " << n << ": " << std::to_string(V) << std::endl;
}
template<> void RsTypeSerializer::print_data(const std::string& n, const uint8_t & V)
{
std::cerr << " [uint8_t ] " << n << ": " << std::to_string(V) << std::endl;
}
template<> void RsTypeSerializer::print_data(const std::string& n, const uint16_t& V)
{
std::cerr << " [uint16_t ] " << n << ": " << std::to_string(V) << std::endl;
}
template<> void RsTypeSerializer::print_data(const std::string& n, const uint32_t& V)
{
std::cerr << " [uint32_t ] " << n << ": " << std::to_string(V) << std::endl;
}
template<> void RsTypeSerializer::print_data(const std::string& n, const uint64_t& V)
{
std::cerr << " [uint64_t ] " << n << ": " << std::to_string(V) << std::endl;
}
template<> void RsTypeSerializer::print_data(const std::string& n, const rstime_t& V)
{
std::cerr << " [rstime_t ] " << n << ": " << V << " (" << time(NULL)-V << " secs ago)" << std::endl;
}
#define SIMPLE_TO_JSON_DEF(T) \
template<> bool RsTypeSerializer::to_JSON( const std::string& memberName, \
const T& member, RsJson& jDoc ) \
@ -268,28 +121,45 @@ SIMPLE_TO_JSON_DEF(uint32_t)
/** Be very careful in changing this constant as it would break 64 bit integers
* members JSON string representation retrocompatibility */
static constexpr char strReprSuffix[] = "_sixtyfour_str";
static constexpr char strReprKey[] = "xstr64";
/** While JSON doesn't have problems representing 64 bit integers JavaScript
* standard represents numbers in a double-like format thus it is not capable to
* handle safely integers outside the range [-(2^53 - 1), 2^53 - 1], so we add
* to JSON also the string representation for this types as a workaround for the
* sake of JavaScript clients @see https://stackoverflow.com/a/34989371
/** Be very careful in changing this constant as it would break 64 bit integers
* members JSON string representation retrocompatibility */
static constexpr char intReprKey[] = "xint64";
/** While JSON doesn't have problems representing 64 bits integers JavaScript,
* Dart and other languages represents numbers in a double-like format thus they
* are not capable to handle safely integers outside the range
* [-(2^53 - 1), 2^53 - 1].
* To overcome this limitation we represent 64 bit integers as an object with
* two keys, one as integer and one as string representation.
* In our case we need to wrap those into an object instead of just adding a key
* with a suffix so support well also containers like std::map or std::vector.
* More discussion on the topic at @see https://stackoverflow.com/a/34989371
*/
#define SIXTYFOUR_INTEGERS_TO_JSON_DEF(T) \
template<> bool RsTypeSerializer::to_JSON( const std::string& memberName, \
const T& member, RsJson& jDoc ) \
{ \
rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); \
using namespace rapidjson; \
Document::AllocatorType& allocator = jDoc.GetAllocator(); \
\
rapidjson::Value key; \
Document wrapper(rapidjson::kObjectType, &allocator); \
\
Value intKey; \
intKey.SetString(intReprKey, allocator ); \
Value intValue(member); \
wrapper.AddMember(intKey, intValue, allocator); \
\
bool ok = to_JSON(strReprKey, std::to_string(member), wrapper); \
\
Value key; \
key.SetString( memberName.c_str(), \
static_cast<rapidjson::SizeType>(memberName.length()), \
allocator ); \
rapidjson::Value value(member); \
jDoc.AddMember(key, value, allocator); \
jDoc.AddMember(key, wrapper, allocator); \
\
return to_JSON(memberName + strReprSuffix, std::to_string(member), jDoc); \
return ok; \
}
SIXTYFOUR_INTEGERS_TO_JSON_DEF(int64_t);
@ -345,100 +215,71 @@ bool RsTypeSerializer::from_JSON( const std::string& memberName,
return ret;
}
/** While JSON doesn't have problems representing 64 bit integers JavaScript
* standard represents numbers in a double-like format thus it is not capable to
* handle safely integers outside the range [-(2^53 - 1), 2^53 - 1], so we look
* for the string representation in the JSON for this types as a workaround for
* the sake of JavaScript clients @see https://stackoverflow.com/a/34989371
*/
template<> /*static*/
bool RsTypeSerializer::from_JSON(
const std::string& memberName, int64_t& member, RsJson& jDoc )
{
const char* mName = memberName.c_str();
if(jDoc.HasMember(mName))
{
rapidjson::Value& v = jDoc[mName];
if(v.IsInt64())
{
member = v.GetInt64();
return true;
}
}
Dbg4() << __PRETTY_FUNCTION__ << " int64_t " << memberName << " not found "
<< "in JSON then attempt to look for string representation"
<< std::endl;
const std::string str_key = memberName + strReprSuffix;
std::string str_value;
if(from_JSON(str_key, str_value, jDoc))
{
try { member = std::stoll(str_value); }
catch (...)
{
RsErr() << __PRETTY_FUNCTION__ << " cannot convert "
<< str_value << " to int64_t" << std::endl;
return false;
}
return true;
}
Dbg3() << __PRETTY_FUNCTION__ << " neither " << memberName << " nor its "
<< "string representation " << str_key << " has been found "
<< "in JSON" << std::endl;
return false;
}
/** While JSON doesn't have problems representing 64 bit integers JavaScript
* standard represents numbers in a double-like format thus it is not capable to
* handle safely integers outside the range [-(2^53 - 1), 2^53 - 1], so we look
* for the string representation in the JSON for this types as a workaround for
* the sake of JavaScript clients @see https://stackoverflow.com/a/34989371
*/
template<> /*static*/
bool RsTypeSerializer::from_JSON(
const std::string& memberName, uint64_t& member, RsJson& jDoc )
{
const char* mName = memberName.c_str();
if(jDoc.HasMember(mName))
{
rapidjson::Value& v = jDoc[mName];
if(v.IsUint64())
{
member = v.GetUint64();
return true;
}
}
Dbg4() << __PRETTY_FUNCTION__ << " uint64_t " << memberName << " not found "
<< "in JSON then attempt to look for string representation"
<< std::endl;
const std::string str_key = memberName + strReprSuffix;
std::string str_value;
if(from_JSON(str_key, str_value, jDoc))
{
try { member = std::stoull(str_value); }
catch (...)
{
RsErr() << __PRETTY_FUNCTION__ << " cannot convert "
<< str_value << " to uint64_t" << std::endl;
return false;
}
return true;
}
Dbg3() << __PRETTY_FUNCTION__ << " neither " << memberName << " nor its "
<< "string representation " << str_key << " has been found "
<< "in JSON" << std::endl;
return false;
/** inverse of @see SIXTYFOUR_INTEGERS_TO_JSON_DEF */
#define SIXTYFOUR_INTEGERS_FROM_JSON_DEF(T, PRED, GET, CONV) \
template<> bool RsTypeSerializer::from_JSON( \
const std::string& memberName, T& member, RsJson& jDoc ) \
{ \
using namespace rapidjson; \
\
SAFE_GET_JSON_V(); \
\
/* For retro-compatibility take it directly if it is passed as integer */ \
if(v.PRED()) \
{ \
member = v.GET(); \
return true; \
} \
\
ret = ret && v.IsObject(); \
\
if(!ret) \
{ \
Dbg3() << __PRETTY_FUNCTION__ << " " << memberName << " not found" \
<< std::endl; \
return false; \
} \
\
if(v.HasMember(intReprKey)) \
{ \
Value& iVal = v[intReprKey]; \
if(iVal.PRED()) \
{ \
member = iVal.GET(); \
return true; \
} \
} \
\
Dbg4() << __PRETTY_FUNCTION__ << " integer representation of " << memberName \
<< " not found in JSON then attempt to look for string representation" \
<< std::endl; \
\
\
if(v.HasMember(strReprKey)) \
{ \
Value& sVal = v[strReprKey]; \
if(sVal.IsString()) \
{ \
try { member = CONV(sVal.GetString()); } \
catch (...) \
{ \
RsErr() << __PRETTY_FUNCTION__ << " cannot convert " \
<< sVal.GetString() << " to integral type" << std::endl; \
return false; \
} \
\
return true; \
} \
} \
\
Dbg3() << __PRETTY_FUNCTION__ << " neither integral representation nor " \
<< "string representation found for: " << memberName << std::endl; \
\
return false; \
}
SIXTYFOUR_INTEGERS_FROM_JSON_DEF(uint64_t, IsUint64, GetUint64, std::stoull)
SIXTYFOUR_INTEGERS_FROM_JSON_DEF( int64_t, IsInt64, GetInt64, std::stoll)
//============================================================================//
// Floats //
@ -662,113 +503,176 @@ bool RsTypeSerializer::from_JSON( const std::string& /*memberName*/,
// Binary blocks //
//============================================================================//
template<> uint32_t RsTypeSerializer::serial_size(const RsTypeSerializer::TlvMemBlock_proxy& r) { return 4 + r.second ; }
/*static*/ /* without this Android compilation breaks */
constexpr uint32_t RsTypeSerializer::RawMemoryWrapper::MAX_SERIALIZED_CHUNK_SIZE;
template<> bool RsTypeSerializer::deserialize(const uint8_t data[],uint32_t size,uint32_t& offset,RsTypeSerializer::TlvMemBlock_proxy& r)
/*static*/
void RsTypeSerializer::RawMemoryWrapper::serial_process(
RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx )
{
uint32_t saved_offset = offset ;
bool ok = deserialize<uint32_t>(data,size,offset,r.second) ;
if(r.second == 0)
{
r.first = NULL ;
if(!ok)
offset = saved_offset ;
return ok ;
}
if(r.second > MAX_SERIALIZED_CHUNK_SIZE)
{
std::cerr << "(EE) RsTypeSerializer::deserialize<TlvMemBlock_proxy>(): data chunk has size larger than safety size (" << MAX_SERIALIZED_CHUNK_SIZE << "). Item will be dropped." << std::endl;
offset = saved_offset ;
return false ;
}
r.first = (uint8_t*)rs_malloc(r.second) ;
ok = ok && (NULL != r.first);
memcpy(r.first,&data[offset],r.second) ;
offset += r.second ;
if(!ok)
offset = saved_offset ;
return ok;
}
template<> bool RsTypeSerializer::serialize(uint8_t data[],uint32_t size,uint32_t& offset,const RsTypeSerializer::TlvMemBlock_proxy& r)
{
uint32_t saved_offset = offset ;
bool ok = serialize<uint32_t>(data,size,offset,r.second) ;
memcpy(&data[offset],r.first,r.second) ;
offset += r.second ;
if(!ok)
offset = saved_offset ;
return ok;
}
template<> void RsTypeSerializer::print_data(const std::string& n, const RsTypeSerializer::TlvMemBlock_proxy& s)
{
std::cerr << " [Binary data] " << n << ", length=" << s.second << " data=" << RsUtil::BinToHex((uint8_t*)s.first,std::min(50u,s.second)) << ((s.second>50)?"...":"") << std::endl;
}
template<> /*static*/
bool RsTypeSerializer::to_JSON(
const std::string& memberName,
const RsTypeSerializer::TlvMemBlock_proxy& member, RsJson& jDoc )
{
rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator();
rapidjson::Value key;
key.SetString( memberName.c_str(),
static_cast<rapidjson::SizeType>(memberName.length()),
allocator );
std::string encodedValue;
Radix64::encode( reinterpret_cast<uint8_t*>(member.first),
static_cast<int>(member.second), encodedValue );
rapidjson::Value value;
value.SetString(encodedValue.data(), allocator);
jDoc.AddMember(key, value, allocator);
return true;
}
template<> /*static*/
bool RsTypeSerializer::from_JSON( const std::string& memberName,
RsTypeSerializer::TlvMemBlock_proxy& member,
RsJson& jDoc)
{
SAFE_GET_JSON_V();
ret = ret && v.IsString();
if(ret)
switch(j)
{
std::string encodedValue = v.GetString();
std::vector<uint8_t> decodedValue = Radix64::decode(encodedValue);
member.second = decodedValue.size();
if(member.second == 0)
case RsGenericSerializer::SIZE_ESTIMATE:
RS_SERIAL_PROCESS(second);
ctx.mOffset += second;
break;
case RsGenericSerializer::SERIALIZE:
if(!ctx.mOk) break;
if(second > MAX_SERIALIZED_CHUNK_SIZE)
{
member.first = nullptr;
return ret;
RsErr() << __PRETTY_FUNCTION__
<< std::errc::message_size << " "
<< second << " > " << MAX_SERIALIZED_CHUNK_SIZE
<< std::endl;
print_stacktrace();
break;
}
RS_SERIAL_PROCESS(second);
if(!ctx.mOk) break;
ctx.mOk = ctx.mSize >= ctx.mOffset + second;
if(!ctx.mOk)
{
RsErr() << __PRETTY_FUNCTION__ << std::errc::no_buffer_space
<< std::endl;
print_stacktrace();
break;
}
memcpy(ctx.mData + ctx.mOffset, first, second);
ctx.mOffset += second;
break;
case RsGenericSerializer::DESERIALIZE:
{
uint32_t serialSize = 0;
RS_SERIAL_PROCESS(serialSize);
if(!ctx.mOk) break;
ctx.mOk = serialSize <= MAX_SERIALIZED_CHUNK_SIZE;
if(!ctx.mOk)
{
RsErr() << __PRETTY_FUNCTION__
<< std::errc::message_size << " "
<< serialSize << " > " << MAX_SERIALIZED_CHUNK_SIZE
<< std::endl;
clear();
break;
}
member.first = rs_malloc(member.second);
ret = ret && member.first &&
memcpy(member.first, decodedValue.data(), member.second);
if(!serialSize)
{
Dbg3() << __PRETTY_FUNCTION__ << " Deserialized empty memory chunk"
<< std::endl;
clear();
break;
}
ctx.mOk = ctx.mSize >= ctx.mOffset + serialSize;
if(!ctx.mOk)
{
RsErr() << __PRETTY_FUNCTION__ << std::errc::no_buffer_space
<< std::endl;
print_stacktrace();
clear();
break;
}
if(serialSize != second)
{
first = reinterpret_cast<uint8_t*>(realloc(first, serialSize));
second = serialSize;
}
memcpy(first, ctx.mData + ctx.mOffset, second);
ctx.mOffset += second;
break;
}
case RsGenericSerializer::PRINT: break;
case RsGenericSerializer::TO_JSON:
{
if(!ctx.mOk) break;
std::string encodedValue;
RsBase64::encode(first, second, encodedValue, true, false);
ctx.mJson.SetString(
encodedValue.data(),
static_cast<rapidjson::SizeType>(encodedValue.length()) );
break;
}
case RsGenericSerializer::FROM_JSON:
{
const bool yelding = !!(
RsSerializationFlags::YIELDING & ctx.mFlags );
if(!(ctx.mOk || yelding))
{
clear();
break;
}
if(!ctx.mJson.IsString())
{
RsErr() << __PRETTY_FUNCTION__ << " "
<< std::errc::invalid_argument << std::endl;
print_stacktrace();
ctx.mOk = false;
clear();
break;
}
if( ctx.mJson.GetStringLength() >
RsBase64::encodedSize(MAX_SERIALIZED_CHUNK_SIZE, true) )
{
RsErr() << __PRETTY_FUNCTION__ << " "
<< std::errc::message_size << std::endl;
print_stacktrace();
ctx.mOk = false;
clear();
break;
}
std::string encodedValue = ctx.mJson.GetString();
std::vector<uint8_t> decoded;
auto ec = RsBase64::decode(encodedValue, decoded);
if(ec)
{
RsErr() << __PRETTY_FUNCTION__ << " " << ec << std::endl;
print_stacktrace();
ctx.mOk = false;
clear();
break;
}
const auto decodedSize = decoded.size();
if(!decodedSize)
{
clear();
break;
}
if(decodedSize != second)
{
first = reinterpret_cast<uint8_t*>(realloc(first, decodedSize));
second = static_cast<uint32_t>(decodedSize);
}
memcpy(first, decoded.data(), second);
break;
}
default: RsTypeSerializer::fatalUnknownSerialJob(j);
}
return ret;
}
void RsTypeSerializer::RawMemoryWrapper::clear()
{
free(first);
first = nullptr;
second = 0;
}
//============================================================================//
// std::error_condition //
//============================================================================//
void RsTypeSerializer::ErrConditionWrapper::serial_process(
RsGenericSerializer::SerializeJob j,
RsGenericSerializer::SerializeContext& ctx )
@ -778,12 +682,12 @@ void RsTypeSerializer::ErrConditionWrapper::serial_process(
case RsGenericSerializer::SIZE_ESTIMATE: // fallthrough
case RsGenericSerializer::DESERIALIZE: // fallthrough
case RsGenericSerializer::SERIALIZE: // fallthrough
case RsGenericSerializer::FROM_JSON:
case RsGenericSerializer::FROM_JSON: // [[fallthrough]]
case RsGenericSerializer::PRINT:
RsFatal() << __PRETTY_FUNCTION__ << " SerializeJob: " << j
<< "is not supported on std::error_condition " << std::endl;
print_stacktrace();
exit(-2);
case RsGenericSerializer::PRINT: // fallthrough
case RsGenericSerializer::TO_JSON:
{
constexpr RsGenericSerializer::SerializeJob rj =

File diff suppressed because it is too large Load Diff

View File

@ -80,7 +80,9 @@ p3MsgService::p3MsgService( p3ServiceControl *sc, p3IdService *id_serv,
recentlyReceivedMutex("p3MsgService recently received hash mutex"),
mGxsTransServ(gxsMS)
{
_serialiser = new RsMsgSerialiser(RsServiceSerializer::SERIALIZATION_FLAG_NONE); // this serialiser is used for services. It's not the same than the one returned by setupSerialiser(). We need both!!
/* this serialiser is used for services. It's not the same than the one
* returned by setupSerialiser(). We need both!! */
_serialiser = new RsMsgSerialiser();
addSerialType(_serialiser);
/* MsgIds are not transmitted, but only used locally as a storage index.
@ -509,7 +511,7 @@ RsSerialiser* p3MsgService::setupSerialiser() // this serialiser is used for con
{
RsSerialiser *rss = new RsSerialiser ;
rss->addSerialType(new RsMsgSerialiser(RsServiceSerializer::SERIALIZATION_FLAG_CONFIG));
rss->addSerialType(new RsMsgSerialiser(RsSerializationFlags::CONFIG));
rss->addSerialType(new RsGeneralConfigSerialiser());
return rss;
@ -2386,10 +2388,11 @@ void p3MsgService::sendDistantMsgItem(RsMsgItem *msgitem)
/* The item is serialized and turned into a generic turtle item. Use use the
* explicit serialiser to make sure that the msgId is not included */
uint32_t msg_serialized_rssize = RsMsgSerialiser(RsServiceSerializer::SERIALIZATION_FLAG_NONE).size(msgitem) ;
uint32_t msg_serialized_rssize = RsMsgSerialiser().size(msgitem);
RsTemporaryMemory msg_serialized_data(msg_serialized_rssize) ;
if(!RsMsgSerialiser(RsServiceSerializer::SERIALIZATION_FLAG_NONE).serialise(msgitem,msg_serialized_data,&msg_serialized_rssize))
if( !RsMsgSerialiser().
serialise(msgitem,msg_serialized_data,&msg_serialized_rssize) )
{
std::cerr << "(EE) p3MsgService::sendTurtleData(): Serialization error." << std::endl;
return ;

View File

@ -3,7 +3,9 @@
* *
* libretroshare: retroshare core library *
* *
* Copyright (C) 2019 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2019-2020 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2019-2020 Retroshare Team <contact@retroshare.cc> *
* Copyright (C) 2020 Asociación Civil Altermundi <info@altermundi.net> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
@ -27,64 +29,62 @@
/*extern*/ RsEvents* rsEvents = nullptr;
RsEvent::~RsEvent() {};
RsEvents::~RsEvents() {};
bool isEventValid(
std::shared_ptr<const RsEvent> event, std::string& errorMessage )
RsEvent::~RsEvent() = default;
RsEvents::~RsEvents() = default;
/*static*/ const RsEventsErrorCategory RsEventsErrorCategory::instance;
std::error_condition RsEventsErrorCategory::default_error_condition(int ev)
const noexcept
{
if(!event)
switch(static_cast<RsEventsErrorNum>(ev))
{
errorMessage = "Event is null!";
return false;
case RsEventsErrorNum::INVALID_HANDLER_ID: // [[fallthrough]];
case RsEventsErrorNum::NULL_EVENT_POINTER: // [[fallthrough]];
case RsEventsErrorNum::EVENT_TYPE_UNDEFINED: // [[fallthrough]];
case RsEventsErrorNum::EVENT_TYPE_OUT_OF_RANGE:
return std::errc::invalid_argument;
default:
return std::error_condition(ev, *this);
}
if(event->mType <= RsEventType::NONE)
{
errorMessage = "Event has type NONE: " +
std::to_string(
static_cast<std::underlying_type<RsEventType>::type >(
event->mType ) );
return false;
}
if(event->mType >= RsEventType::MAX)
{
errorMessage = "Event has type >= RsEventType::MAX: " +
std::to_string(
static_cast<std::underlying_type<RsEventType>::type >(
event->mType ) );
}
return true;
}
bool RsEventsService::postEvent( std::shared_ptr<const RsEvent> event,
std::string& errorMessage )
std::error_condition RsEventsService::isEventTypeInvalid(RsEventType eventType)
{
if(!isEventValid(event, errorMessage))
{
std::cerr << __PRETTY_FUNCTION__ << " Error: "<< errorMessage
<< std::endl;
return false;
}
if(eventType == RsEventType::__NONE)
return RsEventsErrorNum::EVENT_TYPE_UNDEFINED;
if( eventType < RsEventType::__NONE ||
eventType >= static_cast<RsEventType>(mHandlerMaps.size()) )
return RsEventsErrorNum::EVENT_TYPE_OUT_OF_RANGE;
return std::error_condition();
}
std::error_condition RsEventsService::isEventInvalid(
std::shared_ptr<const RsEvent> event)
{
if(!event) return RsEventsErrorNum::NULL_EVENT_POINTER;
return isEventTypeInvalid(event->mType);
}
std::error_condition RsEventsService::postEvent(
std::shared_ptr<const RsEvent> event )
{
if(std::error_condition ec = isEventInvalid(event)) return ec;
RS_STACK_MUTEX(mEventQueueMtx);
mEventQueue.push_back(event);
return true;
return std::error_condition();
}
bool RsEventsService::sendEvent( std::shared_ptr<const RsEvent> event,
std::string& errorMessage )
std::error_condition RsEventsService::sendEvent(
std::shared_ptr<const RsEvent> event )
{
if(!isEventValid(event, errorMessage))
{
RsErr() << __PRETTY_FUNCTION__ << " "<< errorMessage << std::endl;
return false;
}
if(std::error_condition ec = isEventInvalid(event)) return ec;
handleEvent(event);
return true;
return std::error_condition();
}
RsEventsHandlerId_t RsEventsService::generateUniqueHandlerId()
@ -99,43 +99,42 @@ RsEventsHandlerId_t RsEventsService::generateUniqueHandlerId_unlocked()
return 1;
}
bool RsEventsService::registerEventsHandler(
RsEventType eventType,
std::error_condition RsEventsService::registerEventsHandler(
std::function<void(std::shared_ptr<const RsEvent>)> multiCallback,
RsEventsHandlerId_t& hId )
RsEventsHandlerId_t& hId, RsEventType eventType )
{
RS_STACK_MUTEX(mHandlerMapMtx);
if( (int)eventType > mHandlerMaps.size() + 10)
{
RsErr() << "Cannot register an event handler for an event type larger than 10 plus the max pre-defined event (value passed was " << (int)eventType << " whereas max is " << (int)RsEventType::MAX << ")" << std::endl;
return false;
}
if(eventType != RsEventType::__NONE)
if(std::error_condition ec = isEventTypeInvalid(eventType))
return ec;
if( (int)eventType >= mHandlerMaps.size())
mHandlerMaps.resize( (int)eventType +1 );
if(!hId) hId = generateUniqueHandlerId_unlocked();
else if (hId > mLastHandlerId)
{
print_stacktrace();
return RsEventsErrorNum::INVALID_HANDLER_ID;
}
if(!hId)
hId = generateUniqueHandlerId_unlocked();
mHandlerMaps[(int)eventType][hId] = multiCallback;
return true;
mHandlerMaps[static_cast<std::size_t>(eventType)][hId] = multiCallback;
return std::error_condition();
}
bool RsEventsService::unregisterEventsHandler(RsEventsHandlerId_t hId)
std::error_condition RsEventsService::unregisterEventsHandler(
RsEventsHandlerId_t hId )
{
RS_STACK_MUTEX(mHandlerMapMtx);
for(uint32_t i=0;i<mHandlerMaps.size();++i)
for(uint32_t i=0; i<mHandlerMaps.size(); ++i)
{
auto it = mHandlerMaps[i].find(hId);
if(it != mHandlerMaps[i].end())
{
{
mHandlerMaps[i].erase(it);
return true;
}
return std::error_condition();
}
}
return false;
return RsEventsErrorNum::INVALID_HANDLER_ID;
}
void RsEventsService::threadTick()
@ -174,27 +173,25 @@ dispatchEventFromQueueLock:
void RsEventsService::handleEvent(std::shared_ptr<const RsEvent> event)
{
std::function<void(std::shared_ptr<const RsEvent>)> mCallback;
uint32_t event_type_index = static_cast<uint32_t>(event->mType);
if(std::error_condition ec = isEventInvalid(event))
{
RS_STACK_MUTEX(mHandlerMapMtx); /* LOCKED AREA */
if(event_type_index >= mHandlerMaps.size() || event_type_index < 1)
{
RsErr() << "Cannot handle an event of type " << event_type_index << ": out of scope!" << std::endl;
return;
}
// Call all clients that registered a callback for this event type
for(auto cbit: mHandlerMaps[event_type_index])
cbit.second(event);
// Also call all clients that registered with NONE, meaning that they expect all events
for(auto cbit: mHandlerMaps[static_cast<uint32_t>(RsEventType::NONE)])
cbit.second(event);
RsErr() << __PRETTY_FUNCTION__ << " " << ec << std::endl;
print_stacktrace();
return;
}
RS_STACK_MUTEX(mHandlerMapMtx);
/* It is important to also call the callback under mutex protection to
* ensure they are not unregistered in the meanwhile.
* If a callback try to fiddle with registering/unregistering it will
* deadlock */
// Call all clients that registered a callback for this event type
for(auto cbit: mHandlerMaps[static_cast<uint32_t>(event->mType)])
cbit.second(event);
/* Also call all clients that registered with NONE, meaning that they
* expect all events */
for(auto cbit: mHandlerMaps[static_cast<uint32_t>(RsEventType::__NONE)])
cbit.second(event);
}

View File

@ -3,7 +3,8 @@
* *
* libretroshare: retroshare core library *
* *
* Copyright (C) 2019 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2019-2020 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2020 Asociación Civil Altermundi <info@altermundi.net> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
@ -24,6 +25,7 @@
#include <memory>
#include <cstdint>
#include <deque>
#include <array>
#include "retroshare/rsevents.h"
#include "util/rsthreads.h"
@ -35,42 +37,44 @@ class RsEventsService :
public:
RsEventsService():
mHandlerMapMtx("RsEventsService::mHandlerMapMtx"), mLastHandlerId(1),
mHandlerMaps(static_cast<int>(RsEventType::MAX)),
mEventQueueMtx("RsEventsService::mEventQueueMtx") {}
/// @see RsEvents
bool postEvent(
std::shared_ptr<const RsEvent> event,
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
) override;
std::error_condition postEvent(
std::shared_ptr<const RsEvent> event ) override;
/// @see RsEvents
bool sendEvent(
std::shared_ptr<const RsEvent> event,
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
) override;
std::error_condition sendEvent(
std::shared_ptr<const RsEvent> event ) override;
/// @see RsEvents
RsEventsHandlerId_t generateUniqueHandlerId() override;
/// @see RsEvents
bool registerEventsHandler(
RsEventType eventType,
std::error_condition registerEventsHandler(
std::function<void(std::shared_ptr<const RsEvent>)> multiCallback,
RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0)
) override;
RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0),
RsEventType eventType = RsEventType::__NONE ) override;
/// @see RsEvents
bool unregisterEventsHandler(RsEventsHandlerId_t hId) override;
std::error_condition unregisterEventsHandler(
RsEventsHandlerId_t hId ) override;
protected:
std::error_condition isEventTypeInvalid(RsEventType eventType);
std::error_condition isEventInvalid(std::shared_ptr<const RsEvent> event);
RsMutex mHandlerMapMtx;
RsEventsHandlerId_t mLastHandlerId;
std::vector<
std::map<
RsEventsHandlerId_t,
std::function<void(std::shared_ptr<const RsEvent>)> > > mHandlerMaps;
/** Storage for event handlers, keep 10 extra types for plugins that might
* be released indipendently */
std::array<
std::map<
RsEventsHandlerId_t,
std::function<void(std::shared_ptr<const RsEvent>)> >,
static_cast<std::size_t>(RsEventType::__MAX) + 10
> mHandlerMaps;
RsMutex mEventQueueMtx;
std::deque< std::shared_ptr<const RsEvent> > mEventQueue;

View File

@ -1,9 +1,9 @@
/*******************************************************************************
* libretroshare/src/file_sharing: file_tree.h *
* *
* libretroshare: retroshare core library *
* libretroshare < C++14 retro-compatibility helpers *
* *
* Copyright 2018 by Cyril Soler <csoler@users.sourceforge.net> *
* Copyright (C) 2020 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2020 Asociación Civil Altermundi <info@altermundi.net> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
@ -18,37 +18,21 @@
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
******************************************************************************/
#include "retroshare/rsfiles.h"
*******************************************************************************/
#pragma once
class FileTreeImpl: public FileTree
#if __cplusplus < 201402L
#include <type_traits>
namespace std
{
public:
FileTreeImpl()
{
mTotalFiles = 0 ;
mTotalSize = 0 ;
}
template<class T> using decay_t = typename decay<T>::type;
virtual std::string toRadix64() const ;
virtual bool getDirectoryContent(uint32_t index,std::string& name,std::vector<uint32_t>& subdirs,std::vector<FileData>& subfiles) const ;
virtual void print() const ;
template<bool B, class T = void>
using enable_if_t = typename enable_if<B,T>::type;
bool serialise(unsigned char *& data,uint32_t& data_size) const ;
bool deserialise(unsigned char* data, uint32_t data_size) ;
protected:
void recurs_print(uint32_t index,const std::string& indent) const;
static void recurs_buildFileTree(FileTreeImpl& ft, uint32_t index, const DirDetails& dd, bool remote, bool remove_top_dirs);
struct DirData {
std::string name;
std::vector<uint32_t> subdirs ;
std::vector<uint32_t> subfiles ;
};
std::vector<FileData> mFiles ;
std::vector<DirData> mDirs ;
friend class FileTree ;
};
template<class T>
using remove_const_t = typename remove_const<T>::type;
}
#endif // __cplusplus < 201402L

View File

@ -26,7 +26,10 @@
#include <vector>
#include <stdint.h>
class Radix64
#include "util/rsdeprecate.h"
/** @deprecated use RsBase64 instead which supports also URL safe encoding */
class RS_DEPRECATED_FOR(RsBase64) Radix64
{
public:
static std::vector<uint8_t> decode(const std::string& buffer)
@ -195,5 +198,3 @@ again:
return true ;
}
};

View File

@ -0,0 +1,192 @@
/*******************************************************************************
* *
* libretroshare base64 encoding utilities *
* *
* Copyright (C) 2015 Retroshare Team <contact@retroshare.cc> *
* Copyright (C) 2020 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2020 Asociación Civil Altermundi <info@altermundi.net> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 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 Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#include <cmath>
#include "util/rsbase64.h"
#include "util/rsdebug.h"
#if __cplusplus < 201703L
/* Solve weird undefined reference error with C++ < 17 see:
* https://stackoverflow.com/questions/8016780/undefined-reference-to-static-constexpr-char
*/
/*static*/ decltype(RsBase64::bDict) constexpr RsBase64::bDict;
/*static*/ decltype(RsBase64::uDict) constexpr RsBase64::uDict;
/*static*/ decltype(RsBase64::rDict) constexpr RsBase64::rDict;
/*static*/ decltype(RsBase64::sPad) constexpr RsBase64::sPad;
#endif
/*static*/ void RsBase64::encode(
rs_view_ptr<const uint8_t> data, size_t len, std::string& outString,
bool padding, bool urlSafe )
{
const char* sDict = urlSafe ? uDict : bDict;
// Workaround if input and output are the same buffer.
bool inplace = (outString.data() == reinterpret_cast<const char*>(data));
std::string tBuff;
std::string& outStr = inplace ? tBuff : outString;
auto encSize = encodedSize(len, padding);
outStr.resize(encSize);
char* p = &outStr[0];
for (; len >= 3; len -= 3, data += 3)
{
*p++ = sDict[ (data[0] >> 2) & 077 ];
*p++ = sDict[
(((data[0] << 4) & 060) | ((data[1] >> 4) & 017)) & 077 ];
*p++ = sDict[
(((data[1] << 2) & 074) | ((data[2] >> 6) & 03)) & 077 ];
*p++ = sDict[ data[2] & 077 ];
}
if (len == 2)
{
*p++ = sDict[ (data[0] >> 2) & 077 ];
*p++ = sDict[
(((data[0] << 4) & 060) | ((data[1] >> 4) & 017)) & 077 ];
*p++ = sDict[ ((data[1] << 2) & 074) ];
if(padding) *p++ = sPad;
}
else if (len == 1)
{
*p++ = sDict[ (data[0] >> 2) & 077 ];
*p++ = sDict[ (data[0] << 4) & 060 ];
if(padding) { *p++ = sPad; *p++ = sPad; }
}
if(inplace) outString = tBuff;
}
/*static*/ std::error_condition RsBase64::decode(
const std::string& encoded, std::vector<uint8_t>& decoded )
{
size_t decSize; std::error_condition ec;
std::tie(decSize, ec) = decodedSize(encoded);
if(!decSize || ec) return ec;
size_t encSize = encoded.size();
decoded.resize(decSize);
for (size_t i = 0, o = 0; i < encSize; i += 4, o += 3)
{
char input0 = encoded[i + 0];
char input1 = encoded[i + 1];
/* At the end of the string, missing bytes 2 and 3 are considered
* padding '=' */
char input2 = i + 2 < encoded.size() ? encoded[i + 2] : sPad;
char input3 = i + 3 < encSize ? encoded[i + 3] : sPad;
// If any unknown characters appear, it's an error.
if(!( isBase64Char(input0) && isBase64Char(input1) &&
isBase64Char(input2) && isBase64Char(input3) ))
return std::errc::argument_out_of_domain;
/* If padding appears anywhere but the last 1 or 2 characters, or if
* it appears but encoded.size() % 4 != 0, it's an error. */
bool at_end = (i + 4 >= encSize);
if ( (input0 == sPad) || (input1 == sPad) ||
( input2 == sPad && !at_end ) ||
( input2 == sPad && input3 != sPad ) ||
( input3 == sPad && !at_end) )
return std::errc::illegal_byte_sequence;
uint32_t b0 = rDict[static_cast<uint8_t>(input0)] & 0x3f;
uint32_t b1 = rDict[static_cast<uint8_t>(input1)] & 0x3f;
uint32_t b2 = rDict[static_cast<uint8_t>(input2)] & 0x3f;
uint32_t b3 = rDict[static_cast<uint8_t>(input3)] & 0x3f;
uint32_t stream = (b0 << 18) | (b1 << 12) | (b2 << 6) | b3;
decoded[o + 0] = (stream >> 16) & 0xFF;
if (input2 != sPad) decoded[o + 1] = (stream >> 8) & 0xFF;
/* If there are any stale bits in this from input1, the text is
* malformed. */
else if (((stream >> 8) & 0xFF) != 0)
return std::errc::invalid_argument;
if (input3 != sPad) decoded[o + 2] = (stream >> 0) & 0xFF;
/* If there are any stale bits in this from input2, the text is
* malformed. */
else if (((stream >> 0) & 0xFF) != 0)
return std::errc::invalid_argument;
}
return std::error_condition();
}
/*static*/ size_t RsBase64::encodedSize(size_t decodedSize, bool padding)
{
if(padding) return 4 * (decodedSize + 2) / 3;
return static_cast<size_t>(
std::ceil(4L * static_cast<double>(decodedSize) / 3L) );
}
/*static*/ std::tuple<size_t, std::error_condition> RsBase64::decodedSize(
const std::string& input )
{
const auto success = [](size_t val)
{ return std::make_tuple(val, std::error_condition()); };
if(input.empty()) return success(0);
auto mod = input.size() % 4;
if(mod == 1) std::make_tuple(0, std::errc::invalid_argument);
size_t padded_size = ((input.size() + 3) / 4) * 3;
if (mod >= 2 || (mod == 0 && input[input.size() - 1] == sPad))
{
/* If the last byte is '=', or the input size % 4 is 2 or 3 (thus
* there are implied '='s), then the actual size is 1-2 bytes
* smaller. */
if ( mod == 2 || (mod == 0 && input[input.size() - 2] == sPad) )
{
/* If the second-to-last byte is also '=', or the input
* size % 4 is 2 (implying a second '='), then the actual size
* is 2 bytes smaller. */
return success(padded_size - 2);
}
else
{
/* Otherwise it's just the last character and the actual size is
* 1 byte smaller. */
return success(padded_size - 1);
}
}
return success(padded_size);
}
/*static*/ size_t RsBase64::stripInvalid(
const std::string& in, std::string& out )
{
size_t strippedCnt = 0;
auto inSize = in.size();
out.resize(inSize);
for(size_t i = 0; i < inSize; ++i)
{
if(isBase64Char(in[i])) out[i-strippedCnt] = in[i];
else ++strippedCnt;
}
out.resize(inSize-strippedCnt);
return strippedCnt;
}

View File

@ -0,0 +1,140 @@
/*******************************************************************************
* *
* libretroshare base64 encoding utilities *
* *
* Copyright (C) 2015 Retroshare Team <contact@retroshare.cc> *
* Copyright (C) 2020 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2020 Asociación Civil Altermundi <info@altermundi.net> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 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 Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#pragma once
#include <string>
#include <vector>
#include <cstdint>
#include <system_error>
#include <tuple>
#include "util/rsmemory.h"
/**
* Implement methods to encode e decode to base64 format as per RFC 4648
* This implementation support also the file name and URL safe base64url format
* @see https://tools.ietf.org/html/rfc4648#section-5
*/
class RsBase64
{
public:
/// Enable base64url by default
static constexpr bool DEFAULT_URL_SAFE = true;
/// Disable padding by default
static constexpr bool DEFAULT_PADDING = false;
/**
* @brief Encode arbitrary data to base64
* @param[in] data pointer to the input data buffer
* @param[in] len lenght of the input buffer
* @param[out] outString storage for the resulting base64 encoded string
* @param[in] padding set to true to enable padding to 32 bits
* @param[in] urlSafe pass true for base64url format, false for base64 format
*/
static void encode(
rs_view_ptr<const uint8_t> data, size_t len,
std::string& outString,
bool padding = DEFAULT_PADDING, bool urlSafe = DEFAULT_URL_SAFE );
/**
* @brief Decode data from a base64 encoded string
* @param[in] encoded encoded string
* @param[out] decoded storage for decoded data
* @return success or error details
*/
static std::error_condition decode(
const std::string& encoded, std::vector<uint8_t>& decoded );
/**
* Remove invalid characters from base64 encoded string.
* Often when copy and pasting from one progam to another long base64
* strings, new lines, spaces or other characters end up polluting the
* original text. This function is useful to cleanup the pollution before
* attempting to decode the message.
* @param in input string
* @param out storage for cleaned string. In-place operation in supported so
* the same input string may be passed.
* @return count of stripped invalid characters
*/
static size_t stripInvalid(const std::string& in, std::string& out);
/**
* Calculate how much bytes are needed to store the base64 encoded version
* of some data.
* @param decodedSize size of the original decoded data
* @param padding true to enable base64 padding
* @return how much bytes would take to store the encoded version
*/
static size_t encodedSize(
size_t decodedSize, bool padding = DEFAULT_PADDING );
/**
* @brief Calculate how much space is needed to store the decoded version of
* a base64 encoded string
* @param input encoded string
* @return decoded size, plus error information on failure
*/
static std::tuple<size_t, std::error_condition> decodedSize(
const std::string& input );
private:
/// base64 conversion table
static constexpr char bDict[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/// base64url conversion table
static constexpr char uDict[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
/// This reverse table supports both base64 and base64url
static constexpr int8_t rDict[256] = {
/* index +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 */
/* 0 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
/* 16 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
/* 32 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63,
/* 48 */ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 0, -1, -1,
/* 64 */ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
/* 80 */ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63,
/* 96 */ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
/* 112 */ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
/* 128 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
/* 144 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
/* 160 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
/* 176 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
/* 192 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
/* 208 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
/* 224 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
/* 240 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
};
/// base64 padding character
static constexpr char sPad = '=';
/** Check if given character is valid either for base64 or for base64url
* @param c character to check
* @return true if valid false otherwise
*/
static inline bool isBase64Char(char c)
{ return rDict[static_cast<uint8_t>(c)] >= 0; }
};

View File

@ -46,7 +46,10 @@ struct t_RsLogger
{
inline t_RsLogger() = default;
typedef t_RsLogger stream_type;
/** On other platforms expose the type of underlying stream.
* On Android it cannot work like that so return the class type itself
* just for code compatibility with other platforms */
using stream_type = t_RsLogger;
template<typename T>
inline stream_type& operator<<(const T& val)
@ -68,6 +71,11 @@ struct t_RsLogger
return *this;
}
/** On other platforms return underlying stream to write avoiding additional
* prefixes. On Android it cannot work like that so return the object itself
* just for code compatibility with other platforms */
inline stream_type& uStream() { return *this; }
private:
std::ostringstream ostr;
};
@ -92,7 +100,8 @@ struct t_RsLogger
{
inline t_RsLogger() = default;
typedef decltype(std::cerr) stream_type;
/// Expose the type of underlying stream
using stream_type = decltype(std::cerr);
template<typename T>
inline stream_type& operator<<(const T& val)
@ -107,6 +116,13 @@ struct t_RsLogger
<< std::setfill('0') << std::setw(3) << msec.count()
<< std::setfill(tFill) << " " << val;
}
/// needed for manipulators and things like std::endl
stream_type& operator<<(std::ostream& (*pf)(std::ostream&))
{ return std::cerr << pf; }
/// Return underlying stream to write avoiding additional prefixes
inline stream_type& uStream() const { return std::cerr; }
};
#endif // def __ANDROID__
@ -172,16 +188,22 @@ struct RsNoDbg
{
inline RsNoDbg() = default;
/**
* This match most of the types, but might be not enough for templated
* types
*/
/** Defined as the type itself just for code compatibility with other
* logging classes */
using stream_type = RsNoDbg;
/** This match most of the types, but might be not enough for templated
* types */
template<typename T>
inline RsNoDbg& operator<<(const T&) { return *this; }
inline stream_type& operator<<(const T&) { return *this; }
/// needed for manipulators and things like std::endl
inline RsNoDbg& operator<<(std::ostream& (*/*pf*/)(std::ostream&))
inline stream_type& operator<<(std::ostream& (*/*pf*/)(std::ostream&))
{ return *this; }
/** Return the object itself just for code compatibility with other
* logging classes */
inline stream_type& uStream() { return *this; }
};
/**

View File

@ -3,7 +3,9 @@
* *
* libretroshare: retroshare core library *
* *
* Copyright 2004-2007 by Robert Fernie <retroshare@lunamutt.com> *
* Copyright (C) 2004-2007 Robert Fernie <retroshare@lunamutt.com> *
* Copyright (C) 2020 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2020 Asociación Civil Altermundi <info@altermundi.net> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
@ -265,36 +267,48 @@ bool RsDirUtil::fileExists(const std::string& filename)
bool RsDirUtil::moveFile(const std::string& source,const std::string& dest)
{
// Check that the destination directory exists. If not, create it.
Dbg3() << __PRETTY_FUNCTION__<< " source: " << source
<< " dest: " << dest << std::endl;
std::string dest_dir ;
std::string dest_file ;
splitDirFromFile(dest,dest_dir,dest_file) ;
splitDirFromFile(dest, dest_dir, dest_file);
std::cerr << "Moving file " << source << " to " << dest << std::endl;
std::cerr << "Checking that directory " << dest_dir << " actually exists." << std::endl;
if(!checkDirectory(dest_dir))
{
if(!std::filesystem::create_directories(dest_dir))
{
RsErr() << __PRETTY_FUNCTION__ << " failure creating directory: "
<< dest_dir << std::endl;
return false;
}
}
if(!checkCreateDirectory(dest_dir))
return false ;
// First try a rename
if(renameFile(source,dest))
{
Dbg3() << __PRETTY_FUNCTION__ << " plain rename worked" << std::endl;
return true;
}
// First try a rename
//
/* If not, try to copy. The src and dest probably belong to different file
* systems */
if(!copyFile(source,dest))
{
RsErr() << __PRETTY_FUNCTION__ << " failure copying file" << std::endl;
return false;
}
if(renameFile(source,dest))
return true ;
// delete the original
if(!removeFile(source))
{
RsErr() << __PRETTY_FUNCTION__ << " failure deleting original file"
<< std::endl;
return false;
}
// If not, try to copy. The src and dest probably belong to different file systems
if(!copyFile(source,dest))
return false ;
// copy was successful, let's delete the original
if(!removeFile(source))
return false ;
return true ;
return true;
}
bool RsDirUtil::removeFile(const std::string& filename)
@ -425,7 +439,7 @@ bool RsDirUtil::checkFile(const std::string& filename,uint64_t& file_size,bool d
}
bool RsDirUtil::checkDirectory(const std::string& dir)
bool RsDirUtil::checkDirectory(const std::string& dir)
{
int val;
mode_t st_mode;
@ -461,11 +475,9 @@ bool RsDirUtil::checkDirectory(const std::string& dir)
}
bool RsDirUtil::checkCreateDirectory(const std::string& dir)
bool RsDirUtil::checkCreateDirectory(const std::string& dir)
{
#ifdef RSDIR_DEBUG
std::cerr << "RsDirUtil::checkCreateDirectory() dir: " << dir << std::endl;
#endif
Dbg3() << __PRETTY_FUNCTION__ << " " << dir << std::endl;
#ifdef WINDOWS_SYS
std::wstring wdir;
@ -516,6 +528,23 @@ bool RsDirUtil::checkCreateDirectory(const std::string& dir)
return true;
}
#if __cplusplus < 201703L
bool std::filesystem::create_directories(const std::string& path)
{
for( std::string::size_type lastIndex = 0; lastIndex < std::string::npos;
lastIndex = path.find('/', lastIndex) )
{
std::string&& curDir = path.substr(0, ++lastIndex);
if(!RsDirUtil::checkCreateDirectory(curDir))
{
RsErr() << __PRETTY_FUNCTION__ << " failure creating: " << curDir
<< " of: " << path << std::endl;
return false;
}
}
return true;
}
#endif // __cplusplus < 201703L
std::string RsDirUtil::removeSymLinks(const std::string& path)
{

View File

@ -3,7 +3,9 @@
* *
* libretroshare: retroshare core library *
* *
* Copyright 2004-2007 by Robert Fernie <retroshare@lunamutt.com> *
* Copyright (C) 2004-2007 Robert Fernie <retroshare@lunamutt.com> *
* Copyright (C) 2020 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2020 Asociación Civil Altermundi <info@altermundi.net> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
@ -20,8 +22,7 @@
* *
*******************************************************************************/
#ifndef RSUTIL_DIRFNS_H
#define RSUTIL_DIRFNS_H
#pragma once
#include <string>
#include <list>
@ -84,7 +85,10 @@ int breakupDirList(const std::string& path, std::list<std::string> &subdirs
bool splitDirFromFile(const std::string& full_path,std::string& dir, std::string& file);
bool copyFile(const std::string& source,const std::string& dest);
bool moveFile(const std::string& source,const std::string& dest);
/** Move file. If destination directory doesn't exists create it. */
bool moveFile(const std::string& source, const std::string& dest);
bool removeFile(const std::string& file);
bool fileExists(const std::string& file);
bool checkFile(const std::string& filename,uint64_t& file_size,bool disallow_empty_file = false);
@ -141,8 +145,20 @@ bool getWideFileHash(std::wstring filepath, RsFileHash &hash, u
FILE *rs_fopen(const char* filename, const char* mode);
std::string convertPathToUnix(std::string path);
/** Concatenate two path pieces putting '/' separator between them only if
* needed */
std::string makePath(const std::string &path1, const std::string &path2);
RS_SET_CONTEXT_DEBUG_LEVEL(1);
}
#endif
#if __cplusplus < 201703L
namespace std
{
namespace filesystem
{
bool create_directories(const std::string& path);
}
}
#endif // __cplusplus < 201703L

View File

@ -0,0 +1,59 @@
/*******************************************************************************
* *
* libretroshare base64 encoding utilities *
* *
* Copyright (C) 2020 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2020 Asociación Civil Altermundi <info@altermundi.net> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 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 Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#pragma once
/**
* @file
* This file provide convenient integer endiannes conversion utilities.
* Instead of providing them with different names for each type (a la C htonl,
* htons, ntohl, ntohs ), which make them uncomfortable to use, expose a
* templated function `rs_endian_fix` to reorder integers representation byets
* when sending or receiving from the network. */
/* enforce LITTLE_ENDIAN on Windows */
#ifdef WINDOWS_SYS
# define BYTE_ORDER 1234
# define LITTLE_ENDIAN 1234
# define BIG_ENDIAN 4321
#else
#include <arpa/inet.h>
#endif
template<typename INTTYPE> inline INTTYPE rs_endian_fix(INTTYPE val)
{
#if BYTE_ORDER == LITTLE_ENDIAN
INTTYPE swapped = 0;
for (size_t i = 0; i < sizeof(INTTYPE); ++i)
swapped |= (val >> (8*(sizeof(INTTYPE)-i-1)) & 0xFF) << (8*i);
return swapped;
#else
return hostI;
#endif
};
#ifndef BYTE_ORDER
# error "ENDIAN determination Failed (BYTE_ORDER not defined)"
#endif
#if !(BYTE_ORDER == BIG_ENDIAN || BYTE_ORDER == LITTLE_ENDIAN)
# error "ENDIAN determination Failed (unkown BYTE_ORDER value)"
#endif

View File

@ -4,7 +4,7 @@
* libretroshare: retroshare core library *
* *
* Copyright 2012 Cyril Soler <csoler@users.sourceforge.net> *
* Copyright 2019 Gioacchino Mazzurco <gio@altermundi.net> *
* Copyright 2019-2020 Gioacchino Mazzurco <gio@altermundi.net> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
@ -62,7 +62,6 @@ bool myFunnyFunction(
*/
#define RS_DEFAULT_STORAGE_PARAM(Type,...) *std::unique_ptr<Type>(new Type(__VA_ARGS__))
/** @brief Safely dynamic cast between std::unique_ptr of different types
* std::unique_ptr semantic rely on the invariant that only one instance own
* the object, when casting between differents types one would be tempted to do
@ -90,9 +89,28 @@ bool rs_unique_cast(
return false;
}
/** Mark a pointer as non-owned aka it must not be deleted/freed in that context.
* If a function take an `rs_view_ptr` as paramether it means that she will not
* own (aka free/delete) the passed memory, instead the caller is in charge of
* managing it. If a function return an `rs_view_ptr` it means the memory is
* managed internally and the caller should not call free/delete on it.
* @see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1408r0.pdf */
template<typename T> using rs_view_ptr = T*;
/** Mark a pointer as owned aka the receiving context is in charge of dealing
* with it by free/delete once finished.
* If a function take an `rs_owner_ptr` as paramether it means that she will own
* (aka free/delete when finished using it) the passed memory, instead the
* caller is NOT in charge of managing it.
* If a function return an `rs_owner_ptr` it means the memory is NOT managed
* internally and the caller should call free/delete on it once finished using
* it.
* @see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1408r0.pdf */
template<typename T> using rs_owner_ptr = T*;
void *rs_malloc(size_t size) ;
/** @deprecated use std::unique_ptr instead
// This is a scope guard to release the memory block when going of of the current scope.
// Can be very useful to auto-delete some memory on quit without the need to call free each time.
//
@ -109,11 +127,11 @@ void *rs_malloc(size_t size) ;
// [do something]
//
// } // mem gets freed automatically
//
*/
class RsTemporaryMemory
{
public:
RsTemporaryMemory(size_t s)
explicit RsTemporaryMemory(size_t s)
{
_mem = (unsigned char *)rs_malloc(s) ;
@ -127,14 +145,7 @@ public:
size_t size() const { return _size ; }
~RsTemporaryMemory()
{
if(_mem != NULL)
{
free(_mem) ;
_mem = NULL ;
}
}
~RsTemporaryMemory() { free(_mem); }
private:
unsigned char *_mem ;

View File

@ -224,7 +224,7 @@ RsUrl& RsUrl::delQueryK(const std::string& key)
}
bool RsUrl::hasQueryK(const std::string& key)
{ return (mQuery.find(key) != mQuery.end()); }
const std::string* RsUrl::getQueryV(const std::string& key)
rs_view_ptr<const std::string> RsUrl::getQueryV(const std::string& key)
{
if(hasQueryK(key)) return &(mQuery.find(key)->second);
return nullptr;

View File

@ -20,6 +20,7 @@
#include <string>
#include <map>
#include "util/rsmemory.h"
#include "serialiser/rsserializable.h"
struct sockaddr_storage;
@ -63,7 +64,7 @@ struct RsUrl : RsSerializable
RsUrl& setQueryKV(const std::string& key, const std::string& value);
RsUrl& delQueryK(const std::string& key);
bool hasQueryK(const std::string& key);
const std::string* getQueryV(const std::string& key);
rs_view_ptr<const std::string> getQueryV(const std::string& key);
const std::string& fragment() const;
RsUrl& setFragment(const std::string& fragment);

View File

@ -462,9 +462,9 @@ char *ops_get_passphrase(void)
{
#ifndef __ANDROID__
return ops_malloc_passphrase(getpass("Passphrase: "));
#else // __ANDROID__
return ops_malloc_passphrase("getpass not supported on android");
#warning "getpass not supported on android"
#else // __ANDROID
// We should never get here on Android, getpass not supported.
abort();
#endif // __ANDROID__
}

View File

@ -623,10 +623,7 @@ void SharedFilesDialog::copyLinks(const QModelIndexList& lst, bool remote,QList<
if (details.type == DIR_TYPE_DIR)
{
FileTree *ft = FileTree::create(details,remote) ;
std::cerr << "Created collection file tree:" << std::endl;
ft->print();
auto ft = RsFileTree::fromDirDetails(details,remote);
QString dir_name = QDir(QString::fromUtf8(details.name.c_str())).dirName();
@ -634,8 +631,6 @@ void SharedFilesDialog::copyLinks(const QModelIndexList& lst, bool remote,QList<
if(link.valid())
urls.push_back(link) ;
delete ft ;
}
else
{

View File

@ -1076,30 +1076,36 @@ TransfersDialog::TransfersDialog(QWidget *parent)
// load settings
processSettings(true);
int S = QFontMetricsF(font()).height();
QString help_str = tr(
" <h1><img width=\"%1\" src=\":/icons/help_64.png\">&nbsp;&nbsp;File Transfer</h1> \
<p>Retroshare brings two ways of transferring files: direct transfers from your friends, and \
distant anonymous tunnelled transfers. In addition, file transfer is multi-source and allows swarming \
(you can be a source while downloading)</p> \
<p>You can share files using the <img src=\":/images/directoryadd_24x24_shadow.png\" width=%2 /> icon from the left side bar. \
These files will be listed in the My Files tab. You can decide for each friend group whether they can or not see these files \
in their Friends Files tab</p>\
<p>The search tab reports files from your friends' file lists, and distant files that can be reached \
anonymously using the multi-hop tunnelling system.</p> \
").arg(QString::number(2*S)).arg(QString::number(S)) ;
int S = static_cast<int>(QFontMetricsF(font()).height());
QString help_str = tr(
"<h1><img width=\"%1\" src=\":/icons/help_64.png\">&nbsp;&nbsp;"
"File Transfer</h1>"
"<p>Retroshare brings two ways of transferring files: direct "
"transfers from your friends, and distant anonymous tunnelled "
"transfers. In addition, file transfer is multi-source and "
"allows swarming (you can be a source while downloading)</p>"
"<p>You can share files using the "
"<img src=\":/images/directoryadd_24x24_shadow.png\" width=%2 />"
" icon from the left side bar. These files will be listed in "
"the My Files tab. You can decide for each friend group whether"
" they can or not see these files in their Friends Files tab</p>"
"<p>The search tab reports files from your friends' file lists,"
" and distant files that can be reached anonymously using the "
"multi-hop tunnelling system.</p>")
.arg(QString::number(2*S)).arg(QString::number(S)) ;
registerHelpButton(ui.helpButton,help_str,"TransfersDialog") ;
registerHelpButton(ui.helpButton,help_str,"TransfersDialog") ;
mEventHandlerId=0;
rsEvents->registerEventsHandler(RsEventType::FILE_TRANSFER, [this](std::shared_ptr<const RsEvent> event) { handleEvent(event); }, mEventHandlerId );
mEventHandlerId=0;
rsEvents->registerEventsHandler(
[this](std::shared_ptr<const RsEvent> event) { handleEvent(event); },
mEventHandlerId, RsEventType::FILE_TRANSFER );
}
void TransfersDialog::handleEvent(std::shared_ptr<const RsEvent> event)
{
if(event->mType != RsEventType::FILE_TRANSFER)
return;
if(event->mType != RsEventType::FILE_TRANSFER) return;
const RsFileTransferEvent *fe = dynamic_cast<const RsFileTransferEvent*>(event.get());
if(!fe)
@ -2225,9 +2231,8 @@ void TransfersDialog::pasteLink()
for(QList<RetroShareLink>::const_iterator it(links.begin());it!=links.end();++it)
{
FileTree *ft = FileTree::create((*it).radix().toStdString()) ;
col.merge_in(*ft) ;
auto ft = RsFileTree::fromRadix64((*it).radix().toStdString());
col.merge_in(*ft);
}
links.clear();
RSLinkClipboard::pasteLinks(links,RetroShareLink::TYPE_FILE);

View File

@ -149,11 +149,17 @@ IdDialog::IdDialog(QWidget *parent) : MainPage(parent), ui(new Ui::IdDialog)
{
ui->setupUi(this);
mEventHandlerId_identity = 0;
rsEvents->registerEventsHandler(RsEventType::GXS_IDENTITY, [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); }, mEventHandlerId_identity );
mEventHandlerId_identity = 0;
rsEvents->registerEventsHandler(
[this](std::shared_ptr<const RsEvent> event)
{ RsQThreadUtils::postToObject([=](){ handleEvent_main_thread(event); }, this); },
mEventHandlerId_identity, RsEventType::GXS_IDENTITY );
mEventHandlerId_circles = 0;
rsEvents->registerEventsHandler(RsEventType::GXS_CIRCLES, [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); }, mEventHandlerId_circles );
mEventHandlerId_circles = 0;
rsEvents->registerEventsHandler(
[this](std::shared_ptr<const RsEvent> event)
{ RsQThreadUtils::postToObject([=](){ handleEvent_main_thread(event); }, this); },
mEventHandlerId_circles, RsEventType::GXS_CIRCLES );
// This is used to grab the broadcast of changes from p3GxsCircles, which is discarded by the current dialog, since it expects data for p3Identity only.
//mCirclesBroadcastBase = new RsGxsUpdateBroadcastBase(rsGxsCircles, this);

View File

@ -67,12 +67,11 @@
* #define NEWS_DEBUG 1
****/
static NewsFeed *instance = NULL;
static NewsFeed* instance = nullptr;
/** Constructor */
NewsFeed::NewsFeed(QWidget *parent) : MainPage(parent), ui(new Ui::NewsFeed)
{
mEventTypes = {
NewsFeed::NewsFeed(QWidget *parent) : MainPage(parent), ui(new Ui::NewsFeed),
mEventTypes({
RsEventType::AUTHSSL_CONNECTION_AUTENTICATION,
RsEventType::PEER_CONNECTION ,
RsEventType::GXS_CIRCLES ,
@ -80,12 +79,14 @@ NewsFeed::NewsFeed(QWidget *parent) : MainPage(parent), ui(new Ui::NewsFeed)
RsEventType::GXS_FORUMS ,
RsEventType::GXS_POSTED ,
RsEventType::MAIL_STATUS
};
for(uint32_t i=0;i<mEventTypes.size();++i)
})
{
for(uint32_t i=0;i<mEventTypes.size();++i)
{
mEventHandlerIds.push_back(0); // needed to force intialization by registerEventsHandler()
rsEvents->registerEventsHandler(mEventTypes[i], [this](std::shared_ptr<const RsEvent> event) { handleEvent(event); }, mEventHandlerIds.back() );
rsEvents->registerEventsHandler(
[this](std::shared_ptr<const RsEvent> event) { handleEvent(event); },
mEventHandlerIds.back(), mEventTypes[i] );
}
/* Invoke the Qt Designer generated object setup routine */

View File

@ -41,13 +41,14 @@ public:
};
/** Constructor */
PostedDialog::PostedDialog(QWidget *parent)
: GxsGroupFrameDialog(rsPosted, parent)
PostedDialog::PostedDialog(QWidget *parent):
GxsGroupFrameDialog(rsPosted, parent), mEventHandlerId(0)
{
mEventHandlerId = 0;
// Needs to be asynced because this function is likely to be called by another thread!
rsEvents->registerEventsHandler(RsEventType::GXS_POSTED, [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); }, mEventHandlerId );
// Needs to be asynced because this function is likely to be called by another thread!
rsEvents->registerEventsHandler(
[this](std::shared_ptr<const RsEvent> event)
{ RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); },
mEventHandlerId, RsEventType::GXS_POSTED );
}
void PostedDialog::handleEvent_main_thread(std::shared_ptr<const RsEvent> event)

View File

@ -107,9 +107,11 @@ PostedListWidget::PostedListWidget(const RsGxsGroupId &postedId, QWidget *parent
processSettings(true);
mEventHandlerId = 0;
// Needs to be asynced because this function is likely to be called by another thread!
rsEvents->registerEventsHandler(RsEventType::GXS_POSTED, [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); }, mEventHandlerId );
// Needs to be asynced because this function is called by another thread!
rsEvents->registerEventsHandler(
[this](std::shared_ptr<const RsEvent> event)
{ RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); },
mEventHandlerId, RsEventType::GXS_POSTED );
/* Initialize GUI */
setGroupId(postedId);

View File

@ -1706,15 +1706,13 @@ static void processList(const QStringList &list, const QString &textSingular, co
}
break;
case TYPE_FILE_TREE:
{
FileTree *ft = FileTree::create(link.radix().toStdString()) ;
RsCollection(*ft).downloadFiles() ;
delete ft;
}
case TYPE_FILE_TREE:
{
auto ft = RsFileTree::fromRadix64(
link.radix().toStdString() );
RsCollection(*ft).downloadFiles();
break;
}
case TYPE_CHAT_ROOM:
{

View File

@ -177,8 +177,10 @@ NewFriendList::NewFriendList(QWidget *parent) : /* RsAutoUpdatePage(5000,parent)
ui->filterLineEdit->setPlaceholderText(tr("Search")) ;
ui->filterLineEdit->showFilterIcon();
mEventHandlerId=0; // forces initialization
rsEvents->registerEventsHandler( RsEventType::PEER_CONNECTION, [this](std::shared_ptr<const RsEvent> e) { handleEvent(e); }, mEventHandlerId );
mEventHandlerId=0; // forces initialization
rsEvents->registerEventsHandler(
[this](std::shared_ptr<const RsEvent> e) { handleEvent(e); },
mEventHandlerId, RsEventType::PEER_CONNECTION );
mModel = new RsFriendListModel();
mProxyModel = new FriendListSortFilterProxyModel(ui->peerTreeWidget->header(),this);

View File

@ -44,7 +44,7 @@ RsCollection::RsCollection(QObject *parent)
_xml_doc.appendChild(_root);
}
RsCollection::RsCollection(const FileTree& fr)
RsCollection::RsCollection(const RsFileTree& fr)
: _xml_doc("RsCollection")
{
_root = _xml_doc.createElement("RsCollection");
@ -153,7 +153,7 @@ void RsCollection::merge_in(const QString& fname,uint64_t size,const RsFileHash&
recursAddElements(_xml_doc,info,_root) ;
}
void RsCollection::merge_in(const FileTree& tree)
void RsCollection::merge_in(const RsFileTree& tree)
{
recursAddElements(_xml_doc,tree,0,_root) ;
}
@ -273,14 +273,14 @@ void RsCollection::recursAddElements(QDomDocument& doc,const ColFileInfo& colFil
}
}
void RsCollection::recursAddElements(QDomDocument& doc,const FileTree& ft,uint32_t index,QDomElement& e) const
void RsCollection::recursAddElements(
QDomDocument& doc, const RsFileTree& ft, uint32_t index,
QDomElement& e ) const
{
std::vector<uint32_t> subdirs ;
std::vector<FileTree::FileData> subfiles ;
std::vector<uint64_t> subdirs;
std::vector<RsFileTree::FileData> subfiles ;
std::string name;
if(!ft.getDirectoryContent(index,name,subdirs,subfiles))
return ;
if(!ft.getDirectoryContent(name, subdirs, subfiles, index)) return;
QDomElement d = doc.createElement("Directory") ;
d.setAttribute(QString("name"),QString::fromUtf8(name.c_str())) ;

View File

@ -62,11 +62,11 @@ public:
RsCollection(QObject *parent = 0) ;
// create from list of files and directories
RsCollection(const std::vector<DirDetails>& file_entries, FileSearchFlags flags, QObject *parent = 0) ;
RsCollection(const FileTree& fr);
RsCollection(const RsFileTree& fr);
virtual ~RsCollection() ;
void merge_in(const QString& fname,uint64_t size,const RsFileHash& hash) ;
void merge_in(const FileTree& tree) ;
void merge_in(const RsFileTree& tree) ;
static const QString ExtensionString ;
@ -99,7 +99,9 @@ private:
void recursAddElements(QDomDocument&, const DirDetails&, QDomElement&, FileSearchFlags flags) const ;
void recursAddElements(QDomDocument&,const ColFileInfo&,QDomElement&) const;
void recursAddElements(QDomDocument& doc,const FileTree& ft,uint32_t index,QDomElement& e) const;
void recursAddElements(
QDomDocument& doc, const RsFileTree& ft, uint32_t index,
QDomElement& e ) const;
void recursCollectColFileInfos(const QDomElement&,std::vector<ColFileInfo>& colFileInfos,const QString& current_dir,bool bad_chars_in_parent) const ;
// check that the file is a valid rscollection file, and not a lol bomb or some shit like this

View File

@ -47,12 +47,14 @@
// };
/** Constructor */
GxsChannelDialog::GxsChannelDialog(QWidget *parent)
: GxsGroupFrameDialog(rsGxsChannels, parent,true)
GxsChannelDialog::GxsChannelDialog(QWidget *parent):
GxsGroupFrameDialog(rsGxsChannels, parent, true), mEventHandlerId(0)
{
mEventHandlerId = 0;
// Needs to be asynced because this function is likely to be called by another thread!
rsEvents->registerEventsHandler(RsEventType::GXS_CHANNELS, [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); }, mEventHandlerId );
// Needs to be asynced because this function is called by another thread!
rsEvents->registerEventsHandler(
[this](std::shared_ptr<const RsEvent> event)
{ RsQThreadUtils::postToObject([=]() { handleEvent_main_thread(event); }, this ); },
mEventHandlerId, RsEventType::GXS_CHANNELS );
}
void GxsChannelDialog::handleEvent_main_thread(std::shared_ptr<const RsEvent> event)

View File

@ -130,9 +130,11 @@ GxsChannelPostsWidget::GxsChannelPostsWidget(const RsGxsGroupId &channelId, QWid
setGroupId(channelId);
mEventHandlerId = 0;
// Needs to be asynced because this function is likely to be called by another thread!
rsEvents->registerEventsHandler(RsEventType::GXS_CHANNELS, [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); }, mEventHandlerId );
// Needs to be asynced because this function is called by another thread!
rsEvents->registerEventsHandler(
[this](std::shared_ptr<const RsEvent> event)
{ RsQThreadUtils::postToObject([=](){ handleEvent_main_thread(event); }, this ); },
mEventHandlerId, RsEventType::GXS_CHANNELS );
}
void GxsChannelPostsWidget::handleEvent_main_thread(std::shared_ptr<const RsEvent> event)

View File

@ -345,10 +345,12 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget
ui->threadTreeWidget->enableColumnCustomize(true);
#endif
mEventHandlerId = 0;
// Needs to be asynced because this function is likely to be called by another thread!
rsEvents->registerEventsHandler(RsEventType::GXS_FORUMS, [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); }, mEventHandlerId );
mEventHandlerId = 0;
// Needs to be asynced because this function is called by another thread!
rsEvents->registerEventsHandler(
[this](std::shared_ptr<const RsEvent> event)
{ RsQThreadUtils::postToObject([=](){ handleEvent_main_thread(event); }, this ); },
mEventHandlerId, RsEventType::GXS_FORUMS );
}
void GxsForumThreadWidget::handleEvent_main_thread(std::shared_ptr<const RsEvent> event)

View File

@ -38,14 +38,15 @@ public:
};
/** Constructor */
GxsForumsDialog::GxsForumsDialog(QWidget *parent)
: GxsGroupFrameDialog(rsGxsForums, parent)
GxsForumsDialog::GxsForumsDialog(QWidget *parent) :
GxsGroupFrameDialog(rsGxsForums, parent), mEventHandlerId(0)
{
mCountChildMsgs = true;
mEventHandlerId = 0;
// Needs to be asynced because this function is likely to be called by another thread!
rsEvents->registerEventsHandler(RsEventType::GXS_FORUMS, [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); }, mEventHandlerId );
rsEvents->registerEventsHandler(
[this](std::shared_ptr<const RsEvent> event)
{ RsQThreadUtils::postToObject( [=]() { handleEvent_main_thread(event); }, this ); },
mEventHandlerId, RsEventType::GXS_FORUMS );
}
void GxsForumsDialog::handleEvent_main_thread(std::shared_ptr<const RsEvent> event)

View File

@ -52,8 +52,10 @@ HashingStatus::HashingStatus(QWidget *parent)
hashloader->hide();
statusHashing->hide();
mEventHandlerId=0;
rsEvents->registerEventsHandler(RsEventType::SHARED_DIRECTORIES, [this](std::shared_ptr<const RsEvent> event) { handleEvent(event); }, mEventHandlerId );
mEventHandlerId=0;
rsEvents->registerEventsHandler(
[this](std::shared_ptr<const RsEvent> event) { handleEvent(event); },
mEventHandlerId, RsEventType::SHARED_DIRECTORIES );
}
void HashingStatus::handleEvent(std::shared_ptr<const RsEvent> event)

View File

@ -1,7 +1,7 @@
/*******************************************************************************
* util/RsGxsUpdateBroadcast.cpp *
* *
* Copyright (c) 2014 Retroshare Team <retroshare.project@gmail.com> *
* Copyright (C) 2014-2020 Retroshare Team <contact@retroshare.cc> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
@ -22,6 +22,7 @@
#include "RsGxsUpdateBroadcast.h"
#include "gui/notifyqt.h"
#include "util/qtthreadsutils.h"
#include <retroshare/rsgxsifacehelper.h>
@ -32,17 +33,20 @@
// now the update notify works through rsnotify and notifyqt
// so the single instance per service is not really needed anymore
QMap<RsGxsIfaceHelper*, RsGxsUpdateBroadcast*> updateBroadcastMap;
static QMap<RsGxsIfaceHelper*, RsGxsUpdateBroadcast*> updateBroadcastMap;
RsGxsUpdateBroadcast::RsGxsUpdateBroadcast(RsGxsIfaceHelper *ifaceImpl) :
QObject(NULL), mIfaceImpl(ifaceImpl)
QObject(nullptr), mIfaceImpl(ifaceImpl), mEventHandlerId(0)
{
mEventHandlerId = 0; // forces initialization in registerEventsHandler()
rsEvents->registerEventsHandler(RsEventType::GXS_CHANGES, [this](std::shared_ptr<const RsEvent> event)
{
onChangesReceived(*dynamic_cast<const RsGxsChanges*>(event.get()));
}, mEventHandlerId );
rsEvents->registerEventsHandler(
[this](std::shared_ptr<const RsEvent> event)
{
RsQThreadUtils::postToObject(
[=]()
{ onChangesReceived(*dynamic_cast<const RsGxsChanges*>(event.get())); },
this );
},
mEventHandlerId, RsEventType::GXS_CHANGES );
}
RsGxsUpdateBroadcast::~RsGxsUpdateBroadcast()

View File

@ -31,7 +31,7 @@ struct RsGxsChanges;
typedef uint32_t TurtleRequestId ;
class RsGxsUpdateBroadcast : public QObject
class RS_DEPRECATED RsGxsUpdateBroadcast : public QObject
{
Q_OBJECT