From b069bb9e71d31495f3f1312529d19fdb83c1779e Mon Sep 17 00:00:00 2001
From: Christian Goetze <cg@lindenlab.com>
Date: Wed, 1 Oct 2008 00:42:47 +0000
Subject: [PATCH] svn merge -r96886:98039
 svn+ssh://svn.lindenlab.com/svn/linden/branches/Branch_1-24-Server -->
 release

---
 etc/message.xml                               | 24 ++++++++
 indra/lib/python/indra/ipc/llmessage.py       |  5 +-
 indra/llcommon/lltimer.h                      |  4 +-
 indra/llcommon/llversionserver.h              |  4 +-
 indra/llcommon/llversionviewer.h              |  2 +-
 indra/llmath/llmodularmath.h                  | 57 +++++++++++++++++
 indra/llmessage/llcircuit.cpp                 | 11 ++++
 indra/llmessage/llcircuit.h                   |  7 +++
 indra/llmessage/llmail.cpp                    | 36 ++++++++---
 indra/llmessage/llmail.h                      | 61 ++++++++++++-------
 indra/llmessage/llmessagetemplate.cpp         | 20 ++++++
 indra/llmessage/llmessagetemplate.h           |  8 +++
 indra/llmessage/llmessagetemplateparser.cpp   |  4 ++
 indra/llmessage/lltemplatemessagereader.cpp   |  5 ++
 indra/llmessage/lltemplatemessagereader.h     |  2 +-
 indra/llmessage/message.cpp                   | 25 +++++++-
 indra/llmessage/message.h                     |  3 +
 .../lscript/lscript_compile/lscript_tree.cpp  | 29 +++++++--
 indra/newview/English.lproj/InfoPlist.strings |  4 +-
 indra/newview/Info-SecondLife.plist           |  2 +-
 indra/newview/llstartup.cpp                   | 35 ++++++++++-
 indra/newview/res/viewerRes.rc                |  8 +--
 indra/test/CMakeLists.txt                     |  1 +
 23 files changed, 307 insertions(+), 50 deletions(-)
 create mode 100644 indra/llmath/llmodularmath.h

diff --git a/etc/message.xml b/etc/message.xml
index 0695d0580d..d833074765 100644
--- a/etc/message.xml
+++ b/etc/message.xml
@@ -441,6 +441,30 @@
 					<boolean>true</boolean>
 				</map>
 				
+				<key>EnableSimulator</key>
+				<map>
+					<key>flavor</key>
+					<string>llsd</string>
+					<key>trusted-sender</key>
+					<boolean>true</boolean>
+				</map>
+				
+				<key>TeleportFinish</key>
+				<map>
+					<key>flavor</key>
+					<string>llsd</string>
+					<key>trusted-sender</key>
+					<boolean>true</boolean>
+				</map>
+				
+				<key>CrossedRegion</key>
+				<map>
+					<key>flavor</key>
+					<string>llsd</string>
+					<key>trusted-sender</key>
+					<boolean>true</boolean>
+				</map>
+				
 				<!-- UDPDeprecated Messages -->
 				<key>ScriptRunningReply</key>
 				<map>
diff --git a/indra/lib/python/indra/ipc/llmessage.py b/indra/lib/python/indra/ipc/llmessage.py
index 2497393cbd..ffefd74586 100644
--- a/indra/lib/python/indra/ipc/llmessage.py
+++ b/indra/lib/python/indra/ipc/llmessage.py
@@ -86,8 +86,9 @@ class Message:
     NOTDEPRECATED = "NotDeprecated"
     DEPRECATED = "Deprecated"
     UDPDEPRECATED = "UDPDeprecated"
-    deprecations = [ NOTDEPRECATED, UDPDEPRECATED, DEPRECATED ]
-        # in order of increasing deprecation
+    UDPBLACKLISTED = "UDPBlackListed"
+    deprecations = [ NOTDEPRECATED, UDPDEPRECATED, UDPBLACKLISTED, DEPRECATED ]
+    # in order of increasing deprecation
     
     def __init__(self, name, number, priority, trust, coding):
         self.name = name
diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h
index d3a83339f0..ea84f8ea2c 100644
--- a/indra/llcommon/lltimer.h
+++ b/indra/llcommon/lltimer.h
@@ -39,6 +39,8 @@
 
 #include "stdtypes.h"
 
