/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. #include "linden_common.h"
  29. #include "lldbstrings.h"
  30. #include "llinstantmessage.h"
  31. #include "llhost.h"
  32. #include "lluuid.h"
  33. #include "llsd.h"
  34. #include "llsdserialize.h"
  35. #include "llsdutil_math.h"
  36. #include "llpointer.h"
  37. #include "message.h"
  38. #include "message.h"
  39. const U8 IM_ONLINE = 0;
  40. const U8 IM_OFFLINE = 1;
  41. const S32 VOTE_YES = 1;
  42. const S32 VOTE_NO = 0;
  43. const S32 VOTE_ABSTAIN = -1;
  44. const S32 VOTE_MAJORITY = 0;
  45. const S32 VOTE_SUPER_MAJORITY = 1;
  46. const S32 VOTE_UNANIMOUS = 2;
  47. const char EMPTY_BINARY_BUCKET[] = "";
  48. const S32 EMPTY_BINARY_BUCKET_SIZE = 1;
  49. const U32 NO_TIMESTAMP = 0;
  50. const std::string SYSTEM_FROM("Second Life");
  51. const std::string INTERACTIVE_SYSTEM_FROM("F387446C-37C4-45f2-A438-D99CBDBB563B");
  52. const S32 IM_TTL = 1;
  53. /**
  54. * LLIMInfo
  55. */
  56. LLIMInfo::LLIMInfo() :
  57. mFromGroup(FALSE),
  58. mParentEstateID(0),
  59. mOffline(0),
  60. mViewerThinksToIsOnline(false),
  61. mIMType(IM_NOTHING_SPECIAL),
  62. mTimeStamp(0),
  63. mSource(IM_FROM_SIM),
  64. mTTL(IM_TTL)
  65. {
  66. }
  67. LLIMInfo::LLIMInfo(
  68. const LLUUID& from_id,
  69. BOOL from_group,
  70. const LLUUID& to_id,
  71. EInstantMessage im_type,
  72. const std::string& name,
  73. const std::string& message,
  74. const LLUUID& id,
  75. U32 parent_estate_id,
  76. const LLUUID& region_id,
  77. const LLVector3& position,
  78. LLSD data,
  79. U8 offline,
  80. U32 timestamp,
  81. EIMSource source,
  82. S32 ttl) :
  83. mFromID(from_id),
  84. mFromGroup(from_group),
  85. mToID(to_id),
  86. mParentEstateID(0),
  87. mRegionID(region_id),
  88. mPosition(position),
  89. mOffline(offline),
  90. mViewerThinksToIsOnline(false),
  91. mIMType(im_type),
  92. mID(id),
  93. mTimeStamp(timestamp),
  94. mName(name),
  95. mMessage(message),
  96. mData(data),
  97. mSource(source),
  98. mTTL(ttl)
  99. {
  100. }
  101. LLIMInfo::LLIMInfo(LLMessageSystem* msg, EIMSource source, S32 ttl) :
  102. mViewerThinksToIsOnline(false),
  103. mSource(source),
  104. mTTL(ttl)
  105. {
  106. unpackMessageBlock(msg);
  107. }
  108. LLIMInfo::~LLIMInfo()
  109. {
  110. }
  111. void LLIMInfo::packInstantMessage(LLMessageSystem* msg) const
  112. {
  113. lldebugs << "LLIMInfo::packInstantMessage()" << llendl;
  114. msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
  115. packMessageBlock(msg);
  116. }
  117. void LLIMInfo::packMessageBlock(LLMessageSystem* msg) const
  118. {
  119. // Construct binary bucket
  120. std::vector<U8> bucket;
  121. if (mData.has("binary_bucket"))
  122. {
  123. bucket = mData["binary_bucket"].asBinary();
  124. }
  125. pack_instant_message_block(
  126. msg,
  127. mFromID,
  128. mFromGroup,
  129. LLUUID::null,
  130. mToID,
  131. mName,
  132. mMessage,
  133. mOffline,
  134. mIMType,
  135. mID,
  136. mParentEstateID,
  137. mRegionID,
  138. mPosition,
  139. mTimeStamp,
  140. &bucket[0],
  141. bucket.size());
  142. }
  143. void pack_instant_message(
  144. LLMessageSystem* msg,
  145. const LLUUID& from_id,
  146. BOOL from_group,
  147. const LLUUID& session_id,
  148. const LLUUID& to_id,
  149. const std::string& name,
  150. const std::string& message,
  151. U8 offline,
  152. EInstantMessage dialog,
  153. const LLUUID& id,
  154. U32 parent_estate_id,
  155. const LLUUID& region_id,
  156. const LLVector3& position,
  157. U32 timestamp,
  158. const U8* binary_bucket,
  159. S32 binary_bucket_size)
  160. {
  161. lldebugs << "pack_instant_message()" << llendl;
  162. msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
  163. pack_instant_message_block(
  164. msg,
  165. from_id,
  166. from_group,
  167. session_id,
  168. to_id,
  169. name,
  170. message,
  171. offline,
  172. dialog,
  173. id,
  174. parent_estate_id,
  175. region_id,
  176. position,
  177. timestamp,
  178. binary_bucket,
  179. binary_bucket_size);
  180. }
  181. void pack_instant_message_block(
  182. LLMessageSystem* msg,
  183. const LLUUID& from_id,
  184. BOOL from_group,
  185. const LLUUID& session_id,
  186. const LLUUID& to_id,
  187. const std::string& name,
  188. const std::string& message,
  189. U8 offline,
  190. EInstantMessage dialog,
  191. const LLUUID& id,
  192. U32 parent_estate_id,
  193. const LLUUID& region_id,
  194. const LLVector3& position,
  195. U32 timestamp,
  196. const U8* binary_bucket,
  197. S32 binary_bucket_size)
  198. {
  199. msg->nextBlockFast(_PREHASH_AgentData);
  200. msg->addUUIDFast(_PREHASH_AgentID, from_id);
  201. msg->addUUIDFast(_PREHASH_SessionID, session_id);
  202. msg->nextBlockFast(_PREHASH_MessageBlock);
  203. msg->addBOOLFast(_PREHASH_FromGroup, from_group);
  204. msg->addUUIDFast(_PREHASH_ToAgentID, to_id);
  205. msg->addU32Fast(_PREHASH_ParentEstateID, parent_estate_id);
  206. msg->addUUIDFast(_PREHASH_RegionID, region_id);
  207. msg->addVector3Fast(_PREHASH_Position, position);
  208. msg->addU8Fast(_PREHASH_Offline, offline);
  209. msg->addU8Fast(_PREHASH_Dialog, (U8) dialog);
  210. msg->addUUIDFast(_PREHASH_ID, id);
  211. msg->addU32Fast(_PREHASH_Timestamp, timestamp);
  212. msg->addStringFast(_PREHASH_FromAgentName, name);
  213. S32 bytes_left = MTUBYTES;
  214. if(!message.empty())
  215. {
  216. char buffer[MTUBYTES];
  217. int num_written = snprintf(buffer, MTUBYTES, "%s", message.c_str()); /* Flawfinder: ignore */
  218. // snprintf returns number of bytes that would have been written
  219. // had the output not being truncated. In that case, it will
  220. // return either -1 or value >= passed in size value . So a check needs to be added
  221. // to detect truncation, and if there is any, only account for the
  222. // actual number of bytes written..and not what could have been
  223. // written.
  224. if (num_written < 0 || num_written >= MTUBYTES)
  225. {
  226. num_written = MTUBYTES - 1;
  227. llwarns << "pack_instant_message_block: message truncated: " << message << llendl;
  228. }
  229. bytes_left -= num_written;
  230. bytes_left = llmax(0, bytes_left);
  231. msg->addStringFast(_PREHASH_Message, buffer);
  232. }
  233. else
  234. {
  235. msg->addStringFast(_PREHASH_Message, NULL);
  236. }
  237. const U8* bb;
  238. if(binary_bucket)
  239. {
  240. bb = binary_bucket;
  241. binary_bucket_size = llmin(bytes_left, binary_bucket_size);
  242. }
  243. else
  244. {
  245. bb = (const U8*)EMPTY_BINARY_BUCKET;
  246. binary_bucket_size = EMPTY_BINARY_BUCKET_SIZE;
  247. }
  248. msg->addBinaryDataFast(_PREHASH_BinaryBucket, bb, binary_bucket_size);
  249. }
  250. void LLIMInfo::unpackMessageBlock(LLMessageSystem* msg)
  251. {
  252. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, mFromID);
  253. msg->getBOOLFast(_PREHASH_MessageBlock, _PREHASH_FromGroup, mFromGroup);
  254. msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_ToAgentID, mToID);
  255. msg->getU32Fast(_PREHASH_MessageBlock, _PREHASH_ParentEstateID, mParentEstateID);
  256. msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_RegionID, mRegionID);
  257. msg->getVector3Fast(_PREHASH_MessageBlock, _PREHASH_Position, mPosition);
  258. msg->getU8Fast(_PREHASH_MessageBlock, _PREHASH_Offline, mOffline);
  259. U8 dialog;
  260. msg->getU8Fast(_PREHASH_MessageBlock, _PREHASH_Dialog, dialog);
  261. mIMType = (EInstantMessage) dialog;
  262. msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_ID, mID);
  263. msg->getU32Fast(_PREHASH_MessageBlock, _PREHASH_Timestamp, mTimeStamp);
  264. msg->getStringFast(_PREHASH_MessageBlock, _PREHASH_FromAgentName, mName);
  265. msg->getStringFast(_PREHASH_MessageBlock, _PREHASH_Message, mMessage);
  266. S32 binary_bucket_size = llmin(
  267. MTUBYTES,
  268. msg->getSizeFast(
  269. _PREHASH_MessageBlock,
  270. _PREHASH_BinaryBucket));
  271. if(binary_bucket_size > 0)
  272. {
  273. std::vector<U8> bucket;
  274. bucket.resize(binary_bucket_size);
  275. msg->getBinaryDataFast(
  276. _PREHASH_MessageBlock,
  277. _PREHASH_BinaryBucket,
  278. &bucket[0],
  279. 0,
  280. 0,
  281. binary_bucket_size);
  282. mData["binary_bucket"] = bucket;
  283. }
  284. else
  285. {
  286. mData.clear();
  287. }
  288. }
  289. LLSD im_info_to_llsd(LLPointer<LLIMInfo> im_info)
  290. {
  291. LLSD param_version;
  292. param_version["version"] = 1;
  293. LLSD param_message;
  294. param_message["from_id"] = im_info->mFromID;
  295. param_message["from_group"] = im_info->mFromGroup;
  296. param_message["to_id"] = im_info->mToID;
  297. param_message["from_name"] = im_info->mName;
  298. param_message["message"] = im_info->mMessage;
  299. param_message["type"] = (S32)im_info->mIMType;
  300. param_message["id"] = im_info->mID;
  301. param_message["timestamp"] = (S32)im_info->mTimeStamp;
  302. param_message["offline"] = (S32)im_info->mOffline;
  303. param_message["parent_estate_id"] = (S32)im_info->mParentEstateID;
  304. param_message["region_id"] = im_info->mRegionID;
  305. param_message["position"] = ll_sd_from_vector3(im_info->mPosition);
  306. param_message["data"] = im_info->mData;
  307. param_message["source"]= im_info->mSource;
  308. param_message["ttl"] = im_info->mTTL;
  309. LLSD param_agent;
  310. param_agent["agent_id"] = im_info->mFromID;
  311. LLSD params;
  312. params["version_params"] = param_version;
  313. params["message_params"] = param_message;
  314. params["agent_params"] = param_agent;
  315. return params;
  316. }
  317. LLPointer<LLIMInfo> llsd_to_im_info(const LLSD& im_info_sd)
  318. {
  319. LLSD param_message = im_info_sd["message_params"];
  320. LLSD param_agent = im_info_sd["agent_params"];
  321. LLPointer<LLIMInfo> im_info = new LLIMInfo(
  322. param_message["from_id"].asUUID(),
  323. param_message["from_group"].asBoolean(),
  324. param_message["to_id"].asUUID(),
  325. (EInstantMessage) param_message["type"].asInteger(),
  326. param_message["from_name"].asString(),
  327. param_message["message"].asString(),
  328. param_message["id"].asUUID(),
  329. (U32) param_message["parent_estate_id"].asInteger(),
  330. param_message["region_id"].asUUID(),
  331. ll_vector3_from_sd(param_message["position"]),
  332. param_message["data"],
  333. (U8) param_message["offline"].asInteger(),
  334. (U32) param_message["timestamp"].asInteger(),
  335. (EIMSource)param_message["source"].asInteger(),
  336. param_message["ttl"].asInteger());
  337. return im_info;
  338. }
  339. LLPointer<LLIMInfo> LLIMInfo::clone()
  340. {
  341. return new LLIMInfo(
  342. mFromID,
  343. mFromGroup,
  344. mToID,
  345. mIMType,
  346. mName,
  347. mMessage,
  348. mID,
  349. mParentEstateID,
  350. mRegionID,
  351. mPosition,
  352. mData,
  353. mOffline,
  354. mTimeStamp,
  355. mSource,
  356. mTTL);
  357. }