diff options
128 files changed, 8186 insertions, 4336 deletions
diff --git a/etc/message.xml b/etc/message.xml new file mode 100644 index 0000000000..b0153452ac --- /dev/null +++ b/etc/message.xml @@ -0,0 +1,231 @@ +<?xml version="1.0"?> +<llsd> + <map> + <key>serverDefaults</key> + <!-- + a map of server names to default message transport + --> + <map> + <key>simulator</key> + <string>template</string> + + <key>userserver</key> + <string>template</string> + + <key>spaceserver</key> + <string>template</string> + + <key>dataserver</key> + <string>template</string> + + <key>logDataserver</key> + <string>template</string> + + <key>inventoryDataserver</key> + <string>template</string> + + <key>rpcserver</key> + <string>template</string> + + <key>mapserver</key> + <string>template</string> + + </map> + <key>messages</key> + <!-- + a map of individual message names that override defaults + --> + <map> + <!-- + Circuit related messages + --> + <key>PacketAck</key> + <map> + <key>builder</key> + <string>template</string> + <key>trusted-sender</key> + <boolean>false</boolean> + </map> + + <key>OpenCircuit</key> + <map> + <key>builder</key> + <string>template</string> + <key>trusted-sender</key> + <boolean>false</boolean> + </map> + + <key>CloseCircuit</key> + <map> + <key>builder</key> + <string>template</string> + <key>trusted-sender</key> + <boolean>false</boolean> + </map> + + <key>StartPingCheck</key> + <map> + <key>builder</key> + <string>template</string> + <key>trusted-sender</key> + <boolean>false</boolean> + </map> + + <key>CompletePingCheck</key> + <map> + <key>builder</key> + <string>template</string> + <key>trusted-sender</key> + <boolean>false</boolean> + </map> + + <key>AddCircuitCode</key> + <map> + <key>builder</key> + <string>template</string> + <key>trusted-sender</key> + <boolean>true</boolean> + </map> + + <key>UseCircuitCode</key> + <map> + <key>builder</key> + <string>template</string> + <key>trusted-sender</key> + <boolean>false</boolean> + </map> + + <key>CreateTrustedCircuit</key> + <map> + <key>builder</key> + <string>template</string> + <key>trusted-sender</key> + <boolean>false</boolean> + </map> + + <!-- + Viewer to userserver messages. + --> + <key>ConnectAgentToUserserver</key> + <map> + <key>builder</key> + <string>template</string> + <key>trusted-sender</key> + <boolean>false</boolean> + </map> + + <!-- + Viewer to simulator messages sent before Untrusted-senderSimulatorMessage cap received. + --> + <key>SecuredTemplateChecksumRequest</key> + <map> + <key>builder</key> + <string>template</string> + <key>trusted-sender</key> + <boolean>false</boolean> + </map> + + <key>CompleteAgentMovement</key> + <map> + <key>builder</key> + <string>template</string> + <key>trusted-sender</key> + <boolean>false</boolean> + </map> + + <key>EconomyDataRequest</key> + <map> + <key>builder</key> + <string>template</string> + <key>trusted-sender</key> + <boolean>false</boolean> + </map> + + <key>ViewerEffect</key> + <map> + <key>builder</key> + <string>template</string> + <key>trusted-sender</key> + <boolean>false</boolean> + </map> + + <!-- + Viewer to simulator messages sent unreliably. + --> + <key>AgentUpdate</key> + <map> + <key>builder</key> + <string>template</string> + <key>trusted-sender</key> + <boolean>false</boolean> + </map> + + <!-- + Messages created by LLThrottleGroup clients + --> + <key>ImagePacket</key> + <map> + <key>builder</key> + <string>template</string> + <key>trusted-sender</key> + <boolean>false</boolean> + </map> + + <key>LayerData</key> + <map> + <key>builder</key> + <string>template</string> + <key>trusted-sender</key> + <boolean>false</boolean> + </map> + + <key>ObjectUpdateCached</key> + <map> + <key>builder</key> + <string>template</string> + <key>trusted-sender</key> + <boolean>false</boolean> + </map> + + <key>ObjectUpdateCompressed</key> + <map> + <key>builder</key> + <string>template</string> + <key>trusted-sender</key> + <boolean>false</boolean> + </map> + + <key>ObjectUpdate</key> + <map> + <key>builder</key> + <string>template</string> + <key>trusted-sender</key> + <boolean>false</boolean> + </map> + + <key>ImprovedTerseObjectUpdate</key> + <map> + <key>builder</key> + <string>template</string> + <key>trusted-sender</key> + <boolean>false</boolean> + </map> + + <key>AvatarAnimation</key> + <map> + <key>builder</key> + <string>template</string> + <key>trusted-sender</key> + <boolean>false</boolean> + </map> + + <key>AvatarAppearance</key> + <map> + <key>builder</key> + <string>template</string> + <key>trusted-sender</key> + <boolean>false</boolean> + </map> + </map> + </map> +</llsd> diff --git a/indra/llcommon/bitpack.cpp b/indra/llcommon/bitpack.cpp deleted file mode 100644 index 4acd533600..0000000000 --- a/indra/llcommon/bitpack.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/** - * @file bitpack.cpp - * @brief Convert data to packed bit stream - * - * Copyright (c) 2000-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -#include "linden_common.h" - -#include "bitpack.h" - -#if 0 -#include <stdio.h> -#include <stdlib.h> -#include "stdtypes.h" - -U8 gLoad, gUnLoad; -U32 gLoadSize, gUnLoadSize, gTotalBits; - -const U32 gMaxDataBits = 8; - -///////////////////////////////////////////////////////////////////////////////////////// -#if 0 -void bit_pack(U8 *outbase, U32 *outptr, U8 *total_data, U32 total_dsize) -{ - U32 max_data_bits = gMaxDataBits; - U32 load_size = gLoadSize, total_bits = gTotalBits; - U32 dsize; - - U8 data; - U8 load = gLoad; - - while (total_dsize > 0) - { - if (total_dsize > max_data_bits) - { - dsize = max_data_bits; - total_dsize -= max_data_bits; - } - else - { - dsize = total_dsize; - total_dsize = 0; - } - - data = *total_data++; - - data <<= (max_data_bits - dsize); - while (dsize > 0) - { - if (load_size == max_data_bits) - { - *(outbase + (*outptr)++) = load; - load_size = 0; - load = 0x00; - } - load <<= 1; - load |= (data >> (max_data_bits - 1)); - data <<= 1; - load_size++; - total_bits++; - dsize--; - } - } - - gLoad = load; - gLoadSize = load_size; - gTotalBits = total_bits; -} -#endif - -///////////////////////////////////////////////////////////////////////////////////////// - -void bit_pack_reset() -{ - gLoad = 0x0; - gLoadSize = 0; - gTotalBits = 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void bit_pack_flush(U8 *outbase, U32 *outptr) -{ - if (gLoadSize) - { - gTotalBits += gLoadSize; - gLoad <<= (gMaxDataBits - gLoadSize); - outbase[(*outptr)++] = gLoad; - gLoadSize = 0; - } -} - -//////////////////////////////////////////////////////////////////////////////////////// -#if 0 -void bit_unpack(U8 *total_retval, U32 total_dsize, U8 *indata, U32 *inptr) -{ - U32 max_data_bits = gMaxDataBits; - U32 unload_size = gUnLoadSize; - U32 dsize; - U8 *retval; - U8 unload = gUnLoad; - - while (total_dsize > 0) - { - if (total_dsize > max_data_bits) - { - dsize = max_data_bits; - total_dsize -= max_data_bits; - } - else - { - dsize = total_dsize; - total_dsize = 0; - } - - retval = total_data++; - *retval = 0x00; - while (dsize > 0) - { - if (unload_size == 0) - { - unload = indata[(*inptr)++]; - unload_size = max_data_bits; - } - *retval <<= 1; - *retval |= (unload >> (max_data_bits - 1)); - unload_size--; - unload <<= 1; - dsize--; - } - } - - gUnLoad = unload; - gUnLoadSize = unload_size; -} -#endif - - -/////////////////////////////////////////////////////////////////////////////////////// - -void bit_unpack_reset() -{ - gUnLoad = 0; - gUnLoadSize = 0; -} -#endif diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h index 20499d4ad3..7f1c48a215 100644 --- a/indra/llcommon/indra_constants.h +++ b/indra/llcommon/indra_constants.h @@ -12,10 +12,6 @@ #include "stdtypes.h" #include "lluuid.h" -// Viewer object cache version, change if object update -// format changes. JC -const U32 INDRA_OBJECT_CACHE_VERSION = 11; - // At 45 Hz collisions seem stable and objects seem // to settle down at a reasonable rate. // JC 3/18/2003 @@ -97,11 +93,11 @@ const U32 DEFAULT_USER_SERVER_PORT = 12036; const U32 DEFAULT_RPC_SERVER_PORT = 12037; const U32 DEFAULT_LOG_DATA_SERVER_PORT = 12039; const U32 DEFAULT_BACKBONE_PORT = 12040; -const U32 DEFAULT_CGI_SERVICES_PORT = 12045; const U32 DEFAULT_LOCAL_ASSET_PORT = 12041; //const U32 DEFAULT_BACKBONE_CAP_PORT = 12042; // Deprecated const U32 DEFAULT_CAP_PROXY_PORT = 12043; const U32 DEFAULT_INV_DATA_SERVER_PORT = 12044; +const U32 DEFAULT_CGI_SERVICES_PORT = 12045; // For automatic port discovery when running multiple viewers on one host const U32 PORT_DISCOVERY_RANGE_MIN = 13000; diff --git a/indra/llcommon/llbase32.h b/indra/llcommon/llbase32.h index 5fd06f9e30..6927607c8f 100644 --- a/indra/llcommon/llbase32.h +++ b/indra/llcommon/llbase32.h @@ -1,19 +1,19 @@ -/**
- * @file llbase32.h
- * @brief base32 encoding that returns a std::string
- * @author James Cook
- *
- * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
- * $License$
- */
-
-#ifndef LLBASE32_H
-#define LLBASE32_h
-
-class LLBase32
-{
-public:
- static std::string encode(const U8* input, size_t input_size);
-};
-
-#endif
+/** + * @file llbase32.h + * @brief base32 encoding that returns a std::string + * @author James Cook + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#ifndef LLBASE32_H +#define LLBASE32_h + +class LLBase32 +{ +public: + static std::string encode(const U8* input, size_t input_size); +}; + +#endif diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp index 796cd9f9f4..c5ab369d0f 100644 --- a/indra/llcommon/llsdserialize_xml.cpp +++ b/indra/llcommon/llsdserialize_xml.cpp @@ -234,7 +234,7 @@ public: Impl(); ~Impl(); - LLSD parse(std::istream& input); + S32 parse(std::istream& input, LLSD& data); void parsePart(const char *buf, int len); @@ -336,7 +336,7 @@ static unsigned get_till_eol(std::istream& input, char *buf, unsigned bufsize) return count; } -LLSD LLSDXMLParser::Impl::parse(std::istream& input) +S32 LLSDXMLParser::Impl::parse(std::istream& input, LLSD& data) { reset(); XML_Status status; @@ -380,11 +380,13 @@ LLSD LLSDXMLParser::Impl::parse(std::istream& input) { ((char*) buffer)[count? count - 1 : 0] = '\0'; llinfos << "LLSDXMLParser::Impl::parse: XML_STATUS_ERROR parsing:" << (char*) buffer << llendl; - return LLSD(); + data = LLSD(); + return -1; } clear_eol(input); - return mResult; + data = mResult; + return 1; } void LLSDXMLParser::Impl::reset() @@ -703,6 +705,5 @@ void LLSDXMLParser::parsePart(const char *buf, int len) // virtual S32 LLSDXMLParser::parse(std::istream& input, LLSD& data) const { - data = impl.parse(input); - return 0; + return impl.parse(input, data); } diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp index a6ac2fb12b..57a024ecee 100644 --- a/indra/llcommon/llsdutil.cpp +++ b/indra/llcommon/llsdutil.cpp @@ -21,7 +21,7 @@ # include <arpa/inet.h> #endif - +#include "llsdserialize.h" // vector3 LLSD ll_sd_from_vector3(const LLVector3& vec) @@ -42,6 +42,27 @@ LLVector3 ll_vector3_from_sd(const LLSD& sd, S32 start_index) return rv; } +// vector4 +LLSD ll_sd_from_vector4(const LLVector4& vec) +{ + LLSD rv; + rv.append((F64)vec.mV[VX]); + rv.append((F64)vec.mV[VY]); + rv.append((F64)vec.mV[VZ]); + rv.append((F64)vec.mV[VW]); + return rv; +} + +LLVector4 ll_vector4_from_sd(const LLSD& sd, S32 start_index) +{ + LLVector4 rv; + rv.mV[VX] = (F32)sd[start_index].asReal(); + rv.mV[VY] = (F32)sd[++start_index].asReal(); + rv.mV[VZ] = (F32)sd[++start_index].asReal(); + rv.mV[VW] = (F32)sd[++start_index].asReal(); + return rv; +} + // vector3d LLSD ll_sd_from_vector3d(const LLVector3d& vec) { @@ -208,9 +229,39 @@ U32 ll_ipaddr_from_sd(const LLSD& sd) LLSD ll_string_from_binary(const LLSD& sd) { std::vector<U8> value = sd.asBinary(); - char* c_str = new char[value.size() + 1]; - memcpy(c_str, &value[0], value.size()); - c_str[value.size()] = '\0'; + std::string str; + str.resize(value.size()); + memcpy(&str[0], &value[0], value.size()); + return str; +} - return c_str; +// Converts an LLSD string to an LLSD binary +LLSD ll_binary_from_string(const LLSD& sd) +{ + std::vector<U8> binary_value; + + LLString string_value = sd.asString(); + const char* string_p = string_value.c_str(); + while (*string_p) + { + binary_value.push_back(*string_p); + string_p++; + } + + binary_value.push_back('\0'); + + return binary_value; +} + +char* ll_print_sd(const LLSD& sd) +{ + const U32 bufferSize = 10 * 1024; + static char buffer[bufferSize]; + std::ostringstream stream; + //stream.rdbuf()->pubsetbuf(buffer, bufferSize); + stream << LLSDOStreamer<LLSDXMLFormatter>(sd); + stream << std::ends; + strncpy(buffer, stream.str().c_str(), bufferSize); + buffer[bufferSize - 1] = '\0'; + return buffer; } diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h index 44e9429d7f..860232044e 100644 --- a/indra/llcommon/llsdutil.h +++ b/indra/llcommon/llsdutil.h @@ -13,6 +13,7 @@ #include "llsd.h" #include "../llmath/v3math.h" +#include "../llmath/v4math.h" #include "../llmath/v3dmath.h" #include "../llmath/v2math.h" #include "../llmath/llquaternion.h" @@ -23,6 +24,10 @@ LLSD ll_sd_from_vector3(const LLVector3& vec); LLVector3 ll_vector3_from_sd(const LLSD& sd, S32 start_index = 0); +// vector4 +LLSD ll_sd_from_vector4(const LLVector4& vec); +LLVector4 ll_vector4_from_sd(const LLSD& sd, S32 start_index = 0); + // vector3d (double) LLSD ll_sd_from_vector3d(const LLVector3d& vec); LLVector3d ll_vector3d_from_sd(const LLSD& sd, S32 start_index = 0); @@ -54,4 +59,10 @@ U32 ll_ipaddr_from_sd(const LLSD& sd); // Binary to string LLSD ll_string_from_binary(const LLSD& sd); +//String to binary +LLSD ll_binary_from_string(const LLSD& sd); + +// Serializes sd to static buffer and returns pointer, useful for gdb debugging. +char* ll_print_sd(const LLSD& sd); + #endif // LL_LLSDUTIL_H diff --git a/indra/llcommon/lluri.cpp b/indra/llcommon/lluri.cpp index bf0d2cb21e..52270376f8 100644 --- a/indra/llcommon/lluri.cpp +++ b/indra/llcommon/lluri.cpp @@ -195,6 +195,19 @@ LLURI LLURI::buildHTTP(const std::string& prefix, result.mEscapedPath += "/" + escapePathComponent(it->asString()); } } + else if(path.isString()) + { + result.mEscapedPath += "/" + escapePathComponent(path.asString()); + } + else if(path.isUndefined()) + { + // do nothing + } + else + { + llwarns << "Valid path arguments to buildHTTP are array, string, or undef, you passed type" + << path.type() << llendl; + } result.mEscapedOpaque = "//" + result.mEscapedAuthority + result.mEscapedPath; return result; @@ -265,17 +278,22 @@ namespace { } } - +#if LL_ENABLE_JANKY_DEPRECATED_WEB_SERVICE_CALLS // static -LLURI LLURI::buildAgentPresenceURI(const LLUUID& agent_id, LLApp* app) +LLURI LLURI::buildBulkAgentNamesURI(LLApp* app) { - return buildBackboneURL(app, "agent", agent_id.asString(), "presence"); -} + std::string host = "localhost:12040"; -// static -LLURI LLURI::buildBulkAgentPresenceURI(LLApp* app) -{ - return buildBackboneURL(app, "agent", "presence"); + if (app) + { + host = app->getOption("backbone-host-port").asString(); + } + + LLSD path = LLSD::emptyArray(); + path.append("agent"); + path.append("names"); + + return buildHTTP(host, path); } // static @@ -302,7 +320,7 @@ LLURI LLURI::buildAgentSessionURI(const LLUUID& agent_id, LLApp* app) } // static -LLURI LLURI::buildInventoryHostURI(const LLUUID& agent_id, LLApp* app) +LLURI LLURI::buildAgentNameURI(const LLUUID& agent_id, LLApp* app) { std::string host = "localhost:12040"; @@ -314,8 +332,7 @@ LLURI LLURI::buildInventoryHostURI(const LLUUID& agent_id, LLApp* app) LLSD path = LLSD::emptyArray(); path.append("agent"); path.append(agent_id); - path.append("inventory"); - path.append("host"); + path.append("name"); return buildHTTP(host, path); } @@ -348,6 +365,7 @@ LLURI LLURI::buildAgentLoginInfoURI(const LLUUID& agent_id, const std::string& d return buildHTTP(dataserver, path); } +#endif // LL_ENABLE_JANKY_DEPRECATED_WEB_SERVICE_CALLS std::string LLURI::asString() const { diff --git a/indra/llcommon/lluri.h b/indra/llcommon/lluri.h index 865a3b21a0..f42cc102e6 100644 --- a/indra/llcommon/lluri.h +++ b/indra/llcommon/lluri.h @@ -77,13 +77,12 @@ public: static std::string unescape(const std::string& str); // Functions for building specific URIs for web services - static LLURI buildAgentPresenceURI(const LLUUID& agent_id, LLApp* app); - static LLURI buildBulkAgentPresenceURI(LLApp* app); - static LLURI buildBulkAgentNamesURI(LLApp* app); - static LLURI buildAgentSessionURI(const LLUUID& agent_id, LLApp* app); - static LLURI buildAgentLoginInfoURI(const LLUUID& agent_id, const std::string& dataserver); - static LLURI buildInventoryHostURI(const LLUUID& agent_id, LLApp* app); - static LLURI buildAgentNameURI(const LLUUID& agent_id, LLApp* app); + // *NOTE: DEPRECATED. use the service builder instead. + //static LLURI buildBulkAgentNamesURI(LLApp* app); + //static LLURI buildAgentSessionURI(const LLUUID& agent_id, LLApp* app); + //static LLURI buildAgentLoginInfoURI(const LLUUID& agent_id, const std::string& dataserver); + //static LLURI buildAgentNameURI(const LLUUID& agent_id, LLApp* app); + private: std::string mScheme; std::string mEscapedOpaque; diff --git a/indra/llinventory/lleconomy.cpp b/indra/llinventory/lleconomy.cpp index 378ab8ced1..f7442380b0 100644 --- a/indra/llinventory/lleconomy.cpp +++ b/indra/llinventory/lleconomy.cpp @@ -151,6 +151,11 @@ void LLRegionEconomy::processEconomyData(LLMessageSystem *msg, void** user_data) void LLRegionEconomy::processEconomyDataRequest(LLMessageSystem *msg, void **user_data) { LLRegionEconomy *this_ptr = (LLRegionEconomy*)user_data; + if (!this_ptr->hasData()) + { + llwarns << "Dropping EconomyDataRequest, because EconomyData message " + << "has not been processed" << llendl; + } msg->newMessageFast(_PREHASH_EconomyData); msg->nextBlockFast(_PREHASH_Info); diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index 94a90f2c20..6164dae22f 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -1772,7 +1772,17 @@ LLPointer<LLInventoryItem> ll_create_item_from_sd(const LLSD& sd_item) rv->rename(sd_item[INV_NAME_LABEL].asString()); rv->setType( LLAssetType::lookup(sd_item[INV_ASSET_TYPE_LABEL].asString().c_str())); - rv->setAssetUUID(sd_item[INV_ASSET_ID_LABEL].asUUID()); + if (sd_item.has("shadow_id")) + { + LLUUID asset_id = sd_item["shadow_id"]; + LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); + cipher.decrypt(asset_id.mData, UUID_BYTES); + rv->setAssetUUID(asset_id); + } + if (sd_item.has(INV_ASSET_ID_LABEL)) + { + rv->setAssetUUID(sd_item[INV_ASSET_ID_LABEL].asUUID()); + } rv->setDescription(sd_item[INV_DESC_LABEL].asString()); rv->setSaleInfo(ll_sale_info_from_sd(sd_item[INV_SALE_INFO_LABEL])); rv->setPermissions(ll_permissions_from_sd(sd_item[INV_PERMISSIONS_LABEL])); diff --git a/indra/llinventory/llparcel.cpp b/indra/llinventory/llparcel.cpp index 42a9d64254..7ea83f6e5e 100644 --- a/indra/llinventory/llparcel.cpp +++ b/indra/llinventory/llparcel.cpp @@ -173,7 +173,6 @@ void LLParcel::init(const LLUUID &owner_id, mRecordTransaction = FALSE; mAuctionID = 0; - mIsReservedForNewbie = FALSE; mInEscrow = false; mParcelFlags = PF_DEFAULT; @@ -633,10 +632,6 @@ BOOL LLParcel::importStream(std::istream& input_stream) { LLString::convertToU32(value, mAuctionID); } - else if("reserved_newbie" == keyword) - { - LLString::convertToBOOL(value, mIsReservedForNewbie); - } else if ("allow_modify" == keyword) { LLString::convertToU32(value, setting); @@ -1071,10 +1066,6 @@ BOOL LLParcel::exportStream(std::ostream& output_stream) { output_stream << "\t\t auction_id " << mAuctionID << "\n"; } - if(mIsReservedForNewbie) - { - output_stream << "\t\t reserved_newbie " << mIsReservedForNewbie << "\n"; - } output_stream << "\t\t allow_modify " << getAllowModify() << "\n"; output_stream << "\t\t allow_group_modify " << getAllowGroupModify() << "\n"; @@ -1615,7 +1606,6 @@ void LLParcel::expireSale(U32& type, U8& flags, LLUUID& from_id, LLUUID& to_id) setSellWithObjects(FALSE); type = TRANS_LAND_RELEASE; mStatus = OS_NONE; - mIsReservedForNewbie = FALSE; flags = pack_transaction_flags(mGroupOwned, FALSE); mAuthBuyerID.setNull(); from_id = mOwnerID; @@ -1633,7 +1623,6 @@ void LLParcel::completeSale(U32& type, U8& flags, flags = pack_transaction_flags(mGroupOwned, mGroupOwned); to_id = mOwnerID; mAuthBuyerID.setNull(); - mIsReservedForNewbie = FALSE; // Purchased parcels are assumed to no longer be for sale. // Otherwise someone can snipe the sale. @@ -1666,7 +1655,6 @@ void LLParcel::clearSale() setPreviousOwnerID(LLUUID::null); setPreviouslyGroupOwned(FALSE); setSellWithObjects(FALSE); - mIsReservedForNewbie = FALSE; } BOOL LLParcel::isPublic() const @@ -1700,7 +1688,6 @@ void LLParcel::clearParcel() setUserLookAt(LLVector3::x_axis); setLandingType(L_LANDING_POINT); setAuctionID(0); - setReservedForNewbie(FALSE); setGroupID(LLUUID::null); setPassPrice(0); setPassHours(0.f); diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h index 16d3cb01e5..131bcdd55d 100644 --- a/indra/llinventory/llparcel.h +++ b/indra/llinventory/llparcel.h @@ -190,7 +190,6 @@ public: void setLandingType(const ELandingType type) { mLandingType = type; } void setAuctionID(U32 auction_id) { mAuctionID = auction_id;} - void setReservedForNewbie(BOOL reserve) { mIsReservedForNewbie = reserve; } void setAllParcelFlags(U32 flags) { mParcelFlags = flags; } void setParcelFlag(U32 flag, BOOL b); @@ -271,7 +270,6 @@ public: BOOL getIsGroupOwned() const { return mGroupOwned; } U32 getAuctionID() { return mAuctionID; } - BOOL getReservedForNewbie() { return mIsReservedForNewbie; } bool isInEscrow() const { return mInEscrow; } BOOL isPublic() const; @@ -518,9 +516,6 @@ protected: // the parcel. U32 mAuctionID; - // This value is TRUE if the land is reserved for a newbie. - BOOL mIsReservedForNewbie; - // value used to temporarily lock attempts to purchase the parcel. bool mInEscrow; diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 00a192aca8..c5d105c9ee 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -196,7 +196,7 @@ void LLProfile::genNGon(S32 sides, F32 offset, F32 bevel, F32 ang_scale, S32 spl t_fraction = (begin - t_first)*sides; // Only use if it's not almost exactly on an edge. - if (t_fraction < 0.99f) + if (t_fraction < 0.9999f) { LLVector3 new_pt = lerp(pt1, pt2, t_fraction); F32 pt_x = new_pt.mV[VX]; @@ -247,7 +247,7 @@ void LLProfile::genNGon(S32 sides, F32 offset, F32 bevel, F32 ang_scale, S32 spl // Find the fraction that we need to add to the end point. t_fraction = (end - (t - t_step))*sides; - if (t_fraction > 0.01f) + if (t_fraction > 0.0001f) { LLVector3 new_pt = lerp(pt1, pt2, t_fraction); F32 pt_x = new_pt.mV[VX]; diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 97aeeb9589..22742e09da 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -42,12 +42,12 @@ const S32 MAX_LOD = 3; const F32 MIN_VOLUME_PROFILE_WIDTH = 0.05f; const F32 MIN_VOLUME_PATH_WIDTH = 0.05f; -const F32 CUT_QUANTA = 0.005f; -const F32 SCALE_QUANTA = 0.01f; -const F32 SHEAR_QUANTA = 0.01f; -const F32 TAPER_QUANTA = 0.01f; -const F32 REV_QUANTA = 0.015f; - +const F32 CUT_QUANTA = 0.00002f; +const F32 SCALE_QUANTA = 0.01f; +const F32 SHEAR_QUANTA = 0.01f; +const F32 TAPER_QUANTA = 0.01f; +const F32 REV_QUANTA = 0.015f; +const F32 HOLLOW_QUANTA = 0.00002f; //============================================================================ @@ -165,7 +165,7 @@ public: { } - LLProfileParams(U8 curve, U8 begin, U8 end, U8 hollow) + LLProfileParams(U8 curve, U16 begin, U16 end, U16 hollow) { mCurveType = curve; F32 temp_f32 = begin * CUT_QUANTA; @@ -180,7 +180,7 @@ public: temp_f32 = 1.f; } mEnd = 1.f - temp_f32; - temp_f32 = hollow * SCALE_QUANTA; + temp_f32 = hollow * HOLLOW_QUANTA; if (temp_f32 > 1.f) { temp_f32 = 1.f; @@ -210,9 +210,9 @@ public: const U8& getCurveType () const { return mCurveType; } void setCurveType(const U32 type) { mCurveType = type;} - void setBegin(const F32 begin) { mBegin = (begin >= 1.0f) ? 0.0f : ((int) (begin * 1000))/1000.0f;} - void setEnd(const F32 end) { mEnd = (end <= 0.0f) ? 1.0f : ((int) (end * 1000))/1000.0f;} - void setHollow(const F32 hollow) { mHollow = ((int) (hollow * 1000))/1000.0f;} + void setBegin(const F32 begin) { mBegin = (begin >= 1.0f) ? 0.0f : ((int) (begin * 100000))/100000.0f;} + void setEnd(const F32 end) { mEnd = (end <= 0.0f) ? 1.0f : ((int) (end * 100000))/100000.0f;} + void setHollow(const F32 hollow) { mHollow = ((int) (hollow * 100000))/100000.0f;} friend std::ostream& operator<<(std::ostream &s, const LLProfileParams &profile_params); @@ -296,11 +296,11 @@ public: mTaper.setVec(tx,ty); } - LLPathParams(U8 curve, U8 begin, U8 end, U8 scx, U8 scy, U8 shx, U8 shy, U8 twistend, U8 twistbegin, U8 radiusoffset, U8 tx, U8 ty, U8 revolutions, U8 skew) + LLPathParams(U8 curve, U16 begin, U16 end, U8 scx, U8 scy, U8 shx, U8 shy, U8 twistend, U8 twistbegin, U8 radiusoffset, U8 tx, U8 ty, U8 revolutions, U8 skew) { mCurveType = curve; - mBegin = (F32)(begin * SCALE_QUANTA); - mEnd = (F32)(100.f - end) * SCALE_QUANTA; + mBegin = (F32)(begin * CUT_QUANTA); + mEnd = (F32)(100.f - end) * CUT_QUANTA; if (mEnd > 1.f) mEnd = 1.f; mScale.setVec((F32) (200 - scx) * SCALE_QUANTA,(F32) (200 - scy) * SCALE_QUANTA); diff --git a/indra/llmessage/llblowfishcipher.cpp b/indra/llmessage/llblowfishcipher.cpp index 0255a654df..d15e4fb69a 100644 --- a/indra/llmessage/llblowfishcipher.cpp +++ b/indra/llmessage/llblowfishcipher.cpp @@ -65,27 +65,33 @@ U32 LLBlowfishCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len) << " iv_len " << iv_length << llendl; - int output_len = 0; - if (!EVP_EncryptUpdate(&context, - dst, - &output_len, - src, - src_len)) - { - llwarns << "LLBlowfishCipher::encrypt EVP_EncryptUpdate failure" << llendl; - return 0; - } - - // There may be some final data left to encrypt if the input is - // not an exact multiple of the block size. - int temp_len = 0; - if (!EVP_EncryptFinal_ex(&context, (unsigned char*)(dst + output_len), &temp_len)) - { - llwarns << "LLBlowfishCipher::encrypt EVP_EncryptFinal failure" << llendl; - return 0; - } - output_len += temp_len; - return output_len; + int output_len = 0;
+ int temp_len = 0;
+ if (!EVP_EncryptUpdate(&context,
+ dst,
+ &output_len,
+ src,
+ src_len))
+ {
+ llwarns << "LLBlowfishCipher::encrypt EVP_EncryptUpdate failure" << llendl;
+ goto ERROR;
+ }
+
+ // There may be some final data left to encrypt if the input is
+ // not an exact multiple of the block size.
+ if (!EVP_EncryptFinal_ex(&context, (unsigned char*)(dst + output_len), &temp_len))
+ {
+ llwarns << "LLBlowfishCipher::encrypt EVP_EncryptFinal failure" << llendl;
+ goto ERROR;
+ }
+ output_len += temp_len;
+
+ EVP_CIPHER_CTX_cleanup(&context);
+ return output_len;
+
+ERROR:
+ EVP_CIPHER_CTX_cleanup(&context);
+ return 0;
} // virtual diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp index 339fdda9ef..36cd2ce188 100644 --- a/indra/llmessage/llcachename.cpp +++ b/indra/llmessage/llcachename.cpp @@ -32,6 +32,10 @@ const char* CN_NONE = "(none)"; const char* CN_HIPPOS = "(hippos)"; const F32 HIPPO_PROBABILITY = 0.01f; +// We track name requests in flight for up to this long. +// We won't re-request a name during this time +const U32 PENDING_TIMEOUT_SECS = 5 * 60; + // File version number const S32 CN_FILE_VERSION = 2; @@ -162,8 +166,9 @@ namespace { } - typedef std::vector<LLUUID> AskQueue; + typedef std::set<LLUUID> AskQueue; typedef std::vector<PendingReply> ReplyQueue; + typedef std::map<LLUUID,U32> PendingQueue; typedef std::map<LLUUID, LLCacheNameEntry*> Cache; typedef std::vector<LLCacheNameCallback> Observers; }; @@ -180,6 +185,9 @@ public: AskQueue mAskNameQueue; AskQueue mAskGroupQueue; // UUIDs to ask our upstream host about + + PendingQueue mPendingQueue; + // UUIDs that have been requested but are not in cache yet. ReplyQueue mReplyQueue; // requests awaiting replies from us @@ -194,6 +202,7 @@ public: void processPendingAsks(); void processPendingReplies(); void sendRequest(const char* msg_name, const AskQueue& queue); + bool isRequestPending(const LLUUID& id); // Message system callbacks. void processUUIDRequest(LLMessageSystem* msg, bool isGroup); @@ -436,7 +445,10 @@ BOOL LLCacheName::getName(const LLUUID& id, char* first, char* last) : CN_WAITING); strcpy(last, ""); /*Flawfinder: ignore*/ - impl.mAskNameQueue.push_back(id); + if (!impl.isRequestPending(id)) + { + impl.mAskNameQueue.insert(id); + } return FALSE; } @@ -476,8 +488,10 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, char* group) // The function signature needs to change to pass in the length // of first and last. strcpy(group, CN_WAITING); /*Flawfinder: ignore*/ - - impl.mAskGroupQueue.push_back(id); + if (!impl.isRequestPending(id)) + { + impl.mAskGroupQueue.insert(id); + } return FALSE; } } @@ -505,13 +519,16 @@ void LLCacheName::get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callb } else { - if (!is_group) - { - impl.mAskNameQueue.push_back(id); - } - else + if (!impl.isRequestPending(id)) { - impl.mAskGroupQueue.push_back(id); + if (!is_group) + { + impl.mAskNameQueue.insert(id); + } + else + { + impl.mAskGroupQueue.insert(id); + } } impl.mReplyQueue.push_back(PendingReply(id, callback, user_data)); } @@ -550,6 +567,19 @@ void LLCacheName::deleteEntriesOlderThan(S32 secs) impl.mCache.erase(curiter); } } + + // These are pending requests that we never heard back from. + U32 pending_expire_time = now - PENDING_TIMEOUT_SECS; + for(PendingQueue::iterator p_iter = impl.mPendingQueue.begin(); + p_iter != impl.mPendingQueue.end(); ) + { + PendingQueue::iterator p_curitor = p_iter++; + + if (p_curitor->second < pending_expire_time) + { + impl.mPendingQueue.erase(p_curitor); + } + } } @@ -579,6 +609,18 @@ void LLCacheName::dump() } } +void LLCacheName::dumpStats() +{ + llinfos << "Queue sizes: " + << " Cache=" << impl.mCache.size() + << " AskName=" << impl.mAskNameQueue.size() + << " AskGroup=" << impl.mAskGroupQueue.size() + << " Pending=" << impl.mPendingQueue.size() + << " Reply=" << impl.mReplyQueue.size() + << " Observers=" << impl.mObservers.size() + << llendl; +} + void LLCacheName::Impl::processPendingAsks() { sendRequest(_PREHASH_UUIDNameRequest, mAskNameQueue); @@ -682,7 +724,23 @@ void LLCacheName::Impl::notifyObservers(const LLUUID& id, } } +bool LLCacheName::Impl::isRequestPending(const LLUUID& id) +{ + U32 now = (U32)time(NULL); + U32 expire_time = now - PENDING_TIMEOUT_SECS; + PendingQueue::iterator iter = mPendingQueue.find(id); + + if (iter == mPendingQueue.end() + || (iter->second < expire_time) ) + { + mPendingQueue[id] = now; + return false; + } + + return true; +} + void LLCacheName::Impl::processUUIDRequest(LLMessageSystem* msg, bool isGroup) { // You should only get this message if the cache is at the simulator @@ -720,13 +778,16 @@ void LLCacheName::Impl::processUUIDRequest(LLMessageSystem* msg, bool isGroup) } else { - if (isGroup) + if (!isRequestPending(id)) { - mAskGroupQueue.push_back(id); - } - else - { - mAskNameQueue.push_back(id); + if (isGroup) + { + mAskGroupQueue.insert(id); + } + else + { + mAskNameQueue.insert(id); + } } mReplyQueue.push_back(PendingReply(id, fromHost)); @@ -750,6 +811,8 @@ void LLCacheName::Impl::processUUIDReply(LLMessageSystem* msg, bool isGroup) mCache[id] = entry; } + mPendingQueue.erase(id); + entry->mIsGroup = isGroup; entry->mCreateTime = (U32)time(NULL); if (!isGroup) diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h index af49903c88..c4f88ac490 100644 --- a/indra/llmessage/llcachename.h +++ b/indra/llmessage/llcachename.h @@ -78,7 +78,8 @@ public: void deleteEntriesOlderThan(S32 secs); // Debugging - void dump(); + void dump(); // Dumps the contents of the cache + void dumpStats(); // Dumps the sizes of the cache and associated queues. private: class Impl; diff --git a/indra/llmessage/llhost.cpp b/indra/llmessage/llhost.cpp index d395188b72..6a74cfe831 100644 --- a/indra/llmessage/llhost.cpp +++ b/indra/llmessage/llhost.cpp @@ -28,7 +28,7 @@ LLHost LLHost::invalid(INVALID_PORT,INVALID_HOST_IP_ADDRESS); LLHost::LLHost(const std::string& ip_and_port) { std::string::size_type colon_index = ip_and_port.find(":"); - if (colon_index != std::string::npos) + if (colon_index == std::string::npos) { mIP = ip_string_to_u32(ip_and_port.c_str()); mPort = 0; diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index 121cbd2e68..92c309f1bc 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -18,6 +18,7 @@ #include "llvfile.h" #include "llvfs.h" +#include "message.h" #include <curl/curl.h> const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f; @@ -92,6 +93,14 @@ namespace if (200 <= mStatus && mStatus < 300) { LLSDSerialize::fromXML(content, istr); +/* + const S32 parseError = -1; + if(LLSDSerialize::fromXML(content, istr) == parseError) + { + mStatus = 498; + mReason = "Client Parse Error"; + } +*/ } if (mResponder.get()) @@ -232,10 +241,17 @@ static void request(const std::string& url, LLURLRequest::ERequestAction method, } req->setCallback(new LLHTTPClientURLAdaptor(responder)); + if (method == LLURLRequest::HTTP_POST && gMessageSystem) { + req->addHeader(llformat("X-SecondLife-UDP-Listen-Port: %d", + gMessageSystem->mPort).c_str()); + } + if (method == LLURLRequest::HTTP_PUT || method == LLURLRequest::HTTP_POST) { - req->addHeader(llformat("Content-Type: %s", body_injector->contentType()).c_str()); - chain.push_back(LLIOPipe::ptr_t(body_injector)); + req->addHeader(llformat("Content-Type: %s", + body_injector->contentType()).c_str()); + + chain.push_back(LLIOPipe::ptr_t(body_injector)); } chain.push_back(LLIOPipe::ptr_t(req)); @@ -293,6 +309,14 @@ LLSD LLHTTPClient::blockingGet(const std::string& url) LLHTTPBuffer http_buffer; + // Without this timeout, blockingGet() calls have been observed to take + // up to 90 seconds to complete. Users of blockingGet() already must + // check the HTTP return code for validity, so this will not introduce + // new errors. A 5 second timeout will succeed > 95% of the time (and + // probably > 99% of the time) based on my statistics. JC + curl_easy_setopt(curlp, CURLOPT_NOSIGNAL, 1); // don't use SIGALRM for timeouts + curl_easy_setopt(curlp, CURLOPT_TIMEOUT, 5); // seconds + curl_easy_setopt(curlp, CURLOPT_WRITEFUNCTION, LLHTTPBuffer::curl_write); curl_easy_setopt(curlp, CURLOPT_WRITEDATA, &http_buffer); curl_easy_setopt(curlp, CURLOPT_URL, url.c_str()); @@ -382,7 +406,7 @@ namespace boost void intrusive_ptr_release(LLHTTPClient::Responder* p) { - if(0 == --p->mReferenceCount) + if(p && 0 == --p->mReferenceCount) { delete p; } diff --git a/indra/llmessage/llhttpsender.cpp b/indra/llmessage/llhttpsender.cpp new file mode 100644 index 0000000000..4152dedae5 --- /dev/null +++ b/indra/llmessage/llhttpsender.cpp @@ -0,0 +1,70 @@ +/** + * @file llhttpsender.cpp + * @brief Abstracts details of sending messages via HTTP. + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#include "linden_common.h" + +#include "llhttpsender.h" + +#include <map> +#include <sstream> + +#include "llhost.h" +#include "llsd.h" + +namespace +{ + typedef std::map<LLHost, LLHTTPSender*> SenderMap; + static SenderMap senderMap; +} + +//virtual +LLHTTPSender::~LLHTTPSender() +{ +} + +//virtual +void LLHTTPSender::send(const LLHost& host, const char* name, + const LLSD& body, + LLHTTPClient::ResponderPtr response) const +{ + // Default implementation inserts sender, message and sends HTTP POST + std::ostringstream stream; + stream << "http://" << host << "/trusted-message/" << name; + llinfos << "LLHTTPSender::send: POST to " << stream.str() << llendl; + LLHTTPClient::post(stream.str(), body, response); +} + +//static +void LLHTTPSender::setSender(const LLHost& host, LLHTTPSender* sender) +{ + llinfos << "LLHTTPSender::setSender " << host << llendl; + senderMap[host] = sender; +} + +//static +const LLHTTPSender& LLHTTPSender::getSender(const LLHost& host) +{ + static LLHTTPSender defaultSender; + SenderMap::const_iterator iter = senderMap.find(host); + if(iter == senderMap.end()) + { + return defaultSender; + } + return *(iter->second); +} + +//static +void LLHTTPSender::clearSender(const LLHost& host) +{ + SenderMap::iterator iter = senderMap.find(host); + if(iter != senderMap.end()) + { + delete iter->second; + senderMap.erase(iter); + } +} diff --git a/indra/llmessage/llhttpsender.h b/indra/llmessage/llhttpsender.h new file mode 100644 index 0000000000..a9f42579c2 --- /dev/null +++ b/indra/llmessage/llhttpsender.h @@ -0,0 +1,38 @@ +/** + * @file llhttpsender.h + * @brief Abstracts details of sending messages via HTTP. + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#ifndef LL_HTTP_SENDER_H +#define LL_HTTP_SENDER_H + +#include "llhttpclient.h" + +class LLHost; +class LLSD; + +class LLHTTPSender +{ + public: + + virtual ~LLHTTPSender(); + + /** @brief Send message to host with body, call response when done */ + virtual void send(const LLHost& host, + const char* message, const LLSD& body, + LLHTTPClient::ResponderPtr response) const; + + /** @brief Set sender for host, takes ownership of sender. */ + static void setSender(const LLHost& host, LLHTTPSender* sender); + + /** @brief Get sender for host, retains ownership of returned sender. */ + static const LLHTTPSender& getSender(const LLHost& host); + + /** @brief Clear sender for host. */ + static void clearSender(const LLHost& host); +}; + +#endif // LL_HTTP_SENDER_H diff --git a/indra/llmessage/llinstantmessage.cpp b/indra/llmessage/llinstantmessage.cpp index 944785c3a5..28886108ea 100644 --- a/indra/llmessage/llinstantmessage.cpp +++ b/indra/llmessage/llinstantmessage.cpp @@ -16,6 +16,7 @@ #include "lluuid.h" #include "llsd.h" #include "llsdserialize.h" +#include "llsdutil.h" #include "llmemory.h" #include "message.h" @@ -290,6 +291,35 @@ void LLIMInfo::unpackMessageBlock(LLMessageSystem* msg) } } +LLSD im_info_to_llsd(LLPointer<LLIMInfo> im_info) +{ + LLSD param_version; + param_version["version"] = 1; + LLSD param_message; + param_message["from_id"] = im_info->mFromID; + param_message["from_group"] = im_info->mFromGroup; + param_message["to_id"] = im_info->mToID; + param_message["from_name"] = im_info->mName; + param_message["message"] = im_info->mMessage; + param_message["type"] = (S32)im_info->mIMType; + param_message["id"] = im_info->mID; + param_message["timestamp"] = (S32)im_info->mTimeStamp; + param_message["offline"] = (S32)im_info->mOffline; + param_message["parent_estate_id"] = (S32)im_info->mParentEstateID; + param_message["region_id"] = im_info->mRegionID; + param_message["position"] = ll_sd_from_vector3(im_info->mPosition); + if (im_info->mData) param_message["data"] = im_info->mData; + LLSD param_agent; + param_agent["agent_id"] = im_info->mFromID; + + LLSD params; + params.append(param_version); + params.append(param_message); + params.append(param_agent); + + return params; +} + LLPointer<LLIMInfo> LLIMInfo::clone() { return new LLIMInfo( diff --git a/indra/llmessage/llinstantmessage.h b/indra/llmessage/llinstantmessage.h index c8138cf491..99b2734a70 100644 --- a/indra/llmessage/llinstantmessage.h +++ b/indra/llmessage/llinstantmessage.h @@ -74,17 +74,19 @@ enum EInstantMessage // communicate with each other. // - // Start a session, or add users to a session. + // Add users to a session. IM_SESSION_ADD = 13, - // Start a session, but don't prune offline users - IM_SESSION_OFFLINE_ADD = 14, + // IM sent automatically on call for help, + // sets up a way for each Helper reached to teleport to the + // helpee + IM_SESSION_911_SEND = 14, // start a session with your gruop IM_SESSION_GROUP_START = 15, // start a session without a calling card (finder or objects) - IM_SESSION_CARDLESS_START = 16, + IM_SESSION_CONFERENCE_START = 16, // send a message to a session. IM_SESSION_SEND = 17, @@ -123,9 +125,9 @@ enum EInstantMessage // Binary bucket contains the name of the session. IM_SESSION_911_START = 29, - // IM sent automatically on call for help, - // sends a lure to each Helper reached - IM_LURE_911 = 30, + // IM for requesting to teleport to the creator + // of a livehelp session (assuming they are verified first) + IM_TELEPORT_911 = 30, // a message generated by a script which we don't want to // be sent through e-mail. Similar to IM_FROM_TASK, but @@ -266,6 +268,7 @@ public: S32 mTTL; }; +LLSD im_info_to_llsd(LLPointer<LLIMInfo> im_info); void pack_instant_message( LLMessageSystem* msgsystem, diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp index c1a9bc442e..869012e431 100644 --- a/indra/llmessage/lliohttpserver.cpp +++ b/indra/llmessage/lliohttpserver.cpp @@ -27,6 +27,8 @@ #include "llsdserialize_xml.h" #include "llstl.h" +#include <sstream> + static const char HTTP_VERSION_STR[] = "HTTP/1.0"; static const std::string CONTEXT_REQUEST("request"); static const std::string HTTP_VERB_GET("GET"); @@ -374,7 +376,7 @@ LLIOPipe::EStatus LLHTTPResponseHeader::process_impl( class LLHTTPResponder : public LLIOPipe { public: - LLHTTPResponder(const LLHTTPNode& tree); + LLHTTPResponder(const LLHTTPNode& tree, const LLSD& ctx); ~LLHTTPResponder(); protected: @@ -435,6 +437,7 @@ protected: STATE_SHORT_CIRCUIT }; + LLSD mBuildContext; EState mState; U8* mLastRead; std::string mVerb; @@ -443,12 +446,14 @@ protected: std::string mQuery; std::string mVersion; S32 mContentLength; + LLSD mHeaders; // handle the urls const LLHTTPNode& mRootNode; }; -LLHTTPResponder::LLHTTPResponder(const LLHTTPNode& tree) : +LLHTTPResponder::LLHTTPResponder(const LLHTTPNode& tree, const LLSD& ctx) : + mBuildContext(ctx), mState(STATE_NOTHING), mLastRead(NULL), mContentLength(0), @@ -636,6 +641,11 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl( lldebugs << "Content-Length: " << value << llendl; mContentLength = atoi(value.c_str()); } + else + { + LLString::trimTail(value); + mHeaders[name] = value; + } } } } @@ -701,6 +711,11 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl( chain.push_back(LLIOPipe::ptr_t(new LLIOFlush)); context[CONTEXT_REQUEST]["path"] = mPath; context[CONTEXT_REQUEST]["query-string"] = mQuery; + context[CONTEXT_REQUEST]["remote-host"] + = mBuildContext["remote-host"]; + context[CONTEXT_REQUEST]["remote-port"] + = mBuildContext["remote-port"]; + context[CONTEXT_REQUEST]["headers"] = mHeaders; const LLChainIOFactory* protocolHandler = node->getProtocolHandler(); @@ -785,9 +800,10 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl( -void LLCreateHTTPPipe(LLPumpIO::chain_t& chain, const LLHTTPNode& root) +void LLCreateHTTPPipe(LLPumpIO::chain_t& chain, + const LLHTTPNode& root, const LLSD& ctx) { - chain.push_back(LLIOPipe::ptr_t(new LLHTTPResponder(root))); + chain.push_back(LLIOPipe::ptr_t(new LLHTTPResponder(root, ctx))); } @@ -796,7 +812,7 @@ class LLHTTPResponseFactory : public LLChainIOFactory public: bool build(LLPumpIO::chain_t& chain, LLSD ctx) const { - LLCreateHTTPPipe(chain, mTree); + LLCreateHTTPPipe(chain, mTree, ctx); return true; } diff --git a/indra/llmessage/lliohttpserver.h b/indra/llmessage/lliohttpserver.h index 05dfdc4bf7..f11a1eccf6 100644 --- a/indra/llmessage/lliohttpserver.h +++ b/indra/llmessage/lliohttpserver.h @@ -31,7 +31,8 @@ LLHTTPNode& LLCreateHTTPServer(apr_pool_t* pool, LLPumpIO& pump, U16 port); * for example), use the helper templates below. */ -void LLCreateHTTPPipe(LLPumpIO::chain_t& chain, const LLHTTPNode& root); +void LLCreateHTTPPipe(LLPumpIO::chain_t& chain, + const LLHTTPNode& root, const LLSD& ctx); /**< Create a pipe on the chain that handles HTTP requests. * The requests are served by the node tree given at root. * diff --git a/indra/llmessage/lliopipe.h b/indra/llmessage/lliopipe.h index 5cbe3d8743..6f7fbe652d 100644 --- a/indra/llmessage/lliopipe.h +++ b/indra/llmessage/lliopipe.h @@ -237,7 +237,7 @@ namespace boost } inline void intrusive_ptr_release(LLIOPipe* p) { - if(0 == --p->mReferenceCount) + if(p && 0 == --p->mReferenceCount) { delete p; } diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp index 7649fef0cf..7c33153086 100644 --- a/indra/llmessage/lliosocket.cpp +++ b/indra/llmessage/lliosocket.cpp @@ -519,9 +519,20 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl( if(llsocket) { PUMP_DEBUG; + + apr_sockaddr_t* remote_addr; + apr_socket_addr_get(&remote_addr, APR_REMOTE, socket); + + char* remote_host_string; + apr_sockaddr_ip_get(&remote_host_string, remote_addr); + + LLSD context; + context["remote-host"] = remote_host_string; + context["remote-port"] = remote_addr->port; + LLPumpIO::chain_t chain; chain.push_back(LLIOPipe::ptr_t(new LLIOSocketReader(llsocket))); - if(mReactor->build(chain, LLSD())) + if(mReactor->build(chain, context)) { chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(llsocket))); pump->addChain(chain, mResponseTimeout); diff --git a/indra/llmessage/llmessagebuilder.cpp b/indra/llmessage/llmessagebuilder.cpp new file mode 100644 index 0000000000..d467e6d808 --- /dev/null +++ b/indra/llmessage/llmessagebuilder.cpp @@ -0,0 +1,18 @@ +/** + * @file llmessagebuilder.cpp + * @brief LLMessageBuilder class implementation + * + * Copyright (c) 2006-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#include "linden_common.h" + +#include "llmessagebuilder.h" + +//virtual +LLMessageBuilder::~LLMessageBuilder() +{ + // even abstract base classes need a concrete destructor +} + diff --git a/indra/llmessage/llmessagebuilder.h b/indra/llmessage/llmessagebuilder.h new file mode 100644 index 0000000000..7ae09c54d5 --- /dev/null +++ b/indra/llmessage/llmessagebuilder.h @@ -0,0 +1,70 @@ +#ifndef LL_LLMESSAGEBUILDER_H +#define LL_LLMESSAGEBUILDER_H + +#include <string> + +#include "stdtypes.h" + +class LLMsgData; +class LLQuaternion; +class LLSD; +class LLUUID; +class LLVector3; +class LLVector3d; +class LLVector4; + +class LLMessageBuilder +{ +public: + + //CLASS_LOG_TYPE(LLMessageBuilder); + + virtual ~LLMessageBuilder(); + virtual void newMessage(const char *name) = 0; + + virtual void nextBlock(const char* blockname) = 0; + virtual BOOL removeLastBlock() = 0; // TODO: babbage: remove this horror + + /** All add* methods expect pointers to canonical strings. */ + virtual void addBinaryData(const char *varname, const void *data, + S32 size) = 0; + virtual void addBOOL(const char* varname, BOOL b) = 0; + virtual void addS8(const char *varname, S8 s) = 0; + virtual void addU8(const char *varname, U8 u) = 0; + virtual void addS16(const char *varname, S16 i) = 0; + virtual void addU16(const char *varname, U16 i) = 0; + virtual void addF32(const char *varname, F32 f) = 0; + virtual void addS32(const char *varname, S32 s) = 0; + virtual void addU32(const char *varname, U32 u) = 0; + virtual void addU64(const char *varname, U64 lu) = 0; + virtual void addF64(const char *varname, F64 d) = 0; + virtual void addVector3(const char *varname, const LLVector3& vec) = 0; + virtual void addVector4(const char *varname, const LLVector4& vec) = 0; + virtual void addVector3d(const char *varname, const LLVector3d& vec) = 0; + virtual void addQuat(const char *varname, const LLQuaternion& quat) = 0; + virtual void addUUID(const char *varname, const LLUUID& uuid) = 0; + virtual void addIPAddr(const char *varname, const U32 ip) = 0; + virtual void addIPPort(const char *varname, const U16 port) = 0; + virtual void addString(const char* varname, const char* s) = 0; + virtual void addString(const char* varname, const std::string& s) = 0; + + virtual BOOL isMessageFull(const char* blockname) const = 0; + virtual void compressMessage(U8*& buf_ptr, U32& buffer_length) = 0; + virtual S32 getMessageSize() = 0; + + virtual BOOL isBuilt() const = 0; + virtual BOOL isClear() const = 0; + virtual U32 buildMessage(U8* buffer, U32 buffer_size) = 0; + /**< Return built message size */ + virtual void clearMessage() = 0; + + // TODO: babbage: remove this horror + virtual void setBuilt(BOOL b) = 0; + + virtual const char* getMessageName() const = 0; + + virtual void copyFromMessageData(const LLMsgData& data) = 0; + virtual void copyFromLLSD(const LLSD& data) = 0; +}; + +#endif // LL_LLMESSAGEBUILDER_H diff --git a/indra/llmessage/llmessageconfig.cpp b/indra/llmessage/llmessageconfig.cpp new file mode 100644 index 0000000000..a2b0bc5efa --- /dev/null +++ b/indra/llmessage/llmessageconfig.cpp @@ -0,0 +1,210 @@ +/** + * @file llmessageconfig.cpp + * @brief Live file handling for messaging + * + * Copyright (c) 2000-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#include "linden_common.h" + +#include "llmessageconfig.h" +#include "llfile.h" +#include "lllivefile.h" +#include "llsd.h" +#include "llsdserialize.h" + +static const char messageConfigFileName[] = "message.xml"; +static const F32 messageConfigRefreshRate = 5.0; // seconds +static std::string sServerName = ""; +static std::string sConfigDir = ""; + +class LLMessageConfigFile : public LLLiveFile +{ +private: + LLMessageConfigFile() + : LLLiveFile(fileName(), messageConfigRefreshRate), + mChanged(false) + { } + + static std::string fileName(); + +public: + static LLMessageConfigFile& instance(); + // return the singleton configuration file + +protected: + /* virtual */ void loadFile(); + void loadServerDefaults(const LLSD& data); + void loadMessages(const LLSD& data); + +public: + bool mChanged; + + std::string mServerDefault; + LLSD mMessages; +}; + +std::string LLMessageConfigFile::fileName() +{ + std::ostringstream ostr; + ostr << sConfigDir//gAppSimp->getOption("configdir").asString() + << "/" << messageConfigFileName; + return ostr.str(); +} + +LLMessageConfigFile& LLMessageConfigFile::instance() +{ + static LLMessageConfigFile the_file; + the_file.checkAndReload(); + return the_file; +} + +// virtual +void LLMessageConfigFile::loadFile() +{ + LLSD data; + { + llifstream file(filename().c_str()); + if (file.is_open()) + { + llinfos << "Loading message.xml file at " << fileName() << llendl; + LLSDSerialize::fromXML(data, file); + } + + if (data.isUndefined()) + { + llinfos << "LLMessageConfigFile::loadFile: file missing," + " ill-formed, or simply undefined; not changing the" + " file" << llendl; + return; + } + } + loadServerDefaults(data); + loadMessages(data); +} + +void LLMessageConfigFile::loadServerDefaults(const LLSD& data) +{ + mServerDefault = data["serverDefaults"][sServerName].asString(); + lldebugs << "loading default " << mServerDefault << llendl; +} + +void LLMessageConfigFile::loadMessages(const LLSD& data) +{ + mMessages = data["messages"]; + std::ostringstream out; + LLSDXMLFormatter *formatter = new LLSDXMLFormatter; + formatter->format(mMessages, out); + lldebugs << "loading ... " << out.str() + << " LLMessageConfigFile::loadMessages loaded " + << mMessages.size() << " messages" << llendl; +} + + +//--------------------------------------------------------------- +// LLMessageConfig +//--------------------------------------------------------------- + +//static +void LLMessageConfig::initClass(const std::string& server_name, + const std::string& config_dir) +{ + sServerName = server_name; + sConfigDir = config_dir; + (void) LLMessageConfigFile::instance(); + llinfos << "LLMessageConfig::intiClass config file " + << config_dir << "/" << messageConfigFileName << llendl; +} + +//static +bool LLMessageConfig::isServerDefaultBuilderLLSD() +{ + if (sServerName.empty()) + { + llerrs << "LLMessageConfig::isServerDefaultBuilderLLSD() before" + << " LLMessageConfig::initClass()" << llendl; + } + LLMessageConfigFile& file = LLMessageConfigFile::instance(); + return (file.mServerDefault == "llsd"); +} + +//static +bool LLMessageConfig::isServerDefaultBuilderTemplate() +{ + if (sServerName.empty()) + { + llerrs << "LLMessageConfig::isServerDefaultBuilderTemplate() before" + << " LLMessageConfig::initClass()" << llendl; + } + LLMessageConfigFile& file = LLMessageConfigFile::instance(); + return (file.mServerDefault == "template"); +} + +//static +bool LLMessageConfig::isMessageBuiltLLSD(const std::string& msg_name) +{ + if (sServerName.empty()) + { + llerrs << "LLMessageConfig::isMessageBuiltLLSD(name) before" + << " LLMessageConfig::initClass()" << llendl; + } + LLMessageConfigFile& file = LLMessageConfigFile::instance(); + LLSD config = file.mMessages[msg_name]; + if (!config.has("builder")) + { + return isServerDefaultBuilderLLSD(); + } + return (config["builder"].asString() == "llsd"); +} + +//static +bool LLMessageConfig::isMessageBuiltTemplate(const std::string& msg_name) +{ + if (sServerName.empty()) + { + llerrs << "LLMessageConfig::isMessageBuiltTemplate(name) before" + << " LLMessageConfig::initClass()" << llendl; + } + LLMessageConfigFile& file = LLMessageConfigFile::instance(); + LLSD config = file.mMessages[msg_name]; + if (!config.has("builder")) + { + return isServerDefaultBuilderTemplate(); + } + return (config["builder"].asString() == "template"); +} + +//static +bool LLMessageConfig::isMessageTrusted(const std::string& msg_name) +{ + if (sServerName.empty()) + { + llerrs << "LLMessageConfig::isMessageTrusted(name) before" + << " LLMessageConfig::initClass()" << llendl; + } + LLMessageConfigFile& file = LLMessageConfigFile::instance(); + LLSD config = file.mMessages[msg_name]; + if (!config.has("trusted-sender")) + { + return false; + } + return config["trusted-sender"].asBoolean(); +} + +//static +bool LLMessageConfig::isValidUntrustedMessage(const std::string& msg_name) +{ + if (sServerName.empty()) + { + llerrs << "LLMessageConfig::isMessageTrusted(name) before" + << " LLMessageConfig::initClass()" << llendl; + } + LLMessageConfigFile& file = LLMessageConfigFile::instance(); + LLSD config = file.mMessages[msg_name]; + if (!config.has("trusted-sender")) + { + return false; + } + return !(config["trusted-sender"].asBoolean()); +} diff --git a/indra/llmessage/llmessageconfig.h b/indra/llmessage/llmessageconfig.h new file mode 100644 index 0000000000..2fb6f2077e --- /dev/null +++ b/indra/llmessage/llmessageconfig.h @@ -0,0 +1,31 @@ +/** + * @file llmessageconfig.h + * @brief Live file handling for messaging + * + * Copyright (c) 2000-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#ifndef LL_MESSAGECONFIG_H +#define LL_MESSAGECONFIG_H + +#include <string> + +class LLMessageConfig +{ +public: + static void initClass(const std::string& server_name, + const std::string& config_dir); + // force loading of config file during startup process + // so it can be used for startup features + + static bool isServerDefaultBuilderLLSD(); + static bool isServerDefaultBuilderTemplate(); + + // For individual messages + static bool isMessageBuiltLLSD(const std::string& msg_name); + static bool isMessageBuiltTemplate(const std::string& msg_name); + static bool isMessageTrusted(const std::string& msg_name); + static bool isValidUntrustedMessage(const std::string& msg_name); +}; +#endif // LL_MESSAGECONFIG_H diff --git a/indra/llmessage/llmessagereader.cpp b/indra/llmessage/llmessagereader.cpp new file mode 100644 index 0000000000..4824480e32 --- /dev/null +++ b/indra/llmessage/llmessagereader.cpp @@ -0,0 +1,35 @@ +#include "llmessagereader.h" + +static BOOL sTimeDecodes = FALSE; + +static F32 sTimeDecodesSpamThreshold = 0.05f; + +//virtual +LLMessageReader::~LLMessageReader() +{ + // even abstract base classes need a concrete destructor +} + +//static +void LLMessageReader::setTimeDecodes(BOOL b) +{ + sTimeDecodes = b; +} + +//static +void LLMessageReader::setTimeDecodesSpamThreshold(F32 seconds) +{ + sTimeDecodesSpamThreshold = seconds; +} + +//static +BOOL LLMessageReader::getTimeDecodes() +{ + return sTimeDecodes; +} + +//static +F32 LLMessageReader::getTimeDecodesSpamThreshold() +{ + return sTimeDecodesSpamThreshold; +} diff --git a/indra/llmessage/llmessagereader.h b/indra/llmessage/llmessagereader.h new file mode 100644 index 0000000000..33ce9289f5 --- /dev/null +++ b/indra/llmessage/llmessagereader.h @@ -0,0 +1,59 @@ +#ifndef LL_LLMESSAGEREADER_H +#define LL_LLMESSAGEREADER_H + +#include "stdtypes.h" + +class LLHost; +class LLMessageBuilder; +class LLMsgData; +class LLQuaternion; +class LLUUID; +class LLVector3; +class LLVector3d; +class LLVector4; + +class LLMessageReader +{ + public: + + virtual ~LLMessageReader(); + + /** All get* methods expect pointers to canonical strings. */ + virtual void getBinaryData(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum = 0, S32 max_size = S32_MAX) = 0; + virtual void getBOOL(const char *block, const char *var, BOOL &data, S32 blocknum = 0) = 0; + virtual void getS8(const char *block, const char *var, S8 &data, S32 blocknum = 0) = 0; + virtual void getU8(const char *block, const char *var, U8 &data, S32 blocknum = 0) = 0; + virtual void getS16(const char *block, const char *var, S16 &data, S32 blocknum = 0) = 0; + virtual void getU16(const char *block, const char *var, U16 &data, S32 blocknum = 0) = 0; + virtual void getS32(const char *block, const char *var, S32 &data, S32 blocknum = 0) = 0; + virtual void getF32(const char *block, const char *var, F32 &data, S32 blocknum = 0) = 0; + virtual void getU32(const char *block, const char *var, U32 &data, S32 blocknum = 0) = 0; + virtual void getU64(const char *block, const char *var, U64 &data, S32 blocknum = 0) = 0; + virtual void getF64(const char *block, const char *var, F64 &data, S32 blocknum = 0) = 0; + virtual void getVector3(const char *block, const char *var, LLVector3 &vec, S32 blocknum = 0) = 0; + virtual void getVector4(const char *block, const char *var, LLVector4 &vec, S32 blocknum = 0) = 0; + virtual void getVector3d(const char *block, const char *var, LLVector3d &vec, S32 blocknum = 0) = 0; + virtual void getQuat(const char *block, const char *var, LLQuaternion &q, S32 blocknum = 0) = 0; + virtual void getUUID(const char *block, const char *var, LLUUID &uuid, S32 blocknum = 0) = 0; + virtual void getIPAddr(const char *block, const char *var, U32 &ip, S32 blocknum = 0) = 0; + virtual void getIPPort(const char *block, const char *var, U16 &port, S32 blocknum = 0) = 0; + virtual void getString(const char *block, const char *var, S32 buffer_size, char *buffer, S32 blocknum = 0) = 0; + + virtual S32 getNumberOfBlocks(const char *blockname) = 0; + virtual S32 getSize(const char *blockname, const char *varname) = 0; + virtual S32 getSize(const char *blockname, S32 blocknum, const char *varname) = 0; + + virtual void clearMessage() = 0; + + virtual const char* getMessageName() const = 0; + virtual S32 getMessageSize() const = 0; + + virtual void copyToBuilder(LLMessageBuilder&) const = 0; + + static void setTimeDecodes(BOOL b); + static BOOL getTimeDecodes(); + static void setTimeDecodesSpamThreshold(F32 seconds); + static F32 getTimeDecodesSpamThreshold(); +}; + +#endif // LL_LLMESSAGEREADER_H diff --git a/indra/llmessage/llmessagetemplate.cpp b/indra/llmessage/llmessagetemplate.cpp new file mode 100644 index 0000000000..026843d6ec --- /dev/null +++ b/indra/llmessage/llmessagetemplate.cpp @@ -0,0 +1,146 @@ +#include "linden_common.h" + +#include "llmessagetemplate.h" + +#include "message.h" + +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); + } +} + +void LLMsgData::addDataFast(char *blockname, char *varname, const void *data, S32 size, EMsgVariableType type, S32 data_size) +{ + // remember that if the blocknumber is > 0 then the number is appended to the name + char *namep = (char *)blockname; + LLMsgBlkData* block_data = mMemberBlocks[namep]; + if (block_data->mBlockNumber) + { + namep += block_data->mBlockNumber; + block_data->addData(varname, data, size, type, data_size); + } + else + { + block_data->addData(varname, data, size, type, data_size); + } +} + +// LLMessageVariable functions and friends + +std::ostream& operator<<(std::ostream& s, LLMessageVariable &msg) +{ + s << "\t\t" << msg.mName << " ("; + switch (msg.mType) + { + case MVT_FIXED: + s << "Fixed, " << msg.mSize << " bytes total)\n"; + break; + case MVT_VARIABLE: + s << "Variable, " << msg.mSize << " bytes of size info)\n"; + break; + default: + s << "Unknown\n"; + break; + } + return s; +} + +// LLMessageBlock functions and friends + +std::ostream& operator<<(std::ostream& s, LLMessageBlock &msg) +{ + s << "\t" << msg.mName << " ("; + switch (msg.mType) + { + case MBT_SINGLE: + s << "Fixed"; + break; + case MBT_MULTIPLE: + s << "Multiple - " << msg.mNumber << " copies"; + break; + case MBT_VARIABLE: + s << "Variable"; + break; + default: + s << "Unknown"; + break; + } + if (msg.mTotalSize != -1) + { + s << ", " << msg.mTotalSize << " bytes each, " << msg.mNumber*msg.mTotalSize << " bytes total)\n"; + } + else + { + s << ")\n"; + } + + + for (LLMessageBlock::message_variable_map_t::iterator iter = msg.mMemberVariables.begin(); + iter != msg.mMemberVariables.end(); iter++) + { + LLMessageVariable& ci = *(iter->second); + s << ci; + } + + return s; +} + +// LLMessageTemplate functions and friends + +std::ostream& operator<<(std::ostream& s, LLMessageTemplate &msg) +{ + switch (msg.mFrequency) + { + case MFT_HIGH: + s << "========================================\n" << "Message #" << msg.mMessageNumber << "\n" << msg.mName << " ("; + s << "High"; + break; + case MFT_MEDIUM: + s << "========================================\n" << "Message #"; + s << (msg.mMessageNumber & 0xFF) << "\n" << msg.mName << " ("; + s << "Medium"; + break; + case MFT_LOW: + s << "========================================\n" << "Message #"; + s << (msg.mMessageNumber & 0xFFFF) << "\n" << msg.mName << " ("; + s << "Low"; + break; + default: + s << "Unknown"; + break; + } + + if (msg.mTotalSize != -1) + { + s << ", " << msg.mTotalSize << " bytes total)\n"; + } + else + { + s << ")\n"; + } + + for (LLMessageTemplate::message_block_map_t::iterator iter = msg.mMemberBlocks.begin(); + iter != msg.mMemberBlocks.end(); iter++) + { + LLMessageBlock* ci = iter->second; + s << *ci; + } + + return s; +} diff --git a/indra/llmessage/llmessagetemplate.h b/indra/llmessage/llmessagetemplate.h new file mode 100644 index 0000000000..8847ddc0d9 --- /dev/null +++ b/indra/llmessage/llmessagetemplate.h @@ -0,0 +1,356 @@ +#ifndef LL_LLMESSAGETEMPLATE_H +#define LL_LLMESSAGETEMPLATE_H + +#include "lldarray.h" +#include "message.h" // TODO: babbage: Remove... +#include "llstl.h" + +class LLMsgVarData +{ +public: + LLMsgVarData() : mName(NULL), mSize(-1), mDataSize(-1), mData(NULL), mType(MVT_U8) + { + } + + LLMsgVarData(const char *name, EMsgVariableType type) : mSize(-1), mDataSize(-1), mData(NULL), mType(type) + { + mName = (char *)name; + } + + ~LLMsgVarData() + { + // copy constructor just copies the mData pointer, so only delete mData explicitly + } + + void deleteData() + { + delete[] mData; + mData = NULL; + } + + void addData(const void *indata, S32 size, EMsgVariableType type, S32 data_size = -1); + + char *getName() const { return mName; } + S32 getSize() const { return mSize; } + void *getData() { return (void*)mData; } + const void *getData() const { return (const void*)mData; } + S32 getDataSize() const { return mDataSize; } + EMsgVariableType getType() const { return mType; } + +protected: + char *mName; + S32 mSize; + S32 mDataSize; + + U8 *mData; + EMsgVariableType mType; +}; + +class LLMsgBlkData +{ +public: + LLMsgBlkData(const char *name, S32 blocknum) : mOffset(-1), mBlockNumber(blocknum), mTotalSize(-1) + { + mName = (char *)name; + } + + ~LLMsgBlkData() + { + for (msg_var_data_map_t::iterator iter = mMemberVarData.begin(); + iter != mMemberVarData.end(); iter++) + { + iter->deleteData(); + } + } + + void addVariable(const char *name, EMsgVariableType type) + { + LLMsgVarData tmp(name,type); + mMemberVarData[name] = tmp; + } + + void addData(char *name, const void *data, S32 size, EMsgVariableType type, S32 data_size = -1) + { + LLMsgVarData* temp = &mMemberVarData[name]; // creates a new entry if one doesn't exist + temp->addData(data, size, type, data_size); + } + + S32 mOffset; + S32 mBlockNumber; + typedef LLDynamicArrayIndexed<LLMsgVarData, const char *, 8> msg_var_data_map_t; + msg_var_data_map_t mMemberVarData; + char *mName; + S32 mTotalSize; +}; + +class LLMsgData +{ +public: + LLMsgData(const char *name) : mTotalSize(-1) + { + mName = (char *)name; + } + ~LLMsgData() + { + for_each(mMemberBlocks.begin(), mMemberBlocks.end(), DeletePairedPointer()); + } + + void addBlock(LLMsgBlkData *blockp) + { + mMemberBlocks[blockp->mName] = blockp; + } + + void addDataFast(char *blockname, char *varname, const void *data, S32 size, EMsgVariableType type, S32 data_size = -1); + +public: + S32 mOffset; + typedef std::map<char*, LLMsgBlkData*> msg_blk_data_map_t; + msg_blk_data_map_t mMemberBlocks; + char *mName; + S32 mTotalSize; +}; + +// LLMessage* classes store the template of messages +class LLMessageVariable +{ +public: + LLMessageVariable() : mName(NULL), mType(MVT_NULL), mSize(-1) + { + } + + LLMessageVariable(char *name) : mType(MVT_NULL), mSize(-1) + { + mName = name; + } + + LLMessageVariable(char *name, const EMsgVariableType type, const S32 size) : mType(type), mSize(size) + { + mName = gMessageStringTable.getString(name); + } + + ~LLMessageVariable() {} + + friend std::ostream& operator<<(std::ostream& s, LLMessageVariable &msg); + + EMsgVariableType getType() const { return mType; } + S32 getSize() const { return mSize; } + char *getName() const { return mName; } +protected: + char *mName; + EMsgVariableType mType; + S32 mSize; +}; + + +typedef enum e_message_block_type +{ + MBT_NULL, + MBT_SINGLE, + MBT_MULTIPLE, + MBT_VARIABLE, + MBT_EOF +} EMsgBlockType; + +class LLMessageBlock +{ +public: + LLMessageBlock(char *name, EMsgBlockType type, S32 number = 1) : mType(type), mNumber(number), mTotalSize(0) + { + mName = gMessageStringTable.getString(name); + } + + ~LLMessageBlock() + { + for_each(mMemberVariables.begin(), mMemberVariables.end(), DeletePairedPointer()); + } + + void addVariable(char *name, const EMsgVariableType type, const S32 size) + { + LLMessageVariable** varp = &mMemberVariables[name]; + if (*varp != NULL) + { + llerrs << name << " has already been used as a variable name!" << llendl; + } + *varp = new LLMessageVariable(name, type, size); + if (((*varp)->getType() != MVT_VARIABLE) + &&(mTotalSize != -1)) + { + mTotalSize += (*varp)->getSize(); + } + else + { + mTotalSize = -1; + } + } + + EMsgVariableType getVariableType(char *name) + { + return (mMemberVariables[name])->getType(); + } + + S32 getVariableSize(char *name) + { + return (mMemberVariables[name])->getSize(); + } + + friend std::ostream& operator<<(std::ostream& s, LLMessageBlock &msg); + + typedef std::map<const char *, LLMessageVariable*> message_variable_map_t; + message_variable_map_t mMemberVariables; + char *mName; + EMsgBlockType mType; + S32 mNumber; + S32 mTotalSize; +}; + + +enum EMsgFrequency +{ + MFT_NULL = 0, // value is size of message number in bytes + MFT_HIGH = 1, + MFT_MEDIUM = 2, + MFT_LOW = 4 +}; + +typedef enum e_message_trust +{ + MT_TRUST, + MT_NOTRUST +} EMsgTrust; + +enum EMsgEncoding +{ + ME_UNENCODED, + ME_ZEROCODED +}; + +class LLMessageTemplate +{ +public: + LLMessageTemplate(const char *name, U32 message_number, EMsgFrequency freq) + : + //mMemberBlocks(), + mName(NULL), + mFrequency(freq), + mTrust(MT_NOTRUST), + mEncoding(ME_ZEROCODED), + mMessageNumber(message_number), + mTotalSize(0), + mReceiveCount(0), + mReceiveBytes(0), + mReceiveInvalid(0), + mDecodeTimeThisFrame(0.f), + mTotalDecoded(0), + mTotalDecodeTime(0.f), + mMaxDecodeTimePerMsg(0.f), + mBanFromTrusted(false), + mBanFromUntrusted(false), + mHandlerFunc(NULL), + mUserData(NULL) + { + mName = gMessageStringTable.getString(name); + } + + ~LLMessageTemplate() + { + for_each(mMemberBlocks.begin(), mMemberBlocks.end(), DeletePairedPointer()); + } + + void addBlock(LLMessageBlock *blockp) + { + LLMessageBlock** member_blockp = &mMemberBlocks[blockp->mName]; + if (*member_blockp != NULL) + { + llerrs << "Block " << blockp->mName + << "has already been used as a block name!" << llendl; + } + *member_blockp = blockp; + if ( (mTotalSize != -1) + &&(blockp->mTotalSize != -1) + &&( (blockp->mType == MBT_SINGLE) + ||(blockp->mType == MBT_MULTIPLE))) + { + mTotalSize += blockp->mNumber*blockp->mTotalSize; + } + else + { + mTotalSize = -1; + } + } + + LLMessageBlock *getBlock(char *name) + { + return mMemberBlocks[name]; + } + + // Trusted messages can only be recieved on trusted circuits. + void setTrust(EMsgTrust t) + { + mTrust = t; + } + + EMsgTrust getTrust(void) + { + return mTrust; + } + + // controls for how the message should be encoded + void setEncoding(EMsgEncoding e) + { + mEncoding = e; + } + EMsgEncoding getEncoding() + { + return mEncoding; + } + + void setHandlerFunc(void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data) + { + mHandlerFunc = handler_func; + mUserData = user_data; + } + + BOOL callHandlerFunc(LLMessageSystem *msgsystem) + { + if (mHandlerFunc) + { + mHandlerFunc(msgsystem, mUserData); + return TRUE; + } + return FALSE; + } + + bool isBanned(bool trustedSource) + { + return trustedSource ? mBanFromTrusted : mBanFromUntrusted; + } + + friend std::ostream& operator<<(std::ostream& s, LLMessageTemplate &msg); + +public: + typedef std::map<char*, LLMessageBlock*> message_block_map_t; + message_block_map_t mMemberBlocks; + char *mName; + EMsgFrequency mFrequency; + EMsgTrust mTrust; + EMsgEncoding mEncoding; + U32 mMessageNumber; + S32 mTotalSize; + U32 mReceiveCount; // how many of this template have been received since last reset + U32 mReceiveBytes; // How many bytes received + U32 mReceiveInvalid; // How many "invalid" packets + F32 mDecodeTimeThisFrame; // Total seconds spent decoding this frame + U32 mTotalDecoded; // Total messages successfully decoded + F32 mTotalDecodeTime; // Total time successfully decoding messages + F32 mMaxDecodeTimePerMsg; + + bool mBanFromTrusted; + bool mBanFromUntrusted; + +private: + // message handler function (this is set by each application) + void (*mHandlerFunc)(LLMessageSystem *msgsystem, void **user_data); + void **mUserData; +}; + +#endif // LL_LLMESSAGETEMPLATE_H diff --git a/indra/llmessage/llmsgvariabletype.h b/indra/llmessage/llmsgvariabletype.h new file mode 100644 index 0000000000..360d949690 --- /dev/null +++ b/indra/llmessage/llmsgvariabletype.h @@ -0,0 +1,33 @@ +#ifndef LL_LLMSGVARIABLETYPE_H +#define LL_LLMSGVARIABLETYPE_H + +typedef enum e_message_variable_type +{ + MVT_NULL, + MVT_FIXED, + MVT_VARIABLE, + MVT_U8, + MVT_U16, + MVT_U32, + MVT_U64, + MVT_S8, + MVT_S16, + MVT_S32, + MVT_S64, + MVT_F32, + MVT_F64, + MVT_LLVector3, + MVT_LLVector3d, + MVT_LLVector4, + MVT_LLQuaternion, + MVT_LLUUID, + MVT_BOOL, + MVT_IP_ADDR, + MVT_IP_PORT, + MVT_U16Vec3, + MVT_U16Quat, + MVT_S16Array, + MVT_EOL +} EMsgVariableType; + +#endif // LL_LLMSGVARIABLETYPE_H diff --git a/indra/llmessage/llpacketack.h b/indra/llmessage/llpacketack.h index 0874da6236..4c22dc2d62 100644 --- a/indra/llmessage/llpacketack.h +++ b/indra/llmessage/llpacketack.h @@ -44,6 +44,14 @@ public: public: LLReliablePacketParams() { + clear(); + }; + + ~LLReliablePacketParams() { }; + + void clear() + { + mHost.invalidate(); mRetries = 0; mPingBasedRetry = TRUE; mTimeout = 0.f; @@ -52,8 +60,6 @@ public: mMessageName = NULL; }; - ~LLReliablePacketParams() { }; - void set ( const LLHost &host, S32 retries, BOOL ping_based_retry, F32 timeout, void (*callback)(void **,S32), void **callback_data, char *name ) @@ -117,7 +123,13 @@ public: } }; - ~LLReliablePacket(){ delete [] mBuffer; }; + + ~LLReliablePacket() + { + mCallback = NULL; + delete [] mBuffer; + mBuffer = NULL; + }; friend class LLCircuitData; protected: diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp index 1be6c21cc2..4fa3fab1c9 100644 --- a/indra/llmessage/llpumpio.cpp +++ b/indra/llmessage/llpumpio.cpp @@ -314,6 +314,12 @@ bool LLPumpIO::copyCurrentLinkInfo(links_t& links) const void LLPumpIO::pump() { + pump(DEFAULT_POLL_TIMEOUT); +} + +//timeout is in microseconds +void LLPumpIO::pump(const S32& poll_timeout) +{ LLMemType m1(LLMemType::MTYPE_IO_PUMP); LLFastTimer t1(LLFastTimer::FTM_PUMP); //llinfos << "LLPumpIO::pump()" << llendl; @@ -395,7 +401,7 @@ void LLPumpIO::pump() S32 count = 0; S32 client_id = 0; const apr_pollfd_t* poll_fd = NULL; - apr_pollset_poll(mPollset, DEFAULT_POLL_TIMEOUT, &count, &poll_fd); + apr_pollset_poll(mPollset, poll_timeout, &count, &poll_fd); PUMP_DEBUG; for(S32 i = 0; i < count; ++i) { diff --git a/indra/llmessage/llpumpio.h b/indra/llmessage/llpumpio.h index 50f7411298..5edfbdf8ee 100644 --- a/indra/llmessage/llpumpio.h +++ b/indra/llmessage/llpumpio.h @@ -227,6 +227,7 @@ public: * chain has a file descriptor ready, <code>process()</code> will * be called for all pipes which have requested it. */ + void pump(const S32& poll_timeout); void pump(); /** diff --git a/indra/llmessage/llsdmessagebuilder.cpp b/indra/llmessage/llsdmessagebuilder.cpp new file mode 100755 index 0000000000..b7deb4817f --- /dev/null +++ b/indra/llmessage/llsdmessagebuilder.cpp @@ -0,0 +1,281 @@ +#include "linden_common.h" + +#include "llsdmessagebuilder.h" + +#include "llmessagetemplate.h" +#include "llquaternion.h" +#include "llsdutil.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<U8> v; + v.resize(size); + memcpy(&(v[0]), reinterpret_cast<const U8*>(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; +} + +// make sure that all the desired data is in place and then copy the data +// into MAX_BUFFER_SIZEd buffer +U32 LLSDMessageBuilder::buildMessage(U8* buffer, U32 buffer_size) +{ + 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; + + // TODO: Copy mvci data in to block: + // (*mCurrentBlock)[varname] = v; + } + } +} + +//virtual +void LLSDMessageBuilder::copyFromLLSD(const LLSD& msg) +{ + mCurrentMessage = msg; + llinfos << LLSDXMLStreamer(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(); +} diff --git a/indra/llmessage/llsdmessagebuilder.h b/indra/llmessage/llsdmessagebuilder.h new file mode 100755 index 0000000000..f04194d12f --- /dev/null +++ b/indra/llmessage/llsdmessagebuilder.h @@ -0,0 +1,98 @@ +#ifndef LL_LLSDMESSAGEBUILDER_H +#define LL_LLSDMESSAGEBUILDER_H + +#include <map> + +#include "llmessagebuilder.h" +#include "llmsgvariabletype.h" +#include "llsd.h" + +class LLMessageTemplate; +class LLMsgData; + +class LLSDMessageBuilder : public LLMessageBuilder +{ +public: + + //CLASS_LOG_TYPE(LLSDMessageBuilder); + + LLSDMessageBuilder(); + virtual ~LLSDMessageBuilder(); + + virtual void newMessage(const char *name); + + virtual void nextBlock(const char* blockname); + virtual BOOL removeLastBlock(); // TODO: babbage: remove this horror... + + /** All add* methods expect pointers to canonical varname strings. */ + virtual void addBinaryData(const char *varname, const void *data, + S32 size); + virtual void addBOOL(const char* varname, BOOL b); + virtual void addS8(const char *varname, S8 s); + virtual void addU8(const char *varname, U8 u); + virtual void addS16(const char *varname, S16 i); + virtual void addU16(const char *varname, U16 i); + virtual void addF32(const char *varname, F32 f); + virtual void addS32(const char *varname, S32 s); + virtual void addU32(const char *varname, U32 u); + virtual void addU64(const char *varname, U64 lu); + virtual void addF64(const char *varname, F64 d); + virtual void addVector3(const char *varname, const LLVector3& vec); + virtual void addVector4(const char *varname, const LLVector4& vec); + virtual void addVector3d(const char *varname, const LLVector3d& vec); + virtual void addQuat(const char *varname, const LLQuaternion& quat); + virtual void addUUID(const char *varname, const LLUUID& uuid); + virtual void addIPAddr(const char *varname, const U32 ip); + virtual void addIPPort(const char *varname, const U16 port); + virtual void addString(const char* varname, const char* s); + virtual void addString(const char* varname, const std::string& s); + + virtual BOOL isMessageFull(const char* blockname) const; + virtual void compressMessage(U8*& buf_ptr, U32& buffer_length); + + virtual BOOL isBuilt() const; + virtual BOOL isClear() const; + virtual U32 buildMessage(U8* buffer, U32 buffer_size); + /**< Return built message size */ + + virtual void clearMessage(); + + // TODO: babbage: remove this horror. + virtual void setBuilt(BOOL b); + + virtual S32 getMessageSize(); + virtual const char* getMessageName() const; + + virtual void copyFromMessageData(const LLMsgData& data); + + virtual void copyFromLLSD(const LLSD& msg); + + const LLSD& getMessage() const; +private: + + /* mCurrentMessage is of the following format: + mCurrentMessage = { 'block_name1' : [ { 'block1_field1' : 'b1f1_data', + 'block1_field2' : 'b1f2_data', + ... + 'block1_fieldn' : 'b1fn_data'}, + { 'block2_field1' : 'b2f1_data', + 'block2_field2' : 'b2f2_data', + ... + 'block2_fieldn' : 'b2fn_data'}, + ... + { 'blockm_field1' : 'bmf1_data', + 'blockm_field2' : 'bmf2_data', + ... + 'blockm_fieldn' : 'bmfn_data'} ], + 'block_name2' : ..., + ... + 'block_namem' } */ + LLSD mCurrentMessage; + LLSD* mCurrentBlock; + std::string mCurrentMessageName; + std::string mCurrentBlockName; + BOOL mbSBuilt; + BOOL mbSClear; +}; + +#endif // LL_LLSDMESSAGEBUILDER_H diff --git a/indra/llmessage/llsdmessagereader.cpp b/indra/llmessage/llsdmessagereader.cpp new file mode 100755 index 0000000000..6312bee0ab --- /dev/null +++ b/indra/llmessage/llsdmessagereader.cpp @@ -0,0 +1,264 @@ +#include "llsdmessagereader.h" +#include "llsdutil.h" +#include "llmessagebuilder.h" +#include "llsdmessagebuilder.h" + +LLSDMessageReader::LLSDMessageReader() +{ +} + +//virtual +LLSDMessageReader::~LLSDMessageReader() +{ +} + + +LLSD getLLSD(const LLSD& input, const char* block, const char* var, S32 blocknum) +{ + if(input[block].isArray()) + { + return input[block][blocknum][var]; + } + return LLSD(); +} + +//virtual +void LLSDMessageReader::getBinaryData(const char *block, const char *var, + void *datap, S32 size, S32 blocknum, + S32 max_size) +{ + std::vector<U8> data = getLLSD(mMessage, block, var, blocknum); + S32 data_size = (S32)data.size(); + + if (size && data_size != size) + { + return; + } + + if (max_size < data_size) + { + data_size = max_size; + } + + memcpy(datap, &(data[0]), data_size); +} + +//virtual +void LLSDMessageReader::getBOOL(const char *block, const char *var, + BOOL &data, + S32 blocknum) +{ + data = getLLSD(mMessage, block, var, blocknum); +} + +//virtual +void LLSDMessageReader::getS8(const char *block, const char *var, S8 &data, + S32 blocknum) +{ + data = getLLSD(mMessage, block, var, blocknum).asInteger(); +} + +//virtual +void LLSDMessageReader::getU8(const char *block, const char *var, U8 &data, + S32 blocknum) +{ + data = getLLSD(mMessage, block, var, blocknum).asInteger(); +} + +//virtual +void LLSDMessageReader::getS16(const char *block, const char *var, S16 &data, + S32 blocknum) +{ + data = getLLSD(mMessage, block, var, blocknum).asInteger(); +} + +//virtual +void LLSDMessageReader::getU16(const char *block, const char *var, U16 &data, + S32 blocknum) +{ + data = getLLSD(mMessage, block, var, blocknum).asInteger(); +} + +//virtual +void LLSDMessageReader::getS32(const char *block, const char *var, S32 &data, + S32 blocknum) +{ + data = getLLSD(mMessage, block, var, blocknum); +} + +//virtual +void LLSDMessageReader::getF32(const char *block, const char *var, F32 &data, + S32 blocknum) +{ + data = (F32)getLLSD(mMessage, block, var, blocknum).asReal(); +} + +//virtual +void LLSDMessageReader::getU32(const char *block, const char *var, U32 &data, + S32 blocknum) +{ + data = ll_U32_from_sd(getLLSD(mMessage, block, var, blocknum)); +} + +//virtual +void LLSDMessageReader::getU64(const char *block, const char *var, + U64 &data, S32 blocknum) +{ + data = ll_U64_from_sd(getLLSD(mMessage, block, var, blocknum)); +} + +//virtual +void LLSDMessageReader::getF64(const char *block, const char *var, + F64 &data, S32 blocknum) +{ + data = getLLSD(mMessage, block, var, blocknum); +} + +//virtual +void LLSDMessageReader::getVector3(const char *block, const char *var, + LLVector3 &vec, S32 blocknum) +{ + vec = ll_vector3_from_sd(getLLSD(mMessage, block, var, blocknum)); +} + +//virtual +void LLSDMessageReader::getVector4(const char *block, const char *var, + LLVector4 &vec, S32 blocknum) +{ + vec = ll_vector4_from_sd(getLLSD(mMessage, block, var, blocknum)); +} + +//virtual +void LLSDMessageReader::getVector3d(const char *block, const char *var, + LLVector3d &vec, S32 blocknum) +{ + vec = ll_vector3d_from_sd(getLLSD(mMessage, block, var, blocknum)); +} + +//virtual +void LLSDMessageReader::getQuat(const char *block, const char *var, + LLQuaternion &q, S32 blocknum) +{ + q = ll_quaternion_from_sd(getLLSD(mMessage, block, var, blocknum)); +} + +//virtual +void LLSDMessageReader::getUUID(const char *block, const char *var, + LLUUID &uuid, S32 blocknum) +{ + uuid = getLLSD(mMessage, block, var, blocknum); +} + +//virtual +void LLSDMessageReader::getIPAddr(const char *block, const char *var, + U32 &ip, S32 blocknum) +{ + ip = ll_ipaddr_from_sd(getLLSD(mMessage, block, var, blocknum)); +} + +//virtual +void LLSDMessageReader::getIPPort(const char *block, const char *var, + U16 &port, S32 blocknum) +{ + port = getLLSD(mMessage, block, var, blocknum).asInteger(); +} + +//virtual +void LLSDMessageReader::getString(const char *block, const char *var, + S32 buffer_size, char *buffer, S32 blocknum) +{ + std::string data = getLLSD(mMessage, block, var, blocknum); + + S32 data_size = data.size(); + if (data_size >= buffer_size) + { + data_size = buffer_size - 1; + } + memcpy(buffer, data.data(), data_size); + buffer[data_size] = '\0'; +} + + +//virtual +S32 LLSDMessageReader::getNumberOfBlocks(const char *blockname) +{ + return mMessage[blockname].size(); +} + +S32 getElementSize(const LLSD& llsd) +{ + LLSD::Type type = llsd.type(); + switch(type) + { + case LLSD::TypeBoolean: + return sizeof(bool); + case LLSD::TypeInteger: + return sizeof(S32); + case LLSD::TypeReal: + return sizeof(F64); + case LLSD::TypeString: + return llsd.asString().size(); + case LLSD::TypeUUID: + return sizeof(LLUUID); + case LLSD::TypeDate: + return sizeof(LLDate); + case LLSD::TypeURI: + return sizeof(LLURI); + case LLSD::TypeBinary: + { + std::vector<U8> data = llsd; + return data.size() * sizeof(U8); + } + case LLSD::TypeMap: + case LLSD::TypeArray: + case LLSD::TypeUndefined: + return 0; + } + return 0; +} + +//virtual +//Mainly used to find size of binary block of data +S32 LLSDMessageReader::getSize(const char *blockname, const char *varname) +{ + return getElementSize(mMessage[blockname][0][varname]); +} + + +//virtual +S32 LLSDMessageReader::getSize(const char *blockname, S32 blocknum, + const char *varname) +{ + return getElementSize(mMessage[blockname][blocknum][varname]); +} + +//virtual +void LLSDMessageReader::clearMessage() +{ + mMessage = LLSD(); +} + +//virtual +const char* LLSDMessageReader::getMessageName() const +{ + return mMessageName.c_str(); +} + +// virtual +S32 LLSDMessageReader::getMessageSize() const +{ + return 0; +} + +//virtual +void LLSDMessageReader::copyToBuilder(LLMessageBuilder& builder) const +{ + builder.copyFromLLSD(mMessage); +} + +void LLSDMessageReader::setMessage(const std::string& name, const LLSD& message) +{ + mMessageName = name; + // TODO: Validate + mMessage = message; +} diff --git a/indra/llmessage/llsdmessagereader.h b/indra/llmessage/llsdmessagereader.h new file mode 100755 index 0000000000..57851941a2 --- /dev/null +++ b/indra/llmessage/llsdmessagereader.h @@ -0,0 +1,79 @@ +#ifndef LL_LLSDMESSAGEREADER_H +#define LL_LLSDMESSAGEREADER_H + +#include "llmessagereader.h" +#include "llsd.h" + +#include <map> + +class LLMessageTemplate; +class LLMsgData; + +class LLSDMessageReader : public LLMessageReader +{ +public: + + LLSDMessageReader(); + virtual ~LLSDMessageReader(); + + /** All get* methods expect pointers to canonical strings. */ + virtual void getBinaryData(const char *block, const char *var, + void *datap, S32 size, S32 blocknum = 0, + S32 max_size = S32_MAX); + virtual void getBOOL(const char *block, const char *var, BOOL &data, + S32 blocknum = 0); + virtual void getS8(const char *block, const char *var, S8 &data, + S32 blocknum = 0); + virtual void getU8(const char *block, const char *var, U8 &data, + S32 blocknum = 0); + virtual void getS16(const char *block, const char *var, S16 &data, + S32 blocknum = 0); + virtual void getU16(const char *block, const char *var, U16 &data, + S32 blocknum = 0); + virtual void getS32(const char *block, const char *var, S32 &data, + S32 blocknum = 0); + virtual void getF32(const char *block, const char *var, F32 &data, + S32 blocknum = 0); + virtual void getU32(const char *block, const char *var, U32 &data, + S32 blocknum = 0); + virtual void getU64(const char *block, const char *var, U64 &data, + S32 blocknum = 0); + virtual void getF64(const char *block, const char *var, F64 &data, + S32 blocknum = 0); + virtual void getVector3(const char *block, const char *var, + LLVector3 &vec, S32 blocknum = 0); + virtual void getVector4(const char *block, const char *var, + LLVector4 &vec, S32 blocknum = 0); + virtual void getVector3d(const char *block, const char *var, + LLVector3d &vec, S32 blocknum = 0); + virtual void getQuat(const char *block, const char *var, LLQuaternion &q, + S32 blocknum = 0); + virtual void getUUID(const char *block, const char *var, LLUUID &uuid, + S32 blocknum = 0); + virtual void getIPAddr(const char *block, const char *var, U32 &ip, + S32 blocknum = 0); + virtual void getIPPort(const char *block, const char *var, U16 &port, + S32 blocknum = 0); + virtual void getString(const char *block, const char *var, + S32 buffer_size, char *buffer, S32 blocknum = 0); + + virtual S32 getNumberOfBlocks(const char *blockname); + virtual S32 getSize(const char *blockname, const char *varname); + virtual S32 getSize(const char *blockname, S32 blocknum, + const char *varname); + + virtual void clearMessage(); + + virtual const char* getMessageName() const; + virtual S32 getMessageSize() const; + + virtual void copyToBuilder(LLMessageBuilder&) const; + + void setMessage(const std::string& name, const LLSD& msg); + +private: + std::string mMessageName; + LLSD mMessage; +}; + +#endif // LL_LLSDMESSAGEREADER_H diff --git a/indra/llmessage/llservice.h b/indra/llmessage/llservice.h index e243e710d6..fe6fa56477 100644 --- a/indra/llmessage/llservice.h +++ b/indra/llmessage/llservice.h @@ -71,7 +71,7 @@ namespace boost } inline void intrusive_ptr_release(LLServiceCreator* p) { - if(0 == --p->mReferenceCount) + if(p && 0 == --p->mReferenceCount) { delete p; } diff --git a/indra/llmessage/llservicebuilder.cpp b/indra/llmessage/llservicebuilder.cpp new file mode 100644 index 0000000000..fbcf38ae35 --- /dev/null +++ b/indra/llmessage/llservicebuilder.cpp @@ -0,0 +1,115 @@ +/** +* @file llservicebuilder.cpp +* @brief Implementation of the LLServiceBuilder class. +* +* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. +* $License$ +*/ + +#include "llapp.h" +#include "llfile.h" +#include "llservicebuilder.h" +#include "llsd.h" +#include "llsdserialize.h" + +void LLServiceBuilder::loadServiceDefinitionsFromFile( + const std::string& service_filename) +{ + llifstream service_file(service_filename.c_str(), std::ios::binary); + if(service_file.is_open()) + { + LLSD service_data; + LLSDSerialize::fromXML(service_data, service_file); + service_file.close(); + // Load service + LLSD service_map = service_data["services"]; + for(LLSD::array_iterator array_itr = service_map.beginArray(); + array_itr != service_map.endArray(); + ++array_itr) + { + LLSD service_llsd = (*array_itr)["service-builder"]; + std::string service_name = (*array_itr)["name"].asString(); + createServiceDefinition(service_name, service_llsd); + } + llinfos << "loaded config file: " << service_filename << llendl; + } + else + { + llwarns << "unable to find config file: " << service_filename << llendl; + } +} + +void LLServiceBuilder::createServiceDefinition( + const std::string& service_name, + LLSD& service_llsd) +{ + if(service_llsd.isString()) + { + mServiceMap[ service_name ] = service_llsd.asString(); + } + else if(service_llsd.isMap()) + { + for(LLSD::map_iterator map_itr = service_llsd.beginMap(); + map_itr != service_llsd.endMap(); + ++map_itr) + { + std::string compound_builder_name = service_name; + compound_builder_name.append("-"); + compound_builder_name.append((*map_itr).first); + mServiceMap[ compound_builder_name ] = (*map_itr).second.asString(); + } + } +} + +std::string LLServiceBuilder::buildServiceURI(const std::string& service_name) +{ + std::ostringstream service_url; + // Find the service builder + if(mServiceMap.find(service_name) != mServiceMap.end()) + { + // construct the service builder url + LLApp* app = LLApp::instance(); + if(app) + { + LLSD base_url = app->getOption("services-base-url"); + service_url << base_url.asString(); + } + service_url << mServiceMap[service_name]; + } + else + { + llwarns << "Cannot find service " << service_name << llendl; + } + return service_url.str(); +} + +std::string LLServiceBuilder::buildServiceURI( + const std::string& service_name, + const LLSD& option_map) +{ + std::string service_url = buildServiceURI(service_name); + + // Find the Service Name + if(!service_url.empty() && option_map.isMap()) + { + // Do brace replacements - NOT CURRENTLY RECURSIVE + for(LLSD::map_const_iterator option_itr = option_map.beginMap(); + option_itr != option_map.endMap(); + ++option_itr) + { + std::string variable_name = "{$"; + variable_name.append((*option_itr).first); + variable_name.append("}"); + std::string::size_type find_pos = service_url.find(variable_name); + if(find_pos != std::string::npos) + { + service_url.replace( + find_pos, + variable_name.length(), + (*option_itr).second.asString()); + } + } + } + + return service_url; +} diff --git a/indra/llmessage/llservicebuilder.h b/indra/llmessage/llservicebuilder.h new file mode 100644 index 0000000000..2692ffe1e5 --- /dev/null +++ b/indra/llmessage/llservicebuilder.h @@ -0,0 +1,73 @@ +/** +* @file llservicebuilder.h +* @brief Declaration of the LLServiceBuilder class. +* +* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. +* $License$ +*/ + +#ifndef LLSERVICEBUILDER_H +#define LLSERVICEBUILDER_H + +#include <string> +#include <map> +#include "llerror.h" + +class LLSD; + +/** + * @class LLServiceBuilder + * @brief This class builds urls for us to use when making web service calls. + */ + +class LLServiceBuilder +{ + LOG_CLASS(LLServiceBuilder); +public: + LLServiceBuilder(void) {} + ~LLServiceBuilder(void) {} + + /** + * @brief Initialize this object with the service definitions. + * + * @param service_filename The services definition files -- services.xml. + */ + void loadServiceDefinitionsFromFile(const std::string& service_filename); + + /** + * @brief Build a service url if the url needs no construction parameters. + * + * @param service_name The name of the service you want to call. + */ + std::string buildServiceURI(const std::string& service_name); + + /** + * @brief Build a service url if the url with construction parameters. + * + * The parameter substitution supports string substituition from RUSS: + * [[Recursive_URL_Substitution_Syntax]] + * @param service_name The name of the service you want to call. + * @param option_map The parameters in a map of name:value for the service. + */ + std::string buildServiceURI( + const std::string& service_name, + const LLSD& option_map); + +public: + /** + * @brief Helper method which builds construction state for a service + * + * This method should probably be protected, but we need to test this + * method. + */ + void createServiceDefinition( + const std::string& service_name, + LLSD& service_url); + +protected: + std::map<std::string, std::string> mServiceMap; +}; + + + +#endif diff --git a/indra/llmessage/lltemplatemessagebuilder.cpp b/indra/llmessage/lltemplatemessagebuilder.cpp new file mode 100644 index 0000000000..806f03422d --- /dev/null +++ b/indra/llmessage/lltemplatemessagebuilder.cpp @@ -0,0 +1,856 @@ +#include "linden_common.h" + +#include "lltemplatemessagebuilder.h" + +#include "llmessagetemplate.h" +#include "llquaternion.h" +#include "u64.h" +#include "v3dmath.h" +#include "v3math.h" +#include "v4math.h" + +LLTemplateMessageBuilder::LLTemplateMessageBuilder(message_template_name_map_t& name_template_map) : + mCurrentSMessageData(NULL), + mCurrentSMessageTemplate(NULL), + mCurrentSDataBlock(NULL), + mCurrentSMessageName(NULL), + mCurrentSBlockName(NULL), + mbSBuilt(FALSE), + mbSClear(TRUE), + mCurrentSendTotal(0), + mMessageTemplates(name_template_map) +{ +} + +//virtual +LLTemplateMessageBuilder::~LLTemplateMessageBuilder() +{ + delete mCurrentSMessageData; + mCurrentSMessageData = NULL; +} + + +// virtual +void LLTemplateMessageBuilder::newMessage(const char *name) +{ + mbSBuilt = FALSE; + mbSClear = FALSE; + + mCurrentSendTotal = 0; + + delete mCurrentSMessageData; + mCurrentSMessageData = NULL; + + char *namep = (char *)name; + + if (mMessageTemplates.count(namep) > 0) + { + mCurrentSMessageTemplate = mMessageTemplates[namep]; + if (mCurrentSMessageData) + { + delete mCurrentSMessageData; + } + mCurrentSMessageData = new LLMsgData(namep); + mCurrentSMessageName = namep; + mCurrentSDataBlock = NULL; + mCurrentSBlockName = NULL; + + // add at one of each block + LLMessageTemplate* msg_template = mMessageTemplates[namep]; + for (LLMessageTemplate::message_block_map_t::iterator iter = msg_template->mMemberBlocks.begin(); + iter != msg_template->mMemberBlocks.end(); iter++) + { + LLMessageBlock* ci = iter->second; + LLMsgBlkData *tblockp; + tblockp = new LLMsgBlkData(ci->mName, 0); + mCurrentSMessageData->addBlock(tblockp); + } + } + else + { + llerrs << "newMessage - Message " << name << " not registered" << llendl; + } +} + +// virtual +void LLTemplateMessageBuilder::clearMessage() +{ + mbSBuilt = FALSE; + mbSClear = TRUE; + + mCurrentSendTotal = 0; + + mCurrentSMessageTemplate = NULL; + + delete mCurrentSMessageData; + mCurrentSMessageData = NULL; + + mCurrentSMessageName = NULL; + mCurrentSDataBlock = NULL; + mCurrentSBlockName = NULL; +} + +// virtual +void LLTemplateMessageBuilder::nextBlock(const char* blockname) +{ + char *bnamep = (char *)blockname; + + if (!mCurrentSMessageTemplate) + { + llerrs << "newMessage not called prior to setBlock" << llendl; + return; + } + + // now, does this block exist? + LLMessageTemplate::message_block_map_t::iterator temp_iter = mCurrentSMessageTemplate->mMemberBlocks.find(bnamep); + if (temp_iter == mCurrentSMessageTemplate->mMemberBlocks.end()) + { + llerrs << "LLTemplateMessageBuilder::nextBlock " << bnamep + << " not a block in " << mCurrentSMessageTemplate->mName << llendl; + return; + } + + LLMessageBlock* template_data = temp_iter->second; + + // ok, have we already set this block? + LLMsgBlkData* block_data = mCurrentSMessageData->mMemberBlocks[bnamep]; + if (block_data->mBlockNumber == 0) + { + // nope! set this as the current block + block_data->mBlockNumber = 1; + mCurrentSDataBlock = block_data; + mCurrentSBlockName = bnamep; + + // add placeholders for each of the variables + for (LLMessageBlock::message_variable_map_t::iterator iter = template_data->mMemberVariables.begin(); + iter != template_data->mMemberVariables.end(); iter++) + { + LLMessageVariable& ci = *(iter->second); + mCurrentSDataBlock->addVariable(ci.getName(), ci.getType()); + } + return; + } + else + { + // already have this block. . . + // are we supposed to have a new one? + + // if the block is type MBT_SINGLE this is bad! + if (template_data->mType == MBT_SINGLE) + { + llerrs << "LLTemplateMessageBuilder::nextBlock called multiple times" + << " for " << bnamep << " but is type MBT_SINGLE" << llendl; + return; + } + + + // if the block is type MBT_MULTIPLE then we need a known number, + // make sure that we're not exceeding it + if ( (template_data->mType == MBT_MULTIPLE) + &&(mCurrentSDataBlock->mBlockNumber == template_data->mNumber)) + { + llerrs << "LLTemplateMessageBuilder::nextBlock called " + << mCurrentSDataBlock->mBlockNumber << " times for " << bnamep + << " exceeding " << template_data->mNumber + << " specified in type MBT_MULTIPLE." << llendl; + return; + } + + // ok, we can make a new one + // modify the name to avoid name collision by adding number to end + S32 count = block_data->mBlockNumber; + + // incrememt base name's count + block_data->mBlockNumber++; + + if (block_data->mBlockNumber > MAX_BLOCKS) + { + llerrs << "Trying to pack too many blocks into MBT_VARIABLE type " + << "(limited to " << MAX_BLOCKS << ")" << llendl; + } + + // create new name + // Nota Bene: if things are working correctly, + // mCurrentMessageData->mMemberBlocks[blockname]->mBlockNumber == + // mCurrentDataBlock->mBlockNumber + 1 + + char *nbnamep = bnamep + count; + + mCurrentSDataBlock = new LLMsgBlkData(bnamep, count); + mCurrentSDataBlock->mName = nbnamep; + mCurrentSMessageData->mMemberBlocks[nbnamep] = mCurrentSDataBlock; + + // add placeholders for each of the variables + for (LLMessageBlock::message_variable_map_t::iterator + iter = template_data->mMemberVariables.begin(), + end = template_data->mMemberVariables.end(); + iter != end; iter++) + { + LLMessageVariable& ci = *(iter->second); + mCurrentSDataBlock->addVariable(ci.getName(), ci.getType()); + } + return; + } +} + +// TODO: Remove this horror... +BOOL LLTemplateMessageBuilder::removeLastBlock() +{ + if (mCurrentSBlockName) + { + if ( (mCurrentSMessageData) + &&(mCurrentSMessageTemplate)) + { + if (mCurrentSMessageData->mMemberBlocks[mCurrentSBlockName]->mBlockNumber >= 1) + { + // At least one block for the current block name. + + // Store the current block name for future reference. + char *block_name = mCurrentSBlockName; + + // Decrement the sent total by the size of the + // data in the message block that we're currently building. + + LLMessageBlock* template_data = mCurrentSMessageTemplate->mMemberBlocks[mCurrentSBlockName]; + + for (LLMessageBlock::message_variable_map_t::iterator iter = template_data->mMemberVariables.begin(); + iter != template_data->mMemberVariables.end(); iter++) + { + LLMessageVariable& ci = *(iter->second); + mCurrentSendTotal -= ci.getSize(); + } + + + // Now we want to find the block that we're blowing away. + + // Get the number of blocks. + LLMsgBlkData* block_data = mCurrentSMessageData->mMemberBlocks[block_name]; + S32 num_blocks = block_data->mBlockNumber; + + // Use the same (suspect?) algorithm that's used to generate + // the names in the nextBlock method to find it. + char *block_getting_whacked = block_name + num_blocks - 1; + LLMsgBlkData* whacked_data = mCurrentSMessageData->mMemberBlocks[block_getting_whacked]; + delete whacked_data; + mCurrentSMessageData->mMemberBlocks.erase(block_getting_whacked); + + if (num_blocks <= 1) + { + // we just blew away the last one, so return FALSE + llwarns << "not blowing away the only block of message " + << mCurrentSMessageName + << ". Block: " << block_name + << ". Number: " << num_blocks + << llendl; + return FALSE; + } + else + { + // Decrement the counter. + block_data->mBlockNumber--; + return TRUE; + } + } + } + } + return FALSE; +} + +// add data to variable in current block +void LLTemplateMessageBuilder::addData(const char *varname, const void *data, EMsgVariableType type, S32 size) +{ + char *vnamep = (char *)varname; + + // do we have a current message? + if (!mCurrentSMessageTemplate) + { + llerrs << "newMessage not called prior to addData" << llendl; + return; + } + + // do we have a current block? + if (!mCurrentSDataBlock) + { + llerrs << "setBlock not called prior to addData" << llendl; + return; + } + + // kewl, add the data if it exists + LLMessageVariable* var_data = mCurrentSMessageTemplate->mMemberBlocks[mCurrentSBlockName]->mMemberVariables[vnamep]; + if (!var_data || !var_data->getName()) + { + llerrs << vnamep << " not a variable in block " << mCurrentSBlockName << " of " << mCurrentSMessageTemplate->mName << llendl; + return; + } + + // ok, it seems ok. . . are we the correct size? + if (var_data->getType() == MVT_VARIABLE) + { + // Variable 1 can only store 255 bytes, make sure our data is smaller + if ((var_data->getSize() == 1) && + (size > 255)) + { + llwarns << "Field " << varname << " is a Variable 1 but program " + << "attempted to stuff more than 255 bytes in " + << "(" << size << "). Clamping size and truncating data." << llendl; + size = 255; + char *truncate = (char *)data; + truncate[255] = 0; + } + + // no correct size for MVT_VARIABLE, instead we need to tell how many bytes the size will be encoded as + mCurrentSDataBlock->addData(vnamep, data, size, type, var_data->getSize()); + mCurrentSendTotal += size; + } + else + { + if (size != var_data->getSize()) + { + llerrs << varname << " is type MVT_FIXED but request size " << size << " doesn't match template size " + << var_data->getSize() << llendl; + return; + } + // alright, smash it in + mCurrentSDataBlock->addData(vnamep, data, size, type); + mCurrentSendTotal += size; + } +} + +// add data to variable in current block - fails if variable isn't MVT_FIXED +void LLTemplateMessageBuilder::addData(const char *varname, const void *data, EMsgVariableType type) +{ + char *vnamep = (char *)varname; + + // do we have a current message? + if (!mCurrentSMessageTemplate) + { + llerrs << "newMessage not called prior to addData" << llendl; + return; + } + + // do we have a current block? + if (!mCurrentSDataBlock) + { + llerrs << "setBlock not called prior to addData" << llendl; + return; + } + + // kewl, add the data if it exists + LLMessageVariable* var_data = mCurrentSMessageTemplate->mMemberBlocks[mCurrentSBlockName]->mMemberVariables[vnamep]; + if (!var_data->getName()) + { + llerrs << vnamep << " not a variable in block " << mCurrentSBlockName << " of " << mCurrentSMessageTemplate->mName << llendl; + return; + } + + // ok, it seems ok. . . are we MVT_VARIABLE? + if (var_data->getType() == MVT_VARIABLE) + { + // nope + llerrs << vnamep << " is type MVT_VARIABLE. Call using addData(name, data, size)" << llendl; + return; + } + else + { + mCurrentSDataBlock->addData(vnamep, data, var_data->getSize(), type); + mCurrentSendTotal += var_data->getSize(); + } +} + +void LLTemplateMessageBuilder::addBinaryData(const char *varname, + const void *data, S32 size) +{ + addData(varname, data, MVT_FIXED, size); +} + +void LLTemplateMessageBuilder::addS8(const char *varname, S8 s) +{ + addData(varname, &s, MVT_S8, sizeof(s)); +} + +void LLTemplateMessageBuilder::addU8(const char *varname, U8 u) +{ + addData(varname, &u, MVT_U8, sizeof(u)); +} + +void LLTemplateMessageBuilder::addS16(const char *varname, S16 i) +{ + addData(varname, &i, MVT_S16, sizeof(i)); +} + +void LLTemplateMessageBuilder::addU16(const char *varname, U16 i) +{ + addData(varname, &i, MVT_U16, sizeof(i)); +} + +void LLTemplateMessageBuilder::addF32(const char *varname, F32 f) +{ + addData(varname, &f, MVT_F32, sizeof(f)); +} + +void LLTemplateMessageBuilder::addS32(const char *varname, S32 s) +{ + addData(varname, &s, MVT_S32, sizeof(s)); +} + +void LLTemplateMessageBuilder::addU32(const char *varname, U32 u) +{ + addData(varname, &u, MVT_U32, sizeof(u)); +} + +void LLTemplateMessageBuilder::addU64(const char *varname, U64 lu) +{ + addData(varname, &lu, MVT_U64, sizeof(lu)); +} + +void LLTemplateMessageBuilder::addF64(const char *varname, F64 d) +{ + addData(varname, &d, MVT_F64, sizeof(d)); +} + +void LLTemplateMessageBuilder::addIPAddr(const char *varname, U32 u) +{ + addData(varname, &u, MVT_IP_ADDR, sizeof(u)); +} + +void LLTemplateMessageBuilder::addIPPort(const char *varname, U16 u) +{ + u = htons(u); + addData(varname, &u, MVT_IP_PORT, sizeof(u)); +} + +void LLTemplateMessageBuilder::addBOOL(const char* varname, BOOL b) +{ + // Can't just cast a BOOL (actually a U32) to a U8. + // In some cases the low order bits will be zero. + U8 temp = (b != 0); + addData(varname, &temp, MVT_BOOL, sizeof(temp)); +} + +void LLTemplateMessageBuilder::addString(const char* varname, const char* s) +{ + if (s) + addData( varname, (void *)s, MVT_VARIABLE, (S32)strlen(s) + 1); /* Flawfinder: ignore */ + else + addData( varname, NULL, MVT_VARIABLE, 0); +} + +void LLTemplateMessageBuilder::addString(const char* varname, const std::string& s) +{ + if (s.size()) + addData( varname, (void *)s.c_str(), MVT_VARIABLE, (S32)(s.size()) + 1); + else + addData( varname, NULL, MVT_VARIABLE, 0); +} + +void LLTemplateMessageBuilder::addVector3(const char *varname, const LLVector3& vec) +{ + addData(varname, vec.mV, MVT_LLVector3, sizeof(vec.mV)); +} + +void LLTemplateMessageBuilder::addVector4(const char *varname, const LLVector4& vec) +{ + addData(varname, vec.mV, MVT_LLVector4, sizeof(vec.mV)); +} + +void LLTemplateMessageBuilder::addVector3d(const char *varname, const LLVector3d& vec) +{ + addData(varname, vec.mdV, MVT_LLVector3d, sizeof(vec.mdV)); +} + +void LLTemplateMessageBuilder::addQuat(const char *varname, const LLQuaternion& quat) +{ + addData(varname, quat.packToVector3().mV, MVT_LLQuaternion, sizeof(LLVector3)); +} + +void LLTemplateMessageBuilder::addUUID(const char *varname, const LLUUID& uuid) +{ + addData(varname, uuid.mData, MVT_LLUUID, sizeof(uuid.mData)); +} + +static S32 zero_code(U8 **data, U32 *data_size) +{ + // Encoded send buffer needs to be slightly larger since the zero + // coding can potentially increase the size of the send data. + static U8 encodedSendBuffer[2 * MAX_BUFFER_SIZE]; + + S32 count = *data_size; + + S32 net_gain = 0; + U8 num_zeroes = 0; + + U8 *inptr = (U8 *)*data; + U8 *outptr = (U8 *)encodedSendBuffer; + +// skip the packet id field + + for (U32 i=0;i<LL_PACKET_ID_SIZE;i++) + { + count--; + *outptr++ = *inptr++; + } + +// build encoded packet, keeping track of net size gain + +// sequential zero bytes are encoded as 0 [U8 count] +// with 0 0 [count] representing wrap (>256 zeroes) + + while (count--) + { + if (!(*inptr)) // in a zero count + { + if (num_zeroes) + { + if (++num_zeroes > 254) + { + *outptr++ = num_zeroes; + num_zeroes = 0; + } + net_gain--; // subseqent zeroes save one + } + else + { + *outptr++ = 0; + net_gain++; // starting a zero count adds one + num_zeroes = 1; + } + inptr++; + } + else + { + if (num_zeroes) + { + *outptr++ = num_zeroes; + num_zeroes = 0; + } + *outptr++ = *inptr++; + } + } + + if (num_zeroes) + { + *outptr++ = num_zeroes; + } + + if (net_gain < 0) + { + // TODO: babbage: reinstate stat collecting... + //mCompressedPacketsOut++; + //mUncompressedBytesOut += *data_size; + + *data = encodedSendBuffer; + *data_size += net_gain; + encodedSendBuffer[0] |= LL_ZERO_CODE_FLAG; // set the head bit to indicate zero coding + + //mCompressedBytesOut += *data_size; + + } + //mTotalBytesOut += *data_size; + + return(net_gain); +} + +void LLTemplateMessageBuilder::compressMessage(U8*& buf_ptr, U32& buffer_length) +{ + if(ME_ZEROCODED == mCurrentSMessageTemplate->getEncoding()) + { + zero_code(&buf_ptr, &buffer_length); + } +} + +BOOL LLTemplateMessageBuilder::isMessageFull(const char* blockname) const +{ + if(mCurrentSendTotal > MTUBYTES) + { + return TRUE; + } + if(!blockname) + { + return FALSE; + } + char* bnamep = (char*)blockname; + S32 max; + + LLMessageBlock* template_data = mCurrentSMessageTemplate->mMemberBlocks[bnamep]; + + switch(template_data->mType) + { + case MBT_SINGLE: + max = 1; + break; + case MBT_MULTIPLE: + max = template_data->mNumber; + break; + case MBT_VARIABLE: + default: + max = MAX_BLOCKS; + break; + } + if(mCurrentSMessageData->mMemberBlocks[bnamep]->mBlockNumber >= max) + { + return TRUE; + } + return FALSE; +} + + +// make sure that all the desired data is in place and then copy the data into MAX_BUFFER_SIZEd buffer +U32 LLTemplateMessageBuilder::buildMessage(U8* buffer, U32 buffer_size) +{ + // basic algorithm is to loop through the various pieces, building + // size and offset info if we encounter a -1 for mSize at any + // point that variable wasn't given data + + // do we have a current message? + if (!mCurrentSMessageTemplate) + { + llerrs << "newMessage not called prior to buildMessage" << llendl; + return 0; + } + + // zero out some useful values + + // leave room for circuit counter + U32 result = LL_PACKET_ID_SIZE; + + // encode message number and adjust total_offset + if (mCurrentSMessageTemplate->mFrequency == MFT_HIGH) + { +// old, endian-dependant way +// memcpy(&buffer[result], &mCurrentMessageTemplate->mMessageNumber, sizeof(U8)); + +// new, independant way + buffer[result] = (U8)mCurrentSMessageTemplate->mMessageNumber; + result += sizeof(U8); + } + else if (mCurrentSMessageTemplate->mFrequency == MFT_MEDIUM) + { + U8 temp = 255; + memcpy(&buffer[result], &temp, sizeof(U8)); /*Flawfinder: ignore*/ + result += sizeof(U8); + + // mask off unsightly bits + temp = mCurrentSMessageTemplate->mMessageNumber & 255; + memcpy(&buffer[result], &temp, sizeof(U8)); /*Flawfinder: ignore*/ + result += sizeof(U8); + } + else if (mCurrentSMessageTemplate->mFrequency == MFT_LOW) + { + U8 temp = 255; + U16 message_num; + memcpy(&buffer[result], &temp, sizeof(U8)); /*Flawfinder: ignore*/ + result += sizeof(U8); + memcpy(&buffer[result], &temp, sizeof(U8)); /*Flawfinder: ignore*/ + result += sizeof(U8); + + // mask off unsightly bits + message_num = mCurrentSMessageTemplate->mMessageNumber & 0xFFFF; + + // convert to network byte order + message_num = htons(message_num); + memcpy(&buffer[result], &message_num, sizeof(U16)); /*Flawfinder: ignore*/ + result += sizeof(U16); + } + else + { + llerrs << "unexpected message frequency in buildMessage" << llendl; + return 0; + } + + // counting variables used to encode multiple block info + S32 block_count = 0; + U8 temp_block_number; + + // loop through msg blocks to loop through variables, + // totalling up size data and copying into buffer + for (LLMsgData::msg_blk_data_map_t::iterator + iter = mCurrentSMessageData->mMemberBlocks.begin(), + end = mCurrentSMessageData->mMemberBlocks.end(); + iter != end; iter++) + { + LLMsgBlkData* mbci = iter->second; + // do we need to encode a block code? + if (block_count == 0) + { + block_count = mbci->mBlockNumber; + + LLMessageBlock* template_data = + mCurrentSMessageTemplate->mMemberBlocks[mbci->mName]; + + // 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 + if (template_data->mType == MBT_VARIABLE) + { + // remember that mBlockNumber is a S32 + 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 << "buildMessage 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; + } + } + } + + // counting down multiple blocks + block_count--; + + // now loop through the variables + for (LLMsgBlkData::msg_var_data_map_t::iterator iter = mbci->mMemberVarData.begin(); + iter != mbci->mMemberVarData.end(); iter++) + { + 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 " + << mCurrentSMessageData->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 << "LLMessageSystem::buildMessage failed. " + << "Attempted to pack " + << result + mvci.getSize() + << " bytes into a buffer with size " + << buffer_size << "." << llendl + } + } + } + } + } + mbSBuilt = TRUE; + + return result; +} + +void LLTemplateMessageBuilder::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; + addData(mvci.getName(), mvci.getData(), mvci.getType(), mvci.getSize()); + } + } +} + +//virtual +void LLTemplateMessageBuilder::copyFromLLSD(const LLSD&) +{ + // TODO +} + +//virtual +void LLTemplateMessageBuilder::setBuilt(BOOL b) { mbSBuilt = b; } + +//virtual +BOOL LLTemplateMessageBuilder::isBuilt() const {return mbSBuilt;} + +//virtual +BOOL LLTemplateMessageBuilder::isClear() const {return mbSClear;} + +//virtual +S32 LLTemplateMessageBuilder::getMessageSize() {return mCurrentSendTotal;} + +//virtual +const char* LLTemplateMessageBuilder::getMessageName() const +{ + return mCurrentSMessageName; +} diff --git a/indra/llmessage/lltemplatemessagebuilder.h b/indra/llmessage/lltemplatemessagebuilder.h new file mode 100644 index 0000000000..ae533288fb --- /dev/null +++ b/indra/llmessage/lltemplatemessagebuilder.h @@ -0,0 +1,88 @@ +#ifndef LL_LLTEMPLATEMESSAGEBUILDER_H +#define LL_LLTEMPLATEMESSAGEBUILDER_H + +#include <map> + +#include "llmessagebuilder.h" +#include "llmsgvariabletype.h" + +class LLMsgData; +class LLMessageTemplate; +class LLMsgBlkData; +class LLMessageTemplate; + +class LLTemplateMessageBuilder : public LLMessageBuilder +{ +public: + + typedef std::map<const char *, LLMessageTemplate*> message_template_name_map_t; + + LLTemplateMessageBuilder(message_template_name_map_t&); + virtual ~LLTemplateMessageBuilder(); + + virtual void newMessage(const char *name); + + virtual void nextBlock(const char* blockname); + virtual BOOL removeLastBlock(); // TODO: babbage: remove this horror... + + /** All add* methods expect pointers to canonical varname strings. */ + virtual void addBinaryData(const char *varname, const void *data, + S32 size); + virtual void addBOOL(const char* varname, BOOL b); + virtual void addS8(const char *varname, S8 s); + virtual void addU8(const char *varname, U8 u); + virtual void addS16(const char *varname, S16 i); + virtual void addU16(const char *varname, U16 i); + virtual void addF32(const char *varname, F32 f); + virtual void addS32(const char *varname, S32 s); + virtual void addU32(const char *varname, U32 u); + virtual void addU64(const char *varname, U64 lu); + virtual void addF64(const char *varname, F64 d); + virtual void addVector3(const char *varname, const LLVector3& vec); + virtual void addVector4(const char *varname, const LLVector4& vec); + virtual void addVector3d(const char *varname, const LLVector3d& vec); + virtual void addQuat(const char *varname, const LLQuaternion& quat); + virtual void addUUID(const char *varname, const LLUUID& uuid); + virtual void addIPAddr(const char *varname, const U32 ip); + virtual void addIPPort(const char *varname, const U16 port); + virtual void addString(const char* varname, const char* s); + virtual void addString(const char* varname, const std::string& s); + + virtual BOOL isMessageFull(const char* blockname) const; + virtual void compressMessage(U8*& buf_ptr, U32& buffer_length); + + virtual BOOL isBuilt() const; + virtual BOOL isClear() const; + virtual U32 buildMessage(U8* buffer, U32 buffer_size); + /**< Return built message size */ + + virtual void clearMessage(); + + // TODO: babbage: remove this horror. + virtual void setBuilt(BOOL b); + + virtual S32 getMessageSize(); + virtual const char* getMessageName() const; + + virtual void copyFromMessageData(const LLMsgData& data); + virtual void copyFromLLSD(const LLSD&); + +private: + void addData(const char *varname, const void *data, + EMsgVariableType type, S32 size); + + void addData(const char *varname, const void *data, + EMsgVariableType type); + + LLMsgData* mCurrentSMessageData; + LLMessageTemplate* mCurrentSMessageTemplate; + LLMsgBlkData* mCurrentSDataBlock; + char* mCurrentSMessageName; + char* mCurrentSBlockName; + BOOL mbSBuilt; + BOOL mbSClear; + S32 mCurrentSendTotal; + message_template_name_map_t& mMessageTemplates; +}; + +#endif // LL_LLTEMPLATEMESSAGEBUILDER_H diff --git a/indra/llmessage/lltemplatemessagereader.cpp b/indra/llmessage/lltemplatemessagereader.cpp new file mode 100644 index 0000000000..892efb8697 --- /dev/null +++ b/indra/llmessage/lltemplatemessagereader.cpp @@ -0,0 +1,750 @@ +#include "lltemplatemessagereader.h" + +#include "llfasttimer.h" +#include "llmessagebuilder.h" +#include "llmessagetemplate.h" +#include "llquaternion.h" +#include "message.h" +#include "u64.h" +#include "v3dmath.h" +#include "v3math.h" +#include "v4math.h" + +LLTemplateMessageReader::LLTemplateMessageReader(message_template_number_map_t& + number_template_map) : + mReceiveSize(0), + mCurrentRMessageTemplate(NULL), + mCurrentRMessageData(NULL), + mMessageNumbers(number_template_map) +{ +} + +//virtual +LLTemplateMessageReader::~LLTemplateMessageReader() +{ + delete mCurrentRMessageData; + mCurrentRMessageData = NULL; +} + +//virtual +void LLTemplateMessageReader::clearMessage() +{ + mReceiveSize = -1; + mCurrentRMessageTemplate = NULL; + delete mCurrentRMessageData; + mCurrentRMessageData = NULL; +} + +void LLTemplateMessageReader::getData(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum, S32 max_size) +{ + // is there a message ready to go? + if (mReceiveSize == -1) + { + llerrs << "No message waiting for decode 2!" << llendl; + return; + } + + if (!mCurrentRMessageData) + { + llerrs << "Invalid mCurrentMessageData in getData!" << llendl; + return; + } + + char *bnamep = (char *)blockname + blocknum; // this works because it's just a hash. The bnamep is never derefference + char *vnamep = (char *)varname; + + LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep); + + if (iter == mCurrentRMessageData->mMemberBlocks.end()) + { + llerrs << "Block " << blockname << " #" << blocknum + << " not in message " << mCurrentRMessageData->mName << llendl; + return; + } + + LLMsgBlkData *msg_block_data = iter->second; + LLMsgVarData& vardata = msg_block_data->mMemberVarData[vnamep]; + + if (!vardata.getName()) + { + llerrs << "Variable "<< vnamep << " not in message " + << mCurrentRMessageData->mName<< " block " << bnamep << llendl; + return; + } + + if (size && size != vardata.getSize()) + { + llerrs << "Msg " << mCurrentRMessageData->mName + << " variable " << vnamep + << " is size " << vardata.getSize() + << " but copying into buffer of size " << size + << llendl; + return; + } + + + const S32 vardata_size = vardata.getSize(); + if( max_size >= vardata_size ) + { + switch( vardata_size ) + { + case 1: + *((U8*)datap) = *((U8*)vardata.getData()); + break; + case 2: + *((U16*)datap) = *((U16*)vardata.getData()); + break; + case 4: + *((U32*)datap) = *((U32*)vardata.getData()); + break; + case 8: + ((U32*)datap)[0] = ((U32*)vardata.getData())[0]; + ((U32*)datap)[1] = ((U32*)vardata.getData())[1]; + break; + default: + memcpy(datap, vardata.getData(), vardata_size); + break; + } + } + else + { + llwarns << "Msg " << mCurrentRMessageData->mName + << " variable " << vnamep + << " is size " << vardata.getSize() + << " but truncated to max size of " << max_size + << llendl; + + memcpy(datap, vardata.getData(), max_size); + } +} + +S32 LLTemplateMessageReader::getNumberOfBlocks(const char *blockname) +{ + // is there a message ready to go? + if (mReceiveSize == -1) + { + llerrs << "No message waiting for decode 3!" << llendl; + return -1; + } + + if (!mCurrentRMessageData) + { + llerrs << "Invalid mCurrentRMessageData in getData!" << llendl; + return -1; + } + + char *bnamep = (char *)blockname; + + LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep); + + if (iter == mCurrentRMessageData->mMemberBlocks.end()) + { +// sprintf(errmsg, "Block %s not in message %s", bnamep, mCurrentRMessageData->mName); +// llerrs << errmsg << llendl; +// return -1; + return 0; + } + + return (iter->second)->mBlockNumber; +} + +S32 LLTemplateMessageReader::getSize(const char *blockname, const char *varname) +{ + // is there a message ready to go? + if (mReceiveSize == -1) + { + llerrs << "No message waiting for decode 4!" << llendl; + return -1; + } + + if (!mCurrentRMessageData) + { + llerrs << "Invalid mCurrentRMessageData in getData!" << llendl; + return -1; + } + + char *bnamep = (char *)blockname; + + LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep); + + if (iter == mCurrentRMessageData->mMemberBlocks.end()) + { + llerrs << "Block " << bnamep << " not in message " + << mCurrentRMessageData->mName << llendl; + return -1; + } + + char *vnamep = (char *)varname; + + LLMsgBlkData* msg_data = iter->second; + LLMsgVarData& vardata = msg_data->mMemberVarData[vnamep]; + + if (!vardata.getName()) + { + llerrs << "Variable " << varname << " not in message " + << mCurrentRMessageData->mName << " block " << bnamep << llendl; + return -1; + } + + if (mCurrentRMessageTemplate->mMemberBlocks[bnamep]->mType != MBT_SINGLE) + { + llerrs << "Block " << bnamep << " isn't type MBT_SINGLE," + " use getSize with blocknum argument!" << llendl; + return -1; + } + + return vardata.getSize(); +} + +S32 LLTemplateMessageReader::getSize(const char *blockname, S32 blocknum, const char *varname) +{ + // is there a message ready to go? + if (mReceiveSize == -1) + { + llerrs << "No message waiting for decode 5!" << llendl; + return -1; + } + + if (!mCurrentRMessageData) + { + llerrs << "Invalid mCurrentRMessageData in getData!" << llendl; + return -1; + } + + char *bnamep = (char *)blockname + blocknum; + char *vnamep = (char *)varname; + + LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep); + + if (iter == mCurrentRMessageData->mMemberBlocks.end()) + { + llerrs << "Block " << bnamep << " not in message " + << mCurrentRMessageData->mName << llendl; + return -1; + } + + LLMsgBlkData* msg_data = iter->second; + LLMsgVarData& vardata = msg_data->mMemberVarData[vnamep]; + + if (!vardata.getName()) + { + llerrs << "Variable " << vnamep << " not in message " + << mCurrentRMessageData->mName << " block " << bnamep << llendl; + return -1; + } + + return vardata.getSize(); +} + +void LLTemplateMessageReader::getBinaryData(const char *blockname, + const char *varname, void *datap, + S32 size, S32 blocknum, + S32 max_size) +{ + getData(blockname, varname, datap, size, blocknum, max_size); +} + +void LLTemplateMessageReader::getS8(const char *block, const char *var, + S8 &u, S32 blocknum) +{ + getData(block, var, &u, sizeof(S8), blocknum); +} + +void LLTemplateMessageReader::getU8(const char *block, const char *var, + U8 &u, S32 blocknum) +{ + getData(block, var, &u, sizeof(U8), blocknum); +} + +void LLTemplateMessageReader::getBOOL(const char *block, const char *var, + BOOL &b, S32 blocknum ) +{ + U8 value; + getData(block, var, &value, sizeof(U8), blocknum); + b = (BOOL) value; +} + +void LLTemplateMessageReader::getS16(const char *block, const char *var, + S16 &d, S32 blocknum) +{ + getData(block, var, &d, sizeof(S16), blocknum); +} + +void LLTemplateMessageReader::getU16(const char *block, const char *var, + U16 &d, S32 blocknum) +{ + getData(block, var, &d, sizeof(U16), blocknum); +} + +void LLTemplateMessageReader::getS32(const char *block, const char *var, + S32 &d, S32 blocknum) +{ + getData(block, var, &d, sizeof(S32), blocknum); +} + +void LLTemplateMessageReader::getU32(const char *block, const char *var, + U32 &d, S32 blocknum) +{ + getData(block, var, &d, sizeof(U32), blocknum); +} + +void LLTemplateMessageReader::getU64(const char *block, const char *var, + U64 &d, S32 blocknum) +{ + getData(block, var, &d, sizeof(U64), blocknum); +} + +void LLTemplateMessageReader::getF32(const char *block, const char *var, + F32 &d, S32 blocknum) +{ + getData(block, var, &d, sizeof(F32), blocknum); + + if( !llfinite( d ) ) + { + llwarns << "non-finite in getF32Fast " << block << " " << var + << llendl; + d = 0; + } +} + +void LLTemplateMessageReader::getF64(const char *block, const char *var, + F64 &d, S32 blocknum) +{ + getData(block, var, &d, sizeof(F64), blocknum); + + if( !llfinite( d ) ) + { + llwarns << "non-finite in getF64Fast " << block << " " << var + << llendl; + d = 0; + } +} + +void LLTemplateMessageReader::getVector3(const char *block, const char *var, + LLVector3 &v, S32 blocknum ) +{ + getData(block, var, v.mV, sizeof(v.mV), blocknum); + + if( !v.isFinite() ) + { + llwarns << "non-finite in getVector3Fast " << block << " " + << var << llendl; + v.zeroVec(); + } +} + +void LLTemplateMessageReader::getVector4(const char *block, const char *var, + LLVector4 &v, S32 blocknum) +{ + getData(block, var, v.mV, sizeof(v.mV), blocknum); + + if( !v.isFinite() ) + { + llwarns << "non-finite in getVector4Fast " << block << " " + << var << llendl; + v.zeroVec(); + } +} + +void LLTemplateMessageReader::getVector3d(const char *block, const char *var, + LLVector3d &v, S32 blocknum ) +{ + getData(block, var, v.mdV, sizeof(v.mdV), blocknum); + + if( !v.isFinite() ) + { + llwarns << "non-finite in getVector3dFast " << block << " " + << var << llendl; + v.zeroVec(); + } + +} + +void LLTemplateMessageReader::getQuat(const char *block, const char *var, + LLQuaternion &q, S32 blocknum) +{ + LLVector3 vec; + getData(block, var, vec.mV, sizeof(vec.mV), blocknum); + if( vec.isFinite() ) + { + q.unpackFromVector3( vec ); + } + else + { + llwarns << "non-finite in getQuatFast " << block << " " << var + << llendl; + q.loadIdentity(); + } +} + +void LLTemplateMessageReader::getUUID(const char *block, const char *var, + LLUUID &u, S32 blocknum) +{ + getData(block, var, u.mData, sizeof(u.mData), blocknum); +} + +inline void LLTemplateMessageReader::getIPAddr(const char *block, const char *var, U32 &u, S32 blocknum) +{ + getData(block, var, &u, sizeof(U32), blocknum); +} + +inline void LLTemplateMessageReader::getIPPort(const char *block, const char *var, U16 &u, S32 blocknum) +{ + getData(block, var, &u, sizeof(U16), blocknum); + u = ntohs(u); +} + +inline void LLTemplateMessageReader::getString(const char *block, const char *var, S32 buffer_size, char *s, S32 blocknum ) +{ + s[0] = '\0'; + getData(block, var, s, 0, blocknum, buffer_size); + s[buffer_size - 1] = '\0'; +} + +//virtual +S32 LLTemplateMessageReader::getMessageSize() const +{ + return mReceiveSize; +} + +// Returns template for the message contained in buffer +BOOL LLTemplateMessageReader::decodeTemplate( + const U8* buffer, S32 buffer_size, // inputs + LLMessageTemplate** msg_template ) // outputs +{ + const U8* header = buffer + LL_PACKET_ID_SIZE; + + // is there a message ready to go? + if (buffer_size <= 0) + { + llwarns << "No message waiting for decode!" << llendl; + return(FALSE); + } + + U32 num = 0; + + if (header[0] != 255) + { + // high frequency message + num = header[0]; + } + else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 1)) && (header[1] != 255)) + { + // medium frequency message + num = (255 << 8) | header[1]; + } + else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 3)) && (header[1] == 255)) + { + // low frequency message + U16 message_id_U16 = 0; + // I think this check busts the message system. + // it appears that if there is a NULL in the message #, it won't copy it.... + // what was the goal? + //if(header[2]) + memcpy(&message_id_U16, &header[2], 2); + + // dependant on endian-ness: + // U32 temp = (255 << 24) | (255 << 16) | header[2]; + + // independant of endian-ness: + message_id_U16 = ntohs(message_id_U16); + num = 0xFFFF0000 | message_id_U16; + } + else // bogus packet received (too short) + { + llwarns << "Packet with unusable length received (too short): " + << buffer_size << llendl; + return(FALSE); + } + + LLMessageTemplate* temp = get_ptr_in_map(mMessageNumbers,num); + if (temp) + { + *msg_template = temp; + } + else + { + llwarns << "Message #" << std::hex << num << std::dec + << " received but not registered!" << llendl; + gMessageSystem->callExceptionFunc(MX_UNREGISTERED_MESSAGE); + return(FALSE); + } + + return(TRUE); +} + +void LLTemplateMessageReader::logRanOffEndOfPacket( const LLHost& host ) +{ + // we've run off the end of the packet! + llwarns << "Ran off end of packet " << mCurrentRMessageTemplate->mName +// << " with id " << mCurrentRecvPacketID + << " from " << host + << llendl; + if(gMessageSystem->mVerboseLog) + { + llinfos << "MSG: -> " << host << "\tREAD PAST END:\t" +// << mCurrentRecvPacketID << " " + << getMessageName() << llendl; + } + gMessageSystem->callExceptionFunc(MX_RAN_OFF_END_OF_PACKET); +} + +// 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 + + S32 decode_pos = LL_PACKET_ID_SIZE + (S32)(mCurrentRMessageTemplate->mFrequency); + + // create base working data set + mCurrentRMessageData = new LLMsgData(mCurrentRMessageTemplate->mName); + + // loop through the template building the data structure as we go + for (LLMessageTemplate::message_block_map_t::iterator iter = mCurrentRMessageTemplate->mMemberBlocks.begin(); + iter != mCurrentRMessageTemplate->mMemberBlocks.end(); iter++) + { + LLMessageBlock* mbci = iter->second; + 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) + { + logRanOffEndOfPacket( sender ); + return FALSE; + } + 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::iterator iter = mbci->mMemberVariables.begin(); + iter != mbci->mMemberVariables.end(); iter++) + { + LLMessageVariable& mvci = *(iter->second); + // 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 ); + return FALSE; + } + 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(&tsizeb, &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; + + if ((decode_pos + (S32)tsize) > mReceiveSize) + { + logRanOffEndOfPacket( sender ); + return FALSE; + } + 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 ); + return FALSE; + } + + 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(); + } + + // if( mCurrentRMessageTemplate->mName == _PREHASH_AgentToNewRegion ) + // { + // VTResume(); // VTune + // } + + { + LLFastTimer t(LLFastTimer::FTM_PROCESS_MESSAGES); + if( !mCurrentRMessageTemplate->callHandlerFunc(gMessageSystem) ) + { + llwarns << "Message from " << sender << " with no handler function received: " << mCurrentRMessageTemplate->mName << llendl; + } + } + + // if( mCurrentRMessageTemplate->mName == _PREHASH_AgentToNewRegion ) + // { + // VTPause(); // VTune + // } + + 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; +} + +BOOL LLTemplateMessageReader::validateMessage(const U8* buffer, + S32 buffer_size, + const LLHost& sender) +{ + mReceiveSize = buffer_size; + BOOL result = decodeTemplate(buffer, buffer_size, &mCurrentRMessageTemplate ); + if(result) + { + mCurrentRMessageTemplate->mReceiveCount++; + lldebugst(LLERR_MESSAGE) << "MessageRecvd:" + << mCurrentRMessageTemplate->mName + << " from " << sender << llendl; + } + return result; +} + +BOOL LLTemplateMessageReader::readMessage(const U8* buffer, + const LLHost& sender) +{ + return decodeData(buffer, sender); +} + +//virtual +const char* LLTemplateMessageReader::getMessageName() const +{ + static char empty_string[] = ""; + return mCurrentRMessageTemplate ? mCurrentRMessageTemplate->mName : empty_string; +} + +//virtual +bool LLTemplateMessageReader::isTrusted() const +{ + return mCurrentRMessageTemplate->getTrust() == MT_TRUST; +} + +//virtual +bool LLTemplateMessageReader::isBanned(bool trustedSource) const +{ + return mCurrentRMessageTemplate->isBanned(trustedSource); +} + +//virtual +void LLTemplateMessageReader::copyToBuilder(LLMessageBuilder& builder) const +{ + if(NULL == mCurrentRMessageTemplate) + { + return; + } + builder.copyFromMessageData(*mCurrentRMessageData); +} diff --git a/indra/llmessage/lltemplatemessagereader.h b/indra/llmessage/lltemplatemessagereader.h new file mode 100644 index 0000000000..dd5ee393fe --- /dev/null +++ b/indra/llmessage/lltemplatemessagereader.h @@ -0,0 +1,98 @@ +#ifndef LL_LLTEMPLATEMESSAGEREADER_H +#define LL_LLTEMPLATEMESSAGEREADER_H + +#include "llmessagereader.h" + +#include <map> + +class LLMessageTemplate; +class LLMsgData; + +class LLTemplateMessageReader : public LLMessageReader +{ +public: + + typedef std::map<U32, LLMessageTemplate*> message_template_number_map_t; + + LLTemplateMessageReader(message_template_number_map_t&); + virtual ~LLTemplateMessageReader(); + + /** All get* methods expect pointers to canonical strings. */ + virtual void getBinaryData(const char *blockname, const char *varname, + void *datap, S32 size, S32 blocknum = 0, + S32 max_size = S32_MAX); + virtual void getBOOL(const char *block, const char *var, BOOL &data, + S32 blocknum = 0); + virtual void getS8(const char *block, const char *var, S8 &data, + S32 blocknum = 0); + virtual void getU8(const char *block, const char *var, U8 &data, + S32 blocknum = 0); + virtual void getS16(const char *block, const char *var, S16 &data, + S32 blocknum = 0); + virtual void getU16(const char *block, const char *var, U16 &data, + S32 blocknum = 0); + virtual void getS32(const char *block, const char *var, S32 &data, + S32 blocknum = 0); + virtual void getF32(const char *block, const char *var, F32 &data, + S32 blocknum = 0); + virtual void getU32(const char *block, const char *var, U32 &data, + S32 blocknum = 0); + virtual void getU64(const char *block, const char *var, U64 &data, + S32 blocknum = 0); + virtual void getF64(const char *block, const char *var, F64 &data, + S32 blocknum = 0); + virtual void getVector3(const char *block, const char *var, + LLVector3 &vec, S32 blocknum = 0); + virtual void getVector4(const char *block, const char *var, + LLVector4 &vec, S32 blocknum = 0); + virtual void getVector3d(const char *block, const char *var, + LLVector3d &vec, S32 blocknum = 0); + virtual void getQuat(const char *block, const char *var, LLQuaternion &q, + S32 blocknum = 0); + virtual void getUUID(const char *block, const char *var, LLUUID &uuid, + S32 blocknum = 0); + virtual void getIPAddr(const char *block, const char *var, U32 &ip, + S32 blocknum = 0); + virtual void getIPPort(const char *block, const char *var, U16 &port, + S32 blocknum = 0); + virtual void getString(const char *block, const char *var, + S32 buffer_size, char *buffer, S32 blocknum = 0); + + virtual S32 getNumberOfBlocks(const char *blockname); + virtual S32 getSize(const char *blockname, const char *varname); + virtual S32 getSize(const char *blockname, S32 blocknum, + const char *varname); + + virtual void clearMessage(); + + virtual const char* getMessageName() const; + virtual S32 getMessageSize() const; + + virtual void copyToBuilder(LLMessageBuilder&) const; + + BOOL validateMessage(const U8* buffer, S32 buffer_size, + const LLHost& sender); + BOOL readMessage(const U8* buffer, const LLHost& sender); + + bool isTrusted() const; + bool isBanned(bool trusted_source) const; + +private: + + void getData(const char *blockname, const char *varname, void *datap, + S32 size = 0, S32 blocknum = 0, S32 max_size = S32_MAX); + + BOOL decodeTemplate(const U8* buffer, S32 buffer_size, // inputs + LLMessageTemplate** msg_template ); // outputs + + void logRanOffEndOfPacket( const LLHost& host ); + + BOOL decodeData(const U8* buffer, const LLHost& sender ); + + S32 mReceiveSize; + LLMessageTemplate* mCurrentRMessageTemplate; + LLMsgData* mCurrentRMessageData; + message_template_number_map_t& mMessageNumbers; +}; + +#endif // LL_LLTEMPLATEMESSAGEREADER_H diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index 6fb319326b..78d12cbda9 100644 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -36,9 +36,20 @@ #include "lldarray.h" #include "lldir.h" #include "llerror.h" +#include "llerrorlegacy.h" #include "llfasttimer.h" +#include "llhttpclient.h" +#include "llhttpsender.h" #include "llmd5.h" +#include "llmessagebuilder.h" +#include "llmessageconfig.h" +#include "llpumpio.h" +#include "lltemplatemessagebuilder.h" +#include "lltemplatemessagereader.h" +#include "llmessagetemplate.h" #include "llsd.h" +#include "llsdmessagebuilder.h" +#include "llsdmessagereader.h" #include "lltransfermanager.h" #include "lluuid.h" #include "llxfermanager.h" @@ -55,405 +66,6 @@ static const F32 CIRCUIT_DUMP_TIMEOUT = 30.f; static const S32 TRUST_TIME_WINDOW = 3; -class LLMsgVarData -{ -public: - LLMsgVarData() : mName(NULL), mSize(-1), mDataSize(-1), mData(NULL), mType(MVT_U8) - { - } - - LLMsgVarData(const char *name, EMsgVariableType type) : mSize(-1), mDataSize(-1), mData(NULL), mType(type) - { - mName = (char *)name; - } - - ~LLMsgVarData() - { - // copy constructor just copies the mData pointer, so only delete mData explicitly - } - - void deleteData() - { - delete[] mData; - mData = NULL; - } - - void addData(const void *indata, S32 size, EMsgVariableType type, S32 data_size = -1); - - char *getName() const { return mName; } - S32 getSize() const { return mSize; } - void *getData() { return (void*)mData; } - S32 getDataSize() const { return mDataSize; } - EMsgVariableType getType() const { return mType; } - -protected: - char *mName; - S32 mSize; - S32 mDataSize; - - U8 *mData; - EMsgVariableType mType; -}; - - -class LLMsgBlkData -{ -public: - LLMsgBlkData(const char *name, S32 blocknum) : mOffset(-1), mBlockNumber(blocknum), mTotalSize(-1) - { - mName = (char *)name; - } - - ~LLMsgBlkData() - { - for (msg_var_data_map_t::iterator iter = mMemberVarData.begin(); - iter != mMemberVarData.end(); iter++) - { - iter->deleteData(); - } - } - - void addVariable(const char *name, EMsgVariableType type) - { - LLMsgVarData tmp(name,type); - mMemberVarData[name] = tmp; - } - - void addData(char *name, const void *data, S32 size, EMsgVariableType type, S32 data_size = -1) - { - LLMsgVarData* temp = &mMemberVarData[name]; // creates a new entry if one doesn't exist - temp->addData(data, size, type, data_size); - } - - S32 mOffset; - S32 mBlockNumber; - typedef LLDynamicArrayIndexed<LLMsgVarData, const char *, 8> msg_var_data_map_t; - msg_var_data_map_t mMemberVarData; - char *mName; - S32 mTotalSize; -}; - - -class LLMsgData -{ -public: - LLMsgData(const char *name) : mTotalSize(-1) - { - mName = (char *)name; - } - ~LLMsgData() - { - for_each(mMemberBlocks.begin(), mMemberBlocks.end(), DeletePairedPointer()); - } - - void addBlock(LLMsgBlkData *blockp) - { - mMemberBlocks[blockp->mName] = blockp; - } - - void addDataFast(char *blockname, char *varname, const void *data, S32 size, EMsgVariableType type, S32 data_size = -1); - -public: - S32 mOffset; - typedef std::map<char*, LLMsgBlkData*> msg_blk_data_map_t; - msg_blk_data_map_t mMemberBlocks; - char *mName; - S32 mTotalSize; -}; - -inline 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 addData for " << mName - << " message: " << gMessageSystem->getCurrentSMessageName() - << " block: " << gMessageSystem->getCurrentSBlockName() - << llendl; - } - } - if(size) - { - delete mData; // Delete it if it already exists - mData = new U8[size]; - htonmemcpy(mData, data, mType, size); - } -} - - - -inline void LLMsgData::addDataFast(char *blockname, char *varname, const void *data, S32 size, EMsgVariableType type, S32 data_size) -{ - // remember that if the blocknumber is > 0 then the number is appended to the name - char *namep = (char *)blockname; - LLMsgBlkData* block_data = mMemberBlocks[namep]; - if (block_data->mBlockNumber) - { - namep += block_data->mBlockNumber; - block_data->addData(varname, data, size, type, data_size); - } - else - { - block_data->addData(varname, data, size, type, data_size); - } -} - -// LLMessage* classes store the template of messages - - -class LLMessageVariable -{ -public: - LLMessageVariable() : mName(NULL), mType(MVT_NULL), mSize(-1) - { - } - - LLMessageVariable(char *name) : mType(MVT_NULL), mSize(-1) - { - mName = name; - } - - LLMessageVariable(char *name, const EMsgVariableType type, const S32 size) : mType(type), mSize(size) - { - mName = gMessageStringTable.getString(name); - } - - ~LLMessageVariable() {} - - friend std::ostream& operator<<(std::ostream& s, LLMessageVariable &msg); - - EMsgVariableType getType() const { return mType; } - S32 getSize() const { return mSize; } - char *getName() const { return mName; } -protected: - char *mName; - EMsgVariableType mType; - S32 mSize; -}; - - -typedef enum e_message_block_type -{ - MBT_NULL, - MBT_SINGLE, - MBT_MULTIPLE, - MBT_VARIABLE, - MBT_EOF -} EMsgBlockType; - -class LLMessageBlock -{ -public: - LLMessageBlock(char *name, EMsgBlockType type, S32 number = 1) : mType(type), mNumber(number), mTotalSize(0) - { - mName = gMessageStringTable.getString(name); - } - - ~LLMessageBlock() - { - for_each(mMemberVariables.begin(), mMemberVariables.end(), DeletePairedPointer()); - } - - void addVariable(char *name, const EMsgVariableType type, const S32 size) - { - LLMessageVariable** varp = &mMemberVariables[name]; - if (*varp != NULL) - { - llerrs << name << " has already been used as a variable name!" << llendl; - } - *varp = new LLMessageVariable(name, type, size); - if (((*varp)->getType() != MVT_VARIABLE) - &&(mTotalSize != -1)) - { - mTotalSize += (*varp)->getSize(); - } - else - { - mTotalSize = -1; - } - } - - EMsgVariableType getVariableType(char *name) - { - return (mMemberVariables[name])->getType(); - } - - S32 getVariableSize(char *name) - { - return (mMemberVariables[name])->getSize(); - } - - friend std::ostream& operator<<(std::ostream& s, LLMessageBlock &msg); - - typedef std::map<const char *, LLMessageVariable*> message_variable_map_t; - message_variable_map_t mMemberVariables; - char *mName; - EMsgBlockType mType; - S32 mNumber; - S32 mTotalSize; -}; - - -enum EMsgFrequency -{ - MFT_NULL = 0, // value is size of message number in bytes - MFT_HIGH = 1, - MFT_MEDIUM = 2, - MFT_LOW = 4 -}; - -typedef enum e_message_trust -{ - MT_TRUST, - MT_NOTRUST -} EMsgTrust; - -enum EMsgEncoding -{ - ME_UNENCODED, - ME_ZEROCODED -}; - -class LLMessageTemplate -{ -public: - LLMessageTemplate(const char *name, U32 message_number, EMsgFrequency freq) - : - //mMemberBlocks(), - mName(NULL), - mFrequency(freq), - mTrust(MT_NOTRUST), - mEncoding(ME_ZEROCODED), - mMessageNumber(message_number), - mTotalSize(0), - mReceiveCount(0), - mReceiveBytes(0), - mReceiveInvalid(0), - mDecodeTimeThisFrame(0.f), - mTotalDecoded(0), - mTotalDecodeTime(0.f), - mMaxDecodeTimePerMsg(0.f), - mBanFromTrusted(false), - mBanFromUntrusted(false), - mHandlerFunc(NULL), - mUserData(NULL) - { - mName = gMessageStringTable.getString(name); - } - - ~LLMessageTemplate() - { - for_each(mMemberBlocks.begin(), mMemberBlocks.end(), DeletePairedPointer()); - } - - void addBlock(LLMessageBlock *blockp) - { - LLMessageBlock** member_blockp = &mMemberBlocks[blockp->mName]; - if (*member_blockp != NULL) - { - llerrs << "Block " << blockp->mName - << "has already been used as a block name!" << llendl; - } - *member_blockp = blockp; - if ( (mTotalSize != -1) - &&(blockp->mTotalSize != -1) - &&( (blockp->mType == MBT_SINGLE) - ||(blockp->mType == MBT_MULTIPLE))) - { - mTotalSize += blockp->mNumber*blockp->mTotalSize; - } - else - { - mTotalSize = -1; - } - } - - LLMessageBlock *getBlock(char *name) - { - return mMemberBlocks[name]; - } - - // Trusted messages can only be recieved on trusted circuits. - void setTrust(EMsgTrust t) - { - mTrust = t; - } - - EMsgTrust getTrust(void) - { - return mTrust; - } - - // controls for how the message should be encoded - void setEncoding(EMsgEncoding e) - { - mEncoding = e; - } - EMsgEncoding getEncoding() - { - return mEncoding; - } - - void setHandlerFunc(void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data) - { - mHandlerFunc = handler_func; - mUserData = user_data; - } - - BOOL callHandlerFunc(LLMessageSystem *msgsystem) - { - if (mHandlerFunc) - { - mHandlerFunc(msgsystem, mUserData); - return TRUE; - } - return FALSE; - } - - bool isBanned(bool trustedSource) - { - return trustedSource ? mBanFromTrusted : mBanFromUntrusted; - } - - friend std::ostream& operator<<(std::ostream& s, LLMessageTemplate &msg); - -public: - typedef std::map<char*, LLMessageBlock*> message_block_map_t; - message_block_map_t mMemberBlocks; - char *mName; - EMsgFrequency mFrequency; - EMsgTrust mTrust; - EMsgEncoding mEncoding; - U32 mMessageNumber; - S32 mTotalSize; - U32 mReceiveCount; // how many of this template have been received since last reset - U32 mReceiveBytes; // How many bytes received - U32 mReceiveInvalid; // How many "invalid" packets - F32 mDecodeTimeThisFrame; // Total seconds spent decoding this frame - U32 mTotalDecoded; // Total messages successfully decoded - F32 mTotalDecodeTime; // Total time successfully decoding messages - F32 mMaxDecodeTimePerMsg; - - bool mBanFromTrusted; - bool mBanFromUntrusted; - -private: - // message handler function (this is set by each application) - void (*mHandlerFunc)(LLMessageSystem *msgsystem, void **user_data); - void **mUserData; -}; - - -// static -BOOL LLMessageSystem::mTimeDecodes = FALSE; - -// static, 50ms per message decode -F32 LLMessageSystem::mTimeDecodesSpamThreshold = 0.05f; - // *NOTE: This needs to be moved into a seperate file so that it never gets // included in the viewer. 30 Sep 2002 mark // *NOTE: I don't think it's important that the messgage system tracks @@ -468,113 +80,6 @@ public: apr_pollfd_t mPollFD; }; - -// LLMessageVariable functions and friends - -std::ostream& operator<<(std::ostream& s, LLMessageVariable &msg) -{ - s << "\t\t" << msg.mName << " ("; - switch (msg.mType) - { - case MVT_FIXED: - s << "Fixed, " << msg.mSize << " bytes total)\n"; - break; - case MVT_VARIABLE: - s << "Variable, " << msg.mSize << " bytes of size info)\n"; - break; - default: - s << "Unknown\n"; - break; - } - return s; -} - -// LLMessageBlock functions and friends - -std::ostream& operator<<(std::ostream& s, LLMessageBlock &msg) -{ - s << "\t" << msg.mName << " ("; - switch (msg.mType) - { - case MBT_SINGLE: - s << "Fixed"; - break; - case MBT_MULTIPLE: - s << "Multiple - " << msg.mNumber << " copies"; - break; - case MBT_VARIABLE: - s << "Variable"; - break; - default: - s << "Unknown"; - break; - } - if (msg.mTotalSize != -1) - { - s << ", " << msg.mTotalSize << " bytes each, " << msg.mNumber*msg.mTotalSize << " bytes total)\n"; - } - else - { - s << ")\n"; - } - - - for (LLMessageBlock::message_variable_map_t::iterator iter = msg.mMemberVariables.begin(); - iter != msg.mMemberVariables.end(); iter++) - { - LLMessageVariable& ci = *(iter->second); - s << ci; - } - - return s; -} - -// LLMessageTemplate functions and friends - -std::ostream& operator<<(std::ostream& s, LLMessageTemplate &msg) -{ - switch (msg.mFrequency) - { - case MFT_HIGH: - s << "========================================\n" << "Message #" << msg.mMessageNumber << "\n" << msg.mName << " ("; - s << "High"; - break; - case MFT_MEDIUM: - s << "========================================\n" << "Message #"; - s << (msg.mMessageNumber & 0xFF) << "\n" << msg.mName << " ("; - s << "Medium"; - break; - case MFT_LOW: - s << "========================================\n" << "Message #"; - s << (msg.mMessageNumber & 0xFFFF) << "\n" << msg.mName << " ("; - s << "Low"; - break; - default: - s << "Unknown"; - break; - } - - if (msg.mTotalSize != -1) - { - s << ", " << msg.mTotalSize << " bytes total)\n"; - } - else - { - s << ")\n"; - } - - for (LLMessageTemplate::message_block_map_t::iterator iter = msg.mMemberBlocks.begin(); - iter != msg.mMemberBlocks.end(); iter++) - { - LLMessageBlock* ci = iter->second; - s << *ci; - } - - return s; -} - -// LLMessageList functions and friends - // Lets support a small subset of regular expressions here // Syntax is a string made up of: // a - checks against alphanumeric ([A-Za-z0-9]) @@ -776,6 +281,106 @@ BOOL b_positive_integer_ok(char *token) return TRUE; } +namespace +{ + class LLFnPtrResponder : public LLHTTPClient::Responder + { + public: + LLFnPtrResponder(void (*callback)(void **,S32), void **callbackData) : + mCallback(callback), + mCallbackData(callbackData) + { + } + + virtual void error(U32 status, const std::string& reason) + { + // TODO: Map status in to useful error code. + if(NULL != mCallback) mCallback(mCallbackData, LL_ERR_TCP_TIMEOUT); + } + + virtual void result(const LLSD& content) + { + if(NULL != mCallback) mCallback(mCallbackData, LL_ERR_NOERR); + } + + private: + + void (*mCallback)(void **,S32); + void **mCallbackData; + }; +} + + +class LLTrustedMessageService : public LLHTTPNode +{ + virtual bool validate(const std::string& name, LLSD& context) const + { return true; } + + virtual void post(LLHTTPNode::ResponsePtr response, + const LLSD& context, + const LLSD& input) const; +}; + +//virtual +void LLTrustedMessageService::post(LLHTTPNode::ResponsePtr response, + const LLSD& context, + const LLSD& input) const +{ + std::string name = context["request"]["wildcard"]["message-name"]; + std::string senderIP = context["request"]["remote-host"]; + std::string senderPort = context["request"]["headers"] + ["x-secondlife-udp-listen-port"]; + + LLSD message_data; + message_data["sender"] = senderIP + ":" + senderPort; + message_data["body"] = input; + + LLMessageSystem::dispatch(name, message_data, response); +} + +class LLMessageHandlerBridge : public LLHTTPNode +{ + virtual bool validate(const std::string& name, LLSD& context) const + { return true; } + + virtual void post(LLHTTPNode::ResponsePtr response, const LLSD& context, + const LLSD& input) const; +}; + +//virtual +void LLMessageHandlerBridge::post(LLHTTPNode::ResponsePtr response, + const LLSD& context, const LLSD& input) const +{ + std::string name = context["request"]["wildcard"]["message-name"]; + + lldebugs << "Setting mLastSender " << input["sender"].asString() << llendl; + gMessageSystem->mLastSender = LLHost(input["sender"].asString()); + gMessageSystem->mPacketsIn += 1; + gMessageSystem->mLLSDMessageReader->setMessage(name, input["body"]); + gMessageSystem->mMessageReader = gMessageSystem->mLLSDMessageReader; + + if(gMessageSystem->callHandler(name.c_str(), false, gMessageSystem)) + { + response->result(LLSD()); + } + else + { + response->notFound(); + } +} + +LLHTTPRegistration<LLMessageHandlerBridge> + gHTTPRegistrationMessageWildcard("/message/<message-name>"); + +LLHTTPRegistration<LLTrustedMessageService> + gHTTPRegistrationTrustedMessageWildcard("/trusted-message/<message-name>"); + +//virtual +LLUseCircuitCodeResponder::~LLUseCircuitCodeResponder() +{ + // even abstract base classes need a concrete destructor +} + void LLMessageSystem::init() { // initialize member variables @@ -783,25 +388,12 @@ void LLMessageSystem::init() mbError = FALSE; mErrorCode = 0; - mIncomingCompressedSize = 0; mSendReliable = FALSE; - mbSBuilt = FALSE; - mbSClear = TRUE; - mUnackedListDepth = 0; mUnackedListSize = 0; mDSMaxListDepth = 0; - mCurrentRMessageData = NULL; - mCurrentRMessageTemplate = NULL; - - mCurrentSMessageData = NULL; - mCurrentSMessageTemplate = NULL; - mCurrentSMessageName = NULL; - - mCurrentRecvPacketID = 0; - mNumberHighFreqMessages = 0; mNumberMediumFreqMessages = 0; mNumberLowFreqMessages = 0; @@ -825,57 +417,26 @@ void LLMessageSystem::init() mOurCircuitCode = 0; + mIncomingCompressedSize = 0; + mCurrentRecvPacketID = 0; + mMessageFileChecksum = 0; mMessageFileVersionNumber = 0.f; mTimingCallback = NULL; mTimingCallbackData = NULL; -} - -LLMessageSystem::LLMessageSystem() -{ - init(); - mSystemVersionMajor = 0; - mSystemVersionMinor = 0; - mSystemVersionPatch = 0; - mSystemVersionServer = 0; - mVersionFlags = 0x0; - - // default to not accepting packets from not alive circuits - mbProtected = TRUE; - - mSendPacketFailureCount = 0; - mCircuitPrintFreq = 0.f; // seconds - - // initialize various bits of net info - mSocket = 0; - mPort = 0; - - mPollInfop = NULL; - - mResendDumpTime = 0; - mMessageCountTime = 0; - mCircuitPrintTime = 0; - mCurrentMessageTimeSeconds = 0; - - // Constants for dumping output based on message processing time/count - mNumMessageCounts = 0; - mMaxMessageCounts = 0; // >= 0 means dump warnings - mMaxMessageTime = 0.f; - - mTrueReceiveSize = 0; - - // Error if checking this state, subclass methods which aren't implemented are delegated - // to properly constructed message system. - mbError = TRUE; + mMessageBuilder = NULL; + mMessageReader = NULL; } // Read file and build message templates LLMessageSystem::LLMessageSystem(const char *filename, U32 port, S32 version_major, S32 version_minor, - S32 version_patch) + S32 version_patch) : + mTemplateConfirmed(FALSE), + mTemplateMatches(FALSE) { init(); @@ -894,6 +455,14 @@ LLMessageSystem::LLMessageSystem(const char *filename, U32 port, loadTemplateFile(filename); + mTemplateMessageBuilder = new LLTemplateMessageBuilder(mMessageTemplates); + mLLSDMessageBuilder = new LLSDMessageBuilder(); + mMessageBuilder = NULL; + + mTemplateMessageReader = new LLTemplateMessageReader(mMessageNumbers); + mLLSDMessageReader = new LLSDMessageReader(); + mMessageReader = NULL; + // initialize various bits of net info mSocket = 0; mPort = port; @@ -1712,25 +1281,25 @@ LLMessageSystem::~LLMessageSystem() end_net(); } - delete mCurrentRMessageData; - mCurrentRMessageData = NULL; + delete mMessageReader; + mMessageReader = NULL; - delete mCurrentSMessageData; - mCurrentSMessageData = NULL; + delete mMessageBuilder; + mMessageBuilder = NULL; delete mPollInfop; mPollInfop = NULL; + + mIncomingCompressedSize = 0; + mCurrentRecvPacketID = 0; } void LLMessageSystem::clearReceiveState() { - mReceiveSize = -1; mCurrentRecvPacketID = 0; - mCurrentRMessageTemplate = NULL; - delete mCurrentRMessageData; - mCurrentRMessageData = NULL; mIncomingCompressedSize = 0; mLastSender.invalidate(); + mMessageReader->clearMessage(); } @@ -1757,20 +1326,23 @@ BOOL LLMessageSystem::poll(F32 seconds) // Returns TRUE if a valid, on-circuit message has been received. BOOL LLMessageSystem::checkMessages( S64 frame_count ) { + // Pump BOOL valid_packet = FALSE; + mMessageReader = mTemplateMessageReader; LLTransferTargetVFile::updateQueue(); if (!mNumMessageCounts) { - // This is the first message being handled after a resetReceiveCounts, we must be starting - // the message processing loop. Reset the timers. + // This is the first message being handled after a resetReceiveCounts, + // we must be starting the message processing loop. Reset the timers. mCurrentMessageTimeSeconds = totalTime() * SEC_PER_USEC; mMessageCountTime = getMessageTimeSeconds(); } // loop until either no packets or a valid packet // i.e., burn through packets from unregistered circuits + S32 receive_size = 0; do { clearReceiveState(); @@ -1786,16 +1358,16 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count ) // If you want to dump all received packets into SecondLife.log, uncomment this //dumpPacketToLog(); - mReceiveSize = mTrueReceiveSize; + receive_size = mTrueReceiveSize; mLastSender = mPacketRing.getLastSender(); - if (mReceiveSize < (S32) LL_MINIMUM_VALID_PACKET_SIZE) + if (receive_size < (S32) LL_MINIMUM_VALID_PACKET_SIZE) { // A receive size of zero is OK, that means that there are no more packets available. // Ones that are non-zero but below the minimum packet size are worrisome. - if (mReceiveSize > 0) + if (receive_size > 0) { - llwarns << "Invalid (too short) packet discarded " << mReceiveSize << llendl; + llwarns << "Invalid (too short) packet discarded " << receive_size << llendl; callExceptionFunc(MX_PACKET_TOO_SHORT); } // no data in packet receive buffer @@ -1809,18 +1381,18 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count ) // note if packet acks are appended. if(buffer[0] & LL_ACK_FLAG) { - acks += buffer[--mReceiveSize]; - true_rcv_size = mReceiveSize; - if(mReceiveSize >= ((S32)(acks * sizeof(TPACKETID) + LL_MINIMUM_VALID_PACKET_SIZE))) + acks += buffer[--receive_size]; + true_rcv_size = receive_size; + if(receive_size >= ((S32)(acks * sizeof(TPACKETID) + LL_MINIMUM_VALID_PACKET_SIZE))) { - mReceiveSize -= acks * sizeof(TPACKETID); + receive_size -= acks * sizeof(TPACKETID); } else { // mal-formed packet. ignore it and continue with // the next one llwarns << "Malformed packet received. Packet size " - << mReceiveSize << " with invalid no. of acks " << acks + << receive_size << " with invalid no. of acks " << acks << llendl; valid_packet = FALSE; continue; @@ -1829,7 +1401,7 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count ) // process the message as normal - mIncomingCompressedSize = zeroCodeExpand(&buffer,&mReceiveSize); + mIncomingCompressedSize = zeroCodeExpand(&buffer,&receive_size); mCurrentRecvPacketID = buffer[1] + ((buffer[0] & 0x0f ) * 256); if (sizeof(TPACKETID) == 4) { @@ -1953,7 +1525,7 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count ) std::ostringstream str; str << "MSG: <- " << host; char buffer[MAX_STRING]; /* Flawfinder: ignore*/ - snprintf(buffer, MAX_STRING, "\t%6d\t%6d\t%6d ", mReceiveSize, (mIncomingCompressedSize ? mIncomingCompressedSize : mReceiveSize), mCurrentRecvPacketID); /* Flawfinder: ignore */ + snprintf(buffer, MAX_STRING, "\t%6d\t%6d\t%6d ", receive_size, (mIncomingCompressedSize ? mIncomingCompressedSize : receive_size), mCurrentRecvPacketID); /* Flawfinder: ignore */ str << buffer << "(unknown)" << (recv_reliable ? " reliable" : "") << " resent " @@ -1971,23 +1543,22 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count ) // But we don't want to acknowledge UseCircuitCode until the circuit is // available, which is why the acknowledgement test is done above. JC - valid_packet = decodeTemplate( buffer, mReceiveSize, &mCurrentRMessageTemplate ); - if( valid_packet ) - { - mCurrentRMessageTemplate->mReceiveCount++; - lldebugst(LLERR_MESSAGE) << "MessageRecvd:" << mCurrentRMessageTemplate->mName << " from " << host << llendl; - } + valid_packet = mTemplateMessageReader->validateMessage(buffer, + receive_size, + host); // UseCircuitCode is allowed in even from an invalid circuit, so that // we can toss circuits around. - if (valid_packet && !cdp && (mCurrentRMessageTemplate->mName != _PREHASH_UseCircuitCode) ) + if(valid_packet && !cdp && + (mTemplateMessageReader->getMessageName() != _PREHASH_UseCircuitCode)) { logMsgFromInvalidCircuit( host, recv_reliable ); clearReceiveState(); valid_packet = FALSE; } - if (valid_packet && cdp && !cdp->getTrusted() && (mCurrentRMessageTemplate->getTrust() == MT_TRUST) ) + if(valid_packet && cdp && !cdp->getTrusted() && + mTemplateMessageReader->isTrusted()) { logTrustedMsgFromUntrustedCircuit( host ); clearReceiveState(); @@ -1997,11 +1568,11 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count ) } if (valid_packet - && mCurrentRMessageTemplate->isBanned(cdp && cdp->getTrusted())) + && mTemplateMessageReader->isBanned(cdp && cdp->getTrusted())) { llwarns << "LLMessageSystem::checkMessages " << "received banned message " - << mCurrentRMessageTemplate->mName + << mTemplateMessageReader->getMessageName() << " from " << ((cdp && cdp->getTrusted()) ? "trusted " : "untrusted ") << host << llendl; @@ -2013,7 +1584,7 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count ) { logValidMsg(cdp, host, recv_reliable, recv_resent, (BOOL)(acks>0) ); - valid_packet = decodeData( buffer, host ); + valid_packet = mTemplateMessageReader->readMessage(buffer, host); } // It's possible that the circuit went away, because ANY message can disable the circuit @@ -2026,7 +1597,7 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count ) if( 1 ) { static char* object_update = gMessageStringTable.getString("ObjectUpdate"); - if(object_update == mCurrentRMessageTemplate->mName ) + if(object_update == mTemplateMessageReader->getMessageName() ) { llinfos << "ObjectUpdate:" << llendl; U32 i; @@ -2037,8 +1608,8 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count ) } llinfos << "" << llendl; - llinfos << " Zero Unencoded: " << mReceiveSize << llendl; - for( i = 0; i<mReceiveSize; i++ ) + llinfos << " Zero Unencoded: " << receive_size << llendl; + for( i = 0; i<receive_size; i++ ) { llinfos << " " << i << ": " << (U32) buffer[i] << llendl; } @@ -2127,7 +1698,7 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count ) if (mbProtected && (!cdp)) { llwarns << "Packet " - << (mCurrentRMessageTemplate ? mCurrentRMessageTemplate->mName : "") + << mTemplateMessageReader->getMessageName() << " from invalid circuit " << host << llendl; mOffCircuitPackets++; } @@ -2140,7 +1711,7 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count ) // Code for dumping the complete contents of a message // delete [] zero_unexpanded_buffer; } - } while (!valid_packet && mReceiveSize > 0); + } while (!valid_packet && receive_size > 0); F64 mt_sec = getMessageTimeSeconds(); // Check to see if we need to print debug info @@ -2241,600 +1812,56 @@ void LLMessageSystem::processAcks() } } - -void LLMessageSystem::newMessageFast(const char *name) -{ - mbSBuilt = FALSE; - mbSClear = FALSE; - - mCurrentSendTotal = 0; - mSendReliable = FALSE; - - char *namep = (char *)name; - - if (mMessageTemplates.count(namep) > 0) - { - mCurrentSMessageTemplate = mMessageTemplates[namep]; - if (mCurrentSMessageData) - { - delete mCurrentSMessageData; - } - mCurrentSMessageData = new LLMsgData(namep); - mCurrentSMessageName = namep; - mCurrentSDataBlock = NULL; - mCurrentSBlockName = NULL; - - // add at one of each block - LLMessageTemplate* msg_template = mMessageTemplates[namep]; - for (LLMessageTemplate::message_block_map_t::iterator iter = msg_template->mMemberBlocks.begin(); - iter != msg_template->mMemberBlocks.end(); iter++) - { - LLMessageBlock* ci = iter->second; - LLMsgBlkData *tblockp; - tblockp = new LLMsgBlkData(ci->mName, 0); - mCurrentSMessageData->addBlock(tblockp); - } - } - else - { - llerrs << "newMessage - Message " << name << " not registered" << llendl; - } -} - void LLMessageSystem::copyMessageRtoS() { - if (!mCurrentRMessageTemplate) + // NOTE: babbage: switch builder to match reader to avoid + // converting message format + if(mMessageReader == mTemplateMessageReader) { - return; + mMessageBuilder = mTemplateMessageBuilder; } - newMessageFast(mCurrentRMessageTemplate->mName); - - // 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::iterator iter = mCurrentRMessageData->mMemberBlocks.begin(); - LLMsgData::msg_blk_data_map_t::iterator end = mCurrentRMessageData->mMemberBlocks.end(); - for(; iter != end; ++iter) + else { - 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--; - - nextBlockFast(block_name); - - // now loop through the variables - LLMsgBlkData::msg_var_data_map_t::iterator dit = mbci->mMemberVarData.begin(); - LLMsgBlkData::msg_var_data_map_t::iterator dend = mbci->mMemberVarData.end(); - - for(; dit != dend; ++dit) - { - LLMsgVarData& mvci = *dit; - addDataFast(mvci.getName(), mvci.getData(), mvci.getType(), mvci.getSize()); - } + mMessageBuilder = mLLSDMessageBuilder; } + mSendReliable = FALSE; + mMessageBuilder->newMessage(mMessageReader->getMessageName()); + mMessageReader->copyToBuilder(*mMessageBuilder); } void LLMessageSystem::clearMessage() { - mbSBuilt = FALSE; - mbSClear = TRUE; - - mCurrentSendTotal = 0; mSendReliable = FALSE; - - mCurrentSMessageTemplate = NULL; - - delete mCurrentSMessageData; - mCurrentSMessageData = NULL; - - mCurrentSMessageName = NULL; - mCurrentSDataBlock = NULL; - mCurrentSBlockName = NULL; + mMessageBuilder->clearMessage(); } - // set block to add data to within current message void LLMessageSystem::nextBlockFast(const char *blockname) { - char *bnamep = (char *)blockname; - - if (!mCurrentSMessageTemplate) - { - llerrs << "newMessage not called prior to setBlock" << llendl; - return; - } - - // now, does this block exist? - LLMessageTemplate::message_block_map_t::iterator temp_iter = mCurrentSMessageTemplate->mMemberBlocks.find(bnamep); - if (temp_iter == mCurrentSMessageTemplate->mMemberBlocks.end()) - { - llerrs << "LLMessageSystem::nextBlockFast " << bnamep - << " not a block in " << mCurrentSMessageTemplate->mName << llendl; - return; - } - - LLMessageBlock* template_data = temp_iter->second; - - // ok, have we already set this block? - LLMsgBlkData* block_data = mCurrentSMessageData->mMemberBlocks[bnamep]; - if (block_data->mBlockNumber == 0) - { - // nope! set this as the current block - block_data->mBlockNumber = 1; - mCurrentSDataBlock = block_data; - mCurrentSBlockName = bnamep; - - // add placeholders for each of the variables - for (LLMessageBlock::message_variable_map_t::iterator iter = template_data->mMemberVariables.begin(); - iter != template_data->mMemberVariables.end(); iter++) - { - LLMessageVariable& ci = *(iter->second); - mCurrentSDataBlock->addVariable(ci.getName(), ci.getType()); - } - return; - } - else - { - // already have this block. . . - // are we supposed to have a new one? - - // if the block is type MBT_SINGLE this is bad! - if (template_data->mType == MBT_SINGLE) - { - llerrs << "LLMessageSystem::nextBlockFast called multiple times" - << " for " << bnamep << " but is type MBT_SINGLE" << llendl; - return; - } - - - // if the block is type MBT_MULTIPLE then we need a known number, make sure that we're not exceeding it - if ( (template_data->mType == MBT_MULTIPLE) - &&(mCurrentSDataBlock->mBlockNumber == template_data->mNumber)) - { - llerrs << "LLMessageSystem::nextBlockFast called " - << mCurrentSDataBlock->mBlockNumber << " times for " << bnamep - << " exceeding " << template_data->mNumber - << " specified in type MBT_MULTIPLE." << llendl; - return; - } - - // ok, we can make a new one - // modify the name to avoid name collision by adding number to end - S32 count = block_data->mBlockNumber; - - // incrememt base name's count - block_data->mBlockNumber++; - - if (block_data->mBlockNumber > MAX_BLOCKS) - { - llerrs << "Trying to pack too many blocks into MBT_VARIABLE type (limited to " << MAX_BLOCKS << ")" << llendl; - } - - // create new name - // Nota Bene: if things are working correctly, mCurrentMessageData->mMemberBlocks[blockname]->mBlockNumber == mCurrentDataBlock->mBlockNumber + 1 - - char *nbnamep = bnamep + count; - - mCurrentSDataBlock = new LLMsgBlkData(bnamep, count); - mCurrentSDataBlock->mName = nbnamep; - mCurrentSMessageData->mMemberBlocks[nbnamep] = mCurrentSDataBlock; - - // add placeholders for each of the variables - for (LLMessageBlock::message_variable_map_t::iterator - iter = template_data->mMemberVariables.begin(), - end = template_data->mMemberVariables.end(); - iter != end; iter++) - { - LLMessageVariable& ci = *(iter->second); - mCurrentSDataBlock->addVariable(ci.getName(), ci.getType()); - } - return; - } -} - -// add data to variable in current block -void LLMessageSystem::addDataFast(const char *varname, const void *data, EMsgVariableType type, S32 size) -{ - char *vnamep = (char *)varname; - - // do we have a current message? - if (!mCurrentSMessageTemplate) - { - llerrs << "newMessage not called prior to addData" << llendl; - return; - } - - // do we have a current block? - if (!mCurrentSDataBlock) - { - llerrs << "setBlock not called prior to addData" << llendl; - return; - } - - // kewl, add the data if it exists - LLMessageVariable* var_data = mCurrentSMessageTemplate->mMemberBlocks[mCurrentSBlockName]->mMemberVariables[vnamep]; - if (!var_data || !var_data->getName()) - { - llerrs << vnamep << " not a variable in block " << mCurrentSBlockName << " of " << mCurrentSMessageTemplate->mName << llendl; - return; - } - - // ok, it seems ok. . . are we the correct size? - if (var_data->getType() == MVT_VARIABLE) - { - // Variable 1 can only store 255 bytes, make sure our data is smaller - if ((var_data->getSize() == 1) && - (size > 255)) - { - llwarns << "Field " << varname << " is a Variable 1 but program " - << "attempted to stuff more than 255 bytes in " - << "(" << size << "). Clamping size and truncating data." << llendl; - size = 255; - char *truncate = (char *)data; - truncate[255] = 0; - } - - // no correct size for MVT_VARIABLE, instead we need to tell how many bytes the size will be encoded as - mCurrentSDataBlock->addData(vnamep, data, size, type, var_data->getSize()); - mCurrentSendTotal += size; - } - else - { - if (size != var_data->getSize()) - { - llerrs << varname << " is type MVT_FIXED but request size " << size << " doesn't match template size " - << var_data->getSize() << llendl; - return; - } - // alright, smash it in - mCurrentSDataBlock->addData(vnamep, data, size, type); - mCurrentSendTotal += size; - } -} - -// add data to variable in current block - fails if variable isn't MVT_FIXED -void LLMessageSystem::addDataFast(const char *varname, const void *data, EMsgVariableType type) -{ - char *vnamep = (char *)varname; - - // do we have a current message? - if (!mCurrentSMessageTemplate) - { - llerrs << "newMessage not called prior to addData" << llendl; - return; - } - - // do we have a current block? - if (!mCurrentSDataBlock) - { - llerrs << "setBlock not called prior to addData" << llendl; - return; - } - - // kewl, add the data if it exists - LLMessageVariable* var_data = mCurrentSMessageTemplate->mMemberBlocks[mCurrentSBlockName]->mMemberVariables[vnamep]; - if (!var_data->getName()) - { - llerrs << vnamep << " not a variable in block " << mCurrentSBlockName << " of " << mCurrentSMessageTemplate->mName << llendl; - return; - } - - // ok, it seems ok. . . are we MVT_VARIABLE? - if (var_data->getType() == MVT_VARIABLE) - { - // nope - llerrs << vnamep << " is type MVT_VARIABLE. Call using addData(name, data, size)" << llendl; - return; - } - else - { - mCurrentSDataBlock->addData(vnamep, data, var_data->getSize(), type); - mCurrentSendTotal += var_data->getSize(); - } + mMessageBuilder->nextBlock(blockname); } BOOL LLMessageSystem::isSendFull(const char* blockname) { - if(!blockname) + char* stringTableName = NULL; + if(NULL != blockname) { - return (mCurrentSendTotal > MTUBYTES); + stringTableName = gMessageStringTable.getString(blockname); } - return isSendFullFast(gMessageStringTable.getString(blockname)); + return isSendFullFast(stringTableName); } BOOL LLMessageSystem::isSendFullFast(const char* blockname) { - if(mCurrentSendTotal > MTUBYTES) - { - return TRUE; - } - if(!blockname) - { - return FALSE; - } - char* bnamep = (char*)blockname; - S32 max; - - LLMessageBlock* template_data = mCurrentSMessageTemplate->mMemberBlocks[bnamep]; - - switch(template_data->mType) - { - case MBT_SINGLE: - max = 1; - break; - case MBT_MULTIPLE: - max = template_data->mNumber; - break; - case MBT_VARIABLE: - default: - max = MAX_BLOCKS; - break; - } - if(mCurrentSMessageData->mMemberBlocks[bnamep]->mBlockNumber >= max) - { - return TRUE; - } - return FALSE; + return mMessageBuilder->isMessageFull(blockname); } // blow away the last block of a message, return FALSE if that leaves no blocks or there wasn't a block to remove -BOOL LLMessageSystem::removeLastBlock() -{ - if (mCurrentSBlockName) - { - if ( (mCurrentSMessageData) - &&(mCurrentSMessageTemplate)) - { - if (mCurrentSMessageData->mMemberBlocks[mCurrentSBlockName]->mBlockNumber >= 1) - { - // At least one block for the current block name. - - // Store the current block name for future reference. - char *block_name = mCurrentSBlockName; - - // Decrement the sent total by the size of the - // data in the message block that we're currently building. - - LLMessageBlock* template_data = mCurrentSMessageTemplate->mMemberBlocks[mCurrentSBlockName]; - - for (LLMessageBlock::message_variable_map_t::iterator iter = template_data->mMemberVariables.begin(); - iter != template_data->mMemberVariables.end(); iter++) - { - LLMessageVariable& ci = *(iter->second); - mCurrentSendTotal -= ci.getSize(); - } - - - // Now we want to find the block that we're blowing away. - - // Get the number of blocks. - LLMsgBlkData* block_data = mCurrentSMessageData->mMemberBlocks[block_name]; - S32 num_blocks = block_data->mBlockNumber; - - // Use the same (suspect?) algorithm that's used to generate - // the names in the nextBlock method to find it. - char *block_getting_whacked = block_name + num_blocks - 1; - LLMsgBlkData* whacked_data = mCurrentSMessageData->mMemberBlocks[block_getting_whacked]; - delete whacked_data; - mCurrentSMessageData->mMemberBlocks.erase(block_getting_whacked); - - if (num_blocks <= 1) - { - // we just blew away the last one, so return FALSE - return FALSE; - } - else - { - // Decrement the counter. - block_data->mBlockNumber--; - return TRUE; - } - } - } - } - return FALSE; -} - -// make sure that all the desired data is in place and then copy the data into mSendBuffer -void LLMessageSystem::buildMessage() +// TODO: Babbage: Remove this horror. +BOOL LLMessageSystem::removeLastBlock() { - // basic algorithm is to loop through the various pieces, building - // size and offset info if we encounter a -1 for mSize at any - // point that variable wasn't given data - - // do we have a current message? - if (!mCurrentSMessageTemplate) - { - llerrs << "newMessage not called prior to buildMessage" << llendl; - return; - } - - // zero out some useful values - - // leave room for circuit counter - mSendSize = LL_PACKET_ID_SIZE; - - // encode message number and adjust total_offset - if (mCurrentSMessageTemplate->mFrequency == MFT_HIGH) - { -// old, endian-dependant way -// memcpy(&mSendBuffer[mSendSize], &mCurrentMessageTemplate->mMessageNumber, sizeof(U8)); - -// new, independant way - mSendBuffer[mSendSize] = (U8)mCurrentSMessageTemplate->mMessageNumber; - mSendSize += sizeof(U8); - } - else if (mCurrentSMessageTemplate->mFrequency == MFT_MEDIUM) - { - U8 temp = 255; - memcpy(&mSendBuffer[mSendSize], &temp, sizeof(U8)); /*Flawfinder: ignore*/ - mSendSize += sizeof(U8); - - // mask off unsightly bits - temp = mCurrentSMessageTemplate->mMessageNumber & 255; - memcpy(&mSendBuffer[mSendSize], &temp, sizeof(U8)); /*Flawfinder: ignore*/ - mSendSize += sizeof(U8); - } - else if (mCurrentSMessageTemplate->mFrequency == MFT_LOW) - { - U8 temp = 255; - U16 message_num; - memcpy(&mSendBuffer[mSendSize], &temp, sizeof(U8)); /*Flawfinder: ignore*/ - mSendSize += sizeof(U8); - memcpy(&mSendBuffer[mSendSize], &temp, sizeof(U8)); /*Flawfinder: ignore*/ - mSendSize += sizeof(U8); - - // mask off unsightly bits - message_num = mCurrentSMessageTemplate->mMessageNumber & 0xFFFF; - - // convert to network byte order - message_num = htons(message_num); - memcpy(&mSendBuffer[mSendSize], &message_num, sizeof(U16)); /*Flawfinder: ignore*/ - mSendSize += sizeof(U16); - } - else - { - llerrs << "unexpected message frequency in buildMessage" << llendl; - return; - } - - // counting variables used to encode multiple block info - S32 block_count = 0; - U8 temp_block_number; - - // loop through msg blocks to loop through variables, totalling up size data and copying into mSendBuffer - for (LLMsgData::msg_blk_data_map_t::iterator - iter = mCurrentSMessageData->mMemberBlocks.begin(), - end = mCurrentSMessageData->mMemberBlocks.end(); - iter != end; iter++) - { - LLMsgBlkData* mbci = iter->second; - // do we need to encode a block code? - if (block_count == 0) - { - block_count = mbci->mBlockNumber; - - LLMessageBlock* template_data = mCurrentSMessageTemplate->mMemberBlocks[mbci->mName]; - - // 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 - if (template_data->mType == MBT_VARIABLE) - { - // remember that mBlockNumber is a S32 - temp_block_number = (U8)mbci->mBlockNumber; - if ((S32)(mSendSize + sizeof(U8)) < MAX_BUFFER_SIZE) - { - memcpy(&mSendBuffer[mSendSize], &temp_block_number, sizeof(U8)); /* Flawfinder: ignore */ - mSendSize += 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 << "buildMessage 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; - } - } - } - - // counting down multiple blocks - block_count--; - - // now loop through the variables - for (LLMsgBlkData::msg_var_data_map_t::iterator iter = mbci->mMemberVarData.begin(); - iter != mbci->mMemberVarData.end(); iter++) - { - 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 " - << mCurrentSMessageData->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(&mSendBuffer[mSendSize], &sizeb, MVT_U8, 1); - break; - case 2: - sizeh = size; - htonmemcpy(&mSendBuffer[mSendSize], &sizeh, MVT_U16, 2); - break; - case 4: - htonmemcpy(&mSendBuffer[mSendSize], &size, MVT_S32, 4); - break; - default: - llerrs << "Attempting to build variable field with unknown size of " << size << llendl; - break; - } - mSendSize += mvci.getDataSize(); - } - - // if there is any data to pack, pack it - if((mvci.getData() != NULL) && mvci.getSize()) - { - if(mSendSize + mvci.getSize() < (S32)sizeof(mSendBuffer)) - { - memcpy( /* Flawfinder: ignore */ - &mSendBuffer[mSendSize], - mvci.getData(), - mvci.getSize()); - mSendSize += 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 << "LLMessageSystem::buildMessage failed. " - << "Attempted to pack " - << mSendSize + mvci.getSize() - << " bytes into a buffer with size " - << mSendBuffer << "." << llendl - } - } - } - } - } - mbSBuilt = TRUE; + return mMessageBuilder->removeLastBlock(); } S32 LLMessageSystem::sendReliable(const LLHost &host) @@ -2858,7 +1885,9 @@ S32 LLMessageSystem::sendSemiReliable(const LLHost &host, void (*callback)(void timeout = LL_SEMIRELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX; } - return sendReliable(host, 0, FALSE, timeout, callback, callback_data); + const S32 retries = 0; + const BOOL ping_based_timeout = FALSE; + return sendReliable(host, retries, ping_based_timeout, timeout, callback, callback_data); } // send the message via a UDP packet @@ -2884,7 +1913,8 @@ S32 LLMessageSystem::sendReliable( const LLHost &host, mSendReliable = TRUE; mReliablePacketParams.set(host, retries, ping_based_timeout, timeout, - callback, callback_data, mCurrentSMessageName); + callback, callback_data, + const_cast<char*>(mMessageBuilder->getMessageName())); return sendMessage(host); } @@ -2922,11 +1952,13 @@ S32 LLMessageSystem::flushSemiReliable(const LLHost &host, void (*callback)(void } S32 send_bytes = 0; - if (mCurrentSendTotal) + if (mMessageBuilder->getMessageSize()) { mSendReliable = TRUE; // No need for ping-based retry as not going to retry - mReliablePacketParams.set(host, 0, FALSE, timeout, callback, callback_data, mCurrentSMessageName); + mReliablePacketParams.set(host, 0, FALSE, timeout, callback, + callback_data, + const_cast<char*>(mMessageBuilder->getMessageName())); send_bytes = sendMessage(host); clearMessage(); } @@ -2940,7 +1972,7 @@ S32 LLMessageSystem::flushSemiReliable(const LLHost &host, void (*callback)(void S32 LLMessageSystem::flushReliable(const LLHost &host) { S32 send_bytes = 0; - if (mCurrentSendTotal) + if (mMessageBuilder->getMessageSize()) { send_bytes = sendReliable(host); } @@ -2953,13 +1985,12 @@ S32 LLMessageSystem::flushReliable(const LLHost &host) // so should should not use llinfos. S32 LLMessageSystem::sendMessage(const LLHost &host) { - if (!mbSBuilt) + if (! mMessageBuilder->isBuilt()) { - buildMessage(); + mSendSize = mMessageBuilder->buildMessage(mSendBuffer, + MAX_BUFFER_SIZE); } - mCurrentSendTotal = 0; - if (!(host.isOk())) // if port and ip are zero, don't bother trying to send the message { return 0; @@ -2976,10 +2007,10 @@ S32 LLMessageSystem::sendMessage(const LLHost &host) if(mVerboseLog) { llinfos << "MSG: -> " << host << "\tUNKNOWN CIRCUIT:\t" - << mCurrentSMessageName << llendl; + << mMessageBuilder->getMessageName() << llendl; } llwarns << "sendMessage - Trying to send " - << mCurrentSMessageName << " on unknown circuit " + << mMessageBuilder->getMessageName() << " on unknown circuit " << host << llendl; return 0; } @@ -2998,15 +2029,41 @@ S32 LLMessageSystem::sendMessage(const LLHost &host) if(mVerboseLog) { llinfos << "MSG: -> " << host << "\tDEAD CIRCUIT\t\t" - << mCurrentSMessageName << llendl; + << mMessageBuilder->getMessageName() << llendl; } llwarns << "sendMessage - Trying to send message " - << mCurrentSMessageName << " to dead circuit " + << mMessageBuilder->getMessageName() << " to dead circuit " << host << llendl; return 0; } } + // NOTE: babbage: LLSD message -> HTTP, template message -> UDP + if(mMessageBuilder == mLLSDMessageBuilder) + { + LLSD message = mLLSDMessageBuilder->getMessage(); + + const LLHTTPSender& sender = LLHTTPSender::getSender(host); + LLHTTPClient::ResponderPtr responder = NULL; + if(mSendReliable) + { + responder = + new LLFnPtrResponder(mReliablePacketParams.mCallback, + mReliablePacketParams.mCallbackData); + } + else + { + llwarns << "LLMessageSystem::sendMessage: Sending unreliable " << mMessageBuilder->getMessageName() << " message via HTTP" << llendl; + responder = new LLFnPtrResponder(NULL, NULL); + } + sender.send(host, mLLSDMessageBuilder->getMessageName(), + message, responder); + + mSendReliable = FALSE; + mReliablePacketParams.clear(); + return 1; + } + memset(mSendBuffer,0,LL_PACKET_ID_SIZE); // zero out the packet ID field // add the send id to the front of the message @@ -3017,20 +2074,17 @@ S32 LLMessageSystem::sendMessage(const LLHost &host) // Compress the message, which will usually reduce its size. U8 * buf_ptr = (U8 *)mSendBuffer; - S32 buffer_length = mSendSize; - if(ME_ZEROCODED == mCurrentSMessageTemplate->getEncoding()) - { - zeroCode(&buf_ptr, &buffer_length); - } + U32 buffer_length = mSendSize; + mMessageBuilder->compressMessage(buf_ptr, buffer_length); if (buffer_length > 1500) { - if((mCurrentSMessageName != _PREHASH_ChildAgentUpdate) - && (mCurrentSMessageName != _PREHASH_SendXferPacket)) + if((mMessageBuilder->getMessageName() != _PREHASH_ChildAgentUpdate) + && (mMessageBuilder->getMessageName() != _PREHASH_SendXferPacket)) { llwarns << "sendMessage - Trying to send " << ((buffer_length > 4000) ? "EXTRA " : "") - << "BIG message " << mCurrentSMessageName << " - " + << "BIG message " << mMessageBuilder->getMessageName() << " - " << buffer_length << llendl; } } @@ -3055,7 +2109,7 @@ S32 LLMessageSystem::sendMessage(const LLHost &host) BOOL is_ack_appended = FALSE; std::vector<TPACKETID> acks; if((space_left > 0) && (ack_count > 0) && - (mCurrentSMessageName != _PREHASH_PacketAck)) + (mMessageBuilder->getMessageName() != _PREHASH_PacketAck)) { buf_ptr[0] |= LL_ACK_FLAG; S32 append_ack_count = llmin(space_left, ack_count); @@ -3126,7 +2180,7 @@ S32 LLMessageSystem::sendMessage(const LLHost &host) char buffer[MAX_STRING]; /* Flawfinder: ignore */ snprintf(buffer, MAX_STRING, "\t%6d\t%6d\t%6d ", mSendSize, buffer_length, cdp->getPacketOutID()); /* Flawfinder: ignore */ str << buffer - << mCurrentSMessageTemplate->mName + << mMessageBuilder->getMessageName() << (mSendReliable ? " reliable " : ""); if(is_ack_appended) { @@ -3137,89 +2191,19 @@ S32 LLMessageSystem::sendMessage(const LLHost &host) llinfos << str.str() << llendl; } - lldebugst(LLERR_MESSAGE) << "MessageSent at: " << (S32)totalTime() - << ", " << mCurrentSMessageTemplate->mName - << " to " << host - << llendl; - - // ok, clean up temp data - delete mCurrentSMessageData; - mCurrentSMessageData = NULL; + /*lldebugst(LLERR_MESSAGE) << "MessageSent at: " << (S32)totalTime() + << "," << mMessageBuilder->getMessageName() + << " to " << host + << llendl;*/ mPacketsOut++; mBytesOut += buffer_length; + mSendReliable = FALSE; + mReliablePacketParams.clear(); return buffer_length; } - -// Returns template for the message contained in buffer -BOOL LLMessageSystem::decodeTemplate( - const U8* buffer, S32 buffer_size, // inputs - LLMessageTemplate** msg_template ) // outputs -{ - const U8* header = buffer + LL_PACKET_ID_SIZE; - - // is there a message ready to go? - if (buffer_size <= 0) - { - llwarns << "No message waiting for decode!" << llendl; - return(FALSE); - } - - U32 num = 0; - - if (header[0] != 255) - { - // high frequency message - num = header[0]; - } - else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 1)) && (header[1] != 255)) - { - // medium frequency message - num = (255 << 8) | header[1]; - } - else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 3)) && (header[1] == 255)) - { - // low frequency message - U16 message_id_U16 = 0; - // I think this check busts the message system. - // it appears that if there is a NULL in the message #, it won't copy it.... - // what was the goal? - //if(header[2]) - memcpy(&message_id_U16, &header[2], 2); /* Flawfinder: ignore */ - - // dependant on endian-ness: - // U32 temp = (255 << 24) | (255 << 16) | header[2]; - - // independant of endian-ness: - message_id_U16 = ntohs(message_id_U16); - num = 0xFFFF0000 | message_id_U16; - } - else // bogus packet received (too short) - { - llwarns << "Packet with unusable length received (too short): " - << buffer_size << llendl; - return(FALSE); - } - - LLMessageTemplate* temp = get_ptr_in_map(mMessageNumbers,num); - if (temp) - { - *msg_template = temp; - } - else - { - llwarns << "Message #" << std::hex << num << std::dec - << " received but not registered!" << llendl; - callExceptionFunc(MX_UNREGISTERED_MESSAGE); - return(FALSE); - } - - return(TRUE); -} - - void LLMessageSystem::logMsgFromInvalidCircuit( const LLHost& host, BOOL recv_reliable ) { if(mVerboseLog) @@ -3227,9 +2211,9 @@ void LLMessageSystem::logMsgFromInvalidCircuit( const LLHost& host, BOOL recv_re std::ostringstream str; str << "MSG: <- " << host; char buffer[MAX_STRING]; /* Flawfinder: ignore */ - snprintf(buffer, MAX_STRING, "\t%6d\t%6d\t%6d ", mReceiveSize, (mIncomingCompressedSize ? mIncomingCompressedSize: mReceiveSize), mCurrentRecvPacketID); /* Flawfinder: ignore */ + snprintf(buffer, MAX_STRING, "\t%6d\t%6d\t%6d ", mMessageReader->getMessageSize(), (mIncomingCompressedSize ? mIncomingCompressedSize: mMessageReader->getMessageSize()), mCurrentRecvPacketID); /* Flawfinder: ignore */ str << buffer - << mCurrentRMessageTemplate->mName + << mMessageReader->getMessageName() << (recv_reliable ? " reliable" : "") << " REJECTED"; llinfos << str.str() << llendl; @@ -3244,8 +2228,9 @@ void LLMessageSystem::logMsgFromInvalidCircuit( const LLHost& host, BOOL recv_re } else { - mMessageCountList[mNumMessageCounts].mMessageNum = mCurrentRMessageTemplate->mMessageNumber; - mMessageCountList[mNumMessageCounts].mMessageBytes = mReceiveSize; + // TODO: babbage: work out if we need these + // mMessageCountList[mNumMessageCounts].mMessageNum = mCurrentRMessageTemplate->mMessageNumber; + mMessageCountList[mNumMessageCounts].mMessageBytes = mMessageReader->getMessageSize(); mMessageCountList[mNumMessageCounts].mInvalid = TRUE; mNumMessageCounts++; } @@ -3255,11 +2240,11 @@ void LLMessageSystem::logTrustedMsgFromUntrustedCircuit( const LLHost& host ) { // RequestTrustedCircuit is how we establish trust, so don't spam // if it's received on a trusted circuit. JC - if (strcmp(mCurrentRMessageTemplate->mName, "RequestTrustedCircuit")) + if (strcmp(mMessageReader->getMessageName(), "RequestTrustedCircuit")) { llwarns << "Received trusted message on untrusted circuit. " << "Will reply with deny. " - << "Message: " << mCurrentRMessageTemplate->mName + << "Message: " << mMessageReader->getMessageName() << " Host: " << host << llendl; } @@ -3271,10 +2256,11 @@ void LLMessageSystem::logTrustedMsgFromUntrustedCircuit( const LLHost& host ) } else { - mMessageCountList[mNumMessageCounts].mMessageNum - = mCurrentRMessageTemplate->mMessageNumber; + // TODO: babbage: work out if we need these + //mMessageCountList[mNumMessageCounts].mMessageNum + // = mCurrentRMessageTemplate->mMessageNumber; mMessageCountList[mNumMessageCounts].mMessageBytes - = mReceiveSize; + = mMessageReader->getMessageSize(); mMessageCountList[mNumMessageCounts].mInvalid = TRUE; mNumMessageCounts++; } @@ -3288,8 +2274,9 @@ void LLMessageSystem::logValidMsg(LLCircuitData *cdp, const LLHost& host, BOOL r } else { - mMessageCountList[mNumMessageCounts].mMessageNum = mCurrentRMessageTemplate->mMessageNumber; - mMessageCountList[mNumMessageCounts].mMessageBytes = mReceiveSize; + // TODO: babbage: work out if we need these + //mMessageCountList[mNumMessageCounts].mMessageNum = mCurrentRMessageTemplate->mMessageNumber; + mMessageCountList[mNumMessageCounts].mMessageBytes = mMessageReader->getMessageSize(); mMessageCountList[mNumMessageCounts].mInvalid = FALSE; mNumMessageCounts++; } @@ -3306,9 +2293,9 @@ void LLMessageSystem::logValidMsg(LLCircuitData *cdp, const LLHost& host, BOOL r std::ostringstream str; str << "MSG: <- " << host; char buffer[MAX_STRING]; /* Flawfinder: ignore */ - snprintf(buffer, MAX_STRING, "\t%6d\t%6d\t%6d ", mReceiveSize, (mIncomingCompressedSize ? mIncomingCompressedSize : mReceiveSize), mCurrentRecvPacketID); /* Flawfinder: ignore */ + snprintf(buffer, MAX_STRING, "\t%6d\t%6d\t%6d ", mMessageReader->getMessageSize(), (mIncomingCompressedSize ? mIncomingCompressedSize : mMessageReader->getMessageSize()), mCurrentRecvPacketID); /* Flawfinder: ignore */ str << buffer - << mCurrentRMessageTemplate->mName + << mMessageReader->getMessageName() << (recv_reliable ? " reliable" : "") << (recv_resent ? " resent" : "") << (recv_acks ? " acks" : ""); @@ -3316,446 +2303,19 @@ void LLMessageSystem::logValidMsg(LLCircuitData *cdp, const LLHost& host, BOOL r } } - -void LLMessageSystem::logRanOffEndOfPacket( const LLHost& host ) -{ - // we've run off the end of the packet! - llwarns << "Ran off end of packet " << mCurrentRMessageTemplate->mName - << " with id " << mCurrentRecvPacketID << " from " << host - << llendl; - if(mVerboseLog) - { - llinfos << "MSG: -> " << host << "\tREAD PAST END:\t" - << mCurrentRecvPacketID << " " - << mCurrentSMessageTemplate->mName << llendl; - } - callExceptionFunc(MX_RAN_OFF_END_OF_PACKET); -} - - -// decode a given message -BOOL LLMessageSystem::decodeData(const U8* buffer, const LLHost& sender ) -{ - llassert( mReceiveSize >= 0 ); - llassert( mCurrentRMessageTemplate); - llassert( !mCurrentRMessageData ); - delete mCurrentRMessageData; // just to make sure - - S32 decode_pos = LL_PACKET_ID_SIZE + (S32)(mCurrentRMessageTemplate->mFrequency); - - // create base working data set - mCurrentRMessageData = new LLMsgData(mCurrentRMessageTemplate->mName); - - // loop through the template building the data structure as we go - for (LLMessageTemplate::message_block_map_t::iterator iter = mCurrentRMessageTemplate->mMemberBlocks.begin(); - iter != mCurrentRMessageTemplate->mMemberBlocks.end(); iter++) - { - LLMessageBlock* mbci = iter->second; - 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) - { - logRanOffEndOfPacket( sender ); - return FALSE; - } - 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::iterator iter = mbci->mMemberVariables.begin(); - iter != mbci->mMemberVariables.end(); iter++) - { - LLMessageVariable& mvci = *(iter->second); - // 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 ); - return FALSE; - } - 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(&tsizeb, &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; - - if ((decode_pos + (S32)tsize) > mReceiveSize) - { - logRanOffEndOfPacket( sender ); - return FALSE; - } - 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 ); - return FALSE; - } - - 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( mTimeDecodes || mTimingCallback ) - { - decode_timer.reset(); - } - - // if( mCurrentRMessageTemplate->mName == _PREHASH_AgentToNewRegion ) - // { - // VTResume(); // VTune - // } - - { - LLFastTimer t(LLFastTimer::FTM_PROCESS_MESSAGES); - if( !mCurrentRMessageTemplate->callHandlerFunc(this) ) - { - llwarns << "Message from " << sender << " with no handler function received: " << mCurrentRMessageTemplate->mName << llendl; - } - } - - // if( mCurrentRMessageTemplate->mName == _PREHASH_AgentToNewRegion ) - // { - // VTPause(); // VTune - // } - - if( mTimeDecodes || mTimingCallback ) - { - F32 decode_time = decode_timer.getElapsedTimeF32(); - - if (mTimingCallback) - { - mTimingCallback(mCurrentRMessageTemplate->mName, - decode_time, - mTimingCallbackData); - } - - if (mTimeDecodes) - { - mCurrentRMessageTemplate->mDecodeTimeThisFrame += decode_time; - - mCurrentRMessageTemplate->mTotalDecoded++; - mCurrentRMessageTemplate->mTotalDecodeTime += decode_time; - - if( mCurrentRMessageTemplate->mMaxDecodeTimePerMsg < decode_time ) - { - mCurrentRMessageTemplate->mMaxDecodeTimePerMsg = decode_time; - } - - - if( decode_time > mTimeDecodesSpamThreshold ) - { - lldebugs << "--------- Message " << mCurrentRMessageTemplate->mName << " decode took " << decode_time << " seconds. (" << - mCurrentRMessageTemplate->mMaxDecodeTimePerMsg << " max, " << - (mCurrentRMessageTemplate->mTotalDecodeTime / mCurrentRMessageTemplate->mTotalDecoded) << " avg)" << llendl; - } - } - } - } - return TRUE; -} - -void LLMessageSystem::getDataFast(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum, S32 max_size) -{ - // is there a message ready to go? - if (mReceiveSize == -1) - { - llerrs << "No message waiting for decode 2!" << llendl; - return; - } - - if (!mCurrentRMessageData) - { - llerrs << "Invalid mCurrentMessageData in getData!" << llendl; - return; - } - - char *bnamep = (char *)blockname + blocknum; // this works because it's just a hash. The bnamep is never derefference - char *vnamep = (char *)varname; - - LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep); - - if (iter == mCurrentRMessageData->mMemberBlocks.end()) - { - llerrs << "Block " << blockname << " #" << blocknum - << " not in message " << mCurrentRMessageData->mName << llendl; - return; - } - - LLMsgBlkData *msg_block_data = iter->second; - LLMsgVarData& vardata = msg_block_data->mMemberVarData[vnamep]; - - if (!vardata.getName()) - { - llerrs << "Variable "<< vnamep << " not in message " - << mCurrentRMessageData->mName<< " block " << bnamep << llendl; - return; - } - - if (size && size != vardata.getSize()) - { - llerrs << "Msg " << mCurrentRMessageData->mName - << " variable " << vnamep - << " is size " << vardata.getSize() - << " but copying into buffer of size " << size - << llendl; - return; - } - - - const S32 vardata_size = vardata.getSize(); - if( max_size >= vardata_size ) - { - switch( vardata_size ) - { - case 1: - *((U8*)datap) = *((U8*)vardata.getData()); - break; - case 2: - *((U16*)datap) = *((U16*)vardata.getData()); - break; - case 4: - *((U32*)datap) = *((U32*)vardata.getData()); - break; - case 8: - ((U32*)datap)[0] = ((U32*)vardata.getData())[0]; - ((U32*)datap)[1] = ((U32*)vardata.getData())[1]; - break; - default: - memcpy(datap, vardata.getData(), vardata_size); /* Flawfinder: ignore */ - break; - } - } - else - { - llwarns << "Msg " << mCurrentRMessageData->mName - << " variable " << vnamep - << " is size " << vardata.getSize() - << " but truncated to max size of " << max_size - << llendl; - - memcpy(datap, vardata.getData(), max_size); /* Flawfinder: ignore */ - } -} - -S32 LLMessageSystem::getNumberOfBlocksFast(const char *blockname) -{ - // is there a message ready to go? - if (mReceiveSize == -1) - { - llerrs << "No message waiting for decode 3!" << llendl; - return -1; - } - - if (!mCurrentRMessageData) - { - llerrs << "Invalid mCurrentRMessageData in getData!" << llendl; - return -1; - } - - char *bnamep = (char *)blockname; - - LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep); - - if (iter == mCurrentRMessageData->mMemberBlocks.end()) - { -// sprintf(errmsg, "Block %s not in message %s", bnamep, mCurrentRMessageData->mName); -// llerrs << errmsg << llendl; -// return -1; - return 0; - } - - return (iter->second)->mBlockNumber; -} - -S32 LLMessageSystem::getSizeFast(const char *blockname, const char *varname) -{ - // is there a message ready to go? - if (mReceiveSize == -1) - { - llerrs << "No message waiting for decode 4!" << llendl; - return -1; - } - - if (!mCurrentRMessageData) - { - llerrs << "Invalid mCurrentRMessageData in getData!" << llendl; - return -1; - } - - char *bnamep = (char *)blockname; - - LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep); - - if (iter == mCurrentRMessageData->mMemberBlocks.end()) - { - llerrs << "Block " << bnamep << " not in message " - << mCurrentRMessageData->mName << llendl; - return -1; - } - - char *vnamep = (char *)varname; - - LLMsgBlkData* msg_data = iter->second; - LLMsgVarData& vardata = msg_data->mMemberVarData[vnamep]; - - if (!vardata.getName()) - { - llerrs << "Variable " << varname << " not in message " - << mCurrentRMessageData->mName << " block " << bnamep << llendl; - return -1; - } - - if (mCurrentRMessageTemplate->mMemberBlocks[bnamep]->mType != MBT_SINGLE) - { - llerrs << "Block " << bnamep << " isn't type MBT_SINGLE," - " use getSize with blocknum argument!" << llendl; - return -1; - } - - return vardata.getSize(); -} - - -S32 LLMessageSystem::getSizeFast(const char *blockname, S32 blocknum, const char *varname) -{ - // is there a message ready to go? - if (mReceiveSize == -1) - { - llerrs << "No message waiting for decode 5!" << llendl; - return -1; - } - - if (!mCurrentRMessageData) - { - llerrs << "Invalid mCurrentRMessageData in getData!" << llendl; - return -1; - } - - char *bnamep = (char *)blockname + blocknum; - char *vnamep = (char *)varname; - - LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep); - - if (iter == mCurrentRMessageData->mMemberBlocks.end()) - { - llerrs << "Block " << bnamep << " not in message " - << mCurrentRMessageData->mName << llendl; - return -1; - } - - LLMsgBlkData* msg_data = iter->second; - LLMsgVarData& vardata = msg_data->mMemberVarData[vnamep]; - - if (!vardata.getName()) - { - llerrs << "Variable " << vnamep << " not in message " - << mCurrentRMessageData->mName << " block " << bnamep << llendl; - return -1; - } - - return vardata.getSize(); -} - - void LLMessageSystem::sanityCheck() { - if (!mCurrentRMessageData) - { - llerrs << "mCurrentRMessageData is NULL" << llendl; - } +// TODO: babbage: reinstate - if (!mCurrentRMessageTemplate) - { - llerrs << "mCurrentRMessageTemplate is NULL" << llendl; - } +// if (!mCurrentRMessageData) +// { +// llerrs << "mCurrentRMessageData is NULL" << llendl; +// } + +// if (!mCurrentRMessageTemplate) +// { +// llerrs << "mCurrentRMessageTemplate is NULL" << llendl; +// } // if (!mCurrentRTemplateBlock) // { @@ -3767,25 +2327,25 @@ void LLMessageSystem::sanityCheck() // llerrs << "mCurrentRDataBlock is NULL" << llendl; // } - if (!mCurrentSMessageData) - { - llerrs << "mCurrentSMessageData is NULL" << llendl; - } +// if (!mCurrentSMessageData) +// { +// llerrs << "mCurrentSMessageData is NULL" << llendl; +// } - if (!mCurrentSMessageTemplate) - { - llerrs << "mCurrentSMessageTemplate is NULL" << llendl; - } +// if (!mCurrentSMessageTemplate) +// { +// llerrs << "mCurrentSMessageTemplate is NULL" << llendl; +// } // if (!mCurrentSTemplateBlock) // { // llerrs << "mCurrentSTemplateBlock is NULL" << llendl; // } - if (!mCurrentSDataBlock) - { - llerrs << "mCurrentSDataBlock is NULL" << llendl; - } +// if (!mCurrentSDataBlock) +// { +// llerrs << "mCurrentSDataBlock is NULL" << llendl; +// } } void LLMessageSystem::showCircuitInfo() @@ -4171,7 +2731,8 @@ bool LLMessageSystem::addCircuitCode(U32 code, const LLUUID& session_id) //} // static -void LLMessageSystem::processUseCircuitCode(LLMessageSystem* msg, void**) +void LLMessageSystem::processUseCircuitCode(LLMessageSystem* msg, + void** user) { U32 circuit_code_in; msg->getU32Fast(_PREHASH_CircuitCode, _PREHASH_Code, circuit_code_in); @@ -4291,6 +2852,13 @@ void LLMessageSystem::processUseCircuitCode(LLMessageSystem* msg, void**) llinfos << "Circuit code " << circuit_code_in << " from " << msg->getSender() << " for agent " << id << " in session " << session_id << llendl; + + const LLUseCircuitCodeResponder* responder = + (const LLUseCircuitCodeResponder*) user; + if(responder) + { + responder->complete(msg->getSender(), id); + } } else { @@ -4298,7 +2866,50 @@ void LLMessageSystem::processUseCircuitCode(LLMessageSystem* msg, void**) } } +static LLHTTPNode& messageRootNode() +{ + static LLHTTPNode root_node; + static bool initialized = false; + if (!initialized) { + initialized = true; + LLHTTPRegistrar::buildAllServices(root_node); + } + + return root_node; +} + +//static +void LLMessageSystem::dispatch(const std::string& msg_name, + const LLSD& message) +{ + LLPointer<LLSimpleResponse> responsep = LLSimpleResponse::create(); + dispatch(msg_name, message, responsep); +} +//static +void LLMessageSystem::dispatch(const std::string& msg_name, + const LLSD& message, + LLHTTPNode::ResponsePtr responsep) +{ + if (msg_name.empty()) + { + llwarns << "LLMessageService::dispatch called with no message name" + << llendl; + return; + } + + std::string path = "/message/" + msg_name; + LLSD context; + const LLHTTPNode* handler = messageRootNode().traverse(path, context); + if (!handler) + { + llwarns << "LLMessageService::dispatch > no handler for " + << path << llendl; + return; + } + + handler->post(responsep, context, message); +} static void check_for_unrecognized_messages( const char* type, @@ -4613,7 +3224,8 @@ BOOL start_messaging_system( S32 version_minor, S32 version_patch, BOOL b_dump_prehash_file, - const std::string& secret) + const std::string& secret, + const LLUseCircuitCodeResponder* responder) { gMessageSystem = new LLMessageSystem( template_name.c_str(), @@ -4662,7 +3274,7 @@ BOOL start_messaging_system( //gMessageSystem->setHandlerFuncFast(_PREHASH_AssignCircuitCode, LLMessageSystem::processAssignCircuitCode); gMessageSystem->setHandlerFuncFast(_PREHASH_AddCircuitCode, LLMessageSystem::processAddCircuitCode); //gMessageSystem->setHandlerFuncFast(_PREHASH_AckAddCircuitCode, ack_add_circuit_code, NULL); - gMessageSystem->setHandlerFuncFast(_PREHASH_UseCircuitCode, LLMessageSystem::processUseCircuitCode); + gMessageSystem->setHandlerFuncFast(_PREHASH_UseCircuitCode, LLMessageSystem::processUseCircuitCode, (void**)responder); gMessageSystem->setHandlerFuncFast(_PREHASH_PacketAck, process_packet_ack, NULL); gMessageSystem->setHandlerFuncFast(_PREHASH_TemplateChecksumRequest, process_template_checksum_request, NULL); gMessageSystem->setHandlerFuncFast(_PREHASH_SecuredTemplateChecksumRequest, process_secured_template_checksum_request, NULL); @@ -4882,13 +3494,13 @@ void LLMessageSystem::dumpReceiveCounts() BOOL LLMessageSystem::isClear() const { - return mbSClear; + return mMessageBuilder->isClear(); } S32 LLMessageSystem::flush(const LLHost &host) { - if (mCurrentSendTotal) + if (mMessageBuilder->getMessageSize()) { S32 sentbytes = sendMessage(host); clearMessage(); @@ -4905,91 +3517,22 @@ U32 LLMessageSystem::getListenPort( void ) const return mPort; } - -S32 LLMessageSystem::zeroCode(U8 **data, S32 *data_size) +// TODO: babbage: remove this horror! +S32 LLMessageSystem::zeroCodeAdjustCurrentSendTotal() { - S32 count = *data_size; - - S32 net_gain = 0; - U8 num_zeroes = 0; - - U8 *inptr = (U8 *)*data; - U8 *outptr = (U8 *)mEncodedSendBuffer; - -// skip the packet id field - - for (U32 i=0;i<LL_PACKET_ID_SIZE;i++) - { - count--; - *outptr++ = *inptr++; - } - -// build encoded packet, keeping track of net size gain - -// sequential zero bytes are encoded as 0 [U8 count] -// with 0 0 [count] representing wrap (>256 zeroes) - - while (count--) - { - if (!(*inptr)) // in a zero count - { - if (num_zeroes) - { - if (++num_zeroes > 254) - { - *outptr++ = num_zeroes; - num_zeroes = 0; - } - net_gain--; // subseqent zeroes save one - } - else - { - *outptr++ = 0; - net_gain++; // starting a zero count adds one - num_zeroes = 1; - } - inptr++; - } - else - { - if (num_zeroes) - { - *outptr++ = num_zeroes; - num_zeroes = 0; - } - *outptr++ = *inptr++; - } - } - - if (num_zeroes) + if(mMessageBuilder == mLLSDMessageBuilder) { - *outptr++ = num_zeroes; - } - - if (net_gain < 0) - { - mCompressedPacketsOut++; - mUncompressedBytesOut += *data_size; - - *data = mEncodedSendBuffer; - *data_size += net_gain; - mEncodedSendBuffer[0] |= LL_ZERO_CODE_FLAG; // set the head bit to indicate zero coding - - mCompressedBytesOut += *data_size; - + // babbage: don't compress LLSD messages, so delta is 0 + return 0; } - mTotalBytesOut += *data_size; - - return(net_gain); -} - -S32 LLMessageSystem::zeroCodeAdjustCurrentSendTotal() -{ - if (!mbSBuilt) + + if (! mMessageBuilder->isBuilt()) { - buildMessage(); + mSendSize = mMessageBuilder->buildMessage(mSendBuffer, + MAX_BUFFER_SIZE); } - mbSBuilt = FALSE; + // TODO: babbage: remove this horror + mMessageBuilder->setBuilt(FALSE); S32 count = mSendSize; @@ -5169,7 +3712,6 @@ void LLMessageSystem::setHandlerFuncFast(const char *name, void (*handler_func)( } } - bool LLMessageSystem::callHandler(const char *name, bool trustedSource, LLMessageSystem* msg) { @@ -5237,27 +3779,14 @@ BOOL LLMessageSystem::isCircuitCodeKnown(U32 code) const BOOL LLMessageSystem::isMessageFast(const char *msg) { - if (mCurrentRMessageTemplate) - { - return(msg == mCurrentRMessageTemplate->mName); - } - else - { - return FALSE; - } + return(msg == mMessageReader->getMessageName()); } char* LLMessageSystem::getMessageName() { - if (mCurrentRMessageTemplate) - { - return mCurrentRMessageTemplate->mName; - } - else - { - return NULL; - } + const char* name = mMessageReader->getMessageName(); + return name[0] == '\0'? NULL : const_cast<char*>(name); } const LLUUID& LLMessageSystem::getSenderID() const @@ -5281,211 +3810,6 @@ const LLUUID& LLMessageSystem::getSenderSessionID() const return LLUUID::null; } -void LLMessageSystem::addVector3Fast(const char *varname, const LLVector3& vec) -{ - addDataFast(varname, vec.mV, MVT_LLVector3, sizeof(vec.mV)); -} - -void LLMessageSystem::addVector3(const char *varname, const LLVector3& vec) -{ - addDataFast(gMessageStringTable.getString(varname), vec.mV, MVT_LLVector3, sizeof(vec.mV)); -} - -void LLMessageSystem::addVector4Fast(const char *varname, const LLVector4& vec) -{ - addDataFast(varname, vec.mV, MVT_LLVector4, sizeof(vec.mV)); -} - -void LLMessageSystem::addVector4(const char *varname, const LLVector4& vec) -{ - addDataFast(gMessageStringTable.getString(varname), vec.mV, MVT_LLVector4, sizeof(vec.mV)); -} - - -void LLMessageSystem::addVector3dFast(const char *varname, const LLVector3d& vec) -{ - addDataFast(varname, vec.mdV, MVT_LLVector3d, sizeof(vec.mdV)); -} - -void LLMessageSystem::addVector3d(const char *varname, const LLVector3d& vec) -{ - addDataFast(gMessageStringTable.getString(varname), vec.mdV, MVT_LLVector3d, sizeof(vec.mdV)); -} - - -void LLMessageSystem::addQuatFast(const char *varname, const LLQuaternion& quat) -{ - addDataFast(varname, quat.packToVector3().mV, MVT_LLQuaternion, sizeof(LLVector3)); -} - -void LLMessageSystem::addQuat(const char *varname, const LLQuaternion& quat) -{ - addDataFast(gMessageStringTable.getString(varname), quat.packToVector3().mV, MVT_LLQuaternion, sizeof(LLVector3)); -} - - -void LLMessageSystem::addUUIDFast(const char *varname, const LLUUID& uuid) -{ - addDataFast(varname, uuid.mData, MVT_LLUUID, sizeof(uuid.mData)); -} - -void LLMessageSystem::addUUID(const char *varname, const LLUUID& uuid) -{ - addDataFast(gMessageStringTable.getString(varname), uuid.mData, MVT_LLUUID, sizeof(uuid.mData)); -} - -void LLMessageSystem::getF32Fast(const char *block, const char *var, F32 &d, S32 blocknum) -{ - getDataFast(block, var, &d, sizeof(F32), blocknum); - - if( !llfinite( d ) ) - { - llwarns << "non-finite in getF32Fast " << block << " " << var << llendl; - d = 0; - } -} - -void LLMessageSystem::getF32(const char *block, const char *var, F32 &d, S32 blocknum) -{ - getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(F32), blocknum); - - if( !llfinite( d ) ) - { - llwarns << "non-finite in getF32 " << block << " " << var << llendl; - d = 0; - } -} - -void LLMessageSystem::getF64Fast(const char *block, const char *var, F64 &d, S32 blocknum) -{ - getDataFast(block, var, &d, sizeof(F64), blocknum); - - if( !llfinite( d ) ) - { - llwarns << "non-finite in getF64Fast " << block << " " << var << llendl; - d = 0; - } -} - -void LLMessageSystem::getF64(const char *block, const char *var, F64 &d, S32 blocknum) -{ - getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(F64), blocknum); - - if( !llfinite( d ) ) - { - llwarns << "non-finite in getF64 " << block << " " << var << llendl; - d = 0; - } -} - - -void LLMessageSystem::getVector3Fast(const char *block, const char *var, LLVector3 &v, S32 blocknum ) -{ - getDataFast(block, var, v.mV, sizeof(v.mV), blocknum); - - if( !v.isFinite() ) - { - llwarns << "non-finite in getVector3Fast " << block << " " << var << llendl; - v.zeroVec(); - } -} - -void LLMessageSystem::getVector3(const char *block, const char *var, LLVector3 &v, S32 blocknum ) -{ - getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), v.mV, sizeof(v.mV), blocknum); - - if( !v.isFinite() ) - { - llwarns << "non-finite in getVector4 " << block << " " << var << llendl; - v.zeroVec(); - } -} - -void LLMessageSystem::getVector4Fast(const char *block, const char *var, LLVector4 &v, S32 blocknum ) -{ - getDataFast(block, var, v.mV, sizeof(v.mV), blocknum); - - if( !v.isFinite() ) - { - llwarns << "non-finite in getVector4Fast " << block << " " << var << llendl; - v.zeroVec(); - } -} - -void LLMessageSystem::getVector4(const char *block, const char *var, LLVector4 &v, S32 blocknum ) -{ - getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), v.mV, sizeof(v.mV), blocknum); - - if( !v.isFinite() ) - { - llwarns << "non-finite in getVector3 " << block << " " << var << llendl; - v.zeroVec(); - } -} - -void LLMessageSystem::getVector3dFast(const char *block, const char *var, LLVector3d &v, S32 blocknum ) -{ - getDataFast(block, var, v.mdV, sizeof(v.mdV), blocknum); - - if( !v.isFinite() ) - { - llwarns << "non-finite in getVector3dFast " << block << " " << var << llendl; - v.zeroVec(); - } - -} - -void LLMessageSystem::getVector3d(const char *block, const char *var, LLVector3d &v, S32 blocknum ) -{ - getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), v.mdV, sizeof(v.mdV), blocknum); - - if( !v.isFinite() ) - { - llwarns << "non-finite in getVector3d " << block << " " << var << llendl; - v.zeroVec(); - } -} - -void LLMessageSystem::getQuatFast(const char *block, const char *var, LLQuaternion &q, S32 blocknum ) -{ - LLVector3 vec; - getDataFast(block, var, vec.mV, sizeof(vec.mV), blocknum); - if( vec.isFinite() ) - { - q.unpackFromVector3( vec ); - } - else - { - llwarns << "non-finite in getQuatFast " << block << " " << var << llendl; - q.loadIdentity(); - } -} - -void LLMessageSystem::getQuat(const char *block, const char *var, LLQuaternion &q, S32 blocknum ) -{ - LLVector3 vec; - getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), vec.mV, sizeof(vec.mV), blocknum); - if( vec.isFinite() ) - { - q.unpackFromVector3( vec ); - } - else - { - llwarns << "non-finite in getQuat " << block << " " << var << llendl; - q.loadIdentity(); - } -} - -void LLMessageSystem::getUUIDFast(const char *block, const char *var, LLUUID &u, S32 blocknum ) -{ - getDataFast(block, var, u.mData, sizeof(u.mData), blocknum); -} - -void LLMessageSystem::getUUID(const char *block, const char *var, LLUUID &u, S32 blocknum ) -{ - getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), u.mData, sizeof(u.mData), blocknum); -} - bool LLMessageSystem::generateDigestForNumberAndUUIDs( char* digest, const U32 number, @@ -5790,6 +4114,121 @@ void LLMessageSystem::dumpPacketToLog() } //static +BOOL LLMessageSystem::isTemplateConfirmed() +{ + return gMessageSystem->mTemplateConfirmed; +} + +//static +BOOL LLMessageSystem::doesTemplateMatch() +{ + if (!isTemplateConfirmed()) + { + return FALSE; + } + return gMessageSystem->mTemplateMatches; +} + +//static +void LLMessageSystem::sendMessageTemplateChecksum(const LLHost ¤tHost) +{ + gMessageSystem->mTemplateConfirmed = FALSE; + gMessageSystem->mTemplateMatches = FALSE; + gMessageSystem->newMessageFast(_PREHASH_TemplateChecksumRequest); + // Don't use ping-based retry + gMessageSystem->sendReliable(currentHost, 40, FALSE, 3, NULL, NULL); +} + +//static +void LLMessageSystem::processMessageTemplateChecksumReply(LLMessageSystem *msg, + void** user_data) +{ + U32 remote_template_checksum = 0; + msg->getU32Fast(_PREHASH_DataBlock, _PREHASH_Checksum, remote_template_checksum); + msg->mTemplateConfirmed = TRUE; + if ((remote_template_checksum) != msg->mMessageFileChecksum) + { + llwarns << "out of sync message template!" << llendl; + + msg->mTemplateMatches = FALSE; + msg->newMessageFast(_PREHASH_CloseCircuit); + msg->sendMessage(msg->getSender()); + return; + } + + msg->mTemplateMatches = TRUE; + llinfos << "According to " << msg->getSender() + << " the message template is current!" + << llendl; +} + +//static +void LLMessageSystem::sendSecureMessageTemplateChecksum(const LLHost& host) +{ + // generate an token for use during template checksum requests to + // prevent DOS attacks from injected bad template checksum replies. + LLUUID *template_tokenp = new LLUUID; + template_tokenp->generate(); + lldebugs << "random token: " << *template_tokenp << llendl; + + // register the handler for the reply while saving off template_token + gMessageSystem->setHandlerFuncFast(_PREHASH_TemplateChecksumReply, + LLMessageSystem::processSecureTemplateChecksumReply, + (void**)template_tokenp); + + // send checksum request + gMessageSystem->mTemplateConfirmed = FALSE; + gMessageSystem->newMessageFast(_PREHASH_SecuredTemplateChecksumRequest); + gMessageSystem->nextBlockFast(_PREHASH_TokenBlock); + gMessageSystem->addUUIDFast(_PREHASH_Token, *template_tokenp); + gMessageSystem->sendReliable(host); +} + +//static +void LLMessageSystem::processSecureTemplateChecksumReply(LLMessageSystem *msg, + void** user_data) +{ + // copy the token out into the stack and delete allocated memory + LLUUID template_token = *((LLUUID*)user_data); + delete user_data; + + LLUUID received_token; + msg->getUUID("TokenBlock", "Token", received_token); + + if(received_token != template_token) + { + llwarns << "Incorrect token in template checksum reply: " + << received_token << llendl; + //return do_normal_idle; + return; + } + + U32 remote_template_checksum = 0; + U8 major_version = 0; + U8 minor_version = 0; + U8 patch_version = 0; + U8 server_version = 0; + U32 flags = 0x0; + msg->getU32("DataBlock", "Checksum", remote_template_checksum); + msg->getU8 ("DataBlock", "MajorVersion", major_version); + msg->getU8 ("DataBlock", "MinorVersion", minor_version); + msg->getU8 ("DataBlock", "PatchVersion", patch_version); + msg->getU8 ("DataBlock", "ServerVersion", server_version); + msg->getU32("DataBlock", "Flags", flags); + + msg->mTemplateConfirmed = TRUE; + if (remote_template_checksum != gMessageSystem->mMessageFileChecksum) + { + llinfos << "Message template out of sync" << llendl; + msg->mTemplateMatches = FALSE; + } + else + { + msg->mTemplateMatches = TRUE; + } +} + +//static U64 LLMessageSystem::getMessageTimeUsecs(const BOOL update) { if (gMessageSystem) @@ -5834,3 +4273,558 @@ std::string get_shared_secret() return g_shared_secret; } +typedef std::map<const char*, LLMessageBuilder*> BuilderMap; + +static void setBuilder(BuilderMap& map, const char* name, LLMessageBuilder* builder) +{ + map[gMessageStringTable.getString(name)] = builder; +} + +void LLMessageSystem::newMessageFast(const char *name) +{ + if(LLMessageConfig::isMessageBuiltTemplate(name)) + { + mMessageBuilder = mTemplateMessageBuilder; + } + else + { + mMessageBuilder = mLLSDMessageBuilder; + } + mSendReliable = FALSE; + mMessageBuilder->newMessage(name); +} + +void LLMessageSystem::newMessage(const char *name) +{ + newMessageFast(gMessageStringTable.getString(name)); +} + +void LLMessageSystem::addBinaryDataFast(const char *varname, const void *data, S32 size) +{ + mMessageBuilder->addBinaryData(varname, data, size); +} + +void LLMessageSystem::addBinaryData(const char *varname, const void *data, S32 size) +{ + mMessageBuilder->addBinaryData(gMessageStringTable.getString(varname),data, size); +} + +void LLMessageSystem::addS8Fast(const char *varname, S8 v) +{ + mMessageBuilder->addS8(varname, v); +} + +void LLMessageSystem::addS8(const char *varname, S8 v) +{ + mMessageBuilder->addS8(gMessageStringTable.getString(varname), v); +} + +void LLMessageSystem::addU8Fast(const char *varname, U8 v) +{ + mMessageBuilder->addU8(varname, v); +} + +void LLMessageSystem::addU8(const char *varname, U8 v) +{ + mMessageBuilder->addU8(gMessageStringTable.getString(varname), v); +} + +void LLMessageSystem::addS16Fast(const char *varname, S16 v) +{ + mMessageBuilder->addS16(varname, v); +} + +void LLMessageSystem::addS16(const char *varname, S16 v) +{ + mMessageBuilder->addS16(gMessageStringTable.getString(varname), v); +} + +void LLMessageSystem::addU16Fast(const char *varname, U16 v) +{ + mMessageBuilder->addU16(varname, v); +} + +void LLMessageSystem::addU16(const char *varname, U16 v) +{ + mMessageBuilder->addU16(gMessageStringTable.getString(varname), v); +} + +void LLMessageSystem::addF32Fast(const char *varname, F32 v) +{ + mMessageBuilder->addF32(varname, v); +} + +void LLMessageSystem::addF32(const char *varname, F32 v) +{ + mMessageBuilder->addF32(gMessageStringTable.getString(varname), v); +} + +void LLMessageSystem::addS32Fast(const char *varname, S32 v) +{ + mMessageBuilder->addS32(varname, v); +} + +void LLMessageSystem::addS32(const char *varname, S32 v) +{ + mMessageBuilder->addS32(gMessageStringTable.getString(varname), v); +} + +void LLMessageSystem::addU32Fast(const char *varname, U32 v) +{ + mMessageBuilder->addU32(varname, v); +} + +void LLMessageSystem::addU32(const char *varname, U32 v) +{ + mMessageBuilder->addU32(gMessageStringTable.getString(varname), v); +} + +void LLMessageSystem::addU64Fast(const char *varname, U64 v) +{ + mMessageBuilder->addU64(varname, v); +} + +void LLMessageSystem::addU64(const char *varname, U64 v) +{ + mMessageBuilder->addU64(gMessageStringTable.getString(varname), v); +} + +void LLMessageSystem::addF64Fast(const char *varname, F64 v) +{ + mMessageBuilder->addF64(varname, v); +} + +void LLMessageSystem::addF64(const char *varname, F64 v) +{ + mMessageBuilder->addF64(gMessageStringTable.getString(varname), v); +} + +void LLMessageSystem::addIPAddrFast(const char *varname, U32 v) +{ + mMessageBuilder->addIPAddr(varname, v); +} + +void LLMessageSystem::addIPAddr(const char *varname, U32 v) +{ + mMessageBuilder->addIPAddr(gMessageStringTable.getString(varname), v); +} + +void LLMessageSystem::addIPPortFast(const char *varname, U16 v) +{ + mMessageBuilder->addIPPort(varname, v); +} + +void LLMessageSystem::addIPPort(const char *varname, U16 v) +{ + mMessageBuilder->addIPPort(gMessageStringTable.getString(varname), v); +} + +void LLMessageSystem::addBOOLFast(const char* varname, BOOL v) +{ + mMessageBuilder->addBOOL(varname, v); +} + +void LLMessageSystem::addBOOL(const char* varname, BOOL v) +{ + mMessageBuilder->addBOOL(gMessageStringTable.getString(varname), v); +} + +void LLMessageSystem::addStringFast(const char* varname, const char* v) +{ + mMessageBuilder->addString(varname, v); +} + +void LLMessageSystem::addString(const char* varname, const char* v) +{ + mMessageBuilder->addString(gMessageStringTable.getString(varname), v); +} + +void LLMessageSystem::addStringFast(const char* varname, const std::string& v) +{ + mMessageBuilder->addString(varname, v); +} + +void LLMessageSystem::addString(const char* varname, const std::string& v) +{ + mMessageBuilder->addString(gMessageStringTable.getString(varname), v); +} + +void LLMessageSystem::addVector3Fast(const char *varname, const LLVector3& v) +{ + mMessageBuilder->addVector3(varname, v); +} + +void LLMessageSystem::addVector3(const char *varname, const LLVector3& v) +{ + mMessageBuilder->addVector3(gMessageStringTable.getString(varname), v); +} + +void LLMessageSystem::addVector4Fast(const char *varname, const LLVector4& v) +{ + mMessageBuilder->addVector4(varname, v); +} + +void LLMessageSystem::addVector4(const char *varname, const LLVector4& v) +{ + mMessageBuilder->addVector4(gMessageStringTable.getString(varname), v); +} + +void LLMessageSystem::addVector3dFast(const char *varname, const LLVector3d& v) +{ + mMessageBuilder->addVector3d(varname, v); +} + +void LLMessageSystem::addVector3d(const char *varname, const LLVector3d& v) +{ + mMessageBuilder->addVector3d(gMessageStringTable.getString(varname), v); +} + +void LLMessageSystem::addQuatFast(const char *varname, const LLQuaternion& v) +{ + mMessageBuilder->addQuat(varname, v); +} + +void LLMessageSystem::addQuat(const char *varname, const LLQuaternion& v) +{ + mMessageBuilder->addQuat(gMessageStringTable.getString(varname), v); +} + + +void LLMessageSystem::addUUIDFast(const char *varname, const LLUUID& v) +{ + mMessageBuilder->addUUID(varname, v); +} + +void LLMessageSystem::addUUID(const char *varname, const LLUUID& v) +{ + mMessageBuilder->addUUID(gMessageStringTable.getString(varname), v); +} + +S32 LLMessageSystem::getCurrentSendTotal() const +{ + return mMessageBuilder->getMessageSize(); +} + +void LLMessageSystem::getS8Fast(const char *block, const char *var, S8 &u, + S32 blocknum) +{ + mMessageReader->getS8(block, var, u, blocknum); +} + +void LLMessageSystem::getS8(const char *block, const char *var, S8 &u, + S32 blocknum) +{ + getS8Fast(gMessageStringTable.getString(block), + gMessageStringTable.getString(var), u, blocknum); +} + +void LLMessageSystem::getU8Fast(const char *block, const char *var, U8 &u, + S32 blocknum) +{ + mMessageReader->getU8(block, var, u, blocknum); +} + +void LLMessageSystem::getU8(const char *block, const char *var, U8 &u, + S32 blocknum) +{ + getU8Fast(gMessageStringTable.getString(block), + gMessageStringTable.getString(var), u, blocknum); +} + +void LLMessageSystem::getBOOLFast(const char *block, const char *var, BOOL &b, + S32 blocknum) +{ + mMessageReader->getBOOL(block, var, b, blocknum); +} + +void LLMessageSystem::getBOOL(const char *block, const char *var, BOOL &b, + S32 blocknum) +{ + getBOOLFast(gMessageStringTable.getString(block), + gMessageStringTable.getString(var), b, blocknum); +} + +void LLMessageSystem::getS16Fast(const char *block, const char *var, S16 &d, + S32 blocknum) +{ + mMessageReader->getS16(block, var, d, blocknum); +} + +void LLMessageSystem::getS16(const char *block, const char *var, S16 &d, + S32 blocknum) +{ + getS16Fast(gMessageStringTable.getString(block), + gMessageStringTable.getString(var), d, blocknum); +} + +void LLMessageSystem::getU16Fast(const char *block, const char *var, U16 &d, + S32 blocknum) +{ + mMessageReader->getU16(block, var, d, blocknum); +} + +void LLMessageSystem::getU16(const char *block, const char *var, U16 &d, + S32 blocknum) +{ + getU16Fast(gMessageStringTable.getString(block), + gMessageStringTable.getString(var), d, blocknum); +} + +void LLMessageSystem::getS32Fast(const char *block, const char *var, S32 &d, + S32 blocknum) +{ + mMessageReader->getS32(block, var, d, blocknum); +} + +void LLMessageSystem::getS32(const char *block, const char *var, S32 &d, + S32 blocknum) +{ + getS32Fast(gMessageStringTable.getString(block), + gMessageStringTable.getString(var), d, blocknum); +} + +void LLMessageSystem::getU32Fast(const char *block, const char *var, U32 &d, + S32 blocknum) +{ + mMessageReader->getU32(block, var, d, blocknum); +} + +void LLMessageSystem::getU32(const char *block, const char *var, U32 &d, + S32 blocknum) +{ + getU32Fast(gMessageStringTable.getString(block), + gMessageStringTable.getString(var), d, blocknum); +} + +void LLMessageSystem::getU64Fast(const char *block, const char *var, U64 &d, + S32 blocknum) +{ + mMessageReader->getU64(block, var, d, blocknum); +} + +void LLMessageSystem::getU64(const char *block, const char *var, U64 &d, + S32 blocknum) +{ + + getU64Fast(gMessageStringTable.getString(block), + gMessageStringTable.getString(var), d, blocknum); +} + +void LLMessageSystem::getBinaryDataFast(const char *blockname, + const char *varname, + void *datap, S32 size, + S32 blocknum, S32 max_size) +{ + mMessageReader->getBinaryData(blockname, varname, datap, size, blocknum, + max_size); +} + +void LLMessageSystem::getBinaryData(const char *blockname, + const char *varname, + void *datap, S32 size, + S32 blocknum, S32 max_size) +{ + getBinaryDataFast(gMessageStringTable.getString(blockname), + gMessageStringTable.getString(varname), + datap, size, blocknum, max_size); +} + +void LLMessageSystem::getF32Fast(const char *block, const char *var, F32 &d, + S32 blocknum) +{ + mMessageReader->getF32(block, var, d, blocknum); +} + +void LLMessageSystem::getF32(const char *block, const char *var, F32 &d, + S32 blocknum) +{ + getF32Fast(gMessageStringTable.getString(block), + gMessageStringTable.getString(var), d, blocknum); +} + +void LLMessageSystem::getF64Fast(const char *block, const char *var, F64 &d, + S32 blocknum) +{ + mMessageReader->getF64(block, var, d, blocknum); +} + +void LLMessageSystem::getF64(const char *block, const char *var, F64 &d, + S32 blocknum) +{ + getF64Fast(gMessageStringTable.getString(block), + gMessageStringTable.getString(var), d, blocknum); +} + + +void LLMessageSystem::getVector3Fast(const char *block, const char *var, + LLVector3 &v, S32 blocknum ) +{ + mMessageReader->getVector3(block, var, v, blocknum); +} + +void LLMessageSystem::getVector3(const char *block, const char *var, + LLVector3 &v, S32 blocknum ) +{ + getVector3Fast(gMessageStringTable.getString(block), + gMessageStringTable.getString(var), v, blocknum); +} + +void LLMessageSystem::getVector4Fast(const char *block, const char *var, + LLVector4 &v, S32 blocknum ) +{ + mMessageReader->getVector4(block, var, v, blocknum); +} + +void LLMessageSystem::getVector4(const char *block, const char *var, + LLVector4 &v, S32 blocknum ) +{ + getVector4Fast(gMessageStringTable.getString(block), + gMessageStringTable.getString(var), v, blocknum); +} + +void LLMessageSystem::getVector3dFast(const char *block, const char *var, + LLVector3d &v, S32 blocknum ) +{ + mMessageReader->getVector3d(block, var, v, blocknum); +} + +void LLMessageSystem::getVector3d(const char *block, const char *var, + LLVector3d &v, S32 blocknum ) +{ + getVector3dFast(gMessageStringTable.getString(block), + gMessageStringTable.getString(var), v, blocknum); +} + +void LLMessageSystem::getQuatFast(const char *block, const char *var, + LLQuaternion &q, S32 blocknum ) +{ + mMessageReader->getQuat(block, var, q, blocknum); +} + +void LLMessageSystem::getQuat(const char *block, const char *var, + LLQuaternion &q, S32 blocknum) +{ + getQuatFast(gMessageStringTable.getString(block), + gMessageStringTable.getString(var), q, blocknum); +} + +void LLMessageSystem::getUUIDFast(const char *block, const char *var, + LLUUID &u, S32 blocknum ) +{ + mMessageReader->getUUID(block, var, u, blocknum); +} + +void LLMessageSystem::getUUID(const char *block, const char *var, LLUUID &u, + S32 blocknum ) +{ + getUUIDFast(gMessageStringTable.getString(block), + gMessageStringTable.getString(var), u, blocknum); +} + +void LLMessageSystem::getIPAddrFast(const char *block, const char *var, + U32 &u, S32 blocknum) +{ + mMessageReader->getIPAddr(block, var, u, blocknum); +} + +void LLMessageSystem::getIPAddr(const char *block, const char *var, U32 &u, + S32 blocknum) +{ + getIPAddrFast(gMessageStringTable.getString(block), + gMessageStringTable.getString(var), u, blocknum); +} + +void LLMessageSystem::getIPPortFast(const char *block, const char *var, + U16 &u, S32 blocknum) +{ + mMessageReader->getIPPort(block, var, u, blocknum); +} + +void LLMessageSystem::getIPPort(const char *block, const char *var, U16 &u, + S32 blocknum) +{ + getIPPortFast(gMessageStringTable.getString(block), + gMessageStringTable.getString(var), u, + blocknum); +} + + +void LLMessageSystem::getStringFast(const char *block, const char *var, + S32 buffer_size, char *s, S32 blocknum) +{ + mMessageReader->getString(block, var, buffer_size, s, blocknum); +} + +void LLMessageSystem::getString(const char *block, const char *var, + S32 buffer_size, char *s, S32 blocknum ) +{ + getStringFast(gMessageStringTable.getString(block), + gMessageStringTable.getString(var), buffer_size, s, + blocknum); +} + +S32 LLMessageSystem::getNumberOfBlocksFast(const char *blockname) +{ + return mMessageReader->getNumberOfBlocks(blockname); +} + +S32 LLMessageSystem::getNumberOfBlocks(const char *blockname) +{ + return getNumberOfBlocksFast(gMessageStringTable.getString(blockname)); +} + +S32 LLMessageSystem::getSizeFast(const char *blockname, const char *varname) +{ + return mMessageReader->getSize(blockname, varname); +} + +S32 LLMessageSystem::getSize(const char *blockname, const char *varname) +{ + return getSizeFast(gMessageStringTable.getString(blockname), + gMessageStringTable.getString(varname)); +} + +// size in bytes of variable length data +S32 LLMessageSystem::getSizeFast(const char *blockname, S32 blocknum, + const char *varname) +{ + return mMessageReader->getSize(blockname, blocknum, varname); +} + +S32 LLMessageSystem::getSize(const char *blockname, S32 blocknum, + const char *varname) +{ + return getSizeFast(gMessageStringTable.getString(blockname), blocknum, + gMessageStringTable.getString(varname)); +} + +S32 LLMessageSystem::getReceiveSize() const +{ + return mMessageReader->getMessageSize(); +} + +//static +void LLMessageSystem::setTimeDecodes( BOOL b ) +{ + LLMessageReader::setTimeDecodes(b); +} + +//static +void LLMessageSystem::setTimeDecodesSpamThreshold( F32 seconds ) +{ + LLMessageReader::setTimeDecodesSpamThreshold(seconds); +} + +// HACK! babbage: return true if message rxed via either UDP or HTTP +// TODO: babbage: move gServicePump in to LLMessageSystem? +bool LLMessageSystem::checkAllMessages(S64 frame_count, LLPumpIO* http_pump) +{ + if(checkMessages(frame_count)) + { + return true; + } + U32 packetsIn = mPacketsIn; + http_pump->pump(); + http_pump->callback(); + return (mPacketsIn - packetsIn) > 0; +} diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h index 3ffafcc1b8..a4a8022631 100644 --- a/indra/llmessage/message.h +++ b/indra/llmessage/message.h @@ -1,5 +1,5 @@ /** - * @file message.h + * @FILE message.h * @brief LLMessageSystem class header file * * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. @@ -30,9 +30,11 @@ #include "lltimer.h" #include "llpacketring.h" #include "llhost.h" +#include "llhttpnode.h" #include "llpacketack.h" #include "message_prehash.h" #include "llstl.h" +#include "llmsgvariabletype.h" const U32 MESSAGE_MAX_STRINGS_LENGTH = 64; const U32 MESSAGE_NUMBER_OF_HASH_BUCKETS = 8192; @@ -131,39 +133,10 @@ class LLQuaternion; class LLSD; class LLUUID; class LLMessageSystem; +class LLPumpIO; // message data pieces are used to collect the data called for by the message template -// iterator typedefs precede each class as needed -typedef enum e_message_variable_type -{ - MVT_NULL, - MVT_FIXED, - MVT_VARIABLE, - MVT_U8, - MVT_U16, - MVT_U32, - MVT_U64, - MVT_S8, - MVT_S16, - MVT_S32, - MVT_S64, - MVT_F32, - MVT_F64, - MVT_LLVector3, - MVT_LLVector3d, - MVT_LLVector4, - MVT_LLQuaternion, - MVT_LLUUID, - MVT_BOOL, - MVT_IP_ADDR, - MVT_IP_PORT, - MVT_U16Vec3, - MVT_U16Quat, - MVT_S16Array, - MVT_EOL -} EMsgVariableType; - // message system exceptional condition handlers. enum EMessageException { @@ -180,19 +153,29 @@ class LLMsgBlkData; class LLMessageTemplate; class LLMessagePollInfo; +class LLMessageBuilder; +class LLTemplateMessageBuilder; +class LLSDMessageBuilder; +class LLMessageReader; +class LLTemplateMessageReader; +class LLSDMessageReader; -class LLMessageSystem +class LLUseCircuitCodeResponder { LOG_CLASS(LLMessageSystem); public: + virtual ~LLUseCircuitCodeResponder(); + virtual void complete(const LLHost& host, const LLUUID& agent) const = 0; +}; + +class LLMessageSystem +{ + private: U8 mSendBuffer[MAX_BUFFER_SIZE]; - // Encoded send buffer needs to be slightly larger since the zero - // coding can potentially increase the size of the send data. - U8 mEncodedSendBuffer[2 * MAX_BUFFER_SIZE]; S32 mSendSize; - S32 mCurrentSendTotal; + public: LLPacketRing mPacketRing; LLReliablePacketParams mReliablePacketParams; @@ -271,12 +254,7 @@ public: LLMessageSystem(const char *filename, U32 port, S32 version_major, S32 version_minor, S32 version_patch); -public: - // Subclass use. - LLMessageSystem(); - -public: - virtual ~LLMessageSystem(); + ~LLMessageSystem(); BOOL isOK() const { return !mbError; } S32 getErrorCode() const { return mErrorCode; } @@ -294,9 +272,6 @@ public: setHandlerFuncFast(gMessageStringTable.getString(name), handler_func, user_data); } - bool callHandler(const char *name, bool trustedSource, - LLMessageSystem* msg); - // Set a callback function for a message system exception. void setExceptionFunc(EMessageException exception, msg_exception_callback func, void* data = NULL); // Call the specified exception func, and return TRUE if a @@ -308,6 +283,14 @@ public: // measured in seconds. JC typedef void (*msg_timing_callback)(const char* hashed_name, F32 time, void* data); void setTimingFunc(msg_timing_callback func, void* data = NULL); + msg_timing_callback getTimingCallback() + { + return mTimingCallback; + } + void* getTimingCallbackData() + { + return mTimingCallbackData; + } // This method returns true if the code is in the circuit codes map. BOOL isCircuitCodeKnown(U32 code) const; @@ -347,42 +330,21 @@ public: void setMySessionID(const LLUUID& session_id) { mSessionID = session_id; } const LLUUID& getMySessionID() { return mSessionID; } - virtual void newMessageFast(const char *name); - void newMessage(const char *name) - { - newMessageFast(gMessageStringTable.getString(name)); - } + void newMessageFast(const char *name); + void newMessage(const char *name); void copyMessageRtoS(); void clearMessage(); - virtual void nextBlockFast(const char *blockname); + void nextBlockFast(const char *blockname); void nextBlock(const char *blockname) { nextBlockFast(gMessageStringTable.getString(blockname)); } -private: - void addDataFast(const char *varname, const void *data, EMsgVariableType type, S32 size); // Use only for types not in system already - void addData(const char *varname, const void *data, EMsgVariableType type, S32 size) - { - addDataFast(gMessageStringTable.getString(varname), data, type, size); - } - - void addDataFast(const char *varname, const void *data, EMsgVariableType type); // DEPRECATED - not typed, doesn't check storage space - void addData(const char *varname, const void *data, EMsgVariableType type) - { - addDataFast(gMessageStringTable.getString(varname), data, type); - } public: - void addBinaryDataFast(const char *varname, const void *data, S32 size) - { - addDataFast(varname, data, MVT_FIXED, size); - } - void addBinaryData(const char *varname, const void *data, S32 size) - { - addDataFast(gMessageStringTable.getString(varname), data, MVT_FIXED, size); - } + void addBinaryDataFast(const char *varname, const void *data, S32 size); + void addBinaryData(const char *varname, const void *data, S32 size); void addBOOLFast( const char* varname, BOOL b); // typed, checks storage space void addBOOL( const char* varname, BOOL b); // typed, checks storage space @@ -398,7 +360,7 @@ public: void addF32( const char *varname, F32 f); // typed, checks storage space void addS32Fast( const char *varname, S32 s); // typed, checks storage space void addS32( const char *varname, S32 s); // typed, checks storage space - virtual void addU32Fast( const char *varname, U32 u); // typed, checks storage space + void addU32Fast( const char *varname, U32 u); // typed, checks storage space void addU32( const char *varname, U32 u); // typed, checks storage space void addU64Fast( const char *varname, U64 lu); // typed, checks storage space void addU64( const char *varname, U64 lu); // typed, checks storage space @@ -412,7 +374,7 @@ public: void addVector3d( const char *varname, const LLVector3d& vec); // typed, checks storage space void addQuatFast( const char *varname, const LLQuaternion& quat); // typed, checks storage space void addQuat( const char *varname, const LLQuaternion& quat); // typed, checks storage space - virtual void addUUIDFast( const char *varname, const LLUUID& uuid); // typed, checks storage space + void addUUIDFast( const char *varname, const LLUUID& uuid); // typed, checks storage space void addUUID( const char *varname, const LLUUID& uuid); // typed, checks storage space void addIPAddrFast( const char *varname, const U32 ip); // typed, checks storage space void addIPAddr( const char *varname, const U32 ip); // typed, checks storage space @@ -423,8 +385,8 @@ public: void addStringFast( const char* varname, const std::string& s); // typed, checks storage space void addString( const char* varname, const std::string& s); // typed, checks storage space + S32 getCurrentSendTotal() const; TPACKETID getCurrentRecvPacketID() { return mCurrentRecvPacketID; } - S32 getCurrentSendTotal() const { return mCurrentSendTotal; } // This method checks for current send total and returns true if // you need to go to the next block type or need to start a new @@ -433,16 +395,16 @@ public: BOOL isSendFull(const char* blockname = NULL); BOOL isSendFullFast(const char* blockname = NULL); - BOOL removeLastBlock(); + BOOL removeLastBlock(); - void buildMessage(); + //void buildMessage(); S32 zeroCode(U8 **data, S32 *data_size); S32 zeroCodeExpand(U8 **data, S32 *data_size); S32 zeroCodeAdjustCurrentSendTotal(); // Uses ping-based retry - virtual S32 sendReliable(const LLHost &host); + S32 sendReliable(const LLHost &host); // Uses ping-based retry S32 sendReliable(const U32 circuit) { return sendReliable(findHost(circuit)); } @@ -471,28 +433,10 @@ public: S32 sendMessage(const LLHost &host); S32 sendMessage(const U32 circuit); - BOOL decodeData(const U8 *buffer, const LLHost &host); - - // TODO: Consolide these functions - // TODO: Make these private, force use of typed functions. - // If size is not 0, an error is generated if size doesn't exactly match the size of the data. - // At all times, the number if bytes written to *datap is <= max_size. -private: - void getDataFast(const char *blockname, const char *varname, void *datap, S32 size = 0, S32 blocknum = 0, S32 max_size = S32_MAX); - void getData(const char *blockname, const char *varname, void *datap, S32 size = 0, S32 blocknum = 0, S32 max_size = S32_MAX) - { - getDataFast(gMessageStringTable.getString(blockname), gMessageStringTable.getString(varname), datap, size, blocknum, max_size); - } -public: - void getBinaryDataFast(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum = 0, S32 max_size = S32_MAX) - { - getDataFast(blockname, varname, datap, size, blocknum, max_size); - } - void getBinaryData(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum = 0, S32 max_size = S32_MAX) - { - getDataFast(gMessageStringTable.getString(blockname), gMessageStringTable.getString(varname), datap, size, blocknum, max_size); - } + // BOOL decodeData(const U8 *buffer, const LLHost &host); + void getBinaryDataFast(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum = 0, S32 max_size = S32_MAX); + void getBinaryData(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum = 0, S32 max_size = S32_MAX); void getBOOLFast( const char *block, const char *var, BOOL &data, S32 blocknum = 0); void getBOOL( const char *block, const char *var, BOOL &data, S32 blocknum = 0); void getS8Fast( const char *block, const char *var, S8 &data, S32 blocknum = 0); @@ -507,9 +451,9 @@ public: void getS32( const char *block, const char *var, S32 &data, S32 blocknum = 0); void getF32Fast( const char *block, const char *var, F32 &data, S32 blocknum = 0); void getF32( const char *block, const char *var, F32 &data, S32 blocknum = 0); - virtual void getU32Fast( const char *block, const char *var, U32 &data, S32 blocknum = 0); + void getU32Fast( const char *block, const char *var, U32 &data, S32 blocknum = 0); void getU32( const char *block, const char *var, U32 &data, S32 blocknum = 0); - virtual void getU64Fast( const char *block, const char *var, U64 &data, S32 blocknum = 0); + void getU64Fast( const char *block, const char *var, U64 &data, S32 blocknum = 0); void getU64( const char *block, const char *var, U64 &data, S32 blocknum = 0); void getF64Fast( const char *block, const char *var, F64 &data, S32 blocknum = 0); void getF64( const char *block, const char *var, F64 &data, S32 blocknum = 0); @@ -521,13 +465,13 @@ public: void getVector3d(const char *block, const char *var, LLVector3d &vec, S32 blocknum = 0); void getQuatFast( const char *block, const char *var, LLQuaternion &q, S32 blocknum = 0); void getQuat( const char *block, const char *var, LLQuaternion &q, S32 blocknum = 0); - virtual void getUUIDFast( const char *block, const char *var, LLUUID &uuid, S32 blocknum = 0); + void getUUIDFast( const char *block, const char *var, LLUUID &uuid, S32 blocknum = 0); void getUUID( const char *block, const char *var, LLUUID &uuid, S32 blocknum = 0); - virtual void getIPAddrFast( const char *block, const char *var, U32 &ip, S32 blocknum = 0); + void getIPAddrFast( const char *block, const char *var, U32 &ip, S32 blocknum = 0); void getIPAddr( const char *block, const char *var, U32 &ip, S32 blocknum = 0); - virtual void getIPPortFast( const char *block, const char *var, U16 &port, S32 blocknum = 0); + void getIPPortFast( const char *block, const char *var, U16 &port, S32 blocknum = 0); void getIPPort( const char *block, const char *var, U16 &port, S32 blocknum = 0); - virtual void getStringFast( const char *block, const char *var, S32 buffer_size, char *buffer, S32 blocknum = 0); + void getStringFast( const char *block, const char *var, S32 buffer_size, char *buffer, S32 blocknum = 0); void getString( const char *block, const char *var, S32 buffer_size, char *buffer, S32 blocknum = 0); @@ -549,7 +493,7 @@ public: void showCircuitInfo(); LLString getCircuitInfoString(); - virtual U32 getOurCircuitCode(); + U32 getOurCircuitCode(); void enableCircuit(const LLHost &host, BOOL trusted); void disableCircuit(const LLHost &host); @@ -595,20 +539,12 @@ public: void sanityCheck(); S32 getNumberOfBlocksFast(const char *blockname); - S32 getNumberOfBlocks(const char *blockname) - { - return getNumberOfBlocksFast(gMessageStringTable.getString(blockname)); - } + S32 getNumberOfBlocks(const char *blockname); S32 getSizeFast(const char *blockname, const char *varname); - S32 getSize(const char *blockname, const char *varname) - { - return getSizeFast(gMessageStringTable.getString(blockname), gMessageStringTable.getString(varname)); - } - S32 getSizeFast(const char *blockname, S32 blocknum, const char *varname); // size in bytes of variable length data - S32 getSize(const char *blockname, S32 blocknum, const char *varname) - { - return getSizeFast(gMessageStringTable.getString(blockname), blocknum, gMessageStringTable.getString(varname)); - } + S32 getSize(const char *blockname, const char *varname); + S32 getSizeFast(const char *blockname, S32 blocknum, + const char *varname); // size in bytes of data + S32 getSize(const char *blockname, S32 blocknum, const char *varname); void resetReceiveCounts(); // resets receive counts for all message types to 0 void dumpReceiveCounts(); // dumps receive count for each message type to llinfos @@ -623,14 +559,14 @@ public: void stopLogging(); // flush and close file void summarizeLogs(std::ostream& str); // log statistics - S32 getReceiveSize() const { return mReceiveSize; } - S32 getReceiveCompressedSize() const { return mIncomingCompressedSize; } + S32 getReceiveSize() const; + S32 getReceiveCompressedSize() const { return mIncomingCompressedSize; } S32 getReceiveBytes() const; S32 getUnackedListSize() const { return mUnackedListSize; } - const char* getCurrentSMessageName() const { return mCurrentSMessageName; } - const char* getCurrentSBlockName() const { return mCurrentSBlockName; } + //const char* getCurrentSMessageName() const { return mCurrentSMessageName; } + //const char* getCurrentSBlockName() const { return mCurrentSBlockName; } // friends friend std::ostream& operator<<(std::ostream& s, LLMessageSystem &msg); @@ -639,25 +575,41 @@ public: void setMaxMessageCounts(const S32 num); // Max number of messages before dumping (neg to disable) // statics -public: + static BOOL isTemplateConfirmed(); + static BOOL doesTemplateMatch(); + static void sendMessageTemplateChecksum(const LLHost&); + static void processMessageTemplateChecksumReply(LLMessageSystem *msg, + void** user_data); + static void sendSecureMessageTemplateChecksum(const LLHost&); + static void processSecureTemplateChecksumReply(LLMessageSystem *msg, + void** user_data); static U64 getMessageTimeUsecs(const BOOL update = FALSE); // Get the current message system time in microseconds static F64 getMessageTimeSeconds(const BOOL update = FALSE); // Get the current message system time in seconds - static void setTimeDecodes( BOOL b ) - { LLMessageSystem::mTimeDecodes = b; } - - static void setTimeDecodesSpamThreshold( F32 seconds ) - { LLMessageSystem::mTimeDecodesSpamThreshold = seconds; } + static void setTimeDecodes(BOOL b); + static void setTimeDecodesSpamThreshold(F32 seconds); // message handlers internal to the message systesm //static void processAssignCircuitCode(LLMessageSystem* msg, void**); static void processAddCircuitCode(LLMessageSystem* msg, void**); static void processUseCircuitCode(LLMessageSystem* msg, void**); + // dispatch llsd message to http node tree + static void dispatch(const std::string& msg_name, + const LLSD& message); + static void dispatch(const std::string& msg_name, + const LLSD& message, + LLHTTPNode::ResponsePtr responsep); + void setMessageBans(const LLSD& trusted, const LLSD& untrusted); + + // Check UDP messages and pump http_pump to receive HTTP messages. + bool checkAllMessages(S64 frame_count, LLPumpIO* http_pump); private: // data used in those internal handlers + BOOL mTemplateConfirmed; + BOOL mTemplateMatches; // The mCircuitCodes is a map from circuit codes to session // ids. This allows us to verify sessions on connect. @@ -668,7 +620,6 @@ private: // that no one gives them a bad circuit code. LLUUID mSessionID; -private: void addTemplate(LLMessageTemplate *templatep); void clearReceiveState(); BOOL decodeTemplate( const U8* buffer, S32 buffer_size, LLMessageTemplate** msg_template ); @@ -678,7 +629,6 @@ private: void logValidMsg(LLCircuitData *cdp, const LLHost& sender, BOOL recv_reliable, BOOL recv_resent, BOOL recv_acks ); void logRanOffEndOfPacket( const LLHost& sender ); -private: class LLMessageCountInfo { public: @@ -694,26 +644,10 @@ private: S32 mTrueReceiveSize; // Must be valid during decode - S32 mReceiveSize; - TPACKETID mCurrentRecvPacketID; // packet ID of current receive packet (for reporting) - LLMessageTemplate *mCurrentRMessageTemplate; - LLMsgData *mCurrentRMessageData; - S32 mIncomingCompressedSize; // original size of compressed msg (0 if uncomp.) - LLHost mLastSender; - - // send message storage - LLMsgData *mCurrentSMessageData; - LLMessageTemplate *mCurrentSMessageTemplate; - LLMsgBlkData *mCurrentSDataBlock; - char *mCurrentSMessageName; - char *mCurrentSBlockName; - + BOOL mbError; S32 mErrorCode; - BOOL mbSBuilt; // is send message built? - BOOL mbSClear; // is the send message clear? - F64 mResendDumpTime; // The last time we dumped resends LLMessageCountInfo mMessageCountList[MAX_MESSAGE_COUNT_NUM]; @@ -740,6 +674,22 @@ private: void* mTimingCallbackData; void init(); // ctor shared initialisation. + + LLHost mLastSender; + S32 mIncomingCompressedSize; // original size of compressed msg (0 if uncomp.) + TPACKETID mCurrentRecvPacketID; // packet ID of current receive packet (for reporting) + + LLMessageBuilder* mMessageBuilder; + LLTemplateMessageBuilder* mTemplateMessageBuilder; + LLSDMessageBuilder* mLLSDMessageBuilder; + LLMessageReader* mMessageReader; + LLTemplateMessageReader* mTemplateMessageReader; + LLSDMessageReader* mLLSDMessageReader; + + friend class LLMessageHandlerBridge; + + bool callHandler(const char *name, bool trustedSource, + LLMessageSystem* msg); }; @@ -756,7 +706,8 @@ BOOL start_messaging_system( S32 version_minor, S32 version_patch, BOOL b_dump_prehash_file, - const std::string& secret); + const std::string& secret, + const LLUseCircuitCodeResponder* responder = NULL); void end_messaging_system(); @@ -932,12 +883,9 @@ inline void *ntohmemcpy(void *s, const void *ct, EMsgVariableType type, size_t n } -inline const LLHost& LLMessageSystem::getSender() const -{ - return mLastSender; -} +inline const LLHost& LLMessageSystem::getSender() const {return mLastSender;} -inline U32 LLMessageSystem::getSenderIP() const +inline U32 LLMessageSystem::getSenderIP() const { return mLastSender.getAddress(); } @@ -947,291 +895,9 @@ inline U32 LLMessageSystem::getSenderPort() const return mLastSender.getPort(); } -inline void LLMessageSystem::addS8Fast(const char *varname, S8 s) -{ - addDataFast(varname, &s, MVT_S8, sizeof(s)); -} - -inline void LLMessageSystem::addS8(const char *varname, S8 s) -{ - addDataFast(gMessageStringTable.getString(varname), &s, MVT_S8, sizeof(s)); -} - -inline void LLMessageSystem::addU8Fast(const char *varname, U8 u) -{ - addDataFast(varname, &u, MVT_U8, sizeof(u)); -} - -inline void LLMessageSystem::addU8(const char *varname, U8 u) -{ - addDataFast(gMessageStringTable.getString(varname), &u, MVT_U8, sizeof(u)); -} - -inline void LLMessageSystem::addS16Fast(const char *varname, S16 i) -{ - addDataFast(varname, &i, MVT_S16, sizeof(i)); -} - -inline void LLMessageSystem::addS16(const char *varname, S16 i) -{ - addDataFast(gMessageStringTable.getString(varname), &i, MVT_S16, sizeof(i)); -} - -inline void LLMessageSystem::addU16Fast(const char *varname, U16 i) -{ - addDataFast(varname, &i, MVT_U16, sizeof(i)); -} - -inline void LLMessageSystem::addU16(const char *varname, U16 i) -{ - addDataFast(gMessageStringTable.getString(varname), &i, MVT_U16, sizeof(i)); -} - -inline void LLMessageSystem::addF32Fast(const char *varname, F32 f) -{ - addDataFast(varname, &f, MVT_F32, sizeof(f)); -} - -inline void LLMessageSystem::addF32(const char *varname, F32 f) -{ - addDataFast(gMessageStringTable.getString(varname), &f, MVT_F32, sizeof(f)); -} - -inline void LLMessageSystem::addS32Fast(const char *varname, S32 s) -{ - addDataFast(varname, &s, MVT_S32, sizeof(s)); -} - -inline void LLMessageSystem::addS32(const char *varname, S32 s) -{ - addDataFast(gMessageStringTable.getString(varname), &s, MVT_S32, sizeof(s)); -} - -inline void LLMessageSystem::addU32Fast(const char *varname, U32 u) -{ - addDataFast(varname, &u, MVT_U32, sizeof(u)); -} - -inline void LLMessageSystem::addU32(const char *varname, U32 u) -{ - addDataFast(gMessageStringTable.getString(varname), &u, MVT_U32, sizeof(u)); -} - -inline void LLMessageSystem::addU64Fast(const char *varname, U64 lu) -{ - addDataFast(varname, &lu, MVT_U64, sizeof(lu)); -} - -inline void LLMessageSystem::addU64(const char *varname, U64 lu) -{ - addDataFast(gMessageStringTable.getString(varname), &lu, MVT_U64, sizeof(lu)); -} - -inline void LLMessageSystem::addF64Fast(const char *varname, F64 d) -{ - addDataFast(varname, &d, MVT_F64, sizeof(d)); -} - -inline void LLMessageSystem::addF64(const char *varname, F64 d) -{ - addDataFast(gMessageStringTable.getString(varname), &d, MVT_F64, sizeof(d)); -} - -inline void LLMessageSystem::addIPAddrFast(const char *varname, U32 u) -{ - addDataFast(varname, &u, MVT_IP_ADDR, sizeof(u)); -} - -inline void LLMessageSystem::addIPAddr(const char *varname, U32 u) -{ - addDataFast(gMessageStringTable.getString(varname), &u, MVT_IP_ADDR, sizeof(u)); -} - -inline void LLMessageSystem::addIPPortFast(const char *varname, U16 u) -{ - u = htons(u); - addDataFast(varname, &u, MVT_IP_PORT, sizeof(u)); -} - -inline void LLMessageSystem::addIPPort(const char *varname, U16 u) -{ - u = htons(u); - addDataFast(gMessageStringTable.getString(varname), &u, MVT_IP_PORT, sizeof(u)); -} - -inline void LLMessageSystem::addBOOLFast(const char* varname, BOOL b) -{ - // Can't just cast a BOOL (actually a U32) to a U8. - // In some cases the low order bits will be zero. - U8 temp = (b != 0); - addDataFast(varname, &temp, MVT_BOOL, sizeof(temp)); -} - -inline void LLMessageSystem::addBOOL(const char* varname, BOOL b) -{ - // Can't just cast a BOOL (actually a U32) to a U8. - // In some cases the low order bits will be zero. - U8 temp = (b != 0); - addDataFast(gMessageStringTable.getString(varname), &temp, MVT_BOOL, sizeof(temp)); -} - -inline void LLMessageSystem::addStringFast(const char* varname, const char* s) -{ - if (s) - addDataFast( varname, (void *)s, MVT_VARIABLE, (S32)strlen(s) + 1); /* Flawfinder: ignore */ - else - addDataFast( varname, NULL, MVT_VARIABLE, 0); -} - -inline void LLMessageSystem::addString(const char* varname, const char* s) -{ - if (s) - addDataFast( gMessageStringTable.getString(varname), (void *)s, MVT_VARIABLE, (S32)strlen(s) + 1); /* Flawfinder: ignore */ - else - addDataFast( gMessageStringTable.getString(varname), NULL, MVT_VARIABLE, 0); -} - -inline void LLMessageSystem::addStringFast(const char* varname, const std::string& s) -{ - if (s.size()) - addDataFast( varname, (void *)s.c_str(), MVT_VARIABLE, (S32)(s.size()) + 1); - else - addDataFast( varname, NULL, MVT_VARIABLE, 0); -} - -inline void LLMessageSystem::addString(const char* varname, const std::string& s) -{ - if (s.size()) - addDataFast( gMessageStringTable.getString(varname), (void *)s.c_str(), MVT_VARIABLE, (S32)(s.size()) + 1); - else - addDataFast( gMessageStringTable.getString(varname), NULL, MVT_VARIABLE, 0); -} - - //----------------------------------------------------------------------------- -// Retrieval aliases +// Transmission aliases //----------------------------------------------------------------------------- -inline void LLMessageSystem::getS8Fast(const char *block, const char *var, S8 &u, S32 blocknum) -{ - getDataFast(block, var, &u, sizeof(S8), blocknum); -} - -inline void LLMessageSystem::getS8(const char *block, const char *var, S8 &u, S32 blocknum) -{ - getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &u, sizeof(S8), blocknum); -} - -inline void LLMessageSystem::getU8Fast(const char *block, const char *var, U8 &u, S32 blocknum) -{ - getDataFast(block, var, &u, sizeof(U8), blocknum); -} - -inline void LLMessageSystem::getU8(const char *block, const char *var, U8 &u, S32 blocknum) -{ - getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &u, sizeof(U8), blocknum); -} - -inline void LLMessageSystem::getBOOLFast(const char *block, const char *var, BOOL &b, S32 blocknum ) -{ - U8 value; - getDataFast(block, var, &value, sizeof(U8), blocknum); - b = (BOOL) value; -} - -inline void LLMessageSystem::getBOOL(const char *block, const char *var, BOOL &b, S32 blocknum ) -{ - U8 value; - getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &value, sizeof(U8), blocknum); - b = (BOOL) value; -} - -inline void LLMessageSystem::getS16Fast(const char *block, const char *var, S16 &d, S32 blocknum) -{ - getDataFast(block, var, &d, sizeof(S16), blocknum); -} - -inline void LLMessageSystem::getS16(const char *block, const char *var, S16 &d, S32 blocknum) -{ - getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(S16), blocknum); -} - -inline void LLMessageSystem::getU16Fast(const char *block, const char *var, U16 &d, S32 blocknum) -{ - getDataFast(block, var, &d, sizeof(U16), blocknum); -} - -inline void LLMessageSystem::getU16(const char *block, const char *var, U16 &d, S32 blocknum) -{ - getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(U16), blocknum); -} - -inline void LLMessageSystem::getS32Fast(const char *block, const char *var, S32 &d, S32 blocknum) -{ - getDataFast(block, var, &d, sizeof(S32), blocknum); -} - -inline void LLMessageSystem::getS32(const char *block, const char *var, S32 &d, S32 blocknum) -{ - getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(S32), blocknum); -} - -inline void LLMessageSystem::getU32Fast(const char *block, const char *var, U32 &d, S32 blocknum) -{ - getDataFast(block, var, &d, sizeof(U32), blocknum); -} - -inline void LLMessageSystem::getU32(const char *block, const char *var, U32 &d, S32 blocknum) -{ - getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(U32), blocknum); -} - -inline void LLMessageSystem::getU64Fast(const char *block, const char *var, U64 &d, S32 blocknum) -{ - getDataFast(block, var, &d, sizeof(U64), blocknum); -} - -inline void LLMessageSystem::getU64(const char *block, const char *var, U64 &d, S32 blocknum) -{ - getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(U64), blocknum); -} - - -inline void LLMessageSystem::getIPAddrFast(const char *block, const char *var, U32 &u, S32 blocknum) -{ - getDataFast(block, var, &u, sizeof(U32), blocknum); -} - -inline void LLMessageSystem::getIPAddr(const char *block, const char *var, U32 &u, S32 blocknum) -{ - getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &u, sizeof(U32), blocknum); -} - -inline void LLMessageSystem::getIPPortFast(const char *block, const char *var, U16 &u, S32 blocknum) -{ - getDataFast(block, var, &u, sizeof(U16), blocknum); - u = ntohs(u); -} - -inline void LLMessageSystem::getIPPort(const char *block, const char *var, U16 &u, S32 blocknum) -{ - getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &u, sizeof(U16), blocknum); - u = ntohs(u); -} - - -inline void LLMessageSystem::getStringFast(const char *block, const char *var, S32 buffer_size, char *s, S32 blocknum ) -{ - s[0] = '\0'; - getDataFast(block, var, s, 0, blocknum, buffer_size); - s[buffer_size - 1] = '\0'; -} - -inline void LLMessageSystem::getString(const char *block, const char *var, S32 buffer_size, char *s, S32 blocknum ) -{ - s[0] = '\0'; - getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), s, 0, blocknum, buffer_size); - s[buffer_size - 1] = '\0'; -} inline S32 LLMessageSystem::sendMessage(const U32 circuit) { diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp index c2d7c9c2a3..9d7e603690 100644 --- a/indra/llmessage/message_prehash.cpp +++ b/indra/llmessage/message_prehash.cpp @@ -20,7 +20,6 @@ char * _PREHASH_X; char * _PREHASH_Y; char * _PREHASH_Z; char * _PREHASH_AddFlags; -char * _PREHASH_ReservedNewbie; char * _PREHASH_FailureInfo; char * _PREHASH_MapData; char * _PREHASH_AddItem; @@ -89,7 +88,6 @@ char * _PREHASH_RelatedRights; char * _PREHASH_RedirectGridX; char * _PREHASH_RedirectGridY; char * _PREHASH_TransferID; -char * _PREHASH_Transacted; char * _PREHASH_TexturesChanged; char * _PREHASH_UserLookAt; char * _PREHASH_TestBlock1; @@ -116,7 +114,6 @@ char * _PREHASH_SetSimStatusInDatabase; char * _PREHASH_SetSimPresenceInDatabase; char * _PREHASH_CameraProperty; char * _PREHASH_BrushSize; -char * _PREHASH_StartExpungeProcess; char * _PREHASH_SimulatorSetMap; char * _PREHASH_RegionPresenceRequestByRegionID; char * _PREHASH_ParcelObjectOwnersReply; @@ -210,8 +207,8 @@ char * _PREHASH_SimName; char * _PREHASH_UserReport; char * _PREHASH_DownloadPriority; char * _PREHASH_ToAgentId; -char * _PREHASH_Mag; char * _PREHASH_DirPopularQuery; +char * _PREHASH_Mag; char * _PREHASH_ParcelPropertiesRequestByID; char * _PREHASH_ObjectLink; char * _PREHASH_RpcScriptReplyInbound; @@ -420,7 +417,6 @@ char * _PREHASH_TerminateFriendship; char * _PREHASH_TaskData; char * _PREHASH_SimWideMaxPrims; char * _PREHASH_TotalPrims; -char * _PREHASH_SourceFilename; char * _PREHASH_ProfileBegin; char * _PREHASH_MoneyDetailsRequest; char * _PREHASH_Request; @@ -467,7 +463,6 @@ char * _PREHASH_ParamInUse; char * _PREHASH_GodKickUser; char * _PREHASH_PickName; char * _PREHASH_TaskName; -char * _PREHASH_ParcelGodReserveForNewbie; char * _PREHASH_SubType; char * _PREHASH_ObjectCount; char * _PREHASH_RegionPresenceRequestByHandle; @@ -486,10 +481,13 @@ char * _PREHASH_UpdateParcel; char * _PREHASH_ClearAgentSessions; char * _PREHASH_SetAlwaysRun; char * _PREHASH_NVPair; +char * _PREHASH_SearchType; char * _PREHASH_ObjectSpinStart; char * _PREHASH_UseEstateSun; char * _PREHASH_LogoutBlock; +char * _PREHASH_RelayLogControl; char * _PREHASH_RegionID; +char * _PREHASH_AbuseRegionID; char * _PREHASH_Creator; char * _PREHASH_ProposalText; char * _PREHASH_DirEventsReply; @@ -534,7 +532,6 @@ char * _PREHASH_MaxY; char * _PREHASH_TextureAnim; char * _PREHASH_ReturnIDs; char * _PREHASH_Date; -char * _PREHASH_GestureUpdate; char * _PREHASH_AgentWearablesUpdate; char * _PREHASH_AgentDataUpdate; char * _PREHASH_Hash; @@ -556,7 +553,6 @@ char * _PREHASH_HistoryItemData; char * _PREHASH_AgentCachedTexture; char * _PREHASH_Subject; char * _PREHASH_East; -char * _PREHASH_GodExpungeUser; char * _PREHASH_QueryReplies; char * _PREHASH_ObjectCategory; char * _PREHASH_Time; @@ -783,6 +779,7 @@ char * _PREHASH_UnsubscribeLoad; char * _PREHASH_Packet; char * _PREHASH_UndoLand; char * _PREHASH_SimAccess; +char * _PREHASH_AbuserID; char * _PREHASH_MembershipFee; char * _PREHASH_InviteGroupResponse; char * _PREHASH_CreateInventoryFolder; @@ -920,6 +917,7 @@ char * _PREHASH_ImageNotInDatabase; char * _PREHASH_StartDate; char * _PREHASH_AnimID; char * _PREHASH_Serial; +char * _PREHASH_AbuseRegionName; char * _PREHASH_ControlPort; char * _PREHASH_ModifyLand; char * _PREHASH_Digest; @@ -984,11 +982,11 @@ char * _PREHASH_EventFlags; char * _PREHASH_TallyVotes; char * _PREHASH_Result; char * _PREHASH_LookAt; +char * _PREHASH_SearchOrder; char * _PREHASH_PayButton; char * _PREHASH_SelfCount; char * _PREHASH_PacketCount; char * _PREHASH_ParcelBuyPass; -char * _PREHASH_Identified; char * _PREHASH_OldItemID; char * _PREHASH_RegionPort; char * _PREHASH_PriceEnergyUnit; @@ -1024,7 +1022,6 @@ char * _PREHASH_EconomyDataRequest; char * _PREHASH_TeleportLureRequest; char * _PREHASH_FolderID; char * _PREHASH_RegionHandleRequest; -char * _PREHASH_GestureRequest; char * _PREHASH_ScriptDataRequest; char * _PREHASH_GroupRoleDataRequest; char * _PREHASH_GroupTitlesRequest; @@ -1168,11 +1165,9 @@ char * _PREHASH_Ratio; char * _PREHASH_JoinGroupReply; char * _PREHASH_LiveHelpGroupReply; char * _PREHASH_Score; -char * _PREHASH_ExpungeData; char * _PREHASH_Image; char * _PREHASH_ObjectClickAction; char * _PREHASH_Delta; -char * _PREHASH_InitiateUpload; char * _PREHASH_Parameter; char * _PREHASH_Flags; char * _PREHASH_Plane; @@ -1208,7 +1203,6 @@ char * _PREHASH_Disconnect; char * _PREHASH_SimPosition; char * _PREHASH_SimWideTotalPrims; char * _PREHASH_Index; -char * _PREHASH_BaseFilename; char * _PREHASH_SimFilename; char * _PREHASH_LastOwnerID; char * _PREHASH_GroupNoticeRequest; @@ -1293,6 +1287,7 @@ char * _PREHASH_AssetBlock; char * _PREHASH_AcceptNotices; char * _PREHASH_SetGroupAcceptNotices; char * _PREHASH_CloseCircuit; +char * _PREHASH_LogControl; char * _PREHASH_TeleportFinish; char * _PREHASH_PathRevolutions; char * _PREHASH_ClassifiedInfoReply; @@ -1472,7 +1467,6 @@ char * _PREHASH_DirLandReply; char * _PREHASH_SpaceLocationTeleportReply; char * _PREHASH_MuteType; char * _PREHASH_IMViaEMail; -char * _PREHASH_StartExpungeProcessAck; char * _PREHASH_RentPrice; char * _PREHASH_GenericMessage; char * _PREHASH_ChildAgentAlive; @@ -1492,7 +1486,6 @@ void init_prehash_data() _PREHASH_Y = gMessageStringTable.getString("Y"); _PREHASH_Z = gMessageStringTable.getString("Z"); _PREHASH_AddFlags = gMessageStringTable.getString("AddFlags"); - _PREHASH_ReservedNewbie = gMessageStringTable.getString("ReservedNewbie"); _PREHASH_FailureInfo = gMessageStringTable.getString("FailureInfo"); _PREHASH_MapData = gMessageStringTable.getString("MapData"); _PREHASH_AddItem = gMessageStringTable.getString("AddItem"); @@ -1561,7 +1554,6 @@ void init_prehash_data() _PREHASH_RedirectGridX = gMessageStringTable.getString("RedirectGridX"); _PREHASH_RedirectGridY = gMessageStringTable.getString("RedirectGridY"); _PREHASH_TransferID = gMessageStringTable.getString("TransferID"); - _PREHASH_Transacted = gMessageStringTable.getString("Transacted"); _PREHASH_TexturesChanged = gMessageStringTable.getString("TexturesChanged"); _PREHASH_UserLookAt = gMessageStringTable.getString("UserLookAt"); _PREHASH_TestBlock1 = gMessageStringTable.getString("TestBlock1"); @@ -1588,7 +1580,6 @@ void init_prehash_data() _PREHASH_SetSimPresenceInDatabase = gMessageStringTable.getString("SetSimPresenceInDatabase"); _PREHASH_CameraProperty = gMessageStringTable.getString("CameraProperty"); _PREHASH_BrushSize = gMessageStringTable.getString("BrushSize"); - _PREHASH_StartExpungeProcess = gMessageStringTable.getString("StartExpungeProcess"); _PREHASH_SimulatorSetMap = gMessageStringTable.getString("SimulatorSetMap"); _PREHASH_RegionPresenceRequestByRegionID = gMessageStringTable.getString("RegionPresenceRequestByRegionID"); _PREHASH_ParcelObjectOwnersReply = gMessageStringTable.getString("ParcelObjectOwnersReply"); @@ -1682,8 +1673,8 @@ void init_prehash_data() _PREHASH_UserReport = gMessageStringTable.getString("UserReport"); _PREHASH_DownloadPriority = gMessageStringTable.getString("DownloadPriority"); _PREHASH_ToAgentId = gMessageStringTable.getString("ToAgentId"); - _PREHASH_Mag = gMessageStringTable.getString("Mag"); _PREHASH_DirPopularQuery = gMessageStringTable.getString("DirPopularQuery"); + _PREHASH_Mag = gMessageStringTable.getString("Mag"); _PREHASH_ParcelPropertiesRequestByID = gMessageStringTable.getString("ParcelPropertiesRequestByID"); _PREHASH_ObjectLink = gMessageStringTable.getString("ObjectLink"); _PREHASH_RpcScriptReplyInbound = gMessageStringTable.getString("RpcScriptReplyInbound"); @@ -1892,7 +1883,6 @@ void init_prehash_data() _PREHASH_TaskData = gMessageStringTable.getString("TaskData"); _PREHASH_SimWideMaxPrims = gMessageStringTable.getString("SimWideMaxPrims"); _PREHASH_TotalPrims = gMessageStringTable.getString("TotalPrims"); - _PREHASH_SourceFilename = gMessageStringTable.getString("SourceFilename"); _PREHASH_ProfileBegin = gMessageStringTable.getString("ProfileBegin"); _PREHASH_MoneyDetailsRequest = gMessageStringTable.getString("MoneyDetailsRequest"); _PREHASH_Request = gMessageStringTable.getString("Request"); @@ -1939,7 +1929,6 @@ void init_prehash_data() _PREHASH_GodKickUser = gMessageStringTable.getString("GodKickUser"); _PREHASH_PickName = gMessageStringTable.getString("PickName"); _PREHASH_TaskName = gMessageStringTable.getString("TaskName"); - _PREHASH_ParcelGodReserveForNewbie = gMessageStringTable.getString("ParcelGodReserveForNewbie"); _PREHASH_SubType = gMessageStringTable.getString("SubType"); _PREHASH_ObjectCount = gMessageStringTable.getString("ObjectCount"); _PREHASH_RegionPresenceRequestByHandle = gMessageStringTable.getString("RegionPresenceRequestByHandle"); @@ -1958,10 +1947,13 @@ void init_prehash_data() _PREHASH_ClearAgentSessions = gMessageStringTable.getString("ClearAgentSessions"); _PREHASH_SetAlwaysRun = gMessageStringTable.getString("SetAlwaysRun"); _PREHASH_NVPair = gMessageStringTable.getString("NVPair"); + _PREHASH_SearchType = gMessageStringTable.getString("SearchType"); _PREHASH_ObjectSpinStart = gMessageStringTable.getString("ObjectSpinStart"); _PREHASH_UseEstateSun = gMessageStringTable.getString("UseEstateSun"); _PREHASH_LogoutBlock = gMessageStringTable.getString("LogoutBlock"); + _PREHASH_RelayLogControl = gMessageStringTable.getString("RelayLogControl"); _PREHASH_RegionID = gMessageStringTable.getString("RegionID"); + _PREHASH_AbuseRegionID = gMessageStringTable.getString("AbuseRegionID"); _PREHASH_Creator = gMessageStringTable.getString("Creator"); _PREHASH_ProposalText = gMessageStringTable.getString("ProposalText"); _PREHASH_DirEventsReply = gMessageStringTable.getString("DirEventsReply"); @@ -2006,7 +1998,6 @@ void init_prehash_data() _PREHASH_TextureAnim = gMessageStringTable.getString("TextureAnim"); _PREHASH_ReturnIDs = gMessageStringTable.getString("ReturnIDs"); _PREHASH_Date = gMessageStringTable.getString("Date"); - _PREHASH_GestureUpdate = gMessageStringTable.getString("GestureUpdate"); _PREHASH_AgentWearablesUpdate = gMessageStringTable.getString("AgentWearablesUpdate"); _PREHASH_AgentDataUpdate = gMessageStringTable.getString("AgentDataUpdate"); _PREHASH_Hash = gMessageStringTable.getString("Hash"); @@ -2028,7 +2019,6 @@ void init_prehash_data() _PREHASH_AgentCachedTexture = gMessageStringTable.getString("AgentCachedTexture"); _PREHASH_Subject = gMessageStringTable.getString("Subject"); _PREHASH_East = gMessageStringTable.getString("East"); - _PREHASH_GodExpungeUser = gMessageStringTable.getString("GodExpungeUser"); _PREHASH_QueryReplies = gMessageStringTable.getString("QueryReplies"); _PREHASH_ObjectCategory = gMessageStringTable.getString("ObjectCategory"); _PREHASH_Time = gMessageStringTable.getString("Time"); @@ -2255,6 +2245,7 @@ void init_prehash_data() _PREHASH_Packet = gMessageStringTable.getString("Packet"); _PREHASH_UndoLand = gMessageStringTable.getString("UndoLand"); _PREHASH_SimAccess = gMessageStringTable.getString("SimAccess"); + _PREHASH_AbuserID = gMessageStringTable.getString("AbuserID"); _PREHASH_MembershipFee = gMessageStringTable.getString("MembershipFee"); _PREHASH_InviteGroupResponse = gMessageStringTable.getString("InviteGroupResponse"); _PREHASH_CreateInventoryFolder = gMessageStringTable.getString("CreateInventoryFolder"); @@ -2392,6 +2383,7 @@ void init_prehash_data() _PREHASH_StartDate = gMessageStringTable.getString("StartDate"); _PREHASH_AnimID = gMessageStringTable.getString("AnimID"); _PREHASH_Serial = gMessageStringTable.getString("Serial"); + _PREHASH_AbuseRegionName = gMessageStringTable.getString("AbuseRegionName"); _PREHASH_ControlPort = gMessageStringTable.getString("ControlPort"); _PREHASH_ModifyLand = gMessageStringTable.getString("ModifyLand"); _PREHASH_Digest = gMessageStringTable.getString("Digest"); @@ -2456,11 +2448,11 @@ void init_prehash_data() _PREHASH_TallyVotes = gMessageStringTable.getString("TallyVotes"); _PREHASH_Result = gMessageStringTable.getString("Result"); _PREHASH_LookAt = gMessageStringTable.getString("LookAt"); + _PREHASH_SearchOrder = gMessageStringTable.getString("SearchOrder"); _PREHASH_PayButton = gMessageStringTable.getString("PayButton"); _PREHASH_SelfCount = gMessageStringTable.getString("SelfCount"); _PREHASH_PacketCount = gMessageStringTable.getString("PacketCount"); _PREHASH_ParcelBuyPass = gMessageStringTable.getString("ParcelBuyPass"); - _PREHASH_Identified = gMessageStringTable.getString("Identified"); _PREHASH_OldItemID = gMessageStringTable.getString("OldItemID"); _PREHASH_RegionPort = gMessageStringTable.getString("RegionPort"); _PREHASH_PriceEnergyUnit = gMessageStringTable.getString("PriceEnergyUnit"); @@ -2496,7 +2488,6 @@ void init_prehash_data() _PREHASH_TeleportLureRequest = gMessageStringTable.getString("TeleportLureRequest"); _PREHASH_FolderID = gMessageStringTable.getString("FolderID"); _PREHASH_RegionHandleRequest = gMessageStringTable.getString("RegionHandleRequest"); - _PREHASH_GestureRequest = gMessageStringTable.getString("GestureRequest"); _PREHASH_ScriptDataRequest = gMessageStringTable.getString("ScriptDataRequest"); _PREHASH_GroupRoleDataRequest = gMessageStringTable.getString("GroupRoleDataRequest"); _PREHASH_GroupTitlesRequest = gMessageStringTable.getString("GroupTitlesRequest"); @@ -2640,11 +2631,9 @@ void init_prehash_data() _PREHASH_JoinGroupReply = gMessageStringTable.getString("JoinGroupReply"); _PREHASH_LiveHelpGroupReply = gMessageStringTable.getString("LiveHelpGroupReply"); _PREHASH_Score = gMessageStringTable.getString("Score"); - _PREHASH_ExpungeData = gMessageStringTable.getString("ExpungeData"); _PREHASH_Image = gMessageStringTable.getString("Image"); _PREHASH_ObjectClickAction = gMessageStringTable.getString("ObjectClickAction"); _PREHASH_Delta = gMessageStringTable.getString("Delta"); - _PREHASH_InitiateUpload = gMessageStringTable.getString("InitiateUpload"); _PREHASH_Parameter = gMessageStringTable.getString("Parameter"); _PREHASH_Flags = gMessageStringTable.getString("Flags"); _PREHASH_Plane = gMessageStringTable.getString("Plane"); @@ -2680,7 +2669,6 @@ void init_prehash_data() _PREHASH_SimPosition = gMessageStringTable.getString("SimPosition"); _PREHASH_SimWideTotalPrims = gMessageStringTable.getString("SimWideTotalPrims"); _PREHASH_Index = gMessageStringTable.getString("Index"); - _PREHASH_BaseFilename = gMessageStringTable.getString("BaseFilename"); _PREHASH_SimFilename = gMessageStringTable.getString("SimFilename"); _PREHASH_LastOwnerID = gMessageStringTable.getString("LastOwnerID"); _PREHASH_GroupNoticeRequest = gMessageStringTable.getString("GroupNoticeRequest"); @@ -2765,6 +2753,7 @@ void init_prehash_data() _PREHASH_AcceptNotices = gMessageStringTable.getString("AcceptNotices"); _PREHASH_SetGroupAcceptNotices = gMessageStringTable.getString("SetGroupAcceptNotices"); _PREHASH_CloseCircuit = gMessageStringTable.getString("CloseCircuit"); + _PREHASH_LogControl = gMessageStringTable.getString("LogControl"); _PREHASH_TeleportFinish = gMessageStringTable.getString("TeleportFinish"); _PREHASH_PathRevolutions = gMessageStringTable.getString("PathRevolutions"); _PREHASH_ClassifiedInfoReply = gMessageStringTable.getString("ClassifiedInfoReply"); @@ -2944,7 +2933,6 @@ void init_prehash_data() _PREHASH_SpaceLocationTeleportReply = gMessageStringTable.getString("SpaceLocationTeleportReply"); _PREHASH_MuteType = gMessageStringTable.getString("MuteType"); _PREHASH_IMViaEMail = gMessageStringTable.getString("IMViaEMail"); - _PREHASH_StartExpungeProcessAck = gMessageStringTable.getString("StartExpungeProcessAck"); _PREHASH_RentPrice = gMessageStringTable.getString("RentPrice"); _PREHASH_GenericMessage = gMessageStringTable.getString("GenericMessage"); _PREHASH_ChildAgentAlive = gMessageStringTable.getString("ChildAgentAlive"); diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h index 63e23237f5..19b9881dde 100644 --- a/indra/llmessage/message_prehash.h +++ b/indra/llmessage/message_prehash.h @@ -20,7 +20,6 @@ extern char * _PREHASH_X; extern char * _PREHASH_Y; extern char * _PREHASH_Z; extern char * _PREHASH_AddFlags; -extern char * _PREHASH_ReservedNewbie; extern char * _PREHASH_FailureInfo; extern char * _PREHASH_MapData; extern char * _PREHASH_AddItem; @@ -89,7 +88,6 @@ extern char * _PREHASH_RelatedRights; extern char * _PREHASH_RedirectGridX; extern char * _PREHASH_RedirectGridY; extern char * _PREHASH_TransferID; -extern char * _PREHASH_Transacted; extern char * _PREHASH_TexturesChanged; extern char * _PREHASH_UserLookAt; extern char * _PREHASH_TestBlock1; @@ -116,7 +114,6 @@ extern char * _PREHASH_SetSimStatusInDatabase; extern char * _PREHASH_SetSimPresenceInDatabase; extern char * _PREHASH_CameraProperty; extern char * _PREHASH_BrushSize; -extern char * _PREHASH_StartExpungeProcess; extern char * _PREHASH_SimulatorSetMap; extern char * _PREHASH_RegionPresenceRequestByRegionID; extern char * _PREHASH_ParcelObjectOwnersReply; @@ -210,8 +207,8 @@ extern char * _PREHASH_SimName; extern char * _PREHASH_UserReport; extern char * _PREHASH_DownloadPriority; extern char * _PREHASH_ToAgentId; -extern char * _PREHASH_Mag; extern char * _PREHASH_DirPopularQuery; +extern char * _PREHASH_Mag; extern char * _PREHASH_ParcelPropertiesRequestByID; extern char * _PREHASH_ObjectLink; extern char * _PREHASH_RpcScriptReplyInbound; @@ -420,7 +417,6 @@ extern char * _PREHASH_TerminateFriendship; extern char * _PREHASH_TaskData; extern char * _PREHASH_SimWideMaxPrims; extern char * _PREHASH_TotalPrims; -extern char * _PREHASH_SourceFilename; extern char * _PREHASH_ProfileBegin; extern char * _PREHASH_MoneyDetailsRequest; extern char * _PREHASH_Request; @@ -467,7 +463,6 @@ extern char * _PREHASH_ParamInUse; extern char * _PREHASH_GodKickUser; extern char * _PREHASH_PickName; extern char * _PREHASH_TaskName; -extern char * _PREHASH_ParcelGodReserveForNewbie; extern char * _PREHASH_SubType; extern char * _PREHASH_ObjectCount; extern char * _PREHASH_RegionPresenceRequestByHandle; @@ -486,10 +481,13 @@ extern char * _PREHASH_UpdateParcel; extern char * _PREHASH_ClearAgentSessions; extern char * _PREHASH_SetAlwaysRun; extern char * _PREHASH_NVPair; +extern char * _PREHASH_SearchType; extern char * _PREHASH_ObjectSpinStart; extern char * _PREHASH_UseEstateSun; extern char * _PREHASH_LogoutBlock; +extern char * _PREHASH_RelayLogControl; extern char * _PREHASH_RegionID; +extern char * _PREHASH_AbuseRegionID; extern char * _PREHASH_Creator; extern char * _PREHASH_ProposalText; extern char * _PREHASH_DirEventsReply; @@ -534,7 +532,6 @@ extern char * _PREHASH_MaxY; extern char * _PREHASH_TextureAnim; extern char * _PREHASH_ReturnIDs; extern char * _PREHASH_Date; -extern char * _PREHASH_GestureUpdate; extern char * _PREHASH_AgentWearablesUpdate; extern char * _PREHASH_AgentDataUpdate; extern char * _PREHASH_Hash; @@ -556,7 +553,6 @@ extern char * _PREHASH_HistoryItemData; extern char * _PREHASH_AgentCachedTexture; extern char * _PREHASH_Subject; extern char * _PREHASH_East; -extern char * _PREHASH_GodExpungeUser; extern char * _PREHASH_QueryReplies; extern char * _PREHASH_ObjectCategory; extern char * _PREHASH_Time; @@ -783,6 +779,7 @@ extern char * _PREHASH_UnsubscribeLoad; extern char * _PREHASH_Packet; extern char * _PREHASH_UndoLand; extern char * _PREHASH_SimAccess; +extern char * _PREHASH_AbuserID; extern char * _PREHASH_MembershipFee; extern char * _PREHASH_InviteGroupResponse; extern char * _PREHASH_CreateInventoryFolder; @@ -920,6 +917,7 @@ extern char * _PREHASH_ImageNotInDatabase; extern char * _PREHASH_StartDate; extern char * _PREHASH_AnimID; extern char * _PREHASH_Serial; +extern char * _PREHASH_AbuseRegionName; extern char * _PREHASH_ControlPort; extern char * _PREHASH_ModifyLand; extern char * _PREHASH_Digest; @@ -984,11 +982,11 @@ extern char * _PREHASH_EventFlags; extern char * _PREHASH_TallyVotes; extern char * _PREHASH_Result; extern char * _PREHASH_LookAt; +extern char * _PREHASH_SearchOrder; extern char * _PREHASH_PayButton; extern char * _PREHASH_SelfCount; extern char * _PREHASH_PacketCount; extern char * _PREHASH_ParcelBuyPass; -extern char * _PREHASH_Identified; extern char * _PREHASH_OldItemID; extern char * _PREHASH_RegionPort; extern char * _PREHASH_PriceEnergyUnit; @@ -1024,7 +1022,6 @@ extern char * _PREHASH_EconomyDataRequest; extern char * _PREHASH_TeleportLureRequest; extern char * _PREHASH_FolderID; extern char * _PREHASH_RegionHandleRequest; -extern char * _PREHASH_GestureRequest; extern char * _PREHASH_ScriptDataRequest; extern char * _PREHASH_GroupRoleDataRequest; extern char * _PREHASH_GroupTitlesRequest; @@ -1168,11 +1165,9 @@ extern char * _PREHASH_Ratio; extern char * _PREHASH_JoinGroupReply; extern char * _PREHASH_LiveHelpGroupReply; extern char * _PREHASH_Score; -extern char * _PREHASH_ExpungeData; extern char * _PREHASH_Image; extern char * _PREHASH_ObjectClickAction; extern char * _PREHASH_Delta; -extern char * _PREHASH_InitiateUpload; extern char * _PREHASH_Parameter; extern char * _PREHASH_Flags; extern char * _PREHASH_Plane; @@ -1208,7 +1203,6 @@ extern char * _PREHASH_Disconnect; extern char * _PREHASH_SimPosition; extern char * _PREHASH_SimWideTotalPrims; extern char * _PREHASH_Index; -extern char * _PREHASH_BaseFilename; extern char * _PREHASH_SimFilename; extern char * _PREHASH_LastOwnerID; extern char * _PREHASH_GroupNoticeRequest; @@ -1293,6 +1287,7 @@ extern char * _PREHASH_AssetBlock; extern char * _PREHASH_AcceptNotices; extern char * _PREHASH_SetGroupAcceptNotices; extern char * _PREHASH_CloseCircuit; +extern char * _PREHASH_LogControl; extern char * _PREHASH_TeleportFinish; extern char * _PREHASH_PathRevolutions; extern char * _PREHASH_ClassifiedInfoReply; @@ -1472,7 +1467,6 @@ extern char * _PREHASH_DirLandReply; extern char * _PREHASH_SpaceLocationTeleportReply; extern char * _PREHASH_MuteType; extern char * _PREHASH_IMViaEMail; -extern char * _PREHASH_StartExpungeProcessAck; extern char * _PREHASH_RentPrice; extern char * _PREHASH_GenericMessage; extern char * _PREHASH_ChildAgentAlive; diff --git a/indra/llmessage/net.cpp b/indra/llmessage/net.cpp index a78b216ccb..9e83ce1434 100644 --- a/indra/llmessage/net.cpp +++ b/indra/llmessage/net.cpp @@ -222,6 +222,12 @@ S32 start_net(S32& socket_out, int& nPort) return 4; } } + + sockaddr_in socket_address; + S32 socket_address_size = sizeof(socket_address); + getsockname(hSocket, (SOCKADDR*) &socket_address, &socket_address_size); + attempt_port = ntohs(socket_address.sin_port); + llinfos << "connected on port " << attempt_port << llendl; nPort = attempt_port; diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 366ecc7d6f..fa0b4747e6 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -1260,8 +1260,8 @@ BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys) const U8 image_ids[MAX_TES*16]; U8 colors[MAX_TES*4]; - S16 scale_s[MAX_TES]; - S16 scale_t[MAX_TES]; + F32 scale_s[MAX_TES]; + F32 scale_t[MAX_TES]; S16 offset_s[MAX_TES]; S16 offset_t[MAX_TES]; S16 image_rot[MAX_TES]; @@ -1296,8 +1296,8 @@ BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys) const colors[4*face_index + 3] = 255 - coloru.mV[3]; const LLTextureEntry* te = getTE(face_index); - scale_s[face_index] = (S16) llround(((llclamp(te->mScaleS,-LL_MAX_SCALE_S, LL_MAX_SCALE_S)-1.0f)/(LL_MAX_SCALE_S+1.f) * (F32)0x7FFF)); - scale_t[face_index] = (S16) llround(((llclamp(te->mScaleT,-LL_MAX_SCALE_T, LL_MAX_SCALE_T)-1.0f)/(LL_MAX_SCALE_T+1.f) * (F32)0x7FFF)); + scale_s[face_index] = (F32) te->mScaleS; + scale_t[face_index] = (F32) te->mScaleT; offset_s[face_index] = (S16) llround((llclamp(te->mOffsetS,-1.0f,1.0f) * (F32)0x7FFF)) ; offset_t[face_index] = (S16) llround((llclamp(te->mOffsetT,-1.0f,1.0f) * (F32)0x7FFF)) ; image_rot[face_index] = (S16) llround(((fmod(te->mRotation, F_TWO_PI)/F_TWO_PI) * (F32)0x7FFF)); @@ -1310,9 +1310,9 @@ BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys) const *cur_ptr++ = 0; cur_ptr += packTEField(cur_ptr, (U8 *)colors, 4 ,last_face_index, MVT_U8); *cur_ptr++ = 0; - cur_ptr += packTEField(cur_ptr, (U8 *)scale_s, 2 ,last_face_index, MVT_S16Array); + cur_ptr += packTEField(cur_ptr, (U8 *)scale_s, 4 ,last_face_index, MVT_F32); *cur_ptr++ = 0; - cur_ptr += packTEField(cur_ptr, (U8 *)scale_t, 2 ,last_face_index, MVT_S16Array); + cur_ptr += packTEField(cur_ptr, (U8 *)scale_t, 4 ,last_face_index, MVT_F32); *cur_ptr++ = 0; cur_ptr += packTEField(cur_ptr, (U8 *)offset_s, 2 ,last_face_index, MVT_S16Array); *cur_ptr++ = 0; @@ -1336,8 +1336,8 @@ BOOL LLPrimitive::packTEMessage(LLDataPacker &dp) const U8 image_ids[MAX_TES*16]; U8 colors[MAX_TES*4]; - S16 scale_s[MAX_TES]; - S16 scale_t[MAX_TES]; + F32 scale_s[MAX_TES]; + F32 scale_t[MAX_TES]; S16 offset_s[MAX_TES]; S16 offset_t[MAX_TES]; S16 image_rot[MAX_TES]; @@ -1372,8 +1372,8 @@ BOOL LLPrimitive::packTEMessage(LLDataPacker &dp) const colors[4*face_index + 3] = 255 - coloru.mV[3]; const LLTextureEntry* te = getTE(face_index); - scale_s[face_index] = (S16) llround(((llclamp(te->mScaleS,-LL_MAX_SCALE_S, LL_MAX_SCALE_S)-1.0f)/(LL_MAX_SCALE_S+1.f) * (F32)0x7FFF)); - scale_t[face_index] = (S16) llround(((llclamp(te->mScaleT,-LL_MAX_SCALE_T, LL_MAX_SCALE_T)-1.0f)/(LL_MAX_SCALE_T+1.f) * (F32)0x7FFF)); + scale_s[face_index] = (F32) te->mScaleS; + scale_t[face_index] = (F32) te->mScaleT; offset_s[face_index] = (S16) llround((llclamp(te->mOffsetS,-1.0f,1.0f) * (F32)0x7FFF)) ; offset_t[face_index] = (S16) llround((llclamp(te->mOffsetT,-1.0f,1.0f) * (F32)0x7FFF)) ; image_rot[face_index] = (S16) llround(((fmod(te->mRotation, F_TWO_PI)/F_TWO_PI) * (F32)0x7FFF)); @@ -1387,9 +1387,9 @@ BOOL LLPrimitive::packTEMessage(LLDataPacker &dp) const *cur_ptr++ = 0; cur_ptr += packTEField(cur_ptr, (U8 *)colors, 4 ,last_face_index, MVT_U8); *cur_ptr++ = 0; - cur_ptr += packTEField(cur_ptr, (U8 *)scale_s, 2 ,last_face_index, MVT_S16Array); + cur_ptr += packTEField(cur_ptr, (U8 *)scale_s, 4 ,last_face_index, MVT_F32); *cur_ptr++ = 0; - cur_ptr += packTEField(cur_ptr, (U8 *)scale_t, 2 ,last_face_index, MVT_S16Array); + cur_ptr += packTEField(cur_ptr, (U8 *)scale_t, 4 ,last_face_index, MVT_F32); *cur_ptr++ = 0; cur_ptr += packTEField(cur_ptr, (U8 *)offset_s, 2 ,last_face_index, MVT_S16Array); *cur_ptr++ = 0; @@ -1421,8 +1421,8 @@ S32 LLPrimitive::unpackTEMessage(LLMessageSystem *mesgsys, char *block_name, con U8 image_data[MAX_TES*16]; U8 colors[MAX_TES*4]; - S16 scale_s[MAX_TES]; - S16 scale_t[MAX_TES]; + F32 scale_s[MAX_TES]; + F32 scale_t[MAX_TES]; S16 offset_s[MAX_TES]; S16 offset_t[MAX_TES]; S16 image_rot[MAX_TES]; @@ -1465,9 +1465,9 @@ S32 LLPrimitive::unpackTEMessage(LLMessageSystem *mesgsys, char *block_name, con cur_ptr++; cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)colors, 4, face_count, MVT_U8); cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_s, 2, face_count, MVT_S16Array); + cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_s, 4, face_count, MVT_F32); cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_t, 2, face_count, MVT_S16Array); + cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_t, 4, face_count, MVT_F32); cur_ptr++; cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)offset_s, 2, face_count, MVT_S16Array); cur_ptr++; @@ -1484,9 +1484,7 @@ S32 LLPrimitive::unpackTEMessage(LLMessageSystem *mesgsys, char *block_name, con for (U32 i = 0; i < face_count; i++) { retval |= setTETexture(i, ((LLUUID*)image_data)[i]); - retval |= setTEScale(i, - floor((1.0f + ((((F32)scale_s[i] / (F32)0x7FFF)) * (LL_MAX_SCALE_S+1.f))) * 100.f + 0.5f) / 100.f, - floor((1.0f + ((((F32)scale_t[i] / (F32)0x7FFF)) * (LL_MAX_SCALE_T+1.f))) * 100.f + 0.5f) / 100.f); + retval |= setTEScale(i, scale_s[i], scale_t[i]); retval |= setTEOffset(i, (F32)offset_s[i] / (F32)0x7FFF, (F32) offset_t[i] / (F32) 0x7FFF); retval |= setTERotation(i, ((F32)image_rot[i]/ (F32)0x7FFF) * F_TWO_PI); retval |= setTEBumpShinyFullbright(i, bump[i]); @@ -1518,8 +1516,8 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp) U8 image_data[MAX_TES*16]; U8 colors[MAX_TES*4]; - S16 scale_s[MAX_TES]; - S16 scale_t[MAX_TES]; + F32 scale_s[MAX_TES]; + F32 scale_t[MAX_TES]; S16 offset_s[MAX_TES]; S16 offset_t[MAX_TES]; S16 image_rot[MAX_TES]; @@ -1552,9 +1550,9 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp) cur_ptr++; cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)colors, 4, face_count, MVT_U8); cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_s, 2, face_count, MVT_S16Array); + cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_s, 4, face_count, MVT_F32); cur_ptr++; - cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_t, 2, face_count, MVT_S16Array); + cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_t, 4, face_count, MVT_F32); cur_ptr++; cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)offset_s, 2, face_count, MVT_S16Array); cur_ptr++; @@ -1577,9 +1575,7 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp) for (i = 0; i < face_count; i++) { retval |= setTETexture(i, image_ids[i]); - retval |= setTEScale(i, - floor((1.0f + ((((F32)scale_s[i] / (F32)0x7FFF)) * (LL_MAX_SCALE_S+1.f))) * 100.f + 0.5f) / 100.f, - floor((1.0f + ((((F32)scale_t[i] / (F32)0x7FFF)) * (LL_MAX_SCALE_T+1.f))) * 100.f + 0.5f) / 100.f); + retval |= setTEScale(i, scale_s[i], scale_t[i]); retval |= setTEOffset(i, (F32)offset_s[i] / (F32)0x7FFF, (F32) offset_t[i] / (F32) 0x7FFF); retval |= setTERotation(i, ((F32)image_rot[i]/ (F32)0x7FFF) * F_TWO_PI); retval |= setTEBumpShinyFullbright(i, bump[i]); diff --git a/indra/llprimitive/llvolumemessage.cpp b/indra/llprimitive/llvolumemessage.cpp index a43aa19cab..60c6bae34a 100644 --- a/indra/llprimitive/llvolumemessage.cpp +++ b/indra/llprimitive/llvolumemessage.cpp @@ -23,23 +23,25 @@ bool LLVolumeMessage::packProfileParams( LLMessageSystem *mesgsys) { // Default to cylinder - static LLProfileParams defaultparams(LL_PCODE_PROFILE_CIRCLE, U8(0), U8(0), U8(0)); + static LLProfileParams defaultparams(LL_PCODE_PROFILE_CIRCLE, U16(0), U16(0), U16(0)); if (!params) params = &defaultparams; U8 tempU8; + U16 tempU16; + tempU8 = params->getCurveType(); mesgsys->addU8Fast(_PREHASH_ProfileCurve, tempU8); - tempU8 = (U8) llround( params->getBegin() / CUT_QUANTA); - mesgsys->addU8Fast(_PREHASH_ProfileBegin, tempU8); + tempU16 = (U16) llround( params->getBegin() / CUT_QUANTA); + mesgsys->addU16Fast(_PREHASH_ProfileBegin, tempU16); - tempU8 = 200 - (U8) llround(params->getEnd() / CUT_QUANTA); - mesgsys->addU8Fast(_PREHASH_ProfileEnd, tempU8); + tempU16 = 50000 - (U16) llround(params->getEnd() / CUT_QUANTA); + mesgsys->addU16Fast(_PREHASH_ProfileEnd, tempU16); - tempU8 = (S8) llround(params->getHollow() / SHEAR_QUANTA); - mesgsys->addU8Fast(_PREHASH_ProfileHollow, tempU8); + tempU16 = (U16) llround(params->getHollow() / HOLLOW_QUANTA); + mesgsys->addU16Fast(_PREHASH_ProfileHollow, tempU16); return true; } @@ -49,23 +51,25 @@ bool LLVolumeMessage::packProfileParams( LLDataPacker &dp) { // Default to cylinder - static LLProfileParams defaultparams(LL_PCODE_PROFILE_CIRCLE, U8(0), U8(0), U8(0)); + static LLProfileParams defaultparams(LL_PCODE_PROFILE_CIRCLE, U16(0), U16(0), U16(0)); if (!params) params = &defaultparams; U8 tempU8; + U16 tempU16; + tempU8 = params->getCurveType(); dp.packU8(tempU8, "Curve"); - tempU8 = (U8) llround( params->getBegin() / CUT_QUANTA); - dp.packU8(tempU8, "Begin"); + tempU16 = (U16) llround( params->getBegin() / CUT_QUANTA); + dp.packU16(tempU16, "Begin"); - tempU8 = 200 - (U8) llround(params->getEnd() / CUT_QUANTA); - dp.packU8(tempU8, "End"); + tempU16 = 50000 - (U16) llround(params->getEnd() / CUT_QUANTA); + dp.packU16(tempU16, "End"); - tempU8 = (S8) llround(params->getHollow() / SHEAR_QUANTA); - dp.packU8(tempU8, "Hollow"); + tempU16 = (U16) llround(params->getHollow() / HOLLOW_QUANTA); + dp.packU16(tempU16, "Hollow"); return true; } @@ -77,13 +81,14 @@ bool LLVolumeMessage::unpackProfileParams( { bool ok = true; U8 temp_u8; + U16 temp_u16; F32 temp_f32; mesgsys->getU8Fast(block_name, _PREHASH_ProfileCurve, temp_u8, block_num); params->setCurveType(temp_u8); - mesgsys->getU8Fast(block_name, _PREHASH_ProfileBegin, temp_u8, block_num); - temp_f32 = temp_u8 * CUT_QUANTA; + mesgsys->getU16Fast(block_name, _PREHASH_ProfileBegin, temp_u16, block_num); + temp_f32 = temp_u16 * CUT_QUANTA; if (temp_f32 > 1.f) { llwarns << "Profile begin out of range: " << temp_f32 @@ -93,8 +98,8 @@ bool LLVolumeMessage::unpackProfileParams( } params->setBegin(temp_f32); - mesgsys->getU8Fast(block_name, _PREHASH_ProfileEnd, temp_u8, block_num); - temp_f32 = temp_u8 * CUT_QUANTA; + mesgsys->getU16Fast(block_name, _PREHASH_ProfileEnd, temp_u16, block_num); + temp_f32 = temp_u16 * CUT_QUANTA; if (temp_f32 > 1.f) { llwarns << "Profile end out of range: " << 1.f - temp_f32 @@ -104,8 +109,8 @@ bool LLVolumeMessage::unpackProfileParams( } params->setEnd(1.f - temp_f32); - mesgsys->getU8Fast(block_name, _PREHASH_ProfileHollow, temp_u8, block_num); - temp_f32 = temp_u8 * SCALE_QUANTA; + mesgsys->getU16Fast(block_name, _PREHASH_ProfileHollow, temp_u16, block_num); + temp_f32 = temp_u16 * HOLLOW_QUANTA; if (temp_f32 > 1.f) { llwarns << "Profile hollow out of range: " << temp_f32 @@ -132,13 +137,14 @@ bool LLVolumeMessage::unpackProfileParams( { bool ok = true; U8 temp_u8; + U16 temp_u16; F32 temp_f32; dp.unpackU8(temp_u8, "Curve"); params->setCurveType(temp_u8); - dp.unpackU8(temp_u8, "Begin"); - temp_f32 = temp_u8 * CUT_QUANTA; + dp.unpackU16(temp_u16, "Begin"); + temp_f32 = temp_u16 * CUT_QUANTA; if (temp_f32 > 1.f) { llwarns << "Profile begin out of range: " << temp_f32 << llendl; @@ -148,8 +154,8 @@ bool LLVolumeMessage::unpackProfileParams( } params->setBegin(temp_f32); - dp.unpackU8(temp_u8, "End"); - temp_f32 = temp_u8 * CUT_QUANTA; + dp.unpackU16(temp_u16, "End"); + temp_f32 = temp_u16 * CUT_QUANTA; if (temp_f32 > 1.f) { llwarns << "Profile end out of range: " << 1.f - temp_f32 << llendl; @@ -159,8 +165,8 @@ bool LLVolumeMessage::unpackProfileParams( } params->setEnd(1.f - temp_f32); - dp.unpackU8(temp_u8, "Hollow"); - temp_f32 = temp_u8 * SCALE_QUANTA; + dp.unpackU16(temp_u16, "Hollow"); + temp_f32 = temp_u16 * HOLLOW_QUANTA; if (temp_f32 > 1.f) { llwarns << "Profile hollow out of range: " << temp_f32 << llendl; @@ -193,11 +199,11 @@ bool LLVolumeMessage::packPathParams( U8 curve = params->getCurveType(); mesgsys->addU8Fast(_PREHASH_PathCurve, curve); - U8 begin = (U8) llround(params->getBegin() / SCALE_QUANTA); - mesgsys->addU8Fast(_PREHASH_PathBegin, begin); + U16 begin = (U16) llround(params->getBegin() / CUT_QUANTA); + mesgsys->addU16Fast(_PREHASH_PathBegin, begin); - U8 end = 100 - (U8) llround(params->getEnd() / SCALE_QUANTA); - mesgsys->addU8Fast(_PREHASH_PathEnd, end); + U16 end = 50000 - (U16) llround(params->getEnd() / CUT_QUANTA); + mesgsys->addU16Fast(_PREHASH_PathEnd, end); // Avoid truncation problem with direct F32->U8 cast. // (e.g., (U8) (0.50 / 0.01) = (U8) 49.9999999 = 49 not 50. @@ -250,11 +256,11 @@ bool LLVolumeMessage::packPathParams( U8 curve = params->getCurveType(); dp.packU8(curve, "Curve"); - U8 begin = (U8) llround(params->getBegin() / SCALE_QUANTA); - dp.packU8(begin, "Begin"); + U16 begin = (U16) llround(params->getBegin() / CUT_QUANTA); + dp.packU16(begin, "Begin"); - U8 end = 100 - (U8) llround(params->getEnd() / SCALE_QUANTA); - dp.packU8(end, "End"); + U16 end = 50000 - (U16) llround(params->getEnd() / CUT_QUANTA); + dp.packU16(end, "End"); // Avoid truncation problem with direct F32->U8 cast. // (e.g., (U8) (0.50 / 0.01) = (U8) 49.9999999 = 49 not 50. @@ -305,13 +311,13 @@ bool LLVolumeMessage::unpackPathParams( mesgsys->getU8Fast(block_name, _PREHASH_PathCurve, curve, block_num); params->setCurveType(curve); - U8 begin; - mesgsys->getU8Fast(block_name, _PREHASH_PathBegin, begin, block_num); - params->setBegin((F32)(begin * SCALE_QUANTA)); + U16 begin; + mesgsys->getU16Fast(block_name, _PREHASH_PathBegin, begin, block_num); + params->setBegin((F32)(begin * CUT_QUANTA)); - U8 end; - mesgsys->getU8Fast(block_name, _PREHASH_PathEnd, end, block_num); - params->setEnd((F32)((100 - end) * SCALE_QUANTA)); + U16 end; + mesgsys->getU16Fast(block_name, _PREHASH_PathEnd, end, block_num); + params->setEnd((F32)((50000 - end) * CUT_QUANTA)); U8 pack_scale_x, pack_scale_y; mesgsys->getU8Fast(block_name, _PREHASH_PathScaleX, pack_scale_x, block_num); @@ -371,14 +377,16 @@ bool LLVolumeMessage::unpackPathParams(LLPathParams* params, LLDataPacker &dp) { U8 value; S8 svalue; + U16 temp_u16; + dp.unpackU8(value, "Curve"); params->setCurveType( value ); - dp.unpackU8(value, "Begin"); - params->setBegin((F32)(value * SCALE_QUANTA)); + dp.unpackU16(temp_u16, "Begin"); + params->setBegin((F32)(temp_u16 * CUT_QUANTA)); - dp.unpackU8(value, "End"); - params->setEnd((F32)((100 - value) * SCALE_QUANTA)); + dp.unpackU16(temp_u16, "End"); + params->setEnd((F32)((50000 - temp_u16) * CUT_QUANTA)); dp.unpackU8(value, "ScaleX"); F32 x = (F32) (200 - value) * SCALE_QUANTA; diff --git a/indra/llui/llcheckboxctrl.cpp b/indra/llui/llcheckboxctrl.cpp index fde27132e6..215f6d40ed 100644 --- a/indra/llui/llcheckboxctrl.cpp +++ b/indra/llui/llcheckboxctrl.cpp @@ -156,7 +156,7 @@ void LLCheckBoxCtrl::onCommit() void LLCheckBoxCtrl::setEnabled(BOOL b) { - LLUICtrl::setEnabled(b); + LLView::setEnabled(b); mButton->setEnabled(b); } diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index f13e0d54b9..f548045474 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -102,7 +102,7 @@ LLComboBox::LLComboBox( const LLString& name, const LLRect &rect, const LLString LLUUID arrow_image_id( LLUI::sAssetsGroup->getString("combobox_arrow.tga") ); mArrowImage = LLUI::sImageProvider->getUIImageByID(arrow_image_id); - mArrowImageWidth = llmax(8,mArrowImage->getWidth()); // In case image hasn't loaded yet + mArrowImageWidth = llmax(8,mArrowImage->getWidth(0)); // In case image hasn't loaded yet } @@ -202,7 +202,7 @@ LLView* LLComboBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory * void LLComboBox::setEnabled(BOOL enabled) { - LLUICtrl::setEnabled(enabled); + LLView::setEnabled(enabled); mButton->setEnabled(enabled); } @@ -477,14 +477,15 @@ void LLComboBox::showList() mList->arrange( 192, llfloor((F32)window_size.mY / LLUI::sGLScaleFactor.mV[VY]) - 50 ); // Make sure that we can see the whole list - LLRect floater_area_local; - gFloaterView->localRectToOtherView(gFloaterView->getLocalSnapRect(), &floater_area_local, this); + LLRect root_view_local; + LLView* root_view = getRootView(); + root_view->localRectToOtherView(root_view->getLocalRect(), &root_view_local, this); LLRect rect = mList->getRect(); if (mListPosition == BELOW) { - if (rect.getHeight() <= -floater_area_local.mBottom) + if (rect.getHeight() <= -root_view_local.mBottom) { // Move rect so it hangs off the bottom of this view rect.setLeftTopAndSize(0, 0, rect.getWidth(), rect.getHeight() ); @@ -492,44 +493,44 @@ void LLComboBox::showList() else { // stack on top or bottom, depending on which has more room - if (-floater_area_local.mBottom > floater_area_local.mTop - mRect.getHeight()) + if (-root_view_local.mBottom > root_view_local.mTop - mRect.getHeight()) { // Move rect so it hangs off the bottom of this view - rect.setLeftTopAndSize(0, 0, rect.getWidth(), llmin(-floater_area_local.mBottom, rect.getHeight())); + rect.setLeftTopAndSize(0, 0, rect.getWidth(), llmin(-root_view_local.mBottom, rect.getHeight())); } else { // move rect so it stacks on top of this view (clipped to size of screen) - rect.setOriginAndSize(0, mRect.getHeight(), rect.getWidth(), llmin(floater_area_local.mTop - mRect.getHeight(), rect.getHeight())); + rect.setOriginAndSize(0, mRect.getHeight(), rect.getWidth(), llmin(root_view_local.mTop - mRect.getHeight(), rect.getHeight())); } } } else // ABOVE { - if (rect.getHeight() <= floater_area_local.mTop - mRect.getHeight()) + if (rect.getHeight() <= root_view_local.mTop - mRect.getHeight()) { // move rect so it stacks on top of this view (clipped to size of screen) - rect.setOriginAndSize(0, mRect.getHeight(), rect.getWidth(), llmin(floater_area_local.mTop - mRect.getHeight(), rect.getHeight())); + rect.setOriginAndSize(0, mRect.getHeight(), rect.getWidth(), llmin(root_view_local.mTop - mRect.getHeight(), rect.getHeight())); } else { // stack on top or bottom, depending on which has more room - if (-floater_area_local.mBottom > floater_area_local.mTop - mRect.getHeight()) + if (-root_view_local.mBottom > root_view_local.mTop - mRect.getHeight()) { // Move rect so it hangs off the bottom of this view - rect.setLeftTopAndSize(0, 0, rect.getWidth(), llmin(-floater_area_local.mBottom, rect.getHeight())); + rect.setLeftTopAndSize(0, 0, rect.getWidth(), llmin(-root_view_local.mBottom, rect.getHeight())); } else { // move rect so it stacks on top of this view (clipped to size of screen) - rect.setOriginAndSize(0, mRect.getHeight(), rect.getWidth(), llmin(floater_area_local.mTop - mRect.getHeight(), rect.getHeight())); + rect.setOriginAndSize(0, mRect.getHeight(), rect.getWidth(), llmin(root_view_local.mTop - mRect.getHeight(), rect.getHeight())); } } } mList->setOrigin(rect.mLeft, rect.mBottom); mList->reshape(rect.getWidth(), rect.getHeight()); - mList->translateIntoRect(floater_area_local, FALSE); + mList->translateIntoRect(root_view_local, FALSE); // Make sure we didn't go off bottom of screen S32 x, y; @@ -656,7 +657,8 @@ void LLComboBox::onItemSelected(LLUICtrl* item, void *userdata) void LLComboBox::onListFocusChanged(LLUICtrl* list, void* user_data) { LLComboBox *self = (LLComboBox *) list->getParent(); - if (!list->hasFocus()) + // user not manipulating list or clicking on drop down button + if (!self->mList->hasFocus() && !self->mButton->hasMouseCapture()) { //*HACK: store the original value explicitly somewhere, not just in label LLString orig_selection = self->mAllowTextEntry ? self->mTextEntry->getText() : self->mButton->getLabelSelected(); diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index f442855aca..146052538a 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -405,6 +405,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect, mNumDynamicWidthColumns(0), mTotalStaticColumnWidth(0), mSortColumn(-1), + mSorted(TRUE), mSortAscending(TRUE) { mItemListRect.setOriginAndSize( @@ -623,22 +624,28 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos ) { case ADD_TOP: mItemList.push_front(item); + setSorted(FALSE); break; case ADD_SORTED: - mSortColumn = 0; - mSortAscending = TRUE; + if (mSortColumn == -1) + { + mSortColumn = 0; + mSortAscending = TRUE; + } mItemList.push_back(item); std::sort(mItemList.begin(), mItemList.end(), SortScrollListItem(mSortColumn, mSortAscending)); break; case ADD_BOTTOM: mItemList.push_back(item); + setSorted(FALSE); break; default: llassert(0); mItemList.push_back(item); + setSorted(FALSE); break; } @@ -1094,7 +1101,7 @@ void LLScrollListCtrl::selectNextItem( BOOL extend_selection) } } - if ((mCommitOnSelectionChange || mCommitOnKeyboardMovement)) + if (mCommitOnKeyboardMovement) { onCommit(); } @@ -1685,8 +1692,7 @@ BOOL LLScrollListCtrl::handleMouseUp(S32 x, S32 y, MASK mask) } // always commit when mouse operation is completed inside list - // this only needs to be done for lists that don't commit on selection change - if (!mCommitOnSelectionChange && pointInView(x,y)) + if (mItemListRect.pointInRect(x,y)) { mSelectionChanged = FALSE; onCommit(); @@ -2090,6 +2096,16 @@ void LLScrollListCtrl::commitIfChanged() } } +void LLScrollListCtrl::setSorted(BOOL sorted) +{ + mSorted = sorted; +} + +BOOL LLScrollListCtrl::isSorted() +{ + return mSorted; +} + // Called by scrollbar //static void LLScrollListCtrl::onScrollChange( S32 new_pos, LLScrollbar* scrollbar, void* userdata ) @@ -2102,10 +2118,11 @@ void LLScrollListCtrl::onScrollChange( S32 new_pos, LLScrollbar* scrollbar, void // First column is column 0 void LLScrollListCtrl::sortByColumn(U32 column, BOOL ascending) { - if (mSortColumn != column) + if (!mSorted || mSortColumn != column) { mSortColumn = column; std::sort(mItemList.begin(), mItemList.end(), SortScrollListItem(mSortColumn, mSortAscending)); + setSorted(TRUE); } // just reverse the list if changing sort order @@ -2358,6 +2375,9 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac LLString sortname(columnname); child->getAttributeString("sort", sortname); + + BOOL sort_ascending = TRUE; + child->getAttributeBOOL("sort_ascending", sort_ascending); LLString imagename; child->getAttributeString("image", imagename); @@ -2379,6 +2399,7 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac columns[index]["name"] = columnname; columns[index]["sort"] = sortname; + columns[index]["sort_ascending"] = sort_ascending; columns[index]["image"] = imagename; columns[index]["label"] = labelname; columns[index]["width"] = columnwidth; @@ -2543,6 +2564,13 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos) { mDefaultColumn = 0; } + // if no column name provided, just use ordinal as name + if (name.empty()) + { + std::ostringstream new_name; + new_name << mColumnsIndexed.size(); + name = new_name.str(); + } if (mColumns.find(name) == mColumns.end()) { // Add column @@ -2621,6 +2649,7 @@ void LLScrollListCtrl::onClickColumn(void *userdata) U32 column_index = info->mIndex; LLScrollListColumn* column = parent->mColumnsIndexed[info->mIndex]; + bool ascending = column->mSortAscending; if (column->mSortingColumn != column->mName) { if (parent->mColumns.find(column->mSortingColumn) != parent->mColumns.end()) @@ -2630,7 +2659,6 @@ void LLScrollListCtrl::onClickColumn(void *userdata) } } - bool ascending = true; if (column_index == parent->mSortColumn) { ascending = !parent->mSortAscending; @@ -2715,6 +2743,7 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p // Add any columns we don't already have LLSD columns = value["columns"]; LLSD::array_const_iterator itor; + S32 col_index = 0 ; for (itor = columns.beginArray(); itor != columns.endArray(); ++itor) { LLString column = (*itor)["column"].asString(); @@ -2723,21 +2752,39 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p { mDefaultColumn = 0; } - std::map<LLString, LLScrollListColumn>::iterator column_itor = mColumns.find(column); - if (column_itor == mColumns.end()) + + LLScrollListColumn* columnp = NULL; + + // empty columns strings index by ordinal + if (column.empty()) + { + std::ostringstream new_name; + new_name << col_index; + column = new_name.str(); + } + + std::map<LLString, LLScrollListColumn>::iterator column_itor; + column_itor = mColumns.find(column); + if (column_itor != mColumns.end()) + { + columnp = &column_itor->second; + } + + // create new column on demand + if (!columnp) { LLSD new_column; new_column["name"] = column; new_column["label"] = column; - new_column["width"] = 0; + new_column["width"] = (*itor)["width"]; addColumn(new_column); - column_itor = mColumns.find(column); + columnp = &mColumns.find(column)->second; new_item->setNumColumns(mColumns.size()); } - S32 index = column_itor->second.mIndex; - S32 width = column_itor->second.mWidth; - LLFontGL::HAlign font_alignment = column_itor->second.mFontAlignment; + S32 index = columnp->mIndex; + S32 width = columnp->mWidth; + LLFontGL::HAlign font_alignment = columnp->mFontAlignment; LLSD value = (*itor)["value"]; LLString fontname = (*itor)["font"].asString(); @@ -2770,11 +2817,13 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p else { new_item->setColumn(index, new LLScrollListText(value.asString(), font, width, font_style, font_alignment)); - if (column_itor->second.mHeader && !value.asString().empty()) + if (columnp->mHeader && !value.asString().empty()) { - column_itor->second.mHeader->setHasResizableElement(TRUE); + columnp->mHeader->setHasResizableElement(TRUE); } } + + col_index++; } S32 num_columns = mColumns.size(); @@ -2917,32 +2966,6 @@ LLColumnHeader::LLColumnHeader(const LLString& label, const LLRect &rect, LLScro mAscendingText = "[LOW]...[HIGH](Ascending)"; mDescendingText = "[HIGH]...[LOW](Descending)"; - LLSD row; - row["columns"][0]["column"] = "label"; - row["columns"][0]["value"] = mAscendingText.getString(); - row["columns"][0]["font"] = "SANSSERIF_SMALL"; - row["columns"][0]["width"] = 80; - - row["columns"][1]["column"] = "arrow"; - row["columns"][1]["type"] = "icon"; - row["columns"][1]["value"] = LLUI::sAssetsGroup->getString("up_arrow.tga"); - row["columns"][1]["width"] = 20; - - mList->addElement(row); - - row["columns"][0]["column"] = "label"; - row["columns"][0]["type"] = "text"; - row["columns"][0]["value"] = mDescendingText.getString(); - row["columns"][0]["font"] = "SANSSERIF_SMALL"; - row["columns"][0]["width"] = 80; - - row["columns"][1]["column"] = "arrow"; - row["columns"][1]["type"] = "icon"; - row["columns"][1]["value"] = LLUI::sAssetsGroup->getString("down_arrow.tga"); - row["columns"][1]["width"] = 20; - - mList->addElement(row); - mList->reshape(llmax(mList->getRect().getWidth(), 110, mRect.getWidth()), mList->getRect().getHeight()); // resize handles on left and right @@ -2964,7 +2987,7 @@ void LLColumnHeader::draw() { if( getVisible() ) { - mDrawArrow = !mColumn->mLabel.empty() && mColumn->mParentCtrl->getSortColumnName() == mColumn->mSortingColumn; + mDrawArrow = !mColumn->mLabel.empty() && mColumn->mParentCtrl->isSorted() && mColumn->mParentCtrl->getSortColumnName() == mColumn->mSortingColumn; BOOL is_ascending = mColumn->mParentCtrl->getSortAscending(); mArrowImage = is_ascending ? LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("up_arrow.tga"))) @@ -3311,7 +3334,11 @@ void LLColumnHeader::setHasResizableElement(BOOL resizable) void LLColumnHeader::enableResizeBar(BOOL enable) { - mResizeBar->setEnabled(enable); + // for now, dynamically spaced columns can't be resized + if (!mColumn->mDynamicWidth) + { + mResizeBar->setEnabled(enable); + } } BOOL LLColumnHeader::canResize() diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index 7a0a32c87e..de9b58bd1e 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -142,6 +142,7 @@ public: LLScrollListColumn() : mName(""), mSortingColumn(""), + mSortAscending(TRUE), mLabel(""), mWidth(-1), mRelWidth(-1.0), @@ -156,6 +157,7 @@ public: LLScrollListColumn(LLString name, LLString label, S32 width, F32 relwidth) : mName(name), mSortingColumn(name), + mSortAscending(TRUE), mLabel(label), mWidth(width), mRelWidth(relwidth), @@ -176,6 +178,11 @@ public: { mSortingColumn = sd.get("sort").asString(); } + mSortAscending = TRUE; + if (sd.has("sort_ascending")) + { + mSortAscending = sd.get("sort_ascending").asBoolean(); + } mLabel = sd.get("label").asString(); if (sd.has("relwidth") && (F32)sd.get("relwidth").asReal() > 0) { @@ -210,6 +217,7 @@ public: LLString mName; LLString mSortingColumn; + BOOL mSortAscending; LLString mLabel; S32 mWidth; F32 mRelWidth; @@ -381,8 +389,10 @@ public: // Returns FALSE if not found. BOOL setSelectedByValue(LLSD value, BOOL selected); - virtual BOOL isSelected(LLSD value); + BOOL isSorted(); + virtual BOOL isSelected(LLSD value); + BOOL selectFirstItem(); BOOL selectNthItem( S32 index ); BOOL selectItemAt(S32 x, S32 y, MASK mask); @@ -552,6 +562,7 @@ protected: void selectItem(LLScrollListItem* itemp, BOOL single_select = TRUE); void deselectItem(LLScrollListItem* itemp); void commitIfChanged(); + void setSorted(BOOL sorted); protected: S32 mCurIndex; // For get[First/Next]Data @@ -615,6 +626,7 @@ protected: S32 mSortColumn; BOOL mSortAscending; + BOOL mSorted; std::map<LLString, LLScrollListColumn> mColumns; std::vector<LLScrollListColumn*> mColumnsIndexed; diff --git a/indra/llui/llsliderctrl.cpp b/indra/llui/llsliderctrl.cpp index b3c49e81f1..8b5cd4690e 100644 --- a/indra/llui/llsliderctrl.cpp +++ b/indra/llui/llsliderctrl.cpp @@ -300,7 +300,7 @@ void LLSliderCtrl::onSliderCommit( LLUICtrl* caller, void *userdata ) void LLSliderCtrl::setEnabled(BOOL b) { - LLUICtrl::setEnabled( b ); + LLView::setEnabled( b ); if( mLabelBox ) { diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp index fbd8335e6c..34363eb506 100644 --- a/indra/llui/llspinctrl.cpp +++ b/indra/llui/llspinctrl.cpp @@ -123,6 +123,23 @@ LLSpinCtrl::~LLSpinCtrl() } +F32 clamp_precision(F32 value, S32 decimal_precision) +{ + // pow() isn't perfect + + F64 clamped_value = value; + for (S32 i = 0; i < decimal_precision; i++) + clamped_value *= 10.0; + + clamped_value = llround((F32)clamped_value); + + for (S32 i = 0; i < decimal_precision; i++) + clamped_value /= 10.0; + + return (F32)clamped_value; +} + + // static void LLSpinCtrl::onUpBtn( void *userdata ) { @@ -131,6 +148,7 @@ void LLSpinCtrl::onUpBtn( void *userdata ) { // use getValue()/setValue() to force reload from/to control F32 val = (F32)self->getValue().asReal() + self->mIncrement; + val = clamp_precision(val, self->mPrecision); val = llmin( val, self->mMaxValue ); if( self->mValidateCallback ) @@ -163,6 +181,7 @@ void LLSpinCtrl::onDownBtn( void *userdata ) if( self->getEnabled() ) { F32 val = (F32)self->getValue().asReal() - self->mIncrement; + val = clamp_precision(val, self->mPrecision); val = llmax( val, self->mMinValue ); if( self->mValidateCallback ) @@ -224,12 +243,13 @@ void LLSpinCtrl::clear() } + void LLSpinCtrl::updateEditor() { LLLocale locale(LLLocale::USER_LOCALE); // Don't display very small negative values as -0.000 - F32 displayed_value = (F32)floor(getValue().asReal() * pow(10.0, (F64)mPrecision) + 0.5) / (F32)pow(10.0, (F64)mPrecision); + F32 displayed_value = clamp_precision((F32)getValue().asReal(), mPrecision); // if( S32( displayed_value * pow( 10, mPrecision ) ) == 0 ) // { @@ -301,7 +321,7 @@ void LLSpinCtrl::setFocus(BOOL b) void LLSpinCtrl::setEnabled(BOOL b) { - LLUICtrl::setEnabled( b ); + LLView::setEnabled( b ); mEditor->setEnabled( b ); } diff --git a/indra/mac_updater/mac_updater.cpp b/indra/mac_updater/mac_updater.cpp index 52902ea819..4b56148f10 100644 --- a/indra/mac_updater/mac_updater.cpp +++ b/indra/mac_updater/mac_updater.cpp @@ -46,9 +46,8 @@ EventHandlerRef gEventHandler = NULL; OSStatus gFailure = noErr; Boolean gCancelled = false; -char *gUserServer; +char *gUpdateURL; char *gProductName; -char gUpdateURL[2048]; /* Flawfinder: ignore */ void *updatethreadproc(void*); @@ -305,20 +304,13 @@ int curl_progress_callback_func(void *clientp, int parse_args(int argc, char **argv) { - // Check for old-type arguments. - if (2 == argc) - { - gUserServer = argv[1]; - return 0; - } - int j; for (j = 1; j < argc; j++) { - if ((!strcmp(argv[j], "-userserver")) && (++j < argc)) + if ((!strcmp(argv[j], "-url")) && (++j < argc)) { - gUserServer = argv[j]; + gUpdateURL = argv[j]; } else if ((!strcmp(argv[j], "-name")) && (++j < argc)) { @@ -338,17 +330,17 @@ int main(int argc, char **argv) // // Process command line arguments // - gUserServer = NULL; + gUpdateURL = NULL; gProductName = NULL; parse_args(argc, argv); - if (!gUserServer) + if (!gUpdateURL) { - llinfos << "Usage: mac_updater -userserver <server> [-name <product_name>] [-program <program_name>]" << llendl; + llinfos << "Usage: mac_updater -url <url> [-name <product_name>] [-program <program_name>]" << llendl; exit(1); } else { - llinfos << "User server is: " << gUserServer << llendl; + llinfos << "Update url is: " << gUpdateURL << llendl; if (gProductName) { llinfos << "Product name is: " << gProductName << llendl; @@ -361,9 +353,6 @@ int main(int argc, char **argv) llinfos << "Starting " << gProductName << " Updater" << llendl; - // Build the URL to download the update - snprintf(gUpdateURL, sizeof(gUpdateURL), "http://secondlife.com/update-macos.php?userserver=%s", gUserServer); - // Real UI... OSStatus err; IBNibRef nib = NULL; diff --git a/indra/newview/English.lproj/InfoPlist.strings b/indra/newview/English.lproj/InfoPlist.strings index 784525aad4..54687b1a43 100644 --- a/indra/newview/English.lproj/InfoPlist.strings +++ b/indra/newview/English.lproj/InfoPlist.strings @@ -1,5 +1,5 @@ /* Localized versions of Info.plist keys */ CFBundleName = "Second Life"; -CFBundleShortVersionString = "Second Life version 1.14.0.1"; -CFBundleGetInfoString = "Second Life version 1.14.0.1, Copyright 2004-2007 Linden Research, Inc."; +CFBundleShortVersionString = "Second Life version 1.15.0.2"; +CFBundleGetInfoString = "Second Life version 1.15.0.2, Copyright 2004-2007 Linden Research, Inc."; diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist index c7d430725f..0908e18a1a 100644 --- a/indra/newview/Info-SecondLife.plist +++ b/indra/newview/Info-SecondLife.plist @@ -32,7 +32,7 @@ </dict> </array> <key>CFBundleVersion</key> - <string>1.14.0.1</string> + <string>1.15.0.2</string> <key>CSResourcesFileMapped</key> <true/> </dict> diff --git a/indra/newview/gpu_table.txt b/indra/newview/gpu_table.txt index 49b199c0a4..4e6373d57e 100644 --- a/indra/newview/gpu_table.txt +++ b/indra/newview/gpu_table.txt @@ -22,8 +22,11 @@ ATI All-in-Wonder X1800 .*ATI.*All-in-Wonder X18.* 3 ATI All-in-Wonder X1900 .*ATI.*All-in-Wonder X19.* 3 ATI ASUS X1xxx .*ASUS X1.* 3 ATI Mobility Radeon X1xxx .*ATI.*Mobility.*X1.* 2 -ATI Mobility Radeon X3xx .*ATI.*Mobility.*X3.* 1 -ATI Mobility Radeon X6xx .*ATI.*Mobility.*X6.* 1 +// HACK: We crash on startup on some Mobility Radeon chips, with 1.15.0 +// in FMOD (!). Try defaulting them to class 0. JC +ATI Mobility Radeon X3xx .*ATI.*Mobility.*X3.* 0 +ATI Mobility Radeon X6xx .*ATI.*Mobility.*X6.* 0 +ATI Mobility Radeon X7xx .*ATI.*Mobility.*X7.* 0 ATI Radeon OpenGL .*ATI.*Radeon OpenGL.* 3 ATI Diamond X1xxx .*ATI.*Diamond.*X1.* 3 ATI FireGL 5xxx .*ATI.*FireGL V5.* 3 diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 3939c14dbb..13fa29e242 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -203,6 +203,9 @@ BOOL LLAgent::sDebugDisplayTarget = FALSE; const F32 LLAgent::TYPING_TIMEOUT_SECS = 5.f; +std::map<LLString, LLString> LLAgent::sTeleportErrorMessages; +std::map<LLString, LLString> LLAgent::sTeleportProgressMessages; + class LLAgentFriendObserver : public LLFriendObserver { public: @@ -5472,6 +5475,8 @@ bool LLAgent::teleportCore(bool is_local) LLFloaterWorldMap::hide(NULL); LLFloaterDirectory::hide(NULL); + gParcelMgr->deselectLand(); + // Close all pie menus, deselect land, etc. // Don't change the camera until we know teleport succeeded. JC resetView(FALSE); @@ -7197,4 +7202,57 @@ void LLAgent::observeFriends() } } +void LLAgent::parseTeleportMessages(const LLString& xml_filename) +{ + LLXMLNodePtr root; + BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root); + + if (!success || !root || !root->hasName( "teleport_messages" )) + { + llerrs << "Problem reading teleport string XML file: " + << xml_filename << llendl; + return; + } + + for (LLXMLNode* message_set = root->getFirstChild(); + message_set != NULL; + message_set = message_set->getNextSibling()) + { + if ( !message_set->hasName("message_set") ) continue; + + std::map<LLString, LLString> *teleport_msg_map = NULL; + LLString message_set_name; + + if ( message_set->getAttributeString("name", message_set_name) ) + { + //now we loop over all the string in the set and add them + //to the appropriate set + if ( message_set_name == "errors" ) + { + teleport_msg_map = &sTeleportErrorMessages; + } + else if ( message_set_name == "progress" ) + { + teleport_msg_map = &sTeleportProgressMessages; + } + } + + if ( !teleport_msg_map ) continue; + + LLString message_name; + for (LLXMLNode* message_node = message_set->getFirstChild(); + message_node != NULL; + message_node = message_node->getNextSibling()) + { + if ( message_node->hasName("message") && + message_node->getAttributeString("name", message_name) ) + { + (*teleport_msg_map)[message_name] = + message_node->getTextContents(); + } //end if ( message exists and has a name) + } //end for (all message in set) + }//end for (all message sets in xml file) +} + + // EOF diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index d0bda5d46a..89d60709d5 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -672,6 +672,13 @@ public: BOOL mForceMouselook; + static void parseTeleportMessages(const LLString& xml_filename); + //we should really define ERROR and PROGRESS enums here + //but I don't really feel like doing that, so I am just going + //to expose the mappings....yup + static std::map<LLString, LLString> sTeleportErrorMessages; + static std::map<LLString, LLString> sTeleportProgressMessages; + private: ETeleportState mTeleportState; LLString mTeleportMessage; diff --git a/indra/newview/llcaphttpsender.cpp b/indra/newview/llcaphttpsender.cpp new file mode 100644 index 0000000000..7928a5004c --- /dev/null +++ b/indra/newview/llcaphttpsender.cpp @@ -0,0 +1,30 @@ +/** + * @file llcaphttpsender.cpp + * @brief Abstracts details of sending messages via UntrustedMessage cap. + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "linden_common.h" +#include "llcaphttpsender.h" + +LLCapHTTPSender::LLCapHTTPSender(const std::string& cap) : + mCap(cap) +{ +} + +//virtual +void LLCapHTTPSender::send(const LLHost& host, const char* message, + const LLSD& body, + LLHTTPClient::ResponderPtr response) const +{ + llinfos << "LLCapHTTPSender::send: message " << message + << " to host " << host << llendl; + LLSD llsd; + llsd["message"] = message; + llsd["body"] = body; + LLHTTPClient::post(mCap, llsd, response); +} diff --git a/indra/newview/llcaphttpsender.h b/indra/newview/llcaphttpsender.h new file mode 100644 index 0000000000..af71c66563 --- /dev/null +++ b/indra/newview/llcaphttpsender.h @@ -0,0 +1,30 @@ +/** + * @file llcaphttpsender.h + * @brief Abstracts details of sending messages via the + * UntrustedMessage capability. + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#ifndef LL_CAP_HTTP_SENDER_H +#define LL_CAP_HTTP_SENDER_H + +#include "llhttpsender.h" + +class LLCapHTTPSender : public LLHTTPSender +{ +public: + LLCapHTTPSender(const std::string& cap); + + /** @brief Send message via UntrustedMessage capability with body, + call response when done */ + virtual void send(const LLHost& host, + const char* message, const LLSD& body, + LLHTTPClient::ResponderPtr response) const; + +private: + std::string mCap; +}; + +#endif // LL_CAP_HTTP_SENDER_H diff --git a/indra/newview/llcolorswatch.cpp b/indra/newview/llcolorswatch.cpp index 13e7fef4ec..41f8f1d714 100644 --- a/indra/newview/llcolorswatch.cpp +++ b/indra/newview/llcolorswatch.cpp @@ -226,7 +226,7 @@ void LLColorSwatchCtrl::draw() void LLColorSwatchCtrl::setEnabled( BOOL enabled ) { mCaption->setEnabled( enabled ); - LLUICtrl::setEnabled( enabled ); + LLView::setEnabled( enabled ); if (!enabled) { diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 2ad7eb6866..6d1c384b5a 100644 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -1,163 +1,167 @@ -/** +/** * @file lleventpoll.cpp - * @brief Implementation of the LLEventPoll class. + * @brief Implementation of the LLEventPoll class. * - * Copyright (c) 2006-$CurrentYear$, Linden Research, Inc. + * Copyright (c) 2006-$CurrentYear$, Linden Research, Inc. * $License$ */ #include "llviewerprecompiledheaders.h" +#include "llagent.h" #include "lleventpoll.h" #include "llhttpclient.h" -#include "llhttpnode.h" #include "llsdserialize.h" +#include "llviewerregion.h" +#include "message.h" +class LLEventPoll::Impl : LLHTTPClient::Responder +{ +public: + static Impl& start(const std::string& pollURL); + void stop(); + +private: + Impl(const std::string& pollURL); + ~Impl(); + + void makeRequest(); + void handleMessage(const LLSD& content); + virtual void error(U32 status, const std::string& reason); + virtual void result(const LLSD& content); +private: + typedef LLHTTPClient::ResponderPtr Ptr; -class LLEventPoll::Impl : LLHTTPClient::Responder + Ptr mPtr; + bool mDone; + + std::string mPollURL; + std::string mSender; + + LLSD mAcknowledge; + + // these are only here for debugging so we can see which poller is which + static int sCount; + int mCount; +}; + +//static +LLEventPoll::Impl& LLEventPoll::Impl::start( + const std::string& pollURL) { -public: - static Impl& start( - const std::string& pollURL, const LLHTTPNode& treeRoot) - { - Impl* i = new Impl(pollURL, treeRoot); - llinfos << "LLEventPoll::Impl::start <" << i->mCount << "> " + Impl* i = new Impl(pollURL); + llinfos << "LLEventPoll::Impl::start <" << i->mCount << "> " << pollURL << llendl; - return *i; - } - - void stop() + return *i; +} + +void LLEventPoll::Impl::stop() +{ + lldebugs << "LLEventPoll::Impl::stop <" << mCount << "> " + << mPollURL << llendl; + // there should be a way to stop a LLHTTPClient request in progress + mDone = true; + mPtr = NULL; +} + +int LLEventPoll::Impl::sCount = 0; + +LLEventPoll::Impl::Impl(const std::string& pollURL) + : mPtr(NULL), mDone(false), + mPollURL(pollURL), + mCount(++sCount) +{ + mPtr = this; + //extract host and port of simulator to set as sender + LLViewerRegion *regionp = gAgent.getRegion(); + if (!regionp) { - lldebugs << "LLEventPoll::Impl::stop <" << mCount << "> " - << mPollURL << llendl; - // there should be a way to stop a LLHTTPClient request in progress - mDone = true; - mPtr = NULL; + llerrs << "LLEventPoll initialized before region is added." << llendl; } + mSender = regionp->getHost().getIPandPort(); + llinfos << "LLEventPoll initialized with sender " << mSender << llendl; + makeRequest(); +} + +LLEventPoll::Impl::~Impl() +{ + lldebugs << "LLEventPoll::Impl::~Impl <" << mCount << "> " + << mPollURL << llendl; +} + +void LLEventPoll::Impl::makeRequest() +{ + LLSD request; + request["ack"] = mAcknowledge; + request["done"] = mDone; -private: - Impl(const std::string& pollURL, const LLHTTPNode& treeRoot) - : mPtr(NULL), mDone(false), - mPollURL(pollURL), mTreeRoot(treeRoot), - mCount(++sCount) - { - mPtr = this; - makeRequest(); - } - - ~Impl() - { - lldebugs << "LLEventPoll::Impl::~Impl <" << mCount << "> " - << mPollURL << llendl; - } + lldebugs << "LLEventPoll::Impl::makeRequest <" << mCount << "> ack = " + << LLSDXMLStreamer(mAcknowledge) << llendl; + LLHTTPClient::post(mPollURL, request, mPtr); +} + +void LLEventPoll::Impl::handleMessage(const LLSD& content) +{ + std::string msg_name = content["message"]; + LLSD message; + message["sender"] = mSender; + message["body"] = content["body"]; + LLMessageSystem::dispatch(msg_name, message); +} +//virtual +void LLEventPoll::Impl::error(U32 status, const std::string& reason) +{ + if (mDone) return; - void makeRequest() + if(status != 499) { - LLSD request; - request["ack"] = mAcknowledge; - request["done"] = mDone; - - lldebugs << "LLEventPoll::Impl::makeRequest <" << mCount << "> ack = " - << LLSDXMLStreamer(mAcknowledge) << llendl; - LLHTTPClient::post(mPollURL, request, mPtr); + llwarns << "LLEventPoll::Impl::error: <" << mCount << "> got " + << status << ": " << reason + << (mDone ? " -- done" : "") << llendl; + stop(); + return; } + + makeRequest(); +} + +//virtual +void LLEventPoll::Impl::result(const LLSD& content) +{ + lldebugs << "LLEventPoll::Impl::result <" << mCount << ">" + << (mDone ? " -- done" : "") << llendl; - void handleMessage(const LLSD& content) - { - std::string message = content["message"]; - if (message.empty()) - { - llwarns << "LLEventPoll::Impl::handleMessage <" << mCount - << "> empty message name" << llendl; - return; - } - - std::string path = "/message/" + message; - - LLSD context; - const LLHTTPNode* handler = mTreeRoot.traverse(path, context); - if (!handler) - { - llwarns << "LLEventPoll::Impl::handleMessage <" << mCount - << "> no handler for " << path << llendl; - return; - } - LLPointer<LLSimpleResponse> responsep = LLSimpleResponse::create(); - handler->post((LLHTTPNode::ResponsePtr)responsep, context, content["body"]); - - lldebugs << "LLEventPoll::Impl::handleMessage handled <" << mCount << "> " - << message << ": " << *responsep << llendl; - } + if (mDone) return; + + mAcknowledge = content["id"]; + LLSD events = content["events"]; - virtual void error(U32 status, const std::string& reason) + if(mAcknowledge.isUndefined()) { - lldebugs << "LLEventPoll::Impl::error <" << mCount << "> got " - << status << ": " << reason - << (mDone ? " -- done" : "") << llendl; - - if (mDone) return; - - if (status == 404) - { - // the capability has been revoked - stop(); - return; - } - - makeRequest(); + llwarns << "LLEventPoll::Impl: id undefined" << llendl; } + llinfos << "LLEventPoll::Impl::completed <" << mCount << "> " << events.size() << "events (id " + << LLSDXMLStreamer(mAcknowledge) << ")" << llendl; - virtual void result(const LLSD& content) + LLSD::array_const_iterator i = events.beginArray(); + LLSD::array_const_iterator end = events.endArray(); + for (; i != end; ++i) { - lldebugs << "LLEventPoll::Impl::result <" << mCount << ">" - << (mDone ? " -- done" : "") << llendl; - - if (mDone) return; - - mAcknowledge = content["id"]; - LLSD events = content["events"]; - - lldebugs << "LLEventPoll::Impl::completed <" << mCount << "> ack = " - << LLSDXMLStreamer(mAcknowledge) << llendl; - - LLSD::array_const_iterator i = events.beginArray(); - LLSD::array_const_iterator end = events.endArray(); - for (; i != end; ++i) + if (i->has("message")) { - if (i->has("message")) - { - handleMessage(*i); - } + handleMessage(*i); } - - makeRequest(); } - -private: - typedef LLHTTPClient::ResponderPtr Ptr; - - Ptr mPtr; - bool mDone; - - std::string mPollURL; - const LLHTTPNode& mTreeRoot; - LLSD mAcknowledge; - - // these are only here for debugging so we can see which poller is which - static int sCount; - int mCount; -}; - -int LLEventPoll::Impl::sCount = 0; - + makeRequest(); +} -LLEventPoll::LLEventPoll(const std::string& pollURL, const LLHTTPNode& treeRoot) - : impl(Impl::start(pollURL, treeRoot)) +LLEventPoll::LLEventPoll(const std::string& pollURL) + : impl(Impl::start(pollURL)) { } LLEventPoll::~LLEventPoll() diff --git a/indra/newview/lleventpoll.h b/indra/newview/lleventpoll.h index c5024b2b95..c2d798360f 100644 --- a/indra/newview/lleventpoll.h +++ b/indra/newview/lleventpoll.h @@ -9,20 +9,12 @@ #ifndef LL_LLEVENTPOLL_H #define LL_LLEVENTPOLL_H -class LLHTTPNode; - - class LLEventPoll ///< implements the viewer side of server-to-viewer pushed events. { public: - LLEventPoll(const std::string& pollURL, const LLHTTPNode& treeRoot); - /**< Start polling the URL. - - The object will automatically responde to events - by calling handlers in the tree. - */ - + LLEventPoll(const std::string& pollURL); + ///< Start polling the URL. virtual ~LLEventPoll(); ///< will stop polling, cancelling any poll in progress. diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp index 12891bd7b2..bc2c340999 100644 --- a/indra/newview/llfloaterauction.cpp +++ b/indra/newview/llfloaterauction.cpp @@ -57,12 +57,6 @@ LLFloaterAuction::LLFloaterAuction() : childSetCommitCallback("fence_check", LLSavedSettingsGlue::setBOOL, (void*)"AuctionShowFence"); - LLComboBox* combo = LLUICtrlFactory::getComboBoxByName(this, "saletype_combo"); - if (combo) - { - combo->selectFirstItem(); - } - childSetAction("snapshot_btn", onClickSnapshot, this); childSetAction("ok_btn", onClickOK, this); } @@ -196,28 +190,18 @@ void LLFloaterAuction::onClickSnapshot(void* data) void LLFloaterAuction::onClickOK(void* data) { LLFloaterAuction* self = (LLFloaterAuction*)(data); - bool is_auction = false; - LLComboBox* combo = LLUICtrlFactory::getComboBoxByName(self, "saletype_combo"); - if (combo - && combo->getCurrentIndex() == 0) - { - is_auction = true; - } + if(self->mImageID.notNull()) { LLSD parcel_name = self->childGetValue("parcel_text"); - // create the asset - if(is_auction) - { - // only need the tga if it is an auction. - LLString* name = new LLString(parcel_name.asString()); - gAssetStorage->storeAssetData(self->mTransactionID, LLAssetType::AT_IMAGE_TGA, - &auction_tga_upload_done, - (void*)name, - FALSE); - self->getWindow()->incBusyCount(); - } + // create the asset + LLString* name = new LLString(parcel_name.asString()); + gAssetStorage->storeAssetData(self->mTransactionID, LLAssetType::AT_IMAGE_TGA, + &auction_tga_upload_done, + (void*)name, + FALSE); + self->getWindow()->incBusyCount(); LLString* j2c_name = new LLString(parcel_name.asString()); gAssetStorage->storeAssetData(self->mTransactionID, LLAssetType::AT_TEXTURE, @@ -226,24 +210,13 @@ void LLFloaterAuction::onClickOK(void* data) FALSE); self->getWindow()->incBusyCount(); - if(is_auction) - { - LLNotifyBox::showXml("UploadingAuctionSnapshot"); - } - else - { - LLNotifyBox::showXml("UploadingSnapshot"); - } + LLNotifyBox::showXml("UploadingAuctionSnapshot"); + } LLMessageSystem* msg = gMessageSystem; - if(is_auction) - { - msg->newMessage("ViewerStartAuction"); - } - else - { - msg->newMessage("ParcelGodReserveForNewbie"); - } + + msg->newMessage("ViewerStartAuction"); + msg->nextBlock("AgentData"); msg->addUUID("AgentID", gAgent.getID()); msg->addUUID("SessionID", gAgent.getSessionID()); diff --git a/indra/newview/llfloaterbump.cpp b/indra/newview/llfloaterbump.cpp index 68f002f9d9..9beaa82cb9 100644 --- a/indra/newview/llfloaterbump.cpp +++ b/indra/newview/llfloaterbump.cpp @@ -65,7 +65,7 @@ void LLFloaterBump::show(void *contents) LLString none_detected = sInstance->childGetText("none_detected"); LLSD row; row["columns"][0]["value"] = none_detected; - row["columns"][0]["font-style"] = "BOLD"; + row["columns"][0]["font"] = "SansSerifBold"; list->addElement(row); } else @@ -136,6 +136,6 @@ void LLFloaterBump::add(LLScrollListCtrl* list, LLMeanCollisionData* mcd) LLSD row; row["id"] = mcd->mPerp; row["columns"][0]["value"] = text; - row["columns"][0]["font-style"] = "BOLD"; + row["columns"][0]["font"] = "SansSerifBold"; list->addElement(row); } diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp index 1ee8cd62ab..7ed84e495a 100644 --- a/indra/newview/llfloaterbuyland.cpp +++ b/indra/newview/llfloaterbuyland.cpp @@ -75,7 +75,6 @@ private: // information about the parcel bool mParcelValid; bool mParcelIsForSale; - bool mParcelIsFirstLand; bool mParcelIsGroupLand; S32 mParcelGroupContribution; S32 mParcelPrice; @@ -352,7 +351,6 @@ void LLFloaterBuyLandUI::updateParcelInfo() LLParcel* parcel = mParcel->getParcel(); mParcelValid = parcel && mRegion; mParcelIsForSale = false; - mParcelIsFirstLand = false; mParcelIsGroupLand = false; mParcelGroupContribution = 0; mParcelPrice = 0; @@ -386,7 +384,6 @@ void LLFloaterBuyLandUI::updateParcelInfo() { mParcelActualArea = parcel->getArea(); mParcelIsForSale = parcel->getForSale(); - mParcelIsFirstLand = parcel->getReservedForNewbie(); mParcelIsGroupLand = parcel->getIsGroupOwned(); mParcelPrice = mParcelIsForSale ? parcel->getSalePrice() : 0; @@ -493,36 +490,6 @@ void LLFloaterBuyLandUI::updateParcelInfo() } } - /* - if ((mRegion->getRegionFlags() & REGION_FLAGS_BLOCK_LAND_RESELL) - && !gAgent.isGodlike()) - { - mCannotBuyReason = llformat( - "The region %s does not allow transfer of land.", - mRegion->getName().c_str() ); - return; - } - */ - - if (parcel->getReservedForNewbie()) - { - if (mIsForGroup) - { - mCannotBuyReason = childGetText("first_time_group"); - return; - } - - if (gStatusBar->getSquareMetersCommitted() > 0) - { - mCannotBuyReason == childGetText("first_time"); - return; - } - - // *TODO: There should be a check based on the database value - // indra.user.ever_owned_land, only that value never makes it - // to the viewer, see SL-10728 - } - mCanBuy = true; } @@ -1143,17 +1110,6 @@ void LLFloaterBuyLandUI::refreshUI() message += childGetText("insufficient_land_credits"); } - else if (mAgentHasNeverOwnedLand) - { - if (mParcelIsFirstLand) - { - message += childGetText("first_purchase"); - } - else - { - message += childGetText("first_time_but_not_first_land"); - } - } else { diff --git a/indra/newview/llfloaterfriends.cpp b/indra/newview/llfloaterfriends.cpp index 534aac077f..1e65ae5620 100644 --- a/indra/newview/llfloaterfriends.cpp +++ b/indra/newview/llfloaterfriends.cpp @@ -501,14 +501,11 @@ void LLFloaterFriends::onClickIM(void* user_data) } else { - LLUUID session_id; - session_id.generate(); gIMView->setFloaterOpen(TRUE); - gIMView->addSession( - "Friends Conference", - IM_SESSION_ADD, - session_id, - ids); + gIMView->addSession("Friends Conference", + IM_SESSION_CONFERENCE_START, + ids[0], + ids); } } } diff --git a/indra/newview/llfloaterinspect.cpp b/indra/newview/llfloaterinspect.cpp index 8bb73e3a9b..1548c0e5d6 100644 --- a/indra/newview/llfloaterinspect.cpp +++ b/indra/newview/llfloaterinspect.cpp @@ -218,4 +218,3 @@ void LLFloaterInspect::draw() LLFloater::draw(); } - diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 9b28211476..51a1a99d71 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -793,10 +793,6 @@ void LLPanelLandGeneral::refreshNames() mSaleInfoForSale2->setTextArg("[BUYER]", name); } - else if(parcel->getReservedForNewbie()) - { - mSaleInfoForSale2->setTextArg("[BUYER]", childGetText("new users only")); - } else { mSaleInfoForSale2->setTextArg("[BUYER]", childGetText("anyone")); diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 9a486d76ee..8968da9720 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -40,7 +40,6 @@ #include "llviewerobject.h" #include "llviewerregion.h" #include "llcombobox.h" -#include "llfloaterrate.h" #include "lltooldraganddrop.h" #include "llfloatermap.h" #include "lluiconstants.h" diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp index f7bf4de34f..b71772bd93 100644 --- a/indra/newview/llfloatertos.cpp +++ b/indra/newview/llfloatertos.cpp @@ -162,6 +162,7 @@ BOOL LLFloaterTOS::postBuild() childSetValue("tos_text", LLSD(mMessage)); #endif + return TRUE; } diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 9ab9a3f6bb..7c03500f85 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -55,40 +55,171 @@ const S32 MIN_HEIGHT = 130; // static LLString sTitleString = "Instant Message with [NAME]"; static LLString sTypingStartString = "[NAME]: ..."; +static LLString sSessionStartString = "Starting session with [NAME] please wait."; + +void session_starter_helper(const LLUUID& temp_session_id, + const LLUUID& other_participant_id, + EInstantMessage im_type) +{ + LLMessageSystem *msg = gMessageSystem; + + msg->newMessageFast(_PREHASH_ImprovedInstantMessage); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + + msg->nextBlockFast(_PREHASH_MessageBlock); + msg->addBOOLFast(_PREHASH_FromGroup, FALSE); + msg->addUUIDFast(_PREHASH_ToAgentID, other_participant_id); + msg->addU8Fast(_PREHASH_Offline, IM_ONLINE); + msg->addU8Fast(_PREHASH_Dialog, im_type); + msg->addUUIDFast(_PREHASH_ID, temp_session_id); + msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary + + std::string name; + gAgent.buildFullname(name); + + msg->addStringFast(_PREHASH_FromAgentName, name); + msg->addStringFast(_PREHASH_Message, LLString::null); + msg->addU32Fast(_PREHASH_ParentEstateID, 0); + msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null); + msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent()); +} + +// Returns true if any messages were sent, false otherwise. +// Is sort of equivalent to "does the server need to do anything?" +bool send_start_session_messages(const LLUUID& temp_session_id, + const LLUUID& other_participant_id, + const LLDynamicArray<LLUUID>& ids, + EInstantMessage dialog) +{ + if ( (dialog == IM_SESSION_911_START) || + (dialog == IM_SESSION_GROUP_START) || + (dialog == IM_SESSION_CONFERENCE_START) ) + { + S32 count = ids.size(); + S32 bucket_size = UUID_BYTES * count; + U8* bucket; + U8* pos; + + session_starter_helper(temp_session_id, + other_participant_id, + dialog); + + switch(dialog) + { + case IM_SESSION_GROUP_START: + case IM_SESSION_911_START: + gMessageSystem->addBinaryDataFast(_PREHASH_BinaryBucket, + EMPTY_BINARY_BUCKET, + EMPTY_BINARY_BUCKET_SIZE); + break; + case IM_SESSION_CONFERENCE_START: + bucket = new U8[bucket_size]; + pos = bucket; + + // *FIX: this could suffer from endian issues + for(S32 i = 0; i < count; ++i) + { + memcpy(pos, &(ids.get(i)), UUID_BYTES); + pos += UUID_BYTES; + } + gMessageSystem->addBinaryDataFast(_PREHASH_BinaryBucket, + bucket, + bucket_size); + delete[] bucket; + + break; + default: + break; + } + gAgent.sendReliableMessage(); + + return true; + } + + return false; +} // Member Functions // -LLFloaterIMPanel::LLFloaterIMPanel(const std::string& name, const LLRect& rect, - const std::string& session_label, - const LLUUID& session_id, - const LLUUID& other_participant_id, - EInstantMessage dialog) : +LLFloaterIMPanel::LLFloaterIMPanel(const std::string& name, + const LLRect& rect, + const std::string& session_label, + const LLUUID& session_id, + const LLUUID& other_participant_id, + EInstantMessage dialog) : + LLFloater(name, rect, session_label), + mInputEditor(NULL), + mHistoryEditor(NULL), + mSessionUUID(session_id), + mOtherParticipantUUID(other_participant_id), + mDialog(dialog), + mTyping(FALSE), + mOtherTyping(FALSE), + mTypingLineStartIndex(0), + mSentTypingState(TRUE), + mFirstKeystrokeTimer(), + mLastKeystrokeTimer(), + mSessionInitialized(FALSE), + mSessionInitRequested(FALSE) +{ + init(session_label); +} + +LLFloaterIMPanel::LLFloaterIMPanel(const std::string& name, + const LLRect& rect, + const std::string& session_label, + const LLUUID& session_id, + const LLUUID& other_participant_id, + const LLDynamicArray<LLUUID>& ids, + EInstantMessage dialog) : LLFloater(name, rect, session_label), mInputEditor(NULL), mHistoryEditor(NULL), - mSessionLabel(session_label), mSessionUUID(session_id), mOtherParticipantUUID(other_participant_id), - mLureID(), mDialog(dialog), mTyping(FALSE), mOtherTyping(FALSE), mTypingLineStartIndex(0), mSentTypingState(TRUE), mFirstKeystrokeTimer(), - mLastKeystrokeTimer() + mLastKeystrokeTimer(), + mSessionInitialized(FALSE), + mSessionInitRequested(FALSE) +{ + init(session_label); + + mSessionInitialTargetIDs = ids; +} + + +void LLFloaterIMPanel::init(const LLString& session_label) { - init(); + gUICtrlFactory->buildFloater(this, + "floater_instant_message.xml", + NULL, + FALSE); + setLabel(session_label); setTitle(session_label); mInputEditor->setMaxTextLength(1023); -} + if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") ) + { + LLLogChat::loadHistory(session_label, + &chatFromLogFile, + (void *)this); + } -void LLFloaterIMPanel::init() -{ - gUICtrlFactory->buildFloater(this, "floater_instant_message.xml", NULL, FALSE); + if(IM_SESSION_911_START == mDialog) + { + LLTextBox* live_help_text = + LLUICtrlFactory::getTextBoxByName(this, "live_help_dialog"); + addHistoryLine(live_help_text->getText()); + } } @@ -101,6 +232,8 @@ BOOL LLFloaterIMPanel::postBuild() requires("live_help_dialog", WIDGET_TYPE_TEXT_BOX); requires("title_string", WIDGET_TYPE_TEXT_BOX); requires("typing_start_string", WIDGET_TYPE_TEXT_BOX); + requires("session_start_string", WIDGET_TYPE_TEXT_BOX); + requires("teleport_btn", WIDGET_TYPE_BUTTON); if (checkRequirements()) { @@ -118,24 +251,19 @@ BOOL LLFloaterIMPanel::postBuild() LLButton* close_btn = LLUICtrlFactory::getButtonByName(this, "close_btn"); close_btn->setClickedCallback(&LLFloaterIMPanel::onClickClose, this); + LLButton* tp_btn = LLUICtrlFactory::getButtonByName(this, "teleport_btn"); + tp_btn->setClickedCallback(&LLFloaterIMPanel::onTeleport, this); + tp_btn->setVisible(FALSE); + tp_btn->setEnabled(FALSE); + mHistoryEditor = LLViewerUICtrlFactory::getViewerTextEditorByName(this, "im_history"); mHistoryEditor->setParseHTML(TRUE); - if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") ) - { - LLLogChat::loadHistory(mSessionLabel, &chatFromLogFile, (void *)this); - } if (IM_SESSION_GROUP_START == mDialog || IM_SESSION_911_START == mDialog) { profile_btn->setEnabled(FALSE); - if(IM_SESSION_911_START == mDialog) - { - LLTextBox* live_help_text = LLUICtrlFactory::getTextBoxByName(this, "live_help_dialog"); - addHistoryLine(live_help_text->getText()); - } } - LLTextBox* title = LLUICtrlFactory::getTextBoxByName(this, "title_string"); sTitleString = title->getText(); @@ -143,6 +271,11 @@ BOOL LLFloaterIMPanel::postBuild() sTypingStartString = typing_start->getText(); + LLTextBox* session_start = LLUICtrlFactory::getTextBoxByName( + this, + "session_start_string"); + sSessionStartString = session_start->getText(); + return TRUE; } @@ -176,12 +309,14 @@ void LLFloaterIMPanel::draw() BOOL LLFloaterIMPanel::addParticipants(const LLDynamicArray<LLUUID>& ids) { - if(isAddAllowed()) + S32 count = ids.count(); + + if( isAddAllowed() && (count > 0) ) { llinfos << "LLFloaterIMPanel::addParticipants() - adding participants" << llendl; const S32 MAX_AGENTS = 50; - S32 count = ids.count(); if(count > MAX_AGENTS) return FALSE; + LLMessageSystem *msg = gMessageSystem; msg->newMessageFast(_PREHASH_ImprovedInstantMessage); msg->nextBlockFast(_PREHASH_AgentData); @@ -191,7 +326,7 @@ BOOL LLFloaterIMPanel::addParticipants(const LLDynamicArray<LLUUID>& ids) msg->addBOOLFast(_PREHASH_FromGroup, FALSE); msg->addUUIDFast(_PREHASH_ToAgentID, mOtherParticipantUUID); msg->addU8Fast(_PREHASH_Offline, IM_ONLINE); - msg->addU8Fast(_PREHASH_Dialog, mDialog); + msg->addU8Fast(_PREHASH_Dialog, IM_SESSION_ADD); msg->addUUIDFast(_PREHASH_ID, mSessionUUID); msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary std::string name; @@ -201,57 +336,21 @@ BOOL LLFloaterIMPanel::addParticipants(const LLDynamicArray<LLUUID>& ids) msg->addU32Fast(_PREHASH_ParentEstateID, 0); msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null); msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent()); - if (IM_SESSION_GROUP_START == mDialog) - { - // *HACK: binary bucket contains session label - the server - // will actually add agents. - llinfos << "Group IM session name '" << mSessionLabel - << "'" << llendl; - msg->addStringFast(_PREHASH_BinaryBucket, mSessionLabel); - gAgent.sendReliableMessage(); - } - else if (IM_SESSION_911_START == mDialog) - { - // HACK -- we modify the name of the session going out to - // the helpers to help them easily identify "Help" - // sessions in their collection of IM panels. - LLString name; - gAgent.getName(name); - LLString buffer = LLString("HELP ") + name; - llinfos << "LiveHelp IM session '" << buffer << "'." << llendl; - msg->addStringFast(_PREHASH_BinaryBucket, buffer.c_str()); - - // automaticaly open a wormhole when this reliable message gets through - msg->sendReliable( - gAgent.getRegionHost(), - 3, // retries - TRUE, // ping-based - 5.0f, // timeout - send_lure_911, - (void**)&mSessionUUID); - } - else + + // *FIX: this could suffer from endian issues + S32 bucket_size = UUID_BYTES * count; + U8* bucket = new U8[bucket_size]; + U8* pos = bucket; + for(S32 i = 0; i < count; ++i) { - if (mDialog != IM_SESSION_ADD - && mDialog != IM_SESSION_OFFLINE_ADD) - { - llwarns << "LLFloaterIMPanel::addParticipants() - dialog type " << mDialog - << " is not an ADD" << llendl; - } - // *FIX: this could suffer from endian issues - S32 bucket_size = UUID_BYTES * count; - U8* bucket = new U8[bucket_size]; - U8* pos = bucket; - for(S32 i = 0; i < count; ++i) - { - memcpy(pos, &(ids.get(i)), UUID_BYTES); /* Flawfinder: ignore */ - pos += UUID_BYTES; - } - msg->addBinaryDataFast(_PREHASH_BinaryBucket, bucket, bucket_size); - delete[] bucket; - gAgent.sendReliableMessage(); + memcpy(pos, &(ids.get(i)), UUID_BYTES); + pos += UUID_BYTES; } - + msg->addBinaryDataFast(_PREHASH_BinaryBucket, + bucket, + bucket_size); + delete[] bucket; + gAgent.sendReliableMessage(); } else { @@ -260,6 +359,7 @@ BOOL LLFloaterIMPanel::addParticipants(const LLDynamicArray<LLUUID>& ids) // successful add, because everyone that needed to get added // was added. } + return TRUE; } @@ -293,7 +393,7 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, const LLColor4 { LLString histstr = timestring + utf8msg; - LLLogChat::saveHistory(mSessionLabel,histstr); + LLLogChat::saveHistory(getTitle(),histstr); } } @@ -455,11 +555,8 @@ BOOL LLFloaterIMPanel::dropCategory(LLInventoryCategory* category, BOOL drop) BOOL LLFloaterIMPanel::isAddAllowed() const { - return ((IM_SESSION_ADD == mDialog) - || (IM_SESSION_OFFLINE_ADD == mDialog) - || (IM_SESSION_GROUP_START == mDialog) - || (IM_SESSION_911_START == mDialog) - || (IM_SESSION_CARDLESS_START == mDialog)); + return ((IM_SESSION_CONFERENCE_START == mDialog) + || (IM_SESSION_ADD) ); } @@ -493,72 +590,36 @@ void LLFloaterIMPanel::onClickClose( void* userdata ) } } -void LLFloaterIMPanel::addTeleportButton(const LLUUID& lure_id) +void LLFloaterIMPanel::addTeleportButton() { - LLButton* btn = LLViewerUICtrlFactory::getButtonByName(this, "Teleport Btn"); - if (!btn) - { - S32 BTN_VPAD = 2; - S32 BTN_HPAD = 2; + LLButton* btn = + LLViewerUICtrlFactory::getButtonByName(this, "teleport_btn"); - const char* teleport_label = "Teleport"; - - const LLFontGL* font = gResMgr->getRes( LLFONT_SANSSERIF ); - S32 p_btn_width = 75; - S32 c_btn_width = 60; - S32 t_btn_width = 75; - - // adjust the size of the editor to make room for the new button + if ( !btn->getEnabled() ) + { + //it's required, don't need to check for null here + // adjust the size of the editor to make room for the button LLRect rect = mInputEditor->getRect(); - S32 editor_right = rect.mRight - t_btn_width; + S32 editor_right = rect.mRight - btn->getRect().getWidth(); rect.mRight = editor_right; mInputEditor->reshape(rect.getWidth(), rect.getHeight(), FALSE); mInputEditor->setRect(rect); - - const S32 IMPANEL_PAD = 1 + LLPANEL_BORDER_WIDTH; - const S32 IMPANEL_INPUT_HEIGHT = 20; - - rect.setLeftTopAndSize( - mRect.getWidth() - IMPANEL_PAD - p_btn_width - c_btn_width - t_btn_width - BTN_HPAD - RESIZE_HANDLE_WIDTH, - IMPANEL_INPUT_HEIGHT + IMPANEL_PAD - BTN_VPAD, - t_btn_width, - BTN_HEIGHT); - - btn = new LLButton( - "Teleport Btn", rect, - "","", "", - &LLFloaterIMPanel::onTeleport, this, - font, teleport_label, teleport_label ); - - btn->setFollowsBottom(); - btn->setFollowsRight(); - addChild( btn ); - } - btn->setEnabled(TRUE); - mLureID = lure_id; -} -void LLFloaterIMPanel::removeTeleportButton() -{ - // TODO -- purge the button - LLButton* btn = LLViewerUICtrlFactory::getButtonByName(this, "Teleport Btn"); - if (btn) - { - btn->setEnabled(FALSE); + btn->setVisible(TRUE); + btn->setEnabled(TRUE); } } -// static +// static void LLFloaterIMPanel::onTeleport(void* userdata) { LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata; if(self) { - send_simple_im(self->mLureID, - "", - IM_LURE_911, - LLUUID::null); - self->removeTeleportButton(); + send_simple_im(self->mSessionUUID, //to + "", + IM_TELEPORT_911, + self->mSessionUUID);//session } } @@ -618,6 +679,44 @@ void LLFloaterIMPanel::onClose(bool app_quitting) destroy(); } +void deliver_message(const std::string& utf8_text, + const LLUUID& im_session_id, + const LLUUID& other_participant_id, + EInstantMessage dialog) +{ + std::string name; + gAgent.buildFullname(name); + + const LLRelationship* info = NULL; + info = LLAvatarTracker::instance().getBuddyInfo(other_participant_id); + U8 offline = (!info || info->isOnline()) ? IM_ONLINE : IM_OFFLINE; + + // default to IM_SESSION_SEND unless it's nothing special - in + // which case it's probably an IM to everyone. + U8 new_dialog = dialog; + + if ( dialog == IM_SESSION_911_START ) + { + new_dialog = IM_SESSION_911_SEND; + } + else if ( dialog != IM_NOTHING_SPECIAL ) + { + new_dialog = IM_SESSION_SEND; + } + + pack_instant_message( + gMessageSystem, + gAgent.getID(), + FALSE, + gAgent.getSessionID(), + other_participant_id, + name.c_str(), + utf8_text.c_str(), + offline, + (EInstantMessage)new_dialog, + im_session_id); + gAgent.sendReliableMessage(); +} void LLFloaterIMPanel::sendMsg() { @@ -635,50 +734,82 @@ void LLFloaterIMPanel::sendMsg() // Truncate and convert to UTF8 for transport std::string utf8_text = wstring_to_utf8str(text); utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1); - std::string name; - gAgent.buildFullname(name); - - const LLRelationship* info = NULL; - info = LLAvatarTracker::instance().getBuddyInfo(mOtherParticipantUUID); - U8 offline = (!info || info->isOnline()) ? IM_ONLINE : IM_OFFLINE; - - // default to IM_SESSION_SEND unless it's nothing special - in - // which case it's probably an IM to everyone. - U8 dialog = (mDialog == IM_NOTHING_SPECIAL) - ? (U8)IM_NOTHING_SPECIAL : (U8)IM_SESSION_SEND; - pack_instant_message( - gMessageSystem, - gAgent.getID(), - FALSE, - gAgent.getSessionID(), - mOtherParticipantUUID, - name.c_str(), - utf8_text.c_str(), - offline, - (EInstantMessage)dialog, - mSessionUUID); - gAgent.sendReliableMessage(); - // local echo - if((mDialog == IM_NOTHING_SPECIAL) && (mOtherParticipantUUID.notNull())) + if ( !mSessionInitialized ) { - std::string history_echo; - gAgent.buildFullname(history_echo); - - // Look for IRC-style emotes here. - char tmpstr[5]; /* Flawfinder: ignore */ - strncpy(tmpstr,utf8_text.substr(0,4).c_str(), sizeof(tmpstr) -1); /* Flawfinder: ignore */ - tmpstr[sizeof(tmpstr) -1] = '\0'; - if (!strncmp(tmpstr, "/me ", 4) || !strncmp(tmpstr, "/me'", 4)) + //we send requests (if we need to) to initialize our session + if ( !mSessionInitRequested ) { - utf8_text.replace(0,3,""); + mSessionInitRequested = TRUE; + if ( !send_start_session_messages(mSessionUUID, + mOtherParticipantUUID, + mSessionInitialTargetIDs, + mDialog) ) + { + //we don't need to need to wait for any responses + //so we don't need to disable + mSessionInitialized = TRUE; + } + else + { + //queue up the message to send once the session is + //initialized + mQueuedMsgsForInit.append(utf8_text); + + //locally echo a little "starting session" message + LLUIString session_start = sSessionStartString; + + session_start.setArg("[NAME]", getTitle()); + mSessionStartMsgPos = + mHistoryEditor->getText().length(); + + bool log_to_file = false; + addHistoryLine(session_start, + LLColor4::grey, + log_to_file); + + } } else { - history_echo += ": "; + //queue up the message to send once the session is + //initialized + mQueuedMsgsForInit.append(utf8_text); + } + } + + if ( mSessionInitialized ) + { + deliver_message(utf8_text, + mSessionUUID, + mOtherParticipantUUID, + mDialog); + + // local echo + if((mDialog == IM_NOTHING_SPECIAL) && + (mOtherParticipantUUID.notNull())) + { + std::string history_echo; + gAgent.buildFullname(history_echo); + + // Look for IRC-style emotes here. + char tmpstr[5]; /* Flawfinder: ignore */ + strncpy(tmpstr, + utf8_text.substr(0,4).c_str(), + sizeof(tmpstr) -1); /* Flawfinder: ignore */ + tmpstr[sizeof(tmpstr) -1] = '\0'; + if (!strncmp(tmpstr, "/me ", 4) || + !strncmp(tmpstr, "/me'", 4)) + { + utf8_text.replace(0,3,""); + } + else + { + history_echo += ": "; + } + history_echo += utf8_text; + addHistoryLine(history_echo); } - history_echo += utf8_text; - addHistoryLine(history_echo); } gViewerStats->incStat(LLViewerStats::ST_IM_COUNT); @@ -691,6 +822,31 @@ void LLFloaterIMPanel::sendMsg() mSentTypingState = TRUE; } +void LLFloaterIMPanel::sessionInitReplyReceived(const LLUUID& session_id) +{ + mSessionUUID = session_id; + mSessionInitialized = TRUE; + + //we assume the history editor hasn't moved at all since + //we added the starting session message + //so, we count how many characters to remove + S32 chars_to_remove = mHistoryEditor->getText().length() - + mSessionStartMsgPos; + mHistoryEditor->removeTextFromEnd(chars_to_remove); + + //and now, send the queued msg + LLSD::array_iterator iter; + for ( iter = mQueuedMsgsForInit.beginArray(); + iter != mQueuedMsgsForInit.endArray(); + ++iter) + { + deliver_message(iter->asString(), + mSessionUUID, + mOtherParticipantUUID, + mDialog); + } +} + void LLFloaterIMPanel::setTyping(BOOL typing) { diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h index 21a0cbcd41..45dda8ec79 100644 --- a/indra/newview/llimpanel.h +++ b/indra/newview/llimpanel.h @@ -27,10 +27,20 @@ public: // the default. For example, if you open a session though a // calling card, a new session id will be generated, but the // target_id will be the agent referenced by the calling card. - LLFloaterIMPanel(const std::string& name, const LLRect& rect, - const std::string& session_label, - const LLUUID& session_id, const LLUUID& target_id, - EInstantMessage dialog); + LLFloaterIMPanel(const std::string& name, + const LLRect& rect, + const std::string& session_label, + const LLUUID& session_id, + const LLUUID& target_id, + EInstantMessage dialog); + LLFloaterIMPanel(const std::string& name, + const LLRect& rect, + const std::string& session_label, + const LLUUID& session_id, + const LLUUID& target_id, + const LLDynamicArray<LLUUID>& ids, + EInstantMessage dialog); + /*virtual*/ BOOL postBuild(); @@ -66,14 +76,14 @@ public: static void onClickProfile( void* userdata ); // Profile button pressed static void onClickClose( void* userdata ); - //const LLUUID& getItemUUID() const { return mItemUUID; } const LLUUID& getSessionID() const { return mSessionUUID; } const LLUUID& getOtherParticipantID() const { return mOtherParticipantUUID; } // HACK -- for enabling a teleport button for helpers static void onTeleport(void* userdata); - void addTeleportButton(const LLUUID& lure_id); - void removeTeleportButton(); + void addTeleportButton(); + + void sessionInitReplyReceived(const LLUUID& im_session_id); // Handle other participant in the session typing. void processIMTyping(const LLIMInfo* im_info, BOOL typing); @@ -81,7 +91,7 @@ public: private: // called by constructors - void init(); + void init(const LLString& session_label); // Called by UI methods. void sendMsg(); @@ -110,7 +120,6 @@ private: private: LLLineEditor* mInputEditor; LLViewerTextEditor* mHistoryEditor; - std::string mSessionLabel; // The value of the mSessionUUID depends on how the IM session was started: // one-on-one ==> random id @@ -119,15 +128,17 @@ private: // 911 ==> Gaurdian_Angel_Group_ID ^ gAgent.getID() LLUUID mSessionUUID; + BOOL mSessionInitRequested; + BOOL mSessionInitialized; + LLSD mQueuedMsgsForInit; + // The value mOtherParticipantUUID depends on how the IM session was started: // one-on-one = recipient's id // group ==> group_id // inventory folder ==> first target id in list // 911 ==> sender LLUUID mOtherParticipantUUID; - - // the lure ID for help IM sessions - LLUUID mLureID; + LLDynamicArray<LLUUID> mSessionInitialTargetIDs; EInstantMessage mDialog; @@ -139,6 +150,8 @@ private: // Where does the "User is typing..." line start? S32 mTypingLineStartIndex; + //Where does the "Starting session..." line start? + S32 mSessionStartMsgPos; BOOL mSentTypingState; @@ -149,6 +162,8 @@ private: // Timer to detect when user has stopped typing. LLFrameTimer mLastKeystrokeTimer; + + void disableWhileSessionStarting(); }; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index c093faa1ca..553c6ec6c3 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -23,6 +23,7 @@ #include "llviewerwindow.h" #include "llresmgr.h" #include "llfloaternewim.h" +#include "llhttpnode.h" #include "llimpanel.h" #include "llresizebar.h" #include "lltabcontainer.h" @@ -35,7 +36,6 @@ #include "llcallingcard.h" #include "lltoolbar.h" -const EInstantMessage EVERYONE_DIALOG = IM_NOTHING_SPECIAL; const EInstantMessage GROUP_DIALOG = IM_SESSION_GROUP_START; const EInstantMessage DEFAULT_DIALOG = IM_NOTHING_SPECIAL; @@ -50,6 +50,9 @@ LLIMView* gIMView = NULL; static LLString sOnlyUserMessage; static LLString sOfflineMessage; +static std::map<std::string,LLString> sEventStringsMap; +static std::map<std::string,LLString> sErrorStringsMap; +static std::map<std::string,LLString> sForceCloseSessionMap; // // Helper Functions // @@ -63,7 +66,8 @@ static BOOL group_dictionary_sort( LLGroupData* a, LLGroupData* b ) // the other_participant_id is either an agent_id, a group_id, or an inventory // folder item_id (collection of calling cards) -static LLUUID compute_session_id(EInstantMessage dialog, const LLUUID& other_participant_id) +static LLUUID compute_session_id(EInstantMessage dialog, + const LLUUID& other_participant_id) { LLUUID session_id; if (IM_SESSION_GROUP_START == dialog) @@ -71,6 +75,10 @@ static LLUUID compute_session_id(EInstantMessage dialog, const LLUUID& other_par // slam group session_id to the group_id (other_participant_id) session_id = other_participant_id; } + else if (IM_SESSION_CONFERENCE_START == dialog) + { + session_id.generate(); + } else { LLUUID agent_id = gAgent.getID(); @@ -102,11 +110,34 @@ BOOL LLFloaterIM::postBuild() { requires("only_user_message", WIDGET_TYPE_TEXT_BOX); requires("offline_message", WIDGET_TYPE_TEXT_BOX); + requires("generic_request_error", WIDGET_TYPE_TEXT_BOX); + requires("insufficient_perms_error", WIDGET_TYPE_TEXT_BOX); + requires("generic_request_error", WIDGET_TYPE_TEXT_BOX); + requires("add_session_event", WIDGET_TYPE_TEXT_BOX); + requires("message_session_event", WIDGET_TYPE_TEXT_BOX); + requires("removed_from_group", WIDGET_TYPE_TEXT_BOX); if (checkRequirements()) { sOnlyUserMessage = childGetText("only_user_message"); sOfflineMessage = childGetText("offline_message"); + + sErrorStringsMap["generic"] = + childGetText("generic_request_error"); + sErrorStringsMap["unverified"] = + childGetText("insufficient_perms_error"); + sErrorStringsMap["no_user_911"] = + childGetText("user_no_help"); + + sEventStringsMap["add"] = childGetText("add_session_event");; + sEventStringsMap["message"] = + childGetText("message_session_event");; + sEventStringsMap["teleport"] = + childGetText("teleport_session_event");; + + sForceCloseSessionMap["removed"] = + childGetText("removed_from_group"); + return TRUE; } return FALSE; @@ -190,16 +221,12 @@ protected: // static EInstantMessage LLIMView::defaultIMTypeForAgent(const LLUUID& agent_id) { - EInstantMessage type = IM_SESSION_CARDLESS_START; + EInstantMessage type = IM_NOTHING_SPECIAL; if(is_agent_friend(agent_id)) { if(LLAvatarTracker::instance().isBuddyOnline(agent_id)) { - type = IM_SESSION_ADD; - } - else - { - type = IM_SESSION_OFFLINE_ADD; + type = IM_SESSION_CONFERENCE_START; } } return type; @@ -327,11 +354,21 @@ void LLIMView::addMessage( } else { + //if we have recently requsted to be dropped from a session + //but are still receiving messages from the session, don't make + //a new floater +// if ( mSessionsDropRequested.has(session_id.asString()) ) +// { +// return ; +// } + const char* name = from; if(session_name && (strlen(session_name)>1)) { name = session_name; } + + floater = createFloater(new_session_id, other_participant_id, name, dialog, FALSE); // When we get a new IM, and if you are a god, display a bit @@ -407,18 +444,25 @@ BOOL LLIMView::isIMSessionOpen(const LLUUID& uuid) // exists, it is brought forward. Specifying id = NULL results in an // im session to everyone. Returns the uuid of the session. LLUUID LLIMView::addSession(const std::string& name, - EInstantMessage dialog, - const LLUUID& other_participant_id) + EInstantMessage dialog, + const LLUUID& other_participant_id) { LLUUID session_id = compute_session_id(dialog, other_participant_id); + LLFloaterIMPanel* floater = findFloaterBySession(session_id); if(!floater) { - floater = createFloater(session_id, other_participant_id, name, dialog, TRUE); LLDynamicArray<LLUUID> ids; ids.put(other_participant_id); + + floater = createFloater(session_id, + other_participant_id, + name, + ids, + dialog, + TRUE); + noteOfflineUsers(floater, ids); - floater->addParticipants(ids); mTalkFloater->showFloater(floater); } else @@ -433,30 +477,34 @@ LLUUID LLIMView::addSession(const std::string& name, // Adds a session using the given session_id. If the session already exists // the dialog type is assumed correct. Returns the uuid of the session. LLUUID LLIMView::addSession(const std::string& name, - EInstantMessage dialog, - const LLUUID& session_id, - const LLDynamicArray<LLUUID>& ids) + EInstantMessage dialog, + const LLUUID& other_participant_id, + const LLDynamicArray<LLUUID>& ids) { if (0 == ids.getLength()) { return LLUUID::null; } - LLUUID other_participant_id = ids[0]; - LLUUID new_session_id = session_id; - if (new_session_id.isNull()) - { - new_session_id = compute_session_id(dialog, other_participant_id); - } + LLUUID session_id = compute_session_id(dialog, + other_participant_id); - LLFloaterIMPanel* floater = findFloaterBySession(new_session_id); + LLFloaterIMPanel* floater = findFloaterBySession(session_id); if(!floater) { - // On creation, use the first element of ids as the "other_participant_id" - floater = createFloater(new_session_id, other_participant_id, name, dialog, TRUE); + // On creation, use the first element of ids as the + // "other_participant_id" + floater = createFloater(session_id, + other_participant_id, + name, + ids, + dialog, + TRUE); + + if ( !floater ) return LLUUID::null; + noteOfflineUsers(floater, ids); } - floater->addParticipants(ids); mTalkFloater->showFloater(floater); //mTabContainer->selectTabPanel(panel); floater->setInputFocus(TRUE); @@ -474,6 +522,11 @@ void LLIMView::removeSession(const LLUUID& session_id) mTalkFloater->removeFloater(floater); //mTabContainer->removeTabPanel(floater); } + +// if ( session_id.notNull() ) +// { +// mSessionsDropRequested[session_id.asString()] = LLSD(); +// } } void LLIMView::refresh() @@ -499,8 +552,7 @@ void LLIMView::refresh() group; group = group_list.getNextData()) { - mNewIMFloater->addTarget(group->mID, group->mName, - (void*)(&GROUP_DIALOG), TRUE, FALSE); + mNewIMFloater->addGroup(group->mID, (void*)(&GROUP_DIALOG), TRUE, FALSE); } // build a set of buddies in the current buddy list. @@ -520,13 +572,6 @@ void LLIMView::refresh() { mNewIMFloater->addAgent((*it).second, (void*)(&DEFAULT_DIALOG), FALSE); } - - if(gAgent.isGodlike()) - { - // XUI:translate - mNewIMFloater->addTarget(LLUUID::null, "All Residents, All Grids", - (void*)(&EVERYONE_DIALOG), TRUE, FALSE); - } mNewIMFloater->setScrollPos( old_scroll_pos ); } @@ -600,12 +645,17 @@ void LLIMView::disconnectAllSessions() std::set<LLViewHandle>::iterator handle_it; for(handle_it = mFloaters.begin(); handle_it != mFloaters.end(); - ++handle_it) + ) { floater = (LLFloaterIMPanel*)LLFloater::getFloaterByHandle(*handle_it); + + // MUST do this BEFORE calling floater->onClose() because that may remove the item from the set, causing the subsequent increment to crash. + ++handle_it; + if (floater) { floater->setEnabled(FALSE); + floater->onClose(TRUE); } } } @@ -643,16 +693,45 @@ BOOL LLIMView::hasSession(const LLUUID& session_id) // consistency. Returns the pointer, caller (the class instance since // it is a private method) is not responsible for deleting the // pointer. Add the floater to this but do not select it. -LLFloaterIMPanel* LLIMView::createFloater(const LLUUID& session_id, - const LLUUID& other_participant_id, - const std::string& session_label, - EInstantMessage dialog, - BOOL user_initiated) +LLFloaterIMPanel* LLIMView::createFloater( + const LLUUID& session_id, + const LLUUID& other_participant_id, + const std::string& session_label, + EInstantMessage dialog, + BOOL user_initiated) +{ + if (session_id.isNull()) + { + llwarns << "Creating LLFloaterIMPanel with null session ID" << llendl; + } + + llinfos << "LLIMView::createFloater: from " << other_participant_id + << " in session " << session_id << llendl; + LLFloaterIMPanel* floater = new LLFloaterIMPanel(session_label, + LLRect(), + session_label, + session_id, + other_participant_id, + dialog); + LLTabContainerCommon::eInsertionPoint i_pt = user_initiated ? LLTabContainerCommon::RIGHT_OF_CURRENT : LLTabContainerCommon::END; + mTalkFloater->addFloater(floater, FALSE, i_pt); + mFloaters.insert(floater->getHandle()); + return floater; +} + +LLFloaterIMPanel* LLIMView::createFloater( + const LLUUID& session_id, + const LLUUID& other_participant_id, + const std::string& session_label, + const LLDynamicArray<LLUUID>& ids, + EInstantMessage dialog, + BOOL user_initiated) { if (session_id.isNull()) { llwarns << "Creating LLFloaterIMPanel with null session ID" << llendl; } + llinfos << "LLIMView::createFloater: from " << other_participant_id << " in session " << session_id << llendl; LLFloaterIMPanel* floater = new LLFloaterIMPanel(session_label, @@ -660,6 +739,7 @@ LLFloaterIMPanel* LLIMView::createFloater(const LLUUID& session_id, session_label, session_id, other_participant_id, + ids, dialog); LLTabContainerCommon::eInsertionPoint i_pt = user_initiated ? LLTabContainerCommon::RIGHT_OF_CURRENT : LLTabContainerCommon::END; mTalkFloater->addFloater(floater, FALSE, i_pt); @@ -715,3 +795,193 @@ void LLIMView::processIMTypingCore(const LLIMInfo* im_info, BOOL typing) floater->processIMTyping(im_info, typing); } } + +void LLIMView::updateFloaterSessionID(const LLUUID& old_session_id, + const LLUUID& new_session_id) +{ + LLFloaterIMPanel* floater = findFloaterBySession(old_session_id); + if (floater) + { + floater->sessionInitReplyReceived(new_session_id); + } +} + +void LLIMView::onDropRequestReplyReceived(const LLUUID& session_id) +{ + mSessionsDropRequested.erase(session_id.asString()); +} + +void onConfirmForceCloseError(S32 option, void* data) +{ + //only 1 option really + LLFloaterIMPanel* floater = ((LLFloaterIMPanel*) data); + + if ( floater ) floater->onClose(FALSE); +} + +class LLViewerIMSessionStartReply : public LLHTTPNode +{ +public: + virtual void describe(Description& desc) const + { + desc.shortInfo("Used for receiving a reply to a request to initialize an IM session"); + desc.postAPI(); + desc.input( + "{\"client_session_id\": UUID, \"session_id\": UUID, \"success\" boolean, \"reason\": string"); + desc.source(__FILE__, __LINE__); + } + + virtual void post(ResponsePtr response, + const LLSD& context, + const LLSD& input) const + { + LLSD body; + LLUUID temp_session_id; + LLUUID session_id; + bool success; + + body = input["body"]; + success = body["success"].asBoolean(); + temp_session_id = body["temp_session_id"].asUUID(); + + if ( success ) + { + session_id = body["session_id"].asUUID(); + gIMView->updateFloaterSessionID(temp_session_id, + session_id); + } + else + { + //throw an error dialog and close the temp session's + //floater + LLFloaterIMPanel* floater = + gIMView->findFloaterBySession(temp_session_id); + if (floater) + { + LLString::format_map_t args; + args["[REASON]"] = + sErrorStringsMap[body["error"].asString()]; + args["[RECIPIENT]"] = floater->getTitle(); + + gViewerWindow->alertXml("IMSessionStartError", + args, + onConfirmForceCloseError, + floater); + + } + } + } +}; + +class LLViewerIMSessionEventReply : public LLHTTPNode +{ +public: + virtual void describe(Description& desc) const + { + desc.shortInfo("Used for receiving a reply to a IM session event"); + desc.postAPI(); + desc.input( + "{\"event\": string, \"reason\": string, \"success\": boolean, \"session_id\": UUID"); + desc.source(__FILE__, __LINE__); + } + + virtual void post(ResponsePtr response, + const LLSD& context, + const LLSD& input) const + { + LLUUID session_id; + bool success; + + LLSD body = input["body"]; + success = body["success"].asBoolean(); + session_id = body["session_id"].asUUID(); + + if ( !success ) + { + //throw an error dialog + LLFloaterIMPanel* floater = + gIMView->findFloaterBySession(session_id); + if (floater) + { + LLString::format_map_t args; + args["[REASON]"] = + sErrorStringsMap[body["error"].asString()]; + args["[EVENT]"] = + sEventStringsMap[body["event"].asString()]; + args["[RECIPIENT]"] = floater->getTitle(); + + gViewerWindow->alertXml("IMSessionEventError", + args); + } + } + } +}; + +class LLViewerForceCloseIMSession: public LLHTTPNode +{ +public: + virtual void post(ResponsePtr response, + const LLSD& context, + const LLSD& input) const + { + LLUUID session_id; + LLString reason; + + session_id = input["body"]["session_id"].asUUID(); + reason = input["body"]["reason"].asString(); + + LLFloaterIMPanel* floater = + gIMView ->findFloaterBySession(session_id); + + if ( floater ) + { + LLString::format_map_t args; + + args["[NAME]"] = floater->getTitle(); + args["[REASON]"] = sForceCloseSessionMap[reason]; + + gViewerWindow->alertXml("ForceCloseIMSession", + args, + onConfirmForceCloseError, + floater); + } + } +}; + +class LLViewerIMSessionDropReply : public LLHTTPNode +{ +public: + virtual void post(ResponsePtr response, + const LLSD& context, + const LLSD& input) const + { + LLUUID session_id; + bool success; + + success = input["body"]["success"].asBoolean(); + session_id = input["body"]["session_id"].asUUID(); + + if ( !success ) + { + //throw an error alert? + } + + gIMView->onDropRequestReplyReceived(session_id); + } +}; + +LLHTTPRegistration<LLViewerIMSessionStartReply> + gHTTPRegistrationMessageImsessionstartreply( + "/message/IMSessionStartReply"); + +LLHTTPRegistration<LLViewerIMSessionEventReply> + gHTTPRegistrationMessageImsessioneventreply( + "/message/IMSessionEventReply"); + +LLHTTPRegistration<LLViewerForceCloseIMSession> + gHTTPRegistrationMessageForceCloseImSession( + "/message/ForceCloseIMSession"); + +LLHTTPRegistration<LLViewerIMSessionDropReply> + gHTTPRegistrationMessageImSessionDropReply( + "/message/IMSessionDropReply"); diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 8732484e0e..aac6fd63ce 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -55,11 +55,11 @@ public: EInstantMessage dialog, const LLUUID& other_participant_id); - // Adds a session using the given session_id. If the session already exists + // Adds a session using a specific group of starting agents // the dialog type is assumed correct. Returns the uuid of the session. LLUUID addSession(const std::string& name, EInstantMessage dialog, - const LLUUID& session_id, + const LLUUID& other_participant_id, const LLDynamicArray<LLUUID>& ids); // This removes the panel referenced by the uuid, and then @@ -67,6 +67,12 @@ public: // deleted. void removeSession(const LLUUID& session_id); + //Updates a given session's session IDs. Does not open, + //create or do anything new. If the old session doesn't + //exist, then nothing happens. + void updateFloaterSessionID(const LLUUID& old_session_id, + const LLUUID& new_session_id); + void processIMTypingStart(const LLIMInfo* im_info); void processIMTypingStop(const LLIMInfo* im_info); @@ -105,13 +111,25 @@ public: // is no matching panel. LLFloaterIMPanel* findFloaterBySession(const LLUUID& session_id); + void onDropRequestReplyReceived(const LLUUID& session_id); + private: // create a panel and update internal representation for // consistency. Returns the pointer, caller (the class instance // since it is a private method) is not responsible for deleting // the pointer. - LLFloaterIMPanel* createFloater(const LLUUID& session_id, const LLUUID& target_id, - const std::string& name, EInstantMessage dialog, BOOL user_initiated = FALSE); + LLFloaterIMPanel* createFloater(const LLUUID& session_id, + const LLUUID& target_id, + const std::string& name, + EInstantMessage dialog, + BOOL user_initiated = FALSE); + + LLFloaterIMPanel* createFloater(const LLUUID& session_id, + const LLUUID& target_id, + const std::string& name, + const LLDynamicArray<LLUUID>& ids, + EInstantMessage dialog, + BOOL user_initiated = FALSE); // This simple method just iterates through all of the ids, and // prints a simple message if they are not online. Used to help @@ -131,6 +149,8 @@ private: // An IM has been received that you haven't seen yet. BOOL mIMReceived; + + LLSD mSessionsDropRequested; }; diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 0338e7f02a..f90fe340b4 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1724,7 +1724,7 @@ void LLFolderBridge::folderOptionsMenu() if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard)) { mItems.push_back("Calling Card Separator"); - mItems.push_back("IM Contacts In Folder"); + mItems.push_back("Conference Chat Folder"); mItems.push_back("IM All Contacts In Folder"); } @@ -2043,58 +2043,6 @@ void LLFolderBridge::createWearable(LLUUID parent_id, EWearableType type) LLPointer<LLInventoryCallback>(NULL)); } -void LLFolderBridge::beginIMSession(BOOL only_online) -{ - LLInventoryModel* model = mInventoryPanel->getModel(); - if(!model) return; - LLViewerInventoryCategory* cat = getCategory(); - if(!cat) return; - LLUniqueBuddyCollector is_buddy; - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - model->collectDescendentsIf(mUUID, - cat_array, - item_array, - LLInventoryModel::EXCLUDE_TRASH, - is_buddy); - S32 count = item_array.count(); - if(count > 0) - { - // create the session - gIMView->setFloaterOpen(TRUE); - LLDynamicArray<LLUUID> members; - //members.put(gAgent.getID()); - S32 i; - EInstantMessage type = IM_SESSION_ADD; - if(only_online) - { - LLAvatarTracker& at = LLAvatarTracker::instance(); - LLUUID id; - for(i = 0; i < count; ++i) - { - id = item_array.get(i)->getCreatorUUID(); - if(at.isBuddyOnline(id)) - { - members.put(id); - } - } - } - else - { - type = IM_SESSION_OFFLINE_ADD; - for(i = 0; i < count; ++i) - { - members.put(item_array.get(i)->getCreatorUUID()); - } - } - // the session_id is always the item_id of the inventory folder - gIMView->addSession(cat->getName(), - type, - mUUID, - members); - } -} - void LLFolderBridge::modifyOutfit(BOOL append) { LLInventoryModel* model = mInventoryPanel->getModel(); @@ -2689,11 +2637,13 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) items.push_back("Send Instant Message"); items.push_back("Offer Teleport..."); + items.push_back("Conference Chat"); if (!good_card) { disabled_items.push_back("Send Instant Message"); disabled_items.push_back("Offer Teleport..."); + disabled_items.push_back("Conference Chat"); } } hideContextEntries(menu, items, disabled_items); diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index ddfc4fe791..d91ca7fc75 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -296,7 +296,6 @@ protected: BOOL checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& typeToCheck); - void beginIMSession(BOOL only_online); void modifyOutfit(BOOL append); public: static LLFolderBridge* sSelf; diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index b834845107..edc4ba0ca6 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1823,7 +1823,7 @@ void LLInventoryModel::buildParentChildMap() msg->addUUIDFast(_PREHASH_ItemID, (*it)); msg->addUUIDFast(_PREHASH_FolderID, lnf); msg->addString("NewName", NULL); - if(msg->mCurrentSendTotal >= MTUBYTES) + if(msg->isSendFull(NULL)) { start_new_message = TRUE; gAgent.sendReliableMessage(); @@ -3182,7 +3182,7 @@ void LLInventoryFetchObserver::fetchItems( msg->nextBlockFast(_PREHASH_InventoryData); msg->addUUIDFast(_PREHASH_OwnerID, owner_id); msg->addUUIDFast(_PREHASH_ItemID, (*it)); - if(msg->getCurrentSendTotal() >= MTUBYTES) + if(msg->isSendFull(NULL)) { start_new_message = TRUE; gAgent.sendReliableMessage(); diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp index 6aca7abc11..7ba0ccad3a 100644 --- a/indra/newview/llmutelist.cpp +++ b/indra/newview/llmutelist.cpp @@ -36,7 +36,7 @@ #include "llagent.h" #include "llfloatermute.h" -#include "llviewermessage.h" // for gGenericDispatcher +#include "llviewergenericmessage.h" // for gGenericDispatcher #include "llviewerwindow.h" #include "viewer.h" #include "llworld.h" //for particle system banning diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index d8c2987470..bc451ecfc0 100644 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -175,20 +175,28 @@ LLScrollListItem* LLNameListCtrl::addElement(const LLSD& value, EAddPosition pos char first[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ char last[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ - LLString fullname; - if (gCacheName->getName(item->getUUID(), first, last)) - { - fullname.assign(first); - fullname.append(1, ' '); - fullname.append(last); - } - else // didn't work as a resident name, try looking up as a group + // use supplied name by default + LLString fullname = value["name"].asString(); + if (value["target"].asString() == "GROUP") { char group_name[DB_GROUP_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ gCacheName->getGroupName(item->getUUID(), group_name); // fullname will be "nobody" if group not found fullname = group_name; } + else if (value["target"].asString() == "SPECIAL") + { + // just use supplied name + } + else // normal resident + { + if (gCacheName->getName(item->getUUID(), first, last)) + { + fullname.assign(first); + fullname.append(1, ' '); + fullname.append(last); + } + } LLScrollListCell* cell = (LLScrollListCell*)item->getColumn(mNameColumnIndex); ((LLScrollListText*)cell)->setText( fullname ); @@ -429,3 +437,4 @@ LLView* LLNameListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto return name_list; } + diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 1b0c731ea9..383d2846c0 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -30,7 +30,6 @@ #include "llfloatergroupinfo.h" #include "llfloaterworldmap.h" #include "llfloatermute.h" -#include "llfloaterrate.h" #include "llfloateravatarinfo.h" #include "lliconctrl.h" #include "llinventoryview.h" @@ -48,7 +47,7 @@ #include "lluiconstants.h" #include "llvoavatar.h" #include "llviewermenu.h" // *FIX: for is_agent_friend() -#include "llviewermessage.h" // send_generic_message +#include "llviewergenericmessage.h" // send_generic_message #include "llviewerobjectlist.h" #include "llviewerregion.h" #include "llviewborder.h" @@ -258,14 +257,13 @@ void LLPanelAvatarTab::draw() } } -void LLPanelAvatarTab::sendAvatarProfileRequestIfNeeded(const char* type) +void LLPanelAvatarTab::sendAvatarProfileRequestIfNeeded(const char* method) { if (!mDataRequested) { std::vector<std::string> strings; strings.push_back( mPanelAvatar->getAvatarID().asString() ); - strings.push_back( type ); - send_generic_message("avatarprofilerequest", strings); + send_generic_message(method, strings); mDataRequested = true; } } @@ -449,7 +447,7 @@ BOOL LLPanelAvatarSecondLife::postBuild(void) childSetAction("Show on Map", LLPanelAvatar::onClickTrack, getPanelAvatar()); childSetAction("Instant Message...", LLPanelAvatar::onClickIM, getPanelAvatar()); - //childSetAction("Rate...", LLPanelAvatar::onClickRate, getPanelAvatar()); + childSetAction("Add Friend...", LLPanelAvatar::onClickAddFriend, getPanelAvatar()); childSetAction("Pay...", LLPanelAvatar::onClickPay, getPanelAvatar()); childSetAction("Mute", LLPanelAvatar::onClickMute, getPanelAvatar() ); @@ -807,7 +805,7 @@ LLPanelAvatarNotes::LLPanelAvatarNotes(const std::string& name, const LLRect& re void LLPanelAvatarNotes::refresh() { - sendAvatarProfileRequestIfNeeded("notes"); + sendAvatarProfileRequestIfNeeded("avatarnotesrequest"); } void LLPanelAvatarNotes::clearControls() @@ -851,7 +849,7 @@ void LLPanelAvatarClassified::refresh() childSetEnabled("Delete...",self && allow_delete); childSetVisible("classified tab",!show_help); - sendAvatarProfileRequestIfNeeded("classifieds"); + sendAvatarProfileRequestIfNeeded("avatarclassifiedsrequest"); } @@ -1052,7 +1050,7 @@ void LLPanelAvatarPicks::refresh() childSetEnabled("New...",self && allow_new); childSetEnabled("Delete...",self && allow_delete); - sendAvatarProfileRequestIfNeeded("picks"); + sendAvatarProfileRequestIfNeeded("avatarpicksrequest"); } @@ -1083,6 +1081,9 @@ void LLPanelAvatarPicks::processAvatarPicksReply(LLMessageSystem* msg, void**) // number of new panels. deletePickPanels(); + // The database needs to know for which user to look up picks. + LLUUID avatar_id = getPanelAvatar()->getAvatarID(); + block_count = msg->getNumberOfBlocks("Data"); for (block = 0; block < block_count; block++) { @@ -1091,7 +1092,7 @@ void LLPanelAvatarPicks::processAvatarPicksReply(LLMessageSystem* msg, void**) panel_pick = new LLPanelPick(FALSE); - panel_pick->setPickID(pick_id); + panel_pick->setPickID(pick_id, avatar_id); // This will request data from the server when the pick is first // drawn. @@ -1170,23 +1171,24 @@ void LLPanelAvatarPicks::callbackDelete(S32 option, void* data) if(gAgent.isGodlike()) { msg->newMessage("PickGodDelete"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgent.getID()); + msg->addUUID("SessionID", gAgent.getSessionID()); + msg->nextBlock("Data"); + msg->addUUID("PickID", panel_pick->getPickID()); + // *HACK: We need to send the pick's creator id to accomplish + // the delete, and we don't use the query id for anything. JC + msg->addUUID( "QueryID", panel_pick->getPickCreatorID() ); } else { msg->newMessage("PickDelete"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgent.getID()); + msg->addUUID("SessionID", gAgent.getSessionID()); + msg->nextBlock("Data"); + msg->addUUID("PickID", panel_pick->getPickID()); } - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); - msg->addUUID("SessionID", gAgent.getSessionID()); - msg->nextBlock("Data"); - msg->addUUID("PickID", panel_pick->getPickID()); - - //God delete receiving end expects a query ID but we dont need it, so send a null. - //This is to resolve SL-24170 God Picks Delete results in crash. - if(gAgent.isGodlike()) - msg->addUUID( "QueryID", LLUUID::null ); - - gAgent.sendReliableMessage(); if(tabs) @@ -1219,8 +1221,7 @@ LLPanelAvatar::LLPanelAvatar( mAvatarID( LLUUID::null ), // mAvatarID is set with 'setAvatar' or 'setAvatarID' mHaveProperties(FALSE), mHaveStatistics(FALSE), - mAllowEdit(allow_edit), - mDisableRate(FALSE) + mAllowEdit(allow_edit) { sAllPanels.push_back(this); @@ -1435,8 +1436,6 @@ void LLPanelAvatar::setAvatarID(const LLUUID &avatar_id, const LLString &name, childSetEnabled("drop target",FALSE); childSetVisible("Show on Map",FALSE); childSetEnabled("Show on Map",FALSE); - childSetVisible("Rate...",FALSE); - childSetEnabled("Rate...",FALSE); childSetVisible("Add Friend...",FALSE); childSetEnabled("Add Friend...",FALSE); childSetVisible("Pay...",FALSE); @@ -1475,8 +1474,6 @@ void LLPanelAvatar::setAvatarID(const LLUUID &avatar_id, const LLString &name, { childSetToolTip("Show on Map",childGetValue("ShowOnMapFriendOnline").asString()); } - childSetVisible("Rate...",TRUE); - childSetEnabled("Rate...",FALSE); childSetVisible("Add Friend...", true); childSetEnabled("Add Friend...", true); childSetVisible("Pay...",TRUE); @@ -1576,16 +1573,6 @@ void LLPanelAvatar::onClickTrack(void* userdata) } } -// static -//----------------------------------------------------------------------------- -// onClickRate() -//----------------------------------------------------------------------------- -void LLPanelAvatar::onClickRate(void *userdata) -{ - LLPanelAvatar* self = (LLPanelAvatar*) userdata; - - LLFloaterRate::show(self->mAvatarID); -} // static void LLPanelAvatar::onClickAddFriend(void* userdata) @@ -1627,15 +1614,6 @@ void LLPanelAvatar::onClickMute(void *userdata) } -void LLPanelAvatar::disableRate() -{ - // Force off the rate button, but enable IM. - // Note that these buttons may not exist if it is your own profile. - childSetEnabled("Rate...",FALSE); - mDisableRate = TRUE; -} - - // static void LLPanelAvatar::onClickOfferTeleport(void *userdata) { @@ -1783,10 +1761,6 @@ void LLPanelAvatar::processAvatarPropertiesReply(LLMessageSystem *msg, void**) self->childSetEnabled("Pay...",TRUE); self->childSetEnabled("Mute",TRUE); - if (!self->mDisableRate) - { - self->childSetEnabled("Rate...",TRUE); - } self->childSetEnabled("drop target",TRUE); self->mHaveProperties = TRUE; @@ -2015,7 +1989,7 @@ void LLPanelAvatar::processAvatarGroupsReply(LLMessageSystem *msg, void**) // Otherwise you will write blanks back into the database. void LLPanelAvatar::enableOKIfReady() { - if(mHaveProperties && mHaveStatistics && childIsVisible("OK")) + if(mHaveProperties && childIsVisible("OK")) { childSetEnabled("OK", TRUE); } @@ -2121,69 +2095,6 @@ void LLPanelAvatar::selectTabByName(std::string tab_name) } -// static -void LLPanelAvatar::processAvatarStatisticsReply(LLMessageSystem *msg, void**) -{ - // extract the agent id - LLUUID agent_id; - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id ); - - LLUUID avatar_id; - msg->getUUIDFast(_PREHASH_AvatarData, _PREHASH_AvatarID, avatar_id); - - // look up all panels which have this avatar - for (panel_list_t::iterator iter = sAllPanels.begin(); iter != sAllPanels.end(); ++iter) - { - LLPanelAvatar* self = *iter; - if (self->mAvatarID != avatar_id) - { - continue; - } - - self->mHaveStatistics = TRUE; - self->enableOKIfReady(); - - // clear out list - LLScrollListCtrl* ratings_list = LLUICtrlFactory::getScrollListByName(self->mPanelSecondLife,"ratings"); - if (ratings_list) - { - ratings_list->deleteAllItems(); - } - // build the item list - S32 items = msg->getNumberOfBlocksFast(_PREHASH_StatisticsData); - for (S32 i = 0; i < items; i++) - { - char name[MAX_STRING]; /*Flawfinder: ignore*/ - S32 positive; - S32 negative; - char value_string[MAX_STRING]; /*Flawfinder: ignore*/ - - msg->getStringFast( _PREHASH_StatisticsData, - _PREHASH_Name, MAX_STRING, name, i); - msg->getS32( "StatisticsData", "Positive", positive, i); - msg->getS32( "StatisticsData", "Negative", negative, i); - - const S32 TEXT_WIDTH = 75; - - LLSD row; - row["columns"][0]["value"] = name; - row["columns"][0]["font"] = "SANSSERIF_SMALL"; - row["columns"][0]["width"] = TEXT_WIDTH; - row["columns"][1]["value"] = value_string; - row["columns"][1]["font"] = "SANSSERIF_SMALL"; - row["columns"][1]["width"] = 50; - row["columns"][2]["value"] = ""; - row["columns"][2]["font"] = "SANSSERIF_SMALL"; - - if(ratings_list) - { - ratings_list->addElement( row ); - } - } - } -} - - void LLPanelAvatar::processAvatarNotesReply(LLMessageSystem *msg, void**) { // extract the agent id diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h index 994d23b7d3..f54da2538f 100644 --- a/indra/newview/llpanelavatar.h +++ b/indra/newview/llpanelavatar.h @@ -60,8 +60,9 @@ public: // If the data for this tab has not yet been requested, // send the request. Used by tabs that are filled in only // when they are first displayed. - // type is one of "notes", "classifieds", "picks" - void sendAvatarProfileRequestIfNeeded(const char* type); + // type is one of "avatarnotesrequest", "avatarpicksrequest", + // or "avatarclassifiedsrequest" + void sendAvatarProfileRequestIfNeeded(const char* method); private: LLPanelAvatar* mPanelAvatar; @@ -256,8 +257,6 @@ public: void setOnlineStatus(EOnlineStatus online_status); const LLUUID& getAvatarID() const { return mAvatarID; } - - void disableRate(); void resetGroupList(); @@ -279,7 +278,6 @@ public: static void processAvatarPropertiesReply(LLMessageSystem *msg, void **); static void processAvatarInterestsReply(LLMessageSystem *msg, void **); static void processAvatarGroupsReply(LLMessageSystem* msg, void**); - static void processAvatarStatisticsReply(LLMessageSystem *msg, void **); static void processAvatarNotesReply(LLMessageSystem *msg, void **); static void processAvatarPicksReply(LLMessageSystem *msg, void **); static void processAvatarClassifiedReply(LLMessageSystem *msg, void **); @@ -288,7 +286,6 @@ public: static void onClickIM( void *userdata); static void onClickOfferTeleport( void *userdata); static void onClickPay( void *userdata); - static void onClickRate( void *userdata); static void onClickAddFriend(void* userdata); static void onClickOK( void *userdata); static void onClickCancel( void *userdata); @@ -337,7 +334,6 @@ protected: BOOL mHaveStatistics; LLTabContainerCommon* mTab; BOOL mAllowEdit; - BOOL mDisableRate; typedef std::list<LLPanelAvatar*> panel_list_t; static panel_list_t sAllPanels; diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index 5c5e0479d4..95ed517794 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -38,7 +38,7 @@ #include "llviewerwindow.h" #include "llworldmap.h" #include "llfloaterworldmap.h" -#include "llviewermessage.h" // send_generic_message +#include "llviewergenericmessage.h" // send_generic_message #include "llviewerwindow.h" // for window width, height const S32 MINIMUM_PRICE_FOR_LISTING = 50; // L$ diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index 9d40357544..610bfec8ae 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -146,6 +146,7 @@ BOOL LLPanelGroupGeneral::postBuild() { mCtrlMature->setCommitCallback(onCommitAny); mCtrlMature->setCallbackUserData(this); + mCtrlMature->setVisible( gAgent.mAccess > SIM_ACCESS_PG ); } mCtrlOpenEnrollment = (LLCheckBoxCtrl*) getChildByName("open_enrollement", recurse); @@ -447,7 +448,17 @@ bool LLPanelGroupGeneral::apply(LLString& mesg) if (mCtrlPublishOnWeb) gdatap->mAllowPublish = mCtrlPublishOnWeb->get(); if (mEditCharter) gdatap->mCharter = mEditCharter->getText(); if (mInsignia) gdatap->mInsigniaID = mInsignia->getImageAssetID(); - if (mCtrlMature) gdatap->mMaturePublish = mCtrlMature->get(); + if (mCtrlMature) + { + if (gAgent.mAccess > SIM_ACCESS_PG) + { + gdatap->mMaturePublish = mCtrlMature->get(); + } + else + { + gdatap->mMaturePublish = FALSE; + } + } if (mCtrlShowInGroupList) gdatap->mShowInList = mCtrlShowInGroupList->get(); } @@ -598,6 +609,7 @@ void LLPanelGroupGeneral::update(LLGroupChange gc) { mCtrlMature->set(gdatap->mMaturePublish); mCtrlMature->setEnabled(mAllowEdit && can_change_ident); + mCtrlMature->setVisible( gAgent.mAccess > SIM_ACCESS_PG ); } if (mCtrlOpenEnrollment) { diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp index a05f7c54c6..ff2a64075c 100644 --- a/indra/newview/llpanelpick.cpp +++ b/indra/newview/llpanelpick.cpp @@ -28,6 +28,7 @@ #include "llviewertexteditor.h" #include "lltexturectrl.h" #include "lluiconstants.h" +#include "llviewergenericmessage.h" #include "llvieweruictrlfactory.h" #include "llviewerparcelmgr.h" #include "llworldmap.h" @@ -165,9 +166,10 @@ void LLPanelPick::initNewPick() } -void LLPanelPick::setPickID(const LLUUID& id) +void LLPanelPick::setPickID(const LLUUID& pick_id, const LLUUID& creator_id) { - mPickID = id; + mPickID = pick_id; + mCreatorID = creator_id; } @@ -188,15 +190,12 @@ std::string LLPanelPick::getPickName() void LLPanelPick::sendPickInfoRequest() { - LLMessageSystem *msg = gMessageSystem; - - msg->newMessage("PickInfoRequest"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID() ); - msg->addUUID("SessionID", gAgent.getSessionID()); - msg->nextBlock("Data"); - msg->addUUID("PickID", mPickID); - gAgent.sendReliableMessage(); + // Must ask for a pick based on the creator id because + // the pick database is distributed to the inventory cluster. JC + std::vector<std::string> strings; + strings.push_back( mCreatorID.asString() ); + strings.push_back( mPickID.asString() ); + send_generic_message("pickinforequest", strings); mDataRequested = TRUE; } diff --git a/indra/newview/llpanelpick.h b/indra/newview/llpanelpick.h index a347133be6..232bbb736a 100644 --- a/indra/newview/llpanelpick.h +++ b/indra/newview/llpanelpick.h @@ -39,13 +39,15 @@ public: /*virtual*/ void draw(); - void refresh(); + /*virtual*/ void refresh(); // Setup a new pick, including creating an id, giving a sane // initial position, etc. void initNewPick(); - void setPickID(const LLUUID& id); + // We need to know the creator id so the database knows which partition + // to query for the pick data. + void setPickID(const LLUUID& pick_id, const LLUUID& creator_id); // Schedules the panel to request data // from the server next time it is drawn. @@ -53,6 +55,7 @@ public: std::string getPickName(); const LLUUID& getPickID() const { return mPickID; } + const LLUUID& getPickCreatorID() const { return mCreatorID; } void sendPickInfoRequest(); void sendPickInfoUpdate(); diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index cd4d8d2f87..a02dd912e3 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -32,7 +32,6 @@ #include "lldrawable.h" #include "llfloaterinspect.h" #include "llfloaterproperties.h" -#include "llfloaterrate.h" #include "llfloaterreporter.h" #include "llfloatertools.h" #include "llframetimer.h" @@ -542,7 +541,7 @@ void LLSelectMgr::deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_s msg->addU32Fast(_PREHASH_ObjectLocalID, (objects[i])->getLocalID()); select_count++; - if(msg->mCurrentSendTotal >= MTUBYTES || select_count >= MAX_OBJECTS_PER_PACKET) + if(msg->isSendFull(NULL) || select_count >= MAX_OBJECTS_PER_PACKET) { msg->sendReliable(regionp->getHost() ); select_count = 0; @@ -4179,7 +4178,7 @@ void LLSelectMgr::sendListToRegions(const LLString& message_name, // if to same simulator and message not too big if ((current_region == last_region) - && (gMessageSystem->mCurrentSendTotal < MTUBYTES) + && (! gMessageSystem->isSendFull(NULL)) && (objects_in_this_packet < MAX_OBJECTS_PER_PACKET)) { // add another instance of the body of the data @@ -4214,7 +4213,7 @@ void LLSelectMgr::sendListToRegions(const LLString& message_name, } // flush messages - if (gMessageSystem->mCurrentSendTotal > 0) + if (gMessageSystem->getCurrentSendTotal() > 0) { gMessageSystem->sendReliable( current_region->getHost()); packets_sent++; @@ -6220,7 +6219,6 @@ BOOL LLObjectSelection::getOwnershipCost(S32 &cost) } - //----------------------------------------------------------------------------- // getObjectCount() //----------------------------------------------------------------------------- @@ -6556,3 +6554,4 @@ LLViewerObject* LLObjectSelection::getFirstMoveableObject(BOOL get_root) return object; } + diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index baf6abda11..4bbdca521c 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -35,6 +35,7 @@ #include "llloginflags.h" #include "llmd5.h" #include "llmemorystream.h" +#include "llmessageconfig.h" #include "llregionhandle.h" #include "llsd.h" #include "llsdserialize.h" @@ -67,7 +68,6 @@ #include "llfloatergesture.h" #include "llfloaterland.h" #include "llfloatertopobjects.h" -#include "llfloaterrate.h" #include "llfloatertos.h" #include "llfloaterworldmap.h" #include "llframestats.h" @@ -108,6 +108,7 @@ #include "llviewerassetstorage.h" #include "llviewercamera.h" #include "llviewerdisplay.h" +#include "llviewergenericmessage.h" #include "llviewergesture.h" #include "llviewerimagelist.h" #include "llviewermenu.h" @@ -398,6 +399,7 @@ BOOL idle_startup() port = gSavedSettings.getU32("ConnectionPort"); } + LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); if(!start_messaging_system( message_template_path, port, @@ -941,16 +943,7 @@ BOOL idle_startup() } llinfos << "Verifying message template..." << llendl; - - // register with the message system so it knows we're - // expecting this message - LLMessageSystem* msg = gMessageSystem; - msg->setHandlerFuncFast(_PREHASH_TemplateChecksumReply, null_message_callback, NULL); - msg->newMessageFast(_PREHASH_SecuredTemplateChecksumRequest); - msg->nextBlockFast(_PREHASH_TokenBlock); - lldebugs << "random token: " << gTemplateToken << llendl; - msg->addUUIDFast(_PREHASH_Token, gTemplateToken); - msg->sendReliable(mt_host); + LLMessageSystem::sendSecureMessageTemplateChecksum(mt_host); timeout.reset(); gStartupState++; @@ -959,40 +952,16 @@ BOOL idle_startup() if (STATE_MESSAGE_TEMPLATE_WAIT == gStartupState) { - U32 remote_template_checksum = 0; - - U8 major_version = 0; - U8 minor_version = 0; - U8 patch_version = 0; - U8 server_version = 0; - U32 flags = 0x0; - LLMessageSystem* msg = gMessageSystem; - while (msg->checkMessages(gFrameCount)) + while (msg->checkAllMessages(gFrameCount, gServicePump)) { - if (msg->isMessageFast(_PREHASH_TemplateChecksumReply)) + if (msg->isTemplateConfirmed()) { - LLUUID token; - msg->getUUID("TokenBlock", "Token", token); - if(token != gTemplateToken) - { - llwarns << "Incorrect token in template checksum reply: " - << token << llendl; - return do_normal_idle; - } - msg->getU32("DataBlock", "Checksum", remote_template_checksum); - msg->getU8 ("DataBlock", "MajorVersion", major_version); - msg->getU8 ("DataBlock", "MinorVersion", minor_version); - msg->getU8 ("DataBlock", "PatchVersion", patch_version); - msg->getU8 ("DataBlock", "ServerVersion", server_version); - msg->getU32("DataBlock", "Flags", flags); - BOOL update_available = FALSE; BOOL mandatory = FALSE; - if (remote_template_checksum != msg->mMessageFileChecksum) + if (!LLMessageSystem::doesTemplateMatch()) { - llinfos << "Message template out of sync" << llendl; // Mandatory update -- message template checksum doesn't match update_available = TRUE; mandatory = TRUE; @@ -1012,6 +981,7 @@ BOOL idle_startup() quit = TRUE; } } + // Bail out and clean up circuit if (quit) { @@ -1022,7 +992,6 @@ BOOL idle_startup() } // If we get here, we've got a compatible message template - if (!mandatory) { llinfos << "Message template is current!" << llendl; @@ -1189,7 +1158,7 @@ BOOL idle_startup() } // Process messages to keep from dropping circuit. LLMessageSystem* msg = gMessageSystem; - while (msg->checkMessages(gFrameCount)) + while (msg->checkAllMessages(gFrameCount, gServicePump)) { } msg->processAcks(); @@ -1214,7 +1183,7 @@ BOOL idle_startup() } // Process messages to keep from dropping circuit. LLMessageSystem* msg = gMessageSystem; - while (msg->checkMessages(gFrameCount)) + while (msg->checkAllMessages(gFrameCount, gServicePump)) { } msg->processAcks(); @@ -1920,7 +1889,7 @@ BOOL idle_startup() ++gStartupState; } LLMessageSystem* msg = gMessageSystem; - while (msg->checkMessages(gFrameCount)) + while (msg->checkAllMessages(gFrameCount, gServicePump)) { } msg->processAcks(); @@ -1939,8 +1908,7 @@ BOOL idle_startup() LLMessageSystem* msg = gMessageSystem; msg->setHandlerFuncFast( _PREHASH_AgentMovementComplete, - process_agent_movement_complete, - NULL); + process_agent_movement_complete); LLViewerRegion* regionp = gAgent.getRegion(); if(!gRunLocal && regionp) { @@ -1977,9 +1945,9 @@ BOOL idle_startup() if (STATE_AGENT_WAIT == gStartupState) { LLMessageSystem* msg = gMessageSystem; - while (msg->checkMessages(gFrameCount)) + while (msg->checkAllMessages(gFrameCount, gServicePump)) { - if (msg->isMessageFast(_PREHASH_AgentMovementComplete)) + if (gAgentMovementCompleted) { gStartupState++; // Sometimes we have more than one message in the @@ -2887,7 +2855,21 @@ void update_dialog_callback(S32 option, void *userdata) } return; } - + + LLSD query_map = LLSD::emptyMap(); + // *TODO place os string in a global constant +#if LL_WINDOWS + query_map["os"] = "win"; +#elif LL_DARWIN + query_map["os"] = "mac"; +#elif LL_LINUX + query_map["os"] = "lnx"; +#endif + query_map["userserver"] = gUserServerName; + query_map["channel"] = gChannelName; + // *TODO constantize this guy + LLURI update_url = LLURI::buildHTTP("secondlife.com", 80, "update.php", query_map); + #if LL_WINDOWS char ip[MAX_STRING]; /* Flawfinder: ignore */ @@ -2919,9 +2901,6 @@ void update_dialog_callback(S32 option, void *userdata) } u32_to_ip_string(gUserServer.getAddress(), ip); - std::ostringstream params; - params << "-userserver " << gUserServerName; - // if a sim name was passed in via command line parameter (typically through a SLURL) if ( LLURLSimString::sInstance.mSimString.length() ) { @@ -2929,6 +2908,8 @@ void update_dialog_callback(S32 option, void *userdata) gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString ); }; + std::ostringstream params; + params << "-url \"" << update_url.asString() << "\""; if (gHideLinks) { // Figure out the program name. @@ -2949,7 +2930,8 @@ void update_dialog_callback(S32 option, void *userdata) program_name = "SecondLife"; } - params << " -silent -name \"" << gSecondLife << "\" -program \"" << program_name << "\""; + params << " -silent -name \"" << gSecondLife << "\""; + params << " -program \"" << program_name << "\""; } llinfos << "Calling updater: " << update_exe_path << " " << params.str() << llendl; @@ -2967,12 +2949,12 @@ void update_dialog_callback(S32 option, void *userdata) // record the location to start at next time gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString ); }; - + update_exe_path = "'"; update_exe_path += gDirUtilp->getAppRODataDir(); - update_exe_path += "/AutoUpdater.app/Contents/MacOS/AutoUpdater' -userserver "; - update_exe_path += gUserServerName; - update_exe_path += " -name \""; + update_exe_path += "/AutoUpdater.app/Contents/MacOS/AutoUpdater' -url \""; + update_exe_path += update_url.asString(); + update_exe_path += "\" -name \""; update_exe_path += gSecondLife; update_exe_path += "\" &"; @@ -3100,8 +3082,9 @@ void register_viewer_callbacks(LLMessageSystem* msg) LLPanelAvatar::processAvatarInterestsReply); msg->setHandlerFunc("AvatarGroupsReply", LLPanelAvatar::processAvatarGroupsReply); - msg->setHandlerFuncFast(_PREHASH_AvatarStatisticsReply, - LLPanelAvatar::processAvatarStatisticsReply); + // ratings deprecated + //msg->setHandlerFuncFast(_PREHASH_AvatarStatisticsReply, + // LLPanelAvatar::processAvatarStatisticsReply); msg->setHandlerFunc("AvatarNotesReply", LLPanelAvatar::processAvatarNotesReply); msg->setHandlerFunc("AvatarPicksReply", @@ -3120,8 +3103,9 @@ void register_viewer_callbacks(LLMessageSystem* msg) msg->setHandlerFuncFast(_PREHASH_GroupProfileReply, LLGroupMgr::processGroupPropertiesReply); - msg->setHandlerFuncFast(_PREHASH_ReputationIndividualReply, - LLFloaterRate::processReputationIndividualReply); + // ratings deprecated + // msg->setHandlerFuncFast(_PREHASH_ReputationIndividualReply, + // LLFloaterRate::processReputationIndividualReply); msg->setHandlerFuncFast(_PREHASH_AgentWearablesUpdate, LLAgent::processAgentInitialWearablesUpdate ); @@ -3129,9 +3113,6 @@ void register_viewer_callbacks(LLMessageSystem* msg) msg->setHandlerFunc("ScriptControlChange", LLAgent::processScriptControlChange ); - msg->setHandlerFuncFast(_PREHASH_GestureUpdate, - LLViewerGestureList::processGestureUpdate); - msg->setHandlerFuncFast(_PREHASH_ViewerEffect, LLHUDManager::processViewerEffect); msg->setHandlerFuncFast(_PREHASH_GrantGodlikePowers, process_grant_godlike_powers); diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index e5952f4f5b..7d64640fb0 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -61,6 +61,7 @@ enum EStartupState{ // exorted symbol extern S32 gStartupState; +extern BOOL gAgentMovementCompleted; extern bool gQuickTimeInitialized; extern LLPointer<LLImageGL> gStartImageGL; diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index c732394b4e..bc5efa20aa 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -1012,7 +1012,7 @@ void LLTextureCtrl::setEnabled( BOOL enabled ) mCaption->setEnabled( enabled ); - LLUICtrl::setEnabled( enabled ); + LLView::setEnabled( enabled ); } void LLTextureCtrl::setValid(BOOL valid ) diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index b4aee4e2e1..64ec8f0b2f 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -1219,6 +1219,7 @@ BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj, return FALSE; } } +std::cout << "ASSET ID: " << new_item->getAssetUUID() << "\n"; hit_obj->updateInventory(new_item, TASK_INVENTORY_ASSET_KEY, true); } else if(!item->getPermissions().allowOperationBy(PERM_TRANSFER, @@ -1232,6 +1233,7 @@ BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj, // *FIX: may want to make sure agent can paint hit_obj. // make sure the object has the texture in it's inventory. +std::cout << "ASSET ID: " << new_item->getAssetUUID() << "\n"; hit_obj->updateInventory(new_item, TASK_INVENTORY_ASSET_KEY, true); } return TRUE; diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index ee878c1dc0..cbb37e5fe4 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -253,7 +253,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield) gViewerWindow->setShowProgress(TRUE); gViewerWindow->setProgressPercent(0); gAgent.setTeleportState( LLAgent::TELEPORT_REQUESTED ); - gAgent.setTeleportMessage("Requesting Teleport..."); + gAgent.setTeleportMessage( + LLAgent::sTeleportProgressMessages["requesting"]); break; case LLAgent::TELEPORT_REQUESTED: @@ -274,7 +275,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield) gViewerWindow->setProgressCancelButtonVisible(FALSE, "Cancel"); gViewerWindow->setProgressPercent(75.f); gAgent.setTeleportState( LLAgent::TELEPORT_ARRIVING ); - gAgent.setTeleportMessage("Arriving..."); + gAgent.setTeleportMessage( + LLAgent::sTeleportProgressMessages["arriving"]); gImageList.mForceResetTextureStats = TRUE; break; diff --git a/indra/newview/llviewergenericmessage.cpp b/indra/newview/llviewergenericmessage.cpp new file mode 100644 index 0000000000..d155d11570 --- /dev/null +++ b/indra/newview/llviewergenericmessage.cpp @@ -0,0 +1,77 @@ +/** + * @file llviewergenericmessage.cpp + * @brief Handle processing of "generic messages" which contain short lists of strings. + * @author James Cook + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llviewergenericmessage.h" + +#include "lldispatcher.h" +#include "lluuid.h" +#include "message.h" + +#include "llagent.h" + + +LLDispatcher gGenericDispatcher; + + +void send_generic_message(const char* method, + const std::vector<std::string>& strings, + const LLUUID& invoice) +{ + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("GenericMessage"); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used + msg->nextBlock("MethodData"); + msg->addString("Method", method); + msg->addUUID("Invoice", invoice); + if(strings.empty()) + { + msg->nextBlock("ParamList"); + msg->addString("Parameter", NULL); + } + else + { + std::vector<std::string>::const_iterator it = strings.begin(); + std::vector<std::string>::const_iterator end = strings.end(); + for(; it != end; ++it) + { + msg->nextBlock("ParamList"); + msg->addString("Parameter", (*it).c_str()); + } + } + gAgent.sendReliableMessage(); +} + + + +void process_generic_message(LLMessageSystem* msg, void**) +{ + LLUUID agent_id; + msg->getUUID("AgentData", "AgentID", agent_id); + if (agent_id != gAgent.getID()) + { + llwarns << "GenericMessage for wrong agent" << llendl; + return; + } + + std::string request; + LLUUID invoice; + LLDispatcher::sparam_t strings; + LLDispatcher::unpackMessage(msg, request, invoice, strings); + + if(!gGenericDispatcher.dispatch(request, invoice, strings)) + { + llwarns << "GenericMessage " << request << " failed to dispatch" + << llendl; + } +} diff --git a/indra/newview/llviewergenericmessage.h b/indra/newview/llviewergenericmessage.h new file mode 100644 index 0000000000..547421648c --- /dev/null +++ b/indra/newview/llviewergenericmessage.h @@ -0,0 +1,26 @@ +/** + * @file llviewergenericmessage.h + * @brief Handle processing of "generic messages" which contain short lists of strings. + * @author James Cook + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#ifndef LLVIEWERGENERICMESSAGE_H +#define LLVIEWERGENERICMESSAGE_H + +class LLUUID; +class LLDispatcher; + + +void send_generic_message(const char* method, + const std::vector<std::string>& strings, + const LLUUID& invoice = LLUUID::null); + +void process_generic_message(LLMessageSystem* msg, void**); + + +extern LLDispatcher gGenericDispatcher; + +#endif diff --git a/indra/newview/llviewergesture.cpp b/indra/newview/llviewergesture.cpp index 69bee4431f..f5ef19cc33 100644 --- a/indra/newview/llviewergesture.cpp +++ b/indra/newview/llviewergesture.cpp @@ -123,69 +123,6 @@ LLViewerGestureList::LLViewerGestureList() mIsLoaded = FALSE; } -void LLViewerGestureList::saveToServer() -{ - U8 *buffer = new U8[getMaxSerialSize()]; - - U8 *end = serialize(buffer); - - if (end - buffer > getMaxSerialSize()) - { - llerrs << "Wrote off end of buffer, serial size computation is wrong" << llendl; - } - - //U64 xfer_id = gXferManager->registerXfer(buffer, end - buffer); - // write to a file because mem<->mem xfer isn't implemented - LLUUID random_uuid; - char filename[LL_MAX_PATH]; /* Flawfinder: ignore */ - random_uuid.generate(); - random_uuid.toString(filename); - strcat(filename,".tmp"); /* Flawfinder: ignore */ - - char filename_and_path[LL_MAX_PATH]; /* Flawfinder: ignore */ - snprintf(filename_and_path, LL_MAX_PATH, "%s%s%s", /* Flawfinder: ignore */ - gDirUtilp->getTempDir().c_str(), - gDirUtilp->getDirDelimiter().c_str(), - filename); - - FILE* fp = LLFile::fopen(filename_and_path, "wb"); /* Flawfinder: ignore */ - - if (fp) - { - fwrite(buffer, end - buffer, 1, fp); - fclose(fp); - - gMessageSystem->newMessageFast(_PREHASH_GestureUpdate); - gMessageSystem->nextBlockFast(_PREHASH_AgentBlock); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addStringFast(_PREHASH_Filename, filename); - gMessageSystem->addBOOLFast(_PREHASH_ToViewer, FALSE); - gMessageSystem->sendReliable(gUserServer); - } - - delete[] buffer; -} - -/* -void LLViewerGestureList::requestFromServer() -{ - gMessageSystem->newMessageFast(_PREHASH_GestureRequest); - gMessageSystem->nextBlockFast(_PREHASH_AgentBlock); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, agent_get_id()); - gMessageSystem->addU8("Reset", 0); - gMessageSystem->sendReliable(gUserServer); -} - -void LLViewerGestureList::requestResetFromServer( BOOL is_male ) -{ - gMessageSystem->newMessageFast(_PREHASH_GestureRequest); - gMessageSystem->nextBlockFast(_PREHASH_AgentBlock); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, agent_get_id()); - gMessageSystem->addU8("Reset", is_male ? 1 : 2); - gMessageSystem->sendReliable(gUserServer); - mIsLoaded = FALSE; -} -*/ // helper for deserialize that creates the right LLGesture subclass LLGesture *LLViewerGestureList::create_gesture(U8 **buffer, S32 max_size) @@ -247,14 +184,3 @@ void LLViewerGestureList::xferCallback(void *data, S32 size, void** /*user_data* llwarns << "Unable to load gesture list!" << llendl; } } - -// static -void LLViewerGestureList::processGestureUpdate(LLMessageSystem *msg, void** /*user_data*/) -{ - char remote_filename[MAX_STRING]; /* Flawfinder: ignore */ - msg->getStringFast(_PREHASH_AgentBlock, _PREHASH_Filename, MAX_STRING, remote_filename); - - - gXferManager->requestFile(remote_filename, LL_PATH_CACHE, msg->getSender(), TRUE, xferCallback, NULL, - LLXferManager::HIGH_PRIORITY); -} diff --git a/indra/newview/llviewergesture.h b/indra/newview/llviewergesture.h index ced12a7c34..6eca0d1eca 100644 --- a/indra/newview/llviewergesture.h +++ b/indra/newview/llviewergesture.h @@ -45,7 +45,6 @@ class LLViewerGestureList : public LLGestureList public: LLViewerGestureList(); - void saveToServer(); //void requestFromServer(); BOOL getIsLoaded() { return mIsLoaded; } @@ -57,7 +56,6 @@ public: BOOL matchPrefix(const std::string& in_str, std::string* out_str); static void xferCallback(void *data, S32 size, void** /*user_data*/, S32 status); - static void processGestureUpdate(LLMessageSystem *msg, void** /*user_data*/); protected: LLGesture *create_gesture(U8 **buffer, S32 max_size); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index e9d2218d55..2ac1c30ae5 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -95,7 +95,6 @@ #include "llfloateropenobject.h" #include "llfloaterpermissionsmgr.h" #include "llfloaterpreference.h" -#include "llfloaterrate.h" #include "llfloaterregioninfo.h" #include "llfloaterreporter.h" #include "llfloaterscriptdebug.h" @@ -155,6 +154,7 @@ #include "lluuid.h" #include "llvelocitybar.h" #include "llviewercamera.h" +#include "llviewergenericmessage.h" #include "llviewergesture.h" #include "llviewerimagelist.h" #include "llviewerinventory.h" @@ -377,8 +377,6 @@ void handle_force_parcel_owner_to_me(void*); void handle_force_parcel_to_content(void*); void handle_claim_public_land(void*); -void handle_god_expunge_user(void*); - void handle_god_request_havok(void *); void handle_god_request_avatar_geometry(void *); // Hack for easy testing of new avatar geometry void reload_personal_settings_overrides(void *); @@ -1381,8 +1379,6 @@ void init_server_menu(LLMenuGL* menu) &handle_force_parcel_to_content, &enable_god_customer_service, NULL, 'C', MASK_SHIFT | MASK_ALT | MASK_CONTROL)); - //sub->append(new LLMenuItemCallGL("Toggle First Land bit", - // &handle_toggle_parcel_newbie)); sub->appendSeparator(); sub->append(new LLMenuItemCallGL("Claim Public Land", &handle_claim_public_land, &enable_god_customer_service)); @@ -1435,33 +1431,6 @@ void cleanup_menus() // Object pie menu //----------------------------------------------------------------------------- -class LLObjectRateCreator : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - LLFloaterRate::show(LLFloaterRate::RS_CREATOR); - return true; - } -}; - -class LLObjectRateOwner : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - // Don't allow rating of group owned objects. - LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode(); - if (!node) return true; - if (node->mPermissions->isGroupOwned()) - { - gViewerWindow->alertXml("CantRateOwnedByGroup"); - return true; - } - - LLFloaterRate::show(LLFloaterRate::RS_OWNER); - return true; - } -}; - class LLObjectReportAbuse : public view_listener_t { bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) @@ -1471,59 +1440,6 @@ class LLObjectReportAbuse : public view_listener_t } }; -// Enable only when you didn't create it, and the creator -// is not the owner. -class LLObjectEnableRateCreator : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - LLUUID creator_id; - LLUUID owner_id; - LLString dummy; - BOOL identical_creator = gSelectMgr->selectGetCreator(creator_id, dummy); - - BOOL new_value; - if (!identical_creator) - { - new_value = FALSE; - } - else - { - new_value = (creator_id != gAgent.getID()); - } - gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); - return true; - } -}; - -// Enabled if object owner isn't the agent. -class LLObjectEnableRateOwner : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - LLUUID owner_id; - LLString dummy; - BOOL identical_owner = gSelectMgr->selectGetOwner(owner_id, dummy); - - BOOL new_value; - if (!identical_owner) - { - new_value = FALSE; - } - else if (owner_id.isNull()) - { - new_value = FALSE; - } - else - { - new_value = (owner_id != gAgent.getID()); - } - gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); - return true; - } -}; - - // Enabled it you clicked an object class LLObjectEnableReportAbuse : public view_listener_t { @@ -2247,20 +2163,6 @@ void login_done(S32 which, void *user) } - -class LLAvatarRate : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - LLVOAvatar* avatar = find_avatar_from_object( gViewerWindow->lastObjectHit() ); - if( avatar ) - { - LLFloaterRate::show( avatar->getID() ); - } - return true; - } -}; - void callback_leave_group(S32 option, void *userdata) { if (option == 0) @@ -3397,40 +3299,6 @@ void handle_claim_public_land(void*) gAgent.sendReliableMessage(); } -//void handle_toggle_parcel_newbie(void*) -//{ -// gParcelMgr->toggleParcelGodReserveForNewbie(); -//} - -void on_expunge_user(S32 option, const LLString& text, void*) -{ - if(option == -1) return; - llinfos << "on_expunge_user(" << option << "," << text << ")" << llendl; - LLMessageSystem* msg = gMessageSystem; - LLUUID user_id; - if(user_id.set(text)) - { - msg->newMessage("GodExpungeUser"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); - msg->addUUID("SessionID", gAgent.getSessionID()); - msg->nextBlock("ExpungeData"); - msg->addUUID("AgentID", user_id); - msg->sendReliable(gUserServer); - } - else - { - gViewerWindow->alertXml("InvalidUUID"); - } -} - -void handle_god_expunge_user(void*) -{ - gViewerWindow->alertXmlEditText("ExpungeUser", LLString::format_map_t(), - NULL, NULL, - on_expunge_user, NULL); -} - void handle_god_request_havok(void *) { if (gAgent.isGodlike()) @@ -6433,14 +6301,7 @@ class LLShowFloater : public view_listener_t { if (gParcelMgr->selectionEmpty()) { - if (gLastHitPosGlobal.isExactlyZero()) - { - gParcelMgr->selectParcelAt(gAgent.getPositionGlobal()); - } - else - { - gParcelMgr->selectParcelAt( gLastHitPosGlobal ); - } + gParcelMgr->selectParcelAt(gAgent.getPositionGlobal()); } LLFloaterLand::show(); @@ -6449,14 +6310,7 @@ class LLShowFloater : public view_listener_t { if (gParcelMgr->selectionEmpty()) { - if (gLastHitPosGlobal.isExactlyZero()) - { - gParcelMgr->selectParcelAt(gAgent.getPositionGlobal()); - } - else - { - gParcelMgr->selectParcelAt( gLastHitPosGlobal ); - } + gParcelMgr->selectParcelAt(gAgent.getPositionGlobal()); } gParcelMgr->startBuyLand(); @@ -8709,7 +8563,6 @@ void initialize_menu_actions() // Avatar pie menu (new LLObjectMute())->registerListener(gMenuHolder, "Avatar.Mute"); - (new LLAvatarRate())->registerListener(gMenuHolder, "Avatar.Rate"); (new LLAvatarAddFriend())->registerListener(gMenuHolder, "Avatar.AddFriend"); (new LLAvatarFreeze())->registerListener(gMenuHolder, "Avatar.Freeze"); (new LLAvatarDebug())->registerListener(gMenuHolder, "Avatar.Debug"); @@ -8731,9 +8584,7 @@ void initialize_menu_actions() (new LLObjectDelete())->registerListener(gMenuHolder, "Object.Delete"); (new LLObjectAttachToAvatar())->registerListener(gMenuHolder, "Object.AttachToAvatar"); (new LLObjectReturn())->registerListener(gMenuHolder, "Object.Return"); - (new LLObjectRateOwner())->registerListener(gMenuHolder, "Object.RateOwner"); (new LLObjectReportAbuse())->registerListener(gMenuHolder, "Object.ReportAbuse"); - (new LLObjectRateCreator())->registerListener(gMenuHolder, "Object.RateCreator"); (new LLObjectMute())->registerListener(gMenuHolder, "Object.Mute"); (new LLObjectBuy())->registerListener(gMenuHolder, "Object.Buy"); (new LLObjectEdit())->registerListener(gMenuHolder, "Object.Edit"); @@ -8745,9 +8596,7 @@ void initialize_menu_actions() (new LLObjectEnableDelete())->registerListener(gMenuHolder, "Object.EnableDelete"); (new LLObjectEnableWear())->registerListener(gMenuHolder, "Object.EnableWear"); (new LLObjectEnableReturn())->registerListener(gMenuHolder, "Object.EnableReturn"); - (new LLObjectEnableRateOwner())->registerListener(gMenuHolder, "Object.EnableRateOwner"); (new LLObjectEnableReportAbuse())->registerListener(gMenuHolder, "Object.EnableReportAbuse"); - (new LLObjectEnableRateCreator())->registerListener(gMenuHolder, "Object.EnableRateCreator"); (new LLObjectEnableMute())->registerListener(gMenuHolder, "Object.EnableMute"); (new LLObjectEnableBuy())->registerListener(gMenuHolder, "Object.EnableBuy"); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index cc1beefec5..316de37ce1 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -87,6 +87,7 @@ #include "llui.h" // for make_ui_sound #include "lluploaddialog.h" #include "llviewercamera.h" +#include "llviewergenericmessage.h" #include "llviewerinventory.h" #include "llviewermenu.h" #include "llviewerobject.h" @@ -123,8 +124,6 @@ extern BOOL gDebugClicks; extern void bad_network_handler(); -LLDispatcher gGenericDispatcher; - // function prototypes void open_offer(const std::vector<LLUUID>& items); void friendship_offer_callback(S32 option, void* user_data); @@ -1540,26 +1539,90 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) break; } case IM_GROUP_VOTE: + { + LLUUID *userdata = new LLUUID(session_id); + args["[NAME]"] = name; + args["[MESSAGE]"] = message; + LLNotifyBox::showXml("GroupVote", args, + &group_vote_callback, userdata); + } + break; + + case IM_GROUP_ELECTION_DEPRECATED: + { + llwarns << "Received IM: IM_GROUP_ELECTION_DEPRECATED" << llendl; + } + break; + + case IM_SESSION_911_SEND: + { + //this is just the same code as IM_SESSION_SEND for a bit + //I was too lazy to make this a function....sorry - jwolk + if (!is_linden && is_busy) { - LLUUID *userdata = new LLUUID(session_id); - args["[NAME]"] = name; - args["[MESSAGE]"] = message; - LLNotifyBox::showXml("GroupVote", args, - &group_vote_callback, userdata); + return; + } + + // standard message, not from system + char saved[MAX_STRING]; /* Flawfinder: ignore */ + saved[0] = '\0'; + if(offline == IM_OFFLINE) + { + char time_buf[TIME_STR_LENGTH]; /* Flawfinder: ignore */ + snprintf(saved, /* Flawfinder: ignore */ + MAX_STRING, + "(Saved %s) ", + formatted_time(timestamp, time_buf)); + } + + snprintf(buffer, /* Flawfinder: ignore */ + sizeof(buffer), + "%s%s%s%s", + name, + separator_string, + saved, + (message+message_offset)); + + BOOL is_this_agent = FALSE; + if(from_id == gAgentID) + { + from_id = LLUUID::null; + is_this_agent = TRUE; } - break; - case IM_GROUP_ELECTION_DEPRECATED: + gIMView->addMessage( + session_id, + from_id, + name, + buffer, + (char*)binary_bucket, + IM_SESSION_ADD, + parent_estate_id, + region_id, + position); + + snprintf(buffer, sizeof(buffer), "IM: %s%s%s%s", name, separator_string, saved, (message+message_offset)); /* Flawfinder: ignore */ + chat.mText = buffer; + LLFloaterChat::addChat(chat, TRUE, is_this_agent); + + //ok, now we want to add a teleport button if we are receving + //a message from not ourself + LLFloaterIMPanel* panel = + gIMView->findFloaterBySession(session_id); + + if (panel && !is_this_agent ) { - llwarns << "Received IM: IM_GROUP_ELECTION_DEPRECATED" << llendl; + //don't add a teleport button for yourself + panel->addTeleportButton(); } break; + } case IM_SESSION_SEND: + { + if (!is_linden && is_busy) { - if (!is_linden && is_busy) - { - return; - } + return; + } // System messages, specifically "Foo Bar has left this session" // are not shown unless you actually have that session open. @@ -1571,40 +1634,40 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) return; } - // standard message, not from system - char saved[MAX_STRING]; /* Flawfinder: ignore */ - saved[0] = '\0'; - if(offline == IM_OFFLINE) - { - char time_buf[TIME_STR_LENGTH]; /* Flawfinder: ignore */ - snprintf(saved, /* Flawfinder: ignore */ - MAX_STRING, - "(Saved %s) ", - formatted_time(timestamp, time_buf)); - } - snprintf(buffer, sizeof(buffer), "%s%s%s%s", name, separator_string, saved, (message+message_offset)); /* Flawfinder: ignore */ - BOOL is_this_agent = FALSE; - if(from_id == gAgentID) - { - from_id = LLUUID::null; - is_this_agent = TRUE; - } - gIMView->addMessage( - session_id, - from_id, - name, - buffer, - (char*)binary_bucket, - IM_SESSION_ADD, - parent_estate_id, - region_id, - position); - - snprintf(buffer, sizeof(buffer), "IM: %s%s%s%s", name, separator_string, saved, (message+message_offset)); /* Flawfinder: ignore */ - chat.mText = buffer; - LLFloaterChat::addChat(chat, TRUE, is_this_agent); + // standard message, not from system + char saved[MAX_STRING]; /* Flawfinder: ignore */ + saved[0] = '\0'; + if(offline == IM_OFFLINE) + { + char time_buf[TIME_STR_LENGTH]; /* Flawfinder: ignore */ + snprintf(saved, /* Flawfinder: ignore */ + MAX_STRING, + "(Saved %s) ", + formatted_time(timestamp, time_buf)); } - break; + snprintf(buffer, sizeof(buffer), "%s%s%s%s", name, separator_string, saved, (message+message_offset)); /* Flawfinder: ignore */ + BOOL is_this_agent = FALSE; + if(from_id == gAgentID) + { + from_id = LLUUID::null; + is_this_agent = TRUE; + } + gIMView->addMessage( + session_id, + from_id, + name, + buffer, + (char*)binary_bucket, + IM_SESSION_ADD, + parent_estate_id, + region_id, + position); + + snprintf(buffer, sizeof(buffer), "IM: %s%s%s%s", name, separator_string, saved, (message+message_offset)); /* Flawfinder: ignore */ + chat.mText = buffer; + LLFloaterChat::addChat(chat, TRUE, is_this_agent); + } + break; case IM_FROM_TASK: if (is_busy && !is_owned_by_me) @@ -1675,21 +1738,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) } break; - case IM_LURE_911: - { - // HACK -- the from_id is the im_session_id - LLFloaterIMPanel* panel = gIMView->findFloaterBySession(session_id); - if (panel) - { - panel->addTeleportButton(from_id); - } - else - { - llinfos << "LLFloaterIMPanel not found for " << session_id << " from " << from_id << llendl; - } - } - break; - case IM_GOTO_URL: { char* url = new char[binary_bucket_size]; @@ -2299,7 +2347,18 @@ void process_teleport_progress(LLMessageSystem* msg, void**) char buffer[MAX_STRING]; /* Flawfinder: ignore */ msg->getString("Info", "Message", MAX_STRING, buffer); lldebugs << "teleport progress: " << buffer << llendl; - gAgent.setTeleportMessage(buffer); + + //Sorta hacky...default to using simulator raw messages + //if we don't find the coresponding mapping in our progress mappings + LLString message = buffer; + + if (LLAgent::sTeleportProgressMessages.find(buffer) != + LLAgent::sTeleportProgressMessages.end() ) + { + message = LLAgent::sTeleportProgressMessages[buffer]; + } + + gAgent.setTeleportMessage(LLAgent::sTeleportProgressMessages[message]); } class LLFetchInWelcomeArea : public LLInventoryFetchDescendentsObserver @@ -2456,7 +2515,7 @@ void process_teleport_finish(LLMessageSystem* msg, void**) send_complete_agent_movement(sim_host); gAgent.setTeleportState( LLAgent::TELEPORT_MOVING ); - gAgent.setTeleportMessage("Contacting New Region..."); + gAgent.setTeleportMessage(LLAgent::sTeleportProgressMessages["contacting"]); regionp->setSeedCapability(std::string(seedCap)); @@ -2492,6 +2551,8 @@ void process_avatar_init_complete(LLMessageSystem* msg, void**) void process_agent_movement_complete(LLMessageSystem* msg, void**) { + gAgentMovementCompleted = TRUE; + LLUUID agent_id; msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); LLUUID session_id; @@ -4295,7 +4356,7 @@ void process_teleport_failed(LLMessageSystem *msg, void**) msg->getStringFast(_PREHASH_Info, _PREHASH_Reason, STD_STRING_BUF_SIZE, reason); LLStringBase<char>::format_map_t args; - args["[REASON]"] = reason; + args["[REASON]"] = LLAgent::sTeleportErrorMessages[reason]; gViewerWindow->alertXml("CouldNotTeleportReason", args); if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE ) @@ -4449,25 +4510,6 @@ void handle_lure_callback_godlike(S32 option, void* userdata) handle_lure_callback(option, LLString::null, userdata); } -void send_lure_911(void** user_data, S32 result) -{ - LLUUID im_session_id(*((LLUUID*)user_data)); - LLString name; - gAgent.getName(name); - LLString text = name + " needs help"; // this text is ignored for 911 lures - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_StartLure); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_Info); - msg->addU8Fast(_PREHASH_LureType, (U8)IM_LURE_911); - msg->addStringFast(_PREHASH_Message, text.c_str()); - msg->nextBlockFast(_PREHASH_TargetData); - msg->addUUIDFast(_PREHASH_TargetID, im_session_id); - gAgent.sendReliableMessage(); -} - void handle_lure(const LLUUID& invitee) { LLDynamicArray<LLUUID> ids; @@ -4985,59 +5027,6 @@ void onCovenantLoadComplete(LLVFS *vfs, LLFloaterBuyLand::updateCovenantText(covenant_text, asset_uuid); } -void send_generic_message(const char* method, - const std::vector<std::string>& strings, - const LLUUID& invoice) -{ - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("GenericMessage"); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used - msg->nextBlock("MethodData"); - msg->addString("Method", method); - msg->addUUID("Invoice", invoice); - if(strings.empty()) - { - msg->nextBlock("ParamList"); - msg->addString("Parameter", NULL); - } - else - { - std::vector<std::string>::const_iterator it = strings.begin(); - std::vector<std::string>::const_iterator end = strings.end(); - for(; it != end; ++it) - { - msg->nextBlock("ParamList"); - msg->addString("Parameter", (*it).c_str()); - } - } - gAgent.sendReliableMessage(); -} - - -void process_generic_message(LLMessageSystem* msg, void**) -{ - LLUUID agent_id; - msg->getUUID("AgentData", "AgentID", agent_id); - if (agent_id != gAgent.getID()) - { - llwarns << "GenericMessage for wrong agent" << llendl; - return; - } - - std::string request; - LLUUID invoice; - LLDispatcher::sparam_t strings; - LLDispatcher::unpackMessage(msg, request, invoice, strings); - - if(!gGenericDispatcher.dispatch(request, invoice, strings)) - { - llwarns << "GenericMessage " << request << " failed to dispatch" - << llendl; - } -} void process_feature_disabled_message(LLMessageSystem* msg, void**) { @@ -5062,3 +5051,6 @@ void invalid_message_callback(LLMessageSystem* msg, { bad_network_handler(); } + +// Please do not add more message handlers here. This file is huge. +// Put them in a file related to the functionality you are implementing. JC diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index c7d22656c7..04fb668aba 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -9,12 +9,10 @@ #ifndef LL_LLVIEWERMESSAGE_H #define LL_LLVIEWERMESSAGE_H -//#include "linked_lists.h" #include "llinstantmessage.h" #include "lltransactiontypes.h" #include "lluuid.h" #include "stdenums.h" -#include "message.h" // // Forward declarations @@ -23,6 +21,7 @@ class LLColor4; class LLViewerObject; class LLInventoryObject; class LLInventoryItem; +class LLMessageSystem; class LLViewerRegion; // @@ -169,8 +168,6 @@ void process_decline_callingcard(LLMessageSystem* msg, void**); // Message system exception prototypes void invalid_message_callback(LLMessageSystem*, void*, EMessageException); -void send_lure_911(void** user_data, S32 result); - void process_initiate_download(LLMessageSystem* msg, void**); void inventory_offer_callback(S32 option, void* user_data); @@ -189,15 +186,7 @@ struct LLOfferInfo LLHost mHost; }; -void send_generic_message(const char* method, - const std::vector<std::string>& strings, - const LLUUID& invoice = LLUUID::null); - -void process_generic_message(LLMessageSystem* msg, void**); - void process_feature_disabled_message(LLMessageSystem* msg, void**); -extern LLDispatcher gGenericDispatcher; - #endif diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index c3f2b2d2f6..5af3d532a6 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -1347,7 +1347,6 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use LLUUID owner_id; BOOL is_group_owned; U32 auction_id = 0; - BOOL is_reserved = FALSE; S32 claim_price_per_meter = 0; S32 rent_price_per_meter = 0; S32 claim_date = 0; @@ -1424,7 +1423,6 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use msg->getUUIDFast(_PREHASH_ParcelData, _PREHASH_OwnerID, owner_id); msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_IsGroupOwned, is_group_owned); msg->getU32Fast(_PREHASH_ParcelData, _PREHASH_AuctionID, auction_id); - msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_ReservedNewbie, is_reserved); msg->getS32Fast( _PREHASH_ParcelData, _PREHASH_ClaimDate, claim_date); msg->getS32Fast( _PREHASH_ParcelData, _PREHASH_ClaimPrice, claim_price_per_meter); msg->getS32Fast( _PREHASH_ParcelData, _PREHASH_RentPrice, rent_price_per_meter); @@ -1461,7 +1459,6 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use parcel->setAABBMax(aabb_max); parcel->setAuctionID(auction_id); - parcel->setReservedForNewbie(is_reserved); parcel->setOwnershipStatus((LLParcel::EOwnershipStatus)status); parcel->setSimWideMaxPrimCapacity(sw_max_prims); @@ -2214,16 +2211,10 @@ bool LLViewerParcelMgr::canAgentBuyParcel(LLParcel* parcel, bool forGroup) const bool isOwner = parcelOwner == (forGroup ? gAgent.getGroupID() : gAgent.getID()); - bool isAvailable - = parcel->getReservedForNewbie() - ? (!forGroup && gStatusBar->getSquareMetersCommitted() == 0) - : true; - // *TODO: should be based on never_owned_land, see SL-10728 - bool isAuthorized = (authorizeBuyer.isNull() || (gAgent.getID() == authorizeBuyer)); - return isForSale && !isOwner && isAuthorized && isAvailable && isEmpowered; + return isForSale && !isOwner && isAuthorized && isEmpowered; } diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h index ae772aebf1..ae288d70ec 100644 --- a/indra/newview/llviewerparcelmgr.h +++ b/indra/newview/llviewerparcelmgr.h @@ -203,12 +203,6 @@ public: // make the selected parcel a content parcel. void sendParcelGodForceToContent(); - // Take the selected parcel, and toggle it's 'reserved for newbie' - // status. - // *NOTE: There is no longer a newbie toggle. It is a linden sale - // for newbie now. - //void toggleParcelGodReserveForNewbie(); - // Pack information about this parcel and send it to the region // containing the southwest corner of the selection. // If want_reply_to_update, simulator will send back a ParcelProperties diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index cc93ea8bdc..303e83d672 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -15,7 +15,6 @@ #include "llhttpclient.h" #include "llregionflags.h" #include "llregionhandle.h" -#include "llsdmessagesystem.h" #include "llsurface.h" #include "message.h" //#include "vmath.h" @@ -24,6 +23,7 @@ #include "llagent.h" #include "llcallingcard.h" +#include "llcaphttpsender.h" #include "lldir.h" #include "lleventpoll.h" #include "llfloatergodtools.h" @@ -38,6 +38,12 @@ #include "llvocache.h" #include "llvoclouds.h" #include "llworld.h" +#include "viewer.h" + +// Viewer object cache version, change if object update +// format changes. JC +const U32 INDRA_OBJECT_CACHE_VERSION = 12; + extern BOOL gNoRender; @@ -142,6 +148,7 @@ LLViewerRegion::~LLViewerRegion() delete mParcelOverlay; delete mLandp; delete mEventPoll; + LLHTTPSender::clearSender(mHost); saveCache(); } @@ -1278,35 +1285,34 @@ void LLViewerRegion::setSeedCapability(const std::string& url) capabilityNames.append("SendUserReport"); capabilityNames.append("SendUserReportWithScreenshot"); capabilityNames.append("RequestTextureDownload"); + capabilityNames.append("UntrustedSimulatorMessage"); + LLHTTPClient::post(url, capabilityNames, BaseCapabilitiesComplete::build(this)); } static LLEventPoll* createViewerEventPoll(const std::string& url) { - static LLHTTPNode eventRoot; - static bool eventRootServicesAdded = false; - if (!eventRootServicesAdded) - { - LLSDMessageSystem::useServices(); - LLHTTPRegistrar::buildAllServices(eventRoot); - eventRootServicesAdded = true; - } - - return new LLEventPoll(url, eventRoot); + return new LLEventPoll(url); } void LLViewerRegion::setCapability(const std::string& name, const std::string& url) { - mCapabilities[name] = url; - - if (name == "EventQueueGet") + if(name == "EventQueueGet") { delete mEventPoll; mEventPoll = NULL; mEventPoll = createViewerEventPoll(url); } + else if(name == "UntrustedSimulatorMessage") + { + LLHTTPSender::setSender(mHost, new LLCapHTTPSender(url)); + } + else + { + mCapabilities[name] = url; + } } std::string LLViewerRegion::getCapability(const std::string& name) const diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index f11f9fb1be..1b3c0193f4 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -610,22 +610,19 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask // Topmost view gets a chance before the hierarchy LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); + BOOL mouse_over_top_ctrl = FALSE; if (top_ctrl) { S32 local_x, local_y; top_ctrl->screenPointToLocal( x, y, &local_x, &local_y ); if (top_ctrl->pointInView(local_x, local_y)) { + mouse_over_top_ctrl = TRUE; if(top_ctrl->handleMouseDown(local_x, local_y, mask)) { return TRUE; } } - else if (top_ctrl->hasFocus()) - { - // always defocus top view if we click off of it - top_ctrl->setFocus(FALSE); - } } // Give the UI views a chance to process the click @@ -636,6 +633,11 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask llinfos << "Left Mouse Down" << LLView::sMouseHandlerMessage << llendl; LLView::sMouseHandlerMessage = ""; } + if (top_ctrl && top_ctrl->hasFocus() && !mouse_over_top_ctrl) + { + // always defocus top view if we click off of it + top_ctrl->setFocus(FALSE); + } return TRUE; } else if (LLView::sDebugMouseHandling) @@ -643,6 +645,12 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask llinfos << "Left Mouse Down not handled by view" << llendl; } + if (top_ctrl && top_ctrl->hasFocus() && !mouse_over_top_ctrl) + { + // always defocus top view if we click off of it + top_ctrl->setFocus(FALSE); + } + if (gDisconnected) { return FALSE; @@ -699,24 +707,19 @@ BOOL LLViewerWindow::handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK ma // Check for hit on UI. LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); + BOOL mouse_over_top_ctrl = FALSE; if (top_ctrl) { S32 local_x, local_y; top_ctrl->screenPointToLocal( x, y, &local_x, &local_y ); if (top_ctrl->pointInView(local_x, local_y)) { + mouse_over_top_ctrl = TRUE; if(top_ctrl->handleDoubleClick(local_x, local_y, mask)) { return TRUE; } } - else - { - if (top_ctrl->hasFocus()) - { - top_ctrl->setFocus(FALSE); - } - } } if (mRootView->handleDoubleClick(x, y, mask)) @@ -726,6 +729,11 @@ BOOL LLViewerWindow::handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK ma llinfos << "Left Mouse Down" << LLView::sMouseHandlerMessage << llendl; LLView::sMouseHandlerMessage = ""; } + if (top_ctrl && top_ctrl->hasFocus() && !mouse_over_top_ctrl) + { + // always defocus top view if we click off of it + top_ctrl->setFocus(FALSE); + } return TRUE; } else if (LLView::sDebugMouseHandling) @@ -733,7 +741,13 @@ BOOL LLViewerWindow::handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK ma llinfos << "Left Mouse Down not handled by view" << llendl; } - // Why is this here? JC 9/3/2002 + if (top_ctrl && top_ctrl->hasFocus() && !mouse_over_top_ctrl) + { + // always defocus top view if we click off of it + top_ctrl->setFocus(FALSE); + } + + // Why is this here? JC 9/3/2002 if (gNoRender) { return TRUE; @@ -903,24 +917,19 @@ BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK } LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); + BOOL mouse_over_top_ctrl = FALSE; if (top_ctrl) { S32 local_x, local_y; top_ctrl->screenPointToLocal( x, y, &local_x, &local_y ); if (top_ctrl->pointInView(local_x, local_y)) { + mouse_over_top_ctrl = TRUE; if(top_ctrl->handleRightMouseDown(local_x, local_y, mask)) { return TRUE; } } - else - { - if (top_ctrl->hasFocus()) - { - top_ctrl->setFocus(FALSE); - } - } } if( mRootView->handleRightMouseDown(x, y, mask) ) @@ -930,6 +939,11 @@ BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK llinfos << "Right Mouse Down" << LLView::sMouseHandlerMessage << llendl; LLView::sMouseHandlerMessage = ""; } + if (top_ctrl && top_ctrl->hasFocus() && !mouse_over_top_ctrl) + { + // always defocus top view if we click off of it + top_ctrl->setFocus(FALSE); + } return TRUE; } else if (LLView::sDebugMouseHandling) @@ -937,6 +951,12 @@ BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK llinfos << "Right Mouse Down not handled by view" << llendl; } + if (top_ctrl && top_ctrl->hasFocus() && !mouse_over_top_ctrl) + { + // always defocus top view if we click off of it + top_ctrl->setFocus(FALSE); + } + if (gToolMgr) { if(gToolMgr->getCurrentTool()->handleRightMouseDown( x, y, mask ) ) @@ -1464,8 +1484,27 @@ LLViewerWindow::LLViewerWindow( // stuff like AGP if we think that it'll crash the viewer. // gFeatureManagerp->initGraphicsFeatureMasks(); + + // The ATI Mobility Radeon with 1.15.0 causes crashes in FMOD on startup for + // unknown reasons, but only if you have an old settings.ini file. + // In this case, force the graphics settings back to recommended, but only + // do it once. JC + std::string gpu_string = gFeatureManagerp->getGPUString(); + LLString::toLower(gpu_string); + bool upgrade_to_1_15 = (gSavedSettings.getString("LastRunVersion") != "1.15.0"); + bool mobility_radeon = (gpu_string.find("mobility radeon") != std::string::npos); + bool mobility_radeon_upgrade_hack = upgrade_to_1_15 && mobility_radeon; + if (mobility_radeon_upgrade_hack) + { + llinfos << "1.15.0 update on Mobility Radeon" << llendl; + llinfos << "Forcing recommended graphics settings" << llendl; + llinfos << "Forcing audio off" << llendl; + gUseAudio = FALSE; + } + if (gFeatureManagerp->isSafe() - || (gSavedSettings.getS32("LastFeatureVersion") != gFeatureManagerp->getVersion())) + || (gSavedSettings.getS32("LastFeatureVersion") != gFeatureManagerp->getVersion()) + || mobility_radeon_upgrade_hack) { gFeatureManagerp->applyRecommendedFeatures(); } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index e74c286e43..2b821bed9f 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -3060,6 +3060,13 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) return; } + // For fading out the names above heads, only let the timer + // run if we're visible. + if (mDrawable.notNull() && !mDrawable->isVisible()) + { + mTimeVisible.reset(); + } + if (!mIsSelf && !isVisible()) { return; @@ -3090,13 +3097,6 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) getOffObject(); } - // For fading out the names above heads, only let the timer - // run if we're visible. - if (mDrawable.notNull() && !mDrawable->isVisible()) - { - mTimeVisible.reset(); - } - //-------------------------------------------------------------------- // create local variables in world coords for region position values //-------------------------------------------------------------------- diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index c00a202f91..cf57ae3cd0 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -219,6 +219,7 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip) curl_easy_setopt(mCurl, CURLOPT_ERRORBUFFER, &mCurlErrorBuffer); curl_easy_setopt(mCurl, CURLOPT_CAINFO, gDirUtilp->getCAFile().c_str()); curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYPEER, gVerifySSLCert); + curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYHOST, gVerifySSLCert? 2 : 0); /* Setting the DNS cache timeout to -1 disables it completely. This might help with bug #503 */ diff --git a/indra/test/llhttpclient_tut.cpp b/indra/test/llhttpclient_tut.cpp index 865af98761..b169499543 100644 --- a/indra/test/llhttpclient_tut.cpp +++ b/indra/test/llhttpclient_tut.cpp @@ -216,7 +216,7 @@ namespace tut template<> template<> void HTTPClientTestObject::test<1>() { - LLHTTPClient::get("http://www.google.com/", newResult()); + LLHTTPClient::get("http://www.secondlife.com/", newResult()); runThePump(); ensureStatusOK(); ensure("result object wasn't destroyed", mResultDeleted); diff --git a/indra/test/lliohttpserver_tut.cpp b/indra/test/lliohttpserver_tut.cpp index 1284a1fc0d..2f64cc81d7 100644 --- a/indra/test/lliohttpserver_tut.cpp +++ b/indra/test/lliohttpserver_tut.cpp @@ -97,7 +97,7 @@ namespace tut LLSD context; chain.push_back(LLIOPipe::ptr_t(injector)); - LLCreateHTTPPipe(chain, mRoot); + LLCreateHTTPPipe(chain, mRoot, LLSD()); chain.push_back(LLIOPipe::ptr_t(extractor)); pump->addChain(chain, DEFAULT_CHAIN_EXPIRY_SECS); @@ -278,6 +278,33 @@ namespace tut ); } + template<> template<> + void HTTPServiceTestObject::test<7>() + { + // test large request + std::stringstream stream; + + //U32 size = 36 * 1024 * 1024; + //U32 size = 36 * 1024; + //std::vector<char> data(size); + //memset(&(data[0]), '1', size); + //data[size - 1] = '\0'; + + + //std::string result = httpPOST("web/echo", &(data[0])); + + stream << "<llsd><array>"; + for(U32 i = 0; i < 1000000; ++i) + { + stream << "<integer>42</integer>"; + } + stream << "</array></llsd>"; + llinfos << "HTTPServiceTestObject::test<7>" + << stream.str().length() << llendl; + std::string result = httpPOST("web/echo", stream.str()); + ensure_starts_with("large echo status", result, "HTTP/1.0 200 OK\r\n"); + } + /* TO DO: test generation of not found and method not allowed errors */ diff --git a/indra/test/llmessageconfig_tut.cpp b/indra/test/llmessageconfig_tut.cpp new file mode 100644 index 0000000000..c9a62e5230 --- /dev/null +++ b/indra/test/llmessageconfig_tut.cpp @@ -0,0 +1,207 @@ +/** + * @file llmessageconfig_tut.cpp + * @date March 2007 + * @brief LLMessageConfig unit tests + * + * Copyright (c) 2006-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#include <tut/tut.h> +#include "lltut.h" +#include "llmessageconfig.h" +#include "llsdserialize.h" +#include "llfile.h" +#include "lltimer.h" +#include "llframetimer.h" + +namespace tut +{ + ///var/tmp/babbage/dev/message-liberation/etc + static const char file_name[] = "/tmp/message.xml"; + static const F32 refreshRate = 6.0*1000.0; // milliseconds + + struct LLMessageConfigTestData { + + LLSD getCurrentConfig() + { + LLSD data; + // store aside the current config to overwrite the test ones + // when the test finishes + llifstream in_file(file_name); + if (in_file.is_open()) + { + LLSDSerialize::fromXML(data, in_file); + } + return data; + } + + void writeConfigFile(const LLSD& config) + { + LLMessageConfig::initClass("simulator", "/tmp"); + llofstream file(file_name); + if (file.is_open()) + { + LLSDSerialize::toPrettyXML(config, file); + } + file.close(); + ms_sleep(refreshRate); + LLFrameTimer::updateFrameTime(); + } + }; + + typedef test_group<LLMessageConfigTestData> LLMessageConfigTestGroup; + typedef LLMessageConfigTestGroup::object LLMessageConfigTestObject; + LLMessageConfigTestGroup llMessageConfigTestGroup("LLMessageConfig"); + + template<> template<> + void LLMessageConfigTestObject::test<1>() + // tests server defaults + { + LLSD config_backup = getCurrentConfig(); + LLSD config; + config["serverDefaults"]["simulator"] = "template"; + writeConfigFile(config); + ensure_equals("Ensure server default is not llsd", + LLMessageConfig::isServerDefaultBuilderLLSD(), + false); + ensure_equals("Ensure server default is template", + LLMessageConfig::isServerDefaultBuilderTemplate(), + true); + writeConfigFile(config_backup); + } + + template<> template<> + void LLMessageConfigTestObject::test<2>() + // tests message builders + { + LLSD config_backup = getCurrentConfig(); + LLSD config; + config["serverDefaults"]["simulator"] = "template"; + config["messages"]["msg1"]["builder"] = "template"; + config["messages"]["msg2"]["builder"] = "llsd"; + writeConfigFile(config); + ensure_equals("Ensure msg template builder not llsd", + LLMessageConfig::isMessageBuiltLLSD("msg1"), + false); + ensure_equals("Ensure msg template builder", + LLMessageConfig::isMessageBuiltTemplate("msg1"), + true); + ensure_equals("Ensure msg llsd builder", + LLMessageConfig::isMessageBuiltLLSD("msg2"), + true); + ensure_equals("Ensure msg llsd builder not template", + LLMessageConfig::isMessageBuiltTemplate("msg2"), + false); + writeConfigFile(config_backup); + } + + template<> template<> + void LLMessageConfigTestObject::test<4>() + // tests message builder defaults + { + LLSD config_backup = getCurrentConfig(); + LLSD config; + config["serverDefaults"]["simulator"] = "llsd"; + config["messages"]["msg1"]["trusted-sender"] = true; + writeConfigFile(config); + ensure_equals("Ensure missing message defaults to server builder, not template", + LLMessageConfig::isMessageBuiltTemplate("Test"), + false); + ensure_equals("Ensure missing message default to server builder llsd", + LLMessageConfig::isMessageBuiltLLSD("Test"), + true); + ensure_equals("Ensure missing builder defaults to server builder, not template", + LLMessageConfig::isMessageBuiltTemplate("msg1"), + false); + ensure_equals("Ensure missing builder default to server builder llsd", + LLMessageConfig::isMessageBuiltLLSD("msg1"), + true); + + ensure_equals("Ensure server default is not llsd", + LLMessageConfig::isServerDefaultBuilderLLSD(), + true); + ensure_equals("Ensure server default is template", + LLMessageConfig::isServerDefaultBuilderTemplate(), + false); + + writeConfigFile(config_backup); + } + + template<> template<> + void LLMessageConfigTestObject::test<3>() + // tests trusted/untrusted senders + { + LLSD config_backup = getCurrentConfig(); + LLSD config; + config["serverDefaults"]["simulator"] = "template"; + config["messages"]["msg1"]["builder"] = "llsd"; + config["messages"]["msg1"]["trusted-sender"] = false; + config["messages"]["msg2"]["builder"] = "llsd"; + config["messages"]["msg2"]["trusted-sender"] = true; + writeConfigFile(config); + ensure_equals("Ensure untrusted is not trusted", + LLMessageConfig::isMessageTrusted("msg1"), + false); + ensure_equals("Ensure untrusted is untrusted", + LLMessageConfig::isValidUntrustedMessage("msg1"), + true); + ensure_equals("Ensure trusted is trusted", + LLMessageConfig::isMessageTrusted("msg2"), + true); + ensure_equals("Ensure trusted is not untrusted", + LLMessageConfig::isValidUntrustedMessage("msg2"), + false); + writeConfigFile(config_backup); + } + + template<> template<> + void LLMessageConfigTestObject::test<5>() + // tests trusted/untrusted without flag, only builder + { + LLSD config_backup = getCurrentConfig(); + LLSD config; + config["serverDefaults"]["simulator"] = "template"; + config["messages"]["msg1"]["builder"] = "llsd"; + writeConfigFile(config); + ensure_equals("Ensure missing trusted is not trusted", + LLMessageConfig::isMessageTrusted("msg1"), + false); + ensure_equals("Ensure missing trusted is not untrusted", + LLMessageConfig::isValidUntrustedMessage("msg1"), + false); + writeConfigFile(config_backup); + } + + template<> template<> + void LLMessageConfigTestObject::test<6>() + // tests message builder defaults + { + LLSD config_backup = getCurrentConfig(); + LLSD config; + config["serverDefaults"]["simulator"] = "template"; + config["messages"]["msg1"]["trusted-sender"] = true; + writeConfigFile(config); + ensure_equals("Ensure missing message defaults to server builder, not template", + LLMessageConfig::isMessageBuiltTemplate("Test"), + true); + ensure_equals("Ensure missing message default to server builder llsd", + LLMessageConfig::isMessageBuiltLLSD("Test"), + false); + ensure_equals("Ensure missing builder defaults to server builder, not template", + LLMessageConfig::isMessageBuiltTemplate("msg1"), + true); + ensure_equals("Ensure missing builder default to server builder llsd", + LLMessageConfig::isMessageBuiltLLSD("msg1"), + false); + + ensure_equals("Ensure server default is not llsd", + LLMessageConfig::isServerDefaultBuilderLLSD(), + false); + ensure_equals("Ensure server default is template", + LLMessageConfig::isServerDefaultBuilderTemplate(), + true); + + writeConfigFile(config_backup); + } +} diff --git a/indra/test/llsd_new_tut.cpp b/indra/test/llsd_new_tut.cpp index 2354698239..0ceb4302ff 100644 --- a/indra/test/llsd_new_tut.cpp +++ b/indra/test/llsd_new_tut.cpp @@ -12,82 +12,11 @@ #include "linden_common.h" #include "lltut.h" -#include "llsd.h" +#include "llsdtraits.h" #include "llstring.h" namespace tut { - template<class T> - class SDTraits - { - protected: - typedef T (LLSD::*Getter)() const; - - LLSD::Type type; - Getter getter; - - public: - SDTraits(); - - T get(const LLSD& actual) - { - return (actual.*getter)(); - } - - bool checkType(const LLSD& actual) - { - return actual.type() == type; - } - }; - - template<> - SDTraits<LLSD::Boolean>::SDTraits() - : type(LLSD::TypeBoolean), getter(&LLSD::asBoolean) - { } - - template<> - SDTraits<LLSD::Integer>::SDTraits() - : type(LLSD::TypeInteger), getter(&LLSD::asInteger) - { } - - template<> - SDTraits<LLSD::Real>::SDTraits() - : type(LLSD::TypeReal), getter(&LLSD::asReal) - { } - - template<> - SDTraits<LLSD::UUID>::SDTraits() - : type(LLSD::TypeUUID), getter(&LLSD::asUUID) - { } - - template<> - SDTraits<LLSD::String>::SDTraits() - : type(LLSD::TypeString), getter(&LLSD::asString) - { } - - template<> - class SDTraits<LLString> : public SDTraits<LLSD::String> - { }; - - template<> - class SDTraits<const char*> : public SDTraits<LLSD::String> - { }; - - template<> - SDTraits<LLSD::Date>::SDTraits() - : type(LLSD::TypeDate), getter(&LLSD::asDate) - { } - - template<> - SDTraits<LLSD::URI>::SDTraits() - : type(LLSD::TypeURI), getter(&LLSD::asURI) - { } - - template<> - SDTraits<LLSD::Binary>::SDTraits() - : type(LLSD::TypeBinary), getter(&LLSD::asBinary) - { } - class SDCleanupCheck { private: @@ -126,7 +55,7 @@ namespace tut static void ensureTypeAndValue(const char* msg, const LLSD& actual, T expectedValue) { - SDTraits<T> traits; + LLSDTraits<T> traits; std::string s(msg); @@ -334,7 +263,7 @@ namespace tut } LLSD u(str); - SDTraits<T> traits; + LLSDTraits<T> traits; ensure_equals(msg + " value", traits.get(u), vExpected); } diff --git a/indra/test/llsdmessagebuilder_tut.cpp b/indra/test/llsdmessagebuilder_tut.cpp new file mode 100755 index 0000000000..b153292abc --- /dev/null +++ b/indra/test/llsdmessagebuilder_tut.cpp @@ -0,0 +1,259 @@ +/** + * @file llsdmessagebuilder_tut.cpp + * @date February 2006 + * @brief LLSDMessageBuilder unit tests + * + * Copyright (c) 2006-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#include <tut/tut.h> +#include "lltut.h" + +#include "llsdmessagebuilder.h" +#include "llsdmessagereader.h" +#include "llsdtraits.h" +#include "llquaternion.h" +#include "u64.h" +#include "v3dmath.h" +#include "v3math.h" +#include "v4math.h" + +namespace tut +{ + struct LLSDMessageBuilderTestData { + static LLSDMessageBuilder defaultBuilder() + { + LLSDMessageBuilder builder; + builder.newMessage("name"); + builder.nextBlock("block"); + return builder; + } + + static LLSDMessageReader setReader(const LLSDMessageBuilder& builder) + { + LLSDMessageReader reader; + reader.setMessage("name", builder.getMessage()); + return reader; + } + }; + + typedef test_group<LLSDMessageBuilderTestData> LLSDMessageBuilderTestGroup; + typedef LLSDMessageBuilderTestGroup::object LLSDMessageBuilderTestObject; + LLSDMessageBuilderTestGroup llsdMessageBuilderTestGroup("LLSDMessageBuilder"); + + template<> template<> + void LLSDMessageBuilderTestObject::test<1>() + // construction and test of undefined + { + LLSDMessageBuilder builder = defaultBuilder(); + LLSDMessageReader reader = setReader(builder); + } + + template<> template<> + void LLSDMessageBuilderTestObject::test<2>() + // BOOL + { + BOOL outValue, inValue = TRUE; + LLSDMessageBuilder builder = defaultBuilder(); + builder.addBOOL("var", inValue); + LLSDMessageReader reader = setReader(builder); + reader.getBOOL("block", "var", outValue); + ensure_equals("Ensure BOOL", inValue, outValue); + } + + template<> template<> + void LLSDMessageBuilderTestObject::test<3>() + // U8 + { + U8 outValue, inValue = 2; + LLSDMessageBuilder builder = defaultBuilder(); + builder.addU8("var", inValue); + LLSDMessageReader reader = setReader(builder); + reader.getU8("block", "var", outValue); + ensure_equals("Ensure U8", inValue, outValue); + } + + template<> template<> + void LLSDMessageBuilderTestObject::test<4>() + // S16 + { + S16 outValue, inValue = 90; + LLSDMessageBuilder builder = defaultBuilder(); + builder.addS16("var", inValue); + LLSDMessageReader reader = setReader(builder); + reader.getS16("block", "var", outValue); + ensure_equals("Ensure S16", inValue, outValue); + } + + template<> template<> + void LLSDMessageBuilderTestObject::test<5>() + // U16 + { + U16 outValue, inValue = 3; + LLSDMessageBuilder builder = defaultBuilder(); + builder.addU16("var", inValue); + LLSDMessageReader reader = setReader(builder); + reader.getU16("block", "var", outValue); + ensure_equals("Ensure U16", inValue, outValue); + } + + template<> template<> + void LLSDMessageBuilderTestObject::test<6>() + // S32 + { + S32 outValue, inValue = 44; + LLSDMessageBuilder builder = defaultBuilder(); + builder.addS32("var", inValue); + LLSDMessageReader reader = setReader(builder); + reader.getS32("block", "var", outValue); + ensure_equals("Ensure S32", inValue, outValue); + } + + template<> template<> + void LLSDMessageBuilderTestObject::test<7>() + // F32 + { + F32 outValue, inValue = 121.44; + LLSDMessageBuilder builder = defaultBuilder(); + builder.addF32("var", inValue); + LLSDMessageReader reader = setReader(builder); + reader.getF32("block", "var", outValue); + ensure_equals("Ensure F32", inValue, outValue); + } + + template<> template<> + void LLSDMessageBuilderTestObject::test<8>() + // U32 + { + U32 outValue, inValue = 88; + LLSDMessageBuilder builder = defaultBuilder(); + builder.addU32("var", inValue); + LLSDMessageReader reader = setReader(builder); + reader.getU32("block", "var", outValue); + ensure_equals("Ensure U32", inValue, outValue); + } + + template<> template<> + void LLSDMessageBuilderTestObject::test<9>() + // U64 + { + U64 outValue, inValue = 121; + LLSDMessageBuilder builder = defaultBuilder(); + builder.addU64("var", inValue); + LLSDMessageReader reader = setReader(builder); + reader.getU64("block", "var", outValue); + ensure_equals("Ensure U64", inValue, outValue); + } + + template<> template<> + void LLSDMessageBuilderTestObject::test<10>() + // F64 + { + F64 outValue, inValue = 3232143.33; + LLSDMessageBuilder builder = defaultBuilder(); + builder.addF64("var", inValue); + LLSDMessageReader reader = setReader(builder); + reader.getF64("block", "var", outValue); + ensure_equals("Ensure F64", inValue, outValue); + } + + template<> template<> + void LLSDMessageBuilderTestObject::test<11>() + // Vector3 + { + LLVector3 outValue, inValue = LLVector3(1,2,3); + LLSDMessageBuilder builder = defaultBuilder(); + builder.addVector3("var", inValue); + LLSDMessageReader reader = setReader(builder); + reader.getVector3("block", "var", outValue); + ensure_equals("Ensure Vector3", inValue, outValue); + } + + template<> template<> + void LLSDMessageBuilderTestObject::test<12>() + // Vector4 + { + LLVector4 outValue, inValue = LLVector4(1,2,3,4); + LLSDMessageBuilder builder = defaultBuilder(); + builder.addVector4("var", inValue); + LLSDMessageReader reader = setReader(builder); + reader.getVector4("block", "var", outValue); + ensure_equals("Ensure Vector4", inValue, outValue); + } + + template<> template<> + void LLSDMessageBuilderTestObject::test<13>() + // Vector3d + { + LLVector3d outValue, inValue = LLVector3d(1,2,3); + LLSDMessageBuilder builder = defaultBuilder(); + builder.addVector3d("var", inValue); + LLSDMessageReader reader = setReader(builder); + reader.getVector3d("block", "var", outValue); + ensure_equals("Ensure Vector3d", inValue, outValue); + } + + template<> template<> + void LLSDMessageBuilderTestObject::test<14>() + // Quaternion + { + LLQuaternion outValue, inValue = LLQuaternion(1,2,3,4); + LLSDMessageBuilder builder = defaultBuilder(); + builder.addQuat("var", inValue); + LLSDMessageReader reader = setReader(builder); + reader.getQuat("block", "var", outValue); + ensure_equals("Ensure Quaternion", inValue, outValue); + } + + template<> template<> + void LLSDMessageBuilderTestObject::test<15>() + // UUID + { + LLUUID outValue, inValue; + inValue.generate(); + LLSDMessageBuilder builder = defaultBuilder(); + builder.addUUID("var", inValue); + LLSDMessageReader reader = setReader(builder); + reader.getUUID("block", "var", outValue); + ensure_equals("Ensure UUID", inValue, outValue); + } + + template<> template<> + void LLSDMessageBuilderTestObject::test<16>() + // IPAddr + { + U32 outValue, inValue = 12344556; + LLSDMessageBuilder builder = defaultBuilder(); + builder.addIPAddr("var", inValue); + LLSDMessageReader reader = setReader(builder); + reader.getIPAddr("block", "var", outValue); + ensure_equals("Ensure IPAddr", inValue, outValue); + } + + template<> template<> + void LLSDMessageBuilderTestObject::test<17>() + // IPPort + { + U16 outValue, inValue = 80; + LLSDMessageBuilder builder = defaultBuilder(); + builder.addIPPort("var", inValue); + LLSDMessageReader reader = setReader(builder); + reader.getIPPort("block", "var", outValue); + ensure_equals("Ensure IPPort", inValue, outValue); + } + + template<> template<> + void LLSDMessageBuilderTestObject::test<18>() + { + std::string outValue, inValue = "testing"; + LLSDMessageBuilder builder = defaultBuilder(); + builder.addString("var", inValue.c_str()); + LLSDMessageReader reader = setReader(builder); + char buffer[MAX_STRING]; + reader.getString("block", "var", MAX_STRING, buffer); + outValue = buffer; + ensure_equals("Ensure String", inValue, outValue); + } +} + diff --git a/indra/test/llsdmessagereader_tut.cpp b/indra/test/llsdmessagereader_tut.cpp new file mode 100755 index 0000000000..31810ae00e --- /dev/null +++ b/indra/test/llsdmessagereader_tut.cpp @@ -0,0 +1,300 @@ +/** + * @file llsdmessagereader_tut.cpp + * @date February 2006 + * @brief LLSDMessageReader unit tests + * + * Copyright (c) 2006-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#include <tut/tut.h> +#include "lltut.h" + +#include "llsdmessagereader.h" +#include "llsdutil.h" + +namespace tut +{ + struct LLSDMessageReaderTestData { + static void ensureMessageName(const std::string& msg_name, + const LLSD& msg_data, + const std::string& expected_name) + { + LLSDMessageReader msg; + msg.setMessage(msg_name, msg_data); + ensure_equals("Ensure name", std::string(msg.getMessageName()), + expected_name); + } + + static void ensureNumberOfBlocks(const LLSD& msg_data, + const std::string& block, + S32 expected_number) + { + LLSDMessageReader msg; + msg.setMessage("fakename", msg_data); + ensure_equals("Ensure number of blocks", msg.getNumberOfBlocks(block.c_str()), + expected_number); + } + + static void ensureMessageSize(const LLSD& msg_data, + S32 expected_size) + { + LLSDMessageReader msg; + msg.setMessage("fakename", msg_data); + ensure_equals( "Ensure size", msg.getMessageSize(), expected_size); + } + + static void ensureBool(const LLSD& msg_data, + const std::string& block, + const std::string& var, + S32 blocknum, + BOOL expected) + { + LLSDMessageReader msg; + msg.setMessage("fakename", msg_data); + BOOL test_data; + msg.getBOOL(block.c_str(), var.c_str(), test_data, blocknum); + ensure_equals( "Ensure bool field", test_data, expected); + } + }; + + typedef test_group<LLSDMessageReaderTestData> LLSDMessageReaderTestGroup; + typedef LLSDMessageReaderTestGroup::object LLSDMessageReaderTestObject; + LLSDMessageReaderTestGroup llsdMessageReaderTestGroup("LLSDMessageReader"); + + template<> template<> + void LLSDMessageReaderTestObject::test<1>() + // construction and test of empty LLSD + { + LLSD message = LLSD::emptyMap(); + + ensureMessageName("", message, ""); + ensureNumberOfBlocks(message, "Fakeblock", 0); + ensureMessageSize(message, 0); + } + + template<> template<> + void LLSDMessageReaderTestObject::test<2>() + // construction and test of simple message with one block + { + LLSD message = LLSD::emptyMap(); + message["block1"] = LLSD::emptyArray(); + message["block1"][0] = LLSD::emptyMap(); + message["block1"][0]["Field1"] = 0; + + ensureMessageName("name2", message, "name2"); + ensureNumberOfBlocks(message, "block1", 1); + ensureMessageSize(message, 0); + } + + template<> template<> + void LLSDMessageReaderTestObject::test<3>() + // multiple blocks + { + LLSD message = LLSD::emptyMap(); + message["block1"] = LLSD::emptyArray(); + BOOL bool_true = TRUE; + BOOL bool_false = FALSE; + message["block1"][0] = LLSD::emptyMap(); + message["block1"][0]["BoolField1"] = bool_true; + message["block1"][1] = LLSD::emptyMap(); + message["block1"][1]["BoolField1"] = bool_false; + message["block1"][1]["BoolField2"] = bool_true; + + ensureMessageName("name3", message, "name3"); + ensureBool(message, "block1", "BoolField1", 0, TRUE); + ensureBool(message, "block1", "BoolField1", 1, FALSE); + ensureBool(message, "block1", "BoolField2", 1, TRUE); + ensureNumberOfBlocks(message, "block1", 2); + ensureMessageSize(message, 0); + } + + template<typename T> + LLSDMessageReader testType(const T& value) + { + LLSD message = LLSD::emptyMap(); + message["block"][0]["var"] = value; + LLSDMessageReader msg; + msg.setMessage("fakename", message); + return msg; + } + + template<> template<> + void LLSDMessageReaderTestObject::test<4>() + // S8 + { + S8 outValue, inValue = -3; + LLSDMessageReader msg = testType(inValue); + msg.getS8("block", "var", outValue); + ensure_equals("Ensure S8", outValue, inValue); + } + template<> template<> + void + LLSDMessageReaderTestObject::test<5>() + // U8 + { + U8 outValue, inValue = 2; + LLSDMessageReader msg = testType(inValue); + msg.getU8("block", "var", outValue); + ensure_equals("Ensure U8", outValue, inValue); + } + template<> template<> + void LLSDMessageReaderTestObject::test<6>() + // S16 + { + S16 outValue, inValue = 90; + LLSDMessageReader msg = testType(inValue); + msg.getS16("block", "var", outValue); + ensure_equals("Ensure S16", outValue, inValue); + } + template<> template<> + void LLSDMessageReaderTestObject::test<7>() + // U16 + { + U16 outValue, inValue = 3; + LLSDMessageReader msg = testType(inValue); + msg.getU16("block", "var", outValue); + ensure_equals("Ensure S16", outValue, inValue); + } + template<> template<> + void LLSDMessageReaderTestObject::test<8>() + // S32 + { + S32 outValue, inValue = 44; + LLSDMessageReader msg = testType(inValue); + msg.getS32("block", "var", outValue); + ensure_equals("Ensure S32", outValue, inValue); + } + template<> template<> + void LLSDMessageReaderTestObject::test<9>() + // F32 + { + F32 outValue, inValue = 121.44; + LLSDMessageReader msg = testType(inValue); + msg.getF32("block", "var", outValue); + ensure_equals("Ensure F32", outValue, inValue); + } + template<> template<> + void LLSDMessageReaderTestObject::test<10>() + // U32 + { + U32 outValue, inValue = 88; + LLSD sdValue = ll_sd_from_U32(inValue); + LLSDMessageReader msg = testType(sdValue); + msg.getU32("block", "var", outValue); + ensure_equals("Ensure U32", outValue, inValue); + } + template<> template<> + void LLSDMessageReaderTestObject::test<11>() + // U64 + { + U64 outValue, inValue = 121; + LLSD sdValue = ll_sd_from_U64(inValue); + LLSDMessageReader msg = testType(sdValue); + msg.getU64("block", "var", outValue); + ensure_equals("Ensure U64", outValue, inValue); + } + template<> template<> + void LLSDMessageReaderTestObject::test<12>() + // F64 + { + F64 outValue, inValue = 3232143.33; + LLSDMessageReader msg = testType(inValue); + msg.getF64("block", "var", outValue); + ensure_equals("Ensure F64", outValue, inValue); + } + template<> template<> + void LLSDMessageReaderTestObject::test<13>() + // String + { + std::string outValue, inValue = "testing"; + LLSDMessageReader msg = testType<std::string>(inValue.c_str()); + + char buffer[MAX_STRING]; + msg.getString("block", "var", MAX_STRING, buffer); + outValue = buffer; + ensure_equals("Ensure String", outValue, inValue); + } + template<> template<> + void LLSDMessageReaderTestObject::test<14>() + // Vector3 + { + LLVector3 outValue, inValue = LLVector3(1,2,3); + LLSD sdValue = ll_sd_from_vector3(inValue); + LLSDMessageReader msg = testType(sdValue); + msg.getVector3("block", "var", outValue); + ensure_equals("Ensure Vector3", outValue, inValue); + } + template<> template<> + void LLSDMessageReaderTestObject::test<15>() + // Vector4 + { + LLVector4 outValue, inValue = LLVector4(1,2,3,4); + LLSD sdValue = ll_sd_from_vector4(inValue); + LLSDMessageReader msg = testType(sdValue); + msg.getVector4("block", "var", outValue); + ensure_equals("Ensure Vector4", outValue, inValue); + } + template<> template<> + void LLSDMessageReaderTestObject::test<16>() + // Vector3d + { + LLVector3d outValue, inValue = LLVector3d(1,2,3); + LLSD sdValue = ll_sd_from_vector3d(inValue); + LLSDMessageReader msg = testType(sdValue); + msg.getVector3d("block", "var", outValue); + ensure_equals("Ensure Vector3d", outValue, inValue); + } + template<> template<> + void LLSDMessageReaderTestObject::test<17>() + // Quaternion + { + LLQuaternion outValue, inValue = LLQuaternion(1,2,3,4); + LLSD sdValue = ll_sd_from_quaternion(inValue); + LLSDMessageReader msg = testType(sdValue); + msg.getQuat("block", "var", outValue); + ensure_equals("Ensure Quaternion", outValue, inValue); + } + template<> template<> + void LLSDMessageReaderTestObject::test<18>() + // UUID + { + LLUUID outValue, inValue; + inValue.generate(); + LLSDMessageReader msg = testType(inValue); + msg.getUUID("block", "var", outValue); + ensure_equals("Ensure UUID", outValue, inValue); + } + template<> template<> + void LLSDMessageReaderTestObject::test<19>() + // IPAddr + { + U32 outValue, inValue = 12344556; + LLSD sdValue = ll_sd_from_ipaddr(inValue); + LLSDMessageReader msg = testType(sdValue); + msg.getIPAddr("block", "var", outValue); + ensure_equals("Ensure IPAddr", outValue, inValue); + } + template<> template<> + void LLSDMessageReaderTestObject::test<20>() + // IPPort + { + U16 outValue, inValue = 80; + LLSDMessageReader msg = testType(inValue); + msg.getIPPort("block", "var", outValue); + ensure_equals("Ensure IPPort", outValue, inValue); + } + template<> template<> + void LLSDMessageReaderTestObject::test<21>() + // Binary + { + std::vector<U8> outValue(2), inValue(2); + inValue[0] = 0; + inValue[1] = 1; + + LLSDMessageReader msg = testType(inValue); + msg.getBinaryData("block", "var", &(outValue[0]), inValue.size()); + ensure_equals("Ensure Binary", outValue, inValue); + } +} + diff --git a/indra/test/llsdtraits.h b/indra/test/llsdtraits.h new file mode 100644 index 0000000000..2e6a96a425 --- /dev/null +++ b/indra/test/llsdtraits.h @@ -0,0 +1,78 @@ +#ifndef LLSDTRAITS_H +#define LLSDTRAITS_H + +#include "llsd.h" +#include "llstring.h" + +template<class T> +class LLSDTraits +{ + protected: + typedef T (LLSD::*Getter)() const; + + LLSD::Type type; + Getter getter; + + public: + LLSDTraits(); + + T get(const LLSD& actual) + { + return (actual.*getter)(); + } + + bool checkType(const LLSD& actual) + { + return actual.type() == type; + } +}; + +template<> inline +LLSDTraits<LLSD::Boolean>::LLSDTraits() + : type(LLSD::TypeBoolean), getter(&LLSD::asBoolean) +{ } + +template<> inline +LLSDTraits<LLSD::Integer>::LLSDTraits() + : type(LLSD::TypeInteger), getter(&LLSD::asInteger) +{ } + +template<> inline +LLSDTraits<LLSD::Real>::LLSDTraits() + : type(LLSD::TypeReal), getter(&LLSD::asReal) +{ } + +template<> inline +LLSDTraits<LLSD::UUID>::LLSDTraits() + : type(LLSD::TypeUUID), getter(&LLSD::asUUID) +{ } + +template<> inline +LLSDTraits<LLSD::String>::LLSDTraits() + : type(LLSD::TypeString), getter(&LLSD::asString) +{ } + +template<> +class LLSDTraits<LLString> : public LLSDTraits<LLSD::String> +{ }; + +template<> +class LLSDTraits<const char*> : public LLSDTraits<LLSD::String> +{ }; + +template<> inline +LLSDTraits<LLSD::Date>::LLSDTraits() + : type(LLSD::TypeDate), getter(&LLSD::asDate) +{ } + +template<> inline +LLSDTraits<LLSD::URI>::LLSDTraits() + : type(LLSD::TypeURI), getter(&LLSD::asURI) +{ } + +template<> inline +LLSDTraits<LLSD::Binary>::LLSDTraits() + : type(LLSD::TypeBinary), getter(&LLSD::asBinary) +{ } + +#endif // LLSDTRAITS_H diff --git a/indra/test/llservicebuilder_tut.cpp b/indra/test/llservicebuilder_tut.cpp new file mode 100644 index 0000000000..b4a814ebb9 --- /dev/null +++ b/indra/test/llservicebuilder_tut.cpp @@ -0,0 +1,76 @@ +/** +* @file llservicebuilder_tut.cpp +* @brief LLServiceBuilder unit tests +* @date March 2007 +* +* Copyright (c) 2006-$CurrentYear$, Linden Research, Inc. +* $License$ +*/ + +#include <tut/tut.h> +#include "lltut.h" + +#include "llsd.h" +#include "llservicebuilder.h" + +namespace tut +{ + + struct ServiceBuilderTestData { + LLServiceBuilder mServiceBuilder; + }; + + typedef test_group<ServiceBuilderTestData> ServiceBuilderTestGroup; + typedef ServiceBuilderTestGroup::object ServiceBuilderTestObject; + + ServiceBuilderTestGroup serviceBuilderTestGroup("ServiceBuilder"); + + template<> template<> + void ServiceBuilderTestObject::test<1>() + { + //Simple service build and reply with no mapping + LLSD test_block; + test_block["service-builder"] = "/agent/name"; + mServiceBuilder.createServiceDefinition("ServiceBuilderTest", test_block["service-builder"]); + std::string test_url = mServiceBuilder.buildServiceURI("ServiceBuilderTest"); + ensure_equals("Basic URL Creation", test_url , "/agent/name"); + } + + template<> template<> + void ServiceBuilderTestObject::test<2>() + { + //Simple replace test + LLSD test_block; + test_block["service-builder"] = "/agent/{$agent-id}/name"; + mServiceBuilder.createServiceDefinition("ServiceBuilderTest", test_block["service-builder"]); + LLSD data_map; + data_map["agent-id"] = "257c631f-a0c5-4f29-8a9f-9031feaae6c6"; + std::string test_url = mServiceBuilder.buildServiceURI("ServiceBuilderTest", data_map); + ensure_equals("Replacement URL Creation", test_url , "/agent/257c631f-a0c5-4f29-8a9f-9031feaae6c6/name"); + } + + template<> template<> + void ServiceBuilderTestObject::test<3>() + { + //Incorrect service test + LLSD test_block; + test_block["service-builder"] = "/agent/{$agent-id}/name"; + mServiceBuilder.createServiceDefinition("ServiceBuilderTest", test_block["service-builder"]); + std::string test_url = mServiceBuilder.buildServiceURI("ServiceBuilder"); + ensure_equals("Replacement URL Creation for Non-existant Service", test_url , ""); + } + + template<> template<> + void ServiceBuilderTestObject::test<4>() + { + //Incorrect service test + LLSD test_block; + test_block["service-builder"] = "/agent/{$agent-id}/name"; + mServiceBuilder.createServiceDefinition("ServiceBuilderTest", test_block["service-builder"]); + LLSD data_map; + data_map["agent_id"] = "257c631f-a0c5-4f29-8a9f-9031feaae6c6"; + std::string test_url = mServiceBuilder.buildServiceURI("ServiceBuilderTest", data_map); + ensure_equals("Replacement URL Creation for Non-existant Service", test_url , "/agent/{$agent-id}/name"); + } +} + diff --git a/indra/test/test_llmanifest.py b/indra/test/test_llmanifest.py index cc464237a2..f4fc2820eb 100644 --- a/indra/test/test_llmanifest.py +++ b/indra/test/test_llmanifest.py @@ -87,7 +87,7 @@ class TestLLManifest(unittest.TestCase): def testruncommand(self): self.assertEqual("Hello\n", self.m.run_command("echo Hello")) def tmp_test(): - self.m.run_command("fff_garbage") + self.m.run_command("test_command_that_should_not_be_found") self.assertRaises(RuntimeError, tmp_test) def testpathof(self): diff --git a/indra/win_updater/updater.cpp b/indra/win_updater/updater.cpp index 96ffd5f66a..c139d2f55c 100644 --- a/indra/win_updater/updater.cpp +++ b/indra/win_updater/updater.cpp @@ -7,7 +7,7 @@ */ // -// Usage: updater -userserver <server> [-name <window_title>] [-program <program_name>] [-silent] +// Usage: updater -url <url> [-name <window_title>] [-program <program_name>] [-silent] // #include <windows.h> @@ -23,7 +23,7 @@ int gTotalBytesRead = 0; HWND gWindow = NULL; WCHAR gProgress[256]; -char* gUserServer; +char* gUpdateURL; char* gProgramName; char* gProductName; bool gIsSilent; @@ -254,28 +254,20 @@ LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) } #define win_class_name L"FullScreen" -#define UPDATE_URIBASE L"http://secondlife.com/update.php?userserver=" int parse_args(int argc, char **argv) { - // Check for old-type arguments. - if (2 == argc) - { - gUserServer = argv[1]; - return 0; - } - int j; for (j = 1; j < argc; j++) { - if ((!strcmp(argv[j], "-userserver")) && (++j < argc)) + if ((!strcmp(argv[j], "-name")) && (++j < argc)) { - gUserServer = argv[j]; + gProductName = argv[j]; } - else if ((!strcmp(argv[j], "-name")) && (++j < argc)) + else if ((!strcmp(argv[j], "-url")) && (++j < argc)) { - gProductName = argv[j]; + gUpdateURL = argv[j]; } else if ((!strcmp(argv[j], "-program")) && (++j < argc)) { @@ -288,7 +280,7 @@ int parse_args(int argc, char **argv) } // If nothing was set, let the caller know. - if (!gUserServer && !gProductName && !gProgramName && !gIsSilent) + if (!gProductName && !gProgramName && !gIsSilent && !gUpdateURL) { return 1; } @@ -339,7 +331,7 @@ WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nSho } } - gUserServer = NULL; + gUpdateURL = NULL; gProgramName = NULL; gProductName = NULL; gIsSilent = false; @@ -373,7 +365,6 @@ WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nSho DEVMODE dev_mode = { 0 }; char update_exec_path[MAX_PATH]; /* Flawfinder: ignore */ char *ptr; - WCHAR update_uri[4096]; const int WINDOW_WIDTH = 250; const int WINDOW_HEIGHT = 100; @@ -408,15 +399,15 @@ WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nSho if (parse_args_result) { MessageBox(gWindow, - L"Usage: updater -userserver <server> [-name <window_title>] [-program <program_name>] [-silent]", + L"Usage: updater -url <url> [-name <window_title>] [-program <program_name>] [-silent]", L"Usage", MB_OK); return parse_args_result; } // Did we get a userserver to work with? - if (!gUserServer) + if (!gUpdateURL) { - MessageBox(gWindow, L"Please specify the IP address of the userserver on the command line", + MessageBox(gWindow, L"Please specify the download url from the command line", L"Error", MB_OK); return 1; } @@ -440,10 +431,9 @@ WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nSho *(ptr + 2) = 'x'; *(ptr + 3) = 'e'; *(ptr + 4) = 0; - wcscpy(update_uri, UPDATE_URIBASE); /* Flawfinder: ignore */ - WCHAR wcmdline[2048]; - mbstowcs(wcmdline, gUserServer, 2048); - wcscat(update_uri, wcmdline); /* Flawfinder: ignore */ + + WCHAR update_uri[4096]; + mbstowcs(update_uri, gUpdateURL, 4096); int success; int cancelled; diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg index 32a514502f..8213ed0bc9 100644 --- a/scripts/messages/message_template.msg +++ b/scripts/messages/message_template.msg @@ -952,7 +952,6 @@ sim -> dataserver { Name Variable 1 } { ForSale BOOL } { Auction BOOL } - { ReservedNewbie BOOL } { Dwell F32 } } } @@ -1019,8 +1018,7 @@ sim -> dataserver { GroupID LLUUID } { GroupName Variable 1 } // string { Members S32 } - { OpenEnrollment BOOL } - { MembershipFee S32 } + { SearchOrder F32 } } } @@ -1339,7 +1337,6 @@ sim -> dataserver { Name Variable 1 } { Auction BOOL } { ForSale BOOL } - { ReservedNewbie BOOL } { SalePrice S32 } { ActualArea S32 } } @@ -2259,8 +2256,8 @@ sim -> dataserver { PathCurve U8 } { ProfileCurve U8 } - { PathBegin U8 } // 0 to 1, quanta = 0.01 - { PathEnd U8 } // 0 to 1, quanta = 0.01 + { PathBegin U16 } // 0 to 1, quanta = 0.01 + { PathEnd U16 } // 0 to 1, quanta = 0.01 { PathScaleX U8 } // 0 to 1, quanta = 0.01 { PathScaleY U8 } // 0 to 1, quanta = 0.01 { PathShearX U8 } // -.5 to .5, quanta = 0.01 @@ -2272,9 +2269,9 @@ sim -> dataserver { PathTaperY S8 } // -1 to 1, quanta = 0.01 { PathRevolutions U8 } // 0 to 3, quanta = 0.015 { PathSkew S8 } // -1 to 1, quanta = 0.01 - { ProfileBegin U8 } // 0 to 1, quanta = 0.01 - { ProfileEnd U8 } // 0 to 1, quanta = 0.01 - { ProfileHollow U8 } // 0 to 1, quanta = 0.01 + { ProfileBegin U16 } // 0 to 1, quanta = 0.01 + { ProfileEnd U16 } // 0 to 1, quanta = 0.01 + { ProfileHollow U16 } // 0 to 1, quanta = 0.01 { BypassRaycast U8 } { RayStart LLVector3 } @@ -2531,8 +2528,8 @@ sim -> dataserver { ObjectLocalID U32 } { PathCurve U8 } { ProfileCurve U8 } - { PathBegin U8 } // 0 to 1, quanta = 0.01 - { PathEnd U8 } // 0 to 1, quanta = 0.01 + { PathBegin U16 } // 0 to 1, quanta = 0.01 + { PathEnd U16 } // 0 to 1, quanta = 0.01 { PathScaleX U8 } // 0 to 1, quanta = 0.01 { PathScaleY U8 } // 0 to 1, quanta = 0.01 { PathShearX U8 } // -.5 to .5, quanta = 0.01 @@ -2544,9 +2541,9 @@ sim -> dataserver { PathTaperY S8 } // -1 to 1, quanta = 0.01 { PathRevolutions U8 } // 0 to 3, quanta = 0.015 { PathSkew S8 } // -1 to 1, quanta = 0.01 - { ProfileBegin U8 } // 0 to 1, quanta = 0.01 - { ProfileEnd U8 } // 0 to 1, quanta = 0.01 - { ProfileHollow U8 } // 0 to 1, quanta = 0.01 + { ProfileBegin U16 } // 0 to 1, quanta = 0.01 + { ProfileEnd U16 } // 0 to 1, quanta = 0.01 + { ProfileHollow U16 } // 0 to 1, quanta = 0.01 } } @@ -3623,8 +3620,8 @@ sim -> dataserver { PathCurve U8 } { ProfileCurve U8 } - { PathBegin U8 } // 0 to 1, quanta = 0.01 - { PathEnd U8 } // 0 to 1, quanta = 0.01 + { PathBegin U16 } // 0 to 1, quanta = 0.01 + { PathEnd U16 } // 0 to 1, quanta = 0.01 { PathScaleX U8 } // 0 to 1, quanta = 0.01 { PathScaleY U8 } // 0 to 1, quanta = 0.01 { PathShearX U8 } // -.5 to .5, quanta = 0.01 @@ -3636,9 +3633,9 @@ sim -> dataserver { PathTaperY S8 } // -1 to 1, quanta = 0.01 { PathRevolutions U8 } // 0 to 3, quanta = 0.015 { PathSkew S8 } // -1 to 1, quanta = 0.01 - { ProfileBegin U8 } // 0 to 1, quanta = 0.01 - { ProfileEnd U8 } // 0 to 1, quanta = 0.01 - { ProfileHollow U8 } // 0 to 1, quanta = 0.01 + { ProfileBegin U16 } // 0 to 1, quanta = 0.01 + { ProfileEnd U16 } // 0 to 1, quanta = 0.01 + { ProfileHollow U16 } // 0 to 1, quanta = 0.01 { TextureEntry Variable 2 } { TextureAnim Variable 1 } @@ -4861,7 +4858,6 @@ sim -> dataserver { OwnerID LLUUID } { IsGroupOwned BOOL } { AuctionID U32 } - { ReservedNewbie BOOL } { ClaimDate S32 } // time_t { ClaimPrice S32 } { RentPrice S32 } @@ -5358,7 +5354,6 @@ sim -> dataserver { BillableArea S32 } { ActualArea S32 } { Final BOOL } // true if buyer should be in tier - { ReservedNewbie BOOL } } } @@ -5390,7 +5385,6 @@ sim -> dataserver { UserLocation LLVector3 } { SalePrice S32 } { AuthorizedBuyerID LLUUID } - { ReservedNewbie BOOL } { AllowPublish BOOL } { MaturePublish BOOL } } @@ -5479,20 +5473,6 @@ sim -> dataserver } } -// viewer -> sim -{ - ParcelGodReserveForNewbie Low NotTrusted Unencoded - { - AgentData Single - { AgentID LLUUID } - { SessionID LLUUID } - } - { - ParcelData Single - { LocalID S32 } - { SnapshotID LLUUID } - } -} // viewer -> sim // start an auction. viewer fills in the appropriate date, simulator @@ -5845,8 +5825,8 @@ sim -> dataserver { PathCurve U8 } { ProfileCurve U8 } - { PathBegin U8 } // 0 to 1, quanta = 0.01 - { PathEnd U8 } // 0 to 1, quanta = 0.01 + { PathBegin U16 } // 0 to 1, quanta = 0.01 + { PathEnd U16 } // 0 to 1, quanta = 0.01 { PathScaleX U8 } // 0 to 1, quanta = 0.01 { PathScaleY U8 } // 0 to 1, quanta = 0.01 { PathShearX U8 } // -.5 to .5, quanta = 0.01 @@ -5858,9 +5838,9 @@ sim -> dataserver { PathTaperY S8 } // -1 to 1, quanta = 0.01 { PathRevolutions U8 } // 0 to 3, quanta = 0.015 { PathSkew S8 } // -1 to 1, quanta = 0.01 - { ProfileBegin U8 } // 0 to 1, quanta = 0.01 - { ProfileEnd U8 } // 0 to 1, quanta = 0.01 - { ProfileHollow U8 } // 0 to 1, quanta = 0.01 + { ProfileBegin U16 } // 0 to 1, quanta = 0.01 + { ProfileEnd U16 } // 0 to 1, quanta = 0.01 + { ProfileHollow U16 } // 0 to 1, quanta = 0.01 { TextureEntry Variable 2 } @@ -6178,12 +6158,6 @@ sim -> dataserver } } -// DequeueInstantMessages - used to get messages out of the IM -// queue that have come from outside of the system. -{ - DequeueInstantMessages Low Trusted Unencoded -} - // FindAgent - used to find an agent's global position. I used a // variable sized LocationBlock so that the message can be recycled with // minimum new messages and handlers. @@ -7367,6 +7341,9 @@ sim -> dataserver { AggregatePermNextOwner U8 } { AggregatePermInventory U8 } { TransactionType S32 } // see lltransactiontypes.h + { RegionID LLUUID } // region sending the request, for logging + { GridX U32 } // *HACK: database doesn't have region_id in schema + { GridY U32 } // *HACK: database doesn't have region_id in schema { Description Variable 1 } // string, name of item for purchases } } @@ -7638,27 +7615,6 @@ sim -> dataserver // Gesture saves/loads //--------------------------------------------------------------------------- -// viewer -> userserver -> dataserver -// dataserver -> userserver -> viewer -{ - GestureUpdate Medium NotTrusted Unencoded - { - AgentBlock Single - { AgentID LLUUID } - { Filename Variable 1 } // String - { ToViewer BOOL } // BOOL, direction this is going - } -} - -// viewer -> userserver -> dataserver -{ - GestureRequest Low NotTrusted Unencoded - { - AgentBlock Single - { AgentID LLUUID } - { Reset BOOL } // 0=no reset, 1=male, 2=female - } -} // Tell the database that some gestures are now active // viewer -> sim -> data @@ -8096,8 +8052,12 @@ sim -> dataserver { ReputationIndividualRequest Low NotTrusted Unencoded { + AgentData Single + { AgentID LLUUID } + { SessionID LLUUID } + } + { ReputationData Single - { FromID LLUUID } { ToID LLUUID } } } @@ -8107,8 +8067,11 @@ sim -> dataserver { ReputationIndividualReply Low Trusted Unencoded { + AgentData Single + { AgentID LLUUID } + } + { ReputationData Single - { FromID LLUUID } { ToID LLUUID } { Behavior F32 } // float, usually -1 or +1 { Appearance F32 } // float, usually -1 or +1 @@ -9387,43 +9350,6 @@ sim -> dataserver // System operations and maintenance //----------------------------------------------------------------------------- -// GodExpungeUser is sent from a viewer or other untrusted source to -// start the process for getting rid of a list of users. The message -// goes to the userserver, checks for godhood, and forwards the -// request to the dataserver. The dataserver then marks the user as being -// expunged and sends a StartExpungeProcess out to the simulators. -{ - GodExpungeUser Low NotTrusted Zerocoded - { - AgentData Single - { AgentID LLUUID } - { SessionID LLUUID } - } - { - ExpungeData Variable - { AgentID LLUUID } - } -} - -// StartExpungeProcess is sent from the dataserver to the userserver, -// and from there relayed to the simulators which mark parcels and -// objects owned by the agent as being expunged. -{ - StartExpungeProcess Low Trusted Zerocoded - { - ExpungeData Variable - { AgentID LLUUID } - } -} - -// StartExpungeProcessAck - is sent from the userserver to anyone who -// sends a StartExpungeProcess. This is used to aid scripting the -// expunge process, since the message system does not generate -// any errors if you attempt to connect to a non-existant host within -// a reasonable timeframe for scripting -{ - StartExpungeProcessAck Low Trusted Unencoded -} // Message to rename identified parcels. script -> userserver -> dataserver { |