+#include <string>
+#include <list>
 // units conversions
 #ifndef USEC_PER_SEC
     const U32	USEC_PER_SEC	= 1000000;
@@ -184,7 +186,7 @@ protected:
 
 private:
 	//list of active timers
-	static std::list<LLEventTimer*> sActiveList;
+	static std::list<LLEventTimer*> sActiveList; // TODO should this be a vector
 };
 
 #endif
diff --git a/indra/llcommon/llversionserver.h b/indra/llcommon/llversionserver.h
index b79c729184..de2cbde0e1 100644
--- a/indra/llcommon/llversionserver.h
+++ b/indra/llcommon/llversionserver.h
@@ -34,8 +34,8 @@
 
 const S32 LL_VERSION_MAJOR = 1;
 const S32 LL_VERSION_MINOR = 24;
-const S32 LL_VERSION_PATCH = 6;
-const S32 LL_VERSION_BUILD = 94536;
+const S32 LL_VERSION_PATCH = 7;
+const S32 LL_VERSION_BUILD = 97877;
 
 const char * const LL_CHANNEL = "Second Life Server";
 
diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index 9e3ad076fc..ac568798cf 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -35,7 +35,7 @@
 const S32 LL_VERSION_MAJOR = 1;
 const S32 LL_VERSION_MINOR = 21;
 const S32 LL_VERSION_PATCH = 3;
-const S32 LL_VERSION_BUILD = 0;
+const S32 LL_VERSION_BUILD = 97417;
 
 const char * const LL_CHANNEL = "Second Life Release";
 
