diff --git a/etc/message.xml b/etc/message.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b0153452acd571d482dda47b6cb4d983fb5c427b
--- /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 4acd53360036b28f807af497663ea00ac8edde7f..0000000000000000000000000000000000000000
--- 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 20499d4ad331f145c17e9ea462f808304a84abb8..7f1c48a215ae4764a475f0a9de564203fae8c1f6 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 5fd06f9e3018e830b638298bd066a72e379dd60b..6927607c8f4b55275471d256be4df24f2da2e732 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 796cd9f9f498b53a529aa25ed49b91ed51e71a18..c5ab369d0f127cda0a473087644611396197bff5 100644
--- a/indra/llcommon/llsdserialize_xml.cpp
+++ b/indra/llcommon/llsdserialize_xml.cpp
@@ -234,7 +234,7 @@ class LLSDXMLParser::Impl
 	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 a6ac2fb12b74787b81ea10c75ce5c865aea5641b..57a024ecee5e2fdebbe5a9460103cf03b637c617 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 44e9429d7ff916423d02f077850c0c9c01690d5e..860232044ea23b3893be77593e9d1d0f2a7db307 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 bf0d2cb21e3be29eece990d032fe21cc713c5863..52270376f8737180b1b410362220e14f94bf3d94 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 865a3b21a043a5bdea68f6b913f96073d019e44b..f42cc102e650c20f445d2c7b0e3eaf08e0d3812e 100644
--- a/indra/llcommon/lluri.h
+++ b/indra/llcommon/lluri.h
@@ -77,13 +77,12 @@ class LLURI
   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 378ab8ced1e520efa026740d8a75f891219799d2..f7442380b06202c1f93b3297c41f54bf7cb6e2e4 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 94a90f2c2042ea661a6654cde583fa19ea1f36f7..6164dae22f7be0b0142099d1c5b291ae9bed2af2 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 42a9d642545f9060a33b88a0ab809edd4c632eed..7ea83f6e5e8cf32bc673bb10d5edfd5b63295ecb 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 16d3cb01e5fbc07e5c307211f2c20ee3c672902e..131bcdd55d938dc01d821cac66c10eaceaa9a590 100644
--- a/indra/llinventory/llparcel.h
+++ b/indra/llinventory/llparcel.h
@@ -190,7 +190,6 @@ class LLParcel
 	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 @@ class LLParcel
 	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 @@ class LLParcel
 	// 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 00a192aca8ca8af68a05b91ab697ebfa7206caa9..c5d105c9eed7b103d2b1a21b6719f5633b4678d6 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 97aeeb9589f150c5b5949528deaa183a6a9b222f..22742e09da664046024548fa41961bfd99a02c26 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 @@ class LLProfileParams
 	{
 	}
 
-	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 @@ class LLProfileParams
 			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 @@ class LLProfileParams
 	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 @@ class LLPathParams
 		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 0255a654df882188b8113110300f2ec314651696..d15e4fb69a61f0e602c49ae5662808cc6f526049 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 339fdda9efd036a5c0f017ea757ecd88fd0620da..36cd2ce188ea536865e25f6ef8fe94dc28abb07f 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 @@ class LLCacheName::Impl
 	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 @@ class LLCacheName::Impl
 	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 af49903c884757bf0ce84ebb847d5bd6a7ce5c39..c4f88ac490210e864763a3b91bbdaefb0089092c 100644
--- a/indra/llmessage/llcachename.h
+++ b/indra/llmessage/llcachename.h
@@ -78,7 +78,8 @@ class LLCacheName
 	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 d395188b72edafeba530a4fc5fe0ae268718a6ae..6a74cfe831fe91865b188f896d7527b72516b20d 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 121cbd2e6868e7566d30c268186338a3d4c97b6c..92c309f1bc14512d7c1db764f7fd9cc002409d85 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 0000000000000000000000000000000000000000..4152dedae503105de5ae3328020e5c133988190d
--- /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 0000000000000000000000000000000000000000..a9f42579c2714a50b8054b74f453823a519017f8
--- /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 944785c3a544b554a19e18228e05d0cc1383bf3c..28886108ea3eef9e1fcbf603abb3afa3ee054cc2 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 c8138cf491dadb5022eebd60d3e1fe68e93d92fb..99b2734a7049d8acf972b9cadca859e12c8ef3b2 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 @@ class LLIMInfo : public LLRefCount
 	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 c1a9bc442e05bcc8dcde43802e8df81fa5b3f0e5..869012e43152eeac0f2993983304e411ae41978b 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 @@ class LLHTTPResponder : public LLIOPipe
 		STATE_SHORT_CIRCUIT
 	};
 
+	LLSD mBuildContext;
 	EState mState;
 	U8* mLastRead;
 	std::string mVerb;
@@ -443,12 +446,14 @@ class LLHTTPResponder : public LLIOPipe
 	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 05dfdc4bf754816f8f8128c14e9dc231f49268e5..f11a1eccf680b3583dda241f9d9b591dfc807304 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 5cbe3d874307e98816d9cd193420819315d2c37e..6f7fbe652d750709d279cbcb74392351599d68b2 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 7649fef0cfe1eecccc0b909d2b13aaa475b500eb..7c33153086aa90fb0f2e5302cd2bbe6e57635c21 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 0000000000000000000000000000000000000000..d467e6d8088c734804282030c05671ca5110e31b
--- /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 0000000000000000000000000000000000000000..7ae09c54d53458965a43612f6a57f070ffdb7f43
--- /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 0000000000000000000000000000000000000000..a2b0bc5efaa9aab4303d3e77e565297bac51a987
--- /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 0000000000000000000000000000000000000000..2fb6f2077e9942e675815c8137d1c7a76b8e2658
--- /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 0000000000000000000000000000000000000000..4824480e32ed1a30ec23ac8374f2741ba48f518d
--- /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 0000000000000000000000000000000000000000..33ce9289f56ea7cfce2ec9d45b75f250196b14fd
--- /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 0000000000000000000000000000000000000000..026843d6ec08e2484720baecc3ff28ffe2d11d2e
--- /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 0000000000000000000000000000000000000000..8847ddc0d96c690d204c5feef40dbec10f3b5e3a
--- /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 0000000000000000000000000000000000000000..360d9496904e3eb5608533acba1280067be14d57
--- /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 0874da6236c0e97eb8fad3ccfbeeac716bb5d050..4c22dc2d623b120374df435ccf7e9986afd44da6 100644
--- a/indra/llmessage/llpacketack.h
+++ b/indra/llmessage/llpacketack.h
@@ -44,6 +44,14 @@ class LLReliablePacketParams
 public:
 	LLReliablePacketParams()
 	{
+		clear();
+	};
+
+	~LLReliablePacketParams() { };
+
+	void clear()
+	{
+		mHost.invalidate();
 		mRetries = 0;
 		mPingBasedRetry = TRUE;
 		mTimeout = 0.f;
@@ -52,8 +60,6 @@ class LLReliablePacketParams
 		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 @@ class LLReliablePacket
 			
 		}
 	};
-	~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 1be6c21cc2c562cb25c6dec155a3ccdb1dd1dbbc..4fa3fab1c930e9745f9b1199e1698b4e14fcbd95 100644
--- a/indra/llmessage/llpumpio.cpp
+++ b/indra/llmessage/llpumpio.cpp
@@ -313,6 +313,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);
@@ -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 50f7411298dbb51426347bb5e2ecc3b2a2161184..5edfbdf8ee3866ae51e341e4c048d5f28ca927c5 100644
--- a/indra/llmessage/llpumpio.h
+++ b/indra/llmessage/llpumpio.h
@@ -227,6 +227,7 @@ class LLPumpIO
 	 * 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 0000000000000000000000000000000000000000..b7deb4817f328c300b83f4a46857003971fad1ef
