PageRenderTime 67ms CodeModel.GetById 10ms app.highlight 52ms RepoModel.GetById 2ms app.codeStats 0ms

/indra/llmessage/llinstantmessage.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 387 lines | 320 code | 30 blank | 37 comment | 6 complexity | 4b667615c447c8bb6c7f0e6e05c33763 MD5 | raw file
  1/** 
  2 * @file llinstantmessage.cpp
  3 * @author Phoenix
  4 * @date 2005-08-29
  5 * @brief Constants and functions used in IM.
  6 *
  7 * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  8 * Second Life Viewer Source Code
  9 * Copyright (C) 2010, Linden Research, Inc.
 10 * 
 11 * This library is free software; you can redistribute it and/or
 12 * modify it under the terms of the GNU Lesser General Public
 13 * License as published by the Free Software Foundation;
 14 * version 2.1 of the License only.
 15 * 
 16 * This library is distributed in the hope that it will be useful,
 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 19 * Lesser General Public License for more details.
 20 * 
 21 * You should have received a copy of the GNU Lesser General Public
 22 * License along with this library; if not, write to the Free Software
 23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 24 * 
 25 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 26 * $/LicenseInfo$
 27 */
 28
 29#include "linden_common.h"
 30
 31#include "lldbstrings.h"
 32#include "llinstantmessage.h"
 33#include "llhost.h"
 34#include "lluuid.h"
 35#include "llsd.h"
 36#include "llsdserialize.h"
 37#include "llsdutil_math.h"
 38#include "llpointer.h"
 39#include "message.h"
 40
 41#include "message.h"
 42
 43const U8 IM_ONLINE = 0;
 44const U8 IM_OFFLINE = 1;
 45
 46const S32 VOTE_YES = 1;
 47const S32 VOTE_NO = 0;
 48const S32 VOTE_ABSTAIN = -1;
 49
 50const S32 VOTE_MAJORITY = 0;
 51const S32 VOTE_SUPER_MAJORITY = 1;
 52const S32 VOTE_UNANIMOUS = 2;
 53
 54const char EMPTY_BINARY_BUCKET[] = "";
 55const S32 EMPTY_BINARY_BUCKET_SIZE = 1;
 56const U32 NO_TIMESTAMP = 0;
 57const std::string SYSTEM_FROM("Second Life");
 58const std::string INTERACTIVE_SYSTEM_FROM("F387446C-37C4-45f2-A438-D99CBDBB563B");
 59const S32 IM_TTL = 1;
 60
 61
 62/**
 63 * LLIMInfo
 64 */
 65LLIMInfo::LLIMInfo() :
 66	mFromGroup(FALSE),
 67	mParentEstateID(0),
 68	mOffline(0),
 69	mViewerThinksToIsOnline(false),
 70	mIMType(IM_NOTHING_SPECIAL),
 71	mTimeStamp(0),
 72	mSource(IM_FROM_SIM),
 73	mTTL(IM_TTL)
 74{
 75}
 76
 77LLIMInfo::LLIMInfo(
 78	const LLUUID& from_id,
 79	BOOL from_group,
 80	const LLUUID& to_id,
 81	EInstantMessage im_type, 
 82	const std::string& name,
 83	const std::string& message,
 84	const LLUUID& id,
 85	U32 parent_estate_id,
 86	const LLUUID& region_id,
 87	const LLVector3& position,
 88	LLSD data,
 89	U8 offline,
 90	U32 timestamp,
 91	EIMSource source,
 92	S32 ttl) :
 93	mFromID(from_id),
 94	mFromGroup(from_group),
 95	mToID(to_id),
 96	mParentEstateID(0),
 97	mRegionID(region_id),
 98	mPosition(position),
 99	mOffline(offline),