diff --git a/indra/llmath/llmodularmath.h b/indra/llmath/llmodularmath.h
new file mode 100644
index 0000000000..87429f67c7
--- /dev/null
+++ b/indra/llmath/llmodularmath.h
@@ -0,0 +1,57 @@
+/** 
+ * @file llmodularmath.h
+ * @brief Useful modular math functions.
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * 
+ * Copyright (c) 2008, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLMODULARMATH_H
+#define LLMODULARMATH_H
+
+namespace LLModularMath
+{
+    // Return difference between lhs and rhs
+    // treating the U32 operands and result
+    // as unsigned values of given width.
+	template<int width>
+	inline U32 subtract(U32 lhs, U32 rhs)
+	{
+		// Generate a bit mask which will truncate
+		// unsigned values to given width at compile time.
+		const U32 mask = (1 << width) - 1;
+		
+		// Operands are unsigned, so modular
+		// arithmetic applies. If lhs < rhs,
+		// difference will wrap in to lower
+		// bits of result, which is then masked
+		// to give a value that can be represented
+		// by an unsigned value of width bits.
+		return mask & (lhs - rhs);
+	}	
+}
+
+#endif
diff --git a/indra/llmessage/llcircuit.cpp b/indra/llmessage/llcircuit.cpp
index 431fe802f6..9ad84d8242 100644
--- a/indra/llmessage/llcircuit.cpp
+++ b/indra/llmessage/llcircuit.cpp
@@ -60,6 +60,7 @@
 #include "llrand.h"
 #include "llstl.h"
 #include "lltransfermanager.h"
+#include "llmodularmath.h"
 
 const F32 PING_INTERVAL = 5.f; // seconds
 const S32 PING_START_BLOCK = 3;		// How many pings behind we have to be to consider ourself blocked.
@@ -676,6 +677,8 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent)
 		mPacketsIn++;
 		setPacketInID((id + 1) % LL_MAX_OUT_PACKET_ID);
 
+        mLastPacketGap = 0;
+        mOutOfOrderRate.count(0);
 		return;
 	}
 
@@ -683,6 +686,7 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent)
 
 
 	// now, check to see if we've got a gap
+    U32 gap = 0;
 	if ((mPacketsInID == id))
 	{
 		// nope! bump and wrap the counter, then return
@@ -704,6 +708,11 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent)
 		// otherwise, walk from mCurrentCircuit->mPacketsInID to id with wrapping, adding the values to the map
 		// and setting mPacketsInID to id + 1 % LL_MAX_OUT_PACKET_ID
 
+        // babbage: all operands in expression are unsigned, so modular 
+		// arithmetic will always find correct gap, regardless of wrap arounds.
+		const U8 width = 24;
+		gap = LLModularMath::subtract<width>(mPacketsInID, id);
+
 		if (mPotentialLostPackets.find(id) != mPotentialLostPackets.end())
 		{
 			if(gMessageSystem->mVerboseLog)
@@ -765,6 +774,8 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent)
 
 		}
 	}
+    mOutOfOrderRate.count(gap);
+    mLastPacketGap = gap;
 }
 
 
diff --git a/indra/llmessage/llcircuit.h b/indra/llmessage/llcircuit.h
index 8824e6825a..492313da93 100644
--- a/indra/llmessage/llcircuit.h
+++ b/indra/llmessage/llcircuit.h
@@ -45,6 +45,7 @@
 #include "llpacketack.h"
 #include "lluuid.h"
 #include "llthrottle.h"
+#include "llstat.h"
 
 //
 // Constants
@@ -133,6 +134,10 @@ public:
 	S32			getUnackedPacketCount() const	{ return mUnackedPacketCount; }
 	S32			getUnackedPacketBytes() const	{ return mUnackedPacketBytes; }
 	F64         getNextPingSendTime() const { return mNextPingSendTime; }
+    F32         getOutOfOrderRate(LLStatAccum::TimeScale scale = LLStatAccum::SCALE_MINUTE) 
+                    { return mOutOfOrderRate.meanValue(scale); }
+    U32         getLastPacketGap() const { return mLastPacketGap; }
+    LLHost      getHost() const { return mHost; }
 
 	LLThrottleGroup &getThrottleGroup()		{	return mThrottles; }
 
@@ -276,6 +281,8 @@ protected:
 	LLTimer	mExistenceTimer;	    // initialized when circuit created, used to track bandwidth numbers
 
 	S32		mCurrentResendCount;	// Number of resent packets since last spam
+    LLStatRate  mOutOfOrderRate;    // Rate of out of order packets coming in.
+    U32     mLastPacketGap;         // Gap in sequence number of last packet.
 };
 
 
diff --git a/indra/llmessage/llmail.cpp b/indra/llmessage/llmail.cpp
index 6a8931cf73..82e477884b 100644
--- a/indra/llmessage/llmail.cpp
+++ b/indra/llmessage/llmail.cpp
@@ -51,6 +51,7 @@
 #include "llblowfishcipher.h"
 #include "llerror.h"
 #include "llhost.h"
+#include "llsd.h"
 #include "llstring.h"
 #include "lluuid.h"
 #include "net.h"
@@ -111,16 +112,22 @@ void disconnect_smtp()
 // Returns TRUE on success.
 // message should NOT be SMTP escaped.
 // static
-BOOL LLMail::send(const char* from_name, const char* from_address,
-			   const char* to_name, const char* to_address,
-			   const char* subject, const char* message)
+BOOL LLMail::send(
+	const char* from_name,
+	const char* from_address,
+	const char* to_name,
+	const char* to_address,
+	const char* subject,
+	const char* message,
+	const LLSD& headers)
 {
 	std::string header = buildSMTPTransaction(
 		from_name,
 		from_address,
 		to_name,
 		to_address,
-		subject);
+		subject,
+		headers);
 	if(header.empty())
 	{
 		return FALSE;
@@ -192,7 +199,8 @@ std::string LLMail::buildSMTPTransaction(
 	const char* from_address,
 	const char* to_name,
 	const char* to_address,
-	const char* subject)
+	const char* subject,
+	const LLSD& headers)
 {
 	if(!from_address || !to_address)
 	{
@@ -236,8 +244,20 @@ std::string LLMail::buildSMTPTransaction(
 		<< "DATA\r\n"
 		<< "From: " << from_fmt.str() << "\r\n"
 		<< "To: " << to_fmt.str() << "\r\n"
-		<< "Subject: " << subject << "\r\n"
-		<< "\r\n";
+		<< "Subject: " << subject << "\r\n";
+	
+	if(headers.isMap())
+	{
+		LLSD::map_const_iterator iter = headers.beginMap();
+		LLSD::map_const_iterator end = headers.endMap();
+		for(; iter != end; ++iter)
+		{
+			header << (*iter).first << ": " << ((*iter).second).asString()
+				<< "\r\n";
+		}
+	}
+
+	header << "\r\n";
 	return header.str();
 }
 
@@ -324,7 +344,7 @@ bool LLMail::send(
 			<< "when sending messages larger than " << LL_MAX_KNOWN_GOOD_MAIL_SIZE
 			<< " bytes. The next log about success is potentially a lie." << llendl;
 	}
-	llinfos << "send_mail success: "
+	lldebugs << "send_mail success: "
 		<< "to=<" << to_address
 		<< ">, from=<" << from_address << ">"
 		<< ", bytes=" << original_size
diff --git a/indra/llmessage/llmail.h b/indra/llmessage/llmail.h
index 2a88592b89..0329602e0b 100644
--- a/indra/llmessage/llmail.h
+++ b/indra/llmessage/llmail.h
@@ -34,7 +34,7 @@
 
 typedef struct apr_pool_t apr_pool_t;
 
-class LLUUID;
+#include "llsd.h"
 
 class LLMail
 {
@@ -45,34 +45,51 @@ public:
 	// Allow all email transmission to be disabled/enabled.
 	static void enable(bool mail_enabled);
 
-	// returns TRUE if the call succeeds, FALSE otherwise.
-	//
-	// Results in:
-	// From: "from_name" <from_address>
-	// To:   "to_name" <to_address>
-	// Subject: subject
-	// message
-	static BOOL send(const char* from_name, const char* from_address,
-				const char* to_name, const char* to_address,
-				const char* subject, const char* message);
+	/**
+	 * @brief send an email
+	 * @param from_name The name of the email sender
+	 * @param from_address The email address for the sender
+	 * @param to_name The name of the email recipient
+	 * @param to_address The email recipient address
+	 * @param subject The subject of the email
+	 * @param headers optional X-Foo headers in an llsd map. 
+	 * @return Returns TRUE if the call succeeds, FALSE otherwise.
+	 *
+	 * Results in:
+	 * From: "from_name" <from_address>
+	 * To:   "to_name" <to_address>
+	 * Subject: subject
+	 * 
+	 * message
+	 */
+	static BOOL send(
+		const char* from_name,
+		const char* from_address,
+		const char* to_name,
+		const char* to_address,
+		const char* subject,
+		const char* message,
+		const LLSD& headers = LLSD());
 
 	/**
-	* @brief build the complete smtp transaction & header for use in an
-	* mail.
-	*
-	* @param from_name The name of the email sender
-	* @param from_address The email address for the sender
-	* @param to_name The name of the email recipient
-	* @param to_name The email recipient address
-	* @param subject The subject of the email
-	* @return Returns the complete SMTP transaction mail header.
-	*/
+	 * @brief build the complete smtp transaction & header for use in an
+	 * mail.
+	 *
+	 * @param from_name The name of the email sender
+	 * @param from_address The email address for the sender
+	 * @param to_name The name of the email recipient
+	 * @param to_address The email recipient address
+	 * @param subject The subject of the email
+	 * @param headers optional X-Foo headers in an llsd map. 
+	 * @return Returns the complete SMTP transaction mail header.
+	 */
 	static std::string buildSMTPTransaction(
 		const char* from_name,
 		const char* from_address,
 		const char* to_name,
 		const char* to_address,
-		const char* subject);
+		const char* subject,
+		const LLSD& headers = LLSD());
 
 	/**
 	* @brief send an email with header and body.
diff --git a/indra/llmessage/llmessagetemplate.cpp b/indra/llmessage/llmessagetemplate.cpp
index c09f3e9c49..78085f40af 100644
--- a/indra/llmessage/llmessagetemplate.cpp
+++ b/indra/llmessage/llmessagetemplate.cpp
@@ -175,3 +175,23 @@ std::ostream& operator<<(std::ostream& s, LLMessageTemplate &msg)
 
 	return s;
 }
+
+void LLMessageTemplate::banUdp()
+{
+	static const char* deprecation[] = {
+		"NotDeprecated",
+		"Deprecated",
+		"UDPDeprecated",
+		"UDPBlackListed"
+	};
+	if (mDeprecation != MD_DEPRECATED)
+	{
+		llinfos << "Setting " << mName << " to UDPBlackListed was " << deprecation[mDeprecation] << llendl;
+		mDeprecation = MD_UDPBLACKLISTED;
+	}
+	else
+	{
+		llinfos << mName << " is already more deprecated than UDPBlackListed" << llendl;
+	}
+}
+
diff --git a/indra/llmessage/llmessagetemplate.h b/indra/llmessage/llmessagetemplate.h
index 85fb0a7782..82421b1f5a 100644
--- a/indra/llmessage/llmessagetemplate.h
+++ b/indra/llmessage/llmessagetemplate.h
@@ -265,6 +265,7 @@ enum EMsgDeprecation
 {
 	MD_NOTDEPRECATED,
 	MD_UDPDEPRECATED,
+	MD_UDPBLACKLISTED,
 	MD_DEPRECATED
 };
 
@@ -375,6 +376,13 @@ public:
 		return FALSE;
 	}
 
+	bool isUdpBanned() const
+	{
+		return mDeprecation == MD_UDPBLACKLISTED;
+	}
+
+	void banUdp();
+
 	bool isBanned(bool trustedSource) const
 	{
 		return trustedSource ? mBanFromTrusted : mBanFromUntrusted;
diff --git a/indra/llmessage/llmessagetemplateparser.cpp b/indra/llmessage/llmessagetemplateparser.cpp
index 50f216ed6f..86662c5342 100644
--- a/indra/llmessage/llmessagetemplateparser.cpp
+++ b/indra/llmessage/llmessagetemplateparser.cpp
@@ -525,6 +525,10 @@ LLMessageTemplate * LLTemplateParser::parseMessage(LLTemplateTokenizer & tokens)
 	{
 		templatep->setDeprecation(MD_UDPDEPRECATED);
 	}
+	else if (tokens.want("UDPBlackListed"))
+	{
+		templatep->setDeprecation(MD_UDPBLACKLISTED);
+	}	
 	else if (tokens.want("NotDeprecated"))
 	{
 		// this is the default value, but it can't hurt to set it twice
diff --git a/indra/llmessage/lltemplatemessagereader.cpp b/indra/llmessage/lltemplatemessagereader.cpp
index b5186ad539..822051d363 100644
--- a/indra/llmessage/lltemplatemessagereader.cpp
+++ b/indra/llmessage/lltemplatemessagereader.cpp
@@ -797,6 +797,11 @@ bool LLTemplateMessageReader::isBanned(bool trustedSource) const
 	return mCurrentRMessageTemplate->isBanned(trustedSource);
 }
 
+bool LLTemplateMessageReader::isUdpBanned() const
+{
+       return mCurrentRMessageTemplate->isUdpBanned();
+}
+
 //virtual 
 void LLTemplateMessageReader::copyToBuilder(LLMessageBuilder& builder) const
 {
diff --git a/indra/llmessage/lltemplatemessagereader.h b/indra/llmessage/lltemplatemessagereader.h
index ea3ec9a3d8..268afa3ef6 100644
--- a/indra/llmessage/lltemplatemessagereader.h
+++ b/indra/llmessage/lltemplatemessagereader.h
@@ -109,7 +109,7 @@ public:
 
 	bool isTrusted() const;
 	bool isBanned(bool trusted_source) const;
-
+	bool isUdpBanned() const;
 private:
 
 	void getData(const char *blockname, const char *varname, void *datap, 
diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp
index 290682f7ce..abd9467602 100644
--- a/indra/llmessage/message.cpp
+++ b/indra/llmessage/message.cpp
@@ -754,7 +754,15 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
 				clearReceiveState();
 				valid_packet = FALSE;
 			}
-			
+			if( valid_packet && mTemplateMessageReader->isUdpBanned())
+			{
+				llwarns << "Received UDP black listed message "
+					<<  mTemplateMessageReader->getMessageName()
+					<< " from " << host << llendl;
+				clearReceiveState();
+				valid_packet = FALSE;
+			}
+
 			if( valid_packet )
 			{
 				logValidMsg(cdp, host, recv_reliable, recv_resent, (BOOL)(acks>0) );
@@ -4013,3 +4021,18 @@ bool LLMessageSystem::checkAllMessages(S64 frame_count, LLPumpIO* http_pump)
 	http_pump->callback();
 	return (mPacketsIn - packetsIn) > 0;
 }
+
+void LLMessageSystem::banUdpMessage(const std::string& name)
+{
+	message_template_name_map_t::iterator itt = mMessageTemplates.find(
+		LLMessageStringTable::getInstance()->getString(name.c_str())
+		);
+	if(itt != mMessageTemplates.end())
+	{
+		itt->second->banUdp();
+	}
+	else
+	{
+		llwarns << "Attempted to ban an unknown message: " << name << "." << llendl;
+	}
+}
diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h
index e2d2ed46e2..f4f3927f66 100644
--- a/indra/llmessage/message.h
+++ b/indra/llmessage/message.h
@@ -562,6 +562,9 @@ public:
 	/** Return false true if name is unknown or trusted */
 	bool isUntrustedMessage(const std::string& name) const;
 