--- /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 0000000000000000000000000000000000000000..f04194d12f228eee090e82dc6e67b2fef1e6c6d3
--- /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 0000000000000000000000000000000000000000..6312bee0abc25c303605a1f1ff307714b2ae9f64
--- /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 0000000000000000000000000000000000000000..57851941a2f330711d87310f21a325099a06de58
--- /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 e243e710d68f85a11cb19e986890cf5aeebe7f9f..fe6fa56477ff6ed647d89f28b9249d0923b3c783 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 0000000000000000000000000000000000000000..fbcf38ae359c11b49065d4a6d9df3e51202f924e
--- /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 0000000000000000000000000000000000000000..2692ffe1e5228539eea0b134a86f348d0fa3ada9
--- /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 0000000000000000000000000000000000000000..806f03422dba7e43cf53da692466acead7398f33
--- /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 0000000000000000000000000000000000000000..ae533288fba461ad7d38f81d1cac90f8d053c1e5
--- /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 0000000000000000000000000000000000000000..892efb86977ed6198a1f782639449d243160a23f
--- /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 0000000000000000000000000000000000000000..dd5ee393fefec4127c8ad476fc9622effd338d7f
--- /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 6fb319326b015b695c9a36849541348dba6d5baa..78d12cbda9e7965865ff35cccf1a54a17436f1c1 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 @@ class LLMessagePollInfo
 	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,106 +281,162 @@ BOOL	b_positive_integer_ok(char *token)
 	return TRUE;
 }
 
-void LLMessageSystem::init()
+namespace
 {
-	// initialize member variables
-	mVerboseLog = FALSE;
+	class LLFnPtrResponder : public LLHTTPClient::Responder
+	{
+	public:
+		LLFnPtrResponder(void (*callback)(void **,S32), void **callbackData) :
+			mCallback(callback),
+			mCallbackData(callbackData)
+		{
+		}
 
-	mbError = FALSE;
-	mErrorCode = 0;
-	mIncomingCompressedSize = 0;
-	mSendReliable = FALSE;
+		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);
+		}
 
-	mbSBuilt = FALSE;
-	mbSClear = TRUE;
+	private:
 
-	mUnackedListDepth = 0;
-	mUnackedListSize = 0;
-	mDSMaxListDepth = 0;
+		void (*mCallback)(void **,S32);    
+		void **mCallbackData;
+	};
+}
 
-	mCurrentRMessageData = NULL;
-	mCurrentRMessageTemplate = NULL;
 
-	mCurrentSMessageData = NULL;
-	mCurrentSMessageTemplate = NULL;
-	mCurrentSMessageName = NULL;
+class LLTrustedMessageService : public LLHTTPNode
+{
+	virtual bool validate(const std::string& name, LLSD& context) const
+		{ return true; }
 
-	mCurrentRecvPacketID = 0;
+	virtual void post(LLHTTPNode::ResponsePtr response,
+					  const LLSD& context,
+					  const LLSD& input) const;
+};
 
-	mNumberHighFreqMessages = 0;
-	mNumberMediumFreqMessages = 0;
-	mNumberLowFreqMessages = 0;
-	mPacketsIn = mPacketsOut = 0;
-	mBytesIn = mBytesOut = 0;
-	mCompressedPacketsIn = mCompressedPacketsOut = 0;
-	mReliablePacketsIn = mReliablePacketsOut = 0;
+//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"];
 
-	mCompressedBytesIn = 0;
-	mCompressedBytesOut = 0;
-	mUncompressedBytesIn = 0;
-	mUncompressedBytesOut = 0;
-	mTotalBytesIn = 0;
-	mTotalBytesOut = 0;
+	LLSD message_data;
+	message_data["sender"] = senderIP + ":" + senderPort;
+	message_data["body"] = input;
+	
+	LLMessageSystem::dispatch(name, message_data, response);
+}
 
-    mDroppedPackets = 0;            // total dropped packets in
-    mResentPackets = 0;             // total resent packets out
-    mFailedResendPackets = 0;       // total resend failure packets out
-    mOffCircuitPackets = 0;         // total # of off-circuit packets rejected
-    mInvalidOnCircuitPackets = 0;   // total # of on-circuit packets rejected
+class LLMessageHandlerBridge : public LLHTTPNode
+{
+	virtual bool validate(const std::string& name, LLSD& context) const
+		{ return true; }
 
-	mOurCircuitCode = 0;
+	virtual void post(LLHTTPNode::ResponsePtr response, const LLSD& context, 
+					  const LLSD& input) const;
+};
 
-	mMessageFileChecksum = 0;
-	mMessageFileVersionNumber = 0.f;
+//virtual 
+void LLMessageHandlerBridge::post(LLHTTPNode::ResponsePtr response, 
+							const LLSD& context, const LLSD& input) const
+{
+	std::string name = context["request"]["wildcard"]["message-name"];
 
-	mTimingCallback = NULL;
-	mTimingCallbackData = NULL;
+	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();
+	}
 }
 
-LLMessageSystem::LLMessageSystem()
+LLHTTPRegistration<LLMessageHandlerBridge>
+	gHTTPRegistrationMessageWildcard("/message/<message-name>");
+
+LLHTTPRegistration<LLTrustedMessageService>
+	gHTTPRegistrationTrustedMessageWildcard("/trusted-message/<message-name>");
+
+//virtual
+LLUseCircuitCodeResponder::~LLUseCircuitCodeResponder()
 {
-	init();
+	// even abstract base classes need a concrete destructor
+}
 
-	mSystemVersionMajor = 0;
-	mSystemVersionMinor = 0;
-	mSystemVersionPatch = 0;
-	mSystemVersionServer = 0;
-	mVersionFlags = 0x0;
+void LLMessageSystem::init()
+{
+	// initialize member variables
+	mVerboseLog = FALSE;
 
-	// default to not accepting packets from not alive circuits
-	mbProtected = TRUE;
+	mbError = FALSE;
+	mErrorCode = 0;
+	mSendReliable = FALSE;
 
-	mSendPacketFailureCount = 0;
-	mCircuitPrintFreq = 0.f;		// seconds
+	mUnackedListDepth = 0;
+	mUnackedListSize = 0;
+	mDSMaxListDepth = 0;
 
-	// initialize various bits of net info
-	mSocket = 0;
-	mPort = 0;
+	mNumberHighFreqMessages = 0;
+	mNumberMediumFreqMessages = 0;
+	mNumberLowFreqMessages = 0;
+	mPacketsIn = mPacketsOut = 0;
+	mBytesIn = mBytesOut = 0;
+	mCompressedPacketsIn = mCompressedPacketsOut = 0;
+	mReliablePacketsIn = mReliablePacketsOut = 0;
 
-	mPollInfop = NULL;
+	mCompressedBytesIn = 0;
+	mCompressedBytesOut = 0;
+	mUncompressedBytesIn = 0;
+	mUncompressedBytesOut = 0;
+	mTotalBytesIn = 0;
+	mTotalBytesOut = 0;
 
-	mResendDumpTime = 0;
-	mMessageCountTime = 0;
-	mCircuitPrintTime = 0;
-	mCurrentMessageTimeSeconds = 0;
+    mDroppedPackets = 0;            // total dropped packets in
+    mResentPackets = 0;             // total resent packets out
+    mFailedResendPackets = 0;       // total resend failure packets out
+    mOffCircuitPackets = 0;         // total # of off-circuit packets rejected
+    mInvalidOnCircuitPackets = 0;   // total # of on-circuit packets rejected
 
-	// Constants for dumping output based on message processing time/count
-	mNumMessageCounts = 0;
-	mMaxMessageCounts = 0; // >= 0 means dump warnings
-	mMaxMessageTime   = 0.f;
+	mOurCircuitCode = 0;
 
-	mTrueReceiveSize = 0;
+	mIncomingCompressedSize = 0;
+	mCurrentRecvPacketID = 0;
 
-	// Error if checking this state, subclass methods which aren't implemented are delegated
-	// to properly constructed message system.
-	mbError = TRUE;
+	mMessageFileChecksum = 0;
+	mMessageFileVersionNumber = 0.f;
+
+	mTimingCallback = NULL;
+	mTimingCallbackData = NULL;
+
+	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,724 +1812,184 @@ void LLMessageSystem::processAcks()
 	}
 }
 
-
-void LLMessageSystem::newMessageFast(const char *name)
+void LLMessageSystem::copyMessageRtoS()
 {
-	mbSBuilt = FALSE;
-	mbSClear = FALSE;
-
-	mCurrentSendTotal = 0;
-	mSendReliable = FALSE;
-
-	char *namep = (char *)name; 
-
-	if (mMessageTemplates.count(namep) > 0)
+	// NOTE: babbage: switch builder to match reader to avoid
+	// converting message format
+	if(mMessageReader == mTemplateMessageReader)
 	{
-		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);
-		}
+		mMessageBuilder = mTemplateMessageBuilder;
 	}
 	else
 	{
-		llerrs << "newMessage - Message " << name << " not registered" << llendl;
+		mMessageBuilder = mLLSDMessageBuilder;
 	}
