diff --git a/libretroshare/src/retroshare/rsgxschannels.h b/libretroshare/src/retroshare/rsgxschannels.h index 15ca90ca5..69a672d09 100644 --- a/libretroshare/src/retroshare/rsgxschannels.h +++ b/libretroshare/src/retroshare/rsgxschannels.h @@ -48,10 +48,9 @@ class RsGxsChannelGroup public: RsGroupMetaData mMeta; std::string mDescription; + RsGxsImage mImage; - //RsGxsImage mChanImage; bool mAutoDownload; - }; class RsGxsChannelPost @@ -60,15 +59,14 @@ class RsGxsChannelPost RsMsgMetaData mMeta; std::string mMsg; // UTF8 encoded. - //std::list mFiles; + std::list mFiles; uint32_t mCount; // auto calced. uint64_t mSize; // auto calced. - //RsGxsImage mThumbnail; + + RsGxsImage mThumbnail; }; -//typedef std::map > GxsChannelMsgResult; - std::ostream &operator<<(std::ostream &out, const RsGxsChannelGroup &group); std::ostream &operator<<(std::ostream &out, const RsGxsChannelPost &post); @@ -95,6 +93,8 @@ virtual bool getRelatedPosts(const uint32_t &token, std::vector #include #include + #include "retroshare/rstokenservice.h" #include "retroshare/rsgxsifacehelper.h" +#include "retroshare/rsgxscommon.h" +/* The Main Interface Class - for information about your Posted */ class RsPosted; extern RsPosted *rsPosted; -/* The Main Interface Class - for information about your Peers */ - +class RsPostedPost; class RsPostedGroup { - public: - RsGroupMetaData mMeta; - std::string mDescription; - RsPostedGroup() { return; } + public: + RsPostedGroup() { return; } + + RsGroupMetaData mMeta; + std::string mDescription; }; + //#define RSPOSTED_MSGTYPE_POST 0x0001 //#define RSPOSTED_MSGTYPE_VOTE 0x0002 //#define RSPOSTED_MSGTYPE_COMMENT 0x0004 @@ -61,127 +64,99 @@ class RsPostedGroup #define RSPOSTED_VIEWMODE_HOT 3 #define RSPOSTED_VIEWMODE_COMMENTS 4 -class RsPostedPost; -class RsPostedComment; -class RsPostedVote; -class RsPostedPostRanking; - -typedef std::map > PostedPostResult; -typedef std::map > PostedCommentResult; -typedef std::map > PostedVoteResult; -typedef std::map > PostedRelatedCommentResult; -typedef std::pair GroupRank; -typedef std::map PostedRanking; std::ostream &operator<<(std::ostream &out, const RsPostedGroup &group); std::ostream &operator<<(std::ostream &out, const RsPostedPost &post); -std::ostream &operator<<(std::ostream &out, const RsPostedVote &vote); -std::ostream &operator<<(std::ostream &out, const RsPostedComment &comment); - -class RsPosted : public RsGxsIfaceHelper +class RsPosted : public RsGxsIfaceHelper, public RsGxsCommentService { - public: + public: - enum RankType {TopRankType, HotRankType, NewRankType }; + enum RankType {TopRankType, HotRankType, NewRankType }; - static const uint32_t FLAG_MSGTYPE_POST; - static const uint32_t FLAG_MSGTYPE_VOTE; - static const uint32_t FLAG_MSGTYPE_COMMENT; - static const uint32_t FLAG_MSGTYPE_MASK; + static const uint32_t FLAG_MSGTYPE_POST; + static const uint32_t FLAG_MSGTYPE_MASK; - - RsPosted(RsGxsIface* gxs) : RsGxsIfaceHelper(gxs) { return; } + RsPosted(RsGxsIface* gxs) : RsGxsIfaceHelper(gxs) { return; } virtual ~RsPosted() { return; } - /* Specific Service Data */ + /* Specific Service Data */ - virtual bool getGroup(const uint32_t &token, std::vector &group) = 0; - virtual bool getPost(const uint32_t &token, PostedPostResult &post) = 0; - virtual bool getComment(const uint32_t &token, PostedCommentResult &comment) = 0; - virtual bool getRelatedComment(const uint32_t& token, PostedRelatedCommentResult& comments) = 0; - virtual bool getPostRanking(const uint32_t& token, RsPostedPostRanking& ranking) = 0; +virtual bool getGroupData(const uint32_t &token, std::vector &groups) = 0; +virtual bool getPostData(const uint32_t &token, std::vector &posts) = 0; +virtual bool getRelatedPosts(const uint32_t &token, std::vector &posts) = 0; - virtual bool submitGroup(uint32_t &token, RsPostedGroup &group) = 0; - virtual bool submitPost(uint32_t &token, RsPostedPost &post) = 0; - virtual bool submitVote(uint32_t &token, RsPostedVote &vote) = 0; - virtual bool submitComment(uint32_t &token, RsPostedComment &comment) = 0; - virtual bool retrieveScores(const std::string& serviceString, uint32_t& upVotes, uint32_t& downVotes, uint32_t& nComments) const = 0; + // SPECIAL RANKING FNS. +virtual bool requestPostRankings(uint32_t &token, const RankType &rType, uint32_t count, uint32_t page_no, const RsGxsGroupId &groupId) = 0; - // Special Ranking Request. - /*! - * Makes request for posts of a topic - * @param token - * @param rType - * @param groupId - */ - virtual bool requestPostRankings(uint32_t &token, const RankType& rType, const RsGxsGroupId& groupId) = 0; +virtual bool getPostRanking(const uint32_t &token, std::vector &msgs) = 0; - /*! - * Makes request for ranking of comments for a post - * @param token - * @param rType type of ranking to collect - * @param msgId message id of post as groupid-messageid pair - */ - virtual bool requestCommentRankings(uint32_t &token, const RankType& rType, const RsGxsGrpMsgIdPair& msgId) = 0; + +//virtual bool getPostRanking(const uint32_t& token, std::vector &ranking) = 0; + + /* From RsGxsCommentService */ +//virtual bool getCommentData(const uint32_t &token, std::vector &comments) = 0; +//virtual bool getRelatedComments(const uint32_t &token, std::vector &comments) = 0; +//virtual bool createComment(uint32_t &token, RsGxsComment &comment) = 0; +//virtual bool createVote(uint32_t &token, RsGxsVote &vote) = 0; + + ////////////////////////////////////////////////////////////////////////////// +virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) = 0; + +virtual bool createGroup(uint32_t &token, RsPostedGroup &group) = 0; +virtual bool createPost(uint32_t &token, RsPostedPost &post) = 0; + + //virtual bool retrieveScores(const std::string& serviceString, uint32_t& upVotes, uint32_t& downVotes, uint32_t& nComments) const = 0; + + // Special Ranking Request. + /*! + * Makes request for posts of a topic + * @param token + * @param rType + * @param groupId + */ + //virtual bool requestPostRankings(uint32_t &token, const RankType& rType, const RsGxsGroupId& groupId) = 0; + + /*! + * Makes request for ranking of comments for a post + * @param token + * @param rType type of ranking to collect + * @param msgId message id of post as groupid-messageid pair + */ + //virtual bool requestCommentRankings(uint32_t &token, const RankType& rType, const RsGxsGrpMsgIdPair& msgId) = 0; }; + + class RsPostedPost { - public: - RsPostedPost() - { - mMeta.mMsgFlags = RsPosted::FLAG_MSGTYPE_POST; - mMeta.mServiceString = " 0 0 0"; - return; - } + public: + RsPostedPost() + { + mMeta.mMsgFlags = RsPosted::FLAG_MSGTYPE_POST; + mUpVotes = 0; + mDownVotes = 0; + mComments = 0; + return; + } - RsMsgMetaData mMeta; - std::string mLink; - std::string mNotes; + RsMsgMetaData mMeta; + std::string mLink; + std::string mNotes; + + // Calculated. + uint32_t mUpVotes; + uint32_t mDownVotes; + uint32_t mComments; + + // and Calculated Scores:??? + double mHotScore; + double mTopScore; + double mNewScore; }; -class RsGxsPostedVoteItem; -class RsPostedVote -{ -public: - - RsPostedVote(const RsGxsPostedVoteItem&); - RsPostedVote() - { - mMeta.mMsgFlags = RsPosted::FLAG_MSGTYPE_VOTE; - return; - } - uint8_t mDirection; - RsMsgMetaData mMeta; -}; - -class RsGxsPostedCommentItem; - -class RsPostedComment -{ - public: - RsPostedComment() - { - mMeta.mMsgFlags = RsPosted::FLAG_MSGTYPE_COMMENT; - return; - } - - RsPostedComment(const RsGxsPostedCommentItem& ); - std::string mComment; - RsMsgMetaData mMeta; -}; - -class RsPostedPostRanking -{ -public: - - RsGxsGroupId grpId; - PostedRanking ranking; - RsPosted::RankType rType; -}; -#endif // RSPOSTED_H +#endif // RETROSHARE_GXS_RSPOSTED_GUI_INTERFACE_H diff --git a/libretroshare/src/rsserver/rsinit.cc b/libretroshare/src/rsserver/rsinit.cc index 9b58e1d1e..3cb78e9c4 100644 --- a/libretroshare/src/rsserver/rsinit.cc +++ b/libretroshare/src/rsserver/rsinit.cc @@ -2370,11 +2370,11 @@ int RsServer::StartupRetroShare() RsGeneralDataService* posted_ds = new RsDataService(currGxsDir + "/", "posted_db", RS_SERVICE_GXSV1_TYPE_POSTED); -#ifndef GXS_DEV_TESTNET // NO RESET, OR DUMMYDATA for TESTNET +//#ifndef GXS_DEV_TESTNET // NO RESET, OR DUMMYDATA for TESTNET posted_ds->resetDataStore(); //TODO: remove, new service data per RS session, for testing -#endif +//#endif - mPosted = new p3Posted(posted_ds, NULL); + mPosted = new p3Posted(posted_ds, NULL, mGxsIdService); // create GXS photo service RsGxsNetService* posted_ns = new RsGxsNetService( diff --git a/libretroshare/src/serialiser/rsgxschannelitems.cc b/libretroshare/src/serialiser/rsgxschannelitems.cc index 2277162ad..478094209 100644 --- a/libretroshare/src/serialiser/rsgxschannelitems.cc +++ b/libretroshare/src/serialiser/rsgxschannelitems.cc @@ -122,7 +122,8 @@ RsItem* RsGxsChannelSerialiser::deserialise(void* data, uint32_t* size) void RsGxsChannelGroupItem::clear() { - mGroup.mDescription.clear(); + mDescription.clear(); + mImage.TlvClear(); } std::ostream& RsGxsChannelGroupItem::print(std::ostream& out, uint16_t indent) @@ -131,20 +132,61 @@ std::ostream& RsGxsChannelGroupItem::print(std::ostream& out, uint16_t indent) uint16_t int_Indent = indent + 2; printIndent(out, int_Indent); - out << "Description: " << mGroup.mDescription << std::endl; + out << "Description: " << mDescription << std::endl; + + out << "Image: " << std::endl; + mImage.print(out, int_Indent); printRsItemEnd(out ,"RsGxsChannelGroupItem", indent); return out; } + +bool RsGxsChannelGroupItem::fromChannelGroup(RsGxsChannelGroup &group, bool moveImage) +{ + clear(); + meta = group.mMeta; + mDescription = group.mDescription; + + if (moveImage) + { + mImage.binData.bin_data = group.mImage.mData; + mImage.binData.bin_len = group.mImage.mSize; + group.mImage.shallowClear(); + } + else + { + mImage.binData.setBinData(group.mImage.mData, group.mImage.mSize); + } + return true; +} + + + +bool RsGxsChannelGroupItem::toChannelGroup(RsGxsChannelGroup &group, bool moveImage) +{ + group.mMeta = meta; + group.mDescription = mDescription; + if (moveImage) + { + group.mImage.take((uint8_t *) mImage.binData.bin_data, mImage.binData.bin_len); + mImage.TlvShallowClear(); + } + else + { + group.mImage.copy((uint8_t *) mImage.binData.bin_data, mImage.binData.bin_len); + } + return true; +} + + uint32_t RsGxsChannelSerialiser::sizeGxsChannelGroupItem(RsGxsChannelGroupItem *item) { - - const RsGxsChannelGroup& group = item->mGroup; uint32_t s = 8; // header - s += GetTlvStringSize(group.mDescription); + s += GetTlvStringSize(item->mDescription); + s += item->mImage.TlvSize(); return s; } @@ -177,7 +219,8 @@ bool RsGxsChannelSerialiser::serialiseGxsChannelGroupItem(RsGxsChannelGroupItem offset += 8; /* GxsChannelGroupItem */ - ok &= SetTlvString(data, tlvsize, &offset, 1, item->mGroup.mDescription); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->mDescription); + item->mImage.SetTlv(data, tlvsize, &offset); if(offset != tlvsize) { @@ -237,7 +280,8 @@ RsGxsChannelGroupItem* RsGxsChannelSerialiser::deserialiseGxsChannelGroupItem(vo /* skip the header */ offset += 8; - ok &= GetTlvString(data, rssize, &offset, 1, item->mGroup.mDescription); + ok &= GetTlvString(data, rssize, &offset, 1, item->mDescription); + item->mImage.GetTlv(data, rssize, &offset); if (offset != rssize) { @@ -270,7 +314,9 @@ RsGxsChannelGroupItem* RsGxsChannelSerialiser::deserialiseGxsChannelGroupItem(vo void RsGxsChannelPostItem::clear() { - mMsg.mMsg.clear(); + mMsg.clear(); + mAttachment.TlvClear(); + mThumbnail.TlvClear(); } std::ostream& RsGxsChannelPostItem::print(std::ostream& out, uint16_t indent) @@ -279,20 +325,90 @@ std::ostream& RsGxsChannelPostItem::print(std::ostream& out, uint16_t indent) uint16_t int_Indent = indent + 2; printIndent(out, int_Indent); - out << "Msg: " << mMsg.mMsg << std::endl; + out << "Msg: " << mMsg << std::endl; + + out << "Attachment: " << std::endl; + mAttachment.print(out, int_Indent); + + out << "Thumbnail: " << std::endl; + mThumbnail.print(out, int_Indent); printRsItemEnd(out ,"RsGxsChannelPostItem", indent); return out; } +bool RsGxsChannelPostItem::fromChannelPost(RsGxsChannelPost &post, bool moveImage) +{ + clear(); + meta = post.mMeta; + mMsg = post.mMsg; + + if (moveImage) + { + mThumbnail.binData.bin_data = post.mThumbnail.mData; + mThumbnail.binData.bin_len = post.mThumbnail.mSize; + post.mThumbnail.shallowClear(); + } + else + { + mThumbnail.binData.setBinData(post.mThumbnail.mData, post.mThumbnail.mSize); + } + + std::list::iterator fit; + for(fit = post.mFiles.begin(); fit != post.mFiles.end(); fit++) + { + RsTlvFileItem fi; + fi.name = fit->mName; + fi.filesize = fit->mSize; + fi.hash = fit->mHash; + mAttachment.items.push_back(fi); + } + return true; +} + + + +bool RsGxsChannelPostItem::toChannelPost(RsGxsChannelPost &post, bool moveImage) +{ + post.mMeta = meta; + post.mMsg = mMsg; + if (moveImage) + { + post.mThumbnail.take((uint8_t *) mThumbnail.binData.bin_data, mThumbnail.binData.bin_len); + mThumbnail.TlvShallowClear(); + } + else + { + post.mThumbnail.copy((uint8_t *) mThumbnail.binData.bin_data, mThumbnail.binData.bin_len); + } + + post.mCount = 0; + post.mSize = 0; + std::list::iterator fit; + for(fit = mAttachment.items.begin(); fit != mAttachment.items.end(); fit++) + { + RsGxsFile fi; + fi.mName = RsDirUtil::getTopDir(fit->name); + fi.mSize = fit->filesize; + fi.mHash = fit->hash; + fi.mPath = fit->path; + + post.mFiles.push_back(fi); + post.mCount++; + post.mSize += fi.mSize; + } + return true; +} + + uint32_t RsGxsChannelSerialiser::sizeGxsChannelPostItem(RsGxsChannelPostItem *item) { - - const RsGxsChannelPost& msg = item->mMsg; uint32_t s = 8; // header - s += GetTlvStringSize(msg.mMsg); // mMsg. + s += GetTlvStringSize(item->mMsg); // mMsg. + s += item->mAttachment.TlvSize(); + s += item->mThumbnail.TlvSize(); return s; } @@ -325,7 +441,9 @@ bool RsGxsChannelSerialiser::serialiseGxsChannelPostItem(RsGxsChannelPostItem *i offset += 8; /* GxsChannelPostItem */ - ok &= SetTlvString(data, tlvsize, &offset, 1, item->mMsg.mMsg); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->mMsg); + item->mAttachment.SetTlv(data, tlvsize, &offset); + item->mThumbnail.SetTlv(data, tlvsize, &offset); if(offset != tlvsize) { @@ -385,7 +503,9 @@ RsGxsChannelPostItem* RsGxsChannelSerialiser::deserialiseGxsChannelPostItem(void /* skip the header */ offset += 8; - ok &= GetTlvString(data, rssize, &offset, 1, item->mMsg.mMsg); + ok &= GetTlvString(data, rssize, &offset, 1, item->mMsg); + item->mAttachment.GetTlv(data, rssize, &offset); + item->mThumbnail.GetTlv(data, rssize, &offset); if (offset != rssize) { diff --git a/libretroshare/src/serialiser/rsgxschannelitems.h b/libretroshare/src/serialiser/rsgxschannelitems.h index 3c5e56a9d..f74e4c5af 100644 --- a/libretroshare/src/serialiser/rsgxschannelitems.h +++ b/libretroshare/src/serialiser/rsgxschannelitems.h @@ -37,6 +37,8 @@ #include "rsgxsitems.h" #include "retroshare/rsgxschannels.h" +#include "util/rsdir.h" + const uint8_t RS_PKT_SUBTYPE_GXSCHANNEL_GROUP_ITEM = 0x02; const uint8_t RS_PKT_SUBTYPE_GXSCHANNEL_POST_ITEM = 0x03; @@ -52,8 +54,12 @@ public: void clear(); std::ostream &print(std::ostream &out, uint16_t indent = 0); + // use conversion functions to transform: + bool fromChannelGroup(RsGxsChannelGroup &group, bool moveImage); + bool toChannelGroup(RsGxsChannelGroup &group, bool moveImage); - RsGxsChannelGroup mGroup; + std::string mDescription; + RsTlvImage mImage; }; class RsGxsChannelPostItem : public RsGxsMsgItem @@ -66,7 +72,14 @@ public: void clear(); std::ostream &print(std::ostream &out, uint16_t indent = 0); - RsGxsChannelPost mMsg; + // Slightly unusual structure. + // use conversion functions to transform: + bool fromChannelPost(RsGxsChannelPost &post, bool moveImage); + bool toChannelPost(RsGxsChannelPost &post, bool moveImage); + + std::string mMsg; + RsTlvFileSet mAttachment; + RsTlvImage mThumbnail; }; diff --git a/libretroshare/src/serialiser/rsposteditems.cc b/libretroshare/src/serialiser/rsposteditems.cc index fa6aef754..7acce10b8 100644 --- a/libretroshare/src/serialiser/rsposteditems.cc +++ b/libretroshare/src/serialiser/rsposteditems.cc @@ -4,11 +4,11 @@ * * RetroShare Serialiser. * - * Copyright 2012 by Christopher Evi-Parker + * Copyright 2012-2013 by Robert Fernie, Christopher Evi-Parker * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. + * License Version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -31,627 +31,363 @@ uint32_t RsGxsPostedSerialiser::size(RsItem *item) { - RsGxsPostedPostItem* ppItem = NULL; - RsGxsPostedCommentItem* pcItem = NULL; - RsGxsPostedVoteItem* pvItem = NULL; - RsGxsPostedGroupItem* pgItem = NULL; - - if((ppItem = dynamic_cast(item)) != NULL) - { - return sizeGxsPostedPostItem(ppItem); - } - else if((pcItem = dynamic_cast(item)) != NULL) - { - return sizeGxsPostedCommentItem(pcItem); - }else if((pvItem = dynamic_cast(item)) != NULL) - { - return sizeGxsPostedVoteItem(pvItem); - }else if((pgItem = dynamic_cast(item)) != NULL) - { - return sizeGxsPostedGroupItem(pgItem); - } - else - { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::size() Failed" << std::endl; +#ifdef POSTED_DEBUG + std::cerr << "RsGxsPostedSerialiser::size()" << std::endl; #endif - return NULL; - } + + RsGxsPostedGroupItem* pgItem = NULL; + RsGxsPostedPostItem* ppItem = NULL; + + if ((pgItem = dynamic_cast(item)) != NULL) + { + return sizeGxsPostedGroupItem(pgItem); + } + else if ((ppItem = dynamic_cast(item)) != NULL) + { + return sizeGxsPostedPostItem(ppItem); + } + else + { + return RsGxsCommentSerialiser::size(item); + } + + return NULL; } bool RsGxsPostedSerialiser::serialise(RsItem *item, void *data, uint32_t *size) { - - RsGxsPostedPostItem* ppItem = NULL; - RsGxsPostedCommentItem* pcItem = NULL; - RsGxsPostedVoteItem* pvItem = NULL; - RsGxsPostedGroupItem* pgItem = NULL; - - if((ppItem = dynamic_cast(item)) != NULL) - { - return serialiseGxsPostedPostItem(ppItem, data, size); - } - else if((pcItem = dynamic_cast(item)) != NULL) - { - return serialiseGxsPostedCommentItem(pcItem, data, size); - }else if((pvItem = dynamic_cast(item)) != NULL) - { - return serialiseGxsPostedVoteItem(pvItem, data, size); - }else if((pgItem = dynamic_cast(item)) != NULL) - { - return serialiseGxsPostedGroupItem(pgItem, data, size); - } - else - { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::serialise() FAILED" << std::endl; +#ifdef POSTED_DEBUG + std::cerr << "RsGxsPostedSerialiser::serialise()" << std::endl; #endif - return false; - } + + RsGxsPostedPostItem* ppItem = NULL; + RsGxsPostedGroupItem* pgItem = NULL; + + if ((pgItem = dynamic_cast(item)) != NULL) + { + return serialiseGxsPostedGroupItem(pgItem, data, size); + } + else if ((ppItem = dynamic_cast(item)) != NULL) + { + return serialiseGxsPostedPostItem(ppItem, data, size); + } + else + { + return RsGxsCommentSerialiser::serialise(item, data, size); + } + return false; } RsItem* RsGxsPostedSerialiser::deserialise(void *data, uint32_t *size) { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::deserialise()" << std::endl; +#ifdef POSTED_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialise()" << std::endl; #endif - /* get the type and size */ - uint32_t rstype = getRsItemId(data); + /* get the type and size */ + uint32_t rstype = getRsItemId(data); - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (RS_SERVICE_GXSV1_TYPE_POSTED != getRsItemService(rstype))) - { - return NULL; /* wrong type */ - } + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_POSTED != getRsItemService(rstype))) + { + std::cerr << "RsGxsPostedSerialiser::deserialise() ERROR Wrong Type"; + std::cerr << std::endl; + return NULL; /* wrong type */ + } - switch(getRsItemSubType(rstype)) - { + switch(getRsItemSubType(rstype)) + { - case RS_PKT_SUBTYPE_POSTED_COMMENT_ITEM: - return deserialiseGxsPostedCommentItem(data, size); - case RS_PKT_SUBTYPE_POSTED_GRP_ITEM: - return deserialiseGxsPostedGroupItem(data, size); - case RS_PKT_SUBTYPE_POSTED_POST_ITEM: - return deserialiseGxsPostedPostItem(data, size); - case RS_PKT_SUBTYPE_POSTED_VOTE_ITEM: - return deserialiseGxsPostedVoteItem(data, size); - default: - { -#ifdef RS_SSERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::deserialise(): subtype could not be dealt with" - << std::endl; -#endif - break; - } - } - return NULL; + case RS_PKT_SUBTYPE_POSTED_GRP_ITEM: + return deserialiseGxsPostedGroupItem(data, size); + break; + case RS_PKT_SUBTYPE_POSTED_POST_ITEM: + return deserialiseGxsPostedPostItem(data, size); + break; + default: + return RsGxsCommentSerialiser::deserialise(data, size); + break; + } + return NULL; } +/*****************************************************************************************/ +/*****************************************************************************************/ +/*****************************************************************************************/ + +void RsGxsPostedPostItem::clear() +{ + mPost.mLink.clear(); + mPost.mNotes.clear(); +} + +std::ostream & RsGxsPostedPostItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsGxsPostedPostItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "Link: " << mPost.mLink << std::endl; + printIndent(out, int_Indent); + out << "Notes: " << mPost.mNotes << std::endl; + + printRsItemEnd(out ,"RsGxsPostedPostItem", indent); + return out; +} uint32_t RsGxsPostedSerialiser::sizeGxsPostedPostItem(RsGxsPostedPostItem* item) { - RsPostedPost& p = item->mPost; + RsPostedPost& p = item->mPost; - uint32_t s = 8; + uint32_t s = 8; - s += GetTlvStringSize(p.mLink); - s += GetTlvStringSize(p.mNotes); + s += GetTlvStringSize(p.mLink); + s += GetTlvStringSize(p.mNotes); - return s; -} - -uint32_t RsGxsPostedSerialiser::sizeGxsPostedCommentItem(RsGxsPostedCommentItem* item) -{ - RsPostedComment& c = item->mComment; - - uint32_t s = 8; - - s += GetTlvStringSize(c.mComment); - - return s; -} - -uint32_t RsGxsPostedSerialiser::sizeGxsPostedVoteItem(RsGxsPostedVoteItem* item) -{ - RsPostedVote& v = item->mVote; - - uint32_t s = 8; - s += 1; // for vote direction - - return s; -} - -uint32_t RsGxsPostedSerialiser::sizeGxsPostedGroupItem(RsGxsPostedGroupItem* item) -{ - RsPostedGroup& g = item->mGroup; - - uint32_t s = 8; - return s; + return s; } bool RsGxsPostedSerialiser::serialiseGxsPostedPostItem(RsGxsPostedPostItem* item, void* data, uint32_t *size) { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedPostItem()" << std::endl; +#ifdef POSTED_DEBUG + std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedPostItem()" << std::endl; #endif - uint32_t tlvsize = sizeGxsPostedPostItem(item); - uint32_t offset = 0; + uint32_t tlvsize = sizeGxsPostedPostItem(item); + uint32_t offset = 0; - if(*size < tlvsize){ -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedPostItem()()" << std::endl; -#endif - return false; - } + if(*size < tlvsize){ + std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedPostItem() Size too small" << std::endl; + return false; + } - *size = tlvsize; + *size = tlvsize; - bool ok = true; + bool ok = true; - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - /* skip the header */ - offset += 8; + /* skip the header */ + offset += 8; - /* GxsPhotoAlbumItem */ + /* RsPostedPost */ - ok &= SetTlvString(data, tlvsize, &offset, 1, item->mPost.mLink); - ok &= SetTlvString(data, tlvsize, &offset, 1, item->mPost.mNotes); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->mPost.mLink); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->mPost.mNotes); - if(offset != tlvsize) - { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedPostItem() FAIL Size Error! " << std::endl; -#endif - ok = false; - } + if(offset != tlvsize) + { + std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedPostItem() FAIL Size Error! " << std::endl; + ok = false; + } -#ifdef GXS_POSTED_SERIAL_DEBUG - if (!ok) - { - std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedPostItem() NOK" << std::endl; - } +#ifdef POSTED_DEBUG + if (!ok) + { + std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedPostItem() NOK" << std::endl; + } #endif - return ok; + return ok; } -bool RsGxsPostedSerialiser::serialiseGxsPostedCommentItem(RsGxsPostedCommentItem* item, void* data, uint32_t *size) + + + +RsGxsPostedPostItem* RsGxsPostedSerialiser::deserialiseGxsPostedPostItem(void *data, uint32_t *size) { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedCommentItem()" << std::endl; + +#ifdef POSTED_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedPostItem()" << std::endl; #endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); - uint32_t tlvsize = sizeGxsPostedCommentItem(item); - uint32_t offset = 0; + uint32_t offset = 0; - if(*size < tlvsize){ -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedCommentItem()" << std::endl; + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_POSTED != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_POSTED_POST_ITEM != getRsItemSubType(rstype))) + { + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedPostItem() FAIL wrong type" << std::endl; + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedPostItem() FAIL wrong size" << std::endl; + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsPostedPostItem* item = new RsGxsPostedPostItem(); + /* skip the header */ + offset += 8; + + ok &= GetTlvString(data, rssize, &offset, 1, item->mPost.mLink); + ok &= GetTlvString(data, rssize, &offset, 1, item->mPost.mNotes); + + if (offset != rssize) + { + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedPostItem() FAIL size mismatch" << std::endl; + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef POSTED_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedPostItem() NOK" << std::endl; #endif - return false; - } + delete item; + return NULL; + } - *size = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - - /* skip the header */ - offset += 8; - - /* GxsPhotoAlbumItem */ - - ok &= SetTlvString(data, tlvsize, &offset, 1, item->mComment.mComment); - - - if(offset != tlvsize) - { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedCommentItem()() FAIL Size Error! " << std::endl; -#endif - ok = false; - } - -#ifdef GXS_POSTED_SERIAL_DEBUG - if (!ok) - { - std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedCommentItem()() NOK" << std::endl; - } -#endif - - return ok; + return item; } -bool RsGxsPostedSerialiser::serialiseGxsPostedVoteItem(RsGxsPostedVoteItem* item, void* data, uint32_t *size) + +/*****************************************************************************************/ +/*****************************************************************************************/ +/*****************************************************************************************/ + +void RsGxsPostedGroupItem::clear() { + mGroup.mDescription.clear(); + return; +} -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedVoteItem()" << std::endl; -#endif +std::ostream & RsGxsPostedGroupItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsGxsPostedGroupItem", indent); + uint16_t int_Indent = indent + 2; - uint32_t tlvsize = sizeGxsPostedVoteItem(item); - uint32_t offset = 0; + printIndent(out, int_Indent); + out << "Description: " << mGroup.mDescription << std::endl; - if(*size < tlvsize){ -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedVoteItem()" << std::endl; -#endif - return false; - } + printRsItemEnd(out ,"RsGxsPostedGroupItem", indent); + return out; +} - *size = tlvsize; - bool ok = true; +uint32_t RsGxsPostedSerialiser::sizeGxsPostedGroupItem(RsGxsPostedGroupItem* item) +{ + RsPostedGroup& g = item->mGroup; + uint32_t s = 8; // header - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + s += GetTlvStringSize(g.mDescription); - /* skip the header */ - offset += 8; - - ok &= setRawUInt8(data, tlvsize, &offset, item->mVote.mDirection); - - if(offset != tlvsize) - { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedVoteItem() FAIL Size Error! " << std::endl; -#endif - ok = false; - } - -#ifdef GXS_POSTED_SERIAL_DEBUG - if (!ok) - { - std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedVoteItem() NOK" << std::endl; - } -#endif - - return ok; + return s; } bool RsGxsPostedSerialiser::serialiseGxsPostedGroupItem(RsGxsPostedGroupItem* item, void* data, uint32_t *size) { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedGroupItem()" << std::endl; +#ifdef POSTED_DEBUG + std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedGroupItem()" << std::endl; #endif - uint32_t tlvsize = sizeGxsPostedGroupItem(item); - uint32_t offset = 0; + uint32_t tlvsize = sizeGxsPostedGroupItem(item); + uint32_t offset = 0; - if(*size < tlvsize){ -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedGroupItem()" << std::endl; + if(*size < tlvsize){ +#ifdef POSTED_DEBUG + std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedGroupItem()" << std::endl; #endif - return false; - } + return false; + } - *size = tlvsize; + *size = tlvsize; - bool ok = true; + bool ok = true; - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - /* skip the header */ - offset += 8; + /* skip the header */ + offset += 8; - /* GxsPhotoAlbumItem */ + /* PostedGroupItem */ + ok &= SetTlvString(data, tlvsize, &offset, 1, item->mGroup.mDescription); - if(offset != tlvsize) - { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedGroupItem() FAIL Size Error! " << std::endl; + + if(offset != tlvsize) + { +#ifdef POSTED_DEBUG + std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedGroupItem() FAIL Size Error! " << std::endl; #endif - ok = false; - } + ok = false; + } -#ifdef GXS_POSTED_SERIAL_DEBUG - if (!ok) - { - std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedGroupItem() NOK" << std::endl; - } +#ifdef POSTED_DEBUG + if (!ok) + { + std::cerr << "RsGxsPostedSerialiser::serialiseGxsPostedGroupItem() NOK" << std::endl; + } #endif - return ok; + return ok; } - -RsGxsPostedPostItem* RsGxsPostedSerialiser::deserialiseGxsPostedPostItem(void *data, uint32_t *size) -{ - -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedPostItem()" << std::endl; -#endif - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t rssize = getRsItemSize(data); - - uint32_t offset = 0; - - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (RS_SERVICE_GXSV1_TYPE_POSTED != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_POSTED_POST_ITEM != getRsItemSubType(rstype))) - { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedPostItem() FAIL wrong type" << std::endl; -#endif - return NULL; /* wrong type */ - } - - if (*size < rssize) /* check size */ - { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedPostItem() FAIL wrong size" << std::endl; -#endif - return NULL; /* not enough data */ - } - - /* set the packet length */ - *size = rssize; - - bool ok = true; - - RsGxsPostedPostItem* item = new RsGxsPostedPostItem(); - /* skip the header */ - offset += 8; - - - ok &= GetTlvString(data, rssize, &offset, 1, item->mPost.mLink); - ok &= GetTlvString(data, rssize, &offset, 1, item->mPost.mNotes); - - if (offset != rssize) - { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedPostItem() FAIL size mismatch" << std::endl; -#endif - /* error */ - delete item; - return NULL; - } - - if (!ok) - { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedPostItem() NOK" << std::endl; -#endif - delete item; - return NULL; - } - - return item; -} - -RsGxsPostedCommentItem* RsGxsPostedSerialiser::deserialiseGxsPostedCommentItem(void *data, uint32_t *size) -{ -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedCommentItem()" << std::endl; -#endif - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t rssize = getRsItemSize(data); - - uint32_t offset = 0; - - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (RS_SERVICE_GXSV1_TYPE_POSTED != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_POSTED_COMMENT_ITEM != getRsItemSubType(rstype))) - { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedCommentItem() FAIL wrong type" << std::endl; -#endif - return NULL; /* wrong type */ - } - - if (*size < rssize) /* check size */ - { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedCommentItem() FAIL wrong size" << std::endl; -#endif - return NULL; /* not enough data */ - } - - /* set the packet length */ - *size = rssize; - - bool ok = true; - - RsGxsPostedCommentItem* item = new RsGxsPostedCommentItem(); - /* skip the header */ - offset += 8; - - - ok &= GetTlvString(data, rssize, &offset, 1, item->mComment.mComment); - - if (offset != rssize) - { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedCommentItem() FAIL size mismatch" << std::endl; -#endif - /* error */ - delete item; - return NULL; - } - - if (!ok) - { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedCommentItem() NOK" << std::endl; -#endif - delete item; - return NULL; - } - - return item; -} - -RsGxsPostedVoteItem* RsGxsPostedSerialiser::deserialiseGxsPostedVoteItem(void *data, uint32_t *size) -{ - -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedVoteItem()" << std::endl; -#endif - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t rssize = getRsItemSize(data); - - uint32_t offset = 0; - - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (RS_SERVICE_GXSV1_TYPE_POSTED != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_POSTED_VOTE_ITEM != getRsItemSubType(rstype))) - { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedVoteItem() FAIL wrong type" << std::endl; -#endif - return NULL; /* wrong type */ - } - - if (*size < rssize) /* check size */ - { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedVoteItem() FAIL wrong size" << std::endl; -#endif - return NULL; /* not enough data */ - } - - /* set the packet length */ - *size = rssize; - - bool ok = true; - - RsGxsPostedVoteItem* item = new RsGxsPostedVoteItem(); - /* skip the header */ - offset += 8; - - ok &= getRawUInt8(data, rssize, &offset, &(item->mVote.mDirection)); - - if (offset != rssize) - { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedVoteItem() FAIL size mismatch" << std::endl; -#endif - /* error */ - delete item; - return NULL; - } - - if (!ok) - { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedVoteItem() NOK" << std::endl; -#endif - delete item; - return NULL; - } - - return item; -} - RsGxsPostedGroupItem* RsGxsPostedSerialiser::deserialiseGxsPostedGroupItem(void *data, uint32_t *size) { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedGroupItem()" << std::endl; +#ifdef POSTED_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedGroupItem()" << std::endl; #endif - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t rssize = getRsItemSize(data); + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); - uint32_t offset = 0; + uint32_t offset = 0; - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (RS_SERVICE_GXSV1_TYPE_POSTED != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_POSTED_VOTE_ITEM != getRsItemSubType(rstype))) - { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedGroupItem() FAIL wrong type" << std::endl; + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXSV1_TYPE_POSTED != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_POSTED_GRP_ITEM != getRsItemSubType(rstype))) + { + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedGroupItem() FAIL wrong type" << std::endl; + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedGroupItem() FAIL wrong size" << std::endl; + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsPostedGroupItem* item = new RsGxsPostedGroupItem(); + /* skip the header */ + offset += 8; + + ok &= GetTlvString(data, rssize, &offset, 1, item->mGroup.mDescription); + + if (offset != rssize) + { + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedGroupItem() FAIL size mismatch" << std::endl; + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef POSTED_DEBUG + std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedGroupItem() NOK" << std::endl; #endif - return NULL; /* wrong type */ - } + delete item; + return NULL; + } - if (*size < rssize) /* check size */ - { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedGroupItem() FAIL wrong size" << std::endl; -#endif - return NULL; /* not enough data */ - } - - /* set the packet length */ - *size = rssize; - - bool ok = true; - - RsGxsPostedGroupItem* item = new RsGxsPostedGroupItem(); - /* skip the header */ - offset += 8; - - if (offset != rssize) - { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedGroupItem() FAIL size mismatch" << std::endl; -#endif - /* error */ - delete item; - return NULL; - } - - if (!ok) - { -#ifdef GXS_POSTED_SERIAL_DEBUG - std::cerr << "RsGxsPostedSerialiser::deserialiseGxsPostedGroupItem() NOK" << std::endl; -#endif - delete item; - return NULL; - } - - return item; + return item; } - -void RsGxsPostedPostItem::clear() -{ - -} - -std::ostream & RsGxsPostedPostItem::print(std::ostream &out, uint16_t indent) -{ - return out; -} - -void RsGxsPostedVoteItem::clear() -{ - return; -} - -std::ostream & RsGxsPostedVoteItem::print(std::ostream &out, uint16_t indent) -{ - return out; -} - -void RsGxsPostedCommentItem::clear() -{ - return; -} - -std::ostream & RsGxsPostedCommentItem::print(std::ostream &out, uint16_t indent) -{ - return out; -} - -void RsGxsPostedGroupItem::clear() -{ - return; -} - -std::ostream & RsGxsPostedGroupItem::print(std::ostream &out, uint16_t indent) -{ - return out; - -} diff --git a/libretroshare/src/serialiser/rsposteditems.h b/libretroshare/src/serialiser/rsposteditems.h index d7212c3f8..3e676c807 100644 --- a/libretroshare/src/serialiser/rsposteditems.h +++ b/libretroshare/src/serialiser/rsposteditems.h @@ -5,98 +5,64 @@ #include "serialiser/rsserial.h" #include "serialiser/rstlvtypes.h" +#include "serialiser/rsgxscommentitems.h" + #include "rsgxsitems.h" #include "retroshare/rsposted.h" const uint8_t RS_PKT_SUBTYPE_POSTED_GRP_ITEM = 0x02; const uint8_t RS_PKT_SUBTYPE_POSTED_POST_ITEM = 0x03; -const uint8_t RS_PKT_SUBTYPE_POSTED_VOTE_ITEM = 0x04; -const uint8_t RS_PKT_SUBTYPE_POSTED_COMMENT_ITEM = 0x05; - -class RsGxsPostedPostItem : public RsGxsMsgItem -{ -public: - RsGxsPostedPostItem() : RsGxsMsgItem(RS_SERVICE_GXSV1_TYPE_POSTED, - RS_PKT_SUBTYPE_POSTED_POST_ITEM) - {return ; } - - void clear(); - std::ostream &print(std::ostream &out, uint16_t indent = 0); - - RsPostedPost mPost; -}; - -class RsGxsPostedVoteItem : public RsGxsMsgItem -{ -public: - RsGxsPostedVoteItem() : RsGxsMsgItem(RS_SERVICE_GXSV1_TYPE_POSTED, - RS_PKT_SUBTYPE_POSTED_VOTE_ITEM) - {return ;} - - void clear(); - std::ostream &print(std::ostream &out, uint16_t indent = 0); - - RsPostedVote mVote; -}; - -class RsGxsPostedCommentItem : public RsGxsMsgItem -{ -public: - RsGxsPostedCommentItem() : RsGxsMsgItem(RS_SERVICE_GXSV1_TYPE_POSTED, - RS_PKT_SUBTYPE_POSTED_COMMENT_ITEM) - { return; } - - void clear(); - std::ostream &print(std::ostream &out, uint16_t indent = 0); - - RsPostedComment mComment; -}; class RsGxsPostedGroupItem : public RsGxsGrpItem { public: - RsGxsPostedGroupItem() : RsGxsGrpItem(RS_SERVICE_GXSV1_TYPE_POSTED, - RS_PKT_SUBTYPE_POSTED_GRP_ITEM) - { return; } + RsGxsPostedGroupItem() : RsGxsGrpItem(RS_SERVICE_GXSV1_TYPE_POSTED, + RS_PKT_SUBTYPE_POSTED_GRP_ITEM) { return; } + virtual ~RsGxsPostedGroupItem() { return; } - void clear(); - std::ostream &print(std::ostream &out, uint16_t indent = 0); + void clear(); + std::ostream &print(std::ostream &out, uint16_t indent = 0); - RsPostedGroup mGroup; + RsPostedGroup mGroup; }; -class RsGxsPostedSerialiser : public RsSerialType +class RsGxsPostedPostItem : public RsGxsMsgItem +{ +public: + RsGxsPostedPostItem() : RsGxsMsgItem(RS_SERVICE_GXSV1_TYPE_POSTED, + RS_PKT_SUBTYPE_POSTED_POST_ITEM) {return ; } + virtual ~RsGxsPostedPostItem() { return; } + + void clear(); + std::ostream &print(std::ostream &out, uint16_t indent = 0); + + RsPostedPost mPost; +}; + +class RsGxsPostedSerialiser : public RsGxsCommentSerialiser { public: - RsGxsPostedSerialiser() - : RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_GXSV1_TYPE_PHOTO) - { return; } + RsGxsPostedSerialiser() + :RsGxsCommentSerialiser(RS_SERVICE_GXSV1_TYPE_POSTED) + { return; } - virtual ~RsGxsPostedSerialiser() { return; } + virtual ~RsGxsPostedSerialiser() { return; } - uint32_t size(RsItem *item); - bool serialise(RsItem *item, void *data, uint32_t *size); - RsItem* deserialise(void *data, uint32_t *size); + uint32_t size(RsItem *item); + bool serialise(RsItem *item, void *data, uint32_t *size); + RsItem* deserialise(void *data, uint32_t *size); private: - uint32_t sizeGxsPostedPostItem(RsGxsPostedPostItem* item); - bool serialiseGxsPostedPostItem(RsGxsPostedPostItem* item, void* data, uint32_t *size); - RsGxsPostedPostItem* deserialiseGxsPostedPostItem(void *data, uint32_t *size); + uint32_t sizeGxsPostedGroupItem(RsGxsPostedGroupItem* item); + bool serialiseGxsPostedGroupItem(RsGxsPostedGroupItem* item, void* data, uint32_t *size); + RsGxsPostedGroupItem* deserialiseGxsPostedGroupItem(void *data, uint32_t *size); - uint32_t sizeGxsPostedCommentItem(RsGxsPostedCommentItem* item); - bool serialiseGxsPostedCommentItem(RsGxsPostedCommentItem* item, void* data, uint32_t *size); - RsGxsPostedCommentItem* deserialiseGxsPostedCommentItem(void *data, uint32_t *size); - - uint32_t sizeGxsPostedVoteItem(RsGxsPostedVoteItem* item); - bool serialiseGxsPostedVoteItem(RsGxsPostedVoteItem* item, void* data, uint32_t *size); - RsGxsPostedVoteItem* deserialiseGxsPostedVoteItem(void *data, uint32_t *size); - - uint32_t sizeGxsPostedGroupItem(RsGxsPostedGroupItem* item); - bool serialiseGxsPostedGroupItem(RsGxsPostedGroupItem* item, void* data, uint32_t *size); - RsGxsPostedGroupItem* deserialiseGxsPostedGroupItem(void *data, uint32_t *size); + uint32_t sizeGxsPostedPostItem(RsGxsPostedPostItem* item); + bool serialiseGxsPostedPostItem(RsGxsPostedPostItem* item, void* data, uint32_t *size); + RsGxsPostedPostItem* deserialiseGxsPostedPostItem(void *data, uint32_t *size); }; diff --git a/libretroshare/src/services/p3gxschannels.cc b/libretroshare/src/services/p3gxschannels.cc index ccc364ea2..e6751ce7a 100644 --- a/libretroshare/src/services/p3gxschannels.cc +++ b/libretroshare/src/services/p3gxschannels.cc @@ -44,7 +44,12 @@ RsGxsChannels *rsGxsChannels = NULL; -#define CHANNEL_TESTEVENT_DUMMYDATA 0x0001 +#define GXSCHANNELS_SUBSCRIBED_META 1 +#define GXSCHANNELS_UNPROCESSED_SPECIFIC 2 +#define GXSCHANNELS_UNPROCESSED_GENERIC 3 + +#define CHANNEL_PROCESS 0x0001 +#define CHANNEL_TESTEVENT_DUMMYDATA 0x0002 #define DUMMYDATA_PERIOD 60 // long enough for some RsIdentities to be generated. /********************************************************************************/ @@ -52,17 +57,16 @@ RsGxsChannels *rsGxsChannels = NULL; /********************************************************************************/ p3GxsChannels::p3GxsChannels(RsGeneralDataService *gds, RsNetworkExchangeService *nes, RsGixs* gixs) - : RsGenExchange(gds, nes, new RsGxsChannelSerialiser(), RS_SERVICE_GXSV1_TYPE_CHANNELS, gixs, channelsAuthenPolicy()), RsGxsChannels(this) + : RsGenExchange(gds, nes, new RsGxsChannelSerialiser(), RS_SERVICE_GXSV1_TYPE_CHANNELS, gixs, channelsAuthenPolicy()), RsGxsChannels(this), GxsTokenQueue(this) { // For Dummy Msgs. mGenActive = false; mCommentService = new p3GxsCommentService(this, RS_SERVICE_GXSV1_TYPE_CHANNELS); -#ifndef GXS_DEV_TESTNET // NO RESET, OR DUMMYDATA for TESTNET + RsTickEvent::schedule_in(CHANNEL_PROCESS, 0); - RsTickEvent::schedule_in(CHANNEL_TESTEVENT_DUMMYDATA, DUMMYDATA_PERIOD); - -#endif + // Test Data disabled in repo. + //RsTickEvent::schedule_in(CHANNEL_TESTEVENT_DUMMYDATA, DUMMYDATA_PERIOD); } @@ -86,6 +90,44 @@ uint32_t p3GxsChannels::channelsAuthenPolicy() void p3GxsChannels::notifyChanges(std::vector &changes) { + std::cerr << "p3GxsChannels::notifyChanges()"; + std::cerr << std::endl; + + /* iterate through and grab any new messages */ + std::list unprocessedGroups; + + std::vector::iterator it; + for(it = changes.begin(); it != changes.end(); it++) + { + RsGxsMsgChange *msgChange = dynamic_cast(*it); + if (msgChange) + { + std::cerr << "p3GxsChannels::notifyChanges() Found Message Change Notification"; + std::cerr << std::endl; + + std::map > &msgChangeMap = msgChange->msgChangeMap; + std::map >::iterator mit; + for(mit = msgChangeMap.begin(); mit != msgChangeMap.end(); mit++) + { + std::cerr << "p3GxsChannels::notifyChanges() Msgs for Group: " << mit->first; + std::cerr << std::endl; + + if (autoDownloadEnabled(mit->first)) + { + std::cerr << "p3GxsChannels::notifyChanges() AutoDownload for Group: " << mit->first; + std::cerr << std::endl; + + /* problem is most of these will be comments and votes, + * should make it occasional - every 5mins / 10minutes TODO */ + unprocessedGroups.push_back(mit->first); + } + } + } + } + + request_SpecificSubscribedGroups(unprocessedGroups); + + RsGxsIfaceHelper::receiveChanges(changes); } @@ -98,6 +140,9 @@ void p3GxsChannels::service_tick() bool p3GxsChannels::getGroupData(const uint32_t &token, std::vector &groups) { + std::cerr << "p3GxsChannels::getGroupData()"; + std::cerr << std::endl; + std::vector grpData; bool ok = RsGenExchange::getGroupData(token, grpData); @@ -108,13 +153,26 @@ bool p3GxsChannels::getGroupData(const uint32_t &token, std::vector(*vit); - RsGxsChannelGroup grp = item->mGroup; - item->mGroup.mMeta = item->meta; - grp.mMeta = item->mGroup.mMeta; - delete item; - groups.push_back(grp); + if (item) + { + RsGxsChannelGroup grp; + item->toChannelGroup(grp, true); + delete item; + groups.push_back(grp); + } + else + { + std::cerr << "p3GxsChannels::getGroupData() ERROR in decode"; + std::cerr << std::endl; + } } } + else + { + std::cerr << "p3GxsChannels::getGroupData() ERROR in request"; + std::cerr << std::endl; + } + return ok; } @@ -125,6 +183,9 @@ bool p3GxsChannels::getGroupData(const uint32_t &token, std::vector &msgs) { + std::cerr << "p3GxsChannels::getPostData()"; + std::cerr << std::endl; + GxsMsgDataMap msgData; bool ok = RsGenExchange::getMsgData(token, msgData); @@ -144,8 +205,8 @@ bool p3GxsChannels::getPostData(const uint32_t &token, std::vectormMsg; - msg.mMeta = item->meta; + RsGxsChannelPost msg; + item->toChannelPost(msg, true); msgs.push_back(msg); delete item; } @@ -157,6 +218,11 @@ bool p3GxsChannels::getPostData(const uint32_t &token, std::vector &msgs) { + std::cerr << "p3GxsChannels::getRelatedPosts()"; + std::cerr << std::endl; + GxsMsgRelatedDataMap msgData; bool ok = RsGenExchange::getMsgRelatedData(token, msgData); @@ -182,8 +251,8 @@ bool p3GxsChannels::getRelatedPosts(const uint32_t &token, std::vectormMsg; - msg.mMeta = item->meta; + RsGxsChannelPost msg; + item->toChannelPost(msg, true); msgs.push_back(msg); delete item; } @@ -195,11 +264,424 @@ bool p3GxsChannels::getRelatedPosts(const uint32_t &token, std::vectorrequestGroupInfo(token, ansType, opts); + GxsTokenQueue::queueRequest(token, GXSCHANNELS_SUBSCRIBED_META); + +} + + +void p3GxsChannels::request_SpecificSubscribedGroups(const std::list &groups) +{ +#ifdef GXSCHANNELS_DEBUG + std::cerr << "p3GxsChannels::request_SpecificSubscribedGroups()"; + std::cerr << std::endl; +#endif // GXSCHANNELS_DEBUG + + uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; + + uint32_t token = 0; + + RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts, groups); + GxsTokenQueue::queueRequest(token, GXSCHANNELS_SUBSCRIBED_META); +} + + +void p3GxsChannels::load_SubscribedGroups(const uint32_t &token) +{ +#ifdef GXSCHANNELS_DEBUG + std::cerr << "p3GxsChannels::load_SubscribedGroups()"; + std::cerr << std::endl; +#endif // GXSCHANNELS_DEBUG + + std::list groups; + std::list groupList; + + getGroupMeta(token, groups); + + std::list::iterator it; + for(it = groups.begin(); it != groups.end(); it++) + { + if (it->mSubscribeFlags & + (GXS_SERV::GROUP_SUBSCRIBE_ADMIN | + GXS_SERV::GROUP_SUBSCRIBE_PUBLISH | + GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED )) + { + std::cerr << "p3GxsChannels::load_SubscribedGroups() updating Subscribed Group: " << it->mGroupId; + std::cerr << std::endl; + + updateSubscribedGroup(*it); + if (autoDownloadEnabled(it->mGroupId)) + { + std::cerr << "p3GxsChannels::load_SubscribedGroups() remembering AutoDownload Group: " << it->mGroupId; + std::cerr << std::endl; + groupList.push_back(it->mGroupId); + } + } + else + { + std::cerr << "p3GxsChannels::load_SubscribedGroups() clearing unsubscribed Group: " << it->mGroupId; + std::cerr << std::endl; + clearUnsubscribedGroup(it->mGroupId); + } + } + + /* Query for UNPROCESSED POSTS from checkGroupList */ + request_GroupUnprocessedPosts(groupList); +} + + + +void p3GxsChannels::updateSubscribedGroup(const RsGroupMetaData &group) +{ + std::cerr << "p3GxsChannels::updateSubscribedGroup() id: " << group.mGroupId; + std::cerr << std::endl; + + mSubscribedGroups[group.mGroupId] = group; +} + + +void p3GxsChannels::clearUnsubscribedGroup(const RsGxsGroupId &id) +{ + std::cerr << "p3GxsChannels::clearUnsubscribedGroup() id: " << id; + std::cerr << std::endl; + + //std::map mSubscribedGroups; + std::map::iterator it; + + it = mSubscribedGroups.find(id); + if (it != mSubscribedGroups.end()) + { + mSubscribedGroups.erase(it); + } +} + + +void p3GxsChannels::subscribeToGroup(const RsGxsGroupId &groupId, bool subscribe) +{ + std::cerr << "p3GxsChannels::subscribedToGroup() id: " << groupId << " subscribe: " << subscribe; + std::cerr << std::endl; + + std::list groups; + groups.push_back(groupId); + + // Call down to do the real work. + uint32_t token; + RsGenExchange::subscribeToGroup(token, groupId, subscribe); + + // reload Group afterwards. + request_SpecificSubscribedGroups(groups); +} + + +void p3GxsChannels::request_SpecificUnprocessedPosts(std::list > &ids) +{ +#ifdef GXSCHANNELS_DEBUG + std::cerr << "p3GxsChannels::request_SpecificUnprocessedPosts()"; + std::cerr << std::endl; +#endif // GXSCHANNELS_DEBUG + + uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + + uint32_t token = 0; + + RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); + GxsTokenQueue::queueRequest(token, GXSCHANNELS_UNPROCESSED_SPECIFIC); +} + + +void p3GxsChannels::request_GroupUnprocessedPosts(const std::list &grouplist) +{ +#ifdef GXSCHANNELS_DEBUG + std::cerr << "p3GxsChannels::request_GroupUnprocessedPosts()"; + std::cerr << std::endl; +#endif // GXSCHANNELS_DEBUG + + uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + + uint32_t token = 0; + + RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); + GxsTokenQueue::queueRequest(token, GXSCHANNELS_UNPROCESSED_GENERIC); +} + + +void p3GxsChannels::load_SpecificUnprocessedPosts(const uint32_t &token) +{ + std::vector posts; + if (!getRelatedPosts(token, posts)) + { + std::cerr << "p3GxsChannels::load_GroupUnprocessedPosts ERROR"; + return; + } + + + std::vector::iterator it; + for(it = posts.begin(); it != posts.end(); it++) + { + /* autodownload the files */ + handleUnprocessedPost(*it); + } +} + + +void p3GxsChannels::load_GroupUnprocessedPosts(const uint32_t &token) +{ + std::vector posts; + + if (!getPostData(token, posts)) + { + std::cerr << "p3GxsChannels::load_GroupUnprocessedPosts ERROR"; + return; + } + + + std::vector::iterator it; + for(it = posts.begin(); it != posts.end(); it++) + { + handleUnprocessedPost(*it); + } +} + + + +void p3GxsChannels::handleUnprocessedPost(const RsGxsChannelPost &msg) +{ + std::cerr << "p3GxsChannels::handleUnprocessedPost() GroupId: " << msg.mMeta.mGroupId << " MsgId: " << msg.mMeta.mMsgId; + std::cerr << std::endl; + + /* check that autodownload is set */ + if (autoDownloadEnabled(msg.mMeta.mGroupId)) + { + + std::cerr << "p3GxsChannels::handleUnprocessedPost() AutoDownload Enabled ... handling"; + std::cerr << std::endl; + + /* check the date is not too old */ + + /* start download */ + + std::cerr << "p3GxsChannels::handleUnprocessedPost() START DOWNLOAD (TODO)"; + std::cerr << std::endl; + + + /* mark as processed */ + uint32_t token; + RsGxsGrpMsgIdPair msgId(msg.mMeta.mGroupId, msg.mMeta.mMsgId); + setMessageProcessedStatus(token, msgId, true); + } + else + { + std::cerr << "p3GxsChannels::handleUnprocessedPost() AutoDownload Disabled ... skipping"; + std::cerr << std::endl; + } +} + + + // Overloaded from GxsTokenQueue for Request callbacks. +void p3GxsChannels::handleResponse(uint32_t token, uint32_t req_type) +{ +#ifdef GXSCHANNELS_DEBUG + std::cerr << "p3GxsChannels::handleResponse(" << token << "," << req_type << ")"; + std::cerr << std::endl; +#endif // GXSCHANNELS_DEBUG + + // stuff. + switch(req_type) + { + case GXSCHANNELS_SUBSCRIBED_META: + load_SubscribedGroups(token); + break; + + case GXSCHANNELS_UNPROCESSED_SPECIFIC: + load_SpecificUnprocessedPosts(token); + break; + + case GXSCHANNELS_UNPROCESSED_GENERIC: + load_SpecificUnprocessedPosts(token); + break; + + default: + /* error */ + std::cerr << "p3GxsService::handleResponse() Unknown Request Type: " << req_type; + std::cerr << std::endl; + break; + } +} + + +/********************************************************************************************/ +/********************************************************************************************/ + + +bool p3GxsChannels::autoDownloadEnabled(const RsGxsGroupId &id) +{ + std::cerr << "p3GxsChannels::autoDownloadEnabled(" << id << ")"; + std::cerr << std::endl; + + std::map::iterator it; + + it = mSubscribedGroups.find(id); + if (it != mSubscribedGroups.end()) + { + std::cerr << "p3GxsChannels::autoDownloadEnabled() No Entry"; + std::cerr << std::endl; + + return false; + } + + /* extract from ServiceString */ + SSGxsChannelGroup ss; + ss.load(it->second.mServiceString); + return ss.mAutoDownload; +} + +#define RSGXSCHANNEL_MAX_SERVICE_STRING 128 + +bool SSGxsChannelGroup::load(const std::string &input) +{ + char line[RSGXSCHANNEL_MAX_SERVICE_STRING]; + int download_val; + mAutoDownload = false; + if (1 == sscanf(input.c_str(), "D:%d", &download_val)) + { + if (download_val == 1) + { + mAutoDownload = true; + } + } + return true; +} + +std::string SSGxsChannelGroup::save() const +{ + std::string output; + if (mAutoDownload) + { + output += "D:1"; + } + else + { + output += "D:0"; + } + return output; +} + +bool p3GxsChannels::setAutoDownload(const RsGxsGroupId &groupId, bool enabled) +{ + std::cerr << "p3GxsChannels::setAutoDownload() id: " << groupId << " enabled: " << enabled; + std::cerr << std::endl; + + std::map::iterator it; + + it = mSubscribedGroups.find(groupId); + if (it != mSubscribedGroups.end()) + { + std::cerr << "p3GxsChannels::setAutoDownload() Missing Group"; + std::cerr << std::endl; + + return false; + } + + /* extract from ServiceString */ + SSGxsChannelGroup ss; + ss.load(it->second.mServiceString); + if (enabled == ss.mAutoDownload) + { + /* it should be okay! */ + std::cerr << "p3GxsChannels::setAutoDownload() WARNING setting looks okay already"; + std::cerr << std::endl; + + } + + /* we are just going to set it anyway. */ + ss.mAutoDownload = enabled; + std::string serviceString = ss.save(); + uint32_t token; + RsGenExchange::setGroupServiceString(token, groupId, serviceString); + + /* now reload it */ + std::list groups; + groups.push_back(groupId); + + request_SpecificSubscribedGroups(groups); + + return true; +} + +/********************************************************************************************/ +/********************************************************************************************/ + +void p3GxsChannels::setMessageProcessedStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool processed) +{ + std::cerr << "p3GxsChannels::setMessageProcessedStatus()"; + std::cerr << std::endl; + + uint32_t mask = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; + uint32_t status = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; + if (processed) + { + status = 0; + } + setMsgStatusFlags(token, msgId, status, mask); +} + +void p3GxsChannels::setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) +{ + std::cerr << "p3GxsChannels::setMessageReadStatus()"; + std::cerr << std::endl; + + uint32_t mask = GXS_SERV::GXS_MSG_STATUS_UNREAD; + uint32_t status = GXS_SERV::GXS_MSG_STATUS_UNREAD; + if (read) + { + status = 0; + } + setMsgStatusFlags(token, msgId, status, mask); +} + + +/********************************************************************************************/ /********************************************************************************************/ bool p3GxsChannels::createGroup(uint32_t &token, RsGxsChannelGroup &group) @@ -207,8 +689,7 @@ bool p3GxsChannels::createGroup(uint32_t &token, RsGxsChannelGroup &group) std::cerr << "p3GxsChannels::createGroup()" << std::endl; RsGxsChannelGroupItem* grpItem = new RsGxsChannelGroupItem(); - grpItem->mGroup = group; - grpItem->meta = group.mMeta; + grpItem->fromChannelGroup(group, true); RsGenExchange::publishGroup(token, grpItem); return true; @@ -221,30 +702,13 @@ bool p3GxsChannels::createPost(uint32_t &token, RsGxsChannelPost &msg) std::cerr << std::endl; RsGxsChannelPostItem* msgItem = new RsGxsChannelPostItem(); - msgItem->mMsg = msg; - msgItem->meta = msg.mMeta; + msgItem->fromChannelPost(msg, true); RsGenExchange::publishMsg(token, msgItem); return true; } -/********************************************************************************************/ -/********************************************************************************************/ - -void p3GxsChannels::setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) -{ - uint32_t mask = GXS_SERV::GXS_MSG_STATUS_UNREAD | GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - uint32_t status = GXS_SERV::GXS_MSG_STATUS_UNREAD; - if (read) - { - status = 0; - } - - setMsgStatusFlags(token, msgId, status, mask); - -} - /********************************************************************************************/ /********************************************************************************************/ @@ -451,7 +915,7 @@ bool p3GxsChannels::generateComment(uint32_t &token, const RsGxsGroupId &grpId, rsIdentity->getOwnIds(ownIds); uint32_t idx = (uint32_t) (ownIds.size() * RSRandom::random_f32()); - int i = 0; + uint32_t i = 0; for(it = ownIds.begin(); (it != ownIds.end()) && (i < idx); it++, i++); if (it != ownIds.end()) @@ -497,6 +961,9 @@ void p3GxsChannels::handle_event(uint32_t event_type, const std::string &elabel) generateDummyData(); break; + case CHANNEL_PROCESS: + request_AllSubscribedGroups(); + default: /* error */ std::cerr << "p3GxsChannels::handle_event() Unknown Event Type: " << event_type; diff --git a/libretroshare/src/services/p3gxschannels.h b/libretroshare/src/services/p3gxschannels.h index 452ffc052..09d30ee91 100644 --- a/libretroshare/src/services/p3gxschannels.h +++ b/libretroshare/src/services/p3gxschannels.h @@ -30,6 +30,7 @@ #include "retroshare/rsgxschannels.h" #include "services/p3gxscommon.h" #include "gxs/rsgenexchange.h" +#include "gxs/gxstokenqueue.h" #include "util/rstickevent.h" @@ -40,7 +41,20 @@ * */ + +class SSGxsChannelGroup +{ + public: + + bool load(const std::string &input); + std::string save() const; + + bool mAutoDownload; +}; + + class p3GxsChannels: public RsGenExchange, public RsGxsChannels, + public GxsTokenQueue, public RsTickEvent /* only needed for testing - remove after */ { public: @@ -65,7 +79,6 @@ virtual bool getPostData(const uint32_t &token, std::vector &p virtual bool getRelatedPosts(const uint32_t &token, std::vector &posts); ////////////////////////////////////////////////////////////////////////////// -virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read); //virtual bool setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask); //virtual bool setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask); @@ -76,7 +89,7 @@ virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgI virtual bool createGroup(uint32_t &token, RsGxsChannelGroup &group); virtual bool createPost(uint32_t &token, RsGxsChannelPost &post); - +virtual void setChannelAutoDownload(uint32_t&, const RsGxsGroupId&, bool); /* Comment service - Provide RsGxsCommentService - redirect to p3GxsCommentService */ virtual bool getCommentData(const uint32_t &token, std::vector &msgs) @@ -104,10 +117,46 @@ virtual bool acknowledgeComment(const uint32_t& token, std::pair &groups); + void load_SubscribedGroups(const uint32_t &token); + + void request_SpecificUnprocessedPosts(std::list > &ids); + void load_SpecificUnprocessedPosts(const uint32_t &token); + + void request_GroupUnprocessedPosts(const std::list &grouplist); + void load_GroupUnprocessedPosts(const uint32_t &token); + + void handleUnprocessedPost(const RsGxsChannelPost &msg); + + // Local Cache of Subscribed Groups. and AutoDownload Flag. + void updateSubscribedGroup(const RsGroupMetaData &group); + void clearUnsubscribedGroup(const RsGxsGroupId &id); + bool autoDownloadEnabled(const RsGxsGroupId &id); + bool setAutoDownload(const RsGxsGroupId &groupId, bool enabled); + + + + std::map mSubscribedGroups; + // DUMMY DATA, virtual bool generateDummyData(); diff --git a/libretroshare/src/services/p3gxscommon.cc b/libretroshare/src/services/p3gxscommon.cc index d6c9b4ff3..0af666c1f 100644 --- a/libretroshare/src/services/p3gxscommon.cc +++ b/libretroshare/src/services/p3gxscommon.cc @@ -28,6 +28,7 @@ #include "serialiser/rsgxscommentitems.h" #include +#include RsGxsComment::RsGxsComment() @@ -37,6 +38,8 @@ RsGxsComment::RsGxsComment() score = 0; } +/********************************************************************************/ + RsGxsImage::RsGxsImage() { mData = NULL; @@ -44,6 +47,64 @@ RsGxsImage::RsGxsImage() } +RsGxsImage::~RsGxsImage() +{ + clear(); +} + + +void RsGxsImage::take(uint8_t *data, uint32_t size) +{ + // Copies Pointer. + clear(); + mData = data; + mSize = size; +} + +// NB Must make sure that we always use malloc/free for this data. +uint8_t *RsGxsImage::allocate(uint32_t size) +{ + return (uint8_t *) malloc(size); +} + +void RsGxsImage::release(void *data) +{ + free(data); +} + +void RsGxsImage::copy(uint8_t *data, uint32_t size) +{ + // Allocates and Copies. + clear(); + if (data && size) + { + mData = allocate(size); + memcpy(mData, data, size); + mSize = size; + } +} + +void RsGxsImage::clear() +{ + // Frees. + if (mData) + { + release(mData); + } + mData = NULL; + mSize = 0; +} + +void RsGxsImage::shallowClear() +{ + // Clears Pointer. + mData = NULL; + mSize = 0; +} + +/********************************************************************************/ + + RsGxsFile::RsGxsFile() { mSize = 0; diff --git a/libretroshare/src/services/p3gxscommon.h b/libretroshare/src/services/p3gxscommon.h index 6832927aa..9d642c9ce 100644 --- a/libretroshare/src/services/p3gxscommon.h +++ b/libretroshare/src/services/p3gxscommon.h @@ -22,6 +22,8 @@ * Please report all bugs and problems to "retroshare@lunamutt.com". * */ +#ifndef P3_GXSCOMMON_SERVICE_HEADER +#define P3_GXSCOMMON_SERVICE_HEADER #include "retroshare/rsgxscommon.h" #include "gxs/rsgenexchange.h" @@ -56,4 +58,5 @@ class p3GxsCommentService }; +#endif diff --git a/libretroshare/src/services/p3gxsforums.cc b/libretroshare/src/services/p3gxsforums.cc index 2dd1df213..ce67aa3be 100644 --- a/libretroshare/src/services/p3gxsforums.cc +++ b/libretroshare/src/services/p3gxsforums.cc @@ -56,11 +56,8 @@ p3GxsForums::p3GxsForums(RsGeneralDataService *gds, RsNetworkExchangeService *ne // For Dummy Msgs. mGenActive = false; -#ifndef GXS_DEV_TESTNET // NO RESET, OR DUMMYDATA for TESTNET - - RsTickEvent::schedule_in(FORUM_TESTEVENT_DUMMYDATA, DUMMYDATA_PERIOD); - -#endif + // Test Data disabled in Repo. + //RsTickEvent::schedule_in(FORUM_TESTEVENT_DUMMYDATA, DUMMYDATA_PERIOD); } diff --git a/libretroshare/src/services/p3posted.cc b/libretroshare/src/services/p3posted.cc index 40cf5a0fb..d462f6b07 100644 --- a/libretroshare/src/services/p3posted.cc +++ b/libretroshare/src/services/p3posted.cc @@ -1,1210 +1,589 @@ - -#include -#include -#include -#include - -#include "p3posted.h" -#include "retroshare/rsgxsflags.h" -#include "serialiser/rsposteditems.h" - -#define UPDATE_PHASE_GRP_REQUEST 1 -#define UPDATE_PHASE_MSG_REQUEST 2 -#define UPDATE_PHASE_VOTE_COMMENT_REQUEST 3 -#define UPDATE_PHASE_VOTE_COUNT 4 -#define UPDATE_PHASE_COMMENT_COUNT 5 -#define UPDATE_PHASE_COMPLETE 6 - -#define NUM_TOPICS_TO_GENERATE 5 -#define NUM_POSTS_TO_GENERATE 7 -#define NUM_VOTES_TO_GENERATE 11 -#define NUM_COMMENTS_TO_GENERATE 3 - -#define VOTE_UPDATE_PERIOD 5 // 20 seconds -#define HOT_PERIOD 4 // 4 secs for testing prob 1 to 2 days in practice - -const uint32_t RsPosted::FLAG_MSGTYPE_COMMENT = 0x0001; -const uint32_t RsPosted::FLAG_MSGTYPE_POST = 0x0002; -const uint32_t RsPosted::FLAG_MSGTYPE_VOTE = 0x0004; -const uint32_t RsPosted::FLAG_MSGTYPE_MASK = 0x000f; - -#define POSTED_MAX_SERVICE_STRING 50 - -RsPosted *rsPosted = NULL; - -RsPostedComment::RsPostedComment(const RsGxsPostedCommentItem & item) -{ - mComment = item.mComment.mComment; - mMeta = item.meta; -} - -RsPostedVote::RsPostedVote(const RsGxsPostedVoteItem& item) -{ - mDirection = item.mVote.mDirection; - mMeta = item.meta; -} - -p3Posted::p3Posted(RsGeneralDataService *gds, RsNetworkExchangeService *nes) - : RsGenExchange(gds, nes, new RsGxsPostedSerialiser(), RS_SERVICE_GXSV1_TYPE_POSTED), RsPosted(this), mPostedMutex("Posted"), - mTokenService(NULL), mGeneratingTopics(true), mGeneratingPosts(false), mRequestPhase1(true), mRequestPhase2(false), - mRequestPhase3(false), mGenerateVotesAndComments(false) -{ - mPostUpdate = false; - mLastUpdate = time(NULL); - mUpdatePhase = UPDATE_PHASE_GRP_REQUEST; - - mTokenService = RsGenExchange::getTokenService(); -} - -void p3Posted::notifyChanges(std::vector &changes) -{ - RsGxsIfaceHelper::receiveChanges(changes); -} - -void p3Posted::service_tick() -{ - -#ifndef GXS_DEV_TESTNET // DISABLE DUMMYDATA if TEST_NET - - generateTopics(); - generatePosts(); - generateVotesAndComments(); - -#endif - -// time_t now = time(NULL); -// -// if((now > (time_t) (VOTE_UPDATE_PERIOD + mLastUpdate)) && -// (mUpdatePhase == UPDATE_PHASE_GRP_REQUEST)) -// { -// mPostUpdate = true; -// mLastUpdate = time(NULL); -// } -// -// updateVotes(); -// -// processRankings(); -} - -void p3Posted::generateVotesAndComments() -{ - if(mGenerateVotesAndComments) - { - - if(mRequestPhase1) - { - // request topics then chose at random which one to use to generate a post about - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_IDS; - opts.mMsgFlagFilter = RsPosted::FLAG_MSGTYPE_POST; - opts.mMsgFlagMask = RsPosted::FLAG_MSGTYPE_MASK; - - mTokenService->requestMsgInfo(mToken, 0, opts, mGrpIds); - mRequestPhase1 = false; - mRequestPhase2 = true; - return; - } - - if(mRequestPhase2) - { - - if(mTokenService->requestStatus(mToken) == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) - { - GxsMsgIdResult msgIds; - RsGenExchange::getMsgList(mToken, msgIds); - - // for each msg generate a random number of votes and comments - - - GxsMsgIdResult::iterator mit = msgIds.begin(); - - for(; mit != msgIds.end(); mit++) - { - const RsGxsGroupId& grpId = mit->first; - std::vector& msgIdsV = mit->second; - std::vector::iterator vit = msgIdsV.begin(); - - for(; vit != msgIdsV.end(); vit++) - { - const RsGxsMessageId& msgId = *vit; - - int nVotes = rand()%NUM_VOTES_TO_GENERATE; - uint32_t token; - - for(int i=1; i < nVotes; i++) - { - RsPostedVote v; - - v.mDirection = (rand()%10 > 3) ? 0 : 1; - v.mMeta.mParentId = msgId; - v.mMeta.mGroupId = grpId; - - std::ostringstream ostrm; - ostrm << i; - - v.mMeta.mMsgName = "Vote " + ostrm.str(); - - - - submitVote(token, v); - mTokens.push_back(token); - - } - - int nComments = rand()%NUM_COMMENTS_TO_GENERATE; - - // single level comments for now - for(int i=1; i < nComments; i++) - { - RsPostedComment c; - - std::ostringstream ostrm; - ostrm << i; - - c.mComment = "Comment " + ostrm.str(); - c.mMeta.mParentId = msgId; - c.mMeta.mGroupId = grpId; - c.mMeta.mThreadId = msgId; - - submitComment(token, c); - mTokens.push_back(token); - - } - - } - } - mRequestPhase2 = false; - mRequestPhase3 = true; - } - } - - if(mRequestPhase3) - { - if(!mTokens.empty()) - { - std::vector::iterator vit = mTokens.begin(); - - for(; vit != mTokens.end(); ) - { - if(mTokenService->requestStatus(*vit) == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) - vit = mTokens.erase(vit); - else - vit++; - } - }else - { - // stop generating posts after acknowledging all the ones you created - mGeneratingPosts = false; - mRequestPhase3 = false; - } - } - - } -} - -void p3Posted::generatePosts() -{ - if(mGeneratingPosts) - { - - - if(mRequestPhase1) - { - // request topics then chose at random which one to use to generate a post about - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_IDS; - mTokenService->requestGroupInfo(mToken, 0, opts); - mRequestPhase1 = false; - return; - } - else if(!mRequestPhase2) - { - if(mTokenService->requestStatus(mToken) == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) - { - RsGenExchange::getGroupList(mToken, mGrpIds); - - mRequestPhase2 = true; - } - } - - if(mRequestPhase2) - { - // for each group generate NUM_POSTS_TO_GENERATE posts - std::list::iterator lit = mGrpIds.begin(); - - for(; lit != mGrpIds.end(); lit++) - { - RsGxsGroupId& grpId = *lit; - - for(int i=0; i < NUM_POSTS_TO_GENERATE; i++) - { - std::ostringstream ostrm; - ostrm << i; - std::string link = "link " + ostrm.str(); - - RsPostedPost post; - post.mLink = link; - post.mNotes = link; - post.mMeta.mMsgName = link; - post.mMeta.mGroupId = grpId; - - uint32_t token; - submitPost(token, post); - mTokens.push_back(token); - } - } - - mRequestPhase2 = false; - mRequestPhase3 = true; - - } - else if(mRequestPhase3) - { - - if(!mTokens.empty()) - { - std::vector::iterator vit = mTokens.begin(); - - for(; vit != mTokens.end(); ) - { - if(mTokenService->requestStatus(*vit) == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) - vit = mTokens.erase(vit); - else - vit++; - } - }else - { - // stop generating posts after acknowledging all the ones you created - mGeneratingPosts = false; - mRequestPhase3 = false; - mGenerateVotesAndComments = true; - mRequestPhase1 = true; - } - - } - } -} - -void p3Posted::generateTopics() -{ - if(mGeneratingTopics) - { - if(mRequestPhase1) - { - - - for(int i=0; i < NUM_TOPICS_TO_GENERATE; i++) - { - std::ostringstream strm; - strm << i; - std::string topicName = "Topic " + strm.str(); - - RsPostedGroup topic; - topic.mMeta.mGroupName = topicName; - - uint32_t token; - submitGroup(token, topic); - mTokens.push_back(token); - } - - mRequestPhase1 = false; - } - else - { - - if(!mTokens.empty()) - { - std::vector::iterator vit = mTokens.begin(); - - for(; vit != mTokens.end(); ) - { - if(mTokenService->requestStatus(*vit) == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) - { - RsGxsGroupId grpId; - RsGenExchange::acknowledgeTokenGrp(*vit, grpId); - vit = mTokens.erase(vit); - } - else - vit++; - } - } - else - { - mGeneratingPosts = true; - mGeneratingTopics = false; - mRequestPhase1 = true; - } - } - } -} - -bool p3Posted::getGroup(const uint32_t &token, std::vector &groups) -{ - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); vit++) - { - RsGxsPostedGroupItem* item = dynamic_cast(*vit); - RsPostedGroup grp = item->mGroup; - item->mGroup.mMeta = item->meta; - grp.mMeta = item->mGroup.mMeta; - delete item; - groups.push_back(grp); - } - } - return ok; -} - -bool p3Posted::getPost(const uint32_t &token, PostedPostResult &posts) -{ - GxsMsgDataMap msgData; - bool ok = RsGenExchange::getMsgData(token, msgData); - - if(ok) - { - GxsMsgDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); mit++) - { - RsGxsGroupId grpId = mit->first; - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); vit++) - { - RsGxsPostedPostItem* item = dynamic_cast(*vit); - - if(item) - { - RsPostedPost post = item->mPost; - post.mMeta = item->meta; - posts[grpId].push_back(post); - delete item; - }else - { - std::cerr << "Not a post Item, deleting!" << std::endl; - delete *vit; - } - } - } - } - - return ok; -} - -bool p3Posted::getComment(const uint32_t &token, PostedCommentResult &comments) -{ - GxsMsgDataMap msgData; - bool ok = RsGenExchange::getMsgData(token, msgData); - - if(ok) - { - GxsMsgDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); mit++) - { - RsGxsGroupId grpId = mit->first; - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); vit++) - { - RsGxsPostedCommentItem* item = dynamic_cast(*vit); - - if(item) - { - RsPostedComment comment = item->mComment; - comment.mMeta = item->meta; - comments[grpId].push_back(comment); - delete item; - }else - { - std::cerr << "Not a comment Item, deleting!" << std::endl; - delete *vit; - } - } - } - } - - return ok; -} - -bool p3Posted::getRelatedComment(const uint32_t& token, PostedRelatedCommentResult &comments) -{ - return RsGenExchange::getMsgRelatedDataT(token, comments); -} - -bool p3Posted::submitGroup(uint32_t &token, RsPostedGroup &group) -{ - RsGxsPostedGroupItem* grpItem = new RsGxsPostedGroupItem(); - grpItem->mGroup = group; - grpItem->meta = group.mMeta; - RsGenExchange::publishGroup(token, grpItem); - return true; -} - -bool p3Posted::submitPost(uint32_t &token, RsPostedPost &post) -{ - RsGxsPostedPostItem* postItem = new RsGxsPostedPostItem(); - postItem->mPost = post; - postItem->meta = post.mMeta; - postItem->meta.mMsgFlags |= FLAG_MSGTYPE_POST; - - RsGenExchange::publishMsg(token, postItem); - return true; -} - -bool p3Posted::submitVote(uint32_t &token, RsPostedVote &vote) -{ - RsGxsPostedVoteItem* voteItem = new RsGxsPostedVoteItem(); - voteItem->mVote = vote; - voteItem->meta = vote.mMeta; - voteItem->meta.mMsgFlags |= FLAG_MSGTYPE_VOTE; - - RsGenExchange::publishMsg(token, voteItem); - return true; -} - -bool p3Posted::submitComment(uint32_t &token, RsPostedComment &comment) -{ - RsGxsPostedCommentItem* commentItem = new RsGxsPostedCommentItem(); - commentItem->mComment = comment; - commentItem->meta = comment.mMeta; - commentItem->meta.mMsgFlags |= FLAG_MSGTYPE_COMMENT; - - RsGenExchange::publishMsg(token, commentItem); - return true; -} - - // Special Ranking Request. -bool p3Posted::requestCommentRankings(uint32_t &token, const RankType &rType, const RsGxsGrpMsgIdPair &msgId) -{ - token = RsGenExchange::generatePublicToken(); - - RsStackMutex stack(mPostedMutex); - - GxsPostedCommentRanking* gpc = new GxsPostedCommentRanking(); - gpc->msgId = msgId; - gpc->rType = rType; - gpc->pubToken = token; - - mPendingCommentRanks.insert(std::make_pair(token, gpc)); - - return true; -} - -bool p3Posted::requestPostRankings(uint32_t &token, const RankType &rType, const RsGxsGroupId &groupId) -{ - token = RsGenExchange::generatePublicToken(); - - RsStackMutex stack(mPostedMutex); - GxsPostedPostRanking* gp = new GxsPostedPostRanking(); - gp->grpId = groupId; - gp->rType = rType; - gp->pubToken = token; - gp->rankingResult.rType = gp->rType; - gp->rankingResult.grpId = gp->grpId; - - mPendingPostRanks.push_back(gp); - - return true; -} - -bool p3Posted::getPostRanking(const uint32_t &token, RsPostedPostRanking &ranking) -{ - RsStackMutex stack(mPostedMutex); - - if( mCompletePostRanks.find(token) == mCompletePostRanks.end()) return false; - - ranking = mCompletePostRanks[token]; - mCompletePostRanks.erase(token); - - // put this in service tick as it's blocking - // and likely costly - disposeOfPublicToken(token); - - return true; -} - -void p3Posted::processRankings() -{ - processPostRanks(); - - //processCommentRanks(); -} - -void p3Posted::processPostRanks() -{ - - RsStackMutex stack(mPostedMutex); - - std::vector::iterator vit = mPendingPostRanks.begin(); - - // go through all pending posts - for(; vit !=mPendingPostRanks.end(); ) - { - GxsPostedPostRanking* gp = *vit; - uint32_t token; - std::list grpL; - grpL.push_back(gp->grpId); - - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_META; - opts.mMsgFlagFilter = RsPosted::FLAG_MSGTYPE_POST; - opts.mMsgFlagMask = RsPosted::FLAG_MSGTYPE_MASK; - opts.mOptions = RS_TOKREQOPT_MSG_LATEST | RS_TOKREQOPT_MSG_THREAD; - - RsGenExchange::getTokenService()->requestMsgInfo(token, GXS_REQUEST_TYPE_GROUP_DATA, opts, grpL); - - - gp->reqToken = token; - - vit = mPendingPostRanks.erase(vit); - mCompletionPostRanks.push_back(gp); - } - - mPendingPostRanks.clear(); - - vit = mCompletionPostRanks.begin(); - - for(; vit != mCompletionPostRanks.end(); ) - { - bool ok = false; - GxsPostedPostRanking *gp = *vit; - uint32_t status = mTokenService->requestStatus(gp->reqToken); - - if(RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE == status) - { - ok = completePostedPostCalc(gp); - - if(ok) - { - mCompletePostRanks.insert( - std::make_pair(gp->pubToken, gp->rankingResult)); - } - } - else if(RsTokenService::GXS_REQUEST_V2_STATUS_FAILED - == status) - { - discardCalc(gp->reqToken); - ok = false; - }else - { - vit++; - continue; - } - - if(ok) - { - updatePublicRequestStatus(gp->pubToken, RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE); - } - else - { - updatePublicRequestStatus(gp->pubToken, RsTokenService::GXS_REQUEST_V2_STATUS_FAILED); - } - - vit = mCompletionPostRanks.erase(vit); - delete gp; - } - -} - -void p3Posted::discardCalc(const uint32_t &token) -{ - mTokenService->cancelRequest(token); -} - -bool PostedTopScoreComp(const PostedScore& i, const PostedScore& j) -{ - int32_t i_score = (int32_t)i.upVotes - (int32_t)i.downVotes; - int32_t j_score = (int32_t)j.upVotes - (int32_t)j.downVotes; - - if(i_score == j_score){ - return i.date > j.date; - }else - { - return i_score > j_score; - } -} - - -bool PostedHotScoreComp(const PostedScore& i, const PostedScore& j) -{ - int32_t i_score = (int32_t)i.upVotes - (int32_t)i.downVotes; - int32_t j_score = (int32_t)j.upVotes - (int32_t)j.downVotes; - - time_t now = time(NULL); - long long td = now - i.date; - - if(td == 0) - { - return i.date > j.date; - } - - int y; - if(i_score > 0) - { - y = 1; - }else if(i_score == 0) - { - y = 0; - }else - { - y = -1; - } - - double z; - if(abs(i_score) >= 1) - { - z = abs(i_score); - } - else - { - z = 1; - } - - double i_hot_score = log10(z) + ( ((double)(y*td)) - / HOT_PERIOD ); - - if(j_score > 0) - { - y = 1; - }else if(j_score == 0) - { - y = 0; - }else - { - y = -1; - } - - - if(abs(j_score) >= 1) - { - z = abs(j_score); - } - else - { - z = 1; - } - - td = now - j.date; - - double j_hot_score = log10(z) + ( ((double)(y*td)) - / HOT_PERIOD ); - if(i_hot_score == j_hot_score) - { - return i.date > j.date; - }else - { - return i_hot_score > j_hot_score; - } - -} - -bool PostedNewScoreComp(const PostedScore& i, const PostedScore& j) -{ - return i.date > j.date; -} - -bool PostedBestScoreComp(const PostedScore& i, const PostedScore& j) -{ - -// n = ups + downs if n == 0: return 0 z = 1.0 -// #1.0 = 85%, 1.6 = 95% phat = float(ups) -// / n return sqrt(phat+z*z/(2*n)-z*((phat*(1-phat)+z*z/(4*n))/n))/(1+z*z/n) -// def confidence(ups, downs): if ups + downs == 0: return 0 else: -// return _confidence(ups, downs) - // very expensive!! - - static float z = 1.0; - float phat; - - float i_score; - int n = i.upVotes + (-i.downVotes); - if(n==0) - i_score = 0.; - else - { - phat = float(i.upVotes); - i_score = sqrt(phat+z*z/(2*n)-z*((phat*(1-phat)+z*z/(4*n))/n))/(1+z*z/n); - } - - float j_score; - n = j.upVotes + (-j.downVotes); - if(n==0) - j_score = 0.; - else - { - phat = float(j.upVotes); - j_score = sqrt(phat+z*z/(2*n)-z*((phat*(1-phat)+z*z/(4*n))/n))/(1+z*z/n); - } - - if(j_score == i_score) - return i.date < j.date; - else - return i_score < j_score; -} - -bool p3Posted::completePostedPostCalc(GxsPostedPostRanking *gpp) -{ - GxsMsgMetaMap msgMetas; - - if(getMsgMeta(gpp->reqToken, msgMetas)) - { - std::vector& msgMetaV = msgMetas[gpp->grpId]; - switch(gpp->rType) - { - case NewRankType: - calcPostedPostRank(msgMetaV, gpp->rankingResult.ranking, PostedNewScoreComp); - break; - case HotRankType: - calcPostedPostRank(msgMetaV, gpp->rankingResult.ranking, PostedHotScoreComp); - break; - case TopRankType: - calcPostedPostRank(msgMetaV, gpp->rankingResult.ranking, PostedTopScoreComp); - break; - default: - std::cerr << "Unknown ranking tpye: " << gpp->rType << std::endl; - break; - } - return true; - }else - return false; -} - - -void p3Posted::calcPostedPostRank(const std::vector msgMeta, PostedRanking &ranking, - bool comp(const PostedScore &, const PostedScore &)) const -{ - - std::vector::const_iterator cit = msgMeta.begin(); - std::vector scores; - - for(; cit != msgMeta.end(); cit++) - { - const RsMsgMetaData& m = *cit; - uint32_t upVotes, downVotes, nComments; - retrieveScores(m.mServiceString, upVotes, downVotes, nComments); - - PostedScore c; - c.upVotes = upVotes; - c.downVotes = downVotes; - c.date = m.mPublishTs; - c.msgId = m.mMsgId; - scores.push_back(c); - } - - std::sort(scores.begin(), scores.end(), comp); - - - for(int i = 0; i < scores.size(); i++) - { - const PostedScore& p = scores[i]; - ranking.insert(std::make_pair(i+1, p.msgId)); - } -} - -void p3Posted::calcPostedCommentsRank(const std::map > &msgBranches, - std::map& msgMetas, PostedRanking &ranking, bool comp(const PostedScore &, const PostedScore &)) const -{ - - std::map >::const_iterator cit = msgBranches.begin(); - - for(; cit != msgBranches.end(); cit++) - { - const std::vector& branch = cit->second; - std::vector scores; - - std::vector::const_iterator vit = branch.begin(); - - for(; vit != branch.end(); vit++) - { - - std::map::iterator mit = - msgMetas.find(*vit); - - if(mit != msgMetas.end()) - { - uint32_t upVotes, downVotes, nComments; - - const RsMsgMetaData& m = mit->second; - retrieveScores(m.mServiceString, upVotes, downVotes, nComments); - - PostedScore c; - c.upVotes = upVotes; - c.downVotes = downVotes; - c.date = m.mPublishTs; - scores.push_back(c); - } - } - - std::sort(scores.begin(), scores.end(), comp); - - std::vector::iterator cvit = scores.begin(); - - int i = 1; - for(; cvit != scores.end(); ++cvit) - { - const PostedScore& p = *cvit; - ranking.insert(std::make_pair(i++, p.msgId)); - } - } - -} - -void p3Posted::completePostedCommentRanking(GxsPostedCommentRanking *gpc) -{ - GxsMsgRelatedMetaMap msgMetas; - - if(getMsgRelatedMeta(gpc->reqToken, msgMetas)) - { - - // create map of msgs - std::vector& msgV = msgMetas[gpc->msgId]; - std::map > msgBranches; - std::map remappedMsgMeta; - - std::vector::iterator vit = msgV.begin(); - - for(; vit != msgV.end(); vit++) - { - const RsMsgMetaData& m = *vit; - - if(!m.mParentId.empty()) - { - msgBranches[m.mParentId].push_back(m.mMsgId); - } - - remappedMsgMeta.insert(std::make_pair(m.mMsgId, m)); - } - - switch(gpc->rType) - { - case HotRankType: - calcPostedCommentsRank(msgBranches, remappedMsgMeta, gpc->result, PostedBestScoreComp); - break; - case TopRankType: - calcPostedCommentsRank(msgBranches, remappedMsgMeta, gpc->result, PostedTopScoreComp); - break; - case NewRankType: - calcPostedCommentsRank(msgBranches, remappedMsgMeta, gpc->result, PostedNewScoreComp); - break; - default: - std::cerr << "Unknown Rank type" << gpc->rType << std::endl; - break; - } - } -} - -bool p3Posted::retrieveScores(const std::string &serviceString, uint32_t &upVotes, uint32_t& downVotes, uint32_t& nComments) const -{ - if (3 == sscanf(serviceString.c_str(), "%d %d %d", &upVotes, &downVotes, &nComments)) - { - return true; - } - - return false; -} - -bool p3Posted::storeScores(std::string &serviceString, uint32_t &upVotes, uint32_t downVotes, uint32_t nComments) const -{ - char line[POSTED_MAX_SERVICE_STRING]; - - bool ok = snprintf(line, POSTED_MAX_SERVICE_STRING, "%d %d %d", upVotes, downVotes, nComments) > -1; - - serviceString = line; - return ok; -} -void p3Posted::processCommentRanks() -{ - -} - - - -void p3Posted::updateVotes() -{ - // any request failure stops update process - - if(mPostUpdate) - { - switch(mUpdatePhase) - { - case UPDATE_PHASE_GRP_REQUEST: - { - mPostUpdate = updateRequestGroups(); - break; - } - case UPDATE_PHASE_MSG_REQUEST: - { - mPostUpdate = updateRequestMessages(); - break; - } - case UPDATE_PHASE_VOTE_COMMENT_REQUEST: - { - mPostUpdate = updateRequestVotesComments(); - break; - } - case UPDATE_PHASE_VOTE_COUNT: - { - mPostUpdate = updateCompleteVotes(); - break; - } - case UPDATE_PHASE_COMMENT_COUNT: - { - mPostUpdate = updateCompleteComments(); - break; - } - case UPDATE_PHASE_COMPLETE: - { - updateComplete(); - break; - } - default: - { - std::cerr << "Unknown update phase, we should not be here!" << std::endl; - break; - } - } - } -} - -bool p3Posted::updateRequestGroups() -{ - - - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_IDS; - // opts.mSubscribeMask = GXS_SERV::GROUP_SUBSCRIBE_MASK; -// opts.mSubscribeFilter = GXS_SERV::GROUP_SUBSCRIBE_ADMIN | -// GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED; - mTokenService->requestGroupInfo(mUpdateRequestGroup, 0, opts); - - mUpdatePhase = UPDATE_PHASE_MSG_REQUEST; - - return true ; -} - -bool p3Posted::updateRequestMessages() -{ - - uint32_t status = mTokenService->requestStatus(mUpdateRequestGroup); - - if(status == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) - { - std::list grpIds; - RsGenExchange::getGroupList(mUpdateRequestGroup, grpIds); - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_META; - opts.mOptions = RS_TOKREQOPT_MSG_LATEST | RS_TOKREQOPT_MSG_THREAD; - mTokenService->requestMsgInfo(mUpdateRequestMessages, 0, opts, grpIds); - mUpdatePhase = UPDATE_PHASE_VOTE_COMMENT_REQUEST; - return true; - } - else if(status == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED) - { - mTokenService->cancelRequest(mUpdateRequestGroup); - return false; - } - - return true; -} - -bool p3Posted::updateRequestVotesComments() -{ - - uint32_t status = mTokenService->requestStatus(mUpdateRequestMessages); - - if(status == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) - { - - RsGenExchange::getMsgMeta(mUpdateRequestMessages, mMsgMetaUpdate); - - std::vector msgIds; - - GxsMsgMetaMap::iterator mit = mMsgMetaUpdate.begin(); - - for(; mit != mMsgMetaUpdate.end(); mit++) - { - std::vector& msgIdV = mit->second; - std::vector::const_iterator cit = msgIdV.begin(); - - for(; cit != msgIdV.end(); cit++) - msgIds.push_back(std::make_pair(mit->first, cit->mMsgId)); - } - - RsTokReqOptions opts; - // only need ids for comments - - opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_IDS; - opts.mOptions = RS_TOKREQOPT_MSG_LATEST | RS_TOKREQOPT_MSG_PARENT; - opts.mMsgFlagMask = RsPosted::FLAG_MSGTYPE_MASK; - opts.mMsgFlagFilter = RsPosted::FLAG_MSGTYPE_COMMENT; - mTokenService->requestMsgRelatedInfo(mUpdateRequestComments, 0, opts, msgIds); - - // need actual data for votes - opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA; - opts.mOptions = RS_TOKREQOPT_MSG_LATEST | RS_TOKREQOPT_MSG_PARENT; - opts.mMsgFlagMask = RsPosted::FLAG_MSGTYPE_MASK; - opts.mMsgFlagFilter = RsPosted::FLAG_MSGTYPE_VOTE; - mTokenService->requestMsgRelatedInfo(mUpdateRequestVotes, 0, opts, msgIds); - - mUpdatePhase = UPDATE_PHASE_VOTE_COUNT; - - return true; - } - else if(status == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED) - { - mTokenService->cancelRequest(mUpdateRequestMessages); - return false; - } - - return true; -} - - -bool p3Posted::updateCompleteVotes() -{ - uint32_t status = mTokenService->requestStatus(mUpdateRequestVotes); - - if(status == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) - { - std::map > votes; - getMsgRelatedDataT(mUpdateRequestVotes, - votes); - - // now for each msg count the number of votes and thats it - - std::map >::iterator mit = votes.begin(); - - for(; mit != votes.end(); mit++) - { - const std::vector& v = mit->second; - std::vector::const_iterator cit = v.begin(); - - for(; cit != v.end(); cit++) - { - const RsPostedVote& vote = *cit; - - if(vote.mDirection) - { - mMsgCounts[mit->first].upVotes++; - }else - { - mMsgCounts[mit->first].downVotes++; - } - } - } - mUpdatePhase = UPDATE_PHASE_COMMENT_COUNT; - } - else if(status == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED) - { - mTokenService->cancelRequest(mUpdateRequestVotes); - return false; - } - return true; -} - -bool p3Posted::updateCompleteComments() -{ - uint32_t status = mTokenService->requestStatus(mUpdateRequestComments); - - if(status == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) - { - MsgRelatedIdResult commentIds; - RsGenExchange::getMsgRelatedList(mUpdateRequestComments, commentIds); - - // now for each msg count the number of votes and thats it - - MsgRelatedIdResult::iterator mit = commentIds.begin(); - - for(; mit != commentIds.end(); mit++) - { - const std::vector& v = mit->second; - std::vector::const_iterator cit = v.begin(); - - for(; cit != v.end(); cit++) - { - mMsgCounts[mit->first].commentCount++; - } - } - mUpdatePhase = UPDATE_PHASE_COMPLETE; - } - else if(status == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED) - { - mTokenService->cancelRequest(mUpdateRequestComments); - return false; - } - return true; -} - -bool p3Posted::updateComplete() -{ - // now compare with msg meta to see what currently store there - - GxsMsgMetaMap::iterator mit = mMsgMetaUpdate.begin(); - - for(; mit != mMsgMetaUpdate.end(); mit++) - { - const std::vector& msgMetaV = mit->second; - std::vector::const_iterator cit = msgMetaV.begin(); - - for(; cit != msgMetaV.end(); cit++) - { - const RsMsgMetaData& msgMeta = *cit; - uint32_t upVotes, downVotes, nComments; - retrieveScores(msgMeta.mServiceString, upVotes, downVotes, nComments); - - RsGxsGrpMsgIdPair msgId; - msgId.first = mit->first; - msgId.second = msgMeta.mMsgId; - PostedScore& sc = mMsgCounts[msgId]; - - bool changed = (sc.upVotes != upVotes) || (sc.downVotes != downVotes) - || (sc.commentCount != nComments); - - if(changed) - { - std::string servStr; - storeScores(servStr, sc.upVotes, sc.downVotes, sc.commentCount); - uint32_t token; - setMsgServiceString(token, msgId, servStr); - mChangeTokens.push_back(token); - } - else - { - mMsgCounts.erase(msgId); - } - } - } - - mPostUpdate = false; - mUpdatePhase = UPDATE_PHASE_GRP_REQUEST; - - if(!mMsgCounts.empty()) - { - RsGxsMsgChange* msgChange = new RsGxsMsgChange(); - - std::map::iterator mit_c = mMsgCounts.begin(); - - for(; mit_c != mMsgCounts.end(); mit_c++) - { - const RsGxsGrpMsgIdPair& msgId = mit_c->first; - msgChange->msgChangeMap[msgId.first].push_back(msgId.second); - } - - std::vector n; - n.push_back(msgChange); - notifyChanges(n); - - mMsgCounts.clear(); - } - - - return true ; -} +/* + * libretroshare/src/services p3posted.cc + * + * Posted interface for RetroShare. + * + * Copyright 2012-2012 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "services/p3posted.h" +#include "serialiser/rsposteditems.h" + +#include + + +#include "retroshare/rsgxsflags.h" +#include + +// For Dummy Msgs. +#include "util/rsrandom.h" +#include "util/rsstring.h" + +/**** + * #define POSTED_DEBUG 1 + ****/ +#define POSTED_DEBUG 1 + +RsPosted *rsPosted = NULL; + +const uint32_t RsPosted::FLAG_MSGTYPE_POST = 0x0001; +const uint32_t RsPosted::FLAG_MSGTYPE_MASK = 0x000f; + + +#define POSTED_TESTEVENT_DUMMYDATA 0x0001 +#define DUMMYDATA_PERIOD 60 // long enough for some RsIdentities to be generated. + +/********************************************************************************/ +/******************* Startup / Tick ******************************************/ +/********************************************************************************/ + +p3Posted::p3Posted(RsGeneralDataService *gds, RsNetworkExchangeService *nes, RsGixs* gixs) + : RsGenExchange(gds, nes, new RsGxsPostedSerialiser(), RS_SERVICE_GXSV1_TYPE_POSTED, gixs, postedAuthenPolicy()), RsPosted(this) +{ + // For Dummy Msgs. + mGenActive = false; + mCommentService = new p3GxsCommentService(this, RS_SERVICE_GXSV1_TYPE_POSTED); + + // Test Data disabled in repo. + //RsTickEvent::schedule_in(POSTED_TESTEVENT_DUMMYDATA, DUMMYDATA_PERIOD); +} + + + +uint32_t p3Posted::postedAuthenPolicy() +{ + uint32_t policy = 0; + uint32_t flag = 0; + + flag = GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN; + //RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS); + RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS); + RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS); + + flag = GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN; + //RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS); + RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS); + RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS); + + flag = GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN; + RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS); + RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS); + RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS); + + flag = GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; + RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS); + RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS); + RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS); + + return policy; +} + + + + + +void p3Posted::notifyChanges(std::vector &changes) +{ + RsGxsIfaceHelper::receiveChanges(changes); +} + +void p3Posted::service_tick() +{ + dummy_tick(); + RsTickEvent::tick_events(); + return; +} + +bool p3Posted::getGroupData(const uint32_t &token, std::vector &groups) +{ + std::vector grpData; + bool ok = RsGenExchange::getGroupData(token, grpData); + + if(ok) + { + std::vector::iterator vit = grpData.begin(); + + for(; vit != grpData.end(); vit++) + { + RsGxsPostedGroupItem* item = dynamic_cast(*vit); + RsPostedGroup grp = item->mGroup; + item->mGroup.mMeta = item->meta; + grp.mMeta = item->mGroup.mMeta; + delete item; + groups.push_back(grp); + } + } + return ok; +} + +bool p3Posted::getPostData(const uint32_t &token, std::vector &msgs) +{ + GxsMsgDataMap msgData; + bool ok = RsGenExchange::getMsgData(token, msgData); + + if(ok) + { + GxsMsgDataMap::iterator mit = msgData.begin(); + + for(; mit != msgData.end(); mit++) + { + RsGxsGroupId grpId = mit->first; + std::vector& msgItems = mit->second; + std::vector::iterator vit = msgItems.begin(); + + for(; vit != msgItems.end(); vit++) + { + RsGxsPostedPostItem* item = dynamic_cast(*vit); + + if(item) + { + RsPostedPost msg = item->mPost; + msg.mMeta = item->meta; + msgs.push_back(msg); + delete item; + } + else + { + std::cerr << "Not a PostedPostItem, deleting!" << std::endl; + delete *vit; + } + } + } + } + + return ok; +} + + +bool p3Posted::getRelatedPosts(const uint32_t &token, std::vector &msgs) +{ + GxsMsgRelatedDataMap msgData; + bool ok = RsGenExchange::getMsgRelatedData(token, msgData); + + if(ok) + { + GxsMsgRelatedDataMap::iterator mit = msgData.begin(); + + for(; mit != msgData.end(); mit++) + { + std::vector& msgItems = mit->second; + std::vector::iterator vit = msgItems.begin(); + + for(; vit != msgItems.end(); vit++) + { + RsGxsPostedPostItem* item = dynamic_cast(*vit); + + if(item) + { + RsPostedPost msg = item->mPost; + msg.mMeta = item->meta; + msgs.push_back(msg); + delete item; + } + else + { + std::cerr << "Not a PostedPostItem, deleting!" << std::endl; + delete *vit; + } + } + } + } + + return ok; +} + + +/********************************************************************************************/ +/********************************************************************************************/ +/********************************************************************************************/ + +bool p3Posted::requestPostRankings(uint32_t &token, const RankType &rType, uint32_t count, uint32_t page_no, const RsGxsGroupId &groupId) +{ + std::cerr << "p3Posted::requestPostRankings() doing boring call for now"; + std::cerr << std::endl; + + /* turn it into a boring Post Request for the moment */ + std::list groups; + groups.push_back(groupId); + + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; + opts.mMsgFlagFilter = RsPosted::FLAG_MSGTYPE_POST; + opts.mMsgFlagMask = RsPosted::FLAG_MSGTYPE_MASK; + opts.mOptions = RS_TOKREQOPT_MSG_LATEST | RS_TOKREQOPT_MSG_THREAD; + + RsGenExchange::getTokenService()->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, groups); + + + /* what this should be doing ... + * - Grab Public Token. + * Trigger search for Post MetaData. + * Score & Sort MetaData. + * get Final list. + * retrieve PostData. + */ + return true; +} + + +bool p3Posted::getPostRanking(const uint32_t &token, std::vector &msgs) +{ + std::cerr << "p3Posted::getPostRanking() doing boring call for now"; + std::cerr << std::endl; + + /* for the moment - this just returns the posts */ + return getPostData(token, msgs); +} + + + + + + + +/********************************************************************************************/ +/********************************************************************************************/ +/********************************************************************************************/ + +bool p3Posted::createGroup(uint32_t &token, RsPostedGroup &group) +{ + std::cerr << "p3Posted::createGroup()" << std::endl; + + RsGxsPostedGroupItem* grpItem = new RsGxsPostedGroupItem(); + grpItem->mGroup = group; + grpItem->meta = group.mMeta; + + RsGenExchange::publishGroup(token, grpItem); + return true; +} + + +bool p3Posted::createPost(uint32_t &token, RsPostedPost &msg) +{ + std::cerr << "p3Posted::createPost() GroupId: " << msg.mMeta.mGroupId; + std::cerr << std::endl; + + RsGxsPostedPostItem* msgItem = new RsGxsPostedPostItem(); + msgItem->mPost = msg; + msgItem->meta = msg.mMeta; + + RsGenExchange::publishMsg(token, msgItem); + return true; +} + + +/********************************************************************************************/ +/********************************************************************************************/ + +void p3Posted::setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) +{ + uint32_t mask = GXS_SERV::GXS_MSG_STATUS_UNREAD | GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; + uint32_t status = GXS_SERV::GXS_MSG_STATUS_UNREAD; + if (read) + { + status = 0; + } + + setMsgStatusFlags(token, msgId, status, mask); + +} + +/********************************************************************************************/ +/********************************************************************************************/ + +/* so we need the same tick idea as wiki for generating dummy channels + */ + +#define MAX_GEN_GROUPS 5 +#define MAX_GEN_MESSAGES 100 + +std::string p3Posted::genRandomId() +{ + std::string randomId; + for(int i = 0; i < 20; i++) + { + randomId += (char) ('a' + (RSRandom::random_u32() % 26)); + } + + return randomId; +} + +bool p3Posted::generateDummyData() +{ + mGenCount = 0; + mGenRefs.resize(MAX_GEN_MESSAGES); + + std::string groupName; + rs_sprintf(groupName, "TestTopic_%d", mGenCount); + + std::cerr << "p3Posted::generateDummyData() Starting off with Group: " << groupName; + std::cerr << std::endl; + + /* create a new group */ + generateGroup(mGenToken, groupName); + + mGenActive = true; + + return true; +} + + +void p3Posted::dummy_tick() +{ + /* check for a new callback */ + + if (mGenActive) + { + std::cerr << "p3Posted::dummyTick() AboutActive"; + std::cerr << std::endl; + + uint32_t status = RsGenExchange::getTokenService()->requestStatus(mGenToken); + if (status != RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) + { + std::cerr << "p3Posted::dummy_tick() Status: " << status; + std::cerr << std::endl; + + if (status == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED) + { + std::cerr << "p3Posted::dummy_tick() generateDummyMsgs() FAILED"; + std::cerr << std::endl; + mGenActive = false; + } + return; + } + + if (mGenCount < MAX_GEN_GROUPS) + { + /* get the group Id */ + RsGxsGroupId groupId; + RsGxsMessageId emptyId; + if (!acknowledgeTokenGrp(mGenToken, groupId)) + { + std::cerr << " ERROR "; + std::cerr << std::endl; + mGenActive = false; + return; + } + + std::cerr << "p3Posted::dummy_tick() Acknowledged GroupId: " << groupId; + std::cerr << std::endl; + + PostedDummyRef ref(groupId, emptyId, emptyId); + mGenRefs[mGenCount] = ref; + } + else if (mGenCount < MAX_GEN_MESSAGES) + { + /* get the msg Id, and generate next snapshot */ + RsGxsGrpMsgIdPair msgId; + if (!acknowledgeTokenMsg(mGenToken, msgId)) + { + std::cerr << " ERROR "; + std::cerr << std::endl; + mGenActive = false; + return; + } + + std::cerr << "p3Posted::dummy_tick() Acknowledged "; + std::cerr << std::endl; + + /* store results for later selection */ + + PostedDummyRef ref(msgId.first, mGenThreadId, msgId.second); + mGenRefs[mGenCount] = ref; + } + else + { + std::cerr << "p3Posted::dummy_tick() Finished"; + std::cerr << std::endl; + + /* done */ + mGenActive = false; + return; + } + + mGenCount++; + + if (mGenCount < MAX_GEN_GROUPS) + { + std::string groupName; + rs_sprintf(groupName, "TestTopic_%d", mGenCount); + + std::cerr << "p3Posted::dummy_tick() Generating Group: " << groupName; + std::cerr << std::endl; + + /* create a new group */ + generateGroup(mGenToken, groupName); + } + else + { + /* create a new message */ + uint32_t idx = (uint32_t) (mGenCount * RSRandom::random_f32()); + PostedDummyRef &ref = mGenRefs[idx]; + + RsGxsGroupId grpId = ref.mGroupId; + RsGxsMessageId parentId = ref.mMsgId; + mGenThreadId = ref.mThreadId; + if (mGenThreadId.empty()) + { + mGenThreadId = parentId; + } + + std::cerr << "p3Posted::dummy_tick() Generating Msg ... "; + std::cerr << " GroupId: " << grpId; + std::cerr << " ThreadId: " << mGenThreadId; + std::cerr << " ParentId: " << parentId; + std::cerr << std::endl; + + if (parentId.empty()) + { + generatePost(mGenToken, grpId); + } + else + { + generateComment(mGenToken, grpId, parentId, mGenThreadId); + } + } + } +} + + +bool p3Posted::generatePost(uint32_t &token, const RsGxsGroupId &grpId) +{ + RsPostedPost msg; + + std::string rndId = genRandomId(); + + rs_sprintf(msg.mNotes, "Posted Msg: GroupId: %s, some randomness: %s", + grpId.c_str(), rndId.c_str()); + + msg.mMeta.mMsgName = msg.mNotes; + + msg.mMeta.mGroupId = grpId; + msg.mMeta.mThreadId = ""; + msg.mMeta.mParentId = ""; + + msg.mMeta.mMsgStatus = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED | GXS_SERV::GXS_MSG_STATUS_UNREAD; + + /* chose a random Id to sign with */ + std::list ownIds; + std::list::iterator it; + + rsIdentity->getOwnIds(ownIds); + + uint32_t idx = (uint32_t) (ownIds.size() * RSRandom::random_f32()); + int i = 0; + for(it = ownIds.begin(); (it != ownIds.end()) && (i < idx); it++, i++); + + if (it != ownIds.end()) + { + std::cerr << "p3Posted::generateMessage() Author: " << *it; + std::cerr << std::endl; + msg.mMeta.mAuthorId = *it; + } + else + { + std::cerr << "p3Posted::generateMessage() No Author!"; + std::cerr << std::endl; + } + + createPost(token, msg); + + return true; +} + + +bool p3Posted::generateComment(uint32_t &token, const RsGxsGroupId &grpId, const RsGxsMessageId &parentId, const RsGxsMessageId &threadId) +{ + RsGxsComment msg; + + std::string rndId = genRandomId(); + + rs_sprintf(msg.mComment, "Posted Comment: GroupId: %s, ThreadId: %s, ParentId: %s + some randomness: %s", + grpId.c_str(), threadId.c_str(), parentId.c_str(), rndId.c_str()); + + msg.mMeta.mMsgName = msg.mComment; + + msg.mMeta.mGroupId = grpId; + msg.mMeta.mThreadId = threadId; + msg.mMeta.mParentId = parentId; + + msg.mMeta.mMsgStatus = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED | GXS_SERV::GXS_MSG_STATUS_UNREAD; + + /* chose a random Id to sign with */ + std::list ownIds; + std::list::iterator it; + + rsIdentity->getOwnIds(ownIds); + + uint32_t idx = (uint32_t) (ownIds.size() * RSRandom::random_f32()); + int i = 0; + for(it = ownIds.begin(); (it != ownIds.end()) && (i < idx); it++, i++); + + if (it != ownIds.end()) + { + std::cerr << "p3Posted::generateMessage() Author: " << *it; + std::cerr << std::endl; + msg.mMeta.mAuthorId = *it; + } + else + { + std::cerr << "p3Posted::generateMessage() No Author!"; + std::cerr << std::endl; + } + + createComment(token, msg); + + return true; +} + + +bool p3Posted::generateGroup(uint32_t &token, std::string groupName) +{ + /* generate a new group */ + RsPostedGroup group; + group.mMeta.mGroupName = groupName; + + createGroup(token, group); + + return true; +} + + + // Overloaded from RsTickEvent for Event callbacks. +void p3Posted::handle_event(uint32_t event_type, const std::string &elabel) +{ + std::cerr << "p3Posted::handle_event(" << event_type << ")"; + std::cerr << std::endl; + + // stuff. + switch(event_type) + { + case POSTED_TESTEVENT_DUMMYDATA: + generateDummyData(); + break; + + default: + /* error */ + std::cerr << "p3Posted::handle_event() Unknown Event Type: " << event_type; + std::cerr << std::endl; + break; + } +} + diff --git a/libretroshare/src/services/p3posted.h b/libretroshare/src/services/p3posted.h index 0996208e5..bf7d1e04a 100644 --- a/libretroshare/src/services/p3posted.h +++ b/libretroshare/src/services/p3posted.h @@ -1,175 +1,153 @@ -#ifndef P3POSTED_H -#define P3POSTED_H - -#include - -#include "retroshare/rsposted.h" -#include "gxs/rsgenexchange.h" - - -class GxsPostedPostRanking -{ -public: - - uint32_t pubToken; - uint32_t reqToken; - RsPosted::RankType rType; - RsGxsGroupId grpId; - RsPostedPostRanking rankingResult; -}; - -class GxsPostedCommentRanking -{ -public: - - uint32_t pubToken; - uint32_t reqToken; - RsPosted::RankType rType; - RsGxsGrpMsgIdPair msgId; - PostedRanking result; -}; - -class PostedScore { -public: - - PostedScore() : upVotes(0), downVotes(0), commentCount(0), date(0) {} - uint32_t upVotes, downVotes; - uint32_t commentCount; - time_t date; - RsGxsMessageId msgId; -}; - - - -class p3Posted : public RsGenExchange, public RsPosted -{ -public: - p3Posted(RsGeneralDataService* gds, RsNetworkExchangeService* nes); - -protected: - - /*! - * This confirms this class as an abstract one that \n - * should not be instantiated \n - * The deriving class should implement this function \n - * as it is called by the backend GXS system to \n - * update client of changes which should \n - * instigate client to retrieve new content from the system - * @param changes the changes that have occured to data held by this service - */ - void notifyChanges(std::vector& changes) ; - - void service_tick(); - -public: - - void generateTopics(); - /*! - * Exists solely for testing - */ - void generatePosts(); - - /*! - * Exists solely for testing - * Generates random votes to existing posts - * in the system - */ - void generateVotesAndComments(); - -public: - - bool getGroup(const uint32_t &token, std::vector &group); - bool getPost(const uint32_t &token, PostedPostResult& posts) ; - bool getComment(const uint32_t &token, PostedCommentResult& comments) ; - bool getRelatedComment(const uint32_t& token, PostedRelatedCommentResult &comments); - bool getPostRanking(const uint32_t &token, RsPostedPostRanking &ranking); - - bool submitGroup(uint32_t &token, RsPostedGroup &group); - bool submitPost(uint32_t &token, RsPostedPost &post); - bool submitVote(uint32_t &token, RsPostedVote &vote); - bool submitComment(uint32_t &token, RsPostedComment &comment) ; - // Special Ranking Request. - bool requestPostRankings(uint32_t &token, const RankType &rType, const RsGxsGroupId &groupId); - bool requestCommentRankings(uint32_t &token, const RankType &rType, const RsGxsGrpMsgIdPair &msgId); - - bool retrieveScores(const std::string& serviceString, uint32_t& upVotes, uint32_t& downVotes, uint32_t& nComments) const; - -private: - - /* Functions for processing rankings */ - - void processRankings(); - void processPostRanks(); - void processCommentRanks(); - void discardCalc(const uint32_t& token); - bool completePostedPostCalc(GxsPostedPostRanking* gpp); - void completePostedCommentRanking(GxsPostedCommentRanking* gpc); - - bool storeScores(std::string& serviceString, uint32_t& upVotes, uint32_t downVotes, uint32_t nComments) const; - - // for posts - void calcPostedPostRank(const std::vector, PostedRanking& ranking, bool com(const PostedScore& i, const PostedScore &j)) const; - - // for comments - void calcPostedCommentsRank(const std::map >& msgBranches, std::map& msgMetas, - PostedRanking& ranking, bool com(const PostedScore& i, const PostedScore &j)) const; - - /* Functions for maintaing vote counts in meta data */ - - /*! - * Update votes should only be called when a vote comes in - * Several phases to calculating votes. - * First get all messages for groups which you are subscribed - * Then for these messages get all the votes accorded to them - * Then do the calculation and update messages - * Also stores updates for messages which have new scores - */ - void updateVotes(); - bool updateRequestGroups(); - bool updateRequestMessages(); - bool updateRequestVotesComments(); - bool updateCompleteVotes(); - bool updateCompleteComments(); - - /*! - * The aim of this is create notifications - * for the UI of changes to a post if their vote - * or comment count has changed - */ - bool updateComplete(); - - -private: - - // for calculating ranks - std::vector mPendingPostRanks; - std::vector mCompletionPostRanks; - std::map mCompletePostRanks; - std::map mPendingCommentRanks; - std::map mPendingCalculationCommentRanks; - - // for maintaining vote counts in msg meta - uint32_t mUpdateRequestGroup, mUpdateRequestMessages, mUpdateRequestComments, mUpdateRequestVotes; - bool mPostUpdate; - uint32_t mUpdatePhase; - std::vector mMsgsPendingUpdate; - time_t mLastUpdate; - GxsMsgMetaMap mMsgMetaUpdate; - std::map mMsgCounts; - std::vector mChangeTokens; - - RsTokenService* mTokenService; - RsMutex mPostedMutex; - - - // for data generation - - bool mGeneratingPosts, mGeneratingTopics, - mRequestPhase1, mRequestPhase2, mRequestPhase3, mGenerateVotesAndComments; - std::vector mTokens; - uint32_t mToken; - std::list mGrpIds; - -}; - -#endif // P3POSTED_H +/* + * libretroshare/src/services: p3posted.h + * + * GxsChannel interface for RetroShare. + * + * Copyright 2012-2013 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef P3_POSTED_SERVICE_HEADER +#define P3_POSTED_SERVICE_HEADER + + +#include "retroshare/rsposted.h" +#include "services/p3gxscommon.h" +#include "gxs/rsgenexchange.h" + +#include "util/rstickevent.h" + +#include +#include + +/* + * + */ + +class p3Posted: public RsGenExchange, public RsPosted, + public RsTickEvent /* only needed for testing - remove after */ +{ + public: + + p3Posted(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs* gixs); + +virtual void service_tick(); + + protected: + + +virtual void notifyChanges(std::vector& changes); + + // Overloaded from RsTickEvent. +virtual void handle_event(uint32_t event_type, const std::string &elabel); + + public: + +virtual bool getGroupData(const uint32_t &token, std::vector &groups); +virtual bool getPostData(const uint32_t &token, std::vector &posts); + +virtual bool getRelatedPosts(const uint32_t &token, std::vector &posts); + + ////////////////////////////////////////////////////////////////////////////// + + // SPECIAL REQUEST. +virtual bool requestPostRankings(uint32_t &token, const RankType &rType, uint32_t count, uint32_t page_no, const RsGxsGroupId &groupId); + +virtual bool getPostRanking(const uint32_t &token, std::vector &msgs); + + + ////////////////////////////////////////////////////////////////////////////// +virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read); + +//virtual bool setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask); +//virtual bool setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask); + +//virtual bool groupRestoreKeys(const std::string &groupId); +//virtual bool groupShareKeys(const std::string &groupId, std::list& peers); + +virtual bool createGroup(uint32_t &token, RsPostedGroup &group); +virtual bool createPost(uint32_t &token, RsPostedPost &post); + + + + /* Comment service - Provide RsGxsCommentService - redirect to p3GxsCommentService */ +virtual bool getCommentData(const uint32_t &token, std::vector &msgs) + { + return mCommentService->getGxsCommentData(token, msgs); + } + +virtual bool getRelatedComments(const uint32_t &token, std::vector &msgs) + { + return mCommentService->getGxsRelatedComments(token, msgs); + } + +virtual bool createComment(uint32_t &token, RsGxsComment &msg) + { + return mCommentService->createGxsComment(token, msg); + } + +virtual bool createVote(uint32_t &token, RsGxsVote &msg) + { + return mCommentService->createGxsVote(token, msg); + } + +virtual bool acknowledgeComment(const uint32_t& token, std::pair& msgId) + { + return acknowledgeMsg(token, msgId); + } + + private: + +static uint32_t postedAuthenPolicy(); + + +// DUMMY DATA, +virtual bool generateDummyData(); + +std::string genRandomId(); + +void dummy_tick(); + +bool generatePost(uint32_t &token, const RsGxsGroupId &grpId); +bool generateComment(uint32_t &token, const RsGxsGroupId &grpId, + const RsGxsMessageId &parentId, const RsGxsMessageId &threadId); +bool generateGroup(uint32_t &token, std::string groupName); + + class PostedDummyRef + { + public: + PostedDummyRef() { return; } + PostedDummyRef(const RsGxsGroupId &grpId, const RsGxsMessageId &threadId, const RsGxsMessageId &msgId) + :mGroupId(grpId), mThreadId(threadId), mMsgId(msgId) { return; } + + RsGxsGroupId mGroupId; + RsGxsMessageId mThreadId; + RsGxsMessageId mMsgId; + }; + + uint32_t mGenToken; + bool mGenActive; + int mGenCount; + std::vector mGenRefs; + RsGxsMessageId mGenThreadId; + + p3GxsCommentService *mCommentService; +}; + +#endif diff --git a/libretroshare/src/services/p3wiki.cc b/libretroshare/src/services/p3wiki.cc index 7df0b7cd0..154275aef 100644 --- a/libretroshare/src/services/p3wiki.cc +++ b/libretroshare/src/services/p3wiki.cc @@ -35,11 +35,6 @@ RsWiki *rsWiki = NULL; -/** - * #define WIKI_GEN_DUMMY_DATA 1 - **/ - -#define WIKI_GEN_DUMMY_DATA 1 #define WIKI_EVENT_DUMMYTICK 0x0001 #define WIKI_EVENT_DUMMYSTART 0x0002 @@ -56,11 +51,8 @@ p3Wiki::p3Wiki(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs mImprovActive = false; mMarkdownActive = false; -#ifndef GXS_DEV_TESTNET // NO RESET, OR DUMMYDATA for TESTNET - #ifdef WIKI_GEN_DUMMY_DATA - RsTickEvent::schedule_in(WIKI_EVENT_DUMMYSTART, DUMMYSTART_PERIOD); - #endif -#endif + // TestData disabled in Repo. + //RsTickEvent::schedule_in(WIKI_EVENT_DUMMYSTART, DUMMYSTART_PERIOD); }