From 4ecb9cb63e4993b3b4bc65d73ed255139b5c3f75 Mon Sep 17 00:00:00 2001
From: Don Kjer <don@lindenlab.com>
Date: Tue, 1 May 2007 21:39:25 +0000
Subject: svn merge -r 59163:61099
 svn+ssh://svn/svn/linden/branches/release-candidate into release

---
 indra/llmessage/llblowfishcipher.cpp         |   48 +-
 indra/llmessage/llcachename.cpp              |   95 +-
 indra/llmessage/llcachename.h                |    3 +-
 indra/llmessage/llhost.cpp                   |    2 +-
 indra/llmessage/llhttpclient.cpp             |   30 +-
 indra/llmessage/llhttpsender.cpp             |   70 +
 indra/llmessage/llhttpsender.h               |   38 +
 indra/llmessage/llinstantmessage.cpp         |   30 +
 indra/llmessage/llinstantmessage.h           |   17 +-
 indra/llmessage/lliohttpserver.cpp           |   26 +-
 indra/llmessage/lliohttpserver.h             |    3 +-
 indra/llmessage/lliopipe.h                   |    2 +-
 indra/llmessage/lliosocket.cpp               |   13 +-
 indra/llmessage/llmessagebuilder.cpp         |   18 +
 indra/llmessage/llmessagebuilder.h           |   70 +
 indra/llmessage/llmessageconfig.cpp          |  210 ++
 indra/llmessage/llmessageconfig.h            |   31 +
 indra/llmessage/llmessagereader.cpp          |   35 +
 indra/llmessage/llmessagereader.h            |   59 +
 indra/llmessage/llmessagetemplate.cpp        |  146 ++
 indra/llmessage/llmessagetemplate.h          |  356 +++
 indra/llmessage/llmsgvariabletype.h          |   33 +
 indra/llmessage/llpacketack.h                |   18 +-
 indra/llmessage/llpumpio.cpp                 |    8 +-
 indra/llmessage/llpumpio.h                   |    1 +
 indra/llmessage/llsdmessagebuilder.cpp       |  281 ++
 indra/llmessage/llsdmessagebuilder.h         |   98 +
 indra/llmessage/llsdmessagereader.cpp        |  264 ++
 indra/llmessage/llsdmessagereader.h          |   79 +
 indra/llmessage/llservice.h                  |    2 +-
 indra/llmessage/llservicebuilder.cpp         |  115 +
 indra/llmessage/llservicebuilder.h           |   73 +
 indra/llmessage/lltemplatemessagebuilder.cpp |  856 ++++++
 indra/llmessage/lltemplatemessagebuilder.h   |   88 +
 indra/llmessage/lltemplatemessagereader.cpp  |  750 ++++++
 indra/llmessage/lltemplatemessagereader.h    |   98 +
 indra/llmessage/message.cpp                  | 3592 +++++++++-----------------
 indra/llmessage/message.h                    |  538 +---
 indra/llmessage/message_prehash.cpp          |   44 +-
 indra/llmessage/message_prehash.h            |   22 +-
 indra/llmessage/net.cpp                      |    6 +
 41 files changed, 5429 insertions(+), 2839 deletions(-)
 create mode 100644 indra/llmessage/llhttpsender.cpp
 create mode 100644 indra/llmessage/llhttpsender.h
 create mode 100644 indra/llmessage/llmessagebuilder.cpp
 create mode 100644 indra/llmessage/llmessagebuilder.h
 create mode 100644 indra/llmessage/llmessageconfig.cpp
 create mode 100644 indra/llmessage/llmessageconfig.h
 create mode 100644 indra/llmessage/llmessagereader.cpp
 create mode 100644 indra/llmessage/llmessagereader.h
 create mode 100644 indra/llmessage/llmessagetemplate.cpp
 create mode 100644 indra/llmessage/llmessagetemplate.h
 create mode 100644 indra/llmessage/llmsgvariabletype.h
 create mode 100755 indra/llmessage/llsdmessagebuilder.cpp
 create mode 100755 indra/llmessage/llsdmessagebuilder.h
 create mode 100755 indra/llmessage/llsdmessagereader.cpp
 create mode 100755 indra/llmessage/llsdmessagereader.h
 create mode 100644 indra/llmessage/llservicebuilder.cpp
 create mode 100644 indra/llmessage/llservicebuilder.h
 create mode 100644 indra/llmessage/lltemplatemessagebuilder.cpp
 create mode 100644 indra/llmessage/lltemplatemessagebuilder.h
 create mode 100644 indra/llmessage/lltemplatemessagereader.cpp
 create mode 100644 indra/llmessage/lltemplatemessagereader.h

(limited to 'indra/llmessage')

diff --git a/indra/llmessage/llblowfishcipher.cpp b/indra/llmessage/llblowfishcipher.cpp
index 0255a654df..d15e4fb69a 100644
--- a/indra/llmessage/llblowfishcipher.cpp
+++ b/indra/llmessage/llblowfishcipher.cpp
@@ -65,27 +65,33 @@ U32 LLBlowfishCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
 		<< " iv_len " << iv_length
 		<< llendl;
 
-    int output_len = 0;
-    if (!EVP_EncryptUpdate(&context,
-                dst,
-                &output_len,
-                src,
-                src_len))
-    {
-        llwarns << "LLBlowfishCipher::encrypt EVP_EncryptUpdate failure" << llendl;
-        return 0;
-    }
-
-	// There may be some final data left to encrypt if the input is
-	// not an exact multiple of the block size.
-    int temp_len = 0;
-    if (!EVP_EncryptFinal_ex(&context, (unsigned char*)(dst + output_len), &temp_len))
-    {
-        llwarns << "LLBlowfishCipher::encrypt EVP_EncryptFinal failure" << llendl;
-        return 0;
-    }
-    output_len += temp_len;
-	return output_len;
+	int output_len = 0;
+	int temp_len = 0;
+	if (!EVP_EncryptUpdate(&context,
+			dst,
+			&output_len,
+			src,
+			src_len))
+	{
+		llwarns << "LLBlowfishCipher::encrypt EVP_EncryptUpdate failure" << llendl;
+		goto ERROR;
+	}
+
+	// There may be some final data left to encrypt if the input is
+	// not an exact multiple of the block size.
+	if (!EVP_EncryptFinal_ex(&context, (unsigned char*)(dst + output_len), &temp_len))
+	{
+		llwarns << "LLBlowfishCipher::encrypt EVP_EncryptFinal failure" << llendl;
+		goto ERROR;
+	}
+	output_len += temp_len;
+
+	EVP_CIPHER_CTX_cleanup(&context);
+	return output_len;
+
+ERROR:
+	EVP_CIPHER_CTX_cleanup(&context);
+	return 0;
 }
 
 // virtual
diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp
index 339fdda9ef..36cd2ce188 100644
--- a/indra/llmessage/llcachename.cpp
+++ b/indra/llmessage/llcachename.cpp
@@ -32,6 +32,10 @@ const char* CN_NONE = "(none)";
 const char* CN_HIPPOS = "(hippos)";
 const F32 HIPPO_PROBABILITY = 0.01f;
 
+// We track name requests in flight for up to this long.
+// We won't re-request a name during this time
+const U32 PENDING_TIMEOUT_SECS = 5 * 60;
+
 // File version number
 const S32 CN_FILE_VERSION = 2;
 
@@ -162,8 +166,9 @@ namespace {
 	}
 
 
-	typedef std::vector<LLUUID>					AskQueue;
+	typedef std::set<LLUUID>					AskQueue;
 	typedef std::vector<PendingReply>			ReplyQueue;
+	typedef std::map<LLUUID,U32>				PendingQueue;
 	typedef std::map<LLUUID, LLCacheNameEntry*> Cache;
 	typedef std::vector<LLCacheNameCallback>	Observers;
 };
@@ -180,6 +185,9 @@ public:
 	AskQueue			mAskNameQueue;
 	AskQueue			mAskGroupQueue;
 		// UUIDs to ask our upstream host about
+	
+	PendingQueue		mPendingQueue;
+		// UUIDs that have been requested but are not in cache yet.
 
 	ReplyQueue			mReplyQueue;
 		// requests awaiting replies from us
@@ -194,6 +202,7 @@ public:
 	void processPendingAsks();
 	void processPendingReplies();
 	void sendRequest(const char* msg_name, const AskQueue& queue);
+	bool isRequestPending(const LLUUID& id);
 
 	// Message system callbacks.
 	void processUUIDRequest(LLMessageSystem* msg, bool isGroup);
@@ -436,7 +445,10 @@ BOOL LLCacheName::getName(const LLUUID& id, char* first, char* last)
 						: CN_WAITING);
 		strcpy(last, "");	/*Flawfinder: ignore*/
 
-		impl.mAskNameQueue.push_back(id);
+		if (!impl.isRequestPending(id))
+		{
+			impl.mAskNameQueue.insert(id);
+		}	
 		return FALSE;
 	}
 
@@ -476,8 +488,10 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, char* group)
 		// The function signature needs to change to pass in the length
 		// of first and last.
 		strcpy(group, CN_WAITING);	/*Flawfinder: ignore*/
-
-		impl.mAskGroupQueue.push_back(id);
+		if (!impl.isRequestPending(id))
+		{
+			impl.mAskGroupQueue.insert(id);
+		}
 		return FALSE;
 	}
 }
@@ -505,13 +519,16 @@ void LLCacheName::get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callb
 	}
 	else
 	{
-		if (!is_group)
-		{
-			impl.mAskNameQueue.push_back(id);
-		}
-		else
+		if (!impl.isRequestPending(id))
 		{
-			impl.mAskGroupQueue.push_back(id);
+			if (!is_group)
+			{
+				impl.mAskNameQueue.insert(id);
+			}
+			else
+			{
+				impl.mAskGroupQueue.insert(id);
+			}
 		}
 		impl.mReplyQueue.push_back(PendingReply(id, callback, user_data));
 	}
@@ -550,6 +567,19 @@ void LLCacheName::deleteEntriesOlderThan(S32 secs)
 			impl.mCache.erase(curiter);
 		}
 	}
+
+	// These are pending requests that we never heard back from.
+	U32 pending_expire_time = now - PENDING_TIMEOUT_SECS;
+	for(PendingQueue::iterator p_iter = impl.mPendingQueue.begin();
+		p_iter != impl.mPendingQueue.end(); )
+	{
+		PendingQueue::iterator p_curitor = p_iter++;
+ 
+		if (p_curitor->second < pending_expire_time)
+		{
+			impl.mPendingQueue.erase(p_curitor);
+		}
+	}
 }
 
 
@@ -579,6 +609,18 @@ void LLCacheName::dump()
 	}
 }
 
+void LLCacheName::dumpStats()
+{
+	llinfos << "Queue sizes: "
+			<< " Cache=" << impl.mCache.size()
+			<< " AskName=" << impl.mAskNameQueue.size()
+			<< " AskGroup=" << impl.mAskGroupQueue.size()
+			<< " Pending=" << impl.mPendingQueue.size()
+			<< " Reply=" << impl.mReplyQueue.size()
+			<< " Observers=" << impl.mObservers.size()
+			<< llendl;
+}
+
 void LLCacheName::Impl::processPendingAsks()
 {
 	sendRequest(_PREHASH_UUIDNameRequest, mAskNameQueue);
@@ -682,7 +724,23 @@ void LLCacheName::Impl::notifyObservers(const LLUUID& id,
 	}
 }
 
+bool LLCacheName::Impl::isRequestPending(const LLUUID& id)
+{
+	U32 now = (U32)time(NULL);
+	U32 expire_time = now - PENDING_TIMEOUT_SECS;
 
+	PendingQueue::iterator iter = mPendingQueue.find(id);
+
+	if (iter == mPendingQueue.end()
+		|| (iter->second < expire_time) )
+	{
+		mPendingQueue[id] = now;
+		return false;
+	}
+
+	return true;
+}
+	
 void LLCacheName::Impl::processUUIDRequest(LLMessageSystem* msg, bool isGroup)
 {
 	// You should only get this message if the cache is at the simulator
@@ -720,13 +778,16 @@ void LLCacheName::Impl::processUUIDRequest(LLMessageSystem* msg, bool isGroup)
 		}
 		else
 		{
-			if (isGroup)
+			if (!isRequestPending(id))
 			{
-				mAskGroupQueue.push_back(id);
-			}
-			else
-			{
-				mAskNameQueue.push_back(id);
+				if (isGroup)
+				{
+					mAskGroupQueue.insert(id);
+				}
+				else
+				{
+					mAskNameQueue.insert(id);
+				}
 			}
 			
 			mReplyQueue.push_back(PendingReply(id, fromHost));
@@ -750,6 +811,8 @@ void LLCacheName::Impl::processUUIDReply(LLMessageSystem* msg, bool isGroup)
 			mCache[id] = entry;
 		}
 
+		mPendingQueue.erase(id);
+
 		entry->mIsGroup = isGroup;
 		entry->mCreateTime = (U32)time(NULL);
 		if (!isGroup)
diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h
index af49903c88..c4f88ac490 100644
--- a/indra/llmessage/llcachename.h
+++ b/indra/llmessage/llcachename.h
@@ -78,7 +78,8 @@ public:
 	void deleteEntriesOlderThan(S32 secs);
 
 	// Debugging
-	void dump();
+	void dump();		// Dumps the contents of the cache
+	void dumpStats();	// Dumps the sizes of the cache and associated queues.
 
 private:
 	class Impl;
diff --git a/indra/llmessage/llhost.cpp b/indra/llmessage/llhost.cpp
index d395188b72..6a74cfe831 100644
--- a/indra/llmessage/llhost.cpp
+++ b/indra/llmessage/llhost.cpp
@@ -28,7 +28,7 @@ LLHost LLHost::invalid(INVALID_PORT,INVALID_HOST_IP_ADDRESS);
 LLHost::LLHost(const std::string& ip_and_port)
 {
 	std::string::size_type colon_index = ip_and_port.find(":");
-	if (colon_index != std::string::npos)
+	if (colon_index == std::string::npos)
 	{
 		mIP = ip_string_to_u32(ip_and_port.c_str());
 		mPort = 0;
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
index 121cbd2e68..92c309f1bc 100644
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -18,6 +18,7 @@
 #include "llvfile.h"
 #include "llvfs.h"
 
+#include "message.h"
 #include <curl/curl.h>
 
 const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f;
@@ -92,6 +93,14 @@ namespace
 			if (200 <= mStatus && mStatus < 300)
 			{
 				LLSDSerialize::fromXML(content, istr);
+/*
+				const S32 parseError = -1;
+				if(LLSDSerialize::fromXML(content, istr) == parseError)
+				{
+					mStatus = 498;
+					mReason = "Client Parse Error";
+				}
+*/
 			}
 
 			if (mResponder.get())
@@ -232,10 +241,17 @@ static void request(const std::string& url, LLURLRequest::ERequestAction method,
 	}
 	req->setCallback(new LLHTTPClientURLAdaptor(responder));
 
+	if (method == LLURLRequest::HTTP_POST  &&  gMessageSystem) {
+		req->addHeader(llformat("X-SecondLife-UDP-Listen-Port: %d",
+								gMessageSystem->mPort).c_str());
+   	}
+	
 	if (method == LLURLRequest::HTTP_PUT || method == LLURLRequest::HTTP_POST)
 	{
-		req->addHeader(llformat("Content-Type: %s", body_injector->contentType()).c_str());
-		chain.push_back(LLIOPipe::ptr_t(body_injector));
+		req->addHeader(llformat("Content-Type: %s",
+								body_injector->contentType()).c_str());
+
+   		chain.push_back(LLIOPipe::ptr_t(body_injector));
 	}
 	chain.push_back(LLIOPipe::ptr_t(req));
 
@@ -293,6 +309,14 @@ LLSD LLHTTPClient::blockingGet(const std::string& url)
 
 	LLHTTPBuffer http_buffer;
 
+	// Without this timeout, blockingGet() calls have been observed to take
+	// up to 90 seconds to complete.  Users of blockingGet() already must 
+	// check the HTTP return code for validity, so this will not introduce
+	// new errors.  A 5 second timeout will succeed > 95% of the time (and 
+	// probably > 99% of the time) based on my statistics. JC
+	curl_easy_setopt(curlp, CURLOPT_NOSIGNAL, 1);	// don't use SIGALRM for timeouts
+	curl_easy_setopt(curlp, CURLOPT_TIMEOUT, 5);	// seconds
+
 	curl_easy_setopt(curlp, CURLOPT_WRITEFUNCTION, LLHTTPBuffer::curl_write);
 	curl_easy_setopt(curlp, CURLOPT_WRITEDATA, &http_buffer);
 	curl_easy_setopt(curlp, CURLOPT_URL, url.c_str());
@@ -382,7 +406,7 @@ namespace boost
 	
 	void intrusive_ptr_release(LLHTTPClient::Responder* p)
 	{
-		if(0 == --p->mReferenceCount)
+		if(p && 0 == --p->mReferenceCount)
 		{
 			delete p;
 		}
diff --git a/indra/llmessage/llhttpsender.cpp b/indra/llmessage/llhttpsender.cpp
new file mode 100644
index 0000000000..4152dedae5
--- /dev/null
+++ b/indra/llmessage/llhttpsender.cpp
@@ -0,0 +1,70 @@
+/** 
+ * @file llhttpsender.cpp
+ * @brief Abstracts details of sending messages via HTTP.
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "linden_common.h"
+
+#include "llhttpsender.h"
+
+#include <map>
+#include <sstream>
+
+#include "llhost.h"
+#include "llsd.h"
+
+namespace
+{
+	typedef std::map<LLHost, LLHTTPSender*> SenderMap;
+	static SenderMap senderMap;
+}
+
+//virtual 
+LLHTTPSender::~LLHTTPSender()
+{
+}
+
+//virtual 
+void LLHTTPSender::send(const LLHost& host, const char* name, 
+						const LLSD& body, 
+						LLHTTPClient::ResponderPtr response) const
+{
+	// Default implementation inserts sender, message and sends HTTP POST
+	std::ostringstream stream;
+	stream << "http://" << host << "/trusted-message/" << name;
+	llinfos << "LLHTTPSender::send: POST to " << stream.str() << llendl;
+	LLHTTPClient::post(stream.str(), body, response);
+}
+
+//static 
+void LLHTTPSender::setSender(const LLHost& host, LLHTTPSender* sender)
+{
+	llinfos << "LLHTTPSender::setSender " << host << llendl;
+	senderMap[host] = sender;
+}
+
+//static
+const LLHTTPSender& LLHTTPSender::getSender(const LLHost& host)
+{
+	static LLHTTPSender defaultSender;
+	SenderMap::const_iterator iter = senderMap.find(host);
+	if(iter == senderMap.end())
+	{
+		return defaultSender;
+	}
+	return *(iter->second);
+}
+
+//static 
+void LLHTTPSender::clearSender(const LLHost& host)
+{
+	SenderMap::iterator iter = senderMap.find(host);
+	if(iter != senderMap.end())
+	{
+		delete iter->second;
+		senderMap.erase(iter);
+	}
+}
diff --git a/indra/llmessage/llhttpsender.h b/indra/llmessage/llhttpsender.h
new file mode 100644
index 0000000000..a9f42579c2
--- /dev/null
+++ b/indra/llmessage/llhttpsender.h
@@ -0,0 +1,38 @@
+/** 
+ * @file llhttpsender.h
+ * @brief Abstracts details of sending messages via HTTP.
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#ifndef LL_HTTP_SENDER_H
+#define LL_HTTP_SENDER_H
+
+#include "llhttpclient.h"
+
+class LLHost;
+class LLSD;
+
+class LLHTTPSender
+{
+ public:
+
+	virtual ~LLHTTPSender();
+
+	/** @brief Send message to host with body, call response when done */ 
+	virtual void send(const LLHost& host, 
+					  const char* message, const LLSD& body, 
+					  LLHTTPClient::ResponderPtr response) const;
+
+	/** @brief Set sender for host, takes ownership of sender. */
+	static void setSender(const LLHost& host, LLHTTPSender* sender);
+
+	/** @brief Get sender for host, retains ownership of returned sender. */
+	static const LLHTTPSender& getSender(const LLHost& host);
+	
+	/** @brief Clear sender for host. */
+	static void clearSender(const LLHost& host);
+};
+
+#endif // LL_HTTP_SENDER_H
diff --git a/indra/llmessage/llinstantmessage.cpp b/indra/llmessage/llinstantmessage.cpp
index 944785c3a5..28886108ea 100644
--- a/indra/llmessage/llinstantmessage.cpp
+++ b/indra/llmessage/llinstantmessage.cpp
@@ -16,6 +16,7 @@
 #include "lluuid.h"
 #include "llsd.h"
 #include "llsdserialize.h"
+#include "llsdutil.h"
 #include "llmemory.h"
 #include "message.h"
 
@@ -290,6 +291,35 @@ void LLIMInfo::unpackMessageBlock(LLMessageSystem* msg)
 	}
 }
 
+LLSD im_info_to_llsd(LLPointer<LLIMInfo> im_info)
+{
+	LLSD param_version;
+	param_version["version"] = 1;
+	LLSD param_message;
+	param_message["from_id"] = im_info->mFromID;
+	param_message["from_group"] = im_info->mFromGroup;
+	param_message["to_id"] = im_info->mToID;
+	param_message["from_name"] = im_info->mName;
+	param_message["message"] = im_info->mMessage;
+	param_message["type"] = (S32)im_info->mIMType;
+	param_message["id"] = im_info->mID;
+	param_message["timestamp"] = (S32)im_info->mTimeStamp;
+	param_message["offline"] = (S32)im_info->mOffline;
+	param_message["parent_estate_id"] = (S32)im_info->mParentEstateID;
+	param_message["region_id"] = im_info->mRegionID;
+	param_message["position"] = ll_sd_from_vector3(im_info->mPosition);
+	if (im_info->mData) param_message["data"] = im_info->mData;
+	LLSD param_agent;
+	param_agent["agent_id"] = im_info->mFromID;
+
+	LLSD params;
+	params.append(param_version);
+	params.append(param_message);
+	params.append(param_agent);
+
+	return params;
+}
+
 LLPointer<LLIMInfo> LLIMInfo::clone()
 {
 	return new LLIMInfo(
diff --git a/indra/llmessage/llinstantmessage.h b/indra/llmessage/llinstantmessage.h
index c8138cf491..99b2734a70 100644
--- a/indra/llmessage/llinstantmessage.h
+++ b/indra/llmessage/llinstantmessage.h
@@ -74,17 +74,19 @@ enum EInstantMessage
 	// communicate with each other.
 	//
 
-	// Start a session, or add users to a session.
+	// Add users to a session.
 	IM_SESSION_ADD = 13,
 
-	// Start a session, but don't prune offline users
-	IM_SESSION_OFFLINE_ADD = 14,
+	// IM sent automatically on call for help, 
+	// sets up a way for each Helper reached to teleport to the
+	// helpee
+	IM_SESSION_911_SEND = 14,
 
 	// start a session with your gruop
 	IM_SESSION_GROUP_START = 15,
 
 	// start a session without a calling card (finder or objects)
-	IM_SESSION_CARDLESS_START = 16,
+	IM_SESSION_CONFERENCE_START = 16,
 
 	// send a message to a session.
 	IM_SESSION_SEND = 17,
@@ -123,9 +125,9 @@ enum EInstantMessage
 	// Binary bucket contains the name of the session.
 	IM_SESSION_911_START = 29,
 
-	// IM sent automatically on call for help, 
-	// sends a lure to each Helper reached
-	IM_LURE_911 = 30,
+	// IM for requesting to teleport to the creator
+	// of a livehelp session (assuming they are verified first)
+	IM_TELEPORT_911 = 30,
 
 	// a message generated by a script which we don't want to
 	// be sent through e-mail.  Similar to IM_FROM_TASK, but
@@ -266,6 +268,7 @@ public:
 	S32 mTTL;
 };
 
+LLSD im_info_to_llsd(LLPointer<LLIMInfo> im_info);
 
 void pack_instant_message(
 	LLMessageSystem* msgsystem,
diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp
index c1a9bc442e..869012e431 100644
--- a/indra/llmessage/lliohttpserver.cpp
+++ b/indra/llmessage/lliohttpserver.cpp
@@ -27,6 +27,8 @@
 #include "llsdserialize_xml.h"
 #include "llstl.h"
 
+#include <sstream>
+
 static const char HTTP_VERSION_STR[] = "HTTP/1.0";
 static const std::string CONTEXT_REQUEST("request");
 static const std::string HTTP_VERB_GET("GET");
@@ -374,7 +376,7 @@ LLIOPipe::EStatus LLHTTPResponseHeader::process_impl(
 class LLHTTPResponder : public LLIOPipe
 {
 public:
-	LLHTTPResponder(const LLHTTPNode& tree);
+	LLHTTPResponder(const LLHTTPNode& tree, const LLSD& ctx);
 	~LLHTTPResponder();
 
 protected:
@@ -435,6 +437,7 @@ protected:
 		STATE_SHORT_CIRCUIT
 	};
 
+	LLSD mBuildContext;
 	EState mState;
 	U8* mLastRead;
 	std::string mVerb;
@@ -443,12 +446,14 @@ protected:
 	std::string mQuery;
 	std::string mVersion;
 	S32 mContentLength;
+	LLSD mHeaders;
 
 	// handle the urls
 	const LLHTTPNode& mRootNode;
 };
 
-LLHTTPResponder::LLHTTPResponder(const LLHTTPNode& tree) :
+LLHTTPResponder::LLHTTPResponder(const LLHTTPNode& tree, const LLSD& ctx) :
+	mBuildContext(ctx),
 	mState(STATE_NOTHING),
 	mLastRead(NULL),
 	mContentLength(0),
@@ -636,6 +641,11 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
 						lldebugs << "Content-Length: " << value << llendl;
 						mContentLength = atoi(value.c_str());
 					}
+					else
+					{
+						LLString::trimTail(value);
+						mHeaders[name] = value;
+					}
 				}
 			}
 		}
@@ -701,6 +711,11 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
 			chain.push_back(LLIOPipe::ptr_t(new LLIOFlush));
 			context[CONTEXT_REQUEST]["path"] = mPath;
 			context[CONTEXT_REQUEST]["query-string"] = mQuery;
+			context[CONTEXT_REQUEST]["remote-host"]
+				= mBuildContext["remote-host"];
+			context[CONTEXT_REQUEST]["remote-port"]
+				= mBuildContext["remote-port"];
+			context[CONTEXT_REQUEST]["headers"] = mHeaders;
 
 			const LLChainIOFactory* protocolHandler
 				= node->getProtocolHandler();
@@ -785,9 +800,10 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
 
 
 
-void LLCreateHTTPPipe(LLPumpIO::chain_t& chain, const LLHTTPNode& root)
+void LLCreateHTTPPipe(LLPumpIO::chain_t& chain,
+		const LLHTTPNode& root, const LLSD& ctx)
 {
-	chain.push_back(LLIOPipe::ptr_t(new LLHTTPResponder(root)));
+	chain.push_back(LLIOPipe::ptr_t(new LLHTTPResponder(root, ctx)));
 }
 
 
@@ -796,7 +812,7 @@ class LLHTTPResponseFactory : public LLChainIOFactory
 public:
 	bool build(LLPumpIO::chain_t& chain, LLSD ctx) const
 	{
-		LLCreateHTTPPipe(chain, mTree);
+		LLCreateHTTPPipe(chain, mTree, ctx);
 		return true;
 	}
 
diff --git a/indra/llmessage/lliohttpserver.h b/indra/llmessage/lliohttpserver.h
index 05dfdc4bf7..f11a1eccf6 100644
--- a/indra/llmessage/lliohttpserver.h
+++ b/indra/llmessage/lliohttpserver.h
@@ -31,7 +31,8 @@ LLHTTPNode& LLCreateHTTPServer(apr_pool_t* pool, LLPumpIO& pump, U16 port);
 	 *   for example), use the helper templates below.
 	 */
  
-void LLCreateHTTPPipe(LLPumpIO::chain_t& chain, const LLHTTPNode& root);
+void LLCreateHTTPPipe(LLPumpIO::chain_t& chain,
+		const LLHTTPNode& root, const LLSD& ctx);
 	/**< Create a pipe on the chain that handles HTTP requests.
 	 *   The requests are served by the node tree given at root.
 	 *
diff --git a/indra/llmessage/lliopipe.h b/indra/llmessage/lliopipe.h
index 5cbe3d8743..6f7fbe652d 100644
--- a/indra/llmessage/lliopipe.h
+++ b/indra/llmessage/lliopipe.h
@@ -237,7 +237,7 @@ namespace boost
 	}
 	inline void intrusive_ptr_release(LLIOPipe* p)
 	{
-		if(0 == --p->mReferenceCount)
+		if(p && 0 == --p->mReferenceCount)
 		{
 			delete p;
 		}
diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp
index 7649fef0cf..7c33153086 100644
--- a/indra/llmessage/lliosocket.cpp
+++ b/indra/llmessage/lliosocket.cpp
@@ -519,9 +519,20 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(
 	if(llsocket)
 	{
 		PUMP_DEBUG;
+
+		apr_sockaddr_t* remote_addr;
+		apr_socket_addr_get(&remote_addr, APR_REMOTE, socket);
+		
+		char* remote_host_string;
+		apr_sockaddr_ip_get(&remote_host_string, remote_addr);
+
+		LLSD context;
+		context["remote-host"] = remote_host_string;
+		context["remote-port"] = remote_addr->port;
+
 		LLPumpIO::chain_t chain;
 		chain.push_back(LLIOPipe::ptr_t(new LLIOSocketReader(llsocket)));
-		if(mReactor->build(chain, LLSD()))
+		if(mReactor->build(chain, context))
 		{
 			chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(llsocket)));
 			pump->addChain(chain, mResponseTimeout);
diff --git a/indra/llmessage/llmessagebuilder.cpp b/indra/llmessage/llmessagebuilder.cpp
new file mode 100644
index 0000000000..d467e6d808
--- /dev/null
+++ b/indra/llmessage/llmessagebuilder.cpp
@@ -0,0 +1,18 @@
+/** 
+ * @file llmessagebuilder.cpp
+ * @brief LLMessageBuilder class implementation
+ *
+ * Copyright (c) 2006-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "linden_common.h"
+
+#include "llmessagebuilder.h"
+
+//virtual
+LLMessageBuilder::~LLMessageBuilder()
+{
+	// even abstract base classes need a concrete destructor
+}
+
diff --git a/indra/llmessage/llmessagebuilder.h b/indra/llmessage/llmessagebuilder.h
new file mode 100644
index 0000000000..7ae09c54d5
--- /dev/null
+++ b/indra/llmessage/llmessagebuilder.h
@@ -0,0 +1,70 @@
+#ifndef LL_LLMESSAGEBUILDER_H
+#define LL_LLMESSAGEBUILDER_H
+
+#include <string>
+
+#include "stdtypes.h"
+
+class LLMsgData;
+class LLQuaternion;
+class LLSD;
+class LLUUID;
+class LLVector3;
+class LLVector3d;
+class LLVector4;
+
+class LLMessageBuilder
+{
+public:
+
+	//CLASS_LOG_TYPE(LLMessageBuilder);
+	
+	virtual ~LLMessageBuilder();
+	virtual void newMessage(const char *name) = 0;
+
+	virtual void nextBlock(const char* blockname) = 0;
+	virtual BOOL removeLastBlock() = 0; // TODO: babbage: remove this horror
+
+	/** All add* methods expect pointers to canonical strings. */
+	virtual void addBinaryData(const char *varname, const void *data, 
+							   S32 size) = 0;
+	virtual void addBOOL(const char* varname, BOOL b) = 0;
+	virtual void addS8(const char *varname, S8 s) = 0;
+	virtual void addU8(const char *varname, U8 u) = 0;
+	virtual void addS16(const char *varname, S16 i) = 0;
+	virtual void addU16(const char *varname, U16 i) = 0;
+	virtual void addF32(const char *varname, F32 f) = 0;
+	virtual void addS32(const char *varname, S32 s) = 0;
+	virtual void addU32(const char *varname, U32 u) = 0;
+	virtual void addU64(const char *varname, U64 lu) = 0;
+	virtual void addF64(const char *varname, F64 d) = 0;
+	virtual void addVector3(const char *varname, const LLVector3& vec) = 0;
+	virtual void addVector4(const char *varname, const LLVector4& vec) = 0;
+	virtual void addVector3d(const char *varname, const LLVector3d& vec) = 0;
+	virtual void addQuat(const char *varname, const LLQuaternion& quat) = 0;
+	virtual void addUUID(const char *varname, const LLUUID& uuid) = 0;
+	virtual void addIPAddr(const char *varname, const U32 ip) = 0;
+	virtual void addIPPort(const char *varname, const U16 port) = 0;
+	virtual void addString(const char* varname, const char* s) = 0;
+	virtual void addString(const char* varname, const std::string& s) = 0;
+
+	virtual BOOL isMessageFull(const char* blockname) const = 0;
+	virtual void compressMessage(U8*& buf_ptr, U32& buffer_length) = 0;
+	virtual S32 getMessageSize() = 0;
+
+	virtual BOOL isBuilt() const = 0;
+	virtual BOOL isClear() const = 0;
+	virtual U32 buildMessage(U8* buffer, U32 buffer_size) = 0; 
+        /**< Return built message size */
+	virtual void clearMessage() = 0;
+
+	// TODO: babbage: remove this horror
+	virtual void setBuilt(BOOL b) = 0;
+
+	virtual const char* getMessageName() const = 0;
+
+	virtual void copyFromMessageData(const LLMsgData& data) = 0;
+	virtual void copyFromLLSD(const LLSD& data) = 0;
+};
+
+#endif //  LL_LLMESSAGEBUILDER_H
diff --git a/indra/llmessage/llmessageconfig.cpp b/indra/llmessage/llmessageconfig.cpp
new file mode 100644
index 0000000000..a2b0bc5efa
--- /dev/null
+++ b/indra/llmessage/llmessageconfig.cpp
@@ -0,0 +1,210 @@
+/** 
+ * @file llmessageconfig.cpp
+ * @brief Live file handling for messaging
+ *
+ * Copyright (c) 2000-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "linden_common.h"
+
+#include "llmessageconfig.h"
+#include "llfile.h"
+#include "lllivefile.h"
+#include "llsd.h"
+#include "llsdserialize.h"
+
+static const char messageConfigFileName[] = "message.xml";
+static const F32 messageConfigRefreshRate = 5.0; // seconds
+static std::string sServerName = "";
+static std::string sConfigDir = "";
+
+class LLMessageConfigFile : public LLLiveFile
+{
+private:
+	LLMessageConfigFile()
+        : LLLiveFile(fileName(), messageConfigRefreshRate),
+		  mChanged(false)
+            { }
+
+    static std::string fileName();
+    
+public:
+	static LLMessageConfigFile& instance();
+		// return the singleton configuration file
+
+protected:
+	/* virtual */ void loadFile();
+	void loadServerDefaults(const LLSD& data);
+	void loadMessages(const LLSD& data);
+
+public:
+    bool mChanged;
+	
+	std::string mServerDefault;
+	LLSD mMessages;
+};
+
+std::string LLMessageConfigFile::fileName()
+{
+    std::ostringstream ostr;
+	ostr << sConfigDir//gAppSimp->getOption("configdir").asString()
+		<< "/" << messageConfigFileName;
+	return ostr.str();
+}
+
+LLMessageConfigFile& LLMessageConfigFile::instance()
+{
+	static LLMessageConfigFile the_file;
+	the_file.checkAndReload();
+	return the_file;
+}
+
+// virtual
+void LLMessageConfigFile::loadFile()
+{
+	LLSD data;
+    {
+        llifstream file(filename().c_str());
+        if (file.is_open())
+        {
+			llinfos << "Loading message.xml file at " << fileName() << llendl;
+            LLSDSerialize::fromXML(data, file);
+        }
+
+        if (data.isUndefined())
+        {
+            llinfos << "LLMessageConfigFile::loadFile: file missing,"
+				" ill-formed, or simply undefined; not changing the"
+				" file" << llendl;
+            return;
+        }
+    }
+	loadServerDefaults(data);
+	loadMessages(data);
+}
+
+void LLMessageConfigFile::loadServerDefaults(const LLSD& data)
+{
+	mServerDefault = data["serverDefaults"][sServerName].asString();
+	lldebugs << "loading default " << mServerDefault << llendl;
+}
+
+void LLMessageConfigFile::loadMessages(const LLSD& data)
+{
+	mMessages = data["messages"];
+	std::ostringstream out;
+	LLSDXMLFormatter *formatter = new LLSDXMLFormatter;
+	formatter->format(mMessages, out);
+	lldebugs << "loading ... " << out.str()
+			<< " LLMessageConfigFile::loadMessages loaded "
+			<< mMessages.size() << " messages" << llendl;
+}
+
+
+//---------------------------------------------------------------
+// LLMessageConfig
+//---------------------------------------------------------------
+
+//static
+void LLMessageConfig::initClass(const std::string& server_name,
+								const std::string& config_dir)
+{
+	sServerName = server_name;
+	sConfigDir = config_dir;
+	(void) LLMessageConfigFile::instance();
+	llinfos << "LLMessageConfig::intiClass config file "
+			<< config_dir << "/" << messageConfigFileName << llendl;
+}
+
+//static
+bool LLMessageConfig::isServerDefaultBuilderLLSD()
+{
+	if (sServerName.empty())
+	{
+		llerrs << "LLMessageConfig::isServerDefaultBuilderLLSD() before"
+				<< " LLMessageConfig::initClass()" << llendl;
+	}
+	LLMessageConfigFile& file = LLMessageConfigFile::instance();
+	return (file.mServerDefault == "llsd");
+}
+
+//static
+bool LLMessageConfig::isServerDefaultBuilderTemplate()
+{
+	if (sServerName.empty())
+	{
+		llerrs << "LLMessageConfig::isServerDefaultBuilderTemplate() before"
+				<< " LLMessageConfig::initClass()" << llendl;
+	}
+	LLMessageConfigFile& file = LLMessageConfigFile::instance();
+	return (file.mServerDefault == "template");
+}
+
+//static
+bool LLMessageConfig::isMessageBuiltLLSD(const std::string& msg_name)
+{
+	if (sServerName.empty())
+	{
+		llerrs << "LLMessageConfig::isMessageBuiltLLSD(name) before"
+				<< " LLMessageConfig::initClass()" << llendl;
+	}
+	LLMessageConfigFile& file = LLMessageConfigFile::instance();
+	LLSD config = file.mMessages[msg_name];
+	if (!config.has("builder"))
+	{
+		return isServerDefaultBuilderLLSD();
+	}
+	return (config["builder"].asString() == "llsd");
+}
+
+//static
+bool LLMessageConfig::isMessageBuiltTemplate(const std::string& msg_name)
+{
+	if (sServerName.empty())
+	{
+		llerrs << "LLMessageConfig::isMessageBuiltTemplate(name) before"
+				<< " LLMessageConfig::initClass()" << llendl;
+	}
+	LLMessageConfigFile& file = LLMessageConfigFile::instance();
+	LLSD config = file.mMessages[msg_name];
+	if (!config.has("builder"))
+	{
+		return isServerDefaultBuilderTemplate();
+	}
+	return (config["builder"].asString() == "template");
+}
+
+//static
+bool LLMessageConfig::isMessageTrusted(const std::string& msg_name)
+{
+	if (sServerName.empty())
+	{
+		llerrs << "LLMessageConfig::isMessageTrusted(name) before"
+				<< " LLMessageConfig::initClass()" << llendl;
+	}
+	LLMessageConfigFile& file = LLMessageConfigFile::instance();
+	LLSD config = file.mMessages[msg_name];
+	if (!config.has("trusted-sender"))
+	{
+		return false;
+	}
+	return config["trusted-sender"].asBoolean();
+}
+
+//static
+bool LLMessageConfig::isValidUntrustedMessage(const std::string& msg_name)
+{
+	if (sServerName.empty())
+	{
+		llerrs << "LLMessageConfig::isMessageTrusted(name) before"
+				<< " LLMessageConfig::initClass()" << llendl;
+	}
+	LLMessageConfigFile& file = LLMessageConfigFile::instance();
+	LLSD config = file.mMessages[msg_name];
+	if (!config.has("trusted-sender"))
+	{
+		return false;
+	}
+	return !(config["trusted-sender"].asBoolean());
+}
diff --git a/indra/llmessage/llmessageconfig.h b/indra/llmessage/llmessageconfig.h
new file mode 100644
index 0000000000..2fb6f2077e
--- /dev/null
+++ b/indra/llmessage/llmessageconfig.h
@@ -0,0 +1,31 @@
+/** 
+ * @file llmessageconfig.h
+ * @brief Live file handling for messaging
+ *
+ * Copyright (c) 2000-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#ifndef LL_MESSAGECONFIG_H
+#define LL_MESSAGECONFIG_H
+
+#include <string>
+
+class LLMessageConfig
+{
+public:
+	static void initClass(const std::string& server_name,
+						  const std::string& config_dir);
+		// force loading of config file during startup process
+		// so it can be used for startup features
+
+	static bool isServerDefaultBuilderLLSD();
+	static bool isServerDefaultBuilderTemplate();
+
+	// For individual messages
+	static bool isMessageBuiltLLSD(const std::string& msg_name);
+	static bool isMessageBuiltTemplate(const std::string& msg_name);
+	static bool isMessageTrusted(const std::string& msg_name);
+	static bool isValidUntrustedMessage(const std::string& msg_name);
+};
+#endif // LL_MESSAGECONFIG_H
diff --git a/indra/llmessage/llmessagereader.cpp b/indra/llmessage/llmessagereader.cpp
new file mode 100644
index 0000000000..4824480e32
--- /dev/null
+++ b/indra/llmessage/llmessagereader.cpp
@@ -0,0 +1,35 @@
+#include "llmessagereader.h"
+
+static BOOL sTimeDecodes = FALSE;
+
+static F32 sTimeDecodesSpamThreshold = 0.05f;
+
+//virtual
+LLMessageReader::~LLMessageReader()
+{
+	// even abstract base classes need a concrete destructor
+}
+
+//static 
+void LLMessageReader::setTimeDecodes(BOOL b)
+{
+	sTimeDecodes = b;
+}
+
+//static 
+void LLMessageReader::setTimeDecodesSpamThreshold(F32 seconds)
+{
+	sTimeDecodesSpamThreshold = seconds;
+}
+
+//static 
+BOOL LLMessageReader::getTimeDecodes()
+{
+	return sTimeDecodes;
+}
+
+//static 
+F32 LLMessageReader::getTimeDecodesSpamThreshold()
+{
+	return sTimeDecodesSpamThreshold;
+}
diff --git a/indra/llmessage/llmessagereader.h b/indra/llmessage/llmessagereader.h
new file mode 100644
index 0000000000..33ce9289f5
--- /dev/null
+++ b/indra/llmessage/llmessagereader.h
@@ -0,0 +1,59 @@
+#ifndef LL_LLMESSAGEREADER_H
+#define LL_LLMESSAGEREADER_H
+
+#include "stdtypes.h"
+
+class LLHost;
+class LLMessageBuilder;
+class LLMsgData;
+class LLQuaternion;
+class LLUUID;
+class LLVector3;
+class LLVector3d;
+class LLVector4;
+
+class LLMessageReader
+{
+ public:
+
+	virtual ~LLMessageReader();
+
+	/** All get* methods expect pointers to canonical strings. */
+	virtual void getBinaryData(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum = 0, S32 max_size = S32_MAX) = 0;
+	virtual void getBOOL(const char *block, const char *var, BOOL &data, S32 blocknum = 0) = 0;
+	virtual void getS8(const char *block, const char *var, S8 &data, S32 blocknum = 0) = 0;
+	virtual void getU8(const char *block, const char *var, U8 &data, S32 blocknum = 0) = 0;
+	virtual void getS16(const char *block, const char *var, S16 &data, S32 blocknum = 0) = 0;
+	virtual void getU16(const char *block, const char *var, U16 &data, S32 blocknum = 0) = 0;
+	virtual void getS32(const char *block, const char *var, S32 &data, S32 blocknum = 0) = 0;
+	virtual void getF32(const char *block, const char *var, F32 &data, S32 blocknum = 0) = 0;
+	virtual void getU32(const char *block, const char *var, U32 &data, S32 blocknum = 0) = 0;
+	virtual void getU64(const char *block, const char *var, U64 &data, S32 blocknum = 0) = 0;
+	virtual void getF64(const char *block, const char *var, F64 &data, S32 blocknum = 0) = 0;
+	virtual void getVector3(const char *block, const char *var, LLVector3 &vec, S32 blocknum = 0) = 0;
+	virtual void getVector4(const char *block, const char *var, LLVector4 &vec, S32 blocknum = 0) = 0;
+	virtual void getVector3d(const char *block, const char *var, LLVector3d &vec, S32 blocknum = 0) = 0;
+	virtual void getQuat(const char *block, const char *var, LLQuaternion &q, S32 blocknum = 0) = 0;
+	virtual void getUUID(const char *block, const char *var, LLUUID &uuid, S32 blocknum = 0) = 0;
+	virtual void getIPAddr(const char *block, const char *var, U32 &ip, S32 blocknum = 0) = 0;
+	virtual void getIPPort(const char *block, const char *var, U16 &port, S32 blocknum = 0) = 0;
+	virtual void getString(const char *block, const char *var, S32 buffer_size, char *buffer, S32 blocknum = 0) = 0;
+
+	virtual S32	getNumberOfBlocks(const char *blockname) = 0;
+	virtual S32	getSize(const char *blockname, const char *varname) = 0;
+	virtual S32	getSize(const char *blockname, S32 blocknum, const char *varname) = 0;
+
+	virtual void clearMessage() = 0;
+
+	virtual const char* getMessageName() const = 0;
+	virtual S32 getMessageSize() const = 0;
+
+	virtual void copyToBuilder(LLMessageBuilder&) const = 0;
+
+	static void setTimeDecodes(BOOL b);
+	static BOOL getTimeDecodes();
+	static void setTimeDecodesSpamThreshold(F32 seconds);
+	static F32 getTimeDecodesSpamThreshold();
+};
+
+#endif // LL_LLMESSAGEREADER_H
diff --git a/indra/llmessage/llmessagetemplate.cpp b/indra/llmessage/llmessagetemplate.cpp
new file mode 100644
index 0000000000..026843d6ec
--- /dev/null
+++ b/indra/llmessage/llmessagetemplate.cpp
@@ -0,0 +1,146 @@
+#include "linden_common.h"
+
+#include "llmessagetemplate.h"
+
+#include "message.h"
+
+void LLMsgVarData::addData(const void *data, S32 size, EMsgVariableType type, S32 data_size)
+{
+	mSize = size;
+	mDataSize = data_size;
+	if ( (type != MVT_VARIABLE) && (type != MVT_FIXED) 
+		 && (mType != MVT_VARIABLE) && (mType != MVT_FIXED))
+	{
+		if (mType != type)
+		{
+			llwarns << "Type mismatch in LLMsgVarData::addData for " << mName
+					<< llendl;
+		}
+	}
+	if(size)
+	{
+		delete mData; // Delete it if it already exists
+		mData = new U8[size];
+		htonmemcpy(mData, data, mType, size);
+	}
+}
+
+void LLMsgData::addDataFast(char *blockname, char *varname, const void *data, S32 size, EMsgVariableType type, S32 data_size)
+{
+	// remember that if the blocknumber is > 0 then the number is appended to the name
+	char *namep = (char *)blockname;
+	LLMsgBlkData* block_data = mMemberBlocks[namep];
+	if (block_data->mBlockNumber)
+	{
+		namep += block_data->mBlockNumber;
+		block_data->addData(varname, data, size, type, data_size);
+	}
+	else
+	{
+		block_data->addData(varname, data, size, type, data_size);
+	}
+}
+
+// LLMessageVariable functions and friends
+
+std::ostream& operator<<(std::ostream& s, LLMessageVariable &msg)
+{
+	s << "\t\t" << msg.mName << " (";
+	switch (msg.mType)
+	{
+	case MVT_FIXED:
+		s << "Fixed, " << msg.mSize << " bytes total)\n";
+		break;
+	case MVT_VARIABLE:
+		s << "Variable, " << msg.mSize << " bytes of size info)\n";
+		break;
+	default:
+		s << "Unknown\n";
+		break;
+	}
+	return s;
+}
+
+// LLMessageBlock functions and friends
+
+std::ostream& operator<<(std::ostream& s, LLMessageBlock &msg)
+{
+	s << "\t" << msg.mName << " (";
+	switch (msg.mType)
+	{
+	case MBT_SINGLE:
+		s << "Fixed";
+		break;
+	case MBT_MULTIPLE:
+		s << "Multiple - " << msg.mNumber << " copies";
+		break;
+	case MBT_VARIABLE:
+		s << "Variable";
+		break;
+	default:
+		s << "Unknown";
+		break;
+	}
+	if (msg.mTotalSize != -1)
+	{
+		s << ", " << msg.mTotalSize << " bytes each, " << msg.mNumber*msg.mTotalSize << " bytes total)\n";
+	}
+	else
+	{
+		s << ")\n";
+	}
+
+
+	for (LLMessageBlock::message_variable_map_t::iterator iter = msg.mMemberVariables.begin();
+		 iter != msg.mMemberVariables.end(); iter++)
+	{
+		LLMessageVariable& ci = *(iter->second);
+		s << ci;
+	}
+
+	return s;
+}
+
+// LLMessageTemplate functions and friends
+
+std::ostream& operator<<(std::ostream& s, LLMessageTemplate &msg)
+{
+	switch (msg.mFrequency)
+	{
+	case MFT_HIGH:
+		s << "========================================\n" << "Message #" << msg.mMessageNumber << "\n" << msg.mName << " (";
+		s << "High";
+		break;
+	case MFT_MEDIUM:
+		s << "========================================\n" << "Message #";
+		s << (msg.mMessageNumber & 0xFF) << "\n" << msg.mName << " (";
+		s << "Medium";
+		break;
+	case MFT_LOW:
+		s << "========================================\n" << "Message #";
+		s << (msg.mMessageNumber & 0xFFFF) << "\n" << msg.mName << " (";
+		s << "Low";
+		break;
+	default:
+		s << "Unknown";
+		break;
+	}
+
+	if (msg.mTotalSize != -1)
+	{
+		s << ", " << msg.mTotalSize << " bytes total)\n";
+	}
+	else
+	{
+		s << ")\n";
+	}
+	
+	for (LLMessageTemplate::message_block_map_t::iterator iter = msg.mMemberBlocks.begin();
+		 iter != msg.mMemberBlocks.end(); iter++)
+	{
+		LLMessageBlock* ci = iter->second;
+		s << *ci;
+	}
+
+	return s;
+}
diff --git a/indra/llmessage/llmessagetemplate.h b/indra/llmessage/llmessagetemplate.h
new file mode 100644
index 0000000000..8847ddc0d9
--- /dev/null
+++ b/indra/llmessage/llmessagetemplate.h
@@ -0,0 +1,356 @@
+#ifndef LL_LLMESSAGETEMPLATE_H
+#define LL_LLMESSAGETEMPLATE_H
+
+#include "lldarray.h"
+#include "message.h" // TODO: babbage: Remove...
+#include "llstl.h"
+
+class LLMsgVarData
+{
+public:
+	LLMsgVarData() : mName(NULL), mSize(-1), mDataSize(-1), mData(NULL), mType(MVT_U8)
+	{
+	}
+
+	LLMsgVarData(const char *name, EMsgVariableType type) : mSize(-1), mDataSize(-1), mData(NULL), mType(type)
+	{
+		mName = (char *)name; 
+	}
+
+	~LLMsgVarData() 
+	{
+		// copy constructor just copies the mData pointer, so only delete mData explicitly
+	}
+	
+	void deleteData() 
+	{
+		delete[] mData;
+		mData = NULL;
+	}
+	
+	void addData(const void *indata, S32 size, EMsgVariableType type, S32 data_size = -1);
+
+	char *getName() const	{ return mName; }
+	S32 getSize() const		{ return mSize; }
+	void *getData()			{ return (void*)mData; }
+	const void *getData() const { return (const void*)mData; }
+	S32 getDataSize() const	{ return mDataSize; }
+	EMsgVariableType getType() const	{ return mType; }
+
+protected:
+	char				*mName;
+	S32					mSize;
+	S32					mDataSize;
+
+	U8					*mData;
+	EMsgVariableType	mType;
+};
+
+class LLMsgBlkData
+{
+public:
+	LLMsgBlkData(const char *name, S32 blocknum) : mOffset(-1), mBlockNumber(blocknum), mTotalSize(-1) 
+	{ 
+		mName = (char *)name; 
+	}
+
+	~LLMsgBlkData()
+	{
+		for (msg_var_data_map_t::iterator iter = mMemberVarData.begin();
+			 iter != mMemberVarData.end(); iter++)
+		{
+			iter->deleteData();
+		}
+	}
+
+	void addVariable(const char *name, EMsgVariableType type)
+	{
+		LLMsgVarData tmp(name,type);
+		mMemberVarData[name] = tmp;
+	}
+
+	void addData(char *name, const void *data, S32 size, EMsgVariableType type, S32 data_size = -1)
+	{
+		LLMsgVarData* temp = &mMemberVarData[name]; // creates a new entry if one doesn't exist
+		temp->addData(data, size, type, data_size);
+	}
+
+	S32									mOffset;
+	S32									mBlockNumber;
+	typedef LLDynamicArrayIndexed<LLMsgVarData, const char *, 8> msg_var_data_map_t;
+	msg_var_data_map_t					mMemberVarData;
+	char								*mName;
+	S32									mTotalSize;
+};
+
+class LLMsgData
+{
+public:
+	LLMsgData(const char *name) : mTotalSize(-1) 
+	{ 
+		mName = (char *)name; 
+	}
+	~LLMsgData()
+	{
+		for_each(mMemberBlocks.begin(), mMemberBlocks.end(), DeletePairedPointer());
+	}
+
+	void addBlock(LLMsgBlkData *blockp)
+	{
+		mMemberBlocks[blockp->mName] = blockp;
+	}
+
+	void addDataFast(char *blockname, char *varname, const void *data, S32 size, EMsgVariableType type, S32 data_size = -1);
+
+public:
+	S32									mOffset;
+	typedef std::map<char*, LLMsgBlkData*> msg_blk_data_map_t;
+	msg_blk_data_map_t					mMemberBlocks;
+	char								*mName;
+	S32									mTotalSize;
+};
+
+// LLMessage* classes store the template of messages
+class LLMessageVariable
+{
+public:
+	LLMessageVariable() : mName(NULL), mType(MVT_NULL), mSize(-1)
+	{
+	}
+
+	LLMessageVariable(char *name) : mType(MVT_NULL), mSize(-1)
+	{
+		mName = name;
+	}
+
+	LLMessageVariable(char *name, const EMsgVariableType type, const S32 size) : mType(type), mSize(size) 
+	{
+		mName = gMessageStringTable.getString(name); 
+	}
+	
+	~LLMessageVariable() {}
+
+	friend std::ostream&	 operator<<(std::ostream& s, LLMessageVariable &msg);
+
+	EMsgVariableType getType() const				{ return mType; }
+	S32	getSize() const								{ return mSize; }
+	char *getName() const							{ return mName; }
+protected:
+	char				*mName;
+	EMsgVariableType	mType;
+	S32					mSize;
+};
+
+
+typedef enum e_message_block_type
+{
+	MBT_NULL,
+	MBT_SINGLE,
+	MBT_MULTIPLE,
+	MBT_VARIABLE,
+	MBT_EOF
+} EMsgBlockType;
+
+class LLMessageBlock
+{
+public:
+	LLMessageBlock(char *name, EMsgBlockType type, S32 number = 1) : mType(type), mNumber(number), mTotalSize(0) 
+	{ 
+		mName = gMessageStringTable.getString(name);
+	}
+
+	~LLMessageBlock()
+	{
+		for_each(mMemberVariables.begin(), mMemberVariables.end(), DeletePairedPointer());
+	}
+
+	void addVariable(char *name, const EMsgVariableType type, const S32 size)
+	{
+		LLMessageVariable** varp = &mMemberVariables[name];
+		if (*varp != NULL)
+		{
+			llerrs << name << " has already been used as a variable name!" << llendl;
+		}
+		*varp = new LLMessageVariable(name, type, size);
+		if (((*varp)->getType() != MVT_VARIABLE)
+			&&(mTotalSize != -1))
+		{
+			mTotalSize += (*varp)->getSize();
+		}
+		else
+		{
+			mTotalSize = -1;
+		}
+	}
+
+	EMsgVariableType getVariableType(char *name)
+	{
+		return (mMemberVariables[name])->getType();
+	}
+
+	S32 getVariableSize(char *name)
+	{
+		return (mMemberVariables[name])->getSize();
+	}
+
+	friend std::ostream&	 operator<<(std::ostream& s, LLMessageBlock &msg);
+
+	typedef std::map<const char *, LLMessageVariable*> message_variable_map_t;
+	message_variable_map_t 					mMemberVariables;
+	char									*mName;
+	EMsgBlockType							mType;
+	S32										mNumber;
+	S32										mTotalSize;
+};
+
+
+enum EMsgFrequency
+{
+	MFT_NULL	= 0,  // value is size of message number in bytes
+	MFT_HIGH	= 1,
+	MFT_MEDIUM	= 2,
+	MFT_LOW		= 4
+};
+
+typedef enum e_message_trust
+{
+	MT_TRUST,
+	MT_NOTRUST
+} EMsgTrust;
+
+enum EMsgEncoding
+{
+	ME_UNENCODED,
+	ME_ZEROCODED
+};
+
+class LLMessageTemplate
+{
+public:
+	LLMessageTemplate(const char *name, U32 message_number, EMsgFrequency freq)
+		: 
+		//mMemberBlocks(),
+		mName(NULL),
+		mFrequency(freq),
+		mTrust(MT_NOTRUST),
+		mEncoding(ME_ZEROCODED),
+		mMessageNumber(message_number), 
+		mTotalSize(0), 
+		mReceiveCount(0),
+		mReceiveBytes(0),
+		mReceiveInvalid(0),
+		mDecodeTimeThisFrame(0.f),
+		mTotalDecoded(0),
+		mTotalDecodeTime(0.f),
+		mMaxDecodeTimePerMsg(0.f),
+		mBanFromTrusted(false),
+		mBanFromUntrusted(false),
+		mHandlerFunc(NULL), 
+		mUserData(NULL)
+	{ 
+		mName = gMessageStringTable.getString(name);
+	}
+
+	~LLMessageTemplate()
+	{
+		for_each(mMemberBlocks.begin(), mMemberBlocks.end(), DeletePairedPointer());
+	}
+
+	void addBlock(LLMessageBlock *blockp)
+	{
+		LLMessageBlock** member_blockp = &mMemberBlocks[blockp->mName];
+		if (*member_blockp != NULL)
+		{
+			llerrs << "Block " << blockp->mName
+				<< "has already been used as a block name!" << llendl;
+		}
+		*member_blockp = blockp;
+		if (  (mTotalSize != -1)
+			&&(blockp->mTotalSize != -1)
+			&&(  (blockp->mType == MBT_SINGLE)
+			   ||(blockp->mType == MBT_MULTIPLE)))
+		{
+			mTotalSize += blockp->mNumber*blockp->mTotalSize;
+		}
+		else
+		{
+			mTotalSize = -1;
+		}
+	}
+
+	LLMessageBlock *getBlock(char *name)
+	{
+		return mMemberBlocks[name];
+	}
+
+	// Trusted messages can only be recieved on trusted circuits.
+	void setTrust(EMsgTrust t)
+	{
+		mTrust = t;
+	}
+
+	EMsgTrust getTrust(void)
+	{
+		return mTrust;
+	}
+
+	// controls for how the message should be encoded
+	void setEncoding(EMsgEncoding e)
+	{
+		mEncoding = e;
+	}
+	EMsgEncoding getEncoding()
+	{
+		return mEncoding;
+	}
+
+	void setHandlerFunc(void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data)
+	{
+		mHandlerFunc = handler_func;
+		mUserData = user_data;
+	}
+
+	BOOL callHandlerFunc(LLMessageSystem *msgsystem)
+	{
+		if (mHandlerFunc)
+		{
+			mHandlerFunc(msgsystem, mUserData);
+			return TRUE;
+		}
+		return FALSE;
+	}
+
+	bool isBanned(bool trustedSource)
+	{
+		return trustedSource ? mBanFromTrusted : mBanFromUntrusted;
+	}
+
+	friend std::ostream&	 operator<<(std::ostream& s, LLMessageTemplate &msg);
+
+public:
+	typedef std::map<char*, LLMessageBlock*> message_block_map_t;
+	message_block_map_t						mMemberBlocks;
+	char									*mName;
+	EMsgFrequency							mFrequency;
+	EMsgTrust								mTrust;
+	EMsgEncoding							mEncoding;
+	U32										mMessageNumber;
+	S32										mTotalSize;
+	U32										mReceiveCount;		// how many of this template have been received since last reset
+	U32										mReceiveBytes;		// How many bytes received
+	U32										mReceiveInvalid;	// How many "invalid" packets
+	F32										mDecodeTimeThisFrame;	// Total seconds spent decoding this frame
+	U32										mTotalDecoded;		// Total messages successfully decoded
+	F32										mTotalDecodeTime;	// Total time successfully decoding messages
+	F32										mMaxDecodeTimePerMsg;
+
+	bool									mBanFromTrusted;
+	bool									mBanFromUntrusted;
+
+private:
+	// message handler function (this is set by each application)
+	void									(*mHandlerFunc)(LLMessageSystem *msgsystem, void **user_data);
+	void									**mUserData;
+};
+
+#endif // LL_LLMESSAGETEMPLATE_H
diff --git a/indra/llmessage/llmsgvariabletype.h b/indra/llmessage/llmsgvariabletype.h
new file mode 100644
index 0000000000..360d949690
--- /dev/null
+++ b/indra/llmessage/llmsgvariabletype.h
@@ -0,0 +1,33 @@
+#ifndef LL_LLMSGVARIABLETYPE_H
+#define LL_LLMSGVARIABLETYPE_H
+
+typedef enum e_message_variable_type
+{
+	MVT_NULL,
+	MVT_FIXED,
+	MVT_VARIABLE,
+	MVT_U8,
+	MVT_U16,
+	MVT_U32,
+	MVT_U64,
+	MVT_S8,
+	MVT_S16,
+	MVT_S32,
+	MVT_S64,
+	MVT_F32,
+	MVT_F64,
+	MVT_LLVector3,
+	MVT_LLVector3d,
+	MVT_LLVector4,
+	MVT_LLQuaternion,
+	MVT_LLUUID,	
+	MVT_BOOL,
+	MVT_IP_ADDR,
+	MVT_IP_PORT,
+	MVT_U16Vec3,
+	MVT_U16Quat,
+	MVT_S16Array,
+	MVT_EOL
+} EMsgVariableType;
+
+#endif // LL_LLMSGVARIABLETYPE_H
diff --git a/indra/llmessage/llpacketack.h b/indra/llmessage/llpacketack.h
index 0874da6236..4c22dc2d62 100644
--- a/indra/llmessage/llpacketack.h
+++ b/indra/llmessage/llpacketack.h
@@ -44,6 +44,14 @@ public:
 public:
 	LLReliablePacketParams()
 	{
+		clear();
+	};
+
+	~LLReliablePacketParams() { };
+
+	void clear()
+	{
+		mHost.invalidate();
 		mRetries = 0;
 		mPingBasedRetry = TRUE;
 		mTimeout = 0.f;
@@ -52,8 +60,6 @@ public:
 		mMessageName = NULL;
 	};
 
-	~LLReliablePacketParams() { };
-
 	void set (	const LLHost &host, S32 retries, BOOL ping_based_retry,
 				F32 timeout, 
 				void (*callback)(void **,S32), void **callback_data, char *name )
@@ -117,7 +123,13 @@ public:
 			
 		}
 	};
-	~LLReliablePacket(){ delete [] mBuffer; };
+
+	~LLReliablePacket()
+	{ 
+		mCallback = NULL;
+		delete [] mBuffer;
+		mBuffer = NULL;
+	};
 
 	friend class LLCircuitData;
 protected:
diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp
index 1be6c21cc2..4fa3fab1c9 100644
--- a/indra/llmessage/llpumpio.cpp
+++ b/indra/llmessage/llpumpio.cpp
@@ -313,6 +313,12 @@ bool LLPumpIO::copyCurrentLinkInfo(links_t& links) const
 }
 
 void LLPumpIO::pump()
+{
+	pump(DEFAULT_POLL_TIMEOUT);
+}
+
+//timeout is in microseconds
+void LLPumpIO::pump(const S32& poll_timeout)
 {
 	LLMemType m1(LLMemType::MTYPE_IO_PUMP);
 	LLFastTimer t1(LLFastTimer::FTM_PUMP);
@@ -395,7 +401,7 @@ void LLPumpIO::pump()
 		S32 count = 0;
 		S32 client_id = 0;
 		const apr_pollfd_t* poll_fd = NULL;
-		apr_pollset_poll(mPollset, DEFAULT_POLL_TIMEOUT, &count, &poll_fd);
+		apr_pollset_poll(mPollset, poll_timeout, &count, &poll_fd);
 		PUMP_DEBUG;
 		for(S32 i = 0; i < count; ++i)
 		{
diff --git a/indra/llmessage/llpumpio.h b/indra/llmessage/llpumpio.h
index 50f7411298..5edfbdf8ee 100644
--- a/indra/llmessage/llpumpio.h
+++ b/indra/llmessage/llpumpio.h
@@ -227,6 +227,7 @@ public:
 	 * chain has a file descriptor ready, <code>process()</code> will
 	 * be called for all pipes which have requested it.
 	 */
+	void pump(const S32& poll_timeout);
 	void pump();
 
 	/** 
diff --git a/indra/llmessage/llsdmessagebuilder.cpp b/indra/llmessage/llsdmessagebuilder.cpp
new file mode 100755
index 0000000000..b7deb4817f
--- /dev/null
+++ b/indra/llmessage/llsdmessagebuilder.cpp
@@ -0,0 +1,281 @@
+#include "linden_common.h"
+
+#include "llsdmessagebuilder.h"
+
+#include "llmessagetemplate.h"
+#include "llquaternion.h"
+#include "llsdutil.h"
+#include "llsdserialize.h"
+#include "u64.h"
+#include "v3dmath.h"
+#include "v3math.h"
+#include "v4math.h"
+
+LLSDMessageBuilder::LLSDMessageBuilder() :
+	mCurrentMessage(LLSD::emptyMap()),
+	mCurrentBlock(NULL),
+	mCurrentMessageName(""),
+	mCurrentBlockName(""),
+	mbSBuilt(FALSE),
+	mbSClear(TRUE)
+{
+}
+
+//virtual
+LLSDMessageBuilder::~LLSDMessageBuilder()
+{
+}
+
+
+// virtual
+void LLSDMessageBuilder::newMessage(const char *name)
+{
+	mbSBuilt = FALSE;
+	mbSClear = FALSE;
+
+	mCurrentMessage = LLSD::emptyMap();
+	mCurrentMessageName = (char *)name;
+}
+
+// virtual
+void LLSDMessageBuilder::clearMessage()
+{
+	mbSBuilt = FALSE;
+	mbSClear = TRUE;
+
+	mCurrentMessage = LLSD::emptyMap();
+	mCurrentMessageName = "";
+}
+
+// virtual
+void LLSDMessageBuilder::nextBlock(const char* blockname)
+{
+	LLSD& block = mCurrentMessage[blockname];
+	if(block.isUndefined())
+	{
+		block[0] = LLSD::emptyMap();
+		mCurrentBlock = &(block[0]);
+	}
+	else if(block.isArray())
+	{
+		block[block.size()] = LLSD::emptyMap();
+		mCurrentBlock = &(block[block.size() - 1]);
+	}
+	else
+	{
+		llerrs << "existing block not array" << llendl;
+	}
+}
+
+// TODO: Remove this horror...
+BOOL LLSDMessageBuilder::removeLastBlock()
+{
+	/* TODO: finish implementing this */
+	return FALSE;
+}
+
+void LLSDMessageBuilder::addBinaryData(const char *varname, 
+									   const void *data, S32 size)
+{
+	std::vector<U8> v;
+	v.resize(size);
+	memcpy(&(v[0]), reinterpret_cast<const U8*>(data), size);
+	(*mCurrentBlock)[varname] = v;
+}
+
+void LLSDMessageBuilder::addS8(const char *varname, S8 v)
+{
+	(*mCurrentBlock)[varname] = v;
+}
+
+void LLSDMessageBuilder::addU8(const char *varname, U8 v)
+{
+	(*mCurrentBlock)[varname] = v;
+}
+
+void LLSDMessageBuilder::addS16(const char *varname, S16 v)
+{
+	(*mCurrentBlock)[varname] = v;
+}
+
+void LLSDMessageBuilder::addU16(const char *varname, U16 v)
+{
+	(*mCurrentBlock)[varname] = v;
+}
+
+void LLSDMessageBuilder::addF32(const char *varname, F32 v)
+{
+	(*mCurrentBlock)[varname] = v;
+}
+
+void LLSDMessageBuilder::addS32(const char *varname, S32 v)
+{
+	(*mCurrentBlock)[varname] = v;
+}
+
+void LLSDMessageBuilder::addU32(const char *varname, U32 v)
+{
+	(*mCurrentBlock)[varname] = ll_sd_from_U32(v);
+}
+
+void LLSDMessageBuilder::addU64(const char *varname, U64 v)
+{
+	(*mCurrentBlock)[varname] = ll_sd_from_U64(v);
+}
+
+void LLSDMessageBuilder::addF64(const char *varname, F64 v)
+{
+	(*mCurrentBlock)[varname] = v;
+}
+
+void LLSDMessageBuilder::addIPAddr(const char *varname, U32 v)
+{
+	(*mCurrentBlock)[varname] = ll_sd_from_ipaddr(v);
+}
+
+void LLSDMessageBuilder::addIPPort(const char *varname, U16 v)
+{
+	(*mCurrentBlock)[varname] = v;
+}
+
+void LLSDMessageBuilder::addBOOL(const char* varname, BOOL v)
+{
+	(*mCurrentBlock)[varname] = (v == TRUE);
+}
+
+void LLSDMessageBuilder::addString(const char* varname, const char* v)
+{
+	if (v)
+		(*mCurrentBlock)[varname] = v;  /* Flawfinder: ignore */  
+	else
+		(*mCurrentBlock)[varname] = ""; 
+}
+
+void LLSDMessageBuilder::addString(const char* varname, const std::string& v)
+{
+	if (v.size())
+		(*mCurrentBlock)[varname] = v; 
+	else
+		(*mCurrentBlock)[varname] = ""; 
+}
+
+void LLSDMessageBuilder::addVector3(const char *varname, const LLVector3& v)
+{
+	(*mCurrentBlock)[varname] = ll_sd_from_vector3(v);
+}
+
+void LLSDMessageBuilder::addVector4(const char *varname, const LLVector4& v)
+{
+	(*mCurrentBlock)[varname] = ll_sd_from_vector4(v);
+}
+
+void LLSDMessageBuilder::addVector3d(const char *varname, const LLVector3d& v)
+{
+	(*mCurrentBlock)[varname] = ll_sd_from_vector3d(v);
+}
+
+void LLSDMessageBuilder::addQuat(const char *varname, const LLQuaternion& v)
+{
+	(*mCurrentBlock)[varname] = ll_sd_from_quaternion(v);
+}
+
+void LLSDMessageBuilder::addUUID(const char *varname, const LLUUID& v)
+{
+	(*mCurrentBlock)[varname] = v;
+}
+
+void LLSDMessageBuilder::compressMessage(U8*& buf_ptr, U32& buffer_length)
+{
+}
+
+BOOL LLSDMessageBuilder::isMessageFull(const char* blockname) const
+{
+	return FALSE;
+}
+
+// make sure that all the desired data is in place and then copy the data 
+// into MAX_BUFFER_SIZEd buffer
+U32 LLSDMessageBuilder::buildMessage(U8* buffer, U32 buffer_size)
+{
+	return 0;
+}
+
+void LLSDMessageBuilder::copyFromMessageData(const LLMsgData& data)
+{
+	// copy the blocks
+	// counting variables used to encode multiple block info
+	S32 block_count = 0;
+    char *block_name = NULL;
+
+	// loop through msg blocks to loop through variables, totalling up size
+	// data and filling the new (send) message
+	LLMsgData::msg_blk_data_map_t::const_iterator iter = 
+		data.mMemberBlocks.begin();
+	LLMsgData::msg_blk_data_map_t::const_iterator end = 
+		data.mMemberBlocks.end();
+	for(; iter != end; ++iter)
+	{
+		const LLMsgBlkData* mbci = iter->second;
+		if(!mbci) continue;
+
+		// do we need to encode a block code?
+		if (block_count == 0)
+		{
+			block_count = mbci->mBlockNumber;
+			block_name = (char *)mbci->mName;
+		}
+
+		// counting down mutliple blocks
+		block_count--;
+
+		nextBlock(block_name);
+
+		// now loop through the variables
+		LLMsgBlkData::msg_var_data_map_t::const_iterator dit = mbci->mMemberVarData.begin();
+		LLMsgBlkData::msg_var_data_map_t::const_iterator dend = mbci->mMemberVarData.end();
+		
+		for(; dit != dend; ++dit)
+		{
+			//const LLMsgVarData& mvci = *dit;
+
+			// TODO: Copy mvci data in to block:
+			// (*mCurrentBlock)[varname] = v;
+		}
+	}
+}
+
+//virtual
+void LLSDMessageBuilder::copyFromLLSD(const LLSD& msg)
+{
+	mCurrentMessage = msg;
+	llinfos << LLSDXMLStreamer(mCurrentMessage) << llendl;
+}
+
+const LLSD& LLSDMessageBuilder::getMessage() const
+{
+	 return mCurrentMessage;
+}
+
+//virtual
+void LLSDMessageBuilder::setBuilt(BOOL b) { mbSBuilt = b; }
+
+//virtual 
+BOOL LLSDMessageBuilder::isBuilt() const {return mbSBuilt;}
+
+//virtual 
+BOOL LLSDMessageBuilder::isClear() const {return mbSClear;}
+
+//virtual 
+S32 LLSDMessageBuilder::getMessageSize()
+{
+	// babbage: size is unknown as message stored as LLSD.
+	// return non-zero if pending data, as send can be skipped for 0 size.
+	// return 1 to encourage senders checking size against splitting message.
+	return mCurrentMessage.size()? 1 : 0;
+}
+
+//virtual 
+const char* LLSDMessageBuilder::getMessageName() const 
+{
+	return mCurrentMessageName.c_str();
+}
diff --git a/indra/llmessage/llsdmessagebuilder.h b/indra/llmessage/llsdmessagebuilder.h
new file mode 100755
index 0000000000..f04194d12f
--- /dev/null
+++ b/indra/llmessage/llsdmessagebuilder.h
@@ -0,0 +1,98 @@
+#ifndef LL_LLSDMESSAGEBUILDER_H
+#define LL_LLSDMESSAGEBUILDER_H
+
+#include <map>
+
+#include "llmessagebuilder.h"
+#include "llmsgvariabletype.h"
+#include "llsd.h"
+
+class LLMessageTemplate;
+class LLMsgData;
+
+class LLSDMessageBuilder : public LLMessageBuilder
+{
+public:
+
+	//CLASS_LOG_TYPE(LLSDMessageBuilder);
+	
+	LLSDMessageBuilder();
+	virtual ~LLSDMessageBuilder();
+
+	virtual void newMessage(const char *name);
+
+	virtual void nextBlock(const char* blockname);
+	virtual BOOL removeLastBlock(); // TODO: babbage: remove this horror...
+
+	/** All add* methods expect pointers to canonical varname strings. */
+	virtual void addBinaryData(const char *varname, const void *data, 
+							   S32 size);
+	virtual void addBOOL(const char* varname, BOOL b);
+	virtual void addS8(const char *varname, S8 s);
+	virtual void addU8(const char *varname, U8 u);
+	virtual void addS16(const char *varname, S16 i);
+	virtual void addU16(const char *varname, U16 i);
+	virtual void addF32(const char *varname, F32 f);
+	virtual void addS32(const char *varname, S32 s);
+	virtual void addU32(const char *varname, U32 u);
+	virtual void addU64(const char *varname, U64 lu);
+	virtual void addF64(const char *varname, F64 d);
+	virtual void addVector3(const char *varname, const LLVector3& vec);
+	virtual void addVector4(const char *varname, const LLVector4& vec);
+	virtual void addVector3d(const char *varname, const LLVector3d& vec);
+	virtual void addQuat(const char *varname, const LLQuaternion& quat);
+	virtual void addUUID(const char *varname, const LLUUID& uuid);
+	virtual void addIPAddr(const char *varname, const U32 ip);
+	virtual void addIPPort(const char *varname, const U16 port);
+	virtual void addString(const char* varname, const char* s);
+	virtual void addString(const char* varname, const std::string& s);
+
+	virtual BOOL isMessageFull(const char* blockname) const;
+	virtual void compressMessage(U8*& buf_ptr, U32& buffer_length);
+
+	virtual BOOL isBuilt() const;
+	virtual BOOL isClear() const;
+	virtual U32 buildMessage(U8* buffer, U32 buffer_size); 
+        /**< Return built message size */
+	
+	virtual void clearMessage();
+
+	// TODO: babbage: remove this horror.
+	virtual void setBuilt(BOOL b);
+
+	virtual S32 getMessageSize();
+	virtual const char* getMessageName() const;
+
+	virtual void copyFromMessageData(const LLMsgData& data);
+
+	virtual void copyFromLLSD(const LLSD& msg);
+
+	const LLSD& getMessage() const;
+private:
+
+	/* mCurrentMessage is of the following format:
+		mCurrentMessage = { 'block_name1' : [ { 'block1_field1' : 'b1f1_data',
+												'block1_field2' : 'b1f2_data',
+												...
+												'block1_fieldn' : 'b1fn_data'},
+											{ 'block2_field1' : 'b2f1_data',
+												'block2_field2' : 'b2f2_data',
+												...
+												'block2_fieldn' : 'b2fn_data'},
+											...											
+											{ 'blockm_field1' : 'bmf1_data',
+												'blockm_field2' : 'bmf2_data',
+												...
+												'blockm_fieldn' : 'bmfn_data'} ],
+							'block_name2' : ...,
+							...
+							'block_namem' } */
+	LLSD mCurrentMessage;
+	LLSD* mCurrentBlock;
+	std::string mCurrentMessageName;
+	std::string mCurrentBlockName;
+	BOOL mbSBuilt;
+	BOOL mbSClear;
+};
+
+#endif // LL_LLSDMESSAGEBUILDER_H
diff --git a/indra/llmessage/llsdmessagereader.cpp b/indra/llmessage/llsdmessagereader.cpp
new file mode 100755
index 0000000000..6312bee0ab
--- /dev/null
+++ b/indra/llmessage/llsdmessagereader.cpp
@@ -0,0 +1,264 @@
+#include "llsdmessagereader.h"
+#include "llsdutil.h"
+#include "llmessagebuilder.h"
+#include "llsdmessagebuilder.h"
+
+LLSDMessageReader::LLSDMessageReader()
+{
+}
+
+//virtual 
+LLSDMessageReader::~LLSDMessageReader()
+{
+}
+
+
+LLSD getLLSD(const LLSD& input, const char* block, const char* var, S32 blocknum)
+{
+	if(input[block].isArray())
+	{
+		return input[block][blocknum][var];
+	}
+	return LLSD();
+}
+
+//virtual 
+void LLSDMessageReader::getBinaryData(const char *block, const char *var, 
+									  void *datap, S32 size, S32 blocknum, 
+									  S32 max_size)
+{
+	std::vector<U8> data = getLLSD(mMessage, block, var, blocknum);
+	S32 data_size = (S32)data.size();
+
+	if (size && data_size != size)
+	{
+		return;
+	}
+	
+	if (max_size < data_size)
+	{
+		data_size = max_size;
+	}
+	
+	memcpy(datap, &(data[0]), data_size);
+}
+
+//virtual 
+void LLSDMessageReader::getBOOL(const char *block, const char *var, 
+								BOOL &data, 
+								S32 blocknum)
+{
+	data = getLLSD(mMessage, block, var, blocknum);
+}
+
+//virtual 
+void LLSDMessageReader::getS8(const char *block, const char *var, S8 &data, 
+					   S32 blocknum)
+{
+	data = getLLSD(mMessage, block, var, blocknum).asInteger();
+}
+
+//virtual 
+void LLSDMessageReader::getU8(const char *block, const char *var, U8 &data, 
+					   S32 blocknum)
+{
+	data = getLLSD(mMessage, block, var, blocknum).asInteger();
+}
+
+//virtual 
+void LLSDMessageReader::getS16(const char *block, const char *var, S16 &data, 
+						S32 blocknum)
+{
+	data = getLLSD(mMessage, block, var, blocknum).asInteger();
+}
+
+//virtual 
+void LLSDMessageReader::getU16(const char *block, const char *var, U16 &data, 
+						S32 blocknum)
+{
+	data = getLLSD(mMessage, block, var, blocknum).asInteger();
+}
+
+//virtual 
+void LLSDMessageReader::getS32(const char *block, const char *var, S32 &data, 
+						S32 blocknum)
+{
+	data = getLLSD(mMessage, block, var, blocknum);
+}
+
+//virtual 
+void LLSDMessageReader::getF32(const char *block, const char *var, F32 &data, 
+						S32 blocknum)
+{
+	data = (F32)getLLSD(mMessage, block, var, blocknum).asReal();
+}
+
+//virtual 
+void LLSDMessageReader::getU32(const char *block, const char *var, U32 &data, 
+						S32 blocknum)
+{
+	data = ll_U32_from_sd(getLLSD(mMessage, block, var, blocknum));
+}
+
+//virtual 
+void LLSDMessageReader::getU64(const char *block, const char *var,
+								U64 &data, S32 blocknum)
+{
+	data = ll_U64_from_sd(getLLSD(mMessage, block, var, blocknum));
+}
+
+//virtual 
+void LLSDMessageReader::getF64(const char *block, const char *var,
+								F64 &data, S32 blocknum)
+{
+	data = getLLSD(mMessage, block, var, blocknum);
+}
+
+//virtual 
+void LLSDMessageReader::getVector3(const char *block, const char *var, 
+							LLVector3 &vec, S32 blocknum)
+{
+	vec = ll_vector3_from_sd(getLLSD(mMessage, block, var, blocknum));
+}
+
+//virtual 
+void LLSDMessageReader::getVector4(const char *block, const char *var, 
+							LLVector4 &vec, S32 blocknum)
+{
+	vec = ll_vector4_from_sd(getLLSD(mMessage, block, var, blocknum));
+}
+
+//virtual 
+void LLSDMessageReader::getVector3d(const char *block, const char *var, 
+							 LLVector3d &vec, S32 blocknum)
+{
+	vec = ll_vector3d_from_sd(getLLSD(mMessage, block, var, blocknum));
+}
+
+//virtual 
+void LLSDMessageReader::getQuat(const char *block, const char *var,
+								 LLQuaternion &q, S32 blocknum)
+{
+	q = ll_quaternion_from_sd(getLLSD(mMessage, block, var, blocknum));
+}
+
+//virtual 
+void LLSDMessageReader::getUUID(const char *block, const char *var,
+								 LLUUID &uuid, S32 blocknum)
+{
+	uuid = getLLSD(mMessage, block, var, blocknum);
+}
+
+//virtual 
+void LLSDMessageReader::getIPAddr(const char *block, const char *var,
+								   U32 &ip, S32 blocknum)
+{
+	ip = ll_ipaddr_from_sd(getLLSD(mMessage, block, var, blocknum));
+}
+
+//virtual 
+void LLSDMessageReader::getIPPort(const char *block, const char *var,
+								   U16 &port, S32 blocknum)
+{
+	port = getLLSD(mMessage, block, var, blocknum).asInteger();
+}
+
+//virtual 
+void LLSDMessageReader::getString(const char *block, const char *var, 
+						   S32 buffer_size, char *buffer, S32 blocknum)
+{
+	std::string data = getLLSD(mMessage, block, var, blocknum);
+	
+	S32 data_size = data.size();
+	if (data_size >= buffer_size)
+	{
+		data_size = buffer_size - 1;
+	}
+	memcpy(buffer, data.data(), data_size);
+	buffer[data_size] = '\0';
+}
+
+
+//virtual 
+S32	LLSDMessageReader::getNumberOfBlocks(const char *blockname)
+{
+	return mMessage[blockname].size();
+}
+
+S32 getElementSize(const LLSD& llsd)
+{
+	LLSD::Type type = llsd.type();
+	switch(type)
+	{
+	case LLSD::TypeBoolean:
+		return sizeof(bool);
+	case LLSD::TypeInteger:
+		return sizeof(S32);
+	case LLSD::TypeReal:
+		return sizeof(F64);
+	case LLSD::TypeString:
+		return llsd.asString().size();
+	case LLSD::TypeUUID:
+		return sizeof(LLUUID);
+	case LLSD::TypeDate:
+		return sizeof(LLDate);
+	case LLSD::TypeURI:
+		return sizeof(LLURI);
+	case LLSD::TypeBinary:
+	{
+		std::vector<U8> data = llsd;
+		return data.size() * sizeof(U8);
+	}
+	case LLSD::TypeMap:
+	case LLSD::TypeArray:
+	case LLSD::TypeUndefined:
+		return 0;
+	}
+	return 0;
+}
+
+//virtual 
+//Mainly used to find size of binary block of data
+S32	LLSDMessageReader::getSize(const char *blockname, const char *varname)
+{
+	return getElementSize(mMessage[blockname][0][varname]);
+}
+
+
+//virtual 
+S32	LLSDMessageReader::getSize(const char *blockname, S32 blocknum, 
+							   const char *varname)
+{
+	return getElementSize(mMessage[blockname][blocknum][varname]);
+}
+
+//virtual 
+void LLSDMessageReader::clearMessage()
+{
+	mMessage = LLSD();
+}
+
+//virtual 
+const char* LLSDMessageReader::getMessageName() const
+{
+	return mMessageName.c_str();
+}
+
+// virtual 
+S32 LLSDMessageReader::getMessageSize() const
+{
+	return 0;
+}
+
+//virtual 
+void LLSDMessageReader::copyToBuilder(LLMessageBuilder& builder) const
+{
+	builder.copyFromLLSD(mMessage);
+}
+
+void LLSDMessageReader::setMessage(const std::string& name, const LLSD& message)
+{
+	mMessageName = name;
+	// TODO: Validate
+	mMessage = message;
+}
diff --git a/indra/llmessage/llsdmessagereader.h b/indra/llmessage/llsdmessagereader.h
new file mode 100755
index 0000000000..57851941a2
--- /dev/null
+++ b/indra/llmessage/llsdmessagereader.h
@@ -0,0 +1,79 @@
+#ifndef LL_LLSDMESSAGEREADER_H
+#define LL_LLSDMESSAGEREADER_H
+
+#include "llmessagereader.h"
+#include "llsd.h"
+
+#include <map>
+
+class LLMessageTemplate;
+class LLMsgData;
+
+class LLSDMessageReader : public LLMessageReader
+{
+public:
+
+	LLSDMessageReader();
+	virtual ~LLSDMessageReader();
+
+	/** All get* methods expect pointers to canonical strings. */
+	virtual void getBinaryData(const char *block, const char *var, 
+							   void *datap, S32 size, S32 blocknum = 0, 
+							   S32 max_size = S32_MAX);
+	virtual void getBOOL(const char *block, const char *var, BOOL &data, 
+						 S32 blocknum = 0);
+	virtual void getS8(const char *block, const char *var, S8 &data, 
+					   S32 blocknum = 0);
+	virtual void getU8(const char *block, const char *var, U8 &data, 
+					   S32 blocknum = 0);
+	virtual void getS16(const char *block, const char *var, S16 &data, 
+						S32 blocknum = 0);
+	virtual void getU16(const char *block, const char *var, U16 &data, 
+						S32 blocknum = 0);
+	virtual void getS32(const char *block, const char *var, S32 &data, 
+						S32 blocknum = 0);
+	virtual void getF32(const char *block, const char *var, F32 &data, 
+						S32 blocknum = 0);
+	virtual void getU32(const char *block, const char *var, U32 &data, 
+						S32 blocknum = 0);
+	virtual void getU64(const char *block, const char *var, U64 &data, 
+						S32 blocknum = 0);
+	virtual void getF64(const char *block, const char *var, F64 &data, 
+						S32 blocknum = 0);
+	virtual void getVector3(const char *block, const char *var, 
+							LLVector3 &vec, S32 blocknum = 0);
+	virtual void getVector4(const char *block, const char *var, 
+							LLVector4 &vec, S32 blocknum = 0);
+	virtual void getVector3d(const char *block, const char *var, 
+							 LLVector3d &vec, S32 blocknum = 0);
+	virtual void getQuat(const char *block, const char *var, LLQuaternion &q, 
+						 S32 blocknum = 0);
+	virtual void getUUID(const char *block, const char *var, LLUUID &uuid, 
+						 S32 blocknum = 0);
+	virtual void getIPAddr(const char *block, const char *var, U32 &ip, 
+						   S32 blocknum = 0);
+	virtual void getIPPort(const char *block, const char *var, U16 &port, 
+						   S32 blocknum = 0);
+	virtual void getString(const char *block, const char *var, 
+						   S32 buffer_size, char *buffer, S32 blocknum = 0);
+
+	virtual S32	getNumberOfBlocks(const char *blockname);
+	virtual S32	getSize(const char *blockname, const char *varname);
+	virtual S32	getSize(const char *blockname, S32 blocknum, 
+						const char *varname);
+
+	virtual void clearMessage();
+
+	virtual const char* getMessageName() const;
+	virtual S32 getMessageSize() const;
+
+	virtual void copyToBuilder(LLMessageBuilder&) const;
+
+	void setMessage(const std::string& name, const LLSD& msg);
+
+private:
+	std::string mMessageName;
+	LLSD mMessage;
+};
+
+#endif // LL_LLSDMESSAGEREADER_H
diff --git a/indra/llmessage/llservice.h b/indra/llmessage/llservice.h
index e243e710d6..fe6fa56477 100644
--- a/indra/llmessage/llservice.h
+++ b/indra/llmessage/llservice.h
@@ -71,7 +71,7 @@ namespace boost
 	}
 	inline void intrusive_ptr_release(LLServiceCreator* p)
 	{
-		if(0 == --p->mReferenceCount)
+		if(p && 0 == --p->mReferenceCount)
 		{
 			delete p;
 		}
diff --git a/indra/llmessage/llservicebuilder.cpp b/indra/llmessage/llservicebuilder.cpp
new file mode 100644
index 0000000000..fbcf38ae35
--- /dev/null
+++ b/indra/llmessage/llservicebuilder.cpp
@@ -0,0 +1,115 @@
+/** 
+* @file llservicebuilder.cpp
+* @brief Implementation of the LLServiceBuilder class.
+*
+* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+* $License$
+*/
+
+#include "llapp.h"
+#include "llfile.h"
+#include "llservicebuilder.h"
+#include "llsd.h"
+#include "llsdserialize.h"
+
+void LLServiceBuilder::loadServiceDefinitionsFromFile(
+	const std::string& service_filename)
+{
+	llifstream service_file(service_filename.c_str(), std::ios::binary);
+	if(service_file.is_open())
+	{
+		LLSD service_data;
+		LLSDSerialize::fromXML(service_data, service_file);
+		service_file.close();
+		// Load service 
+		LLSD service_map = service_data["services"];
+		for(LLSD::array_iterator array_itr = service_map.beginArray();
+			array_itr != service_map.endArray();
+			++array_itr)
+		{	
+			LLSD service_llsd = (*array_itr)["service-builder"];
+			std::string service_name = (*array_itr)["name"].asString();
+			createServiceDefinition(service_name, service_llsd);
+		}
+		llinfos << "loaded config file: " << service_filename << llendl;
+	}
+	else
+	{
+		llwarns << "unable to find config file: " << service_filename << llendl;
+	}
+}
+
+void LLServiceBuilder::createServiceDefinition(
+	const std::string& service_name,
+	LLSD& service_llsd)
+{
+	if(service_llsd.isString())
+	{
+		mServiceMap[ service_name ] = service_llsd.asString();
+	}			
+	else if(service_llsd.isMap())
+	{
+		for(LLSD::map_iterator map_itr = service_llsd.beginMap();
+			map_itr != service_llsd.endMap();
+			++map_itr)
+		{
+			std::string compound_builder_name = service_name;
+			compound_builder_name.append("-");
+			compound_builder_name.append((*map_itr).first);
+			mServiceMap[ compound_builder_name ] = (*map_itr).second.asString();
+		}
+	}
+}
+
+std::string LLServiceBuilder::buildServiceURI(const std::string& service_name)
+{
+	std::ostringstream service_url;
+	// Find the service builder
+	if(mServiceMap.find(service_name) != mServiceMap.end())
+	{
+		// construct the service builder url
+		LLApp* app = LLApp::instance();
+		if(app)
+		{
+			LLSD base_url = app->getOption("services-base-url");
+			service_url << base_url.asString();
+		}
+		service_url << mServiceMap[service_name];
+	}
+	else
+	{
+		llwarns << "Cannot find service " << service_name << llendl;
+	}
+	return service_url.str();
+}
+
+std::string LLServiceBuilder::buildServiceURI(
+	const std::string& service_name,
+	const LLSD& option_map)
+{
+	std::string service_url = buildServiceURI(service_name);
+
+	// Find the Service Name
+	if(!service_url.empty() && option_map.isMap())
+	{
+		// Do brace replacements - NOT CURRENTLY RECURSIVE
+		for(LLSD::map_const_iterator option_itr = option_map.beginMap();
+			option_itr != option_map.endMap();
+			++option_itr)
+		{
+			std::string variable_name = "{$";
+			variable_name.append((*option_itr).first);
+			variable_name.append("}");
+			std::string::size_type find_pos = service_url.find(variable_name);
+			if(find_pos != std::string::npos)
+			{
+				service_url.replace(
+					find_pos,
+					variable_name.length(),
+					(*option_itr).second.asString());
+			}
+		}
+	}
+
+	return service_url;
+}
diff --git a/indra/llmessage/llservicebuilder.h b/indra/llmessage/llservicebuilder.h
new file mode 100644
index 0000000000..2692ffe1e5
--- /dev/null
+++ b/indra/llmessage/llservicebuilder.h
@@ -0,0 +1,73 @@
+/** 
+* @file llservicebuilder.h
+* @brief Declaration of the LLServiceBuilder class.
+*
+* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+* $License$
+*/
+
+#ifndef LLSERVICEBUILDER_H
+#define LLSERVICEBUILDER_H
+
+#include <string>
+#include <map>
+#include "llerror.h"
+
+class LLSD;
+
+/** 
+ * @class LLServiceBuilder
+ * @brief This class builds urls for us to use when making web service calls.
+ */
+
+class LLServiceBuilder
+{
+	LOG_CLASS(LLServiceBuilder);
+public:
+	LLServiceBuilder(void) {}
+	~LLServiceBuilder(void) {}
+
+	/** 
+	 * @brief Initialize this object with the service definitions.
+	 *
+	 * @param service_filename The services definition files -- services.xml.
+	 */
+	void loadServiceDefinitionsFromFile(const std::string& service_filename);
+
+	/** 
+	 * @brief Build a service url if the url needs no construction parameters.
+	 *
+	 * @param service_name The name of the service you want to call.
+	 */
+	std::string buildServiceURI(const std::string& service_name);
+
+	/** 
+	 * @brief Build a service url if the url with construction parameters.
+	 *
+	 * The parameter substitution supports string substituition from RUSS:
+	 * [[Recursive_URL_Substitution_Syntax]]
+	 * @param service_name The name of the service you want to call.
+	 * @param option_map The parameters in a map of name:value for the service.
+	 */
+	std::string buildServiceURI(
+		const std::string& service_name,
+		const LLSD& option_map);	
+
+public:
+	/** 
+	 * @brief Helper method which builds construction state for a service
+	 *
+	 * This method should probably be protected, but we need to test this
+	 * method.
+	 */
+	void createServiceDefinition(
+		const std::string& service_name,
+		LLSD& service_url);
+
+protected:
+	std::map<std::string, std::string> mServiceMap;
+};
+
+
+
+#endif
diff --git a/indra/llmessage/lltemplatemessagebuilder.cpp b/indra/llmessage/lltemplatemessagebuilder.cpp
new file mode 100644
index 0000000000..806f03422d
--- /dev/null
+++ b/indra/llmessage/lltemplatemessagebuilder.cpp
@@ -0,0 +1,856 @@
+#include "linden_common.h"
+
+#include "lltemplatemessagebuilder.h"
+
+#include "llmessagetemplate.h"
+#include "llquaternion.h"
+#include "u64.h"
+#include "v3dmath.h"
+#include "v3math.h"
+#include "v4math.h"
+
+LLTemplateMessageBuilder::LLTemplateMessageBuilder(message_template_name_map_t& name_template_map) :
+	mCurrentSMessageData(NULL),
+	mCurrentSMessageTemplate(NULL),
+	mCurrentSDataBlock(NULL),
+	mCurrentSMessageName(NULL),
+	mCurrentSBlockName(NULL),
+	mbSBuilt(FALSE),
+	mbSClear(TRUE),
+	mCurrentSendTotal(0),
+	mMessageTemplates(name_template_map)
+{
+}
+
+//virtual
+LLTemplateMessageBuilder::~LLTemplateMessageBuilder()
+{
+	delete mCurrentSMessageData;
+	mCurrentSMessageData = NULL;
+}
+
+
+// virtual
+void LLTemplateMessageBuilder::newMessage(const char *name)
+{
+	mbSBuilt = FALSE;
+	mbSClear = FALSE;
+
+	mCurrentSendTotal = 0;
+
+	delete mCurrentSMessageData;
+	mCurrentSMessageData = NULL;
+
+	char *namep = (char *)name; 
+
+	if (mMessageTemplates.count(namep) > 0)
+	{
+		mCurrentSMessageTemplate = mMessageTemplates[namep];
+		if (mCurrentSMessageData)
+		{
+			delete mCurrentSMessageData;
+		}
+		mCurrentSMessageData = new LLMsgData(namep);
+		mCurrentSMessageName = namep;
+		mCurrentSDataBlock = NULL;
+		mCurrentSBlockName = NULL;
+
+		// add at one of each block
+		LLMessageTemplate* msg_template = mMessageTemplates[namep];
+		for (LLMessageTemplate::message_block_map_t::iterator iter = msg_template->mMemberBlocks.begin();
+			 iter != msg_template->mMemberBlocks.end(); iter++)
+		{
+			LLMessageBlock* ci = iter->second;
+			LLMsgBlkData	*tblockp;
+			tblockp = new LLMsgBlkData(ci->mName, 0);
+			mCurrentSMessageData->addBlock(tblockp);
+		}
+	}
+	else
+	{
+		llerrs << "newMessage - Message " << name << " not registered" << llendl;
+	}
+}
+
+// virtual
+void LLTemplateMessageBuilder::clearMessage()
+{
+	mbSBuilt = FALSE;
+	mbSClear = TRUE;
+
+	mCurrentSendTotal = 0;
+
+	mCurrentSMessageTemplate = NULL;
+
+	delete mCurrentSMessageData;
+	mCurrentSMessageData = NULL;
+
+	mCurrentSMessageName = NULL;
+	mCurrentSDataBlock = NULL;
+	mCurrentSBlockName = NULL;
+}
+
+// virtual
+void LLTemplateMessageBuilder::nextBlock(const char* blockname)
+{
+	char *bnamep = (char *)blockname; 
+
+	if (!mCurrentSMessageTemplate)
+	{
+		llerrs << "newMessage not called prior to setBlock" << llendl;
+		return;
+	}
+
+	// now, does this block exist?
+	LLMessageTemplate::message_block_map_t::iterator temp_iter = mCurrentSMessageTemplate->mMemberBlocks.find(bnamep);
+	if (temp_iter == mCurrentSMessageTemplate->mMemberBlocks.end())
+	{
+		llerrs << "LLTemplateMessageBuilder::nextBlock " << bnamep
+			<< " not a block in " << mCurrentSMessageTemplate->mName << llendl;
+		return;
+	}
+	
+	LLMessageBlock* template_data = temp_iter->second;
+	
+	// ok, have we already set this block?
+	LLMsgBlkData* block_data = mCurrentSMessageData->mMemberBlocks[bnamep];
+	if (block_data->mBlockNumber == 0)
+	{
+		// nope! set this as the current block
+		block_data->mBlockNumber = 1;
+		mCurrentSDataBlock = block_data;
+		mCurrentSBlockName = bnamep;
+
+		// add placeholders for each of the variables
+		for (LLMessageBlock::message_variable_map_t::iterator iter = template_data->mMemberVariables.begin();
+			 iter != template_data->mMemberVariables.end(); iter++)
+		{
+			LLMessageVariable& ci = *(iter->second);
+			mCurrentSDataBlock->addVariable(ci.getName(), ci.getType());
+		}
+		return;
+	}
+	else
+	{
+		// already have this block. . . 
+		// are we supposed to have a new one?
+
+		// if the block is type MBT_SINGLE this is bad!
+		if (template_data->mType == MBT_SINGLE)
+		{
+			llerrs << "LLTemplateMessageBuilder::nextBlock called multiple times"
+				<< " for " << bnamep << " but is type MBT_SINGLE" << llendl;
+			return;
+		}
+
+
+		// if the block is type MBT_MULTIPLE then we need a known number, 
+		// make sure that we're not exceeding it
+		if (  (template_data->mType == MBT_MULTIPLE)
+			&&(mCurrentSDataBlock->mBlockNumber == template_data->mNumber))
+		{
+			llerrs << "LLTemplateMessageBuilder::nextBlock called "
+				<< mCurrentSDataBlock->mBlockNumber << " times for " << bnamep
+				<< " exceeding " << template_data->mNumber
+				<< " specified in type MBT_MULTIPLE." << llendl;
+			return;
+		}
+
+		// ok, we can make a new one
+		// modify the name to avoid name collision by adding number to end
+		S32  count = block_data->mBlockNumber;
+
+		// incrememt base name's count
+		block_data->mBlockNumber++;
+
+		if (block_data->mBlockNumber > MAX_BLOCKS)
+		{
+			llerrs << "Trying to pack too many blocks into MBT_VARIABLE type "
+				   << "(limited to " << MAX_BLOCKS << ")" << llendl;
+		}
+
+		// create new name
+		// Nota Bene: if things are working correctly, 
+		// mCurrentMessageData->mMemberBlocks[blockname]->mBlockNumber == 
+		// mCurrentDataBlock->mBlockNumber + 1
+
+		char *nbnamep = bnamep + count;
+	
+		mCurrentSDataBlock = new LLMsgBlkData(bnamep, count);
+		mCurrentSDataBlock->mName = nbnamep;
+		mCurrentSMessageData->mMemberBlocks[nbnamep] = mCurrentSDataBlock;
+
+		// add placeholders for each of the variables
+		for (LLMessageBlock::message_variable_map_t::iterator
+				 iter = template_data->mMemberVariables.begin(),
+				 end = template_data->mMemberVariables.end();
+			 iter != end; iter++)
+		{
+			LLMessageVariable& ci = *(iter->second);
+			mCurrentSDataBlock->addVariable(ci.getName(), ci.getType());
+		}
+		return;
+	}
+}
+
+// TODO: Remove this horror...
+BOOL LLTemplateMessageBuilder::removeLastBlock()
+{
+	if (mCurrentSBlockName)
+	{
+		if (  (mCurrentSMessageData)
+			&&(mCurrentSMessageTemplate))
+		{
+			if (mCurrentSMessageData->mMemberBlocks[mCurrentSBlockName]->mBlockNumber >= 1)
+			{
+				// At least one block for the current block name.
+
+				// Store the current block name for future reference.
+				char *block_name = mCurrentSBlockName;
+
+				// Decrement the sent total by the size of the
+				// data in the message block that we're currently building.
+
+				LLMessageBlock* template_data = mCurrentSMessageTemplate->mMemberBlocks[mCurrentSBlockName];
+				
+				for (LLMessageBlock::message_variable_map_t::iterator iter = template_data->mMemberVariables.begin();
+					 iter != template_data->mMemberVariables.end(); iter++)
+				{
+					LLMessageVariable& ci = *(iter->second);
+					mCurrentSendTotal -= ci.getSize();
+				}
+
+
+				// Now we want to find the block that we're blowing away.
+
+				// Get the number of blocks.
+				LLMsgBlkData* block_data = mCurrentSMessageData->mMemberBlocks[block_name];
+				S32 num_blocks = block_data->mBlockNumber;
+
+				// Use the same (suspect?) algorithm that's used to generate
+				// the names in the nextBlock method to find it.
+				char *block_getting_whacked = block_name + num_blocks - 1;
+				LLMsgBlkData* whacked_data = mCurrentSMessageData->mMemberBlocks[block_getting_whacked];
+				delete whacked_data;
+				mCurrentSMessageData->mMemberBlocks.erase(block_getting_whacked);
+
+				if (num_blocks <= 1)
+				{
+					// we just blew away the last one, so return FALSE
+					llwarns << "not blowing away the only block of message "
+							<< mCurrentSMessageName
+							<< ". Block: " << block_name
+							<< ". Number: " << num_blocks
+							<< llendl;
+					return FALSE;
+				}
+				else
+				{
+					// Decrement the counter.
+					block_data->mBlockNumber--;
+					return TRUE;
+				}
+			}
+		}
+	}
+	return FALSE;
+}
+
+// add data to variable in current block
+void LLTemplateMessageBuilder::addData(const char *varname, const void *data, EMsgVariableType type, S32 size)
+{
+	char *vnamep = (char *)varname; 
+
+	// do we have a current message?
+	if (!mCurrentSMessageTemplate)
+	{
+		llerrs << "newMessage not called prior to addData" << llendl;
+		return;
+	}
+
+	// do we have a current block?
+	if (!mCurrentSDataBlock)
+	{
+		llerrs << "setBlock not called prior to addData" << llendl;
+		return;
+	}
+
+	// kewl, add the data if it exists
+	LLMessageVariable* var_data = mCurrentSMessageTemplate->mMemberBlocks[mCurrentSBlockName]->mMemberVariables[vnamep];
+	if (!var_data || !var_data->getName())
+	{
+		llerrs << vnamep << " not a variable in block " << mCurrentSBlockName << " of " << mCurrentSMessageTemplate->mName << llendl;
+		return;
+	}
+
+	// ok, it seems ok. . . are we the correct size?
+	if (var_data->getType() == MVT_VARIABLE)
+	{
+		// Variable 1 can only store 255 bytes, make sure our data is smaller
+		if ((var_data->getSize() == 1) &&
+			(size > 255))
+		{
+			llwarns << "Field " << varname << " is a Variable 1 but program "
+			       << "attempted to stuff more than 255 bytes in "
+			       << "(" << size << ").  Clamping size and truncating data." << llendl;
+			size = 255;
+			char *truncate = (char *)data;
+			truncate[255] = 0;
+		}
+
+		// no correct size for MVT_VARIABLE, instead we need to tell how many bytes the size will be encoded as
+		mCurrentSDataBlock->addData(vnamep, data, size, type, var_data->getSize());
+		mCurrentSendTotal += size;
+	}
+	else
+	{
+		if (size != var_data->getSize())
+		{
+			llerrs << varname << " is type MVT_FIXED but request size " << size << " doesn't match template size "
+				   << var_data->getSize() << llendl;
+			return;
+		}
+		// alright, smash it in
+		mCurrentSDataBlock->addData(vnamep, data, size, type);
+		mCurrentSendTotal += size;
+	}
+}
+
+// add data to variable in current block - fails if variable isn't MVT_FIXED
+void LLTemplateMessageBuilder::addData(const char *varname, const void *data, EMsgVariableType type)
+{
+	char *vnamep = (char *)varname; 
+
+	// do we have a current message?
+	if (!mCurrentSMessageTemplate)
+	{
+		llerrs << "newMessage not called prior to addData" << llendl;
+		return;
+	}
+
+	// do we have a current block?
+	if (!mCurrentSDataBlock)
+	{
+		llerrs << "setBlock not called prior to addData" << llendl;
+		return;
+	}
+
+	// kewl, add the data if it exists
+	LLMessageVariable* var_data = mCurrentSMessageTemplate->mMemberBlocks[mCurrentSBlockName]->mMemberVariables[vnamep];
+	if (!var_data->getName())
+	{
+		llerrs << vnamep << " not a variable in block " << mCurrentSBlockName << " of " << mCurrentSMessageTemplate->mName << llendl;
+		return;
+	}
+
+	// ok, it seems ok. . . are we MVT_VARIABLE?
+	if (var_data->getType() == MVT_VARIABLE)
+	{
+		// nope
+		llerrs << vnamep << " is type MVT_VARIABLE. Call using addData(name, data, size)" << llendl;
+		return;
+	}
+	else
+	{
+		mCurrentSDataBlock->addData(vnamep, data, var_data->getSize(), type);
+		mCurrentSendTotal += var_data->getSize();
+	}
+}
+
+void LLTemplateMessageBuilder::addBinaryData(const char *varname, 
+											const void *data, S32 size)
+{
+	addData(varname, data, MVT_FIXED, size);
+}
+
+void LLTemplateMessageBuilder::addS8(const char *varname, S8 s)
+{
+	addData(varname, &s, MVT_S8, sizeof(s));
+}
+
+void LLTemplateMessageBuilder::addU8(const char *varname, U8 u)
+{
+	addData(varname, &u, MVT_U8, sizeof(u));
+}
+
+void LLTemplateMessageBuilder::addS16(const char *varname, S16 i)
+{
+	addData(varname, &i, MVT_S16, sizeof(i));
+}
+
+void LLTemplateMessageBuilder::addU16(const char *varname, U16 i)
+{
+	addData(varname, &i, MVT_U16, sizeof(i));
+}
+
+void LLTemplateMessageBuilder::addF32(const char *varname, F32 f)
+{
+	addData(varname, &f, MVT_F32, sizeof(f));
+}
+
+void LLTemplateMessageBuilder::addS32(const char *varname, S32 s)
+{
+	addData(varname, &s, MVT_S32, sizeof(s));
+}
+
+void LLTemplateMessageBuilder::addU32(const char *varname, U32 u)
+{
+	addData(varname, &u, MVT_U32, sizeof(u));
+}
+
+void LLTemplateMessageBuilder::addU64(const char *varname, U64 lu)
+{
+	addData(varname, &lu, MVT_U64, sizeof(lu));
+}
+
+void LLTemplateMessageBuilder::addF64(const char *varname, F64 d)
+{
+	addData(varname, &d, MVT_F64, sizeof(d));
+}
+
+void LLTemplateMessageBuilder::addIPAddr(const char *varname, U32 u)
+{
+	addData(varname, &u, MVT_IP_ADDR, sizeof(u));
+}
+
+void LLTemplateMessageBuilder::addIPPort(const char *varname, U16 u)
+{
+	u = htons(u);
+	addData(varname, &u, MVT_IP_PORT, sizeof(u));
+}
+
+void LLTemplateMessageBuilder::addBOOL(const char* varname, BOOL b)
+{
+	// Can't just cast a BOOL (actually a U32) to a U8.
+	// In some cases the low order bits will be zero.
+	U8 temp = (b != 0);
+	addData(varname, &temp, MVT_BOOL, sizeof(temp));
+}
+
+void LLTemplateMessageBuilder::addString(const char* varname, const char* s)
+{
+	if (s)
+		addData( varname, (void *)s, MVT_VARIABLE, (S32)strlen(s) + 1);  /* Flawfinder: ignore */  
+	else
+		addData( varname, NULL, MVT_VARIABLE, 0); 
+}
+
+void LLTemplateMessageBuilder::addString(const char* varname, const std::string& s)
+{
+	if (s.size())
+		addData( varname, (void *)s.c_str(), MVT_VARIABLE, (S32)(s.size()) + 1); 
+	else
+		addData( varname, NULL, MVT_VARIABLE, 0); 
+}
+
+void LLTemplateMessageBuilder::addVector3(const char *varname, const LLVector3& vec)
+{
+	addData(varname, vec.mV, MVT_LLVector3, sizeof(vec.mV));
+}
+
+void LLTemplateMessageBuilder::addVector4(const char *varname, const LLVector4& vec)
+{
+	addData(varname, vec.mV, MVT_LLVector4, sizeof(vec.mV));
+}
+
+void LLTemplateMessageBuilder::addVector3d(const char *varname, const LLVector3d& vec)
+{
+	addData(varname, vec.mdV, MVT_LLVector3d, sizeof(vec.mdV));
+}
+
+void LLTemplateMessageBuilder::addQuat(const char *varname, const LLQuaternion& quat)
+{
+	addData(varname, quat.packToVector3().mV, MVT_LLQuaternion, sizeof(LLVector3));
+}
+
+void LLTemplateMessageBuilder::addUUID(const char *varname, const LLUUID& uuid)
+{
+	addData(varname, uuid.mData, MVT_LLUUID, sizeof(uuid.mData));
+}
+
+static S32 zero_code(U8 **data, U32 *data_size)
+{
+	// Encoded send buffer needs to be slightly larger since the zero
+	// coding can potentially increase the size of the send data.
+	static U8 encodedSendBuffer[2 * MAX_BUFFER_SIZE];
+
+	S32 count = *data_size;
+	
+	S32 net_gain = 0;
+	U8 num_zeroes = 0;
+	
+	U8 *inptr = (U8 *)*data;
+	U8 *outptr = (U8 *)encodedSendBuffer;
+
+// skip the packet id field
+
+	for (U32 i=0;i<LL_PACKET_ID_SIZE;i++)
+	{
+		count--;
+		*outptr++ = *inptr++;
+	}
+
+// build encoded packet, keeping track of net size gain
+
+// sequential zero bytes are encoded as 0 [U8 count] 
+// with 0 0 [count] representing wrap (>256 zeroes)
+
+	while (count--)
+	{
+		if (!(*inptr))   // in a zero count
+		{
+			if (num_zeroes)
+			{
+				if (++num_zeroes > 254)
+				{
+					*outptr++ = num_zeroes;
+					num_zeroes = 0;
+				}
+				net_gain--;   // subseqent zeroes save one
+			}
+			else
+			{
+				*outptr++ = 0;
+				net_gain++;  // starting a zero count adds one
+				num_zeroes = 1;
+			}
+			inptr++;
+		}
+		else
+		{
+			if (num_zeroes)
+			{
+				*outptr++ = num_zeroes;
+				num_zeroes = 0;
+			}
+			*outptr++ = *inptr++;
+		}
+	}
+
+	if (num_zeroes)
+	{
+		*outptr++ = num_zeroes;
+	}
+
+	if (net_gain < 0)
+	{
+		// TODO: babbage: reinstate stat collecting...
+		//mCompressedPacketsOut++;
+		//mUncompressedBytesOut += *data_size;
+
+		*data = encodedSendBuffer;
+		*data_size += net_gain;
+		encodedSendBuffer[0] |= LL_ZERO_CODE_FLAG;          // set the head bit to indicate zero coding
+
+		//mCompressedBytesOut += *data_size;
+
+	}
+	//mTotalBytesOut += *data_size;
+
+	return(net_gain);
+}
+
+void LLTemplateMessageBuilder::compressMessage(U8*& buf_ptr, U32& buffer_length)
+{
+	if(ME_ZEROCODED == mCurrentSMessageTemplate->getEncoding())
+	{
+		zero_code(&buf_ptr, &buffer_length);
+	}
+}
+
+BOOL LLTemplateMessageBuilder::isMessageFull(const char* blockname) const
+{
+	if(mCurrentSendTotal > MTUBYTES)
+	{
+		return TRUE;
+	}
+	if(!blockname)
+	{
+		return FALSE;
+	}
+	char* bnamep = (char*)blockname;
+	S32 max;
+
+	LLMessageBlock* template_data = mCurrentSMessageTemplate->mMemberBlocks[bnamep];
+	
+	switch(template_data->mType)
+	{
+	case MBT_SINGLE:
+		max = 1;
+		break;
+	case MBT_MULTIPLE:
+		max = template_data->mNumber;
+		break;
+	case MBT_VARIABLE:
+	default:
+		max = MAX_BLOCKS;
+		break;
+	}
+	if(mCurrentSMessageData->mMemberBlocks[bnamep]->mBlockNumber >= max)
+	{
+		return TRUE;
+	}
+	return FALSE;
+}
+
+
+// make sure that all the desired data is in place and then copy the data into MAX_BUFFER_SIZEd buffer
+U32 LLTemplateMessageBuilder::buildMessage(U8* buffer, U32 buffer_size)
+{
+	// basic algorithm is to loop through the various pieces, building
+	// size and offset info if we encounter a -1 for mSize at any
+	// point that variable wasn't given data
+
+	// do we have a current message?
+	if (!mCurrentSMessageTemplate)
+	{
+		llerrs << "newMessage not called prior to buildMessage" << llendl;
+		return 0;
+	}
+
+	// zero out some useful values
+
+	// leave room for circuit counter
+	U32 result = LL_PACKET_ID_SIZE;
+
+	// encode message number and adjust total_offset
+	if (mCurrentSMessageTemplate->mFrequency == MFT_HIGH)
+	{
+// old, endian-dependant way
+//		memcpy(&buffer[result], &mCurrentMessageTemplate->mMessageNumber, sizeof(U8));
+
+// new, independant way
+		buffer[result] = (U8)mCurrentSMessageTemplate->mMessageNumber;
+		result += sizeof(U8);
+	}
+	else if (mCurrentSMessageTemplate->mFrequency == MFT_MEDIUM)
+	{
+		U8 temp = 255;
+		memcpy(&buffer[result], &temp, sizeof(U8));  /*Flawfinder: ignore*/
+		result += sizeof(U8);
+
+		// mask off unsightly bits
+		temp = mCurrentSMessageTemplate->mMessageNumber & 255;
+		memcpy(&buffer[result], &temp, sizeof(U8));  /*Flawfinder: ignore*/
+		result += sizeof(U8);
+	}
+	else if (mCurrentSMessageTemplate->mFrequency == MFT_LOW)
+	{
+		U8 temp = 255;
+		U16  message_num;
+		memcpy(&buffer[result], &temp, sizeof(U8));  /*Flawfinder: ignore*/
+		result += sizeof(U8);
+		memcpy(&buffer[result], &temp, sizeof(U8));  /*Flawfinder: ignore*/
+		result += sizeof(U8);
+
+		// mask off unsightly bits
+		message_num = mCurrentSMessageTemplate->mMessageNumber & 0xFFFF;
+
+	    // convert to network byte order
+		message_num = htons(message_num);
+		memcpy(&buffer[result], &message_num, sizeof(U16)); /*Flawfinder: ignore*/
+		result += sizeof(U16);
+	}
+	else
+	{
+		llerrs << "unexpected message frequency in buildMessage" << llendl;
+		return 0;
+	}
+
+	// counting variables used to encode multiple block info
+	S32 block_count = 0;
+	U8  temp_block_number;
+
+	// loop through msg blocks to loop through variables,
+	// totalling up size data and copying into buffer
+	for (LLMsgData::msg_blk_data_map_t::iterator
+			 iter = mCurrentSMessageData->mMemberBlocks.begin(),
+			 end = mCurrentSMessageData->mMemberBlocks.end();
+		 iter != end; iter++)
+	{
+		LLMsgBlkData* mbci = iter->second;
+		// do we need to encode a block code?
+		if (block_count == 0)
+		{
+			block_count = mbci->mBlockNumber;
+
+			LLMessageBlock* template_data =
+				mCurrentSMessageTemplate->mMemberBlocks[mbci->mName];
+			
+			// ok, if this is the first block of a repeating pack, set
+			// block_count and, if it's type MBT_VARIABLE encode a byte
+			// for how many there are
+			if (template_data->mType == MBT_VARIABLE)
+			{
+				// remember that mBlockNumber is a S32
+				temp_block_number = (U8)mbci->mBlockNumber;
+				if ((S32)(result + sizeof(U8)) < MAX_BUFFER_SIZE)
+				{
+				    memcpy(&buffer[result], &temp_block_number, sizeof(U8));
+				    result += sizeof(U8);
+				}
+				else
+				{
+				    // Just reporting error is likely not enough. Need
+				    // to check how to abort or error out gracefully
+				    // from this function. XXXTBD
+				    llerrs << "buildMessage failed. Message excedding "
+						   << "sendBuffersize." << llendl;
+				}
+			}
+			else if (template_data->mType == MBT_MULTIPLE)
+			{
+				if (block_count != template_data->mNumber)
+				{
+					// nope!  need to fill it in all the way!
+					llerrs << "Block " << mbci->mName
+						<< " is type MBT_MULTIPLE but only has data for "
+						<< block_count << " out of its "
+						<< template_data->mNumber << " blocks" << llendl;
+				}
+			}
+		}
+
+		// counting down multiple blocks
+		block_count--;
+
+		// now loop through the variables
+		for (LLMsgBlkData::msg_var_data_map_t::iterator iter = mbci->mMemberVarData.begin();
+			 iter != mbci->mMemberVarData.end(); iter++)
+		{
+			LLMsgVarData& mvci = *iter;
+			if (mvci.getSize() == -1)
+			{
+				// oops, this variable wasn't ever set!
+				llerrs << "The variable " << mvci.getName() << " in block "
+					<< mbci->mName << " of message "
+					<< mCurrentSMessageData->mName
+					<< " wasn't set prior to buildMessage call" << llendl;
+			}
+			else
+			{
+				S32 data_size = mvci.getDataSize();
+				if(data_size > 0)
+				{
+					// The type is MVT_VARIABLE, which means that we
+					// need to encode a size argument. Otherwise,
+					// there is no need.
+					S32 size = mvci.getSize();
+					U8 sizeb;
+					U16 sizeh;
+					switch(data_size)
+					{
+					case 1:
+						sizeb = size;
+						htonmemcpy(&buffer[result], &sizeb, MVT_U8, 1);
+						break;
+					case 2:
+						sizeh = size;
+						htonmemcpy(&buffer[result], &sizeh, MVT_U16, 2);
+						break;
+					case 4:
+						htonmemcpy(&buffer[result], &size, MVT_S32, 4);
+						break;
+					default:
+						llerrs << "Attempting to build variable field with unknown size of " << size << llendl;
+						break;
+					}
+					result += mvci.getDataSize();
+				}
+
+				// if there is any data to pack, pack it
+				if((mvci.getData() != NULL) && mvci.getSize())
+				{
+					if(result + mvci.getSize() < buffer_size)
+					{
+					    memcpy(
+							&buffer[result],
+							mvci.getData(),
+							mvci.getSize());
+					    result += mvci.getSize();
+					}
+					else
+					{
+					    // Just reporting error is likely not
+					    // enough. Need to check how to abort or error
+					    // out gracefully from this function. XXXTBD
+						llerrs << "LLMessageSystem::buildMessage failed. "
+							<< "Attempted to pack "
+							<< result + mvci.getSize()
+							<< " bytes into a buffer with size "
+							<< buffer_size << "." << llendl
+					}						
+				}
+			}
+		}
+	}
+	mbSBuilt = TRUE;
+
+	return result;
+}
+
+void LLTemplateMessageBuilder::copyFromMessageData(const LLMsgData& data)
+{
+	// copy the blocks
+	// counting variables used to encode multiple block info
+	S32 block_count = 0;
+    char *block_name = NULL;
+
+	// loop through msg blocks to loop through variables, totalling up size
+	// data and filling the new (send) message
+	LLMsgData::msg_blk_data_map_t::const_iterator iter = 
+		data.mMemberBlocks.begin();
+	LLMsgData::msg_blk_data_map_t::const_iterator end = 
+		data.mMemberBlocks.end();
+	for(; iter != end; ++iter)
+	{
+		const LLMsgBlkData* mbci = iter->second;
+		if(!mbci) continue;
+
+		// do we need to encode a block code?
+		if (block_count == 0)
+		{
+			block_count = mbci->mBlockNumber;
+			block_name = (char *)mbci->mName;
+		}
+
+		// counting down mutliple blocks
+		block_count--;
+
+		nextBlock(block_name);
+
+		// now loop through the variables
+		LLMsgBlkData::msg_var_data_map_t::const_iterator dit = mbci->mMemberVarData.begin();
+		LLMsgBlkData::msg_var_data_map_t::const_iterator dend = mbci->mMemberVarData.end();
+		
+		for(; dit != dend; ++dit)
+		{
+			const LLMsgVarData& mvci = *dit;
+			addData(mvci.getName(), mvci.getData(), mvci.getType(), mvci.getSize());
+		}
+	}
+}
+
+//virtual 
+void LLTemplateMessageBuilder::copyFromLLSD(const LLSD&)
+{
+	// TODO
+}
+
+//virtual
+void LLTemplateMessageBuilder::setBuilt(BOOL b) { mbSBuilt = b; }
+
+//virtual 
+BOOL LLTemplateMessageBuilder::isBuilt() const {return mbSBuilt;}
+
+//virtual 
+BOOL LLTemplateMessageBuilder::isClear() const {return mbSClear;}
+
+//virtual 
+S32 LLTemplateMessageBuilder::getMessageSize() {return mCurrentSendTotal;}
+
+//virtual 
+const char* LLTemplateMessageBuilder::getMessageName() const 
+{
+	return mCurrentSMessageName;
+}
diff --git a/indra/llmessage/lltemplatemessagebuilder.h b/indra/llmessage/lltemplatemessagebuilder.h
new file mode 100644
index 0000000000..ae533288fb
--- /dev/null
+++ b/indra/llmessage/lltemplatemessagebuilder.h
@@ -0,0 +1,88 @@
+#ifndef LL_LLTEMPLATEMESSAGEBUILDER_H
+#define LL_LLTEMPLATEMESSAGEBUILDER_H
+
+#include <map>
+
+#include "llmessagebuilder.h"
+#include "llmsgvariabletype.h"
+
+class LLMsgData;
+class LLMessageTemplate;
+class LLMsgBlkData;
+class LLMessageTemplate;
+
+class LLTemplateMessageBuilder : public LLMessageBuilder
+{
+public:
+	
+	typedef std::map<const char *, LLMessageTemplate*> message_template_name_map_t;
+
+	LLTemplateMessageBuilder(message_template_name_map_t&);
+	virtual ~LLTemplateMessageBuilder();
+
+	virtual void newMessage(const char *name);
+
+	virtual void nextBlock(const char* blockname);
+	virtual BOOL removeLastBlock(); // TODO: babbage: remove this horror...
+
+	/** All add* methods expect pointers to canonical varname strings. */
+	virtual void addBinaryData(const char *varname, const void *data, 
+							   S32 size);
+	virtual void addBOOL(const char* varname, BOOL b);
+	virtual void addS8(const char *varname, S8 s);
+	virtual void addU8(const char *varname, U8 u);
+	virtual void addS16(const char *varname, S16 i);
+	virtual void addU16(const char *varname, U16 i);
+	virtual void addF32(const char *varname, F32 f);
+	virtual void addS32(const char *varname, S32 s);
+	virtual void addU32(const char *varname, U32 u);
+	virtual void addU64(const char *varname, U64 lu);
+	virtual void addF64(const char *varname, F64 d);
+	virtual void addVector3(const char *varname, const LLVector3& vec);
+	virtual void addVector4(const char *varname, const LLVector4& vec);
+	virtual void addVector3d(const char *varname, const LLVector3d& vec);
+	virtual void addQuat(const char *varname, const LLQuaternion& quat);
+	virtual void addUUID(const char *varname, const LLUUID& uuid);
+	virtual void addIPAddr(const char *varname, const U32 ip);
+	virtual void addIPPort(const char *varname, const U16 port);
+	virtual void addString(const char* varname, const char* s);
+	virtual void addString(const char* varname, const std::string& s);
+
+	virtual BOOL isMessageFull(const char* blockname) const;
+	virtual void compressMessage(U8*& buf_ptr, U32& buffer_length);
+
+	virtual BOOL isBuilt() const;
+	virtual BOOL isClear() const;
+	virtual U32 buildMessage(U8* buffer, U32 buffer_size); 
+        /**< Return built message size */
+	
+	virtual void clearMessage();
+
+	// TODO: babbage: remove this horror.
+	virtual void setBuilt(BOOL b);
+
+	virtual S32 getMessageSize();
+	virtual const char* getMessageName() const;
+
+	virtual void copyFromMessageData(const LLMsgData& data);
+	virtual void copyFromLLSD(const LLSD&);
+
+private:
+	void addData(const char *varname, const void *data, 
+					 EMsgVariableType type, S32 size);
+	
+	void addData(const char *varname, const void *data, 
+						EMsgVariableType type);
+
+	LLMsgData* mCurrentSMessageData;
+	LLMessageTemplate* mCurrentSMessageTemplate;
+	LLMsgBlkData* mCurrentSDataBlock;
+	char* mCurrentSMessageName;
+	char* mCurrentSBlockName;
+	BOOL mbSBuilt;
+	BOOL mbSClear;
+	S32	 mCurrentSendTotal;
+	message_template_name_map_t& mMessageTemplates;
+};
+
+#endif // LL_LLTEMPLATEMESSAGEBUILDER_H
diff --git a/indra/llmessage/lltemplatemessagereader.cpp b/indra/llmessage/lltemplatemessagereader.cpp
new file mode 100644
index 0000000000..892efb8697
--- /dev/null
+++ b/indra/llmessage/lltemplatemessagereader.cpp
@@ -0,0 +1,750 @@
+#include "lltemplatemessagereader.h"
+
+#include "llfasttimer.h"
+#include "llmessagebuilder.h"
+#include "llmessagetemplate.h"
+#include "llquaternion.h"
+#include "message.h"
+#include "u64.h"
+#include "v3dmath.h"
+#include "v3math.h"
+#include "v4math.h"
+
+LLTemplateMessageReader::LLTemplateMessageReader(message_template_number_map_t&
+												 number_template_map) :
+	mReceiveSize(0),
+	mCurrentRMessageTemplate(NULL),
+	mCurrentRMessageData(NULL),
+	mMessageNumbers(number_template_map)
+{
+}
+
+//virtual 
+LLTemplateMessageReader::~LLTemplateMessageReader()
+{
+	delete mCurrentRMessageData;
+	mCurrentRMessageData = NULL;
+}
+
+//virtual
+void LLTemplateMessageReader::clearMessage()
+{
+	mReceiveSize = -1;
+	mCurrentRMessageTemplate = NULL;
+	delete mCurrentRMessageData;
+	mCurrentRMessageData = NULL;
+}
+
+void LLTemplateMessageReader::getData(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum, S32 max_size)
+{
+	// is there a message ready to go?
+	if (mReceiveSize == -1)
+	{
+		llerrs << "No message waiting for decode 2!" << llendl;
+		return;
+	}
+
+	if (!mCurrentRMessageData)
+	{
+		llerrs << "Invalid mCurrentMessageData in getData!" << llendl;
+		return;
+	}
+
+	char *bnamep = (char *)blockname + blocknum; // this works because it's just a hash.  The bnamep is never derefference
+	char *vnamep = (char *)varname; 
+
+	LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
+
+	if (iter == mCurrentRMessageData->mMemberBlocks.end())
+	{
+		llerrs << "Block " << blockname << " #" << blocknum
+			<< " not in message " << mCurrentRMessageData->mName << llendl;
+		return;
+	}
+
+	LLMsgBlkData *msg_block_data = iter->second;
+	LLMsgVarData& vardata = msg_block_data->mMemberVarData[vnamep];
+
+	if (!vardata.getName())
+	{
+		llerrs << "Variable "<< vnamep << " not in message "
+			<< mCurrentRMessageData->mName<< " block " << bnamep << llendl;
+		return;
+	}
+
+	if (size && size != vardata.getSize())
+	{
+		llerrs << "Msg " << mCurrentRMessageData->mName 
+			<< " variable " << vnamep
+			<< " is size " << vardata.getSize()
+			<< " but copying into buffer of size " << size
+			<< llendl;
+		return;
+	}
+
+
+	const S32 vardata_size = vardata.getSize();
+	if( max_size >= vardata_size )
+	{   
+		switch( vardata_size )
+		{ 
+		case 1:
+			*((U8*)datap) = *((U8*)vardata.getData());
+			break;
+		case 2:
+			*((U16*)datap) = *((U16*)vardata.getData());
+			break;
+		case 4:
+			*((U32*)datap) = *((U32*)vardata.getData());
+			break;
+		case 8:
+			((U32*)datap)[0] = ((U32*)vardata.getData())[0];
+			((U32*)datap)[1] = ((U32*)vardata.getData())[1];
+			break;
+		default:
+			memcpy(datap, vardata.getData(), vardata_size);
+			break;
+		}
+	}
+	else
+	{
+		llwarns << "Msg " << mCurrentRMessageData->mName 
+			<< " variable " << vnamep
+			<< " is size " << vardata.getSize()
+			<< " but truncated to max size of " << max_size
+			<< llendl;
+
+		memcpy(datap, vardata.getData(), max_size);
+	}
+}
+
+S32 LLTemplateMessageReader::getNumberOfBlocks(const char *blockname)
+{
+	// is there a message ready to go?
+	if (mReceiveSize == -1)
+	{
+		llerrs << "No message waiting for decode 3!" << llendl;
+		return -1;
+	}
+
+	if (!mCurrentRMessageData)
+	{
+		llerrs << "Invalid mCurrentRMessageData in getData!" << llendl;
+		return -1;
+	}
+
+	char *bnamep = (char *)blockname; 
+
+	LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
+	
+	if (iter == mCurrentRMessageData->mMemberBlocks.end())
+	{
+//		sprintf(errmsg, "Block %s not in message %s", bnamep, mCurrentRMessageData->mName);
+//		llerrs << errmsg << llendl;
+//		return -1;
+		return 0;
+	}
+
+	return (iter->second)->mBlockNumber;
+}
+
+S32 LLTemplateMessageReader::getSize(const char *blockname, const char *varname)
+{
+	// is there a message ready to go?
+	if (mReceiveSize == -1)
+	{
+		llerrs << "No message waiting for decode 4!" << llendl;
+		return -1;
+	}
+
+	if (!mCurrentRMessageData)
+	{
+		llerrs << "Invalid mCurrentRMessageData in getData!" << llendl;
+		return -1;
+	}
+
+	char *bnamep = (char *)blockname; 
+
+	LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
+	
+	if (iter == mCurrentRMessageData->mMemberBlocks.end())
+	{
+		llerrs << "Block " << bnamep << " not in message "
+			<< mCurrentRMessageData->mName << llendl;
+		return -1;
+	}
+
+	char *vnamep = (char *)varname; 
+
+	LLMsgBlkData* msg_data = iter->second;
+	LLMsgVarData& vardata = msg_data->mMemberVarData[vnamep];
+	
+	if (!vardata.getName())
+	{
+		llerrs << "Variable " << varname << " not in message "
+			<< mCurrentRMessageData->mName << " block " << bnamep << llendl;
+		return -1;
+	}
+
+	if (mCurrentRMessageTemplate->mMemberBlocks[bnamep]->mType != MBT_SINGLE)
+	{
+		llerrs << "Block " << bnamep << " isn't type MBT_SINGLE,"
+			" use getSize with blocknum argument!" << llendl;
+		return -1;
+	}
+
+	return vardata.getSize();
+}
+
+S32 LLTemplateMessageReader::getSize(const char *blockname, S32 blocknum, const char *varname)
+{
+	// is there a message ready to go?
+	if (mReceiveSize == -1)
+	{
+		llerrs << "No message waiting for decode 5!" << llendl;
+		return -1;
+	}
+
+	if (!mCurrentRMessageData)
+	{
+		llerrs << "Invalid mCurrentRMessageData in getData!" << llendl;
+		return -1;
+	}
+
+	char *bnamep = (char *)blockname + blocknum; 
+	char *vnamep = (char *)varname; 
+
+	LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
+	
+	if (iter == mCurrentRMessageData->mMemberBlocks.end())
+	{
+		llerrs << "Block " << bnamep << " not in message "
+			<< mCurrentRMessageData->mName << llendl;
+		return -1;
+	}
+
+	LLMsgBlkData* msg_data = iter->second;
+	LLMsgVarData& vardata = msg_data->mMemberVarData[vnamep];
+	
+	if (!vardata.getName())
+	{
+		llerrs << "Variable " << vnamep << " not in message "
+			<<  mCurrentRMessageData->mName << " block " << bnamep << llendl;
+		return -1;
+	}
+
+	return vardata.getSize();
+}
+
+void LLTemplateMessageReader::getBinaryData(const char *blockname, 
+											const char *varname, void *datap, 
+											S32 size, S32 blocknum, 
+											S32 max_size)
+{
+	getData(blockname, varname, datap, size, blocknum, max_size);
+}
+
+void LLTemplateMessageReader::getS8(const char *block, const char *var, 
+										S8 &u, S32 blocknum)
+{
+	getData(block, var, &u, sizeof(S8), blocknum);
+}
+
+void LLTemplateMessageReader::getU8(const char *block, const char *var, 
+										U8 &u, S32 blocknum)
+{
+	getData(block, var, &u, sizeof(U8), blocknum);
+}
+
+void LLTemplateMessageReader::getBOOL(const char *block, const char *var, 
+										  BOOL &b, S32 blocknum )
+{
+	U8 value;
+	getData(block, var, &value, sizeof(U8), blocknum);
+	b = (BOOL) value;
+}
+
+void LLTemplateMessageReader::getS16(const char *block, const char *var, 
+										 S16 &d, S32 blocknum)
+{
+	getData(block, var, &d, sizeof(S16), blocknum);
+}
+
+void LLTemplateMessageReader::getU16(const char *block, const char *var, 
+										 U16 &d, S32 blocknum)
+{
+	getData(block, var, &d, sizeof(U16), blocknum);
+}
+
+void LLTemplateMessageReader::getS32(const char *block, const char *var, 
+										 S32 &d, S32 blocknum)
+{
+	getData(block, var, &d, sizeof(S32), blocknum);
+}
+
+void LLTemplateMessageReader::getU32(const char *block, const char *var, 
+									 U32 &d, S32 blocknum)
+{
+	getData(block, var, &d, sizeof(U32), blocknum);
+}
+
+void LLTemplateMessageReader::getU64(const char *block, const char *var, 
+									 U64 &d, S32 blocknum)
+{
+	getData(block, var, &d, sizeof(U64), blocknum);
+}
+
+void LLTemplateMessageReader::getF32(const char *block, const char *var, 
+									 F32 &d, S32 blocknum)
+{
+	getData(block, var, &d, sizeof(F32), blocknum);
+
+	if( !llfinite( d ) )
+	{
+		llwarns << "non-finite in getF32Fast " << block << " " << var 
+				<< llendl;
+		d = 0;
+	}
+}
+
+void LLTemplateMessageReader::getF64(const char *block, const char *var, 
+									 F64 &d, S32 blocknum)
+{
+	getData(block, var, &d, sizeof(F64), blocknum);
+
+	if( !llfinite( d ) )
+	{
+		llwarns << "non-finite in getF64Fast " << block << " " << var 
+				<< llendl;
+		d = 0;
+	}
+}
+
+void LLTemplateMessageReader::getVector3(const char *block, const char *var, 
+										 LLVector3 &v, S32 blocknum )
+{
+	getData(block, var, v.mV, sizeof(v.mV), blocknum);
+
+	if( !v.isFinite() )
+	{
+		llwarns << "non-finite in getVector3Fast " << block << " " 
+				<< var << llendl;
+		v.zeroVec();
+	}
+}
+
+void LLTemplateMessageReader::getVector4(const char *block, const char *var, 
+										 LLVector4 &v, S32 blocknum)
+{
+	getData(block, var, v.mV, sizeof(v.mV), blocknum);
+
+	if( !v.isFinite() )
+	{
+		llwarns << "non-finite in getVector4Fast " << block << " " 
+				<< var << llendl;
+		v.zeroVec();
+	}
+}
+
+void LLTemplateMessageReader::getVector3d(const char *block, const char *var, 
+										  LLVector3d &v, S32 blocknum )
+{
+	getData(block, var, v.mdV, sizeof(v.mdV), blocknum);
+
+	if( !v.isFinite() )
+	{
+		llwarns << "non-finite in getVector3dFast " << block << " " 
+				<< var << llendl;
+		v.zeroVec();
+	}
+
+}
+
+void LLTemplateMessageReader::getQuat(const char *block, const char *var, 
+									  LLQuaternion &q, S32 blocknum)
+{
+	LLVector3 vec;
+	getData(block, var, vec.mV, sizeof(vec.mV), blocknum);
+	if( vec.isFinite() )
+	{
+		q.unpackFromVector3( vec );
+	}
+	else
+	{
+		llwarns << "non-finite in getQuatFast " << block << " " << var 
+				<< llendl;
+		q.loadIdentity();
+	}
+}
+
+void LLTemplateMessageReader::getUUID(const char *block, const char *var, 
+									  LLUUID &u, S32 blocknum)
+{
+	getData(block, var, u.mData, sizeof(u.mData), blocknum);
+}
+
+inline void LLTemplateMessageReader::getIPAddr(const char *block, const char *var, U32 &u, S32 blocknum)
+{
+	getData(block, var, &u, sizeof(U32), blocknum);
+}
+
+inline void LLTemplateMessageReader::getIPPort(const char *block, const char *var, U16 &u, S32 blocknum)
+{
+	getData(block, var, &u, sizeof(U16), blocknum);
+	u = ntohs(u);
+}
+
+inline void LLTemplateMessageReader::getString(const char *block, const char *var, S32 buffer_size, char *s, S32 blocknum )
+{
+	s[0] = '\0';
+	getData(block, var, s, 0, blocknum, buffer_size);
+	s[buffer_size - 1] = '\0';
+}
+
+//virtual 
+S32 LLTemplateMessageReader::getMessageSize() const
+{
+	return mReceiveSize;
+}
+
+// Returns template for the message contained in buffer
+BOOL LLTemplateMessageReader::decodeTemplate(  
+		const U8* buffer, S32 buffer_size,  // inputs
+		LLMessageTemplate** msg_template ) // outputs
+{
+	const U8* header = buffer + LL_PACKET_ID_SIZE;
+
+	// is there a message ready to go?
+	if (buffer_size <= 0)
+	{
+		llwarns << "No message waiting for decode!" << llendl;
+		return(FALSE);
+	}
+
+	U32 num = 0;
+
+	if (header[0] != 255)
+	{
+		// high frequency message
+		num = header[0];
+	}
+	else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 1)) && (header[1] != 255))
+	{
+		// medium frequency message
+		num = (255 << 8) | header[1];
+	}
+	else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 3)) && (header[1] == 255))
+	{
+		// low frequency message
+		U16	message_id_U16 = 0;
+		// I think this check busts the message system.
+		// it appears that if there is a NULL in the message #, it won't copy it....
+		// what was the goal?
+		//if(header[2])
+		memcpy(&message_id_U16, &header[2], 2);
+
+		// dependant on endian-ness:
+		//		U32	temp = (255 << 24) | (255 << 16) | header[2];
+
+		// independant of endian-ness:
+		message_id_U16 = ntohs(message_id_U16);
+		num = 0xFFFF0000 | message_id_U16;
+	}
+	else // bogus packet received (too short)
+	{
+		llwarns << "Packet with unusable length received (too short): "
+				<< buffer_size << llendl;
+		return(FALSE);
+	}
+
+	LLMessageTemplate* temp = get_ptr_in_map(mMessageNumbers,num);
+	if (temp)
+	{
+		*msg_template = temp;
+	}
+	else
+	{
+		llwarns << "Message #" << std::hex << num << std::dec
+			<< " received but not registered!" << llendl;
+		gMessageSystem->callExceptionFunc(MX_UNREGISTERED_MESSAGE);
+		return(FALSE);
+	}
+
+	return(TRUE);
+}
+
+void LLTemplateMessageReader::logRanOffEndOfPacket( const LLHost& host )
+{
+	// we've run off the end of the packet!
+	llwarns << "Ran off end of packet " << mCurrentRMessageTemplate->mName
+//			<< " with id " << mCurrentRecvPacketID 
+			<< " from " << host
+			<< llendl;
+	if(gMessageSystem->mVerboseLog)
+	{
+		llinfos << "MSG: -> " << host << "\tREAD PAST END:\t"
+//				<< mCurrentRecvPacketID << " "
+				<< getMessageName() << llendl;
+	}
+	gMessageSystem->callExceptionFunc(MX_RAN_OFF_END_OF_PACKET);
+}
+
+// decode a given message
+BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender )
+{
+	llassert( mReceiveSize >= 0 );
+	llassert( mCurrentRMessageTemplate);
+	llassert( !mCurrentRMessageData );
+	delete mCurrentRMessageData; // just to make sure
+
+	S32 decode_pos = LL_PACKET_ID_SIZE + (S32)(mCurrentRMessageTemplate->mFrequency);
+
+	// create base working data set
+	mCurrentRMessageData = new LLMsgData(mCurrentRMessageTemplate->mName);
+	
+	// loop through the template building the data structure as we go
+	for (LLMessageTemplate::message_block_map_t::iterator iter = mCurrentRMessageTemplate->mMemberBlocks.begin();
+		 iter != mCurrentRMessageTemplate->mMemberBlocks.end(); iter++)
+	{
+		LLMessageBlock* mbci = iter->second;
+		U8	repeat_number;
+		S32	i;
+
+		// how many of this block?
+
+		if (mbci->mType == MBT_SINGLE)
+		{
+			// just one
+			repeat_number = 1;
+		}
+		else if (mbci->mType == MBT_MULTIPLE)
+		{
+			// a known number
+			repeat_number = mbci->mNumber;
+		}
+		else if (mbci->mType == MBT_VARIABLE)
+		{
+			// need to read the number from the message
+			// repeat number is a single byte
+			if (decode_pos >= mReceiveSize)
+			{
+				logRanOffEndOfPacket( sender );
+				return FALSE;
+			}
+			repeat_number = buffer[decode_pos];
+			decode_pos++;
+		}
+		else
+		{
+			llerrs << "Unknown block type" << llendl;
+			return FALSE;
+		}
+
+		LLMsgBlkData* cur_data_block = NULL;
+
+		// now loop through the block
+		for (i = 0; i < repeat_number; i++)
+		{
+			if (i)
+			{
+				// build new name to prevent collisions
+				// TODO: This should really change to a vector
+				cur_data_block = new LLMsgBlkData(mbci->mName, repeat_number);
+				cur_data_block->mName = mbci->mName + i;
+			}
+			else
+			{
+				cur_data_block = new LLMsgBlkData(mbci->mName, repeat_number);
+			}
+
+			// add the block to the message
+			mCurrentRMessageData->addBlock(cur_data_block);
+
+			// now read the variables
+			for (LLMessageBlock::message_variable_map_t::iterator iter = mbci->mMemberVariables.begin();
+				 iter != mbci->mMemberVariables.end(); iter++)
+			{
+				LLMessageVariable& mvci = *(iter->second);
+				// ok, build out the variables
+				// add variable block
+				cur_data_block->addVariable(mvci.getName(), mvci.getType());
+
+				// what type of variable?
+				if (mvci.getType() == MVT_VARIABLE)
+				{
+					// variable, get the number of bytes to read from the template
+					S32 data_size = mvci.getSize();
+					U8 tsizeb = 0;
+					U16 tsizeh = 0;
+					U32 tsize = 0;
+
+					if ((decode_pos + data_size) > mReceiveSize)
+					{
+						logRanOffEndOfPacket( sender );
+						return FALSE;
+					}
+					switch(data_size)
+					{
+					case 1:
+						htonmemcpy(&tsizeb, &buffer[decode_pos], MVT_U8, 1);
+						tsize = tsizeb;
+						break;
+					case 2:
+						htonmemcpy(&tsizeh, &buffer[decode_pos], MVT_U16, 2);
+						tsize = tsizeh;
+						break;
+					case 4:
+						htonmemcpy(&tsizeb, &buffer[decode_pos], MVT_U32, 4);
+						break;
+					default:
+						llerrs << "Attempting to read variable field with unknown size of " << data_size << llendl;
+						break;
+						
+					}
+					decode_pos += data_size;
+
+					if ((decode_pos + (S32)tsize) > mReceiveSize)
+					{
+						logRanOffEndOfPacket( sender );
+						return FALSE;
+					}
+					cur_data_block->addData(mvci.getName(), &buffer[decode_pos], tsize, mvci.getType());
+					decode_pos += tsize;
+				}
+				else
+				{
+					// fixed!
+					// so, copy data pointer and set data size to fixed size
+
+					if ((decode_pos + mvci.getSize()) > mReceiveSize)
+					{
+						logRanOffEndOfPacket( sender );
+						return FALSE;
+					}
+
+					cur_data_block->addData(mvci.getName(), &buffer[decode_pos], mvci.getSize(), mvci.getType());
+					decode_pos += mvci.getSize();
+				}
+			}
+		}
+	}
+
+	if (mCurrentRMessageData->mMemberBlocks.empty()
+		&& !mCurrentRMessageTemplate->mMemberBlocks.empty())
+	{
+		lldebugs << "Empty message '" << mCurrentRMessageTemplate->mName << "' (no blocks)" << llendl;
+		return FALSE;
+	}
+
+	{
+		static LLTimer decode_timer;
+
+		if(LLMessageReader::getTimeDecodes() || gMessageSystem->getTimingCallback())
+		{
+			decode_timer.reset();
+		}
+
+		//	if( mCurrentRMessageTemplate->mName == _PREHASH_AgentToNewRegion )
+		//	{
+		//		VTResume();  // VTune
+		//	}
+
+		{
+			LLFastTimer t(LLFastTimer::FTM_PROCESS_MESSAGES);
+			if( !mCurrentRMessageTemplate->callHandlerFunc(gMessageSystem) )
+			{
+				llwarns << "Message from " << sender << " with no handler function received: " << mCurrentRMessageTemplate->mName << llendl;
+			}
+		}
+
+		//	if( mCurrentRMessageTemplate->mName == _PREHASH_AgentToNewRegion )
+		//	{
+		//		VTPause();	// VTune
+		//	}
+
+		if(LLMessageReader::getTimeDecodes() || gMessageSystem->getTimingCallback())
+		{
+			F32 decode_time = decode_timer.getElapsedTimeF32();
+
+			if (gMessageSystem->getTimingCallback())
+			{
+				(gMessageSystem->getTimingCallback())(mCurrentRMessageTemplate->mName,
+								decode_time,
+								gMessageSystem->getTimingCallbackData());
+			}
+
+			if (LLMessageReader::getTimeDecodes())
+			{
+				mCurrentRMessageTemplate->mDecodeTimeThisFrame += decode_time;
+
+				mCurrentRMessageTemplate->mTotalDecoded++;
+				mCurrentRMessageTemplate->mTotalDecodeTime += decode_time;
+
+				if( mCurrentRMessageTemplate->mMaxDecodeTimePerMsg < decode_time )
+				{
+					mCurrentRMessageTemplate->mMaxDecodeTimePerMsg = decode_time;
+				}
+
+
+				if(decode_time > LLMessageReader::getTimeDecodesSpamThreshold())
+				{
+					lldebugs << "--------- Message " << mCurrentRMessageTemplate->mName << " decode took " << decode_time << " seconds. (" <<
+						mCurrentRMessageTemplate->mMaxDecodeTimePerMsg << " max, " <<
+						(mCurrentRMessageTemplate->mTotalDecodeTime / mCurrentRMessageTemplate->mTotalDecoded) << " avg)" << llendl;
+				}
+			}
+		}
+	}
+	return TRUE;
+}
+
+BOOL LLTemplateMessageReader::validateMessage(const U8* buffer, 
+											  S32 buffer_size, 
+											  const LLHost& sender)
+{
+	mReceiveSize = buffer_size;
+	BOOL result = decodeTemplate(buffer, buffer_size, &mCurrentRMessageTemplate );
+	if(result)
+	{
+		mCurrentRMessageTemplate->mReceiveCount++;
+		lldebugst(LLERR_MESSAGE) << "MessageRecvd:" 
+								 << mCurrentRMessageTemplate->mName 
+								 << " from " << sender << llendl;
+	}
+	return result;
+}
+
+BOOL LLTemplateMessageReader::readMessage(const U8* buffer, 
+										  const LLHost& sender)
+{
+	return decodeData(buffer, sender);
+}
+
+//virtual 
+const char* LLTemplateMessageReader::getMessageName() const
+{
+	static char empty_string[] = "";
+	return mCurrentRMessageTemplate ? mCurrentRMessageTemplate->mName : empty_string;
+}
+
+//virtual 
+bool LLTemplateMessageReader::isTrusted() const
+{
+	return mCurrentRMessageTemplate->getTrust() == MT_TRUST;
+}
+
+//virtual 
+bool LLTemplateMessageReader::isBanned(bool trustedSource) const
+{
+	return mCurrentRMessageTemplate->isBanned(trustedSource);
+}
+
+//virtual 
+void LLTemplateMessageReader::copyToBuilder(LLMessageBuilder& builder) const
+{
+	if(NULL == mCurrentRMessageTemplate)
+    {
+        return;
+    }
+	builder.copyFromMessageData(*mCurrentRMessageData);
+}
diff --git a/indra/llmessage/lltemplatemessagereader.h b/indra/llmessage/lltemplatemessagereader.h
new file mode 100644
index 0000000000..dd5ee393fe
--- /dev/null
+++ b/indra/llmessage/lltemplatemessagereader.h
@@ -0,0 +1,98 @@
+#ifndef LL_LLTEMPLATEMESSAGEREADER_H
+#define LL_LLTEMPLATEMESSAGEREADER_H
+
+#include "llmessagereader.h"
+
+#include <map>
+
+class LLMessageTemplate;
+class LLMsgData;
+
+class LLTemplateMessageReader : public LLMessageReader
+{
+public:
+
+	typedef std::map<U32, LLMessageTemplate*> message_template_number_map_t;
+
+	LLTemplateMessageReader(message_template_number_map_t&);
+	virtual ~LLTemplateMessageReader();
+
+	/** All get* methods expect pointers to canonical strings. */
+	virtual void getBinaryData(const char *blockname, const char *varname, 
+							   void *datap, S32 size, S32 blocknum = 0, 
+							   S32 max_size = S32_MAX);
+	virtual void getBOOL(const char *block, const char *var, BOOL &data, 
+						 S32 blocknum = 0);
+	virtual void getS8(const char *block, const char *var, S8 &data, 
+					   S32 blocknum = 0);
+	virtual void getU8(const char *block, const char *var, U8 &data, 
+					   S32 blocknum = 0);
+	virtual void getS16(const char *block, const char *var, S16 &data, 
+						S32 blocknum = 0);
+	virtual void getU16(const char *block, const char *var, U16 &data, 
+						S32 blocknum = 0);
+	virtual void getS32(const char *block, const char *var, S32 &data, 
+						S32 blocknum = 0);
+	virtual void getF32(const char *block, const char *var, F32 &data, 
+						S32 blocknum = 0);
+	virtual void getU32(const char *block, const char *var, U32 &data, 
+						S32 blocknum = 0);
+	virtual void getU64(const char *block, const char *var, U64 &data, 
+						S32 blocknum = 0);
+	virtual void getF64(const char *block, const char *var, F64 &data, 
+						S32 blocknum = 0);
+	virtual void getVector3(const char *block, const char *var, 
+							LLVector3 &vec, S32 blocknum = 0);
+	virtual void getVector4(const char *block, const char *var, 
+							LLVector4 &vec, S32 blocknum = 0);
+	virtual void getVector3d(const char *block, const char *var, 
+							 LLVector3d &vec, S32 blocknum = 0);
+	virtual void getQuat(const char *block, const char *var, LLQuaternion &q, 
+						 S32 blocknum = 0);
+	virtual void getUUID(const char *block, const char *var, LLUUID &uuid, 
+						 S32 blocknum = 0);
+	virtual void getIPAddr(const char *block, const char *var, U32 &ip, 
+						   S32 blocknum = 0);
+	virtual void getIPPort(const char *block, const char *var, U16 &port, 
+						   S32 blocknum = 0);
+	virtual void getString(const char *block, const char *var, 
+						   S32 buffer_size, char *buffer, S32 blocknum = 0);
+
+	virtual S32	getNumberOfBlocks(const char *blockname);
+	virtual S32	getSize(const char *blockname, const char *varname);
+	virtual S32	getSize(const char *blockname, S32 blocknum, 
+						const char *varname);
+
+	virtual void clearMessage();
+
+	virtual const char* getMessageName() const;
+	virtual S32 getMessageSize() const;
+
+	virtual void copyToBuilder(LLMessageBuilder&) const;
+
+	BOOL validateMessage(const U8* buffer, S32 buffer_size, 
+						 const LLHost& sender);
+	BOOL readMessage(const U8* buffer, const LLHost& sender);
+
+	bool isTrusted() const;
+	bool isBanned(bool trusted_source) const;
+
+private:
+
+	void getData(const char *blockname, const char *varname, void *datap, 
+				 S32 size = 0, S32 blocknum = 0, S32 max_size = S32_MAX);
+
+	BOOL decodeTemplate(const U8* buffer, S32 buffer_size,  // inputs
+						LLMessageTemplate** msg_template ); // outputs
+
+	void logRanOffEndOfPacket( const LLHost& host );
+
+	BOOL decodeData(const U8* buffer, const LLHost& sender );
+
+	S32	mReceiveSize;
+	LLMessageTemplate* mCurrentRMessageTemplate;
+	LLMsgData* mCurrentRMessageData;
+	message_template_number_map_t& mMessageNumbers;
+};
+
+#endif // LL_LLTEMPLATEMESSAGEREADER_H
diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp
index 6fb319326b..78d12cbda9 100644
--- a/indra/llmessage/message.cpp
+++ b/indra/llmessage/message.cpp
@@ -36,9 +36,20 @@
 #include "lldarray.h"
 #include "lldir.h"
 #include "llerror.h"
+#include "llerrorlegacy.h"
 #include "llfasttimer.h"
+#include "llhttpclient.h"
+#include "llhttpsender.h"
 #include "llmd5.h"
+#include "llmessagebuilder.h"
+#include "llmessageconfig.h"
+#include "llpumpio.h"
+#include "lltemplatemessagebuilder.h"
+#include "lltemplatemessagereader.h"
+#include "llmessagetemplate.h"
 #include "llsd.h"
+#include "llsdmessagebuilder.h"
+#include "llsdmessagereader.h"
 #include "lltransfermanager.h"
 #include "lluuid.h"
 #include "llxfermanager.h"
@@ -55,405 +66,6 @@
 static const F32 CIRCUIT_DUMP_TIMEOUT = 30.f;
 static const S32 TRUST_TIME_WINDOW = 3;
 
-class LLMsgVarData
-{
-public:
-	LLMsgVarData() : mName(NULL), mSize(-1), mDataSize(-1), mData(NULL), mType(MVT_U8)
-	{
-	}
-
-	LLMsgVarData(const char *name, EMsgVariableType type) : mSize(-1), mDataSize(-1), mData(NULL), mType(type)
-	{
-		mName = (char *)name; 
-	}
-
-	~LLMsgVarData() 
-	{
-		// copy constructor just copies the mData pointer, so only delete mData explicitly
-	}
-	
-	void deleteData() 
-	{
-		delete[] mData;
-		mData = NULL;
-	}
-	
-	void addData(const void *indata, S32 size, EMsgVariableType type, S32 data_size = -1);
-
-	char *getName() const	{ return mName; }
-	S32 getSize() const		{ return mSize; }
-	void *getData()			{ return (void*)mData; }
-	S32 getDataSize() const	{ return mDataSize; }
-	EMsgVariableType getType() const	{ return mType; }
-
-protected:
-	char				*mName;
-	S32					mSize;
-	S32					mDataSize;
-
-	U8					*mData;
-	EMsgVariableType	mType;
-};
-
-
-class LLMsgBlkData
-{
-public:
-	LLMsgBlkData(const char *name, S32 blocknum) : mOffset(-1), mBlockNumber(blocknum), mTotalSize(-1) 
-	{ 
-		mName = (char *)name; 
-	}
-
-	~LLMsgBlkData()
-	{
-		for (msg_var_data_map_t::iterator iter = mMemberVarData.begin();
-			 iter != mMemberVarData.end(); iter++)
-		{
-			iter->deleteData();
-		}
-	}
-
-	void addVariable(const char *name, EMsgVariableType type)
-	{
-		LLMsgVarData tmp(name,type);
-		mMemberVarData[name] = tmp;
-	}
-
-	void addData(char *name, const void *data, S32 size, EMsgVariableType type, S32 data_size = -1)
-	{
-		LLMsgVarData* temp = &mMemberVarData[name]; // creates a new entry if one doesn't exist
-		temp->addData(data, size, type, data_size);
-	}
-
-	S32									mOffset;
-	S32									mBlockNumber;
-	typedef LLDynamicArrayIndexed<LLMsgVarData, const char *, 8> msg_var_data_map_t;
-	msg_var_data_map_t					mMemberVarData;
-	char								*mName;
-	S32									mTotalSize;
-};
-
-
-class LLMsgData
-{
-public:
-	LLMsgData(const char *name) : mTotalSize(-1) 
-	{ 
-		mName = (char *)name; 
-	}
-	~LLMsgData()
-	{
-		for_each(mMemberBlocks.begin(), mMemberBlocks.end(), DeletePairedPointer());
-	}
-
-	void addBlock(LLMsgBlkData *blockp)
-	{
-		mMemberBlocks[blockp->mName] = blockp;
-	}
-
-	void addDataFast(char *blockname, char *varname, const void *data, S32 size, EMsgVariableType type, S32 data_size = -1);
-
-public:
-	S32									mOffset;
-	typedef std::map<char*, LLMsgBlkData*> msg_blk_data_map_t;
-	msg_blk_data_map_t					mMemberBlocks;
-	char								*mName;
-	S32									mTotalSize;
-};
-
-inline void LLMsgVarData::addData(const void *data, S32 size, EMsgVariableType type, S32 data_size)
-{
-	mSize = size;
-	mDataSize = data_size;
-	if ( (type != MVT_VARIABLE) && (type != MVT_FIXED) 
-		 && (mType != MVT_VARIABLE) && (mType != MVT_FIXED))
-	{
-		if (mType != type)
-		{
-			llwarns << "Type mismatch in addData for " << mName
-					<< " message: " << gMessageSystem->getCurrentSMessageName()
-					<< " block: " << gMessageSystem->getCurrentSBlockName()
-					<< llendl;
-		}
-	}
-	if(size)
-	{
-		delete mData; // Delete it if it already exists
-		mData = new U8[size];
-		htonmemcpy(mData, data, mType, size);
-	}
-}
-
-
-
-inline void LLMsgData::addDataFast(char *blockname, char *varname, const void *data, S32 size, EMsgVariableType type, S32 data_size)
-{
-	// remember that if the blocknumber is > 0 then the number is appended to the name
-	char *namep = (char *)blockname;
-	LLMsgBlkData* block_data = mMemberBlocks[namep];
-	if (block_data->mBlockNumber)
-	{
-		namep += block_data->mBlockNumber;
-		block_data->addData(varname, data, size, type, data_size);
-	}
-	else
-	{
-		block_data->addData(varname, data, size, type, data_size);
-	}
-}
-
-// LLMessage* classes store the template of messages
-
-
-class LLMessageVariable
-{
-public:
-	LLMessageVariable() : mName(NULL), mType(MVT_NULL), mSize(-1)
-	{
-	}
-
-	LLMessageVariable(char *name) : mType(MVT_NULL), mSize(-1)
-	{
-		mName = name;
-	}
-
-	LLMessageVariable(char *name, const EMsgVariableType type, const S32 size) : mType(type), mSize(size) 
-	{
-		mName = gMessageStringTable.getString(name); 
-	}
-	
-	~LLMessageVariable() {}
-
-	friend std::ostream&	 operator<<(std::ostream& s, LLMessageVariable &msg);
-
-	EMsgVariableType getType() const				{ return mType; }
-	S32	getSize() const								{ return mSize; }
-	char *getName() const							{ return mName; }
-protected:
-	char				*mName;
-	EMsgVariableType	mType;
-	S32					mSize;
-};
-
-
-typedef enum e_message_block_type
-{
-	MBT_NULL,
-	MBT_SINGLE,
-	MBT_MULTIPLE,
-	MBT_VARIABLE,
-	MBT_EOF
-} EMsgBlockType;
-
-class LLMessageBlock
-{
-public:
-	LLMessageBlock(char *name, EMsgBlockType type, S32 number = 1) : mType(type), mNumber(number), mTotalSize(0) 
-	{ 
-		mName = gMessageStringTable.getString(name);
-	}
-
-	~LLMessageBlock()
-	{
-		for_each(mMemberVariables.begin(), mMemberVariables.end(), DeletePairedPointer());
-	}
-
-	void addVariable(char *name, const EMsgVariableType type, const S32 size)
-	{
-		LLMessageVariable** varp = &mMemberVariables[name];
-		if (*varp != NULL)
-		{
-			llerrs << name << " has already been used as a variable name!" << llendl;
-		}
-		*varp = new LLMessageVariable(name, type, size);
-		if (((*varp)->getType() != MVT_VARIABLE)
-			&&(mTotalSize != -1))
-		{
-			mTotalSize += (*varp)->getSize();
-		}
-		else
-		{
-			mTotalSize = -1;
-		}
-	}
-
-	EMsgVariableType getVariableType(char *name)
-	{
-		return (mMemberVariables[name])->getType();
-	}
-
-	S32 getVariableSize(char *name)
-	{
-		return (mMemberVariables[name])->getSize();
-	}
-
-	friend std::ostream&	 operator<<(std::ostream& s, LLMessageBlock &msg);
-
-	typedef std::map<const char *, LLMessageVariable*> message_variable_map_t;
-	message_variable_map_t 					mMemberVariables;
-	char									*mName;
-	EMsgBlockType							mType;
-	S32										mNumber;
-	S32										mTotalSize;
-};
-
-
-enum EMsgFrequency
-{
-	MFT_NULL	= 0,  // value is size of message number in bytes
-	MFT_HIGH	= 1,
-	MFT_MEDIUM	= 2,
-	MFT_LOW		= 4
-};
-
-typedef enum e_message_trust
-{
-	MT_TRUST,
-	MT_NOTRUST
-} EMsgTrust;
-
-enum EMsgEncoding
-{
-	ME_UNENCODED,
-	ME_ZEROCODED
-};
-
-class LLMessageTemplate
-{
-public:
-	LLMessageTemplate(const char *name, U32 message_number, EMsgFrequency freq)
-		: 
-		//mMemberBlocks(),
-		mName(NULL),
-		mFrequency(freq),
-		mTrust(MT_NOTRUST),
-		mEncoding(ME_ZEROCODED),
-		mMessageNumber(message_number), 
-		mTotalSize(0), 
-		mReceiveCount(0),
-		mReceiveBytes(0),
-		mReceiveInvalid(0),
-		mDecodeTimeThisFrame(0.f),
-		mTotalDecoded(0),
-		mTotalDecodeTime(0.f),
-		mMaxDecodeTimePerMsg(0.f),
-		mBanFromTrusted(false),
-		mBanFromUntrusted(false),
-		mHandlerFunc(NULL), 
-		mUserData(NULL)
-	{ 
-		mName = gMessageStringTable.getString(name);
-	}
-
-	~LLMessageTemplate()
-	{
-		for_each(mMemberBlocks.begin(), mMemberBlocks.end(), DeletePairedPointer());
-	}
-
-	void addBlock(LLMessageBlock *blockp)
-	{
-		LLMessageBlock** member_blockp = &mMemberBlocks[blockp->mName];
-		if (*member_blockp != NULL)
-		{
-			llerrs << "Block " << blockp->mName
-				<< "has already been used as a block name!" << llendl;
-		}
-		*member_blockp = blockp;
-		if (  (mTotalSize != -1)
-			&&(blockp->mTotalSize != -1)
-			&&(  (blockp->mType == MBT_SINGLE)
-			   ||(blockp->mType == MBT_MULTIPLE)))
-		{
-			mTotalSize += blockp->mNumber*blockp->mTotalSize;
-		}
-		else
-		{
-			mTotalSize = -1;
-		}
-	}
-
-	LLMessageBlock *getBlock(char *name)
-	{
-		return mMemberBlocks[name];
-	}
-
-	// Trusted messages can only be recieved on trusted circuits.
-	void setTrust(EMsgTrust t)
-	{
-		mTrust = t;
-	}
-
-	EMsgTrust getTrust(void)
-	{
-		return mTrust;
-	}
-
-	// controls for how the message should be encoded
-	void setEncoding(EMsgEncoding e)
-	{
-		mEncoding = e;
-	}
-	EMsgEncoding getEncoding()
-	{
-		return mEncoding;
-	}
-
-	void setHandlerFunc(void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data)
-	{
-		mHandlerFunc = handler_func;
-		mUserData = user_data;
-	}
-
-	BOOL callHandlerFunc(LLMessageSystem *msgsystem)
-	{
-		if (mHandlerFunc)
-		{
-			mHandlerFunc(msgsystem, mUserData);
-			return TRUE;
-		}
-		return FALSE;
-	}
-
-	bool isBanned(bool trustedSource)
-	{
-		return trustedSource ? mBanFromTrusted : mBanFromUntrusted;
-	}
-
-	friend std::ostream&	 operator<<(std::ostream& s, LLMessageTemplate &msg);
-
-public:
-	typedef std::map<char*, LLMessageBlock*> message_block_map_t;
-	message_block_map_t						mMemberBlocks;
-	char									*mName;
-	EMsgFrequency							mFrequency;
-	EMsgTrust								mTrust;
-	EMsgEncoding							mEncoding;
-	U32										mMessageNumber;
-	S32										mTotalSize;
-	U32										mReceiveCount;		// how many of this template have been received since last reset
-	U32										mReceiveBytes;		// How many bytes received
-	U32										mReceiveInvalid;	// How many "invalid" packets
-	F32										mDecodeTimeThisFrame;	// Total seconds spent decoding this frame
-	U32										mTotalDecoded;		// Total messages successfully decoded
-	F32										mTotalDecodeTime;	// Total time successfully decoding messages
-	F32										mMaxDecodeTimePerMsg;
-
-	bool									mBanFromTrusted;
-	bool									mBanFromUntrusted;
-
-private:
-	// message handler function (this is set by each application)
-	void									(*mHandlerFunc)(LLMessageSystem *msgsystem, void **user_data);
-	void									**mUserData;
-};
-
-
-// static
-BOOL LLMessageSystem::mTimeDecodes = FALSE;
-
-// static, 50ms per message decode
-F32  LLMessageSystem::mTimeDecodesSpamThreshold = 0.05f;
-
 // *NOTE: This needs to be moved into a seperate file so that it never gets
 // included in the viewer.  30 Sep 2002 mark
 // *NOTE: I don't think it's important that the messgage system tracks
@@ -468,113 +80,6 @@ public:
 	apr_pollfd_t mPollFD;
 };
 
-
-// LLMessageVariable functions and friends
-
-std::ostream& operator<<(std::ostream& s, LLMessageVariable &msg)
-{
-	s << "\t\t" << msg.mName << " (";
-	switch (msg.mType)
-	{
-	case MVT_FIXED:
-		s << "Fixed, " << msg.mSize << " bytes total)\n";
-		break;
-	case MVT_VARIABLE:
-		s << "Variable, " << msg.mSize << " bytes of size info)\n";
-		break;
-	default:
-		s << "Unknown\n";
-		break;
-	}
-	return s;
-}
-
-// LLMessageBlock functions and friends
-
-std::ostream& operator<<(std::ostream& s, LLMessageBlock &msg)
-{
-	s << "\t" << msg.mName << " (";
-	switch (msg.mType)
-	{
-	case MBT_SINGLE:
-		s << "Fixed";
-		break;
-	case MBT_MULTIPLE:
-		s << "Multiple - " << msg.mNumber << " copies";
-		break;
-	case MBT_VARIABLE:
-		s << "Variable";
-		break;
-	default:
-		s << "Unknown";
-		break;
-	}
-	if (msg.mTotalSize != -1)
-	{
-		s << ", " << msg.mTotalSize << " bytes each, " << msg.mNumber*msg.mTotalSize << " bytes total)\n";
-	}
-	else
-	{
-		s << ")\n";
-	}
-
-
-	for (LLMessageBlock::message_variable_map_t::iterator iter = msg.mMemberVariables.begin();
-		 iter != msg.mMemberVariables.end(); iter++)
-	{
-		LLMessageVariable& ci = *(iter->second);
-		s << ci;
-	}
-
-	return s;
-}
-
-// LLMessageTemplate functions and friends
-
-std::ostream& operator<<(std::ostream& s, LLMessageTemplate &msg)
-{
-	switch (msg.mFrequency)
-	{
-	case MFT_HIGH:
-		s << "========================================\n" << "Message #" << msg.mMessageNumber << "\n" << msg.mName << " (";
-		s << "High";
-		break;
-	case MFT_MEDIUM:
-		s << "========================================\n" << "Message #";
-		s << (msg.mMessageNumber & 0xFF) << "\n" << msg.mName << " (";
-		s << "Medium";
-		break;
-	case MFT_LOW:
-		s << "========================================\n" << "Message #";
-		s << (msg.mMessageNumber & 0xFFFF) << "\n" << msg.mName << " (";
-		s << "Low";
-		break;
-	default:
-		s << "Unknown";
-		break;
-	}
-
-	if (msg.mTotalSize != -1)
-	{
-		s << ", " << msg.mTotalSize << " bytes total)\n";
-	}
-	else
-	{
-		s << ")\n";
-	}
-	
-	for (LLMessageTemplate::message_block_map_t::iterator iter = msg.mMemberBlocks.begin();
-		 iter != msg.mMemberBlocks.end(); iter++)
-	{
-		LLMessageBlock* ci = iter->second;
-		s << *ci;
-	}
-
-	return s;
-}
-
-// LLMessageList functions and friends
-
 // Lets support a small subset of regular expressions here
 // Syntax is a string made up of:
 //	a	- checks against alphanumeric				([A-Za-z0-9])
@@ -776,106 +281,162 @@ BOOL	b_positive_integer_ok(char *token)
 	return TRUE;
 }
 
-void LLMessageSystem::init()
+namespace
 {
-	// initialize member variables
-	mVerboseLog = FALSE;
+	class LLFnPtrResponder : public LLHTTPClient::Responder
+	{
+	public:
+		LLFnPtrResponder(void (*callback)(void **,S32), void **callbackData) :
+			mCallback(callback),
+			mCallbackData(callbackData)
+		{
+		}
 
-	mbError = FALSE;
-	mErrorCode = 0;
-	mIncomingCompressedSize = 0;
-	mSendReliable = FALSE;
+		virtual void error(U32 status, const std::string& reason)
+		{
+			// TODO: Map status in to useful error code.
+			if(NULL != mCallback) mCallback(mCallbackData, LL_ERR_TCP_TIMEOUT);
+		}
+		
+		virtual void result(const LLSD& content)
+		{
+			if(NULL != mCallback) mCallback(mCallbackData, LL_ERR_NOERR);
+		}
 
-	mbSBuilt = FALSE;
-	mbSClear = TRUE;
+	private:
 
-	mUnackedListDepth = 0;
-	mUnackedListSize = 0;
-	mDSMaxListDepth = 0;
+		void (*mCallback)(void **,S32);    
+		void **mCallbackData;
+	};
+}
 
-	mCurrentRMessageData = NULL;
-	mCurrentRMessageTemplate = NULL;
 
-	mCurrentSMessageData = NULL;
-	mCurrentSMessageTemplate = NULL;
-	mCurrentSMessageName = NULL;
+class LLTrustedMessageService : public LLHTTPNode
+{
+	virtual bool validate(const std::string& name, LLSD& context) const
+		{ return true; }
 
-	mCurrentRecvPacketID = 0;
+	virtual void post(LLHTTPNode::ResponsePtr response,
+					  const LLSD& context,
+					  const LLSD& input) const;
+};
 
-	mNumberHighFreqMessages = 0;
-	mNumberMediumFreqMessages = 0;
-	mNumberLowFreqMessages = 0;
-	mPacketsIn = mPacketsOut = 0;
-	mBytesIn = mBytesOut = 0;
-	mCompressedPacketsIn = mCompressedPacketsOut = 0;
-	mReliablePacketsIn = mReliablePacketsOut = 0;
+//virtual
+void LLTrustedMessageService::post(LLHTTPNode::ResponsePtr response,
+								   const LLSD& context,
+								   const LLSD& input) const
+{
+	std::string name = context["request"]["wildcard"]["message-name"];
+	std::string senderIP = context["request"]["remote-host"];
+	std::string senderPort = context["request"]["headers"]
+		["x-secondlife-udp-listen-port"];
 
-	mCompressedBytesIn = 0;
-	mCompressedBytesOut = 0;
-	mUncompressedBytesIn = 0;
-	mUncompressedBytesOut = 0;
-	mTotalBytesIn = 0;
-	mTotalBytesOut = 0;
+	LLSD message_data;
+	message_data["sender"] = senderIP + ":" + senderPort;
+	message_data["body"] = input;
+	
+	LLMessageSystem::dispatch(name, message_data, response);
+}
 
-    mDroppedPackets = 0;            // total dropped packets in
-    mResentPackets = 0;             // total resent packets out
-    mFailedResendPackets = 0;       // total resend failure packets out
-    mOffCircuitPackets = 0;         // total # of off-circuit packets rejected
-    mInvalidOnCircuitPackets = 0;   // total # of on-circuit packets rejected
+class LLMessageHandlerBridge : public LLHTTPNode
+{
+	virtual bool validate(const std::string& name, LLSD& context) const
+		{ return true; }
 
-	mOurCircuitCode = 0;
+	virtual void post(LLHTTPNode::ResponsePtr response, const LLSD& context, 
+					  const LLSD& input) const;
+};
 
-	mMessageFileChecksum = 0;
-	mMessageFileVersionNumber = 0.f;
+//virtual 
+void LLMessageHandlerBridge::post(LLHTTPNode::ResponsePtr response, 
+							const LLSD& context, const LLSD& input) const
+{
+	std::string name = context["request"]["wildcard"]["message-name"];
 
-	mTimingCallback = NULL;
-	mTimingCallbackData = NULL;
+	lldebugs << "Setting mLastSender " << input["sender"].asString() << llendl;
+	gMessageSystem->mLastSender = LLHost(input["sender"].asString());
+	gMessageSystem->mPacketsIn += 1;
+	gMessageSystem->mLLSDMessageReader->setMessage(name, input["body"]);
+	gMessageSystem->mMessageReader = gMessageSystem->mLLSDMessageReader;
+	
+	if(gMessageSystem->callHandler(name.c_str(), false, gMessageSystem))
+	{
+		response->result(LLSD());
+	}
+	else
+	{
+		response->notFound();
+	}
 }
 
-LLMessageSystem::LLMessageSystem()
+LLHTTPRegistration<LLMessageHandlerBridge>
+	gHTTPRegistrationMessageWildcard("/message/<message-name>");
+
+LLHTTPRegistration<LLTrustedMessageService>
+	gHTTPRegistrationTrustedMessageWildcard("/trusted-message/<message-name>");
+
+//virtual
+LLUseCircuitCodeResponder::~LLUseCircuitCodeResponder()
 {
-	init();
+	// even abstract base classes need a concrete destructor
+}
 
-	mSystemVersionMajor = 0;
-	mSystemVersionMinor = 0;
-	mSystemVersionPatch = 0;
-	mSystemVersionServer = 0;
-	mVersionFlags = 0x0;
+void LLMessageSystem::init()
+{
+	// initialize member variables
+	mVerboseLog = FALSE;
 
-	// default to not accepting packets from not alive circuits
-	mbProtected = TRUE;
+	mbError = FALSE;
+	mErrorCode = 0;
+	mSendReliable = FALSE;
 
-	mSendPacketFailureCount = 0;
-	mCircuitPrintFreq = 0.f;		// seconds
+	mUnackedListDepth = 0;
+	mUnackedListSize = 0;
+	mDSMaxListDepth = 0;
 
-	// initialize various bits of net info
-	mSocket = 0;
-	mPort = 0;
+	mNumberHighFreqMessages = 0;
+	mNumberMediumFreqMessages = 0;
+	mNumberLowFreqMessages = 0;
+	mPacketsIn = mPacketsOut = 0;
+	mBytesIn = mBytesOut = 0;
+	mCompressedPacketsIn = mCompressedPacketsOut = 0;
+	mReliablePacketsIn = mReliablePacketsOut = 0;
 
-	mPollInfop = NULL;
+	mCompressedBytesIn = 0;
+	mCompressedBytesOut = 0;
+	mUncompressedBytesIn = 0;
+	mUncompressedBytesOut = 0;
+	mTotalBytesIn = 0;
+	mTotalBytesOut = 0;
 
-	mResendDumpTime = 0;
-	mMessageCountTime = 0;
-	mCircuitPrintTime = 0;
-	mCurrentMessageTimeSeconds = 0;
+    mDroppedPackets = 0;            // total dropped packets in
+    mResentPackets = 0;             // total resent packets out
+    mFailedResendPackets = 0;       // total resend failure packets out
+    mOffCircuitPackets = 0;         // total # of off-circuit packets rejected
+    mInvalidOnCircuitPackets = 0;   // total # of on-circuit packets rejected
 
-	// Constants for dumping output based on message processing time/count
-	mNumMessageCounts = 0;
-	mMaxMessageCounts = 0; // >= 0 means dump warnings
-	mMaxMessageTime   = 0.f;
+	mOurCircuitCode = 0;
 
-	mTrueReceiveSize = 0;
+	mIncomingCompressedSize = 0;
+	mCurrentRecvPacketID = 0;
 
-	// Error if checking this state, subclass methods which aren't implemented are delegated
-	// to properly constructed message system.
-	mbError = TRUE;
+	mMessageFileChecksum = 0;
+	mMessageFileVersionNumber = 0.f;
+
+	mTimingCallback = NULL;
+	mTimingCallbackData = NULL;
+
+	mMessageBuilder = NULL;
+	mMessageReader = NULL;
 }
 
 // Read file and build message templates
 LLMessageSystem::LLMessageSystem(const char *filename, U32 port, 
 								 S32 version_major,
 								 S32 version_minor,
-								 S32 version_patch)
+								 S32 version_patch) :
+	mTemplateConfirmed(FALSE),
+	mTemplateMatches(FALSE)
 {
 	init();
 
@@ -894,6 +455,14 @@ LLMessageSystem::LLMessageSystem(const char *filename, U32 port,
 
 	loadTemplateFile(filename);
 
+	mTemplateMessageBuilder = new LLTemplateMessageBuilder(mMessageTemplates);
+	mLLSDMessageBuilder = new LLSDMessageBuilder();
+	mMessageBuilder = NULL;
+
+	mTemplateMessageReader = new LLTemplateMessageReader(mMessageNumbers);
+	mLLSDMessageReader = new LLSDMessageReader();
+	mMessageReader = NULL;
+
 	// initialize various bits of net info
 	mSocket = 0;
 	mPort = port;
@@ -1712,25 +1281,25 @@ LLMessageSystem::~LLMessageSystem()
 		end_net();
 	}
 	
-	delete mCurrentRMessageData;
-	mCurrentRMessageData = NULL;
+	delete mMessageReader;
+	mMessageReader = NULL;
 
-	delete mCurrentSMessageData;
-	mCurrentSMessageData = NULL;
+	delete mMessageBuilder;
+	mMessageBuilder = NULL;
 
 	delete mPollInfop;
 	mPollInfop = NULL;
+
+	mIncomingCompressedSize = 0;
+	mCurrentRecvPacketID = 0;
 }
 
 void LLMessageSystem::clearReceiveState()
 {
-	mReceiveSize = -1;
 	mCurrentRecvPacketID = 0;
-	mCurrentRMessageTemplate = NULL;
-	delete mCurrentRMessageData;
-	mCurrentRMessageData = NULL;
 	mIncomingCompressedSize = 0;
 	mLastSender.invalidate();
+	mMessageReader->clearMessage();
 }
 
 
@@ -1757,20 +1326,23 @@ BOOL LLMessageSystem::poll(F32 seconds)
 // Returns TRUE if a valid, on-circuit message has been received.
 BOOL LLMessageSystem::checkMessages( S64 frame_count )
 {
+	// Pump 
 	BOOL	valid_packet = FALSE;
+	mMessageReader = mTemplateMessageReader;
 
 	LLTransferTargetVFile::updateQueue();
 	
 	if (!mNumMessageCounts)
 	{
-		// This is the first message being handled after a resetReceiveCounts, we must be starting
-		// the message processing loop.  Reset the timers.
+		// This is the first message being handled after a resetReceiveCounts,
+		// we must be starting the message processing loop.  Reset the timers.
 		mCurrentMessageTimeSeconds = totalTime() * SEC_PER_USEC;
 		mMessageCountTime = getMessageTimeSeconds();
 	}
 
 	// loop until either no packets or a valid packet
 	// i.e., burn through packets from unregistered circuits
+	S32 receive_size = 0;
 	do
 	{
 		clearReceiveState();
@@ -1786,16 +1358,16 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
 		// If you want to dump all received packets into SecondLife.log, uncomment this
 		//dumpPacketToLog();
 		
-		mReceiveSize = mTrueReceiveSize;
+		receive_size = mTrueReceiveSize;
 		mLastSender = mPacketRing.getLastSender();
 		
-		if (mReceiveSize < (S32) LL_MINIMUM_VALID_PACKET_SIZE)
+		if (receive_size < (S32) LL_MINIMUM_VALID_PACKET_SIZE)
 		{
 			// A receive size of zero is OK, that means that there are no more packets available.
 			// Ones that are non-zero but below the minimum packet size are worrisome.
-			if (mReceiveSize > 0)
+			if (receive_size > 0)
 			{
-				llwarns << "Invalid (too short) packet discarded " << mReceiveSize << llendl;
+				llwarns << "Invalid (too short) packet discarded " << receive_size << llendl;
 				callExceptionFunc(MX_PACKET_TOO_SHORT);
 			}
 			// no data in packet receive buffer
@@ -1809,18 +1381,18 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
 			// note if packet acks are appended.
 			if(buffer[0] & LL_ACK_FLAG)
 			{
-				acks += buffer[--mReceiveSize];
-				true_rcv_size = mReceiveSize;
-				if(mReceiveSize >= ((S32)(acks * sizeof(TPACKETID) + LL_MINIMUM_VALID_PACKET_SIZE)))
+				acks += buffer[--receive_size];
+				true_rcv_size = receive_size;
+				if(receive_size >= ((S32)(acks * sizeof(TPACKETID) + LL_MINIMUM_VALID_PACKET_SIZE)))
 				{
-					mReceiveSize -= acks * sizeof(TPACKETID);
+					receive_size -= acks * sizeof(TPACKETID);
 				}
 				else
 				{
 					// mal-formed packet. ignore it and continue with
 					// the next one
 					llwarns << "Malformed packet received. Packet size "
-						<< mReceiveSize << " with invalid no. of acks " << acks
+						<< receive_size << " with invalid no. of acks " << acks
 						<< llendl;
 					valid_packet = FALSE;
 					continue;
@@ -1829,7 +1401,7 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
 
 			// process the message as normal
 
-			mIncomingCompressedSize = zeroCodeExpand(&buffer,&mReceiveSize);
+			mIncomingCompressedSize = zeroCodeExpand(&buffer,&receive_size);
 			mCurrentRecvPacketID = buffer[1] + ((buffer[0] & 0x0f ) * 256);
 			if (sizeof(TPACKETID) == 4)
 			{
@@ -1953,7 +1525,7 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
 						std::ostringstream str;
 						str << "MSG: <- " << host;
 						char buffer[MAX_STRING]; /* Flawfinder: ignore*/
-						snprintf(buffer, MAX_STRING, "\t%6d\t%6d\t%6d ", mReceiveSize, (mIncomingCompressedSize ? mIncomingCompressedSize : mReceiveSize), mCurrentRecvPacketID);	/* Flawfinder: ignore */
+						snprintf(buffer, MAX_STRING, "\t%6d\t%6d\t%6d ", receive_size, (mIncomingCompressedSize ? mIncomingCompressedSize : receive_size), mCurrentRecvPacketID);	/* Flawfinder: ignore */
 						str << buffer << "(unknown)"
 							<< (recv_reliable ? " reliable" : "")
 							<< " resent "
@@ -1971,23 +1543,22 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
 			// But we don't want to acknowledge UseCircuitCode until the circuit is
 			// available, which is why the acknowledgement test is done above.  JC
 
-			valid_packet = decodeTemplate( buffer, mReceiveSize, &mCurrentRMessageTemplate );
-			if( valid_packet )
-			{
-				mCurrentRMessageTemplate->mReceiveCount++;
-				lldebugst(LLERR_MESSAGE) << "MessageRecvd:" << mCurrentRMessageTemplate->mName << " from " << host << llendl;
-			}
+			valid_packet = mTemplateMessageReader->validateMessage(buffer, 
+														   receive_size,
+														   host);
 
 			// UseCircuitCode is allowed in even from an invalid circuit, so that
 			// we can toss circuits around.
-			if (valid_packet && !cdp && (mCurrentRMessageTemplate->mName != _PREHASH_UseCircuitCode) )
+			if(valid_packet && !cdp && 
+			   (mTemplateMessageReader->getMessageName() != _PREHASH_UseCircuitCode))
 			{
 				logMsgFromInvalidCircuit( host, recv_reliable );
 				clearReceiveState();
 				valid_packet = FALSE;
 			}
 
-			if (valid_packet && cdp && !cdp->getTrusted() && (mCurrentRMessageTemplate->getTrust() == MT_TRUST) )
+			if(valid_packet && cdp && !cdp->getTrusted() && 
+				mTemplateMessageReader->isTrusted())
 			{
 				logTrustedMsgFromUntrustedCircuit( host );
 				clearReceiveState();
@@ -1997,11 +1568,11 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
 			}
 
 			if (valid_packet
-			&& mCurrentRMessageTemplate->isBanned(cdp && cdp->getTrusted()))
+			&& mTemplateMessageReader->isBanned(cdp && cdp->getTrusted()))
 			{
 				llwarns << "LLMessageSystem::checkMessages "
 					<< "received banned message "
-					<< mCurrentRMessageTemplate->mName
+					<< mTemplateMessageReader->getMessageName()
 					<< " from "
 					<< ((cdp && cdp->getTrusted()) ? "trusted " : "untrusted ")
 					<< host << llendl;
@@ -2013,7 +1584,7 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
 			{
 				logValidMsg(cdp, host, recv_reliable, recv_resent, (BOOL)(acks>0) );
 
-				valid_packet = decodeData( buffer, host );
+				valid_packet = mTemplateMessageReader->readMessage(buffer, host);
 			}
 
 			// It's possible that the circuit went away, because ANY message can disable the circuit
@@ -2026,7 +1597,7 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
 				if( 1 )
 				{
 					static char* object_update = gMessageStringTable.getString("ObjectUpdate");
-					if(object_update == mCurrentRMessageTemplate->mName )
+					if(object_update == mTemplateMessageReader->getMessageName() )
 					{
 						llinfos << "ObjectUpdate:" << llendl;
 						U32 i;
@@ -2037,8 +1608,8 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
 						}
 						llinfos << "" << llendl;
 
-						llinfos << "    Zero Unencoded: " << mReceiveSize << llendl;
-						for( i = 0; i<mReceiveSize; i++ )
+						llinfos << "    Zero Unencoded: " << receive_size << llendl;
+						for( i = 0; i<receive_size; i++ )
 						{
 							llinfos << "     " << i << ": " << (U32) buffer[i] << llendl;
 						}
@@ -2127,7 +1698,7 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
 				if (mbProtected  && (!cdp))
 				{
 					llwarns << "Packet "
-							<< (mCurrentRMessageTemplate ? mCurrentRMessageTemplate->mName : "")
+							<< mTemplateMessageReader->getMessageName()
 							<< " from invalid circuit " << host << llendl;
 					mOffCircuitPackets++;
 				}
@@ -2140,7 +1711,7 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
 			// Code for dumping the complete contents of a message 
 			// delete [] zero_unexpanded_buffer;
 		}
-	} while (!valid_packet && mReceiveSize > 0);
+	} while (!valid_packet && receive_size > 0);
 
 	F64 mt_sec = getMessageTimeSeconds();
 	// Check to see if we need to print debug info
@@ -2241,724 +1812,184 @@ void LLMessageSystem::processAcks()
 	}
 }
 
-
-void LLMessageSystem::newMessageFast(const char *name)
+void LLMessageSystem::copyMessageRtoS()
 {
-	mbSBuilt = FALSE;
-	mbSClear = FALSE;
-
-	mCurrentSendTotal = 0;
-	mSendReliable = FALSE;
-
-	char *namep = (char *)name; 
-
-	if (mMessageTemplates.count(namep) > 0)
+	// NOTE: babbage: switch builder to match reader to avoid
+	// converting message format
+	if(mMessageReader == mTemplateMessageReader)
 	{
-		mCurrentSMessageTemplate = mMessageTemplates[namep];
-		if (mCurrentSMessageData)
-		{
-			delete mCurrentSMessageData;
-		}
-		mCurrentSMessageData = new LLMsgData(namep);
-		mCurrentSMessageName = namep;
-		mCurrentSDataBlock = NULL;
-		mCurrentSBlockName = NULL;
-
-		// add at one of each block
-		LLMessageTemplate* msg_template = mMessageTemplates[namep];
-		for (LLMessageTemplate::message_block_map_t::iterator iter = msg_template->mMemberBlocks.begin();
-			 iter != msg_template->mMemberBlocks.end(); iter++)
-		{
-			LLMessageBlock* ci = iter->second;
-			LLMsgBlkData	*tblockp;
-			tblockp = new LLMsgBlkData(ci->mName, 0);
-			mCurrentSMessageData->addBlock(tblockp);
-		}
+		mMessageBuilder = mTemplateMessageBuilder;
 	}
 	else
 	{
-		llerrs << "newMessage - Message " << name << " not registered" << llendl;
+		mMessageBuilder = mLLSDMessageBuilder;
 	}
+	mSendReliable = FALSE;
+	mMessageBuilder->newMessage(mMessageReader->getMessageName());
+	mMessageReader->copyToBuilder(*mMessageBuilder);
 }
 
-void LLMessageSystem::copyMessageRtoS()
+void LLMessageSystem::clearMessage()
 {
-	if (!mCurrentRMessageTemplate)
-	{
-		return;
-	}
-	newMessageFast(mCurrentRMessageTemplate->mName);
+	mSendReliable = FALSE;
+	mMessageBuilder->clearMessage();
+}
 
-	// copy the blocks
-	// counting variables used to encode multiple block info
-	S32 block_count = 0;
-    char *block_name = NULL;
+// set block to add data to within current message
+void LLMessageSystem::nextBlockFast(const char *blockname)
+{
+	mMessageBuilder->nextBlock(blockname);
+}
 
-	// loop through msg blocks to loop through variables, totalling up size data and filling the new (send) message
-	LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.begin();
-	LLMsgData::msg_blk_data_map_t::iterator end = mCurrentRMessageData->mMemberBlocks.end();
-	for(; iter != end; ++iter)
+BOOL LLMessageSystem::isSendFull(const char* blockname)
+{
+	char* stringTableName = NULL;
+	if(NULL != blockname)
 	{
-		LLMsgBlkData* mbci = iter->second;
-		if(!mbci) continue;
-
-		// do we need to encode a block code?
-		if (block_count == 0)
-		{
-			block_count = mbci->mBlockNumber;
-			block_name = (char *)mbci->mName;
-		}
-
-		// counting down mutliple blocks
-		block_count--;
-
-		nextBlockFast(block_name);
-
-		// now loop through the variables
-		LLMsgBlkData::msg_var_data_map_t::iterator dit = mbci->mMemberVarData.begin();
-		LLMsgBlkData::msg_var_data_map_t::iterator dend = mbci->mMemberVarData.end();
-		
-		for(; dit != dend; ++dit)
-		{
-			LLMsgVarData& mvci = *dit;
-			addDataFast(mvci.getName(), mvci.getData(), mvci.getType(), mvci.getSize());
-		}
+		stringTableName = gMessageStringTable.getString(blockname);
 	}
+	return isSendFullFast(stringTableName);
 }
 
-void LLMessageSystem::clearMessage()
+BOOL LLMessageSystem::isSendFullFast(const char* blockname)
 {
-	mbSBuilt = FALSE;
-	mbSClear = TRUE;
-
-	mCurrentSendTotal = 0;
-	mSendReliable = FALSE;
+	return mMessageBuilder->isMessageFull(blockname);
+}
 
-	mCurrentSMessageTemplate = NULL;
 
-	delete mCurrentSMessageData;
-	mCurrentSMessageData = NULL;
+// blow away the last block of a message, return FALSE if that leaves no blocks or there wasn't a block to remove
+// TODO: Babbage: Remove this horror.
+BOOL LLMessageSystem::removeLastBlock()
+{
+	return mMessageBuilder->removeLastBlock();
+}
 
-	mCurrentSMessageName = NULL;
-	mCurrentSDataBlock = NULL;
-	mCurrentSBlockName = NULL;
+S32 LLMessageSystem::sendReliable(const LLHost &host)
+{
+	return sendReliable(host, LL_DEFAULT_RELIABLE_RETRIES, TRUE, LL_PING_BASED_TIMEOUT_DUMMY, NULL, NULL);
 }
 
 
-// set block to add data to within current message
-void LLMessageSystem::nextBlockFast(const char *blockname)
+S32 LLMessageSystem::sendSemiReliable(const LLHost &host, void (*callback)(void **,S32), void ** callback_data)
 {
-	char *bnamep = (char *)blockname; 
-
-	if (!mCurrentSMessageTemplate)
-	{
-		llerrs << "newMessage not called prior to setBlock" << llendl;
-		return;
-	}
+	F32 timeout;
 
-	// now, does this block exist?
-	LLMessageTemplate::message_block_map_t::iterator temp_iter = mCurrentSMessageTemplate->mMemberBlocks.find(bnamep);
-	if (temp_iter == mCurrentSMessageTemplate->mMemberBlocks.end())
+	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+	if (cdp)
 	{
-		llerrs << "LLMessageSystem::nextBlockFast " << bnamep
-			<< " not a block in " << mCurrentSMessageTemplate->mName << llendl;
-		return;
-	}
-	
-	LLMessageBlock* template_data = temp_iter->second;
-	
-	// ok, have we already set this block?
-	LLMsgBlkData* block_data = mCurrentSMessageData->mMemberBlocks[bnamep];
-	if (block_data->mBlockNumber == 0)
-	{
-		// nope! set this as the current block
-		block_data->mBlockNumber = 1;
-		mCurrentSDataBlock = block_data;
-		mCurrentSBlockName = bnamep;
-
-		// add placeholders for each of the variables
-		for (LLMessageBlock::message_variable_map_t::iterator iter = template_data->mMemberVariables.begin();
-			 iter != template_data->mMemberVariables.end(); iter++)
-		{
-			LLMessageVariable& ci = *(iter->second);
-			mCurrentSDataBlock->addVariable(ci.getName(), ci.getType());
-		}
-		return;
+		timeout = llmax(LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS,
+						LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged());
 	}
 	else
 	{
-		// already have this block. . . 
-		// are we supposed to have a new one?
-
-		// if the block is type MBT_SINGLE this is bad!
-		if (template_data->mType == MBT_SINGLE)
-		{
-			llerrs << "LLMessageSystem::nextBlockFast called multiple times"
-				<< " for " << bnamep << " but is type MBT_SINGLE" << llendl;
-			return;
-		}
-
-
-		// if the block is type MBT_MULTIPLE then we need a known number, make sure that we're not exceeding it
-		if (  (template_data->mType == MBT_MULTIPLE)
-			&&(mCurrentSDataBlock->mBlockNumber == template_data->mNumber))
-		{
-			llerrs << "LLMessageSystem::nextBlockFast called "
-				<< mCurrentSDataBlock->mBlockNumber << " times for " << bnamep
-				<< " exceeding " << template_data->mNumber
-				<< " specified in type MBT_MULTIPLE." << llendl;
-			return;
-		}
-
-		// ok, we can make a new one
-		// modify the name to avoid name collision by adding number to end
-		S32  count = block_data->mBlockNumber;
-
-		// incrememt base name's count
-		block_data->mBlockNumber++;
-
-		if (block_data->mBlockNumber > MAX_BLOCKS)
-		{
-			llerrs << "Trying to pack too many blocks into MBT_VARIABLE type (limited to " << MAX_BLOCKS << ")" << llendl;
-		}
-
-		// create new name
-		// Nota Bene: if things are working correctly, mCurrentMessageData->mMemberBlocks[blockname]->mBlockNumber == mCurrentDataBlock->mBlockNumber + 1
-
-		char *nbnamep = bnamep + count;
-	
-		mCurrentSDataBlock = new LLMsgBlkData(bnamep, count);
-		mCurrentSDataBlock->mName = nbnamep;
-		mCurrentSMessageData->mMemberBlocks[nbnamep] = mCurrentSDataBlock;
-
-		// add placeholders for each of the variables
-		for (LLMessageBlock::message_variable_map_t::iterator
-				 iter = template_data->mMemberVariables.begin(),
-				 end = template_data->mMemberVariables.end();
-			 iter != end; iter++)
-		{
-			LLMessageVariable& ci = *(iter->second);
-			mCurrentSDataBlock->addVariable(ci.getName(), ci.getType());
-		}
-		return;
+		timeout = LL_SEMIRELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX;
 	}
+
+	const S32 retries = 0;
+	const BOOL ping_based_timeout = FALSE;
+	return sendReliable(host, retries, ping_based_timeout, timeout, callback, callback_data);
 }
 
-// add data to variable in current block
-void LLMessageSystem::addDataFast(const char *varname, const void *data, EMsgVariableType type, S32 size)
+// send the message via a UDP packet
+S32 LLMessageSystem::sendReliable(	const LLHost &host, 
+									S32 retries, 
+									BOOL ping_based_timeout,
+									F32 timeout, 
+									void (*callback)(void **,S32), 
+									void ** callback_data)
 {
-	char *vnamep = (char *)varname; 
-
-	// do we have a current message?
-	if (!mCurrentSMessageTemplate)
-	{
-		llerrs << "newMessage not called prior to addData" << llendl;
-		return;
-	}
-
-	// do we have a current block?
-	if (!mCurrentSDataBlock)
+	if (ping_based_timeout)
 	{
-		llerrs << "setBlock not called prior to addData" << llendl;
-		return;
+	    LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+	    if (cdp)
+	    {
+		    timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, LL_RELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged());
+	    }
+	    else
+	    {
+		    timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, LL_RELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX);
+	    }
 	}
 
-	// kewl, add the data if it exists
-	LLMessageVariable* var_data = mCurrentSMessageTemplate->mMemberBlocks[mCurrentSBlockName]->mMemberVariables[vnamep];
-	if (!var_data || !var_data->getName())
-	{
-		llerrs << vnamep << " not a variable in block " << mCurrentSBlockName << " of " << mCurrentSMessageTemplate->mName << llendl;
-		return;
-	}
+	mSendReliable = TRUE;
+	mReliablePacketParams.set(host, retries, ping_based_timeout, timeout, 
+		callback, callback_data, 
+		const_cast<char*>(mMessageBuilder->getMessageName()));
+	return sendMessage(host);
+}
 
-	// ok, it seems ok. . . are we the correct size?
-	if (var_data->getType() == MVT_VARIABLE)
-	{
-		// Variable 1 can only store 255 bytes, make sure our data is smaller
-		if ((var_data->getSize() == 1) &&
-			(size > 255))
-		{
-			llwarns << "Field " << varname << " is a Variable 1 but program "
-			       << "attempted to stuff more than 255 bytes in "
-			       << "(" << size << ").  Clamping size and truncating data." << llendl;
-			size = 255;
-			char *truncate = (char *)data;
-			truncate[255] = 0;
-		}
+void LLMessageSystem::forwardMessage(const LLHost &host)
+{
+	copyMessageRtoS();
+	sendMessage(host);
+}
 
-		// no correct size for MVT_VARIABLE, instead we need to tell how many bytes the size will be encoded as
-		mCurrentSDataBlock->addData(vnamep, data, size, type, var_data->getSize());
-		mCurrentSendTotal += size;
-	}
-	else
-	{
-		if (size != var_data->getSize())
-		{
-			llerrs << varname << " is type MVT_FIXED but request size " << size << " doesn't match template size "
-				   << var_data->getSize() << llendl;
-			return;
-		}
-		// alright, smash it in
-		mCurrentSDataBlock->addData(vnamep, data, size, type);
-		mCurrentSendTotal += size;
-	}
+void LLMessageSystem::forwardReliable(const LLHost &host)
+{
+	copyMessageRtoS();
+	sendReliable(host);
 }
 
-// add data to variable in current block - fails if variable isn't MVT_FIXED
-void LLMessageSystem::addDataFast(const char *varname, const void *data, EMsgVariableType type)
+void LLMessageSystem::forwardReliable(const U32 circuit_code)
 {
-	char *vnamep = (char *)varname; 
+	copyMessageRtoS();
+	sendReliable(findHost(circuit_code));
+}
 
-	// do we have a current message?
-	if (!mCurrentSMessageTemplate)
-	{
-		llerrs << "newMessage not called prior to addData" << llendl;
-		return;
-	}
+S32 LLMessageSystem::flushSemiReliable(const LLHost &host, void (*callback)(void **,S32), void ** callback_data)
+{
+	F32 timeout; 
 
-	// do we have a current block?
-	if (!mCurrentSDataBlock)
+	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+	if (cdp)
 	{
-		llerrs << "setBlock not called prior to addData" << llendl;
-		return;
+		timeout = llmax(LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS,
+						LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged());
 	}
-
-	// kewl, add the data if it exists
-	LLMessageVariable* var_data = mCurrentSMessageTemplate->mMemberBlocks[mCurrentSBlockName]->mMemberVariables[vnamep];
-	if (!var_data->getName())
+	else
 	{
-		llerrs << vnamep << " not a variable in block " << mCurrentSBlockName << " of " << mCurrentSMessageTemplate->mName << llendl;
-		return;
+		timeout = LL_SEMIRELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX;
 	}
 
-	// ok, it seems ok. . . are we MVT_VARIABLE?
-	if (var_data->getType() == MVT_VARIABLE)
+	S32 send_bytes = 0;
+	if (mMessageBuilder->getMessageSize())
 	{
-		// nope
-		llerrs << vnamep << " is type MVT_VARIABLE. Call using addData(name, data, size)" << llendl;
-		return;
+		mSendReliable = TRUE;
+		// No need for ping-based retry as not going to retry
+		mReliablePacketParams.set(host, 0, FALSE, timeout, callback, 
+								  callback_data, 
+								  const_cast<char*>(mMessageBuilder->getMessageName()));
+		send_bytes = sendMessage(host);
+		clearMessage();
 	}
 	else
 	{
-		mCurrentSDataBlock->addData(vnamep, data, var_data->getSize(), type);
-		mCurrentSendTotal += var_data->getSize();
+		delete callback_data;
 	}
+	return send_bytes;
 }
 
-BOOL LLMessageSystem::isSendFull(const char* blockname)
+S32 LLMessageSystem::flushReliable(const LLHost &host)
 {
-	if(!blockname)
+	S32 send_bytes = 0;
+	if (mMessageBuilder->getMessageSize())
 	{
-		return (mCurrentSendTotal > MTUBYTES);
+		send_bytes = sendReliable(host);
 	}
-	return isSendFullFast(gMessageStringTable.getString(blockname));
+	clearMessage();
+	return send_bytes;
 }
 
-BOOL LLMessageSystem::isSendFullFast(const char* blockname)
+		
+// This can be called from signal handlers,
+// so should should not use llinfos.
+S32 LLMessageSystem::sendMessage(const LLHost &host)
 {
-	if(mCurrentSendTotal > MTUBYTES)
+	if (! mMessageBuilder->isBuilt())
 	{
-		return TRUE;
-	}
-	if(!blockname)
-	{
-		return FALSE;
+		mSendSize = mMessageBuilder->buildMessage(mSendBuffer,
+												  MAX_BUFFER_SIZE);
 	}
-	char* bnamep = (char*)blockname;
-	S32 max;
-
-	LLMessageBlock* template_data = mCurrentSMessageTemplate->mMemberBlocks[bnamep];
-	
-	switch(template_data->mType)
-	{
-	case MBT_SINGLE:
-		max = 1;
-		break;
-	case MBT_MULTIPLE:
-		max = template_data->mNumber;
-		break;
-	case MBT_VARIABLE:
-	default:
-		max = MAX_BLOCKS;
-		break;
-	}
-	if(mCurrentSMessageData->mMemberBlocks[bnamep]->mBlockNumber >= max)
-	{
-		return TRUE;
-	}
-	return FALSE;
-}
-
-
-// blow away the last block of a message, return FALSE if that leaves no blocks or there wasn't a block to remove
-BOOL  LLMessageSystem::removeLastBlock()
-{
-	if (mCurrentSBlockName)
-	{
-		if (  (mCurrentSMessageData)
-			&&(mCurrentSMessageTemplate))
-		{
-			if (mCurrentSMessageData->mMemberBlocks[mCurrentSBlockName]->mBlockNumber >= 1)
-			{
-				// At least one block for the current block name.
-
-				// Store the current block name for future reference.
-				char *block_name = mCurrentSBlockName;
-
-				// Decrement the sent total by the size of the
-				// data in the message block that we're currently building.
-
-				LLMessageBlock* template_data = mCurrentSMessageTemplate->mMemberBlocks[mCurrentSBlockName];
-				
-				for (LLMessageBlock::message_variable_map_t::iterator iter = template_data->mMemberVariables.begin();
-					 iter != template_data->mMemberVariables.end(); iter++)
-				{
-					LLMessageVariable& ci = *(iter->second);
-					mCurrentSendTotal -= ci.getSize();
-				}
-
-
-				// Now we want to find the block that we're blowing away.
-
-				// Get the number of blocks.
-				LLMsgBlkData* block_data = mCurrentSMessageData->mMemberBlocks[block_name];
-				S32 num_blocks = block_data->mBlockNumber;
-
-				// Use the same (suspect?) algorithm that's used to generate
-				// the names in the nextBlock method to find it.
-				char *block_getting_whacked = block_name + num_blocks - 1;
-				LLMsgBlkData* whacked_data = mCurrentSMessageData->mMemberBlocks[block_getting_whacked];
-				delete whacked_data;
-				mCurrentSMessageData->mMemberBlocks.erase(block_getting_whacked);
-
-				if (num_blocks <= 1)
-				{
-					// we just blew away the last one, so return FALSE
-					return FALSE;
-				}
-				else
-				{
-					// Decrement the counter.
-					block_data->mBlockNumber--;
-					return TRUE;
-				}
-			}
-		}
-	}
-	return FALSE;
-}
-
-// make sure that all the desired data is in place and then copy the data into mSendBuffer
-void LLMessageSystem::buildMessage()
-{
-	// basic algorithm is to loop through the various pieces, building
-	// size and offset info if we encounter a -1 for mSize at any
-	// point that variable wasn't given data
-
-	// do we have a current message?
-	if (!mCurrentSMessageTemplate)
-	{
-		llerrs << "newMessage not called prior to buildMessage" << llendl;
-		return;
-	}
-
-	// zero out some useful values
-
-	// leave room for circuit counter
-	mSendSize = LL_PACKET_ID_SIZE;
-
-	// encode message number and adjust total_offset
-	if (mCurrentSMessageTemplate->mFrequency == MFT_HIGH)
-	{
-// old, endian-dependant way
-//		memcpy(&mSendBuffer[mSendSize], &mCurrentMessageTemplate->mMessageNumber, sizeof(U8));
-
-// new, independant way
-		mSendBuffer[mSendSize] = (U8)mCurrentSMessageTemplate->mMessageNumber;
-		mSendSize += sizeof(U8);
-	}
-	else if (mCurrentSMessageTemplate->mFrequency == MFT_MEDIUM)
-	{
-		U8 temp = 255;
-		memcpy(&mSendBuffer[mSendSize], &temp, sizeof(U8));  /*Flawfinder: ignore*/
-		mSendSize += sizeof(U8);
-
-		// mask off unsightly bits
-		temp = mCurrentSMessageTemplate->mMessageNumber & 255;
-		memcpy(&mSendBuffer[mSendSize], &temp, sizeof(U8));  /*Flawfinder: ignore*/
-		mSendSize += sizeof(U8);
-	}
-	else if (mCurrentSMessageTemplate->mFrequency == MFT_LOW)
-	{
-		U8 temp = 255;
-		U16  message_num;
-		memcpy(&mSendBuffer[mSendSize], &temp, sizeof(U8));  /*Flawfinder: ignore*/
-		mSendSize += sizeof(U8);
-		memcpy(&mSendBuffer[mSendSize], &temp, sizeof(U8));  /*Flawfinder: ignore*/
-		mSendSize += sizeof(U8);
-
-		// mask off unsightly bits
-		message_num = mCurrentSMessageTemplate->mMessageNumber & 0xFFFF;
-
-	    // convert to network byte order
-		message_num = htons(message_num);
-		memcpy(&mSendBuffer[mSendSize], &message_num, sizeof(U16)); /*Flawfinder: ignore*/
-		mSendSize += sizeof(U16);
-	}
-	else
-	{
-		llerrs << "unexpected message frequency in buildMessage" << llendl;
-		return;
-	}
-
-	// counting variables used to encode multiple block info
-	S32 block_count = 0;
-	U8  temp_block_number;
-
-	// loop through msg blocks to loop through variables, totalling up size data and copying into mSendBuffer
-	for (LLMsgData::msg_blk_data_map_t::iterator
-			 iter = mCurrentSMessageData->mMemberBlocks.begin(),
-			 end = mCurrentSMessageData->mMemberBlocks.end();
-		 iter != end; iter++)
-	{
-		LLMsgBlkData* mbci = iter->second;
-		// do we need to encode a block code?
-		if (block_count == 0)
-		{
-			block_count = mbci->mBlockNumber;
-
-			LLMessageBlock* template_data = mCurrentSMessageTemplate->mMemberBlocks[mbci->mName];
-			
-			// ok, if this is the first block of a repeating pack, set block_count and, if it's type MBT_VARIABLE encode a byte for how many there are
-			if (template_data->mType == MBT_VARIABLE)
-			{
-				// remember that mBlockNumber is a S32
-				temp_block_number = (U8)mbci->mBlockNumber;
-				if ((S32)(mSendSize + sizeof(U8)) < MAX_BUFFER_SIZE)
-				{
-				    memcpy(&mSendBuffer[mSendSize], &temp_block_number, sizeof(U8));	/* Flawfinder: ignore */
-				    mSendSize += sizeof(U8);
-				}
-				else
-				{
-				    // Just reporting error is likely not enough. Need
-				    // to check how to abort or error out gracefully
-				    // from this function. XXXTBD
-				    llerrs << "buildMessage failed. Message excedding"
-						" sendBuffersize." << llendl;
-				}
-			}
-			else if (template_data->mType == MBT_MULTIPLE)
-			{
-				if (block_count != template_data->mNumber)
-				{
-					// nope!  need to fill it in all the way!
-					llerrs << "Block " << mbci->mName
-						<< " is type MBT_MULTIPLE but only has data for "
-						<< block_count << " out of its "
-						<< template_data->mNumber << " blocks" << llendl;
-				}
-			}
-		}
-
-		// counting down multiple blocks
-		block_count--;
-
-		// now loop through the variables
-		for (LLMsgBlkData::msg_var_data_map_t::iterator iter = mbci->mMemberVarData.begin();
-			 iter != mbci->mMemberVarData.end(); iter++)
-		{
-			LLMsgVarData& mvci = *iter;
-			if (mvci.getSize() == -1)
-			{
-				// oops, this variable wasn't ever set!
-				llerrs << "The variable " << mvci.getName() << " in block "
-					<< mbci->mName << " of message "
-					<< mCurrentSMessageData->mName
-					<< " wasn't set prior to buildMessage call" << llendl;
-			}
-			else
-			{
-				S32 data_size = mvci.getDataSize();
-				if(data_size > 0)
-				{
-					// The type is MVT_VARIABLE, which means that we
-					// need to encode a size argument. Otherwise,
-					// there is no need.
-					S32 size = mvci.getSize();
-					U8 sizeb;
-					U16 sizeh;
-					switch(data_size)
-					{
-					case 1:
-						sizeb = size;
-						htonmemcpy(&mSendBuffer[mSendSize], &sizeb, MVT_U8, 1);
-						break;
-					case 2:
-						sizeh = size;
-						htonmemcpy(&mSendBuffer[mSendSize], &sizeh, MVT_U16, 2);
-						break;
-					case 4:
-						htonmemcpy(&mSendBuffer[mSendSize], &size, MVT_S32, 4);
-						break;
-					default:
-						llerrs << "Attempting to build variable field with unknown size of " << size << llendl;
-						break;
-					}
-					mSendSize += mvci.getDataSize();
-				}
-
-				// if there is any data to pack, pack it
-				if((mvci.getData() != NULL) && mvci.getSize())
-				{
-					if(mSendSize + mvci.getSize() < (S32)sizeof(mSendBuffer))
-					{
-					    memcpy( /* Flawfinder: ignore */
-							&mSendBuffer[mSendSize],
-							mvci.getData(),
-							mvci.getSize());
-					    mSendSize += mvci.getSize();
-					}
-					else
-					{
-					    // Just reporting error is likely not
-					    // enough. Need to check how to abort or error
-					    // out gracefully from this function. XXXTBD
-						llerrs << "LLMessageSystem::buildMessage failed. "
-							<< "Attempted to pack "
-							<< mSendSize + mvci.getSize()
-							<< " bytes into a buffer with size "
-							<< mSendBuffer << "." << llendl
-					}						
-				}
-			}
-		}
-	}
-	mbSBuilt = TRUE;
-}
-
-S32 LLMessageSystem::sendReliable(const LLHost &host)
-{
-	return sendReliable(host, LL_DEFAULT_RELIABLE_RETRIES, TRUE, LL_PING_BASED_TIMEOUT_DUMMY, NULL, NULL);
-}
-
-
-S32 LLMessageSystem::sendSemiReliable(const LLHost &host, void (*callback)(void **,S32), void ** callback_data)
-{
-	F32 timeout;
-
-	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
-	if (cdp)
-	{
-		timeout = llmax(LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS,
-						LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged());
-	}
-	else
-	{
-		timeout = LL_SEMIRELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX;
-	}
-
-	return sendReliable(host, 0, FALSE, timeout, callback, callback_data);
-}
-
-// send the message via a UDP packet
-S32 LLMessageSystem::sendReliable(	const LLHost &host, 
-									S32 retries, 
-									BOOL ping_based_timeout,
-									F32 timeout, 
-									void (*callback)(void **,S32), 
-									void ** callback_data)
-{
-	if (ping_based_timeout)
-	{
-	    LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
-	    if (cdp)
-	    {
-		    timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, LL_RELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged());
-	    }
-	    else
-	    {
-		    timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, LL_RELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX);
-	    }
-	}
-
-	mSendReliable = TRUE;
-	mReliablePacketParams.set(host, retries, ping_based_timeout, timeout, 
-		callback, callback_data, mCurrentSMessageName);
-	return sendMessage(host);
-}
-
-void LLMessageSystem::forwardMessage(const LLHost &host)
-{
-	copyMessageRtoS();
-	sendMessage(host);
-}
-
-void LLMessageSystem::forwardReliable(const LLHost &host)
-{
-	copyMessageRtoS();
-	sendReliable(host);
-}
-
-void LLMessageSystem::forwardReliable(const U32 circuit_code)
-{
-	copyMessageRtoS();
-	sendReliable(findHost(circuit_code));
-}
-
-S32 LLMessageSystem::flushSemiReliable(const LLHost &host, void (*callback)(void **,S32), void ** callback_data)
-{
-	F32 timeout; 
-
-	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
-	if (cdp)
-	{
-		timeout = llmax(LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS,
-						LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged());
-	}
-	else
-	{
-		timeout = LL_SEMIRELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX;
-	}
-
-	S32 send_bytes = 0;
-	if (mCurrentSendTotal)
-	{
-		mSendReliable = TRUE;
-		// No need for ping-based retry as not going to retry
-		mReliablePacketParams.set(host, 0, FALSE, timeout, callback, callback_data, mCurrentSMessageName);
-		send_bytes = sendMessage(host);
-		clearMessage();
-	}
-	else
-	{
-		delete callback_data;
-	}
-	return send_bytes;
-}
-
-S32 LLMessageSystem::flushReliable(const LLHost &host)
-{
-	S32 send_bytes = 0;
-	if (mCurrentSendTotal)
-	{
-		send_bytes = sendReliable(host);
-	}
-	clearMessage();
-	return send_bytes;
-}
-
-		
-// This can be called from signal handlers,
-// so should should not use llinfos.
-S32 LLMessageSystem::sendMessage(const LLHost &host)
-{
-	if (!mbSBuilt)
-	{
-		buildMessage();
-	}
-
-	mCurrentSendTotal = 0;
 
 	if (!(host.isOk()))    // if port and ip are zero, don't bother trying to send the message
 	{
@@ -2976,10 +2007,10 @@ S32 LLMessageSystem::sendMessage(const LLHost &host)
 			if(mVerboseLog)
 			{
 				llinfos << "MSG: -> " << host << "\tUNKNOWN CIRCUIT:\t"
-						<< mCurrentSMessageName << llendl;
+						<< mMessageBuilder->getMessageName() << llendl;
 			}
 			llwarns << "sendMessage - Trying to send "
-					<< mCurrentSMessageName << " on unknown circuit "
+					<< mMessageBuilder->getMessageName() << " on unknown circuit "
 					<< host << llendl;
 			return 0;
 		}
@@ -2998,15 +2029,41 @@ S32 LLMessageSystem::sendMessage(const LLHost &host)
 			if(mVerboseLog)
 			{
 				llinfos << "MSG: -> " << host << "\tDEAD CIRCUIT\t\t"
-						<< mCurrentSMessageName << llendl;
+						<< mMessageBuilder->getMessageName() << llendl;
 			}
 			llwarns << "sendMessage - Trying to send message "
-					<< mCurrentSMessageName << " to dead circuit "
+					<< mMessageBuilder->getMessageName() << " to dead circuit "
 					<< host << llendl;
 			return 0;
 		}
 	}
 
+	// NOTE: babbage: LLSD message -> HTTP, template message -> UDP
+	if(mMessageBuilder == mLLSDMessageBuilder)
+	{
+		LLSD message = mLLSDMessageBuilder->getMessage();
+		
+		const LLHTTPSender& sender = LLHTTPSender::getSender(host);
+		LLHTTPClient::ResponderPtr responder = NULL;
+		if(mSendReliable)
+		{
+			responder =
+				new LLFnPtrResponder(mReliablePacketParams.mCallback,
+									 mReliablePacketParams.mCallbackData);
+		}
+		else
+		{
+			llwarns << "LLMessageSystem::sendMessage: Sending unreliable " << mMessageBuilder->getMessageName() << " message via HTTP" << llendl;
+			responder = new LLFnPtrResponder(NULL, NULL);
+		}
+		sender.send(host, mLLSDMessageBuilder->getMessageName(),
+					message, responder);
+
+		mSendReliable = FALSE;
+		mReliablePacketParams.clear();
+		return 1;
+	}
+
 	memset(mSendBuffer,0,LL_PACKET_ID_SIZE); // zero out the packet ID field
 
 	// add the send id to the front of the message
@@ -3017,20 +2074,17 @@ S32 LLMessageSystem::sendMessage(const LLHost &host)
 
 	// Compress the message, which will usually reduce its size.
 	U8 * buf_ptr = (U8 *)mSendBuffer;
-	S32 buffer_length = mSendSize;
-	if(ME_ZEROCODED == mCurrentSMessageTemplate->getEncoding())
-	{
-		zeroCode(&buf_ptr, &buffer_length);
-	}
+	U32 buffer_length = mSendSize;
+	mMessageBuilder->compressMessage(buf_ptr, buffer_length);
 
 	if (buffer_length > 1500)
 	{
-		if((mCurrentSMessageName != _PREHASH_ChildAgentUpdate)
-		   && (mCurrentSMessageName != _PREHASH_SendXferPacket))
+		if((mMessageBuilder->getMessageName() != _PREHASH_ChildAgentUpdate)
+		   && (mMessageBuilder->getMessageName() != _PREHASH_SendXferPacket))
 		{
 			llwarns << "sendMessage - Trying to send "
 					<< ((buffer_length > 4000) ? "EXTRA " : "")
-					<< "BIG message " << mCurrentSMessageName << " - "
+					<< "BIG message " << mMessageBuilder->getMessageName() << " - "
 					<< buffer_length << llendl;
 		}
 	}
@@ -3055,7 +2109,7 @@ S32 LLMessageSystem::sendMessage(const LLHost &host)
 	BOOL is_ack_appended = FALSE;
 	std::vector<TPACKETID> acks;
 	if((space_left > 0) && (ack_count > 0) && 
-	   (mCurrentSMessageName != _PREHASH_PacketAck))
+	   (mMessageBuilder->getMessageName() != _PREHASH_PacketAck))
 	{
 		buf_ptr[0] |= LL_ACK_FLAG;
 		S32 append_ack_count = llmin(space_left, ack_count);
@@ -3126,7 +2180,7 @@ S32 LLMessageSystem::sendMessage(const LLHost &host)
 		char buffer[MAX_STRING];			/* Flawfinder: ignore */
 		snprintf(buffer, MAX_STRING, "\t%6d\t%6d\t%6d ", mSendSize, buffer_length, cdp->getPacketOutID());		/* Flawfinder: ignore */
 		str << buffer
-			<< mCurrentSMessageTemplate->mName
+			<< mMessageBuilder->getMessageName()
 			<< (mSendReliable ? " reliable " : "");
 		if(is_ack_appended)
 		{
@@ -3137,129 +2191,60 @@ S32 LLMessageSystem::sendMessage(const LLHost &host)
 		llinfos << str.str() << llendl;
 	}
 
-	lldebugst(LLERR_MESSAGE) << "MessageSent at: " << (S32)totalTime() 
-		<< ", " << mCurrentSMessageTemplate->mName
-		<< " to " << host 
-		<< llendl;
-
-	// ok, clean up temp data
-	delete mCurrentSMessageData;
-	mCurrentSMessageData = NULL;
+	/*lldebugst(LLERR_MESSAGE) << "MessageSent at: " << (S32)totalTime() 
+							 << "," << mMessageBuilder->getMessageName()
+							 << " to " << host 
+							 << llendl;*/
 
 	mPacketsOut++;
 	mBytesOut += buffer_length;
 	
+	mSendReliable = FALSE;
+	mReliablePacketParams.clear();
 	return buffer_length;
 }
 
-
-// Returns template for the message contained in buffer
-BOOL LLMessageSystem::decodeTemplate(  
-		const U8* buffer, S32 buffer_size,  // inputs
-		LLMessageTemplate** msg_template ) // outputs
+void LLMessageSystem::logMsgFromInvalidCircuit( const LLHost& host, BOOL recv_reliable )
 {
-	const U8* header = buffer + LL_PACKET_ID_SIZE;
-
-	// is there a message ready to go?
-	if (buffer_size <= 0)
+	if(mVerboseLog)
 	{
-		llwarns << "No message waiting for decode!" << llendl;
-		return(FALSE);
+		std::ostringstream str;
+		str << "MSG: <- " << host;
+		char buffer[MAX_STRING];			/* Flawfinder: ignore */
+		snprintf(buffer, MAX_STRING, "\t%6d\t%6d\t%6d ", mMessageReader->getMessageSize(), (mIncomingCompressedSize ? mIncomingCompressedSize: mMessageReader->getMessageSize()), mCurrentRecvPacketID);		/* Flawfinder: ignore */
+		str << buffer
+			<< mMessageReader->getMessageName()
+			<< (recv_reliable ? " reliable" : "")
+ 			<< " REJECTED";
+		llinfos << str.str() << llendl;
 	}
+	// nope!
+	// cout << "Rejecting unexpected message " << mCurrentMessageTemplate->mName << " from " << hex << ip << " , " << dec << port << endl;
 
-	U32 num = 0;
-
-	if (header[0] != 255)
+	// Keep track of rejected messages as well
+	if (mNumMessageCounts >= MAX_MESSAGE_COUNT_NUM)
 	{
-		// high frequency message
-		num = header[0];
+		llwarns << "Got more than " << MAX_MESSAGE_COUNT_NUM << " packets without clearing counts" << llendl;
 	}
-	else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 1)) && (header[1] != 255))
+	else
 	{
-		// medium frequency message
-		num = (255 << 8) | header[1];
+		// TODO: babbage: work out if we need these
+		// mMessageCountList[mNumMessageCounts].mMessageNum = mCurrentRMessageTemplate->mMessageNumber;
+		mMessageCountList[mNumMessageCounts].mMessageBytes = mMessageReader->getMessageSize();
+		mMessageCountList[mNumMessageCounts].mInvalid = TRUE;
+		mNumMessageCounts++;
 	}
-	else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 3)) && (header[1] == 255))
-	{
-		// low frequency message
-		U16	message_id_U16 = 0;
-		// I think this check busts the message system.
-		// it appears that if there is a NULL in the message #, it won't copy it....
-		// what was the goal?
-		//if(header[2])
-		memcpy(&message_id_U16, &header[2], 2);	/* Flawfinder: ignore */
-
-		// dependant on endian-ness:
-		//		U32	temp = (255 << 24) | (255 << 16) | header[2];
-
-		// independant of endian-ness:
-		message_id_U16 = ntohs(message_id_U16);
-		num = 0xFFFF0000 | message_id_U16;
-	}
-	else // bogus packet received (too short)
-	{
-		llwarns << "Packet with unusable length received (too short): "
-				<< buffer_size << llendl;
-		return(FALSE);
-	}
-
-	LLMessageTemplate* temp = get_ptr_in_map(mMessageNumbers,num);
-	if (temp)
-	{
-		*msg_template = temp;
-	}
-	else
-	{
-		llwarns << "Message #" << std::hex << num << std::dec
-			<< " received but not registered!" << llendl;
-		callExceptionFunc(MX_UNREGISTERED_MESSAGE);
-		return(FALSE);
-	}
-
-	return(TRUE);
-}
-
-
-void LLMessageSystem::logMsgFromInvalidCircuit( const LLHost& host, BOOL recv_reliable )
-{
-	if(mVerboseLog)
-	{
-		std::ostringstream str;
-		str << "MSG: <- " << host;
-		char buffer[MAX_STRING];			/* Flawfinder: ignore */
-		snprintf(buffer, MAX_STRING, "\t%6d\t%6d\t%6d ", mReceiveSize, (mIncomingCompressedSize ? mIncomingCompressedSize: mReceiveSize), mCurrentRecvPacketID);	/* Flawfinder: ignore */
-		str << buffer
-			<< mCurrentRMessageTemplate->mName
-			<< (recv_reliable ? " reliable" : "")
- 			<< " REJECTED";
-		llinfos << str.str() << llendl;
-	}
-	// nope!
-	// cout << "Rejecting unexpected message " << mCurrentMessageTemplate->mName << " from " << hex << ip << " , " << dec << port << endl;
-
-	// Keep track of rejected messages as well
-	if (mNumMessageCounts >= MAX_MESSAGE_COUNT_NUM)
-	{
-		llwarns << "Got more than " << MAX_MESSAGE_COUNT_NUM << " packets without clearing counts" << llendl;
-	}
-	else
-	{
-		mMessageCountList[mNumMessageCounts].mMessageNum = mCurrentRMessageTemplate->mMessageNumber;
-		mMessageCountList[mNumMessageCounts].mMessageBytes = mReceiveSize;
-		mMessageCountList[mNumMessageCounts].mInvalid = TRUE;
-		mNumMessageCounts++;
-	}
-}
+}
 
 void LLMessageSystem::logTrustedMsgFromUntrustedCircuit( const LLHost& host )
 {
 	// RequestTrustedCircuit is how we establish trust, so don't spam
 	// if it's received on a trusted circuit. JC
-	if (strcmp(mCurrentRMessageTemplate->mName, "RequestTrustedCircuit"))
+	if (strcmp(mMessageReader->getMessageName(), "RequestTrustedCircuit"))
 	{
 		llwarns << "Received trusted message on untrusted circuit. "
 	   		<< "Will reply with deny. "
-			<< "Message: " << mCurrentRMessageTemplate->mName
+			<< "Message: " << mMessageReader->getMessageName()
 			<< " Host: " << host << llendl;
 	}
 
@@ -3271,10 +2256,11 @@ void LLMessageSystem::logTrustedMsgFromUntrustedCircuit( const LLHost& host )
 	}
 	else
 	{
-		mMessageCountList[mNumMessageCounts].mMessageNum
-			= mCurrentRMessageTemplate->mMessageNumber;
+		// TODO: babbage: work out if we need these
+		//mMessageCountList[mNumMessageCounts].mMessageNum
+		//	= mCurrentRMessageTemplate->mMessageNumber;
 		mMessageCountList[mNumMessageCounts].mMessageBytes
-			= mReceiveSize;
+			= mMessageReader->getMessageSize();
 		mMessageCountList[mNumMessageCounts].mInvalid = TRUE;
 		mNumMessageCounts++;
 	}
@@ -3288,8 +2274,9 @@ void LLMessageSystem::logValidMsg(LLCircuitData *cdp, const LLHost& host, BOOL r
 	}
 	else
 	{
-		mMessageCountList[mNumMessageCounts].mMessageNum = mCurrentRMessageTemplate->mMessageNumber;
-		mMessageCountList[mNumMessageCounts].mMessageBytes = mReceiveSize;
+		// TODO: babbage: work out if we need these
+		//mMessageCountList[mNumMessageCounts].mMessageNum = mCurrentRMessageTemplate->mMessageNumber;
+		mMessageCountList[mNumMessageCounts].mMessageBytes = mMessageReader->getMessageSize();
 		mMessageCountList[mNumMessageCounts].mInvalid = FALSE;
 		mNumMessageCounts++;
 	}
@@ -3306,9 +2293,9 @@ void LLMessageSystem::logValidMsg(LLCircuitData *cdp, const LLHost& host, BOOL r
 		std::ostringstream str;
 		str << "MSG: <- " << host;
 		char buffer[MAX_STRING];			/* Flawfinder: ignore */
-		snprintf(buffer, MAX_STRING, "\t%6d\t%6d\t%6d ", mReceiveSize, (mIncomingCompressedSize ? mIncomingCompressedSize : mReceiveSize), mCurrentRecvPacketID);		/* Flawfinder: ignore */
+		snprintf(buffer, MAX_STRING, "\t%6d\t%6d\t%6d ", mMessageReader->getMessageSize(), (mIncomingCompressedSize ? mIncomingCompressedSize : mMessageReader->getMessageSize()), mCurrentRecvPacketID);		/* Flawfinder: ignore */
 		str << buffer
-			<< mCurrentRMessageTemplate->mName
+			<< mMessageReader->getMessageName()
 			<< (recv_reliable ? " reliable" : "")
 			<< (recv_resent ? " resent" : "")
 			<< (recv_acks ? " acks" : "");
@@ -3316,631 +2303,204 @@ void LLMessageSystem::logValidMsg(LLCircuitData *cdp, const LLHost& host, BOOL r
 	}
 }
 
-
-void LLMessageSystem::logRanOffEndOfPacket( const LLHost& host )
+void LLMessageSystem::sanityCheck()
 {
-	// we've run off the end of the packet!
-	llwarns << "Ran off end of packet " << mCurrentRMessageTemplate->mName
-			<< " with id " << mCurrentRecvPacketID << " from " << host
-			<< llendl;
-	if(mVerboseLog)
-	{
-		llinfos << "MSG: -> " << host << "\tREAD PAST END:\t"
-				<< mCurrentRecvPacketID << " "
-				<< mCurrentSMessageTemplate->mName << llendl;
-	}
-	callExceptionFunc(MX_RAN_OFF_END_OF_PACKET);
-}
+// TODO: babbage: reinstate
 
+//	if (!mCurrentRMessageData)
+//	{
+//		llerrs << "mCurrentRMessageData is NULL" << llendl;
+//	}
 
-// decode a given message
-BOOL LLMessageSystem::decodeData(const U8* buffer, const LLHost& sender )
-{
-	llassert( mReceiveSize >= 0 );
-	llassert( mCurrentRMessageTemplate);
-	llassert( !mCurrentRMessageData );
-	delete mCurrentRMessageData; // just to make sure
+//	if (!mCurrentRMessageTemplate)
+//	{
+//		llerrs << "mCurrentRMessageTemplate is NULL" << llendl;
+//	}
 
-	S32 decode_pos = LL_PACKET_ID_SIZE + (S32)(mCurrentRMessageTemplate->mFrequency);
+//	if (!mCurrentRTemplateBlock)
+//	{
+//		llerrs << "mCurrentRTemplateBlock is NULL" << llendl;
+//	}
 
-	// create base working data set
-	mCurrentRMessageData = new LLMsgData(mCurrentRMessageTemplate->mName);
-	
-	// loop through the template building the data structure as we go
-	for (LLMessageTemplate::message_block_map_t::iterator iter = mCurrentRMessageTemplate->mMemberBlocks.begin();
-		 iter != mCurrentRMessageTemplate->mMemberBlocks.end(); iter++)
-	{
-		LLMessageBlock* mbci = iter->second;
-		U8	repeat_number;
-		S32	i;
+//	if (!mCurrentRDataBlock)
+//	{
+//		llerrs << "mCurrentRDataBlock is NULL" << llendl;
+//	}
 
-		// how many of this block?
+//	if (!mCurrentSMessageData)
+//	{
+//		llerrs << "mCurrentSMessageData is NULL" << llendl;
+//	}
 
-		if (mbci->mType == MBT_SINGLE)
-		{
-			// just one
-			repeat_number = 1;
-		}
-		else if (mbci->mType == MBT_MULTIPLE)
-		{
-			// a known number
-			repeat_number = mbci->mNumber;
-		}
-		else if (mbci->mType == MBT_VARIABLE)
-		{
-			// need to read the number from the message
-			// repeat number is a single byte
-			if (decode_pos >= mReceiveSize)
-			{
-				logRanOffEndOfPacket( sender );
-				return FALSE;
-			}
-			repeat_number = buffer[decode_pos];
-			decode_pos++;
-		}
-		else
-		{
-			llerrs << "Unknown block type" << llendl;
-			return FALSE;
-		}
+//	if (!mCurrentSMessageTemplate)
+//	{
+//		llerrs << "mCurrentSMessageTemplate is NULL" << llendl;
+//	}
 
-		LLMsgBlkData* cur_data_block = NULL;
+//	if (!mCurrentSTemplateBlock)
+//	{
+//		llerrs << "mCurrentSTemplateBlock is NULL" << llendl;
+//	}
 
-		// now loop through the block
-		for (i = 0; i < repeat_number; i++)
-		{
-			if (i)
-			{
-				// build new name to prevent collisions
-				// TODO: This should really change to a vector
-				cur_data_block = new LLMsgBlkData(mbci->mName, repeat_number);
-				cur_data_block->mName = mbci->mName + i;
-			}
-			else
-			{
-				cur_data_block = new LLMsgBlkData(mbci->mName, repeat_number);
-			}
+//	if (!mCurrentSDataBlock)
+//	{
+//		llerrs << "mCurrentSDataBlock is NULL" << llendl;
+//	}
+}
 
-			// add the block to the message
-			mCurrentRMessageData->addBlock(cur_data_block);
+void LLMessageSystem::showCircuitInfo()
+{
+	llinfos << mCircuitInfo << llendl;
+}
 
-			// now read the variables
-			for (LLMessageBlock::message_variable_map_t::iterator iter = mbci->mMemberVariables.begin();
-				 iter != mbci->mMemberVariables.end(); iter++)
-			{
-				LLMessageVariable& mvci = *(iter->second);
-				// ok, build out the variables
-				// add variable block
-				cur_data_block->addVariable(mvci.getName(), mvci.getType());
 
-				// what type of variable?
-				if (mvci.getType() == MVT_VARIABLE)
-				{
-					// variable, get the number of bytes to read from the template
-					S32 data_size = mvci.getSize();
-					U8 tsizeb = 0;
-					U16 tsizeh = 0;
-					U32 tsize = 0;
+void LLMessageSystem::dumpCircuitInfo()
+{
+	lldebugst(LLERR_CIRCUIT_INFO) << mCircuitInfo << llendl;
+}
 
-					if ((decode_pos + data_size) > mReceiveSize)
-					{
-						logRanOffEndOfPacket( sender );
-						return FALSE;
-					}
-					switch(data_size)
-					{
-					case 1:
-						htonmemcpy(&tsizeb, &buffer[decode_pos], MVT_U8, 1);
-						tsize = tsizeb;
-						break;
-					case 2:
-						htonmemcpy(&tsizeh, &buffer[decode_pos], MVT_U16, 2);
-						tsize = tsizeh;
-						break;
-					case 4:
-						htonmemcpy(&tsizeb, &buffer[decode_pos], MVT_U32, 4);
-						break;
-					default:
-						llerrs << "Attempting to read variable field with unknown size of " << data_size << llendl;
-						break;
-						
-					}
-					decode_pos += data_size;
+/* virtual */
+U32 LLMessageSystem::getOurCircuitCode()
+{
+	return mOurCircuitCode;
+}
 
-					if ((decode_pos + (S32)tsize) > mReceiveSize)
-					{
-						logRanOffEndOfPacket( sender );
-						return FALSE;
-					}
-					cur_data_block->addData(mvci.getName(), &buffer[decode_pos], tsize, mvci.getType());
-					decode_pos += tsize;
-				}
-				else
-				{
-					// fixed!
-					// so, copy data pointer and set data size to fixed size
+LLString LLMessageSystem::getCircuitInfoString()
+{
+	LLString info_string;
 
-					if ((decode_pos + mvci.getSize()) > mReceiveSize)
-					{
-						logRanOffEndOfPacket( sender );
-						return FALSE;
-					}
+	info_string += mCircuitInfo.getInfoString();
+	return info_string;
+}
 
-					cur_data_block->addData(mvci.getName(), &buffer[decode_pos], mvci.getSize(), mvci.getType());
-					decode_pos += mvci.getSize();
-				}
-			}
-		}
+// returns whether the given host is on a trusted circuit
+BOOL    LLMessageSystem::getCircuitTrust(const LLHost &host)
+{
+	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+	if (cdp)
+	{
+		return cdp->getTrusted();
 	}
 
-	if (mCurrentRMessageData->mMemberBlocks.empty()
-		&& !mCurrentRMessageTemplate->mMemberBlocks.empty())
+	return FALSE;
+}
+
+// Activate a circuit, and set its trust level (TRUE if trusted,
+// FALSE if not).
+void LLMessageSystem::enableCircuit(const LLHost &host, BOOL trusted)
+{
+	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+	if (!cdp)
 	{
-		lldebugs << "Empty message '" << mCurrentRMessageTemplate->mName << "' (no blocks)" << llendl;
-		return FALSE;
+		cdp = mCircuitInfo.addCircuitData(host, 0);
 	}
-
+	else
 	{
-		static LLTimer decode_timer;
+		cdp->setAlive(TRUE);
+	}
+	cdp->setTrusted(trusted);
+}
 
-		if( mTimeDecodes || mTimingCallback )
-		{
-			decode_timer.reset();
-		}
+void LLMessageSystem::disableCircuit(const LLHost &host)
+{
+	llinfos << "LLMessageSystem::disableCircuit for " << host << llendl;
+	U32 code = gMessageSystem->findCircuitCode( host );
 
-		//	if( mCurrentRMessageTemplate->mName == _PREHASH_AgentToNewRegion )
-		//	{
-		//		VTResume();  // VTune
-		//	}
+	// Don't need to do this, as we're removing the circuit info anyway - djs 01/28/03
 
+	// don't clean up 0 circuit code entries
+	// because many hosts (neighbor sims, etc) can have the 0 circuit
+	if (code)
+	{
+		//if (mCircuitCodes.checkKey(code))
+		code_session_map_t::iterator it = mCircuitCodes.find(code);
+		if(it != mCircuitCodes.end())
 		{
-			LLFastTimer t(LLFastTimer::FTM_PROCESS_MESSAGES);
-			if( !mCurrentRMessageTemplate->callHandlerFunc(this) )
-			{
-				llwarns << "Message from " << sender << " with no handler function received: " << mCurrentRMessageTemplate->mName << llendl;
-			}
+			llinfos << "Circuit " << code << " removed from list" << llendl;
+			//mCircuitCodes.removeData(code);
+			mCircuitCodes.erase(it);
 		}
 
-		//	if( mCurrentRMessageTemplate->mName == _PREHASH_AgentToNewRegion )
-		//	{
-		//		VTPause();	// VTune
-		//	}
-
-		if( mTimeDecodes || mTimingCallback )
+		U64 ip_port = 0;
+		std::map<U32, U64>::iterator iter = gMessageSystem->mCircuitCodeToIPPort.find(code);
+		if (iter != gMessageSystem->mCircuitCodeToIPPort.end())
 		{
-			F32 decode_time = decode_timer.getElapsedTimeF32();
-
-			if (mTimingCallback)
-			{
-				mTimingCallback(mCurrentRMessageTemplate->mName,
-								decode_time,
-								mTimingCallbackData);
-			}
-
-			if (mTimeDecodes)
-			{
-				mCurrentRMessageTemplate->mDecodeTimeThisFrame += decode_time;
-
-				mCurrentRMessageTemplate->mTotalDecoded++;
-				mCurrentRMessageTemplate->mTotalDecodeTime += decode_time;
+			ip_port = iter->second;
 
-				if( mCurrentRMessageTemplate->mMaxDecodeTimePerMsg < decode_time )
-				{
-					mCurrentRMessageTemplate->mMaxDecodeTimePerMsg = decode_time;
-				}
+			gMessageSystem->mCircuitCodeToIPPort.erase(iter);
 
+			U32 old_port = (U32)(ip_port & (U64)0xFFFFFFFF);
+			U32 old_ip = (U32)(ip_port >> 32);
 
-				if( decode_time > mTimeDecodesSpamThreshold )
-				{
-					lldebugs << "--------- Message " << mCurrentRMessageTemplate->mName << " decode took " << decode_time << " seconds. (" <<
-						mCurrentRMessageTemplate->mMaxDecodeTimePerMsg << " max, " <<
-						(mCurrentRMessageTemplate->mTotalDecodeTime / mCurrentRMessageTemplate->mTotalDecoded) << " avg)" << llendl;
-				}
-			}
+			llinfos << "Host " << LLHost(old_ip, old_port) << " circuit " << code << " removed from lookup table" << llendl;
+			gMessageSystem->mIPPortToCircuitCode.erase(ip_port);
 		}
 	}
-	return TRUE;
+	else
+	{
+		// Sigh, since we can open circuits which don't have circuit
+		// codes, it's possible for this to happen...
+		
+		//llwarns << "Couldn't find circuit code for " << host << llendl;
+	}
+
+	mCircuitInfo.removeCircuitData(host);
 }
 
-void LLMessageSystem::getDataFast(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum, S32 max_size)
+
+void LLMessageSystem::setCircuitAllowTimeout(const LLHost &host, BOOL allow)
 {
-	// is there a message ready to go?
-	if (mReceiveSize == -1)
+	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+	if (cdp)
 	{
-		llerrs << "No message waiting for decode 2!" << llendl;
-		return;
+		cdp->setAllowTimeout(allow);
 	}
+}
 
-	if (!mCurrentRMessageData)
+void LLMessageSystem::setCircuitTimeoutCallback(const LLHost &host, void (*callback_func)(const LLHost & host, void *user_data), void *user_data)
+{
+	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+	if (cdp)
 	{
-		llerrs << "Invalid mCurrentMessageData in getData!" << llendl;
-		return;
+		cdp->setTimeoutCallback(callback_func, user_data);
 	}
+}
 
-	char *bnamep = (char *)blockname + blocknum; // this works because it's just a hash.  The bnamep is never derefference
-	char *vnamep = (char *)varname; 
-
-	LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
-
-	if (iter == mCurrentRMessageData->mMemberBlocks.end())
-	{
-		llerrs << "Block " << blockname << " #" << blocknum
-			<< " not in message " << mCurrentRMessageData->mName << llendl;
-		return;
-	}
 
-	LLMsgBlkData *msg_block_data = iter->second;
-	LLMsgVarData& vardata = msg_block_data->mMemberVarData[vnamep];
+BOOL LLMessageSystem::checkCircuitBlocked(const U32 circuit)
+{
+	LLHost host = findHost(circuit);
 
-	if (!vardata.getName())
+	if (!host.isOk())
 	{
-		llerrs << "Variable "<< vnamep << " not in message "
-			<< mCurrentRMessageData->mName<< " block " << bnamep << llendl;
-		return;
+		//llinfos << "checkCircuitBlocked: Unknown circuit " << circuit << llendl;
+		return TRUE;
 	}
 
-	if (size && size != vardata.getSize())
+	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+	if (cdp)
 	{
-		llerrs << "Msg " << mCurrentRMessageData->mName 
-			<< " variable " << vnamep
-			<< " is size " << vardata.getSize()
-			<< " but copying into buffer of size " << size
-			<< llendl;
-		return;
-	}
-
-
-	const S32 vardata_size = vardata.getSize();
-	if( max_size >= vardata_size )
-	{   
-		switch( vardata_size )
-		{ 
-		case 1:
-			*((U8*)datap) = *((U8*)vardata.getData());
-			break;
-		case 2:
-			*((U16*)datap) = *((U16*)vardata.getData());
-			break;
-		case 4:
-			*((U32*)datap) = *((U32*)vardata.getData());
-			break;
-		case 8:
-			((U32*)datap)[0] = ((U32*)vardata.getData())[0];
-			((U32*)datap)[1] = ((U32*)vardata.getData())[1];
-			break;
-		default:
-			memcpy(datap, vardata.getData(), vardata_size);	/* Flawfinder: ignore */
-			break;
-		}
+		return cdp->isBlocked();
 	}
 	else
 	{
-		llwarns << "Msg " << mCurrentRMessageData->mName 
-			<< " variable " << vnamep
-			<< " is size " << vardata.getSize()
-			<< " but truncated to max size of " << max_size
-			<< llendl;
-
-		memcpy(datap, vardata.getData(), max_size);	/* Flawfinder: ignore */
+		llinfos << "checkCircuitBlocked(circuit): Unknown host - " << host << llendl;
+		return FALSE;
 	}
 }
 
-S32 LLMessageSystem::getNumberOfBlocksFast(const char *blockname)
+BOOL LLMessageSystem::checkCircuitAlive(const U32 circuit)
 {
-	// is there a message ready to go?
-	if (mReceiveSize == -1)
-	{
-		llerrs << "No message waiting for decode 3!" << llendl;
-		return -1;
-	}
+	LLHost host = findHost(circuit);
 
-	if (!mCurrentRMessageData)
+	if (!host.isOk())
 	{
-		llerrs << "Invalid mCurrentRMessageData in getData!" << llendl;
-		return -1;
+		//llinfos << "checkCircuitAlive: Unknown circuit " << circuit << llendl;
+		return FALSE;
 	}
 
-	char *bnamep = (char *)blockname; 
-
-	LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
-	
-	if (iter == mCurrentRMessageData->mMemberBlocks.end())
-	{
-//		sprintf(errmsg, "Block %s not in message %s", bnamep, mCurrentRMessageData->mName);
-//		llerrs << errmsg << llendl;
-//		return -1;
-		return 0;
-	}
-
-	return (iter->second)->mBlockNumber;
-}
-
-S32 LLMessageSystem::getSizeFast(const char *blockname, const char *varname)
-{
-	// is there a message ready to go?
-	if (mReceiveSize == -1)
-	{
-		llerrs << "No message waiting for decode 4!" << llendl;
-		return -1;
-	}
-
-	if (!mCurrentRMessageData)
-	{
-		llerrs << "Invalid mCurrentRMessageData in getData!" << llendl;
-		return -1;
-	}
-
-	char *bnamep = (char *)blockname; 
-
-	LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
-	
-	if (iter == mCurrentRMessageData->mMemberBlocks.end())
-	{
-		llerrs << "Block " << bnamep << " not in message "
-			<< mCurrentRMessageData->mName << llendl;
-		return -1;
-	}
-
-	char *vnamep = (char *)varname; 
-
-	LLMsgBlkData* msg_data = iter->second;
-	LLMsgVarData& vardata = msg_data->mMemberVarData[vnamep];
-	
-	if (!vardata.getName())
-	{
-		llerrs << "Variable " << varname << " not in message "
-			<< mCurrentRMessageData->mName << " block " << bnamep << llendl;
-		return -1;
-	}
-
-	if (mCurrentRMessageTemplate->mMemberBlocks[bnamep]->mType != MBT_SINGLE)
-	{
-		llerrs << "Block " << bnamep << " isn't type MBT_SINGLE,"
-			" use getSize with blocknum argument!" << llendl;
-		return -1;
-	}
-
-	return vardata.getSize();
-}
-
-
-S32 LLMessageSystem::getSizeFast(const char *blockname, S32 blocknum, const char *varname)
-{
-	// is there a message ready to go?
-	if (mReceiveSize == -1)
-	{
-		llerrs << "No message waiting for decode 5!" << llendl;
-		return -1;
-	}
-
-	if (!mCurrentRMessageData)
-	{
-		llerrs << "Invalid mCurrentRMessageData in getData!" << llendl;
-		return -1;
-	}
-
-	char *bnamep = (char *)blockname + blocknum; 
-	char *vnamep = (char *)varname; 
-
-	LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
-	
-	if (iter == mCurrentRMessageData->mMemberBlocks.end())
-	{
-		llerrs << "Block " << bnamep << " not in message "
-			<< mCurrentRMessageData->mName << llendl;
-		return -1;
-	}
-
-	LLMsgBlkData* msg_data = iter->second;
-	LLMsgVarData& vardata = msg_data->mMemberVarData[vnamep];
-	
-	if (!vardata.getName())
-	{
-		llerrs << "Variable " << vnamep << " not in message "
-			<<  mCurrentRMessageData->mName << " block " << bnamep << llendl;
-		return -1;
-	}
-
-	return vardata.getSize();
-}
-
-
-void LLMessageSystem::sanityCheck()
-{
-	if (!mCurrentRMessageData)
-	{
-		llerrs << "mCurrentRMessageData is NULL" << llendl;
-	}
-
-	if (!mCurrentRMessageTemplate)
-	{
-		llerrs << "mCurrentRMessageTemplate is NULL" << llendl;
-	}
-
-//	if (!mCurrentRTemplateBlock)
-//	{
-//		llerrs << "mCurrentRTemplateBlock is NULL" << llendl;
-//	}
-
-//	if (!mCurrentRDataBlock)
-//	{
-//		llerrs << "mCurrentRDataBlock is NULL" << llendl;
-//	}
-
-	if (!mCurrentSMessageData)
-	{
-		llerrs << "mCurrentSMessageData is NULL" << llendl;
-	}
-
-	if (!mCurrentSMessageTemplate)
-	{
-		llerrs << "mCurrentSMessageTemplate is NULL" << llendl;
-	}
-
-//	if (!mCurrentSTemplateBlock)
-//	{
-//		llerrs << "mCurrentSTemplateBlock is NULL" << llendl;
-//	}
-
-	if (!mCurrentSDataBlock)
-	{
-		llerrs << "mCurrentSDataBlock is NULL" << llendl;
-	}
-}
-
-void LLMessageSystem::showCircuitInfo()
-{
-	llinfos << mCircuitInfo << llendl;
-}
-
-
-void LLMessageSystem::dumpCircuitInfo()
-{
-	lldebugst(LLERR_CIRCUIT_INFO) << mCircuitInfo << llendl;
-}
-
-/* virtual */
-U32 LLMessageSystem::getOurCircuitCode()
-{
-	return mOurCircuitCode;
-}
-
-LLString LLMessageSystem::getCircuitInfoString()
-{
-	LLString info_string;
-
-	info_string += mCircuitInfo.getInfoString();
-	return info_string;
-}
-
-// returns whether the given host is on a trusted circuit
-BOOL    LLMessageSystem::getCircuitTrust(const LLHost &host)
-{
-	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
-	if (cdp)
-	{
-		return cdp->getTrusted();
-	}
-
-	return FALSE;
-}
-
-// Activate a circuit, and set its trust level (TRUE if trusted,
-// FALSE if not).
-void LLMessageSystem::enableCircuit(const LLHost &host, BOOL trusted)
-{
-	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
-	if (!cdp)
-	{
-		cdp = mCircuitInfo.addCircuitData(host, 0);
-	}
-	else
-	{
-		cdp->setAlive(TRUE);
-	}
-	cdp->setTrusted(trusted);
-}
-
-void LLMessageSystem::disableCircuit(const LLHost &host)
-{
-	llinfos << "LLMessageSystem::disableCircuit for " << host << llendl;
-	U32 code = gMessageSystem->findCircuitCode( host );
-
-	// Don't need to do this, as we're removing the circuit info anyway - djs 01/28/03
-
-	// don't clean up 0 circuit code entries
-	// because many hosts (neighbor sims, etc) can have the 0 circuit
-	if (code)
-	{
-		//if (mCircuitCodes.checkKey(code))
-		code_session_map_t::iterator it = mCircuitCodes.find(code);
-		if(it != mCircuitCodes.end())
-		{
-			llinfos << "Circuit " << code << " removed from list" << llendl;
-			//mCircuitCodes.removeData(code);
-			mCircuitCodes.erase(it);
-		}
-
-		U64 ip_port = 0;
-		std::map<U32, U64>::iterator iter = gMessageSystem->mCircuitCodeToIPPort.find(code);
-		if (iter != gMessageSystem->mCircuitCodeToIPPort.end())
-		{
-			ip_port = iter->second;
-
-			gMessageSystem->mCircuitCodeToIPPort.erase(iter);
-
-			U32 old_port = (U32)(ip_port & (U64)0xFFFFFFFF);
-			U32 old_ip = (U32)(ip_port >> 32);
-
-			llinfos << "Host " << LLHost(old_ip, old_port) << " circuit " << code << " removed from lookup table" << llendl;
-			gMessageSystem->mIPPortToCircuitCode.erase(ip_port);
-		}
-	}
-	else
-	{
-		// Sigh, since we can open circuits which don't have circuit
-		// codes, it's possible for this to happen...
-		
-		//llwarns << "Couldn't find circuit code for " << host << llendl;
-	}
-
-	mCircuitInfo.removeCircuitData(host);
-}
-
-
-void LLMessageSystem::setCircuitAllowTimeout(const LLHost &host, BOOL allow)
-{
-	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
-	if (cdp)
-	{
-		cdp->setAllowTimeout(allow);
-	}
-}
-
-void LLMessageSystem::setCircuitTimeoutCallback(const LLHost &host, void (*callback_func)(const LLHost & host, void *user_data), void *user_data)
-{
-	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
-	if (cdp)
-	{
-		cdp->setTimeoutCallback(callback_func, user_data);
-	}
-}
-
-
-BOOL LLMessageSystem::checkCircuitBlocked(const U32 circuit)
-{
-	LLHost host = findHost(circuit);
-
-	if (!host.isOk())
-	{
-		//llinfos << "checkCircuitBlocked: Unknown circuit " << circuit << llendl;
-		return TRUE;
-	}
-
-	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
-	if (cdp)
-	{
-		return cdp->isBlocked();
-	}
-	else
-	{
-		llinfos << "checkCircuitBlocked(circuit): Unknown host - " << host << llendl;
-		return FALSE;
-	}
-}
-
-BOOL LLMessageSystem::checkCircuitAlive(const U32 circuit)
-{
-	LLHost host = findHost(circuit);
-
-	if (!host.isOk())
-	{
-		//llinfos << "checkCircuitAlive: Unknown circuit " << circuit << llendl;
-		return FALSE;
-	}
-
-	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
-	if (cdp)
+	LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+	if (cdp)
 	{
 		return cdp->isAlive();
 	}
@@ -4171,7 +2731,8 @@ bool LLMessageSystem::addCircuitCode(U32 code, const LLUUID& session_id)
 //}
 
 // static
-void LLMessageSystem::processUseCircuitCode(LLMessageSystem* msg, void**)
+void LLMessageSystem::processUseCircuitCode(LLMessageSystem* msg,
+											void** user)
 {
 	U32 circuit_code_in;
 	msg->getU32Fast(_PREHASH_CircuitCode, _PREHASH_Code, circuit_code_in);
@@ -4291,6 +2852,13 @@ void LLMessageSystem::processUseCircuitCode(LLMessageSystem* msg, void**)
 		llinfos << "Circuit code " << circuit_code_in << " from "
 				<< msg->getSender() << " for agent " << id << " in session "
 				<< session_id << llendl;
+
+		const LLUseCircuitCodeResponder* responder =
+			(const LLUseCircuitCodeResponder*) user;
+		if(responder)
+		{
+			responder->complete(msg->getSender(), id);
+		}
 	}
 	else
 	{
@@ -4298,16 +2866,59 @@ void LLMessageSystem::processUseCircuitCode(LLMessageSystem* msg, void**)
 	}
 }
 
+static LLHTTPNode& messageRootNode()
+{
+	static LLHTTPNode root_node;
+	static bool initialized = false;
+	if (!initialized) {
+		initialized = true;
+		LLHTTPRegistrar::buildAllServices(root_node);
+	}
 
+	return root_node;
+}
 
-static void check_for_unrecognized_messages(
-		const char* type,
-		const LLSD& map,
-		LLMessageSystem::message_template_name_map_t& templates)
+//static
+void LLMessageSystem::dispatch(const std::string& msg_name,
+								const LLSD& message)
 {
-	for (LLSD::map_const_iterator iter = map.beginMap(),
-			end = map.endMap();
-		 iter != end; ++iter)
+	LLPointer<LLSimpleResponse>	responsep =	LLSimpleResponse::create();
+	dispatch(msg_name, message, responsep);
+}
+
+//static
+void LLMessageSystem::dispatch(const std::string& msg_name,
+								const LLSD& message,
+							   LLHTTPNode::ResponsePtr responsep)
+{
+	if (msg_name.empty())
+	{
+		llwarns	<< "LLMessageService::dispatch called with no message name"
+				<< llendl;
+		return;
+	}
+	
+	std::string	path = "/message/" + msg_name;
+	LLSD context;
+	const LLHTTPNode* handler =	messageRootNode().traverse(path, context);
+	if (!handler)
+	{
+		llwarns	<< "LLMessageService::dispatch > no handler for "
+				<< path << llendl;
+		return;
+	}
+
+	handler->post(responsep, context, message);
+}
+
+static void check_for_unrecognized_messages(
+		const char* type,
+		const LLSD& map,
+		LLMessageSystem::message_template_name_map_t& templates)
+{
+	for (LLSD::map_const_iterator iter = map.beginMap(),
+			end = map.endMap();
+		 iter != end; ++iter)
 	{
 		const char* name = gMessageStringTable.getString(iter->first.c_str());
 
@@ -4613,7 +3224,8 @@ BOOL start_messaging_system(
 	S32 version_minor,
 	S32 version_patch,
 	BOOL b_dump_prehash_file,
-	const std::string& secret)
+	const std::string& secret,
+	const LLUseCircuitCodeResponder* responder)
 {
 	gMessageSystem = new LLMessageSystem(
 		template_name.c_str(),
@@ -4662,7 +3274,7 @@ BOOL start_messaging_system(
 	//gMessageSystem->setHandlerFuncFast(_PREHASH_AssignCircuitCode, LLMessageSystem::processAssignCircuitCode);	   
 	gMessageSystem->setHandlerFuncFast(_PREHASH_AddCircuitCode, LLMessageSystem::processAddCircuitCode);
 	//gMessageSystem->setHandlerFuncFast(_PREHASH_AckAddCircuitCode,		ack_add_circuit_code,		NULL);
-	gMessageSystem->setHandlerFuncFast(_PREHASH_UseCircuitCode, LLMessageSystem::processUseCircuitCode);
+	gMessageSystem->setHandlerFuncFast(_PREHASH_UseCircuitCode, LLMessageSystem::processUseCircuitCode, (void**)responder);
 	gMessageSystem->setHandlerFuncFast(_PREHASH_PacketAck,             process_packet_ack,	    NULL);
 	gMessageSystem->setHandlerFuncFast(_PREHASH_TemplateChecksumRequest,  process_template_checksum_request,	NULL);
 	gMessageSystem->setHandlerFuncFast(_PREHASH_SecuredTemplateChecksumRequest,  process_secured_template_checksum_request,	NULL);
@@ -4882,13 +3494,13 @@ void LLMessageSystem::dumpReceiveCounts()
 
 BOOL LLMessageSystem::isClear() const
 {
-	return mbSClear;
+	return mMessageBuilder->isClear();
 }
 
 
 S32 LLMessageSystem::flush(const LLHost &host)
 {
-	if (mCurrentSendTotal)
+	if (mMessageBuilder->getMessageSize())
 	{
 		S32 sentbytes = sendMessage(host);
 		clearMessage();
@@ -4905,91 +3517,22 @@ U32 LLMessageSystem::getListenPort( void ) const
 	return mPort;
 }
 
-
-S32 LLMessageSystem::zeroCode(U8 **data, S32 *data_size)
+// TODO: babbage: remove this horror!
+S32 LLMessageSystem::zeroCodeAdjustCurrentSendTotal()
 {
-	S32 count = *data_size;
-	
-	S32 net_gain = 0;
-	U8 num_zeroes = 0;
-	
-	U8 *inptr = (U8 *)*data;
-	U8 *outptr = (U8 *)mEncodedSendBuffer;
-
-// skip the packet id field
-
-	for (U32 i=0;i<LL_PACKET_ID_SIZE;i++)
-	{
-		count--;
-		*outptr++ = *inptr++;
-	}
-
-// build encoded packet, keeping track of net size gain
-
-// sequential zero bytes are encoded as 0 [U8 count] 
-// with 0 0 [count] representing wrap (>256 zeroes)
-
-	while (count--)
-	{
-		if (!(*inptr))   // in a zero count
-		{
-			if (num_zeroes)
-			{
-				if (++num_zeroes > 254)
-				{
-					*outptr++ = num_zeroes;
-					num_zeroes = 0;
-				}
-				net_gain--;   // subseqent zeroes save one
-			}
-			else
-			{
-				*outptr++ = 0;
-				net_gain++;  // starting a zero count adds one
-				num_zeroes = 1;
-			}
-			inptr++;
-		}
-		else
-		{
-			if (num_zeroes)
-			{
-				*outptr++ = num_zeroes;
-				num_zeroes = 0;
-			}
-			*outptr++ = *inptr++;
-		}
-	}
-
-	if (num_zeroes)
-	{
-		*outptr++ = num_zeroes;
-	}
-
-	if (net_gain < 0)
+	if(mMessageBuilder == mLLSDMessageBuilder)
 	{
-		mCompressedPacketsOut++;
-		mUncompressedBytesOut += *data_size;
-
-		*data = mEncodedSendBuffer;
-		*data_size += net_gain;
-		mEncodedSendBuffer[0] |= LL_ZERO_CODE_FLAG;          // set the head bit to indicate zero coding
-
-		mCompressedBytesOut += *data_size;
-
+		// babbage: don't compress LLSD messages, so delta is 0
+		return 0;
 	}
-	mTotalBytesOut += *data_size;
-
-	return(net_gain);
-}
-
-S32 LLMessageSystem::zeroCodeAdjustCurrentSendTotal()
-{
-	if (!mbSBuilt)
+	
+	if (! mMessageBuilder->isBuilt())
 	{
-		buildMessage();
+		mSendSize = mMessageBuilder->buildMessage(mSendBuffer,
+												  MAX_BUFFER_SIZE);
 	}
-	mbSBuilt = FALSE;
+	// TODO: babbage: remove this horror
+	mMessageBuilder->setBuilt(FALSE);
 
 	S32 count = mSendSize;
 	
@@ -5169,7 +3712,6 @@ void LLMessageSystem::setHandlerFuncFast(const char *name, void (*handler_func)(
 	}
 }
 
-
 bool LLMessageSystem::callHandler(const char *name,
 		bool trustedSource, LLMessageSystem* msg)
 {
@@ -5237,27 +3779,14 @@ BOOL LLMessageSystem::isCircuitCodeKnown(U32 code) const
 
 BOOL LLMessageSystem::isMessageFast(const char *msg)
 {
-	if (mCurrentRMessageTemplate)
-	{
-		return(msg == mCurrentRMessageTemplate->mName);
-	}
-	else
-	{
-		return FALSE;
-	}
+	return(msg == mMessageReader->getMessageName());
 }
 
 
 char* LLMessageSystem::getMessageName()
 {
-	if (mCurrentRMessageTemplate)
-	{
-		return mCurrentRMessageTemplate->mName;
-	}
-	else
-	{
-		return NULL;
-	}
+	const char* name = mMessageReader->getMessageName();
+	return name[0] == '\0'? NULL : const_cast<char*>(name);
 }
 
 const LLUUID& LLMessageSystem::getSenderID() const
@@ -5281,211 +3810,6 @@ const LLUUID& LLMessageSystem::getSenderSessionID() const
 	return LLUUID::null;
 }
 
-void LLMessageSystem::addVector3Fast(const char *varname, const LLVector3& vec)
-{
-	addDataFast(varname, vec.mV, MVT_LLVector3, sizeof(vec.mV));
-}
-
-void LLMessageSystem::addVector3(const char *varname, const LLVector3& vec)
-{
-	addDataFast(gMessageStringTable.getString(varname), vec.mV, MVT_LLVector3, sizeof(vec.mV));
-}
-
-void LLMessageSystem::addVector4Fast(const char *varname, const LLVector4& vec)
-{
-	addDataFast(varname, vec.mV, MVT_LLVector4, sizeof(vec.mV));
-}
-
-void LLMessageSystem::addVector4(const char *varname, const LLVector4& vec)
-{
-	addDataFast(gMessageStringTable.getString(varname), vec.mV, MVT_LLVector4, sizeof(vec.mV));
-}
-
-
-void LLMessageSystem::addVector3dFast(const char *varname, const LLVector3d& vec)
-{
-	addDataFast(varname, vec.mdV, MVT_LLVector3d, sizeof(vec.mdV));
-}
-
-void LLMessageSystem::addVector3d(const char *varname, const LLVector3d& vec)
-{
-	addDataFast(gMessageStringTable.getString(varname), vec.mdV, MVT_LLVector3d, sizeof(vec.mdV));
-}
-
-
-void LLMessageSystem::addQuatFast(const char *varname, const LLQuaternion& quat)
-{
-	addDataFast(varname, quat.packToVector3().mV, MVT_LLQuaternion, sizeof(LLVector3));
-}
-
-void LLMessageSystem::addQuat(const char *varname, const LLQuaternion& quat)
-{
-	addDataFast(gMessageStringTable.getString(varname), quat.packToVector3().mV, MVT_LLQuaternion, sizeof(LLVector3));
-}
-
-
-void LLMessageSystem::addUUIDFast(const char *varname, const LLUUID& uuid)
-{
-	addDataFast(varname, uuid.mData, MVT_LLUUID, sizeof(uuid.mData));
-}
-
-void LLMessageSystem::addUUID(const char *varname, const LLUUID& uuid)
-{
-	addDataFast(gMessageStringTable.getString(varname), uuid.mData, MVT_LLUUID, sizeof(uuid.mData));
-}
-
-void LLMessageSystem::getF32Fast(const char *block, const char *var, F32 &d, S32 blocknum)
-{
-	getDataFast(block, var, &d, sizeof(F32), blocknum);
-
-	if( !llfinite( d ) )
-	{
-		llwarns << "non-finite in getF32Fast " << block << " " << var << llendl;
-		d = 0;
-	}
-}
-
-void LLMessageSystem::getF32(const char *block, const char *var, F32 &d, S32 blocknum)
-{
-	getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(F32), blocknum);
-
-	if( !llfinite( d ) )
-	{
-		llwarns << "non-finite in getF32 " << block << " " << var << llendl;
-		d = 0;
-	}
-}
-
-void LLMessageSystem::getF64Fast(const char *block, const char *var, F64 &d, S32 blocknum)
-{
-	getDataFast(block, var, &d, sizeof(F64), blocknum);
-
-	if( !llfinite( d ) )
-	{
-		llwarns << "non-finite in getF64Fast " << block << " " << var << llendl;
-		d = 0;
-	}
-}
-
-void LLMessageSystem::getF64(const char *block, const char *var, F64 &d, S32 blocknum)
-{
-	getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(F64), blocknum);
-
-	if( !llfinite( d ) )
-	{
-		llwarns << "non-finite in getF64 " << block << " " << var << llendl;
-		d = 0;
-	}
-}
-
-
-void LLMessageSystem::getVector3Fast(const char *block, const char *var, LLVector3 &v, S32 blocknum )
-{
-	getDataFast(block, var, v.mV, sizeof(v.mV), blocknum);
-
-	if( !v.isFinite() )
-	{
-		llwarns << "non-finite in getVector3Fast " << block << " " << var << llendl;
-		v.zeroVec();
-	}
-}
-
-void LLMessageSystem::getVector3(const char *block, const char *var, LLVector3 &v, S32 blocknum )
-{
-	getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), v.mV, sizeof(v.mV), blocknum);
-
-	if( !v.isFinite() )
-	{
-		llwarns << "non-finite in getVector4 " << block << " " << var << llendl;
-		v.zeroVec();
-	}
-}
-
-void LLMessageSystem::getVector4Fast(const char *block, const char *var, LLVector4 &v, S32 blocknum )
-{
-	getDataFast(block, var, v.mV, sizeof(v.mV), blocknum);
-
-	if( !v.isFinite() )
-	{
-		llwarns << "non-finite in getVector4Fast " << block << " " << var << llendl;
-		v.zeroVec();
-	}
-}
-
-void LLMessageSystem::getVector4(const char *block, const char *var, LLVector4 &v, S32 blocknum )
-{
-	getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), v.mV, sizeof(v.mV), blocknum);
-
-	if( !v.isFinite() )
-	{
-		llwarns << "non-finite in getVector3 " << block << " " << var << llendl;
-		v.zeroVec();
-	}
-}
-
-void LLMessageSystem::getVector3dFast(const char *block, const char *var, LLVector3d &v, S32 blocknum )
-{
-	getDataFast(block, var, v.mdV, sizeof(v.mdV), blocknum);
-
-	if( !v.isFinite() )
-	{
-		llwarns << "non-finite in getVector3dFast " << block << " " << var << llendl;
-		v.zeroVec();
-	}
-
-}
-
-void LLMessageSystem::getVector3d(const char *block, const char *var, LLVector3d &v, S32 blocknum )
-{
-	getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), v.mdV, sizeof(v.mdV), blocknum);
-
-	if( !v.isFinite() )
-	{
-		llwarns << "non-finite in getVector3d " << block << " " << var << llendl;
-		v.zeroVec();
-	}
-}
-
-void LLMessageSystem::getQuatFast(const char *block, const char *var, LLQuaternion &q, S32 blocknum )
-{
-	LLVector3 vec;
-	getDataFast(block, var, vec.mV, sizeof(vec.mV), blocknum);
-	if( vec.isFinite() )
-	{
-		q.unpackFromVector3( vec );
-	}
-	else
-	{
-		llwarns << "non-finite in getQuatFast " << block << " " << var << llendl;
-		q.loadIdentity();
-	}
-}
-
-void LLMessageSystem::getQuat(const char *block, const char *var, LLQuaternion &q, S32 blocknum )
-{
-	LLVector3 vec;
-	getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), vec.mV, sizeof(vec.mV), blocknum);
-	if( vec.isFinite() )
-	{
-		q.unpackFromVector3( vec );
-	}
-	else
-	{
-		llwarns << "non-finite in getQuat " << block << " " << var << llendl;
-		q.loadIdentity();
-	}
-}
-
-void LLMessageSystem::getUUIDFast(const char *block, const char *var, LLUUID &u, S32 blocknum )
-{
-	getDataFast(block, var, u.mData, sizeof(u.mData), blocknum);
-}
-
-void LLMessageSystem::getUUID(const char *block, const char *var, LLUUID &u, S32 blocknum )
-{
-	getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), u.mData, sizeof(u.mData), blocknum);
-}
-
 bool LLMessageSystem::generateDigestForNumberAndUUIDs(
 	char* digest,
 	const U32 number,
@@ -5790,47 +4114,717 @@ void LLMessageSystem::dumpPacketToLog()
 }
 
 //static
-U64 LLMessageSystem::getMessageTimeUsecs(const BOOL update)
+BOOL LLMessageSystem::isTemplateConfirmed()
 {
-	if (gMessageSystem)
-	{
-		if (update)
-		{
-			gMessageSystem->mCurrentMessageTimeSeconds = totalTime()*SEC_PER_USEC;
-		}
-		return (U64)(gMessageSystem->mCurrentMessageTimeSeconds * USEC_PER_SEC);
-	}
-	else
-	{
-		return totalTime();
-	}
+	return gMessageSystem->mTemplateConfirmed;
 }
 
 //static
-F64 LLMessageSystem::getMessageTimeSeconds(const BOOL update)
+BOOL LLMessageSystem::doesTemplateMatch()
 {
-	if (gMessageSystem)
-	{
-		if (update)
-		{
-			gMessageSystem->mCurrentMessageTimeSeconds = totalTime()*SEC_PER_USEC;
-		}
-		return gMessageSystem->mCurrentMessageTimeSeconds;
-	}
-	else
+	if (!isTemplateConfirmed())
 	{
-		return totalTime()*SEC_PER_USEC;
+		return FALSE;
 	}
+	return gMessageSystem->mTemplateMatches;
 }
 
-std::string get_shared_secret()
+//static
+void LLMessageSystem::sendMessageTemplateChecksum(const LLHost &currentHost)
 {
-	static const std::string SHARED_SECRET_KEY("shared_secret");
-	if(g_shared_secret.empty())
+	gMessageSystem->mTemplateConfirmed = FALSE;
+	gMessageSystem->mTemplateMatches = FALSE;
+	gMessageSystem->newMessageFast(_PREHASH_TemplateChecksumRequest);
+	// Don't use ping-based retry
+	gMessageSystem->sendReliable(currentHost, 40, FALSE, 3, NULL, NULL);
+}
+
+//static
+void LLMessageSystem::processMessageTemplateChecksumReply(LLMessageSystem *msg,
+														  void** user_data)
+{
+	U32 remote_template_checksum = 0;
+	msg->getU32Fast(_PREHASH_DataBlock, _PREHASH_Checksum, remote_template_checksum);	
+	msg->mTemplateConfirmed = TRUE;
+	if ((remote_template_checksum) != msg->mMessageFileChecksum)
 	{
-		LLApp* app = LLApp::instance();
-		if(app) return app->getOption(SHARED_SECRET_KEY);
+		llwarns << "out of sync message template!" << llendl;
+		
+		msg->mTemplateMatches = FALSE;
+		msg->newMessageFast(_PREHASH_CloseCircuit);
+		msg->sendMessage(msg->getSender());
+		return;
 	}
-	return g_shared_secret;
+
+	msg->mTemplateMatches = TRUE;
+	llinfos << "According to " << msg->getSender()
+			<< " the message template is current!"
+			<< llendl;
 }
 
+//static
+void LLMessageSystem::sendSecureMessageTemplateChecksum(const LLHost& host)
+{
+	// generate an token for use during template checksum requests to
+	// prevent DOS attacks from injected bad template checksum replies.
+	LLUUID *template_tokenp = new LLUUID;
+	template_tokenp->generate();
+	lldebugs << "random token: " << *template_tokenp << llendl;
+
+	// register the handler for the reply while saving off template_token
+	gMessageSystem->setHandlerFuncFast(_PREHASH_TemplateChecksumReply,
+							LLMessageSystem::processSecureTemplateChecksumReply,
+							(void**)template_tokenp);
+
+	// send checksum request
+	gMessageSystem->mTemplateConfirmed = FALSE;
+	gMessageSystem->newMessageFast(_PREHASH_SecuredTemplateChecksumRequest);
+	gMessageSystem->nextBlockFast(_PREHASH_TokenBlock);
+	gMessageSystem->addUUIDFast(_PREHASH_Token, *template_tokenp);
+	gMessageSystem->sendReliable(host);
+}
+
+//static
+void LLMessageSystem::processSecureTemplateChecksumReply(LLMessageSystem *msg,
+														 void** user_data)
+{
+	// copy the token out into the stack and delete allocated memory
+	LLUUID template_token = *((LLUUID*)user_data);
+	delete user_data;
+
+	LLUUID received_token;
+	msg->getUUID("TokenBlock", "Token", received_token);
+
+	if(received_token != template_token)
+	{
+		llwarns << "Incorrect token in template checksum reply: "
+				<< received_token << llendl;
+		//return do_normal_idle;
+		return;
+	}
+
+	U32 remote_template_checksum = 0;
+	U8 major_version = 0;
+	U8 minor_version = 0;
+	U8 patch_version = 0;
+	U8 server_version = 0;
+	U32 flags = 0x0;
+	msg->getU32("DataBlock", "Checksum", remote_template_checksum);
+	msg->getU8 ("DataBlock", "MajorVersion", major_version);
+	msg->getU8 ("DataBlock", "MinorVersion", minor_version);
+	msg->getU8 ("DataBlock", "PatchVersion", patch_version);
+	msg->getU8 ("DataBlock", "ServerVersion", server_version);
+	msg->getU32("DataBlock", "Flags", flags);
+
+	msg->mTemplateConfirmed = TRUE;
+	if (remote_template_checksum != gMessageSystem->mMessageFileChecksum)
+	{
+		llinfos << "Message template out of sync" << llendl;
+		msg->mTemplateMatches = FALSE;
+	}
+	else
+	{
+		msg->mTemplateMatches = TRUE;
+	}
+}
+
+//static
+U64 LLMessageSystem::getMessageTimeUsecs(const BOOL update)
+{
+	if (gMessageSystem)
+	{
+		if (update)
+		{
+			gMessageSystem->mCurrentMessageTimeSeconds = totalTime()*SEC_PER_USEC;
+		}
+		return (U64)(gMessageSystem->mCurrentMessageTimeSeconds * USEC_PER_SEC);
+	}
+	else
+	{
+		return totalTime();
+	}
+}
+
+//static
+F64 LLMessageSystem::getMessageTimeSeconds(const BOOL update)
+{
+	if (gMessageSystem)
+	{
+		if (update)
+		{
+			gMessageSystem->mCurrentMessageTimeSeconds = totalTime()*SEC_PER_USEC;
+		}
+		return gMessageSystem->mCurrentMessageTimeSeconds;
+	}
+	else
+	{
+		return totalTime()*SEC_PER_USEC;
+	}
+}
+
+std::string get_shared_secret()
+{
+	static const std::string SHARED_SECRET_KEY("shared_secret");
+	if(g_shared_secret.empty())
+	{
+		LLApp* app = LLApp::instance();
+		if(app) return app->getOption(SHARED_SECRET_KEY);
+	}
+	return g_shared_secret;
+}
+
+typedef std::map<const char*, LLMessageBuilder*> BuilderMap;
+
+static void setBuilder(BuilderMap& map, const char* name, LLMessageBuilder* builder)
+{
+	map[gMessageStringTable.getString(name)] = builder;
+}
+
+void LLMessageSystem::newMessageFast(const char *name)
+{
+	if(LLMessageConfig::isMessageBuiltTemplate(name))
+	{
+		mMessageBuilder = mTemplateMessageBuilder;
+	}
+	else
+	{
+		mMessageBuilder = mLLSDMessageBuilder;
+	}
+	mSendReliable = FALSE;
+	mMessageBuilder->newMessage(name);
+}
+	
+void LLMessageSystem::newMessage(const char *name)
+{
+	newMessageFast(gMessageStringTable.getString(name));
+}
+
+void LLMessageSystem::addBinaryDataFast(const char *varname, const void *data, S32 size)
+{
+	mMessageBuilder->addBinaryData(varname, data, size);
+}
+
+void LLMessageSystem::addBinaryData(const char *varname, const void *data, S32 size)
+{
+	mMessageBuilder->addBinaryData(gMessageStringTable.getString(varname),data, size);
+}
+
+void LLMessageSystem::addS8Fast(const char *varname, S8 v)
+{
+	mMessageBuilder->addS8(varname, v);
+}
+
+void LLMessageSystem::addS8(const char *varname, S8 v)
+{
+	mMessageBuilder->addS8(gMessageStringTable.getString(varname), v);
+}
+
+void LLMessageSystem::addU8Fast(const char *varname, U8 v)
+{
+	mMessageBuilder->addU8(varname, v);
+}
+
+void LLMessageSystem::addU8(const char *varname, U8 v)
+{
+	mMessageBuilder->addU8(gMessageStringTable.getString(varname), v);
+}
+
+void LLMessageSystem::addS16Fast(const char *varname, S16 v)
+{
+	mMessageBuilder->addS16(varname, v);
+}
+
+void LLMessageSystem::addS16(const char *varname, S16 v)
+{
+	mMessageBuilder->addS16(gMessageStringTable.getString(varname), v);
+}
+
+void LLMessageSystem::addU16Fast(const char *varname, U16 v)
+{
+	mMessageBuilder->addU16(varname, v);
+}
+
+void LLMessageSystem::addU16(const char *varname, U16 v)
+{
+	mMessageBuilder->addU16(gMessageStringTable.getString(varname), v);
+}
+
+void LLMessageSystem::addF32Fast(const char *varname, F32 v)
+{
+	mMessageBuilder->addF32(varname, v);
+}
+
+void LLMessageSystem::addF32(const char *varname, F32 v)
+{
+	mMessageBuilder->addF32(gMessageStringTable.getString(varname), v);
+}
+
+void LLMessageSystem::addS32Fast(const char *varname, S32 v)
+{
+	mMessageBuilder->addS32(varname, v);
+}
+
+void LLMessageSystem::addS32(const char *varname, S32 v)
+{
+	mMessageBuilder->addS32(gMessageStringTable.getString(varname), v);
+}
+
+void LLMessageSystem::addU32Fast(const char *varname, U32 v)
+{
+	mMessageBuilder->addU32(varname, v);
+}
+
+void LLMessageSystem::addU32(const char *varname, U32 v)
+{
+	mMessageBuilder->addU32(gMessageStringTable.getString(varname), v);
+}
+
+void LLMessageSystem::addU64Fast(const char *varname, U64 v)
+{
+	mMessageBuilder->addU64(varname, v);
+}
+
+void LLMessageSystem::addU64(const char *varname, U64 v)
+{
+	mMessageBuilder->addU64(gMessageStringTable.getString(varname), v);
+}
+
+void LLMessageSystem::addF64Fast(const char *varname, F64 v)
+{
+	mMessageBuilder->addF64(varname, v);
+}
+
+void LLMessageSystem::addF64(const char *varname, F64 v)
+{
+	mMessageBuilder->addF64(gMessageStringTable.getString(varname), v);
+}
+
+void LLMessageSystem::addIPAddrFast(const char *varname, U32 v)
+{
+	mMessageBuilder->addIPAddr(varname, v);
+}
+
+void LLMessageSystem::addIPAddr(const char *varname, U32 v)
+{
+	mMessageBuilder->addIPAddr(gMessageStringTable.getString(varname), v);
+}
+
+void LLMessageSystem::addIPPortFast(const char *varname, U16 v)
+{
+	mMessageBuilder->addIPPort(varname, v);
+}
+
+void LLMessageSystem::addIPPort(const char *varname, U16 v)
+{
+	mMessageBuilder->addIPPort(gMessageStringTable.getString(varname), v);
+}
+
+void LLMessageSystem::addBOOLFast(const char* varname, BOOL v)
+{
+	mMessageBuilder->addBOOL(varname, v);
+}
+
+void LLMessageSystem::addBOOL(const char* varname, BOOL v)
+{
+	mMessageBuilder->addBOOL(gMessageStringTable.getString(varname), v);
+}
+
+void LLMessageSystem::addStringFast(const char* varname, const char* v)
+{
+	mMessageBuilder->addString(varname, v);
+}
+
+void LLMessageSystem::addString(const char* varname, const char* v)
+{
+	mMessageBuilder->addString(gMessageStringTable.getString(varname), v);
+}
+
+void LLMessageSystem::addStringFast(const char* varname, const std::string& v)
+{
+	mMessageBuilder->addString(varname, v);
+}
+
+void LLMessageSystem::addString(const char* varname, const std::string& v)
+{
+	mMessageBuilder->addString(gMessageStringTable.getString(varname), v);
+}
+
+void LLMessageSystem::addVector3Fast(const char *varname, const LLVector3& v)
+{
+	mMessageBuilder->addVector3(varname, v);
+}
+
+void LLMessageSystem::addVector3(const char *varname, const LLVector3& v)
+{
+	mMessageBuilder->addVector3(gMessageStringTable.getString(varname), v);
+}
+
+void LLMessageSystem::addVector4Fast(const char *varname, const LLVector4& v)
+{
+	mMessageBuilder->addVector4(varname, v);
+}
+
+void LLMessageSystem::addVector4(const char *varname, const LLVector4& v)
+{
+	mMessageBuilder->addVector4(gMessageStringTable.getString(varname), v);
+}
+
+void LLMessageSystem::addVector3dFast(const char *varname, const LLVector3d& v)
+{
+	mMessageBuilder->addVector3d(varname, v);
+}
+
+void LLMessageSystem::addVector3d(const char *varname, const LLVector3d& v)
+{
+	mMessageBuilder->addVector3d(gMessageStringTable.getString(varname), v);
+}
+
+void LLMessageSystem::addQuatFast(const char *varname, const LLQuaternion& v)
+{
+	mMessageBuilder->addQuat(varname, v);
+}
+
+void LLMessageSystem::addQuat(const char *varname, const LLQuaternion& v)
+{
+	mMessageBuilder->addQuat(gMessageStringTable.getString(varname), v);
+}
+
+
+void LLMessageSystem::addUUIDFast(const char *varname, const LLUUID& v)
+{
+	mMessageBuilder->addUUID(varname, v);
+}
+
+void LLMessageSystem::addUUID(const char *varname, const LLUUID& v)
+{
+	mMessageBuilder->addUUID(gMessageStringTable.getString(varname), v);
+}
+
+S32 LLMessageSystem::getCurrentSendTotal() const
+{
+	return mMessageBuilder->getMessageSize();
+}
+
+void LLMessageSystem::getS8Fast(const char *block, const char *var, S8 &u, 
+								S32 blocknum)
+{
+	mMessageReader->getS8(block, var, u, blocknum);
+}
+
+void LLMessageSystem::getS8(const char *block, const char *var, S8 &u, 
+							S32 blocknum)
+{
+	getS8Fast(gMessageStringTable.getString(block), 
+			  gMessageStringTable.getString(var), u, blocknum);
+}
+
+void LLMessageSystem::getU8Fast(const char *block, const char *var, U8 &u, 
+								S32 blocknum)
+{
+	mMessageReader->getU8(block, var, u, blocknum);
+}
+
+void LLMessageSystem::getU8(const char *block, const char *var, U8 &u, 
+							S32 blocknum)
+{
+	getU8Fast(gMessageStringTable.getString(block), 
+				gMessageStringTable.getString(var), u, blocknum);
+}
+
+void LLMessageSystem::getBOOLFast(const char *block, const char *var, BOOL &b,
+								  S32 blocknum)
+{
+	mMessageReader->getBOOL(block, var, b, blocknum);
+}
+
+void LLMessageSystem::getBOOL(const char *block, const char *var, BOOL &b, 
+							  S32 blocknum)
+{
+	getBOOLFast(gMessageStringTable.getString(block), 
+				gMessageStringTable.getString(var), b, blocknum);
+}
+
+void LLMessageSystem::getS16Fast(const char *block, const char *var, S16 &d, 
+								 S32 blocknum)
+{
+	mMessageReader->getS16(block, var, d, blocknum);
+}
+
+void LLMessageSystem::getS16(const char *block, const char *var, S16 &d, 
+							 S32 blocknum)
+{
+	getS16Fast(gMessageStringTable.getString(block), 
+			   gMessageStringTable.getString(var), d, blocknum);
+}
+
+void LLMessageSystem::getU16Fast(const char *block, const char *var, U16 &d, 
+								 S32 blocknum)
+{
+	mMessageReader->getU16(block, var, d, blocknum);
+}
+
+void LLMessageSystem::getU16(const char *block, const char *var, U16 &d, 
+							 S32 blocknum)
+{
+	getU16Fast(gMessageStringTable.getString(block), 
+			   gMessageStringTable.getString(var), d, blocknum);
+}
+
+void LLMessageSystem::getS32Fast(const char *block, const char *var, S32 &d, 
+								 S32 blocknum)
+{
+	mMessageReader->getS32(block, var, d, blocknum);
+}
+
+void LLMessageSystem::getS32(const char *block, const char *var, S32 &d, 
+							 S32 blocknum)
+{
+	getS32Fast(gMessageStringTable.getString(block), 
+			   gMessageStringTable.getString(var), d, blocknum);
+}
+
+void LLMessageSystem::getU32Fast(const char *block, const char *var, U32 &d, 
+								 S32 blocknum)
+{
+	mMessageReader->getU32(block, var, d, blocknum);
+}
+
+void LLMessageSystem::getU32(const char *block, const char *var, U32 &d, 
+							 S32 blocknum)
+{
+	getU32Fast(gMessageStringTable.getString(block), 
+				gMessageStringTable.getString(var), d, blocknum);
+}
+
+void LLMessageSystem::getU64Fast(const char *block, const char *var, U64 &d, 
+								 S32 blocknum)
+{
+	mMessageReader->getU64(block, var, d, blocknum);
+}
+
+void LLMessageSystem::getU64(const char *block, const char *var, U64 &d, 
+							 S32 blocknum)
+{
+	
+	getU64Fast(gMessageStringTable.getString(block), 
+			   gMessageStringTable.getString(var), d, blocknum);
+}
+
+void LLMessageSystem::getBinaryDataFast(const char *blockname, 
+										const char *varname, 
+										void *datap, S32 size, 
+										S32 blocknum, S32 max_size)
+{
+	mMessageReader->getBinaryData(blockname, varname, datap, size, blocknum, 
+								  max_size);
+}
+
+void LLMessageSystem::getBinaryData(const char *blockname, 
+									const char *varname, 
+									void *datap, S32 size, 
+									S32 blocknum, S32 max_size)
+{
+	getBinaryDataFast(gMessageStringTable.getString(blockname), 
+					  gMessageStringTable.getString(varname), 
+					  datap, size, blocknum, max_size);
+}
+
+void LLMessageSystem::getF32Fast(const char *block, const char *var, F32 &d, 
+								 S32 blocknum)
+{
+	mMessageReader->getF32(block, var, d, blocknum);
+}
+
+void LLMessageSystem::getF32(const char *block, const char *var, F32 &d, 
+							 S32 blocknum)
+{
+	getF32Fast(gMessageStringTable.getString(block), 
+			   gMessageStringTable.getString(var), d, blocknum);
+}
+
+void LLMessageSystem::getF64Fast(const char *block, const char *var, F64 &d, 
+								 S32 blocknum)
+{
+	mMessageReader->getF64(block, var, d, blocknum);
+}
+
+void LLMessageSystem::getF64(const char *block, const char *var, F64 &d, 
+							 S32 blocknum)
+{
+	getF64Fast(gMessageStringTable.getString(block), 
+				gMessageStringTable.getString(var), d, blocknum);
+}
+
+
+void LLMessageSystem::getVector3Fast(const char *block, const char *var, 
+									 LLVector3 &v, S32 blocknum )
+{
+	mMessageReader->getVector3(block, var, v, blocknum);
+}
+
+void LLMessageSystem::getVector3(const char *block, const char *var, 
+								 LLVector3 &v, S32 blocknum )
+{
+	getVector3Fast(gMessageStringTable.getString(block), 
+				   gMessageStringTable.getString(var), v, blocknum);
+}
+
+void LLMessageSystem::getVector4Fast(const char *block, const char *var, 
+									 LLVector4 &v, S32 blocknum )
+{
+	mMessageReader->getVector4(block, var, v, blocknum);
+}
+
+void LLMessageSystem::getVector4(const char *block, const char *var, 
+								 LLVector4 &v, S32 blocknum )
+{
+	getVector4Fast(gMessageStringTable.getString(block), 
+				   gMessageStringTable.getString(var), v, blocknum);
+}
+
+void LLMessageSystem::getVector3dFast(const char *block, const char *var, 
+									  LLVector3d &v, S32 blocknum )
+{
+	mMessageReader->getVector3d(block, var, v, blocknum);
+}
+
+void LLMessageSystem::getVector3d(const char *block, const char *var, 
+								  LLVector3d &v, S32 blocknum )
+{
+	getVector3dFast(gMessageStringTable.getString(block), 
+				gMessageStringTable.getString(var), v, blocknum);
+}
+
+void LLMessageSystem::getQuatFast(const char *block, const char *var, 
+								  LLQuaternion &q, S32 blocknum )
+{
+	mMessageReader->getQuat(block, var, q, blocknum);
+}
+
+void LLMessageSystem::getQuat(const char *block, const char *var, 
+							  LLQuaternion &q, S32 blocknum)
+{
+	getQuatFast(gMessageStringTable.getString(block), 
+			gMessageStringTable.getString(var), q, blocknum);
+}
+
+void LLMessageSystem::getUUIDFast(const char *block, const char *var, 
+								  LLUUID &u, S32 blocknum )
+{
+	mMessageReader->getUUID(block, var, u, blocknum);
+}
+
+void LLMessageSystem::getUUID(const char *block, const char *var, LLUUID &u, 
+							  S32 blocknum )
+{
+	getUUIDFast(gMessageStringTable.getString(block), 
+				gMessageStringTable.getString(var), u, blocknum);
+}
+
+void LLMessageSystem::getIPAddrFast(const char *block, const char *var, 
+									U32 &u, S32 blocknum)
+{
+	mMessageReader->getIPAddr(block, var, u, blocknum);
+}
+
+void LLMessageSystem::getIPAddr(const char *block, const char *var, U32 &u, 
+								S32 blocknum)
+{
+	getIPAddrFast(gMessageStringTable.getString(block), 
+				  gMessageStringTable.getString(var), u, blocknum);
+}
+
+void LLMessageSystem::getIPPortFast(const char *block, const char *var, 
+									U16 &u, S32 blocknum)
+{
+	mMessageReader->getIPPort(block, var, u, blocknum);
+}
+
+void LLMessageSystem::getIPPort(const char *block, const char *var, U16 &u, 
+								S32 blocknum)
+{
+	getIPPortFast(gMessageStringTable.getString(block), 
+				  gMessageStringTable.getString(var), u, 
+				  blocknum);
+}
+
+
+void LLMessageSystem::getStringFast(const char *block, const char *var, 
+									S32 buffer_size, char *s, S32 blocknum)
+{
+	mMessageReader->getString(block, var, buffer_size, s, blocknum);
+}
+
+void LLMessageSystem::getString(const char *block, const char *var, 
+								S32 buffer_size, char *s, S32 blocknum )
+{
+	getStringFast(gMessageStringTable.getString(block), 
+				  gMessageStringTable.getString(var), buffer_size, s, 
+				  blocknum);
+}
+
+S32	LLMessageSystem::getNumberOfBlocksFast(const char *blockname)
+{
+	return mMessageReader->getNumberOfBlocks(blockname);
+}
+
+S32	LLMessageSystem::getNumberOfBlocks(const char *blockname)
+{
+	return getNumberOfBlocksFast(gMessageStringTable.getString(blockname));
+}
+	
+S32	LLMessageSystem::getSizeFast(const char *blockname, const char *varname)
+{
+	return mMessageReader->getSize(blockname, varname);
+}
+
+S32	LLMessageSystem::getSize(const char *blockname, const char *varname)
+{
+	return getSizeFast(gMessageStringTable.getString(blockname), 
+					   gMessageStringTable.getString(varname));
+}
+	
+// size in bytes of variable length data
+S32	LLMessageSystem::getSizeFast(const char *blockname, S32 blocknum, 
+								 const char *varname)
+{
+	return mMessageReader->getSize(blockname, blocknum, varname);
+}
+		
+S32	LLMessageSystem::getSize(const char *blockname, S32 blocknum, 
+							 const char *varname)
+{
+	return getSizeFast(gMessageStringTable.getString(blockname), blocknum, 
+					   gMessageStringTable.getString(varname));
+}
+
+S32 LLMessageSystem::getReceiveSize() const
+{
+	return mMessageReader->getMessageSize();
+}
+
+//static 
+void LLMessageSystem::setTimeDecodes( BOOL b )
+{
+	LLMessageReader::setTimeDecodes(b);
+}
+		
+//static 
+void LLMessageSystem::setTimeDecodesSpamThreshold( F32 seconds )
+{ 
+	LLMessageReader::setTimeDecodesSpamThreshold(seconds);
+}
+
+// HACK! babbage: return true if message rxed via either UDP or HTTP
+// TODO: babbage: move gServicePump in to LLMessageSystem?
+bool LLMessageSystem::checkAllMessages(S64 frame_count, LLPumpIO* http_pump)
+{
+	if(checkMessages(frame_count))
+	{
+		return true;
+	}
+	U32 packetsIn = mPacketsIn;
+	http_pump->pump();
+	http_pump->callback();
+	return (mPacketsIn - packetsIn) > 0;
+}
diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h
index 3ffafcc1b8..a4a8022631 100644
--- a/indra/llmessage/message.h
+++ b/indra/llmessage/message.h
@@ -1,5 +1,5 @@
 /** 
- * @file message.h
+ * @FILE message.h
  * @brief LLMessageSystem class header file
  *
  * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc.
@@ -30,9 +30,11 @@
 #include "lltimer.h"
 #include "llpacketring.h"
 #include "llhost.h"
+#include "llhttpnode.h"
 #include "llpacketack.h"
 #include "message_prehash.h"
 #include "llstl.h"
+#include "llmsgvariabletype.h"
 
 const U32 MESSAGE_MAX_STRINGS_LENGTH = 64;
 const U32 MESSAGE_NUMBER_OF_HASH_BUCKETS = 8192;
@@ -131,39 +133,10 @@ class LLQuaternion;
 class LLSD;
 class LLUUID;
 class LLMessageSystem;
+class LLPumpIO;
 
 // message data pieces are used to collect the data called for by the message template
 
-// iterator typedefs precede each class as needed
-typedef enum e_message_variable_type
-{
-	MVT_NULL,
-	MVT_FIXED,
-	MVT_VARIABLE,
-	MVT_U8,
-	MVT_U16,
-	MVT_U32,
-	MVT_U64,
-	MVT_S8,
-	MVT_S16,
-	MVT_S32,
-	MVT_S64,
-	MVT_F32,
-	MVT_F64,
-	MVT_LLVector3,
-	MVT_LLVector3d,
-	MVT_LLVector4,
-	MVT_LLQuaternion,
-	MVT_LLUUID,	
-	MVT_BOOL,
-	MVT_IP_ADDR,
-	MVT_IP_PORT,
-	MVT_U16Vec3,
-	MVT_U16Quat,
-	MVT_S16Array,
-	MVT_EOL
-} EMsgVariableType;
-
 // message system exceptional condition handlers.
 enum EMessageException
 {
@@ -180,19 +153,29 @@ class LLMsgBlkData;
 class LLMessageTemplate;
 
 class LLMessagePollInfo;
+class LLMessageBuilder;
+class LLTemplateMessageBuilder;
+class LLSDMessageBuilder;
+class LLMessageReader;
+class LLTemplateMessageReader;
+class LLSDMessageReader;
 
-class LLMessageSystem
+class LLUseCircuitCodeResponder
 {
 	LOG_CLASS(LLMessageSystem);
 	
 public:
+	virtual ~LLUseCircuitCodeResponder();
+	virtual void complete(const LLHost& host, const LLUUID& agent) const = 0;
+};
+
+class LLMessageSystem
+{
+ private:
 	U8										mSendBuffer[MAX_BUFFER_SIZE];
-	// Encoded send buffer needs to be slightly larger since the zero
-	// coding can potentially increase the size of the send data.
-	U8										mEncodedSendBuffer[2 * MAX_BUFFER_SIZE];
 	S32										mSendSize;
-	S32										mCurrentSendTotal;
 
+ public:
 	LLPacketRing							mPacketRing;
 	LLReliablePacketParams					mReliablePacketParams;
 
@@ -271,12 +254,7 @@ public:
 	LLMessageSystem(const char *filename, U32 port, S32 version_major,
 		S32 version_minor, S32 version_patch);
 
-public:
-	// Subclass use.
-	LLMessageSystem();
-
-public:
-	virtual ~LLMessageSystem();
+	~LLMessageSystem();
 
 	BOOL isOK() const { return !mbError; }
 	S32 getErrorCode() const { return mErrorCode; }
@@ -294,9 +272,6 @@ public:
 		setHandlerFuncFast(gMessageStringTable.getString(name), handler_func, user_data);
 	}
 
-	bool callHandler(const char *name, bool trustedSource,
-							LLMessageSystem* msg);
-
 	// Set a callback function for a message system exception.
 	void setExceptionFunc(EMessageException exception, msg_exception_callback func, void* data = NULL);
 	// Call the specified exception func, and return TRUE if a
@@ -308,6 +283,14 @@ public:
 	// measured in seconds.  JC
 	typedef void (*msg_timing_callback)(const char* hashed_name, F32 time, void* data);
 	void setTimingFunc(msg_timing_callback func, void* data = NULL);
+	msg_timing_callback getTimingCallback() 
+	{ 
+		return mTimingCallback; 
+	}
+	void* getTimingCallbackData() 
+	{
+		return mTimingCallbackData;
+	}
 
 	// This method returns true if the code is in the circuit codes map.
 	BOOL isCircuitCodeKnown(U32 code) const;
@@ -347,42 +330,21 @@ public:
 	void setMySessionID(const LLUUID& session_id) { mSessionID = session_id; }
 	const LLUUID& getMySessionID() { return mSessionID; }
 
-	virtual void newMessageFast(const char *name);
-	void	newMessage(const char *name)
-	{
-		newMessageFast(gMessageStringTable.getString(name));
-	}
+	void newMessageFast(const char *name);
+	void newMessage(const char *name);
 
 	void	copyMessageRtoS();
 	void	clearMessage();
 
-	virtual void nextBlockFast(const char *blockname);
+	void nextBlockFast(const char *blockname);
 	void	nextBlock(const char *blockname)
 	{
 		nextBlockFast(gMessageStringTable.getString(blockname));
 	}
-private:
-	void	addDataFast(const char *varname, const void *data, EMsgVariableType type, S32 size);	// Use only for types not in system already
-	void	addData(const char *varname, const void *data, EMsgVariableType type, S32 size)
-	{
-		addDataFast(gMessageStringTable.getString(varname), data, type, size);
-	}
 
-	
-	void	addDataFast(const char *varname, const void *data, EMsgVariableType type);				// DEPRECATED - not typed, doesn't check storage space
-	void	addData(const char *varname, const void *data, EMsgVariableType type)
-	{
-		addDataFast(gMessageStringTable.getString(varname), data, type);
-	}
 public:
-	void	addBinaryDataFast(const char *varname, const void *data, S32 size)
-	{
-		addDataFast(varname, data, MVT_FIXED, size);
-	}
-	void	addBinaryData(const char *varname, const void *data, S32 size)
-	{
-		addDataFast(gMessageStringTable.getString(varname), data, MVT_FIXED, size);
-	}
+	void addBinaryDataFast(const char *varname, const void *data, S32 size);
+	void addBinaryData(const char *varname, const void *data, S32 size);
 
 	void	addBOOLFast( const char* varname, BOOL b);						// typed, checks storage space
 	void	addBOOL( const char* varname, BOOL b);						// typed, checks storage space
@@ -398,7 +360,7 @@ public:
 	void	addF32(	const char *varname, F32 f);						// typed, checks storage space
 	void	addS32Fast(	const char *varname, S32 s);						// typed, checks storage space
 	void	addS32(	const char *varname, S32 s);						// typed, checks storage space
-	virtual void addU32Fast(	const char *varname, U32 u);						// typed, checks storage space
+	void addU32Fast(	const char *varname, U32 u);						// typed, checks storage space
 	void	addU32(	const char *varname, U32 u);						// typed, checks storage space
 	void	addU64Fast(	const char *varname, U64 lu);						// typed, checks storage space
 	void	addU64(	const char *varname, U64 lu);						// typed, checks storage space
@@ -412,7 +374,7 @@ public:
 	void	addVector3d( const char *varname, const LLVector3d& vec);	// typed, checks storage space
 	void	addQuatFast( const char *varname, const LLQuaternion& quat);	// typed, checks storage space
 	void	addQuat( const char *varname, const LLQuaternion& quat);	// typed, checks storage space
-	virtual void addUUIDFast( const char *varname, const LLUUID& uuid);			// typed, checks storage space
+	void addUUIDFast( const char *varname, const LLUUID& uuid);			// typed, checks storage space
 	void	addUUID( const char *varname, const LLUUID& uuid);			// typed, checks storage space
 	void	addIPAddrFast( const char *varname, const U32 ip);			// typed, checks storage space
 	void	addIPAddr( const char *varname, const U32 ip);			// typed, checks storage space
@@ -423,8 +385,8 @@ public:
 	void	addStringFast( const char* varname, const std::string& s);				// typed, checks storage space
 	void	addString( const char* varname, const std::string& s);				// typed, checks storage space
 
+	S32 getCurrentSendTotal() const;
 	TPACKETID getCurrentRecvPacketID() { return mCurrentRecvPacketID; }
-	S32 getCurrentSendTotal() const { return mCurrentSendTotal; }
 
 	// This method checks for current send total and returns true if
 	// you need to go to the next block type or need to start a new
@@ -433,16 +395,16 @@ public:
 	BOOL isSendFull(const char* blockname = NULL);
 	BOOL isSendFullFast(const char* blockname = NULL);
 
-	BOOL	removeLastBlock();
+	BOOL removeLastBlock();
 
-	void	buildMessage();
+	//void	buildMessage();
 
 	S32     zeroCode(U8 **data, S32 *data_size);
 	S32		zeroCodeExpand(U8 **data, S32 *data_size);
 	S32		zeroCodeAdjustCurrentSendTotal();
 
 	// Uses ping-based retry
-	virtual S32 sendReliable(const LLHost &host);
+	S32 sendReliable(const LLHost &host);
 
 	// Uses ping-based retry
 	S32	sendReliable(const U32 circuit)			{ return sendReliable(findHost(circuit)); }
@@ -471,28 +433,10 @@ public:
 	S32		sendMessage(const LLHost &host);
 	S32		sendMessage(const U32 circuit);
 
-	BOOL	decodeData(const U8 *buffer, const LLHost &host);
-
-	// TODO: Consolide these functions
-	// TODO: Make these private, force use of typed functions.
-	// If size is not 0, an error is generated if size doesn't exactly match the size of the data.
-	// At all times, the number if bytes written to *datap is <= max_size.
-private:
-	void	getDataFast(const char *blockname, const char *varname, void *datap, S32 size = 0, S32 blocknum = 0, S32 max_size = S32_MAX);
-	void	getData(const char *blockname, const char *varname, void *datap, S32 size = 0, S32 blocknum = 0, S32 max_size = S32_MAX)
-	{
-		getDataFast(gMessageStringTable.getString(blockname), gMessageStringTable.getString(varname), datap, size, blocknum, max_size);
-	}
-public:
-	void	getBinaryDataFast(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum = 0, S32 max_size = S32_MAX)
-	{
-		getDataFast(blockname, varname, datap, size, blocknum, max_size);
-	}
-	void	getBinaryData(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum = 0, S32 max_size = S32_MAX)
-	{
-		getDataFast(gMessageStringTable.getString(blockname), gMessageStringTable.getString(varname), datap, size, blocknum, max_size);
-	}
+	// BOOL	decodeData(const U8 *buffer, const LLHost &host);
 
+	void	getBinaryDataFast(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum = 0, S32 max_size = S32_MAX);
+	void	getBinaryData(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum = 0, S32 max_size = S32_MAX);
 	void	getBOOLFast(	const char *block, const char *var, BOOL &data, S32 blocknum = 0);
 	void	getBOOL(	const char *block, const char *var, BOOL &data, S32 blocknum = 0);
 	void	getS8Fast(		const char *block, const char *var, S8 &data, S32 blocknum = 0);
@@ -507,9 +451,9 @@ public:
 	void	getS32(		const char *block, const char *var, S32 &data, S32 blocknum = 0);
 	void	getF32Fast(		const char *block, const char *var, F32 &data, S32 blocknum = 0);
 	void	getF32(		const char *block, const char *var, F32 &data, S32 blocknum = 0);
-	virtual void getU32Fast(		const char *block, const char *var, U32 &data, S32 blocknum = 0);
+	void getU32Fast(		const char *block, const char *var, U32 &data, S32 blocknum = 0);
 	void	getU32(		const char *block, const char *var, U32 &data, S32 blocknum = 0);
-	virtual void getU64Fast(		const char *block, const char *var, U64 &data, S32 blocknum = 0);
+	void getU64Fast(		const char *block, const char *var, U64 &data, S32 blocknum = 0);
 	void	getU64(		const char *block, const char *var, U64 &data, S32 blocknum = 0);
 	void	getF64Fast(		const char *block, const char *var, F64 &data, S32 blocknum = 0);
 	void	getF64(		const char *block, const char *var, F64 &data, S32 blocknum = 0);
@@ -521,13 +465,13 @@ public:
 	void	getVector3d(const char *block, const char *var, LLVector3d &vec, S32 blocknum = 0);
 	void	getQuatFast(	const char *block, const char *var, LLQuaternion &q, S32 blocknum = 0);
 	void	getQuat(	const char *block, const char *var, LLQuaternion &q, S32 blocknum = 0);
-	virtual void getUUIDFast(	const char *block, const char *var, LLUUID &uuid, S32 blocknum = 0);
+	void getUUIDFast(	const char *block, const char *var, LLUUID &uuid, S32 blocknum = 0);
 	void	getUUID(	const char *block, const char *var, LLUUID &uuid, S32 blocknum = 0);
-	virtual void getIPAddrFast(	const char *block, const char *var, U32 &ip, S32 blocknum = 0);
+	void getIPAddrFast(	const char *block, const char *var, U32 &ip, S32 blocknum = 0);
 	void	getIPAddr(	const char *block, const char *var, U32 &ip, S32 blocknum = 0);
-	virtual void getIPPortFast(	const char *block, const char *var, U16 &port, S32 blocknum = 0);
+	void getIPPortFast(	const char *block, const char *var, U16 &port, S32 blocknum = 0);
 	void	getIPPort(	const char *block, const char *var, U16 &port, S32 blocknum = 0);
-	virtual void getStringFast(	const char *block, const char *var, S32 buffer_size, char *buffer, S32 blocknum = 0);
+	void getStringFast(	const char *block, const char *var, S32 buffer_size, char *buffer, S32 blocknum = 0);
 	void	getString(	const char *block, const char *var, S32 buffer_size, char *buffer, S32 blocknum = 0);
 
 
@@ -549,7 +493,7 @@ public:
 	void	showCircuitInfo();
 	LLString getCircuitInfoString();
 
-	virtual U32 getOurCircuitCode();
+	U32 getOurCircuitCode();
 	
 	void	enableCircuit(const LLHost &host, BOOL trusted);
 	void	disableCircuit(const LLHost &host);
@@ -595,20 +539,12 @@ public:
 	void	sanityCheck();
 
 	S32		getNumberOfBlocksFast(const char *blockname);
-	S32		getNumberOfBlocks(const char *blockname)
-	{
-		return getNumberOfBlocksFast(gMessageStringTable.getString(blockname));
-	}
+	S32		getNumberOfBlocks(const char *blockname);
 	S32		getSizeFast(const char *blockname, const char *varname);
-	S32		getSize(const char *blockname, const char *varname)
-	{
-		return getSizeFast(gMessageStringTable.getString(blockname), gMessageStringTable.getString(varname));
-	}
-	S32		getSizeFast(const char *blockname, S32 blocknum, const char *varname);		// size in bytes of variable length data
-	S32		getSize(const char *blockname, S32 blocknum, const char *varname)
-	{
-		return getSizeFast(gMessageStringTable.getString(blockname), blocknum, gMessageStringTable.getString(varname));
-	}
+	S32		getSize(const char *blockname, const char *varname);
+	S32		getSizeFast(const char *blockname, S32 blocknum, 
+						const char *varname); // size in bytes of data
+	S32		getSize(const char *blockname, S32 blocknum, const char *varname);
 
 	void	resetReceiveCounts();				// resets receive counts for all message types to 0
 	void	dumpReceiveCounts();				// dumps receive count for each message type to llinfos
@@ -623,14 +559,14 @@ public:
 	void stopLogging();						// flush and close file
 	void summarizeLogs(std::ostream& str);	// log statistics
 
-	S32		getReceiveSize() const				{ return mReceiveSize; }
-	S32		getReceiveCompressedSize() const	{ return mIncomingCompressedSize; }
+	S32		getReceiveSize() const;
+	S32		getReceiveCompressedSize() const { return mIncomingCompressedSize; }
 	S32		getReceiveBytes() const;
 
 	S32		getUnackedListSize() const			{ return mUnackedListSize; }
 
-	const char* getCurrentSMessageName() const { return mCurrentSMessageName; }
-	const char* getCurrentSBlockName() const { return mCurrentSBlockName; }
+	//const char* getCurrentSMessageName() const { return mCurrentSMessageName; }
+	//const char* getCurrentSBlockName() const { return mCurrentSBlockName; }
 
 	// friends
 	friend std::ostream&	operator<<(std::ostream& s, LLMessageSystem &msg);
@@ -639,25 +575,41 @@ public:
 	void setMaxMessageCounts(const S32 num);	// Max number of messages before dumping (neg to disable)
 	
 	// statics
-public:
+	static BOOL isTemplateConfirmed();
+	static BOOL doesTemplateMatch();
+	static void sendMessageTemplateChecksum(const LLHost&);
+	static void processMessageTemplateChecksumReply(LLMessageSystem *msg,
+													void** user_data);
+	static void sendSecureMessageTemplateChecksum(const LLHost&);
+	static void processSecureTemplateChecksumReply(LLMessageSystem *msg,
+													void** user_data);
 	static U64 getMessageTimeUsecs(const BOOL update = FALSE);	// Get the current message system time in microseconds
 	static F64 getMessageTimeSeconds(const BOOL update = FALSE); // Get the current message system time in seconds
 
-	static void setTimeDecodes( BOOL b )		
-		{ LLMessageSystem::mTimeDecodes = b; }
-
-	static void setTimeDecodesSpamThreshold( F32 seconds ) 
-		{ LLMessageSystem::mTimeDecodesSpamThreshold = seconds; }
+	static void setTimeDecodes(BOOL b);
+	static void setTimeDecodesSpamThreshold(F32 seconds); 
 
 	// message handlers internal to the message systesm
 	//static void processAssignCircuitCode(LLMessageSystem* msg, void**);
 	static void processAddCircuitCode(LLMessageSystem* msg, void**);
 	static void processUseCircuitCode(LLMessageSystem* msg, void**);
 
+	// dispatch llsd message to http node tree
+	static void dispatch(const std::string& msg_name,
+						 const LLSD& message);
+	static void dispatch(const std::string& msg_name,
+						 const LLSD& message,
+						 LLHTTPNode::ResponsePtr responsep);
+
 	void setMessageBans(const LLSD& trusted, const LLSD& untrusted);
+
+	// Check UDP messages and pump http_pump to receive HTTP messages.
+	bool checkAllMessages(S64 frame_count, LLPumpIO* http_pump);
 	
 private:
 	// data used in those internal handlers
+	BOOL mTemplateConfirmed;
+	BOOL mTemplateMatches;
 
 	// The mCircuitCodes is a map from circuit codes to session
 	// ids. This allows us to verify sessions on connect.
@@ -668,7 +620,6 @@ private:
 	// that no one gives them a bad circuit code.
 	LLUUID mSessionID;
 
-private:
 	void	addTemplate(LLMessageTemplate *templatep);
 	void		clearReceiveState();
 	BOOL		decodeTemplate( const U8* buffer, S32 buffer_size, LLMessageTemplate** msg_template );
@@ -678,7 +629,6 @@ private:
 	void		logValidMsg(LLCircuitData *cdp, const LLHost& sender, BOOL recv_reliable, BOOL recv_resent, BOOL recv_acks );
 	void		logRanOffEndOfPacket( const LLHost& sender );
 
-private:
 	class LLMessageCountInfo
 	{
 	public:
@@ -694,26 +644,10 @@ private:
 	S32										mTrueReceiveSize;
 
 	// Must be valid during decode
-	S32										mReceiveSize;
-	TPACKETID                               mCurrentRecvPacketID;       // packet ID of current receive packet (for reporting)
-	LLMessageTemplate						*mCurrentRMessageTemplate;
-	LLMsgData								*mCurrentRMessageData;
-	S32									    mIncomingCompressedSize;		// original size of compressed msg (0 if uncomp.)
-	LLHost									mLastSender;
-
-	// send message storage
-	LLMsgData								*mCurrentSMessageData;
-	LLMessageTemplate						*mCurrentSMessageTemplate;
-	LLMsgBlkData							*mCurrentSDataBlock;
-	char									*mCurrentSMessageName;
-	char									*mCurrentSBlockName;
-
+	
 	BOOL									mbError;
 	S32 mErrorCode;
 
-	BOOL									mbSBuilt;	// is send message built?
-	BOOL									mbSClear;	// is the send message clear?
-
 	F64										mResendDumpTime; // The last time we dumped resends
 
 	LLMessageCountInfo mMessageCountList[MAX_MESSAGE_COUNT_NUM];
@@ -740,6 +674,22 @@ private:
 	void* mTimingCallbackData;
 
 	void init(); // ctor shared initialisation.
+
+	LLHost mLastSender;
+	S32 mIncomingCompressedSize;		// original size of compressed msg (0 if uncomp.)
+	TPACKETID mCurrentRecvPacketID;       // packet ID of current receive packet (for reporting)
+
+	LLMessageBuilder* mMessageBuilder;
+	LLTemplateMessageBuilder* mTemplateMessageBuilder;
+	LLSDMessageBuilder* mLLSDMessageBuilder;
+	LLMessageReader* mMessageReader;
+	LLTemplateMessageReader* mTemplateMessageReader;
+	LLSDMessageReader* mLLSDMessageReader;
+
+	friend class LLMessageHandlerBridge;
+	
+	bool callHandler(const char *name, bool trustedSource,
+					 LLMessageSystem* msg);
 };
 
 
@@ -756,7 +706,8 @@ BOOL start_messaging_system(
 	S32 version_minor,
 	S32 version_patch,
 	BOOL b_dump_prehash_file,
-	const std::string& secret);
+	const std::string& secret,
+	const LLUseCircuitCodeResponder* responder = NULL);
 
 void end_messaging_system();
 
@@ -932,12 +883,9 @@ inline void *ntohmemcpy(void *s, const void *ct, EMsgVariableType type, size_t n
 }
 
 
-inline const LLHost& LLMessageSystem::getSender() const
-{
-	return mLastSender;
-}
+inline const LLHost& LLMessageSystem::getSender() const {return mLastSender;}
 
-inline U32 LLMessageSystem::getSenderIP() const
+inline U32 LLMessageSystem::getSenderIP() const 
 {
 	return mLastSender.getAddress();
 }
@@ -947,291 +895,9 @@ inline U32 LLMessageSystem::getSenderPort() const
 	return mLastSender.getPort();
 }
 
-inline void LLMessageSystem::addS8Fast(const char *varname, S8 s)
-{
-	addDataFast(varname, &s, MVT_S8, sizeof(s));
-}
-
-inline void LLMessageSystem::addS8(const char *varname, S8 s)
-{
-	addDataFast(gMessageStringTable.getString(varname), &s, MVT_S8, sizeof(s));
-}
-
-inline void LLMessageSystem::addU8Fast(const char *varname, U8 u)
-{
-	addDataFast(varname, &u, MVT_U8, sizeof(u));
-}
-
-inline void LLMessageSystem::addU8(const char *varname, U8 u)
-{
-	addDataFast(gMessageStringTable.getString(varname), &u, MVT_U8, sizeof(u));
-}
-
-inline void LLMessageSystem::addS16Fast(const char *varname, S16 i)
-{
-	addDataFast(varname, &i, MVT_S16, sizeof(i));
-}
-
-inline void LLMessageSystem::addS16(const char *varname, S16 i)
-{
-	addDataFast(gMessageStringTable.getString(varname), &i, MVT_S16, sizeof(i));
-}
-
-inline void LLMessageSystem::addU16Fast(const char *varname, U16 i)
-{
-	addDataFast(varname, &i, MVT_U16, sizeof(i));
-}
-
-inline void LLMessageSystem::addU16(const char *varname, U16 i)
-{
-	addDataFast(gMessageStringTable.getString(varname), &i, MVT_U16, sizeof(i));
-}
-
-inline void LLMessageSystem::addF32Fast(const char *varname, F32 f)
-{
-	addDataFast(varname, &f, MVT_F32, sizeof(f));
-}
-
-inline void LLMessageSystem::addF32(const char *varname, F32 f)
-{
-	addDataFast(gMessageStringTable.getString(varname), &f, MVT_F32, sizeof(f));
-}
-
-inline void LLMessageSystem::addS32Fast(const char *varname, S32 s)
-{
-	addDataFast(varname, &s, MVT_S32, sizeof(s));
-}
-
-inline void LLMessageSystem::addS32(const char *varname, S32 s)
-{
-	addDataFast(gMessageStringTable.getString(varname), &s, MVT_S32, sizeof(s));
-}
-
-inline void LLMessageSystem::addU32Fast(const char *varname, U32 u)
-{
-	addDataFast(varname, &u, MVT_U32, sizeof(u));
-}
-
-inline void LLMessageSystem::addU32(const char *varname, U32 u)
-{
-	addDataFast(gMessageStringTable.getString(varname), &u, MVT_U32, sizeof(u));
-}
-
-inline void LLMessageSystem::addU64Fast(const char *varname, U64 lu)
-{
-	addDataFast(varname, &lu, MVT_U64, sizeof(lu));
-}
-
-inline void LLMessageSystem::addU64(const char *varname, U64 lu)
-{
-	addDataFast(gMessageStringTable.getString(varname), &lu, MVT_U64, sizeof(lu));
-}
-
-inline void LLMessageSystem::addF64Fast(const char *varname, F64 d)
-{
-	addDataFast(varname, &d, MVT_F64, sizeof(d));
-}
-
-inline void LLMessageSystem::addF64(const char *varname, F64 d)
-{
-	addDataFast(gMessageStringTable.getString(varname), &d, MVT_F64, sizeof(d));
-}
-
-inline void LLMessageSystem::addIPAddrFast(const char *varname, U32 u)
-{
-	addDataFast(varname, &u, MVT_IP_ADDR, sizeof(u));
-}
-
-inline void LLMessageSystem::addIPAddr(const char *varname, U32 u)
-{
-	addDataFast(gMessageStringTable.getString(varname), &u, MVT_IP_ADDR, sizeof(u));
-}
-
-inline void LLMessageSystem::addIPPortFast(const char *varname, U16 u)
-{
-	u = htons(u);
-	addDataFast(varname, &u, MVT_IP_PORT, sizeof(u));
-}
-
-inline void LLMessageSystem::addIPPort(const char *varname, U16 u)
-{
-	u = htons(u);
-	addDataFast(gMessageStringTable.getString(varname), &u, MVT_IP_PORT, sizeof(u));
-}
-
-inline void LLMessageSystem::addBOOLFast(const char* varname, BOOL b)
-{
-	// Can't just cast a BOOL (actually a U32) to a U8.
-	// In some cases the low order bits will be zero.
-	U8 temp = (b != 0);
-	addDataFast(varname, &temp, MVT_BOOL, sizeof(temp));
-}
-
-inline void LLMessageSystem::addBOOL(const char* varname, BOOL b)
-{
-	// Can't just cast a BOOL (actually a U32) to a U8.
-	// In some cases the low order bits will be zero.
-	U8 temp = (b != 0);
-	addDataFast(gMessageStringTable.getString(varname), &temp, MVT_BOOL, sizeof(temp));
-}
-
-inline void LLMessageSystem::addStringFast(const char* varname, const char* s)
-{
-	if (s)
-		addDataFast( varname, (void *)s, MVT_VARIABLE, (S32)strlen(s) + 1);  /* Flawfinder: ignore */  
-	else
-		addDataFast( varname, NULL, MVT_VARIABLE, 0); 
-}
-
-inline void LLMessageSystem::addString(const char* varname, const char* s)
-{
-	if (s)
-		addDataFast( gMessageStringTable.getString(varname), (void *)s, MVT_VARIABLE, (S32)strlen(s) + 1);  /* Flawfinder: ignore */ 
-	else
-		addDataFast( gMessageStringTable.getString(varname), NULL, MVT_VARIABLE, 0); 
-}
-
-inline void LLMessageSystem::addStringFast(const char* varname, const std::string& s)
-{
-	if (s.size())
-		addDataFast( varname, (void *)s.c_str(), MVT_VARIABLE, (S32)(s.size()) + 1); 
-	else
-		addDataFast( varname, NULL, MVT_VARIABLE, 0); 
-}
-
-inline void LLMessageSystem::addString(const char* varname, const std::string& s)
-{
-	if (s.size())
-		addDataFast( gMessageStringTable.getString(varname), (void *)s.c_str(), MVT_VARIABLE, (S32)(s.size()) + 1); 
-	else
-		addDataFast( gMessageStringTable.getString(varname), NULL, MVT_VARIABLE, 0); 
-}
-
-
 //-----------------------------------------------------------------------------
-// Retrieval aliases
+// Transmission aliases
 //-----------------------------------------------------------------------------
-inline void LLMessageSystem::getS8Fast(const char *block, const char *var, S8 &u, S32 blocknum)
-{
-	getDataFast(block, var, &u, sizeof(S8), blocknum);
-}
-
-inline void LLMessageSystem::getS8(const char *block, const char *var, S8 &u, S32 blocknum)
-{
-	getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &u, sizeof(S8), blocknum);
-}
-
-inline void LLMessageSystem::getU8Fast(const char *block, const char *var, U8 &u, S32 blocknum)
-{
-	getDataFast(block, var, &u, sizeof(U8), blocknum);
-}
-
-inline void LLMessageSystem::getU8(const char *block, const char *var, U8 &u, S32 blocknum)
-{
-	getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &u, sizeof(U8), blocknum);
-}
-
-inline void LLMessageSystem::getBOOLFast(const char *block, const char *var, BOOL &b, S32 blocknum )
-{
-	U8 value;
-	getDataFast(block, var, &value, sizeof(U8), blocknum);
-	b = (BOOL) value;
-}
-
-inline void LLMessageSystem::getBOOL(const char *block, const char *var, BOOL &b, S32 blocknum )
-{
-	U8 value;
-	getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &value, sizeof(U8), blocknum);
-	b = (BOOL) value;
-}
-
-inline void LLMessageSystem::getS16Fast(const char *block, const char *var, S16 &d, S32 blocknum)
-{
-	getDataFast(block, var, &d, sizeof(S16), blocknum);
-}
-
-inline void LLMessageSystem::getS16(const char *block, const char *var, S16 &d, S32 blocknum)
-{
-	getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(S16), blocknum);
-}
-
-inline void LLMessageSystem::getU16Fast(const char *block, const char *var, U16 &d, S32 blocknum)
-{
-	getDataFast(block, var, &d, sizeof(U16), blocknum);
-}
-
-inline void LLMessageSystem::getU16(const char *block, const char *var, U16 &d, S32 blocknum)
-{
-	getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(U16), blocknum);
-}
-
-inline void LLMessageSystem::getS32Fast(const char *block, const char *var, S32 &d, S32 blocknum)
-{
-	getDataFast(block, var, &d, sizeof(S32), blocknum);
-}
-
-inline void LLMessageSystem::getS32(const char *block, const char *var, S32 &d, S32 blocknum)
-{
-	getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(S32), blocknum);
-}
-
-inline void LLMessageSystem::getU32Fast(const char *block, const char *var, U32 &d, S32 blocknum)
-{
-	getDataFast(block, var, &d, sizeof(U32), blocknum);
-}
-
-inline void LLMessageSystem::getU32(const char *block, const char *var, U32 &d, S32 blocknum)
-{
-	getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(U32), blocknum);
-}
-
-inline void LLMessageSystem::getU64Fast(const char *block, const char *var, U64 &d, S32 blocknum)
-{
-	getDataFast(block, var, &d, sizeof(U64), blocknum);
-}
-
-inline void LLMessageSystem::getU64(const char *block, const char *var, U64 &d, S32 blocknum)
-{
-	getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(U64), blocknum);
-}
-
-
-inline void LLMessageSystem::getIPAddrFast(const char *block, const char *var, U32 &u, S32 blocknum)
-{
-	getDataFast(block, var, &u, sizeof(U32), blocknum);
-}
-
-inline void LLMessageSystem::getIPAddr(const char *block, const char *var, U32 &u, S32 blocknum)
-{
-	getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &u, sizeof(U32), blocknum);
-}
-
-inline void LLMessageSystem::getIPPortFast(const char *block, const char *var, U16 &u, S32 blocknum)
-{
-	getDataFast(block, var, &u, sizeof(U16), blocknum);
-	u = ntohs(u);
-}
-
-inline void LLMessageSystem::getIPPort(const char *block, const char *var, U16 &u, S32 blocknum)
-{
-	getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &u, sizeof(U16), blocknum);
-	u = ntohs(u);
-}
-
-
-inline void LLMessageSystem::getStringFast(const char *block, const char *var, S32 buffer_size, char *s, S32 blocknum )
-{
-	s[0] = '\0';
-	getDataFast(block, var, s, 0, blocknum, buffer_size);
-	s[buffer_size - 1] = '\0';
-}
-
-inline void LLMessageSystem::getString(const char *block, const char *var, S32 buffer_size, char *s, S32 blocknum )
-{
-	s[0] = '\0';
-	getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), s, 0, blocknum, buffer_size);
-	s[buffer_size - 1] = '\0';
-}
 
 inline S32 LLMessageSystem::sendMessage(const U32 circuit)
 {
diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp
index c2d7c9c2a3..9d7e603690 100644
--- a/indra/llmessage/message_prehash.cpp
+++ b/indra/llmessage/message_prehash.cpp
@@ -20,7 +20,6 @@ char * _PREHASH_X;
 char * _PREHASH_Y;
 char * _PREHASH_Z;
 char * _PREHASH_AddFlags;
-char * _PREHASH_ReservedNewbie;
 char * _PREHASH_FailureInfo;
 char * _PREHASH_MapData;
 char * _PREHASH_AddItem;
@@ -89,7 +88,6 @@ char * _PREHASH_RelatedRights;
 char * _PREHASH_RedirectGridX;
 char * _PREHASH_RedirectGridY;
 char * _PREHASH_TransferID;
-char * _PREHASH_Transacted;
 char * _PREHASH_TexturesChanged;
 char * _PREHASH_UserLookAt;
 char * _PREHASH_TestBlock1;
@@ -116,7 +114,6 @@ char * _PREHASH_SetSimStatusInDatabase;
 char * _PREHASH_SetSimPresenceInDatabase;
 char * _PREHASH_CameraProperty;
 char * _PREHASH_BrushSize;
-char * _PREHASH_StartExpungeProcess;
 char * _PREHASH_SimulatorSetMap;
 char * _PREHASH_RegionPresenceRequestByRegionID;
 char * _PREHASH_ParcelObjectOwnersReply;
@@ -210,8 +207,8 @@ char * _PREHASH_SimName;
 char * _PREHASH_UserReport;
 char * _PREHASH_DownloadPriority;
 char * _PREHASH_ToAgentId;
-char * _PREHASH_Mag;
 char * _PREHASH_DirPopularQuery;
+char * _PREHASH_Mag;
 char * _PREHASH_ParcelPropertiesRequestByID;
 char * _PREHASH_ObjectLink;
 char * _PREHASH_RpcScriptReplyInbound;
@@ -420,7 +417,6 @@ char * _PREHASH_TerminateFriendship;
 char * _PREHASH_TaskData;
 char * _PREHASH_SimWideMaxPrims;
 char * _PREHASH_TotalPrims;
-char * _PREHASH_SourceFilename;
 char * _PREHASH_ProfileBegin;
 char * _PREHASH_MoneyDetailsRequest;
 char * _PREHASH_Request;
@@ -467,7 +463,6 @@ char * _PREHASH_ParamInUse;
 char * _PREHASH_GodKickUser;
 char * _PREHASH_PickName;
 char * _PREHASH_TaskName;
-char * _PREHASH_ParcelGodReserveForNewbie;
 char * _PREHASH_SubType;
 char * _PREHASH_ObjectCount;
 char * _PREHASH_RegionPresenceRequestByHandle;
@@ -486,10 +481,13 @@ char * _PREHASH_UpdateParcel;
 char * _PREHASH_ClearAgentSessions;
 char * _PREHASH_SetAlwaysRun;
 char * _PREHASH_NVPair;
+char * _PREHASH_SearchType;
 char * _PREHASH_ObjectSpinStart;
 char * _PREHASH_UseEstateSun;
 char * _PREHASH_LogoutBlock;
+char * _PREHASH_RelayLogControl;
 char * _PREHASH_RegionID;
+char * _PREHASH_AbuseRegionID;
 char * _PREHASH_Creator;
 char * _PREHASH_ProposalText;
 char * _PREHASH_DirEventsReply;
@@ -534,7 +532,6 @@ char * _PREHASH_MaxY;
 char * _PREHASH_TextureAnim;
 char * _PREHASH_ReturnIDs;
 char * _PREHASH_Date;
-char * _PREHASH_GestureUpdate;
 char * _PREHASH_AgentWearablesUpdate;
 char * _PREHASH_AgentDataUpdate;
 char * _PREHASH_Hash;
@@ -556,7 +553,6 @@ char * _PREHASH_HistoryItemData;
 char * _PREHASH_AgentCachedTexture;
 char * _PREHASH_Subject;
 char * _PREHASH_East;
-char * _PREHASH_GodExpungeUser;
 char * _PREHASH_QueryReplies;
 char * _PREHASH_ObjectCategory;
 char * _PREHASH_Time;
@@ -783,6 +779,7 @@ char * _PREHASH_UnsubscribeLoad;
 char * _PREHASH_Packet;
 char * _PREHASH_UndoLand;
 char * _PREHASH_SimAccess;
+char * _PREHASH_AbuserID;
 char * _PREHASH_MembershipFee;
 char * _PREHASH_InviteGroupResponse;
 char * _PREHASH_CreateInventoryFolder;
@@ -920,6 +917,7 @@ char * _PREHASH_ImageNotInDatabase;
 char * _PREHASH_StartDate;
 char * _PREHASH_AnimID;
 char * _PREHASH_Serial;
+char * _PREHASH_AbuseRegionName;
 char * _PREHASH_ControlPort;
 char * _PREHASH_ModifyLand;
 char * _PREHASH_Digest;
@@ -984,11 +982,11 @@ char * _PREHASH_EventFlags;
 char * _PREHASH_TallyVotes;
 char * _PREHASH_Result;
 char * _PREHASH_LookAt;
+char * _PREHASH_SearchOrder;
 char * _PREHASH_PayButton;
 char * _PREHASH_SelfCount;
 char * _PREHASH_PacketCount;
 char * _PREHASH_ParcelBuyPass;
-char * _PREHASH_Identified;
 char * _PREHASH_OldItemID;
 char * _PREHASH_RegionPort;
 char * _PREHASH_PriceEnergyUnit;
@@ -1024,7 +1022,6 @@ char * _PREHASH_EconomyDataRequest;
 char * _PREHASH_TeleportLureRequest;
 char * _PREHASH_FolderID;
 char * _PREHASH_RegionHandleRequest;
-char * _PREHASH_GestureRequest;
 char * _PREHASH_ScriptDataRequest;
 char * _PREHASH_GroupRoleDataRequest;
 char * _PREHASH_GroupTitlesRequest;
@@ -1168,11 +1165,9 @@ char * _PREHASH_Ratio;
 char * _PREHASH_JoinGroupReply;
 char * _PREHASH_LiveHelpGroupReply;
 char * _PREHASH_Score;
-char * _PREHASH_ExpungeData;
 char * _PREHASH_Image;
 char * _PREHASH_ObjectClickAction;
 char * _PREHASH_Delta;
-char * _PREHASH_InitiateUpload;
 char * _PREHASH_Parameter;
 char * _PREHASH_Flags;
 char * _PREHASH_Plane;
@@ -1208,7 +1203,6 @@ char * _PREHASH_Disconnect;
 char * _PREHASH_SimPosition;
 char * _PREHASH_SimWideTotalPrims;
 char * _PREHASH_Index;
-char * _PREHASH_BaseFilename;
 char * _PREHASH_SimFilename;
 char * _PREHASH_LastOwnerID;
 char * _PREHASH_GroupNoticeRequest;
@@ -1293,6 +1287,7 @@ char * _PREHASH_AssetBlock;
 char * _PREHASH_AcceptNotices;
 char * _PREHASH_SetGroupAcceptNotices;
 char * _PREHASH_CloseCircuit;
+char * _PREHASH_LogControl;
 char * _PREHASH_TeleportFinish;
 char * _PREHASH_PathRevolutions;
 char * _PREHASH_ClassifiedInfoReply;
@@ -1472,7 +1467,6 @@ char * _PREHASH_DirLandReply;
 char * _PREHASH_SpaceLocationTeleportReply;
 char * _PREHASH_MuteType;
 char * _PREHASH_IMViaEMail;
-char * _PREHASH_StartExpungeProcessAck;
 char * _PREHASH_RentPrice;
 char * _PREHASH_GenericMessage;
 char * _PREHASH_ChildAgentAlive;
@@ -1492,7 +1486,6 @@ void init_prehash_data()
 	_PREHASH_Y = gMessageStringTable.getString("Y");
 	_PREHASH_Z = gMessageStringTable.getString("Z");
 	_PREHASH_AddFlags = gMessageStringTable.getString("AddFlags");
-	_PREHASH_ReservedNewbie = gMessageStringTable.getString("ReservedNewbie");
 	_PREHASH_FailureInfo = gMessageStringTable.getString("FailureInfo");
 	_PREHASH_MapData = gMessageStringTable.getString("MapData");
 	_PREHASH_AddItem = gMessageStringTable.getString("AddItem");
@@ -1561,7 +1554,6 @@ void init_prehash_data()
 	_PREHASH_RedirectGridX = gMessageStringTable.getString("RedirectGridX");
 	_PREHASH_RedirectGridY = gMessageStringTable.getString("RedirectGridY");
 	_PREHASH_TransferID = gMessageStringTable.getString("TransferID");
-	_PREHASH_Transacted = gMessageStringTable.getString("Transacted");
 	_PREHASH_TexturesChanged = gMessageStringTable.getString("TexturesChanged");
 	_PREHASH_UserLookAt = gMessageStringTable.getString("UserLookAt");
 	_PREHASH_TestBlock1 = gMessageStringTable.getString("TestBlock1");
@@ -1588,7 +1580,6 @@ void init_prehash_data()
 	_PREHASH_SetSimPresenceInDatabase = gMessageStringTable.getString("SetSimPresenceInDatabase");
 	_PREHASH_CameraProperty = gMessageStringTable.getString("CameraProperty");
 	_PREHASH_BrushSize = gMessageStringTable.getString("BrushSize");
-	_PREHASH_StartExpungeProcess = gMessageStringTable.getString("StartExpungeProcess");
 	_PREHASH_SimulatorSetMap = gMessageStringTable.getString("SimulatorSetMap");
 	_PREHASH_RegionPresenceRequestByRegionID = gMessageStringTable.getString("RegionPresenceRequestByRegionID");
 	_PREHASH_ParcelObjectOwnersReply = gMessageStringTable.getString("ParcelObjectOwnersReply");
@@ -1682,8 +1673,8 @@ void init_prehash_data()
 	_PREHASH_UserReport = gMessageStringTable.getString("UserReport");
 	_PREHASH_DownloadPriority = gMessageStringTable.getString("DownloadPriority");
 	_PREHASH_ToAgentId = gMessageStringTable.getString("ToAgentId");
-	_PREHASH_Mag = gMessageStringTable.getString("Mag");
 	_PREHASH_DirPopularQuery = gMessageStringTable.getString("DirPopularQuery");
+	_PREHASH_Mag = gMessageStringTable.getString("Mag");
 	_PREHASH_ParcelPropertiesRequestByID = gMessageStringTable.getString("ParcelPropertiesRequestByID");
 	_PREHASH_ObjectLink = gMessageStringTable.getString("ObjectLink");
 	_PREHASH_RpcScriptReplyInbound = gMessageStringTable.getString("RpcScriptReplyInbound");
@@ -1892,7 +1883,6 @@ void init_prehash_data()
 	_PREHASH_TaskData = gMessageStringTable.getString("TaskData");
 	_PREHASH_SimWideMaxPrims = gMessageStringTable.getString("SimWideMaxPrims");
 	_PREHASH_TotalPrims = gMessageStringTable.getString("TotalPrims");
-	_PREHASH_SourceFilename = gMessageStringTable.getString("SourceFilename");
 	_PREHASH_ProfileBegin = gMessageStringTable.getString("ProfileBegin");
 	_PREHASH_MoneyDetailsRequest = gMessageStringTable.getString("MoneyDetailsRequest");
 	_PREHASH_Request = gMessageStringTable.getString("Request");
@@ -1939,7 +1929,6 @@ void init_prehash_data()
 	_PREHASH_GodKickUser = gMessageStringTable.getString("GodKickUser");
 	_PREHASH_PickName = gMessageStringTable.getString("PickName");
 	_PREHASH_TaskName = gMessageStringTable.getString("TaskName");
-	_PREHASH_ParcelGodReserveForNewbie = gMessageStringTable.getString("ParcelGodReserveForNewbie");
 	_PREHASH_SubType = gMessageStringTable.getString("SubType");
 	_PREHASH_ObjectCount = gMessageStringTable.getString("ObjectCount");
 	_PREHASH_RegionPresenceRequestByHandle = gMessageStringTable.getString("RegionPresenceRequestByHandle");
@@ -1958,10 +1947,13 @@ void init_prehash_data()
 	_PREHASH_ClearAgentSessions = gMessageStringTable.getString("ClearAgentSessions");
 	_PREHASH_SetAlwaysRun = gMessageStringTable.getString("SetAlwaysRun");
 	_PREHASH_NVPair = gMessageStringTable.getString("NVPair");
+	_PREHASH_SearchType = gMessageStringTable.getString("SearchType");
 	_PREHASH_ObjectSpinStart = gMessageStringTable.getString("ObjectSpinStart");
 	_PREHASH_UseEstateSun = gMessageStringTable.getString("UseEstateSun");
 	_PREHASH_LogoutBlock = gMessageStringTable.getString("LogoutBlock");
+	_PREHASH_RelayLogControl = gMessageStringTable.getString("RelayLogControl");
 	_PREHASH_RegionID = gMessageStringTable.getString("RegionID");
+	_PREHASH_AbuseRegionID = gMessageStringTable.getString("AbuseRegionID");
 	_PREHASH_Creator = gMessageStringTable.getString("Creator");
 	_PREHASH_ProposalText = gMessageStringTable.getString("ProposalText");
 	_PREHASH_DirEventsReply = gMessageStringTable.getString("DirEventsReply");
@@ -2006,7 +1998,6 @@ void init_prehash_data()
 	_PREHASH_TextureAnim = gMessageStringTable.getString("TextureAnim");
 	_PREHASH_ReturnIDs = gMessageStringTable.getString("ReturnIDs");
 	_PREHASH_Date = gMessageStringTable.getString("Date");
-	_PREHASH_GestureUpdate = gMessageStringTable.getString("GestureUpdate");
 	_PREHASH_AgentWearablesUpdate = gMessageStringTable.getString("AgentWearablesUpdate");
 	_PREHASH_AgentDataUpdate = gMessageStringTable.getString("AgentDataUpdate");
 	_PREHASH_Hash = gMessageStringTable.getString("Hash");
@@ -2028,7 +2019,6 @@ void init_prehash_data()
 	_PREHASH_AgentCachedTexture = gMessageStringTable.getString("AgentCachedTexture");
 	_PREHASH_Subject = gMessageStringTable.getString("Subject");
 	_PREHASH_East = gMessageStringTable.getString("East");
-	_PREHASH_GodExpungeUser = gMessageStringTable.getString("GodExpungeUser");
 	_PREHASH_QueryReplies = gMessageStringTable.getString("QueryReplies");
 	_PREHASH_ObjectCategory = gMessageStringTable.getString("ObjectCategory");
 	_PREHASH_Time = gMessageStringTable.getString("Time");
@@ -2255,6 +2245,7 @@ void init_prehash_data()
 	_PREHASH_Packet = gMessageStringTable.getString("Packet");
 	_PREHASH_UndoLand = gMessageStringTable.getString("UndoLand");
 	_PREHASH_SimAccess = gMessageStringTable.getString("SimAccess");
+	_PREHASH_AbuserID = gMessageStringTable.getString("AbuserID");
 	_PREHASH_MembershipFee = gMessageStringTable.getString("MembershipFee");
 	_PREHASH_InviteGroupResponse = gMessageStringTable.getString("InviteGroupResponse");
 	_PREHASH_CreateInventoryFolder = gMessageStringTable.getString("CreateInventoryFolder");
@@ -2392,6 +2383,7 @@ void init_prehash_data()
 	_PREHASH_StartDate = gMessageStringTable.getString("StartDate");
 	_PREHASH_AnimID = gMessageStringTable.getString("AnimID");
 	_PREHASH_Serial = gMessageStringTable.getString("Serial");
+	_PREHASH_AbuseRegionName = gMessageStringTable.getString("AbuseRegionName");
 	_PREHASH_ControlPort = gMessageStringTable.getString("ControlPort");
 	_PREHASH_ModifyLand = gMessageStringTable.getString("ModifyLand");
 	_PREHASH_Digest = gMessageStringTable.getString("Digest");
@@ -2456,11 +2448,11 @@ void init_prehash_data()
 	_PREHASH_TallyVotes = gMessageStringTable.getString("TallyVotes");
 	_PREHASH_Result = gMessageStringTable.getString("Result");
 	_PREHASH_LookAt = gMessageStringTable.getString("LookAt");
+	_PREHASH_SearchOrder = gMessageStringTable.getString("SearchOrder");
 	_PREHASH_PayButton = gMessageStringTable.getString("PayButton");
 	_PREHASH_SelfCount = gMessageStringTable.getString("SelfCount");
 	_PREHASH_PacketCount = gMessageStringTable.getString("PacketCount");
 	_PREHASH_ParcelBuyPass = gMessageStringTable.getString("ParcelBuyPass");
-	_PREHASH_Identified = gMessageStringTable.getString("Identified");
 	_PREHASH_OldItemID = gMessageStringTable.getString("OldItemID");
 	_PREHASH_RegionPort = gMessageStringTable.getString("RegionPort");
 	_PREHASH_PriceEnergyUnit = gMessageStringTable.getString("PriceEnergyUnit");
@@ -2496,7 +2488,6 @@ void init_prehash_data()
 	_PREHASH_TeleportLureRequest = gMessageStringTable.getString("TeleportLureRequest");
 	_PREHASH_FolderID = gMessageStringTable.getString("FolderID");
 	_PREHASH_RegionHandleRequest = gMessageStringTable.getString("RegionHandleRequest");
-	_PREHASH_GestureRequest = gMessageStringTable.getString("GestureRequest");
 	_PREHASH_ScriptDataRequest = gMessageStringTable.getString("ScriptDataRequest");
 	_PREHASH_GroupRoleDataRequest = gMessageStringTable.getString("GroupRoleDataRequest");
 	_PREHASH_GroupTitlesRequest = gMessageStringTable.getString("GroupTitlesRequest");
@@ -2640,11 +2631,9 @@ void init_prehash_data()
 	_PREHASH_JoinGroupReply = gMessageStringTable.getString("JoinGroupReply");
 	_PREHASH_LiveHelpGroupReply = gMessageStringTable.getString("LiveHelpGroupReply");
 	_PREHASH_Score = gMessageStringTable.getString("Score");
-	_PREHASH_ExpungeData = gMessageStringTable.getString("ExpungeData");
 	_PREHASH_Image = gMessageStringTable.getString("Image");
 	_PREHASH_ObjectClickAction = gMessageStringTable.getString("ObjectClickAction");
 	_PREHASH_Delta = gMessageStringTable.getString("Delta");
-	_PREHASH_InitiateUpload = gMessageStringTable.getString("InitiateUpload");
 	_PREHASH_Parameter = gMessageStringTable.getString("Parameter");
 	_PREHASH_Flags = gMessageStringTable.getString("Flags");
 	_PREHASH_Plane = gMessageStringTable.getString("Plane");
@@ -2680,7 +2669,6 @@ void init_prehash_data()
 	_PREHASH_SimPosition = gMessageStringTable.getString("SimPosition");
 	_PREHASH_SimWideTotalPrims = gMessageStringTable.getString("SimWideTotalPrims");
 	_PREHASH_Index = gMessageStringTable.getString("Index");
-	_PREHASH_BaseFilename = gMessageStringTable.getString("BaseFilename");
 	_PREHASH_SimFilename = gMessageStringTable.getString("SimFilename");
 	_PREHASH_LastOwnerID = gMessageStringTable.getString("LastOwnerID");
 	_PREHASH_GroupNoticeRequest = gMessageStringTable.getString("GroupNoticeRequest");
@@ -2765,6 +2753,7 @@ void init_prehash_data()
 	_PREHASH_AcceptNotices = gMessageStringTable.getString("AcceptNotices");
 	_PREHASH_SetGroupAcceptNotices = gMessageStringTable.getString("SetGroupAcceptNotices");
 	_PREHASH_CloseCircuit = gMessageStringTable.getString("CloseCircuit");
+	_PREHASH_LogControl = gMessageStringTable.getString("LogControl");
 	_PREHASH_TeleportFinish = gMessageStringTable.getString("TeleportFinish");
 	_PREHASH_PathRevolutions = gMessageStringTable.getString("PathRevolutions");
 	_PREHASH_ClassifiedInfoReply = gMessageStringTable.getString("ClassifiedInfoReply");
@@ -2944,7 +2933,6 @@ void init_prehash_data()
 	_PREHASH_SpaceLocationTeleportReply = gMessageStringTable.getString("SpaceLocationTeleportReply");
 	_PREHASH_MuteType = gMessageStringTable.getString("MuteType");
 	_PREHASH_IMViaEMail = gMessageStringTable.getString("IMViaEMail");
-	_PREHASH_StartExpungeProcessAck = gMessageStringTable.getString("StartExpungeProcessAck");
 	_PREHASH_RentPrice = gMessageStringTable.getString("RentPrice");
 	_PREHASH_GenericMessage = gMessageStringTable.getString("GenericMessage");
 	_PREHASH_ChildAgentAlive = gMessageStringTable.getString("ChildAgentAlive");
diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h
index 63e23237f5..19b9881dde 100644
--- a/indra/llmessage/message_prehash.h
+++ b/indra/llmessage/message_prehash.h
@@ -20,7 +20,6 @@ extern char * _PREHASH_X;
 extern char * _PREHASH_Y;
 extern char * _PREHASH_Z;
 extern char * _PREHASH_AddFlags;
-extern char * _PREHASH_ReservedNewbie;
 extern char * _PREHASH_FailureInfo;
 extern char * _PREHASH_MapData;
 extern char * _PREHASH_AddItem;
@@ -89,7 +88,6 @@ extern char * _PREHASH_RelatedRights;
 extern char * _PREHASH_RedirectGridX;
 extern char * _PREHASH_RedirectGridY;
 extern char * _PREHASH_TransferID;
-extern char * _PREHASH_Transacted;
 extern char * _PREHASH_TexturesChanged;
 extern char * _PREHASH_UserLookAt;
 extern char * _PREHASH_TestBlock1;
@@ -116,7 +114,6 @@ extern char * _PREHASH_SetSimStatusInDatabase;
 extern char * _PREHASH_SetSimPresenceInDatabase;
 extern char * _PREHASH_CameraProperty;
 extern char * _PREHASH_BrushSize;
-extern char * _PREHASH_StartExpungeProcess;
 extern char * _PREHASH_SimulatorSetMap;
 extern char * _PREHASH_RegionPresenceRequestByRegionID;
 extern char * _PREHASH_ParcelObjectOwnersReply;
@@ -210,8 +207,8 @@ extern char * _PREHASH_SimName;
 extern char * _PREHASH_UserReport;
 extern char * _PREHASH_DownloadPriority;
 extern char * _PREHASH_ToAgentId;
-extern char * _PREHASH_Mag;
 extern char * _PREHASH_DirPopularQuery;
+extern char * _PREHASH_Mag;
 extern char * _PREHASH_ParcelPropertiesRequestByID;
 extern char * _PREHASH_ObjectLink;
 extern char * _PREHASH_RpcScriptReplyInbound;
@@ -420,7 +417,6 @@ extern char * _PREHASH_TerminateFriendship;
 extern char * _PREHASH_TaskData;
 extern char * _PREHASH_SimWideMaxPrims;
 extern char * _PREHASH_TotalPrims;
-extern char * _PREHASH_SourceFilename;
 extern char * _PREHASH_ProfileBegin;
 extern char * _PREHASH_MoneyDetailsRequest;
 extern char * _PREHASH_Request;
@@ -467,7 +463,6 @@ extern char * _PREHASH_ParamInUse;
 extern char * _PREHASH_GodKickUser;
 extern char * _PREHASH_PickName;
 extern char * _PREHASH_TaskName;
-extern char * _PREHASH_ParcelGodReserveForNewbie;
 extern char * _PREHASH_SubType;
 extern char * _PREHASH_ObjectCount;
 extern char * _PREHASH_RegionPresenceRequestByHandle;
@@ -486,10 +481,13 @@ extern char * _PREHASH_UpdateParcel;
 extern char * _PREHASH_ClearAgentSessions;
 extern char * _PREHASH_SetAlwaysRun;
 extern char * _PREHASH_NVPair;
+extern char * _PREHASH_SearchType;
 extern char * _PREHASH_ObjectSpinStart;
 extern char * _PREHASH_UseEstateSun;
 extern char * _PREHASH_LogoutBlock;
+extern char * _PREHASH_RelayLogControl;
 extern char * _PREHASH_RegionID;
+extern char * _PREHASH_AbuseRegionID;
 extern char * _PREHASH_Creator;
 extern char * _PREHASH_ProposalText;
 extern char * _PREHASH_DirEventsReply;
@@ -534,7 +532,6 @@ extern char * _PREHASH_MaxY;
 extern char * _PREHASH_TextureAnim;
 extern char * _PREHASH_ReturnIDs;
 extern char * _PREHASH_Date;
-extern char * _PREHASH_GestureUpdate;
 extern char * _PREHASH_AgentWearablesUpdate;
 extern char * _PREHASH_AgentDataUpdate;
 extern char * _PREHASH_Hash;
@@ -556,7 +553,6 @@ extern char * _PREHASH_HistoryItemData;
 extern char * _PREHASH_AgentCachedTexture;
 extern char * _PREHASH_Subject;
 extern char * _PREHASH_East;
-extern char * _PREHASH_GodExpungeUser;
 extern char * _PREHASH_QueryReplies;
 extern char * _PREHASH_ObjectCategory;
 extern char * _PREHASH_Time;
@@ -783,6 +779,7 @@ extern char * _PREHASH_UnsubscribeLoad;
 extern char * _PREHASH_Packet;
 extern char * _PREHASH_UndoLand;
 extern char * _PREHASH_SimAccess;
+extern char * _PREHASH_AbuserID;
 extern char * _PREHASH_MembershipFee;
 extern char * _PREHASH_InviteGroupResponse;
 extern char * _PREHASH_CreateInventoryFolder;
@@ -920,6 +917,7 @@ extern char * _PREHASH_ImageNotInDatabase;
 extern char * _PREHASH_StartDate;
 extern char * _PREHASH_AnimID;
 extern char * _PREHASH_Serial;
+extern char * _PREHASH_AbuseRegionName;
 extern char * _PREHASH_ControlPort;
 extern char * _PREHASH_ModifyLand;
 extern char * _PREHASH_Digest;
@@ -984,11 +982,11 @@ extern char * _PREHASH_EventFlags;
 extern char * _PREHASH_TallyVotes;
 extern char * _PREHASH_Result;
 extern char * _PREHASH_LookAt;
+extern char * _PREHASH_SearchOrder;
 extern char * _PREHASH_PayButton;
 extern char * _PREHASH_SelfCount;
 extern char * _PREHASH_PacketCount;
 extern char * _PREHASH_ParcelBuyPass;
-extern char * _PREHASH_Identified;
 extern char * _PREHASH_OldItemID;
 extern char * _PREHASH_RegionPort;
 extern char * _PREHASH_PriceEnergyUnit;
@@ -1024,7 +1022,6 @@ extern char * _PREHASH_EconomyDataRequest;
 extern char * _PREHASH_TeleportLureRequest;
 extern char * _PREHASH_FolderID;
 extern char * _PREHASH_RegionHandleRequest;
-extern char * _PREHASH_GestureRequest;
 extern char * _PREHASH_ScriptDataRequest;
 extern char * _PREHASH_GroupRoleDataRequest;
 extern char * _PREHASH_GroupTitlesRequest;
@@ -1168,11 +1165,9 @@ extern char * _PREHASH_Ratio;
 extern char * _PREHASH_JoinGroupReply;
 extern char * _PREHASH_LiveHelpGroupReply;
 extern char * _PREHASH_Score;
-extern char * _PREHASH_ExpungeData;
 extern char * _PREHASH_Image;
 extern char * _PREHASH_ObjectClickAction;
 extern char * _PREHASH_Delta;
-extern char * _PREHASH_InitiateUpload;
 extern char * _PREHASH_Parameter;
 extern char * _PREHASH_Flags;
 extern char * _PREHASH_Plane;
@@ -1208,7 +1203,6 @@ extern char * _PREHASH_Disconnect;
 extern char * _PREHASH_SimPosition;
 extern char * _PREHASH_SimWideTotalPrims;
 extern char * _PREHASH_Index;
-extern char * _PREHASH_BaseFilename;
 extern char * _PREHASH_SimFilename;
 extern char * _PREHASH_LastOwnerID;
 extern char * _PREHASH_GroupNoticeRequest;
@@ -1293,6 +1287,7 @@ extern char * _PREHASH_AssetBlock;
 extern char * _PREHASH_AcceptNotices;
 extern char * _PREHASH_SetGroupAcceptNotices;
 extern char * _PREHASH_CloseCircuit;
+extern char * _PREHASH_LogControl;
 extern char * _PREHASH_TeleportFinish;
 extern char * _PREHASH_PathRevolutions;
 extern char * _PREHASH_ClassifiedInfoReply;
@@ -1472,7 +1467,6 @@ extern char * _PREHASH_DirLandReply;
 extern char * _PREHASH_SpaceLocationTeleportReply;
 extern char * _PREHASH_MuteType;
 extern char * _PREHASH_IMViaEMail;
-extern char * _PREHASH_StartExpungeProcessAck;
 extern char * _PREHASH_RentPrice;
 extern char * _PREHASH_GenericMessage;
 extern char * _PREHASH_ChildAgentAlive;
diff --git a/indra/llmessage/net.cpp b/indra/llmessage/net.cpp
index a78b216ccb..9e83ce1434 100644
--- a/indra/llmessage/net.cpp
+++ b/indra/llmessage/net.cpp
@@ -222,6 +222,12 @@ S32 start_net(S32& socket_out, int& nPort)
 			return 4;
 		}
 	}
+
+	sockaddr_in socket_address;
+	S32 socket_address_size = sizeof(socket_address);
+	getsockname(hSocket, (SOCKADDR*) &socket_address, &socket_address_size);
+	attempt_port = ntohs(socket_address.sin_port);
+
 	llinfos << "connected on port " << attempt_port << llendl;
 	nPort = attempt_port;
 	
-- 
cgit v1.2.3