+	mSendReliable = FALSE;
+	mMessageBuilder->newMessage(mMessageReader->getMessageName());
+	mMessageReader->copyToBuilder(*mMessageBuilder);
 }
 
-void LLMessageSystem::copyMessageRtoS()
+void LLMessageSystem::clearMessage()
 {
-	if (!mCurrentRMessageTemplate)
-	{
-		return;
-	}
-	newMessageFast(mCurrentRMessageTemplate->mName);
+	mSendReliable = FALSE;
+	mMessageBuilder->clearMessage();
+}
 
-	// copy the blocks
-	// counting variables used to encode multiple block info
-	S32 block_count = 0;
-    char *block_name = NULL;
+// set block to add data to within current message
+void LLMessageSystem::nextBlockFast(const char *blockname)
+{
+	mMessageBuilder->nextBlock(blockname);
+}
 
-	// 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)
+BOOL LLMessageSystem::isSendFull(const char* blockname)
+{
+	char* stringTableName = NULL;
+	if(NULL != blockname)
 	{
-		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());
-		}
+		stringTableName = gMessageStringTable.getString(blockname);
 	}
+	return isSendFullFast(stringTableName);
 }
 
-void LLMessageSystem::clearMessage()
+BOOL LLMessageSystem::isSendFullFast(const char* blockname)
 {
-	mbSBuilt = FALSE;
-	mbSClear = TRUE;
-
-	mCurrentSendTotal = 0;
-	mSendReliable = FALSE;
+	return mMessageBuilder->isMessageFull(blockname);
+}
 
-	mCurrentSMessageTemplate = NULL;
 
-	delete mCurrentSMessageData;
-	mCurrentSMessageData = NULL;
+// blow away the last block of a message, return FALSE if that leaves no blocks or there wasn't a block to remove
+// TODO: Babbage: Remove this horror.
+BOOL LLMessageSystem::removeLastBlock()
+{
+	return mMessageBuilder->removeLastBlock();
+}
 
-	mCurrentSMessageName = NULL;
-	mCurrentSDataBlock = NULL;
-	mCurrentSBlockName = NULL;
+S32 LLMessageSystem::sendReliable(const LLHost &host)
+{
+	return sendReliable(host, LL_DEFAULT_RELIABLE_RETRIES, TRUE, LL_PING_BASED_TIMEOUT_DUMMY, NULL, NULL);
 }
 
 
-// set block to add data to within current message
-void LLMessageSystem::nextBlockFast(const char *blockname)
+S32 LLMessageSystem::sendSemiReliable(const LLHost &host, void (*callback)(void **,S32), void ** callback_data)
 {
-	char *bnamep = (char *)blockname; 
-
-	if (!mCurrentSMessageTemplate)
-	{
-		llerrs << "newMessage not called prior to setBlock" << llendl;
-		return;
-	}
+	F32 timeout;
 
-	// now, does this block exist?
-	LLMessageTemplate::message_block_map_t::iterator temp_iter = mCurrentSMessageTemplate->mMemberBlocks.find(bnamep);
-	if (temp_iter == mCurrentSMessageTemplate->mMemberBlocks.end())
+	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+	if (cdp)
 	{
-		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;
+		timeout = llmax(LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS,
+						LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged());
 	}
 	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;
+		timeout = LL_SEMIRELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX;
 	}
+
+	const S32 retries = 0;
+	const BOOL ping_based_timeout = FALSE;
+	return sendReliable(host, retries, ping_based_timeout, timeout, callback, callback_data);
 }
 
-// add data to variable in current block
-void LLMessageSystem::addDataFast(const char *varname, const void *data, EMsgVariableType type, S32 size)
+// send the message via a UDP packet
+S32 LLMessageSystem::sendReliable(	const LLHost &host, 
+									S32 retries, 
+									BOOL ping_based_timeout,
+									F32 timeout, 
+									void (*callback)(void **,S32), 
+									void ** callback_data)
 {
-	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)
+	if (ping_based_timeout)
 	{
-		llerrs << "setBlock not called prior to addData" << llendl;
-		return;
+	    LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+	    if (cdp)
+	    {
+		    timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, LL_RELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged());
+	    }
+	    else
+	    {
+		    timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, LL_RELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX);
+	    }
 	}
 
-	// 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;
-	}
+	mSendReliable = TRUE;
+	mReliablePacketParams.set(host, retries, ping_based_timeout, timeout, 
+		callback, callback_data, 
+		const_cast<char*>(mMessageBuilder->getMessageName()));
+	return sendMessage(host);
+}
 
-	// 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;
-		}
+void LLMessageSystem::forwardMessage(const LLHost &host)
+{
+	copyMessageRtoS();
+	sendMessage(host);
+}
 
-		// 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;
-	}
+void LLMessageSystem::forwardReliable(const LLHost &host)
+{
+	copyMessageRtoS();
+	sendReliable(host);
 }
 
-// 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)
+void LLMessageSystem::forwardReliable(const U32 circuit_code)
 {
-	char *vnamep = (char *)varname; 
+	copyMessageRtoS();
+	sendReliable(findHost(circuit_code));
+}
 
-	// do we have a current message?
-	if (!mCurrentSMessageTemplate)
-	{
-		llerrs << "newMessage not called prior to addData" << llendl;
-		return;
-	}
+S32 LLMessageSystem::flushSemiReliable(const LLHost &host, void (*callback)(void **,S32), void ** callback_data)
+{
+	F32 timeout; 
 
-	// do we have a current block?
-	if (!mCurrentSDataBlock)
+	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+	if (cdp)
 	{
-		llerrs << "setBlock not called prior to addData" << llendl;
-		return;
+		timeout = llmax(LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS,
+						LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged());
 	}
-
-	// kewl, add the data if it exists
-	LLMessageVariable* var_data = mCurrentSMessageTemplate->mMemberBlocks[mCurrentSBlockName]->mMemberVariables[vnamep];
-	if (!var_data->getName())
+	else
 	{
-		llerrs << vnamep << " not a variable in block " << mCurrentSBlockName << " of " << mCurrentSMessageTemplate->mName << llendl;
-		return;
+		timeout = LL_SEMIRELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX;
 	}
 
-	// ok, it seems ok. . . are we MVT_VARIABLE?
-	if (var_data->getType() == MVT_VARIABLE)
+	S32 send_bytes = 0;
+	if (mMessageBuilder->getMessageSize())
 	{
-		// nope
-		llerrs << vnamep << " is type MVT_VARIABLE. Call using addData(name, data, size)" << llendl;
-		return;
+		mSendReliable = TRUE;
+		// No need for ping-based retry as not going to retry
+		mReliablePacketParams.set(host, 0, FALSE, timeout, callback, 
+								  callback_data, 
+								  const_cast<char*>(mMessageBuilder->getMessageName()));
+		send_bytes = sendMessage(host);
+		clearMessage();
 	}
 	else
 	{
-		mCurrentSDataBlock->addData(vnamep, data, var_data->getSize(), type);
-		mCurrentSendTotal += var_data->getSize();
+		delete callback_data;
 	}
+	return send_bytes;
 }
 
-BOOL LLMessageSystem::isSendFull(const char* blockname)
+S32 LLMessageSystem::flushReliable(const LLHost &host)
 {
-	if(!blockname)
+	S32 send_bytes = 0;
+	if (mMessageBuilder->getMessageSize())
 	{
-		return (mCurrentSendTotal > MTUBYTES);
+		send_bytes = sendReliable(host);
 	}
-	return isSendFullFast(gMessageStringTable.getString(blockname));
+	clearMessage();
+	return send_bytes;
 }
 
