void LLMsgVarData::addData(const void *data, S32 size, EMsgVariableType type, S32 data_size) { mSize = size; mDataSize = data_size; if ( (type != MVT_VARIABLE) && (type != MVT_FIXED) && (mType != MVT_VARIABLE) && (mType != MVT_FIXED)) { if (mType != type) { llwarns << "Type mismatch in LLMsgVarData::addData for " << mName << llendl; } } if(size) { delete mData; // Delete it if it already exists mData = new U8[size]; htonmemcpy(mData, data, mType, size); } }
U8 *LLGestureList::deserialize(U8 *buffer, S32 max_size) { deleteAll(); S32 count; U8 *tmp = buffer; if (tmp + sizeof(count) > buffer + max_size) { llwarns << "Invalid max_size" << llendl; return buffer; } htonmemcpy(&count, tmp, MVT_S32, 4); if (count > MAX_GESTURES) { llwarns << "Unreasonably large gesture list count in deserialize: " << count << llendl; return tmp; } tmp += sizeof(count); mList.reserve_block(count); for (S32 i = 0; i < count; i++) { mList[i] = create_gesture(&tmp, max_size - (S32)(tmp - buffer)); if (tmp - buffer > max_size) { llwarns << "Deserialization read past end of buffer, bad data!!!!" << llendl; return tmp; } } return tmp; }
//----------------------------------------------------------------------------- // packData() //----------------------------------------------------------------------------- void LLHUDEffectLookAt::packData(LLMessageSystem *mesgsys) { // Pack the default data LLHUDEffect::packData(mesgsys); // Pack the type-specific data. Uses a fun packed binary format. Whee! U8 packed_data[PKT_SIZE]; memset(packed_data, 0, PKT_SIZE); if (mSourceObject) { htonmemcpy(&(packed_data[SOURCE_AVATAR]), mSourceObject->mID.mData, MVT_LLUUID, 16); } else { htonmemcpy(&(packed_data[SOURCE_AVATAR]), LLUUID::null.mData, MVT_LLUUID, 16); } // pack both target object and position // position interpreted as offset if target object is non-null if (mTargetObject) { htonmemcpy(&(packed_data[TARGET_OBJECT]), mTargetObject->mID.mData, MVT_LLUUID, 16); } else { htonmemcpy(&(packed_data[TARGET_OBJECT]), LLUUID::null.mData, MVT_LLUUID, 16); } htonmemcpy(&(packed_data[TARGET_POS]), mTargetOffsetGlobal.mdV, MVT_LLVector3d, 24); U8 lookAtTypePacked = (U8)mTargetType; htonmemcpy(&(packed_data[LOOKAT_TYPE]), &lookAtTypePacked, MVT_U8, 1); mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, PKT_SIZE); mLastSendTime = mTimer.getElapsedTimeF32(); }
void LLHUDEffectSpiral::unpackData(LLMessageSystem *mesgsys, S32 blocknum) { const size_t EFFECT_SIZE = 56; U8 packed_data[EFFECT_SIZE]; LLHUDEffect::unpackData(mesgsys, blocknum); LLUUID object_id, target_object_id; S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData); if (size != EFFECT_SIZE) { llwarns << "Spiral effect with bad size " << size << llendl; return; } mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, EFFECT_SIZE, blocknum, EFFECT_SIZE); htonmemcpy(object_id.mData, packed_data, MVT_LLUUID, 16); htonmemcpy(target_object_id.mData, packed_data + 16, MVT_LLUUID, 16); htonmemcpy(mPositionGlobal.mdV, packed_data + 32, MVT_LLVector3d, 24); LLViewerObject *objp = NULL; if (object_id.isNull()) { setSourceObject(NULL); } else { LLViewerObject *objp = gObjectList.findObject(object_id); if (objp) { setSourceObject(objp); } else { // We don't have this object, kill this effect markDead(); return; } } if (target_object_id.isNull()) { setTargetObject(NULL); } else { objp = gObjectList.findObject(target_object_id); if (objp) { setTargetObject(objp); } else { // We don't have this object, kill this effect markDead(); return; } } triggerLocal(); }
static S32 buildBlock(U8* buffer, S32 buffer_size, const LLMessageBlock* template_data, LLMsgData* message_data) { S32 result = 0; LLMsgData::msg_blk_data_map_t::const_iterator block_iter = message_data->mMemberBlocks.find(template_data->mName); const LLMsgBlkData* mbci = block_iter->second; // ok, if this is the first block of a repeating pack, set // block_count and, if it's type MBT_VARIABLE encode a byte // for how many there are S32 block_count = mbci->mBlockNumber; if (template_data->mType == MBT_VARIABLE) { // remember that mBlockNumber is a S32 U8 temp_block_number = (U8)mbci->mBlockNumber; if ((S32)(result + sizeof(U8)) < MAX_BUFFER_SIZE) { memcpy(&buffer[result], &temp_block_number, sizeof(U8)); result += sizeof(U8); } else { // Just reporting error is likely not enough. Need // to check how to abort or error out gracefully // from this function. XXXTBD llerrs << "buildBlock failed. Message excedding " << "sendBuffersize." << llendl; } } else if (template_data->mType == MBT_MULTIPLE) { if (block_count != template_data->mNumber) { // nope! need to fill it in all the way! llerrs << "Block " << mbci->mName << " is type MBT_MULTIPLE but only has data for " << block_count << " out of its " << template_data->mNumber << " blocks" << llendl; } } while(block_count > 0) { // now loop through the variables for (LLMsgBlkData::msg_var_data_map_t::const_iterator iter = mbci->mMemberVarData.begin(); iter != mbci->mMemberVarData.end(); iter++) { const LLMsgVarData& mvci = *iter; if (mvci.getSize() == -1) { // oops, this variable wasn't ever set! llerrs << "The variable " << mvci.getName() << " in block " << mbci->mName << " of message " << template_data->mName << " wasn't set prior to buildMessage call" << llendl; } else { S32 data_size = mvci.getDataSize(); if(data_size > 0) { // The type is MVT_VARIABLE, which means that we // need to encode a size argument. Otherwise, // there is no need. S32 size = mvci.getSize(); U8 sizeb; U16 sizeh; switch(data_size) { case 1: sizeb = size; htonmemcpy(&buffer[result], &sizeb, MVT_U8, 1); break; case 2: sizeh = size; htonmemcpy(&buffer[result], &sizeh, MVT_U16, 2); break; case 4: htonmemcpy(&buffer[result], &size, MVT_S32, 4); break; default: llerrs << "Attempting to build variable field with unknown size of " << size << llendl; break; } result += mvci.getDataSize(); } // if there is any data to pack, pack it if((mvci.getData() != NULL) && mvci.getSize()) { if(result + mvci.getSize() < buffer_size) { memcpy( &buffer[result], mvci.getData(), mvci.getSize()); result += mvci.getSize(); } else { // Just reporting error is likely not // enough. Need to check how to abort or error // out gracefully from this function. XXXTBD llerrs << "buildBlock failed. " << "Attempted to pack " << result + mvci.getSize() << " bytes into a buffer with size " << buffer_size << "." << llendl; } } } } --block_count; ++block_iter; if (block_iter != message_data->mMemberBlocks.end()) { mbci = block_iter->second; } } return result; }
//----------------------------------------------------------------------------- // unpackData() //----------------------------------------------------------------------------- void LLHUDEffectLookAt::unpackData(LLMessageSystem *mesgsys, S32 blocknum) { LLVector3d new_target; U8 packed_data[PKT_SIZE]; LLUUID dataId; mesgsys->getUUIDFast(_PREHASH_Effect, _PREHASH_ID, dataId, blocknum); if (!gAgentCamera.mLookAt.isNull() && dataId == gAgentCamera.mLookAt->getID()) { return; } LLHUDEffect::unpackData(mesgsys, blocknum); LLUUID source_id; LLUUID target_id; S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData); if (size != PKT_SIZE) { llwarns << "LookAt effect with bad size " << size << llendl; return; } mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, PKT_SIZE, blocknum); htonmemcpy(source_id.mData, &(packed_data[SOURCE_AVATAR]), MVT_LLUUID, 16); LLViewerObject *objp = gObjectList.findObject(source_id); if (objp && objp->isAvatar()) { setSourceObject(objp); } else { //llwarns << "Could not find source avatar for lookat effect" << llendl; return; } htonmemcpy(target_id.mData, &(packed_data[TARGET_OBJECT]), MVT_LLUUID, 16); objp = gObjectList.findObject(target_id); htonmemcpy(new_target.mdV, &(packed_data[TARGET_POS]), MVT_LLVector3d, 24); if (objp) { setTargetObjectAndOffset(objp, new_target); } else if (target_id.isNull()) { setTargetPosGlobal(new_target); } else { //llwarns << "Could not find target object for lookat effect" << llendl; } U8 lookAtTypeUnpacked = 0; htonmemcpy(&lookAtTypeUnpacked, &(packed_data[LOOKAT_TYPE]), MVT_U8, 1); mTargetType = (ELookAtType)lookAtTypeUnpacked; if (mTargetType == LOOKAT_TARGET_NONE) { clearLookAtTarget(); } }
// decode a given message BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender ) { llassert( mReceiveSize >= 0 ); llassert( mCurrentRMessageTemplate); llassert( !mCurrentRMessageData ); delete mCurrentRMessageData; // just to make sure // The offset tells us how may bytes to skip after the end of the // message name. U8 offset = buffer[PHL_OFFSET]; S32 decode_pos = LL_PACKET_ID_SIZE + (S32)(mCurrentRMessageTemplate->mFrequency) + offset; // create base working data set mCurrentRMessageData = new LLMsgData(mCurrentRMessageTemplate->mName); // loop through the template building the data structure as we go LLMessageTemplate::message_block_map_t::const_iterator iter; for(iter = mCurrentRMessageTemplate->mMemberBlocks.begin(); iter != mCurrentRMessageTemplate->mMemberBlocks.end(); ++iter) { LLMessageBlock* mbci = *iter; U8 repeat_number; S32 i; // how many of this block? if (mbci->mType == MBT_SINGLE) { // just one repeat_number = 1; } else if (mbci->mType == MBT_MULTIPLE) { // a known number repeat_number = mbci->mNumber; } else if (mbci->mType == MBT_VARIABLE) { // need to read the number from the message // repeat number is a single byte if (decode_pos >= mReceiveSize) { // commented out - hetgrid says that missing variable blocks // at end of message are legal // logRanOffEndOfPacket(sender, decode_pos, 1); // default to 0 repeats repeat_number = 0; } else { repeat_number = buffer[decode_pos]; decode_pos++; } } else { llerrs << "Unknown block type" << llendl; return FALSE; } LLMsgBlkData* cur_data_block = NULL; // now loop through the block for (i = 0; i < repeat_number; i++) { if (i) { // build new name to prevent collisions // TODO: This should really change to a vector cur_data_block = new LLMsgBlkData(mbci->mName, repeat_number); cur_data_block->mName = mbci->mName + i; } else { cur_data_block = new LLMsgBlkData(mbci->mName, repeat_number); } // add the block to the message mCurrentRMessageData->addBlock(cur_data_block); // now read the variables for (LLMessageBlock::message_variable_map_t::const_iterator iter = mbci->mMemberVariables.begin(); iter != mbci->mMemberVariables.end(); iter++) { const LLMessageVariable& mvci = **iter; // ok, build out the variables // add variable block cur_data_block->addVariable(mvci.getName(), mvci.getType()); // what type of variable? if (mvci.getType() == MVT_VARIABLE) { // variable, get the number of bytes to read from the template S32 data_size = mvci.getSize(); U8 tsizeb = 0; U16 tsizeh = 0; U32 tsize = 0; if ((decode_pos + data_size) > mReceiveSize) { logRanOffEndOfPacket(sender, decode_pos, data_size); // default to 0 length variable blocks tsize = 0; } else { switch(data_size) { case 1: htonmemcpy(&tsizeb, &buffer[decode_pos], MVT_U8, 1); tsize = tsizeb; break; case 2: htonmemcpy(&tsizeh, &buffer[decode_pos], MVT_U16, 2); tsize = tsizeh; break; case 4: htonmemcpy(&tsize, &buffer[decode_pos], MVT_U32, 4); break; default: llerrs << "Attempting to read variable field with unknown size of " << data_size << llendl; break; } } decode_pos += data_size; cur_data_block->addData(mvci.getName(), &buffer[decode_pos], tsize, mvci.getType()); decode_pos += tsize; } else { // fixed! // so, copy data pointer and set data size to fixed size if ((decode_pos + mvci.getSize()) > mReceiveSize) { logRanOffEndOfPacket(sender, decode_pos, mvci.getSize()); // default to 0s. U32 size = mvci.getSize(); std::vector<U8> data(size); if (size) memset(&(data[0]), 0, size); cur_data_block->addData(mvci.getName(), &(data[0]), size, mvci.getType()); } else { cur_data_block->addData(mvci.getName(), &buffer[decode_pos], mvci.getSize(), mvci.getType()); } decode_pos += mvci.getSize(); } } } } if (mCurrentRMessageData->mMemberBlocks.empty() && !mCurrentRMessageTemplate->mMemberBlocks.empty()) { lldebugs << "Empty message '" << mCurrentRMessageTemplate->mName << "' (no blocks)" << llendl; return FALSE; } { static LLTimer decode_timer; if(LLMessageReader::getTimeDecodes() || gMessageSystem->getTimingCallback()) { decode_timer.reset(); } { LLFastTimer t(LLFastTimer::FTM_PROCESS_MESSAGES); if( !mCurrentRMessageTemplate->callHandlerFunc(gMessageSystem) ) { llwarns << "Message from " << sender << " with no handler function received: " << mCurrentRMessageTemplate->mName << llendl; } } if(LLMessageReader::getTimeDecodes() || gMessageSystem->getTimingCallback()) { F32 decode_time = decode_timer.getElapsedTimeF32(); if (gMessageSystem->getTimingCallback()) { (gMessageSystem->getTimingCallback())(mCurrentRMessageTemplate->mName, decode_time, gMessageSystem->getTimingCallbackData()); } if (LLMessageReader::getTimeDecodes()) { mCurrentRMessageTemplate->mDecodeTimeThisFrame += decode_time; mCurrentRMessageTemplate->mTotalDecoded++; mCurrentRMessageTemplate->mTotalDecodeTime += decode_time; if( mCurrentRMessageTemplate->mMaxDecodeTimePerMsg < decode_time ) { mCurrentRMessageTemplate->mMaxDecodeTimePerMsg = decode_time; } if(decode_time > LLMessageReader::getTimeDecodesSpamThreshold()) { lldebugs << "--------- Message " << mCurrentRMessageTemplate->mName << " decode took " << decode_time << " seconds. (" << mCurrentRMessageTemplate->mMaxDecodeTimePerMsg << " max, " << (mCurrentRMessageTemplate->mTotalDecodeTime / mCurrentRMessageTemplate->mTotalDecoded) << " avg)" << llendl; } } } } return TRUE; }
void LLXfer::sendPacket(S32 packet_num) { char fdata_buf[LL_XFER_LARGE_PAYLOAD+4]; /* Flawfinder: ignore */ S32 fdata_size = mChunkSize; BOOL last_packet = FALSE; S32 num_copy = 0; // if the desired packet is not in our current buffered excerpt from the file. . . if (((U32)packet_num*fdata_size < mBufferStartOffset) || ((U32)llmin((U32)mXferSize,(U32)((U32)(packet_num+1)*fdata_size)) > mBufferStartOffset + mBufferLength)) { if (suck(packet_num*fdata_size)) // returns non-zero on failure { abort(LL_ERR_EOF); return; } } S32 desired_read_position = 0; desired_read_position = packet_num * fdata_size - mBufferStartOffset; fdata_size = llmin((S32)mBufferLength-desired_read_position, mChunkSize); if (fdata_size < 0) { llwarns << "negative data size in xfer send, aborting" << llendl; abort(LL_ERR_EOF); return; } if (((U32)(desired_read_position + fdata_size) >= (U32)mBufferLength) && (mBufferContainsEOF)) { last_packet = TRUE; } if (packet_num) { num_copy = llmin(fdata_size, (S32)sizeof(fdata_buf)); num_copy = llmin(num_copy, (S32)(mBufferLength - desired_read_position)); if (num_copy > 0) { memcpy(fdata_buf,&mBuffer[desired_read_position],num_copy); /*Flawfinder: ignore*/ } } else { // if we're the first packet, encode size as an additional S32 // at start of data. num_copy = llmin(fdata_size, (S32)(sizeof(fdata_buf)-sizeof(S32))); num_copy = llmin( num_copy, (S32)(mBufferLength - desired_read_position)); if (num_copy > 0) { memcpy( /*Flawfinder: ignore*/ fdata_buf + sizeof(S32), &mBuffer[desired_read_position], num_copy); } fdata_size += sizeof(S32); htonmemcpy(fdata_buf,&mXferSize, MVT_S32, sizeof(S32)); } S32 encoded_packetnum = encodePacketNum(packet_num,last_packet); if (fdata_size) { // send the packet gMessageSystem->newMessageFast(_PREHASH_SendXferPacket); gMessageSystem->nextBlockFast(_PREHASH_XferID); gMessageSystem->addU64Fast(_PREHASH_ID, mID); gMessageSystem->addU32Fast(_PREHASH_Packet, encoded_packetnum); gMessageSystem->nextBlockFast(_PREHASH_DataPacket); gMessageSystem->addBinaryDataFast(_PREHASH_Data, &fdata_buf,fdata_size); gMessageSystem->sendMessage(mRemoteHost); ACKTimer.reset(); mWaitingForACK = TRUE; } if (last_packet) { mStatus = e_LL_XFER_COMPLETE; } else { mStatus = e_LL_XFER_IN_PROGRESS; } }