diff --git a/etc/message.xml b/etc/message.xml
index d833074765170386cca46e2ecfe27ae333f59bfa..406235ff73a5c27136d788b616f072b44e48d22b 100644
--- a/etc/message.xml
+++ b/etc/message.xml
@@ -243,6 +243,24 @@
 					<key>trusted-sender</key>
 					<boolean>false</boolean>
 				</map>
+
+				<!-- Simulator to simulator reliable messages -->
+				<key>GodKickUser</key>
+				<map>
+					<key>flavor</key>
+					<string>llsd</string>
+					<key>trusted-sender</key>
+					<boolean>false</boolean>
+				</map>
+
+				<key>RoutedMoneyBalanceReply</key>
+				<map>
+				<key>flavor</key>
+				<string>llsd</string>
+				<key>trusted-sender</key>
+				<boolean>false</boolean>
+				</map>
+
 				<!-- Simulator to simulator unreliable messages -->
 				<key>EdgeDataPacket</key>
 				<map>
@@ -506,6 +524,23 @@
 					<boolean>false</boolean>
 				</map>
 
+				<key>EstateOwnerMessage</key>
+				<map>
+					<key>flavor</key>
+					<string>llsd</string>
+					<key>trusted-sender</key>
+					<boolean>false</boolean>
+				</map>
+
+				<key>RpcScriptRequestInboundForward</key>
+				<map>
+					<key>flavor</key>
+					<string>llsd</string>
+					<key>trusted-sender</key>
+					<boolean>false</boolean>
+				</map>
+
+
 		  </map>
   	  	<key>capBans</key>
     	<map>
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index 610aa99dc98eea09bc9e2bf05d18b4f86afce223..0edacac7a9fbf2d11274632dcf3f418de9ba0763 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -181,7 +181,7 @@ endif (DARWIN)
 
 
 if (LINUX OR DARWIN)
-  set(GCC_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs")
+  set(GCC_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs -Wno-non-virtual-dtor")
 
   if (NOT GCC_DISABLE_FATAL_WARNINGS)
     set(GCC_WARNINGS "${GCC_WARNINGS} -Werror")
diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake
index 7cfdead32e0ab7005e3bf25eeef144fda58cb744..3557a99248a1301407fa89965a0ff1f9cce48fc3 100644
--- a/indra/cmake/LLAddBuildTest.cmake
+++ b/indra/cmake/LLAddBuildTest.cmake
@@ -69,8 +69,13 @@ MACRO(ADD_SIMULATOR_BUILD_TEST name parent)
 ENDMACRO(ADD_SIMULATOR_BUILD_TEST name parent)
 
 MACRO(ADD_BUILD_TEST_INTERNAL name parent libraries source_files)
-        
-    ADD_EXECUTABLE(${name}_test ${source_files})
+    SET(TEST_SOURCE_FILES ${source_files})
+    SET(HEADER "${name}.h")
+    set_source_files_properties(${HEADER}
+                            PROPERTIES HEADER_FILE_ONLY TRUE)
+    LIST(APPEND TEST_SOURCE_FILES ${HEADER})
+    INCLUDE_DIRECTORIES("${LIBS_OPEN_DIR}/test")
+    ADD_EXECUTABLE(${name}_test ${TEST_SOURCE_FILES})
     TARGET_LINK_LIBRARIES(${name}_test
         ${libraries}
         )
@@ -80,11 +85,11 @@ MACRO(ADD_BUILD_TEST_INTERNAL name parent libraries source_files)
     ADD_CUSTOM_COMMAND(
         OUTPUT ${TEST_OUTPUT}
         COMMAND ${TEST_EXE}
-        ARGS --touch=${TEST_OUTPUT}
+        ARGS --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR}
         DEPENDS ${name}_test
         WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
         )
     ADD_CUSTOM_TARGET(${name}_test_ok ALL DEPENDS ${TEST_OUTPUT})
     ADD_DEPENDENCIES(${parent} ${name}_test_ok)
 
-ENDMACRO(ADD_BUILD_TEST_INTERNAL name parent libraries)
\ No newline at end of file
+ENDMACRO(ADD_BUILD_TEST_INTERNAL name parent libraries)
diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h
index f1094a8fd28946470fafa0109afc9435eff39a53..4109eade198a12ee56953baf967de9c930b1d6ce 100644
--- a/indra/llcommon/indra_constants.h
+++ b/indra/llcommon/indra_constants.h
@@ -118,6 +118,7 @@ const	char* const	DEFAULT_AGNI_DATA_SERVER	= "63.211.139.100";
 const	char* const	DEFAULT_AGNI_ASSET_SERVER	= "http://asset.agni.lindenlab.com:80";
 
 // Information about what ports are for what services is in the wiki Name Space Ports page
+// https://wiki.lindenlab.com/wiki/Name_Space_Ports
 const	char* const DEFAULT_LOCAL_ASSET_SERVER	= "http://localhost:12041/asset/tmp";
 const	char* const	LOCAL_ASSET_URL_FORMAT		= "http://%s:12041/asset";
 
@@ -138,6 +139,10 @@ const   U32		DEFAULT_CAP_PROXY_PORT			= 12043;
 const   U32		DEFAULT_INV_DATA_SERVER_PORT	= 12044;
 const	U32		DEFAULT_CGI_SERVICES_PORT		= 12045;
 
+// Mapserver uses ports 12124 - 12139 to allow multiple mapservers to run
+// on a single host for map tile generation. JC
+const	U32		DEFAULT_MAPSERVER_PORT			= 12124;
+
 // For automatic port discovery when running multiple viewers on one host
 const	U32		PORT_DISCOVERY_RANGE_MIN		= 13000;
 const	U32		PORT_DISCOVERY_RANGE_MAX		= PORT_DISCOVERY_RANGE_MIN + 50;
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index 1a1dbd40b6d2a99ba8a23bae4b888f1e7c78e227..8915890e18361a7e44412582f066da1dde5d3d10 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -33,6 +33,8 @@
 #ifndef LL_LLSTRING_H
 #define LL_LLSTRING_H
 
+#include <string>
+
 #if LL_LINUX || LL_SOLARIS
 #include <wctype.h>
 #include <wchar.h>
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index f68d86ff7cd6e11d056afe4f55c9cf3307467fba..2e93b2a3a7db66f0af8e18895a87b6b09422e69f 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -300,19 +300,22 @@ U32 LLOSInfo::getProcessVirtualSizeKB()
 #endif
 #if LL_LINUX
 	LLFILE* status_filep = LLFile::fopen("/proc/self/status", "rb");
-	S32 numRead = 0;		
-	char buff[STATUS_SIZE];		/* Flawfinder: ignore */
+	if (status_filep)
+	{
+		S32 numRead = 0;		
+		char buff[STATUS_SIZE];		/* Flawfinder: ignore */
 
-	size_t nbytes = fread(buff, 1, STATUS_SIZE-1, status_filep);
-	buff[nbytes] = '\0';
+		size_t nbytes = fread(buff, 1, STATUS_SIZE-1, status_filep);
+		buff[nbytes] = '\0';
 
-	// All these guys return numbers in KB
-	char *memp = strstr(buff, "VmSize:");
-	if (memp)
-	{
-		numRead += sscanf(memp, "%*s %u", &virtual_size);
+		// All these guys return numbers in KB
+		char *memp = strstr(buff, "VmSize:");
+		if (memp)
+		{
+			numRead += sscanf(memp, "%*s %u", &virtual_size);
+		}
+		fclose(status_filep);
 	}
-	fclose(status_filep);
 #elif LL_SOLARIS
 	char proc_ps[LL_MAX_PATH];
 	sprintf(proc_ps, "/proc/%d/psinfo", (int)getpid());
diff --git a/indra/llcommon/llversionserver.h b/indra/llcommon/llversionserver.h
index 7593eeae3795c5310b31be8f9bc7c2fb8896c0bd..f9b84dd6bdaf3c55669a57c29f039d14c11b35ef 100644
--- a/indra/llcommon/llversionserver.h
+++ b/indra/llcommon/llversionserver.h
@@ -36,7 +36,7 @@
 const S32 LL_VERSION_MAJOR = 1;
 const S32 LL_VERSION_MINOR = 27;
 const S32 LL_VERSION_PATCH = 0;
-const S32 LL_VERSION_BUILD = 109809;
+const S32 LL_VERSION_BUILD = 112940;
 
 const char * const LL_CHANNEL = "Second Life Server";
 
diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp
index 37c276096e23478e87c65650a8b54e8621f6c5f8..be6b6c817bb4040a3bc272c667dadb5bb05fb9b3 100644
--- a/indra/llimagej2coj/llimagej2coj.cpp
+++ b/indra/llimagej2coj/llimagej2coj.cpp
@@ -58,26 +58,42 @@ void fallbackDestroyLLImageJ2CImpl(LLImageJ2CImpl* impl)
 	impl = NULL;
 }
 
+// Return string from message, eliminating final \n if present
+static std::string chomp(const char* msg)
+{
+	// stomp trailing \n
+	std::string message = msg;
+	if (!message.empty())
+	{
+		size_t last = message.size() - 1;
+		if (message[last] == '\n')
+		{
+			message.resize( last );
+		}
+	}
+	return message;
+}
+
 /**
 sample error callback expecting a LLFILE* client object
 */
 void error_callback(const char* msg, void*)
 {
-	lldebugs << "LLImageJ2CImpl error_callback: " << msg << llendl;
+	lldebugs << "LLImageJ2COJ: " << chomp(msg) << llendl;
 }
 /**
 sample warning callback expecting a LLFILE* client object
 */
 void warning_callback(const char* msg, void*)
 {
-	lldebugs << "LLImageJ2CImpl warning_callback: " << msg << llendl;
+	lldebugs << "LLImageJ2COJ: " << chomp(msg) << llendl;
 }
 /**
 sample debug callback expecting no client object
 */
 void info_callback(const char* msg, void*)
 {
-	lldebugs << "LLImageJ2CImpl info_callback: " << msg << llendl;
+	lldebugs << "LLImageJ2COJ: " << chomp(msg) << llendl;
 }
 
 
diff --git a/indra/llinventory/llparcel.cpp b/indra/llinventory/llparcel.cpp
index 6fa5c9076ef2c0bc9dc7f75fef11a2f3423ecf9a..2689ada80cf8f5b2131959af635a217577f86d28 100644
--- a/indra/llinventory/llparcel.cpp
+++ b/indra/llinventory/llparcel.cpp
@@ -110,37 +110,11 @@ static const std::string PARCEL_ACTION_STRING[LLParcel::A_COUNT + 1] =
     "unknown"
 };
 
-// Timeouts for parcels
-// default is 21 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 1814400000000
-const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(1814400000000);
-// ***** TESTING is 10 minutes
-//const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(600000000);
 
-// group is 60 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 5184000000000
-const U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(5184000000000);
-// ***** TESTING is 10 minutes
-//const U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(600000000);
 
-// default sale timeout is 2 days -> 172800000000
-const U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(172800000000);
-// ***** TESTING is 10 minutes
-//const U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(600000000);
-
-// more grace period extensions.
-const U64 SEVEN_DAYS_IN_USEC = U64L(604800000000);
-
-// if more than 100,000s before sale revert, and no extra extension
-// has been given, go ahead and extend it more. That's about 1.2 days.
-const S32 EXTEND_GRACE_IF_MORE_THAN_SEC = 100000;
-
-
-const std::string& ownership_status_to_string(LLParcel::EOwnershipStatus status);
-LLParcel::EOwnershipStatus ownership_string_to_status(const std::string& s);
 //const char* revert_action_to_string(LLParcel::ESaleTimerExpireAction action);
 //LLParcel::ESaleTimerExpireAction revert_string_to_action(const char* s);
-const std::string& category_to_string(LLParcel::ECategory category);
 const std::string& category_to_ui_string(LLParcel::ECategory category);
-LLParcel::ECategory category_string_to_category(const std::string& s);
 LLParcel::ECategory category_ui_string_to_category(const std::string& s);
 
 LLParcel::LLParcel()
@@ -548,500 +522,6 @@ void LLParcel::setDiscountRate(F32 rate)
 // File input and output
 //-----------------------------------------------------------
 