-BOOL LLMessageSystem::isSendFullFast(const char* blockname)
+		
+// This can be called from signal handlers,
+// so should should not use llinfos.
+S32 LLMessageSystem::sendMessage(const LLHost &host)
 {
-	if(mCurrentSendTotal > MTUBYTES)
+	if (! mMessageBuilder->isBuilt())
 	{
-		return TRUE;
-	}
-	if(!blockname)
-	{
-		return FALSE;
+		mSendSize = mMessageBuilder->buildMessage(mSendBuffer,
+												  MAX_BUFFER_SIZE);
 	}
-	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;
-}
-
-
-// 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()
-{
-	// 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;
-}
-
-S32 LLMessageSystem::sendReliable(const LLHost &host)
-{
-	return sendReliable(host, LL_DEFAULT_RELIABLE_RETRIES, TRUE, LL_PING_BASED_TIMEOUT_DUMMY, NULL, NULL);
-}
-
-
-S32 LLMessageSystem::sendSemiReliable(const LLHost &host, void (*callback)(void **,S32), void ** callback_data)
-{
-	F32 timeout;
-
-	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
-	if (cdp)
-	{
-		timeout = llmax(LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS,
-						LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged());
-	}
-	else
-	{
-		timeout = LL_SEMIRELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX;
-	}
-
-	return sendReliable(host, 0, FALSE, timeout, callback, callback_data);
-}
-
-// send the message via a UDP packet
-S32 LLMessageSystem::sendReliable(	const LLHost &host, 
-									S32 retries, 
-									BOOL ping_based_timeout,
-									F32 timeout, 
-									void (*callback)(void **,S32), 
-									void ** callback_data)
-{
-	if (ping_based_timeout)
-	{
-	    LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
-	    if (cdp)
-	    {
-		    timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, LL_RELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged());
-	    }
-	    else
-	    {
-		    timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, LL_RELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX);
-	    }
-	}
-
-	mSendReliable = TRUE;
-	mReliablePacketParams.set(host, retries, ping_based_timeout, timeout, 
-		callback, callback_data, mCurrentSMessageName);
-	return sendMessage(host);
-}
-
-void LLMessageSystem::forwardMessage(const LLHost &host)
-{
-	copyMessageRtoS();
-	sendMessage(host);
-}
-
-void LLMessageSystem::forwardReliable(const LLHost &host)
-{
-	copyMessageRtoS();
-	sendReliable(host);
-}
-
-void LLMessageSystem::forwardReliable(const U32 circuit_code)
-{
-	copyMessageRtoS();
-	sendReliable(findHost(circuit_code));
-}
-
-S32 LLMessageSystem::flushSemiReliable(const LLHost &host, void (*callback)(void **,S32), void ** callback_data)
-{
-	F32 timeout; 
-
-	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
-	if (cdp)
-	{
-		timeout = llmax(LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS,
-						LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged());
-	}
-	else
-	{
-		timeout = LL_SEMIRELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX;
-	}
-
-	S32 send_bytes = 0;
-	if (mCurrentSendTotal)
-	{
-		mSendReliable = TRUE;
-		// No need for ping-based retry as not going to retry
-		mReliablePacketParams.set(host, 0, FALSE, timeout, callback, callback_data, mCurrentSMessageName);
-		send_bytes = sendMessage(host);
-		clearMessage();
-	}
-	else
-	{
-		delete callback_data;
-	}
-	return send_bytes;
-}
-
-S32 LLMessageSystem::flushReliable(const LLHost &host)
-{
-	S32 send_bytes = 0;
-	if (mCurrentSendTotal)
-	{
-		send_bytes = sendReliable(host);
-	}
-	clearMessage();
-	return send_bytes;
-}
-
-		
-// This can be called from signal handlers,
-// so should should not use llinfos.
-S32 LLMessageSystem::sendMessage(const LLHost &host)
-{
-	if (!mbSBuilt)
-	{
-		buildMessage();
-	}
-
-	mCurrentSendTotal = 0;
 
 	if (!(host.isOk()))    // if port and ip are zero, don't bother trying to send the message
 	{
@@ -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,129 +2191,60 @@ 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
+void LLMessageSystem::logMsgFromInvalidCircuit( const LLHost& host, BOOL recv_reliable )
 {
-	const U8* header = buffer + LL_PACKET_ID_SIZE;
-
-	// is there a message ready to go?
-	if (buffer_size <= 0)
+	if(mVerboseLog)
 	{
-		llwarns << "No message waiting for decode!" << llendl;
-		return(FALSE);
+		std::ostringstream str;
+		str << "MSG: <- " << host;
+		char buffer[MAX_STRING];			/* Flawfinder: ignore */
+		snprintf(buffer, MAX_STRING, "\t%6d\t%6d\t%6d ", mMessageReader->getMessageSize(), (mIncomingCompressedSize ? mIncomingCompressedSize: mMessageReader->getMessageSize()), mCurrentRecvPacketID);		/* Flawfinder: ignore */
+		str << buffer
+			<< mMessageReader->getMessageName()
+			<< (recv_reliable ? " reliable" : "")
+ 			<< " REJECTED";
+		llinfos << str.str() << llendl;
 	}
+	// nope!
+	// cout << "Rejecting unexpected message " << mCurrentMessageTemplate->mName << " from " << hex << ip << " , " << dec << port << endl;
 
-	U32 num = 0;
-
-	if (header[0] != 255)
+	// Keep track of rejected messages as well
+	if (mNumMessageCounts >= MAX_MESSAGE_COUNT_NUM)
 	{
-		// high frequency message
-		num = header[0];
+		llwarns << "Got more than " << MAX_MESSAGE_COUNT_NUM << " packets without clearing counts" << llendl;
 	}
-	else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 1)) && (header[1] != 255))
+	else
 	{
-		// medium frequency message
-		num = (255 << 8) | header[1];
+		// TODO: babbage: work out if we need these
+		// mMessageCountList[mNumMessageCounts].mMessageNum = mCurrentRMessageTemplate->mMessageNumber;
+		mMessageCountList[mNumMessageCounts].mMessageBytes = mMessageReader->getMessageSize();
+		mMessageCountList[mNumMessageCounts].mInvalid = TRUE;
+		mNumMessageCounts++;
 	}
-	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)
-	{
-		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 */
-		str << buffer
-			<< mCurrentRMessageTemplate->mName
-			<< (recv_reliable ? " reliable" : "")
- 			<< " REJECTED";
-		llinfos << str.str() << llendl;
-	}
-	// nope!
-	// cout << "Rejecting unexpected message " << mCurrentMessageTemplate->mName << " from " << hex << ip << " , " << dec << port << endl;
-
-	// Keep track of rejected messages as well
-	if (mNumMessageCounts >= MAX_MESSAGE_COUNT_NUM)
-	{
-		llwarns << "Got more than " << MAX_MESSAGE_COUNT_NUM << " packets without clearing counts" << llendl;
-	}
-	else
-	{
-		mMessageCountList[mNumMessageCounts].mMessageNum = mCurrentRMessageTemplate->mMessageNumber;
-		mMessageCountList[mNumMessageCounts].mMessageBytes = mReceiveSize;
-		mMessageCountList[mNumMessageCounts].mInvalid = TRUE;
-		mNumMessageCounts++;
-	}
-}
+}
 
 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,631 +2303,204 @@ void LLMessageSystem::logValidMsg(LLCircuitData *cdp, const LLHost& host, BOOL r
 	}
 }
 
-
-void LLMessageSystem::logRanOffEndOfPacket( const LLHost& host )
+void LLMessageSystem::sanityCheck()
 {
-	// 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);
-}
+// TODO: babbage: reinstate
 
+//	if (!mCurrentRMessageData)
+//	{
+//		llerrs << "mCurrentRMessageData is NULL" << llendl;
+//	}
 
-// 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
+//	if (!mCurrentRMessageTemplate)
+//	{
+//		llerrs << "mCurrentRMessageTemplate is NULL" << llendl;
+//	}
 
-	S32 decode_pos = LL_PACKET_ID_SIZE + (S32)(mCurrentRMessageTemplate->mFrequency);
+//	if (!mCurrentRTemplateBlock)
+//	{
+//		llerrs << "mCurrentRTemplateBlock is NULL" << llendl;
+//	}
 
-	// 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;
+//	if (!mCurrentRDataBlock)
+//	{
+//		llerrs << "mCurrentRDataBlock is NULL" << llendl;
+//	}
 
-		// how many of this block?
+//	if (!mCurrentSMessageData)
+//	{
+//		llerrs << "mCurrentSMessageData is NULL" << llendl;
+//	}
 
-		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;
-		}
+//	if (!mCurrentSMessageTemplate)
+//	{
+//		llerrs << "mCurrentSMessageTemplate is NULL" << llendl;
+//	}
 
-		LLMsgBlkData* cur_data_block = NULL;
+//	if (!mCurrentSTemplateBlock)
+//	{
+//		llerrs << "mCurrentSTemplateBlock is NULL" << llendl;
+//	}
 