+	// Change this message to be UDP black listed.
+	void banUdpMessage(const std::string& name);
+
 private:
 	// A list of the circuits that need to be sent DenyTrustedCircuit messages.
 	typedef std::set<LLHost> host_set_t;
diff --git a/indra/lscript/lscript_compile/lscript_tree.cpp b/indra/lscript/lscript_compile/lscript_tree.cpp
index aabf0a3c38..69485f05f9 100644
--- a/indra/lscript/lscript_compile/lscript_tree.cpp
+++ b/indra/lscript/lscript_compile/lscript_tree.cpp
@@ -46,7 +46,8 @@
 
 static void print_cil_box(LLFILE* fp, LSCRIPTType type)
 {
-	switch(type)
+	
+switch(type)
 	{
 	case LST_INTEGER:
 		fprintf(fp, "box [mscorlib]System.Int32\n");
@@ -1257,10 +1258,10 @@ static void print_cil_init_variable(LLFILE* fp, LSCRIPTType type)
 		fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateVector'(float32, float32, float32)\n");
 		break;
 	case LST_QUATERNION:
-		fprintf(fp, "ldc.r8 1\n");
 		fprintf(fp, "ldc.r8 0\n");
 		fprintf(fp, "ldc.r8 0\n");
 		fprintf(fp, "ldc.r8 0\n");
+		fprintf(fp, "ldc.r8 1\n");
 		fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Quaternion class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateQuaternion'(float32, float32, float32, float32)\n");
 		break;
 	case LST_LIST:
@@ -3517,7 +3518,7 @@ void LLScriptRezEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompile
 		fprintf(fp, " )\n");
 		break;
 	case LSCP_SCOPE_PASS1:
-	  checkForDuplicateHandler(fp, this, scope, "rez");
+		checkForDuplicateHandler(fp, this, scope, "on_rez");
 		if (scope->checkEntry(mStartParam->mName))
 		{
 			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
@@ -8689,8 +8690,12 @@ void LLScriptIf::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass p
 		break;
 	case LSCP_TYPE:
 		mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+		if (type == LST_NULL)
+		{
+			gErrorToText.writeError(fp, mExpression, LSERROR_TYPE_MISMATCH);
+		}
 		mType = type;
-		mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+		mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);		
 		break;
 	case LSCP_EMIT_BYTE_CODE:
 		{
@@ -8770,6 +8775,10 @@ void LLScriptIfElse::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePa
 		break;
 	case LSCP_TYPE:
 		mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+		if (type == LST_NULL)
+		{
+			gErrorToText.writeError(fp, mExpression, LSERROR_TYPE_MISMATCH);
+		}
 		mType = type;
 		mStatement1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 		mStatement2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
@@ -8869,6 +8878,10 @@ void LLScriptFor::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass
 		if(mSequence)
 			mSequence->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 		mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+		if (type == LST_NULL)
+		{
+			gErrorToText.writeError(fp, mExpression, LSERROR_TYPE_MISMATCH);
+		}
 		mType = type;
 		if(mExpressionList)
 			mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
@@ -8968,6 +8981,10 @@ void LLScriptDoWhile::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompileP
 	case LSCP_TYPE:
 		mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 		mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+		if (type == LST_NULL)
+		{
+			gErrorToText.writeError(fp, mExpression, LSERROR_TYPE_MISMATCH);
+		}
 		mType = type;
 		break;
 	case LSCP_EMIT_BYTE_CODE:
@@ -9039,6 +9056,10 @@ void LLScriptWhile::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePas
 		break;
 	case LSCP_TYPE:
 		mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+		if (type == LST_NULL)
+		{
+			gErrorToText.writeError(fp, mExpression, LSERROR_TYPE_MISMATCH);
+		}
 		mType = type;
 		mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 		break;
diff --git a/indra/newview/English.lproj/InfoPlist.strings b/indra/newview/English.lproj/InfoPlist.strings
index a01eb8c3ee..90646be31f 100644
--- a/indra/newview/English.lproj/InfoPlist.strings
+++ b/indra/newview/English.lproj/InfoPlist.strings
@@ -1,6 +1,6 @@
 /* Localized versions of Info.plist keys */
 
 CFBundleName = "Second Life";
-CFBundleShortVersionString = "Second Life version 1.20.15.0";
-CFBundleGetInfoString = "Second Life version 1.20.15.0, Copyright 2004-2008 Linden Research, Inc.";
+CFBundleShortVersionString = "Second Life version 1.20.15.97417";
+CFBundleGetInfoString = "Second Life version 1.20.15.97417, Copyright 2004-2008 Linden Research, Inc.";
 
diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist
index ee26049d88..3c55badc23 100644
--- a/indra/newview/Info-SecondLife.plist
+++ b/indra/newview/Info-SecondLife.plist
@@ -32,7 +32,7 @@
 		</dict>
 	</array>
 	<key>CFBundleVersion</key>
-	<string>1.20.15.0</string>
+	<string>1.20.15.97417</string>
 	<key>CSResourcesFileMapped</key>
 	<true/>
 </dict>
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index ad1902fa9b..0668241f83 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -244,6 +244,7 @@ void callback_choose_gender(S32 option, void* userdata);
 void init_start_screen(S32 location_id);
 void release_start_screen();
 void reset_login();
+void apply_udp_blacklist(const std::string& csv);
 
 void callback_cache_name(const LLUUID& id, const std::string& firstname, const std::string& lastname, BOOL is_group, void* data)
 {
@@ -1262,8 +1263,14 @@ bool idle_startup()
 
 		if(successful_login)
 		{
-			// unpack login data needed by the application
 			std::string text;
+			text = LLUserAuth::getInstance()->getResponse("udp_blacklist");
+			if(!text.empty())
+			{
+				apply_udp_blacklist(text);
+			}
+
+			// unpack login data needed by the application
 			text = LLUserAuth::getInstance()->getResponse("agent_id");
 			if(!text.empty()) gAgentID.set(text);
 			gDebugInfo["AgentID"] = text;
@@ -3895,3 +3902,29 @@ void login_alert_done(S32 option, void* user_data)
 {
 	LLPanelLogin::giveFocus();
 }
+
+
+void apply_udp_blacklist(const std::string& csv)
+{
+
+	std::string::size_type start = 0;
+	std::string::size_type comma = 0;
+	do 
+	{
+		comma = csv.find(",", start);
+		if (comma == std::string::npos)
+		{
+			comma = csv.length();
+		}
+		std::string item(csv, start, comma-start);
+
+		lldebugs << "udp_blacklist " << item << llendl;
+		gMessageSystem->banUdpMessage(item);
+		
+		start = comma + 1;
+
+	}
+	while(comma < csv.length());
+	
+}
+
diff --git a/indra/newview/res/viewerRes.rc b/indra/newview/res/viewerRes.rc
index efe2d83cce..8df0c57ef2 100644
--- a/indra/newview/res/viewerRes.rc
+++ b/indra/newview/res/viewerRes.rc
@@ -231,8 +231,8 @@ TOOLMEDIAOPEN           CURSOR                  "toolmediaopen.cur"
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,20,15,0
- PRODUCTVERSION 1,20,15,0
+ FILEVERSION 1,20,15,97417
+ PRODUCTVERSION 1,20,15,97417
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -249,12 +249,12 @@ BEGIN
         BEGIN
             VALUE "CompanyName", "Linden Lab"
             VALUE "FileDescription", "Second Life"
-            VALUE "FileVersion", "1.20.15.0"
+            VALUE "FileVersion", "1.20.15.97417"
             VALUE "InternalName", "Second Life"
             VALUE "LegalCopyright", "Copyright © 2001-2008, Linden Research, Inc."
             VALUE "OriginalFilename", "SecondLife.exe"
             VALUE "ProductName", "Second Life"
-            VALUE "ProductVersion", "1.20.15.0"
+            VALUE "ProductVersion", "1.20.15.97417"
         END
     END
     BLOCK "VarFileInfo"
diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt
index 6940c0682f..cb5f1d6c2c 100644
--- a/indra/test/CMakeLists.txt
+++ b/indra/test/CMakeLists.txt
@@ -41,6 +41,7 @@ set(test_SOURCE_FILES
     lljoint_tut.cpp
     llmime_tut.cpp
     llmessageconfig_tut.cpp
+    llmodularmath_tut.cpp
     llnamevalue_tut.cpp
     llpermissions_tut.cpp
     llpipeutil.cpp
-- 
GitLab