-
-// WARNING: Area will be wrong until you calculate it.
-BOOL LLParcel::importStream(std::istream& input_stream)
-{
-	U32 setting;
-	S32 secs_until_revert = 0;
-
-	skip_to_end_of_next_keyword("{", input_stream);
-	if (!input_stream.good()) 
-	{
-		llwarns << "LLParcel::importStream() - bad input_stream" << llendl;
-		return FALSE;
-	}
-
-	while (input_stream.good())
-	{
-		skip_comments_and_emptyspace(input_stream);
-		std::string line, keyword, value;
-		get_line(line, input_stream, MAX_STRING);
-		get_keyword_and_value(keyword, value, line);
-
-		if ("}" == keyword)
-		{
-			break;
-		}
-		else if ("parcel_id" == keyword)
-		{
-			mID.set(value);
-		}
-		else if ("status" == keyword)
-		{
-			mStatus = ownership_string_to_status(value);
-		}
-		else if ("category" == keyword)
-		{
-			mCategory = category_string_to_category(value);
-		}
-		else if ("local_id" == keyword)
-		{
-			LLStringUtil::convertToS32(value, mLocalID);
-		}
-		else if ("name" == keyword)
-		{
-			setName( value );
-		}
-		else if ("desc" == keyword)
-		{
-			setDesc( value );
-		}
-		else if ("music_url" == keyword)
-		{
-			setMusicURL( value );
-		}
-		else if ("media_url" == keyword)
-		{
-			setMediaURL( value );
-		}
-		else if ("media_desc" == keyword)
-		{
-			setMediaDesc( value );
-		}
-		else if ("media_type" == keyword)
-		{
-			setMediaType( value );
-		}
-		else if ("media_width" == keyword)
-		{
-			S32 width;
-			LLStringUtil::convertToS32(value, width);
-			setMediaWidth( width );
-		}
-		else if ("media_height" == keyword)
-		{
-			S32 height;
-			LLStringUtil::convertToS32(value, height);
-			setMediaHeight( height );
-		}
-		else if ("media_id" == keyword)
-		{
-			mMediaID.set( value );
-		}
-		else if ("media_auto_scale" == keyword)
-		{
-			LLStringUtil::convertToU8(value, mMediaAutoScale);
-		}
-		else if ("media_loop" == keyword)
-		{
-			LLStringUtil::convertToU8(value, mMediaLoop);
-		}
-		else if ("obscure_media" == keyword)
-		{
-			LLStringUtil::convertToU8(value, mObscureMedia);
-		}		
-		else if ("obscure_music" == keyword)
-		{
-			LLStringUtil::convertToU8(value, mObscureMusic);
-		}		
-		else if ("owner_id" == keyword)
-		{
-			mOwnerID.set( value );
-		}
-		else if ("group_owned" == keyword)
-		{
-			LLStringUtil::convertToBOOL(value, mGroupOwned);
-		}
-		else if ("clean_other_time" == keyword)
-		{
-			S32 time;
-			LLStringUtil::convertToS32(value, time);
-			setCleanOtherTime(time);
-		}
-		else if ("auth_buyer_id" == keyword)
-		{
-			mAuthBuyerID.set(value);
-		}
-		else if ("snapshot_id" == keyword)
-		{
-			mSnapshotID.set(value);
-		}
-		else if ("user_location" == keyword)
-		{
-			sscanf(value.c_str(), "%f %f %f",
-				&mUserLocation.mV[VX],
-				&mUserLocation.mV[VY],
-				&mUserLocation.mV[VZ]);
-		}
-		else if ("user_look_at" == keyword)
-		{
-			sscanf(value.c_str(), "%f %f %f",
-				&mUserLookAt.mV[VX],
-				&mUserLookAt.mV[VY],
-				&mUserLookAt.mV[VZ]);
-		}
-		else if ("landing_type" == keyword)
-		{
-			S32 landing_type = 0;
-			LLStringUtil::convertToS32(value, landing_type);
-			mLandingType = (ELandingType) landing_type;
-		}
-		else if ("join_neighbors" == keyword)
-		{
-			llinfos << "found deprecated keyword join_neighbors" << llendl;
-		}
-		else if ("revert_sale" == keyword)
-		{
-			LLStringUtil::convertToS32(value, secs_until_revert);
-			if (secs_until_revert > 0)
-			{
-				mSaleTimerExpires.start();
-				mSaleTimerExpires.setTimerExpirySec((F32)secs_until_revert);
-			}
-		}
-		else if("extended_grace" == keyword)
-		{
-			LLStringUtil::convertToS32(value, mGraceExtension);
-		}
-		else if ("user_list_type" == keyword)
-		{
-			// deprecated
-		}
-		else if("auction_id" == keyword)
-		{
-			LLStringUtil::convertToU32(value, mAuctionID);
-		}
-		else if ("allow_modify" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_CREATE_OBJECTS, setting);
-		}
-		else if ("allow_group_modify" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_CREATE_GROUP_OBJECTS, setting);
-		}
-		else if ("allow_all_object_entry" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_ALLOW_ALL_OBJECT_ENTRY, setting);
-		}
-		else if ("allow_group_object_entry" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_ALLOW_GROUP_OBJECT_ENTRY, setting);
-		}
-		else if ("allow_deed_to_group" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_ALLOW_DEED_TO_GROUP, setting);
-		}
-		else if("contribute_with_deed" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_CONTRIBUTE_WITH_DEED, setting);
-		}
-		else if ("allow_terraform" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_ALLOW_TERRAFORM, setting);
-		}
-		else if ("allow_damage" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_ALLOW_DAMAGE, setting);
-		}
-		else if ("allow_fly" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_ALLOW_FLY, setting);
-		}
-		else if ("allow_landmark" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_ALLOW_LANDMARK, setting);
-		}
-		else if ("sound_local" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_SOUND_LOCAL, setting);
-		}
-		else if ("allow_group_scripts" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_ALLOW_GROUP_SCRIPTS, setting);
-		}
-		else if ("allow_voice_chat" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_ALLOW_VOICE_CHAT, setting);
-		}
-		else if ("use_estate_voice_chan" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_USE_ESTATE_VOICE_CHAN, setting);
-		}
-		else if ("allow_scripts" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_ALLOW_OTHER_SCRIPTS, setting);
-		}
-		else if ("for_sale" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_FOR_SALE, setting);
-		}
-		else if ("sell_w_objects" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_SELL_PARCEL_OBJECTS, setting);
-		}
-		else if ("use_pass_list" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_USE_PASS_LIST, setting);
-		}
-		else if ("show_directory" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_SHOW_DIRECTORY, setting);
-		}
-		else if ("allow_publish" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_ALLOW_PUBLISH, setting);
-		}
-		else if ("mature_publish" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_MATURE_PUBLISH, setting);
-		}
-		else if ("claim_date" == keyword)
-		{
-			// BUG: This will fail when time rolls over in 2038.
-			S32 time;
-			LLStringUtil::convertToS32(value, time);
-			mClaimDate = time;
-		}
-		else if ("claim_price" == keyword)
-		{
-			LLStringUtil::convertToS32(value, mClaimPricePerMeter);
-		}
-		else if ("rent_price" == keyword)
-		{
-			LLStringUtil::convertToS32(value, mRentPricePerMeter);
-		}
-		else if ("discount_rate" == keyword)
-		{
-			LLStringUtil::convertToF32(value, mDiscountRate);
-		}
-		else if ("draw_distance" == keyword)
-		{
-			LLStringUtil::convertToF32(value, mDrawDistance);
-		}
-		else if ("sale_price" == keyword)
-		{
-			LLStringUtil::convertToS32(value, mSalePrice);
-		}
-		else if ("pass_price" == keyword)
-		{
-			LLStringUtil::convertToS32(value, mPassPrice);
-		}
-		else if ("pass_hours" == keyword)
-		{
-			LLStringUtil::convertToF32(value, mPassHours);
-		}
-		else if ("box" == keyword)
-		{
-			// deprecated
-		}
-		else if ("aabb_min" == keyword)
-		{
-			sscanf(value.c_str(), "%f %f %f", 
-				&mAABBMin.mV[VX], &mAABBMin.mV[VY], &mAABBMin.mV[VZ]);
-		}
-		else if ("use_access_group" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_USE_ACCESS_GROUP, setting);
-		}
-		else if ("use_access_list" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_USE_ACCESS_LIST, setting);
-		}
-		else if ("use_ban_list" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_USE_BAN_LIST, setting);
-		}
-		else if ("group_name" == keyword)
-		{
-			llinfos << "found deprecated keyword group_name" << llendl;
-		}
-		else if ("group_id" == keyword)
-		{
-			mGroupID.set( value );
-		}
-		// TODO: DEPRECATED FLAG
-		// Flag removed from simstate files in 1.11.1
-		// Remove at some point where we have guarenteed this flag
-		// no longer exists anywhere in simstate files.
-		else if ("require_identified" == keyword)
-		{
-			// LLStringUtil::convertToU32(value, setting);
-			// setParcelFlag(PF_DENY_ANONYMOUS, setting);
-		}
-		// TODO: DEPRECATED FLAG
-		// Flag removed from simstate files in 1.11.1
-		// Remove at some point where we have guarenteed this flag
-		// no longer exists anywhere in simstate files.
-		else if ("require_transacted" == keyword)
-		{
-			// LLStringUtil::convertToU32(value, setting);
-			// setParcelFlag(PF_DENY_ANONYMOUS, setting);
-			// setParcelFlag(PF_DENY_IDENTIFIED, setting);
-		}
-		else if ("restrict_pushobject" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_RESTRICT_PUSHOBJECT, setting);
-		}
-		else if ("deny_anonymous" == keyword)
-		{
-			LLStringUtil::convertToU32(value, setting);
-			setParcelFlag(PF_DENY_ANONYMOUS, setting);
-		}
-		else if ("deny_identified" == keyword)
-		{
-// 			LLStringUtil::convertToU32(value, setting);
-// 			setParcelFlag(PF_DENY_IDENTIFIED, setting);
-		}
-		else if ("deny_transacted" == keyword)
-		{
-// 			LLStringUtil::convertToU32(value, setting);
-// 			setParcelFlag(PF_DENY_TRANSACTED, setting);
-		}
-        else if ("deny_age_unverified" == keyword)
-        {
-            LLStringUtil::convertToU32(value, setting);
-            setParcelFlag(PF_DENY_AGEUNVERIFIED, setting);
-        }
-        else if ("access_list" == keyword)
-        {
-            S32 entry_count = 0;
-            LLStringUtil::convertToS32(value, entry_count);
-            for (S32 i = 0; i < entry_count; i++)
-            {
-                LLAccessEntry entry;
-                if (importAccessEntry(input_stream, &entry))
-                {
-                    mAccessList[entry.mID] = entry;
-                }
-            }
-        }
-        else if ("ban_list" == keyword)
-        {
-            S32 entry_count = 0;
-            LLStringUtil::convertToS32(value, entry_count);
-            for (S32 i = 0; i < entry_count; i++)
-            {
-                LLAccessEntry entry;
-                if (importAccessEntry(input_stream, &entry))
-                {
-                    mBanList[entry.mID] = entry;
-                }
-            }
-        }
-        else if ("renter_list" == keyword)
-        {
-            /*
-             S32 entry_count = 0;
-             LLStringUtil::convertToS32(value, entry_count);
-             for (S32 i = 0; i < entry_count; i++)
-             {
-                 LLAccessEntry entry;
-                 if (importAccessEntry(input_stream, &entry))
-                 {
-                     mRenterList.put(entry);
-                 }
-             }*/
-        }
-        else if ("pass_list" == keyword)
-        {
-            // legacy - put into access list
-            S32 entry_count = 0;
-            LLStringUtil::convertToS32(value, entry_count);
-            for (S32 i = 0; i < entry_count; i++)
-            {
-                LLAccessEntry entry;
-                if (importAccessEntry(input_stream, &entry))
-                {
-                    mAccessList[entry.mID] = entry;
-                }
-            }
-        }
-        
-        else
-        {
-            llwarns << "Unknown keyword in parcel section: <" 
-            << keyword << ">" << llendl;
-        }
-    }
-    
-    // this code block detects if we have loaded a 1.1 simstate file,
-    // and follows the conversion rules specified in
-    // design_docs/land/pay_for_parcel.txt.
-    F32 time_to_expire = 0.0f;
-    if(mID.isNull())
-    {
-        mID.generate();
-        mStatus = OS_LEASE_PENDING;
-        //mBuyerID = mOwnerID;
-        if(getIsGroupOwned())
-        {
-            time_to_expire += GROUP_USEC_CONVERSION_TIMEOUT / SEC_TO_MICROSEC;
-        }
-        else
-        {
-            time_to_expire += DEFAULT_USEC_CONVERSION_TIMEOUT / SEC_TO_MICROSEC;
-        }
-        //mExpireAction = STEA_PUBLIC;
-        mRecordTransaction = TRUE;
-    }
-    
-    // this code block deals with giving an extension to pending
-    // parcels to the midday of 2004-01-19 if they were originally set
-    // for some time on 2004-01-12.
-    if((0 == mGraceExtension)
-       && (EXTEND_GRACE_IF_MORE_THAN_SEC < secs_until_revert))
-    {
-        const S32 NEW_CONVERSION_DATE = 1074538800; // 2004-01-19T11:00:00
-        time_t now = time(NULL); // now in epoch
-        secs_until_revert = (S32)(NEW_CONVERSION_DATE - now);
-        time_to_expire = (F32)secs_until_revert;
-        mGraceExtension = 1;
-    }
-    
-    // This code block adds yet another week to the deadline. :(
-    if(1 == mGraceExtension)
-    {
-        time_to_expire += SEVEN_DAYS_IN_USEC / SEC_TO_MICROSEC;
-        mGraceExtension = 2;
-    }
-    
-    if (time_to_expire > 0)
-    {
-        mSaleTimerExpires.setTimerExpirySec(time_to_expire);
-        mSaleTimerExpires.start();
-    }
-    
-    // successful import
-    return TRUE;
-}
-
-
 BOOL LLParcel::importAccessEntry(std::istream& input_stream, LLAccessEntry* entry)
 {
     skip_to_end_of_next_keyword("{", input_stream);
@@ -1085,230 +565,6 @@ BOOL LLParcel::importAccessEntry(std::istream& input_stream, LLAccessEntry* entr
     return input_stream.good();
 }
 
-BOOL LLParcel::exportStream(std::ostream& output_stream)
-{
-	S32 setting;
-	std::string id_string;
-
-	std::ios::fmtflags old_flags = output_stream.flags();
-	output_stream.setf(std::ios::showpoint);
-	output_stream << "\t{\n";
-
-	mID.toString(id_string);
-	output_stream << "\t\t parcel_id        " << id_string << "\n";
-	output_stream << "\t\t status           " << ownership_status_to_string(mStatus) << "\n";
-	output_stream << "\t\t category         " << category_to_string(mCategory) << "\n";
-
-	output_stream << "\t\t local_id         " << mLocalID  << "\n";
-
-	const char* name = (mName.empty() ? "" : mName.c_str() );
-	output_stream << "\t\t name             " << name << "\n";
-
-	const char* desc = (mDesc.empty() ? "" : mDesc.c_str() );
-	output_stream << "\t\t desc             " << desc << "\n";
-
-	const char* music_url = (mMusicURL.empty() ? "" : mMusicURL.c_str() );
-	output_stream << "\t\t music_url        " << music_url << "\n";
-
-	const char* media_url = (mMediaURL.empty() ? "" : mMediaURL.c_str() );
-	output_stream << "\t\t media_url        " << media_url << "\n";
-
-	const char* media_type = (mMediaType.empty() ? "" : mMediaType.c_str() );
-	output_stream << "\t\t media_type             " << media_type << "\n";
-
-	const char* media_desc = (mMediaDesc.empty() ? "" : mMediaDesc.c_str() );
-	output_stream << "\t\t media_desc             " << media_desc << "\n";
-
-	output_stream << "\t\t media_auto_scale " << (mMediaAutoScale ? 1 : 0)  << "\n";
-	output_stream << "\t\t media_loop " << (mMediaLoop ? 1 : 0)  << "\n";
-	output_stream << "\t\t obscure_media " << (mObscureMedia ? 1 : 0)  << "\n";
-	output_stream << "\t\t obscure_music " << (mObscureMusic ? 1 : 0)  << "\n";
-
-	mMediaID.toString(id_string);
-	output_stream << "\t\t media_id         " << id_string  << "\n";
-
-	output_stream << "\t\t media_width     " << mMediaWidth  << "\n";
-	output_stream << "\t\t media_height     " << mMediaHeight  << "\n";
-
-	mOwnerID.toString(id_string);
-	output_stream << "\t\t owner_id         " << id_string  << "\n";
-	output_stream << "\t\t group_owned	   " << (mGroupOwned ? 1 : 0)  << "\n";
-	output_stream << "\t\t clean_other_time " << getCleanOtherTime() << "\n";
-
-	if(!mAuthBuyerID.isNull())
-	{
-		mAuthBuyerID.toString(id_string);
-		output_stream << "\t\t auth_buyer_id    " << id_string << "\n";
-	}
-	if (!mSnapshotID.isNull())
-	{
-		mSnapshotID.toString(id_string);
-		output_stream << "\t\t snapshot_id      " << id_string << "\n";
-	}
-	if (!mUserLocation.isExactlyZero())
-	{
-		output_stream << "\t\t user_location " 
-			<< (F64)mUserLocation.mV[VX]
-			<< " " << (F64)mUserLocation.mV[VY]
-			<< " " << (F64)mUserLocation.mV[VZ] << "\n";
-		output_stream << "\t\t user_look_at " 
-			<< (F64)mUserLookAt.mV[VX]
-			<< " " << (F64)mUserLookAt.mV[VY]
-			<< " " << (F64)mUserLookAt.mV[VZ] << "\n";
-	}
-	output_stream << "\t\t landing_type " << mLandingType << "\n";
-	//if(mJoinNeighbors)
-	//{
-	//	output_stream << "\t\t join_neighbors " << mJoinNeighbors << "\n";
-	//}
-	if(mSaleTimerExpires.getStarted())
-	{
-		S32 dt_sec = (S32) mSaleTimerExpires.getRemainingTimeF32()+60; // Add a minute to prevent race conditions
-		output_stream << "\t\t revert_sale      " << dt_sec << "\n";
-		//output_stream << "\t\t revert_action    " << revert_action_to_string(mExpireAction) << "\n";
-		output_stream << "\t\t extended_grace   " << mGraceExtension << "\n";
-	}
-
-	if(0 != mAuctionID)
-	{
-		output_stream << "\t\t auction_id       " << mAuctionID << "\n";
-	}
-
-	output_stream << "\t\t allow_modify     " << getAllowModify()  << "\n";
-	output_stream << "\t\t allow_group_modify     " << getAllowGroupModify()  << "\n";
-	output_stream << "\t\t allow_all_object_entry     " << getAllowAllObjectEntry()  << "\n";
-	output_stream << "\t\t allow_group_object_entry     " << getAllowGroupObjectEntry()  << "\n";
-	output_stream << "\t\t allow_terraform  " << getAllowTerraform()  << "\n";
-	output_stream << "\t\t allow_deed_to_group " << getAllowDeedToGroup()  << "\n";
-	output_stream << "\t\t contribute_with_deed " << getContributeWithDeed() << "\n";
-	output_stream << "\t\t allow_damage     " << getAllowDamage()  << "\n";
-	output_stream << "\t\t claim_date       " << (S32)mClaimDate  << "\n";
-	output_stream << "\t\t claim_price      " << mClaimPricePerMeter  << "\n";
-	output_stream << "\t\t rent_price       " << mRentPricePerMeter  << "\n";
-	output_stream << "\t\t discount_rate    " << mDiscountRate  << "\n";
-	output_stream << "\t\t allow_fly        " << (getAllowFly()      ? 1 : 0)  << "\n";
-	output_stream << "\t\t allow_landmark   " << (getAllowLandmark() ? 1 : 0)  << "\n";
-	output_stream << "\t\t sound_local	   " << (getSoundLocal() ? 1 : 0)  << "\n";
-	output_stream << "\t\t allow_scripts    " << (getAllowOtherScripts()  ? 1 : 0)  << "\n";
-	output_stream << "\t\t allow_group_scripts    " << (getAllowGroupScripts()  ? 1 : 0)  << "\n";
-	output_stream << "\t\t use_estate_voice_chan		 " << (getParcelFlagUseEstateVoiceChannel() ? 1 : 0) << "\n";
-
-	output_stream << "\t\t allow_voice_chat    " << (getParcelFlagAllowVoice() ? 1 : 0) << "\n";
-	output_stream << "\t\t use_estate_voice_chan   " << (getParcelFlagUseEstateVoiceChannel() ? 1 : 0) << "\n";
-	output_stream << "\t\t for_sale         " << (getForSale()       ? 1 : 0)  << "\n";
-	output_stream << "\t\t sell_w_objects   " << (getSellWithObjects()	? 1 : 0)  << "\n";
-	output_stream << "\t\t draw_distance    " << mDrawDistance  << "\n";
-	output_stream << "\t\t sale_price       " << mSalePrice  << "\n";
-
-	setting = (getParcelFlag(PF_USE_ACCESS_GROUP) ? 1 : 0);
-	output_stream << "\t\t use_access_group " << setting  << "\n";
-
-	setting = (getParcelFlag(PF_USE_ACCESS_LIST) ? 1 : 0);
-	output_stream << "\t\t use_access_list  " << setting  << "\n";
-
-	setting = (getParcelFlag(PF_USE_BAN_LIST) ? 1 : 0);
-	output_stream << "\t\t use_ban_list     " << setting  << "\n";
-
-	mGroupID.toString(id_string);
-	output_stream << "\t\t group_id  " << id_string  << "\n";
-
-	//const char* group_name
-	//	= (mGroupName.isEmpty() ? "" : mGroupName.c_str() );
-	//output_stream << "\t\t group_name " << group_name << "\n";
-
-	setting = (getParcelFlag(PF_USE_PASS_LIST) ? 1 : 0);
-	output_stream << "\t\t use_pass_list    " << setting  << "\n";
-
-	output_stream << "\t\t pass_price       " << mPassPrice  << "\n";
-	output_stream << "\t\t pass_hours       " << mPassHours  << "\n";
-
-	setting = (getParcelFlag(PF_SHOW_DIRECTORY) ? 1 : 0);
-	output_stream << "\t\t show_directory   " << setting  << "\n";
-
-	setting = (getParcelFlag(PF_ALLOW_PUBLISH) ? 1 : 0);
-	output_stream << "\t\t allow_publish     " << setting  << "\n";
-
-	setting = (getParcelFlag(PF_MATURE_PUBLISH) ? 1 : 0);
-	output_stream << "\t\t mature_publish     " << setting  << "\n";
-
-	setting = (getParcelFlag(PF_DENY_ANONYMOUS) ? 1 : 0);
-	output_stream << "\t\t deny_anonymous     " << setting  << "\n";
-
-//	setting = (getParcelFlag(PF_DENY_IDENTIFIED) ? 1 : 0);
-//	output_stream << "\t\t deny_identified     " << setting  << "\n";
-
-//	setting = (getParcelFlag(PF_DENY_TRANSACTED) ? 1 : 0);
-//	output_stream << "\t\t deny_transacted     " << setting  << "\n";
-
-	setting = (getParcelFlag(PF_DENY_AGEUNVERIFIED) ? 1 : 0);
-	output_stream << "\t\t deny_age_unverified			 " << setting  << "\n";
-
-	setting = (getParcelFlag(PF_RESTRICT_PUSHOBJECT) ? 1 : 0);
-	output_stream << "\t\t restrict_pushobject " << setting  << "\n";
-
-	output_stream << "\t\t aabb_min         " 
-		<< mAABBMin.mV[VX]
-		<< " " << mAABBMin.mV[VY]
-		<< " " << mAABBMin.mV[VZ] << "\n";
-
-	if (!mAccessList.empty())
-	{
-		output_stream << "\t\t access_list " << mAccessList.size()  << "\n";
-		access_map_const_iterator cit = mAccessList.begin();
-		access_map_const_iterator end = mAccessList.end();
-
-		for ( ; cit != end; ++cit)
-		{
-			output_stream << "\t\t{\n";
-			const LLAccessEntry& entry = (*cit).second;
-			entry.mID.toString(id_string);
-			output_stream << "\t\t\tid " << id_string << "\n";
-			output_stream << "\t\t\ttime " << entry.mTime  << "\n";
-			output_stream << "\t\t\tflags " << entry.mFlags  << "\n";
-			output_stream << "\t\t}\n";
-		}
-	}
-
-	if (!mBanList.empty())
-	{
-		output_stream << "\t\t ban_list " << mBanList.size()  << "\n";
-		access_map_const_iterator cit = mBanList.begin();
-		access_map_const_iterator end = mBanList.end();
-
-		for ( ; cit != end; ++cit)
-		{
-			output_stream << "\t\t{\n";
-			const LLAccessEntry& entry = (*cit).second;
-			entry.mID.toString(id_string);
-			output_stream << "\t\t\tid " << id_string << "\n";
-			output_stream << "\t\t\ttime " << entry.mTime  << "\n";
-			output_stream << "\t\t\tflags " << entry.mFlags  << "\n";
-			output_stream << "\t\t}\n";
-		}
-	}
-
-	/*if (mRenterList.count() > 0)
-	{
-		output_stream << "\t\t renter_list " << mRenterList.count()  << "\n";
-		for (i = 0; i < mRenterList.count(); i++)
-		{
-			output_stream << "\t\t{\n";
-			const LLAccessEntry& entry = mRenterList.get(i);
-			entry.mID.toString(id_string);
-			output_stream << "\t\t\tid " << id_string << "\n";
-			output_stream << "\t\t\ttime " << entry.mTime  << "\n";
-			output_stream << "\t\t\tflags " << entry.mFlags  << "\n";
-			output_stream << "\t\t}\n";
-		}
-	}*/
-
-	output_stream << "\t}\n";
-	output_stream.flags(old_flags);
-
-	return TRUE;
-}
-
-
 // Assumes we are in a block "ParcelData"
 void LLParcel::packMessage(LLMessageSystem* msg)
 {
diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h
index 12d0fdf1e906065aa1f775c2460ca12964976348..6f5ae87ebd5c59073689925cae9fd6002a84d041 100644
--- a/indra/llinventory/llparcel.h
+++ b/indra/llinventory/llparcel.h
@@ -103,6 +103,32 @@ const U32 RT_OTHER	= 0x1 << 3;
 const U32 RT_LIST	= 0x1 << 4;
 const U32 RT_SELL	= 0x1 << 5;
 
+
+// Timeouts for parcels
+// default is 21 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 1814400000000
+const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(1814400000000);
+// ***** TESTING is 10 minutes
+//const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(600000000);
+
+// group is 60 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 5184000000000
+const U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(5184000000000);
+// ***** TESTING is 10 minutes
+//const U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(600000000);
+
+// default sale timeout is 2 days -> 172800000000
+const U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(172800000000);
+// ***** TESTING is 10 minutes
+//const U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(600000000);
+
+// more grace period extensions.
+const U64 SEVEN_DAYS_IN_USEC = U64L(604800000000);
+
+// if more than 100,000s before sale revert, and no extra extension
+// has been given, go ahead and extend it more. That's about 1.2 days.
+const S32 EXTEND_GRACE_IF_MORE_THAN_SEC = 100000;
+
+
+
 class LLMessageSystem;
 class LLSD;
 
@@ -271,9 +297,9 @@ class LLParcel
 	void	setPassPrice(S32 price)				{ mPassPrice = price; }
 	void	setPassHours(F32 hours)				{ mPassHours = hours; }
 
-	BOOL	importStream(std::istream& input_stream);
+//	BOOL	importStream(std::istream& input_stream);
 	BOOL	importAccessEntry(std::istream& input_stream, LLAccessEntry* entry);
-	BOOL	exportStream(std::ostream& output_stream);
+//	BOOL	exportStream(std::ostream& output_stream);
 
 	void	packMessage(LLMessageSystem* msg);
 	void	packMessage(LLSD& msg);
@@ -633,4 +659,10 @@ class LLParcel
 };
 
 
+const std::string& ownership_status_to_string(LLParcel::EOwnershipStatus status);
+LLParcel::EOwnershipStatus ownership_string_to_status(const std::string& s);
+LLParcel::ECategory category_string_to_category(const std::string& s);
+const std::string& category_to_string(LLParcel::ECategory category);
+
+
 #endif
diff --git a/indra/llmath/v3math.cpp b/indra/llmath/v3math.cpp
index 101e9d075a71b28ff885ac8612f484aa4ee9c086..d4031796adea97eb2d2a05901149be7ff4c2e161 100644
--- a/indra/llmath/v3math.cpp
+++ b/indra/llmath/v3math.cpp
@@ -134,6 +134,7 @@ BOOL LLVector3::clampLength( F32 length_limit )
 			mV[0] *= length_limit;
 			mV[1] *= length_limit;
 			mV[2] *= length_limit;
+			changed = TRUE;
 		}
 	}
 
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index fd22de9399b935b96b2d0c5105c162e32d0a4541..4fb018741233dd032f307c24e517a0adc5767edf 100644
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -7,6 +7,7 @@ include(LLCommon)
 include(LLMath)
 include(LLMessage)
 include(LLVFS)
