added auto-split of long private messages, and re-combination of partial messages on client side. Corrects the bug causing disconnection when sendign messages of side larger than the maximum packet size.

git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@4598 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
csoler 2011-09-09 19:37:38 +00:00
parent 5b3543d41a
commit b73fd06753
3 changed files with 80 additions and 3 deletions

View File

@ -194,6 +194,7 @@ const uint32_t RS_MSG_FLAGS_UNREAD_BY_USER = 0x0040;
const uint32_t RS_MSG_FLAGS_REPLIED = 0x0080;
const uint32_t RS_MSG_FLAGS_FORWARDED = 0x0100;
const uint32_t RS_MSG_FLAGS_STAR = 0x0200;
const uint32_t RS_MSG_FLAGS_PARTIAL = 0x0400;
class RsMsgItem: public RsItem
{

View File

@ -56,7 +56,7 @@ const int msgservicezone = 54319;
p3MsgService::p3MsgService(p3LinkMgr *lm)
:p3Service(RS_SERVICE_TYPE_MSG), p3Config(CONFIG_TYPE_MSGS),
mLinkMgr(lm), mMsgMtx("p3MsgService"), msgChanged(1), mMsgUniqueId(1)
mLinkMgr(lm), mMsgMtx("p3MsgService"), msgChanged(1), mMsgUniqueId(time(NULL))
{
addSerialType(new RsMsgSerialiser());
@ -171,6 +171,48 @@ void p3MsgService::processMsg(RsMsgItem *mi)
/**** STACK UNLOCKED ***/
}
bool p3MsgService::checkAndRebuildPartialMessage(RsMsgItem *ci)
{
// Check is the item is ending an incomplete item.
//
std::map<std::string,RsMsgItem*>::iterator it = _pendingPartialMessages.find(ci->PeerId()) ;
bool ci_is_partial = ci->msgFlags & RS_MSG_FLAGS_PARTIAL ;
if(it != _pendingPartialMessages.end())
{
//#ifdef CHAT_DEBUG
std::cerr << "Pending message found. Happending it." << std::endl;
//#endif
// Yes, there is. Append the item to ci.
ci->message = it->second->message + ci->message ;
ci->msgFlags |= it->second->msgFlags ;
delete it->second ;
if(!ci_is_partial)
_pendingPartialMessages.erase(it) ;
}
if(ci_is_partial)
{
//#ifdef CHAT_DEBUG
std::cerr << "Message is partial, storing for later." << std::endl;
//#endif
// The item is a partial message. Push it, and wait for the rest.
//
_pendingPartialMessages[ci->PeerId()] = ci ;
return false ;
}
else
{
//#ifdef CHAT_DEBUG
std::cerr << "Message is complete, using it now." << std::endl;
//#endif
return true ;
}
}
int p3MsgService::incomingMsgs()
{
@ -183,6 +225,7 @@ int p3MsgService::incomingMsgs()
changed = true ;
++i;
if(checkAndRebuildPartialMessage(mi)) // only returns true when a msg is complete.
processMsg(mi);
}
if(changed)
@ -197,6 +240,34 @@ void p3MsgService::statusChange(const std::list<pqipeer> &/*plist*/)
checkOutgoingMessages();
}
void p3MsgService::checkSizeAndSendMessage(RsMsgItem *msg)
{
// We check the message item, and possibly split it into multiple messages, if the message is too big.
static const uint32_t MAX_STRING_SIZE = 15000 ;
std::cerr << "Msg is size " << msg->message.size() << std::endl;
while(msg->message.size() > MAX_STRING_SIZE)
{
// chop off the first 15000 wchars
RsMsgItem *item = new RsMsgItem(*msg) ;
item->message = item->message.substr(0,MAX_STRING_SIZE) ;
msg->message = msg->message.substr(MAX_STRING_SIZE,msg->message.size()-MAX_STRING_SIZE) ;
std::cerr << " Chopped off msg of size " << item->message.size() << std::endl;
// Indicate that the message is to be continued.
//
item->msgFlags |= RS_MSG_FLAGS_PARTIAL ;
sendItem(item) ;
}
std::cerr << " Chopped off msg of size " << msg->message.size() << std::endl;
sendItem(msg) ;
}
int p3MsgService::checkOutgoingMessages()
{
/* iterate through the outgoing queue
@ -241,7 +312,7 @@ int p3MsgService::checkOutgoingMessages()
/* remove the pending flag */
(mit->second)->msgFlags &= ~RS_MSG_FLAGS_PENDING;
sendItem(mit->second);
checkSizeAndSendMessage(mit->second) ;
toErase.push_back(mit->first);
changed = true ;

View File

@ -104,8 +104,11 @@ int checkOutgoingMessages();
uint32_t getNewUniqueMsgId();
int sendMessage(RsMsgItem *item);
void checkSizeAndSendMessage(RsMsgItem *msg);
int incomingMsgs();
void processMsg(RsMsgItem *mi);
bool checkAndRebuildPartialMessage(RsMsgItem*) ;
void initRsMI(RsMsgItem *msg, MessageInfo &mi);
void initRsMIS(RsMsgItem *msg, MsgInfoSummary &mis);
@ -124,6 +127,8 @@ void initStandardTagTypes();
/* ones that haven't made it out yet! */
std::map<uint32_t, RsMsgItem *> msgOutgoing;
std::map<std::string, RsMsgItem *> _pendingPartialMessages ;
/* List of notifications to post via Toaster */
std::list<MsgInfoSummary> msgNotifications;