-		// 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);
-			}
+//	if (!mCurrentSDataBlock)
+//	{
+//		llerrs << "mCurrentSDataBlock is NULL" << llendl;
+//	}
+}
 
-			// add the block to the message
-			mCurrentRMessageData->addBlock(cur_data_block);
+void LLMessageSystem::showCircuitInfo()
+{
+	llinfos << mCircuitInfo << llendl;
+}
 
-			// 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;
+void LLMessageSystem::dumpCircuitInfo()
+{
+	lldebugst(LLERR_CIRCUIT_INFO) << mCircuitInfo << llendl;
+}
 
-					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;
+/* virtual */
+U32 LLMessageSystem::getOurCircuitCode()
+{
+	return mOurCircuitCode;
+}
 
-					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
+LLString LLMessageSystem::getCircuitInfoString()
+{
+	LLString info_string;
 
-					if ((decode_pos + mvci.getSize()) > mReceiveSize)
-					{
-						logRanOffEndOfPacket( sender );
-						return FALSE;
-					}
+	info_string += mCircuitInfo.getInfoString();
+	return info_string;
+}
 
-					cur_data_block->addData(mvci.getName(), &buffer[decode_pos], mvci.getSize(), mvci.getType());
-					decode_pos += mvci.getSize();
-				}
-			}
-		}
+// returns whether the given host is on a trusted circuit
+BOOL    LLMessageSystem::getCircuitTrust(const LLHost &host)
+{
+	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+	if (cdp)
+	{
+		return cdp->getTrusted();
 	}
 
-	if (mCurrentRMessageData->mMemberBlocks.empty()
-		&& !mCurrentRMessageTemplate->mMemberBlocks.empty())
+	return FALSE;
+}
+
+// Activate a circuit, and set its trust level (TRUE if trusted,
+// FALSE if not).
+void LLMessageSystem::enableCircuit(const LLHost &host, BOOL trusted)
+{
+	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+	if (!cdp)
 	{
-		lldebugs << "Empty message '" << mCurrentRMessageTemplate->mName << "' (no blocks)" << llendl;
-		return FALSE;
+		cdp = mCircuitInfo.addCircuitData(host, 0);
 	}
-
+	else
 	{
-		static LLTimer decode_timer;
+		cdp->setAlive(TRUE);
+	}
+	cdp->setTrusted(trusted);
+}
 
-		if( mTimeDecodes || mTimingCallback )
-		{
-			decode_timer.reset();
-		}
+void LLMessageSystem::disableCircuit(const LLHost &host)
+{
+	llinfos << "LLMessageSystem::disableCircuit for " << host << llendl;
+	U32 code = gMessageSystem->findCircuitCode( host );
 
-		//	if( mCurrentRMessageTemplate->mName == _PREHASH_AgentToNewRegion )
-		//	{
-		//		VTResume();  // VTune
-		//	}
+	// Don't need to do this, as we're removing the circuit info anyway - djs 01/28/03
 
+	// don't clean up 0 circuit code entries
+	// because many hosts (neighbor sims, etc) can have the 0 circuit
+	if (code)
+	{
+		//if (mCircuitCodes.checkKey(code))
+		code_session_map_t::iterator it = mCircuitCodes.find(code);
+		if(it != mCircuitCodes.end())
 		{
-			LLFastTimer t(LLFastTimer::FTM_PROCESS_MESSAGES);
-			if( !mCurrentRMessageTemplate->callHandlerFunc(this) )
-			{
-				llwarns << "Message from " << sender << " with no handler function received: " << mCurrentRMessageTemplate->mName << llendl;
-			}
+			llinfos << "Circuit " << code << " removed from list" << llendl;
+			//mCircuitCodes.removeData(code);
+			mCircuitCodes.erase(it);
 		}
 
-		//	if( mCurrentRMessageTemplate->mName == _PREHASH_AgentToNewRegion )
-		//	{
-		//		VTPause();	// VTune
-		//	}
-
-		if( mTimeDecodes || mTimingCallback )
+		U64 ip_port = 0;
+		std::map<U32, U64>::iterator iter = gMessageSystem->mCircuitCodeToIPPort.find(code);
+		if (iter != gMessageSystem->mCircuitCodeToIPPort.end())
 		{
-			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;
+			ip_port = iter->second;
 
-				if( mCurrentRMessageTemplate->mMaxDecodeTimePerMsg < decode_time )
-				{
-					mCurrentRMessageTemplate->mMaxDecodeTimePerMsg = decode_time;
-				}
+			gMessageSystem->mCircuitCodeToIPPort.erase(iter);
 
+			U32 old_port = (U32)(ip_port & (U64)0xFFFFFFFF);
+			U32 old_ip = (U32)(ip_port >> 32);
 
-				if( decode_time > mTimeDecodesSpamThreshold )
-				{
-					lldebugs << "--------- Message " << mCurrentRMessageTemplate->mName << " decode took " << decode_time << " seconds. (" <<
-						mCurrentRMessageTemplate->mMaxDecodeTimePerMsg << " max, " <<
-						(mCurrentRMessageTemplate->mTotalDecodeTime / mCurrentRMessageTemplate->mTotalDecoded) << " avg)" << llendl;
-				}
-			}
+			llinfos << "Host " << LLHost(old_ip, old_port) << " circuit " << code << " removed from lookup table" << llendl;
+			gMessageSystem->mIPPortToCircuitCode.erase(ip_port);
 		}
 	}
-	return TRUE;
+	else
+	{
+		// Sigh, since we can open circuits which don't have circuit
+		// codes, it's possible for this to happen...
+		
+		//llwarns << "Couldn't find circuit code for " << host << llendl;
+	}
+
+	mCircuitInfo.removeCircuitData(host);
 }
 
-void LLMessageSystem::getDataFast(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum, S32 max_size)
+
+void LLMessageSystem::setCircuitAllowTimeout(const LLHost &host, BOOL allow)
 {
-	// is there a message ready to go?
-	if (mReceiveSize == -1)
+	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+	if (cdp)
 	{
-		llerrs << "No message waiting for decode 2!" << llendl;
-		return;
+		cdp->setAllowTimeout(allow);
 	}
+}
 
-	if (!mCurrentRMessageData)
+void LLMessageSystem::setCircuitTimeoutCallback(const LLHost &host, void (*callback_func)(const LLHost & host, void *user_data), void *user_data)
+{
+	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+	if (cdp)
 	{
-		llerrs << "Invalid mCurrentMessageData in getData!" << llendl;
-		return;
+		cdp->setTimeoutCallback(callback_func, user_data);
 	}
+}
 
-	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];
+BOOL LLMessageSystem::checkCircuitBlocked(const U32 circuit)
+{
+	LLHost host = findHost(circuit);
 
-	if (!vardata.getName())
+	if (!host.isOk())
 	{
-		llerrs << "Variable "<< vnamep << " not in message "
-			<< mCurrentRMessageData->mName<< " block " << bnamep << llendl;
-		return;
+		//llinfos << "checkCircuitBlocked: Unknown circuit " << circuit << llendl;
+		return TRUE;
 	}
 
-	if (size && size != vardata.getSize())
+	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+	if (cdp)
 	{
-		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;
-		}
+		return cdp->isBlocked();
 	}
 	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 */
+		llinfos << "checkCircuitBlocked(circuit): Unknown host - " << host << llendl;
+		return FALSE;
 	}
 }
 