+include(LLAddBuildTest)
 
 include_directories (${CMAKE_CURRENT_SOURCE_DIR})
 
@@ -34,6 +35,7 @@ set(llmessage_SOURCE_FILES
     llhost.cpp
     llhttpassetstorage.cpp
     llhttpclient.cpp
+    llhttpclientadapter.cpp
     llhttpnode.cpp
     llhttpsender.cpp
     llinstantmessage.cpp
@@ -57,6 +59,7 @@ set(llmessage_SOURCE_FILES
     llpacketring.cpp
     llpartdata.cpp
     llpumpio.cpp
+    llregionpresenceverifier.cpp
     llsdappservices.cpp
     llsdhttpserver.cpp
     llsdmessagebuilder.cpp
@@ -65,7 +68,9 @@ set(llmessage_SOURCE_FILES
     llsdrpcserver.cpp
     llservicebuilder.cpp
     llservice.cpp
+    llstoredmessage.cpp
     lltemplatemessagebuilder.cpp
+    lltemplatemessagedispatcher.cpp
     lltemplatemessagereader.cpp
     llthrottle.cpp
     lltransfermanager.cpp
@@ -73,6 +78,7 @@ set(llmessage_SOURCE_FILES
     lltransfersourcefile.cpp
     lltransfertargetfile.cpp
     lltransfertargetvfile.cpp
+    lltrustedmessageservice.cpp
     llurlrequest.cpp
     lluseroperation.cpp
     llxfer.cpp
@@ -85,7 +91,6 @@ set(llmessage_SOURCE_FILES
     message_prehash.cpp
     message_string_table.cpp
     net.cpp
-    network.cpp
     partsyspacket.cpp
     patch_code.cpp
     patch_dct.cpp
@@ -115,7 +120,10 @@ set(llmessage_HEADER_FILES
     llhost.h
     llhttpassetstorage.h
     llhttpclient.h
+    llhttpclientinterface.h
+    llhttpclientadapter.h
     llhttpnode.h
+    llhttpnodeadapter.h
     llhttpsender.h
     llinstantmessage.h
     llinvite.h
@@ -144,6 +152,7 @@ set(llmessage_HEADER_FILES
     llqueryflags.h
     llregionflags.h
     llregionhandle.h
+    llregionpresenceverifier.h
     llsdappservices.h
     llsdhttpserver.h
     llsdmessagebuilder.h
@@ -152,9 +161,11 @@ set(llmessage_HEADER_FILES
     llsdrpcserver.h
     llservice.h
     llservicebuilder.h
+    llstoredmessage.h
     lltaskname.h
     llteleportflags.h
     lltemplatemessagebuilder.h
+    lltemplatemessagedispatcher.h
     lltemplatemessagereader.h
     llthrottle.h
     lltransfermanager.h
@@ -162,6 +173,7 @@ set(llmessage_HEADER_FILES
     lltransfersourcefile.h
     lltransfertargetfile.h
     lltransfertargetvfile.h
+    lltrustedmessageservice.h
     llurlrequest.h
     lluseroperation.h
     llvehicleparams.h
@@ -176,7 +188,6 @@ set(llmessage_HEADER_FILES
     message.h
     message_prehash.h
     net.h
-    network.h
     partsyspacket.h
     patch_code.h
     patch_dct.h
@@ -197,3 +208,13 @@ target_link_libraries(
     ${CRYPTO_LIBRARIES}
     ${XMLRPCEPI_LIBRARIES}
     )
+
+IF (NOT LINUX AND VIEWER)
+    # When building the viewer the tests links against the shared objects. 
+    # These can not be found when we try to run the tests, so we had to disable them, for the viewer build.
+    # TODO: Can someone with viewer knowledge figure out how to make these find the correct so.
+    #ADD_BUILD_TEST(llhttpclientadapter llmessage)
+    ADD_BUILD_TEST(lltrustedmessageservice llmessage)
+    ADD_BUILD_TEST(lltemplatemessagedispatcher llmessage)
+ENDIF (NOT LINUX AND VIEWER)
+
diff --git a/indra/llmessage/lldispatcher.cpp b/indra/llmessage/lldispatcher.cpp
index bb7c833b49ee0e799e32714d2cb3dc632bc55009..7ce3d11be489172f007822fa250aa690d1992b64 100644
--- a/indra/llmessage/lldispatcher.cpp
+++ b/indra/llmessage/lldispatcher.cpp
@@ -111,40 +111,14 @@ bool LLDispatcher::unpackMessage(
 		LLUUID& invoice,
 		LLDispatcher::sparam_t& parameters)
 {
-	char buf[MAX_STRING];	/*Flawfinder: ignore*/
 	msg->getStringFast(_PREHASH_MethodData, _PREHASH_Method, method);
 	msg->getUUIDFast(_PREHASH_MethodData, _PREHASH_Invoice, invoice);
-	S32 size;
 	S32 count = msg->getNumberOfBlocksFast(_PREHASH_ParamList);
 	for (S32 i = 0; i < count; ++i)
 	{
-		// we treat the SParam as binary data (since it might be an 
-		// LLUUID in compressed form which may have embedded \0's,)
-		size = msg->getSizeFast(_PREHASH_ParamList, i, _PREHASH_Parameter);
-		msg->getBinaryDataFast(
-			_PREHASH_ParamList, _PREHASH_Parameter,
-			buf, size, i, MAX_STRING-1);
-
-		// If the last byte of the data is 0x0, this is either a normally
-		// packed string, or a binary packed UUID (which for these messages
-		// are packed with a 17th byte 0x0).  Unpack into a std::string
-		// without the trailing \0, so "abc\0" becomes std::string("abc", 3)
-		// which matches const char* "abc".
-		if (size > 0
-			&& buf[size-1] == 0x0)
-		{
-			// special char*/size constructor because UUIDs may have embedded
-			// 0x0 bytes.
-			std::string binary_data(buf, size-1);
-			parameters.push_back(binary_data);
-		}
-		else
-		{
-			// This is either a NULL string, or a string that was packed 
-			// incorrectly as binary data, without the usual trailing '\0'.
-			std::string string_data(buf, size);
-			parameters.push_back(string_data);
-		}
+		std::string parameter;
+		msg->getStringFast(_PREHASH_ParamList,_PREHASH_Parameter, parameter, i);
+		parameters.push_back(parameter);
 	}
 	return true;
 }
diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp
index 2438539049e473d6820de33f96b720fd8723c58e..dfdad59e2a66efa9386ead8326c9f2627f1c4b21 100644
--- a/indra/llmessage/llhttpassetstorage.cpp
+++ b/indra/llmessage/llhttpassetstorage.cpp
@@ -235,6 +235,7 @@ LLSD LLHTTPAssetRequest::getFullDetails() const
 
 void LLHTTPAssetRequest::setupCurlHandle()
 {
+	// *NOTE: Similar code exists in mapserver/llcurlutil.cpp  JC
 	mCurlHandle = curl_easy_init();
 	curl_easy_setopt(mCurlHandle, CURLOPT_NOSIGNAL, 1);
 	curl_easy_setopt(mCurlHandle, CURLOPT_NOPROGRESS, 1);
diff --git a/indra/llmessage/llhttpclientadapter.cpp b/indra/llmessage/llhttpclientadapter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f0e7654646cf311b20f6a750eb496a098b9f8314
--- /dev/null
+++ b/indra/llmessage/llhttpclientadapter.cpp
@@ -0,0 +1,53 @@
+/** 
+ * @file 
+ * @brief 
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llhttpclientadapter.h"
+#include "llhttpclient.h"
+
+LLHTTPClientAdapter::~LLHTTPClientAdapter() 
+{
+}
+
+void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder) 
+{
+	LLHTTPClient::get(url, responder);
+}
+
+void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers) 
+{
+	LLHTTPClient::get(url, responder, headers);
+}
+
+void LLHTTPClientAdapter::put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder) 
+{
+	LLHTTPClient::put(url, body, responder);
+}
+
diff --git a/indra/llmessage/llhttpclientadapter.h b/indra/llmessage/llhttpclientadapter.h
new file mode 100644
index 0000000000000000000000000000000000000000..d5f3aeaf2cf06bdeab1137b6a15447e2248a3d8f
--- /dev/null
+++ b/indra/llmessage/llhttpclientadapter.h
@@ -0,0 +1,48 @@
+/** 
+ * @file 
+ * @brief 
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2008, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_HTTPCLIENTADAPTER_H
+#define LL_HTTPCLIENTADAPTER_H
+
+#include "llhttpclientinterface.h"
+#include "llmemory.h"	// LLSingleton<>
+
+class LLHTTPClientAdapter : public LLHTTPClientInterface, public LLSingleton<LLHTTPClientAdapter>
+{
+public:
+	virtual ~LLHTTPClientAdapter();
+	virtual void get(const std::string& url, LLCurl::ResponderPtr responder);
+	virtual void get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers);
+	virtual void put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder);
+};
+
+#endif
+
diff --git a/indra/llmessage/llhttpclientinterface.h b/indra/llmessage/llhttpclientinterface.h
new file mode 100644
index 0000000000000000000000000000000000000000..1f13d46447cedde8117e02f1046426d1a71c8cb1
--- /dev/null
+++ b/indra/llmessage/llhttpclientinterface.h
@@ -0,0 +1,50 @@
+/** 
+ * @file 
+ * @brief 
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2008, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLHTTPCLIENTINTERFACE_H
+#define LL_LLHTTPCLIENTINTERFACE_H
+
+#include "linden_common.h"
+#include "llcurl.h"
+
+#include <string>
+
+class LLHTTPClientInterface
+{
+public:
+	virtual ~LLHTTPClientInterface() {}
+	virtual void get(const std::string& url, LLCurl::ResponderPtr responder) = 0;
+	virtual void get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers) = 0;
+	virtual void put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder) = 0;
+};
+
+#endif // LL_LLHTTPCLIENTINTERFACE_H
+
diff --git a/indra/llmessage/llhttpnode.h b/indra/llmessage/llhttpnode.h
index 4f80db47f176a14c9516417fd729f1b02f87b01c..17ffd66e8f95f20c21159c931cde8a6cb722c32b 100644
--- a/indra/llmessage/llhttpnode.h
+++ b/indra/llmessage/llhttpnode.h
@@ -88,6 +88,9 @@ class LLHTTPNode
 	virtual LLSD post(const LLSD& input) const;
 	virtual LLSD del(const LLSD& context) const;
 
+	/**
+	* @brief Abstract Base Class declaring Response interface.
+	*/
 	class Response : public LLRefCount
 	{
 	protected:
@@ -95,8 +98,8 @@ class LLHTTPNode
 
 	public:
 		/**
-		 * @brief Return the LLSD content and a 200 OK.
-		 */
+		* @brief Return the LLSD content and a 200 OK.
+		*/
 		virtual void result(const LLSD&) = 0;
 
 		/**
@@ -111,42 +114,41 @@ class LLHTTPNode
 		virtual void status(S32 code, const std::string& message) = 0;
 
 		/**
-		 * @brief Return no body, just status code and 'UNKNOWN ERROR'.
-		 */
-		void status(S32 code);
+		* @brief Return no body, just status code and 'UNKNOWN ERROR'.
+		*/
+		virtual void status(S32 code);
 
-		void notFound(const std::string& message);
-		void notFound();
-		void methodNotAllowed();
+		virtual void notFound(const std::string& message);
+		virtual void notFound();
+		virtual void methodNotAllowed();
 
 		/**
-		 * @breif Add a name: value http header.
-		 *
-		 * No effort is made to ensure the response is a valid http
-		 * header.
-		 * The headers are stored as a map of header name : value.
-		 * Though HTTP allows the same header name to be transmitted
-		 * more than once, this implementation only stores a header
-		 * name once.
-		 * @param name The name of the header, eg, "Content-Encoding"
-		 * @param value The value of the header, eg, "gzip"
-		 */
-		void addHeader(const std::string& name, const std::string& value);
+		* @breif Add a name: value http header.
+		*
+		* No effort is made to ensure the response is a valid http
+		* header.
+		* The headers are stored as a map of header name : value.
+		* Though HTTP allows the same header name to be transmitted
+		* more than once, this implementation only stores a header
+		* name once.
+		* @param name The name of the header, eg, "Content-Encoding"
+		* @param value The value of the header, eg, "gzip"
+		*/
+		virtual void addHeader(const std::string& name, const std::string& value);
 
 	protected:
 		/**
-		 * @brief Headers to be sent back with the HTTP response.
-		 *
-		 * Protected class membership since derived classes are
-		 * expected to use it and there is no use case yet for other
-		 * uses. If such a use case arises, I suggest making a
-		 * headers() public method, and moving this member data into
-		 * private.
-		 */
+		* @brief Headers to be sent back with the HTTP response.
+		*
+		* Protected class membership since derived classes are
+		* expected to use it and there is no use case yet for other
+		* uses. If such a use case arises, I suggest making a
+		* headers() public method, and moving this member data into
+		* private.
+		*/
 		LLSD mHeaders;
 	};
 
-
 	typedef LLPointer<Response> ResponsePtr;
 
 	virtual void get(ResponsePtr, const LLSD& context) const;
diff --git a/indra/llmessage/llhttpnodeadapter.h b/indra/llmessage/llhttpnodeadapter.h
new file mode 100644
index 0000000000000000000000000000000000000000..08b56641629f70a9546ea2e1d3f0f1c8c4e611ae
--- /dev/null
+++ b/indra/llmessage/llhttpnodeadapter.h
@@ -0,0 +1,57 @@
+/**
+ * @file llhttpnodeadapter.h
+ * @brief Declaration of llhttpnode adapter classes
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_HTTP_NODE_ADAPTER_H
+#define LL_HTTP_NODE_ADAPTER_H
+
+#include "llhttpnode.h"
+
+template<typename T>
+class LLHTTPNodeAdapter : public LLHTTPNode
+{
+public:
+
+	virtual bool validate(const std::string& name, LLSD& context) const
+	{
+		T node;
+		return node.validate(name, context);
+	}
+	
+	virtual void post(LLHTTPNode::ResponsePtr response,
+					  const LLSD& context,
+					  const LLSD& input) const
+	{
+		T node;
+		return node.post(response, context, input);
+	}
+};
+
+#endif // LL_HTTP_NODE_ADAPTER_H
diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp
index 0895af091b8e9e986c53f4d216d2695edde385bc..83dfa94f00f3970df56798a84042f58f517bec6d 100644
--- a/indra/llmessage/lliohttpserver.cpp
+++ b/indra/llmessage/lliohttpserver.cpp
@@ -844,6 +844,7 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
 				= node->getProtocolHandler();
 			if (protocolHandler)
 			{
+				lldebugs << "HTTP context: " << context << llendl;
 				protocolHandler->build(chain, context);
 			}
 			else
diff --git a/indra/llmessage/llmessagesenderinterface.h b/indra/llmessage/llmessagesenderinterface.h
new file mode 100644
index 0000000000000000000000000000000000000000..40826663398cc84d608a60de143aa867ea48432d
--- /dev/null
+++ b/indra/llmessage/llmessagesenderinterface.h
@@ -0,0 +1,49 @@
+/** 
+ * @file 
+ * @brief 
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2008, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLMESSAGESENDERINTERFACE_H
+#define LL_LLMESSAGESENDERINTERFACE_H
+
+#include "linden_common.h"
+#include "llstoredmessage.h"
+class LLHost;
+class LLSD;
+
+class LLMessageSenderInterface
+{
+public:
+	virtual ~LLMessageSenderInterface() {}
+	virtual S32 sendMessage(const LLHost& host, LLStoredMessagePtr message) = 0;
+
+};
+
+#endif // LL_LLMESSAGESENDERINTERFACE_H
+
diff --git a/indra/llmessage/llregionpresenceverifier.cpp b/indra/llmessage/llregionpresenceverifier.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b3fabddd3e1856b18f7387a30f1255d7d477ab9e
--- /dev/null
+++ b/indra/llmessage/llregionpresenceverifier.cpp
@@ -0,0 +1,87 @@
+/** 
+ * @file 
+ * @brief 
+ *
+ * $LicenseInfo:firstyear=2008&license=internal$
+ * 
+ * Copyright (c) 2008, Linden Research, Inc.
+ * 
+ * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
+ * this source code is governed by the Linden Lab Source Code Disclosure
+ * Agreement ("Agreement") previously entered between you and Linden
+ * Lab. By accessing, using, copying, modifying or distributing this
+ * software, you acknowledge that you have been informed of your
+ * obligations under the Agreement and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llregionpresenceverifier.h"
+#include "llhttpclientinterface.h"
+#include <sstream>
+#include "net.h"
+#include "message.h"
+
+
+LLRegionPresenceVerifier::RegionResponder::RegionResponder(ResponsePtr data) : mSharedData(data)
+{
+}
+
+
+void LLRegionPresenceVerifier::RegionResponder::result(const LLSD& content)
+{
+	std::string host = content["private_host"].asString();
+	U32 port = content["private_port"].asInteger();
+	LLHost destination(host, port);
+	LLUUID id = content["region_id"];
+
+	llinfos << "Verifying " << destination.getString() << " is region " << id << llendl;
+
+	std::stringstream uri;
+	uri << "http://" << destination.getString() << "/state/basic";
+	mSharedData->getHttpClient().get(uri.str(), new VerifiedDestinationResponder(mSharedData, content));
+}
+
+void LLRegionPresenceVerifier::RegionResponder::completed(
+	U32 status,
+	const std::string& reason,
+	const LLSD& content)
+{
+	LLHTTPClient::Responder::completed(status, reason, content);
+	
+	mSharedData->onCompletedRegionRequest();
+}
+
+
+LLRegionPresenceVerifier::VerifiedDestinationResponder::VerifiedDestinationResponder(ResponsePtr data, const LLSD& content) : mSharedData(data), mContent(content)
+{
+}
+
+
+
+
+void LLRegionPresenceVerifier::VerifiedDestinationResponder::result(const LLSD& content)
+{
+	LLUUID actual_region_id = content["region_id"];
+	LLUUID expected_region_id = mContent["region_id"];
+
+	if (mSharedData->checkValidity(content))
+	{
+		mSharedData->onRegionVerified(mContent);
+	}
+	else if ((mSharedData->shouldRetry()) && (actual_region_id != expected_region_id)) // If the region is correct, then it means we've deliberately changed the data
+	{
+		LLSD headers;
+		headers["Cache-Control"] = "no-cache, max-age=0";
+		llinfos << "Requesting region information, get uncached for region " << mSharedData->getRegionUri() << llendl;
+		mSharedData->decrementRetries();
+		mSharedData->getHttpClient().get(mSharedData->getRegionUri(), new RegionResponder(mSharedData), headers);
+	}
+	else
+	{
+		llwarns << "Could not correctly look up region from region presence service. Region: " << mSharedData->getRegionUri() << llendl;
+	}
+}
diff --git a/indra/llmessage/llregionpresenceverifier.h b/indra/llmessage/llregionpresenceverifier.h
new file mode 100644
index 0000000000000000000000000000000000000000..a0f08f12fe87296942c8ff22d70090a23fbb91dd
--- /dev/null
+++ b/indra/llmessage/llregionpresenceverifier.h
@@ -0,0 +1,81 @@
+/** 
+ * @file 
+ * @brief 
+ *
+ * $LicenseInfo:firstyear=2008&license=internal$
+ * 
+ * Copyright (c) 2008, Linden Research, Inc.
+ * 
+ * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
+ * this source code is governed by the Linden Lab Source Code Disclosure
+ * Agreement ("Agreement") previously entered between you and Linden
+ * Lab. By accessing, using, copying, modifying or distributing this
+ * software, you acknowledge that you have been informed of your
+ * obligations under the Agreement and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+/* Macro Definitions */
+#ifndef LL_LLREGIONPRESENCEVERIFIER_H
+#define LL_LLREGIONPRESENCEVERIFIER_H
+
+#include "llhttpclient.h"
+#include <string>
+#include "llsd.h"
+#include <boost/shared_ptr.hpp>
+
+class LLHTTPClientInterface;
+
+class LLRegionPresenceVerifier
+{
+public:
+	class Response
+	{
+	public:
+		virtual ~Response() {}
+
+		virtual bool checkValidity(const LLSD& content) const = 0;
+		virtual void onRegionVerified(const LLSD& region_details) = 0;
+
+		virtual void decrementRetries() = 0;
+
+		virtual LLHTTPClientInterface& getHttpClient() = 0;
+		virtual std::string getRegionUri() const = 0;
+		virtual bool shouldRetry() const = 0;
+
+		virtual void onCompletedRegionRequest() {}
+	};
+
+	typedef boost::shared_ptr<Response> ResponsePtr;
+
+	class RegionResponder : public LLHTTPClient::Responder
+	{
+	public:
+		RegionResponder(ResponsePtr data);
+		virtual void result(const LLSD& content);
+		virtual void completed(
+			U32 status,
+			const std::string& reason,
+			const LLSD& content);
+
+	private:
+		ResponsePtr mSharedData;
+	};
+
+	class VerifiedDestinationResponder : public LLHTTPClient::Responder
+	{
+	public:
+		VerifiedDestinationResponder(ResponsePtr data, const LLSD& content);
+		virtual void result(const LLSD& content);
+	private:
+		ResponsePtr mSharedData;
+		LLSD mContent;
+	};
+};
+
+
+#endif //LL_LLREGIONPRESENCEVERIFIER_H
diff --git a/indra/llmessage/llsdmessagebuilder.cpp b/indra/llmessage/llsdmessagebuilder.cpp
index a62dd04560e4d50752651752515dc40a129191c2..21937f022f4edf042a6b3829e14919d782ba0d9c 100755
--- a/indra/llmessage/llsdmessagebuilder.cpp
+++ b/indra/llmessage/llsdmessagebuilder.cpp
@@ -268,10 +268,125 @@ void LLSDMessageBuilder::copyFromMessageData(const LLMsgData& data)
 		
 		for(; dit != dend; ++dit)
 		{
-			//const LLMsgVarData& mvci = *dit;
-
-			// TODO: Copy mvci data in to block:
-			// (*mCurrentBlock)[varname] = v;
+			const LLMsgVarData& mvci = *dit;
+			const char* varname = mvci.getName();
+
+			switch(mvci.getType())
+			{
+			case MVT_FIXED:
+				addBinaryData(varname, mvci.getData(), mvci.getSize());
+				break;
+
+			case MVT_VARIABLE:
+				{
+					const char end = ((const char*)mvci.getData())[mvci.getSize()-1]; // Ensure null terminated
+					if (mvci.getDataSize() == 1 && end == 0) 
+					{
+						addString(varname, (const char*)mvci.getData());
+					}
+					else
+					{
+						addBinaryData(varname, mvci.getData(), mvci.getSize());
+					}
+					break;
+				}
+
+			case MVT_U8:
+				addU8(varname, *(U8*)mvci.getData());
+				break;
+
+			case MVT_U16:
+				addU16(varname, *(U16*)mvci.getData());
+				break;
+
+			case MVT_U32:
+				addU32(varname, *(U32*)mvci.getData());
+				break;
+
+			case MVT_U64:
+				addU64(varname, *(U64*)mvci.getData());
+				break;
+
+			case MVT_S8:
+				addS8(varname, *(S8*)mvci.getData());
+				break;
+
+			case MVT_S16:
+				addS16(varname, *(S16*)mvci.getData());
+				break;
+
+			case MVT_S32:
+				addS32(varname, *(S32*)mvci.getData());
+				break;
+
+			// S64 not supported in LLSD so we just truncate it
+			case MVT_S64:
+				addS32(varname, *(S64*)mvci.getData());
+				break;
+
+			case MVT_F32:
+				addF32(varname, *(F32*)mvci.getData());
+				break;
+
+			case MVT_F64:
+				addF64(varname, *(F64*)mvci.getData());
+				break;
+
+			case MVT_LLVector3:
+				addVector3(varname, *(LLVector3*)mvci.getData());
+				break;
+
+			case MVT_LLVector3d:
+				addVector3d(varname, *(LLVector3d*)mvci.getData());
+				break;
+
+			case MVT_LLVector4:
+				addVector4(varname, *(LLVector4*)mvci.getData());
+				break;
+
+			case MVT_LLQuaternion:
+				{
+					LLVector3 v = *(LLVector3*)mvci.getData();
+					LLQuaternion q;
+					q.unpackFromVector3(v);
+					addQuat(varname, q);
+					break;
+				}
+
+			case MVT_LLUUID:
+				addUUID(varname, *(LLUUID*)mvci.getData());
+				break;	
+
+			case MVT_BOOL:
+				addBOOL(varname, *(BOOL*)mvci.getData());
+				break;
+
+			case MVT_IP_ADDR:
+				addIPAddr(varname, *(U32*)mvci.getData());
+				break;
+
+			case MVT_IP_PORT:
+				addIPPort(varname, *(U16*)mvci.getData());
+				break;
+
+			case MVT_U16Vec3:
+				//treated as an array of 6 bytes
+				addBinaryData(varname, mvci.getData(), 6);
+				break;
+
+			case MVT_U16Quat:
+				//treated as an array of 8 bytes
+				addBinaryData(varname, mvci.getData(), 8);
+				break;
+
+			case MVT_S16Array:
+				addBinaryData(varname, mvci.getData(), mvci.getSize());
+				break;
+
+			default:
+				llwarns << "Unknown type in conversion of message to LLSD" << llendl;
+				break;
+			}
 		}
 	}
 }
diff --git a/indra/llmessage/llstoredmessage.cpp b/indra/llmessage/llstoredmessage.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..615eff405d4e61d05da495fbc9855bc697f4e198
--- /dev/null
+++ b/indra/llmessage/llstoredmessage.cpp
@@ -0,0 +1,38 @@
+/** 
+ * @file 
+ * @brief 
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llstoredmessage.h"
+
+LLStoredMessage::LLStoredMessage(const std::string& name, const LLSD& message) : mMessage(message), mName(name)
+{
+}
+
diff --git a/indra/llmessage/llstoredmessage.h b/indra/llmessage/llstoredmessage.h
new file mode 100644
index 0000000000000000000000000000000000000000..e817f19bd2c68c8bf97a063f8e7b5b5b896474f7
--- /dev/null
+++ b/indra/llmessage/llstoredmessage.h
@@ -0,0 +1,58 @@
+/** 
+ * @file 
+ * @brief 
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_STOREDMESSAGE_H
+#define LL_STOREDMESSAGE_H
+
+#include "linden_common.h"
+#include "llsd.h"
+#include <boost/shared_ptr.hpp>
+#include <string>
+
+
+class LLMessageSystem;
+
+class LLStoredMessage
+{
+public:
+	LLStoredMessage(const std::string& name, const LLSD& message);
+private:
+	friend class LLMessageSystem;
+
+	LLSD mMessage;
+	std::string mName;
+};
+
+typedef boost::shared_ptr<LLStoredMessage> LLStoredMessagePtr;
+
+
+#endif // LL_STOREDMESSAGE_H
diff --git a/indra/llmessage/lltemplatemessagebuilder.cpp b/indra/llmessage/lltemplatemessagebuilder.cpp
index c153c813724683de68f96bb787310862d6db4878..e6419807fff85ba516446e987d90dc5002125802 100644
--- a/indra/llmessage/lltemplatemessagebuilder.cpp
+++ b/indra/llmessage/lltemplatemessagebuilder.cpp
@@ -41,7 +41,7 @@
 #include "v3math.h"
 #include "v4math.h"
 
-LLTemplateMessageBuilder::LLTemplateMessageBuilder(message_template_name_map_t& name_template_map) :
+LLTemplateMessageBuilder::LLTemplateMessageBuilder(const message_template_name_map_t& name_template_map) :
 	mCurrentSMessageData(NULL),
 	mCurrentSMessageTemplate(NULL),
 	mCurrentSDataBlock(NULL),
@@ -75,14 +75,14 @@ void LLTemplateMessageBuilder::newMessage(const char *name)
 	char* namep = (char*)name; 
 	if (mMessageTemplates.count(namep) > 0)
 	{
-		mCurrentSMessageTemplate = mMessageTemplates[namep];
+		mCurrentSMessageTemplate = mMessageTemplates.find(name)->second;
 		mCurrentSMessageData = new LLMsgData(namep);
 		mCurrentSMessageName = namep;
 		mCurrentSDataBlock = NULL;
 		mCurrentSBlockName = NULL;
 
 		// add at one of each block
-		const LLMessageTemplate* msg_template = mMessageTemplates[namep];
+		const LLMessageTemplate* msg_template = mMessageTemplates.find(name)->second;
 
 		if (msg_template->getDeprecation() != MD_NOTDEPRECATED)
 		{
diff --git a/indra/llmessage/lltemplatemessagebuilder.h b/indra/llmessage/lltemplatemessagebuilder.h
index bcdf722b1b220e7272a6e26e77fb91cf0dc93bbe..96e7ae1a86c4feef036b39b9f16af523c3e7a60c 100644
--- a/indra/llmessage/lltemplatemessagebuilder.h
+++ b/indra/llmessage/lltemplatemessagebuilder.h
@@ -49,7 +49,7 @@ class LLTemplateMessageBuilder : public LLMessageBuilder
 	
 	typedef std::map<const char* , LLMessageTemplate*> message_template_name_map_t;
 
-	LLTemplateMessageBuilder(message_template_name_map_t&);
+	LLTemplateMessageBuilder(const message_template_name_map_t&);
 	virtual ~LLTemplateMessageBuilder();
 
 	virtual void newMessage(const char* name);
@@ -99,6 +99,7 @@ class LLTemplateMessageBuilder : public LLMessageBuilder
 	virtual void copyFromMessageData(const LLMsgData& data);
 	virtual void copyFromLLSD(const LLSD&);
 
+	LLMsgData* getCurrentMessage() const { return mCurrentSMessageData; }
 private:
 	void addData(const char* varname, const void* data, 
 					 EMsgVariableType type, S32 size);
@@ -114,7 +115,7 @@ class LLTemplateMessageBuilder : public LLMessageBuilder
 	BOOL mbSBuilt;
 	BOOL mbSClear;
 	S32	 mCurrentSendTotal;
-	message_template_name_map_t& mMessageTemplates;
+	const message_template_name_map_t& mMessageTemplates;
 };
 
 #endif // LL_LLTEMPLATEMESSAGEBUILDER_H
diff --git a/indra/llmessage/lltemplatemessagedispatcher.cpp b/indra/llmessage/lltemplatemessagedispatcher.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3bbf3a058de61ef6949667f81fd8a7fc8e09e491
--- /dev/null
+++ b/indra/llmessage/lltemplatemessagedispatcher.cpp
@@ -0,0 +1,72 @@
+/**
+ * @file lltemplatemessagedispatcher.h
+ * @brief LLTemplateMessageDispatcher class
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#include "lltemplatemessagedispatcher.h"
+
+#include "llhttpnode.h"
+#include "llhost.h"
+#include "message.h"
+#include "llsd.h"
+#include "lltemplatemessagereader.h"
+
+
+LLTemplateMessageDispatcher::LLTemplateMessageDispatcher(LLTemplateMessageReader &template_message_reader) :
+	mTemplateMessageReader(template_message_reader)
+{
+}
+
+void LLTemplateMessageDispatcher::dispatch(const std::string& msg_name,
+										   const LLSD& message,
+										   LLHTTPNode::ResponsePtr responsep)
+{
+	std::vector<U8> data = message["body"]["binary-template-data"].asBinary();
+	U32 size = data.size();
+	if(size == 0)
+	{
+		return;
+	}
+
+	LLHost host;
+	host = gMessageSystem->getSender();
+
+	bool validate_message = mTemplateMessageReader.validateMessage(&(data[0]), data.size(), host, true);
+
+	if (validate_message)
+	{
+		mTemplateMessageReader.readMessage(&(data[0]),host);
+	} 
+	else 
+	{
+		gMessageSystem->clearReceiveState();
+	}
+}
+
diff --git a/indra/llmessage/lltemplatemessagedispatcher.h b/indra/llmessage/lltemplatemessagedispatcher.h
new file mode 100644
index 0000000000000000000000000000000000000000..b1e74f47bb56d8e7a9ec843769ffd757505d4105
--- /dev/null
+++ b/indra/llmessage/lltemplatemessagedispatcher.h
@@ -0,0 +1,53 @@
+/**
+ * @file lltemplatemessagedispatcher.h
+ * @brief LLTemplateMessageDispatcher class
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLTEMPLATEMESSAGEDISPATCHER_H
+#define LLTEMPLATEMESSAGEDISPATCHER_H
+
+#include "linden_common.h"
+#include "llsd.h"
+#include "llhttpnode.h"
+#include "lltemplatemessagereader.h"
+
+
+class LLTemplateMessageDispatcher
+{
+public:
+	LLTemplateMessageDispatcher(LLTemplateMessageReader& template_message_reader);
+	void dispatch(const std::string& msg_name,
+				  const LLSD& message,
+				  LLHTTPNode::ResponsePtr responsep);
+
+private:
+	LLTemplateMessageReader &mTemplateMessageReader;
+};
+
+#endif // LLTEMPLATEMESSAGEDISPATCHER_H
diff --git a/indra/llmessage/lltemplatemessagereader.cpp b/indra/llmessage/lltemplatemessagereader.cpp
index f64a096b3e9ef0dcf48b19aaac168fbb446aaa30..d635844ee5bb0748e2f76a773e88c1c4f6e0d9f9 100644
--- a/indra/llmessage/lltemplatemessagereader.cpp
+++ b/indra/llmessage/lltemplatemessagereader.cpp
@@ -755,18 +755,38 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender
 
 BOOL LLTemplateMessageReader::validateMessage(const U8* buffer, 
 											  S32 buffer_size, 
-											  const LLHost& sender)
+											  const LLHost& sender,
+											  bool trusted)
 {
 	mReceiveSize = buffer_size;
-	BOOL result = decodeTemplate(buffer, buffer_size, &mCurrentRMessageTemplate );
-	if(result)
+	BOOL valid = decodeTemplate(buffer, buffer_size, &mCurrentRMessageTemplate );
+	if(valid)
 	{
 		mCurrentRMessageTemplate->mReceiveCount++;
-		//lldebugs << "MessageRecvd:" 
+		//lldebugs << "MessageRecvd:"
 		//						 << mCurrentRMessageTemplate->mName 
 		//						 << " from " << sender << llendl;
 	}
-	return result;
+
+	if (valid && isBanned(trusted))
+	{
+		LL_WARNS("Messaging") << "LLMessageSystem::checkMessages "
+			<< "received banned message "
+			<< getMessageName()
+			<< " from "
+			<< ((trusted) ? "trusted " : "untrusted ")
+			<< sender << llendl;
+		valid = FALSE;
+	}
+
+	if(valid && isUdpBanned())
+	{
+		llwarns << "Received UDP black listed message "
+				<<  getMessageName()
+				<< " from " << sender << llendl;
+		valid = FALSE;
+	}
+	return valid;
 }
 
 BOOL LLTemplateMessageReader::readMessage(const U8* buffer, 
diff --git a/indra/llmessage/lltemplatemessagereader.h b/indra/llmessage/lltemplatemessagereader.h
index e1062de88f58c0d34dbde9eadfed1e9f46bfdb60..ab06ab433d592792d47ba683097b209916acc990 100644
--- a/indra/llmessage/lltemplatemessagereader.h
+++ b/indra/llmessage/lltemplatemessagereader.h
@@ -105,7 +105,7 @@ class LLTemplateMessageReader : public LLMessageReader
 	virtual void copyToBuilder(LLMessageBuilder&) const;
 
 	BOOL validateMessage(const U8* buffer, S32 buffer_size, 
-						 const LLHost& sender);
+						 const LLHost& sender, bool trusted = false);
 	BOOL readMessage(const U8* buffer, const LLHost& sender);
 
 	bool isTrusted() const;
diff --git a/indra/llmessage/lltrustedmessageservice.cpp b/indra/llmessage/lltrustedmessageservice.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c1a6c437a7f2bb2d97a158bbe73e743d924f3f2a
--- /dev/null
+++ b/indra/llmessage/lltrustedmessageservice.cpp
@@ -0,0 +1,89 @@
+/**
+ * @file lltrustedmessageservice.cpp
+ * @brief LLTrustedMessageService implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lltrustedmessageservice.h"
+#include "llhost.h"
+#include "llmessageconfig.h"
+#include "message.h"
+
+
+bool LLTrustedMessageService::validate(const std::string& name, LLSD& context)
+const
+{
+	return true;
+}
+
+void LLTrustedMessageService::post(LLHTTPNode::ResponsePtr response,
+								   const LLSD& context,
+								   const LLSD& input) const
+{
+	std::string name = context["request"]["wildcard"]["message-name"];
+	std::string senderIP = context["request"]["remote-host"];
+	std::string senderPort = context["request"]["headers"]
+		["x-secondlife-udp-listen-port"];
+
+	LLSD message_data;
+	std::string sender = senderIP + ":" + senderPort;
+	message_data["sender"] = sender;
+	message_data["body"] = input;
+	
+	// untrusted senders should not have access to the trusted message
+	// service, but this can happen in development, so check and warn
+	LLMessageConfig::SenderTrust trust =
+		LLMessageConfig::getSenderTrustedness(name);
+	if ((trust == LLMessageConfig::TRUSTED ||
+		 (trust == LLMessageConfig::NOT_SET &&
+		  gMessageSystem->isTrustedMessage(name)))
+		 && !gMessageSystem->isTrustedSender(LLHost(sender)))
+	{
+		LL_WARNS("Messaging") << "trusted message POST to /trusted-message/" 
+				<< name << " from unknown or untrusted sender "
+				<< sender << llendl;
+		response->status(403, "Unknown or untrusted sender");
+	}
+	else
+	{
+		gMessageSystem->receivedMessageFromTrustedSender();
+		if (input.has("binary-template-data"))
+		{
+			llinfos << "Dispatching template: " << input << llendl;
+			// try and send this message using udp dispatch
+			LLMessageSystem::dispatchTemplate(name, message_data, response);
+		}
+		else
+		{
+			llinfos << "Dispatching without template: " << input << llendl;
+			LLMessageSystem::dispatch(name, message_data, response);
+		}
+	}
+}
diff --git a/indra/llmessage/lltrustedmessageservice.h b/indra/llmessage/lltrustedmessageservice.h
new file mode 100644
index 0000000000000000000000000000000000000000..bc824565f1917dc216772fb9984e8278dd9070da
--- /dev/null
+++ b/indra/llmessage/lltrustedmessageservice.h
@@ -0,0 +1,51 @@
+/**
+ * @file lltrustedmessageservice.h
+ * @brief LLTrustedMessageService class
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLTRUSTEDMESSAGESERVICE_H
+#define LLTRUSTEDMESSAGESERVICE_H
+
+#include "linden_common.h"
+#include "llhttpnode.h"
+
+class LLSD;
+
+class LLTrustedMessageService
+{
+public:
+
+	bool validate(const std::string& name, LLSD& context) const;
+	
+	void post(LLHTTPNode::ResponsePtr response,
+			  const LLSD& context,
+			  const LLSD& input) const;
+};
+
+#endif // LLTRUSTEDMESSAGESERVICE_H
diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp
index 4e6cda2880658e0e9fa4a3d8a154e62fe92c33b6..8ab12ce991939db4819d0a4442e4406f17bd4cf8 100644
--- a/indra/llmessage/message.cpp
+++ b/indra/llmessage/message.cpp
@@ -59,13 +59,16 @@
 #include "llerrorlegacy.h"
 #include "llfasttimer.h"
 #include "llhttpclient.h"
+#include "llhttpnodeadapter.h"
 #include "llhttpsender.h"
 #include "llmd5.h"
 #include "llmessagebuilder.h"
 #include "llmessageconfig.h"
+#include "lltemplatemessagedispatcher.h"
 #include "llpumpio.h"
 #include "lltemplatemessagebuilder.h"
 #include "lltemplatemessagereader.h"
+#include "lltrustedmessageservice.h"
 #include "llmessagetemplate.h"
 #include "llmessagetemplateparser.h"
 #include "llsd.h"
@@ -142,52 +145,6 @@ namespace
 	};
 }
 
-
-class LLTrustedMessageService : public LLHTTPNode
-{
-	virtual bool validate(const std::string& name, LLSD& context) const
-		{ return true; }
-
-	virtual void post(LLHTTPNode::ResponsePtr response,
-					  const LLSD& context,
-					  const LLSD& input) const;
-};
-
-//virtual
-void LLTrustedMessageService::post(LLHTTPNode::ResponsePtr response,
-								   const LLSD& context,
-								   const LLSD& input) const
-{
-	std::string name = context["request"]["wildcard"]["message-name"];
-	std::string senderIP = context["request"]["remote-host"];
-	std::string senderPort = context["request"]["headers"]
-		["x-secondlife-udp-listen-port"];
-
-	LLSD message_data;
-	std::string sender = senderIP + ":" + senderPort;
-	message_data["sender"] = sender;
-	message_data["body"] = input;
-	
-	// untrusted senders should not have access to the trusted message
-	// service, but this can happen in development, so check and warn
-	LLMessageConfig::SenderTrust trust =
-		LLMessageConfig::getSenderTrustedness(name);
-	if ((trust == LLMessageConfig::TRUSTED ||
-		 (trust == LLMessageConfig::NOT_SET &&
-		  gMessageSystem->isTrustedMessage(name)))
-		 && !gMessageSystem->isTrustedSender(LLHost(sender)))
-	{
-		LL_WARNS("Messaging") << "trusted message POST to /trusted-message/" 
-				<< name << " from unknown or untrusted sender "
-				<< sender << llendl;
-		response->status(403, "Unknown or untrusted sender");
-	}
-	else
-	{
-		LLMessageSystem::dispatch(name, message_data, response);
-	}
-}
-
 class LLMessageHandlerBridge : public LLHTTPNode
 {
 	virtual bool validate(const std::string& name, LLSD& context) const
@@ -223,9 +180,6 @@ void LLMessageHandlerBridge::post(LLHTTPNode::ResponsePtr response,
 LLHTTPRegistration<LLMessageHandlerBridge>
 	gHTTPRegistrationMessageWildcard("/message/<message-name>");
 
-LLHTTPRegistration<LLTrustedMessageService>
-	gHTTPRegistrationTrustedMessageWildcard("/trusted-message/<message-name>");
-
 //virtual
 LLUseCircuitCodeResponder::~LLUseCircuitCodeResponder()
 {
@@ -293,7 +247,8 @@ LLMessageSystem::LLMessageSystem(const std::string& filename, U32 port,
 								 S32 version_patch,
 								 bool failure_is_fatal,
 								 const F32 circuit_heartbeat_interval, const F32 circuit_timeout) :
-	mCircuitInfo(circuit_heartbeat_interval, circuit_timeout)
+	mCircuitInfo(circuit_heartbeat_interval, circuit_timeout),
+	mLastMessageFromTrustedMessageService(false)
 {
 	init();
 
@@ -445,6 +400,7 @@ void LLMessageSystem::clearReceiveState()
 	mLastSender.invalidate();
 	mLastReceivingIF.invalidate();
 	mMessageReader->clearMessage();
+	mLastMessageFromTrustedMessageService = false;
 }
 
 
@@ -477,6 +433,17 @@ bool LLMessageSystem::isTrustedSender(const LLHost& host) const
 	return cdp->getTrusted();
 }
 
+void LLMessageSystem::receivedMessageFromTrustedSender()
+{
+	mLastMessageFromTrustedMessageService = true;
+}
+
+bool LLMessageSystem::isTrustedSender() const
+{	
+	return mLastMessageFromTrustedMessageService ||
+		isTrustedSender(getSender());
+}
+
 static LLMessageSystem::message_template_name_map_t::const_iterator 
 findTemplate(const LLMessageSystem::message_template_name_map_t& templates, 
 			 std::string name)
@@ -717,11 +684,16 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
 			// UseCircuitCode can be a valid, off-circuit packet.
 			// But we don't want to acknowledge UseCircuitCode until the circuit is
 			// available, which is why the acknowledgement test is done above.  JC
-
+			bool trusted = cdp && cdp->getTrusted();
 			valid_packet = mTemplateMessageReader->validateMessage(
 				buffer,
 				receive_size,
-				host);
+				host,
+				trusted);
+			if (!valid_packet)
+			{
+				clearReceiveState();
+			}
 
 			// UseCircuitCode is allowed in even from an invalid circuit, so that
 			// we can toss circuits around.
@@ -749,29 +721,6 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
 				valid_packet = FALSE;
 			}
 
-			if (
-				valid_packet &&
-				mTemplateMessageReader->isBanned(cdp && cdp->getTrusted()))
-			{
-				LL_WARNS("Messaging") << "LLMessageSystem::checkMessages "
-					<< "received banned message "
-					<< mTemplateMessageReader->getMessageName()
-					<< " from "
-					<< ((cdp && cdp->getTrusted()) ? "trusted " : "untrusted ")
-					<< host << llendl;
-				clearReceiveState();
-				valid_packet = FALSE;
-			}
-
-			if( valid_packet && mTemplateMessageReader->isUdpBanned())
-			{
-				llwarns << "Received UDP black listed message "
-						<<  mTemplateMessageReader->getMessageName()
-						<< " from " << host << llendl;
-				clearReceiveState();
-				valid_packet = FALSE;
-			}
-
 			if( valid_packet )
 			{
 				logValidMsg(cdp, host, recv_reliable, recv_resent, (BOOL)(acks>0) );
@@ -784,94 +733,6 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
 
 			if (valid_packet)
 			{
-				// enable this for output of message names
-				//LL_INFOS("Messaging") << "< \"" << mTemplateMessageReader->getMessageName()
-						//<< "\"" << llendl;
-
-				/* Code for dumping the complete contents of a message.  Keep for future use in optimizing messages.
-				if( 1 )
-				{
-					static char* object_update = LLMessageStringTable::getInstance()->getString("ObjectUpdate");
-					if(object_update == mTemplateMessageReader->getMessageName() )
-					{
-						LL_INFOS("Messaging") << "ObjectUpdate:" << llendl;
-						U32 i;
-						LL_INFOS("Messaging") << "    Zero Encoded: " << zero_unexpanded_size << llendl;
-						for( i = 0; i<zero_unexpanded_size; i++ )
-						{
-							LL_INFOS("Messaging") << "     " << i << ": " << (U32) zero_unexpanded_buffer[i] << llendl;
-						}
-						LL_INFOS("Messaging") << "" << llendl;
-
-						LL_INFOS("Messaging") << "    Zero Unencoded: " << receive_size << llendl;
-						for( i = 0; i<receive_size; i++ )
-						{
-							LL_INFOS("Messaging") << "     " << i << ": " << (U32) buffer[i] << llendl;
-						}
-						LL_INFOS("Messaging") << "" << llendl;
-
-						LL_INFOS("Messaging") << "    Blocks and variables: " << llendl;
-						S32 byte_count = 0;
-						for (LLMessageTemplate::message_block_map_t::iterator
-								 iter = mCurrentRMessageTemplate->mMemberBlocks.begin(),
-								 end = mCurrentRMessageTemplate->mMemberBlocks.end();
-							 iter != end; iter++)
-						{
-							LLMessageBlock* block = iter->second;
-							const char* block_name = block->mName;
-							for (LLMsgBlkData::msg_var_data_map_t::iterator
-									 iter = block->mMemberVariables.begin(),
-									 end = block->mMemberVariables.end();
-								 iter != end; iter++)
-							{
-								const char* var_name = iter->first;
-								
-								if( getNumberOfBlocksFast( block_name ) < 1 )
-								{
-									LL_INFOS("Messaging") << var_name << " has no blocks" << llendl;
-								}
-								for( S32 blocknum = 0; blocknum < getNumberOfBlocksFast( block_name ); blocknum++ )
-								{
-									char *bnamep = (char *)block_name + blocknum; // this works because it's just a hash.  The bnamep is never derefference
-									char *vnamep = (char *)var_name; 
-
-									LLMsgBlkData *msg_block_data = mCurrentRMessageData->mMemberBlocks[bnamep];
-
-									if (!msg_block_data)
-									{
-										std::string errmsg = llformat("Block %s #%d not in message %s", block_name, blocknum, mCurrentRMessageData->mName);
-										LL_ERRS("Messaging") << errmsg << llendl;
-									}
-
-									LLMsgVarData vardata = msg_block_data->mMemberVarData[vnamep];
-
-									if (!vardata.getName())
-									{
-										std::string errmsg = llformat("Variable %s not in message %s block %s", vnamep, mCurrentRMessageData->mName, bnamep);
-										LL_ERRS("Messaging") << errmsg << llendl;
-									}
-
-									const S32 vardata_size = vardata.getSize();
-									if( vardata_size )
-									{
-										for( i = 0; i < vardata_size; i++ )
-										{
-											byte_count++;
-											LL_INFOS("Messaging") << block_name << " " << var_name << " [" << blocknum << "][" << i << "]= " << (U32)(((U8*)vardata.getData())[i]) << llendl;
-										}
-									}
-									else
-									{
-										LL_INFOS("Messaging") << block_name << " " << var_name << " [" << blocknum << "] 0 bytes" << llendl;
-									}
-								}
-							}
-						}
-						LL_INFOS("Messaging") << "Byte count =" << byte_count << llendl;
-					}
-				}
-				*/
-
 				mPacketsIn++;
 				mBytesIn += mTrueReceiveSize;
 				
@@ -899,9 +760,6 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
 					mInvalidOnCircuitPackets++;
 				}
 			}
-
-			// Code for dumping the complete contents of a message 
-			// delete [] zero_unexpanded_buffer;
 		}
 	} while (!valid_packet && receive_size > 0);
 
@@ -1004,7 +862,7 @@ void LLMessageSystem::processAcks()
 	}
 }
 
-void LLMessageSystem::copyMessageRtoS()
+void LLMessageSystem::copyMessageReceivedToSend()
 {
 	// NOTE: babbage: switch builder to match reader to avoid
 	// converting message format
@@ -1021,6 +879,72 @@ void LLMessageSystem::copyMessageRtoS()
 	mMessageReader->copyToBuilder(*mMessageBuilder);
 }
 
+LLSD LLMessageSystem::getReceivedMessageLLSD() const
+{
+	LLSDMessageBuilder builder;
+	mMessageReader->copyToBuilder(builder);
+	return builder.getMessage();
+}
+
+LLSD LLMessageSystem::getBuiltMessageLLSD() const 
+{
+	LLSD result;
+	if (mLLSDMessageBuilder == mMessageBuilder)
+	{
+		 result = mLLSDMessageBuilder->getMessage();
+	}
+	else
+	{
+		// TODO: implement as below?
+		llerrs << "Message not built as LLSD." << llendl; 
+	}
+	return result;
+}
+
+LLSD LLMessageSystem::wrapReceivedTemplateData() const
+{
+	if(mMessageReader == mTemplateMessageReader)
+	{
+		LLTemplateMessageBuilder builder(mMessageTemplates);
+		builder.newMessage(mMessageReader->getMessageName());
+		mMessageReader->copyToBuilder(builder);
+		U8 buffer[MAX_BUFFER_SIZE];
+		const U8 offset_to_data = 0;
+		U32 size = builder.buildMessage(buffer, MAX_BUFFER_SIZE,
+										offset_to_data);
+		std::vector<U8> binary_data(buffer, buffer+size);
+		LLSD wrapped_data = LLSD::emptyMap();
+		wrapped_data["binary-template-data"] = binary_data;
+		return wrapped_data;
+	}
+	else
+	{
+		return getReceivedMessageLLSD();
+	}
+}
+
+LLStoredMessagePtr LLMessageSystem::getReceivedMessage() const
+{
+	const std::string& name = mMessageReader->getMessageName();
+	LLSD message = wrapReceivedTemplateData();
+
+	return LLStoredMessagePtr(new LLStoredMessage(name, message));
+}
+
+LLStoredMessagePtr LLMessageSystem::getBuiltMessage() const
+{
+	const std::string& name = mMessageBuilder->getMessageName();
+	LLSD message = getBuiltMessageLLSD();
+
+	return LLStoredMessagePtr(new LLStoredMessage(name, message));
+}
+
+S32 LLMessageSystem::sendMessage(const LLHost &host, LLStoredMessagePtr message)
+{
+	return sendMessage(host, message->mName.c_str(), message->mMessage);
+}
+
+
 void LLMessageSystem::clearMessage()
 {
 	mSendReliable = FALSE;
@@ -1033,6 +957,11 @@ void LLMessageSystem::nextBlockFast(const char *blockname)
 	mMessageBuilder->nextBlock(blockname);
 }
 
+void LLMessageSystem::nextBlock(const char *blockname)
+{
+	nextBlockFast(LLMessageStringTable::getInstance()->getString(blockname));
+}
+
 BOOL LLMessageSystem::isSendFull(const char* blockname)
 {
 	char* stringTableName = NULL;
@@ -1112,19 +1041,19 @@ S32 LLMessageSystem::sendReliable(	const LLHost &host,
 
 void LLMessageSystem::forwardMessage(const LLHost &host)
 {
-	copyMessageRtoS();
+	copyMessageReceivedToSend();
 	sendMessage(host);
 }
 
 void LLMessageSystem::forwardReliable(const LLHost &host)
 {
-	copyMessageRtoS();
+	copyMessageReceivedToSend();
 	sendReliable(host);
 }
 
 void LLMessageSystem::forwardReliable(const U32 circuit_code)
 {
-	copyMessageRtoS();
+	copyMessageReceivedToSend();
 	sendReliable(findHost(circuit_code));
 }
 
@@ -1135,7 +1064,7 @@ S32 LLMessageSystem::forwardReliable(	const LLHost &host,
 										void (*callback)(void **,S32), 
 										void ** callback_data)
 {
-	copyMessageRtoS();
+	copyMessageReceivedToSend();
 	return sendReliable(host, retries, ping_based_timeout, timeout, callback, callback_data);
 }
 
@@ -1463,13 +1392,6 @@ S32 LLMessageSystem::sendMessage(
 		LL_WARNS("Messaging") << "trying to send message to invalid host"	<< llendl;
 		return 0;
 	}
-	newMessage(name);	
-	if (mMessageBuilder != mLLSDMessageBuilder)
-	{
-		LL_WARNS("Messaging") << "trying to send llsd message when builder is not LLSD!"
-				<< llendl;
-		return 0;
-	}
 
 	const LLHTTPSender& sender = LLHTTPSender::getSender(host);
 	sender.send(host, name, message, createResponder(name));
@@ -2178,6 +2100,15 @@ void LLMessageSystem::dispatch(
 	handler->post(responsep, context, message);
 }
 
+//static 
+void LLMessageSystem::dispatchTemplate(const std::string& msg_name,
+										const LLSD& message,
+										LLHTTPNode::ResponsePtr responsep)
+{
+	LLTemplateMessageDispatcher dispatcher(*(gMessageSystem->mTemplateMessageReader));
+	dispatcher.dispatch(msg_name, message, responsep);
+}
+
 static void check_for_unrecognized_messages(
 		const char* type,
 		const LLSD& map,
@@ -2730,7 +2661,7 @@ void LLMessageSystem::summarizeLogs(std::ostream& str)
 	str << "END MESSAGE LOG SUMMARY" << std::endl;
 }
 
-void end_messaging_system()
+void end_messaging_system(bool print_summary)
 {
 	gTransferManager.cleanup();
 	LLTransferTargetVFile::updateQueue(true); // shutdown LLTransferTargetVFile
@@ -2738,9 +2669,12 @@ void end_messaging_system()
 	{
 		gMessageSystem->stopLogging();
 
-		std::ostringstream str;
-		gMessageSystem->summarizeLogs(str);
-		LL_INFOS("Messaging") << str.str().c_str() << llendl;
+		if (print_summary)
+		{
+			std::ostringstream str;
+			gMessageSystem->summarizeLogs(str);
+			LL_INFOS("Messaging") << str.str().c_str() << llendl;
+		}
 
 		delete gMessageSystem;
 		gMessageSystem = NULL;
@@ -4088,3 +4022,11 @@ void LLMessageSystem::banUdpMessage(const std::string& name)
 		llwarns << "Attempted to ban an unknown message: " << name << "." << llendl;
 	}
 }
+const LLHost& LLMessageSystem::getSender() const
+{
+	return mLastSender;
+}
+
+LLHTTPRegistration<LLHTTPNodeAdapter<LLTrustedMessageService> >
+	gHTTPRegistrationTrustedMessageWildcard("/trusted-message/<message-name>");
+
diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h
index 25eeb853239c7ba5f7ddc94741fc52d95c5649c5..4fda8f01d7c15da1e820315423e7058d8722359e 100644
--- a/indra/llmessage/message.h
+++ b/indra/llmessage/message.h
@@ -63,6 +63,9 @@
 #include "llstl.h"
 #include "llmsgvariabletype.h"
 #include "llmsgvariabletype.h"
+#include "llmessagesenderinterface.h"
+
+#include "llstoredmessage.h"
 
 const U32 MESSAGE_MAX_STRINGS_LENGTH = 64;
 const U32 MESSAGE_NUMBER_OF_HASH_BUCKETS = 8192;
@@ -206,7 +209,7 @@ class LLUseCircuitCodeResponder
 	virtual void complete(const LLHost& host, const LLUUID& agent) const = 0;
 };
 
-class LLMessageSystem
+class LLMessageSystem : public LLMessageSenderInterface
 {
  private:
 	U8					mSendBuffer[MAX_BUFFER_SIZE];
@@ -373,14 +376,33 @@ class LLMessageSystem
 	void newMessageFast(const char *name);
 	void newMessage(const char *name);
 
-	void	copyMessageRtoS();
-	void	clearMessage();
+
+public:
+	LLStoredMessagePtr getReceivedMessage() const; 
+	LLStoredMessagePtr getBuiltMessage() const;
+	S32 sendMessage(const LLHost &host, LLStoredMessagePtr message);
+
+private:
+	LLSD getReceivedMessageLLSD() const;
+	LLSD getBuiltMessageLLSD() const;
+
+	// NOTE: babbage: Only use to support legacy misuse of the
+	// LLMessageSystem API where values are dangerously written
+	// as one type and read as another. LLSD does not support
+	// dangerous conversions and so converting the message to an
+	// LLSD would result in the reads failing. All code which
+	// misuses the message system in this way should be made safe
+	// but while the unsafe code is run in old processes, this
+	// method should be used to forward unsafe messages.
+	LLSD wrapReceivedTemplateData() const;
+
+public:
+
+	void copyMessageReceivedToSend();
+	void clearMessage();
 
 	void nextBlockFast(const char *blockname);
-	void	nextBlock(const char *blockname)
-	{
-		nextBlockFast(LLMessageStringTable::getInstance()->getString(blockname));
-	}
+	void nextBlock(const char *blockname);
 
 public:
 	void addBinaryDataFast(const char *varname, const void *data, S32 size);
@@ -461,14 +483,14 @@ class LLMessageSystem
 							void (*callback)(void **,S32), void ** callback_data);
 
 	// flush sends a message only if data's been pushed on it.
-	S32		flushSemiReliable(	const LLHost &host, 
+	S32	 flushSemiReliable(	const LLHost &host, 
 								void (*callback)(void **,S32), void ** callback_data);
 
-	S32		flushReliable(	const LLHost &host );
+	S32	flushReliable(	const LLHost &host );
 
-	void    forwardMessage(const LLHost &host);
-	void    forwardReliable(const LLHost &host);
-	void    forwardReliable(const U32 circuit_code);
+	void forwardMessage(const LLHost &host);
+	void forwardReliable(const LLHost &host);
+	void forwardReliable(const U32 circuit_code);
 	S32 forwardReliable(
 		const LLHost &host, 
 		S32 retries, 
@@ -480,9 +502,10 @@ class LLMessageSystem
 	LLHTTPClient::ResponderPtr createResponder(const std::string& name);
 	S32		sendMessage(const LLHost &host);
 	S32		sendMessage(const U32 circuit);
+private:
 	S32		sendMessage(const LLHost &host, const char* name,
 						const LLSD& message);
-
+public:
 	// 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);
@@ -561,8 +584,12 @@ class LLMessageSystem
 	void	sendDenyTrustedCircuit(const LLHost &host);
 
 	/** Return false if host is unknown or untrusted */
+	// Note:DaveH/Babbage some trusted messages can be received without a circuit
 	bool isTrustedSender(const LLHost& host) const;
 
+	/** Return true if current message is from trusted source */
+	bool isTrustedSender() const;
+
 	/** Return false true if name is unknown or untrusted */
 	bool isTrustedMessage(const std::string& name) const;
 
@@ -578,6 +605,7 @@ class LLMessageSystem
 	// Change this message to be UDP black listed.
 	void banUdpMessage(const std::string& name);
 
+
 private:
 	// A list of the circuits that need to be sent DenyTrustedCircuit messages.
 	typedef std::set<LLHost> host_set_t;
@@ -594,6 +622,7 @@ class LLMessageSystem
 	void	establishBidirectionalTrust(const LLHost &host, S64 frame_count = 0);
 
 	// returns whether the given host is on a trusted circuit
+	// Note:DaveH/Babbage some trusted messages can be received without a circuit
 	BOOL    getCircuitTrust(const LLHost &host);
 	
 	void	setCircuitAllowTimeout(const LLHost &host, BOOL allow);
@@ -663,6 +692,12 @@ class LLMessageSystem
 						 const LLSD& message,
 						 LLHTTPNode::ResponsePtr responsep);
 
+	// this is added to support specific legacy messages and is
+	// ***not intended for general use*** Si, Gabriel, 2009
+	static void dispatchTemplate(const std::string& msg_name,
+						 const LLSD& message,
+						 LLHTTPNode::ResponsePtr responsep);
+
 	void setMessageBans(const LLSD& trusted, const LLSD& untrusted);
 
 	/**
@@ -690,9 +725,18 @@ class LLMessageSystem
 
 	// Check UDP messages and pump http_pump to receive HTTP messages.
 	bool checkAllMessages(S64 frame_count, LLPumpIO* http_pump);
+
+	// Moved to allow access from LLTemplateMessageDispatcher
+	void clearReceiveState();
+
+	// This will cause all trust queries to return true until the next message
+	// is read: use with caution!
+	void receivedMessageFromTrustedSender();
 	
 private:
 
+	bool mLastMessageFromTrustedMessageService;
+	
 	// The mCircuitCodes is a map from circuit codes to session
 	// ids. This allows us to verify sessions on connect.
 	typedef std::map<U32, LLUUID> code_session_map_t;
@@ -703,7 +747,6 @@ class LLMessageSystem
 	LLUUID mSessionID;
 	
 	void	addTemplate(LLMessageTemplate *templatep);
-	void		clearReceiveState();
 	BOOL		decodeTemplate( const U8* buffer, S32 buffer_size, LLMessageTemplate** msg_template );
 
 	void		logMsgFromInvalidCircuit( const LLHost& sender, BOOL recv_reliable );
@@ -799,7 +842,7 @@ bool start_messaging_system(
 	const F32 circuit_heartbeat_interval, 
 	const F32 circuit_timeout);
 
-void end_messaging_system();
+void end_messaging_system(bool print_summary = true);
 
 void null_message_callback(LLMessageSystem *msg, void **data);
 
@@ -976,8 +1019,6 @@ inline void *ntohmemcpy(void *s, const void *ct, EMsgVariableType type, size_t n
 	return(htonmemcpy(s,ct,type, n));
 }
 
-
-inline const LLHost& LLMessageSystem::getSender() const {return mLastSender;}
 inline const LLHost& LLMessageSystem::getReceivingInterface() const {return mLastReceivingIF;}
 
 inline U32 LLMessageSystem::getSenderIP() const 
diff --git a/indra/llmessage/net.cpp b/indra/llmessage/net.cpp
index 8cbd9f63f1e3231ce778d8ad81ba65f599d15860..f63faa511ad683d5e91741fe20cefad25c26486c 100644
--- a/indra/llmessage/net.cpp
+++ b/indra/llmessage/net.cpp
@@ -51,7 +51,6 @@
 #endif
 
 // linden library includes
-#include "network.h"
 #include "llerror.h"
 #include "llhost.h"
 #include "lltimer.h"
@@ -395,11 +394,30 @@ S32 start_net(S32& socket_out, int& nPort)
 		return 1;
 	}
 
-	// Don't bind() if we want the operating system to assign our ports for 
-	// us.
 	if (NET_USE_OS_ASSIGNED_PORT == nPort)
 	{
-		// Do nothing; the operating system will do it for us.
+		// Although bind is not required it will tell us which port we were
+		// assigned to.
+		stLclAddr.sin_family      = AF_INET;
+		stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+		stLclAddr.sin_port        = htons(0);
+		llinfos << "attempting to connect on OS assigned port" << llendl;
+		nRet = bind(hSocket, (struct sockaddr*) &stLclAddr, sizeof(stLclAddr));
+		if (nRet < 0)
+		{
+			llwarns << "Failed to bind on an OS assigned port error: "
+					<< nRet << llendl;
+		}
+		else
+		{
+			sockaddr_in socket_info;
+			socklen_t len = sizeof(sockaddr_in);
+			int err = getsockname(hSocket, (sockaddr*)&socket_info, &len);
+			llinfos << "Get socket returned: " << err << " length " << len << llendl;
+			nPort = ntohs(socket_info.sin_port);
+			llinfos << "Assigned port: " << nPort << llendl;
+			
+		}
 	}
 	else
 	{
diff --git a/indra/llmessage/tests/llcurl_stub.cpp b/indra/llmessage/tests/llcurl_stub.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9d1d3fa2218e58d1a909f8286107652dabd86d0d
--- /dev/null
+++ b/indra/llmessage/tests/llcurl_stub.cpp
@@ -0,0 +1,88 @@
+/**
+ * @file llcurl_stub.cpp
+ * @brief stub class to allow unit testing
+ *
+ * $LicenseInfo:firstyear=2008&license=internal$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
+ * this source code is governed by the Linden Lab Source Code Disclosure
+ * Agreement ("Agreement") { }
+ * Lab. By accessing, using, copying, modifying or distributing this
+ * software, you acknowledge that you have been informed of your
+ * obligations under the Agreement and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+LLCurl::Responder::Responder()
+{
+}
+
+void LLCurl::Responder::completed(U32 status, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const &reason,
+								  LLSD const& mContent)
+{
+	if (isGoodStatus(status))
+	{
+		result(mContent);
+	}
+	else
+	{
+		error(status, reason, mContent);
+	}
+}
+
+void LLCurl::Responder::completedHeader(unsigned,
+										std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&,
+										LLSD const&)
+{
+}
+
+void LLCurl::Responder::completedRaw(unsigned,
+									 std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&,
+									 LLChannelDescriptors const&,
+									 boost::shared_ptr<LLBufferArray> const&)
+{
+}
+
+void LLCurl::Responder::error(unsigned,
+							  std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&,
+							  LLSD const&)
+{
+}
+
+LLCurl::Responder::~Responder ()
+{
+}
+
+void LLCurl::Responder::error(unsigned,
+							  std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
+{
+}
+
+void LLCurl::Responder::result(LLSD const&)
+{
+}
+
+namespace boost
+{
+	void intrusive_ptr_add_ref(LLCurl::Responder* p)
+	{
+		++p->mReferenceCount;
+	}
+
+	void intrusive_ptr_release(LLCurl::Responder* p)
+	{
+		if(p && 0 == --p->mReferenceCount)
+		{
+			delete p;
+		}
+	}
+};
+
diff --git a/indra/llmessage/tests/llhttpclientadapter_test.cpp b/indra/llmessage/tests/llhttpclientadapter_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bde76db08b04018f92ec99b7d039aab2892c0b79
--- /dev/null
+++ b/indra/llmessage/tests/llhttpclientadapter_test.cpp
@@ -0,0 +1,169 @@
+/** 
+ * @file 
+ * @brief 
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2008, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llhttpclientadapter.h"
+
+#include "../test/lltut.h"
+#include "llhttpclient.h"
+#include "llcurl_stub.cpp"
+
+float const HTTP_REQUEST_EXPIRY_SECS = 1.0F;
+
+std::vector<std::string> get_urls;
+std::vector<boost::intrusive_ptr<LLCurl::Responder> > get_responders;
+void LLHTTPClient::get(const std::string& url, boost::intrusive_ptr<LLCurl::Responder> responder, const LLSD& headers, const F32 timeout)
+{
+	get_urls.push_back(url);
+	get_responders.push_back(responder);
+}
+
+std::vector<std::string> put_urls;
+std::vector<LLSD> put_body;
+std::vector<boost::intrusive_ptr<LLCurl::Responder> > put_responders;
+
+void LLHTTPClient::put(std::string const &url, LLSD const &body, boost::intrusive_ptr<LLCurl::Responder> responder,float) 
+{
+	put_urls.push_back(url);
+	put_responders.push_back(responder);
+	put_body.push_back(body);
+
+}
+
+
+namespace tut
+{
+	struct LLHTTPClientAdapterData
+	{
+		LLHTTPClientAdapterData()
+		{
+			get_urls.clear();
+			get_responders.clear();
+			put_urls.clear();
+			put_responders.clear();
+			put_body.clear();
+		}
+	};
+
+	typedef test_group<LLHTTPClientAdapterData> factory;
+	typedef factory::object object;
+}
+
+namespace
+{
+	tut::factory tf("LLHTTPClientAdapterData test");
+}
+
+namespace tut
+{
+	// Ensure we can create the object
+	template<> template<>
+	void object::test<1>()
+	{
+		LLHTTPClientAdapter adapter;
+	}
+
+	// Does the get pass the appropriate arguments to the LLHTTPClient
+	template<> template<>
+	void object::test<2>()
+	{
+		LLHTTPClientAdapter adapter;
+
+		boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder();
+
+		adapter.get("Made up URL", responder);
+		ensure_equals(get_urls.size(), 1);
+		ensure_equals(get_urls[0], "Made up URL");
+	}
+
+	// Ensure the responder matches the one passed to get
+	template<> template<>
+	void object::test<3>()
+	{
+		LLHTTPClientAdapter adapter;
+		boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder();
+
+		adapter.get("Made up URL", responder);
+
+		ensure_equals(get_responders.size(), 1);
+		ensure_equals(get_responders[0].get(), responder.get());
+	}
+	
+	// Ensure the correct url is used in the put
+	template<> template<>
+	void object::test<4>()
+	{
+		LLHTTPClientAdapter adapter;
+
+		boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder();
+
+		LLSD body;
+		body["TestBody"] = "Foobar";
+
+		adapter.put("Made up URL", body, responder);
+		ensure_equals(put_urls.size(), 1);
+		ensure_equals(put_urls[0], "Made up URL");
+	}
+
+	// Ensure the correct responder is used by put
+	template<> template<>
+	void object::test<5>()
+	{
+		LLHTTPClientAdapter adapter;
+
+		boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder();
+
+		LLSD body;
+		body["TestBody"] = "Foobar";
+
+		adapter.put("Made up URL", body, responder);
+
+		ensure_equals(put_responders.size(), 1);
+		ensure_equals(put_responders[0].get(), responder.get());
+	}
+
+	// Ensure the message body is passed through the put properly
+	template<> template<>
+	void object::test<6>()
+	{
+		LLHTTPClientAdapter adapter;
+
+		boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder();
+
+		LLSD body;
+		body["TestBody"] = "Foobar";
+
+		adapter.put("Made up URL", body, responder);
+
+		ensure_equals(put_body.size(), 1);
+		ensure_equals(put_body[0]["TestBody"].asString(), "Foobar");
+	}
+}
+
diff --git a/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp b/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a6f5659352a5169fe43607bdb2294e85a1290c13
--- /dev/null
+++ b/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp
@@ -0,0 +1,164 @@
+/**
+ * @file lltrustedmessageservice_test.cpp
+ * @brief LLTrustedMessageService unit tests
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "lltemplatemessagedispatcher.h"
+#include "lltut.h"
+
+#include "llhttpnode.h"
+#include "llhost.h"
+#include "message.h"
+#include "llsd.h"
+
+#include "llhost.cpp" // Needed for copy operator
+#include "net.cpp" // Needed by LLHost.
+
+LLMessageSystem * gMessageSystem = NULL;
+
+// sensor test doubles
+bool gClearRecvWasCalled = false;
+void LLMessageSystem::clearReceiveState(void) 
+{ 
+	gClearRecvWasCalled = true; 
+}
+
+char gUdpDispatchedData[MAX_BUFFER_SIZE];
+bool gUdpDispatchWasCalled = false;
+BOOL LLTemplateMessageReader::readMessage(const U8* data,class LLHost const &) 
+{ 
+	gUdpDispatchWasCalled = true;
+	strcpy(gUdpDispatchedData, reinterpret_cast<const char*>(data));
+	return  true;
+}
+
+BOOL gValidateMessage = FALSE;
+BOOL LLTemplateMessageReader::validateMessage(const U8*, S32 buffer_size, LLHost const &sender, bool trusted) 
+{ 
+	return gValidateMessage;
+}
+
+LLHost host;
+const LLHost& LLMessageSystem::getSender() const 
+{ 
+	return host; 
+}
+
+const char* gBinaryTemplateData = "BINARYTEMPLATEDATA";
+void fillVector(std::vector<U8>& vector_data, const char* data)
+{
+	vector_data.resize(strlen(data) + 1);
+	strcpy(reinterpret_cast<char*>(&vector_data[0]), data);
+}
+
+namespace tut
+{
+		static LLTemplateMessageReader::message_template_number_map_t numberMap;
+
+		struct LLTemplateMessageDispatcherData
+		{
+			LLTemplateMessageDispatcherData()
+			{
+				mMessageName = "MessageName";
+				gUdpDispatchWasCalled = false;
+				gClearRecvWasCalled = false;
+				gValidateMessage = FALSE;
+				mMessage["body"]["binary-template-data"] = std::vector<U8>();
+			}
+
+			LLSD mMessage;
+			LLHTTPNode::ResponsePtr mResponsePtr;
+			std::string mMessageName;
+		};
+
+	typedef test_group<LLTemplateMessageDispatcherData> factory;
+	typedef factory::object object;
+}
+
+namespace
+{
+	tut::factory tf("LLTemplateMessageDispatcher test");
+}
+
+namespace tut
+{
+	// does an empty message stop processing?
+	template<> template<>
+	void object::test<1>()
+	{
+		LLTemplateMessageReader* pReader = NULL;
+		LLTemplateMessageDispatcher t(*pReader);
+		t.dispatch(mMessageName, mMessage, mResponsePtr);
+		ensure(! gUdpDispatchWasCalled);
+		ensure(! gClearRecvWasCalled);
+	}
+
+	// does the disaptch invoke the udp send method?
+	template<> template<>
+	void object::test<2>()
+	{
+		LLTemplateMessageReader* pReader = NULL;
+		LLTemplateMessageDispatcher t(*pReader);
+		gValidateMessage = TRUE;
+		std::vector<U8> vector_data;
+		fillVector(vector_data, gBinaryTemplateData);		
+		mMessage["body"]["binary-template-data"] = vector_data;
+		t.dispatch(mMessageName, mMessage, mResponsePtr);
+		ensure("udp dispatch was called", gUdpDispatchWasCalled);
+	}
+
+	// what if the message wasn't valid? We would hope the message gets cleared!
+	template<> template<>
+	void object::test<3>()
+	{
+		LLTemplateMessageReader* pReader = NULL;
+		LLTemplateMessageDispatcher t(*pReader);
+		std::vector<U8> vector_data;
+		fillVector(vector_data, gBinaryTemplateData);
+		mMessage["body"]["binary-template-data"] = vector_data;
+		gValidateMessage = FALSE;
+		t.dispatch(mMessageName, mMessage, mResponsePtr);
+		ensure("clear received message was called", gClearRecvWasCalled);
+	}
+
+	// is the binary data passed through correctly?
+	template<> template<>
+	void object::test<4>()
+	{
+		LLTemplateMessageReader* pReader = NULL;
+		LLTemplateMessageDispatcher t(*pReader);
+		gValidateMessage = TRUE;
+		std::vector<U8> vector_data;
+		fillVector(vector_data, gBinaryTemplateData);
+		mMessage["body"]["binary-template-data"] = vector_data;
+		t.dispatch(mMessageName, mMessage, mResponsePtr);
+		ensure("data couriered correctly", strcmp(gBinaryTemplateData, gUdpDispatchedData) == 0);
+	}
+}
+
diff --git a/indra/llmessage/tests/lltesthttpclientadapter.cpp b/indra/llmessage/tests/lltesthttpclientadapter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1140458918fa4a094192042339c899511a2a7598
--- /dev/null
+++ b/indra/llmessage/tests/lltesthttpclientadapter.cpp
@@ -0,0 +1,56 @@
+/** 
+ * @file 
+ * @brief 
+ *
+ * $LicenseInfo:firstyear=2008&license=internal$
+ * 
+ * Copyright (c) 2008, Linden Research, Inc.
+ * 
+ * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
+ * this source code is governed by the Linden Lab Source Code Disclosure
+ * Agreement ("Agreement") previously entered between you and Linden
+ * Lab. By accessing, using, copying, modifying or distributing this
+ * software, you acknowledge that you have been informed of your
+ * obligations under the Agreement and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "lltesthttpclientadapter.h"
+
+LLTestHTTPClientAdapter::LLTestHTTPClientAdapter()
+{
+}
+
+LLTestHTTPClientAdapter::~LLTestHTTPClientAdapter()
+{
+}
+
+void LLTestHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder)
+{
+	mGetUrl.push_back(url);
+	mGetResponder.push_back(responder);
+}
+
+void LLTestHTTPClientAdapter::put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder)
+{
+	mPutUrl.push_back(url);
+	mPutBody.push_back(body);
+	mPutResponder.push_back(responder);
+}
+
+U32 LLTestHTTPClientAdapter::putCalls() const 
+{ 
+	return mPutUrl.size(); 
+}
+
+void LLTestHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers)
+{
+	mGetUrl.push_back(url);
+	mGetHeaders.push_back(headers);
+	mGetResponder.push_back(responder);
+}
+
+
diff --git a/indra/llmessage/tests/lltesthttpclientadapter.h b/indra/llmessage/tests/lltesthttpclientadapter.h
new file mode 100644
index 0000000000000000000000000000000000000000..d03250368595f9d1eccdef4198c95a13877200c9
--- /dev/null
+++ b/indra/llmessage/tests/lltesthttpclientadapter.h
@@ -0,0 +1,52 @@
+/** 
+ * @file 
+ * @brief 
+ *
+ * $LicenseInfo:firstyear=2008&license=internal$
+ * 
+ * Copyright (c) 2008, Linden Research, Inc.
+ * 
+ * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
+ * this source code is governed by the Linden Lab Source Code Disclosure
+ * Agreement ("Agreement") previously entered between you and Linden
+ * Lab. By accessing, using, copying, modifying or distributing this
+ * software, you acknowledge that you have been informed of your
+ * obligations under the Agreement and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+/* Macro Definitions */
+#ifndef LL_LLTESTHTTPCLIENTADAPTER_H
+#define LL_LLTESTHTTPCLIENTADAPTER_H
+
+
+#include "linden_common.h"
+#include "llhttpclientinterface.h"
+
+class LLTestHTTPClientAdapter : public LLHTTPClientInterface
+{
+public:
+	LLTestHTTPClientAdapter();
+	virtual ~LLTestHTTPClientAdapter();
+	virtual void get(const std::string& url, LLCurl::ResponderPtr responder);
+	virtual void get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers);
+
+	virtual void put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder);
+	U32 putCalls() const;
+
+	std::vector<LLSD> mPutBody;
+	std::vector<LLSD> mGetHeaders;
+	std::vector<std::string> mPutUrl;
+	std::vector<std::string> mGetUrl;
+	std::vector<LLCurl::ResponderPtr> mPutResponder;
+	std::vector<LLCurl::ResponderPtr> mGetResponder;
+};
+
+
+
+#endif //LL_LLSIMULATORPRESENCESENDER_H
+
diff --git a/indra/llmessage/tests/lltestmessagesender.cpp b/indra/llmessage/tests/lltestmessagesender.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a37aa4c5664b76c4a3b789eebcf5ccfd435684e9
--- /dev/null
+++ b/indra/llmessage/tests/lltestmessagesender.cpp
@@ -0,0 +1,33 @@
+/** 
+ * @file 
+ * @brief 
+ *
+ * $LicenseInfo:firstyear=2008&license=internal$
+ * 
+ * Copyright (c) 2008, Linden Research, Inc.
+ * 
+ * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
+ * this source code is governed by the Linden Lab Source Code Disclosure
+ * Agreement ("Agreement") previously entered between you and Linden
+ * Lab. By accessing, using, copying, modifying or distributing this
+ * software, you acknowledge that you have been informed of your
+ * obligations under the Agreement and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "lltestmessagesender.h"
+
+LLTestMessageSender::~LLTestMessageSender()
+{
+}
+
+
+S32 LLTestMessageSender::sendMessage(const LLHost& host, LLStoredMessagePtr message)
+{
+	mSendHosts.push_back(host);
+	mSendMessages.push_back(message);
+	return 0;
+}
diff --git a/indra/llmessage/tests/lltestmessagesender.h b/indra/llmessage/tests/lltestmessagesender.h
new file mode 100644
index 0000000000000000000000000000000000000000..83c0eff4d372582c58ee5a0302a4600fcb8c3699
--- /dev/null
+++ b/indra/llmessage/tests/lltestmessagesender.h
@@ -0,0 +1,46 @@
+/** 
+ * @file 
+ * @brief 
+ *
+ * $LicenseInfo:firstyear=2008&license=internal$
+ * 
+ * Copyright (c) 2008, Linden Research, Inc.
+ * 
+ * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
+ * this source code is governed by the Linden Lab Source Code Disclosure
+ * Agreement ("Agreement") previously entered between you and Linden
+ * Lab. By accessing, using, copying, modifying or distributing this
+ * software, you acknowledge that you have been informed of your
+ * obligations under the Agreement and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+/* Macro Definitions */
+#ifndef LL_LLTESTMESSAGESENDER_H
+#define LL_LLTESTMESSAGESENDER_H
+
+
+#include "linden_common.h"
+#include "llmessagesenderinterface.h"
+#include <vector>
+
+
+
+class LLTestMessageSender : public LLMessageSenderInterface
+{
+public:
+	virtual ~LLTestMessageSender();
+	virtual S32 sendMessage(const LLHost& host, LLStoredMessagePtr message);
+
+	std::vector<LLHost> mSendHosts;
+	std::vector<LLStoredMessagePtr> mSendMessages;
+};
+
+
+
+#endif //LL_LLTESTMESSAGESENDER_H
+
diff --git a/indra/llmessage/tests/lltrustedmessageservice_test.cpp b/indra/llmessage/tests/lltrustedmessageservice_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..44595391dfe723f45daf313507cfd72480979505
--- /dev/null
+++ b/indra/llmessage/tests/lltrustedmessageservice_test.cpp
@@ -0,0 +1,145 @@
+/**
+ * @file lltrustedmessageservice_test.cpp
+ * @brief LLTrustedMessageService unit tests
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "lltrustedmessageservice.h"
+#include "../test/lltut.h"
+
+#include "llhost.cpp" // LLHost is a value type for test purposes.
+#include "net.cpp" // Needed by LLHost.
+
+#include "message.h"
+#include "llmessageconfig.h"
+
+LLMessageSystem* gMessageSystem = NULL;
+
+LLMessageConfig::SenderTrust
+LLMessageConfig::getSenderTrustedness(const std::string& msg_name)
+{
+	return LLMessageConfig::NOT_SET;
+}
+
+void LLMessageSystem::receivedMessageFromTrustedSender()
+{
+}
+
+bool LLMessageSystem::isTrustedSender(const LLHost& host) const
+{
+	return false;
+}
+
+bool LLMessageSystem::isTrustedMessage(const std::string& name) const
+{
+	return false;
+}
+
+bool messageDispatched = false;
+bool messageDispatchedAsBinary = false;
+LLSD lastLLSD;
+std::string lastMessageName;
+
+void LLMessageSystem::dispatch(const std::string& msg_name,
+							   const LLSD& message,
+							   LLHTTPNode::ResponsePtr responsep)
+{
+	messageDispatched = true;
+	lastLLSD = message;
+	lastMessageName = msg_name;
+}
+
+void LLMessageSystem::dispatchTemplate(const std::string& msg_name,
+						 const LLSD& message,
+						 LLHTTPNode::ResponsePtr responsep)
+{
+	lastLLSD = message;
+	lastMessageName = msg_name;
+	messageDispatchedAsBinary = true;
+}
+
+namespace tut
+{
+	    struct LLTrustedMessageServiceData
+		{
+			LLTrustedMessageServiceData()
+			{
+				LLSD emptyLLSD;
+				lastLLSD = emptyLLSD;
+				lastMessageName = "uninitialised message name";
+				messageDispatched = false;
+				messageDispatchedAsBinary = false;
+			}
+		};
+
+	typedef test_group<LLTrustedMessageServiceData> factory;
+	typedef factory::object object;
+}
+
+namespace
+{
+	tut::factory tf("LLTrustedMessageServiceData test");
+}
+
+namespace tut
+{
+	// characterisation tests
+
+	// 1) test that messages get forwarded with names etc. as current behaviour (something like LLMessageSystem::dispatch(name, data...)
+
+	// test llsd messages are sent as normal using LLMessageSystem::dispatch() (eventually)
+	template<> template<>
+	void object::test<1>()
+	{
+		LLHTTPNode::ResponsePtr response;
+		LLSD input;
+		LLSD context;
+		LLTrustedMessageService adapter;
+		adapter.post(response, context, input);
+		// test original ting got called wit nowt, ya get me blood?
+		ensure_equals(messageDispatched, true);
+		ensure(lastLLSD.has("body"));
+	}
+
+	// test that llsd wrapped binary-template-data messages are 
+	// sent via LLMessageSystem::binaryDispatch() or similar
+	template<> template<>
+	void object::test<2>()
+	{
+		LLHTTPNode::ResponsePtr response;
+		LLSD input;
+		input["binary-template-data"] = "10001010110"; //make me a message here.
+		LLSD context;
+		LLTrustedMessageService adapter;
+
+		adapter.post(response, context, input);
+		ensure("check template-binary-data message was dispatched as binary", messageDispatchedAsBinary);
+		ensure_equals(lastLLSD["body"]["binary-template-data"].asString(),  "10001010110");
+		// test somit got called with "10001010110" (something like LLMessageSystem::dispatchTemplate(blah))
+	}
+}
diff --git a/indra/llprimitive/llprimlinkinfo.h b/indra/llprimitive/llprimlinkinfo.h
index 7f1840303ba5e9067d79d59074afdfa5fc6f5b78..946fa75bfaba89a212f34ba1a0346384df810a0f 100644
--- a/indra/llprimitive/llprimlinkinfo.h
+++ b/indra/llprimitive/llprimlinkinfo.h
@@ -50,7 +50,7 @@
 
 const F32 MAX_OBJECT_SPAN = 54.f;		// max distance from outside edge of an object to the farthest edge
 const F32 OBJECT_SPAN_BONUS = 2.f;		// infinitesimally small prims can always link up to this distance
-const S32 MAX_PRIMS_PER_OBJECT = 255;
+const S32 MAX_PRIMS_PER_OBJECT = 256;
 
 
 template < typename DATA_TYPE >
diff --git a/indra/newview/English.lproj/InfoPlist.strings b/indra/newview/English.lproj/InfoPlist.strings
index 85b64a878804f521cdf6122b0363ce4eaa09b0c2..cfd333f618e28d93e1cb609e0b1926e5b6f9758e 100644
--- a/indra/newview/English.lproj/InfoPlist.strings
+++ b/indra/newview/English.lproj/InfoPlist.strings
@@ -1,6 +1,7 @@
 /* Localized versions of Info.plist keys */
 
 CFBundleName = "Second Life";
+
 CFBundleShortVersionString = "Second Life version 1.23.0.0";
 CFBundleGetInfoString = "Second Life version 1.23.0.0, Copyright 2004-2008 Linden Research, Inc.";
 
diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt
index 0000cc237bf6a47c9207ea5382e0910121102462..b9e0e3dbdde2c018275f079250e425dfca0f75b8 100644
--- a/indra/test/CMakeLists.txt
+++ b/indra/test/CMakeLists.txt
@@ -60,6 +60,7 @@ set(test_SOURCE_FILES
     llstreamtools_tut.cpp
     llstring_tut.cpp
     lltemplatemessagebuilder_tut.cpp
+    lltimestampcache_tut.cpp
     lltiming_tut.cpp
     lltranscode_tut.cpp
     lltut.cpp
diff --git a/indra/test/llblowfish_tut.cpp b/indra/test/llblowfish_tut.cpp
index 5146bb6b979ca3706ae7e06870f634028072d7a0..4a128a8984837d33ffd16b86d414ebfc487a96ac 100644
--- a/indra/test/llblowfish_tut.cpp
+++ b/indra/test/llblowfish_tut.cpp
@@ -94,7 +94,6 @@ namespace tut
 	template<> template<>
 	void blowfish_object::test<1>()
 	{
-#if LL_LINUX
 		LLUUID blank;
 		LLBlowfishCipher cipher(&blank.mData[0], UUID_BYTES);
 
@@ -107,15 +106,11 @@ namespace tut
 		dst_len = cipher.requiredEncryptionSpace(8);
 		ensure("encryption space 8",
 				(dst_len == 16)  );
-#else
-		skip("Blowfish only supported on Linux.");
-#endif // LL_LINUX
 	}
 
 	template<> template<>
 	void blowfish_object::test<2>()
 	{
-#if LL_LINUX
 		LLUUID blank;
 		LLBlowfishCipher cipher(&blank.mData[0], UUID_BYTES);
 
@@ -129,15 +124,11 @@ namespace tut
 		result.resize(count);
 
 		ensure("encrypt null key", matchFile("blowfish.1.bin", result));
-#else
-		skip("Blowfish only supported on Linux.");
-#endif // LL_LINUX
 	}
 
 	template<> template<>
 	void blowfish_object::test<3>()
 	{
-#if LL_LINUX
         // same as base64 test id
 		LLUUID id("526a1e07-a19d-baed-84c4-ff08a488d15e");
 		LLBlowfishCipher cipher(&id.mData[0], UUID_BYTES);
@@ -152,8 +143,5 @@ namespace tut
 		result.resize(count);
 
 		ensure("encrypt real key", matchFile("blowfish.2.bin", result));
-#else
-        skip("Blowfish only supported on Linux.");
-#endif // LL_LINUX
 	}
 }
diff --git a/indra/test/llsdmessagebuilder_tut.cpp b/indra/test/llsdmessagebuilder_tut.cpp
index 60a50cf75f896d88851ac41554e7205401acf847..27ab127772fe5504852d0d3f0fd04ef48b12fc3c 100755
--- a/indra/test/llsdmessagebuilder_tut.cpp
+++ b/indra/test/llsdmessagebuilder_tut.cpp
@@ -35,6 +35,7 @@
 
 #include "linden_common.h"
 #include "lltut.h"
+#include "llmessagetemplate.h"
 #include "llsdmessagebuilder.h"
 #include "llsdmessagereader.h"
 #include "llsdtraits.h"
@@ -43,10 +44,24 @@
 #include "v3dmath.h"
 #include "v3math.h"
 #include "v4math.h"
+#include "llsdutil_math.cpp"
+#include "lltemplatemessagebuilder.h"
 
 namespace tut
 {	
+	static LLTemplateMessageBuilder::message_template_name_map_t templateNameMap;
+
+    LLMsgData* messageData = NULL;
+    LLMsgBlkData* messageBlockData = NULL;
+
 	struct LLSDMessageBuilderTestData {
+
+		LLSDMessageBuilderTestData()
+		{
+			messageData = new LLMsgData("testMessage");
+			messageBlockData = new LLMsgBlkData("testBlock", 0);
+		}
+
 		static LLSDMessageBuilder defaultBuilder()
 		{
 			LLSDMessageBuilder builder;
@@ -61,6 +76,43 @@ namespace tut
 			reader.setMessage("name", builder.getMessage());
 			return reader;
 		}
+
+		static void addValue(LLMsgBlkData* mbd, char* name, void* v, EMsgVariableType type, int size, int data_size = -1)
+		{
+			LLMsgVarData tmp(name, type);
+			tmp.addData(v, size, type, data_size);
+			mbd->mMemberVarData[name] = tmp;
+		}
+
+
+		static LLMessageBlock* defaultTemplateBlock(const EMsgVariableType type = MVT_NULL, const S32 size = 0, EMsgBlockType block = MBT_VARIABLE)
+		{
+			return createTemplateBlock(_PREHASH_Test0, type, size, block);
+		}
+
+		static LLMessageBlock* createTemplateBlock(char* name, const EMsgVariableType type = MVT_NULL, const S32 size = 0, EMsgBlockType block = MBT_VARIABLE)
+		{
+			LLMessageBlock* result = new LLMessageBlock(name, block);
+			if(type != MVT_NULL)
+			{
+				result->addVariable(_PREHASH_Test0, type, size);
+			}
+			return result;
+		}
+
+		static LLTemplateMessageBuilder* defaultTemplateBuilder(LLMessageTemplate& messageTemplate, char* name = _PREHASH_Test0)
+		{
+			templateNameMap[_PREHASH_TestMessage] = &messageTemplate;
+			LLTemplateMessageBuilder* builder = new LLTemplateMessageBuilder(templateNameMap);
+			builder->newMessage(_PREHASH_TestMessage);
+			builder->nextBlock(name);
+			return builder;
+		}
+
+		static LLMessageTemplate defaultTemplate()
+		{
+			return LLMessageTemplate(_PREHASH_TestMessage, 1, MFT_HIGH);
+		}
 	};
 	
 	typedef test_group<LLSDMessageBuilderTestData>	LLSDMessageBuilderTestGroup;
@@ -280,5 +332,509 @@ namespace tut
 	  outValue = buffer;
 	  ensure_equals("Ensure String", inValue, outValue);
 	}
+
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<19>()
+	{
+	  LLMsgBlkData* mbd = new LLMsgBlkData("testBlock", 0);
+	  LLMsgData* md = new LLMsgData("testMessage");
+	  md->addBlock(mbd);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*md);
+	  LLSD output = builder.getMessage();
+
+	  ensure("Ensure message block created when copied from legacy message to llsd", output["testBlock"].isDefined());
+	}
+
+	// MVT_FIXED
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<20>()
+	{
+	  char binData[] = "abcdefghijklmnop";
+
+	  addValue(messageBlockData, "testBinData", &binData, MVT_FIXED, sizeof(binData));
+	  messageData->addBlock(messageBlockData);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*messageData);
+	  LLSD output = builder.getMessage();
+
+	  std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
+	  ensure("Ensure MVT_S16Array data copied from legacy to llsd give a valid vector", v.size() > 0);
+
+	  ensure_memory_matches("Ensure fixed binary data works in a message copied from legacy to llsd",
+		  &v[0], sizeof(binData), binData, sizeof(binData));
+	}
+
+	// MVT_VARIABLE data_size 1 (U8's)
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<21>()
+	{
+	 /* U8 binData[] = "abcdefghijklmnop";
+
+	  addValue(messageBlockData, "testBinData", &binData, MVT_VARIABLE, sizeof(binData), 1);
+	  messageData->addBlock(messageBlockData);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*messageData);
+	  LLSD output = builder.getMessage();
+
+	  std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
+	  ensure("Ensure MVT_S16Array data copied from legacy to llsd give a valid vector", v.size() > 0);
+
+	  ensure_memory_matches("Ensure MVT_VARIABLE U8 binary data works in a message copied from legacy to llsd",
+		  &v[0], sizeof(binData), binData, sizeof(binData));*/
+	}
+
+	// MVT_VARIABLE data_size 2 (U16's)
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<22>()
+	{
+	  U16 binData[] = {1,2,3,4,5,6,7,8,9}; //9 shorts
+
+	  addValue(messageBlockData, "testBinData", &binData, MVT_VARIABLE, sizeof(binData) >> 1, 2);
+	  messageData->addBlock(messageBlockData);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*messageData);
+	  LLSD output = builder.getMessage();
+
+	  std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
+	  ensure("Ensure MVT_S16Array data copied from legacy to llsd give a valid vector", v.size() > 0);
+
+	  ensure_memory_matches("Ensure MVT_VARIABLE U16 binary data works in a message copied from legacy to llsd",
+		  &v[0], sizeof(binData) >> 1, binData, sizeof(binData) >> 1);
+	}
+
+	// MVT_VARIABLE data_size 4 (S32's)
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<23>()
+	{
+	  U32 binData[] = {9,8,7,6,5,4,3,2,1};
+
+	  addValue(messageBlockData, "testBinData", &binData, MVT_VARIABLE, sizeof(binData) >> 2, 4);
+	  messageData->addBlock(messageBlockData);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*messageData);
+	  LLSD output = builder.getMessage();
+
+	  std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
+	  ensure("Ensure MVT_S16Array data copied from legacy to llsd give a valid vector", v.size() > 0);
+
+	  ensure_memory_matches("Ensure MVT_VARIABLE S32 binary data works in a message copied from legacy to llsd",
+		  &v[0], sizeof(binData) >> 2, binData, sizeof(binData) >> 2);
+	}
+
+	// MVT_U8
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<24>()
+	{
+	  U8 data = 0xa5;
+
+	  addValue(messageBlockData, "testBinData", &data, MVT_U8, sizeof(data));
+	  messageData->addBlock(messageBlockData);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*messageData);
+	  LLSD output = builder.getMessage();
+
+	  ensure_equals("Ensure MVT_U8 data works in a message copied from legacy to llsd",
+		  output["testBlock"][0]["testBinData"].asInteger(), data);
+	}
+
+	// MVT_U16
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<25>()
+	{
+	  U16 data = 0xa55a;
+
+	  addValue(messageBlockData, "testBinData", &data, MVT_U16, sizeof(data));
+	  messageData->addBlock(messageBlockData);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*messageData);
+	  LLSD output = builder.getMessage();
+
+	  ensure_equals("Ensure MVT_U16 data works in a message copied from legacy to llsd",
+		  output["testBlock"][0]["testBinData"].asInteger(), data);
+	}
+
+	// MVT_U32
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<26>()
+	{
+	  U32 data = 0xa55a7117;
+
+	  addValue(messageBlockData, "testBinData", &data, MVT_U32, sizeof(data));
+	  messageData->addBlock(messageBlockData);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*messageData);
+	  LLSD output = builder.getMessage();
+
+	  ensure_equals("Ensure MVT_U32 data works in a message copied from legacy to llsd",
+		  ll_U32_from_sd(output["testBlock"][0]["testBinData"]), data);
+	}
+
+	// MVT_U64 - crush into an s32: LLSD does not support 64 bit values
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<27>()
+	{
+	  U64 data = U64L(0xa55a711711223344);
+	  addValue(messageBlockData, "testBinData", &data, MVT_U64, sizeof(data));
+	  messageData->addBlock(messageBlockData);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*messageData);
+	  LLSD output = builder.getMessage();
+
+	  ensure_equals("Ensure MVT_U64 data works in a message copied from legacy to llsd",
+		  ll_U64_from_sd(output["testBlock"][0]["testBinData"]), data);
+	}
+
+	// MVT_S8
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<28>()
+	{
+	  S8 data = -31;
+
+	  addValue(messageBlockData, "testBinData", &data, MVT_S8, sizeof(data));
+	  messageData->addBlock(messageBlockData);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*messageData);
+	  LLSD output = builder.getMessage();
+
+	  ensure_equals("Ensure MVT_S8 data works in a message copied from legacy to llsd",
+		  output["testBlock"][0]["testBinData"].asInteger(), data);
+	}
+
+	// MVT_S16
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<29>()
+	{
+	  S16 data = -31;
+
+	  addValue(messageBlockData, "testBinData", &data, MVT_S16, sizeof(data));
+	  messageData->addBlock(messageBlockData);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*messageData);
+	  LLSD output = builder.getMessage();
+
+	  ensure_equals("Ensure MVT_S16 data works in a message copied from legacy to llsd",
+		  output["testBlock"][0]["testBinData"].asInteger(), data);
+	}
+
+	// MVT_S32
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<30>()
+	{
+	  S32 data = -3100;
+
+	  addValue(messageBlockData, "testBinData", &data, MVT_S32, sizeof(data));
+	  messageData->addBlock(messageBlockData);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*messageData);
+	  LLSD output = builder.getMessage();
+
+	  ensure_equals("Ensure MVT_S32 data works in a message copied from legacy to llsd",
+		  output["testBlock"][0]["testBinData"].asInteger(), data);
+	}
+
+	// MVT_S64 - crush into an s32: LLSD does not support 64 bit values
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<31>()
+	{
+	  S64 data = -31003100;
+
+	  addValue(messageBlockData, "testBinData", &data, MVT_S64, sizeof(data));
+	  messageData->addBlock(messageBlockData);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*messageData);
+	  LLSD output = builder.getMessage();
+
+	  ensure_equals("Ensure MVT_S64 data works in a message copied from legacy to llsd",
+		  output["testBlock"][0]["testBinData"].asInteger(), (S32)data);
+	}
+
+	// MVT_F32
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<32>()
+	{
+	  F32 data = 1234.1234f;
+
+	  addValue(messageBlockData, "testBinData", &data, MVT_F32, sizeof(data));
+	  messageData->addBlock(messageBlockData);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*messageData);
+	  LLSD output = builder.getMessage();
+
+	  ensure_equals("Ensure MVT_F32 data works in a message copied from legacy to llsd",
+		  output["testBlock"][0]["testBinData"].asReal(), data);
+	}
+
+	// MVT_F64
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<33>()
+	{
+	  F64 data = 1234.1234;
+
+	  addValue(messageBlockData, "testBinData", &data, MVT_F64, sizeof(data));
+	  messageData->addBlock(messageBlockData);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*messageData);
+	  LLSD output = builder.getMessage();
+
+	  ensure_equals("Ensure MVT_F64 data works in a message copied from legacy to llsd",
+		  output["testBlock"][0]["testBinData"].asReal(), data);
+	}
+
+	// MVT_LLVector3
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<34>()
+	{
+	  LLVector3 data(1,2,3);
+
+	  addValue(messageBlockData, "testBinData", &data, MVT_LLVector3, sizeof(data));
+	  messageData->addBlock(messageBlockData);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*messageData);
+	  LLSD output = builder.getMessage();
+
+	  ensure_equals("Ensure MVT_LLVector3 data works in a message copied from legacy to llsd",
+		  ll_vector3_from_sd(output["testBlock"][0]["testBinData"]), data);
+	}
+
+	// MVT_LLVector3d
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<35>()
+	{
+	  LLVector3d data(1,2,3);
+
+	  addValue(messageBlockData, "testBinData", &data, MVT_LLVector3d, sizeof(data));
+	  messageData->addBlock(messageBlockData);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*messageData);
+	  LLSD output = builder.getMessage();
+
+	  ensure_equals("Ensure MVT_LLVector3 data works in a message copied from legacy to llsd",
+		  ll_vector3d_from_sd(output["testBlock"][0]["testBinData"]), data);
+	}
+
+	// MVT_LLVector4
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<36>()
+	{
+	  LLVector4 data(1,2,3,4);
+	  LLSD v = ll_sd_from_vector4(data);
+
+	  addValue(messageBlockData, "testBinData", &data, MVT_LLVector4, sizeof(data));
+	  messageData->addBlock(messageBlockData);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*messageData);
+	  LLSD output = builder.getMessage();
+
+	  ensure_equals("Ensure MVT_LLVector4 data works in a message copied from legacy to llsd",
+		  output["testBlock"][0]["testBinData"], v);
+	}
+
+	// MVT_LLQuaternion
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<37>()
+	{
+	  LLQuaternion data(1,2,3,0);
+
+	  //we send a quaternion packed into a vec3 (w is infered) - so sizeof(vec) == 12 bytes not 16.
+	  LLVector3 vec = data.packToVector3();
+
+	  addValue(messageBlockData, "testBinData", &vec, MVT_LLQuaternion, sizeof(vec));
+	  messageData->addBlock(messageBlockData);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*messageData);
+	  LLSD output = builder.getMessage();
+
+	  ensure_equals("Ensure MVT_LLQuaternion data works in a message copied from legacy to llsd",
+		  ll_quaternion_from_sd(output["testBlock"][0]["testBinData"]), data);
+	}
+
+	// MVT_LLUUID
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<38>()
+	{
+	  LLUUID data("01234567-0123-0123-0123-234567abcdef");
+
+	  addValue(messageBlockData, "testBinData", &data, MVT_LLUUID, sizeof(data));
+	  messageData->addBlock(messageBlockData);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*messageData);
+	  LLSD output = builder.getMessage();
+	 
+	  std::string v = output["testBlock"][0]["testBinData"].asUUID().asString();
+
+	  ensure_equals("Ensure MVT_LLUUID data works in a message copied from legacy to llsd",
+		  output["testBlock"][0]["testBinData"].asUUID(), data);
+	}
+
+	// MVT_BOOL
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<39>()
+	{
+	  BOOL valueTrue = true;
+	  BOOL valueFalse = false;
+
+	  LLMsgData* md = new LLMsgData("testMessage");
+	  LLMsgBlkData* mbd = new LLMsgBlkData("testBlock", 0);
+	  addValue(mbd, "testBoolFalse", &valueFalse, MVT_BOOL, sizeof(BOOL));
+	  addValue(mbd, "testBoolTrue", &valueTrue, MVT_BOOL, sizeof(BOOL));
+	  md->addBlock(mbd);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*md);
+	  LLSD output = builder.getMessage();
+
+	  ensure("Ensure bools work in a message copied from legacy to llsd",
+		  output["testBlock"][0]["testBoolTrue"].asBoolean() && !output["testBlock"][0]["testBoolFalse"].asBoolean());
+	}
+
+	// MVT_IP_ADDR
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<40>()
+	{
+	  U32 data(0xff887766);
+	  LLSD v = ll_sd_from_ipaddr(data);
+
+	  addValue(messageBlockData, "testBinData", &data, MVT_IP_ADDR, sizeof(data));
+	  messageData->addBlock(messageBlockData);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*messageData);
+	  LLSD output = builder.getMessage();
+
+	  ensure_equals("Ensure MVT_IP_ADDR data works in a message copied from legacy to llsd",
+		  output["testBlock"][0]["testBinData"], v);
+	}
+
+	// MVT_IP_PORT
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<41>()
+	{
+	  U16 data = 0xff88;
+
+	  addValue(messageBlockData, "testBinData", &data, MVT_IP_PORT, sizeof(data));
+	  messageData->addBlock(messageBlockData);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*messageData);
+	  LLSD output = builder.getMessage();
+
+	  ensure_equals("Ensure MVT_IP_PORT data works in a message copied from legacy to llsd",
+		  output["testBlock"][0]["testBinData"].asInteger(), data);
+	}
+
+	// MVT_U16Vec3
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<42>()
+	{
+	  U16 data[3] = {0,1,2};
+
+	  addValue(messageBlockData, "testBinData", &data, MVT_U16Vec3, sizeof(data));
+	  messageData->addBlock(messageBlockData);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*messageData);
+	  LLSD output = builder.getMessage();
+
+	  std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
+	  ensure("Ensure MVT_U16Vec3 data copied from legacy to llsd give a valid vector", v.size() > 0);
+
+	  ensure_memory_matches("Ensure MVT_U16Vec3 data works in a message copied from legacy to llsd",
+		  (U16*)&v[0], 6, data, 6);
+	}
+
+	// MVT_U16Quat
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<43>()
+	{
+	  U16 data[4] = {0,1,2,4};
+
+	  addValue(messageBlockData, "testBinData", &data, MVT_U16Quat, sizeof(data));
+	  messageData->addBlock(messageBlockData);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*messageData);
+	  LLSD output = builder.getMessage();
+
+	  std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
+	  ensure("Ensure MVT_U16Quat data copied from legacy to llsd give a valid vector", v.size() > 0);
+
+	  ensure_memory_matches("Ensure MVT_U16Quat data works in a message copied from legacy to llsd",
+		  (U16*)&v[0], 8, data, 8);
+	}
+
+	// MVT_S16Array
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<44>()
+	{
+	  S16 data[19] = {0,-1,2,-4,5,-6,7,-8,9,-10,11,-12,13,-14,15,16,17,18};
+
+	  addValue(messageBlockData, "testBinData", &data, MVT_S16Array, sizeof(data));
+	  messageData->addBlock(messageBlockData);
+	  LLSDMessageBuilder builder = defaultBuilder();
+	  
+	  builder.copyFromMessageData(*messageData);
+	  LLSD output = builder.getMessage();
+
+	  std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
+	  ensure("Ensure MVT_S16Array data copied from legacy to llsd give a valid vector", v.size() > 0);
+
+	  ensure_memory_matches("Ensure MVT_S16Array data works in a message copied from legacy to llsd",
+		  (U16*)&v[0], 19, data, 19);
+	}
+
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<45>()
+	{
+		LLMessageTemplate messageTemplate = defaultTemplate();
+		messageTemplate.addBlock(defaultTemplateBlock(MVT_U8, 1));
+		U8 inValue = 2;
+		LLTemplateMessageBuilder* template_builder = defaultTemplateBuilder(messageTemplate);
+		template_builder->addU8(_PREHASH_Test0, inValue);
+
+		LLSDMessageBuilder builder;
+		builder.copyFromMessageData(*template_builder->getCurrentMessage());
+		LLSD output = builder.getMessage();
+		
+		ensure_equals(output["Test0"][0]["Test0"].asInteger(), 2);
+
+	}
+
+	template<> template<>
+	void LLSDMessageBuilderTestObject::test<46>()
+	{
+		LLMessageTemplate messageTemplate = defaultTemplate();
+		messageTemplate.addBlock(defaultTemplateBlock(MVT_VARIABLE, 1));
+		std::string inValue = "testing";
+		LLTemplateMessageBuilder* builder = defaultTemplateBuilder(messageTemplate);
+		builder->addString(_PREHASH_Test0, inValue.c_str());
+
+		LLSDMessageBuilder sd_builder;
+		sd_builder.copyFromMessageData(*builder->getCurrentMessage());
+		LLSD output = sd_builder.getMessage();
+		
+		ensure_equals(output["Test0"][0]["Test0"].asString(), std::string("testing"));
+	}
+
 }
 
