/** * @file llsdmessagebuilder.cpp * @brief LLSDMessageBuilder class implementation. * * $LicenseInfo:firstyear=2007&license=viewergpl$ * * Copyright (c) 2007-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, * and agree to abide by those obligations. * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ #include "linden_common.h" #include "llsdmessagebuilder.h" #include "llmessagetemplate.h" #include "llquaternion.h" #include "llsdutil.h" #include "llsdutil_math.h" #include "llsdserialize.h" #include "u64.h" #include "v3dmath.h" #include "v3math.h" #include "v4math.h" LLSDMessageBuilder::LLSDMessageBuilder() : mCurrentMessage(LLSD::emptyMap()), mCurrentBlock(NULL), mCurrentMessageName(""), mCurrentBlockName(""), mbSBuilt(FALSE), mbSClear(TRUE) { } //virtual LLSDMessageBuilder::~LLSDMessageBuilder() { } // virtual void LLSDMessageBuilder::newMessage(const char* name) { mbSBuilt = FALSE; mbSClear = FALSE; mCurrentMessage = LLSD::emptyMap(); mCurrentMessageName = (char*)name; } // virtual void LLSDMessageBuilder::clearMessage() { mbSBuilt = FALSE; mbSClear = TRUE; mCurrentMessage = LLSD::emptyMap(); mCurrentMessageName = ""; } // virtual void LLSDMessageBuilder::nextBlock(const char* blockname) { LLSD& block = mCurrentMessage[blockname]; if(block.isUndefined()) { block[0] = LLSD::emptyMap(); mCurrentBlock = &(block[0]); } else if(block.isArray()) { block[block.size()] = LLSD::emptyMap(); mCurrentBlock = &(block[block.size() - 1]); } else { llerrs << "existing block not array" << llendl; } } // TODO: Remove this horror... BOOL LLSDMessageBuilder::removeLastBlock() { /* TODO: finish implementing this */ return FALSE; } void LLSDMessageBuilder::addBinaryData( const char* varname, const void* data, S32 size) { std::vector v; v.resize(size); memcpy(&(v[0]), reinterpret_cast(data), size); (*mCurrentBlock)[varname] = v; } void LLSDMessageBuilder::addS8(const char* varname, S8 v) { (*mCurrentBlock)[varname] = v; } void LLSDMessageBuilder::addU8(const char* varname, U8 v) { (*mCurrentBlock)[varname] = v; } void LLSDMessageBuilder::addS16(const char* varname, S16 v) { (*mCurrentBlock)[varname] = v; } void LLSDMessageBuilder::addU16(const char* varname, U16 v) { (*mCurrentBlock)[varname] = v; } void LLSDMessageBuilder::addF32(const char* varname, F32 v) { (*mCurrentBlock)[varname] = v; } void LLSDMessageBuilder::addS32(const char* varname, S32 v) { (*mCurrentBlock)[varname] = v; } void LLSDMessageBuilder::addU32(const char* varname, U32 v) { (*mCurrentBlock)[varname] = ll_sd_from_U32(v); } void LLSDMessageBuilder::addU64(const char* varname, U64 v) { (*mCurrentBlock)[varname] = ll_sd_from_U64(v); } void LLSDMessageBuilder::addF64(const char* varname, F64 v) { (*mCurrentBlock)[varname] = v; } void LLSDMessageBuilder::addIPAddr(const char* varname, U32 v) { (*mCurrentBlock)[varname] = ll_sd_from_ipaddr(v); } void LLSDMessageBuilder::addIPPort(const char* varname, U16 v) { (*mCurrentBlock)[varname] = v; } void LLSDMessageBuilder::addBOOL(const char* varname, BOOL v) { (*mCurrentBlock)[varname] = (v == TRUE); } void LLSDMessageBuilder::addString(const char* varname, const char* v) { if (v) (*mCurrentBlock)[varname] = v; /* Flawfinder: ignore */ else (*mCurrentBlock)[varname] = ""; } void LLSDMessageBuilder::addString(const char* varname, const std::string& v) { if (v.size()) (*mCurrentBlock)[varname] = v; else (*mCurrentBlock)[varname] = ""; } void LLSDMessageBuilder::addVector3(const char* varname, const LLVector3& v) { (*mCurrentBlock)[varname] = ll_sd_from_vector3(v); } void LLSDMessageBuilder::addVector4(const char* varname, const LLVector4& v) { (*mCurrentBlock)[varname] = ll_sd_from_vector4(v); } void LLSDMessageBuilder::addVector3d(const char* varname, const LLVector3d& v) { (*mCurrentBlock)[varname] = ll_sd_from_vector3d(v); } void LLSDMessageBuilder::addQuat(const char* varname, const LLQuaternion& v) { (*mCurrentBlock)[varname] = ll_sd_from_quaternion(v); } void LLSDMessageBuilder::addUUID(const char* varname, const LLUUID& v) { (*mCurrentBlock)[varname] = v; } void LLSDMessageBuilder::compressMessage(U8*& buf_ptr, U32& buffer_length) { } BOOL LLSDMessageBuilder::isMessageFull(const char* blockname) const { return FALSE; } U32 LLSDMessageBuilder::buildMessage(U8*, U32, U8) { return 0; } void LLSDMessageBuilder::copyFromMessageData(const LLMsgData& data) { // copy the blocks // counting variables used to encode multiple block info S32 block_count = 0; char* block_name = NULL; // loop through msg blocks to loop through variables, totalling up size // data and filling the new (send) message LLMsgData::msg_blk_data_map_t::const_iterator iter = data.mMemberBlocks.begin(); LLMsgData::msg_blk_data_map_t::const_iterator end = data.mMemberBlocks.end(); for(; iter != end; ++iter) { const LLMsgBlkData* mbci = iter->second; if(!mbci) continue; // do we need to encode a block code? if (block_count == 0) { block_count = mbci->mBlockNumber; block_name = (char*)mbci->mName; } // counting down mutliple blocks block_count--; nextBlock(block_name); // now loop through the variables LLMsgBlkData::msg_var_data_map_t::const_iterator dit = mbci->mMemberVarData.begin(); LLMsgBlkData::msg_var_data_map_t::const_iterator dend = mbci->mMemberVarData.end(); for(; dit != dend; ++dit) { const LLMsgVarData& mvci = *dit; const char* varname = mvci.getName(); switch(mvci.getType()) { case MVT_FIXED: addBinaryData(varname, mvci.getData(), mvci.getSize()); break; case MVT_VARIABLE: { const char end = ((const char*)mvci.getData())[mvci.getSize()-1]; // Ensure null terminated if (mvci.getDataSize() == 1 && end == 0) { addString(varname, (const char*)mvci.getData()); } else { addBinaryData(varname, mvci.getData(), mvci.getSize()); } break; } case MVT_U8: addU8(varname, *(U8*)mvci.getData()); break; case MVT_U16: addU16(varname, *(U16*)mvci.getData()); break; case MVT_U32: addU32(varname, *(U32*)mvci.getData()); break; case MVT_U64: addU64(varname, *(U64*)mvci.getData()); break; case MVT_S8: addS8(varname, *(S8*)mvci.getData()); break; case MVT_S16: addS16(varname, *(S16*)mvci.getData()); break; case MVT_S32: addS32(varname, *(S32*)mvci.getData()); break; // S64 not supported in LLSD so we just truncate it case MVT_S64: addS32(varname, *(S64*)mvci.getData()); break; case MVT_F32: addF32(varname, *(F32*)mvci.getData()); break; case MVT_F64: addF64(varname, *(F64*)mvci.getData()); break; case MVT_LLVector3: addVector3(varname, *(LLVector3*)mvci.getData()); break; case MVT_LLVector3d: addVector3d(varname, *(LLVector3d*)mvci.getData()); break; case MVT_LLVector4: addVector4(varname, *(LLVector4*)mvci.getData()); break; case MVT_LLQuaternion: { LLVector3 v = *(LLVector3*)mvci.getData(); LLQuaternion q; q.unpackFromVector3(v); addQuat(varname, q); break; } case MVT_LLUUID: addUUID(varname, *(LLUUID*)mvci.getData()); break; case MVT_BOOL: addBOOL(varname, *(BOOL*)mvci.getData()); break; case MVT_IP_ADDR: addIPAddr(varname, *(U32*)mvci.getData()); break; case MVT_IP_PORT: addIPPort(varname, *(U16*)mvci.getData()); break; case MVT_U16Vec3: //treated as an array of 6 bytes addBinaryData(varname, mvci.getData(), 6); break; case MVT_U16Quat: //treated as an array of 8 bytes addBinaryData(varname, mvci.getData(), 8); break; case MVT_S16Array: addBinaryData(varname, mvci.getData(), mvci.getSize()); break; default: llwarns << "Unknown type in conversion of message to LLSD" << llendl; break; } } } } //virtual void LLSDMessageBuilder::copyFromLLSD(const LLSD& msg) { mCurrentMessage = msg; lldebugs << LLSDNotationStreamer(mCurrentMessage) << llendl; } const LLSD& LLSDMessageBuilder::getMessage() const { return mCurrentMessage; } //virtual void LLSDMessageBuilder::setBuilt(BOOL b) { mbSBuilt = b; } //virtual BOOL LLSDMessageBuilder::isBuilt() const {return mbSBuilt;} //virtual BOOL LLSDMessageBuilder::isClear() const {return mbSClear;} //virtual S32 LLSDMessageBuilder::getMessageSize() { // babbage: size is unknown as message stored as LLSD. // return non-zero if pending data, as send can be skipped for 0 size. // return 1 to encourage senders checking size against splitting message. return mCurrentMessage.size()? 1 : 0; } //virtual const char* LLSDMessageBuilder::getMessageName() const { return mCurrentMessageName.c_str(); }