mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
Merge pull request #1829 from G10h4ck/rsfiles_links
RsFiles links support in libretroshare + a bunch of fixes
This commit is contained in:
commit
2b44492cb6
@ -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
|
||||
- >
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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;
|
||||
|
@ -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 ;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
@ -1053,10 +1060,9 @@ bool ftController::FileRequest(const std::string& fname, const RsFileHash& hash
|
||||
*/
|
||||
|
||||
{
|
||||
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))
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
|
||||
|
@ -76,7 +76,7 @@ void RsDiscPgpKeyItem::clear()
|
||||
pgpKeyId.clear();
|
||||
free(bin_data);
|
||||
bin_data = nullptr;
|
||||
bin_len=0;
|
||||
bin_len = 0;
|
||||
}
|
||||
|
||||
void RsDiscContactItem::clear()
|
||||
|
@ -84,16 +84,22 @@ 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[]
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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") ;
|
||||
}
|
||||
|
@ -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 ;
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -1969,3 +1969,5 @@ bool RsGxsDataAccess::checkMsgFilter(
|
||||
return true;
|
||||
}
|
||||
|
||||
GxsGroupStatistic::~GxsGroupStatistic() = default;
|
||||
GxsServiceStatistic::~GxsServiceStatistic() = default;
|
||||
|
@ -78,7 +78,7 @@ 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") \
|
||||
{ \
|
||||
@ -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);
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -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 \
|
||||
@ -495,6 +496,7 @@ HEADERS += util/folderiterator.h \
|
||||
util/stacktrace.h \
|
||||
util/rsdeprecate.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) {
|
||||
|
@ -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_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);
|
||||
|
||||
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
|
||||
|
@ -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 = "") ;
|
||||
|
@ -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
|
||||
@ -97,9 +99,60 @@ enum class RsEventType : uint32_t
|
||||
/// @see RsMsgs
|
||||
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();
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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 ;
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
@ -446,7 +449,7 @@ protected:
|
||||
std::chrono::milliseconds checkEvery = std::chrono::milliseconds(100),
|
||||
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,7 +457,8 @@ 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);
|
||||
@ -503,19 +507,23 @@ private:
|
||||
|
||||
void locked_dumpTokens()
|
||||
{
|
||||
uint16_t service_id = mGxs.serviceType();
|
||||
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<7;++i)
|
||||
std::cerr << std::dec /* << i << ":" */ << count[i] << " ";
|
||||
std::cerr << std::endl;
|
||||
for(uint32_t i=0; i < countSize; ++i)
|
||||
RsDbg().uStream() /* << i << ":" */ << count[i] << " ";
|
||||
RsDbg().uStream() << std::endl;
|
||||
}
|
||||
|
||||
RS_SET_CONTEXT_DEBUG_LEVEL(1)
|
||||
};
|
||||
|
@ -199,49 +199,44 @@ struct RsGxsGenericMsgData
|
||||
};
|
||||
|
||||
|
||||
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
|
||||
uint32_t mNumMsgs; /// number of message, from the database
|
||||
uint32_t mTotalSizeOfMsgs;
|
||||
uint32_t mNumThreadMsgsNew;
|
||||
uint32_t mNumThreadMsgsUnread;
|
||||
uint32_t mNumChildMsgsNew;
|
||||
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;
|
||||
|
||||
|
@ -37,7 +37,7 @@
|
||||
#include "serialiser/rstypeserializer.h"
|
||||
#include "util/rsdeprecate.h"
|
||||
|
||||
struct RsIdentity;
|
||||
class RsIdentity;
|
||||
|
||||
/**
|
||||
* Pointer to global instance of RsIdentity service implementation
|
||||
|
@ -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>
|
||||
*
|
||||
|
@ -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,6 +607,14 @@ 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;
|
||||
|
||||
/**
|
||||
* @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
|
||||
@ -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;
|
||||
|
||||
|
@ -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__)
|
||||
|
||||
// (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));
|
||||
/* 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);
|
||||
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;
|
||||
ref = reinterpret_cast<void*>(handle);
|
||||
|
||||
#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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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 */
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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 */
|
||||
|
@ -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,10 +43,12 @@ RsItem *RsServiceSerializer::deserialise(void *data, uint32_t *size)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(mFlags & SERIALIZATION_FLAG_SKIP_HEADER)
|
||||
if(!!(mFlags & RsSerializationFlags::SKIP_HEADER))
|
||||
{
|
||||
std::cerr << "(EE) Cannot deserialise item with flags SERIALIZATION_FLAG_SKIP_HEADER. Check your code!" << std::endl;
|
||||
return NULL ;
|
||||
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,10 +85,12 @@ RsItem *RsServiceSerializer::deserialise(void *data, uint32_t *size)
|
||||
}
|
||||
RsItem *RsConfigSerializer::deserialise(void *data, uint32_t *size)
|
||||
{
|
||||
if(mFlags & SERIALIZATION_FLAG_SKIP_HEADER)
|
||||
if(!!(mFlags & RsSerializationFlags::SKIP_HEADER))
|
||||
{
|
||||
std::cerr << "(EE) Cannot deserialise item with flags SERIALIZATION_FLAG_SKIP_HEADER. Check your code!" << std::endl;
|
||||
return NULL ;
|
||||
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 "
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
switch(j)
|
||||
{
|
||||
r.first = NULL ;
|
||||
|
||||
if(!ok)
|
||||
offset = saved_offset ;
|
||||
|
||||
return ok ;
|
||||
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)
|
||||
{
|
||||
RsErr() << __PRETTY_FUNCTION__
|
||||
<< std::errc::message_size << " "
|
||||
<< second << " > " << MAX_SERIALIZED_CHUNK_SIZE
|
||||
<< std::endl;
|
||||
print_stacktrace();
|
||||
break;
|
||||
}
|
||||
if(r.second > MAX_SERIALIZED_CHUNK_SIZE)
|
||||
RS_SERIAL_PROCESS(second);
|
||||
if(!ctx.mOk) break;
|
||||
ctx.mOk = ctx.mSize >= ctx.mOffset + second;
|
||||
if(!ctx.mOk)
|
||||
{
|
||||
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 ;
|
||||
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;
|
||||
}
|
||||
|
||||
r.first = (uint8_t*)rs_malloc(r.second) ;
|
||||
if(!serialSize)
|
||||
{
|
||||
Dbg3() << __PRETTY_FUNCTION__ << " Deserialized empty memory chunk"
|
||||
<< std::endl;
|
||||
clear();
|
||||
break;
|
||||
}
|
||||
|
||||
ok = ok && (NULL != r.first);
|
||||
ctx.mOk = ctx.mSize >= ctx.mOffset + serialSize;
|
||||
if(!ctx.mOk)
|
||||
{
|
||||
RsErr() << __PRETTY_FUNCTION__ << std::errc::no_buffer_space
|
||||
<< std::endl;
|
||||
print_stacktrace();
|
||||
|
||||
memcpy(r.first,&data[offset],r.second) ;
|
||||
offset += r.second ;
|
||||
clear();
|
||||
break;
|
||||
}
|
||||
|
||||
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 );
|
||||
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;
|
||||
Radix64::encode( reinterpret_cast<uint8_t*>(member.first),
|
||||
static_cast<int>(member.second), 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();
|
||||
|
||||
rapidjson::Value value;
|
||||
value.SetString(encodedValue.data(), allocator);
|
||||
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();
|
||||
|
||||
jDoc.AddMember(key, value, allocator);
|
||||
ctx.mOk = false;
|
||||
clear();
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
template<> /*static*/
|
||||
bool RsTypeSerializer::from_JSON( const std::string& memberName,
|
||||
RsTypeSerializer::TlvMemBlock_proxy& member,
|
||||
RsJson& jDoc)
|
||||
void RsTypeSerializer::RawMemoryWrapper::clear()
|
||||
{
|
||||
SAFE_GET_JSON_V();
|
||||
ret = ret && v.IsString();
|
||||
if(ret)
|
||||
{
|
||||
std::string encodedValue = v.GetString();
|
||||
std::vector<uint8_t> decodedValue = Radix64::decode(encodedValue);
|
||||
member.second = decodedValue.size();
|
||||
|
||||
if(member.second == 0)
|
||||
{
|
||||
member.first = nullptr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
member.first = rs_malloc(member.second);
|
||||
ret = ret && member.first &&
|
||||
memcpy(member.first, decodedValue.data(), member.second);
|
||||
}
|
||||
return ret;
|
||||
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
@ -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 ;
|
||||
|
@ -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)
|
||||
if(eventType != RsEventType::__NONE)
|
||||
if(std::error_condition ec = isEventTypeInvalid(eventType))
|
||||
return ec;
|
||||
|
||||
if(!hId) hId = generateUniqueHandlerId_unlocked();
|
||||
else if (hId > mLastHandlerId)
|
||||
{
|
||||
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;
|
||||
print_stacktrace();
|
||||
return RsEventsErrorNum::INVALID_HANDLER_ID;
|
||||
}
|
||||
|
||||
if( (int)eventType >= mHandlerMaps.size())
|
||||
mHandlerMaps.resize( (int)eventType +1 );
|
||||
|
||||
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;
|
||||
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[event_type_index])
|
||||
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)])
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
@ -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<
|
||||
/** 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>)> > > mHandlerMaps;
|
||||
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;
|
||||
|
@ -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
|
@ -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 ;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
192
libretroshare/src/util/rsbase64.cc
Normal file
192
libretroshare/src/util/rsbase64.cc
Normal 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;
|
||||
}
|
140
libretroshare/src/util/rsbase64.h
Normal file
140
libretroshare/src/util/rsbase64.h
Normal 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; }
|
||||
};
|
@ -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; }
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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(!checkCreateDirectory(dest_dir))
|
||||
return false ;
|
||||
if(!checkDirectory(dest_dir))
|
||||
{
|
||||
if(!std::filesystem::create_directories(dest_dir))
|
||||
{
|
||||
RsErr() << __PRETTY_FUNCTION__ << " failure creating directory: "
|
||||
<< dest_dir << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// First try a rename
|
||||
//
|
||||
|
||||
if(renameFile(source,dest))
|
||||
return true ;
|
||||
|
||||
// If not, try to copy. The src and dest probably belong to different file systems
|
||||
{
|
||||
Dbg3() << __PRETTY_FUNCTION__ << " plain rename worked" << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* 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
|
||||
{
|
||||
RsErr() << __PRETTY_FUNCTION__ << " failure copying file" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// delete the original
|
||||
if(!removeFile(source))
|
||||
return false ;
|
||||
{
|
||||
RsErr() << __PRETTY_FUNCTION__ << " failure deleting original file"
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true ;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RsDirUtil::removeFile(const std::string& filename)
|
||||
@ -463,9 +477,7 @@ bool RsDirUtil::checkDirectory(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)
|
||||
{
|
||||
|
@ -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
|
||||
|
59
libretroshare/src/util/rsendian.h
Normal file
59
libretroshare/src/util/rsendian.h
Normal 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
|
@ -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 ;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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__
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -1076,30 +1076,36 @@ TransfersDialog::TransfersDialog(QWidget *parent)
|
||||
// load settings
|
||||
processSettings(true);
|
||||
|
||||
int S = QFontMetricsF(font()).height();
|
||||
int S = static_cast<int>(QFontMetricsF(font()).height());
|
||||
QString help_str = tr(
|
||||
" <h1><img width=\"%1\" src=\":/icons/help_64.png\"> 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)) ;
|
||||
"<h1><img width=\"%1\" src=\":/icons/help_64.png\"> "
|
||||
"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") ;
|
||||
|
||||
mEventHandlerId=0;
|
||||
rsEvents->registerEventsHandler(RsEventType::FILE_TRANSFER, [this](std::shared_ptr<const RsEvent> event) { handleEvent(event); }, mEventHandlerId );
|
||||
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);
|
||||
|
@ -150,10 +150,16 @@ 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 );
|
||||
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 );
|
||||
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);
|
||||
|
@ -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)
|
||||
{
|
||||
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 */
|
||||
|
@ -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 );
|
||||
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)
|
||||
|
@ -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);
|
||||
|
@ -1708,13 +1708,11 @@ static void processList(const QStringList &list, const QString &textSingular, co
|
||||
|
||||
case TYPE_FILE_TREE:
|
||||
{
|
||||
FileTree *ft = FileTree::create(link.radix().toStdString()) ;
|
||||
|
||||
RsCollection(*ft).downloadFiles() ;
|
||||
|
||||
delete ft;
|
||||
}
|
||||
auto ft = RsFileTree::fromRadix64(
|
||||
link.radix().toStdString() );
|
||||
RsCollection(*ft).downloadFiles();
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_CHAT_ROOM:
|
||||
{
|
||||
|
@ -178,7 +178,9 @@ NewFriendList::NewFriendList(QWidget *parent) : /* RsAutoUpdatePage(5000,parent)
|
||||
ui->filterLineEdit->showFilterIcon();
|
||||
|
||||
mEventHandlerId=0; // forces initialization
|
||||
rsEvents->registerEventsHandler( RsEventType::PEER_CONNECTION, [this](std::shared_ptr<const RsEvent> e) { handleEvent(e); }, mEventHandlerId );
|
||||
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);
|
||||
|
@ -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())) ;
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -346,9 +346,11 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget
|
||||
#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 );
|
||||
// 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)
|
||||
|
@ -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)
|
||||
|
@ -53,7 +53,9 @@ HashingStatus::HashingStatus(QWidget *parent)
|
||||
statusHashing->hide();
|
||||
|
||||
mEventHandlerId=0;
|
||||
rsEvents->registerEventsHandler(RsEventType::SHARED_DIRECTORIES, [this](std::shared_ptr<const RsEvent> event) { handleEvent(event); }, mEventHandlerId );
|
||||
rsEvents->registerEventsHandler(
|
||||
[this](std::shared_ptr<const RsEvent> event) { handleEvent(event); },
|
||||
mEventHandlerId, RsEventType::SHARED_DIRECTORIES );
|
||||
}
|
||||
|
||||
void HashingStatus::handleEvent(std::shared_ptr<const RsEvent> event)
|
||||
|
@ -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)
|
||||
rsEvents->registerEventsHandler(
|
||||
[this](std::shared_ptr<const RsEvent> event)
|
||||
{
|
||||
onChangesReceived(*dynamic_cast<const RsGxsChanges*>(event.get()));
|
||||
}, mEventHandlerId );
|
||||
RsQThreadUtils::postToObject(
|
||||
[=]()
|
||||
{ onChangesReceived(*dynamic_cast<const RsGxsChanges*>(event.get())); },
|
||||
this );
|
||||
},
|
||||
mEventHandlerId, RsEventType::GXS_CHANGES );
|
||||
}
|
||||
|
||||
RsGxsUpdateBroadcast::~RsGxsUpdateBroadcast()
|
||||
|
@ -31,7 +31,7 @@ struct RsGxsChanges;
|
||||
|
||||
typedef uint32_t TurtleRequestId ;
|
||||
|
||||
class RsGxsUpdateBroadcast : public QObject
|
||||
class RS_DEPRECATED RsGxsUpdateBroadcast : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user