diff --git a/indra/test/lltimestampcache_tut.cpp b/indra/test/lltimestampcache_tut.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9e0de0fe60882efc5552e4f016039efc7c42f06f
--- /dev/null
+++ b/indra/test/lltimestampcache_tut.cpp
@@ -0,0 +1,129 @@
+/**
+ * @file lltimestampcache_tut.cpp
+ * @author James Tess
+ * @date 2008-12-03
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * 
+ * Copyright (c) 2008, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include <tut/tut.hpp>
+
+#include "linden_common.h"
+#include "../mapserver/lltimestampcache.h"
+#include "lltut.h"
+
+
+namespace tut
+{
+	struct LLTimestampCacheTestData
+	{
+	};
+
+	typedef test_group<LLTimestampCacheTestData> LLTimestampCacheTestGroup;
+	typedef LLTimestampCacheTestGroup::object LLTimestampCacheTestObject;
+
+	LLTimestampCacheTestGroup timestampCacheTestGroup("LLTimestampCache");
+
+	// Most common usage
+	template<> template<>
+		void LLTimestampCacheTestObject::test<1>()
+		{
+			LLTimestampCache<std::string, std::string> cache;
+			// put in some data
+			cache.insert("key1", "val1", 1);
+			cache.insert("key2", "val2", 2);
+			cache.insert("key3", "val3", 3);
+			ensure_equals("size is 3", cache.size(), 3);
+			// check some items
+			ensure("has key1", cache.has("key1"));
+			ensure("no invalid key", !cache.has("invalid key"));
+			// get some items
+			ensure_equals("get key1", cache.get("key1", 4), "val1");
+			ensure_equals("get invalid key", 
+					cache.get("invalid key", 4), std::string() );
+			// timestamps
+			ensure_equals("key1 timestamp updated", cache.getTimestamp("key1"), 4);
+			ensure_equals("invalid key timestamp", 
+					cache.getTimestamp("invalid key"), 0);
+		}
+
+	// New empty cache shouldn't have any entries
+	template<> template<>
+		void LLTimestampCacheTestObject::test<2>()
+		{
+			LLTimestampCache<std::string, std::string> cache;
+			ensure_equals("starts empty",   cache.size(), 0);
+			ensure_equals("has nothing",    cache.has("foo"), false);
+			ensure_equals("gets nothing",   cache.get("foo", 0), std::string() );
+			U32 max_time = 0xFFFFFFFF;
+			ensure_equals("erases nothing", cache.eraseBefore(max_time), 0);
+		}
+
+	// Non empty cache
+	template<> template<>
+		void LLTimestampCacheTestObject::test<3>()
+		{
+			LLTimestampCache<std::string, std::string> cache;
+			cache.insert("foo", "bar", 123);
+			ensure_equals("size one", cache.size(), 1);
+			ensure_equals("has it", cache.has("foo"), true);
+			ensure_equals("timestamp correct", cache.getTimestamp("foo"), 123);
+			std::string value = cache.get("foo", 456);
+			ensure_equals("get value", value, "bar");
+			ensure_equals("timestamp updated", cache.getTimestamp("foo"), 456);
+			ensure_equals("erase nothing", cache.eraseBefore(0), 0);
+			ensure_equals("erase one", cache.eraseBefore(789), 1);
+			ensure_equals("empty after erase", cache.size(), 0);
+		}
+
+	// Recache of item should update timestamp
+	template<> template<>
+		void LLTimestampCacheTestObject::test<4>()
+		{
+			LLTimestampCache<std::string, std::string> cache;
+			cache.insert("foo", "bar", 123);
+			cache.insert("foo", "bar", 456);
+			ensure_equals("duplicate suppressed", cache.size(), 1);
+			ensure_equals("timestamp replaced", cache.getTimestamp("foo"), 456);
+		}
+
+	// Erasing some items
+	template<> template<>
+		void LLTimestampCacheTestObject::test<5>()
+		{
+			LLTimestampCache<std::string, std::string> cache;
+			cache.insert("key1", "val1", 1);
+			cache.insert("key2", "val2", 2);
+			cache.insert("key3", "val3", 3);
+			cache.insert("key4", "val4", 4);
+			size_t erased = cache.eraseBefore(3);
+			ensure_equals("erase range", erased, 2);
+			ensure_equals("cache post erase", cache.size(), 2);
+			ensure_equals("has key3", cache.has("key3"), true);
+			ensure_equals("not has key2", cache.has("key2"), false);
+		}
+}
diff --git a/indra/test/lltut.cpp b/indra/test/lltut.cpp
index 64861c3115417d754ac3d1b04e64521b3fe18d60..201e174f9cf608289e75ee9c286a5adb1b8eb988 100644
--- a/indra/test/lltut.cpp
+++ b/indra/test/lltut.cpp
@@ -33,10 +33,13 @@
  */
 
 #include "linden_common.h"
