diff --git a/src/chat/distributedchat.h b/src/chat/distributedchat.h index ed5a438f9..ca7155dd2 100644 --- a/src/chat/distributedchat.h +++ b/src/chat/distributedchat.h @@ -30,7 +30,7 @@ typedef RsPeerId ChatLobbyVirtualPeerId ; -class RsItem ; +struct RsItem; class p3HistoryMgr ; class p3IdService ; class p3ServiceControl; diff --git a/src/chat/rschatitems.cc b/src/chat/rschatitems.cc index 24aef56f9..7ae680105 100644 --- a/src/chat/rschatitems.cc +++ b/src/chat/rschatitems.cc @@ -205,11 +205,8 @@ void RsPrivateChatMsgConfigItem::get(RsChatMsgItem *ci) ci->recvTime = recvTime; } -/* Necessary to serialize `store` that is an STL container with RsChatMsgItem - * inside which is a subtype of RsItem */ -RS_REGISTER_ITEM_TYPE(RsChatMsgItem) void PrivateOugoingMapItem::serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) -{ RS_REGISTER_SERIAL_MEMBER(store); } +{ RS_SERIAL_PROCESS(store); } diff --git a/src/grouter/grouterclientservice.h b/src/grouter/grouterclientservice.h index a6bef29e1..35c22614a 100644 --- a/src/grouter/grouterclientservice.h +++ b/src/grouter/grouterclientservice.h @@ -34,7 +34,7 @@ #include #include -class RsItem ; +struct RsItem; static const uint32_t GROUTER_CLIENT_SERVICE_DATA_STATUS_UNKNOWN = 0x0000 ; // unused. static const uint32_t GROUTER_CLIENT_SERVICE_DATA_STATUS_RECEIVED = 0x0001 ; // sent when data has been received and a receipt is available. diff --git a/src/grouter/groutermatrix.h b/src/grouter/groutermatrix.h index 99c9ae1bd..cb567b9bc 100644 --- a/src/grouter/groutermatrix.h +++ b/src/grouter/groutermatrix.h @@ -31,7 +31,7 @@ #include "retroshare/rsgrouter.h" #include "groutertypes.h" -class RsItem ; +struct RsItem; // The routing matrix records the event clues received from each friend // diff --git a/src/gxstrans/p3gxstransitems.cc b/src/gxstrans/p3gxstransitems.cc index cebbd9e69..5d28ec582 100644 --- a/src/gxstrans/p3gxstransitems.cc +++ b/src/gxstrans/p3gxstransitems.cc @@ -1,6 +1,6 @@ /* * GXS Mailing Service - * Copyright (C) 2016-2017 Gioacchino Mazzurco + * Copyright (C) 2016-2018 Gioacchino Mazzurco * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -38,30 +38,28 @@ OutgoingRecord::OutgoingRecord( RsGxsId rec, GxsTransSubServices cs, memcpy(&mailData[0], data, size); } - -RS_REGISTER_ITEM_TYPE(RsGxsTransMailItem) // for mailItem -RS_REGISTER_ITEM_TYPE(RsNxsTransPresignedReceipt) // for presignedReceipt - -void OutgoingRecord_deprecated::serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx) +void OutgoingRecord_deprecated::serial_process( + RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx ) { - RS_REGISTER_SERIAL_MEMBER_TYPED(status, uint8_t); - RS_REGISTER_SERIAL_MEMBER(recipient); - RS_REGISTER_SERIAL_MEMBER(mailItem); - RS_REGISTER_SERIAL_MEMBER(mailData); - RS_REGISTER_SERIAL_MEMBER_TYPED(clientService, uint16_t); - RS_REGISTER_SERIAL_MEMBER(presignedReceipt); + RS_SERIAL_PROCESS(status); + RS_SERIAL_PROCESS(recipient); + RS_SERIAL_PROCESS(mailItem); + RS_SERIAL_PROCESS(mailData); + RS_SERIAL_PROCESS(clientService); + RS_SERIAL_PROCESS(presignedReceipt); } void OutgoingRecord::serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx) { - RS_REGISTER_SERIAL_MEMBER_TYPED(status, uint8_t); - RS_REGISTER_SERIAL_MEMBER(recipient); - RS_REGISTER_SERIAL_MEMBER(author); - RS_REGISTER_SERIAL_MEMBER(group_id); - RS_REGISTER_SERIAL_MEMBER(sent_ts); - RS_REGISTER_SERIAL_MEMBER(mailItem); - RS_REGISTER_SERIAL_MEMBER(mailData); - RS_REGISTER_SERIAL_MEMBER_TYPED(clientService, uint16_t); - RS_REGISTER_SERIAL_MEMBER(presignedReceipt); + RS_SERIAL_PROCESS(status); + RS_SERIAL_PROCESS(recipient); + RS_SERIAL_PROCESS(author); + RS_SERIAL_PROCESS(group_id); + RS_SERIAL_PROCESS(sent_ts); + RS_SERIAL_PROCESS(mailItem); + RS_SERIAL_PROCESS(mailData); + RS_SERIAL_PROCESS(clientService); + RS_SERIAL_PROCESS(presignedReceipt); } diff --git a/src/gxstrans/p3gxstransitems.h b/src/gxstrans/p3gxstransitems.h index f158d0bdd..bd13c9e71 100644 --- a/src/gxstrans/p3gxstransitems.h +++ b/src/gxstrans/p3gxstransitems.h @@ -55,7 +55,7 @@ public: void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) - { RS_REGISTER_SERIAL_MEMBER_TYPED(mailId, uint64_t); } + { RS_SERIAL_PROCESS(mailId); } }; class RsGxsTransPresignedReceipt : public RsGxsTransBaseMsgItem @@ -140,9 +140,9 @@ public: RsGenericSerializer::SerializeContext& ctx ) { RsGxsTransBaseMsgItem::serial_process(j, ctx); - RS_REGISTER_SERIAL_MEMBER_TYPED(cryptoType, uint8_t); - RS_REGISTER_SERIAL_MEMBER(recipientHint); - RS_REGISTER_SERIAL_MEMBER(payload); + RS_SERIAL_PROCESS(cryptoType); + RS_SERIAL_PROCESS(recipientHint); + RS_SERIAL_PROCESS(payload); } void clear() diff --git a/src/gxstunnel/rsgxstunnelitems.cc b/src/gxstunnel/rsgxstunnelitems.cc index 8e488c190..d653b03ea 100644 --- a/src/gxstunnel/rsgxstunnelitems.cc +++ b/src/gxstunnel/rsgxstunnelitems.cc @@ -102,6 +102,9 @@ template<> void RsTypeSerializer::print_data(const std::string& name,BIGNUM std::cerr << "[BIGNUM] : " << name << std::endl; } +RS_TYPE_SERIALIZER_TO_JSON_NOT_IMPLEMENTED_DEF(BIGNUM*) +RS_TYPE_SERIALIZER_FROM_JSON_NOT_IMPLEMENTED_DEF(BIGNUM*) + void RsGxsTunnelStatusItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) { RsTypeSerializer::serial_process(j,ctx,status,"status") ; diff --git a/src/libretroshare.pro b/src/libretroshare.pro index fa9491c63..825ff274e 100644 --- a/src/libretroshare.pro +++ b/src/libretroshare.pro @@ -529,7 +529,7 @@ SOURCES += ft/ftchunkmap.cc \ ft/ftfilesearch.cc \ ft/ftserver.cc \ ft/fttransfermodule.cc \ - ft/ftturtlefiletransferitem.cc + ft/ftturtlefiletransferitem.cc SOURCES += crypto/chacha20.cpp \ crypto/hashstream.cc @@ -623,6 +623,7 @@ SOURCES += serialiser/rsbaseserial.cc \ rsitems/rsgxsupdateitems.cc \ rsitems/rsserviceinfoitems.cc \ + SOURCES += services/autoproxy/rsautoproxymonitor.cc \ services/autoproxy/p3i2pbob.cc \ services/p3msgservice.cc \ @@ -764,7 +765,8 @@ SOURCES += gxstunnel/p3gxstunnel.cc \ gxstunnel/rsgxstunnelitems.cc # new serialization code -HEADERS += serialiser/rsserializer.h \ +HEADERS += serialiser/rsserializable.h \ + serialiser/rsserializer.h \ serialiser/rstypeserializer.h SOURCES += serialiser/rsserializer.cc \ diff --git a/src/pqi/pqihandler.h b/src/pqi/pqihandler.h index cf1f19429..c285c4ef7 100644 --- a/src/pqi/pqihandler.h +++ b/src/pqi/pqihandler.h @@ -38,7 +38,7 @@ class PQInterface; class RSTrafficClue; class RsBwRates; -class RsItem; +struct RsItem; class RsRawItem; class SearchModule diff --git a/src/pqi/pqiloopback.cc b/src/pqi/pqiloopback.cc index ba4078ce2..8a8ba342b 100644 --- a/src/pqi/pqiloopback.cc +++ b/src/pqi/pqiloopback.cc @@ -27,7 +27,7 @@ #include // for NULL -class RsItem; +struct RsItem; /*** #define LOOPBACK_DEBUG 1 diff --git a/src/pqi/pqiloopback.h b/src/pqi/pqiloopback.h index 7186dd440..82c3923d8 100644 --- a/src/pqi/pqiloopback.h +++ b/src/pqi/pqiloopback.h @@ -31,7 +31,7 @@ #include "pqi/pqi_base.h" // for NetInterface (ptr only), PQInterface #include "retroshare/rstypes.h" // for RsPeerId -class RsItem; +struct RsItem; class pqiloopback: public PQInterface { diff --git a/src/pqi/pqistreamer.h b/src/pqi/pqistreamer.h index fe2754854..9908651b2 100644 --- a/src/pqi/pqistreamer.h +++ b/src/pqi/pqistreamer.h @@ -38,7 +38,7 @@ #include "retroshare/rstypes.h" // for RsPeerId #include "util/rsthreads.h" // for RsMutex -class RsItem; +struct RsItem; class RsSerialiser; struct PartialPacketRecord diff --git a/src/retroshare/rsgxsifacetypes.h b/src/retroshare/rsgxsifacetypes.h index fd477fc9f..18637f1b1 100644 --- a/src/retroshare/rsgxsifacetypes.h +++ b/src/retroshare/rsgxsifacetypes.h @@ -1,3 +1,23 @@ +/* + * rsgxsifacetypes.h + * + * Copyright (C) 2013 crispy + * Copyright (C) 2018 Gioacchino Mazzurco + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + /* * rsgxsifacetypes.h * @@ -13,8 +33,10 @@ #include #include -#include -#include +#include "retroshare/rstypes.h" +#include "retroshare/rsids.h" +#include "serialiser/rsserializable.h" +#include "serialiser/rstypeserializer.h" typedef GXSGroupId RsGxsGroupId; typedef Sha1CheckSum RsGxsMessageId; @@ -34,7 +56,7 @@ typedef std::map > MsgMetaResult; class RsGxsGrpMetaData; class RsGxsMsgMetaData; -struct RsGroupMetaData +struct RsGroupMetaData : RsSerializable { // (csoler) The correct default value to be used in mCircleType is GXS_CIRCLE_TYPE_PUBLIC, which is defined in rsgxscircles.h, // but because of a loop in the includes, I cannot include it here. So I replaced with its current value 0x0001. @@ -73,6 +95,30 @@ struct RsGroupMetaData std::string mServiceString; // Service Specific Free-Form extra storage. RsPeerId mOriginator; RsGxsCircleId mInternalCircle; + + /// @see RsSerializable + void serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx ) + { + RS_SERIAL_PROCESS(mGroupId); + RS_SERIAL_PROCESS(mGroupName); + RS_SERIAL_PROCESS(mGroupFlags); + RS_SERIAL_PROCESS(mSignFlags); + RS_SERIAL_PROCESS(mPublishTs); + RS_SERIAL_PROCESS(mAuthorId); + RS_SERIAL_PROCESS(mCircleId); + RS_SERIAL_PROCESS(mCircleType); + RS_SERIAL_PROCESS(mAuthenFlags); + RS_SERIAL_PROCESS(mParentGrpId); + RS_SERIAL_PROCESS(mSubscribeFlags); + RS_SERIAL_PROCESS(mPop); + RS_SERIAL_PROCESS(mVisibleMsgCount); + RS_SERIAL_PROCESS(mLastPost); + RS_SERIAL_PROCESS(mGroupStatus); + RS_SERIAL_PROCESS(mServiceString); + RS_SERIAL_PROCESS(mOriginator); + RS_SERIAL_PROCESS(mInternalCircle); + } }; diff --git a/src/retroshare/rsidentity.h b/src/retroshare/rsidentity.h index bf650d462..47da42de4 100644 --- a/src/retroshare/rsidentity.h +++ b/src/retroshare/rsidentity.h @@ -6,7 +6,8 @@ * * RetroShare C++ Interface. * - * Copyright 2012-2012 by Robert Fernie. + * Copyright (C) 2012 Robert Fernie. + * Copyright (C) 2018 Gioacchino Mazzurco * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -36,9 +37,12 @@ #include "retroshare/rsids.h" #include "serialiser/rstlvimage.h" #include "retroshare/rsgxscommon.h" +#include "serialiser/rsserializable.h" +#include "serialiser/rstypeserializer.h" +#include "util/rsdeprecate.h" /* The Main Interface Class - for information about your Peers */ -class RsIdentity; +struct RsIdentity; extern RsIdentity *rsIdentity; @@ -63,6 +67,7 @@ extern RsIdentity *rsIdentity; #define RSID_RELATION_OTHER 0x0008 #define RSID_RELATION_UNKNOWN 0x0010 +/// @deprecated remove toghether with RsGxsIdGroup::mRecognTags #define RSRECOGN_MAX_TAGINFO 5 // Unicode symbols. NOT utf-8 bytes, because of multi byte characters @@ -77,27 +82,36 @@ static const uint32_t RS_IDENTITY_FLAGS_PGP_KNOWN = 0x0004; static const uint32_t RS_IDENTITY_FLAGS_IS_OWN_ID = 0x0008; static const uint32_t RS_IDENTITY_FLAGS_IS_DEPRECATED= 0x0010; // used to denote keys with deprecated fingerprint format. -class GxsReputation +struct GxsReputation : RsSerializable { - public: - GxsReputation(); + GxsReputation(); - bool updateIdScore(bool pgpLinked, bool pgpKnown); - bool update(); // checks ranges and calculates overall score. - int mOverallScore; - int mIdScore; // PGP, Known, etc. - int mOwnOpinion; - int mPeerOpinion; + bool updateIdScore(bool pgpLinked, bool pgpKnown); + bool update(); /// checks ranges and calculates overall score. + + int32_t mOverallScore; + int32_t mIdScore; /// PGP, Known, etc. + int32_t mOwnOpinion; + int32_t mPeerOpinion; + + /// @see RsSerializable + void serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx ) + { + RS_SERIAL_PROCESS(mOverallScore); + RS_SERIAL_PROCESS(mIdScore); + RS_SERIAL_PROCESS(mOwnOpinion); + RS_SERIAL_PROCESS(mPeerOpinion); + } }; -struct RsGxsIdGroup +struct RsGxsIdGroup : RsSerializable { RsGxsIdGroup() : mLastUsageTS(0), mPgpKnown(false), mIsAContact(false) {} ~RsGxsIdGroup() {} - RsGroupMetaData mMeta; // In GroupMetaData. @@ -120,7 +134,7 @@ struct RsGxsIdGroup std::string mPgpIdSign; // Recognition Strings. MAX# defined above. - std::list mRecognTags; + RS_DEPRECATED std::list mRecognTags; // Avatar RsGxsImage mImage ; @@ -131,8 +145,11 @@ struct RsGxsIdGroup bool mIsAContact; // change that into flags one day RsPgpId mPgpId; GxsReputation mReputation; -}; + /// @see RsSerializable + void serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx ); +}; std::ostream &operator<<(std::ostream &out, const RsGxsIdGroup &group); @@ -149,12 +166,11 @@ class RsRecognTag }; -class RsRecognTagDetails +struct RsRecognTagDetails { - public: - RsRecognTagDetails() - :valid_from(0), valid_to(0), tag_class(0), tag_type(0), - is_valid(false), is_pending(false) { return; } + RsRecognTagDetails() : + valid_from(0), valid_to(0), tag_class(0), tag_type(0), is_valid(false), + is_pending(false) {} time_t valid_from; time_t valid_to; @@ -167,105 +183,166 @@ class RsRecognTagDetails bool is_pending; }; -class RsIdOpinion -{ - public: - RsGxsId id; - int rating; -}; - -class RsIdentityParameters +struct RsIdentityParameters { - public: - RsIdentityParameters(): isPgpLinked(false) { return; } + RsIdentityParameters() : + isPgpLinked(false) {} + bool isPgpLinked; - std::string nickname; - RsGxsImage mImage ; + std::string nickname; + RsGxsImage mImage; }; -class RsIdentityUsage +struct RsIdentityUsage : RsSerializable { -public: - enum UsageCode { UNKNOWN_USAGE = 0x00, - GROUP_ADMIN_SIGNATURE_CREATION = 0x01, // These 2 are normally not normal GXS identities, but nothing prevents it to happen either. - GROUP_ADMIN_SIGNATURE_VALIDATION = 0x02, - GROUP_AUTHOR_SIGNATURE_CREATION = 0x03, // not typically used, since most services do not require group author signatures - GROUP_AUTHOR_SIGNATURE_VALIDATION = 0x04, - MESSAGE_AUTHOR_SIGNATURE_CREATION = 0x05, // most common use case. Messages are signed by authors in e.g. forums. - MESSAGE_AUTHOR_SIGNATURE_VALIDATION = 0x06, - GROUP_AUTHOR_KEEP_ALIVE = 0x07, // Identities are stamped regularly by crawlign the set of messages for all groups. That helps keepign the useful identities in hand. - MESSAGE_AUTHOR_KEEP_ALIVE = 0x08, // Identities are stamped regularly by crawlign the set of messages for all groups. That helps keepign the useful identities in hand. - CHAT_LOBBY_MSG_VALIDATION = 0x09, // Chat lobby msgs are signed, so each time one comes, or a chat lobby event comes, a signature verificaiton happens. - GLOBAL_ROUTER_SIGNATURE_CHECK = 0x0a, // Global router message validation - GLOBAL_ROUTER_SIGNATURE_CREATION = 0x0b, // Global router message signature - GXS_TUNNEL_DH_SIGNATURE_CHECK = 0x0c, // - GXS_TUNNEL_DH_SIGNATURE_CREATION = 0x0d, // - IDENTITY_DATA_UPDATE = 0x0e, // Group update on that identity data. Can be avatar, name, etc. - IDENTITY_GENERIC_SIGNATURE_CHECK = 0x0f, // Any signature verified for that identity - IDENTITY_GENERIC_SIGNATURE_CREATION = 0x10, // Any signature made by that identity - IDENTITY_GENERIC_ENCRYPTION = 0x11, - IDENTITY_GENERIC_DECRYPTION = 0x12, - CIRCLE_MEMBERSHIP_CHECK = 0x13 - } ; + enum UsageCode : uint8_t + { + UNKNOWN_USAGE = 0x00, - explicit RsIdentityUsage(uint16_t service,const RsIdentityUsage::UsageCode& code,const RsGxsGroupId& gid=RsGxsGroupId(),const RsGxsMessageId& mid=RsGxsMessageId(),uint64_t additional_id=0,const std::string& comment = std::string()); + /** These 2 are normally not normal GXS identities, but nothing prevents + * it to happen either. */ + GROUP_ADMIN_SIGNATURE_CREATION = 0x01, + GROUP_ADMIN_SIGNATURE_VALIDATION = 0x02, - uint16_t mServiceId; // Id of the service using that identity, as understood by rsServiceControl - UsageCode mUsageCode; // Specific code to use. Will allow forming the correct translated message in the GUI if necessary. - RsGxsGroupId mGrpId; // Group ID using the identity + /** Not typically used, since most services do not require group author + * signatures */ + GROUP_AUTHOR_SIGNATURE_CREATION = 0x03, + GROUP_AUTHOR_SIGNATURE_VALIDATION = 0x04, - RsGxsMessageId mMsgId; // Message ID using the identity - uint64_t mAdditionalId; // Some additional ID. Can be used for e.g. chat lobbies. - std::string mComment ; // additional comment to be used mainly for debugging, but not GUI display + /// most common use case. Messages are signed by authors in e.g. forums. + MESSAGE_AUTHOR_SIGNATURE_CREATION = 0x05, + MESSAGE_AUTHOR_SIGNATURE_VALIDATION = 0x06, - bool operator<(const RsIdentityUsage& u) const - { - return mHash < u.mHash ; - } - RsFileHash mHash ; + /** Identities are stamped regularly by crawlign the set of messages for + * all groups. That helps keepign the useful identities in hand. */ + GROUP_AUTHOR_KEEP_ALIVE = 0x07, + MESSAGE_AUTHOR_KEEP_ALIVE = 0x08, + + /** Chat lobby msgs are signed, so each time one comes, or a chat lobby + * event comes, a signature verificaiton happens. */ + CHAT_LOBBY_MSG_VALIDATION = 0x09, + + /// Global router message validation + GLOBAL_ROUTER_SIGNATURE_CHECK = 0x0a, + + /// Global router message signature + GLOBAL_ROUTER_SIGNATURE_CREATION = 0x0b, + + GXS_TUNNEL_DH_SIGNATURE_CHECK = 0x0c, + GXS_TUNNEL_DH_SIGNATURE_CREATION = 0x0d, + + /// Group update on that identity data. Can be avatar, name, etc. + IDENTITY_DATA_UPDATE = 0x0e, + + /// Any signature verified for that identity + IDENTITY_GENERIC_SIGNATURE_CHECK = 0x0f, + + /// Any signature made by that identity + IDENTITY_GENERIC_SIGNATURE_CREATION = 0x10, + + IDENTITY_GENERIC_ENCRYPTION = 0x11, + IDENTITY_GENERIC_DECRYPTION = 0x12, + CIRCLE_MEMBERSHIP_CHECK = 0x13 + } ; + + RsIdentityUsage( uint16_t service, const RsIdentityUsage::UsageCode& code, + const RsGxsGroupId& gid = RsGxsGroupId(), + const RsGxsMessageId& mid = RsGxsMessageId(), + uint64_t additional_id=0, + const std::string& comment = std::string() ); + + /// Id of the service using that identity, as understood by rsServiceControl + uint16_t mServiceId; + + /** Specific code to use. Will allow forming the correct translated message + * in the GUI if necessary. */ + UsageCode mUsageCode; + + /// Group ID using the identity + RsGxsGroupId mGrpId; + + /// Message ID using the identity + RsGxsMessageId mMsgId; + + /// Some additional ID. Can be used for e.g. chat lobbies. + uint64_t mAdditionalId; + + /// additional comment to be used mainly for debugging, but not GUI display + std::string mComment; + + bool operator<(const RsIdentityUsage& u) const { return mHash < u.mHash; } + RsFileHash mHash ; + + /// @see RsSerializable + void serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx ) + { + RS_SERIAL_PROCESS(mServiceId); + RS_SERIAL_PROCESS(mUsageCode); + RS_SERIAL_PROCESS(mGrpId); + RS_SERIAL_PROCESS(mMsgId); + RS_SERIAL_PROCESS(mAdditionalId); + RS_SERIAL_PROCESS(mComment); + RS_SERIAL_PROCESS(mHash); + } + + friend struct RsTypeSerializer; +private: + /** Accessible only to friend class RsTypeSerializer needed for + * deserialization */ + RsIdentityUsage(); }; -class RsIdentityDetails + +struct RsIdentityDetails : RsSerializable { -public: - RsIdentityDetails() - : mFlags(0), mLastUsageTS(0) { return; } + RsIdentityDetails() : mFlags(0), mLastUsageTS(0) {} RsGxsId mId; - // identity details. std::string mNickname; - uint32_t mFlags ; + uint32_t mFlags; - // PGP Stuff. - RsPgpId mPgpId; + RsPgpId mPgpId; - // Recogn details. - std::list mRecognTags; + /// @deprecated Recogn details. + RS_DEPRECATED std::list mRecognTags; - // Cyril: Reputation details. At some point we might want to merge information - // between the two into a single global score. Since the old reputation system - // is not finished yet, I leave this in place. We should decide what to do with it. - RsReputations::ReputationInfo mReputation; + /** Cyril: Reputation details. At some point we might want to merge + * information between the two into a single global score. Since the old + * reputation system is not finished yet, I leave this in place. We should + * decide what to do with it. + */ + RsReputations::ReputationInfo mReputation; - // avatar - RsGxsImage mAvatar ; + RsGxsImage mAvatar; - // last usage - time_t mLastUsageTS ; - std::map mUseCases ; + time_t mLastUsageTS; + + std::map mUseCases; + + /// @see RsSerializable + virtual void serial_process(RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx) + { + RS_SERIAL_PROCESS(mId); + RS_SERIAL_PROCESS(mNickname); + RS_SERIAL_PROCESS(mFlags); + RS_SERIAL_PROCESS(mPgpId); + //RS_SERIAL_PROCESS(mReputation); + //RS_SERIAL_PROCESS(mAvatar); + RS_SERIAL_PROCESS(mLastUsageTS); + RS_SERIAL_PROCESS(mUseCases); + } }; -class RsIdentity: public RsGxsIfaceHelper +struct RsIdentity : RsGxsIfaceHelper { - -public: - explicit RsIdentity(RsGxsIface *gxs): RsGxsIfaceHelper(gxs) {} virtual ~RsIdentity() {} diff --git a/src/retroshare/rstypes.h b/src/retroshare/rstypes.h index cc04d2312..dcad22795 100644 --- a/src/retroshare/rstypes.h +++ b/src/retroshare/rstypes.h @@ -36,6 +36,8 @@ #include #include +#include +#include #define USE_NEW_CHUNK_CHECKING_CODE @@ -118,13 +120,21 @@ class Condition std::string name; }; -class PeerBandwidthLimits +struct PeerBandwidthLimits : RsSerializable { -public: - PeerBandwidthLimits() : max_up_rate_kbs(0), max_dl_rate_kbs(0) {} - - uint32_t max_up_rate_kbs ; - uint32_t max_dl_rate_kbs ; + PeerBandwidthLimits() : max_up_rate_kbs(0), max_dl_rate_kbs(0) {} + + uint32_t max_up_rate_kbs; + uint32_t max_dl_rate_kbs; + + + /// @see RsSerializable + void serial_process(RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx) + { + RS_SERIAL_PROCESS(max_up_rate_kbs); + RS_SERIAL_PROCESS(max_dl_rate_kbs); + } }; //class SearchRequest // unused stuff. @@ -295,7 +305,7 @@ class FileChunksInfo std::map > pending_slices ; }; -class CompressedChunkMap +class CompressedChunkMap : public RsSerializable { public: CompressedChunkMap() {} @@ -345,10 +355,16 @@ class CompressedChunkMap inline void set(uint32_t j) { _map[j >> 5] |= (1 << (j & 31)) ; } inline void reset(uint32_t j) { _map[j >> 5] &= ~(1 << (j & 31)) ; } - /// compressed map, one bit per chunk - std::vector _map ; + /// compressed map, one bit per chunk + std::vector _map; + + /// @see RsSerializable + void serial_process(RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx) + { RS_SERIAL_PROCESS(_map); } }; + template class t_CRCMap { public: diff --git a/src/rsitems/rsconfigitems.cc b/src/rsitems/rsconfigitems.cc index f6296bd04..83f508794 100644 --- a/src/rsitems/rsconfigitems.cc +++ b/src/rsitems/rsconfigitems.cc @@ -28,6 +28,7 @@ #include "rsitems/rsconfigitems.h" #include "retroshare/rspeers.h" // Needed for RsGroupInfo. +#include "serialiser/rsserializable.h" #include "serialiser/rstypeserializer.h" /*** * #define RSSERIAL_DEBUG 1 @@ -89,7 +90,7 @@ void RsFileTransfer::serial_process(RsGenericSerializer::SerializeJob j,RsGeneri RsTypeSerializer::serial_process (j,ctx,flags,"flags") ; RsTypeSerializer::serial_process (j,ctx,chunk_strategy,"chunk_strategy") ; - RsTypeSerializer::serial_process (j,ctx,compressed_chunk_map,"compressed_chunk_map") ; + RS_SERIAL_PROCESS(compressed_chunk_map); } void RsFileConfigItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) @@ -192,31 +193,6 @@ void RsPeerStunItem::serial_process(RsGenericSerializer::SerializeJob j,RsGeneri RsTypeSerializer::serial_process(j,ctx,stunList,"stunList") ; } -template<> uint32_t RsTypeSerializer::serial_size(const PeerBandwidthLimits& /*s*/) -{ - return 4+4 ; -} - -template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset,const PeerBandwidthLimits& s) -{ - bool ok = true ; - ok = ok && setRawUInt32(data,size,&offset,s.max_up_rate_kbs); - ok = ok && setRawUInt32(data,size,&offset,s.max_dl_rate_kbs); - return ok; -} - -template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size,uint32_t& offset,PeerBandwidthLimits& s) -{ - bool ok = true ; - ok = ok && getRawUInt32(data,size,&offset,&s.max_up_rate_kbs); - ok = ok && getRawUInt32(data,size,&offset,&s.max_dl_rate_kbs); - return ok; -} - -template<> void RsTypeSerializer::print_data(const std::string& /*n*/, const PeerBandwidthLimits& s) -{ - std::cerr << " [Peer BW limit] " << s.max_up_rate_kbs << " / " << s.max_dl_rate_kbs << std::endl; -} RsNodeGroupItem::RsNodeGroupItem(const RsGroupInfo& g) :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_PEER_CONFIG, RS_PKT_SUBTYPE_NODE_GROUP) diff --git a/src/rsitems/rsfiletransferitems.cc b/src/rsitems/rsfiletransferitems.cc index 7579c9560..4241081a7 100644 --- a/src/rsitems/rsfiletransferitems.cc +++ b/src/rsitems/rsfiletransferitems.cc @@ -91,48 +91,6 @@ void RsFileTransferSingleChunkCrcItem::serial_process(RsGenericSerializer::Seria RsTypeSerializer::serial_process (j,ctx,check_sum, "check_sum") ; } -//===================================================================================================// -// CompressedChunkMap // -//===================================================================================================// - -template<> uint32_t RsTypeSerializer::serial_size(const CompressedChunkMap& s) -{ - return 4 + 4*s._map.size() ; -} - -template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset,const CompressedChunkMap& s) -{ - bool ok = true ; - - ok &= setRawUInt32(data, size, &offset, s._map.size()); - - for(uint32_t i=0;i bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size,uint32_t& offset,CompressedChunkMap& s) -{ - uint32_t S =0; - bool ok = getRawUInt32(data, size, &offset, &S); - - if(ok) - { - s._map.resize(S) ; - - for(uint32_t i=0;i void RsTypeSerializer::print_data(const std::string& n, const CompressedChunkMap& s) -{ - std::cerr << " [Compressed chunk map] " << n << " : length=" << s._map.size() << std::endl; -} - //===================================================================================================// // Serializer // //===================================================================================================// diff --git a/src/rsitems/rsgxsupdateitems.cc b/src/rsitems/rsgxsupdateitems.cc index 50f154cb2..a5f3ecf02 100644 --- a/src/rsitems/rsgxsupdateitems.cc +++ b/src/rsitems/rsgxsupdateitems.cc @@ -97,31 +97,6 @@ void RsGxsMsgUpdateItem::serial_process(RsGenericSerializer::SerializeJob j,RsGe RsTypeSerializer::serial_process(j,ctx,msgUpdateInfos,"msgUpdateInfos"); } -template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const RsGxsMsgUpdateItem::MsgUpdateInfo& info) -{ - bool ok = true ; - - ok = ok && setRawUInt32(data,size,&offset,info.time_stamp); - ok = ok && setRawUInt32(data,size,&offset,info.message_count); - - return ok; -} -template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, RsGxsMsgUpdateItem::MsgUpdateInfo& info) -{ - bool ok = true ; - - ok = ok && getRawUInt32(data,size,&offset,&info.time_stamp); - ok = ok && getRawUInt32(data,size,&offset,&info.message_count); - - return ok; -} -template<> uint32_t RsTypeSerializer::serial_size(const RsGxsMsgUpdateItem::MsgUpdateInfo& /* info */) { return 8; } - -template<> void RsTypeSerializer::print_data(const std::string& name,const RsGxsMsgUpdateItem::MsgUpdateInfo& info) -{ - std::cerr << "[MsgUpdateInfo]: " << name << ": " << info.time_stamp << ", " << info.message_count << std::endl; -} - void RsGxsServerMsgUpdateItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) { RsTypeSerializer::serial_process (j,ctx,grpId,"grpId"); @@ -134,5 +109,3 @@ void RsGxsGrpConfigItem::serial_process(RsGenericSerializer::SerializeJob j,RsGe RsTypeSerializer::serial_process(j,ctx,msg_send_delay,"msg_send_delay") ; RsTypeSerializer::serial_process(j,ctx,msg_req_delay,"msg_req_delay") ; } - - diff --git a/src/rsitems/rsgxsupdateitems.h b/src/rsitems/rsgxsupdateitems.h index c9725426c..5d13028ff 100644 --- a/src/rsitems/rsgxsupdateitems.h +++ b/src/rsitems/rsgxsupdateitems.h @@ -28,18 +28,11 @@ -#if 0 -#include -#include "rsitems/rsserviceids.h" -#include "serialiser/rsserial.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvtypes.h" -#include "serialiser/rstlvkeys.h" -#endif - #include "gxs/rsgxs.h" #include "gxs/rsgxsdata.h" #include "serialiser/rstlvidset.h" +#include "serialiser/rstypeserializer.h" +#include "serialiser/rsserializable.h" const uint8_t RS_PKT_SUBTYPE_GXS_GRP_UPDATE = 0x01; @@ -140,17 +133,26 @@ public: class RsGxsMsgUpdate { public: - struct MsgUpdateInfo + struct MsgUpdateInfo : RsSerializable { MsgUpdateInfo(): time_stamp(0), message_count(0) {} uint32_t time_stamp ; uint32_t message_count ; + + /// @see RsSerializable + void serial_process(RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx) + { + RS_SERIAL_PROCESS(time_stamp); + RS_SERIAL_PROCESS(message_count); + } }; std::map msgUpdateInfos; }; + class RsGxsMsgUpdateItem : public RsGxsNetServiceItem, public RsGxsMsgUpdate { public: diff --git a/src/rsitems/rsitem.h b/src/rsitems/rsitem.h index 056bbe084..545870631 100644 --- a/src/rsitems/rsitem.h +++ b/src/rsitems/rsitem.h @@ -1,76 +1,96 @@ #pragma once +/* + * RetroShare Serialiser. + * Copyright (C) 2018 Gioacchino Mazzurco + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ #include // for typeid #include "util/smallobject.h" #include "retroshare/rstypes.h" #include "serialiser/rsserializer.h" +#include "serialiser/rsserializable.h" #include "util/stacktrace.h" #include -class RsItem: public RsMemoryManagement::SmallObject +struct RsItem : RsMemoryManagement::SmallObject, RsSerializable { - public: - explicit RsItem(uint32_t t); - RsItem(uint8_t ver, uint8_t cls, uint8_t t, uint8_t subtype); + explicit RsItem(uint32_t t); + RsItem(uint8_t ver, uint8_t cls, uint8_t t, uint8_t subtype); #ifdef DO_STATISTICS - void *operator new(size_t s) ; - void operator delete(void *,size_t s) ; + void *operator new(size_t s) ; + void operator delete(void *,size_t s) ; #endif - virtual ~RsItem(); + virtual ~RsItem(); - /// TODO: Do this make sense with the new serialization system? - virtual void clear() = 0; + /// TODO: Do this make sense with the new serialization system? + virtual void clear() = 0; - virtual std::ostream &print(std::ostream &out, uint16_t /* indent */ = 0) - { - RsGenericSerializer::SerializeContext ctx(NULL,0,RsGenericSerializer::FORMAT_BINARY,RsGenericSerializer::SERIALIZATION_FLAG_NONE); - serial_process(RsGenericSerializer::PRINT,ctx) ; - return out; - } + virtual std::ostream &print(std::ostream &out, uint16_t /* indent */ = 0) + { + RsGenericSerializer::SerializeContext ctx( + NULL, 0, RsGenericSerializer::FORMAT_BINARY, + RsGenericSerializer::SERIALIZATION_FLAG_NONE ); + serial_process(RsGenericSerializer::PRINT,ctx); + return out; + } - void print_string(std::string &out, uint16_t indent = 0); + void print_string(std::string &out, uint16_t indent = 0); - /* source / destination id */ - const RsPeerId& PeerId() const { return peerId; } - void PeerId(const RsPeerId& id) { peerId = id; } + /// source / destination id + const RsPeerId& PeerId() const { return peerId; } + void PeerId(const RsPeerId& id) { peerId = id; } - /* complete id */ - uint32_t PacketId() const; + /// complete id + uint32_t PacketId() const; - /* id parts */ - uint8_t PacketVersion(); - uint8_t PacketClass(); - uint8_t PacketType(); - uint8_t PacketSubType() const; + /// id parts + uint8_t PacketVersion(); + uint8_t PacketClass(); + uint8_t PacketType(); + uint8_t PacketSubType() const; - /* For Service Packets */ - RsItem(uint8_t ver, uint16_t service, uint8_t subtype); - uint16_t PacketService() const; /* combined Packet class/type (mid 16bits) */ - void setPacketService(uint16_t service); + /// For Service Packets + RsItem(uint8_t ver, uint16_t service, uint8_t subtype); + uint16_t PacketService() const; /* combined Packet class/type (mid 16bits) */ + void setPacketService(uint16_t service); - inline uint8_t priority_level() const { return _priority_level ;} - inline void setPriorityLevel(uint8_t l) { _priority_level = l ;} + inline uint8_t priority_level() const { return _priority_level ;} + inline void setPriorityLevel(uint8_t l) { _priority_level = l ;} - /** - * TODO: This should be made pure virtual as soon as all the codebase - * is ported to the new serialization system - */ - virtual void serial_process(RsGenericSerializer::SerializeJob, - RsGenericSerializer::SerializeContext&)// = 0; - { - std::cerr << "(EE) RsItem::serial_process() called by an item using" - << "new serialization classes, but not derived! Class is " - << typeid(*this).name() << std::endl; - print_stacktrace(); - } + /** + * TODO: This default implementation should be removed and childs structs + * implement ::serial_process(...) as soon as all the codebase is ported to + * the new serialization system + */ + virtual void serial_process(RsGenericSerializer::SerializeJob, + RsGenericSerializer::SerializeContext&)// = 0; + { + std::cerr << "(EE) RsItem::serial_process(...) called by an item using" + << "new serialization classes, but not derived! Class is " + << typeid(*this).name() << std::endl; + print_stacktrace(); + } - protected: - uint32_t type; - RsPeerId peerId; - uint8_t _priority_level ; +protected: + uint32_t type; + RsPeerId peerId; + uint8_t _priority_level; }; /// TODO: Do this make sense with the new serialization system? diff --git a/src/rsitems/rsnxsitems.cc b/src/rsitems/rsnxsitems.cc index 91c35ce72..8c6775275 100644 --- a/src/rsitems/rsnxsitems.cc +++ b/src/rsitems/rsnxsitems.cc @@ -73,12 +73,12 @@ void RsNxsSyncMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGene void RsNxsMsg::serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) { - RS_REGISTER_SERIAL_MEMBER_TYPED(transactionNumber, uint32_t); - RS_REGISTER_SERIAL_MEMBER_TYPED(pos, uint8_t); - RS_REGISTER_SERIAL_MEMBER(msgId); - RS_REGISTER_SERIAL_MEMBER(grpId); - RS_REGISTER_SERIAL_MEMBER_TYPED(msg, RsTlvItem); - RS_REGISTER_SERIAL_MEMBER_TYPED(meta, RsTlvItem); + RS_SERIAL_PROCESS(transactionNumber); + RS_SERIAL_PROCESS(pos); + RS_SERIAL_PROCESS(msgId); + RS_SERIAL_PROCESS(grpId); + RS_SERIAL_PROCESS(msg); + RS_SERIAL_PROCESS(meta); } void RsNxsGrp::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) diff --git a/src/rsserver/rstypes.cc b/src/rsserver/rstypes.cc index 209a7da88..4574c48e8 100644 --- a/src/rsserver/rstypes.cc +++ b/src/rsserver/rstypes.cc @@ -75,5 +75,3 @@ std::ostream &operator<<(std::ostream &out, const FileInfo &info) out << "Hash: " << info.hash; return out; } - - diff --git a/src/serialiser/rsbaseserial.cc b/src/serialiser/rsbaseserial.cc index 44bd249d1..ef862db5c 100644 --- a/src/serialiser/rsbaseserial.cc +++ b/src/serialiser/rsbaseserial.cc @@ -238,8 +238,7 @@ uint32_t getRawStringSize(const std::string &outStr) bool getRawString(const void *data, uint32_t size, uint32_t *offset, std::string &outStr) { -#warning Gio: "I had to change this. It seems like a bug to not clear the string. Should make sure it's not introducing any side effect." - outStr.clear(); + outStr.clear(); uint32_t len = 0; if (!getRawUInt32(data, size, offset, &len)) diff --git a/src/serialiser/rsserial.h b/src/serialiser/rsserial.h index 206f69608..ee3a79537 100644 --- a/src/serialiser/rsserial.h +++ b/src/serialiser/rsserial.h @@ -64,7 +64,7 @@ const uint8_t RS_PKT_CLASS_CONFIG = 0x02; const uint8_t RS_PKT_SUBTYPE_DEFAULT = 0x01; /* if only one subtype */ -class RsItem ; +struct RsItem; class RsSerialType ; diff --git a/src/serialiser/rsserializable.h b/src/serialiser/rsserializable.h new file mode 100644 index 000000000..c717afc4b --- /dev/null +++ b/src/serialiser/rsserializable.h @@ -0,0 +1,48 @@ +#pragma once +/* + * RetroShare Serialiser. + * Copyright (C) 2016-2018 Gioacchino Mazzurco + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "serialiser/rsserializer.h" + + +/** @brief Minimal ancestor for all serializable structs in RetroShare. + * If you want your struct to be easly serializable you should inherit from this + * struct. + */ +struct RsSerializable +{ + /** Process struct members to serialize in this method taking advantage of + * the helper macro @see RS_SERIAL_PROCESS(I) + */ + virtual void serial_process(RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx) = 0; +}; + +/** @def RS_SERIAL_PROCESS(I) + * Use this macro to process the members of `YourSerializable` for serial + * processing inside `YourSerializable::serial_process(j, ctx)` + * + * Pay special attention for member of enum type which must be declared + * specifying the underlying type otherwise the serialization format may differ + * in an uncompatible way depending on the compiler/platform. + * + * Inspired by http://stackoverflow.com/a/39345864 + */ +#define RS_SERIAL_PROCESS(I) do { \ + RsTypeSerializer::serial_process(j, ctx, I, #I ); \ + } while(0) diff --git a/src/serialiser/rsserializer.h b/src/serialiser/rsserializer.h index 2cae93ab7..dcc4d089f 100644 --- a/src/serialiser/rsserializer.h +++ b/src/serialiser/rsserializer.h @@ -3,7 +3,8 @@ * * RetroShare Serialiser. * - * Copyright 2016 by Cyril Soler + * Copyright (C) 2016 Cyril Soler + * Copyright (C) 2018 Gioacchino Mazzurco * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -153,11 +154,13 @@ #include #include #include +#include #include "retroshare/rsflags.h" #include "serialiser/rsserial.h" +#include "util/rsdeprecate.h" -class RsItem ; +struct RsItem; #define SERIALIZE_ERROR() std::cerr << __PRETTY_FUNCTION__ << " : " @@ -194,106 +197,125 @@ class RsRawSerialiser: public RsSerialType virtual RsItem * deserialise(void *data, uint32_t *size); }; -// Top class for all services and config serializers. +typedef rapidjson::Document RsJson; -class RsGenericSerializer: public RsSerialType +/// Top class for all services and config serializers. +struct RsGenericSerializer : RsSerialType { -public: - typedef enum { SIZE_ESTIMATE = 0x01, SERIALIZE = 0x02, DESERIALIZE = 0x03, PRINT=0x04 } SerializeJob ; - typedef enum { FORMAT_BINARY = 0x01, FORMAT_JSON = 0x02 } SerializationFormat ; - - class SerializeContext - { - public: + typedef enum + { + SIZE_ESTIMATE = 0x01, + SERIALIZE = 0x02, + DESERIALIZE = 0x03, + PRINT = 0x04, + TO_JSON, + FROM_JSON + } SerializeJob; - SerializeContext(uint8_t *data,uint32_t size,SerializationFormat format,SerializationFlags flags) - : mData(data),mSize(size),mOffset(0),mOk(true),mFormat(format),mFlags(flags) {} + /** @deprecated use SerializeJob instead */ + RS_DEPRECATED typedef enum + { + FORMAT_BINARY = 0x01, + FORMAT_JSON = 0x02 + } SerializationFormat; - unsigned char *mData ; - uint32_t mSize ; - uint32_t mOffset ; - bool mOk ; - SerializationFormat mFormat ; - SerializationFlags mFlags ; - }; + struct SerializeContext + { + /** Allow shared allocator usage to avoid costly JSON deepcopy for + * nested RsSerializable */ + 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) {} - // 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 + unsigned char *mData; + uint32_t mSize; + uint32_t mOffset; + bool mOk; + RS_DEPRECATED SerializationFormat mFormat; + SerializationFlags mFlags; + RsJson mJson; + }; - 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 + /** 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 - // The following functions overload RsSerialType. They *should not* need to be further overloaded. - - RsItem *deserialise(void *data,uint32_t *size) =0; - bool serialise(RsItem *item,void *data,uint32_t *size) ; - uint32_t size(RsItem *item) ; - void print(RsItem *item) ; + /** + * The following functions overload RsSerialType. + * They *should not* need to be further overloaded. + */ + RsItem *deserialise(void *data,uint32_t *size) = 0; + bool serialise(RsItem *item,void *data,uint32_t *size); + uint32_t size(RsItem *item); + void print(RsItem *item); protected: - RsGenericSerializer(uint8_t serial_class, - uint8_t serial_type, - SerializationFormat format, - SerializationFlags flags ) - : RsSerialType(RS_PKT_VERSION1,serial_class,serial_type), mFormat(format),mFlags(flags) - {} + RsGenericSerializer( + uint8_t serial_class, uint8_t serial_type, + SerializationFormat format, SerializationFlags 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, SerializationFormat format, + SerializationFlags flags ) : + RsSerialType( RS_PKT_VERSION_SERVICE, service ), mFormat(format), + mFlags(flags) {} + SerializationFormat mFormat; + SerializationFlags mFlags; }; -// Top class for service serializers. Derive your on service serializer from this class and overload creat_item(). -class RsServiceSerializer: public RsGenericSerializer +/** Top class for service serializers. + * Derive your on service serializer from this class and overload creat_item(). + */ +struct RsServiceSerializer : RsGenericSerializer { -public: - RsServiceSerializer(uint16_t service_id, - SerializationFormat format = FORMAT_BINARY, - SerializationFlags flags = SERIALIZATION_FLAG_NONE) + RsServiceSerializer( + uint16_t service_id, SerializationFormat format = FORMAT_BINARY, + SerializationFlags flags = SERIALIZATION_FLAG_NONE ) : + RsGenericSerializer(service_id, format, flags) {} - : RsGenericSerializer(service_id,format,flags) {} + /*! should be overloaded to create the correct type of item depending on the + * data */ + virtual RsItem *create_item( uint16_t /* service */, + uint8_t /* item_sub_id */ ) const = 0; - /*! create_item - * should be overloaded to create the correct type of item depending on the data - */ - virtual RsItem *create_item(uint16_t /* service */, uint8_t /* item_sub_id */) const=0; - - RsItem *deserialise(void *data,uint32_t *size) ; + RsItem *deserialise(void *data, uint32_t *size); }; -// Top class for config serializers. Config serializers are only used internally by RS core. The development of new services or plugins do not need this. -class RsConfigSerializer: public RsGenericSerializer +/** Top class for config serializers. + * Config serializers are only used internally by RS core. + * The development of new services or plugins do not need this. + */ +struct RsConfigSerializer : RsGenericSerializer { -public: RsConfigSerializer(uint8_t config_class, uint8_t config_type, SerializationFormat format = FORMAT_BINARY, - SerializationFlags flags = SERIALIZATION_FLAG_NONE) + SerializationFlags flags = SERIALIZATION_FLAG_NONE) : + RsGenericSerializer(config_class,config_type,format,flags) {} - : RsGenericSerializer(config_class,config_type,format,flags) {} + /*! should be overloaded to create the correct type of item depending on the + * data */ + virtual RsItem *create_item(uint8_t /* item_type */, + uint8_t /* item_sub_type */) const = 0; - /*! create_item - * should be overloaded to create the correct type of item depending on the data - */ - virtual RsItem *create_item(uint8_t /* item_type */, uint8_t /* item_sub_type */) const=0; - - RsItem *deserialise(void *data,uint32_t *size) ; + RsItem *deserialise(void *data,uint32_t *size); }; - - - diff --git a/src/serialiser/rstypeserializer.cc b/src/serialiser/rstypeserializer.cc index 8be8660ae..8d7ba5daf 100644 --- a/src/serialiser/rstypeserializer.cc +++ b/src/serialiser/rstypeserializer.cc @@ -3,7 +3,8 @@ * * RetroShare Serialiser. * - * Copyright 2017 by Cyril Soler + * Copyright (C) 2017 Cyril Soler + * Copyright (C) 2018 Gioacchino Mazzurco * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -26,27 +27,49 @@ #include "serialiser/rstypeserializer.h" #include "serialiser/rsbaseserial.h" #include "serialiser/rstlvkeys.h" - -#include "rsitems/rsitem.h" +#include "serialiser/rsserializable.h" #include "util/rsprint.h" #include -#include #include +#include +#include // for typeid +#include +#include //static const uint32_t MAX_SERIALIZED_ARRAY_SIZE = 500 ; static const uint32_t MAX_SERIALIZED_CHUNK_SIZE = 10*1024*1024 ; // 10 MB. -//=================================================================================================// -// Integer types // -//=================================================================================================// +#define SAFE_GET_JSON_V() \ + const char* mName = memberName.c_str(); \ + bool ret = jDoc.HasMember(mName); \ + if(!ret) \ + { \ + std::cerr << __PRETTY_FUNCTION__ << " \"" << memberName \ + << "\" not found in JSON:" << std::endl \ + << jDoc << std::endl << std::endl; \ + print_stacktrace(); \ + return false; \ + } \ + rapidjson::Value& v = jDoc[mName] + + +//============================================================================// +// Integer 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); @@ -70,10 +93,16 @@ template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint3 template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, bool& member) { - uint8_t m ; + uint8_t m; bool ok = getRawUInt8(data,size,&offset,&m); - member = m ; - return ok; + 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) { @@ -100,6 +129,12 @@ 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; @@ -125,6 +160,10 @@ template<> void RsTypeSerializer::print_data(const std::string& n, const bool & { 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 << ": " << V << std::endl; +} template<> void RsTypeSerializer::print_data(const std::string& n, const uint8_t & V) { std::cerr << " [uint8_t ] " << n << ": " << V << std::endl; @@ -146,10 +185,121 @@ template<> void RsTypeSerializer::print_data(const std::string& n, const time_t& std::cerr << " [time_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 ) \ +{ \ + rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); \ + \ + rapidjson::Value key; \ + key.SetString(memberName.c_str(), memberName.length(), allocator); \ + \ + rapidjson::Value value(member); \ + \ + jDoc.AddMember(key, value, allocator); \ + \ + return true; \ +} -//=================================================================================================// -// FLoats // -//=================================================================================================// +SIMPLE_TO_JSON_DEF(bool) +SIMPLE_TO_JSON_DEF(int32_t) + +template<> bool RsTypeSerializer::to_JSON( const std::string& memberName, + const time_t& member, RsJson& jDoc ) +{ + rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); + + rapidjson::Value key; + key.SetString(memberName.c_str(), memberName.length(), allocator); + + // without this compilation may break depending on how time_t is defined + int64_t tValue = member; + rapidjson::Value value(tValue); + + jDoc.AddMember(key, value, allocator); + + return true; +} + +SIMPLE_TO_JSON_DEF(uint8_t) +SIMPLE_TO_JSON_DEF(uint16_t) +SIMPLE_TO_JSON_DEF(uint32_t) +SIMPLE_TO_JSON_DEF(uint64_t) + +template<> /*static*/ +bool RsTypeSerializer::from_JSON( const std::string& memberName, bool& member, + RsJson& jDoc ) +{ + SAFE_GET_JSON_V(); + ret = ret && v.IsBool(); + if(ret) member = v.GetBool(); + return ret; +} + +template<> /*static*/ +bool RsTypeSerializer::from_JSON( const std::string& memberName, + int32_t& member, RsJson& jDoc ) +{ + SAFE_GET_JSON_V(); + ret = ret && v.IsInt(); + if(ret) member = v.GetInt(); + return ret; +} + +template<> /*static*/ +bool RsTypeSerializer::from_JSON( const std::string& memberName, time_t& member, + RsJson& jDoc ) +{ + SAFE_GET_JSON_V(); + ret = ret && v.IsInt(); + if(ret) member = v.GetInt(); + return ret; +} + +template<> /*static*/ +bool RsTypeSerializer::from_JSON( const std::string& memberName, + uint8_t& member, RsJson& jDoc ) +{ + SAFE_GET_JSON_V(); + ret = ret && v.IsUint(); + if(ret) member = v.GetUint(); + return ret; +} + +template<> /*static*/ +bool RsTypeSerializer::from_JSON( const std::string& memberName, + uint16_t& member, RsJson& jDoc ) +{ + SAFE_GET_JSON_V(); + ret = ret && v.IsUint(); + if(ret) member = v.GetUint(); + return ret; +} + +template<> /*static*/ +bool RsTypeSerializer::from_JSON( const std::string& memberName, + uint32_t& member, RsJson& jDoc ) +{ + SAFE_GET_JSON_V(); + ret = ret && v.IsUint(); + if(ret) member = v.GetUint(); + return ret; +} + +template<> /*static*/ +bool RsTypeSerializer::from_JSON( const std::string& memberName, + uint64_t& member, RsJson& jDoc ) +{ + SAFE_GET_JSON_V(); + ret = ret && v.IsUint(); + if(ret) member = v.GetUint(); + return ret; +} + + +//============================================================================// +// Floats // +//============================================================================// template<> uint32_t RsTypeSerializer::serial_size(const float&){ return 4; } @@ -166,10 +316,75 @@ template<> void RsTypeSerializer::print_data(const std::string& n, const float& std::cerr << " [float ] " << n << ": " << V << std::endl; } +SIMPLE_TO_JSON_DEF(float) -//=================================================================================================// -// TlvString with subtype // -//=================================================================================================// +template<> /*static*/ +bool RsTypeSerializer::from_JSON( const std::string& memberName, + float& member, RsJson& jDoc ) +{ + SAFE_GET_JSON_V(); + ret = ret && v.IsFloat(); + if(ret) member = v.GetFloat(); + return ret; +} + + +//============================================================================// +// 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 ) +{ + rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); + + rapidjson::Value key; + key.SetString(membername.c_str(), membername.length(), allocator); + + rapidjson::Value value;; + value.SetString(member.c_str(), member.length(), allocator); + + jDoc.AddMember(key, value, allocator); + + return true; +} +template<> /*static*/ +bool RsTypeSerializer::from_JSON( const std::string& memberName, + std::string& member, RsJson& jDoc ) +{ + SAFE_GET_JSON_V(); + ret = ret && v.IsString(); + if(ret) member = v.GetString(); + return ret; +} + + + +//============================================================================// +// TlvString with subtype // +//============================================================================// template<> uint32_t RsTypeSerializer::serial_size(uint16_t /* type_subtype */,const std::string& s) { @@ -188,46 +403,131 @@ template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t siz template<> void RsTypeSerializer::print_data(const std::string& n, uint16_t type_substring,const std::string& V) { - std::cerr << " [TlvString ] " << n << ": type=" << std::hex < uint32_t RsTypeSerializer::serial_size(uint16_t /* type_subtype */,const uint32_t& /*s*/) +template<> /*static*/ +bool RsTypeSerializer::to_JSON( const std::string& memberName, + uint16_t /*sub_type*/, + const std::string& member, RsJson& jDoc ) { - return GetTlvUInt32Size() ; + return to_JSON(memberName, member, jDoc); } -template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset,uint16_t sub_type,const uint32_t& s) +template<> /*static*/ +bool RsTypeSerializer::from_JSON( const std::string& memberName, + uint16_t /*sub_type*/, + std::string& member, RsJson& jDoc ) { - return SetTlvUInt32(data,size,&offset,sub_type,s) ; + return from_JSON(memberName, member, jDoc); } -template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size,uint32_t& offset,uint16_t sub_type,uint32_t& s) +//============================================================================// +// TlvInt with subtype // +//============================================================================// + +template<> uint32_t RsTypeSerializer::serial_size( uint16_t /* type_subtype */, + const uint32_t& /*s*/ ) { - return GetTlvUInt32((void*)data,size,&offset,sub_type,&s) ; + return GetTlvUInt32Size(); +} + +template<> bool RsTypeSerializer::serialize( uint8_t data[], uint32_t size, + uint32_t &offset,uint16_t sub_type, + const uint32_t& s) +{ + return SetTlvUInt32(data,size,&offset,sub_type,s); +} + +template<> bool RsTypeSerializer::deserialize( const uint8_t data[], + uint32_t size, uint32_t& offset, + uint16_t sub_type, uint32_t& s) +{ + return GetTlvUInt32((void*)data, size, &offset, sub_type, &s); } template<> void RsTypeSerializer::print_data(const std::string& n, uint16_t sub_type,const uint32_t& V) { - std::cerr << " [TlvUInt32 ] " << n << ": type=" << std::hex < void RsTypeSerializer::print_data(const std::string& n, const std::string& V) +template<> /*static*/ +bool RsTypeSerializer::to_JSON( const std::string& memberName, + uint16_t /*sub_type*/, + const uint32_t& member, RsJson& jDoc ) { - std::cerr << " [std::string] " << n << ": " << V << std::endl; + return to_JSON(memberName, member, jDoc); } -//=================================================================================================// -// Binary blocks // -//=================================================================================================// +template<> /*static*/ +bool RsTypeSerializer::from_JSON( const std::string& memberName, + uint16_t /*sub_type*/, + uint32_t& member, RsJson& jDoc ) +{ + return from_JSON(memberName, member, jDoc); +} + + +//============================================================================// +// TlvItems // +//============================================================================// + +template<> uint32_t RsTypeSerializer::serial_size(const RsTlvItem& s) +{ + return s.TlvSize(); +} + +template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, + uint32_t &offset,const RsTlvItem& s) +{ + return s.SetTlv(data,size,&offset); +} + +template<> bool RsTypeSerializer::deserialize(const uint8_t data[], + uint32_t size,uint32_t& offset, + RsTlvItem& s) +{ + return s.GetTlv((void*)data,size,&offset) ; +} + +template<> void RsTypeSerializer::print_data( const std::string& n, + const RsTlvItem& s ) +{ + std::cerr << " [" << typeid(s).name() << "] " << n << std::endl; +} + +template<> /*static*/ +bool RsTypeSerializer::to_JSON( const std::string& memberName, + const RsTlvItem& member, RsJson& jDoc ) +{ + rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); + + rapidjson::Value key; + key.SetString(memberName.c_str(), memberName.length(), allocator); + + rapidjson::Value value; + const char* tName = typeid(member).name(); + value.SetString(tName, allocator); + + jDoc.AddMember(key, value, allocator); + + return true; +} + +template<> /*static*/ +bool RsTypeSerializer::from_JSON( const std::string& /*memberName*/, + RsTlvItem& member, RsJson& /*jDoc*/) +{ + member.TlvClear(); + return true; +} + + +//============================================================================// +// Binary blocks // +//============================================================================// template<> uint32_t RsTypeSerializer::serial_size(const RsTypeSerializer::TlvMemBlock_proxy& r) { return 4 + r.second ; } @@ -286,82 +586,40 @@ template<> void RsTypeSerializer::print_data(const std::string& n, const RsTypeS 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; } -//=================================================================================================// -// TlvItems // -//=================================================================================================// - -template<> uint32_t RsTypeSerializer::serial_size(const RsTlvItem& s) +template<> /*static*/ +bool RsTypeSerializer::to_JSON( + const std::string& memberName, + const RsTypeSerializer::TlvMemBlock_proxy& member, RsJson& jDoc ) { - return s.TlvSize() ; -} + rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); -template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset,const RsTlvItem& s) -{ - return s.SetTlv(data,size,&offset) ; -} + rapidjson::Value key; + key.SetString(memberName.c_str(), memberName.length(), allocator); -template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size,uint32_t& offset,RsTlvItem& s) -{ - return s.GetTlv((void*)data,size,&offset) ; -} + rapidjson::Value value; + const char* tName = typeid(member).name(); + value.SetString(tName, allocator); -template<> void RsTypeSerializer::print_data(const std::string& n, const RsTlvItem& s) -{ - // can we call TlvPrint inside this? + jDoc.AddMember(key, value, allocator); - std::cerr << " [" << typeid(s).name() << "] " << n << std::endl; -} - -//============================================================================// -// RsItem and derivated // -//============================================================================// - -template<> uint32_t RsTypeSerializer::serial_size(const RsItem& s) -{ - RsGenericSerializer::SerializeContext ctx( - NULL, 0, RsGenericSerializer::FORMAT_BINARY, - RsGenericSerializer::SERIALIZATION_FLAG_NONE ); - - ctx.mOffset = 8; // header size - const_cast(s).serial_process(RsGenericSerializer::SIZE_ESTIMATE, - ctx); - - return ctx.mOffset; -} - -template<> bool RsTypeSerializer::serialize( uint8_t data[], uint32_t size, - uint32_t &offset, const RsItem& s ) -{ - RsGenericSerializer::SerializeContext ctx( - data, size, RsGenericSerializer::FORMAT_BINARY, - RsGenericSerializer::SERIALIZATION_FLAG_NONE ); - ctx.mOffset = offset; - const_cast(s).serial_process(RsGenericSerializer::SERIALIZE, - ctx); return true; } -template<> bool RsTypeSerializer::deserialize( const uint8_t data[], - uint32_t size, uint32_t& offset, - RsItem& s ) -{ - RsGenericSerializer::SerializeContext ctx( - const_cast(data), size, - RsGenericSerializer::FORMAT_BINARY, - RsGenericSerializer::SERIALIZATION_FLAG_NONE ); - ctx.mOffset = offset; - const_cast(s).serial_process(RsGenericSerializer::DESERIALIZE, - ctx); - return true; -} +template<> /*static*/ +bool RsTypeSerializer::from_JSON( const std::string& /*memberName*/, + RsTypeSerializer::TlvMemBlock_proxy&, + RsJson& /*jDoc*/) +{ return true; } -template<> void RsTypeSerializer::print_data( const std::string& /*n*/, - const RsItem& s ) + +//============================================================================// +// RsJson std:ostream support // +//============================================================================// + +std::ostream &operator<<(std::ostream &out, const RsJson &jDoc) { - RsGenericSerializer::SerializeContext ctx( - NULL, 0, - RsGenericSerializer::FORMAT_BINARY, - RsGenericSerializer::SERIALIZATION_FLAG_NONE ); - const_cast(s).serial_process(RsGenericSerializer::PRINT, - ctx); + rapidjson::StringBuffer buffer; buffer.Clear(); + rapidjson::PrettyWriter writer(buffer); + jDoc.Accept(writer); + return out << buffer.GetString(); } diff --git a/src/serialiser/rstypeserializer.h b/src/serialiser/rstypeserializer.h index f4867f10f..f08a43239 100644 --- a/src/serialiser/rstypeserializer.h +++ b/src/serialiser/rstypeserializer.h @@ -3,7 +3,8 @@ * * RetroShare Serialiser. * - * Copyright 2017 by Cyril Soler + * Copyright (C) 2017 Cyril Soler + * Copyright (C) 2018 Gioacchino Mazzurco * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -32,83 +33,95 @@ #include "retroshare/rsids.h" #include "serialiser/rsserializer.h" +#include "serialiser/rsserializable.h" -/** @def RS_REGISTER_SERIAL_MEMBER(I) - * Use this macro to register the members of `YourItem` for serial processing - * inside `YourItem::serial_process(j, ctx)` - * - * Inspired by http://stackoverflow.com/a/39345864 +#include +#include // for typeid +#include +#include + + +/** INTERNAL ONLY helper to avoid copy paste code for std::{vector,list,set} + * Can't use a template function because T is needed for const_cast */ +#define RsTypeSerializer_PRIVATE_TO_JSON_ARRAY() do \ +{ \ + using namespace rapidjson; \ +\ + Document::AllocatorType& allocator = ctx.mJson.GetAllocator(); \ +\ + Value arrKey; arrKey.SetString(memberName.c_str(), allocator); \ +\ + Value arr(kArrayType); \ +\ + for (auto& el : v) \ + { \ + /* Use same allocator to avoid deep copy */\ + RsGenericSerializer::SerializeContext elCtx(\ + nullptr, 0, RsGenericSerializer::FORMAT_BINARY,\ + RsGenericSerializer::SERIALIZATION_FLAG_NONE,\ + &allocator );\ +\ + /* If el is const the default serial_process template is matched */ \ + /* also when specialization is necessary so the compilation break */ \ + serial_process(j, elCtx, const_cast(el), memberName); \ +\ + elCtx.mOk = elCtx.mOk && elCtx.mJson.HasMember(arrKey);\ + if(elCtx.mOk) arr.PushBack(elCtx.mJson[arrKey], allocator);\ + else\ + {\ + ctx.mOk = false;\ + break;\ + }\ + }\ +\ + ctx.mJson.AddMember(arrKey, arr, allocator);\ +} while (false) + +/** INTERNAL ONLY helper to avoid copy paste code for std::{vector,list,set} + * Can't use a template function because std::{vector,list,set} has different + * name for insert/push_back function */ -#define RS_REGISTER_SERIAL_MEMBER(I) \ - do { RsTypeSerializer::serial_process(j, ctx, I, #I); } while(0) +#define RsTypeSerializer_PRIVATE_FROM_JSON_ARRAY(INSERT_FUN) do\ +{\ + using namespace rapidjson;\ +\ + bool& ok(ctx.mOk);\ + Document& jDoc(ctx.mJson);\ + Document::AllocatorType& allocator = jDoc.GetAllocator();\ +\ + Value arrKey;\ + arrKey.SetString(memberName.c_str(), memberName.length());\ +\ + ok = ok && jDoc.IsObject();\ + ok = ok && jDoc.HasMember(arrKey);\ +\ + if(ok && jDoc[arrKey].IsArray())\ + {\ + for (auto&& arrEl : jDoc[arrKey].GetArray())\ + {\ + RsGenericSerializer::SerializeContext elCtx(\ + nullptr, 0, RsGenericSerializer::FORMAT_BINARY,\ + RsGenericSerializer::SERIALIZATION_FLAG_NONE,\ + &allocator );\ + elCtx.mJson.AddMember(arrKey, arrEl, allocator);\ +\ + T el;\ + serial_process(j, elCtx, el, memberName); \ + ok = ok && elCtx.mOk;\ +\ + if(ok) v.INSERT_FUN(el);\ + else break;\ + }\ + }\ +} while(false) -/** @def RS_REGISTER_SERIAL_MEMBER_TYPED(I, T) - * This macro usage is similar to @see RS_REGISTER_SERIAL_MEMBER(I) but it - * permit to force serialization/deserialization type, it is expecially useful - * with enum class members or RsTlvItem derivative members, be very careful with - * the type you pass, as reinterpret_cast on a reference is used that is - * expecially permissive so you can shot your feet if not carefull enough. - * - * If you are using this with an RsItem derivative (so passing RsItem as T) - * consider to register your item type with @see RS_REGISTER_ITEM_TYPE(T) in - * association with @see RS_REGISTER_SERIAL_MEMBER(I) that rely on template - * function generation, as in this particular case - * RS_REGISTER_SERIAL_MEMBER_TYPED(I, T) would cause the serial code rely on - * C++ dynamic dispatching that may have a noticeable impact on runtime - * performances. - */ -#pragma GCC diagnostic ignored "-Wstrict-aliasing" -#define RS_REGISTER_SERIAL_MEMBER_TYPED(I, T) do {\ - RsTypeSerializer::serial_process(j, ctx, reinterpret_cast(I), #I);\ - } while(0) -#pragma GCC diagnostic pop - -/** @def RS_REGISTER_ITEM_TYPE(T) - * Use this macro into `youritem.cc` only if you need to process members of - * subtypes of RsItem. - * - * The usage of this macro is strictly needed only in some cases, for example if - * you are registering for serialization a member of a container that contains - * items of subclasses of RsItem like * `std::map` - * - * @code{.cpp} -struct PrivateOugoingMapItem : RsChatItem -{ - PrivateOugoingMapItem() : RsChatItem(RS_PKT_SUBTYPE_OUTGOING_MAP) {} - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ); - - std::map store; -}; - -RS_REGISTER_ITEM_TYPE(RsChatMsgItem) - -void PrivateOugoingMapItem::serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - // store is of type - RS_REGISTER_SERIAL_MEMBER(store); -} - * @endcode - * - * If you use this macro with a lot of different item types this can cause the - * generated binary grow in size, consider the usage of - * @see RS_REGISTER_SERIAL_MEMBER_TYPED(I, T) passing RsItem as type in that - * case. - */ -#define RS_REGISTER_ITEM_TYPE(T) template<> \ - void RsTypeSerializer::serial_process( \ - RsGenericSerializer::SerializeJob j,\ - RsGenericSerializer::SerializeContext& ctx, T& item,\ - const std::string& /*name*/) { item.serial_process(j, ctx); } +std::ostream &operator<<(std::ostream &out, const RsJson &jDoc); struct RsTypeSerializer { /** This type should be used to pass a parameter to drive the serialisation * if needed */ - struct TlvMemBlock_proxy: public std::pair + struct TlvMemBlock_proxy : std::pair { TlvMemBlock_proxy(void*& p, uint32_t& s) : std::pair(p,s) {} @@ -118,9 +131,10 @@ struct RsTypeSerializer /// Generic types template - static void serial_process( RsGenericSerializer::SerializeJob j, + typename std::enable_if::value || !(std::is_base_of::value || std::is_enum::value || std::is_base_of::value)>::type + static /*void*/ serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx, - T& member,const std::string& member_name) + T& member, const std::string& member_name) { switch(j) { @@ -138,9 +152,17 @@ struct RsTypeSerializer case RsGenericSerializer::PRINT: print_data(member_name,member); break; + case RsGenericSerializer::TO_JSON: + ctx.mOk = ctx.mOk && to_JSON(member_name, member, ctx.mJson); + break; + case RsGenericSerializer::FROM_JSON: + ctx.mOk = ctx.mOk && from_JSON(member_name, member, ctx.mJson); + break; default: - ctx.mOk = false; - throw std::runtime_error("Unknown serial job"); + std::cerr << __PRETTY_FUNCTION__ << " Unknown serial job: " + << static_cast::type>(j) + << std::endl; + exit(EINVAL); } } @@ -165,11 +187,21 @@ struct RsTypeSerializer serialize(ctx.mData,ctx.mSize,ctx.mOffset,type_id,member); break; case RsGenericSerializer::PRINT: - print_data(member_name,type_id,member); + print_data(member_name, member); + break; + case RsGenericSerializer::TO_JSON: + ctx.mOk = ctx.mOk && + to_JSON(member_name, type_id, member, ctx.mJson); + break; + case RsGenericSerializer::FROM_JSON: + ctx.mOk = ctx.mOk && + from_JSON(member_name, type_id, member, ctx.mJson); break; default: - ctx.mOk = false; - throw std::runtime_error("Unknown serial job"); + std::cerr << __PRETTY_FUNCTION__ << " Unknown serial job: " + << static_cast::type>(j) + << std::endl; + exit(EINVAL); } } @@ -178,7 +210,7 @@ struct RsTypeSerializer static void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx, std::map& v, - const std::string& member_name ) + const std::string& memberName ) { switch(j) { @@ -225,11 +257,11 @@ struct RsTypeSerializer case RsGenericSerializer::PRINT: { if(v.empty()) - std::cerr << " Empty map \"" << member_name << "\"" + std::cerr << " Empty map \"" << memberName << "\"" << std::endl; else std::cerr << " std::map of " << v.size() << " elements: \"" - << member_name << "\"" << std::endl; + << memberName << "\"" << std::endl; for(typename std::map::iterator it(v.begin());it!=v.end();++it) { @@ -242,6 +274,95 @@ struct RsTypeSerializer } break; } + case RsGenericSerializer::TO_JSON: + { + using namespace rapidjson; + + Document::AllocatorType& allocator = ctx.mJson.GetAllocator(); + Value arrKey; arrKey.SetString(memberName.c_str(), + memberName.length(), allocator); + Value arr(kArrayType); + + for (auto& kv : v) + { + // Use same allocator to avoid deep copy + RsGenericSerializer::SerializeContext kCtx( + nullptr, 0, RsGenericSerializer::FORMAT_BINARY, + RsGenericSerializer::SERIALIZATION_FLAG_NONE, + &allocator ); + serial_process(j, kCtx, const_cast(kv.first), "key"); + + RsGenericSerializer::SerializeContext vCtx( + nullptr, 0, RsGenericSerializer::FORMAT_BINARY, + RsGenericSerializer::SERIALIZATION_FLAG_NONE, + &allocator ); + serial_process(j, vCtx, const_cast(kv.second), "value"); + + if(kCtx.mOk && vCtx.mOk) + { + Value el(kObjectType); + el.AddMember("key", kCtx.mJson["key"], allocator); + el.AddMember("value", vCtx.mJson["value"], allocator); + + arr.PushBack(el, allocator); + } + } + + ctx.mJson.AddMember(arrKey, arr, allocator); + + break; + } + case RsGenericSerializer::FROM_JSON: + { + using namespace rapidjson; + + bool& ok(ctx.mOk); + Document& jDoc(ctx.mJson); + Document::AllocatorType& allocator = jDoc.GetAllocator(); + + Value arrKey; + arrKey.SetString(memberName.c_str(), memberName.length()); + + ok = ok && jDoc.IsObject(); + ok = ok && jDoc.HasMember(arrKey); + + if(ok && jDoc[arrKey].IsArray()) + { + for (auto&& kvEl : jDoc[arrKey].GetArray()) + { + ok = ok && kvEl.IsObject(); + ok = ok && kvEl.HasMember("key"); + ok = ok && kvEl.HasMember("value"); + if (!ok) break; + + RsGenericSerializer::SerializeContext kCtx( + nullptr, 0, RsGenericSerializer::FORMAT_BINARY, + RsGenericSerializer::SERIALIZATION_FLAG_NONE, + &allocator ); + if(ok) + kCtx.mJson.AddMember("key", kvEl["key"], allocator); + + T key; + ok = ok && (serial_process(j, kCtx, key, "key"), kCtx.mOk); + + RsGenericSerializer::SerializeContext vCtx( + nullptr, 0, RsGenericSerializer::FORMAT_BINARY, + RsGenericSerializer::SERIALIZATION_FLAG_NONE, + &allocator ); + if(ok) + vCtx.mJson.AddMember("value", kvEl["value"], allocator); + + U value; + ok = ok && ( serial_process(j, vCtx, value, "value"), + vCtx.mOk ); + + if(ok) v.insert(std::pair(key,value)); + else break; + } + } + + break; + } default: break; } } @@ -251,7 +372,7 @@ struct RsTypeSerializer static void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx, std::vector& v, - const std::string& member_name ) + const std::string& memberName ) { switch(j) { @@ -259,7 +380,7 @@ struct RsTypeSerializer { ctx.mOffset += 4; for(uint32_t i=0;i static void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx, - std::set& v, const std::string& member_name ) + std::set& v, const std::string& memberName ) { switch(j) { @@ -311,7 +438,7 @@ struct RsTypeSerializer for(typename std::set::iterator it(v.begin());it!=v.end();++it) // the const cast here is a hack to avoid serial_process to // instantiate serialise(const T&) - serial_process(j,ctx,const_cast(*it) ,member_name); + serial_process(j,ctx,const_cast(*it) ,memberName); break; } case RsGenericSerializer::DESERIALIZE: @@ -321,7 +448,7 @@ struct RsTypeSerializer for(uint32_t i=0; i(j,ctx,tmp,member_name); + serial_process(j,ctx,tmp,memberName); v.insert(tmp); } break; @@ -333,7 +460,7 @@ struct RsTypeSerializer for(typename std::set::iterator it(v.begin());it!=v.end();++it) // the const cast here is a hack to avoid serial_process to // instantiate serialise(const T&) - serial_process(j,ctx,const_cast(*it) ,member_name); + serial_process(j,ctx,const_cast(*it) ,memberName); break; } case RsGenericSerializer::PRINT: @@ -343,6 +470,12 @@ struct RsTypeSerializer << std::endl; break; } + case RsGenericSerializer::TO_JSON: + RsTypeSerializer_PRIVATE_TO_JSON_ARRAY(); + break; + case RsGenericSerializer::FROM_JSON: + RsTypeSerializer_PRIVATE_FROM_JSON_ARRAY(insert); + break; default: break; } } @@ -352,7 +485,7 @@ struct RsTypeSerializer static void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx, std::list& v, - const std::string& member_name ) + const std::string& memberName ) { switch(j) { @@ -360,7 +493,7 @@ struct RsTypeSerializer { ctx.mOffset += 4; for(typename std::list::iterator it(v.begin());it!=v.end();++it) - serial_process(j,ctx,*it ,member_name); + serial_process(j,ctx,*it ,memberName); break; } case RsGenericSerializer::DESERIALIZE: @@ -370,7 +503,7 @@ struct RsTypeSerializer for(uint32_t i=0;i(j,ctx,tmp,member_name); + serial_process(j,ctx,tmp,memberName); v.push_back(tmp); } break; @@ -380,7 +513,7 @@ struct RsTypeSerializer uint32_t n=v.size(); serial_process(j,ctx,n,"temporary size"); for(typename std::list::iterator it(v.begin());it!=v.end();++it) - serial_process(j,ctx,*it ,member_name); + serial_process(j,ctx,*it ,memberName); break; } case RsGenericSerializer::PRINT: @@ -390,6 +523,12 @@ struct RsTypeSerializer << std::endl; break; } + case RsGenericSerializer::TO_JSON: + RsTypeSerializer_PRIVATE_TO_JSON_ARRAY(); + break; + case RsGenericSerializer::FROM_JSON: + RsTypeSerializer_PRIVATE_FROM_JSON_ARRAY(push_back); + break; default: break; } } @@ -399,7 +538,7 @@ struct RsTypeSerializer static void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx, t_RsFlags32& v, - const std::string& /*member_name*/) + const std::string& memberName ) { switch(j) { @@ -421,16 +560,139 @@ struct RsTypeSerializer std::cerr << " Flags of type " << std::hex << N << " : " << v.toUInt32() << std::endl; break; + case RsGenericSerializer::TO_JSON: + ctx.mOk = to_JSON(memberName, v.toUInt32(), ctx.mJson); + break; + case RsGenericSerializer::FROM_JSON: + { + uint32_t f; + ctx.mOk = from_JSON(memberName, f, ctx.mJson); + v = t_RsFlags32(f); + break; + } + default: break; } } -/** TODO - * Serialization format is inside context, but context is not passed to - * following functions, that need to know the format to do the job, actually - * RsGenericSerializer::FORMAT_BINARY is assumed in all of them!! - */ + /** + * @brief serial process enum types + * + * On declaration of your member of enum type you must specify the + * underlying type otherwise the serialization format may differ in an + * uncompatible way depending on the compiler/platform. + */ + template + typename std::enable_if::value>::type + static /*void*/ serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx, + E& member, + const std::string& memberName ) + { +#ifdef RSSERIAL_DEBUG + std::cerr << __PRETTY_FUNCTION__ << " processing enum: " + << typeid(E).name() << " as " + << typeid(typename std::underlying_type::type).name() + << std::endl; +#endif + serial_process( + j, ctx, + reinterpret_cast::type&>(member), + memberName ); + } + + /// RsSerializable and derivatives + template + typename std::enable_if::value>::type + static /*void*/ serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx, + T& member, + const std::string& memberName ) + { + switch(j) + { + case RsGenericSerializer::SIZE_ESTIMATE: // fallthrough + case RsGenericSerializer::DESERIALIZE: // fallthrough + case RsGenericSerializer::SERIALIZE: // fallthrough + case RsGenericSerializer::PRINT: + member.serial_process(j, ctx); + break; + case RsGenericSerializer::TO_JSON: + { + rapidjson::Document& jDoc(ctx.mJson); + rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); + + // Reuse allocator to avoid deep copy later + RsGenericSerializer::SerializeContext lCtx( + nullptr, 0, RsGenericSerializer::FORMAT_BINARY, + RsGenericSerializer::SERIALIZATION_FLAG_NONE, + &allocator ); + + member.serial_process(j, lCtx); + + rapidjson::Value key; + key.SetString(memberName.c_str(), memberName.length(), allocator); + + /* Because the passed allocator is reused it doesn't go out of scope and + * there is no need of deep copy and we can take advantage of the much + * faster rapidjson move semantic */ + jDoc.AddMember(key, lCtx.mJson, allocator); + + ctx.mOk = ctx.mOk && lCtx.mOk; + break; + } + case RsGenericSerializer::FROM_JSON: + { + rapidjson::Document& jDoc(ctx.mJson); + const char* mName = memberName.c_str(); + ctx.mOk = ctx.mOk && jDoc.HasMember(mName); + + if(!ctx.mOk) + { + std::cerr << __PRETTY_FUNCTION__ << " \"" << memberName + << "\" not found in JSON:" << std::endl + << jDoc << std::endl << std::endl; + print_stacktrace(); + break; + } + + rapidjson::Value& v = jDoc[mName]; + + RsGenericSerializer::SerializeContext lCtx( + nullptr, 0, RsGenericSerializer::FORMAT_BINARY, + RsGenericSerializer::SERIALIZATION_FLAG_NONE ); + lCtx.mJson.SetObject() = v; // Beware of move semantic!! + + member.serial_process(j, lCtx); + ctx.mOk = ctx.mOk && lCtx.mOk; + + break; + } + default: + std::cerr << __PRETTY_FUNCTION__ << " Unknown serial job: " + << static_cast::type>(j) + << std::endl; + exit(EINVAL); + break; + } + } + + /// RsTlvItem derivatives only + template + typename std::enable_if::value && !std::is_same::value>::type + static /*void*/ serial_process( RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx, + T& member, + const std::string& memberName ) + { + serial_process(j, ctx, static_cast(member), memberName); + } protected: + +//============================================================================// +// Generic types declarations // +//============================================================================// + template static bool serialize( uint8_t data[], uint32_t size, uint32_t &offset, const T& member ); @@ -442,17 +704,41 @@ protected: template static void print_data( const std::string& name, const T& member); + template static bool to_JSON( const std::string& membername, + const T& member, RsJson& jDoc ); + + template static bool from_JSON( const std::string& memberName, + T& member, RsJson& jDoc ); + +//============================================================================// +// Generic types + type_id declarations // +//============================================================================// template static bool serialize( uint8_t data[], uint32_t size, uint32_t &offset, uint16_t type_id, const T& member ); + template static bool deserialize( const uint8_t data[], uint32_t size, uint32_t &offset, uint16_t type_id, T& member ); + template static uint32_t serial_size( uint16_t type_id,const T& member ); - template static void print_data( - const std::string& name,uint16_t type_id,const T& member ); + + template static void print_data( const std::string& n, + uint16_t type_id,const T& member ); + + template static bool to_JSON( const std::string& membername, + uint16_t type_id, + const T& member, RsJson& jVal ); + + template static bool from_JSON( const std::string& memberName, + uint16_t type_id, + T& member, RsJson& jDoc ); + +//============================================================================// +// t_RsGenericId<...> declarations // +//============================================================================// template static bool serialize( @@ -466,13 +752,29 @@ protected: template static uint32_t serial_size( - const t_RsGenericIdType& member ); + const t_RsGenericIdType< + ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member ); template static void print_data( const std::string& name, const t_RsGenericIdType& member ); + template + static bool to_JSON( + const std::string& membername, + const t_RsGenericIdType& member, + RsJson& jVal ); + + template + static bool from_JSON( + const std::string& memberName, + t_RsGenericIdType& member, + RsJson& jDoc ); + +//============================================================================// +// t_RsTlvList<...> declarations // +//============================================================================// template static bool serialize( @@ -491,16 +793,33 @@ protected: static void print_data( const std::string& name, const t_RsTlvList& member); + + template + static bool to_JSON( const std::string& membername, + const t_RsTlvList& member, + RsJson& jVal ); + + template + static bool from_JSON( const std::string& memberName, + t_RsTlvList& member, + RsJson& jDoc ); }; +//============================================================================// +// t_RsGenericId<...> // +//============================================================================// -// t_RsGenericId<> template bool RsTypeSerializer::serialize ( uint8_t data[], uint32_t size, uint32_t &offset, - const t_RsGenericIdType& member ) -{ return (*const_cast *>(&member)).serialise(data,size,offset); } + const t_RsGenericIdType< + ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& member ) +{ + return (*const_cast *>(&member) + ).serialise(data,size,offset); +} template bool RsTypeSerializer::deserialize( @@ -522,8 +841,45 @@ void RsTypeSerializer::print_data( << member << std::endl; } +template +bool RsTypeSerializer::to_JSON( const std::string& memberName, + const t_RsGenericIdType& member, + RsJson& jDoc ) +{ + rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); + + rapidjson::Value key; + key.SetString(memberName.c_str(), memberName.length(), allocator); + + const std::string vStr = member.toStdString(); + rapidjson::Value value; + value.SetString(vStr.c_str(), vStr.length(), allocator); + + jDoc.AddMember(key, value, allocator); + + return true; +} + +template +bool RsTypeSerializer::from_JSON( const std::string& membername, + t_RsGenericIdType& member, + RsJson& jVal ) +{ + const char* mName = membername.c_str(); + bool ret = jVal.HasMember(mName); + if(ret) + { + rapidjson::Value& v = jVal[mName]; + ret = ret && v.IsString(); + if(ret) member = t_RsGenericIdType(std::string(v.GetString())); + } + return ret; +} + +//============================================================================// +// t_RsTlvList<...> // +//============================================================================// -// t_RsTlvList<> template bool RsTypeSerializer::serialize( uint8_t data[], uint32_t size, uint32_t &offset, @@ -553,3 +909,86 @@ void RsTypeSerializer::print_data( std::cerr << " [t_RsTlvString<" << std::hex << TLV_TYPE << ">] : size=" << member.mList.size() << std::endl; } + +template /* static */ +bool RsTypeSerializer::to_JSON( const std::string& memberName, + const t_RsTlvList& member, + RsJson& jDoc ) +{ + rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); + + rapidjson::Value key; + key.SetString(memberName.c_str(), memberName.length(), allocator); + + rapidjson::Value value; + const char* tName = typeid(member).name(); + value.SetString(tName, allocator); + + jDoc.AddMember(key, value, allocator); + + std::cerr << __PRETTY_FUNCTION__ << " JSON serialization for type " + << typeid(member).name() << " " << memberName + << " not available." << std::endl; + print_stacktrace(); + return true; +} + +template +bool RsTypeSerializer::from_JSON( const std::string& memberName, + t_RsTlvList& member, + RsJson& /*jVal*/ ) +{ + std::cerr << __PRETTY_FUNCTION__ << " JSON deserialization for type " + << typeid(member).name() << " " << memberName + << " not available." << std::endl; + print_stacktrace(); + return true; +} + + +//============================================================================// +// Not implemented types macros // +//============================================================================// + +/** + * @def RS_TYPE_SERIALIZER_TO_JSON_NOT_IMPLEMENTED_DEF(T) + * @def RS_TYPE_SERIALIZER_FROM_JSON_NOT_IMPLEMENTED_DEF(T) + * Helper macros for types that has not yet implemented to/from JSON + * should be deleted from the code as soon as they are not needed anymore + */ +#define RS_TYPE_SERIALIZER_TO_JSON_NOT_IMPLEMENTED_DEF(T) \ +template<> /*static*/ \ +bool RsTypeSerializer::to_JSON(const std::string& memberName, T const& member, \ + RsJson& jDoc ) \ +{ \ + rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); \ + \ + rapidjson::Value key; \ + key.SetString(memberName.c_str(), memberName.length(), allocator); \ + \ + rapidjson::Value value; \ + const char* tName = typeid(member).name(); \ + value.SetString(tName, allocator); \ + \ + jDoc.AddMember(key, value, allocator); \ + \ + std::cerr << __FILE__ << __LINE__ << __PRETTY_FUNCTION__ \ + << " JSON serialization for type " \ + << typeid(member).name() << " " << memberName \ + << " not available." << std::endl; \ + print_stacktrace(); \ + return true; \ +} + +#define RS_TYPE_SERIALIZER_FROM_JSON_NOT_IMPLEMENTED_DEF(T) \ +template<> /*static*/ \ +bool RsTypeSerializer::from_JSON( const std::string& memberName, \ + T& member, RsJson& /*jDoc*/ ) \ +{ \ + std::cerr << __FILE__ << __LINE__ << __PRETTY_FUNCTION__ \ + << " JSON deserialization for type " \ + << typeid(member).name() << " " << memberName \ + << " not available." << std::endl; \ + print_stacktrace(); \ + return true; \ +} diff --git a/src/services/p3idservice.cc b/src/services/p3idservice.cc index 71b0e2274..5ea8f898e 100644 --- a/src/services/p3idservice.cc +++ b/src/services/p3idservice.cc @@ -3,7 +3,8 @@ * * Id interface for RetroShare. * - * Copyright 2012-2012 by Robert Fernie. + * Copyright (C) 2012 Robert Fernie + * Copyright (C) 2018 Gioacchino Mazzurco * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -4505,11 +4506,30 @@ void p3IdService::handle_event(uint32_t event_type, const std::string &/*elabel* } } -RsIdentityUsage::RsIdentityUsage(uint16_t service,const RsIdentityUsage::UsageCode& code,const RsGxsGroupId& gid,const RsGxsMessageId& mid,uint64_t additional_id,const std::string& comment) - : mServiceId(service), mUsageCode(code), mGrpId(gid), mMsgId(mid),mAdditionalId(additional_id),mComment(comment) +void RsGxsIdGroup::serial_process( + RsGenericSerializer::SerializeJob j, + RsGenericSerializer::SerializeContext& ctx ) +{ + RS_SERIAL_PROCESS(mMeta); + RS_SERIAL_PROCESS(mPgpIdHash); + //RS_SERIAL_PROCESS(mPgpIdSign); + RS_SERIAL_PROCESS(mRecognTags); + //RS_SERIAL_PROCESS(mImage); + RS_SERIAL_PROCESS(mLastUsageTS); + RS_SERIAL_PROCESS(mPgpKnown); + RS_SERIAL_PROCESS(mIsAContact); + RS_SERIAL_PROCESS(mPgpId); + RS_SERIAL_PROCESS(mReputation); +} + +RsIdentityUsage::RsIdentityUsage( + uint16_t service, const RsIdentityUsage::UsageCode& code, + const RsGxsGroupId& gid, const RsGxsMessageId& mid, + uint64_t additional_id,const std::string& comment ) : + mServiceId(service), mUsageCode(code), mGrpId(gid), mMsgId(mid), + mAdditionalId(additional_id), mComment(comment) { #ifdef DEBUG_IDS - // This is a hack, since it will hash also mHash, but because it is initialized to 0, and only computed in the constructor here, it should be ok. std::cerr << "New identity usage: " << std::endl; std::cerr << " service=" << std::hex << service << std::endl; std::cerr << " code =" << std::hex << code << std::endl; @@ -4519,6 +4539,9 @@ RsIdentityUsage::RsIdentityUsage(uint16_t service,const RsIdentityUsage::UsageCo std::cerr << " commnt =\"" << std::hex << comment << "\"" << std::endl; #endif + /* This is a hack, since it will hash also mHash, but because it is + * initialized to 0, and only computed in the constructor here, it should + * be ok. */ librs::crypto::HashStream hs(librs::crypto::HashStream::SHA1) ; hs << (uint32_t)service ; @@ -4535,5 +4558,5 @@ RsIdentityUsage::RsIdentityUsage(uint16_t service,const RsIdentityUsage::UsageCo #endif } - - +RsIdentityUsage::RsIdentityUsage() : + mServiceId(0), mUsageCode(UNKNOWN_USAGE), mAdditionalId(0) {} diff --git a/src/turtle/rsturtleitem.cc b/src/turtle/rsturtleitem.cc index 35b250117..cf206a153 100644 --- a/src/turtle/rsturtleitem.cc +++ b/src/turtle/rsturtleitem.cc @@ -140,6 +140,9 @@ template<> void RsTypeSerializer::print_data(const std::string& n, const RsRegul std::cerr << " [RegExpr ] " << n << ", tokens=" << expr._tokens.size() << " ints=" << expr._ints.size() << " strings=" << expr._strings.size() << std::endl; } +RS_TYPE_SERIALIZER_TO_JSON_NOT_IMPLEMENTED_DEF(RsRegularExpression::LinearizedExpression) +RS_TYPE_SERIALIZER_FROM_JSON_NOT_IMPLEMENTED_DEF(RsRegularExpression::LinearizedExpression) + void RsTurtleSearchResultItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) { RsTypeSerializer::serial_process(j,ctx,request_id,"request_id") ; @@ -193,6 +196,9 @@ template<> void RsTypeSerializer::print_data(const std::string& n, const TurtleF std::cerr << " [FileInfo ] " << n << " size=" << i.size << " hash=" << i.hash << ", name=" << i.name << std::endl; } +RS_TYPE_SERIALIZER_TO_JSON_NOT_IMPLEMENTED_DEF(TurtleFileInfo) +RS_TYPE_SERIALIZER_FROM_JSON_NOT_IMPLEMENTED_DEF(TurtleFileInfo) + void RsTurtleOpenTunnelItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) { RsTypeSerializer::serial_process (j,ctx,file_hash ,"file_hash") ; diff --git a/src/turtle/turtleclientservice.h b/src/turtle/turtleclientservice.h index d9552c662..51a9dbdc3 100644 --- a/src/turtle/turtleclientservice.h +++ b/src/turtle/turtleclientservice.h @@ -36,7 +36,7 @@ #include #include -class RsItem ; +struct RsItem; class p3turtle ; class RsTurtleClientService diff --git a/tests/librssimulator/testing/IsolatedServiceTester.h b/tests/librssimulator/testing/IsolatedServiceTester.h index aca9695ed..3fa5e2afc 100644 --- a/tests/librssimulator/testing/IsolatedServiceTester.h +++ b/tests/librssimulator/testing/IsolatedServiceTester.h @@ -4,7 +4,7 @@ #include "retroshare/rsids.h" #include "pqi/p3linkmgr.h" -class RsItem; +struct RsItem; class PeerNode; class RsSerialType; class RsSerialiser; diff --git a/tests/librssimulator/testing/SetFilter.h b/tests/librssimulator/testing/SetFilter.h index 9b9a8b15d..50df26955 100644 --- a/tests/librssimulator/testing/SetFilter.h +++ b/tests/librssimulator/testing/SetFilter.h @@ -4,7 +4,7 @@ #include "retroshare/rsids.h" #include "SetPacket.h" -class RsItem; +struct RsItem; class SetFilter { diff --git a/tests/librssimulator/testing/SetPacket.h b/tests/librssimulator/testing/SetPacket.h index ae529f37b..1e377191e 100644 --- a/tests/librssimulator/testing/SetPacket.h +++ b/tests/librssimulator/testing/SetPacket.h @@ -5,7 +5,7 @@ #include #include "retroshare/rsids.h" -class RsItem; +struct RsItem; class SetPacket { diff --git a/tests/librssimulator/testing/SetServiceTester.h b/tests/librssimulator/testing/SetServiceTester.h index ad03aed4e..862fc43e0 100644 --- a/tests/librssimulator/testing/SetServiceTester.h +++ b/tests/librssimulator/testing/SetServiceTester.h @@ -8,7 +8,7 @@ #include "SetPacket.h" #include "SetFilter.h" -class RsItem; +struct RsItem; class PeerNode; class RsSerialType; class RsSerialiser;