100	mViewerThinksToIsOnline(false),
101	mIMType(im_type),
102	mID(id),
103	mTimeStamp(timestamp),
104	mName(name),
105	mMessage(message),
106	mData(data),
107	mSource(source),
108	mTTL(ttl)
109{
110}
111
112LLIMInfo::LLIMInfo(LLMessageSystem* msg, EIMSource source, S32 ttl) :
113	mViewerThinksToIsOnline(false),
114	mSource(source),
115	mTTL(ttl)
116{
117	unpackMessageBlock(msg);
118}
119
120LLIMInfo::~LLIMInfo()
121{
122}
123
124void LLIMInfo::packInstantMessage(LLMessageSystem* msg) const
125{
126	lldebugs << "LLIMInfo::packInstantMessage()" << llendl;
127	msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
128	packMessageBlock(msg);
129}
130
131void LLIMInfo::packMessageBlock(LLMessageSystem* msg) const
132{
133	// Construct binary bucket
134	std::vector<U8> bucket;
135	if (mData.has("binary_bucket"))
136	{
137		bucket = mData["binary_bucket"].asBinary();
138	}
139	pack_instant_message_block(
140		msg,
141		mFromID,
142		mFromGroup,
143		LLUUID::null,
144		mToID,
145		mName,
146		mMessage,
147		mOffline,
148		mIMType,
149		mID,
150		mParentEstateID,
151		mRegionID,
152		mPosition,
153		mTimeStamp,
154		&bucket[0],
155		bucket.size());
156}
157
158void pack_instant_message(
159	LLMessageSystem* msg,
160	const LLUUID& from_id,
161	BOOL from_group,
162	const LLUUID& session_id,
163	const LLUUID& to_id,
164	const std::string& name,
165	const std::string& message,
166	U8 offline,
167	EInstantMessage dialog,
168	const LLUUID& id,
169	U32 parent_estate_id,
170	const LLUUID& region_id,
171	const LLVector3& position,
172	U32 timestamp, 
173	const U8* binary_bucket,
174	S32 binary_bucket_size)
175{
176	lldebugs << "pack_instant_message()" << llendl;
177	msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
178	pack_instant_message_block(
179		msg,
180		from_id,
181		from_group,
182		session_id,
183		to_id,
184		name,
185		message,
186		offline,
187		dialog,
188		id,
189		parent_estate_id,
190		region_id,
191		position,
192		timestamp,
193		binary_bucket,
194		binary_bucket_size);
195}
196
197void pack_instant_message_block(
198	LLMessageSystem* msg,
199	const LLUUID& from_id,
200	BOOL from_group,
201	const LLUUID& session_id,
202	const LLUUID& to_id,
203	const std::string& name,
204	const std::string& message,
205	U8 offline,
206	EInstantMessage dialog,
207	const LLUUID& id,
208	U32 parent_estate_id,
209	const LLUUID& region_id,
210	const LLVector3& position,
211	U32 timestamp,
212	const U8* binary_bucket,
213	S32 binary_bucket_size)
214{
215	msg->nextBlockFast(_PREHASH_AgentData);
216	msg->addUUIDFast(_PREHASH_AgentID, from_id);
217	msg->addUUIDFast(_PREHASH_SessionID, session_id);
218	msg->nextBlockFast(_PREHASH_MessageBlock);
219	msg->addBOOLFast(_PREHASH_FromGroup, from_group);
220	msg->addUUIDFast(_PREHASH_ToAgentID, to_id);
221	msg->addU32Fast(_PREHASH_ParentEstateID, parent_estate_id);
222	msg->addUUIDFast(_PREHASH_RegionID, region_id);
223	msg->addVector3Fast(_PREHASH_Position, position);
224	msg->addU8Fast(_PREHASH_Offline, offline);
225	msg->addU8Fast(_PREHASH_Dialog, (U8) dialog);
226	msg->addUUIDFast(_PREHASH_ID, id);
227	msg->addU32Fast(_PREHASH_Timestamp, timestamp);
228	msg->addStringFast(_PREHASH_FromAgentName, name);
229	S32 bytes_left = MTUBYTES;
230	if(!message.empty())
231	{
232		char buffer[MTUBYTES];
233		int num_written = snprintf(buffer, MTUBYTES, "%s", message.c_str());	/* Flawfinder: ignore */
234		// snprintf returns number of bytes that would have been written
235		// had the output not being truncated. In that case, it will
236		// return either -1 or value >= passed in size value . So a check needs to be added
237		// to detect truncation, and if there is any, only account for the
238		// actual number of bytes written..and not what could have been
239		// written.
240		if (num_written < 0 || num_written >= MTUBYTES)
241		{
242			num_written = MTUBYTES - 1;
243			llwarns << "pack_instant_message_block: message truncated: " << message << llendl;
244		}
245
246		bytes_left -= num_written;
247		bytes_left = llmax(0, bytes_left);
248		msg->addStringFast(_PREHASH_Message, buffer);
249	}
250	else
251	{
252		msg->addStringFast(_PREHASH_Message, NULL);
253	}
254	const U8* bb;
255	if(binary_bucket)
256	{
257		bb = binary_bucket;
258		binary_bucket_size = llmin(bytes_left, binary_bucket_size);
259	}
260	else
261	{
262		bb = (const U8*)EMPTY_BINARY_BUCKET;
263		binary_bucket_size = EMPTY_BINARY_BUCKET_SIZE;
264	}
265	msg->addBinaryDataFast(_PREHASH_BinaryBucket, bb, binary_bucket_size);
266}
267
268void LLIMInfo::unpackMessageBlock(LLMessageSystem* msg)
269{
270	msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, mFromID);
271	msg->getBOOLFast(_PREHASH_MessageBlock, _PREHASH_FromGroup, mFromGroup);
272	msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_ToAgentID, mToID);
273	msg->getU32Fast(_PREHASH_MessageBlock, _PREHASH_ParentEstateID, mParentEstateID);
274	msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_RegionID, mRegionID);
275	msg->getVector3Fast(_PREHASH_MessageBlock, _PREHASH_Position, mPosition);
276	msg->getU8Fast(_PREHASH_MessageBlock, _PREHASH_Offline, mOffline);
277	U8 dialog;
278	msg->getU8Fast(_PREHASH_MessageBlock, _PREHASH_Dialog, dialog);
279	mIMType = (EInstantMessage) dialog;
280	msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_ID, mID);
281	msg->getU32Fast(_PREHASH_MessageBlock, _PREHASH_Timestamp, mTimeStamp);
282	msg->getStringFast(_PREHASH_MessageBlock, _PREHASH_FromAgentName, mName);
283
284	msg->getStringFast(_PREHASH_MessageBlock, _PREHASH_Message, mMessage);
285
286	S32 binary_bucket_size = llmin(
287		MTUBYTES,
288		msg->getSizeFast(
289			_PREHASH_MessageBlock,
290			_PREHASH_BinaryBucket));
291	if(binary_bucket_size > 0)
292	{
293		std::vector<U8> bucket;
294		bucket.resize(binary_bucket_size);
295
296		msg->getBinaryDataFast(
297			_PREHASH_MessageBlock,
298			_PREHASH_BinaryBucket,
299			&bucket[0],
300			0,
301			0,
302			binary_bucket_size);
303		mData["binary_bucket"] = bucket;
304	}
305	else
306	{
307		mData.clear();
308	}
309}
310
311LLSD im_info_to_llsd(LLPointer<LLIMInfo> im_info)
312{
313	LLSD param_version;
314	param_version["version"] = 1;
315	LLSD param_message;
316	param_message["from_id"] = im_info->mFromID;
317	param_message["from_group"] = im_info->mFromGroup;
318	param_message["to_id"] = im_info->mToID;
319	param_message["from_name"] = im_info->mName;
320	param_message["message"] = im_info->mMessage;
321	param_message["type"] = (S32)im_info->mIMType;
322	param_message["id"] = im_info->mID;
323	param_message["timestamp"] = (S32)im_info->mTimeStamp;
324	param_message["offline"] = (S32)im_info->mOffline;
325	param_message["parent_estate_id"] = (S32)im_info->mParentEstateID;
326	param_message["region_id"] = im_info->mRegionID;
327	param_message["position"] = ll_sd_from_vector3(im_info->mPosition);
328	param_message["data"] = im_info->mData;
329	param_message["source"]= im_info->mSource;
330	param_message["ttl"] = im_info->mTTL;
331
332	LLSD param_agent;
333	param_agent["agent_id"] = im_info->mFromID;
334
335	LLSD params;
336	params["version_params"] = param_version;
337	params["message_params"] = param_message;
338	params["agent_params"] = param_agent;
339
340	return params;
341}
342
343LLPointer<LLIMInfo> llsd_to_im_info(const LLSD& im_info_sd)
344{
345	LLSD param_message = im_info_sd["message_params"];
346	LLSD param_agent = im_info_sd["agent_params"];
347
348	LLPointer<LLIMInfo> im_info = new LLIMInfo(
349		param_message["from_id"].asUUID(),
350		param_message["from_group"].asBoolean(),
351		param_message["to_id"].asUUID(),
352		(EInstantMessage) param_message["type"].asInteger(),
353		param_message["from_name"].asString(),
354		param_message["message"].asString(),
355		param_message["id"].asUUID(),
356		(U32) param_message["parent_estate_id"].asInteger(),
357		param_message["region_id"].asUUID(),
358		ll_vector3_from_sd(param_message["position"]),
359		param_message["data"],
360		(U8) param_message["offline"].asInteger(),
361		(U32) param_message["timestamp"].asInteger(),
362		(EIMSource)param_message["source"].asInteger(),
363		param_message["ttl"].asInteger());
364
365	return im_info;
366}
367
368LLPointer<LLIMInfo> LLIMInfo::clone()
369{
370	return new LLIMInfo(
371			mFromID,
372			mFromGroup,
373			mToID,
374			mIMType,
375			mName,
376			mMessage,
377			mID,
378			mParentEstateID,
379			mRegionID,
380			mPosition,
381			mData,
382			mOffline,
383			mTimeStamp,
384			mSource,
385			mTTL);
386}
387