+
 #include "lltut.h"
 
+#include "lldate.h"
 #include "llformat.h"
 #include "llsd.h"
+#include "lluri.h"
 
 namespace tut
 {
@@ -74,7 +77,7 @@ namespace tut
 	void ensure_equals(const char* m, const LLSD& actual,
 		const LLSD& expected)
 	{
-		const std::string& msg = m;
+		const std::string& msg = m ? m : "";
 		
 		ensure_equals(msg + " type", actual.type(), expected.type());
 		switch (actual.type())
@@ -196,3 +199,4 @@ namespace tut
 		}
 	}
 }
+
diff --git a/indra/test/lltut.h b/indra/test/lltut.h
index 51e2ee2709ebc54212be411be242d314f62895a5..6d50ebad334c60af2d7c45c6d41f01b364635d71 100644
--- a/indra/test/lltut.h
+++ b/indra/test/lltut.h
@@ -35,13 +35,13 @@
 #ifndef LL_LLTUT_H
 #define LL_LLTUT_H
 
-#include <tut/tut.hpp>
-
-#include "lldate.h"
-#include "lluri.h"
 #include "llmath.h"
 
+#include <tut/tut.hpp>
+
+class LLDate;
 class LLSD;
+class LLURI;
 
 namespace tut
 {
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 566459ee90d6e6d1f88d7e89db75637b51e1cbbf..ba81c6e49e96067384fd12803b79bea39c4c07d4 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -54,9 +54,10 @@
 #	include "ctype_workaround.h"
 #endif
 
-
 namespace tut
 {
+	std::string sSourceDir;
+
     test_runner_singleton runner;
 }
 
@@ -184,6 +185,7 @@ static const apr_getopt_option_t TEST_CL_OPTIONS[] =
 	{"verbose", 'v', 0, "Verbose output."},
 	{"group", 'g', 1, "Run test group specified by option argument."},
 	{"output", 'o', 1, "Write output to the named file."},
+	{"sourcedir", 's', 1, "Project source file directory from CMake."},
 	{"touch", 't', 1, "Touch the given file if all tests succeed"},
 	{"wait", 'w', 0, "Wait for input before exit."},
 	{"debug", 'd', 0, "Emit full debug logs."},
@@ -302,6 +304,11 @@ int main(int argc, char **argv)
 			output = new std::ofstream;
 			output->open(opt_arg);
 			break;
+		case 's':	// --sourcedir
+			tut::sSourceDir = opt_arg;
+			// For convenience, so you can use tut::sSourceDir + "myfile"
+			tut::sSourceDir += '/';
+			break;
 		case 't':
 			touch = opt_arg;
 			break;
diff --git a/indra/test/test.h b/indra/test/test.h
new file mode 100644
index 0000000000000000000000000000000000000000..16ec4effcf123b3928ce0e732a396a6a8f0a0a37
--- /dev/null
+++ b/indra/test/test.h
@@ -0,0 +1,49 @@
+/** 
+ * @file test.h
+ * @author James
+ * @date 2009-01-12
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * 
+ * Copyright (c) 2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#ifndef TEST_H
+#define TEST_H
+
+#include <string>
+
+namespace tut
+{
+	// Source code directory from CMake, used for loading test data and
+	// configuration.  For example:
+	//
+	// loadMyConfig( sSourceDir + "config.dat" );
+	//
+	// Use sparingly, as hitting the file system slows down test execution
+	// and hence every compile. JC
+	extern std::string sSourceDir;
+}
+
+#endif
diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg
index 6d9062228e6347e53809128c282eef6475458ca3..c958fceae9fddf4fa4066fc65a3517d0afbb0cba 100644
--- a/scripts/messages/message_template.msg
+++ b/scripts/messages/message_template.msg
@@ -8717,7 +8717,7 @@ version 2.0
 
 // spaceserver -> simulator
 {
-	RpcScriptRequestInboundForward Low 416 Trusted Unencoded
+	RpcScriptRequestInboundForward Low 416 Trusted Unencoded UDPDeprecated
 	{
 		DataBlock Single
 		{	RPCServerIP	IPADDR }