-S32 LLMessageSystem::getNumberOfBlocksFast(const char *blockname)
+BOOL LLMessageSystem::checkCircuitAlive(const U32 circuit)
 {
-	// is there a message ready to go?
-	if (mReceiveSize == -1)
-	{
-		llerrs << "No message waiting for decode 3!" << llendl;
-		return -1;
-	}
+	LLHost host = findHost(circuit);
 
-	if (!mCurrentRMessageData)
+	if (!host.isOk())
 	{
-		llerrs << "Invalid mCurrentRMessageData in getData!" << llendl;
-		return -1;
+		//llinfos << "checkCircuitAlive: Unknown circuit " << circuit << llendl;
+		return FALSE;
 	}
 
-	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;
-	}
-
-	if (!mCurrentRMessageTemplate)
-	{
-		llerrs << "mCurrentRMessageTemplate is NULL" << llendl;
-	}
-
-//	if (!mCurrentRTemplateBlock)
-//	{
-//		llerrs << "mCurrentRTemplateBlock is NULL" << llendl;
-//	}
-
-//	if (!mCurrentRDataBlock)
-//	{
-//		llerrs << "mCurrentRDataBlock is NULL" << llendl;
-//	}
-
-	if (!mCurrentSMessageData)
-	{
-		llerrs << "mCurrentSMessageData is NULL" << llendl;
-	}
-
-	if (!mCurrentSMessageTemplate)
-	{
-		llerrs << "mCurrentSMessageTemplate is NULL" << llendl;
-	}
-
-//	if (!mCurrentSTemplateBlock)
-//	{
-//		llerrs << "mCurrentSTemplateBlock is NULL" << llendl;
-//	}
-
-	if (!mCurrentSDataBlock)
-	{
-		llerrs << "mCurrentSDataBlock is NULL" << llendl;
-	}
-}
-
-void LLMessageSystem::showCircuitInfo()
-{
-	llinfos << mCircuitInfo << llendl;
-}
-
-
-void LLMessageSystem::dumpCircuitInfo()
-{
-	lldebugst(LLERR_CIRCUIT_INFO) << mCircuitInfo << llendl;
-}
-
-/* virtual */
-U32 LLMessageSystem::getOurCircuitCode()
-{
-	return mOurCircuitCode;
-}
-
-LLString LLMessageSystem::getCircuitInfoString()
-{
-	LLString info_string;
-
-	info_string += mCircuitInfo.getInfoString();
-	return info_string;
-}
-
-// returns whether the given host is on a trusted circuit
-BOOL    LLMessageSystem::getCircuitTrust(const LLHost &host)
-{
-	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
-	if (cdp)
-	{
-		return cdp->getTrusted();
-	}
-
-	return FALSE;
-}
-
-// Activate a circuit, and set its trust level (TRUE if trusted,
-// FALSE if not).
-void LLMessageSystem::enableCircuit(const LLHost &host, BOOL trusted)
-{
-	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
-	if (!cdp)
-	{
-		cdp = mCircuitInfo.addCircuitData(host, 0);
-	}
-	else
-	{
-		cdp->setAlive(TRUE);
-	}
-	cdp->setTrusted(trusted);
-}
-
-void LLMessageSystem::disableCircuit(const LLHost &host)
-{
-	llinfos << "LLMessageSystem::disableCircuit for " << host << llendl;
-	U32 code = gMessageSystem->findCircuitCode( host );
-
-	// Don't need to do this, as we're removing the circuit info anyway - djs 01/28/03
-
-	// don't clean up 0 circuit code entries
-	// because many hosts (neighbor sims, etc) can have the 0 circuit
-	if (code)
-	{
-		//if (mCircuitCodes.checkKey(code))
-		code_session_map_t::iterator it = mCircuitCodes.find(code);
-		if(it != mCircuitCodes.end())
-		{
-			llinfos << "Circuit " << code << " removed from list" << llendl;
-			//mCircuitCodes.removeData(code);
-			mCircuitCodes.erase(it);
-		}
-
-		U64 ip_port = 0;
-		std::map<U32, U64>::iterator iter = gMessageSystem->mCircuitCodeToIPPort.find(code);
-		if (iter != gMessageSystem->mCircuitCodeToIPPort.end())
-		{
-			ip_port = iter->second;
-
-			gMessageSystem->mCircuitCodeToIPPort.erase(iter);
-
-			U32 old_port = (U32)(ip_port & (U64)0xFFFFFFFF);
-			U32 old_ip = (U32)(ip_port >> 32);
-
-			llinfos << "Host " << LLHost(old_ip, old_port) << " circuit " << code << " removed from lookup table" << llendl;
-			gMessageSystem->mIPPortToCircuitCode.erase(ip_port);
-		}
-	}
-	else
-	{
-		// Sigh, since we can open circuits which don't have circuit
-		// codes, it's possible for this to happen...
-		
-		//llwarns << "Couldn't find circuit code for " << host << llendl;
-	}
-
-	mCircuitInfo.removeCircuitData(host);
-}
-
-
-void LLMessageSystem::setCircuitAllowTimeout(const LLHost &host, BOOL allow)
-{
-	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
-	if (cdp)
-	{
-		cdp->setAllowTimeout(allow);
-	}
-}
-
-void LLMessageSystem::setCircuitTimeoutCallback(const LLHost &host, void (*callback_func)(const LLHost & host, void *user_data), void *user_data)
-{
-	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
-	if (cdp)
-	{
-		cdp->setTimeoutCallback(callback_func, user_data);
-	}
-}
-
-
-BOOL LLMessageSystem::checkCircuitBlocked(const U32 circuit)
-{
-	LLHost host = findHost(circuit);
-
-	if (!host.isOk())
-	{
-		//llinfos << "checkCircuitBlocked: Unknown circuit " << circuit << llendl;
-		return TRUE;
-	}
-
-	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
-	if (cdp)
-	{
-		return cdp->isBlocked();
-	}
-	else
-	{
-		llinfos << "checkCircuitBlocked(circuit): Unknown host - " << host << llendl;
-		return FALSE;
-	}
-}
-
-BOOL LLMessageSystem::checkCircuitAlive(const U32 circuit)
-{
-	LLHost host = findHost(circuit);
-
-	if (!host.isOk())
-	{
-		//llinfos << "checkCircuitAlive: Unknown circuit " << circuit << llendl;
-		return FALSE;
-	}
-
-	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
-	if (cdp)
+	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+	if (cdp)
 	{
 		return cdp->isAlive();
 	}
@@ -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,16 +2866,59 @@ 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 check_for_unrecognized_messages(
-		const char* type,
-		const LLSD& map,
-		LLMessageSystem::message_template_name_map_t& templates)
+//static
+void LLMessageSystem::dispatch(const std::string& msg_name,
+								const LLSD& message)
 {
-	for (LLSD::map_const_iterator iter = map.beginMap(),
-			end = map.endMap();
-		 iter != end; ++iter)
+	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,
+		const LLSD& map,
+		LLMessageSystem::message_template_name_map_t& templates)
+{
+	for (LLSD::map_const_iterator iter = map.beginMap(),
+			end = map.endMap();
+		 iter != end; ++iter)
 	{
 		const char* name = gMessageStringTable.getString(iter->first.c_str());
 
@@ -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)
-	{
-		*outptr++ = num_zeroes;
-	}
-
-	if (net_gain < 0)
+	if(mMessageBuilder == mLLSDMessageBuilder)
 	{
-		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,47 +4114,717 @@ void LLMessageSystem::dumpPacketToLog()
 }
 
 //static
-U64 LLMessageSystem::getMessageTimeUsecs(const BOOL update)
+BOOL LLMessageSystem::isTemplateConfirmed()
 {
-	if (gMessageSystem)
-	{
-		if (update)
-		{
-			gMessageSystem->mCurrentMessageTimeSeconds = totalTime()*SEC_PER_USEC;
-		}
-		return (U64)(gMessageSystem->mCurrentMessageTimeSeconds * USEC_PER_SEC);
-	}
-	else
-	{
-		return totalTime();
-	}
+	return gMessageSystem->mTemplateConfirmed;
 }
 
 //static
-F64 LLMessageSystem::getMessageTimeSeconds(const BOOL update)
+BOOL LLMessageSystem::doesTemplateMatch()
 {
-	if (gMessageSystem)
-	{
-		if (update)
-		{
-			gMessageSystem->mCurrentMessageTimeSeconds = totalTime()*SEC_PER_USEC;
-		}
-		return gMessageSystem->mCurrentMessageTimeSeconds;
-	}
-	else
+	if (!isTemplateConfirmed())
 	{
-		return totalTime()*SEC_PER_USEC;
+		return FALSE;
 	}
+	return gMessageSystem->mTemplateMatches;
 }
 
-std::string get_shared_secret()
+//static
+void LLMessageSystem::sendMessageTemplateChecksum(const LLHost &currentHost)
 {
-	static const std::string SHARED_SECRET_KEY("shared_secret");
-	if(g_shared_secret.empty())
+	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)
 	{
-		LLApp* app = LLApp::instance();
-		if(app) return app->getOption(SHARED_SECRET_KEY);
+		llwarns << "out of sync message template!" << llendl;
+		
+		msg->mTemplateMatches = FALSE;
+		msg->newMessageFast(_PREHASH_CloseCircuit);
+		msg->sendMessage(msg->getSender());
+		return;
 	}
-	return g_shared_secret;
+
+	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)
+	{
+		if (update)
+		{
+			gMessageSystem->mCurrentMessageTimeSeconds = totalTime()*SEC_PER_USEC;
+		}
+		return (U64)(gMessageSystem->mCurrentMessageTimeSeconds * USEC_PER_SEC);
+	}
+	else
+	{
+		return totalTime();
+	}
+}
+
+//static
+F64 LLMessageSystem::getMessageTimeSeconds(const BOOL update)
+{
+	if (gMessageSystem)
+	{
+		if (update)
+		{
+			gMessageSystem->mCurrentMessageTimeSeconds = totalTime()*SEC_PER_USEC;
+		}
+		return gMessageSystem->mCurrentMessageTimeSeconds;
+	}
+	else
+	{
+		return totalTime()*SEC_PER_USEC;
+	}
+}
+
+std::string get_shared_secret()
+{
+	static const std::string SHARED_SECRET_KEY("shared_secret");
+	if(g_shared_secret.empty())
+	{
+		LLApp* app = LLApp::instance();
+		if(app) return app->getOption(SHARED_SECRET_KEY);
+	}
+	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 3ffafcc1b8549f3924253c75a618f8237536a5c3..a4a8022631db1bb4137064dc5c75c1230c6a5041 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 @@ class LLMessageSystem
 	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 @@ class LLMessageSystem
 		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 @@ class LLMessageSystem
 	// 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 @@ class LLMessageSystem
 	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 @@ class LLMessageSystem
 	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 @@ class LLMessageSystem
 	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 @@ class LLMessageSystem
 	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 @@ class LLMessageSystem
 	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 @@ class LLMessageSystem
 	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 @@ class LLMessageSystem
 	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 @@ class LLMessageSystem
 	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 @@ class LLMessageSystem
 	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 @@ class LLMessageSystem
 	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 @@ class LLMessageSystem
 	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 @@ class LLMessageSystem
 	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 @@ class LLMessageSystem
 	// 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 @@ class LLMessageSystem
 	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 @@ class LLMessageSystem
 	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 @@ class LLMessageSystem
 	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 c2d7c9c2a34dd39e7e31a5bcc62d8ef042d1aaea..9d7e60369015005eb2059186e8209f090a8209d3 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 63e23237f559a10433ef9fad6c7f82a6c2535453..19b9881ddeff58e5cf146e430eec9d05c03d502e 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 a78b216ccb7ed7fe57b6a50976a7b4f805ce1509..9e83ce143448723b6da4c70bb9d643132eadeade 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 366ecc7d6f5a18d56d07718cd7e1ea3927938ec7..fa0b4747e68d60748a8563b519b39c6bb67ab449 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 a43aa19cabee9eab8dd6ae568c9ef3bfc4a3cd93..60c6bae34a7bae8b11ec3d9aa28ce119fb3cefc6 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 fde27132e64741717457c4c1486104826a5f7b40..215f6d40ede3500781cb3d72de4825e88b58ff14 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 f13e0d54b98c4d532ddff8012477b6fafc9aaf24..f54804547402b9706504e08012697cc7cf9e060a 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 f442855aca3c3e13e11d6d0c55c7d52961a5cf81..146052538a6c69978745c64daa1d878ab252e2e2 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 7a0a32c87ed59577bc3a4027fa50f033d7ad5c7f..de9b58bd1eb2a20ff1c994ab0ae99ea405dff3c4 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -142,6 +142,7 @@ class LLScrollListColumn
 	LLScrollListColumn() : 
 		mName(""), 
 		mSortingColumn(""), 
+        	mSortAscending(TRUE), 
 		mLabel(""), 
 		mWidth(-1), 
 		mRelWidth(-1.0), 
@@ -156,6 +157,7 @@ class LLScrollListColumn
 	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 @@ class LLScrollListColumn
 		{
 			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 @@ class LLScrollListColumn
 
 	LLString			mName;
 	LLString			mSortingColumn;
+	BOOL				mSortAscending;
 	LLString			mLabel;
 	S32					mWidth;
 	F32					mRelWidth;
@@ -381,8 +389,10 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
 	// 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 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
 	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 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
 
 	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 b3c49e81f1a70eb418ea1accacb87ccf7f37d629..8b5cd4690e0e61bd7a0c385bec9552f490baf892 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 fbd8335e6cc25d1f9cc18761c9a9a081ff0a3cb8..34363eb506e83391aa532b79ab75703f37614b93 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 52902ea819c3318c6ea087c3c6ee6b1a60995be4..4b56148f10cc9971b036b1b5625b47b1b594388c 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 784525aad4be7376f681ec3de8bf0f8577ea9ce5..54687b1a43d7e758c36ddab1505307c8c00c33a7 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 c7d430725f0fa3273f04ae2126e985313842123a..0908e18a1a5d19ff876e2ad167b5fa1d4d42168d 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 49b199c0a489e40c9ad451028f7b17da92f091e8..4e6373d57e26afe6cca41ca322f1c1a3030e123e 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 3939c14dbb9916a48e8f519a9cfebfacf45b2892..13fa29e24289bf9e6ecebf106c910ba8ca085583 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 d0bda5d46a9b9c691b1135ef5f6eece42432a917..89d60709d5407db7a7b7c2f5ab129da58f0ad3f7 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -672,6 +672,13 @@ class LLAgent : public LLObservable
 
 	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 0000000000000000000000000000000000000000..7928a5004c1d02186c98c68fd95b23129bccbd1d
--- /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 0000000000000000000000000000000000000000..af71c665630d942f641b45842966eaa0b02681b1
--- /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 13e7fef4ec976accc3710f3513ae9141b06696a4..41f8f1d714389c620adf3be2cd4c2f713ba37c00 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 2ad7eb68667ebbf47a636d5f62509c22b1e60e64..6d1c384b5ad040e3619dc77650488cf8d0457a6a 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 c5024b2b95f16939a834652e9e889c33c03b002a..c2d798360fdc97f6f429712e2e83e757f5835327 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 12891bd7b22fecc0695871b358d0129c4e0558dc..bc2c340999203d6b19f95ee5ca25f5d836ef132f 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 68f002f9d97ef0bb3a5cb232293d0c286add2e76..9beaa82cb9aab8d1705a44e8484d0c37f21c81af 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 1ee8cd62ab5d2d0b478a07bac9a768b28bbc53d1..7ed84e495a0f713a219a4b9cea6649d66aca44ff 100644
--- a/indra/newview/llfloaterbuyland.cpp
+++ b/indra/newview/llfloaterbuyland.cpp
@@ -75,7 +75,6 @@ class LLFloaterBuyLandUI
 	// 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 534aac077f62eba635627505e10500c76c829744..1e65ae5620e3935779268940c1b974b6ccfdb9ea 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 8bb73e3a9b5f04135b54f80b5d1b13fa7dde7575..1548c0e5d68e0ec664c2bb2d3d38f63d0e7f960d 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 9b2821147650376e5ae676ccd02781f90b9af7b6..51a1a99d71d8632fc8021170f4006e4fcf0e3461 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 9a486d76eef9ee7fd7d31337f0247d829301022f..8968da972055c776fe4dfe86aed8acab7d53653a 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 f7bf4de34f3abc73d29e9ee261a824dc988aca65..b71772bd939e1d8d8033e9d39f68c440aa72de2d 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 9ab9a3f6bbcb8d3bd4eaaf052b8c252fa81f533c..7c03500f85c0a4505557aab4e249bd43fee7bcb3 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 21a0cbcd413f65b40f1e217946088d9432d552b8..45dda8ec79f0ee83e2080d0d104727c3fac158a3 100644
--- a/indra/newview/llimpanel.h
+++ b/indra/newview/llimpanel.h
@@ -27,10 +27,20 @@ class LLFloaterIMPanel : public LLFloater
 	// 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 @@ class LLFloaterIMPanel : public LLFloater
 	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 @@ class LLFloaterIMPanel : public LLFloater
 
 private:
 	// called by constructors
-	void init();
+	void init(const LLString& session_label);
 
 	// Called by UI methods.
 	void sendMsg();
@@ -110,7 +120,6 @@ class LLFloaterIMPanel : public LLFloater
 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 @@ class LLFloaterIMPanel : public LLFloater
 	//   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 @@ class LLFloaterIMPanel : public LLFloater
 
 	// 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 @@ class LLFloaterIMPanel : public LLFloater
 
 	// 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 c093faa1cae6411933ddcc4845b15128bebaa624..553c6ec6c30283eed6ded525121c3616d90564dd 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 @@ class LLIMViewFriendObserver : public LLFriendObserver
 // 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 8732484e0e9be6d72ea67882130a6fe5ffa7e0b9..aac6fd63cefea28f0a6db9818645daf6297fc9fe 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -55,11 +55,11 @@ class LLIMView : public LLView
 					  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 @@ class LLIMView : public LLView
 	// 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 @@ class LLIMView : public LLView
 	// 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 @@ class LLIMView : public LLView
 
 	// 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 0338e7f02a413b099023a87a56a632ddde2616b8..f90fe340b414dc066985d029a0a198da3604be51 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 ddfc4fe791fbd39368254f2660bd008d12b20f19..d91ca7fc75345bbb688f1023c3589aa05e195a49 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -296,7 +296,6 @@ class LLFolderBridge : public LLInvFVBridge
 
 	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 b834845107f6ef85730d4010758f6991d3aeb1f0..edc4ba0ca64998c509858e8a8d8fcf5dbf5374ec 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 6aca7abc11c79374baa6d9e4f945846ea86a5b2c..7ba0ccad3a8b5a664b17a7104112d08cbc2b40b2 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 d8c298747009716f552f8764e22f8358a5020642..bc451ecfc09558a1efed5828f3666aeb42a8270c 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 1b0c731ea9fb568ebe81de4ca66f734ed62f6bbe..383d2846c0b3f1592e9c18a6c917671f1a04a8a6 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 994d23b7d33c7a83dbc7afaa534ef199490ba152..f54da2538fb4119cdc163be5af21cff0bc422dfa 100644
--- a/indra/newview/llpanelavatar.h
+++ b/indra/newview/llpanelavatar.h
@@ -60,8 +60,9 @@ class LLPanelAvatarTab : public LLPanel
 	// 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 @@ class LLPanelAvatar : public LLPanel
 	void setOnlineStatus(EOnlineStatus online_status);
 
 	const LLUUID& getAvatarID() const { return mAvatarID; }
-
-	void disableRate();
 	
 	void resetGroupList();
 
@@ -279,7 +278,6 @@ class LLPanelAvatar : public LLPanel
 	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 @@ class LLPanelAvatar : public LLPanel
 	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 @@ class LLPanelAvatar : public LLPanel
 	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 5c5e0479d4001976dff7a4be03bf2b75eab33ebb..95ed51779468b2a50c247762f9d7384bef4ef74e 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 9d40357544e66d25ed7a699425816a496a8d9f2e..610bfec8ae3e16f648c25779622cc745d912d928 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 a05f7c54c6ab5b6e756530d23ca8e55e64d38050..ff2a64075cec2d85f365ad49b2e841c1facbc02f 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 a347133be6ed58ab40e56ec743154f7e95f097e1..232bbb736ac3d820352667f8bd94db99ce038e50 100644
--- a/indra/newview/llpanelpick.h
+++ b/indra/newview/llpanelpick.h
@@ -39,13 +39,15 @@ class LLPanelPick : public LLPanel
 
     /*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 @@ class LLPanelPick : public LLPanel
 
 	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 cd4d8d2f873c1bab5c33f1bbd11be8988243bdde..a02dd912e3fdc3f3b255eaf7b4108925359dfa4d 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 baf6abda11e1f28d856a2afd62ef200bfe5578f7..4bbdca521c1af2d27bd77d238c4692a3cf9042ef 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 e5952f4f5b509a0782f5d8eb4274dc335651151c..7d64640fb00ce8f4d013240283f8d59210aa361b 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 c732394b4e20b7c57295afdb8b7e54c91656bb37..bc5efa20aa17756ae787847f8782523f5be3c4c3 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 b4aee4e2e1a0da7d2453a2497b698002a2735174..64ec8f0b2f3f8deb6b569b7a2904350a0f0a4b93 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 ee878c1dc0fb1b6e6f8831e1d334efc1ed5bd59d..cbb37e5fe463e7efdff5800ffb8cd140ddc247f8 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 0000000000000000000000000000000000000000..d155d115704c39436f61ca714f9a509343b74832
--- /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 0000000000000000000000000000000000000000..547421648c887b8c89c32c4dc5d443a0785eb450
--- /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 69bee4431ffb499ed232f77d24830b1d7217c005..f5ef19cc336dd1805c8a8df06d4b90c14b5448e1 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 ced12a7c34c907294c4f454cb8c80e6237a9e5d2..6eca0d1eca08028c0372c871d9e2d32949c4b24e 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 @@ class LLViewerGestureList : public LLGestureList
 	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 e9d2218d5546024ef9e7aa5317475f8fc2d2a7c7..2ac1c30ae5dbba9279d63ac48ece61811291ecdb 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 cc1beefec5f944c3056663673303e0acbb01df89..316de37ce1eac4aa551eabfe8c670601347f0995 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 c7d22656c7a122e9f1885f48df83e5a8d0d4982e..04fb668abae828feb8e3eaa75ec8cdea52573158 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 c3f2b2d2f6ef230846d24c2cb318c852db136e21..5af3d532a699ecae7d1b3ae47764dd1242cf69d9 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 ae772aebf11bd469121d37ce92d734d50ffd08ed..ae288d70eceb9b7276e66f64b151559ccb955cfb 100644
--- a/indra/newview/llviewerparcelmgr.h
+++ b/indra/newview/llviewerparcelmgr.h
@@ -203,12 +203,6 @@ class LLViewerParcelMgr
 	// 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 cc93ea8bdc6a0fa11021dd52cb5a063b89d005f8..303e83d672b92d1afe7146d5024f65269e3fd101 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 f11f9fb1be6f9d7d4cca901fbb931d6f6ee40874..1b3c0193f43e258864959358e95e3eb904df6892 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 e74c286e439318a0080c31df20a327a6b81f3229..2b821bed9f6d74e5a620e7dbf359d5262732cb40 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 c00a202f9184e83a2a551ce758506c7f5fd521a7..cf57ae3cd0bca4a0b09d89b693bd7ea824985f38 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 865af98761b8bfebef2ebf3dcdde9fca46364171..b169499543e8ec21582b597f43b51dd22074ab13 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 1284a1fc0d5620fc41593ea3917458bfb3ab3b75..2f64cc81d70a5f50af752b65f7cec0a47adc4f46 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 0000000000000000000000000000000000000000..c9a62e5230c23356e7cda8a4edc36d82f8922143
--- /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 23546982395e76d039c5943d420cd0e1aea18408..0ceb4302ffc22ad1924c81d40450d6f33880c102 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 0000000000000000000000000000000000000000..b153292abc7d51035989645f9bc43e6e80a38a1e
--- /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 0000000000000000000000000000000000000000..31810ae00eed698fbb7c32e4df2559e1fb2a8a42
--- /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 0000000000000000000000000000000000000000..2e6a96a425662fccae1562c4ab1c0e6b5d56df6d
--- /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 0000000000000000000000000000000000000000..b4a814ebb99196be1f8e43326c252f2a8b40aed4
--- /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 cc464237a29018211afc289c1d7d011d026adeec..f4fc2820ebf8dbae08bb5e1d28ff95c34cf81c34 100644
--- a/indra/test/test_llmanifest.py
+++ b/indra/test/test_llmanifest.py
@@ -87,7 +87,7 @@ def tmp_test():
     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 96ffd5f66a8c0a368e3c9c7f0c1df75a1e096868..c139d2f55c88a11846e376a394a3e8d352c7475e 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 32a514502f12b51f6379f531b5b3c292e4485002..8213ed0bc9d4240d7c68fef16748774a8b6c7804 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
@@ -8095,9 +8051,13 @@ sim -> dataserver
 // reliable
 {
 	ReputationIndividualRequest Low NotTrusted Unencoded
+	{
+		AgentData		Single
+		{	AgentID			LLUUID	}
+		{	SessionID		LLUUID	}
+	}   
 	{
 		ReputationData		Single
-		{	FromID			LLUUID	}
 		{	ToID			LLUUID	}
 	}
 }
@@ -8106,9 +8066,12 @@ sim -> dataserver
 // reliable
 {
 	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
 {